• 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 TransitiveProvidesQualifierTest {
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 
TransitiveProvidesQualifierTest(String transitiveDependencyType)47   public TransitiveProvidesQualifierTest(String transitiveDependencyType) {
48     this.transitiveDependencyType = transitiveDependencyType;
49   }
50 
51   @Test
testQualifierOnProvidesMethodParameter()52   public void testQualifierOnProvidesMethodParameter() 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         assertThat(result.getOutput())
59             .contains(
60                 "ComponentProcessingStep was unable to process 'app.MyComponent' because "
61                     + "'library2.MyQualifier' could not be resolved."
62                     + "\n  "
63                     + "\n  Dependency trace:"
64                     + "\n      => element (INTERFACE): library1.MyModule"
65                     + "\n      => element (METHOD): provideString(int)"
66                     + "\n      => element (PARAMETER): i"
67                     + "\n      => annotation: @MyQualifier"
68                     + "\n      => type (ERROR annotation type): library2.MyQualifier");
69         break;
70       case "api":
71         result = setupRunner().build();
72         assertThat(result.task(":app:assemble").getOutcome()).isEqualTo(SUCCESS);
73         assertThat(result.getOutput()).contains("REQUEST: @library2.MyQualifier java.lang.Integer");
74         break;
75     }
76   }
77 
setupRunner()78   private GradleRunner setupRunner() throws IOException {
79     File projectDir = folder.getRoot();
80     GradleModule.create(projectDir)
81         .addSettingsFile(
82             "include 'app'",
83             "include 'library1'",
84             "include 'library2'",
85             "include 'spi-plugin'")
86         .addBuildFile(
87             "buildscript {",
88             "  ext {",
89             String.format("dagger_version = \"%s\"", System.getProperty("dagger_version")),
90             "  }",
91             "}",
92             "",
93             "allprojects {",
94             "  repositories {",
95             "    mavenCentral()",
96             "    mavenLocal()",
97             "  }",
98             "}");
99 
100     GradleModule.create(projectDir, "app")
101         .addBuildFile(
102             "plugins {",
103             "  id 'java'",
104             "  id 'application'",
105             "}",
106             "tasks.withType(JavaCompile) {",
107             "    options.compilerArgs += '-Adagger.experimentalDaggerErrorMessages=ENABLED'",
108             "}",
109             "dependencies {",
110             "  implementation project(':library1')",
111             "  annotationProcessor project(':spi-plugin')",
112             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
113             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
114             "}")
115         .addSrcFile(
116             "MyComponent.java",
117             "package app;",
118             "",
119             "import dagger.Component;",
120             "import library1.MyModule;",
121             "",
122             "@Component(modules = MyModule.class)",
123             "public interface MyComponent {",
124             "  String string();",
125             "}");
126 
127     GradleModule.create(projectDir, "library1")
128         .addBuildFile(
129             "plugins {",
130             "  id 'java'",
131             "  id 'java-library'",
132             "}",
133             "dependencies {",
134             transitiveDependencyType + " project(':library2')",
135             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
136             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
137             "}")
138         .addSrcFile(
139             "MyModule.java",
140             "package library1;",
141             "",
142             "import dagger.Module;",
143             "import dagger.Provides;",
144             "import library2.MyQualifier;",
145             "",
146             "@Module",
147             "public interface MyModule {",
148             "  @Provides",
149             "  static String provideString(@MyQualifier int i) {",
150             "    return \"\";",
151             "  }",
152             "",
153             "  @Provides",
154             "  @MyQualifier",
155             "  static int provideInt() {",
156             "    return 0;",
157             "  }",
158             "}");
159 
160     GradleModule.create(projectDir, "library2")
161         .addBuildFile(
162             "plugins {",
163             "  id 'java'",
164             "  id 'java-library'",
165             "}",
166             "dependencies {",
167             "  implementation 'javax.inject:javax.inject:1'",
168             "}")
169         .addSrcFile(
170             "MyQualifier.java",
171             "package library2;",
172             "",
173             "import javax.inject.Qualifier;",
174             "",
175             "@Qualifier",
176             "public @interface MyQualifier {}");
177 
178     // This plugin is used to print output about bindings that we can assert on in tests.
179     GradleModule.create(projectDir, "spi-plugin")
180         .addBuildFile(
181             "plugins {",
182             "  id 'java'",
183             "}",
184             "dependencies {",
185             "  implementation \"com.google.dagger:dagger-spi:$dagger_version\"",
186             "  implementation 'com.google.auto.service:auto-service-annotations:1.0.1'",
187             "  annotationProcessor 'com.google.auto.service:auto-service:1.0.1'",
188             "}")
189         .addSrcFile(
190             "TestBindingGraphPlugin.java",
191             "package spiplugin;",
192             "",
193             "import com.google.auto.service.AutoService;",
194             "import dagger.model.BindingGraph;",
195             "import dagger.model.BindingGraph.DependencyEdge;",
196             "import dagger.model.DependencyRequest;",
197             "import dagger.spi.BindingGraphPlugin;",
198             "import dagger.spi.DiagnosticReporter;",
199             "",
200             "@AutoService(BindingGraphPlugin.class)",
201             "public class TestBindingGraphPlugin implements BindingGraphPlugin {",
202             "  @Override",
203             "  public void visitGraph(",
204             "      BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {",
205             "    bindingGraph.dependencyEdges().stream()",
206             "        .map(DependencyEdge::dependencyRequest)",
207             "        .map(DependencyRequest::key)",
208             "        .forEach(key -> System.out.println(\"REQUEST: \" + key));",
209             "  }",
210             "}");
211 
212     return GradleRunner.create()
213         .withArguments("--stacktrace", "build")
214         .withProjectDir(projectDir);
215   }
216 }
217