Homework 2
This commit is contained in:
parent
12f678a924
commit
bf60a078d7
3 changed files with 4786 additions and 1185 deletions
171
test/cd/AbstractTestAgainstFrozenReference.java
Normal file
171
test/cd/AbstractTestAgainstFrozenReference.java
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
package cd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.DisableOnDebug;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import cd.frontend.parser.ParseFailure;
|
||||
import cd.ir.Ast.ClassDecl;
|
||||
import cd.util.FileUtil;
|
||||
import cd.util.debug.AstDump;
|
||||
|
||||
abstract public class AbstractTestAgainstFrozenReference {
|
||||
|
||||
public static final String SEMANTIC_OK = "OK";
|
||||
public static final String PARSE_FAILURE = "ParseFailure";
|
||||
|
||||
public File file, sfile, binfile, infile;
|
||||
public File parserreffile, semanticreffile, execreffile, cfgreffile, rdreffile,
|
||||
nnreffile, optreffile;
|
||||
public File errfile;
|
||||
public Main main;
|
||||
|
||||
public static int counter = 0;
|
||||
|
||||
@Rule
|
||||
public TestRule timeout = new DisableOnDebug(new Timeout(15, TimeUnit.SECONDS));
|
||||
|
||||
@Test
|
||||
public void test() throws Throwable {
|
||||
System.err.println("[" + counter++ + " = " + file + "]");
|
||||
|
||||
try {
|
||||
// Delete intermediate files from previous runs:
|
||||
if (sfile.exists())
|
||||
sfile.delete();
|
||||
if (binfile.exists())
|
||||
binfile.delete();
|
||||
|
||||
runReference();
|
||||
|
||||
List<ClassDecl> astRoots = testParser();
|
||||
if (astRoots != null) {
|
||||
}
|
||||
} catch (org.junit.ComparisonFailure cf) {
|
||||
throw cf;
|
||||
} catch (Throwable e) {
|
||||
PrintStream err = new PrintStream(errfile);
|
||||
err.println("Debug information for file: " + this.file);
|
||||
err.println(this.main.debug.toString());
|
||||
err.println("Test failed because an exception was thrown:");
|
||||
err.println(" " + e.getLocalizedMessage());
|
||||
err.println("Stack trace:");
|
||||
e.printStackTrace(err);
|
||||
System.err.println(FileUtil.read(errfile));
|
||||
throw e;
|
||||
}
|
||||
|
||||
// if we get here, then the test passed, so delete the errfile:
|
||||
// (which has been accumulating debug output etc)
|
||||
if (errfile.exists())
|
||||
errfile.delete();
|
||||
}
|
||||
|
||||
private void runReference() throws IOException, InterruptedException {
|
||||
String slash = File.separator;
|
||||
String colon = File.pathSeparator;
|
||||
String javaExe = System.getProperty("java.home") + slash + "bin" + slash + Config.JAVA_EXE;
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(
|
||||
javaExe, "-Dcd.meta_hidden.Version=" + referenceVersion(),
|
||||
"-cp", "lib/frozenReferenceObf.jar" + colon + " lib/junit-4.12.jar" + colon + "lib/antlr-4.7.1-complete.jar",
|
||||
"cd.FrozenReferenceMain", file.getAbsolutePath());
|
||||
|
||||
Process proc = pb.start();
|
||||
proc.waitFor();
|
||||
try (InputStream err = proc.getErrorStream()) {
|
||||
if (err.available() > 0) {
|
||||
byte b[] = new byte[err.available()];
|
||||
err.read(b, 0, b.length);
|
||||
System.err.println(new String(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String referenceVersion() {
|
||||
{
|
||||
return "CD_HW_PARSER_SOL";
|
||||
}
|
||||
}
|
||||
|
||||
private String tryReadRefFile(File fileToFind) {
|
||||
if (fileToFind.exists() && fileToFind.lastModified() >= file.lastModified()) {
|
||||
try {
|
||||
return FileUtil.read(fileToFind);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("ERROR: could not read file " + fileToFind.getPath());
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("ERROR: could not find file " + fileToFind.getPath());
|
||||
}
|
||||
|
||||
/** Run the parser and compare the output against the reference results */
|
||||
private List<ClassDecl> testParser() throws Exception {
|
||||
String parserRef = tryReadRefFile(parserreffile);
|
||||
List<ClassDecl> astRoots = null;
|
||||
String parserOut;
|
||||
|
||||
try {
|
||||
astRoots = main.parse(new FileReader(this.file));
|
||||
|
||||
parserOut = AstDump.toString(astRoots);
|
||||
} catch (ParseFailure pf) {
|
||||
{
|
||||
// Parse errors are ok too.
|
||||
main.debug("");
|
||||
main.debug("");
|
||||
main.debug("%s", pf.toString());
|
||||
parserOut = PARSE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
assertEquals("parser", parserRef, parserOut);
|
||||
}
|
||||
return astRoots;
|
||||
}
|
||||
|
||||
|
||||
private void assertEquals(String phase, String exp, String act_) {
|
||||
String act = act_.replace("\r\n", "\n"); // for windows machines
|
||||
if (!exp.equals(act)) {
|
||||
warnAboutDiff(phase, exp, act);
|
||||
}
|
||||
}
|
||||
|
||||
private void warnAboutDiff(String phase, String exp, String act) {
|
||||
try {
|
||||
try (PrintStream err = new PrintStream(errfile)) {
|
||||
err.println("Debug information for file: " + this.file);
|
||||
err.println(this.main.debug.toString());
|
||||
err.println(String.format(
|
||||
"Phase %s failed because we expected to see:", phase));
|
||||
err.println(exp);
|
||||
err.println("But we actually saw:");
|
||||
err.println(act);
|
||||
err.println("The difference is:");
|
||||
err.println(Diff.computeDiff(exp, act));
|
||||
}
|
||||
} catch (FileNotFoundException exc) {
|
||||
System.err.println("Unable to write debug output to " + errfile
|
||||
+ ":");
|
||||
exc.printStackTrace();
|
||||
}
|
||||
Assert.assertEquals(
|
||||
String.format("Phase %s for %s failed!", phase,
|
||||
file.getPath()), exp, act);
|
||||
}
|
||||
|
||||
}
|
||||
87
test/cd/Diff.java
Normal file
87
test/cd/Diff.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package cd;
|
||||
|
||||
// NOTE: This code was adapted from the code found at
|
||||
// http://www.cs.princeton.edu/introcs/96optimization/Diff.java.html
|
||||
|
||||
/*************************************************************************
|
||||
* Compilation: javac Diff
|
||||
* Execution: java Diff filename1 filename2
|
||||
* Dependencies: In.java
|
||||
*
|
||||
* Reads in two files and compute their diff.
|
||||
* A bare bones version.
|
||||
*
|
||||
* % java Diff input1.txt input2.txt
|
||||
*
|
||||
*
|
||||
* Limitations
|
||||
* -----------
|
||||
* - Could hash the lines to avoid potentially more expensive
|
||||
* string comparisons.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
public class Diff {
|
||||
|
||||
public static String computeDiff(String in0, String in1) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
// break into lines of each file
|
||||
String[] x = in0.split("\\n");
|
||||
String[] y = in1.split("\\n");
|
||||
|
||||
// number of lines of each file
|
||||
int M = x.length;
|
||||
int N = y.length;
|
||||
|
||||
// opt[i][j] = length of LCS of x[i..M] and y[j..N]
|
||||
int[][] opt = new int[M+1][N+1];
|
||||
|
||||
// compute length of LCS and all subproblems via dynamic programming
|
||||
for (int i = M-1; i >= 0; i--) {
|
||||
for (int j = N-1; j >= 0; j--) {
|
||||
if (x[i].equals(y[j]))
|
||||
opt[i][j] = opt[i+1][j+1] + 1;
|
||||
else
|
||||
opt[i][j] = Math.max(opt[i+1][j], opt[i][j+1]);
|
||||
}
|
||||
}
|
||||
|
||||
// recover LCS itself and print out non-matching lines to standard output
|
||||
boolean lineNumber = false;
|
||||
int i = 0, j = 0;
|
||||
while(i < M && j < N) {
|
||||
if (x[i].equals(y[j])) {
|
||||
i++;
|
||||
j++;
|
||||
lineNumber = false;
|
||||
}
|
||||
else {
|
||||
if (!lineNumber) {
|
||||
out.append(String.format(
|
||||
"At line %3d / %3d:\n", i+1, j+1));
|
||||
lineNumber = true;
|
||||
}
|
||||
assert lineNumber;
|
||||
if (opt[i+1][j] >= opt[i][j+1])
|
||||
out.append("< " + x[i++] + "\n");
|
||||
else
|
||||
out.append("> " + y[j++] + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// dump out one remainder of one string if the other is exhausted
|
||||
if (!lineNumber) {
|
||||
out.append(String.format("Line %3d / %3d:\n", i+1, j+1));
|
||||
}
|
||||
while(i < M || j < N) {
|
||||
if (i == M)
|
||||
out.append("> " + y[j++] + "\n");
|
||||
else if (j == N)
|
||||
out.append("< " + x[i++] + "\n");
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
}
|
||||
73
test/cd/TestSamplePrograms.java
Normal file
73
test/cd/TestSamplePrograms.java
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package cd;
|
||||
|
||||
import cd.util.FileUtil;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
|
||||
|
||||
/**
|
||||
* If you want to run the test on just one file, then initialize this
|
||||
* variable like:
|
||||
* {@code justFile = new File("javali_tests/HW2/Inheritance.javali")}.
|
||||
*/
|
||||
// public static final File justFile = new File("javali_tests/HW1/HelloWorld.javali");
|
||||
public static final File justFile = null;
|
||||
|
||||
/**
|
||||
* Directory in which to search for test files. If null, then the default is
|
||||
* the current directory (to include all files). To run only tests in a
|
||||
* particular directory, use sth. like:
|
||||
* {@code testDir = new File("javali_tests/HW2/")}.
|
||||
*/
|
||||
public static final File testDir = new File("javali_tests/HW2_nop90");
|
||||
// public static final File testDir = new File("javali_tests");
|
||||
|
||||
@Parameters(name="{index}:{0}")
|
||||
public static Collection<Object[]> testFiles() {
|
||||
List<Object[]> result = new ArrayList<Object[]>();
|
||||
if (justFile != null)
|
||||
result.add(new Object[] { justFile });
|
||||
else if (testDir != null) {
|
||||
for (File file : FileUtil.findJavaliFiles(testDir)) {
|
||||
result.add(new Object[] { file });
|
||||
}
|
||||
} else {
|
||||
for (File file : FileUtil.findJavaliFiles(new File("."))) {
|
||||
result.add(new Object[] { file });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file
|
||||
* The javali file to test.
|
||||
*/
|
||||
public TestSamplePrograms(File file) {
|
||||
this.file = file;
|
||||
this.sfile = new File(file.getPath() + Config.ASMEXT);
|
||||
this.binfile = new File(file.getPath() + Config.BINARYEXT);
|
||||
this.infile = new File(file.getPath() + ".in");
|
||||
this.parserreffile = new File(file.getPath() + ".parser.ref");
|
||||
this.semanticreffile = new File(file.getPath() + ".semantic.ref");
|
||||
this.execreffile = new File(file.getPath() + ".exec.ref");
|
||||
this.cfgreffile = new File(file.getPath() + ".cfg.dot.ref");
|
||||
this.rdreffile = new File(file.getPath() + ".rd.ref");
|
||||
this.nnreffile = new File(file.getPath() + ".nn.ref");
|
||||
this.optreffile = new File(file.getPath() + ".opt.ref");
|
||||
this.errfile = new File(String.format("%s.err", file.getPath()));
|
||||
this.main = new Main();
|
||||
this.main.debug = new StringWriter();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue