comparison truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java @ 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 df6a1647cfb3
children 906a5f6e07cc
comparison
equal deleted inserted replaced
22202:3d9e283e2487 22203:0995fbcf3e60
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 * SOFTWARE. 39 * SOFTWARE.
40 */ 40 */
41 package com.oracle.truffle.sl.test; 41 package com.oracle.truffle.sl.test;
42 42
43 import com.oracle.truffle.api.dsl.NodeFactory;
44 import com.oracle.truffle.api.vm.PolyglotEngine;
45 import com.oracle.truffle.sl.SLLanguage;
46 import com.oracle.truffle.sl.builtins.SLBuiltinNode;
47 import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
48 import java.io.ByteArrayInputStream; 43 import java.io.ByteArrayInputStream;
49 import java.io.ByteArrayOutputStream; 44 import java.io.ByteArrayOutputStream;
50 import java.io.File; 45 import java.io.File;
51 import java.io.FileNotFoundException; 46 import java.io.FileNotFoundException;
52 import java.io.IOException; 47 import java.io.IOException;
48 import java.io.PrintStream;
53 import java.io.PrintWriter; 49 import java.io.PrintWriter;
54 import java.net.URL; 50 import java.net.URL;
55 import java.nio.charset.Charset; 51 import java.nio.charset.Charset;
56 import java.nio.file.FileSystems; 52 import java.nio.file.FileSystems;
57 import java.nio.file.FileVisitResult; 53 import java.nio.file.FileVisitResult;
58 import java.nio.file.Files; 54 import java.nio.file.Files;
59 import java.nio.file.Path; 55 import java.nio.file.Path;
60 import java.nio.file.SimpleFileVisitor; 56 import java.nio.file.SimpleFileVisitor;
61 import java.nio.file.attribute.BasicFileAttributes; 57 import java.nio.file.attribute.BasicFileAttributes;
62 import java.util.ArrayList; 58 import java.util.ArrayList;
59 import java.util.Enumeration;
63 import java.util.List; 60 import java.util.List;
61 import java.util.jar.JarEntry;
62 import java.util.jar.JarFile;
63
64 import org.junit.Assert; 64 import org.junit.Assert;
65 import org.junit.Assume;
65 import org.junit.internal.TextListener; 66 import org.junit.internal.TextListener;
66 import org.junit.runner.Description; 67 import org.junit.runner.Description;
67 import org.junit.runner.JUnitCore; 68 import org.junit.runner.JUnitCore;
68 import org.junit.runner.Result; 69 import org.junit.runner.Result;
69 import org.junit.runner.manipulation.Filter; 70 import org.junit.runner.manipulation.Filter;
71 import org.junit.runner.notification.Failure; 72 import org.junit.runner.notification.Failure;
72 import org.junit.runner.notification.RunNotifier; 73 import org.junit.runner.notification.RunNotifier;
73 import org.junit.runners.ParentRunner; 74 import org.junit.runners.ParentRunner;
74 import org.junit.runners.model.InitializationError; 75 import org.junit.runners.model.InitializationError;
75 76
77 import com.oracle.truffle.api.dsl.NodeFactory;
78 import com.oracle.truffle.api.vm.PolyglotEngine;
79 import com.oracle.truffle.sl.SLLanguage;
80 import com.oracle.truffle.sl.builtins.SLBuiltinNode;
81 import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
82
76 public final class SLTestRunner extends ParentRunner<TestCase> { 83 public final class SLTestRunner extends ParentRunner<TestCase> {
77 84
78 private static int repeats = 1; 85 private static int repeats = 1;
79 86
80 private static final String SOURCE_SUFFIX = ".sl"; 87 private static final String SOURCE_SUFFIX = ".sl";
172 } 179 }
173 }); 180 });
174 return foundCases; 181 return foundCases;
175 } 182 }
176 183
184 /**
185 * Recursively deletes a file that may represent a directory.
186 */
187 private static void delete(File f) {
188 if (f.isDirectory()) {
189 for (File c : f.listFiles()) {
190 delete(c);
191 }
192 }
193 if (!f.delete()) {
194 PrintStream err = System.err;
195 err.println("Failed to delete file: " + f);
196 }
197 }
198
199 /**
200 * Unpacks a jar file to a temporary directory that will be removed when the VM exits.
201 *
202 * @param jarfilePath the path of the jar to unpack
203 * @return the path of the temporary directory
204 */
205 private static String explodeJarToTempDir(File jarfilePath) {
206 try {
207 final Path jarfileDir = Files.createTempDirectory(jarfilePath.getName());
208 Runtime.getRuntime().addShutdownHook(new Thread() {
209 @Override
210 public void run() {
211 delete(jarfileDir.toFile());
212 }
213 });
214 jarfileDir.toFile().deleteOnExit();
215 JarFile jarfile = new JarFile(jarfilePath);
216 Enumeration<JarEntry> entries = jarfile.entries();
217 while (entries.hasMoreElements()) {
218 JarEntry e = entries.nextElement();
219 if (!e.isDirectory()) {
220 File path = new File(jarfileDir.toFile(), e.getName().replace('/', File.separatorChar));
221 File dir = path.getParentFile();
222 dir.mkdirs();
223 assert dir.exists();
224 Files.copy(jarfile.getInputStream(e), path.toPath());
225 }
226 }
227 return jarfileDir.toFile().getAbsolutePath();
228 } catch (IOException e) {
229 throw new AssertionError(e);
230 }
231 }
232
177 public static Path getRootViaResourceURL(final Class<?> c, String[] paths) { 233 public static Path getRootViaResourceURL(final Class<?> c, String[] paths) {
178 URL url = c.getResource(c.getSimpleName() + ".class"); 234 URL url = c.getResource(c.getSimpleName() + ".class");
179 if (url != null) { 235 if (url != null) {
180 char sep = File.separatorChar; 236 char sep = File.separatorChar;
181 String externalForm = url.toExternalForm(); 237 String externalForm = url.toExternalForm();
182 String classPart = sep + c.getName().replace('.', sep) + ".class"; 238 String classPart = sep + c.getName().replace('.', sep) + ".class";
183 String suffix = null;
184 String prefix = null; 239 String prefix = null;
240 String base;
185 if (externalForm.startsWith("jar:file:")) { 241 if (externalForm.startsWith("jar:file:")) {
186 prefix = "jar:file:"; 242 prefix = "jar:file:";
187 suffix = sep + "build/truffle-sl.jar!" + classPart; 243 int bang = externalForm.indexOf('!', prefix.length());
244 Assume.assumeTrue(bang != -1);
245 File jarfilePath = new File(externalForm.substring(prefix.length(), bang));
246 Assume.assumeTrue(jarfilePath.exists());
247 base = explodeJarToTempDir(jarfilePath);
188 } else if (externalForm.startsWith("file:")) { 248 } else if (externalForm.startsWith("file:")) {
189 prefix = "file:"; 249 prefix = "file:";
190 suffix = classPart; 250 base = externalForm.substring(prefix.length(), externalForm.length() - classPart.length());
191 } else { 251 } else {
192 return null; 252 return null;
193 } 253 }
194 if (externalForm.endsWith(suffix)) { 254 for (String path : paths) {
195 String base = externalForm.substring(prefix.length(), externalForm.length() - suffix.length()); 255 String candidate = base + sep + path;
196 for (String path : paths) { 256 if (new File(candidate).exists()) {
197 String candidate = base + sep + path; 257 return FileSystems.getDefault().getPath(candidate);
198 if (new File(candidate).exists()) {
199 return FileSystems.getDefault().getPath(candidate);
200 }
201 } 258 }
202 } 259 }
203 } 260 }
204 return null; 261 return null;
205 } 262 }