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