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", "CompileWithEclipseTest.java", "GradleTest.java"); 71 72 private static final Predicate<File> JAVA_FILE = 73 f -> f.getName().endsWith(".java") && !IGNORED_TEST_FILES.contains(f.getName()); 74 75 private static final Predicate<File> JAVA8_TEST = 76 f -> 77 f.getName().equals("AutoValueJava8Test.java") 78 || f.getName().equals("AutoOneOfJava8Test.java") 79 || f.getName().equals("EmptyExtension.java"); 80 81 @Test compileWithEclipseJava7()82 public void compileWithEclipseJava7() throws Exception { 83 compileWithEclipse("7", JAVA_FILE.and(JAVA8_TEST.negate())); 84 } 85 86 @Test compileWithEclipseJava8()87 public void compileWithEclipseJava8() throws Exception { 88 compileWithEclipse("8", JAVA_FILE); 89 } 90 compileWithEclipse(String version, Predicate<File> predicate)91 private void compileWithEclipse(String version, Predicate<File> predicate) throws IOException { 92 File sourceRootFile = new File(SOURCE_ROOT); 93 File javaDir = new File(sourceRootFile, "src/main/java"); 94 File javatestsDir = new File(sourceRootFile, "src/test/java"); 95 Set<File> sources = 96 new ImmutableSet.Builder<File>() 97 .addAll(filesUnderDirectory(javaDir, predicate)) 98 .addAll(filesUnderDirectory(javatestsDir, predicate)) 99 .build(); 100 assertThat(sources).isNotEmpty(); 101 JavaCompiler compiler = new EclipseCompiler(); 102 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 103 // This hack is only needed in a Google-internal Java 8 environment where symbolic links make it 104 // hard for ecj to find the boot class path. Elsewhere it is unnecessary but harmless. Notably, 105 // on Java 9+ there is no rt.jar. There, fileManager.getLocation(PLATFORM_CLASS_PATH) returns 106 // null, because the relevant classes are in modules inside 107 // fileManager.getLocation(SYSTEM_MODULES). 108 File rtJar = new File(JAVA_HOME.value() + "/lib/rt.jar"); 109 if (rtJar.exists()) { 110 List<File> bootClassPath = 111 ImmutableList.<File>builder() 112 .add(rtJar) 113 .addAll(fileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) 114 .build(); 115 fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath); 116 } 117 Iterable<? extends JavaFileObject> sourceFileObjects = 118 fileManager.getJavaFileObjectsFromFiles(sources); 119 String outputDir = tmp.getRoot().toString(); 120 ImmutableList<String> options = 121 ImmutableList.of( 122 "-d", 123 outputDir, 124 "-s", 125 outputDir, 126 "-source", 127 version, 128 "-target", 129 version, 130 "-warn:-warningToken,-intfAnnotation"); 131 JavaCompiler.CompilationTask task = 132 compiler.getTask(null, fileManager, null, options, null, sourceFileObjects); 133 // Explicitly supply an empty list of extensions for AutoValueProcessor, because otherwise this 134 // test will pick up a test one and get confused. 135 AutoValueProcessor autoValueProcessor = new AutoValueProcessor(ImmutableList.of()); 136 ImmutableList<? extends Processor> processors = 137 ImmutableList.of( 138 autoValueProcessor, 139 new AutoOneOfProcessor(), 140 new AutoAnnotationProcessor(), 141 new AutoBuilderProcessor()); 142 task.setProcessors(processors); 143 assertWithMessage("Compilation should succeed").that(task.call()).isTrue(); 144 } 145 filesUnderDirectory(File dir, Predicate<File> predicate)146 private static ImmutableSet<File> filesUnderDirectory(File dir, Predicate<File> predicate) 147 throws IOException { 148 assertWithMessage(dir.toString()).that(dir.isDirectory()).isTrue(); 149 try (Stream<Path> paths = Files.walk(dir.toPath())) { 150 return paths.map(Path::toFile).filter(predicate).collect(toImmutableSet()); 151 } 152 } 153 } 154