• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 buildtests;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.gradle.testkit.runner.TaskOutcome.SUCCESS;
21 
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import org.gradle.testkit.runner.BuildResult;
27 import org.gradle.testkit.runner.GradleRunner;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.TemporaryFolder;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.Parameterized;
33 import org.junit.runners.Parameterized.Parameters;
34 
35 // This is a regression test for https://github.com/google/dagger/issues/3136
36 @RunWith(Parameterized.class)
37 public class TransitiveComponentDependenciesTest {
38   @Parameters(name = "{0}")
parameters()39   public static Collection<Object[]> parameters() {
40     return Arrays.asList(new Object[][] {{"implementation"}, {"api"}});
41   }
42 
43   @Rule public TemporaryFolder folder = new TemporaryFolder();
44 
45   private final String transitiveDependencyType;
46 
TransitiveComponentDependenciesTest(String transitiveDependencyType)47   public TransitiveComponentDependenciesTest(String transitiveDependencyType) {
48     this.transitiveDependencyType = transitiveDependencyType;
49   }
50 
51   @Test
testsComponentDependencies()52   public void testsComponentDependencies() throws IOException {
53     BuildResult result;
54     switch (transitiveDependencyType) {
55       case "implementation":
56         result = setupRunner().buildAndFail();
57         assertThat(result.getOutput()).contains("Task :app:compileJava FAILED");
58         String expectedErrorMsg =
59             "error: ComponentProcessingStep was unable to process 'app.ComponentC' because"
60                 + " 'libraryA.ComponentA' could not be resolved."
61                 + "\n  "
62                 + "\n  Dependency trace:"
63                 + "\n      => element (CLASS): libraryB.ComponentB"
64                 + "\n      => annotation type: dagger.Component"
65                 + "\n      => annotation: @dagger.Component("
66                 + "modules={}, dependencies={libraryA.ComponentA})"
67                 + "\n      => annotation value (TYPE_ARRAY): dependencies={libraryA.ComponentA}"
68                 + "\n      => annotation value (TYPE): dependencies=libraryA.ComponentA";
69         assertThat(result.getOutput()).contains(expectedErrorMsg);
70         break;
71       case "api":
72         result = setupRunner().build();
73         assertThat(result.task(":app:assemble").getOutcome()).isEqualTo(SUCCESS);
74         break;
75     }
76   }
77 
setupRunner()78   private GradleRunner setupRunner() throws IOException {
79     File projectDir = folder.getRoot();
80     GradleModule.create(projectDir)
81         .addSettingsFile("include 'app'", "include 'libraryB'", "include 'libraryA'")
82         .addBuildFile(
83             "buildscript {",
84             "  ext {",
85             String.format("dagger_version = \"%s\"", System.getProperty("dagger_version")),
86             "  }",
87             "}",
88             "",
89             "allprojects {",
90             "  repositories {",
91             "    mavenCentral()",
92             "    mavenLocal()",
93             "  }",
94             "}");
95 
96     GradleModule.create(projectDir, "app")
97         .addBuildFile(
98             "plugins {",
99             "  id 'java'",
100             "  id 'application'",
101             "}",
102             "tasks.withType(JavaCompile) {",
103             "    options.compilerArgs += '-Adagger.experimentalDaggerErrorMessages=ENABLED'",
104             "}",
105             "dependencies {",
106             "  implementation project(':libraryB')",
107             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
108             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
109             "}")
110         .addSrcFile(
111             "ComponentC.java",
112             "package app;",
113             "",
114             "import dagger.Component;",
115             "import libraryB.ComponentB;",
116             "",
117             "@Component(dependencies = ComponentB.class)",
118             "public interface ComponentC {",
119             "  public abstract C getC();",
120             "}")
121         .addSrcFile(
122             "C.java",
123             "package app;",
124             "",
125             "import javax.inject.Inject;",
126             "import libraryB.B;",
127             "",
128             "public class C {",
129             "  @Inject C(B b) {}",
130             "}");
131 
132     GradleModule.create(projectDir, "libraryB")
133         .addBuildFile(
134             "plugins {",
135             "  id 'java'",
136             "  id 'java-library'",
137             "}",
138             "dependencies {",
139             transitiveDependencyType + " project(':libraryA')",
140             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
141             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
142             "}")
143         .addSrcFile(
144             "ComponentB.java",
145             "package libraryB;",
146             "",
147             "import dagger.Component;",
148             "import libraryA.ComponentA;",
149             "",
150             "@Component(dependencies = ComponentA.class)",
151             "public abstract class ComponentB {",
152             "  public abstract B getB();",
153             "}")
154         .addSrcFile(
155             "B.java",
156             "package libraryB;",
157             "",
158             "import javax.inject.Inject;",
159             "import libraryA.A;",
160             "",
161             "public class B {",
162             "  @Inject B(A a) {}",
163             "}");
164 
165     GradleModule.create(projectDir, "libraryA")
166         .addBuildFile(
167             "plugins {",
168             "  id 'java'",
169             "  id 'java-library'",
170             "}",
171             "dependencies {",
172             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
173             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
174             "}")
175         .addSrcFile(
176             "ComponentA.java",
177             "package libraryA;",
178             "",
179             "import dagger.Component;",
180             "",
181             "@Component",
182             "public abstract class ComponentA {",
183             "  public abstract A getA();",
184             "}")
185         .addSrcFile(
186             "A.java",
187             "package libraryA;",
188             "",
189             "import javax.inject.Inject;",
190             "",
191             "public class A {",
192             "  @Inject A() {}",
193             "}")
194         .addSrcFile(
195             "AScope.java",
196             "package libraryA;",
197             "",
198             "import javax.inject.Scope;",
199             "",
200             "@Scope",
201             "public @interface AScope {}");
202 
203     return GradleRunner.create().withArguments("--stacktrace", "build").withProjectDir(projectDir);
204   }
205 }
206