• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 import static com.google.common.truth.Truth8.assertThat;
21 import static java.lang.annotation.RetentionPolicy.RUNTIME;
22 
23 import dagger.Binds;
24 import dagger.BindsInstance;
25 import dagger.BindsOptionalOf;
26 import dagger.Component;
27 import dagger.Module;
28 import dagger.Provides;
29 import dagger.assisted.AssistedFactory;
30 import dagger.assisted.AssistedInject;
31 import dagger.multibindings.IntoSet;
32 import dagger.multibindings.Multibinds;
33 import java.lang.annotation.Retention;
34 import java.util.Optional;
35 import java.util.Set;
36 import javax.inject.Inject;
37 import javax.inject.Qualifier;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.junit.runners.JUnit4;
41 
42 /** Tests that qualified assisted types can be provided and injected as normal types. */
43 @RunWith(JUnit4.class)
44 public final class AssistedFactoryAsQualifiedBindingTest {
45 
46   @Qualifier
47   @Retention(RUNTIME)
48   @interface AsComponentDependency {}
49 
50   @Qualifier
51   @Retention(RUNTIME)
52   @interface AsProvides {}
53 
54   @Qualifier
55   @Retention(RUNTIME)
56   @interface AsBinds {}
57 
58   @Qualifier
59   @Retention(RUNTIME)
60   @interface AsOptional {}
61 
62   @Qualifier
63   @Retention(RUNTIME)
64   @interface AsMultibinding {}
65 
66   @Component(modules = BarFactoryModule.class)
67   interface TestComponent {
foo()68     Foo foo();
69 
70     @Component.Factory
71     interface Factory {
create( @indsInstance @sComponentDependency Bar bar, @BindsInstance @AsComponentDependency BarFactory barFactory)72       TestComponent create(
73           @BindsInstance @AsComponentDependency Bar bar,
74           @BindsInstance @AsComponentDependency BarFactory barFactory);
75     }
76   }
77 
78   @Module
79   interface BarFactoryModule {
80 
81     @Provides
82     @AsProvides
providesBar(@sComponentDependency Bar bar)83     static Bar providesBar(@AsComponentDependency Bar bar) {
84       return bar;
85     }
86 
87     @Provides
88     @AsProvides
providesBarFactory(@sComponentDependency BarFactory barFactory)89     static BarFactory providesBarFactory(@AsComponentDependency BarFactory barFactory) {
90       return barFactory;
91     }
92 
93     @Binds
94     @AsBinds
bindsBar(@sComponentDependency Bar bar)95     Bar bindsBar(@AsComponentDependency Bar bar);
96 
97     @Binds
98     @AsBinds
bindsBarFactory(@sComponentDependency BarFactory barFactory)99     BarFactory bindsBarFactory(@AsComponentDependency BarFactory barFactory);
100 
101     @BindsOptionalOf
102     @AsOptional
optionalBar()103     Bar optionalBar();
104 
105     @BindsOptionalOf
106     @AsOptional
optionalBarFactory()107     BarFactory optionalBarFactory();
108 
109     @Provides
110     @AsOptional
providesOptionalBar(@sComponentDependency Bar bar)111     static Bar providesOptionalBar(@AsComponentDependency Bar bar) {
112       return bar;
113     }
114 
115     @Provides
116     @AsOptional
providesOptionalBarFactory(@sComponentDependency BarFactory barFactory)117     static BarFactory providesOptionalBarFactory(@AsComponentDependency BarFactory barFactory) {
118       return barFactory;
119     }
120 
121     @Multibinds
122     @AsMultibinding
barSet()123     Set<Bar> barSet();
124 
125     @Multibinds
126     @AsMultibinding
barFactorySet()127     Set<BarFactory> barFactorySet();
128 
129     @Provides
130     @IntoSet
131     @AsMultibinding
providesMultibindingBar(@sComponentDependency Bar bar)132     static Bar providesMultibindingBar(@AsComponentDependency Bar bar) {
133       return bar;
134     }
135 
136     @Provides
137     @IntoSet
138     @AsMultibinding
providesMultibindingBarFactory(@sComponentDependency BarFactory barFactory)139     static BarFactory providesMultibindingBarFactory(@AsComponentDependency BarFactory barFactory) {
140       return barFactory;
141     }
142 
143     @Multibinds
unqualifiedBarSet()144     Set<Bar> unqualifiedBarSet();
145 
146     @Multibinds
unqualifiedBarFactorySet()147     Set<BarFactory> unqualifiedBarFactorySet();
148 
149     @Provides
150     @IntoSet
providesUnqualifiedMultibindingBar(@sComponentDependency Bar bar)151     static Bar providesUnqualifiedMultibindingBar(@AsComponentDependency Bar bar) {
152       return bar;
153     }
154 
155     @Provides
156     @IntoSet
providesUnqualifiedMultibindingBarFactory( @sComponentDependency BarFactory barFactory)157     static BarFactory providesUnqualifiedMultibindingBarFactory(
158         @AsComponentDependency BarFactory barFactory) {
159       return barFactory;
160     }
161   }
162 
163   static class Foo {
164     private final BarFactory barFactory;
165     private final Bar barAsComponentDependency;
166     private final BarFactory barFactoryAsComponentDependency;
167     private final Bar barAsProvides;
168     private final BarFactory barFactoryAsProvides;
169     private final Bar barAsBinds;
170     private final BarFactory barFactoryAsBinds;
171     private final Optional<Bar> optionalBar;
172     private final Optional<BarFactory> optionalBarFactory;
173     private final Set<Bar> barSet;
174     private final Set<BarFactory> barFactorySet;
175     private final Set<Bar> unqualifiedBarSet;
176     private final Set<BarFactory> unqualifiedBarFactorySet;
177 
178     @Inject
Foo( BarFactory barFactory, @AsComponentDependency Bar barAsComponentDependency, @AsComponentDependency BarFactory barFactoryAsComponentDependency, @AsProvides Bar barAsProvides, @AsProvides BarFactory barFactoryAsProvides, @AsBinds Bar barAsBinds, @AsBinds BarFactory barFactoryAsBinds, @AsOptional Optional<Bar> optionalBar, @AsOptional Optional<BarFactory> optionalBarFactory, @AsMultibinding Set<Bar> barSet, @AsMultibinding Set<BarFactory> barFactorySet, Set<Bar> unqualifiedBarSet, Set<BarFactory> unqualifiedBarFactorySet)179     Foo(
180         BarFactory barFactory,
181         @AsComponentDependency Bar barAsComponentDependency,
182         @AsComponentDependency BarFactory barFactoryAsComponentDependency,
183         @AsProvides Bar barAsProvides,
184         @AsProvides BarFactory barFactoryAsProvides,
185         @AsBinds Bar barAsBinds,
186         @AsBinds BarFactory barFactoryAsBinds,
187         @AsOptional Optional<Bar> optionalBar,
188         @AsOptional Optional<BarFactory> optionalBarFactory,
189         @AsMultibinding Set<Bar> barSet,
190         @AsMultibinding Set<BarFactory> barFactorySet,
191         Set<Bar> unqualifiedBarSet,
192         Set<BarFactory> unqualifiedBarFactorySet) {
193       this.barFactory = barFactory;
194       this.barAsComponentDependency = barAsComponentDependency;
195       this.barFactoryAsComponentDependency = barFactoryAsComponentDependency;
196       this.barAsProvides = barAsProvides;
197       this.barFactoryAsProvides = barFactoryAsProvides;
198       this.barAsBinds = barAsBinds;
199       this.barFactoryAsBinds = barFactoryAsBinds;
200       this.optionalBar = optionalBar;
201       this.optionalBarFactory = optionalBarFactory;
202       this.barSet = barSet;
203       this.barFactorySet = barFactorySet;
204       this.unqualifiedBarSet = unqualifiedBarSet;
205       this.unqualifiedBarFactorySet = unqualifiedBarFactorySet;
206     }
207   }
208 
209   static class Bar {
210     @AssistedInject
Bar()211     Bar() {}
212   }
213 
214   @AssistedFactory
215   interface BarFactory {
create()216     Bar create();
217   }
218 
219   @Test
testFoo()220   public void testFoo() {
221     Bar bar = new Bar();
222     BarFactory barFactory = () -> bar;
223     Foo foo =
224         DaggerAssistedFactoryAsQualifiedBindingTest_TestComponent.factory()
225             .create(bar, barFactory)
226             .foo();
227 
228     // Test we can inject the "real" BarFactory implemented by Dagger
229     assertThat(foo.barFactory).isNotNull();
230     assertThat(foo.barFactory).isNotEqualTo(barFactory);
231     assertThat(foo.barFactory.create()).isNotEqualTo(bar);
232 
233     // Test injection of a qualified Bar/BarFactory with custom @BindsInstance implementation
234     assertThat(foo.barAsComponentDependency).isEqualTo(bar);
235     assertThat(foo.barFactoryAsComponentDependency).isEqualTo(barFactory);
236 
237     // Test injection of a qualified Bar/BarFactory with custom @Provides implementation
238     assertThat(foo.barAsProvides).isEqualTo(bar);
239     assertThat(foo.barFactoryAsProvides).isEqualTo(barFactory);
240 
241     // Test injection of a qualified Bar/BarFactory with custom @Binds implementation
242     assertThat(foo.barAsBinds).isEqualTo(bar);
243     assertThat(foo.barFactoryAsBinds).isEqualTo(barFactory);
244 
245     // Test injection of a qualified Bar/BarFactory with custom @BindsOptionalOf implementation
246     assertThat(foo.optionalBar).isPresent();
247     assertThat(foo.optionalBar).hasValue(bar);
248     assertThat(foo.optionalBarFactory).isPresent();
249     assertThat(foo.optionalBarFactory).hasValue(barFactory);
250 
251     // Test injection of a qualified Bar/BarFactory as multibinding
252     assertThat(foo.barSet).containsExactly(bar);
253     assertThat(foo.barFactorySet).containsExactly(barFactory);
254 
255     // Test injection of a unqualified Bar/BarFactory as multibinding
256     assertThat(foo.unqualifiedBarSet).containsExactly(bar);
257     assertThat(foo.unqualifiedBarFactorySet).containsExactly(barFactory);
258   }
259 }
260