package org.overture.codegen.tests.exec.util;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.Vector;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.overture.codegen.ir.IRSettings;
import org.overture.codegen.tests.exec.util.testhandlers.ExecutableTestHandler;
import org.overture.codegen.tests.exec.util.testhandlers.TestHandler;
import org.overture.codegen.tests.util.TestUtils;
import org.overture.codegen.utils.GeneralCodeGenUtils;
import org.overture.interpreter.runtime.ContextException;
import org.overture.test.framework.ConditionalIgnoreMethodRule;
import org.overture.test.framework.Properties;
import org.overture.test.framework.results.IMessage;
import org.overture.test.framework.results.Result;
import org.overture.typechecker.util.TypeCheckerUtil.TypeCheckResult;
public abstract class CheckerTestBase extends JavaCodeGenTestCase
{
public static final String EXEC_TEST_PROPERTY = "tests.javagen.javac";
protected TestHandler testHandler;
protected File outputDir;
public CheckerTestBase(File vdmSpec, TestHandler testHandler)
{
super(vdmSpec, null, null);
this.testHandler = testHandler;
}
protected static Collection<Object[]> collectTests(File root,
TestHandler handler)
{
Collection<Object[]> tests = new Vector<Object[]>();
List<File> vdmSources = TestUtils.getTestInputFiles(root);
final int testCount = vdmSources.size();
for (int i = 0; i < testCount; i++)
{
File vdmSource = vdmSources.get(i);
String name = vdmSource.getAbsolutePath().substring(root.getAbsolutePath().length()
+ 1);
tests.add(new Object[] { name, vdmSource, handler });
}
return tests;
}
@Before
public void setUp() throws Exception
{
outputDir = new File(new File(new File("target"), getClass().getSimpleName()), file.getName());
outputDir.mkdirs();
}
@Rule
public ConditionalIgnoreMethodRule rule = new ConditionalIgnoreMethodRule();
public boolean runTest()
{
return System.getProperty(getExecProperty()) != null;
}
public String getExecProperty()
{
return EXEC_TEST_PROPERTY;
}
abstract public void genSourcesAndCompile();
@Test
public void test() throws Exception
{
Assume.assumeTrue("Pass property -D" + getExecProperty()
+ " to run test", runTest());
assumeTest();
configureResultGeneration();
try
{
genSourcesAndCompile();
if (testHandler instanceof ExecutableTestHandler)
{
Result<Object> result = produceResult();
compareResults(result, file.getName() + ".eval.result");
}
} finally
{
unconfigureResultGeneration();
}
}
public void assumeTest()
{
/* Allow all tests to run by default */
}
public static <T extends TypeCheckResult<?>> T checkTcResult(T tcResult)
{
if (GeneralCodeGenUtils.hasErrors(tcResult))
{
Assert.fail("Problems parsing/type checking VDM model:\n"
+ GeneralCodeGenUtils.errorStr(tcResult));
}
return tcResult;
}
public IRSettings getIrSettings()
{
IRSettings irSettings = new IRSettings();
irSettings.setCharSeqAsString(false);
return irSettings;
}
private Result<Object> produceResult() throws IOException
{
if (testHandler instanceof ExecutableTestHandler)
{
ExecutableTestHandler executableTestHandler = (ExecutableTestHandler) testHandler;
if (Properties.recordTestResults)
{
Object vdmResult = evalVdm(file, executableTestHandler);
return new Result<Object>(vdmResult, new Vector<IMessage>(), new Vector<IMessage>());
}
// Note that the classes returned in javaResult may be loaded by another class loader. This is the case for
// classes representing VDM classes, Quotes etc. that's not part of the cg-runtime
ExecutionResult javaResult = executableTestHandler.runJava(outputDir);
if (javaResult == null)
{
Assert.fail("No Java result could be produced");
}
return new Result<Object>(javaResult, new Vector<IMessage>(), new Vector<IMessage>());
}
Assert.fail("Trying to produce result using an unsupported test handler: "
+ testHandler);
return new Result<Object>(null, new Vector<IMessage>(), new Vector<IMessage>());
}
public File[] consCpFiles()
{
File cgRuntime = new File(org.overture.codegen.runtime.EvaluatePP.class.getProtectionDomain().getCodeSource().getLocation().getFile());
return new File[] { cgRuntime };
}
public void compile(File[] cpJars)
{
ProcessResult result = JavaCommandLineCompiler.compile(outputDir, cpJars);
Assert.assertTrue("Generated Java code did not compile: "
+ result.getOutput().toString(), result.getExitCode() == 0);
}
/**
* Evaluate the VDM specification, exceptions are returned as a String otherwise Value
*
* @param currentInputFile
* @param executableTestHandler
* @return the result of the VDM execution
*/
private Object evalVdm(File currentInputFile,
ExecutableTestHandler executableTestHandler)
{
// Calculating the VDM Result:
Object vdmResult = null;
try
{
ExecutionResult res = executableTestHandler.interpretVdm(currentInputFile);
if (res == null)
{
Assert.fail("no vdm result");
}
vdmResult = res.getExecutionResult();
} catch (ContextException ce1)
{
// Context exceptions are used to report the result of erroneous VDM executions
vdmResult = ce1.getMessage();
} catch (Exception e1)
{
e1.printStackTrace();
Assert.fail("Got unexpected exception when computing the VDM value");
}
return vdmResult;
}
@Override
protected boolean assertEqualResults(Object expected, Object actual,
PrintWriter out)
{
ExecutionResult javaResult = (ExecutionResult) actual;
// Comparison of VDM and Java results
ComparisonIR comp = new ComparisonIR(file);
boolean equal = comp.compare(javaResult.getExecutionResult(), expected);
if (!equal)
{
out.println(String.format("Actual result: %s does not match Expected: %s", ""
+ actual, "" + expected));
}
return equal;
}
}