• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.util.Set;
26 import java.util.stream.Collectors;
27 import org.gradle.testkit.runner.BuildResult;
28 import org.gradle.testkit.runner.GradleRunner;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.rules.TemporaryFolder;
32 import org.junit.runner.RunWith;
33 import org.junit.runners.JUnit4;
34 
35 // This is a regression test for https://github.com/google/dagger/issues/4054
36 @RunWith(JUnit4.class)
37 public class IncrementalProcessingTest {
38   @Rule public TemporaryFolder tmpFolder = new TemporaryFolder();
39 
40   @Test
testIncrementalProcessing()41   public void testIncrementalProcessing() throws IOException {
42     File projectDir = tmpFolder.getRoot();
43     GradleModule.create(projectDir)
44         .addSettingsFile("include 'app'")
45         .addBuildFile(
46             "buildscript {",
47             "  ext {",
48             String.format("dagger_version = \"%s\"", System.getProperty("dagger_version")),
49             String.format("kotlin_version = \"%s\"", System.getProperty("kotlin_version")),
50             String.format("ksp_version = \"%s\"", System.getProperty("ksp_version")),
51             "  }",
52             "}",
53             "",
54             "allprojects {",
55             "  repositories {",
56             "    mavenCentral()",
57             "    mavenLocal()",
58             "  }",
59             "}");
60 
61     GradleModule appModule =
62         GradleModule.create(projectDir, "app")
63             .addBuildFile(
64                 "plugins {",
65                 "  id 'application'",
66                 "  id 'org.jetbrains.kotlin.jvm' version \"$kotlin_version\"",
67                 "  id 'com.google.devtools.ksp' version \"$ksp_version\"",
68                 "}",
69                 "dependencies {",
70                 "  implementation \"org.jetbrains.kotlin:kotlin-stdlib\"",
71                 "  implementation \"com.google.dagger:dagger:$dagger_version\"",
72                 "  ksp \"com.google.dagger:dagger-compiler:$dagger_version\"",
73                 "}")
74             // Note: both A and AFactory need to be in the same source file for this to test the
75             // regression in https://github.com/google/dagger/issues/4054.
76             .addSrcFile(
77                 "A.kt",
78                 "package app",
79                 "",
80                 "import dagger.assisted.AssistedFactory",
81                 "import dagger.assisted.AssistedInject",
82                 "",
83                 "class A @AssistedInject constructor()",
84                 "",
85                 "@AssistedFactory",
86                 "interface AFactory {",
87                 "    fun create(): A",
88                 "}");
89 
90     // We'll be changing the contents of MyComponent between builds, so store it in a variable.
91     String myComponentContent =
92         String.join(
93             "\n",
94             "package app",
95             "",
96             "import dagger.Component",
97             "",
98             "@Component",
99             "interface MyComponent {",
100             "  fun factory(): AFactory",
101             "}");
102     appModule.addSrcFile("MyComponent.kt",  myComponentContent);
103 
104     // Build #1
105     build(projectDir);
106     assertThat(getAllKspGeneratedFileNames(appModule.getDir()))
107         .containsExactly(
108             "A_Factory.java",
109             "AFactory_Impl.java",
110             "DaggerMyComponent.java");
111 
112     // Change method name in MyComponent.kt to trigger incremental processing of only MyComponent.
113     appModule.addSrcFile("MyComponent.kt",  myComponentContent.replace("factory()", "factory2()"));
114 
115     // Build #2
116     build(projectDir);
117     assertThat(getAllKspGeneratedFileNames(appModule.getDir()))
118         .containsExactly(
119             "A_Factory.java",
120             "AFactory_Impl.java",
121             "DaggerMyComponent.java");
122   }
123 
build(File projectDir)124   private static BuildResult build(File projectDir) {
125     return GradleRunner.create()
126         .withArguments("--stacktrace", "build")
127         .withProjectDir(projectDir)
128         .build();
129   }
130 
getAllKspGeneratedFileNames(Path moduleDir)131   private static Set<String> getAllKspGeneratedFileNames(Path moduleDir) throws IOException {
132     return getAllFileNames(moduleDir.resolve("build/generated/ksp/main/java/"));
133   }
134 
getAllFileNames(Path dir)135   private static Set<String> getAllFileNames(Path dir) throws IOException {
136     if (!Files.isDirectory(dir)) {
137       throw new IllegalArgumentException("Expected directory: " + dir);
138     }
139     return Files.walk(dir)
140         .filter(Files::isRegularFile)
141         .map(file -> file.getFileName().toString())
142         .collect(Collectors.toSet());
143   }
144 }
145