package dk.brics.jspointers.test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.runner.RunWith;
import dk.brics.jsparser.AstUtil;
import dk.brics.jspointers.Main;
import dk.brics.jspointers.test.instrument.InstrumentData;
import dk.brics.jspointers.test.instrument.Instrumenter;
import dk.brics.jspointers.test.instrument.JsPointersInstrumentData;
@RunWith(AutoTester.class)
@TestConfig(testFolder="test/instrument-tests",outputFolder="output/instrument")
public class RunInstrumentTests implements TestExecutor {
private String instrumentLib;
private static final File instrumentedOutputDir = new File("output/instrument");
private ExecutorService threads;
private Timer timer;
@Override
public void executeTest(TestCase test) throws Throwable {
File file = test.getFile();
final Main main = new Main(false, file);
InstrumentData data = new JsPointersInstrumentData(main);
new Instrumenter(data).instrument();
File out = new File(instrumentedOutputDir, file.getName());
out.getParentFile().mkdirs();
String code = AstUtil.toSourceString(main.getUserFiles().get(0).getAst());
Writer writer = new BufferedWriter(new FileWriter(out));
try {
writer.write(instrumentLib);
writer.write(code);
} finally {
writer.close();
}
ProcessBuilder pb = new ProcessBuilder("v8-shell", file.getName());
pb.directory(instrumentedOutputDir);
final Process proc = pb.start();
final boolean[] done = new boolean[1];
final boolean[] timeout = new boolean[1];
StringWriter output = new StringWriter();
threads.submit(new Piper(new InputStreamReader(proc.getInputStream()), output));
threads.submit(new Piper(new InputStreamReader(proc.getErrorStream()), output));
timer.schedule(new TimerTask() {
@Override
public void run() {
synchronized (done) {
if (done[0])
return;
proc.destroy(); // timeout if it takes too long
}
synchronized (timeout) {
timeout[0] = true;
}
}
}, 60000);
int exitCode = proc.waitFor();
synchronized (done) {
done[0] = true;
}
if (exitCode != 0) {
String msg = output.getBuffer().toString();
if (timeout[0]) {
msg += "\nTimeout!";
}
throw new RuntimeException(msg);
}
}
@Override
public boolean shouldTestRun(TestCase test) {
return true;
}
@Override
public void initialize(boolean isSingleTest) {
instrumentLib = TestUtil.readResource("dk/brics/jspointers/test/instrument/instrumentlib.js");
timer = new Timer();
threads = Executors.newFixedThreadPool(2);
}
@Override
public void close() {
}
}