/* +----------------------------------------------------------------------+ | 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