-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added unit test to compile add generated class.
- Loading branch information
Showing
5 changed files
with
216 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
test-common/src/main/java/com/linkedin/avroutil1/testcommon/CommonCompilerHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/* | ||
* Copyright 2023 LinkedIn Corp. | ||
* Licensed under the BSD 2-Clause License (the "License"). | ||
* See License in the project root for license information. | ||
*/ | ||
|
||
package com.linkedin.avroutil1.testcommon; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.net.URI; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.FileVisitResult; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.SimpleFileVisitor; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import javax.tools.Diagnostic; | ||
import javax.tools.DiagnosticListener; | ||
import javax.tools.FileObject; | ||
import javax.tools.ForwardingJavaFileManager; | ||
import javax.tools.JavaCompiler; | ||
import javax.tools.JavaFileObject; | ||
import javax.tools.SimpleJavaFileObject; | ||
import javax.tools.StandardJavaFileManager; | ||
import javax.tools.ToolProvider; | ||
import org.apache.commons.io.IOUtils; | ||
import org.testng.Assert; | ||
|
||
|
||
/** | ||
* utility class for dealing with the java compiler in unit tests | ||
*/ | ||
public class CommonCompilerHelper { | ||
|
||
public static void assertCompiles(JavaFileObject sourceFile) throws Exception { | ||
List<JavaFileObject> fileObjects = Arrays.asList(sourceFile); | ||
assertCompiles(fileObjects); | ||
} | ||
|
||
public static void assertCompiles(Path sourceRoot) throws Exception { | ||
List<JavaFileObject> fileObjects = listSourceFiles(sourceRoot); | ||
assertCompiles(fileObjects); | ||
} | ||
|
||
public static void assertCompiles(List<JavaFileObject> fileObjects) throws Exception { | ||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); | ||
ClassFileManager manager = new ClassFileManager(compiler.getStandardFileManager(null, null, null)); | ||
CompilationListener listener = new CompilationListener(); | ||
JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, manager, listener, null, null, fileObjects); | ||
Boolean success = compilationTask.call(); | ||
|
||
if (!Boolean.TRUE.equals(success) || !listener.errors.isEmpty()) { | ||
Assert.fail("failed to compile code: " + listener.errors); | ||
} | ||
} | ||
|
||
private static List<JavaFileObject> listSourceFiles(Path root) throws IOException { | ||
List<JavaFileObject> fileObjects = new ArrayList<>(); | ||
//noinspection Convert2Diamond because java 8 isnt smart enough to figure this out | ||
Files.walkFileTree(root, new SimpleFileVisitor<Path>() { | ||
@Override | ||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { | ||
if (attrs.isRegularFile()) { | ||
fileObjects.add(new JavaSourceFile(file)); | ||
} | ||
return FileVisitResult.CONTINUE; | ||
} | ||
}); | ||
return fileObjects; | ||
} | ||
|
||
private static String summarize(Diagnostic<? extends JavaFileObject> diagnostic) { | ||
StringBuilder sb = new StringBuilder(); | ||
sb.append(diagnostic.getKind()).append(": "); | ||
JavaFileObject sourceObject = diagnostic.getSource(); | ||
if (sourceObject != null) { | ||
sb.append("file ").append(sourceObject.toString()).append(" "); | ||
} | ||
String message = diagnostic.getMessage(Locale.ROOT); | ||
if (message != null && !message.isEmpty()) { | ||
sb.append(message).append(" "); | ||
} | ||
long line = diagnostic.getLineNumber(); | ||
long column = diagnostic.getColumnNumber(); | ||
if (line != -1 || column != -1) { | ||
sb.append("at line ").append(line).append(" column ").append(column); | ||
} | ||
return sb.toString().trim(); | ||
} | ||
|
||
private static class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { | ||
private final Map<String, JavaClassObject> classObjects = new ConcurrentHashMap<>(); | ||
|
||
ClassFileManager(StandardJavaFileManager m) { | ||
super(m); | ||
} | ||
|
||
@Override | ||
public JavaFileObject getJavaFileForOutput( | ||
Location location, | ||
String className, | ||
JavaFileObject.Kind kind, | ||
FileObject sibling | ||
) throws IOException { | ||
if (kind != JavaFileObject.Kind.CLASS) { | ||
throw new UnsupportedOperationException("unhandled kind " + kind); | ||
} | ||
return classObjects.computeIfAbsent(className, s -> new JavaClassObject((JavaFileObject) sibling, className)); | ||
} | ||
|
||
} | ||
|
||
private static class JavaSourceFile extends SimpleJavaFileObject { | ||
private final Path file; | ||
|
||
JavaSourceFile(Path file) { | ||
super(file.toUri(), Kind.SOURCE); | ||
this.file = file; | ||
} | ||
|
||
@Override | ||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { | ||
return IOUtils.toString(file.toUri(), StandardCharsets.UTF_8); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return file.getFileName().toString(); | ||
} | ||
} | ||
|
||
private static class JavaClassObject extends SimpleJavaFileObject { | ||
private final JavaFileObject sourceFile; | ||
private final String fqcn; | ||
private volatile ByteArrayOutputStream outputStream; | ||
|
||
public JavaClassObject(JavaFileObject sourceFile, String fqcn) { | ||
super(URI.create("mem:///" + fqcn.replace('.', '/')), Kind.CLASS); | ||
this.sourceFile = sourceFile; | ||
this.fqcn = fqcn; | ||
} | ||
|
||
@Override | ||
public synchronized OutputStream openOutputStream() { | ||
if (outputStream == null) { | ||
outputStream = new ByteArrayOutputStream(); | ||
} | ||
return outputStream; | ||
} | ||
} | ||
|
||
private static class CompilationListener implements DiagnosticListener<JavaFileObject> { | ||
private final List<String> warnings = new ArrayList<>(); | ||
private final List<String> errors = new ArrayList<>(); | ||
|
||
@Override | ||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) { | ||
Diagnostic.Kind kind = diagnostic.getKind(); | ||
String desc = summarize(diagnostic); | ||
switch (kind) { | ||
case NOTE: | ||
case WARNING: | ||
case MANDATORY_WARNING: | ||
warnings.add(desc); | ||
break; | ||
case ERROR: | ||
case OTHER: | ||
errors.add(desc); | ||
break; | ||
default: | ||
throw new IllegalStateException("unhandled " + kind); | ||
} | ||
} | ||
} | ||
} |