/* +----------------------------------------------------------------------+ | Class: CLauncher | | | | Developper: Eric Gavaldo (eric.gavaldo@xqual.com) | | Version: 1.3 | +----------------------------------------------------------------------+ */ package com.xqual.xlauncher.beanshell; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.Vector; 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.IConstantsResults; import com.xqual.xcommon.utils.CTextUtils; import com.xqual.xcommon.utils.CUtils; import com.xqual.xlauncher.CClientDownloader; import com.xqual.xlauncher.CTimeoutListener; /** * The CLauncherImpl implementation of ILauncher for beanshell. * @author egavaldo */ public class CLauncherImpl extends CLauncher implements IConstantsResults { // +==============================================================+ // | Attributes | // +==============================================================+ static final String TRACE_HEADER = "{beanshell } "; private static final String PROCESS_NAME = "sut_process_name"; private static final String BEANSHELL_INTERPRETER_CLASS = "bsh.Interpreter"; private CClientDownloader downloader; // parameters impacting executing at run time set by the test operator private String testRootPath; private String beanshellInstallPath; private String localInstallersFolder; private String downloadServerUrl; private String installerTemplateName; //private String installerMajorVersion; private String beanshellInterpreter; private File workingDir; // +==============================================================+ // | Constructors | // +==============================================================+ public CLauncherImpl() { super(TRACE_HEADER); } // +==============================================================+ // | Methods | // +==============================================================+ @Override public CReturnStatus initialize(int sutId, String sutName, String sutVersion) { short result; setSutDetails(sutId, sutName, 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"); // C:/beanshell/client beanshellInstallPath = getStringParamValue("Beanshell", "Beanshell install path"); // C:/tools/beanshell-2.0b4/bsh-2.0b4.jar localInstallersFolder = getStringParamValue("Installers", "Folder containing the installers"); // C:/products downloadServerUrl = getStringParamValue("Installers", "Download server URL"); // //NAS/Builds installerTemplateName = getStringParamValue("Installers", "Installer template name"); // sut-setup-%version%.exe //installerMajorVersion = getStringParamValue("Installers", "Major version"); // 0.9.4 (This is used only by the downloader when sutVersion="...latest..." beanshellInterpreter = "java -cp " + beanshellInstallPath + " " + BEANSHELL_INTERPRETER_CLASS; // java -cp T:\tools\beanshell-2.0b4\bsh-2.0b4.jar bsh.Interpreter } 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); } // CClientDownloader will download the setup program from a shared folder and will send some email notifications in case of failure or success // There are 2 simpler alternatives: // - CHttpDownloader // - CSharedFolderDownloader downloader = new CClientDownloader(this); // kill the potentially already running clients CUtils.killIfNeeded(PROCESS_NAME); // download the setup program result = downloader.downloadClient(downloadServerUrl, installerTemplateName, "" /*installerMajorVersion*/, sutVersion, localInstallersFolder); if (result != RESULT_SUCCESS) { executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Download of the client failed")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } else { executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Download of the client succeeded")); } // install the setup program result = downloader.installSilentlyClient(); if (result != RESULT_SUCCESS) { executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Silent install of the client failed")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } else { executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Silent install of the client succeeded")); } CUtils.sleep(5000); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override 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(); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override public CReturnStatus run(int testId, String testPath, String testName, int testcaseIndex, String testcaseName, String additionalInfo) { String scriptParentFolderPath = testRootPath + "/" + testPath; String scriptFilePath = scriptParentFolderPath + "/" + testName + ".bsh"; workingDir = new File(scriptParentFolderPath); // Delete the flag file if necessary File flagFile = new File(workingDir + "/test_completed.txt"); if (flagFile.exists()) { traceln(LOG_PRIORITY_INFO, "deleting flag file..."); boolean deleteResult = flagFile.delete(); traceln(LOG_PRIORITY_INFO, "deleting flag file: " + (deleteResult ? "success" : "failure")); CUtils.sleep(100); } // Delete the log file if necessary File logFile = new File(workingDir + "/log.txt"); if (logFile.exists()) { traceln(LOG_PRIORITY_INFO, "deleting log file..."); boolean deleteResult = logFile.delete(); traceln(LOG_PRIORITY_INFO, "deleting log file: " + (deleteResult ? "success" : "failure")); CUtils.sleep(100); } CUtils.killIfNeeded(PROCESS_NAME); CUtils.sleep(4000); // +-----------------------------------------------+ // | Interpret the script | // +-----------------------------------------------+ traceln(LOG_PRIORITY_INFO, "run testId=" + testId + " testPath=" + testRootPath + "/" + testPath + "/" + testName + " testcaseIndex=" + testcaseIndex + "..."); Vector executionSteps = new Vector(); CRunner beanshellRunner = new CRunner("[" + testId + "] "+ testPath + ":" + testName + "." + testcaseIndex, beanshellInterpreter.toString() + " " + scriptFilePath + " " + testcaseIndex + " " + getSutVersion(), workingDir); beanshellRunner.requestAction(IRunner.START_PROCESS, IRunner.DO_NOT_WAIT_END_OF_EXECUTION); // to check if the execution completed correctly, we need to check if the "test_completed.txt" has been created // this timeout should never expire since there is already a timeout in the tests themself set to a lower value than this one // when the test's timeout expires, the test_completed.txt file is created short resultTimeout = CTimeoutListener.waitForFile(flagFile, 180); if (resultTimeout != RESULT_SUCCESS) { CUtils.killIfNeeded(PROCESS_NAME); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "timeout of 3 minutes to execute the test case expired")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } // file exists, remove it to complete asyncronous handshake if (!flagFile.delete()) executionSteps.add(new CExecutionStep(RESULT_UNKNOWN, "Failed to cleanup test_completed.txt")); // +----------------------------------------------------------+ // | Analyse the log and attach screenshots if there are some | // +----------------------------------------------------------+ CReturnStatus testcaseResult = parseResultFile(executionSteps); if (testcaseResult.getResult() == RESULT_FAILURE){ File scriptDir = new File(scriptParentFolderPath + "/"); File[] dir = scriptDir.listFiles(); for (int i=0; i executionSteps = new Vector(); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override public CReturnStatus terminate() { downloader = null; workingDir = null; return new CReturnStatus(RESULT_SUCCESS); } // +--------------------------+ // ¦ Utilities ¦ // +--------------------------+ public short installSilentlyClient(File nsisSetupFile) { // if this is not a NSIS setup program, this command line will probably be different CRunner install = new CRunner("install silently the client", nsisSetupFile.toString() + " /S"); short result = install.requestAction(IRunner.START_PROCESS, IRunner.WAIT_END_OF_EXECUTION); if (result != RESULT_SUCCESS) { System.out.println("silent install failed!"); return RESULT_FAILURE; } else { return RESULT_SUCCESS; } } private CReturnStatus parseResultFile(Vector executionSteps) { // parse the result file to get the result and the execution steps File logFile = new File(workingDir + "/log.txt"); if (!logFile.exists()) { traceln(LOG_PRIORITY_SEVERE, "Result file not found!"); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "run: result file not found!")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } else { executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "run: result file found")); } String line, timeStamp, message; int labelIndex = 0; boolean errorDetected = false; try { FileInputStream fileInputStream = new FileInputStream(logFile); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream)); while ((line = bufferedReader.readLine()) != null) { line = line.trim(); System.out.println(">" + line); if ((labelIndex = line.indexOf("[Success]")) > 0) { timeStamp = line.substring(0, labelIndex-2); message = CTextUtils.left(line.substring(labelIndex + 10, line.length()), 250); // [Success] length = 9 executionSteps.add(new CExecutionStep(timeStamp, RESULT_SUCCESS, message)); } else if ((labelIndex = line.indexOf("[Failure]")) > 0) { timeStamp = line.substring(0, labelIndex-2); message = CTextUtils.left(line.substring(labelIndex + 10, line.length()), 250); executionSteps.add(new CExecutionStep(timeStamp, RESULT_FAILURE, message)); errorDetected = true; } else if ((labelIndex = line.indexOf("[Log]")) > 0) { timeStamp = line.substring(0, labelIndex-2); message = CTextUtils.left(line.substring(labelIndex + 6, line.length()), 250); executionSteps.add(new CExecutionStep(timeStamp, RESULT_UNKNOWN, message)); } else { traceln(LOG_PRIORITY_SEVERE, "unknown tag!"); } } bufferedReader.close(); fileInputStream.close(); } catch (Exception e) { traceln(LOG_PRIORITY_SEVERE, "exception whle parsing the result file: " + e); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception whle parsing the result file: " + e)); errorDetected = true; } if (errorDetected) { return new CReturnStatus(RESULT_FAILURE, executionSteps); } else { return new CReturnStatus(RESULT_SUCCESS, executionSteps); } } }