• 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.hilt.android.processor.internal.aggregateddeps;
18 
19 import static com.google.testing.compile.CompilationSubject.assertThat;
20 import static dagger.hilt.android.processor.AndroidCompilers.compiler;
21 
22 import com.google.testing.compile.Compilation;
23 import com.google.testing.compile.JavaFileObjects;
24 import javax.tools.JavaFileObject;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.junit.runners.JUnit4;
28 
29 @RunWith(JUnit4.class)
30 public class TestInstallInTest {
31 
32   @Test
testMissingValues()33   public void testMissingValues() {
34     JavaFileObject testInstallInModule =
35         JavaFileObjects.forSourceLines(
36             "test.TestInstallInModule",
37             "package test;",
38             "",
39             "import dagger.Module;",
40             "import dagger.hilt.testing.TestInstallIn;",
41             "",
42             "@Module",
43             "@TestInstallIn",
44             "interface TestInstallInModule {}");
45     Compilation compilation = compiler().compile(testInstallInModule);
46     assertThat(compilation).failed();
47     assertThat(compilation).hadErrorCount(1);
48     assertThat(compilation)
49         .hadErrorContaining(
50             "@dagger.hilt.testing.TestInstallIn is missing default values for elements "
51                 + "components,replaces")
52         .inFile(testInstallInModule)
53         .onLine(7);
54   }
55 
56   @Test
testEmptyComponentValues()57   public void testEmptyComponentValues() {
58     JavaFileObject installInModule =
59         JavaFileObjects.forSourceLines(
60             "test.InstallInModule",
61             "package test;",
62             "",
63             "import dagger.Module;",
64             "import dagger.hilt.InstallIn;",
65             "import dagger.hilt.components.SingletonComponent;",
66             "",
67             "@Module",
68             "@InstallIn(SingletonComponent.class)",
69             "interface InstallInModule {}");
70     JavaFileObject testInstallInModule =
71         JavaFileObjects.forSourceLines(
72             "test.TestInstallInModule",
73             "package test;",
74             "",
75             "import dagger.Module;",
76             "import dagger.hilt.testing.TestInstallIn;",
77             "",
78             "@Module",
79             "@TestInstallIn(components = {}, replaces = InstallInModule.class)",
80             "interface TestInstallInModule {}");
81     Compilation compilation = compiler().compile(installInModule, testInstallInModule);
82     assertThat(compilation).failed();
83     assertThat(compilation).hadErrorCount(1);
84     // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues
85     assertThat(compilation)
86         .hadErrorContaining(
87             "@TestInstallIn, 'components' class is invalid or missing: "
88                 + "@dagger.hilt.testing.TestInstallIn("
89                 + "components={}, replaces={test.InstallInModule.class})");
90   }
91 
92   @Test
testEmptyReplacesValues()93   public void testEmptyReplacesValues() {
94     JavaFileObject testInstallInModule =
95         JavaFileObjects.forSourceLines(
96             "test.TestInstallInModule",
97             "package test;",
98             "",
99             "import dagger.Module;",
100             "import dagger.hilt.testing.TestInstallIn;",
101             "import dagger.hilt.components.SingletonComponent;",
102             "",
103             "@Module",
104             "@TestInstallIn(components = SingletonComponent.class, replaces = {})",
105             "interface TestInstallInModule {}");
106     Compilation compilation = compiler().compile(testInstallInModule);
107     assertThat(compilation).failed();
108     assertThat(compilation).hadErrorCount(1);
109     // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues
110     assertThat(compilation)
111         .hadErrorContaining(
112             "@TestInstallIn, 'replaces' class is invalid or missing: "
113                 + "@dagger.hilt.testing.TestInstallIn("
114                 + "components={dagger.hilt.components.SingletonComponent.class}, replaces={})");
115   }
116 
117   @Test
testMissingModuleAnnotation()118   public void testMissingModuleAnnotation() {
119     JavaFileObject installInModule =
120         JavaFileObjects.forSourceLines(
121             "test.InstallInModule",
122             "package test;",
123             "",
124             "import dagger.Module;",
125             "import dagger.hilt.InstallIn;",
126             "import dagger.hilt.components.SingletonComponent;",
127             "",
128             "@Module",
129             "@InstallIn(SingletonComponent.class)",
130             "interface InstallInModule {}");
131     JavaFileObject testInstallInModule =
132         JavaFileObjects.forSourceLines(
133             "test.TestInstallInModule",
134             "package test;",
135             "",
136             "import dagger.Module;",
137             "import dagger.hilt.components.SingletonComponent;",
138             "import dagger.hilt.testing.TestInstallIn;",
139             "",
140             "@TestInstallIn(",
141             "    components = SingletonComponent.class,",
142             "    replaces = InstallInModule.class)",
143             "interface TestInstallInModule {}");
144     Compilation compilation = compiler().compile(installInModule, testInstallInModule);
145     assertThat(compilation).failed();
146     assertThat(compilation).hadErrorCount(1);
147     assertThat(compilation)
148         .hadErrorContaining(
149             "@TestInstallIn-annotated classes must also be annotated with @Module or @EntryPoint: "
150                 + "test.TestInstallInModule")
151         .inFile(testInstallInModule)
152         .onLine(10);
153   }
154 
155   @Test
testInvalidUsageOnEntryPoint()156   public void testInvalidUsageOnEntryPoint() {
157     JavaFileObject installInModule =
158         JavaFileObjects.forSourceLines(
159             "test.InstallInModule",
160             "package test;",
161             "",
162             "import dagger.Module;",
163             "import dagger.hilt.InstallIn;",
164             "import dagger.hilt.components.SingletonComponent;",
165             "",
166             "@Module",
167             "@InstallIn(SingletonComponent.class)",
168             "interface InstallInModule {}");
169     JavaFileObject testInstallInEntryPoint =
170         JavaFileObjects.forSourceLines(
171             "test.TestInstallInEntryPoint",
172             "package test;",
173             "",
174             "import dagger.hilt.EntryPoint;",
175             "import dagger.hilt.components.SingletonComponent;",
176             "import dagger.hilt.testing.TestInstallIn;",
177             "",
178             "@EntryPoint",
179             "@TestInstallIn(",
180             "    components = SingletonComponent.class,",
181             "    replaces = InstallInModule.class)",
182             "interface TestInstallInEntryPoint {}");
183     Compilation compilation = compiler().compile(installInModule, testInstallInEntryPoint);
184     assertThat(compilation).failed();
185     assertThat(compilation).hadErrorCount(1);
186     assertThat(compilation)
187         .hadErrorContaining("@TestInstallIn can only be used with modules")
188         .inFile(testInstallInEntryPoint)
189         .onLine(11);
190   }
191 
192   @Test
testInvalidReplaceModules()193   public void testInvalidReplaceModules() {
194     JavaFileObject foo =
195         JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "class Foo {}");
196     JavaFileObject testInstallInModule =
197         JavaFileObjects.forSourceLines(
198             "test.TestInstallInModule",
199             "package test;",
200             "",
201             "import dagger.Module;",
202             "import dagger.hilt.components.SingletonComponent;",
203             "import dagger.hilt.testing.TestInstallIn;",
204             "",
205             "@Module",
206             "@TestInstallIn(",
207             "    components = SingletonComponent.class,",
208             "    replaces = Foo.class)",
209             "interface TestInstallInModule {}");
210     Compilation compilation = compiler().compile(foo, testInstallInModule);
211     assertThat(compilation).failed();
212     assertThat(compilation).hadErrorCount(1);
213     assertThat(compilation)
214         .hadErrorContaining(
215             "@TestInstallIn#replaces() can only contain @InstallIn modules, but found: [test.Foo]")
216         .inFile(testInstallInModule)
217         .onLine(11);
218   }
219 
220   @Test
testInternalDaggerReplaceModules()221   public void testInternalDaggerReplaceModules() {
222     JavaFileObject testInstallInModule =
223         JavaFileObjects.forSourceLines(
224             "test.TestInstallInModule",
225             "package test;",
226             "",
227             "import dagger.Module;",
228             "import dagger.hilt.components.SingletonComponent;",
229             "import dagger.hilt.testing.TestInstallIn;",
230             "",
231             "@Module",
232             "@TestInstallIn(",
233             "    components = SingletonComponent.class,",
234             "    replaces = dagger.hilt.android.internal.modules.ApplicationContextModule.class)",
235             "interface TestInstallInModule {}");
236     Compilation compilation = compiler().compile(testInstallInModule);
237     assertThat(compilation).failed();
238     assertThat(compilation).hadErrorCount(1);
239     assertThat(compilation)
240         .hadErrorContaining(
241             "@TestInstallIn#replaces() cannot contain internal Hilt modules, but found: "
242                 + "[dagger.hilt.android.internal.modules.ApplicationContextModule]")
243         .inFile(testInstallInModule)
244         .onLine(11);
245   }
246 
247   @Test
testHiltWrapperDaggerReplaceModules()248   public void testHiltWrapperDaggerReplaceModules() {
249     JavaFileObject testInstallInModule =
250         JavaFileObjects.forSourceLines(
251             "test.TestInstallInModule",
252             "package test;",
253             "",
254             "import dagger.Module;",
255             "import dagger.hilt.components.SingletonComponent;",
256             "import dagger.hilt.testing.TestInstallIn;",
257             "import"
258                 + " dagger.hilt.android.processor.internal.aggregateddeps.HiltWrapper_InstallInModule;",
259             "",
260             "@Module",
261             "@TestInstallIn(",
262             "    components = SingletonComponent.class,",
263             // Note: this module is built in a separate library since AggregatedDepsProcessor can't
264             // handle modules generated in the same round.
265             "    replaces = HiltWrapper_InstallInModule.class)",
266             "interface TestInstallInModule {}");
267     Compilation compilation = compiler().compile(testInstallInModule);
268     assertThat(compilation).failed();
269     assertThat(compilation).hadErrorCount(1);
270     assertThat(compilation)
271         .hadErrorContaining(
272             "@TestInstallIn#replaces() cannot contain Hilt generated public wrapper modules, "
273                 + "but found: [dagger.hilt.android.processor.internal.aggregateddeps."
274                 + "HiltWrapper_InstallInModule]")
275         .inFile(testInstallInModule)
276         .onLine(12);
277   }
278 
279   @Test
testCannotReplaceLocalInstallInModule()280   public void testCannotReplaceLocalInstallInModule() {
281     JavaFileObject test =
282         JavaFileObjects.forSourceLines(
283             "test.MyTest",
284             "package test;",
285             "",
286             "import dagger.Module;",
287             "import dagger.hilt.InstallIn;",
288             "import dagger.hilt.components.SingletonComponent;",
289             "import dagger.hilt.testing.TestInstallIn;",
290             "import dagger.hilt.android.testing.HiltAndroidTest;",
291             "",
292             "@HiltAndroidTest",
293             "public class MyTest {",
294             "  @Module",
295             "  @InstallIn(SingletonComponent.class)",
296             "  interface LocalInstallInModule {}",
297             "}");
298     JavaFileObject testInstallIn =
299         JavaFileObjects.forSourceLines(
300             "test.TestInstallInModule",
301             "package test;",
302             "",
303             "import dagger.Module;",
304             "import dagger.hilt.components.SingletonComponent;",
305             "import dagger.hilt.testing.TestInstallIn;",
306             "",
307             "@Module",
308             "@TestInstallIn(",
309             "    components = SingletonComponent.class,",
310             "    replaces = MyTest.LocalInstallInModule.class)",
311             "interface TestInstallInModule {}");
312     Compilation compilation = compiler().compile(test, testInstallIn);
313     assertThat(compilation).failed();
314     assertThat(compilation).hadErrorCount(1);
315     assertThat(compilation)
316         .hadErrorContaining(
317             "TestInstallIn#replaces() cannot replace test specific @InstallIn modules, but found: "
318                 + "[test.MyTest.LocalInstallInModule].")
319         .inFile(testInstallIn)
320         .onLine(11);
321   }
322 
323   @Test
testThatTestInstallInCannotOriginateFromTest()324   public void testThatTestInstallInCannotOriginateFromTest() {
325     JavaFileObject installInModule =
326         JavaFileObjects.forSourceLines(
327             "test.InstallInModule",
328             "package test;",
329             "",
330             "import dagger.Module;",
331             "import dagger.hilt.InstallIn;",
332             "import dagger.hilt.components.SingletonComponent;",
333             "",
334             "@Module",
335             "@InstallIn(SingletonComponent.class)",
336             "interface InstallInModule {}");
337     JavaFileObject test =
338         JavaFileObjects.forSourceLines(
339             "test.MyTest",
340             "package test;",
341             "",
342             "import dagger.Module;",
343             "import dagger.hilt.components.SingletonComponent;",
344             "import dagger.hilt.testing.TestInstallIn;",
345             "import dagger.hilt.android.testing.HiltAndroidTest;",
346             "",
347             "@HiltAndroidTest",
348             "public class MyTest {",
349             "  @Module",
350             "  @TestInstallIn(",
351             "      components = SingletonComponent.class,",
352             "      replaces = InstallInModule.class)",
353             "  interface TestInstallInModule {}",
354             "}");
355     Compilation compilation = compiler().compile(test, installInModule);
356     assertThat(compilation).failed();
357     assertThat(compilation).hadErrorCount(1);
358     assertThat(compilation)
359         .hadErrorContaining(
360             "@TestInstallIn modules cannot be nested in (or originate from) a "
361                 + "@HiltAndroidTest-annotated class:  test.MyTest")
362         .inFile(test)
363         .onLine(14);
364   }
365 }
366