1 /* 2 * Copyright 2019 Google Inc. All Rights Reserved. 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 com.google.turbine.processing; 18 19 import static com.google.common.collect.Iterables.getOnlyElement; 20 import static com.google.common.truth.Truth.assertThat; 21 import static java.nio.charset.StandardCharsets.UTF_8; 22 import static org.junit.Assert.assertThrows; 23 24 import com.google.common.base.Supplier; 25 import com.google.common.io.CharStreams; 26 import com.google.turbine.diag.SourceFile; 27 import java.io.FileNotFoundException; 28 import java.io.IOException; 29 import java.io.OutputStream; 30 import java.io.Writer; 31 import java.util.Arrays; 32 import java.util.Collection; 33 import java.util.HashSet; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.function.Function; 37 import javax.annotation.processing.FilerException; 38 import javax.lang.model.element.Element; 39 import javax.tools.FileObject; 40 import javax.tools.JavaFileObject; 41 import javax.tools.StandardLocation; 42 import org.jspecify.nullness.Nullable; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.junit.runners.JUnit4; 47 48 @RunWith(JUnit4.class) 49 public class TurbineFilerTest { 50 51 private final Set<String> seen = new HashSet<>(); 52 private TurbineFiler filer; 53 54 @Before setup()55 public void setup() { 56 Function<String, Supplier<byte[]>> classpath = 57 new Function<String, Supplier<byte[]>>() { 58 @Override 59 public @Nullable Supplier<byte[]> apply(String input) { 60 return null; 61 } 62 }; 63 this.filer = new TurbineFiler(seen, classpath, TurbineFilerTest.class.getClassLoader()); 64 } 65 66 @Test hello()67 public void hello() throws IOException { 68 JavaFileObject sourceFile = filer.createSourceFile("com.foo.Bar", (Element[]) null); 69 try (OutputStream os = sourceFile.openOutputStream()) { 70 os.write("hello".getBytes(UTF_8)); 71 } 72 assertThat(sourceFile.getLastModified()).isEqualTo(0); 73 74 JavaFileObject classFile = filer.createClassFile("com.foo.Baz", (Element[]) null); 75 try (OutputStream os = classFile.openOutputStream()) { 76 os.write("goodbye".getBytes(UTF_8)); 77 } 78 assertThat(classFile.getLastModified()).isEqualTo(0); 79 80 Collection<SourceFile> roundSources = filer.finishRound(); 81 assertThat(roundSources).hasSize(1); 82 assertThat(filer.generatedSources()).hasSize(1); 83 assertThat(filer.generatedClasses()).hasSize(1); 84 85 SourceFile source = getOnlyElement(roundSources); 86 assertThat(source.path()).isEqualTo("com/foo/Bar.java"); 87 assertThat(source.source()).isEqualTo("hello"); 88 89 Map.Entry<String, byte[]> clazz = getOnlyElement(filer.generatedClasses().entrySet()); 90 assertThat(clazz.getKey()).isEqualTo("com/foo/Baz.class"); 91 assertThat(new String(clazz.getValue(), UTF_8)).isEqualTo("goodbye"); 92 } 93 94 @Test existing()95 public void existing() throws IOException { 96 seen.add("com/foo/Bar.java"); 97 seen.add("com/foo/Baz.class"); 98 99 assertThrows( 100 FilerException.class, () -> filer.createSourceFile("com.foo.Bar", (Element[]) null)); 101 JavaFileObject unused = filer.createSourceFile("com.foo.Baz", (Element[]) null); 102 103 unused = filer.createClassFile("com.foo.Bar", (Element[]) null); 104 assertThrows( 105 FilerException.class, () -> filer.createClassFile("com.foo.Baz", (Element[]) null)); 106 } 107 108 @Test get()109 public void get() throws IOException { 110 for (StandardLocation location : 111 Arrays.asList( 112 StandardLocation.CLASS_OUTPUT, 113 StandardLocation.SOURCE_OUTPUT, 114 StandardLocation.ANNOTATION_PROCESSOR_PATH, 115 StandardLocation.CLASS_PATH)) { 116 assertThrows(FileNotFoundException.class, () -> filer.getResource(location, "", "NoSuch")); 117 } 118 } 119 120 @Test sourceOutput()121 public void sourceOutput() throws IOException { 122 JavaFileObject classFile = filer.createSourceFile("com.foo.Bar", (Element[]) null); 123 try (Writer writer = classFile.openWriter()) { 124 writer.write("hello"); 125 } 126 Collection<SourceFile> unused = filer.finishRound(); 127 128 FileObject output = filer.getResource(StandardLocation.SOURCE_OUTPUT, "com.foo", "Bar.java"); 129 assertThat(new String(output.openInputStream().readAllBytes(), UTF_8)).isEqualTo("hello"); 130 assertThat(output.getCharContent(false).toString()).isEqualTo("hello"); 131 assertThat(CharStreams.toString(output.openReader(true))).isEqualTo("hello"); 132 } 133 134 @Test classOutput()135 public void classOutput() throws IOException { 136 JavaFileObject classFile = filer.createClassFile("com.foo.Baz", (Element[]) null); 137 try (OutputStream os = classFile.openOutputStream()) { 138 os.write("goodbye".getBytes(UTF_8)); 139 } 140 Collection<SourceFile> unused = filer.finishRound(); 141 142 FileObject output = filer.getResource(StandardLocation.CLASS_OUTPUT, "com.foo", "Baz.class"); 143 assertThat(new String(output.openInputStream().readAllBytes(), UTF_8)).isEqualTo("goodbye"); 144 assertThat(output.getCharContent(false).toString()).isEqualTo("goodbye"); 145 assertThat(CharStreams.toString(output.openReader(true))).isEqualTo("goodbye"); 146 } 147 148 @Test classpathResources()149 public void classpathResources() throws IOException { 150 FileObject resource = 151 filer.getResource(StandardLocation.ANNOTATION_PROCESSOR_PATH, "META-INF", "MANIFEST.MF"); 152 153 assertThat(new String(resource.openInputStream().readAllBytes(), UTF_8)) 154 .contains("Manifest-Version:"); 155 assertThat(CharStreams.toString(resource.openReader(true))).contains("Manifest-Version:"); 156 assertThat(resource.getCharContent(false).toString()).contains("Manifest-Version:"); 157 } 158 } 159