• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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.base.StandardSystemProperty.JAVA_HOME;
19 import static com.google.common.collect.ImmutableSet.toImmutableSet;
20 import static com.google.common.truth.Truth.assertThat;
21 import static com.google.common.truth.Truth.assertWithMessage;
22 
23 import com.google.auto.value.processor.AutoAnnotationProcessor;
24 import com.google.auto.value.processor.AutoBuilderProcessor;
25 import com.google.auto.value.processor.AutoOneOfProcessor;
26 import com.google.auto.value.processor.AutoValueProcessor;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.ImmutableSet;
29 import java.io.File;
30 import java.io.IOException;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.function.Predicate;
36 import java.util.stream.Stream;
37 import javax.annotation.processing.Processor;
38 import javax.tools.JavaCompiler;
39 import javax.tools.JavaFileObject;
40 import javax.tools.StandardJavaFileManager;
41 import javax.tools.StandardLocation;
42 import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
43 import org.junit.BeforeClass;
44 import org.junit.Rule;
45 import org.junit.Test;
46 import org.junit.rules.TemporaryFolder;
47 import org.junit.runner.RunWith;
48 import org.junit.runners.JUnit4;
49 
50 /**
51  * Tests that we can compile our AutoValue tests using the Eclipse batch compiler. Since the tests
52  * exercise many AutoValue subtleties, the ability to compile them all is a good indication of
53  * Eclipse support.
54  */
55 @RunWith(JUnit4.class)
56 public class CompileWithEclipseTest {
57   private static final String SOURCE_ROOT = System.getProperty("basedir");
58 
59   @BeforeClass
setSourceRoot()60   public static void setSourceRoot() {
61     assertWithMessage("basedir property must be set - test must be run from Maven")
62         .that(SOURCE_ROOT)
63         .isNotNull();
64   }
65 
66   public @Rule TemporaryFolder tmp = new TemporaryFolder();
67 
68   private static final ImmutableSet<String> IGNORED_TEST_FILES =
69       ImmutableSet.of(
70           "AutoValueNotEclipseTest.java",
71           "CompileWithEclipseTest.java",
72           "CustomFieldSerializerTest.java",
73           "GradleIT.java",
74 
75           // AutoBuilder sometimes needs to generate a .class file for Kotlin that is used in the
76           // rest of compilation, and Eclipse doesn't seem to handle that well. Presumably not many
77           // Kotlin users use Eclipse since IntelliJ is obviously much more suitable.
78           "AutoBuilderKotlinTest.java");
79 
80   private static final Predicate<File> JAVA_FILE =
81       f -> f.getName().endsWith(".java") && !IGNORED_TEST_FILES.contains(f.getName());
82 
83   private static final ImmutableSet<String> JAVA8_TEST_FILES =
84       ImmutableSet.of(
85           "AutoBuilderTest.java",
86           "AutoOneOfJava8Test.java",
87           "AutoValueJava8Test.java",
88           "EmptyExtension.java");
89   private static final Predicate<File> JAVA8_TEST = f -> JAVA8_TEST_FILES.contains(f.getName());
90 
91   @Test
compileWithEclipseJava7()92   public void compileWithEclipseJava7() throws Exception {
93     compileWithEclipse("7", JAVA_FILE.and(JAVA8_TEST.negate()));
94   }
95 
96   @Test
compileWithEclipseJava8()97   public void compileWithEclipseJava8() throws Exception {
98     compileWithEclipse("8", JAVA_FILE);
99   }
100 
compileWithEclipse(String version, Predicate<File> predicate)101   private void compileWithEclipse(String version, Predicate<File> predicate) throws IOException {
102     File sourceRootFile = new File(SOURCE_ROOT);
103     File javaDir = new File(sourceRootFile, "src/main/java");
104     File javatestsDir = new File(sourceRootFile, "src/test/java");
105     Set<File> sources =
106         new ImmutableSet.Builder<File>()
107             .addAll(filesUnderDirectory(javaDir, predicate))
108             .addAll(filesUnderDirectory(javatestsDir, predicate))
109             .build();
110     assertThat(sources).isNotEmpty();
111     JavaCompiler compiler = new EclipseCompiler();
112     StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
113     // This hack is only needed in a Google-internal Java 8 environment where symbolic links make it
114     // hard for ecj to find the boot class path. Elsewhere it is unnecessary but harmless. Notably,
115     // on Java 9+ there is no rt.jar. There, fileManager.getLocation(PLATFORM_CLASS_PATH) returns
116     // null, because the relevant classes are in modules inside
117     // fileManager.getLocation(SYSTEM_MODULES).
118     File rtJar = new File(JAVA_HOME.value() + "/lib/rt.jar");
119     if (rtJar.exists()) {
120       List<File> bootClassPath =
121           ImmutableList.<File>builder()
122               .add(rtJar)
123               .addAll(fileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH))
124               .build();
125       fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
126     }
127     Iterable<? extends JavaFileObject> sourceFileObjects =
128         fileManager.getJavaFileObjectsFromFiles(sources);
129     String outputDir = tmp.getRoot().toString();
130     ImmutableList<String> options =
131         ImmutableList.of(
132             "-d",
133             outputDir,
134             "-s",
135             outputDir,
136             "-source",
137             version,
138             "-target",
139             version,
140             "-warn:-warningToken,-intfAnnotation");
141     JavaCompiler.CompilationTask task =
142         compiler.getTask(null, fileManager, null, options, null, sourceFileObjects);
143     // Explicitly supply an empty list of extensions for AutoValueProcessor, because otherwise this
144     // test will pick up a test one and get confused.
145     AutoValueProcessor autoValueProcessor = new AutoValueProcessor(ImmutableList.of());
146     ImmutableList<? extends Processor> processors =
147         ImmutableList.of(
148             autoValueProcessor,
149             new AutoOneOfProcessor(),
150             new AutoAnnotationProcessor(),
151             new AutoBuilderProcessor());
152     task.setProcessors(processors);
153     assertWithMessage("Compilation should succeed").that(task.call()).isTrue();
154   }
155 
filesUnderDirectory(File dir, Predicate<File> predicate)156   private static ImmutableSet<File> filesUnderDirectory(File dir, Predicate<File> predicate)
157       throws IOException {
158     assertWithMessage(dir.toString()).that(dir.isDirectory()).isTrue();
159     try (Stream<Path> paths = Files.walk(dir.toPath())) {
160       return paths.map(Path::toFile).filter(predicate).collect(toImmutableSet());
161     }
162   }
163 }
164