package org.overture.codegen.tests.exec.util.testhandlers;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.junit.Assert;
import org.overture.ast.lex.Dialect;
import org.overture.codegen.runtime.traces.InMemoryTestAccumulator;
import org.overture.codegen.tests.exec.util.ExecutionResult;
import org.overture.config.Release;
import org.overture.config.Settings;
import org.overture.ct.ctruntime.TraceRunnerMain;
import org.overture.ct.ctruntime.utils.CtHelper;
import org.overture.ct.ctruntime.utils.Data;
import org.overture.ct.ctruntime.utils.TraceReductionInfo;
import org.overture.ct.ctruntime.utils.TraceResult;
import org.overture.ct.ctruntime.utils.TraceResultReader;
import org.overture.ct.ctruntime.utils.TraceTest;
import org.xml.sax.SAXException;
public class TraceHandler extends ExecutableSpecTestHandler
{
// The socket is used to communicate with the trace interpreter
protected ServerSocket socket;
protected static final int SOCKET_TIMEOUT = 0;
private Logger log = Logger.getLogger(this.getClass().getName());
public TraceHandler(Release release, Dialect dialect)
{
super(release, dialect);
}
public String getTraceName()
{
return "T1";
}
@Override
public String getVdmEntry()
{
return getTraceName();
}
@Override
public String getJavaEntry()
{
return "computeTests()";
}
@Override
public String getFullyQualifiedEntry(String rootPackage)
{
// The entry point is local so we can ignore the package and the enclosing class
return getJavaEntry();
}
public int getFreePort()
{
ServerSocket s = null;
try
{
s = new ServerSocket(0);
// returns the port the system selected
return s.getLocalPort();
} catch (IOException e)
{
e.printStackTrace();
} finally
{
if (s != null)
{
try
{
s.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
return 8999;
}
@Override
public List<String> getMainClassMethods(String rootPackage)
{
String runTraceCall;
if (Settings.dialect == Dialect.VDM_SL)
{
runTraceCall = toFullName(rootPackage, "Entry.Entry_T1_Run(acc);");
} else
{
runTraceCall = " new " + toFullName(rootPackage, "Entry")
+ "().Entry_T1_Run(acc);";
}
String computeTestsMethod = " public static TestAccumulator computeTests()\n"
+ " {\n"
+ " InMemoryTestAccumulator acc = new InMemoryTestAccumulator();\n"
+ runTraceCall + "\n" + " return acc;\n" + " }\n";
List<String> methods = new LinkedList<String>();
methods.add(computeTestsMethod);
return methods;
}
@Override
public ExecutionResult interpretVdm(File intputFile) throws Exception
{
File vdmTraceResultFile = computeVdmTraceResult(intputFile);
List<TraceResult> testResult = new TraceResultReader().read(vdmTraceResultFile);
if (testResult.size() != 1
|| !testResult.get(0).traceName.equals(getTraceName()))
{
log.error("Expected a single trace named: " + getTraceName()
+ ". Got: " + testResult);
return null;
}
TraceResult t1 = testResult.get(0);
StringBuilder sb = new StringBuilder();
for (TraceTest t : t1.tests)
{
sb.append(t).append('\n');
}
return new ExecutionResult(sb.toString(), t1.tests);
}
@Override
public ExecutionResult runJava(File folder)
{
ExecutionResult javaResult = super.runJava(folder);
return processTraceResult(javaResult);
}
public ExecutionResult processTraceResult(ExecutionResult javaResult)
{
Object executionResult = javaResult.getExecutionResult();
if (executionResult instanceof InMemoryTestAccumulator)
{
InMemoryTestAccumulator acc = (InMemoryTestAccumulator) executionResult;
return new ExecutionResult(javaResult.getStrRepresentation(), acc.getAllTests());
} else
{
return new ExecutionResult(javaResult.getStrRepresentation(), javaResult.getExecutionResult().toString());
}
}
public File computeVdmTraceResult(File specFile) throws IOException,
XPathExpressionException, SAXException, ParserConfigurationException
{
// The client thread will close the socket
int port = getFreePort();
socket = new ServerSocket(port);
socket.setSoTimeout(SOCKET_TIMEOUT);
final Data data = new Data();
File traceFolder = new File("target" + File.separatorChar + "cgtest"
+ File.separatorChar + "traceoutput");
traceFolder.mkdirs();
final File actualOutputFile = new File(traceFolder, "Entry-"
+ getVdmEntry() + ".xml");
CtHelper testHelper = new CtHelper();
Thread t = testHelper.consCtClientThread(socket, data);
t.setDaemon(false);
t.start();
File destFile = new File(traceFolder, specFile.getName() + ".vdmpp");
FileUtils.copyFile(specFile, destFile);
TraceRunnerMain.USE_SYSTEM_EXIT = false;
TraceReductionInfo info = new TraceReductionInfo();
String dialect = Settings.dialect == Dialect.VDM_SL ? "-vdmsl"
: "-vdmpp";
String[] buildArgs = new String[] { "-h", "localhost", "-p", port + "",
"-k", "whatever", "-e", "Entry", dialect, "-r", "vdm10", "-t",
getVdmEntry(), "-tracefolder",
traceFolder.toURI().toASCIIString(),
destFile.toURI().toASCIIString(), "-traceReduction",
"{" + info.getSubset() + ","
+ info.getReductionType().toString() + ","
+ info.getSeed() + "}" };
TraceRunnerMain.main(buildArgs);
final String message = data.getMessage();
Assert.assertTrue("Test did not succeed", message.contains("status=\"completed\" progress=\"100\""));
return actualOutputFile;
}
}