1 /*
2  * Copyright (C) 2008 The Guava Authors
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 com.google.common.collect.testing.features;
18 
19 import static org.truth0.Truth.ASSERT;
20 
21 import com.google.common.collect.ImmutableSet;
22 import com.google.common.collect.Sets;
23 
24 import junit.framework.TestCase;
25 
26 import java.lang.annotation.Inherited;
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.reflect.Method;
30 import java.util.Collections;
31 import java.util.Set;
32 
33 /**
34  * @author George van den Driessche
35  */
36 // Enum values use constructors with generic varargs.
37 @SuppressWarnings("unchecked")
38 public class FeatureUtilTest extends TestCase {
39   interface ExampleBaseInterface {
behave()40     void behave();
41   }
42 
43   interface ExampleDerivedInterface extends ExampleBaseInterface {
misbehave()44     void misbehave();
45   }
46 
47   enum ExampleBaseFeature implements Feature<ExampleBaseInterface> {
48     BASE_FEATURE_1,
49     BASE_FEATURE_2;
50 
51     @Override
getImpliedFeatures()52     public Set<Feature<? super ExampleBaseInterface>> getImpliedFeatures() {
53       return Collections.emptySet();
54     }
55 
56     @Retention(RetentionPolicy.RUNTIME)
57     @Inherited
58     @TesterAnnotation
59     @interface Require {
value()60       ExampleBaseFeature[] value() default {};
absent()61       ExampleBaseFeature[] absent() default {};
62     }
63   }
64 
65   enum ExampleDerivedFeature implements Feature<ExampleDerivedInterface>{
66     DERIVED_FEATURE_1,
67     DERIVED_FEATURE_2(ExampleBaseFeature.BASE_FEATURE_1),
68     DERIVED_FEATURE_3,
69 
70     COMPOUND_DERIVED_FEATURE(
71         DERIVED_FEATURE_1,
72         DERIVED_FEATURE_2,
73         ExampleBaseFeature.BASE_FEATURE_2);
74 
75     private Set<Feature<? super ExampleDerivedInterface>> implied;
76 
ExampleDerivedFeature( Feature<? super ExampleDerivedInterface> .... implied)77     ExampleDerivedFeature(
78         Feature<? super ExampleDerivedInterface> ... implied) {
79       this.implied = ImmutableSet.copyOf(implied);
80     }
81 
82     @Override
getImpliedFeatures()83     public Set<Feature<? super ExampleDerivedInterface>> getImpliedFeatures() {
84       return implied;
85     }
86 
87     @Retention(RetentionPolicy.RUNTIME)
88     @Inherited
89     @TesterAnnotation
90     @interface Require {
value()91       ExampleDerivedFeature[] value() default {};
absent()92       ExampleDerivedFeature[] absent() default {};
93     }
94   }
95 
96   @Retention(RetentionPolicy.RUNTIME)
97   @interface NonTesterAnnotation {
98   }
99 
100   @ExampleBaseFeature.Require({ExampleBaseFeature.BASE_FEATURE_1})
101   private static abstract class ExampleBaseInterfaceTester extends TestCase {
doNotActuallyRunThis()102     protected final void doNotActuallyRunThis() {
103       fail("Nobody's meant to actually run this!");
104     }
105   }
106 
107   @NonTesterAnnotation
108   @ExampleDerivedFeature.Require({ExampleDerivedFeature.DERIVED_FEATURE_2})
109   private static class ExampleDerivedInterfaceTester
110       extends ExampleBaseInterfaceTester {
111     // Exists to test that our framework doesn't run it:
112     @SuppressWarnings("unused")
113     @ExampleDerivedFeature.Require({
114         ExampleDerivedFeature.DERIVED_FEATURE_1,
115         ExampleDerivedFeature.DERIVED_FEATURE_2})
testRequiringTwoExplicitDerivedFeatures()116     public void testRequiringTwoExplicitDerivedFeatures() throws Exception {
117       doNotActuallyRunThis();
118     }
119 
120     // Exists to test that our framework doesn't run it:
121     @SuppressWarnings("unused")
122     @ExampleDerivedFeature.Require({
123         ExampleDerivedFeature.DERIVED_FEATURE_1,
124         ExampleDerivedFeature.DERIVED_FEATURE_3})
testRequiringAllThreeDerivedFeatures()125     public void testRequiringAllThreeDerivedFeatures() {
126       doNotActuallyRunThis();
127     }
128 
129     // Exists to test that our framework doesn't run it:
130     @SuppressWarnings("unused")
131     @ExampleBaseFeature.Require(absent = {ExampleBaseFeature.BASE_FEATURE_1})
testRequiringConflictingFeatures()132     public void testRequiringConflictingFeatures() throws Exception {
133       doNotActuallyRunThis();
134     }
135   }
136 
137   @ExampleDerivedFeature.Require(
138       absent = {ExampleDerivedFeature.DERIVED_FEATURE_2})
139   private static class ExampleDerivedInterfaceTester_Conflict
140       extends ExampleBaseInterfaceTester {
141   }
142 
testTestFeatureEnums()143   public void testTestFeatureEnums() throws Exception {
144     // Haha! Let's test our own test rig!
145     FeatureEnumTest.assertGoodFeatureEnum(
146         FeatureUtilTest.ExampleBaseFeature.class);
147     FeatureEnumTest.assertGoodFeatureEnum(
148         FeatureUtilTest.ExampleDerivedFeature.class);
149   }
150 
testAddImpliedFeatures_returnsSameSetInstance()151   public void testAddImpliedFeatures_returnsSameSetInstance() throws Exception {
152     Set<Feature<?>> features = Sets.<Feature<?>>newHashSet(
153         ExampleBaseFeature.BASE_FEATURE_1);
154     assertSame(features, FeatureUtil.addImpliedFeatures(features));
155   }
156 
testAddImpliedFeatures_addsImpliedFeatures()157   public void testAddImpliedFeatures_addsImpliedFeatures() throws Exception {
158     Set<Feature<?>> features;
159 
160     features = Sets.<Feature<?>>newHashSet(
161         ExampleDerivedFeature.DERIVED_FEATURE_1);
162     ASSERT.that(FeatureUtil.addImpliedFeatures(features)).has().item(
163         ExampleDerivedFeature.DERIVED_FEATURE_1);
164 
165     features = Sets.<Feature<?>>newHashSet(
166         ExampleDerivedFeature.DERIVED_FEATURE_2);
167     ASSERT.that(FeatureUtil.addImpliedFeatures(features)).has().exactly(
168         ExampleDerivedFeature.DERIVED_FEATURE_2,
169         ExampleBaseFeature.BASE_FEATURE_1);
170 
171     features = Sets.<Feature<?>>newHashSet(
172         ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
173     ASSERT.that(FeatureUtil.addImpliedFeatures(features)).has().exactly(
174         ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE,
175         ExampleDerivedFeature.DERIVED_FEATURE_1,
176         ExampleDerivedFeature.DERIVED_FEATURE_2,
177         ExampleBaseFeature.BASE_FEATURE_1,
178         ExampleBaseFeature.BASE_FEATURE_2);
179   }
180 
testImpliedFeatures_returnsNewSetInstance()181   public void testImpliedFeatures_returnsNewSetInstance() throws Exception {
182     Set<Feature<?>> features = Sets.<Feature<?>>newHashSet(
183         ExampleBaseFeature.BASE_FEATURE_1);
184     assertNotSame(features, FeatureUtil.impliedFeatures(features));
185   }
186 
testImpliedFeatures_returnsImpliedFeatures()187   public void testImpliedFeatures_returnsImpliedFeatures() throws Exception {
188     Set<Feature<?>> features;
189 
190     features = Sets.<Feature<?>>newHashSet(
191         ExampleDerivedFeature.DERIVED_FEATURE_1);
192     assertTrue(FeatureUtil.impliedFeatures(features).isEmpty());
193 
194     features = Sets.<Feature<?>>newHashSet(
195         ExampleDerivedFeature.DERIVED_FEATURE_2);
196     ASSERT.that(FeatureUtil.impliedFeatures(features)).has().item(
197         ExampleBaseFeature.BASE_FEATURE_1);
198 
199     features = Sets.<Feature<?>>newHashSet(
200         ExampleDerivedFeature.COMPOUND_DERIVED_FEATURE);
201     ASSERT.that(FeatureUtil.impliedFeatures(features)).has().exactly(
202         ExampleDerivedFeature.DERIVED_FEATURE_1,
203         ExampleDerivedFeature.DERIVED_FEATURE_2,
204         ExampleBaseFeature.BASE_FEATURE_1,
205         ExampleBaseFeature.BASE_FEATURE_2);
206   }
207 
testBuildTesterRequirements_class()208   public void testBuildTesterRequirements_class() throws Exception {
209     assertEquals(FeatureUtil.buildTesterRequirements(
210             ExampleBaseInterfaceTester.class),
211         new TesterRequirements(
212             Sets.<Feature<?>>newHashSet(ExampleBaseFeature.BASE_FEATURE_1),
213             Collections.<Feature<?>>emptySet()));
214 
215     assertEquals(FeatureUtil.buildTesterRequirements(
216             ExampleDerivedInterfaceTester.class),
217         new TesterRequirements(
218             Sets.<Feature<?>>newHashSet(
219                 ExampleBaseFeature.BASE_FEATURE_1,
220                 ExampleDerivedFeature.DERIVED_FEATURE_2),
221             Collections.<Feature<?>>emptySet()));
222   }
223 
testBuildTesterRequirements_method()224   public void testBuildTesterRequirements_method() throws Exception {
225     assertEquals(FeatureUtil.buildTesterRequirements(
226         ExampleDerivedInterfaceTester.class.getMethod(
227             "testRequiringTwoExplicitDerivedFeatures")),
228         new TesterRequirements(
229             Sets.<Feature<?>>newHashSet(
230                 ExampleBaseFeature.BASE_FEATURE_1,
231                 ExampleDerivedFeature.DERIVED_FEATURE_1,
232                 ExampleDerivedFeature.DERIVED_FEATURE_2),
233             Collections.<Feature<?>>emptySet()));
234     assertEquals(FeatureUtil.buildTesterRequirements(
235         ExampleDerivedInterfaceTester.class.getMethod(
236             "testRequiringAllThreeDerivedFeatures")),
237         new TesterRequirements(
238             Sets.<Feature<?>>newHashSet(
239                 ExampleBaseFeature.BASE_FEATURE_1,
240                 ExampleDerivedFeature.DERIVED_FEATURE_1,
241                 ExampleDerivedFeature.DERIVED_FEATURE_2,
242                 ExampleDerivedFeature.DERIVED_FEATURE_3),
243             Collections.<Feature<?>>emptySet()));
244   }
245 
testBuildTesterRequirements_classClassConflict()246   public void testBuildTesterRequirements_classClassConflict()
247       throws Exception {
248     try {
249       FeatureUtil.buildTesterRequirements(
250           ExampleDerivedInterfaceTester_Conflict.class);
251       fail("Expected ConflictingRequirementsException");
252     } catch (ConflictingRequirementsException e) {
253       ASSERT.that(e.getConflicts()).has().item(
254           ExampleBaseFeature.BASE_FEATURE_1);
255       assertEquals(ExampleDerivedInterfaceTester_Conflict.class, e.getSource());
256     }
257   }
258 
testBuildTesterRequirements_methodClassConflict()259   public void testBuildTesterRequirements_methodClassConflict()
260       throws Exception {
261     final Method method = ExampleDerivedInterfaceTester.class
262         .getMethod("testRequiringConflictingFeatures");
263     try {
264       FeatureUtil.buildTesterRequirements(method);
265       fail("Expected ConflictingRequirementsException");
266     } catch (ConflictingRequirementsException e) {
267       ASSERT.that(e.getConflicts()).has().item(
268           ExampleBaseFeature.BASE_FEATURE_1);
269       assertEquals(method, e.getSource());
270     }
271   }
272 
testBuildDeclaredTesterRequirements()273   public void testBuildDeclaredTesterRequirements() throws Exception {
274     assertEquals(FeatureUtil.buildDeclaredTesterRequirements(
275         ExampleDerivedInterfaceTester.class
276             .getMethod("testRequiringTwoExplicitDerivedFeatures")),
277         new TesterRequirements(FeatureUtil.addImpliedFeatures(
278             Sets.<Feature<?>>newHashSet(
279                 ExampleDerivedFeature.DERIVED_FEATURE_1,
280                 ExampleDerivedFeature.DERIVED_FEATURE_2)),
281             Collections.<Feature<?>>emptySet()));
282   }
283 
284 }
285