• 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 TransitiveBindsQualifierTest {
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 
TransitiveBindsQualifierTest(String transitiveDependencyType)47   public TransitiveBindsQualifierTest(String transitiveDependencyType) {
48     this.transitiveDependencyType = transitiveDependencyType;
49   }
50 
51   @Test
testQualifierOnBindsMethod()52   public void testQualifierOnBindsMethod() 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): bindObject(java.lang.Number)"
66                     + "\n      => element (PARAMETER): arg0"
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())
74             .contains("BINDINGS: ["
75                 + "@library2.MyQualifier java.lang.Object, "
76                 + "@library2.MyQualifier java.lang.Number, "
77                 + "java.lang.Integer"
78                 + "]");
79         break;
80     }
81   }
82 
setupRunner()83   private GradleRunner setupRunner() throws IOException {
84     File projectDir = folder.getRoot();
85     GradleModule.create(projectDir)
86         .addSettingsFile(
87             "include 'app'",
88             "include 'library1'",
89             "include 'library2'",
90             "include 'spi-plugin'")
91         .addBuildFile(
92             "buildscript {",
93             "  ext {",
94             String.format("dagger_version = \"%s\"", System.getProperty("dagger_version")),
95             "  }",
96             "}",
97             "",
98             "allprojects {",
99             "  repositories {",
100             "    mavenCentral()",
101             "    mavenLocal()",
102             "  }",
103             "}");
104 
105     GradleModule.create(projectDir, "app")
106         .addBuildFile(
107             "plugins {",
108             "  id 'java'",
109             "  id 'application'",
110             "}",
111             "compileJava {",
112             "    options.compilerArgs << '-Adagger.pluginsVisitFullBindingGraphs=ENABLED'",
113             "}",
114             "dependencies {",
115             "  implementation project(':library1')",
116             "  annotationProcessor project(':spi-plugin')",
117             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
118             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
119             "}")
120         .addSrcFile(
121             "MyComponent.java",
122             "package app;",
123             "",
124             "import dagger.BindsInstance;",
125             "import dagger.Component;",
126             "import library1.MyModule;",
127             "",
128             "@Component(modules = MyModule.class)",
129             "public interface MyComponent {",
130             "  @Component.Factory",
131             "  interface Factory {",
132             "    MyComponent create(@BindsInstance int i);",
133             "  }",
134             "}");
135 
136     GradleModule.create(projectDir, "library1")
137         .addBuildFile(
138             "plugins {",
139             "  id 'java'",
140             "  id 'java-library'",
141             "}",
142             "dependencies {",
143             transitiveDependencyType + " project(':library2')",
144             "  implementation \"com.google.dagger:dagger:$dagger_version\"",
145             "  annotationProcessor \"com.google.dagger:dagger-compiler:$dagger_version\"",
146             "}")
147         .addSrcFile(
148             "MyModule.java",
149             "package library1;",
150             "",
151             "import dagger.Binds;",
152             "import dagger.Module;",
153             "import dagger.Provides;",
154             "import library2.MyQualifier;",
155             "",
156             "@Module",
157             "public interface MyModule {",
158             "  @Binds",
159             "  @MyQualifier",
160             "  Object bindObject(@MyQualifier Number number);",
161             "",
162             "  @Binds",
163             "  @MyQualifier",
164             "  Number bindNumber(int i);",
165             "}");
166 
167     GradleModule.create(projectDir, "library2")
168         .addBuildFile(
169             "plugins {",
170             "  id 'java'",
171             "  id 'java-library'",
172             "}",
173             "dependencies {",
174             "  implementation 'javax.inject:javax.inject:1'",
175             "}")
176         .addSrcFile(
177             "MyQualifier.java",
178             "package library2;",
179             "",
180             "import javax.inject.Qualifier;",
181             "",
182             "@Qualifier",
183             "public @interface MyQualifier {}");
184 
185     // This plugin is used to print output about bindings that we can assert on in tests.
186     GradleModule.create(projectDir, "spi-plugin")
187         .addBuildFile(
188             "plugins {",
189             "  id 'java'",
190             "}",
191             "dependencies {",
192             "  implementation \"com.google.dagger:dagger-spi:$dagger_version\"",
193             "  implementation 'com.google.auto.service:auto-service-annotations:1.0.1'",
194             "  annotationProcessor 'com.google.auto.service:auto-service:1.0.1'",
195             "}")
196         .addSrcFile(
197             "TestBindingGraphPlugin.java",
198             "package spiplugin;",
199             "",
200             "import com.google.auto.service.AutoService;",
201             "import dagger.model.Binding;",
202             "import dagger.model.BindingGraph;",
203             "import dagger.model.BindingGraph.DependencyEdge;",
204             "import dagger.model.DependencyRequest;",
205             "import dagger.spi.BindingGraphPlugin;",
206             "import dagger.spi.DiagnosticReporter;",
207             "import java.util.stream.Collectors;",
208             "",
209             "@AutoService(BindingGraphPlugin.class)",
210             "public class TestBindingGraphPlugin implements BindingGraphPlugin {",
211             "  @Override",
212             "  public void visitGraph(",
213             "      BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {",
214             "    if (!bindingGraph.isFullBindingGraph() || bindingGraph.isModuleBindingGraph()) {",
215             "      return;",
216             "    }",
217             "    System.out.print(",
218             "        \"BINDINGS: \"",
219             "            + bindingGraph.bindings().stream()",
220             "                  .map(Binding::key)",
221             "                  .collect(Collectors.toList()));",
222             "  }",
223             "}");
224 
225     return GradleRunner.create()
226         .withArguments("--stacktrace", "build")
227         .withProjectDir(projectDir);
228   }
229 }
230