• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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