20 * or visit www.oracle.com if you need additional information or have any |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 import java.io.File; |
24 import java.io.File; |
|
25 import java.io.FileInputStream; |
25 import java.io.IOException; |
26 import java.io.IOException; |
|
27 import java.io.InputStream; |
|
28 import java.util.Arrays; |
|
29 import java.util.Collections; |
26 import java.util.List; |
30 import java.util.List; |
27 import java.util.Objects; |
31 import java.util.Objects; |
28 import java.util.function.Function; |
32 import java.util.function.Function; |
29 import java.util.stream.Stream; |
33 import java.util.stream.Collectors; |
|
34 |
30 import javax.tools.DiagnosticCollector; |
35 import javax.tools.DiagnosticCollector; |
31 import javax.tools.JavaCompiler; |
36 import javax.tools.JavaCompiler; |
32 import javax.tools.JavaFileObject; |
37 import javax.tools.JavaFileObject; |
33 import javax.tools.ToolProvider; |
38 import javax.tools.ToolProvider; |
34 |
39 |
35 import static java.lang.String.format; |
40 import com.sun.tools.classfile.ClassFile; |
36 import static java.lang.System.lineSeparator; |
41 import com.sun.tools.classfile.ConstantPoolException; |
37 import static java.util.Arrays.asList; |
|
38 import static java.util.Collections.emptyList; |
|
39 import static java.util.stream.Collectors.joining; |
|
40 import static java.util.stream.Collectors.toList; |
|
41 |
42 |
42 /** |
43 /** |
43 * Base class for class file attribute tests. |
44 * Base class for class file attribute tests. |
44 * Contains methods for compiling generated sources in memory, |
45 * Contains methods for compiling generated sources in memory, |
45 * for reading files from disk and a lot of assert* methods. |
46 * for reading files from disk and a lot of assert* methods. |
46 */ |
47 */ |
47 public class TestBase { |
48 public class TestBase { |
48 |
49 |
49 public static final String LINE_SEPARATOR = lineSeparator(); |
50 public static final String LINE_SEPARATOR = System.lineSeparator(); |
50 |
51 |
51 private <S> InMemoryFileManager compile( |
52 private <S> InMemoryFileManager compile( |
52 List<String> options, |
53 List<String> options, |
53 Function<S, ? extends JavaFileObject> src2JavaFileObject, |
54 Function<S, ? extends JavaFileObject> src2JavaFileObject, |
54 List<S> sources) |
55 List<S> sources) |
55 throws IOException, CompilationException { |
56 throws IOException, CompilationException { |
56 |
57 |
57 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
58 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
58 List<? extends JavaFileObject> src = sources.stream() |
59 List<? extends JavaFileObject> src = sources.stream() |
59 .map(src2JavaFileObject) |
60 .map(src2JavaFileObject) |
60 .collect(toList()); |
61 .collect(Collectors.toList()); |
61 |
62 |
62 DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>(); |
63 DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>(); |
63 try (InMemoryFileManager fileManager |
64 try (InMemoryFileManager fileManager |
64 = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) { |
65 = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) { |
65 JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, dc, options, null, src); |
66 JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, dc, options, null, src); |
66 boolean success = task.call(); |
67 boolean success = task.call(); |
67 if (!success) { |
68 if (!success) { |
68 String errorMessage = dc.getDiagnostics().stream() |
69 String errorMessage = dc.getDiagnostics().stream() |
69 .map(Object::toString) |
70 .map(Object::toString) |
70 .collect(joining("\n")); |
71 .collect(Collectors.joining("\n")); |
71 throw new CompilationException("Compilation Error\n\n" + errorMessage); |
72 throw new CompilationException("Compilation Error\n\n" + errorMessage); |
72 } |
73 } |
73 return fileManager; |
74 return fileManager; |
74 } |
75 } |
75 } |
76 } |
92 * @param sources sources to compile. |
93 * @param sources sources to compile. |
93 * @return map where key is className, value is corresponding ClassFile. |
94 * @return map where key is className, value is corresponding ClassFile. |
94 */ |
95 */ |
95 public InMemoryFileManager compile(List<String> options, String... sources) |
96 public InMemoryFileManager compile(List<String> options, String... sources) |
96 throws IOException, CompilationException { |
97 throws IOException, CompilationException { |
97 return compile(options, ToolBox.JavaSource::new, asList(sources)); |
98 return compile(options, ToolBox.JavaSource::new, Arrays.asList(sources)); |
98 } |
99 } |
99 |
100 |
100 /** |
101 /** |
101 * Compiles sources in memory. |
102 * Compiles sources in memory. |
102 * |
103 * |
103 * @param sources sources[i][0] - name of file, sources[i][1] - sources. |
104 * @param sources sources[i][0] - name of file, sources[i][1] - sources. |
104 * @return map where key is className, value is corresponding ClassFile. |
105 * @return map where key is className, value is corresponding ClassFile. |
105 */ |
106 */ |
106 public InMemoryFileManager compile(String[]... sources) throws IOException, |
107 public InMemoryFileManager compile(String[]... sources) throws IOException, |
107 CompilationException { |
108 CompilationException { |
108 return compile(emptyList(), sources); |
109 return compile(Collections.emptyList(), sources); |
109 } |
110 } |
110 |
111 |
111 /** |
112 /** |
112 * Compiles sources in memory. |
113 * Compiles sources in memory. |
113 * |
114 * |
115 * @param sources sources[i][0] - name of file, sources[i][1] - sources. |
116 * @param sources sources[i][0] - name of file, sources[i][1] - sources. |
116 * @return map where key is className, value is corresponding ClassFile. |
117 * @return map where key is className, value is corresponding ClassFile. |
117 */ |
118 */ |
118 public InMemoryFileManager compile(List<String> options, String[]... sources) |
119 public InMemoryFileManager compile(List<String> options, String[]... sources) |
119 throws IOException, CompilationException { |
120 throws IOException, CompilationException { |
120 return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources)); |
121 return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), Arrays.asList(sources)); |
|
122 } |
|
123 |
|
124 /** |
|
125 * Returns class file that is read from {@code is}. |
|
126 * |
|
127 * @param is an input stream |
|
128 * @return class file that is read from {@code is} |
|
129 * @throws IOException if I/O error occurs |
|
130 * @throws ConstantPoolException if constant pool error occurs |
|
131 */ |
|
132 public ClassFile readClassFile(InputStream is) throws IOException, ConstantPoolException { |
|
133 return ClassFile.read(is); |
|
134 } |
|
135 |
|
136 /** |
|
137 * Returns class file that is read from {@code fileObject}. |
|
138 * |
|
139 * @param fileObject a file object |
|
140 * @return class file that is read from {@code fileObject} |
|
141 * @throws IOException if I/O error occurs |
|
142 * @throws ConstantPoolException if constant pool error occurs |
|
143 */ |
|
144 public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException { |
|
145 return readClassFile(fileObject.openInputStream()); |
|
146 } |
|
147 |
|
148 /** |
|
149 * Returns class file that corresponds to {@code clazz}. |
|
150 * |
|
151 * @param clazz a class |
|
152 * @return class file that is read from {@code clazz} |
|
153 * @throws IOException if I/O error occurs |
|
154 * @throws ConstantPoolException if constant pool error occurs |
|
155 */ |
|
156 public ClassFile readClassFile(Class<?> clazz) throws IOException, ConstantPoolException { |
|
157 return readClassFile(getClassFile(clazz)); |
|
158 } |
|
159 |
|
160 /** |
|
161 * Returns class file that corresponds to {@code className}. |
|
162 * |
|
163 * @param className a class name |
|
164 * @return class file that is read from {@code className} |
|
165 * @throws IOException if I/O error occurs |
|
166 * @throws ConstantPoolException if constant pool error occurs |
|
167 */ |
|
168 public ClassFile readClassFile(String className) throws IOException, ConstantPoolException { |
|
169 return readClassFile(getClassFile(className + ".class")); |
|
170 } |
|
171 |
|
172 /** |
|
173 * Returns class file that is read from {@code file}. |
|
174 * |
|
175 * @param file a file |
|
176 * @return class file that is read from {@code file} |
|
177 * @throws IOException if I/O error occurs |
|
178 * @throws ConstantPoolException if constant pool error occurs |
|
179 */ |
|
180 public ClassFile readClassFile(File file) throws IOException, ConstantPoolException { |
|
181 return readClassFile(new FileInputStream(file)); |
121 } |
182 } |
122 |
183 |
123 public void assertEquals(Object actual, Object expected, String message) { |
184 public void assertEquals(Object actual, Object expected, String message) { |
124 if (!Objects.equals(actual, expected)) |
185 if (!Objects.equals(actual, expected)) |
125 throw new AssertionFailedException(format("%s%nGot: %s, Expected: %s", message, actual, expected)); |
186 throw new AssertionFailedException(String.format("%s%nGot: %s, Expected: %s", |
|
187 message, actual, expected)); |
126 } |
188 } |
127 |
189 |
128 public void assertNull(Object actual, String message) { |
190 public void assertNull(Object actual, String message) { |
129 assertEquals(actual, null, message); |
191 assertEquals(actual, null, message); |
130 } |
192 } |
167 * Prints message to standard error. New lines are converted to system dependent NL. |
229 * Prints message to standard error. New lines are converted to system dependent NL. |
168 * |
230 * |
169 * @param message string to print. |
231 * @param message string to print. |
170 */ |
232 */ |
171 public void echo(String message) { |
233 public void echo(String message) { |
172 System.err.println(message.replace("\n", LINE_SEPARATOR)); |
234 printf(message + "\n"); |
173 } |
235 } |
174 |
236 |
175 /** |
237 /** |
176 * Substitutes args in template and prints result to standard error. New lines are converted to system dependent NL. |
238 * Substitutes args in template and prints result to standard error. |
|
239 * New lines are converted to system dependent NL. |
177 * |
240 * |
178 * @param template template in standard String.format(...) format. |
241 * @param template template in standard String.format(...) format. |
179 * @param args arguments to substitute in template. |
242 * @param args arguments to substitute in template. |
180 */ |
243 */ |
181 public void printf(String template, Object... args) { |
244 public void printf(String template, Object... args) { |
182 System.err.printf(template, Stream.of(args) |
245 System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR)); |
183 .map(Objects::toString) |
|
184 .map(m -> m.replace("\n", LINE_SEPARATOR)) |
|
185 .collect(toList()) |
|
186 .toArray()); |
|
187 |
|
188 } |
246 } |
189 |
247 |
190 public static class CompilationException extends Exception { |
248 public static class CompilationException extends Exception { |
191 |
249 |
192 public CompilationException(String message) { |
250 public CompilationException(String message) { |