/*
+----------------------------------------------------------------------+
| Class: CLauncherImpl |
| |
| Developper: Eric Gavaldo (eric.gavaldo@xqual.com) |
| Version: 1.6 |
+----------------------------------------------------------------------+
*/
package com.xqual.xlauncher.squish;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.xqual.xagent.launcher.CExecutionStep;
import com.xqual.xagent.launcher.CLauncher;
import com.xqual.xagent.launcher.CParamParsingException;
import com.xqual.xagent.launcher.CReturnStatus;
import com.xqual.xagent.launcher.runner.CRunner;
import com.xqual.xagent.launcher.runner.IRunner;
import com.xqual.xcommon.CAttribute;
import com.xqual.xcommon.CXmlDocumentFactory;
import com.xqual.xcommon.IConstantsResults;
import com.xqual.xcommon.utils.CFileUtils;
import com.xqual.xcommon.utils.CUtils;
/**
* The CLauncherImpl implementation of ILauncher for Squish.
* @author egavaldo
*/
public class CLauncherImpl extends CLauncher implements IConstantsResults {
// +==============================================================+
// | Attributes |
// +==============================================================+
static final String TRACE_HEADER = "{squish } ";
// parameters impacting executing at run time set by the test operator
private String testRootPath;
private String squishInstallPath;
private String squishBinPath;
private String squishLibPath;
private String squishServerArgs;
private String squishRunnerArgs;
private int squishSnoozeFactor;
private double fractionSquishSnoozeFactor;
private boolean killWebhook;
private boolean killServer;
private boolean killRunner;
private boolean killIExplore;
private boolean killIEUser;
private File squishServer;
private Hashtable environmentHashtable;
private static final String SQUISH_SERVER_EXE = CUtils.getExecutableName("squishserver");
private static final String SQUISH_RUNNER_EXE = CUtils.getExecutableName("squishrunner");
private static final String SQUISH_SERVER_PROCESS_NAME = "squishserver";
private static final String SQUISH_RUNNER_PROCESS_NAME = "squishrunner";
// only useful with Squish for the web
private static final String SQUISH_WEBHOOK_PROCESS_NAME = "webhook";
private static final String IEXPLORE_PROCESS_NAME = "iexplore";
private static final String IEUSER_PROCESS_NAME = "ieuser";
// +==============================================================+
// | Constructors |
// +==============================================================+
public CLauncherImpl() {
super(TRACE_HEADER);
}
// +==============================================================+
// | Methods |
// +==============================================================+
public CReturnStatus initialize(int sutId, String sutName, String sutVersion) {
setDefaultTestcaseMustBeCreated(true); // if there is not testcase, let the systems create a default one
// check the configuration sent by the manager
printConfiguration();
Vector executionSteps = new Vector();
try {
// retrieve the parameters we need
testRootPath = getStringParamValue("General", "Test root path"); // i.e. Y:/XStudio/src/test/squish
squishInstallPath = getStringParamValue("Squish", "Squish install path"); // i.e. Y:/Externals/froglogic/squish-3.4.5-qt46x-win32-msvc9
squishLibPath = getStringParamValue("Squish", "Squish libraries path"); // i.e. Y:/XStudio/src/test/squish/common
squishSnoozeFactor = getIntegerParamValue("Advanced", "Snooze factor");
squishServerArgs = getStringParamValue("Advanced", "Squish server opt. arguments"); // i.e. --port 4322
squishRunnerArgs = getStringParamValue("Advanced", "Squish runner opt. arguments"); // i.e. --port 4322
killRunner = getBooleanParamValue("Advanced", "Force kill squish squishrunner/_squishrunner processes after each testcase");
killServer = getBooleanParamValue("Advanced", "Force kill squish squishserver/_squishserver processes after each test");
killWebhook = getBooleanParamValue("Advanced", "Force kill squish webhook/_webhook processes after each testcase (Squish for web)");
killIExplore = getBooleanParamValue("Advanced", "Force kill iexplore process after each testcase (Squish for web)");
killIEUser = getBooleanParamValue("Advanced", "Force kill ieuser process after each testcase (Squish for web)");
squishBinPath = squishInstallPath + "/bin";
fractionSquishSnoozeFactor = (double)squishSnoozeFactor/100; // 30/100 = 0.3
} catch (CParamParsingException e) {
traceln(LOG_PRIORITY_SEVERE, "parsing error during initialization");
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception during initialize: " + e.getMessage()));
return new CReturnStatus(RESULT_FAILURE, executionSteps);
}
killSquishRunner("initialize()");
killSquishServer("initialize()");
CUtils.sleep(1000); // (PROBABLY NOT USEFUL!!!) leave the time to release all the resources
// set the script library path
environmentHashtable = new Hashtable();
environmentHashtable.put("SQUISH_SCRIPT_DIR", squishLibPath);
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "Initialize"));
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}
public CReturnStatus preRun(int testId, String testPath, String testName, Vector attributes, String additionalInfo) {
traceln(LOG_PRIORITY_INFO, "preRun testId=" + testId + " testPath=" + testPath + ":" + testName + "...");
Vector executionSteps = new Vector();
// test if the SquishServer is already running
// if not, start it in a separate thread (this will be normally executed only before the first test)
boolean serverAlreadyRunning = CUtils.isProcessRunning(SQUISH_SERVER_PROCESS_NAME);
if (!serverAlreadyRunning) {
traceln(LOG_PRIORITY_WARNING, "running squishserver...");
// run the Squish server in a separate thread (just running the CRunner with DO_NOT_WAIT_END_OF_EXECUTION is not enough)
squishServer = new File(squishBinPath + "/" + SQUISH_SERVER_EXE + (squishServerArgs.length()>0 ? " " + squishServerArgs : ""));
new Thread() {
public void run() {
CRunner squishServerRunner = new CRunner("Prerun", squishServer.toString());
squishServerRunner.requestAction(IRunner.START_PROCESS,IRunner.WAIT_END_OF_EXECUTION);
}
}.start();
CUtils.sleep(500); // (PROBABLY NOT USEFUL!!!) leave the server the time to initialize correctly
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "preRun: squishserver launched!"));
traceln(LOG_PRIORITY_INFO, "squishserver launched successfully");
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
} else {
traceln(LOG_PRIORITY_WARNING, "squish server already running");
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}
}
public CReturnStatus run(int testId, String testPath, String testName, int testcaseIndex, String testcaseName, String additionalInfo) {
traceln(LOG_PRIORITY_INFO, "run testId=" + testId + " testPath=" + testRootPath + testPath + "/tst_" + testName + " testcaseIndex=" + testcaseIndex + "...");
Vector executionSteps = new Vector();
File squishTraceFile = new File("squish_traces.txt");
if (squishTraceFile.exists())
squishTraceFile.delete();
try {
squishTraceFile.createNewFile();
} catch (IOException e) {
traceln(LOG_PRIORITY_SEVERE, "Could not create file \"squish_traces.txt\"...");
}
// run the Squish script
CRunner squishRunnerRunner = new CRunner("[" + testId + "] "+ testPath + ":" + testName + "." + testcaseIndex,
CFileUtils.quoteFilePath(squishBinPath + "/" + SQUISH_RUNNER_EXE) + " " +
(squishRunnerArgs.length()>0 ? squishRunnerArgs + " " : "") +
"--testsuite " + CFileUtils.quoteFilePath(testRootPath + "/" + testPath) + " " +
"--testcase tst_" + testName + " " +
"--snoozeFactor " + fractionSquishSnoozeFactor + " " +
"--reportgen xml,_tmp.xml",
environmentHashtable, null);
short result = squishRunnerRunner.requestAction(IRunner.START_PROCESS,
IRunner.WAIT_END_OF_EXECUTION,
squishTraceFile);
addAttachment(squishTraceFile);
if (result != RESULT_SUCCESS) {
traceln(LOG_PRIORITY_SEVERE, "SquishRunner execution failed!");
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "run: squishRunner execution failed!"));
cleanupAfterTest();
return new CReturnStatus(RESULT_FAILURE, executionSteps);
} else {
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "run: squishRunner execution succeeded!"));
}
File resultFile = new File(testRootPath + "/" + testPath + "/_tmp.xml");
if (!resultFile.exists()) {
traceln(LOG_PRIORITY_SEVERE, "Result file not found!");
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "run: result file not found!"));
cleanupAfterTest();
return new CReturnStatus(RESULT_FAILURE, executionSteps);
} else {
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "run: result file found"));
addAttachment(resultFile);
}
cleanupAfterTest();
return parseResultXml(resultFile, executionSteps);
}
public CReturnStatus postRun(int testId, String testPath, String testName) {
traceln(LOG_PRIORITY_INFO, "postRun testId=" + testId + " testPath=" + testPath + ":" + testName + "...");
if (killServer) {
killSquishServer("postRun()");
}
Vector executionSteps = new Vector();
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "postRun: succeeded"));
return new CReturnStatus(RESULT_SUCCESS, null);
}
public CReturnStatus terminate() {
killSquishRunner("terminate()");
killSquishServer("terminate()");
Vector executionSteps = new Vector();
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "Terminate"));
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}
// +--------------------------+
// ¦ Utilities ¦
// +--------------------------+
private CReturnStatus parseResultXml(File input, Vector executionSteps) {
// parse the result file to get the result and the execution steps
Document xmlDocument = CXmlDocumentFactory.createXMLDoc(input);
Node rootXmlNode = xmlDocument.getFirstChild();
int nbErrors;
int nbFails;
int nbSuccess;
try {
nbErrors = CXmlDocumentFactory.getNodeIntegerValueFromXPath(rootXmlNode, "summary/@errors");
nbFails = CXmlDocumentFactory.getNodeIntegerValueFromXPath(rootXmlNode, "summary/@fails") + CXmlDocumentFactory.getNodeIntegerValueFromXPath(rootXmlNode, "summary/@fatals");
nbSuccess = CXmlDocumentFactory.getNodeIntegerValueFromXPath(rootXmlNode, "summary/@passes");
} catch (NumberFormatException e) {
traceln(LOG_PRIORITY_SEVERE, "result file parsing failed !");
return new CReturnStatus(RESULT_FAILURE, executionSteps);
}
short result = RESULT_FAILURE;
if (nbFails == 0 && nbErrors == 0 && nbSuccess > 0) {
result = RESULT_SUCCESS;
} else if (nbFails == 0 && nbErrors == 0 && nbSuccess == 0) {
result = RESULT_NOT_EXECUTED;
}
NodeList resultNodeList = CXmlDocumentFactory.getNodeObjListFromXPath(rootXmlNode, "testresult");
for (int j=0; j