1 /*
2  * Copyright (C) 2017 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 com.google.common.collect.ImmutableList;
21 import dagger.testing.compile.CompilerTests;
22 import dagger.testing.golden.GoldenFileRule;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.junit.runners.Parameterized;
27 import org.junit.runners.Parameterized.Parameters;
28 
29 @RunWith(Parameterized.class)
30 public class MapRequestRepresentationWithGuavaTest {
31   @Parameters(name = "{0}")
parameters()32   public static ImmutableList<Object[]> parameters() {
33     return CompilerMode.TEST_PARAMETERS;
34   }
35 
36   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
37 
38   private final CompilerMode compilerMode;
39 
MapRequestRepresentationWithGuavaTest(CompilerMode compilerMode)40   public MapRequestRepresentationWithGuavaTest(CompilerMode compilerMode) {
41     this.compilerMode = compilerMode;
42   }
43 
44   @Test
mapBindings()45   public void mapBindings() throws Exception {
46     Source mapModuleFile =
47         CompilerTests.javaSource(
48             "test.MapModule",
49             "package test;",
50             "",
51             "import dagger.Module;",
52             "import dagger.Provides;",
53             "import dagger.multibindings.IntKey;",
54             "import dagger.multibindings.IntoMap;",
55             "import dagger.multibindings.LongKey;",
56             "import dagger.multibindings.Multibinds;",
57             "import java.util.Map;",
58             "",
59             "@Module",
60             "interface MapModule {",
61             "  @Multibinds Map<String, String> stringMap();",
62             "  @Provides @IntoMap @IntKey(0) static int provideInt() { return 0; }",
63             "  @Provides @IntoMap @LongKey(0) static long provideLong0() { return 0; }",
64             "  @Provides @IntoMap @LongKey(1) static long provideLong1() { return 1; }",
65             "  @Provides @IntoMap @LongKey(2) static long provideLong2() { return 2; }",
66             "}");
67     Source subcomponentModuleFile =
68         CompilerTests.javaSource(
69             "test.SubcomponentMapModule",
70             "package test;",
71             "",
72             "import dagger.Module;",
73             "import dagger.Provides;",
74             "import dagger.multibindings.IntKey;",
75             "import dagger.multibindings.IntoMap;",
76             "import dagger.multibindings.LongKey;",
77             "import dagger.multibindings.Multibinds;",
78             "import java.util.Map;",
79             "",
80             "@Module",
81             "interface SubcomponentMapModule {",
82             "  @Provides @IntoMap @LongKey(3) static long provideLong3() { return 3; }",
83             "  @Provides @IntoMap @LongKey(4) static long provideLong4() { return 4; }",
84             "  @Provides @IntoMap @LongKey(5) static long provideLong5() { return 5; }",
85             "}");
86     Source componentFile =
87         CompilerTests.javaSource(
88             "test.TestComponent",
89             "package test;",
90             "",
91             "import dagger.Component;",
92             "import java.util.Map;",
93             "import javax.inject.Provider;",
94             "",
95             "@Component(modules = MapModule.class)",
96             "interface TestComponent {",
97             "  Map<String, String> strings();",
98             "  Map<String, Provider<String>> providerStrings();",
99             "",
100             "  Map<Integer, Integer> ints();",
101             "  Map<Integer, Provider<Integer>> providerInts();",
102             "  Map<Long, Long> longs();",
103             "  Map<Long, Provider<Long>> providerLongs();",
104             "",
105             "  Sub sub();",
106             "}");
107     Source subcomponent =
108         CompilerTests.javaSource(
109             "test.Sub",
110             "package test;",
111             "",
112             "import dagger.Subcomponent;",
113             "import java.util.Map;",
114             "import javax.inject.Provider;",
115             "",
116             "@Subcomponent(modules = SubcomponentMapModule.class)",
117             "interface Sub {",
118             "  Map<Long, Long> longs();",
119             "  Map<Long, Provider<Long>> providerLongs();",
120             "}");
121     CompilerTests.daggerCompiler(mapModuleFile, componentFile, subcomponentModuleFile, subcomponent)
122         .withProcessingOptions(compilerMode.processorOptions())
123         .compile(
124             subject -> {
125               subject.hasErrorCount(0);
126               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
127             });
128   }
129 
130   @Test
inaccessible()131   public void inaccessible() throws Exception {
132     Source inaccessible =
133         CompilerTests.javaSource(
134             "other.Inaccessible", "package other;", "", "class Inaccessible {}");
135     Source usesInaccessible =
136         CompilerTests.javaSource(
137             "other.UsesInaccessible",
138             "package other;",
139             "",
140             "import java.util.Map;",
141             "import javax.inject.Inject;",
142             "",
143             "public class UsesInaccessible {",
144             "  @Inject UsesInaccessible(Map<Integer, Inaccessible> map) {}",
145             "}");
146 
147     Source module =
148         CompilerTests.javaSource(
149             "other.TestModule",
150             "package other;",
151             "",
152             "import dagger.Module;",
153             "import dagger.multibindings.Multibinds;",
154             "import java.util.Map;",
155             "",
156             "@Module",
157             "public abstract class TestModule {",
158             "  @Multibinds abstract Map<Integer, Inaccessible> ints();",
159             "}");
160     Source componentFile =
161         CompilerTests.javaSource(
162             "test.TestComponent",
163             "package test;",
164             "",
165             "import dagger.Component;",
166             "import java.util.Map;",
167             "import javax.inject.Provider;",
168             "import other.TestModule;",
169             "import other.UsesInaccessible;",
170             "",
171             "@Component(modules = TestModule.class)",
172             "interface TestComponent {",
173             "  UsesInaccessible usesInaccessible();",
174             "}");
175 
176     CompilerTests.daggerCompiler(module, inaccessible, usesInaccessible, componentFile)
177         .withProcessingOptions(compilerMode.processorOptions())
178         .compile(
179             subject -> {
180               subject.hasErrorCount(0);
181               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
182             });
183   }
184 
185   @Test
subcomponentOmitsInheritedBindings()186   public void subcomponentOmitsInheritedBindings() throws Exception {
187     Source parent =
188         CompilerTests.javaSource(
189             "test.Parent",
190             "package test;",
191             "",
192             "import dagger.Component;",
193             "",
194             "@Component(modules = ParentModule.class)",
195             "interface Parent {",
196             "  Child child();",
197             "}");
198     Source parentModule =
199         CompilerTests.javaSource(
200             "test.ParentModule",
201             "package test;",
202             "",
203             "import dagger.Module;",
204             "import dagger.Provides;",
205             "import dagger.multibindings.IntoMap;",
206             "import dagger.multibindings.StringKey;",
207             "",
208             "@Module",
209             "class ParentModule {",
210             "  @Provides @IntoMap @StringKey(\"parent key\") Object parentKeyObject() {",
211             "    return \"parent value\";",
212             "  }",
213             "}");
214     Source child =
215         CompilerTests.javaSource(
216             "test.Child",
217             "package test;",
218             "",
219             "import dagger.Subcomponent;",
220             "import java.util.Map;",
221             "",
222             "@Subcomponent",
223             "interface Child {",
224             "  Map<String, Object> objectMap();",
225             "}");
226 
227     CompilerTests.daggerCompiler(parent, parentModule, child)
228         .withProcessingOptions(compilerMode.processorOptions())
229         .compile(
230             subject -> {
231               subject.hasErrorCount(0);
232               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerParent"));
233             });
234   }
235 
236   @Test
productionComponents()237   public void productionComponents() throws Exception {
238     Source mapModuleFile =
239         CompilerTests.javaSource(
240             "test.MapModule",
241             "package test;",
242             "",
243             "import dagger.Module;",
244             "import dagger.multibindings.Multibinds;",
245             "import java.util.Map;",
246             "",
247             "@Module",
248             "interface MapModule {",
249             "  @Multibinds Map<String, String> stringMap();",
250             "}");
251     Source componentFile =
252         CompilerTests.javaSource(
253             "test.TestComponent",
254             "package test;",
255             "",
256             "import com.google.common.util.concurrent.ListenableFuture;",
257             "import dagger.producers.ProductionComponent;",
258             "import java.util.Map;",
259             "",
260             "@ProductionComponent(modules = MapModule.class)",
261             "interface TestComponent {",
262             "  ListenableFuture<Map<String, String>> stringMap();",
263             "}");
264 
265     CompilerTests.daggerCompiler(mapModuleFile, componentFile)
266         .withProcessingOptions(compilerMode.processorOptions())
267         .compile(
268             subject -> {
269               subject.hasErrorCount(0);
270               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
271             });
272   }
273 }
274