1 /* 2 * Copyright (C) 2020 The Dagger 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 dagger.functional.assisted; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import dagger.Component; 22 import dagger.assisted.Assisted; 23 import dagger.assisted.AssistedFactory; 24 import dagger.assisted.AssistedInject; 25 import javax.inject.Inject; 26 import javax.inject.Provider; 27 import org.junit.Test; 28 import org.junit.runner.RunWith; 29 import org.junit.runners.JUnit4; 30 31 @RunWith(JUnit4.class) 32 public final class AssistedFactoryTest { 33 @Component 34 interface ParentComponent { 35 // Simple factory using a nested factory. nestedSimpleFooFactory()36 SimpleFoo.Factory nestedSimpleFooFactory(); 37 nestedSimpleFooFactoryProvider()38 Provider<SimpleFoo.Factory> nestedSimpleFooFactoryProvider(); 39 40 // Simple factory using a non-nested factory. nonNestedSimpleFooFactory()41 SimpleFooFactory nonNestedSimpleFooFactory(); 42 43 // Simple factory using a factory that extends a supertype. extendedSimpleFooFactory()44 ExtendedSimpleFooFactory extendedSimpleFooFactory(); 45 46 // Factory as interface fooFactory()47 FooFactory fooFactory(); 48 49 // Factory as abstract class abstractFooFactory()50 AbstractFooFactory abstractFooFactory(); 51 52 // Factory without any assisted parameters noAssistedParametersFooFactory()53 NoAssistedParametersFooFactory noAssistedParametersFooFactory(); 54 55 // Test injecting the factories from another class someEntryPoint()56 SomeEntryPoint someEntryPoint(); 57 } 58 59 // This class tests the request of factories from another binding. 60 static class SomeEntryPoint { 61 private final SimpleFoo.Factory nestedSimpleFooFactory; 62 private final SimpleFooFactory nonNestedSimpleFooFactory; 63 private final Provider<SimpleFoo.Factory> nestedSimpleFooFactoryProvider; 64 private final ExtendedSimpleFooFactory extendedSimpleFooFactory; 65 private final FooFactory fooFactory; 66 private final AbstractFooFactory abstractFooFactory; 67 private final NoAssistedParametersFooFactory noAssistedParametersFooFactory; 68 69 @Inject SomeEntryPoint( SimpleFoo.Factory nestedSimpleFooFactory, Provider<SimpleFoo.Factory> nestedSimpleFooFactoryProvider, SimpleFooFactory nonNestedSimpleFooFactory, ExtendedSimpleFooFactory extendedSimpleFooFactory, FooFactory fooFactory, AbstractFooFactory abstractFooFactory, NoAssistedParametersFooFactory noAssistedParametersFooFactory)70 SomeEntryPoint( 71 SimpleFoo.Factory nestedSimpleFooFactory, 72 Provider<SimpleFoo.Factory> nestedSimpleFooFactoryProvider, 73 SimpleFooFactory nonNestedSimpleFooFactory, 74 ExtendedSimpleFooFactory extendedSimpleFooFactory, 75 FooFactory fooFactory, 76 AbstractFooFactory abstractFooFactory, 77 NoAssistedParametersFooFactory noAssistedParametersFooFactory) { 78 this.nestedSimpleFooFactory = nestedSimpleFooFactory; 79 this.nestedSimpleFooFactoryProvider = nestedSimpleFooFactoryProvider; 80 this.nonNestedSimpleFooFactory = nonNestedSimpleFooFactory; 81 this.extendedSimpleFooFactory = extendedSimpleFooFactory; 82 this.fooFactory = fooFactory; 83 this.abstractFooFactory = abstractFooFactory; 84 this.noAssistedParametersFooFactory = noAssistedParametersFooFactory; 85 } 86 } 87 88 static final class Dep1 { 89 @Inject Dep1(Dep2 dep2, Dep3 dep3)90 Dep1(Dep2 dep2, Dep3 dep3) {} 91 } 92 93 static final class Dep2 { 94 @Inject Dep2(Dep3 dep3)95 Dep2(Dep3 dep3) {} 96 } 97 98 static final class Dep3 { 99 @Inject Dep3(Dep4 dep4)100 Dep3(Dep4 dep4) {} 101 } 102 103 static final class Dep4 { 104 @Inject Dep4()105 Dep4() {} 106 } 107 108 // A base interface to test that factories can reference subclasses of the assisted parameter. 109 interface AssistedDep {} 110 111 static final class AssistedDep1 implements AssistedDep {} 112 113 static final class AssistedDep2 implements AssistedDep {} 114 115 static final class SimpleFoo { 116 private final AssistedDep assistedDep; 117 118 @AssistedInject SimpleFoo(@ssisted AssistedDep assistedDep)119 SimpleFoo(@Assisted AssistedDep assistedDep) { 120 this.assistedDep = assistedDep; 121 } 122 123 @AssistedFactory 124 interface Factory { 125 // Use different parameter names than Foo to make sure we're not assuming they're the same. createSimpleFoo(AssistedDep factoryAssistedDep)126 SimpleFoo createSimpleFoo(AssistedDep factoryAssistedDep); 127 128 // A no-op method to test static methods in assisted factories staticMethod()129 static void staticMethod() { 130 return; 131 } 132 133 // A no-op method to test default methods in assisted factories defaultMethod()134 default void defaultMethod() { 135 return; 136 } 137 } 138 } 139 140 @AssistedFactory 141 interface SimpleFooFactory { 142 // Use different parameter names than Foo to make sure we're not assuming they're the same. createSimpleFoo(AssistedDep factoryAssistedDep1)143 SimpleFoo createSimpleFoo(AssistedDep factoryAssistedDep1); 144 145 // A no-op method to test static methods are allowed staticMethod()146 static void staticMethod() { 147 return; 148 } 149 150 // A no-op method to test static methods that return assisted type are allowed staticSimpleFooMethod()151 static SimpleFoo staticSimpleFooMethod() { 152 return null; 153 } 154 155 // A no-op method to test default methods are allowed defaultMethod()156 default void defaultMethod() { 157 return; 158 } 159 160 // A no-op method to test default methods that return assisted type are allowed defaultSimpleFooMethod()161 default SimpleFoo defaultSimpleFooMethod() { 162 return null; 163 } 164 } 165 166 @AssistedFactory 167 interface ExtendedSimpleFooFactory extends SimpleFooFactory {} 168 169 abstract static class BaseFoo { 170 @Inject Dep4 dep4; 171 } 172 173 static final class Foo extends BaseFoo { 174 private final Dep1 dep1; 175 private final Provider<Dep2> dep2Provider; 176 private final AssistedDep1 assistedDep1; 177 private final AssistedDep2 assistedDep2; 178 private final int assistedInt; 179 private final FooFactory factory; 180 181 @Inject Dep3 dep3; 182 183 @AssistedInject Foo( Dep1 dep1, @Assisted AssistedDep1 assistedDep1, Provider<Dep2> dep2Provider, @Assisted AssistedDep2 assistedDep2, @Assisted int assistedInt, FooFactory factory)184 Foo( 185 Dep1 dep1, 186 @Assisted AssistedDep1 assistedDep1, 187 Provider<Dep2> dep2Provider, 188 @Assisted AssistedDep2 assistedDep2, 189 @Assisted int assistedInt, 190 FooFactory factory) { 191 this.dep1 = dep1; 192 this.dep2Provider = dep2Provider; 193 this.assistedDep1 = assistedDep1; 194 this.assistedDep2 = assistedDep2; 195 this.assistedInt = assistedInt; 196 this.factory = factory; 197 } 198 } 199 200 @AssistedFactory 201 interface FooFactory { 202 // Use different parameter names than Foo to make sure we're not assuming they're the same. createFoo( AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt)203 Foo createFoo( 204 AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt); 205 } 206 207 @AssistedFactory 208 abstract static class AbstractFooFactory { 209 // Use different parameter names than Foo to make sure we're not assuming they're the same. createFoo( AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt)210 abstract Foo createFoo( 211 AssistedDep1 factoryAssistedDep1, AssistedDep2 factoryAssistedDep2, int factoryAssistedInt); 212 213 // A no-op method to test static methods are allowed staticMethod()214 static void staticMethod() { 215 return; 216 } 217 218 // A no-op method to test static methods that return assisted type are allowed staticFooMethod()219 static Foo staticFooMethod() { 220 return null; 221 } 222 223 // A no-op method to test concrete methods are allowed concreteMethod()224 void concreteMethod() { 225 return; 226 } 227 228 // A no-op method to test concrete methods that return assisted type are allowed concreteFooMethod()229 Foo concreteFooMethod() { 230 return null; 231 } 232 } 233 234 static final class NoAssistedParametersFoo extends BaseFoo { 235 private final Dep1 dep1; 236 private final Provider<Dep2> dep2Provider; 237 private final NoAssistedParametersFooFactory factory; 238 239 @Inject Dep3 dep3; 240 241 @AssistedInject NoAssistedParametersFoo( Dep1 dep1, Provider<Dep2> dep2Provider, NoAssistedParametersFooFactory factory)242 NoAssistedParametersFoo( 243 Dep1 dep1, Provider<Dep2> dep2Provider, NoAssistedParametersFooFactory factory) { 244 this.dep1 = dep1; 245 this.dep2Provider = dep2Provider; 246 this.factory = factory; 247 } 248 } 249 250 @AssistedFactory 251 interface NoAssistedParametersFooFactory { createNoAssistedParametersFoo()252 NoAssistedParametersFoo createNoAssistedParametersFoo(); 253 } 254 255 @Test testNestedSimpleFooFactory()256 public void testNestedSimpleFooFactory() { 257 AssistedDep1 assistedDep1 = new AssistedDep1(); 258 SimpleFoo simpleFoo1 = 259 DaggerAssistedFactoryTest_ParentComponent.create() 260 .nestedSimpleFooFactory() 261 .createSimpleFoo(assistedDep1); 262 assertThat(simpleFoo1.assistedDep).isEqualTo(assistedDep1); 263 264 AssistedDep2 assistedDep2 = new AssistedDep2(); 265 SimpleFoo simpleFoo2 = 266 DaggerAssistedFactoryTest_ParentComponent.create() 267 .nestedSimpleFooFactory() 268 .createSimpleFoo(assistedDep2); 269 assertThat(simpleFoo2.assistedDep).isEqualTo(assistedDep2); 270 } 271 272 @Test testNestedSimpleFooFactoryProvider()273 public void testNestedSimpleFooFactoryProvider() { 274 AssistedDep1 assistedDep1 = new AssistedDep1(); 275 SimpleFoo simpleFoo1 = 276 DaggerAssistedFactoryTest_ParentComponent.create() 277 .nestedSimpleFooFactoryProvider() 278 .get() 279 .createSimpleFoo(assistedDep1); 280 assertThat(simpleFoo1.assistedDep).isEqualTo(assistedDep1); 281 282 AssistedDep2 assistedDep2 = new AssistedDep2(); 283 SimpleFoo simpleFoo2 = 284 DaggerAssistedFactoryTest_ParentComponent.create() 285 .nestedSimpleFooFactoryProvider() 286 .get() 287 .createSimpleFoo(assistedDep2); 288 assertThat(simpleFoo2.assistedDep).isEqualTo(assistedDep2); 289 } 290 291 @Test testNonNestedSimpleFooFactory()292 public void testNonNestedSimpleFooFactory() { 293 AssistedDep1 assistedDep1 = new AssistedDep1(); 294 SimpleFoo simpleFoo = 295 DaggerAssistedFactoryTest_ParentComponent.create() 296 .nonNestedSimpleFooFactory() 297 .createSimpleFoo(assistedDep1); 298 assertThat(simpleFoo.assistedDep).isEqualTo(assistedDep1); 299 } 300 301 @Test testExtendedSimpleFooFactory()302 public void testExtendedSimpleFooFactory() { 303 AssistedDep1 assistedDep1 = new AssistedDep1(); 304 SimpleFoo simpleFoo = 305 DaggerAssistedFactoryTest_ParentComponent.create() 306 .extendedSimpleFooFactory() 307 .createSimpleFoo(assistedDep1); 308 assertThat(simpleFoo.assistedDep).isEqualTo(assistedDep1); 309 } 310 311 @Test testFooFactory()312 public void testFooFactory() { 313 AssistedDep1 assistedDep1 = new AssistedDep1(); 314 AssistedDep2 assistedDep2 = new AssistedDep2(); 315 int assistedInt = 7; 316 Foo foo = 317 DaggerAssistedFactoryTest_ParentComponent.create() 318 .fooFactory() 319 .createFoo(assistedDep1, assistedDep2, assistedInt); 320 assertThat(foo.dep1).isNotNull(); 321 assertThat(foo.dep2Provider).isNotNull(); 322 assertThat(foo.dep2Provider.get()).isNotNull(); 323 assertThat(foo.dep3).isNotNull(); 324 assertThat(foo.dep4).isNotNull(); 325 assertThat(foo.assistedDep1).isEqualTo(assistedDep1); 326 assertThat(foo.assistedDep2).isEqualTo(assistedDep2); 327 assertThat(foo.assistedInt).isEqualTo(assistedInt); 328 assertThat(foo.factory).isNotNull(); 329 } 330 331 @Test testNoAssistedParametersFooFactory()332 public void testNoAssistedParametersFooFactory() { 333 NoAssistedParametersFoo foo = 334 DaggerAssistedFactoryTest_ParentComponent.create() 335 .noAssistedParametersFooFactory() 336 .createNoAssistedParametersFoo(); 337 assertThat(foo.dep1).isNotNull(); 338 assertThat(foo.dep2Provider).isNotNull(); 339 assertThat(foo.dep2Provider.get()).isNotNull(); 340 assertThat(foo.dep3).isNotNull(); 341 assertThat(foo.dep4).isNotNull(); 342 assertThat(foo.factory).isNotNull(); 343 } 344 345 @Test testAssistedFactoryFromSomeEntryPoint()346 public void testAssistedFactoryFromSomeEntryPoint() { 347 SomeEntryPoint someEntryPoint = 348 DaggerAssistedFactoryTest_ParentComponent.create().someEntryPoint(); 349 assertThat(someEntryPoint.nestedSimpleFooFactory).isNotNull(); 350 assertThat(someEntryPoint.nestedSimpleFooFactoryProvider).isNotNull(); 351 assertThat(someEntryPoint.nonNestedSimpleFooFactory).isNotNull(); 352 assertThat(someEntryPoint.extendedSimpleFooFactory).isNotNull(); 353 assertThat(someEntryPoint.fooFactory).isNotNull(); 354 assertThat(someEntryPoint.abstractFooFactory).isNotNull(); 355 assertThat(someEntryPoint.noAssistedParametersFooFactory).isNotNull(); 356 } 357 } 358