/**
* 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.testjar;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.thingml.testjar.lang.TargetedLanguage;
import org.thingml.testjar.lang.lArduino;
import org.thingml.testjar.lang.lJava;
import org.thingml.testjar.lang.lJavaScript;
import org.thingml.testjar.lang.lPosix;
import org.thingml.testjar.lang.lPosixMT;
import org.thingml.testjar.lang.lSintefboard;
/**
*
* @author sintef
*/
public class TestJar {
public static void main(String[] args) throws ExecutionException {
//possible command lines to start the process
//java -cp .:target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar org.thingml.testjar.TestJar
//java -cp .:target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar org.thingml.testjar.TestJar <compiler_jar_path> <plugin_jar_path> <config_file>
final File workingDir = new File(System.getProperty("user.dir"));
File configFile = new File(workingDir, "config.properties");
File tmpDir = new File(workingDir, "tmp");
File compilerJar = new File(workingDir, "../compilers/registry/target/compilers.registry-1.0.0-SNAPSHOT-jar-with-dependencies.jar");
File pluginFile = new File(workingDir, "../compilers/official-network-plugins/target/official-network-plugins-1.0.0-SNAPSHOT.jar");
if(args.length == 3) {
compilerJar = new File(args[0]);
pluginFile = new File(args[1]);
configFile = new File(args[2]);
}
final File testCfgDir = new File(tmpDir, "thingml");
final File codeDir = new File(tmpDir, "genCode");
final File logDir = new File(tmpDir, "log");
tmpDir.delete();
tmpDir = new File(workingDir, "tmp");
final File testFolder = new File(workingDir.getPath() + "/src/main/resources/tests");
//final File testFolder = new File(TestJar.class.getClassLoader().getResource("tests").getFile());
String testPattern = "test(.+)\\.thingml";
Set<Command> tasks = new HashSet<>();
List<Future<String>> results = new ArrayList<Future<String>>();
System.out.println("****************************************");
System.out.println("* Test Begin *");
System.out.println("****************************************");
System.out.println("Working Directory = " + workingDir);
System.out.println("Tmp Directory = " + tmpDir);
System.out.println("Compiler = " + compilerJar);
System.out.println("Plugin = " + pluginFile);
System.out.println("Config = " + configFile);
System.out.println("");
System.out.println("****************************************");
System.out.println("* Properties Reading *");
System.out.println("****************************************");
System.out.println("");
Properties prop = new Properties();
InputStream input = null;
String languageList = null, useBlackList = null, testList = null, categoryUseBlackList = null, categoryList = null, webLink = null, myIP = null, myHTTPServerPort = null;
String headerFooter = null;
try {
input = new FileInputStream(configFile);
// load a properties file
prop.load(input);
// get the property value and print it out
languageList = prop.getProperty("languageList");
useBlackList = prop.getProperty("useBlackList");
testList = prop.getProperty("testList");
categoryUseBlackList = prop.getProperty("categoryUseBlackList");
categoryList = prop.getProperty("categoryList");
webLink = prop.getProperty("webLink");
myIP = prop.getProperty("myIP");
myHTTPServerPort = prop.getProperty("myHTTPServerPort");
headerFooter = prop.getProperty("headerFooter");
System.out.println("languageList:" + languageList);
System.out.println("useBlackList:" + useBlackList);
System.out.println("testList:" + testList);
} catch (IOException ex) {
ex.printStackTrace();
}
boolean header_footer = true;
if (headerFooter != null)
header_footer = (headerFooter.compareToIgnoreCase("True") == 0) ? true : false;
boolean localLink = true;
if(webLink != null)
localLink = !((webLink.compareToIgnoreCase("True") == 0) ? true : false);
Set<String> tl = new HashSet<>();
if(testList != null) {
for(String tstr : testList.split(",")) {
tl.add(tstr.trim());
}
}
Set<String> dl = new HashSet<>();
if(categoryList != null) {
for(String tstr : categoryList.split(",")) {
dl.add(tstr.trim());
}
}
boolean cbl = false, tbl = false;
if(categoryUseBlackList != null) {
if (categoryUseBlackList.compareToIgnoreCase("true") == 0) cbl = true;
else if (categoryUseBlackList.compareToIgnoreCase("false") != 0) dl = null;
} else {
dl = null;
}
if(useBlackList != null) {
if (useBlackList.compareToIgnoreCase("true") == 0) tbl = true;
else if (useBlackList.compareToIgnoreCase("false") != 0) tl = null;
} else {
tl = null;
}
//Test Sources Selection
Set<File> testFiles;
testFiles = TestHelper.listTestFiles(testFolder, testPattern, dl, cbl, tl, tbl);
/*
if(useBlackList != null) {
if(useBlackList.compareToIgnoreCase("false") == 0) {
testFiles = TestHelper.whiteListFiles(testFolder, tl);
} else if (useBlackList.compareToIgnoreCase("true") == 0) {
testFiles = TestHelper.blackListFiles(testFolder, tl);
} else {
testFiles = TestHelper.listTestFiles(testFolder, testPattern);
}
} else {
testFiles = TestHelper.listTestFiles(testFolder, testPattern);
}*/
//Language Selection
List<TargetedLanguage> langs = new LinkedList<>();
int spareThreads = 0;
if(languageList != null) {
for(String lstr :languageList.split(",")) {
if(lstr.trim().compareTo("arduino") == 0) {
langs.add(new lArduino());
}
if(lstr.trim().compareTo("posix") == 0) {
langs.add(new lPosix());
}
if(lstr.trim().compareTo("java") == 0) {
langs.add(new lJava());
spareThreads = 2;//FIXME: value to be taken from lJava directly
}
if(lstr.trim().compareTo("nodejs") == 0) {
langs.add(new lJavaScript());
}
if(lstr.trim().compareTo("sintefboard") == 0) {
langs.add(new lSintefboard());
}
if(lstr.trim().compareTo("posixmt") == 0) {
langs.add(new lPosixMT());
}
}
} else {
langs.add(new lPosix());
langs.add(new lJava());
langs.add(new lJavaScript());
langs.add(new lArduino());
langs.add(new lSintefboard());
langs.add(new lPosixMT());
spareThreads = 2;//FIXME: see above
}
//Environement setup
int poolSize = Runtime.getRuntime().availableProcessors() - spareThreads;
if(poolSize <= 0) {
poolSize = 1;
}
ExecutorService executor = Executors.newFixedThreadPool(poolSize);
Set<SimpleGeneratedTest> testCases = new HashSet<>();
Map<String,Map<String,List<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>>> testBench = new HashMap<>();
testCfgDir.mkdir();
codeDir.mkdir();
logDir.mkdir();
for(TargetedLanguage lang : langs) {
File lCfg = new File(testCfgDir, "_" + lang.compilerID);
lCfg.mkdir();
File lcode = new File(codeDir, "_" + lang.compilerID);
lcode.mkdir();
File llog = new File(logDir, "_" + lang.compilerID);
llog.mkdir();
}
System.out.println("Test Files:");
for(File f : testFiles) {
System.out.println(f.getName());
for(TargetedLanguage lang : langs) {
SimpleGeneratedTest tc = new SimpleGeneratedTest(f, compilerJar, lang, codeDir, testCfgDir, logDir, pluginFile);
testCases.add(tc);
}
Map<String,List<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>> cat;
if(testBench.containsKey(f.getParentFile().getName())) {
cat = testBench.get(f.getParentFile().getName());
} else {
cat = new HashMap<>();
testBench.put(f.getParentFile().getName(), cat);
}
cat.put(f.getName(), new LinkedList<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>());
}
System.out.println("");
System.out.println("****************************************");
System.out.println("* ThingML Generation *");
System.out.println("****************************************");
for(SimpleGeneratedTest tc : testCases) {
Command cmd = tc.lang.generateThingML(tc);
cmd.print();
tasks.add(cmd);
}
try {
results = executor.invokeAll(tasks);
} catch (InterruptedException ex) {
Logger.getLogger(TestJar.class.getName()).log(Level.SEVERE, null, ex);
}
executor.shutdown();
tasks.clear();
System.out.println("Done.");
// Concrete test case collection
List<TestCase> testCfg = new LinkedList<>();
for(SimpleGeneratedTest tc : testCases) {
List<SimpleGeneratedTest> children = tc.generateChildren();
testCfg.addAll(children);
for(TargetedLanguage lang : langs) {
if(tc.lang == lang) {
testBench.get(tc.category).get(tc.srcTestCase.getName()).add(new HashMap.SimpleEntry<>(tc.lang, children));
}
}
}
System.out.println("");
System.out.println("****************************************");
System.out.println("* ThingML Compilation *");
System.out.println("****************************************");
executor = Executors.newFixedThreadPool(poolSize);
testRun(testCfg, executor);
System.out.println("");
System.out.println("****************************************");
System.out.println("* Generated Code Compilation *");
System.out.println("****************************************");
executor = Executors.newFixedThreadPool(poolSize);
testRun(testCfg, executor);
System.out.println("");
System.out.println("****************************************");
System.out.println("* Generated Code Execution *");
System.out.println("****************************************");
executor = Executors.newFixedThreadPool(poolSize);
testRun(testCfg, executor);
System.out.println("");
System.out.println("****************************************");
System.out.println("* Test Results *");
System.out.println("****************************************");
System.out.println("");
writeResultsFile(workingDir, tmpDir, new File(tmpDir, "results.html"), testBench, langs, testFolder, localLink, myIP, myHTTPServerPort, header_footer);
if(!header_footer)
writeFooterHeader(new File(tmpDir, "header.html"), new File(tmpDir, "footer.html"), langs);
System.out.println("");
System.out.println("More details in " + tmpDir.getAbsolutePath() + "/results.html");
System.out.println("");
}
public static void testRun(List<TestCase> tests, ExecutorService executor) {
System.out.println("");
System.out.println("Test Cases:");
Set<Command> tasks = new HashSet<>();
List<Future<String>> results = new ArrayList<Future<String>>();
for(TestCase tc : tests) {
if(tc.isLastStepASuccess) {
Command cmd = tc.ongoingCmd;
cmd.print();
tasks.add(cmd);
}
}
try {
results = executor.invokeAll(tasks);
} catch (InterruptedException ex) {
Logger.getLogger(TestJar.class.getName()).log(Level.SEVERE, null, ex);
}
executor.shutdown();
for(TestCase tc : tests) {
tc.collectResults();
}
System.out.println("Done.");
}
public static void writeFooterHeader(File header, File footer, List<TargetedLanguage> langs) {
StringBuilder headerres = new StringBuilder();
headerres.append(TestHelper.writeHeaderResultsFile(langs));
StringBuilder footerres = new StringBuilder();
footerres.append(TestHelper.writeFooterResultsFile(langs));
if(header.exists())
header.delete();
if(footer.exists())
footer.delete();
try {
PrintWriter h = new PrintWriter(header);
h.print(headerres.toString());
h.close();
PrintWriter f = new PrintWriter(footer);
f.print(footerres.toString());
f.close();
} catch (Exception ex) {
System.err.println("Problem writing log");
ex.printStackTrace();
}
}
public static void writeResultsFile(File workingDir, File tmpDir, File results, Map<String,Map<String,List<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>>> tests,
List<TargetedLanguage> langs, File srcDir, boolean localLink, String myIP, String myHTTPServerPort, boolean header_footer) {
StringBuilder res = new StringBuilder();
if(header_footer)
res.append(TestHelper.writeHeaderResultsFile(langs));
for(Map.Entry<String, Map<String,List<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>>> category : tests.entrySet()) {
for(Map.Entry<String,List<Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>>>> line : category.getValue().entrySet()) {
StringBuilder lineB = new StringBuilder();
boolean lineSuccess = true;
res.append(" <tr>\n");
res.append(" <td class=\"category\">" + category.getKey() + "</td>\n");
res.append(" <td class=\"testcase ");
if(localLink) {
String local_path = TestHelper.stripFirstDirFromPath(srcDir.getPath(), workingDir.getPath()).replace("^/+", "");
lineB.append(" <a href=\"" + local_path + "/" + category.getKey() + "/" + line.getKey() + "\" >" + line.getKey() + "</a>\n");
} else {
lineB.append(" <a href=\"http://" + myIP +":" + myHTTPServerPort +"" + TestHelper.stripFirstDirFromPath(srcDir.getPath(), "/thingml") + "/" + category.getKey() + "/" + line.getKey() + "\" target=\"test-case-focus\"> " + line.getKey() + "</a>\n");
}
lineB.append(" </td>\n");
for(TargetedLanguage lang : langs) {
for(Map.Entry<TargetedLanguage,List<SimpleGeneratedTest>> cell : line.getValue()) {
if(cell.getKey() == lang) {
StringBuilder cellB = new StringBuilder();
boolean cellSuccess = !cell.getValue().isEmpty();
lineB.append(" <td class=\"" + cell.getKey().compilerID + " ");
cellB.append(" <table>\n");
String cellRes = "";
for(SimpleGeneratedTest tc : cell.getValue()) {
cellB.append(" <tr>\n");
cellB.append(" <td class=\"" );
if(tc.isLastStepASuccess) {
cellB.append("green");
cellRes = "*";
} else {
cellRes = "!";
cellSuccess = false;
cellB.append("red");
}
cellB.append("\">\n");
if(localLink || (myIP == null) || (myHTTPServerPort == null)) {
cellB.append(" <a href=\"" + TestHelper.stripFirstDirFromPath(tc.genCfg.getPath(), tmpDir.getPath()).replace("^/+", "") + "\">src</a> | \n");
cellB.append(" <a href=\"" + TestHelper.stripFirstDirFromPath(tc.logFile.getPath(), tmpDir.getPath()).replace("^/+", "") + "\">log</a>\n");
} else {
cellB.append(" <a href=http://" + myIP +":" + myHTTPServerPort +"" + TestHelper.stripFirstDirFromPath(tc.genCfg.getPath(), "/thingml") + " target=\"test-case-focus\">src</a> | \n");
cellB.append(" <a href=http://" + myIP +":" + myHTTPServerPort +"" + TestHelper.stripFirstDirFromPath(tc.logFile.getPath(), "/thingml") + " target=\"test-case-focus\">log</a>\n");
}
cellB.append(" </td>\n" );
cellB.append(" </tr>\n");
}
cellB.append(" </table>\n");
if(cellSuccess) {
lineB.append("green");
} else {
lineB.append("red");
cell.getKey().failedTest.add(line.getKey());
}
cell.getKey().testNb++;
lineB.append("\">\n");
lineB.append(cellB);
lineB.append(" </td>\n");
lineSuccess &= cellSuccess;
}
}
}
if(lineSuccess) {
res.append("green");
} else {
res.append("red");
}
res.append("\">\n");
res.append(lineB);
res.append(" </tr>\n");
}
}
if(header_footer)
res.append(TestHelper.writeFooterResultsFile(langs));
for(TargetedLanguage lang : langs) {
System.out.println("[" + lang.compilerID + "] " + lang.failedTest.size() + " failures out of " + lang.testNb);
System.out.println(" Failed tests:");
for(String fail : lang.failedTest) {
System.out.println(" ! " + fail);
}
System.out.println("");
}
if (!results.getParentFile().exists())
results.getParentFile().mkdirs();
try {
PrintWriter w = new PrintWriter(results);
w.print(res.toString());
w.close();
} catch (Exception ex) {
System.err.println("Problem writing log");
ex.printStackTrace();
}
}
}