Adding several more tests to the TCK.

git-svn-id: https://atinject.googlecode.com/svn/trunk@31 3bc8319c-20ab-11de-9edc-3f40a397ab60
diff --git a/tck/com/googlecode/atinject/Candidate.java b/tck/com/googlecode/atinject/Candidate.java
index 75e8192..6a707c2 100644
--- a/tck/com/googlecode/atinject/Candidate.java
+++ b/tck/com/googlecode/atinject/Candidate.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject;
 
 import com.googlecode.atinject.auto.Car;
@@ -35,6 +34,10 @@
  *       Cupholder}, {@link com.googlecode.atinject.auto.Tire Tire} and {@link com.googlecode.atinject.auto.FuelTank
  *       FuelTank}.
  * </ul>
+ *
+ * <p>The static members of the following types shall also be injected: {@link com.googlecode.atinject.auto.Convertible
+ * Convertible}, {@link com.googlecode.atinject.auto.Tire Tire}, and {@link
+ * com.googlecode.atinject.auto.accessories.SpareTire SpareTire}.
  */
 public interface Candidate {
 
diff --git a/tck/com/googlecode/atinject/Tck.java b/tck/com/googlecode/atinject/Tck.java
index e77dec1..7392481 100644
--- a/tck/com/googlecode/atinject/Tck.java
+++ b/tck/com/googlecode/atinject/Tck.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject;
 
 import com.googlecode.atinject.auto.Car;
diff --git a/tck/com/googlecode/atinject/Tester.java b/tck/com/googlecode/atinject/Tester.java
index 898f2a8..0f37e6e 100644
--- a/tck/com/googlecode/atinject/Tester.java
+++ b/tck/com/googlecode/atinject/Tester.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject;
 
 import java.util.List;
@@ -25,8 +24,7 @@
     private final List<String> problems = new ArrayList<String>();
 
     /**
-     * @param problem a description of what went wrong; often of the form,
-     *      "Expected two injections to yield the same instance of Vin".
+     * @param problem a brief description of what went wrong.
      */
     public void addProblem(String problem) {
         problems.add(problem);
@@ -35,8 +33,7 @@
     /**
      * Adds a problem if {@code condition} is not true.
      * 
-     * @param problem a description of what went wrong; often of the form,
-     *      "Expected two injections to yield the same instance of Vin".
+     * @param problem a brief description of what went wrong.
      */
     public void test(boolean condition, String problem) {
         if (!condition) {
diff --git a/tck/com/googlecode/atinject/auto/Car.java b/tck/com/googlecode/atinject/auto/Car.java
index 77185b9..c3832da 100644
--- a/tck/com/googlecode/atinject/auto/Car.java
+++ b/tck/com/googlecode/atinject/auto/Car.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 import com.googlecode.atinject.Tester;
diff --git a/tck/com/googlecode/atinject/auto/Convertible.java b/tck/com/googlecode/atinject/auto/Convertible.java
index 0b18cb1..fdb2181 100644
--- a/tck/com/googlecode/atinject/auto/Convertible.java
+++ b/tck/com/googlecode/atinject/auto/Convertible.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 import com.googlecode.atinject.Tester;
 import com.googlecode.atinject.auto.accessories.SpareTire;
+import com.googlecode.atinject.auto.accessories.Cupholder;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -30,8 +30,9 @@
 
     @Inject DriversSeat driversSeatA;
     @Inject DriversSeat driversSeatB;
-    @Inject V8Engine engine;
     @Inject SpareTire spareTire;
+    @Inject Cupholder cupholder;
+    @Inject Provider<Engine> engineProvider;
 
     private boolean methodWithZeroParamsInjected;
     private boolean methodWithMultipleParamsInjected;
@@ -43,28 +44,46 @@
     private Seat constructorDriversSeat;
     private Tire constructorPlainTire;
     private Tire constructorSpareTire;
-    private Provider<Seat> constructorPlainSeatProvider;
-    private Provider<Seat> constructorDriversSeatProvider;
-    private Provider<Tire> constructorPlainTireProvider;
-    private Provider<Tire> constructorSpareTireProvider;
+    private Provider<Seat> constructorPlainSeatProvider = nullProvider();
+    private Provider<Seat> constructorDriversSeatProvider = nullProvider();
+    private Provider<Tire> constructorPlainTireProvider = nullProvider();
+    private Provider<Tire> constructorSpareTireProvider = nullProvider();
 
     @Inject Seat fieldPlainSeat;
     @Inject @Drivers Seat fieldDriversSeat;
     @Inject Tire fieldPlainTire;
     @Inject @Named("spare") Tire fieldSpareTire;
-    @Inject Provider<Seat> fieldPlainSeatProvider;
-    @Inject @Drivers Provider<Seat> fieldDriversSeatProvider;
-    @Inject Provider<Tire> fieldPlainTireProvider;
-    @Inject @Named("spare") Provider<Tire> fieldSpareTireProvider;
+    @Inject Provider<Seat> fieldPlainSeatProvider = nullProvider();
+    @Inject @Drivers Provider<Seat> fieldDriversSeatProvider = nullProvider();
+    @Inject Provider<Tire> fieldPlainTireProvider = nullProvider();
+    @Inject @Named("spare") Provider<Tire> fieldSpareTireProvider = nullProvider();
 
     private Seat methodPlainSeat;
     private Seat methodDriversSeat;
     private Tire methodPlainTire;
     private Tire methodSpareTire;
-    private Provider<Seat> methodPlainSeatProvider;
-    private Provider<Seat> methodDriversSeatProvider;
-    private Provider<Tire> methodPlainTireProvider;
-    private Provider<Tire> methodSpareTireProvider;
+    private Provider<Seat> methodPlainSeatProvider = nullProvider();
+    private Provider<Seat> methodDriversSeatProvider = nullProvider();
+    private Provider<Tire> methodPlainTireProvider = nullProvider();
+    private Provider<Tire> methodSpareTireProvider = nullProvider();
+
+    @Inject static Seat staticFieldPlainSeat;
+    @Inject @Drivers static Seat staticFieldDriversSeat;
+    @Inject static Tire staticFieldPlainTire;
+    @Inject @Named("spare") static Tire staticFieldSpareTire;
+    @Inject static Provider<Seat> staticFieldPlainSeatProvider = nullProvider();
+    @Inject @Drivers static Provider<Seat> staticFieldDriversSeatProvider = nullProvider();
+    @Inject static Provider<Tire> staticFieldPlainTireProvider = nullProvider();
+    @Inject @Named("spare") static Provider<Tire> staticFieldSpareTireProvider = nullProvider();
+
+    private static Seat staticMethodPlainSeat;
+    private static Seat staticMethodDriversSeat;
+    private static Tire staticMethodPlainTire;
+    private static Tire staticMethodSpareTire;
+    private static Provider<Seat> staticMethodPlainSeatProvider = nullProvider();
+    private static Provider<Seat> staticMethodDriversSeatProvider = nullProvider();
+    private static Provider<Tire> staticMethodPlainTireProvider = nullProvider();
+    private static Provider<Tire> staticMethodSpareTireProvider = nullProvider();
 
     @Inject Convertible(
             Seat plainSeat,
@@ -102,7 +121,7 @@
         return "unused";
     }
 
-    @Inject void injectMethodWithManyArgs(
+    @Inject void injectInstanceMethodWithManyArgs(
             Seat plainSeat,
             @Drivers Seat driversSeat,
             Tire plainTire,
@@ -123,22 +142,62 @@
         methodSpareTireProvider = spareTireProvider;
     }
 
+    @Inject static void injectStaticMethodWithManyArgs(
+            Seat plainSeat,
+            @Drivers Seat driversSeat,
+            Tire plainTire,
+            @Named("spare") Tire spareTire,
+            Provider<Seat> plainSeatProvider,
+            @Drivers Provider<Seat> driversSeatProvider,
+            Provider<Tire> plainTireProvider,
+            @Named("spare") Provider<Tire> spareTireProvider) {
+        staticMethodPlainSeat = plainSeat;
+        staticMethodDriversSeat = driversSeat;
+        staticMethodPlainTire = plainTire;
+        staticMethodSpareTire = spareTire;
+        staticMethodPlainSeatProvider = plainSeatProvider;
+        staticMethodDriversSeatProvider = driversSeatProvider;
+        staticMethodPlainTireProvider = plainTireProvider;
+        staticMethodSpareTireProvider = spareTireProvider;
+    }
+
+    /**
+     * Returns a provider that always returns null. This is used as a default
+     * value to avoid null checks for omitted provider injections.
+     */
+    private static <T> Provider<T> nullProvider() {
+        return new Provider<T>() {
+            public T get() {
+                return null;
+            }
+        };
+    }
+
     public void check(Tester tester) {
         tester.addProblems(moreProblems);
 
-        // values are injected
         tester.test(methodWithZeroParamsInjected, "Zero-parmeter method not injected");
         tester.test(methodWithMultipleParamsInjected, "Multi-parameter method not injected");
         tester.test(methodWithNonVoidReturnInjected, "Non-void method not injected");
-
-        // singleton is not @Inherited
         tester.test(driversSeatA != driversSeatB, "@Singleton inherited from supertype");
 
         testInjectedValues(tester);
         testProviders(tester);
 
-        spareTire.check(tester);
-        engine.check(tester);
+        Engine engine = engineProvider.get();
+
+        if (spareTire == null || cupholder == null || engineProvider == null) {
+            tester.addProblem("Fields not injected");
+        } else {
+            spareTire.check(tester);
+            cupholder.check(tester);
+
+            if (engine == null) {
+                tester.addProblem("Provider returned null");
+            } else {
+                engine.check(tester);
+            }
+        }
     }
 
     private void testInjectedValues(Tester tester) {
@@ -154,6 +213,14 @@
                 methodPlainSeat, methodDriversSeat, methodPlainTire, methodSpareTire);
         testExpectedValues(tester, "provider injected into a method", methodPlainSeatProvider.get(),
                 methodDriversSeatProvider.get(), methodPlainTireProvider.get(), methodSpareTireProvider.get());
+        testExpectedValues(tester, "injected static field",
+                staticFieldPlainSeat, staticFieldDriversSeat, staticFieldPlainTire, staticFieldSpareTire);
+        testExpectedValues(tester, "provider injected into a static field", staticFieldPlainSeatProvider.get(),
+                staticFieldDriversSeatProvider.get(), staticFieldPlainTireProvider.get(), staticFieldSpareTireProvider.get());
+        testExpectedValues(tester, "injected static method",
+                staticMethodPlainSeat, staticMethodDriversSeat, staticMethodPlainTire, staticMethodSpareTire);
+        testExpectedValues(tester, "provider injected into a static method", staticMethodPlainSeatProvider.get(),
+                staticMethodDriversSeatProvider.get(), staticMethodPlainTireProvider.get(), staticMethodSpareTireProvider.get());
     }
 
     private void testProviders(Tester tester) {
@@ -176,13 +243,13 @@
     private void testExpectedValues(Tester tester, String injectionMechanism,
                 Seat plainSeat, Seat driversSeat, Tire plainTire, Tire spareTire) {
         tester.test(!(plainSeat instanceof DriversSeat),
-                "Wrong type injected for " + injectionMechanism);
+                "Wrong value injected for " + injectionMechanism);
         tester.test(driversSeat instanceof DriversSeat,
-                "Wrong type injected for qualified " + injectionMechanism);
+                "Wrong value injected for qualified " + injectionMechanism);
         tester.test(!(plainTire instanceof SpareTire),
-                "Wrong type injected for " + injectionMechanism);
+                "Wrong value injected for " + injectionMechanism);
         tester.test(spareTire instanceof SpareTire,
-                "Wrong type injected for @Named " + injectionMechanism);
+                "Wrong value injected for @Named " + injectionMechanism);
     }
 
     private void testProviderProvidesNewValuesEachTime(Tester tester, Provider<?>... providers) {
diff --git a/tck/com/googlecode/atinject/auto/Drivers.java b/tck/com/googlecode/atinject/auto/Drivers.java
index f59c3fa..fded2bb 100644
--- a/tck/com/googlecode/atinject/auto/Drivers.java
+++ b/tck/com/googlecode/atinject/auto/Drivers.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 import javax.inject.Qualifier;
diff --git a/tck/com/googlecode/atinject/auto/DriversSeat.java b/tck/com/googlecode/atinject/auto/DriversSeat.java
index 521fc0f..d8bffd5 100644
--- a/tck/com/googlecode/atinject/auto/DriversSeat.java
+++ b/tck/com/googlecode/atinject/auto/DriversSeat.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,8 +14,16 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
+import com.googlecode.atinject.auto.accessories.Cupholder;
+
+import javax.inject.Inject;
+
 public class DriversSeat extends Seat {
+
+    @Inject
+    public DriversSeat(Cupholder cupholder) {
+        super(cupholder);
+    }
 }
diff --git a/tck/com/googlecode/atinject/auto/Engine.java b/tck/com/googlecode/atinject/auto/Engine.java
index c427b04..4ee0902 100644
--- a/tck/com/googlecode/atinject/auto/Engine.java
+++ b/tck/com/googlecode/atinject/auto/Engine.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
+import com.googlecode.atinject.auto.accessories.SpareTire;
+import com.googlecode.atinject.Tester;
+
 import javax.inject.Inject;
+import javax.inject.Named;
 import java.util.List;
 import java.util.ArrayList;
 
@@ -25,9 +28,18 @@
     
     protected final List<String> moreProblems = new ArrayList<String>();
 
+    protected boolean publicNoArgsConstructorInjected;
     protected boolean packagePrivateMethodInjected;
     protected boolean packagePrivateMethodForOverrideInjected;
 
+    protected boolean overriddenTwiceWithOmissionInMiddleInjected;
+    protected boolean overriddenTwiceWithOmissionInSubclassInjected;
+
+    protected Seat seatA;
+    protected Seat seatB;
+    protected Tire tireA;
+    protected Tire tireB;
+
     @Inject void injectPackagePrivateMethod() {
         moreProblems.add("Unexpected call to supertype package private method");
     }
@@ -35,4 +47,25 @@
     @Inject void injectPackagePrivateMethodForOverride() {
         moreProblems.add("Unexpected call to supertype package private method");
     }
+
+    @Inject public void injectQualifiers(@Drivers Seat seatA, Seat seatB, 
+            @Named("spare") Tire tireA, Tire tireB) {
+        if (!(seatA instanceof DriversSeat)
+                || (seatB instanceof DriversSeat)
+                || !(tireA instanceof SpareTire)
+                || (tireB instanceof SpareTire)) {
+            moreProblems.add("Qualifiers inherited from overridden methods");
+        }
+    }
+
+    @Inject public void injectTwiceOverriddenWithOmissionInMiddle() {
+        overriddenTwiceWithOmissionInMiddleInjected = true;
+    }
+
+    @Inject public void injectTwiceOverriddenWithOmissionInSubclass() {
+        overriddenTwiceWithOmissionInSubclassInjected = true;
+    }
+
+    public abstract void check(Tester tester);
+
 }
diff --git a/tck/com/googlecode/atinject/auto/FuelTank.java b/tck/com/googlecode/atinject/auto/FuelTank.java
index 49eaae2..19a00a6 100644
--- a/tck/com/googlecode/atinject/auto/FuelTank.java
+++ b/tck/com/googlecode/atinject/auto/FuelTank.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 public class FuelTank {
+
 }
diff --git a/tck/com/googlecode/atinject/auto/GasEngine.java b/tck/com/googlecode/atinject/auto/GasEngine.java
new file mode 100644
index 0000000..951c4ca
--- /dev/null
+++ b/tck/com/googlecode/atinject/auto/GasEngine.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.atinject.auto;
+
+import javax.inject.Inject;
+
+public abstract class GasEngine extends Engine {
+
+    public void injectTwiceOverriddenWithOmissionInMiddle() {
+        overriddenTwiceWithOmissionInMiddleInjected = true;
+    }
+
+    @Inject public void injectTwiceOverriddenWithOmissionInSubclass() {
+        overriddenTwiceWithOmissionInSubclassInjected = true;
+    }
+}
diff --git a/tck/com/googlecode/atinject/auto/Seat.java b/tck/com/googlecode/atinject/auto/Seat.java
index be61b2c..ac23b78 100644
--- a/tck/com/googlecode/atinject/auto/Seat.java
+++ b/tck/com/googlecode/atinject/auto/Seat.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,11 +14,24 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
+import com.googlecode.atinject.auto.accessories.Cupholder;
+
 import javax.inject.Singleton;
+import javax.inject.Inject;
 
 @Singleton
 public class Seat {
+
+    private final Cupholder cupholder;
+
+    @Inject
+    Seat(Cupholder cupholder) {
+        this.cupholder = cupholder;
+    }
+
+    public Cupholder getCupholder() {
+        return cupholder;
+    }
 }
diff --git a/tck/com/googlecode/atinject/auto/Seatbelt.java b/tck/com/googlecode/atinject/auto/Seatbelt.java
index b2188f9..885cf4e 100644
--- a/tck/com/googlecode/atinject/auto/Seatbelt.java
+++ b/tck/com/googlecode/atinject/auto/Seatbelt.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 public class Seatbelt {
diff --git a/tck/com/googlecode/atinject/auto/Tire.java b/tck/com/googlecode/atinject/auto/Tire.java
index a4a2f3e..74dca17 100644
--- a/tck/com/googlecode/atinject/auto/Tire.java
+++ b/tck/com/googlecode/atinject/auto/Tire.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,22 +14,25 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
+import com.googlecode.atinject.auto.accessories.SpareTire;
+
 import javax.inject.Inject;
-import java.util.List;
-import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
 public class Tire {
 
-    protected static final V8Engine NEVER_INJECTED = new V8Engine();
+    protected static final FuelTank NEVER_INJECTED = new FuelTank();
 
-    protected final List<String> moreProblems = new ArrayList<String>();
+    protected static final Set<String> moreProblems = new LinkedHashSet<String>();
 
-    V8Engine constructorInjection = NEVER_INJECTED;
-    @Inject V8Engine fieldInjection = NEVER_INJECTED;
-    V8Engine methodInjection = NEVER_INJECTED;
+    FuelTank constructorInjection = NEVER_INJECTED;
+    @Inject FuelTank fieldInjection = NEVER_INJECTED;
+    FuelTank methodInjection = NEVER_INJECTED;
+    @Inject static FuelTank staticFieldInjection = NEVER_INJECTED;
+    static FuelTank staticMethodInjection = NEVER_INJECTED;
 
     boolean constructorInjected;
 
@@ -49,12 +52,11 @@
     protected boolean protectedMethodForOverrideInjected;
     protected boolean publicMethodForOverrideInjected;
 
-    @Inject
-    public Tire(V8Engine constructorInjection) {
+    @Inject public Tire(FuelTank constructorInjection) {
         this.constructorInjection = constructorInjection;
     }
 
-    @Inject void supertypeMethodInjection(V8Engine methodInjection) {
+    @Inject void supertypeMethodInjection(FuelTank methodInjection) {
         if (!hasTireBeenFieldInjected()) {
             moreProblems.add("Method injected before fields");
         }
@@ -67,6 +69,19 @@
         this.methodInjection = methodInjection;
     }
 
+    @Inject static void supertypeStaticMethodInjection(FuelTank methodInjection) {
+        if (!Tire.hasBeenStaticFieldInjected()) {
+            moreProblems.add("Static method injected before static fields");
+        }
+        if (SpareTire.hasBeenStaticFieldInjected()) {
+            moreProblems.add("Subtype static field injected before supertype static method");
+        }
+        if (SpareTire.hasBeenStaticMethodInjected()) {
+            moreProblems.add("Subtype static method injected before supertype static method");
+        }
+        staticMethodInjection = methodInjection;
+    }
+
     @Inject private void injectPrivateMethod() {
         if (superPrivateMethodInjected) {
             moreProblems.add("Overridden private method injected twice");
@@ -123,6 +138,14 @@
         return methodInjection != NEVER_INJECTED;
     }
 
+    protected static boolean hasBeenStaticFieldInjected() {
+        return staticFieldInjection != NEVER_INJECTED;
+    }
+
+    protected static boolean hasBeenStaticMethodInjected() {
+        return staticMethodInjection != NEVER_INJECTED;
+    }
+
     protected boolean hasSpareTireBeenMethodInjected() {
         return false;
     }
diff --git a/tck/com/googlecode/atinject/auto/V8Engine.java b/tck/com/googlecode/atinject/auto/V8Engine.java
index 9762903..17e9ed4 100644
--- a/tck/com/googlecode/atinject/auto/V8Engine.java
+++ b/tck/com/googlecode/atinject/auto/V8Engine.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,19 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto;
 
 import com.googlecode.atinject.Tester;
+import com.googlecode.atinject.auto.accessories.SpareTire;
 
 import javax.inject.Inject;
+import javax.inject.Named;
 
-public class V8Engine extends Engine {
+public class V8Engine extends GasEngine {
+
+    public V8Engine() {
+        publicNoArgsConstructorInjected = true;
+    }
 
     @Inject void injectPackagePrivateMethod() {
         if (packagePrivateMethodInjected) {
@@ -30,15 +35,42 @@
         packagePrivateMethodInjected = true;
     }
 
+    /**
+     * Qualifiers are swapped from how they appear in the superclass.
+     */
+    public void injectQualifiers(Seat seatA, @Drivers Seat seatB,
+            Tire tireA, @Named("spare") Tire tireB) {
+        if ((seatA instanceof DriversSeat)
+                || !(seatB instanceof DriversSeat)
+                || (tireA instanceof SpareTire)
+                || !(tireB instanceof SpareTire)) {
+            moreProblems.add("Qualifiers inherited from overridden methods");
+        }
+    }
+
     void injectPackagePrivateMethodForOverride() {
         packagePrivateMethodForOverrideInjected = true;
     }
 
+    @Inject public void injectTwiceOverriddenWithOmissionInMiddle() {
+        overriddenTwiceWithOmissionInMiddleInjected = true;
+    }
+
+    public void injectTwiceOverriddenWithOmissionInSubclass() {
+        overriddenTwiceWithOmissionInSubclassInjected = true;
+    }
+
     public void check(Tester tester) {
         tester.addProblems(moreProblems);
 
+        tester.test(publicNoArgsConstructorInjected, "Public no-args constructor not injected");
         tester.test(packagePrivateMethodInjected, "Packge private method not injected");
         tester.test(!packagePrivateMethodForOverrideInjected,
                 "Package private method injected, even though its override lacks @Inject");
+
+        tester.test(overriddenTwiceWithOmissionInMiddleInjected,
+                "Twice-overridden method not injected; middle override lacks @Inject");
+        tester.test(!overriddenTwiceWithOmissionInSubclassInjected,
+                "Twice-overridden method injected, even though its override lacks @Inject");
     }
 }
diff --git a/tck/com/googlecode/atinject/auto/Vin.java b/tck/com/googlecode/atinject/auto/Vin.java
deleted file mode 100644
index cde592c..0000000
--- a/tck/com/googlecode/atinject/auto/Vin.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (C) 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.googlecode.atinject.auto;
-
-public class Vin {
-
-    static Integer nextVin() {
-        return 0;
-    }
-}
diff --git a/tck/com/googlecode/atinject/auto/accessories/Cupholder.java b/tck/com/googlecode/atinject/auto/accessories/Cupholder.java
index b024eb6..22dbd0d 100644
--- a/tck/com/googlecode/atinject/auto/accessories/Cupholder.java
+++ b/tck/com/googlecode/atinject/auto/accessories/Cupholder.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,9 +14,32 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto.accessories;
 
-public class Cupholder {
+import com.googlecode.atinject.auto.Seat;
+import com.googlecode.atinject.Tester;
 
+import javax.inject.Singleton;
+import javax.inject.Provider;
+import javax.inject.Inject;
+import java.util.List;
+import java.util.ArrayList;
+
+@Singleton
+public class Cupholder {
+    
+    protected final List<String> moreProblems = new ArrayList<String>();
+
+    private final Provider<Seat> seatProvider;
+
+    @Inject
+    public Cupholder(Provider<Seat> seatProvider) {
+        this.seatProvider = seatProvider;
+    }
+
+    public void check(Tester tester) {
+        tester.addProblems(moreProblems);
+
+        tester.test(seatProvider.get().getCupholder() == this, "Circularly dependent singletons not singleton");
+    }
 }
diff --git a/tck/com/googlecode/atinject/auto/accessories/SpareTire.java b/tck/com/googlecode/atinject/auto/accessories/SpareTire.java
index 00ad9e6..71848c3 100644
--- a/tck/com/googlecode/atinject/auto/accessories/SpareTire.java
+++ b/tck/com/googlecode/atinject/auto/accessories/SpareTire.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2009 Google Inc.
+/*
+ * Copyright (C) 2009 The JSR-330 Expert Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,34 +14,41 @@
  * limitations under the License.
  */
 
-
 package com.googlecode.atinject.auto.accessories;
 
 import com.googlecode.atinject.Tester;
+import com.googlecode.atinject.auto.FuelTank;
 import com.googlecode.atinject.auto.Tire;
-import com.googlecode.atinject.auto.V8Engine;
 
 import javax.inject.Inject;
 
 public class SpareTire extends Tire {
 
-    V8Engine constructorInjection = NEVER_INJECTED;
-    @Inject V8Engine fieldInjection = NEVER_INJECTED;
-    V8Engine methodInjection = NEVER_INJECTED;
+    FuelTank constructorInjection = NEVER_INJECTED;
+    @Inject FuelTank fieldInjection = NEVER_INJECTED;
+    FuelTank methodInjection = NEVER_INJECTED;
+    @Inject static FuelTank staticFieldInjection = NEVER_INJECTED;
+    static FuelTank staticMethodInjection = NEVER_INJECTED;
 
-
-    @Inject public SpareTire(V8Engine forSupertype, V8Engine forSubtype) {
+    @Inject public SpareTire(FuelTank forSupertype, FuelTank forSubtype) {
         super(forSupertype);
         this.constructorInjection = forSubtype;
     }
 
-    @Inject void subtypeMethodInjection(V8Engine methodInjection) {
+    @Inject void subtypeMethodInjection(FuelTank methodInjection) {
         if (!hasSpareTireBeenFieldInjected()) {
             moreProblems.add("Methods injected before fields");
         }
         this.methodInjection = methodInjection;
     }
 
+    @Inject static void subtypeStaticMethodInjection(FuelTank methodInjection) {
+        if (!hasBeenStaticFieldInjected()) {
+            moreProblems.add("Static methods injected before static fields");
+        }
+        staticMethodInjection = methodInjection;
+    }
+
     @Inject private void injectPrivateMethod() {
         if (subPrivateMethodInjected) {
             moreProblems.add("Overridden private method injected twice");
@@ -94,6 +101,14 @@
         return methodInjection != NEVER_INJECTED;
     }
 
+    public static boolean hasBeenStaticFieldInjected() {
+        return staticFieldInjection != NEVER_INJECTED;
+    }
+
+    public static boolean hasBeenStaticMethodInjected() {
+        return staticMethodInjection != NEVER_INJECTED;
+    }
+
     /**
      * This class is used to check inheritance. By existing in a separate package
      * from Tire, it can make sure the injector does the right thing with overrides
@@ -106,6 +121,10 @@
         tester.test(hasSpareTireBeenMethodInjected(), "Subtype methods not injected");
         tester.test(hasTireBeenFieldInjected(), "Supertype fields not injected");
         tester.test(hasTireBeenMethodInjected(), "Supertype methods not injected");
+        tester.test(SpareTire.hasBeenStaticFieldInjected(), "Subtype static fields not injected");
+        tester.test(SpareTire.hasBeenStaticMethodInjected(), "Subtype static methods not injected");
+        tester.test(Tire.hasBeenStaticFieldInjected(), "Supertype static fields not injected");
+        tester.test(Tire.hasBeenStaticMethodInjected(), "Supertype static methods not injected");
 
         tester.test(superPrivateMethodInjected, "Supertype private method not injected");
         tester.test(superPackagePrivateMethodInjected, "Supertype private method not injected");