// Copyright (c) 2011, David J. Pearce (djp@ecs.vuw.ac.nz)
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.
package wyc.testing;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import wyc.commands.Compile;
import wyc.util.TestUtils;
import wycc.util.Pair;
/**
* Run through all invalid test cases with verification enabled. Since every
* test file is invalid, a successful test occurs when the compiler produces a
* syntax error for the file. Note that an internal failure does not count as a
* valid pass, and indicates the test exposed some kind of compiler bug.
*
* @author David J. Pearce
*
*/
@RunWith(Parameterized.class)
public class AllInvalidTest {
/**
* The directory containing the source files for each test case. Every test
* corresponds to a file in this directory.
*/
public final static String WHILEY_SRC_DIR = "tests/invalid".replace('/', File.separatorChar);
/**
* Ignored tests and a reason why we ignore them.
*/
public final static Map<String, String> IGNORED = new HashMap<>();
static {
IGNORED.put("Constant_Invalid_1", "unclassified");
IGNORED.put("Export_Invalid_1", "unclassified");
IGNORED.put("Function_Invalid_2", "unclassified");
IGNORED.put("Function_Invalid_9", "unclassified");
IGNORED.put("Native_Invalid_1", "unclassified");
IGNORED.put("OpenRecord_Invalid_2", "type testing definite taken");
//
IGNORED.put("ReferenceOpenRecord_Invalid_1", "#585");
//
IGNORED.put("Parsing_Invalid_1", "608");
IGNORED.put("Parsing_Invalid_2", "608");
//
IGNORED.put("Parsing_Invalid_15", "609");
//
IGNORED.put("Parsing_Invalid_31", "610");
//
IGNORED.put("MethodRef_Invalid_1", "#334");
IGNORED.put("MethodRef_Invalid_3", "#334");
//
IGNORED.put("TypeEquals_Invalid_1", "#681");
//
IGNORED.put("Tuple_Invalid_3", "#713");
IGNORED.put("Tuple_Invalid_4", "#713");
IGNORED.put("Tuple_Invalid_5", "#713");
// ===============================================================
// Whiley Theorem Prover faults
// ===============================================================
IGNORED.put("Fail_Invalid_1", "unclassified");
IGNORED.put("Fail_Invalid_3", "unclassified");
IGNORED.put("RecursiveType_Invalid_4", "unclassified");
IGNORED.put("RecursiveType_Invalid_7", "unclassified");
IGNORED.put("RecursiveType_Invalid_8", "unclassified");
IGNORED.put("RecursiveType_Invalid_9", "unclassified");
IGNORED.put("TypeEquals_Invalid_5", "unclassified");
IGNORED.put("UnionType_Invalid_9", "unclassified");
//
IGNORED.put("RecursiveType_Invalid_2", "WyTP#26");
}
/**
* The directory where compiler libraries are stored. This is necessary
* since it will contain the Whiley Runtime.
*/
public final static String WYC_LIB_DIR = "../../lib/".replace('/', File.separatorChar);
// ======================================================================
// Test Harness
// ======================================================================
/**
* Compile a syntactically invalid test case with verification enabled. The
* expectation is that compilation should fail with an error and, hence, the
* test fails if compilation does not.
*
* @param name
* Name of the test to run. This must correspond to a whiley
* source file in the <code>WHILEY_SRC_DIR</code> directory.
* @throws IOException
*/
protected void runTest(String name) throws IOException {
File whileySrcDir = new File(WHILEY_SRC_DIR);
// this will need to turn on verification at some point.
String filename = WHILEY_SRC_DIR + File.separatorChar + name + ".whiley";
Pair<Compile.Result,String> p = TestUtils.compile(
whileySrcDir, // location of source directory
true, // enable verification
filename); // name of test to compile
Compile.Result r = p.first();
String output = p.second();
if (r == Compile.Result.SUCCESS) {
// Clearly, the test should not compile.
fail("Test compiled when it shouldn't have!");
} else if (r == Compile.Result.INTERNAL_FAILURE) {
// This indicates some other kind of internal failure.
fail("Test caused internal failure!\n" + output);
} else {
// Now, let's check the expected output against the file which
// contains the sample output for this test
String sampleOutputFile = WHILEY_SRC_DIR + File.separatorChar + name
+ ".sysout";
// Following used when sample output changed.
// try {
// FileWriter fw = new FileWriter(sampleOutputFile);
// fw.write(output);
// fw.close();
// } catch(Exception e) {}
// Third, compare the output!
if(!TestUtils.compare(output,sampleOutputFile)) {
fail("Output does not match reference");
}
}
}
// ======================================================================
// Tests
// ======================================================================
// Parameter to test case is the name of the current test.
// It will be passed to the constructor by JUnit.
private final String testName;
public AllInvalidTest(String testName) {
this.testName = testName;
}
// Here we enumerate all available test cases.
@Parameters(name = "{0}")
public static Collection<Object[]> data() {
return TestUtils.findTestNames(WHILEY_SRC_DIR);
}
// Skip ignored tests
@Before
public void beforeMethod() {
String ignored = IGNORED.get(this.testName);
Assume.assumeTrue("Test " + this.testName + " skipped: " + ignored, ignored == null);
}
@Test
public void invalid() throws IOException {
if (new File("../../running_on_travis").exists()) {
System.out.println(".");
}
runTest(this.testName);
}
}