/*
+----------------------------------------------------------------------+
| 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);
}
}
}