xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/MultibindingTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2016 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.internal.codegen;
18 
19 import androidx.room.compiler.processing.util.Source;
20 import dagger.testing.compile.CompilerTests;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.junit.runners.JUnit4;
24 
25 @RunWith(JUnit4.class)
26 public class MultibindingTest {
27 
28   @Test
providesWithTwoMultibindingAnnotations_failsToCompile()29   public void providesWithTwoMultibindingAnnotations_failsToCompile() {
30     Source module =
31         CompilerTests.javaSource(
32             "test.MultibindingModule",
33             "package test;",
34             "",
35             "import dagger.Module;",
36             "import dagger.Provides;",
37             "import dagger.multibindings.IntoSet;",
38             "import dagger.multibindings.IntoMap;",
39             "",
40             "@Module",
41             "class MultibindingModule {",
42             "  @Provides",
43             "  @IntoSet",
44             "  @IntoMap",
45             "  Integer provideInt() { ",
46             "    return 1;",
47             "  }",
48             "}");
49 
50     CompilerTests.daggerCompiler(module)
51         .compile(
52             subject -> {
53               subject.hasErrorCount(3);
54               subject.hasErrorContaining(
55                       "@Provides methods cannot have more than one multibinding annotation")
56                   .onSource(module)
57                   .onLine(11);
58               subject.hasErrorContaining(
59                       "@Provides methods cannot have more than one multibinding annotation")
60                   .onSource(module)
61                   .onLine(12);
62               subject.hasErrorContaining("@Provides methods of type map must declare a map key")
63                   .onSource(module)
64                   .onLine(13);
65             });
66   }
67 
68   @Test
appliedOnInvalidMethods_failsToCompile()69   public void appliedOnInvalidMethods_failsToCompile() {
70     Source someType =
71         CompilerTests.javaSource(
72             "test.SomeType",
73             "package test;",
74             "",
75             "import java.util.Set;",
76             "import java.util.Map;",
77             "import dagger.Component;",
78             "import dagger.multibindings.IntoSet;",
79             "import dagger.multibindings.ElementsIntoSet;",
80             "import dagger.multibindings.IntoMap;",
81             "",
82             "interface SomeType {",
83             "  @IntoSet Set<Integer> ints();",
84             "  @ElementsIntoSet Set<Double> doubles();",
85             "  @IntoMap Map<Integer, Double> map();",
86             "}");
87 
88     CompilerTests.daggerCompiler(someType)
89         .compile(
90             subject -> {
91               subject.hasErrorCount(3);
92               String error =
93                   "Multibinding annotations may only be on @Provides, @Produces, or @Binds methods";
94               subject.hasErrorContaining(error).onSource(someType).onLineContaining("ints();");
95               subject.hasErrorContaining(error).onSource(someType).onLineContaining("doubles();");
96               subject.hasErrorContaining(error).onSource(someType).onLineContaining("map();");
97             });
98   }
99 
100   @Test
concreteBindingForMultibindingAlias()101   public void concreteBindingForMultibindingAlias() {
102     Source module =
103         CompilerTests.javaSource(
104             "test.TestModule",
105             "package test;",
106             "",
107             "import dagger.Module;",
108             "import dagger.Provides;",
109             "import java.util.Collections;",
110             "import java.util.Map;",
111             "import javax.inject.Provider;",
112             "",
113             "@Module",
114             "class TestModule {",
115             "  @Provides",
116             "  Map<String, Provider<String>> mapOfStringToProviderOfString() {",
117             "    return Collections.emptyMap();",
118             "  }",
119             "}");
120     Source component =
121         CompilerTests.javaSource(
122             "test.TestComponent",
123             "package test;",
124             "",
125             "import dagger.Component;",
126             "import java.util.Map;",
127             "",
128             "@Component(modules = TestModule.class)",
129             "interface TestComponent {",
130             "  Map<String, String> mapOfStringToString();",
131             "}");
132     CompilerTests.daggerCompiler(module, component)
133         .compile(
134             subject -> {
135               subject.hasErrorCount(1);
136               subject.hasErrorContaining(
137                       "Map<String,String> cannot be provided without an @Provides-annotated method")
138                   .onSource(component)
139                   .onLineContaining("interface TestComponent");
140             });
141   }
142 
143   @Test
produceConcreteSet_andRequestSetOfProduced()144   public void produceConcreteSet_andRequestSetOfProduced() {
145     Source module =
146         CompilerTests.javaSource(
147             "test.TestModule",
148             "package test;",
149             "",
150             "import dagger.producers.ProducerModule;",
151             "import dagger.producers.Produces;",
152             "import java.util.Collections;",
153             "import java.util.Set;",
154             "",
155             "@ProducerModule",
156             "class TestModule {",
157             "  @Produces",
158             "  Set<String> setOfString() {",
159             "    return Collections.emptySet();",
160             "  }",
161             "}");
162     Source component =
163         CompilerTests.javaSource(
164             "test.TestComponent",
165             "package test;",
166             "",
167             "import com.google.common.util.concurrent.ListenableFuture;",
168             "import dagger.BindsInstance;",
169             "import dagger.producers.Produced;",
170             "import dagger.producers.Production;",
171             "import dagger.producers.ProductionComponent;",
172             "import java.util.concurrent.Executor;",
173             "import java.util.Set;",
174             "",
175             "@ProductionComponent(modules = TestModule.class)",
176             "interface TestComponent {",
177             "  ListenableFuture<Set<Produced<String>>> setOfProduced();",
178             "",
179             "  @ProductionComponent.Builder",
180             "  interface Builder {",
181             "    @BindsInstance Builder executor(@Production Executor executor);",
182             "    TestComponent build();",
183             "  }",
184             "}");
185     CompilerTests.daggerCompiler(module, component)
186         .compile(
187             subject -> {
188               subject.hasErrorCount(1);
189               subject.hasErrorContaining(
190                       "Set<Produced<String>> cannot be provided without an @Provides- or "
191                           + "@Produces-annotated method")
192                   .onSource(component)
193                   .onLineContaining("interface TestComponent");
194             });
195   }
196 
197   @Test
provideExplicitSetInParent_AndMultibindingContributionInChild()198   public void provideExplicitSetInParent_AndMultibindingContributionInChild() {
199     Source parent =
200         CompilerTests.javaSource(
201             "test.Parent",
202             "package test;",
203             "",
204             "import dagger.Component;",
205             "import java.util.Set;",
206             "",
207             "@Component(modules = ParentModule.class)",
208             "interface Parent {",
209             "  Set<String> set();",
210             "  Child child();",
211             "}");
212     Source parentModule =
213         CompilerTests.javaSource(
214             "test.ParentModule",
215             "package test;",
216             "",
217             "import dagger.Module;",
218             "import dagger.Provides;",
219             "import java.util.HashSet;",
220             "import java.util.Set;",
221             "",
222             "@Module",
223             "class ParentModule {",
224             "  @Provides",
225             "  Set<String> set() {",
226             "    return new HashSet();",
227             "  }",
228             "}");
229 
230     Source child =
231         CompilerTests.javaSource(
232             "test.Child",
233             "package test;",
234             "",
235             "import dagger.Subcomponent;",
236             "import java.util.Set;",
237             "",
238             "@Subcomponent(modules = ChildModule.class)",
239             "interface Child {",
240             "  Set<String> set();",
241             "}");
242     Source childModule =
243         CompilerTests.javaSource(
244             "test.ChildModule",
245             "package test;",
246             "",
247             "import dagger.Module;",
248             "import dagger.multibindings.IntoSet;",
249             "import dagger.Provides;",
250             "",
251             "@Module",
252             "class ChildModule {",
253             "  @Provides",
254             "  @IntoSet",
255             "  String setContribution() {",
256             "    return new String();",
257             "  }",
258             "}");
259 
260     CompilerTests.daggerCompiler(parent, parentModule, child, childModule)
261         .compile(
262             subject -> {
263               subject.hasErrorCount(1);
264               subject.hasErrorContaining("incompatible bindings or declarations")
265                   .onSource(parent)
266                   .onLineContaining("interface Parent");
267             });
268   }
269 }
270