/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.thingml.testconfigurationgenerator;
import org.sintef.thingml.Thing;
import org.sintef.thingml.ThingMLModel;
import org.sintef.thingml.constraints.ThingMLHelpers;
import org.sintef.thingml.helpers.AnnotatedElementHelper;
import org.thingml.thingmltools.ThingMLTool;
/**
*
* @author sintef
*/
public class TestConfigurationGenerator extends ThingMLTool {
public TestConfigurationGenerator() {
super();
}
@Override
public String getID() {
return "testconfigurationgen";
}
@Override
public String getName() {
return "Test Configuration Generator";
}
@Override
public String getDescription() {
return "Generates test configuration for things annnotated with @test \"input # output\".";
}
@Override
public ThingMLTool clone() {
return new TestConfigurationGenerator();
}
@Override
public void generateThingMLFrom(ThingMLModel model) {
System.out.println("Generate ThingML from model");
for (Thing t : ThingMLHelpers.allThings(model)) {
int i = 0;
for (String an : AnnotatedElementHelper.annotation(t, "test")) {
String[] testAn = an.split("#");
String testInputs, testOutputs;
if (testAn.length == 2) {
testInputs = testAn[0];
testOutputs = testAn[1];
System.out.println("in: " + testInputs + ", out: " + testOutputs);
for (Language lang : TestGenConfig.getLanguages(outDir, this.options)) {
generateCfg(t, testInputs, testOutputs, lang, i);
}
i++;
}
}
}
writeGeneratedCodeToFiles();
}
public void generateTester(StringBuilder builder, Thing t, String in, String out) {
builder.append("thing Tester includes TestHarness, TimerClient {\n");
int i = 0;
builder.append(" statechart TestChart init e0 {\n");
builder.append(" on entry do\n");
//builder.append(" print \"[Expected] \"\n");
//builder.append(" print \"" + out + "\"\n");
//builder.append(" print \" [Test] \"\n");
builder.append(" print \"[Expected] " + out + " [Test] \"\n");
builder.append(" end\n");
for (char c : in.toCharArray()) {
if (c != ' ') {
builder.append(" state e" + i + " {\n");
builder.append(" on entry timer!timer_start(10)\n");
builder.append(" transition -> e" + (i + 1) + "\n");
builder.append(" event timer?timer_timeout\n");
builder.append(" action test!testIn('\\'" + c + "\\'')\n");
builder.append(" }\n");
i++;
}
}
builder.append(" state e" + i + " {\n");
int testDuration = 250;
if (AnnotatedElementHelper.hasAnnotation(t, "test_duration")) {
String timerDuration = AnnotatedElementHelper.annotation(t, "test_duration").iterator().next();
Integer dur = Integer.parseInt(timerDuration);
testDuration = dur.intValue();
}
builder.append(" on entry timer!timer_start(" + testDuration + ")\n");
builder.append(" transition -> e" + (i+1) + "\n");
builder.append(" event timer?timer_timeout\n");
builder.append(" }\n");
i++;
builder.append(" state e" + i + " {\n");
builder.append(" on entry do\n"
+ " testEnd!testEnd()\n"
+ " end");
builder.append(" }\n");
builder.append(" }\n");
builder.append("}\n");
}
public String LowerFirstLetter(String str) {
if (str == null)
return null;
if (str.length() < 2)
return str.toLowerCase();
return str.substring(0, 1).toLowerCase() + str.substring(1, str.length());
}
public void generateCfg(Thing t, String in, String out, Language lang, int testNumber) {
StringBuilder builder = new StringBuilder();
builder.append("import \"../../../src/main/resources/tests/thingml.thingml\"\n\n");
builder.append("import \"../../../src/main/resources/tests/core/_" + lang.longName + "/test.thingml\"\n");
builder.append("import \"../../../src/main/resources/tests/" + src.getParentFile().getName() + "/" + LowerFirstLetter(t.getName()) + ".thingml\"\n");
//builder.append("import \"" + src.getAbsolutePath() + "\"\n");
builder.append("import \"../../../src/main/resources/tests/core/_" + lang.longName + "/timer.thingml\"\n");
builder.append("\n");
generateTester(builder, t, in, out);
builder.append("\n");
builder.append("configuration " + t.getName() + "_" + testNumber + "_Cfg\n");
builder.append("@arduino_stdout \"Serial\"\n");
builder.append("@arduino_stdout_baudrate \"115200\"\n");
builder.append("{\n");
builder.append(" instance harness : Tester\n");
builder.append(" instance dump : TestDump" + lang.shortName + "\n");
builder.append(" instance test : " + t.getName() + "\n");
builder.append(" instance timer : Timer" + lang.shortName + "\n");
if (AnnotatedElementHelper.hasAnnotation(t, "test_timer_instance")) {
String timer_inst_name = AnnotatedElementHelper.annotation(t, "test_timer_instance").iterator().next();
builder.append(" instance " + timer_inst_name + " : Timer" + lang.shortName + "\n");
}
builder.append("\n");
builder.append(" connector harness.testEnd => dump.dumpEnd\n");
builder.append(" connector harness.timer => timer.timer\n");
builder.append(" connector test.harnessOut => dump.dump\n");
builder.append(" connector test.harnessIn => harness.test\n");
for (String an : AnnotatedElementHelper.annotation(t, "conf")) {
builder.append(" " + an + "\n");
}
builder.append("}\n");
generatedCode.put("_" + lang.longName + "/" + t.getName() + "_" + testNumber + ".thingml", builder);
}
}