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