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