26 import java.foreign.annotations.NativeLocation; 27 import java.foreign.annotations.NativeStruct; 28 import java.nio.file.Files; 29 import java.io.ByteArrayInputStream; 30 import java.io.ByteArrayOutputStream; 31 import java.io.File; 32 import java.io.IOException; 33 import java.io.PrintWriter; 34 import java.lang.annotation.Annotation; 35 import java.lang.reflect.Method; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.util.Arrays; 39 import java.util.HashMap; 40 import java.util.HashSet; 41 import java.util.Map; 42 import java.util.Set; 43 import java.util.jar.JarEntry; 44 import java.util.jar.JarInputStream; 45 import java.util.jar.JarOutputStream; 46 import javax.tools.JavaCompiler; 47 import javax.tools.StandardJavaFileManager; 48 import javax.tools.ToolProvider; 49 import jdk.internal.org.objectweb.asm.ClassReader; 50 import jdk.internal.org.objectweb.asm.tree.ClassNode; 51 import jdk.internal.org.objectweb.asm.util.ASMifier; 52 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; 53 import jdk.internal.org.objectweb.asm.util.Textifier; 54 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; 55 import static org.testng.Assert.assertEquals; 56 import static org.testng.Assert.assertNotNull; 57 import static org.testng.Assert.assertTrue; 58 import static org.testng.Assert.fail; 59 import org.testng.annotations.BeforeClass; 60 import org.testng.annotations.DataProvider; 61 import org.testng.annotations.Factory; 62 import org.testng.annotations.Test; 63 import com.sun.tools.jextract.Context; 64 65 /* 66 * @test 67 * @summary Main test runner created all cases 68 * @modules java.base/jdk.internal.org.objectweb.asm 69 * @modules java.base/jdk.internal.org.objectweb.asm.tree 70 * @modules java.base/jdk.internal.org.objectweb.asm.util 71 * @modules jdk.jextract/com.sun.tools.jextract 72 * @build InMemoryFileManager 73 * @run testng Runner 74 */ 75 public class Runner { 76 private final Path nativeSrc; 77 private final Path[] javaSrcFiles; 78 private final Context ctx; 79 private final String pkg; 80 81 private InMemoryFileManager<StandardJavaFileManager> mfm; 82 private ClassLoader expectedCL; 83 private Map<String, byte[]> actualClz; 84 private ClassLoader actualCL; 85 private Object[][] clz_data; 86 87 public Runner(Path nativeSrc, String pkg, Path[] javaSrcFiles) { 88 this.ctx = new Context(); 89 this.nativeSrc = nativeSrc; 90 this.pkg = pkg; 91 this.javaSrcFiles = javaSrcFiles; 92 } 93 94 private Map<String, byte[]> extract(String pkg) throws IOException { 95 if (!Files.isReadable(nativeSrc)) { 96 throw new IllegalArgumentException("Cannot read the file: " + nativeSrc); 97 } 98 Path p = nativeSrc.toAbsolutePath(); 99 ctx.usePackageForFolder(p.getParent(), pkg); 100 ctx.addSource(p); 101 ctx.parse(); 102 return ctx.collectClasses(pkg); 103 } 104 105 private InMemoryFileManager<StandardJavaFileManager> compileJavaCode() { 106 JavaCompiler cl = ToolProvider.getSystemJavaCompiler(); 107 StandardJavaFileManager sfm = cl.getStandardFileManager(null, null, null); 108 InMemoryFileManager<StandardJavaFileManager> fm = new InMemoryFileManager<>(sfm); 109 JavaCompiler.CompilationTask task = cl.getTask(null, fm, null, null, 110 null, sfm.getJavaFileObjects(javaSrcFiles)); 111 task.call(); 112 return fm; 113 } 114 115 @Test 116 public void testJarManifest() throws IOException { 117 // Get the jar 118 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 119 ctx.collectJarFile(new JarOutputStream(bos), new String[0], pkg); 120 121 System.out.println("Jar built, verifying..."); 122 JarInputStream jis = new JarInputStream(new ByteArrayInputStream(bos.toByteArray())); 123 124 // List all classes in the jar 125 Set<String> files = new HashSet<>(); 126 for (JarEntry e = jis.getNextJarEntry(); e != null; e = jis.getNextJarEntry()) { 127 if (e.isDirectory()) { 128 continue; 129 } 130 String name = e.getName(); 131 if (! name.endsWith(".properties")) { 132 if (! name.endsWith(".class")) { 133 // Should not have file not class files 134 System.err.println("Warning: unexpected file " + name); 135 } 136 name = name.substring(0, name.length() - 6); 137 files.add(name.replace(File.separatorChar, '.')); 138 } 139 } 267 if (clz_data == null) { 268 String[] clz_names = mfm.listClasses().toArray(new String[0]); 269 final int len = clz_names.length; 270 clz_data = new Object[len][2]; 271 for (int i = 0; i < len; i++) { 272 String name = clz_names[i]; 273 System.err.println("Load class " + name); 274 // AsmCheckClass(name); 275 // AsmifyClass(name); 276 clz_data[i][0] = actualCL.loadClass(name); 277 clz_data[i][1] = expectedCL.loadClass(name); 278 } 279 } 280 return clz_data; 281 } 282 283 @BeforeClass 284 public void compile() throws IOException { 285 System.out.println("Compiling..."); 286 mfm = compileJavaCode(); 287 actualClz = extract(pkg); 288 expectedCL = mfm.getTheClassLoader(); 289 actualCL = new ClassLoader() { 290 @Override 291 protected Class<?> findClass(String name) throws ClassNotFoundException { 292 byte[] byteCode = actualClz.get(name); 293 if (byteCode == null) throw new ClassNotFoundException(name); 294 return defineClass(name, byteCode, 0, byteCode.length); 295 } 296 }; 297 System.out.println("Done compile, ready for test"); 298 assertEquals(actualClz.keySet(), mfm.listClasses()); 299 System.out.println("Compile result validated."); 300 } 301 302 private static Path[] paths(String testDir, String[] files) { 303 return Arrays.stream(files) 304 .map(f -> Paths.get(testDir, f)) 305 .toArray(Path[]::new); 306 } 307 308 @Factory(dataProvider = "cases") 309 public static Object[] run(String nativeSrc, String pkgName, String[] javaSrcFiles) { 310 String testDir = System.getProperty("test.src", "."); 311 System.out.println("Use test case files in " + testDir); 312 return new Object[] { 313 new Runner(Paths.get(testDir, nativeSrc), pkgName, paths(testDir, javaSrcFiles)) 314 }; 315 } 316 317 @DataProvider(name = "cases") 318 public static Object[][] cases() { 319 return new Object[][] { 320 { "simple.h", "com.acme", new String[] { "simple.java" }}, 321 { "recursive.h", "com.acme", new String[] { "recursive.java" }}, | 26 import java.foreign.annotations.NativeLocation; 27 import java.foreign.annotations.NativeStruct; 28 import java.nio.file.Files; 29 import java.io.ByteArrayInputStream; 30 import java.io.ByteArrayOutputStream; 31 import java.io.File; 32 import java.io.IOException; 33 import java.io.PrintWriter; 34 import java.lang.annotation.Annotation; 35 import java.lang.reflect.Method; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.util.Arrays; 39 import java.util.HashMap; 40 import java.util.HashSet; 41 import java.util.Map; 42 import java.util.Set; 43 import java.util.jar.JarEntry; 44 import java.util.jar.JarInputStream; 45 import java.util.jar.JarOutputStream; 46 import java.util.stream.Collectors; 47 import javax.tools.JavaCompiler; 48 import javax.tools.StandardJavaFileManager; 49 import javax.tools.ToolProvider; 50 51 import com.sun.tools.jextract.JextractTool; 52 import com.sun.tools.jextract.Writer; 53 import jdk.internal.org.objectweb.asm.ClassReader; 54 import jdk.internal.org.objectweb.asm.tree.ClassNode; 55 import jdk.internal.org.objectweb.asm.util.ASMifier; 56 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; 57 import jdk.internal.org.objectweb.asm.util.Textifier; 58 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; 59 import static org.testng.Assert.assertEquals; 60 import static org.testng.Assert.assertNotNull; 61 import static org.testng.Assert.assertTrue; 62 import static org.testng.Assert.fail; 63 import org.testng.annotations.BeforeClass; 64 import org.testng.annotations.DataProvider; 65 import org.testng.annotations.Factory; 66 import org.testng.annotations.Test; 67 import com.sun.tools.jextract.Context; 68 69 /* 70 * @test 71 * @summary Main test runner created all cases 72 * @modules java.base/jdk.internal.org.objectweb.asm 73 * @modules java.base/jdk.internal.org.objectweb.asm.tree 74 * @modules java.base/jdk.internal.org.objectweb.asm.util 75 * @modules jdk.jextract/com.sun.tools.jextract 76 * @build InMemoryFileManager 77 * @run testng Runner 78 */ 79 public class Runner { 80 private final Path nativeSrc; 81 private final Path[] javaSrcFiles; 82 private final Context ctx; 83 private final String pkg; 84 85 private InMemoryFileManager<StandardJavaFileManager> mfm; 86 private ClassLoader expectedCL; 87 private Map<String, byte[]> actualClz; 88 private ClassLoader actualCL; 89 private Writer writer; 90 private Object[][] clz_data; 91 92 public Runner(Path nativeSrc, String pkg, Path[] javaSrcFiles) { 93 this.ctx = new Context(); 94 this.nativeSrc = nativeSrc; 95 this.pkg = pkg; 96 this.javaSrcFiles = javaSrcFiles; 97 } 98 99 private Writer extract() throws IOException { 100 if (!Files.isReadable(nativeSrc)) { 101 throw new IllegalArgumentException("Cannot read the file: " + nativeSrc); 102 } 103 Path p = nativeSrc.toAbsolutePath(); 104 ctx.setTargetPackage(pkg); 105 ctx.addSource(p); 106 return new JextractTool(ctx).processHeaders(); 107 } 108 109 private InMemoryFileManager<StandardJavaFileManager> compileJavaCode() { 110 JavaCompiler cl = ToolProvider.getSystemJavaCompiler(); 111 StandardJavaFileManager sfm = cl.getStandardFileManager(null, null, null); 112 InMemoryFileManager<StandardJavaFileManager> fm = new InMemoryFileManager<>(sfm); 113 JavaCompiler.CompilationTask task = cl.getTask(null, fm, null, null, 114 null, sfm.getJavaFileObjects(javaSrcFiles)); 115 task.call(); 116 return fm; 117 } 118 119 @Test 120 public void testJarManifest() throws IOException { 121 // Get the jar 122 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 123 writer.writeJarFile(new JarOutputStream(bos), new String[0]); 124 125 System.out.println("Jar built, verifying..."); 126 JarInputStream jis = new JarInputStream(new ByteArrayInputStream(bos.toByteArray())); 127 128 // List all classes in the jar 129 Set<String> files = new HashSet<>(); 130 for (JarEntry e = jis.getNextJarEntry(); e != null; e = jis.getNextJarEntry()) { 131 if (e.isDirectory()) { 132 continue; 133 } 134 String name = e.getName(); 135 if (! name.endsWith(".properties")) { 136 if (! name.endsWith(".class")) { 137 // Should not have file not class files 138 System.err.println("Warning: unexpected file " + name); 139 } 140 name = name.substring(0, name.length() - 6); 141 files.add(name.replace(File.separatorChar, '.')); 142 } 143 } 271 if (clz_data == null) { 272 String[] clz_names = mfm.listClasses().toArray(new String[0]); 273 final int len = clz_names.length; 274 clz_data = new Object[len][2]; 275 for (int i = 0; i < len; i++) { 276 String name = clz_names[i]; 277 System.err.println("Load class " + name); 278 // AsmCheckClass(name); 279 // AsmifyClass(name); 280 clz_data[i][0] = actualCL.loadClass(name); 281 clz_data[i][1] = expectedCL.loadClass(name); 282 } 283 } 284 return clz_data; 285 } 286 287 @BeforeClass 288 public void compile() throws IOException { 289 System.out.println("Compiling..."); 290 mfm = compileJavaCode(); 291 writer = extract(); 292 actualClz = writer.results(); 293 expectedCL = mfm.getTheClassLoader(); 294 actualCL = new ClassLoader() { 295 @Override 296 protected Class<?> findClass(String name) throws ClassNotFoundException { 297 byte[] byteCode = actualClz.get(canonicalize(name)); 298 if (byteCode == null) throw new ClassNotFoundException(name); 299 return defineClass(name, byteCode, 0, byteCode.length); 300 } 301 }; 302 System.out.println("Done compile, ready for test"); 303 assertEquals(actualClz.keySet().stream() 304 .map(Runner::normalize) 305 .collect(Collectors.toSet()), 306 mfm.listClasses()); 307 System.out.println("Compile result validated."); 308 } 309 310 private static String normalize(String classname) { 311 return classname.replace(File.separatorChar, '.'); 312 } 313 314 private static String canonicalize(String classname) { 315 return classname.replace('.', File.separatorChar); 316 } 317 318 private static Path[] paths(String testDir, String[] files) { 319 return Arrays.stream(files) 320 .map(f -> Paths.get(testDir, f)) 321 .toArray(Path[]::new); 322 } 323 324 @Factory(dataProvider = "cases") 325 public static Object[] run(String nativeSrc, String pkgName, String[] javaSrcFiles) { 326 String testDir = System.getProperty("test.src", "."); 327 System.out.println("Use test case files in " + testDir); 328 return new Object[] { 329 new Runner(Paths.get(testDir, nativeSrc), pkgName, paths(testDir, javaSrcFiles)) 330 }; 331 } 332 333 @DataProvider(name = "cases") 334 public static Object[][] cases() { 335 return new Object[][] { 336 { "simple.h", "com.acme", new String[] { "simple.java" }}, 337 { "recursive.h", "com.acme", new String[] { "recursive.java" }}, |