• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.processor.internal.definecomponent;
18 
19 import androidx.room.compiler.processing.util.Source;
20 import dagger.hilt.android.testing.compile.HiltCompilerTests;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.junit.runners.JUnit4;
24 
25 @RunWith(JUnit4.class)
26 public final class DefineComponentProcessorTest {
27 
28   @Test
testDefineComponentOutput()29   public void testDefineComponentOutput() {
30     Source component =
31         HiltCompilerTests.javaSource(
32             "test.FooComponent",
33             "package test;",
34             "",
35             "import dagger.hilt.components.SingletonComponent;",
36             "import dagger.hilt.DefineComponent;",
37             "",
38             "@DefineComponent(parent = SingletonComponent.class)",
39             "interface FooComponent {",
40             "  static int staticField = 1;",
41             "  static int staticMethod() { return staticField; }",
42             "}");
43 
44     Source builder =
45         HiltCompilerTests.javaSource(
46             "test.FooComponentBuilder",
47             "package test;",
48             "",
49             "import dagger.hilt.DefineComponent;",
50             "",
51             "@DefineComponent.Builder",
52             "interface FooComponentBuilder {",
53             "  static int staticField = 1;",
54             "  static int staticMethod() { return staticField; }",
55             "",
56             "  FooComponent create();",
57             "}");
58 
59     Source componentOutput =
60         HiltCompilerTests.javaSource(
61             "dagger.hilt.processor.internal.definecomponent.codegen._test_FooComponent",
62             "package dagger.hilt.processor.internal.definecomponent.codegen;",
63             "",
64             "import dagger.hilt.internal.definecomponent.DefineComponentClasses;",
65             "import javax.annotation.processing.Generated;",
66             "",
67             "/**",
68             " * This class should only be referenced by generated code! This class aggregates "
69                 + "information across multiple compilations.",
70             " */",
71             "@DefineComponentClasses(",
72             "    component = \"test.FooComponent\"",
73             ")",
74             "@Generated(\"dagger.hilt.processor.internal.definecomponent.DefineComponentProcessingStep\")",
75             "public class _test_FooComponent {",
76             "}");
77 
78     Source builderOutput =
79         HiltCompilerTests.javaSource(
80             "dagger.hilt.processor.internal.definecomponent.codegen._test_FooComponentBuilder",
81             "package dagger.hilt.processor.internal.definecomponent.codegen;",
82             "",
83             "import dagger.hilt.internal.definecomponent.DefineComponentClasses;",
84             "import javax.annotation.processing.Generated;",
85             "",
86             "/**",
87             " * This class should only be referenced by generated code! This class aggregates "
88                 + "information across multiple compilations.",
89             " */",
90             "@DefineComponentClasses(",
91             "    builder = \"test.FooComponentBuilder\"",
92             ")",
93             "@Generated(\"dagger.hilt.processor.internal.definecomponent.DefineComponentProcessingStep\")",
94             "public class _test_FooComponentBuilder {",
95             "}");
96 
97     HiltCompilerTests.hiltCompiler(component, builder)
98         .compile(
99             subject -> {
100               subject.hasErrorCount(0);
101               subject.generatedSource(componentOutput);
102               subject.generatedSource(builderOutput);
103             });
104   }
105 
106   @Test
testDefineComponentClass_fails()107   public void testDefineComponentClass_fails() {
108     Source component =
109         HiltCompilerTests.javaSource(
110             "test.FooComponent",
111             "package test;",
112             "",
113             "import dagger.hilt.components.SingletonComponent;",
114             "import dagger.hilt.DefineComponent;",
115             "",
116             "@DefineComponent( parent = SingletonComponent.class )",
117             "abstract class FooComponent {}");
118 
119     HiltCompilerTests.hiltCompiler(component)
120         .compile(
121             subject -> {
122               subject.hasErrorCount(1);
123               subject.hasErrorContaining(
124                   "@DefineComponent is only allowed on interfaces. Found: test.FooComponent");
125             });
126   }
127 
128   @Test
testDefineComponentWithTypeParameters_fails()129   public void testDefineComponentWithTypeParameters_fails() {
130     Source component =
131         HiltCompilerTests.javaSource(
132             "test.FooComponent",
133             "package test;",
134             "",
135             "import dagger.hilt.components.SingletonComponent;",
136             "import dagger.hilt.DefineComponent;",
137             "",
138             "@DefineComponent( parent = SingletonComponent.class )",
139             "interface FooComponent<T> {}");
140 
141     HiltCompilerTests.hiltCompiler(component)
142         .compile(
143             subject -> {
144               subject.hasErrorCount(1);
145               subject.hasErrorContaining(
146                   "@DefineComponent test.FooComponent<T>, cannot have type parameters.");
147             });
148   }
149 
150   @Test
testDefineComponentWithInvalidComponent_fails()151   public void testDefineComponentWithInvalidComponent_fails() {
152     Source component =
153         HiltCompilerTests.javaSource(
154             "test.FooComponent",
155             "package test;",
156             "",
157             "import dagger.hilt.DefineComponent;",
158             "import dagger.hilt.android.qualifiers.ApplicationContext;",
159             "",
160             "@DefineComponent( parent = ApplicationContext.class )",
161             "interface FooComponent {}");
162 
163     HiltCompilerTests.hiltCompiler(component)
164         .compile(
165             subject -> {
166               subject.hasErrorCount(1);
167               subject.hasErrorContaining(
168                       "@DefineComponent test.FooComponent, references a type not annotated with "
169                           + "@DefineComponent: dagger.hilt.android.qualifiers.ApplicationContext")
170                   .onSource(component);
171             });
172   }
173 
174   @Test
testDefineComponentExtendsInterface_fails()175   public void testDefineComponentExtendsInterface_fails() {
176     Source component =
177         HiltCompilerTests.javaSource(
178             "test.FooComponent",
179             "package test;",
180             "",
181             "import dagger.hilt.components.SingletonComponent;",
182             "import dagger.hilt.DefineComponent;",
183             "",
184             "interface Foo {}",
185             "",
186             "@DefineComponent( parent = SingletonComponent.class )",
187             "interface FooComponent extends Foo {}");
188 
189     HiltCompilerTests.hiltCompiler(component)
190         .compile(
191             subject -> {
192               subject.hasErrorCount(1);
193               subject.hasErrorContaining(
194                   "@DefineComponent test.FooComponent, cannot extend a super class or interface."
195                       + " Found: [test.Foo]");
196             });
197   }
198 
199   @Test
testDefineComponentNonStaticMethod_fails()200   public void testDefineComponentNonStaticMethod_fails() {
201     Source component =
202         HiltCompilerTests.javaSource(
203             "test.FooComponent",
204             "package test;",
205             "",
206             "import dagger.hilt.components.SingletonComponent;",
207             "import dagger.hilt.DefineComponent;",
208             "",
209             "@DefineComponent( parent = SingletonComponent.class )",
210             "interface FooComponent {",
211             "  int nonStaticMethod();",
212             "}");
213 
214     HiltCompilerTests.hiltCompiler(component)
215         .compile(
216             subject -> {
217               subject.hasErrorCount(1);
218               subject.hasErrorContaining(
219                   "@DefineComponent test.FooComponent, cannot have non-static methods. "
220                       + "Found: [nonStaticMethod()]");
221             });
222   }
223 
224   @Test
testDefineComponentDependencyCycle_fails()225   public void testDefineComponentDependencyCycle_fails() {
226     Source component1 =
227         HiltCompilerTests.javaSource(
228             "test.Component1",
229             "package test;",
230             "",
231             "import dagger.hilt.DefineComponent;",
232             "",
233             "@DefineComponent(parent = Component2.class)",
234             "interface Component1 {}");
235 
236     Source component2 =
237         HiltCompilerTests.javaSource(
238             "test.Component2",
239             "package test;",
240             "",
241             "import dagger.hilt.DefineComponent;",
242             "",
243             "@DefineComponent(parent = Component1.class)",
244             "interface Component2 {}");
245 
246     HiltCompilerTests.hiltCompiler(component1, component2)
247         .compile(
248             subject -> {
249               subject.hasErrorCount(2);
250               subject.hasErrorContaining(
251                   "@DefineComponent cycle: test.Component1 -> test.Component2 -> test.Component1");
252               subject.hasErrorContaining(
253                   "@DefineComponent cycle: test.Component2 -> test.Component1 -> test.Component2");
254             });
255   }
256 
257   @Test
testDefineComponentNoParent_fails()258   public void testDefineComponentNoParent_fails() {
259     Source component =
260         HiltCompilerTests.javaSource(
261             "test.FooComponent",
262             "package test;",
263             "",
264             "import dagger.hilt.DefineComponent;",
265             "",
266             "@DefineComponent",
267             "interface FooComponent {}");
268 
269     HiltCompilerTests.hiltCompiler(component)
270         .compile(
271             subject -> {
272               subject.hasErrorCount(1);
273               subject.hasErrorContaining(
274                   "@DefineComponent test.FooComponent is missing a parent declaration.");
275             });
276   }
277 
278   @Test
testDefineComponentBuilderClass_fails()279   public void testDefineComponentBuilderClass_fails() {
280     Source builder =
281         HiltCompilerTests.javaSource(
282             "test.FooComponentBuilder",
283             "package test;",
284             "",
285             "import dagger.hilt.DefineComponent;",
286             "",
287             "@DefineComponent.Builder",
288             "abstract class FooComponentBuilder {}");
289 
290     HiltCompilerTests.hiltCompiler(builder)
291         .compile(
292             subject -> {
293               subject.hasErrorCount(1);
294               subject.hasErrorContaining(
295                   "@DefineComponent.Builder is only allowed on interfaces. "
296                       + "Found: test.FooComponentBuilder");
297             });
298   }
299 
300   @Test
testDefineComponentBuilderWithTypeParameters_fails()301   public void testDefineComponentBuilderWithTypeParameters_fails() {
302     Source builder =
303         HiltCompilerTests.javaSource(
304             "test.FooComponentBuilder",
305             "package test;",
306             "",
307             "import dagger.hilt.DefineComponent;",
308             "",
309             "@DefineComponent.Builder",
310             "interface FooComponentBuilder<T> {}");
311 
312     HiltCompilerTests.hiltCompiler(builder)
313         .compile(
314             subject -> {
315               subject.hasErrorCount(1);
316               subject.hasErrorContaining(
317                   "@DefineComponent.Builder test.FooComponentBuilder<T>, cannot have type "
318                       + "parameters.");
319             });
320   }
321 
322   @Test
testDefineComponentBuilderExtendsInterface_fails()323   public void testDefineComponentBuilderExtendsInterface_fails() {
324     Source builder =
325         HiltCompilerTests.javaSource(
326             "test.FooComponentBuilder",
327             "package test;",
328             "",
329             "import dagger.hilt.DefineComponent;",
330             "",
331             "interface Foo {}",
332             "",
333             "@DefineComponent.Builder",
334             "interface FooComponentBuilder extends Foo {}");
335 
336     HiltCompilerTests.hiltCompiler(builder)
337         .compile(
338             subject -> {
339               subject.hasErrorCount(1);
340               subject.hasErrorContaining(
341                   "@DefineComponent.Builder test.FooComponentBuilder, cannot extend a super class "
342                       + "or interface. Found: [test.Foo]");
343             });
344   }
345 
346   @Test
testDefineComponentBuilderNoBuilderMethod_fails()347   public void testDefineComponentBuilderNoBuilderMethod_fails() {
348     Source component =
349         HiltCompilerTests.javaSource(
350             "test.FooComponent",
351             "package test;",
352             "",
353             "import dagger.hilt.DefineComponent;",
354             "",
355             "@DefineComponent.Builder",
356             "interface FooComponentBuilder {}");
357 
358     HiltCompilerTests.hiltCompiler(component)
359         .compile(
360             subject -> {
361               subject.hasErrorCount(1);
362               subject.hasErrorContaining(
363                   "@DefineComponent.Builder test.FooComponentBuilder, must have exactly 1 build "
364                       + "method that takes no parameters. Found: []");
365             });
366   }
367 
368   @Test
testDefineComponentBuilderPrimitiveReturnType_fails()369   public void testDefineComponentBuilderPrimitiveReturnType_fails() {
370     Source component =
371         HiltCompilerTests.javaSource(
372             "test.FooComponent",
373             "package test;",
374             "",
375             "import dagger.hilt.DefineComponent;",
376             "",
377             "@DefineComponent.Builder",
378             "interface FooComponentBuilder {",
379             "  int nonStaticMethod();",
380             "}");
381 
382     HiltCompilerTests.hiltCompiler(component)
383         .compile(
384             subject -> {
385               subject.hasErrorCount(1);
386               subject.hasErrorContaining(
387                   "@DefineComponent.Builder method, test.FooComponentBuilder#nonStaticMethod(), "
388                       + "must return a @DefineComponent type. Found: int");
389             });
390   }
391 
392   @Test
testDefineComponentBuilderWrongReturnType_fails()393   public void testDefineComponentBuilderWrongReturnType_fails() {
394     Source component =
395         HiltCompilerTests.javaSource(
396             "test.FooComponent",
397             "package test;",
398             "",
399             "import dagger.hilt.DefineComponent;",
400             "",
401             "interface Foo {}",
402             "",
403             "@DefineComponent.Builder",
404             "interface FooComponentBuilder {",
405             "  Foo build();",
406             "}");
407 
408     HiltCompilerTests.hiltCompiler(component)
409         .compile(
410             subject -> {
411               subject.hasErrorCount(1);
412               subject.hasErrorContaining(
413                   "@DefineComponent.Builder method, test.FooComponentBuilder#build(), must return "
414                       + "a @DefineComponent type. Found: test.Foo");
415             });
416   }
417 }
418