xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/FullBindingGraphValidationTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2018 The Dagger Authors.
3*f585d8a3SJacky Wang  *
4*f585d8a3SJacky Wang  * Licensed under the Apache License, Version 2.0 (the "License");
5*f585d8a3SJacky Wang  * you may not use this file except in compliance with the License.
6*f585d8a3SJacky Wang  * You may obtain a copy of the License at
7*f585d8a3SJacky Wang  *
8*f585d8a3SJacky Wang  * http://www.apache.org/licenses/LICENSE-2.0
9*f585d8a3SJacky Wang  *
10*f585d8a3SJacky Wang  * Unless required by applicable law or agreed to in writing, software
11*f585d8a3SJacky Wang  * distributed under the License is distributed on an "AS IS" BASIS,
12*f585d8a3SJacky Wang  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f585d8a3SJacky Wang  * See the License for the specific language governing permissions and
14*f585d8a3SJacky Wang  * limitations under the License.
15*f585d8a3SJacky Wang  */
16*f585d8a3SJacky Wang 
17*f585d8a3SJacky Wang package dagger.internal.codegen;
18*f585d8a3SJacky Wang 
19*f585d8a3SJacky Wang import static dagger.internal.codegen.TestUtils.endsWithMessage;
20*f585d8a3SJacky Wang 
21*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source;
22*f585d8a3SJacky Wang import com.google.common.collect.ImmutableMap;
23*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests;
24*f585d8a3SJacky Wang import java.util.regex.Pattern;
25*f585d8a3SJacky Wang import org.junit.Test;
26*f585d8a3SJacky Wang import org.junit.runner.RunWith;
27*f585d8a3SJacky Wang import org.junit.runners.JUnit4;
28*f585d8a3SJacky Wang 
29*f585d8a3SJacky Wang @RunWith(JUnit4.class)
30*f585d8a3SJacky Wang public final class FullBindingGraphValidationTest {
31*f585d8a3SJacky Wang   private static final Source MODULE_WITH_ERRORS =
32*f585d8a3SJacky Wang       CompilerTests.javaSource(
33*f585d8a3SJacky Wang           "test.ModuleWithErrors",
34*f585d8a3SJacky Wang           "package test;",
35*f585d8a3SJacky Wang           "",
36*f585d8a3SJacky Wang           "import dagger.Binds;",
37*f585d8a3SJacky Wang           "import dagger.Module;",
38*f585d8a3SJacky Wang           "",
39*f585d8a3SJacky Wang           "@Module",
40*f585d8a3SJacky Wang           "interface ModuleWithErrors {",
41*f585d8a3SJacky Wang           "  @Binds Object object1(String string);",
42*f585d8a3SJacky Wang           "  @Binds Object object2(Long l);",
43*f585d8a3SJacky Wang           "  @Binds Number missingDependency(Integer i);",
44*f585d8a3SJacky Wang           "}");
45*f585d8a3SJacky Wang 
46*f585d8a3SJacky Wang   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
47*f585d8a3SJacky Wang   private static final Pattern MODULE_WITH_ERRORS_MESSAGE =
48*f585d8a3SJacky Wang       endsWithMessage(
49*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
50*f585d8a3SJacky Wang           "    @Binds Object ModuleWithErrors.object1(String)",
51*f585d8a3SJacky Wang           "    @Binds Object ModuleWithErrors.object2(Long)",
52*f585d8a3SJacky Wang           "    in component: [ModuleWithErrors]",
53*f585d8a3SJacky Wang           "",
54*f585d8a3SJacky Wang           "======================",
55*f585d8a3SJacky Wang           "Full classname legend:",
56*f585d8a3SJacky Wang           "======================",
57*f585d8a3SJacky Wang           "ModuleWithErrors: test.ModuleWithErrors",
58*f585d8a3SJacky Wang           "========================",
59*f585d8a3SJacky Wang           "End of classname legend:",
60*f585d8a3SJacky Wang           "========================");
61*f585d8a3SJacky Wang 
62*f585d8a3SJacky Wang   private static final Pattern INCLUDES_MODULE_WITH_ERRORS_MESSAGE =
63*f585d8a3SJacky Wang       endsWithMessage(
64*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
65*f585d8a3SJacky Wang           "    @Binds Object ModuleWithErrors.object1(String)",
66*f585d8a3SJacky Wang           "    @Binds Object ModuleWithErrors.object2(Long)",
67*f585d8a3SJacky Wang           "    in component: [IncludesModuleWithErrors]",
68*f585d8a3SJacky Wang           "",
69*f585d8a3SJacky Wang           "======================",
70*f585d8a3SJacky Wang           "Full classname legend:",
71*f585d8a3SJacky Wang           "======================",
72*f585d8a3SJacky Wang           "IncludesModuleWithErrors: test.IncludesModuleWithErrors",
73*f585d8a3SJacky Wang           "ModuleWithErrors:         test.ModuleWithErrors",
74*f585d8a3SJacky Wang           "========================",
75*f585d8a3SJacky Wang           "End of classname legend:",
76*f585d8a3SJacky Wang           "========================");
77*f585d8a3SJacky Wang 
78*f585d8a3SJacky Wang   @Test
moduleWithErrors_validationTypeNone()79*f585d8a3SJacky Wang   public void moduleWithErrors_validationTypeNone() {
80*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS)
81*f585d8a3SJacky Wang         .compile(
82*f585d8a3SJacky Wang             subject -> {
83*f585d8a3SJacky Wang               subject.hasErrorCount(0);
84*f585d8a3SJacky Wang               subject.hasWarningCount(0);
85*f585d8a3SJacky Wang             });
86*f585d8a3SJacky Wang   }
87*f585d8a3SJacky Wang 
88*f585d8a3SJacky Wang   @Test
moduleWithErrors_validationTypeError()89*f585d8a3SJacky Wang   public void moduleWithErrors_validationTypeError() {
90*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS)
91*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
92*f585d8a3SJacky Wang         .compile(
93*f585d8a3SJacky Wang             subject -> {
94*f585d8a3SJacky Wang               subject.hasErrorCount(1);
95*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(MODULE_WITH_ERRORS_MESSAGE.pattern())
96*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_ERRORS)
97*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithErrors");
98*f585d8a3SJacky Wang             });
99*f585d8a3SJacky Wang   }
100*f585d8a3SJacky Wang 
101*f585d8a3SJacky Wang   @Test
moduleWithErrors_validationTypeWarning()102*f585d8a3SJacky Wang   public void moduleWithErrors_validationTypeWarning() {
103*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS)
104*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
105*f585d8a3SJacky Wang         .compile(
106*f585d8a3SJacky Wang             subject -> {
107*f585d8a3SJacky Wang               subject.hasErrorCount(0);
108*f585d8a3SJacky Wang               subject.hasWarningCount(1);
109*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE.pattern())
110*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_ERRORS)
111*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithErrors");
112*f585d8a3SJacky Wang             });
113*f585d8a3SJacky Wang   }
114*f585d8a3SJacky Wang 
115*f585d8a3SJacky Wang   private static final Source INCLUDES_MODULE_WITH_ERRORS =
116*f585d8a3SJacky Wang       CompilerTests.javaSource(
117*f585d8a3SJacky Wang           "test.IncludesModuleWithErrors",
118*f585d8a3SJacky Wang           "package test;",
119*f585d8a3SJacky Wang           "",
120*f585d8a3SJacky Wang           "import dagger.Binds;",
121*f585d8a3SJacky Wang           "import dagger.Module;",
122*f585d8a3SJacky Wang           "",
123*f585d8a3SJacky Wang           "@Module(includes = ModuleWithErrors.class)",
124*f585d8a3SJacky Wang           "interface IncludesModuleWithErrors {}");
125*f585d8a3SJacky Wang 
126*f585d8a3SJacky Wang   @Test
includesModuleWithErrors_validationTypeNone()127*f585d8a3SJacky Wang   public void includesModuleWithErrors_validationTypeNone() {
128*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS)
129*f585d8a3SJacky Wang         .compile(
130*f585d8a3SJacky Wang             subject -> {
131*f585d8a3SJacky Wang               subject.hasErrorCount(0);
132*f585d8a3SJacky Wang               subject.hasWarningCount(0);
133*f585d8a3SJacky Wang             });
134*f585d8a3SJacky Wang   }
135*f585d8a3SJacky Wang 
136*f585d8a3SJacky Wang   @Test
includesModuleWithErrors_validationTypeError()137*f585d8a3SJacky Wang   public void includesModuleWithErrors_validationTypeError() {
138*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS)
139*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
140*f585d8a3SJacky Wang         .compile(
141*f585d8a3SJacky Wang             subject -> {
142*f585d8a3SJacky Wang               subject.hasErrorCount(2);
143*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(MODULE_WITH_ERRORS_MESSAGE.pattern())
144*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_ERRORS)
145*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithErrors");
146*f585d8a3SJacky Wang               subject.hasErrorContaining("ModuleWithErrors has errors")
147*f585d8a3SJacky Wang                   .onSource(INCLUDES_MODULE_WITH_ERRORS)
148*f585d8a3SJacky Wang                   .onLineContaining("ModuleWithErrors.class");
149*f585d8a3SJacky Wang             });
150*f585d8a3SJacky Wang   }
151*f585d8a3SJacky Wang 
152*f585d8a3SJacky Wang   @Test
includesModuleWithErrors_validationTypeWarning()153*f585d8a3SJacky Wang   public void includesModuleWithErrors_validationTypeWarning() {
154*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS, INCLUDES_MODULE_WITH_ERRORS)
155*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
156*f585d8a3SJacky Wang         .compile(
157*f585d8a3SJacky Wang             subject -> {
158*f585d8a3SJacky Wang               subject.hasErrorCount(0);
159*f585d8a3SJacky Wang               subject.hasWarningCount(2);
160*f585d8a3SJacky Wang 
161*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(MODULE_WITH_ERRORS_MESSAGE.pattern())
162*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_ERRORS)
163*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithErrors");
164*f585d8a3SJacky Wang 
165*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(INCLUDES_MODULE_WITH_ERRORS_MESSAGE.pattern())
166*f585d8a3SJacky Wang                   .onSource(INCLUDES_MODULE_WITH_ERRORS)
167*f585d8a3SJacky Wang                   .onLineContaining("interface IncludesModuleWithErrors");
168*f585d8a3SJacky Wang             });
169*f585d8a3SJacky Wang   }
170*f585d8a3SJacky Wang 
171*f585d8a3SJacky Wang   private static final Source A_MODULE =
172*f585d8a3SJacky Wang       CompilerTests.javaSource(
173*f585d8a3SJacky Wang           "test.AModule",
174*f585d8a3SJacky Wang           "package test;",
175*f585d8a3SJacky Wang           "",
176*f585d8a3SJacky Wang           "import dagger.Binds;",
177*f585d8a3SJacky Wang           "import dagger.Module;",
178*f585d8a3SJacky Wang           "",
179*f585d8a3SJacky Wang           "@Module",
180*f585d8a3SJacky Wang           "interface AModule {",
181*f585d8a3SJacky Wang           "  @Binds Object object(String string);",
182*f585d8a3SJacky Wang           "}");
183*f585d8a3SJacky Wang 
184*f585d8a3SJacky Wang   private static final Source COMBINED_WITH_A_MODULE_HAS_ERRORS =
185*f585d8a3SJacky Wang       CompilerTests.javaSource(
186*f585d8a3SJacky Wang           "test.CombinedWithAModuleHasErrors",
187*f585d8a3SJacky Wang           "package test;",
188*f585d8a3SJacky Wang           "",
189*f585d8a3SJacky Wang           "import dagger.Binds;",
190*f585d8a3SJacky Wang           "import dagger.Module;",
191*f585d8a3SJacky Wang           "",
192*f585d8a3SJacky Wang           "@Module(includes = AModule.class)",
193*f585d8a3SJacky Wang           "interface CombinedWithAModuleHasErrors {",
194*f585d8a3SJacky Wang           "  @Binds Object object(Long l);",
195*f585d8a3SJacky Wang           "}");
196*f585d8a3SJacky Wang 
197*f585d8a3SJacky Wang   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
198*f585d8a3SJacky Wang   private static final Pattern COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE =
199*f585d8a3SJacky Wang       endsWithMessage(
200*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
201*f585d8a3SJacky Wang           "    @Binds Object AModule.object(String)",
202*f585d8a3SJacky Wang           "    @Binds Object CombinedWithAModuleHasErrors.object(Long)",
203*f585d8a3SJacky Wang           "    in component: [CombinedWithAModuleHasErrors]",
204*f585d8a3SJacky Wang           "",
205*f585d8a3SJacky Wang           "======================",
206*f585d8a3SJacky Wang           "Full classname legend:",
207*f585d8a3SJacky Wang           "======================",
208*f585d8a3SJacky Wang           "AModule:                      test.AModule",
209*f585d8a3SJacky Wang           "CombinedWithAModuleHasErrors: test.CombinedWithAModuleHasErrors",
210*f585d8a3SJacky Wang           "========================",
211*f585d8a3SJacky Wang           "End of classname legend:",
212*f585d8a3SJacky Wang           "========================");
213*f585d8a3SJacky Wang 
214*f585d8a3SJacky Wang   @Test
moduleIncludingModuleWithCombinedErrors_validationTypeNone()215*f585d8a3SJacky Wang   public void moduleIncludingModuleWithCombinedErrors_validationTypeNone() {
216*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS)
217*f585d8a3SJacky Wang         .compile(
218*f585d8a3SJacky Wang             subject -> {
219*f585d8a3SJacky Wang               subject.hasErrorCount(0);
220*f585d8a3SJacky Wang               subject.hasWarningCount(0);
221*f585d8a3SJacky Wang             });
222*f585d8a3SJacky Wang   }
223*f585d8a3SJacky Wang 
224*f585d8a3SJacky Wang   @Test
moduleIncludingModuleWithCombinedErrors_validationTypeError()225*f585d8a3SJacky Wang   public void moduleIncludingModuleWithCombinedErrors_validationTypeError() {
226*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS)
227*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
228*f585d8a3SJacky Wang         .compile(
229*f585d8a3SJacky Wang             subject -> {
230*f585d8a3SJacky Wang               subject.hasErrorCount(1);
231*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE.pattern())
232*f585d8a3SJacky Wang                   .onSource(COMBINED_WITH_A_MODULE_HAS_ERRORS)
233*f585d8a3SJacky Wang                   .onLineContaining("interface CombinedWithAModuleHasErrors");
234*f585d8a3SJacky Wang             });
235*f585d8a3SJacky Wang   }
236*f585d8a3SJacky Wang 
237*f585d8a3SJacky Wang   @Test
moduleIncludingModuleWithCombinedErrors_validationTypeWarning()238*f585d8a3SJacky Wang   public void moduleIncludingModuleWithCombinedErrors_validationTypeWarning() {
239*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(A_MODULE, COMBINED_WITH_A_MODULE_HAS_ERRORS)
240*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
241*f585d8a3SJacky Wang         .compile(
242*f585d8a3SJacky Wang             subject -> {
243*f585d8a3SJacky Wang               subject.hasErrorCount(0);
244*f585d8a3SJacky Wang               subject.hasWarningCount(1);
245*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(COMBINED_WITH_A_MODULE_HAS_ERRORS_MESSAGE.pattern())
246*f585d8a3SJacky Wang                   .onSource(COMBINED_WITH_A_MODULE_HAS_ERRORS)
247*f585d8a3SJacky Wang                   .onLineContaining("interface CombinedWithAModuleHasErrors");
248*f585d8a3SJacky Wang             });
249*f585d8a3SJacky Wang   }
250*f585d8a3SJacky Wang 
251*f585d8a3SJacky Wang   private static final Source SUBCOMPONENT_WITH_ERRORS =
252*f585d8a3SJacky Wang       CompilerTests.javaSource(
253*f585d8a3SJacky Wang           "test.SubcomponentWithErrors",
254*f585d8a3SJacky Wang           "package test;",
255*f585d8a3SJacky Wang           "",
256*f585d8a3SJacky Wang           "import dagger.BindsInstance;",
257*f585d8a3SJacky Wang           "import dagger.Subcomponent;",
258*f585d8a3SJacky Wang           "",
259*f585d8a3SJacky Wang           "@Subcomponent(modules = AModule.class)",
260*f585d8a3SJacky Wang           "interface SubcomponentWithErrors {",
261*f585d8a3SJacky Wang           "  @Subcomponent.Builder",
262*f585d8a3SJacky Wang           "  interface Builder {",
263*f585d8a3SJacky Wang           "    @BindsInstance Builder object(Object object);",
264*f585d8a3SJacky Wang           "    SubcomponentWithErrors build();",
265*f585d8a3SJacky Wang           "  }",
266*f585d8a3SJacky Wang           "}");
267*f585d8a3SJacky Wang 
268*f585d8a3SJacky Wang   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
269*f585d8a3SJacky Wang   private static final Pattern SUBCOMPONENT_WITH_ERRORS_MESSAGE =
270*f585d8a3SJacky Wang       endsWithMessage(
271*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
272*f585d8a3SJacky Wang           "    @Binds Object AModule.object(String)",
273*f585d8a3SJacky Wang           "    @BindsInstance SubcomponentWithErrors.Builder"
274*f585d8a3SJacky Wang               + " SubcomponentWithErrors.Builder.object(Object)",
275*f585d8a3SJacky Wang           "    in component: [SubcomponentWithErrors]",
276*f585d8a3SJacky Wang           "",
277*f585d8a3SJacky Wang           "======================",
278*f585d8a3SJacky Wang           "Full classname legend:",
279*f585d8a3SJacky Wang           "======================",
280*f585d8a3SJacky Wang           "AModule:                test.AModule",
281*f585d8a3SJacky Wang           "SubcomponentWithErrors: test.SubcomponentWithErrors",
282*f585d8a3SJacky Wang           "========================",
283*f585d8a3SJacky Wang           "End of classname legend:",
284*f585d8a3SJacky Wang           "========================");
285*f585d8a3SJacky Wang 
286*f585d8a3SJacky Wang   private static final Pattern MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE =
287*f585d8a3SJacky Wang       endsWithMessage(
288*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
289*f585d8a3SJacky Wang           "    @Binds Object AModule.object(String)",
290*f585d8a3SJacky Wang           "    @BindsInstance SubcomponentWithErrors.Builder"
291*f585d8a3SJacky Wang               + " SubcomponentWithErrors.Builder.object(Object)",
292*f585d8a3SJacky Wang           "    in component: [ModuleWithSubcomponentWithErrors → SubcomponentWithErrors]",
293*f585d8a3SJacky Wang           "",
294*f585d8a3SJacky Wang           "======================",
295*f585d8a3SJacky Wang           "Full classname legend:",
296*f585d8a3SJacky Wang           "======================",
297*f585d8a3SJacky Wang           "AModule:                          test.AModule",
298*f585d8a3SJacky Wang           "ModuleWithSubcomponentWithErrors: test.ModuleWithSubcomponentWithErrors",
299*f585d8a3SJacky Wang           "SubcomponentWithErrors:           test.SubcomponentWithErrors",
300*f585d8a3SJacky Wang           "========================",
301*f585d8a3SJacky Wang           "End of classname legend:",
302*f585d8a3SJacky Wang           "========================");
303*f585d8a3SJacky Wang 
304*f585d8a3SJacky Wang   @Test
subcomponentWithErrors_validationTypeNone()305*f585d8a3SJacky Wang   public void subcomponentWithErrors_validationTypeNone() {
306*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(SUBCOMPONENT_WITH_ERRORS, A_MODULE)
307*f585d8a3SJacky Wang         .compile(
308*f585d8a3SJacky Wang             subject -> {
309*f585d8a3SJacky Wang               subject.hasErrorCount(0);
310*f585d8a3SJacky Wang               subject.hasWarningCount(0);
311*f585d8a3SJacky Wang             });
312*f585d8a3SJacky Wang   }
313*f585d8a3SJacky Wang 
314*f585d8a3SJacky Wang   @Test
subcomponentWithErrors_validationTypeError()315*f585d8a3SJacky Wang   public void subcomponentWithErrors_validationTypeError() {
316*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(SUBCOMPONENT_WITH_ERRORS, A_MODULE)
317*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
318*f585d8a3SJacky Wang         .compile(
319*f585d8a3SJacky Wang             subject -> {
320*f585d8a3SJacky Wang               subject.hasErrorCount(1);
321*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
322*f585d8a3SJacky Wang                   .onSource(SUBCOMPONENT_WITH_ERRORS)
323*f585d8a3SJacky Wang                   .onLineContaining("interface SubcomponentWithErrors");
324*f585d8a3SJacky Wang             });
325*f585d8a3SJacky Wang   }
326*f585d8a3SJacky Wang 
327*f585d8a3SJacky Wang   @Test
subcomponentWithErrors_validationTypeWarning()328*f585d8a3SJacky Wang   public void subcomponentWithErrors_validationTypeWarning() {
329*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(SUBCOMPONENT_WITH_ERRORS, A_MODULE)
330*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
331*f585d8a3SJacky Wang         .compile(
332*f585d8a3SJacky Wang             subject -> {
333*f585d8a3SJacky Wang               subject.hasErrorCount(0);
334*f585d8a3SJacky Wang               subject.hasWarningCount(1);
335*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
336*f585d8a3SJacky Wang                   .onSource(SUBCOMPONENT_WITH_ERRORS)
337*f585d8a3SJacky Wang                   .onLineContaining("interface SubcomponentWithErrors");
338*f585d8a3SJacky Wang             });
339*f585d8a3SJacky Wang   }
340*f585d8a3SJacky Wang 
341*f585d8a3SJacky Wang   private static final Source MODULE_WITH_SUBCOMPONENT_WITH_ERRORS =
342*f585d8a3SJacky Wang       CompilerTests.javaSource(
343*f585d8a3SJacky Wang           "test.ModuleWithSubcomponentWithErrors",
344*f585d8a3SJacky Wang           "package test;",
345*f585d8a3SJacky Wang           "",
346*f585d8a3SJacky Wang           "import dagger.Binds;",
347*f585d8a3SJacky Wang           "import dagger.Module;",
348*f585d8a3SJacky Wang           "",
349*f585d8a3SJacky Wang           "@Module(subcomponents = SubcomponentWithErrors.class)",
350*f585d8a3SJacky Wang           "interface ModuleWithSubcomponentWithErrors {}");
351*f585d8a3SJacky Wang 
352*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithErrors_validationTypeNone()353*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithErrors_validationTypeNone() {
354*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(
355*f585d8a3SJacky Wang             MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE)
356*f585d8a3SJacky Wang         .compile(
357*f585d8a3SJacky Wang             subject -> {
358*f585d8a3SJacky Wang               subject.hasErrorCount(0);
359*f585d8a3SJacky Wang               subject.hasWarningCount(0);
360*f585d8a3SJacky Wang             });
361*f585d8a3SJacky Wang   }
362*f585d8a3SJacky Wang 
363*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithErrors_validationTypeError()364*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithErrors_validationTypeError() {
365*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(
366*f585d8a3SJacky Wang             MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE)
367*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
368*f585d8a3SJacky Wang         .compile(
369*f585d8a3SJacky Wang             subject -> {
370*f585d8a3SJacky Wang               subject.hasErrorCount(2);
371*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(
372*f585d8a3SJacky Wang                       MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
373*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
374*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithSubcomponentWithErrors");
375*f585d8a3SJacky Wang               // TODO(b/130283677)
376*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
377*f585d8a3SJacky Wang                   .onSource(SUBCOMPONENT_WITH_ERRORS)
378*f585d8a3SJacky Wang                   .onLineContaining("interface SubcomponentWithErrors");
379*f585d8a3SJacky Wang             });
380*f585d8a3SJacky Wang   }
381*f585d8a3SJacky Wang 
382*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithErrors_validationTypeWarning()383*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithErrors_validationTypeWarning() {
384*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(
385*f585d8a3SJacky Wang             MODULE_WITH_SUBCOMPONENT_WITH_ERRORS, SUBCOMPONENT_WITH_ERRORS, A_MODULE)
386*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
387*f585d8a3SJacky Wang         .compile(
388*f585d8a3SJacky Wang             subject -> {
389*f585d8a3SJacky Wang               subject.hasErrorCount(0);
390*f585d8a3SJacky Wang               subject.hasWarningCount(2);
391*f585d8a3SJacky Wang 
392*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(
393*f585d8a3SJacky Wang                       MODULE_WITH_SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
394*f585d8a3SJacky Wang                   .onSource(MODULE_WITH_SUBCOMPONENT_WITH_ERRORS)
395*f585d8a3SJacky Wang                   .onLineContaining("interface ModuleWithSubcomponentWithErrors");
396*f585d8a3SJacky Wang 
397*f585d8a3SJacky Wang               // TODO(b/130283677): Don't repeat error.
398*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(SUBCOMPONENT_WITH_ERRORS_MESSAGE.pattern())
399*f585d8a3SJacky Wang                   .onSource(SUBCOMPONENT_WITH_ERRORS)
400*f585d8a3SJacky Wang                   .onLineContaining("interface SubcomponentWithErrors");
401*f585d8a3SJacky Wang             });
402*f585d8a3SJacky Wang   }
403*f585d8a3SJacky Wang 
404*f585d8a3SJacky Wang   private static final Source A_SUBCOMPONENT =
405*f585d8a3SJacky Wang       CompilerTests.javaSource(
406*f585d8a3SJacky Wang           "test.ASubcomponent",
407*f585d8a3SJacky Wang           "package test;",
408*f585d8a3SJacky Wang           "",
409*f585d8a3SJacky Wang           "import dagger.BindsInstance;",
410*f585d8a3SJacky Wang           "import dagger.Subcomponent;",
411*f585d8a3SJacky Wang           "",
412*f585d8a3SJacky Wang           "@Subcomponent(modules = AModule.class)",
413*f585d8a3SJacky Wang           "interface ASubcomponent {",
414*f585d8a3SJacky Wang           "  @Subcomponent.Builder",
415*f585d8a3SJacky Wang           "  interface Builder {",
416*f585d8a3SJacky Wang           "    ASubcomponent build();",
417*f585d8a3SJacky Wang           "  }",
418*f585d8a3SJacky Wang           "}");
419*f585d8a3SJacky Wang 
420*f585d8a3SJacky Wang   private static final Source COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS =
421*f585d8a3SJacky Wang       CompilerTests.javaSource(
422*f585d8a3SJacky Wang           "test.CombinedWithASubcomponentHasErrors",
423*f585d8a3SJacky Wang           "package test;",
424*f585d8a3SJacky Wang           "",
425*f585d8a3SJacky Wang           "import dagger.Binds;",
426*f585d8a3SJacky Wang           "import dagger.Module;",
427*f585d8a3SJacky Wang           "",
428*f585d8a3SJacky Wang           "@Module(subcomponents = ASubcomponent.class)",
429*f585d8a3SJacky Wang           "interface CombinedWithASubcomponentHasErrors {",
430*f585d8a3SJacky Wang           "  @Binds Object object(Number number);",
431*f585d8a3SJacky Wang           "}");
432*f585d8a3SJacky Wang 
433*f585d8a3SJacky Wang   // Make sure the error doesn't show other bindings or a dependency trace afterwards.
434*f585d8a3SJacky Wang   private static final Pattern COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE =
435*f585d8a3SJacky Wang       endsWithMessage(
436*f585d8a3SJacky Wang           "\033[1;31m[Dagger/DuplicateBindings]\033[0m Object is bound multiple times:",
437*f585d8a3SJacky Wang           "    @Binds Object AModule.object(String)",
438*f585d8a3SJacky Wang           "    @Binds Object CombinedWithASubcomponentHasErrors.object(Number)",
439*f585d8a3SJacky Wang           "    in component: [CombinedWithASubcomponentHasErrors → ASubcomponent]",
440*f585d8a3SJacky Wang           "",
441*f585d8a3SJacky Wang           "======================",
442*f585d8a3SJacky Wang           "Full classname legend:",
443*f585d8a3SJacky Wang           "======================",
444*f585d8a3SJacky Wang           "AModule:                            test.AModule",
445*f585d8a3SJacky Wang           "ASubcomponent:                      test.ASubcomponent",
446*f585d8a3SJacky Wang           "CombinedWithASubcomponentHasErrors: test.CombinedWithASubcomponentHasErrors",
447*f585d8a3SJacky Wang           "========================",
448*f585d8a3SJacky Wang           "End of classname legend:",
449*f585d8a3SJacky Wang           "========================");
450*f585d8a3SJacky Wang 
451*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithCombinedErrors_validationTypeNone()452*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithCombinedErrors_validationTypeNone() {
453*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE)
454*f585d8a3SJacky Wang         .compile(
455*f585d8a3SJacky Wang             subject -> {
456*f585d8a3SJacky Wang               subject.hasErrorCount(0);
457*f585d8a3SJacky Wang               subject.hasWarningCount(0);
458*f585d8a3SJacky Wang             });
459*f585d8a3SJacky Wang   }
460*f585d8a3SJacky Wang 
461*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithCombinedErrors_validationTypeError()462*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithCombinedErrors_validationTypeError() {
463*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE)
464*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "ERROR"))
465*f585d8a3SJacky Wang         .compile(
466*f585d8a3SJacky Wang             subject -> {
467*f585d8a3SJacky Wang               subject.hasErrorCount(1);
468*f585d8a3SJacky Wang               subject.hasErrorContainingMatch(
469*f585d8a3SJacky Wang                       COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE.pattern())
470*f585d8a3SJacky Wang                   .onSource(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS)
471*f585d8a3SJacky Wang                   .onLineContaining("interface CombinedWithASubcomponentHasErrors");
472*f585d8a3SJacky Wang             });
473*f585d8a3SJacky Wang   }
474*f585d8a3SJacky Wang 
475*f585d8a3SJacky Wang   @Test
moduleWithSubcomponentWithCombinedErrors_validationTypeWarning()476*f585d8a3SJacky Wang   public void moduleWithSubcomponentWithCombinedErrors_validationTypeWarning() {
477*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS, A_SUBCOMPONENT, A_MODULE)
478*f585d8a3SJacky Wang         .withProcessingOptions(ImmutableMap.of("dagger.fullBindingGraphValidation", "WARNING"))
479*f585d8a3SJacky Wang         .compile(
480*f585d8a3SJacky Wang             subject -> {
481*f585d8a3SJacky Wang               subject.hasErrorCount(0);
482*f585d8a3SJacky Wang               subject.hasWarningCount(1);
483*f585d8a3SJacky Wang               subject.hasWarningContainingMatch(
484*f585d8a3SJacky Wang                       COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS_MESSAGE.pattern())
485*f585d8a3SJacky Wang                   .onSource(COMBINED_WITH_A_SUBCOMPONENT_HAS_ERRORS)
486*f585d8a3SJacky Wang                   .onLineContaining("interface CombinedWithASubcomponentHasErrors");
487*f585d8a3SJacky Wang             });
488*f585d8a3SJacky Wang   }
489*f585d8a3SJacky Wang 
490*f585d8a3SJacky Wang   @Test
bothAliasesDifferentValues()491*f585d8a3SJacky Wang   public void bothAliasesDifferentValues() {
492*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS)
493*f585d8a3SJacky Wang         .withProcessingOptions(
494*f585d8a3SJacky Wang             ImmutableMap.of(
495*f585d8a3SJacky Wang                 "dagger.moduleBindingValidation", "NONE",
496*f585d8a3SJacky Wang                 "dagger.fullBindingGraphValidation", "ERROR"))
497*f585d8a3SJacky Wang         .compile(
498*f585d8a3SJacky Wang             subject -> {
499*f585d8a3SJacky Wang               subject.hasErrorCount(1);
500*f585d8a3SJacky Wang               subject.hasErrorContaining(
501*f585d8a3SJacky Wang                   "Only one of the equivalent options "
502*f585d8a3SJacky Wang                       + "(-Adagger.fullBindingGraphValidation, -Adagger.moduleBindingValidation)"
503*f585d8a3SJacky Wang                       + " should be used; prefer -Adagger.fullBindingGraphValidation");
504*f585d8a3SJacky Wang             });
505*f585d8a3SJacky Wang   }
506*f585d8a3SJacky Wang 
507*f585d8a3SJacky Wang   @Test
bothAliasesSameValue()508*f585d8a3SJacky Wang   public void bothAliasesSameValue() {
509*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(MODULE_WITH_ERRORS)
510*f585d8a3SJacky Wang         .withProcessingOptions(
511*f585d8a3SJacky Wang             ImmutableMap.of(
512*f585d8a3SJacky Wang                 "dagger.moduleBindingValidation", "NONE",
513*f585d8a3SJacky Wang                 "dagger.fullBindingGraphValidation", "NONE"))
514*f585d8a3SJacky Wang         .compile(
515*f585d8a3SJacky Wang             subject -> {
516*f585d8a3SJacky Wang               subject.hasErrorCount(0);
517*f585d8a3SJacky Wang               subject.hasWarningCount(1);
518*f585d8a3SJacky Wang               subject.hasWarningContaining(
519*f585d8a3SJacky Wang                   "Only one of the equivalent options "
520*f585d8a3SJacky Wang                       + "(-Adagger.fullBindingGraphValidation, -Adagger.moduleBindingValidation)"
521*f585d8a3SJacky Wang                       + " should be used; prefer -Adagger.fullBindingGraphValidation");
522*f585d8a3SJacky Wang             });
523*f585d8a3SJacky Wang   }
524*f585d8a3SJacky Wang }
525