• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
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 package com.google.auto.value;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 
21 import com.google.common.collect.ImmutableList;
22 import java.io.File;
23 import java.io.IOException;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.Optional;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 import java.util.stream.Stream;
31 import org.gradle.testkit.runner.BuildResult;
32 import org.gradle.testkit.runner.GradleRunner;
33 import org.gradle.util.GradleVersion;
34 import org.junit.Rule;
35 import org.junit.Test;
36 import org.junit.rules.TemporaryFolder;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.JUnit4;
39 
40 @RunWith(JUnit4.class)
41 public class GradleIT {
42   @Rule public TemporaryFolder fakeProject = new TemporaryFolder();
43 
44   private static final String BUILD_GRADLE_TEXT =
45       String.join(
46           "\n",
47           "plugins {",
48           "  id 'java-library'",
49           "}",
50           "repositories {",
51           "  maven { url = uri('${localRepository}') }",
52           "}",
53           "dependencies {",
54           "  compileOnlyApi     "
55               + " 'com.google.auto.value:auto-value-annotations:${autoValueVersion}'",
56           "  annotationProcessor 'com.google.auto.value:auto-value:${autoValueVersion}'",
57           "}");
58 
59   private static final String FOO_TEXT =
60       String.join(
61           "\n",
62           "package com.example;",
63           "",
64           "import com.google.auto.value.AutoValue;",
65           "",
66           "@AutoValue",
67           "abstract class Foo {",
68           "  abstract String bar();",
69           "",
70           "  static Foo of(String bar) {",
71           "    return new AutoValue_Foo(bar);",
72           "  }",
73           "}");
74 
75   private static final Optional<File> GRADLE_INSTALLATION = getGradleInstallation();
76 
77   @Test
basic()78   public void basic() throws IOException {
79     String autoValueVersion = System.getProperty("autoValueVersion");
80     assertThat(autoValueVersion).isNotNull();
81     String localRepository = System.getProperty("localRepository");
82     assertThat(localRepository).isNotNull();
83 
84     // Set up the fake Gradle project.
85     String buildGradleText = expandSystemProperties(BUILD_GRADLE_TEXT);
86     writeFile(fakeProject.newFile("build.gradle").toPath(), buildGradleText);
87     Path srcDir = fakeProject.newFolder("src", "main", "java", "com", "example").toPath();
88     writeFile(srcDir.resolve("Foo.java"), FOO_TEXT);
89 
90     // Build it the first time.
91     BuildResult result1 = buildFakeProject();
92     assertThat(result1.getOutput())
93         .contains(
94             "Full recompilation is required because no incremental change information is"
95                 + " available");
96     Path output =
97         fakeProject
98             .getRoot()
99             .toPath()
100             .resolve("build/classes/java/main/com/example/AutoValue_Foo.class");
101     assertThat(Files.exists(output)).isTrue();
102 
103     // Add a source file to the project.
104     String barText = FOO_TEXT.replace("Foo", "Bar");
105     Path barFile = srcDir.resolve("Bar.java");
106     writeFile(barFile, barText);
107 
108     // Build it a second time.
109     BuildResult result2 = buildFakeProject();
110     assertThat(result2.getOutput()).doesNotContain("Full recompilation is required");
111 
112     // Remove the second source file and build a third time. If incremental annotation processing
113     // is not working, this will produce a message like this:
114     //   Full recompilation is required because com.google.auto.value.processor.AutoValueProcessor
115     //   is not incremental
116     Files.delete(barFile);
117     BuildResult result3 = buildFakeProject();
118     assertThat(result3.getOutput()).doesNotContain("Full recompilation is required");
119   }
120 
buildFakeProject()121   private BuildResult buildFakeProject() throws IOException {
122     GradleRunner runner =
123         GradleRunner.create()
124             .withProjectDir(fakeProject.getRoot())
125             .withArguments("--info", "compileJava");
126     if (GRADLE_INSTALLATION.isPresent()) {
127       runner.withGradleInstallation(GRADLE_INSTALLATION.get());
128     } else {
129       runner.withGradleVersion(GradleVersion.current().getVersion());
130     }
131     return runner.build();
132   }
133 
getGradleInstallation()134   private static Optional<File> getGradleInstallation() {
135     String gradleHome = System.getenv("GRADLE_HOME");
136     if (gradleHome != null) {
137       File gradleHomeFile = new File(gradleHome);
138       if (gradleHomeFile.isDirectory()) {
139         return Optional.of(new File(gradleHome));
140       }
141     }
142     try {
143       Path gradleExecutable = Paths.get("/usr/bin/gradle");
144       Path gradleLink = gradleExecutable.resolveSibling(Files.readSymbolicLink(gradleExecutable));
145       if (!gradleLink.endsWith("bin/gradle")) {
146         return Optional.empty();
147       }
148       Path installationPath = gradleLink.getParent().getParent();
149       if (!Files.isDirectory(installationPath)) {
150         return Optional.empty();
151       }
152       Optional<Path> coreJar;
153       Pattern corePattern = Pattern.compile("gradle-core-([0-9]+)\\..*\\.jar");
154       try (Stream<Path> files = Files.walk(installationPath.resolve("lib"))) {
155         coreJar =
156             files
157                 .filter(
158                     p -> {
159                       Matcher matcher = corePattern.matcher(p.getFileName().toString());
160                       if (matcher.matches()) {
161                         int version = Integer.parseInt(matcher.group(1));
162                         if (version >= 5) {
163                           return true;
164                         }
165                       }
166                       return false;
167                     })
168                 .findFirst();
169       }
170       return coreJar.map(unused -> installationPath.toFile());
171     } catch (IOException e) {
172       return Optional.empty();
173     }
174   }
175 
expandSystemProperties(String s)176   private static String expandSystemProperties(String s) {
177     for (String name : System.getProperties().stringPropertyNames()) {
178       String value = System.getProperty(name);
179       s = s.replace("${" + name + "}", value);
180     }
181     return s;
182   }
183 
writeFile(Path file, String text)184   private static void writeFile(Path file, String text) throws IOException {
185     Files.write(file, ImmutableList.of(text), UTF_8);
186   }
187 }
188