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