Don't put fixed-name, writable files into "java.io.tmpdir"

If multiple tests both write to "/tmp/cg.txt" (for example), then
these tests cannot safely run concurrently.  That never used to be a
problem with Maven, since our Maven tests were all strictly sequential
anyway.  But parallelized testing using Gradle requires that we do
better.  Fortunately, Java has perfectly reasonable APIs for
generating uniquely-named temporary files and directories.
This commit is contained in:
Ben Liblit 2018-04-02 14:23:13 -05:00
parent ba01621de5
commit b14804bfdc
4 changed files with 41 additions and 24 deletions

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.js.nodejs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Set;
@ -52,7 +53,8 @@ public class NodejsRequiredCoreModule extends NodejsRequiredSourceModule {
}
public static NodejsRequiredCoreModule make(String name) throws IOException {
File file = new File(System.getProperty("java.io.tmpdir"), name+".js");
File file = Files.createTempFile(name, ".js").toFile();
file.deleteOnExit();
TemporaryFile.streamToFile(file, getModule(name));
SourceFileModule sourceFileModule = CAstCallGraphUtil.makeSourceModule(file.toURI().toURL(), file.getName());
return new NodejsRequiredCoreModule(file, sourceFileModule);

View File

@ -13,9 +13,9 @@ package com.ibm.wala.core.tests.shrike;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -65,17 +65,26 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
private boolean instrumentedJarBuilt = false;
private String instrumentedJarLocation = System.getProperty("java.io.tmpdir") + File.separator + "test.jar";
private java.nio.file.Path instrumentedJarLocation;
private String cgLocation = System.getProperty("java.io.tmpdir") + File.separator + "cg.txt";
private java.nio.file.Path cgLocation;
protected DynamicCallGraphTestBase() {
try {
instrumentedJarLocation = Files.createTempFile("wala-test", ".jar");
instrumentedJarLocation.toFile().deleteOnExit();
cgLocation = Files.createTempFile("cg", ".txt");
cgLocation.toFile().deleteOnExit();
} catch (IOException problem) {
throw new RuntimeException(problem);
}
}
protected void instrument(String testJarLocation) throws IOException, ClassNotFoundException, InvalidClassFileException, FailureException {
if (! instrumentedJarBuilt) {
System.err.println("core data jar to instrument: " + testJarLocation);
if (new File(instrumentedJarLocation).exists()) {
assert new File(instrumentedJarLocation).delete();
}
Files.deleteIfExists(instrumentedJarLocation);
String rtJar = null;
for(String jar : WalaProperties.getJ2SEJarFiles()) {
@ -85,7 +94,7 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
}
List<String> args = new ArrayList<>();
args.addAll(Arrays.asList(testJarLocation, "-o", instrumentedJarLocation));
args.addAll(Arrays.asList(testJarLocation, "-o", instrumentedJarLocation.toString()));
if (rtJar != null) {
args.addAll(Arrays.asList("--rt-jar", rtJar));
}
@ -93,14 +102,16 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
args.add("--patch-calls");
}
OfflineDynamicCallGraph.main(args.toArray(new String[ args.size() ]));
Assert.assertTrue("expected to create /tmp/test.jar", new File(instrumentedJarLocation).exists());
Assert.assertTrue("expected to create " + instrumentedJarLocation, Files.exists(instrumentedJarLocation));
instrumentedJarBuilt = true;
}
}
protected void run(String mainClass, String exclusionsFile, String... args) throws IOException, SecurityException, IllegalArgumentException, InterruptedException {
Project p = new Project();
p.setBaseDir(new File(System.getProperty("java.io.tmpdir")));
final File projectDir = Files.createTempDirectory("wala-test").toFile();
projectDir.deleteOnExit();
p.setBaseDir(projectDir);
p.init();
p.fireBuildStarted();
@ -125,9 +136,7 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
childJvm.setFailonerror(true);
childJvm.setFork(true);
if (new File(cgLocation).exists()) {
new File(cgLocation).delete();
}
Files.deleteIfExists(cgLocation);
childJvm.init();
String commandLine = childJvm.getCommandLine().toString();
@ -135,7 +144,7 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
Process x = Runtime.getRuntime().exec(commandLine);
x.waitFor();
Assert.assertTrue("expected to create call graph", new File(cgLocation).exists());
Assert.assertTrue("expected to create call graph", Files.exists(cgLocation));
}
interface EdgesTest {
@ -186,7 +195,7 @@ public abstract class DynamicCallGraphTestBase extends WalaTestCase {
protected void check(CallGraph staticCG, EdgesTest test, Predicate<MethodReference> filter) throws IOException {
int lines = 0;
try (final BufferedReader dynamicEdgesFile = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(cgLocation))))) {
try (final BufferedReader dynamicEdgesFile = new BufferedReader(new InputStreamReader(new GZIPInputStream(Files.newInputStream(cgLocation))))) {
String line;
loop: while ((line = dynamicEdgesFile.readLine()) != null) {
if (line.startsWith("call to") || line.startsWith("return from")) {

View File

@ -49,6 +49,7 @@ package com.ibm.wala.dalvik.classLoader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
@ -83,12 +84,12 @@ public class DexFileModule implements Module {
}
}
private static File tf(JarFile f) {
private static File tf(JarFile f) throws IOException {
String name = f.getName();
if (name.indexOf('/') >= 0) {
name = name.substring(name.lastIndexOf('/')+1);
}
File tf = new File(System.getProperty("java.io.tmpdir") + "/" + name + "_classes.dex");
File tf = Files.createTempFile("name", "_classes.dex").toFile();
tf.deleteOnExit();
System.err.println("using " + tf);
return tf;

View File

@ -1,11 +1,12 @@
package com.ibm.wala.shrike.instrumentation;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.ProtectionDomain;
import com.ibm.wala.shrikeCT.ClassReader;
@ -15,11 +16,16 @@ import com.ibm.wala.shrikeCT.SourceFileReader;
public class CodeScraper implements ClassFileTransformer {
private static final String prefix = System.getProperty("java.io.tmpdir") + File.separator + "loggedClasses" + File.separator + System.currentTimeMillis();
private static final Path prefix;
static {
try {
prefix = Files.createTempDirectory("loggedClasses");
prefix.toFile().deleteOnExit();
} catch (final IOException problem) {
throw new RuntimeException(problem);
}
System.err.println("scraping to " + prefix);
(new File(prefix)).mkdirs();
}
@Override
@ -38,9 +44,8 @@ public class CodeScraper implements ClassFileTransformer {
}
}
if (className == null || sourceFile == null || !sourceFile.endsWith("java") || true) try {
String log = prefix + File.separator + reader.getName() + ".class";
(new File(log)).getParentFile().mkdirs();
try (final FileOutputStream f = new FileOutputStream(log)) {
Path log = prefix.resolve(reader.getName() + ".class");
try (final OutputStream f = Files.newOutputStream(log)) {
f.write(classfileBuffer);
}
} catch (IOException e) {