Commit 0d5b35e1 authored by Sascha Niklas Schneiders's avatar Sascha Niklas Schneiders
Browse files

execution can finally create log files now

parent c5f57c8d
Pipeline #69092 passed with stage
in 13 minutes and 45 seconds
......@@ -30,7 +30,64 @@ public class ArmadilloHelperSource {
"#include \"armadillo.h\"\n" +
"#include <stdarg.h>\n" +
"#include <initializer_list>\n" +
"#include <fstream>\n" +
"using namespace arma;\n" +
"#ifndef _FILESTRING_CONVERSION___A\n" +
"#define _FILESTRING_CONVERSION___A\n" +
"#include \"armadillo.h\"\n" +
"using namespace arma;\n" +
"void toFileString(std::ofstream& myfile, mat A){\n" +
" myfile << \"[\";\n" +
" for (int i = 0; i < A.n_rows; i++){\n" +
" for (int j = 0; j < A.n_cols; j++){\n" +
" myfile << A(i,j);\n" +
" if(j + 1 < A.n_cols){\n" +
" myfile << \", \";\n" +
" }\n" +
" }\n" +
" if(i + 1 < A.n_rows){\n" +
" myfile << \";\";\n" +
" }\n" +
" }\n" +
" myfile << \"]\";\n" +
"}\n" +
"void toFileString(std::ofstream& myfile, double A){\n" +
" myfile << A;\n" +
"}\n" +
"void toFileString(std::ofstream& myfile, float A){\n" +
" myfile << A;\n" +
"}\n" +
"void toFileString(std::ofstream& myfile, int A){\n" +
" myfile << A;\n" +
"}\n" +
"void toFileString(std::ofstream& myfile, bool A){\n" +
" myfile << A;\n" +
"}\n" +
"bool Is_close(mat& X, mat& Y, double tol)\n" +
"{\n" +
" // abs returns a mat type then max checks columns and returns a row_vec\n" +
" // max used again will return the biggest element in the row_vec\n" +
" bool close(false);\n" +
" if(arma::max(arma::max(arma::abs(X-Y))) < tol)\n" +
" {\n" +
" close = true;\n" +
" }\n" +
" return close;\n" +
"}\n" +
"void rangeValueCheck(double A, double lower, double upper){\n" +
" REQUIRE( A >= lower );\n" +
" REQUIRE( A <= upper );\n" +
"}\n" +
"\n" +
"void rangeValueCheck(int A, double lower, double upper){\n" +
" REQUIRE( A >= lower );\n" +
" REQUIRE( A <= upper );\n" +
"}\n" +
"void rangeValueCheck(mat& A, mat& lower , mat& upper){\n" +
" REQUIRE(Is_close(A, lower, 0.0001));\n" +
" REQUIRE(Is_close(A, upper, 0.0001));\n" +
"}\n" +
"#endif\n" +
"class HelperA{\n" +
"public:\n" +
"static mat getEigenVectors(mat A){\n" +
......
......@@ -56,6 +56,7 @@ public class GeneratorCPP implements Generator {
private boolean isGenerateTests = false;
private boolean isGenerateAutopilotAdapter = false;
private boolean isGenerateServerWrapper = false;
protected boolean isExecutionLoggingActive = false;
private final List<BluePrintCPP> bluePrints = new ArrayList<>();
protected String generationTargetPath = "./target/generated-sources-cpp/";
......@@ -76,6 +77,14 @@ public class GeneratorCPP implements Generator {
currentInstance = this;
}
public boolean isExecutionLoggingActive() {
return isExecutionLoggingActive;
}
public void setExecutionLoggingActive(boolean executionLoggingActive) {
isExecutionLoggingActive = executionLoggingActive;
}
public void useArmadilloBackend() {
MathConverter.curBackend = new ArmadilloBackend();
}
......
......@@ -99,6 +99,13 @@ public final class GeneratorCppCli {
.required(false)
.build();
public static final Option OPTION_FLAG_EXEC_LOGGING = Option.builder("a")
.longOpt("flag-use-exec-logging")
.desc("optional flag indicating if execution logging should be on")
.hasArg(false)
.required(false)
.build();
public static final Option OPTION_FLAG_AUTOPILOT_ADAPTER = Option.builder()
.longOpt("flag-generate-autopilot-adapter")
......@@ -145,6 +152,7 @@ public final class GeneratorCppCli {
options.addOption(OPTION_FLAG_SERVER_WRAPPER);
options.addOption(OPTION_FLAG_ALGEBRAIC);
options.addOption(OPTION_FLAG_THREADING);
options.addOption(OPTION_FLAG_EXEC_LOGGING);
return options;
}
......@@ -183,6 +191,8 @@ public final class GeneratorCppCli {
g.setUseAlgebraicOptimizations(cliArgs.hasOption(OPTION_FLAG_ALGEBRAIC.getLongOpt()));
g.setUseThreadingOptimization(cliArgs.hasOption(OPTION_FLAG_THREADING.getLongOpt()));
g.setExecutionLoggingActive(cliArgs.hasOption(OPTION_FLAG_EXEC_LOGGING.getLongOpt()));
try {
if (componentSymbol != null) {
g.generateFiles(componentSymbol, symTab);
......
......@@ -111,11 +111,20 @@ public class LanguageUnitCPP extends LanguageUnit {
resultString += "#include \"" + v.getVariableType().getIncludeName() + ".h\"\n";
}
}
}
if (!alreadyGeneratedIncludes.contains("HelperA") && generatorCPP.isExecutionLoggingActive) {
alreadyGeneratedIncludes.add("HelperA");
resultString += "#include \"" + "HelperA" + ".h\"\n";
}
for (String string : bluePrint.getAdditionalIncludeStrings())
resultString += "#include \"" + string + ".h\"\n";
if (generatorCPP.isExecutionLoggingActive)
resultString += "#include <fstream>\n";
for (String include : includeStrings) {
resultString += include;
}
......@@ -136,7 +145,9 @@ public class LanguageUnitCPP extends LanguageUnit {
for (String constString : bluePrint.getConsts())
resultString += constString;
resultString += "public:\n";
if (generatorCPP.isExecutionLoggingActive) {
resultString += "int __EXECCOUNTER;\n";
}
//input variable
for (Variable v : bluePrint.getVariables()) {
if (!v.isArray())
......@@ -147,8 +158,10 @@ public class LanguageUnitCPP extends LanguageUnit {
//generate methods
for (Method method : bluePrint.getMethods()) {
int counter = 0;
resultString += method.getReturnTypeName() + " " + method.getName() + "(";
for (Variable param : method.getParameters()) {
if (counter == 0) {
++counter;
......@@ -163,7 +176,11 @@ public class LanguageUnitCPP extends LanguageUnit {
//method body start
resultString += "{\n";
if (generatorCPP.isExecutionLoggingActive && method.getName().equals("execute")) {
resultString += "std::ofstream __LogExecutionFile;\n";
resultString += "__LogExecutionFile.open(\"execution\"+std::to_string(__EXECCOUNTER)+\".res\");\n";
}
for (Instruction instruction : method.getInstructions()) {
if (instruction instanceof ConnectInstructionCPP) {
ConnectInstructionCPP connectInstructionCPP = (ConnectInstructionCPP) instruction;
......@@ -176,7 +193,22 @@ public class LanguageUnitCPP extends LanguageUnit {
resultString += instruction.getTargetLanguageInstruction();
Log.info(resultString, "afterRes:");
}
if (generatorCPP.isExecutionLoggingActive && method.getName().equals("execute")) {
for (Variable v : bluePrint.getVariables()) {
if (v.hasAdditionalInformation(Variable.ORIGINPORT)) {
resultString += "__LogExecutionFile << \"" + v.getNameTargetLanguageFormat() + " : \";\n";
resultString += "toFileString(__LogExecutionFile, " + v.getNameTargetLanguageFormat() + ");\n";
resultString += "__LogExecutionFile << \"\\n\";\n";
}
}
}
if (generatorCPP.isExecutionLoggingActive && method.getName().equals("execute")) {
resultString += "__LogExecutionFile.close();\n";
resultString += "__EXECCOUNTER = __EXECCOUNTER + 1;\n";
}
if (generatorCPP.isExecutionLoggingActive && method.getName().equals("init")) {
resultString += "__EXECCOUNTER = 0;\n";
}
//method body end
resultString += "}\n";
}
......
......@@ -7,7 +7,7 @@
#include <iostream>
#include <fstream>
#include <string>
void toFileString(std::ofstream& myfile, mat A){
/*void toFileString(std::ofstream& myfile, mat A){
myfile << "[";
for (int i = 0; i < A.n_rows; i++){
for (int j = 0; j < A.n_cols; j++){
......@@ -57,7 +57,7 @@ void rangeValueCheck(int A, double lower, double upper){
void rangeValueCheck(mat& A, mat& lower , mat& upper){
REQUIRE(Is_close(A, lower, 0.0001));
REQUIRE(Is_close(A, upper, 0.0001));
}
}*/
<#list viewModel.streams as stream>
TEST_CASE("${stream.name}", "[${viewModel.componentName}]") {
mat tmpA;
......
<#include "/Common.ftl">
#ifndef ${viewModel.fileNameWithoutExtension?upper_case}
#define ${viewModel.fileNameWithoutExtension?upper_case}
#include "catch.hpp"
#include "../${viewModel.componentName}.h"
#include <iostream>
#include <fstream>
#include <string>
void toFileString(std::ofstream& myfile, mat A){
myfile << "[";
for (int i = 0; i < A.n_rows; i++){
for (int j = 0; j < A.n_cols; j++){
myfile << A(i,j);
if(j + 1 < A.n_cols){
myfile << ", ";
}
}
if(i + 1 < A.n_rows){
myfile << ";";
}
}
myfile << "]";
}
void toFileString(std::ofstream& myfile, double A){
myfile << A;
}
void toFileString(std::ofstream& myfile, float A){
myfile << A;
}
void toFileString(std::ofstream& myfile, int A){
myfile << A;
}
void toFileString(std::ofstream& myfile, bool A){
myfile << A;
}
bool Is_close(mat& X, mat& Y, double tol)
{
// abs returns a mat type then max checks columns and returns a row_vec
// max used again will return the biggest element in the row_vec
bool close(false);
if(arma::max(arma::max(arma::abs(X-Y))) < tol)
{
close = true;
}
return close;
}
void rangeValueCheck(double A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(int A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(mat& A, mat& lower , mat& upper){
REQUIRE(Is_close(A, lower, 0.0001));
REQUIRE(Is_close(A, upper, 0.0001));
}
<#list viewModel.streams as stream>
TEST_CASE("${stream.name}", "[${viewModel.componentName}]") {
mat tmpA;
mat tmpB;
${viewModel.componentName} component;
std::ofstream myfile;
myfile.open ("${stream.name}");
myfile.precision(64);
component.init();
<#list stream.checks as check>
<#list check.inputPortName2Value?keys as portName>
component.${portName} ${check.inputPortName2Value[portName]};
</#list>
component.execute();
<#list check.outputPortName2Check?keys as outputPortName>
<@renderPortCheck outputPortName=outputPortName check=check.outputPortName2Check[outputPortName] />
</#list>
<#list stream.outputPortNames as outputPortName>
myfile << "${outputPortName}: ";
toFileString(myfile, component.${outputPortName});
myfile << "\n";
</#list>
</#list>
myfile.close();
std::cout << "${stream.name}: success\n";
}
</#list>
#endif
<#macro renderPortCheck outputPortName check>
<#assign portValue="component.${outputPortName}">
<#if helper.isBooleanOutputPortCheck(check)>
<#if helper.isTrueExpectedCheck(check)>
REQUIRE( ${portValue} );
<#else>
REQUIRE_FALSE( ${portValue} );
</#if>
<#elseif helper.isRangeOutputPortCheck(check)>
<#if check.isMatrix??>
<#if check.isMatrix()>
tmpA = mat();
tmpA ${check.lowerBound};
tmpB = mat();
tmpB ${check.upperBound};
rangeValueCheck(${portValue}, tmpA , tmpB);
<#else>
rangeValueCheck(${portValue}, ${check.lowerBound} , ${check.upperBound});
</#if>
<#else>
rangeValueCheck(${portValue}, ${check.lowerBound} , ${check.upperBound});
</#if>
<#else>
</#if>
</#macro>
......@@ -8,6 +8,7 @@
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
// start catch.hpp
......@@ -12010,3 +12011,59 @@ using Catch::Detail::Approx;
// end catch.hpp
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#ifndef _FILESTRING_CONVERSION___A
#define _FILESTRING_CONVERSION___A
#include "armadillo.h"
using namespace arma;
void toFileString(std::ofstream& myfile, mat A){
myfile << "[";
for (int i = 0; i < A.n_rows; i++){
for (int j = 0; j < A.n_cols; j++){
myfile << A(i,j);
if(j + 1 < A.n_cols){
myfile << ", ";
}
}
if(i + 1 < A.n_rows){
myfile << ";";
}
}
myfile << "]";
}
void toFileString(std::ofstream& myfile, double A){
myfile << A;
}
void toFileString(std::ofstream& myfile, float A){
myfile << A;
}
void toFileString(std::ofstream& myfile, int A){
myfile << A;
}
void toFileString(std::ofstream& myfile, bool A){
myfile << A;
}
bool Is_close(mat& X, mat& Y, double tol)
{
// abs returns a mat type then max checks columns and returns a row_vec
// max used again will return the biggest element in the row_vec
bool close(false);
if(arma::max(arma::max(arma::abs(X-Y))) < tol)
{
close = true;
}
return close;
}
void rangeValueCheck(double A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(int A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(mat& A, mat& lower , mat& upper){
REQUIRE(Is_close(A, lower, 0.0001));
REQUIRE(Is_close(A, upper, 0.0001));
}
#endif
\ No newline at end of file
......@@ -233,6 +233,30 @@ public class AutomaticStreamTestGenerationTest extends AbstractSymtabTest {
"de.rwth.armin.modeling.autopilot.common.compass2CurrentDirectionTest1");
}
@Test
public void testLoggingExample1() throws Exception {
AutomaticStreamTestGenerator generator = new AutomaticStreamTestGenerator();
generator.generateTests("",
"src/test/resources/emastudio/autopilot", "N:/target/generated-sources-cpp/streamtest/autopilot/", "1", 10);
testGenCPPFilesAndExecWithExecLogging("./target/generated-sources-cpp/streamtest", "/autopilot",
"./src/test/resources/emastudio/autopilot", "./target/generated-sources-cpp/streamtest/autopilot",
"de.rwth.armin.modeling.autopilot.motion.calculatePidError",
"de.rwth.armin.modeling.autopilot.motion.CalculatePidErrorTest1");
}
@Test
public void testLoggingExample2() throws Exception {
AutomaticStreamTestGenerator generator = new AutomaticStreamTestGenerator();
generator.generateTests("",
"src/test/resources/emastudio/autopilot", "N:/target/generated-sources-cpp/streamtest/autopilot/", "1", 10);
testGenCPPFilesAndExecWithExecLogging("./target/generated-sources-cpp/streamtest", "/autopilot",
"./src/test/resources/emastudio/autopilot", "./target/generated-sources-cpp/streamtest/autopilot",
"de.rwth.armin.modeling.autopilot.motion.calculateEngineAndBrakes",
"de.rwth.armin.modeling.autopilot.motion.CalculateEngineAndBrakesTest1");
}
@Ignore //Does not work in maven for some reason
@Test
public void testComponent() throws Exception {
......@@ -273,6 +297,34 @@ public class AutomaticStreamTestGenerationTest extends AbstractSymtabTest {
StreamTestExecution.compileTests(targetFullPath, targetBasePath);
StreamTestExecution.executeTests(targetBasePath);
}
public void testGenCPPFilesAndExecWithExecLogging(String targetBasePath, String targetRestPath, String modelDirectory, String outputDirectory,
String fullComponentInstanceName, String fullStreamTestName) throws Exception {
String targetFullPath = targetBasePath + targetRestPath;
String fullStreamTestPathName = fullStreamTestName.replaceAll("\\.", "\\/");
String args[] = {"--models-dir=" + outputDirectory,
"--output-dir=" + outputDirectory,
"--root-model=" + fullComponentInstanceName,
"--flag-generate-tests",
"--flag-use-armadillo-backend",
"--flag-use-exec-logging"};
File srcDir = new File(modelDirectory);
File destDir = new File(outputDirectory);
FileUtils.copyDirectory(srcDir, destDir);
GeneratorCppCli.main(args);
StreamTestExecution.compileTests(targetFullPath, targetBasePath);
StreamTestExecution.executeTests(targetBasePath);
//Execute again to check if tests pass
StreamTestModifier.updateStreamTestWithResults("N:/target/generated-sources-cpp/streamtest/"+targetRestPath+"/" + fullStreamTestPathName + ".stream"
, "N:/target/generated-sources-cpp/streamtest/exec/" + fullStreamTestName);
GeneratorCppCli.main(args);
StreamTestExecution.compileTests(targetFullPath, targetBasePath);
StreamTestExecution.executeTests(targetBasePath);
}
//Maybe add test that executes all stream tests in the resource dir(will take longer than an hour to execute) later
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment