1 /*
2  * Copyright (C) 2009 The JSR-330 Expert Group
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.atinject.tck;
18 
19 import org.atinject.tck.auto.Car;
20 import org.atinject.tck.auto.Convertible;
21 
22 import junit.framework.Test;
23 import junit.framework.TestSuite;
24 
25 /**
26  * Manufactures the compatibility test suite. This TCK relies on
27  * <a href="http://junit.org/">JUnit</a>. To integrate the TCK with your
28  * injector, create a JUnit test suite class that passes an injected
29  * {@link Car Car} instance to {@link #testsFor testsFor(Car)}:
30  *
31  * <pre>
32  * import junit.framework.Test;
33  * import org.atinject.tck.Tck;
34  * import org.atinject.tck.auto.Car;
35  *
36  * public class MyTck {
37  *   public static Test suite() {
38  *     Car car = new MyInjector().getInstance(Car.class);
39  *     return Tck.testsFor(car,
40  *         true /* supportsStatic &#42;/,
41  *         true /* supportsPrivate &#42;/);
42  *   }
43  * }</pre>
44  *
45  * <p>The static {@code suite} method that returns a {@code Test} is a JUnit
46  * convention. Feel free to run the returned tests in other ways.
47  *
48  * <p>Configure the injector as follows:
49  *
50  * <ul>
51  *   <li>{@link org.atinject.tck.auto.Car} is implemented by
52  *       {@link org.atinject.tck.auto.Convertible Convertible}.
53  *   <li>{@link org.atinject.tck.auto.Drivers @Drivers}
54  *       {@link org.atinject.tck.auto.Seat Seat} is
55  *       implemented by {@link org.atinject.tck.auto.DriversSeat DriversSeat}.
56  *   <li>{@link org.atinject.tck.auto.Seat Seat} is
57  *       implemented by {@link org.atinject.tck.auto.Seat Seat} itself, and
58  *       {@link org.atinject.tck.auto.Tire Tire} by
59  *       {@link org.atinject.tck.auto.Tire Tire} itself
60  *       (not subclasses).
61  *   <li>{@link org.atinject.tck.auto.Engine Engine} is implemented by
62  *       {@link org.atinject.tck.auto.V8Engine V8Engine}.
63  *   <li>{@link javax.inject.Named @Named("spare")}
64  *       {@link org.atinject.tck.auto.Tire Tire} is implemented by
65  *       {@link org.atinject.tck.auto.accessories.SpareTire SpareTire}.
66  *   <li>The following classes may also be injected directly:
67  *       {@link org.atinject.tck.auto.accessories.Cupholder Cupholder},
68  *       {@link org.atinject.tck.auto.accessories.SpareTire SpareTire}, and
69  *       {@link org.atinject.tck.auto.FuelTank FuelTank}.
70  * </ul>
71  *
72  * <p>Static and private member injection support is optional, but if your
73  * injector supports those features, it must pass the respective tests. If
74  * static member injection is supported, the static members of the following
75  * types shall also be injected once:
76  * {@link org.atinject.tck.auto.Convertible Convertible},
77  * {@link org.atinject.tck.auto.Tire Tire}, and
78  * {@link org.atinject.tck.auto.accessories.SpareTire SpareTire}.
79  *
80  * <p>Use your favorite JUnit tool to run the tests. For example, you can use
81  * your IDE or JUnit's command line runner:
82  *
83  * <pre>
84  * java -cp javax.inject-tck.jar:junit.jar:myinjector.jar \
85  *     junit.textui.TestRunner MyTck</pre>
86  */
87 public class Tck {
88 
Tck()89     private Tck() {}
90 
91     /**
92      * Constructs a JUnit test suite for the given {@link Car} instance.
93      *
94      * @param car to test
95      * @param supportsStatic true if the injector supports static member
96      *  injection
97      * @param supportsPrivate true if the injector supports private member
98      *  injection
99      *
100      * @throws NullPointerException if car is null
101      * @throws ClassCastException if car doesn't extend
102      *  {@link Convertible Convertible}
103      */
testsFor(Car car, boolean supportsStatic, boolean supportsPrivate)104     public static Test testsFor(Car car, boolean supportsStatic,
105             boolean supportsPrivate) {
106         if (car == null) {
107             throw new NullPointerException("car");
108         }
109 
110         if (!(car instanceof Convertible)) {
111             throw new ClassCastException("car doesn't implement Convertible");
112         }
113 
114         Convertible.localConvertible.set((Convertible) car);
115         try {
116             TestSuite suite = new TestSuite(Convertible.Tests.class);
117             if (supportsStatic) {
118                 suite.addTestSuite(Convertible.StaticTests.class);
119             }
120             if (supportsPrivate) {
121                 suite.addTestSuite(Convertible.PrivateTests.class);
122             }
123             return suite;
124         } finally {
125             Convertible.localConvertible.remove();
126         }
127     }
128 }
129