changeset 22203:0995fbcf3e60

SLTestRunner unpacks jars to temp directories to ensure SL test sources and expected output files in a jar are loadable
author Doug Simon <doug.simon@oracle.com>
date Wed, 30 Sep 2015 11:01:57 +0200
parents 3d9e283e2487
children 3975d87a5d46
files truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java
diffstat 1 files changed, 72 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Tue Sep 29 18:04:11 2015 +0200
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Wed Sep 30 11:01:57 2015 +0200
@@ -40,16 +40,12 @@
  */
 package com.oracle.truffle.sl.test;
 
-import com.oracle.truffle.api.dsl.NodeFactory;
-import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.sl.SLLanguage;
-import com.oracle.truffle.sl.builtins.SLBuiltinNode;
-import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.nio.charset.Charset;
@@ -60,8 +56,13 @@
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.internal.TextListener;
 import org.junit.runner.Description;
 import org.junit.runner.JUnitCore;
@@ -73,6 +74,12 @@
 import org.junit.runners.ParentRunner;
 import org.junit.runners.model.InitializationError;
 
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.sl.SLLanguage;
+import com.oracle.truffle.sl.builtins.SLBuiltinNode;
+import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
+
 public final class SLTestRunner extends ParentRunner<TestCase> {
 
     private static int repeats = 1;
@@ -174,30 +181,80 @@
         return foundCases;
     }
 
+    /**
+     * Recursively deletes a file that may represent a directory.
+     */
+    private static void delete(File f) {
+        if (f.isDirectory()) {
+            for (File c : f.listFiles()) {
+                delete(c);
+            }
+        }
+        if (!f.delete()) {
+            PrintStream err = System.err;
+            err.println("Failed to delete file: " + f);
+        }
+    }
+
+    /**
+     * Unpacks a jar file to a temporary directory that will be removed when the VM exits.
+     *
+     * @param jarfilePath the path of the jar to unpack
+     * @return the path of the temporary directory
+     */
+    private static String explodeJarToTempDir(File jarfilePath) {
+        try {
+            final Path jarfileDir = Files.createTempDirectory(jarfilePath.getName());
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    delete(jarfileDir.toFile());
+                }
+            });
+            jarfileDir.toFile().deleteOnExit();
+            JarFile jarfile = new JarFile(jarfilePath);
+            Enumeration<JarEntry> entries = jarfile.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry e = entries.nextElement();
+                if (!e.isDirectory()) {
+                    File path = new File(jarfileDir.toFile(), e.getName().replace('/', File.separatorChar));
+                    File dir = path.getParentFile();
+                    dir.mkdirs();
+                    assert dir.exists();
+                    Files.copy(jarfile.getInputStream(e), path.toPath());
+                }
+            }
+            return jarfileDir.toFile().getAbsolutePath();
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
     public static Path getRootViaResourceURL(final Class<?> c, String[] paths) {
         URL url = c.getResource(c.getSimpleName() + ".class");
         if (url != null) {
             char sep = File.separatorChar;
             String externalForm = url.toExternalForm();
             String classPart = sep + c.getName().replace('.', sep) + ".class";
-            String suffix = null;
             String prefix = null;
+            String base;
             if (externalForm.startsWith("jar:file:")) {
                 prefix = "jar:file:";
-                suffix = sep + "build/truffle-sl.jar!" + classPart;
+                int bang = externalForm.indexOf('!', prefix.length());
+                Assume.assumeTrue(bang != -1);
+                File jarfilePath = new File(externalForm.substring(prefix.length(), bang));
+                Assume.assumeTrue(jarfilePath.exists());
+                base = explodeJarToTempDir(jarfilePath);
             } else if (externalForm.startsWith("file:")) {
                 prefix = "file:";
-                suffix = classPart;
+                base = externalForm.substring(prefix.length(), externalForm.length() - classPart.length());
             } else {
                 return null;
             }
-            if (externalForm.endsWith(suffix)) {
-                String base = externalForm.substring(prefix.length(), externalForm.length() - suffix.length());
-                for (String path : paths) {
-                    String candidate = base + sep + path;
-                    if (new File(candidate).exists()) {
-                        return FileSystems.getDefault().getPath(candidate);
-                    }
+            for (String path : paths) {
+                String candidate = base + sep + path;
+                if (new File(candidate).exists()) {
+                    return FileSystems.getDefault().getPath(candidate);
                 }
             }
         }