/*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.runner.remote;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import jsystem.framework.FrameworkOptions;
import jsystem.framework.JSystemProperties;
import jsystem.framework.RunnerStatePersistencyManager;
import jsystem.framework.analyzer.AnalyzerException;
import jsystem.framework.fixture.Fixture;
import jsystem.framework.fixture.FixtureListener;
import jsystem.framework.fixture.FixtureManager;
import jsystem.framework.report.DefaultReporterImpl;
import jsystem.framework.report.ExtendTestListener;
import jsystem.framework.report.ListenerstManager;
import jsystem.framework.report.TestInfo;
import jsystem.framework.scenario.JTestContainer;
import jsystem.framework.scenario.RunningProperties;
import jsystem.framework.scenario.Scenario;
import jsystem.framework.scenario.flow_control.AntForLoop;
import jsystem.framework.sut.SutListener;
import jsystem.framework.system.SystemManagerImpl;
import jsystem.runner.SOCheckStatus;
import jsystem.utils.StringUtils;
import junit.framework.AssertionFailedError;
import junit.framework.NamedTest;
import junit.framework.Test;
import junit.framework.TestResult;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
/**
* A RemoteTestRunner run a scenario and report result via socket using
* ObjectInputStream. for more information regarding the protocol see the
* RemoteMessage enum. To execute the RemoteTestRunner the main method is called
* with the host and port of the runner vm.
*/
public class RemoteTestRunner extends DefaultReporterImpl implements ExtendTestListener, FixtureListener, SutListener, BuildListener {
static Logger log = Logger.getLogger(RemoteTestRunner.class.getName());
boolean silent = false;
public enum RemoteMessage {
/**
* Send flush events to all the reports
*/
M_FLUSH_REPORTER,
/**
* Send init events to all the reports
*/
M_INIT_REPORTER,
/**
* Set the reporter to be silent (<--)
*/
M_SET_SILENT,
/**
* Set the reporter to be silent (<--)
*/
M_SET_TIME_STAMP,
/**
* Reporting step (<--)
*/
M_STEP,
/**
* Regular report (<--)
*/
M_REPORT,
/**
* Set the test report data (<--)
*/
M_SET_DATA,
/**
* Launch start report call (<--)
*/
M_START_REPORT,
/**
* Launch end report call (<--)
*/
M_END_REPORT,
/**
* Save file report call (<--)
*/
M_SAVE_FILE,
/**
* Set fail reports to pass (<--)
*/
M_SET_FAIL_TO_PASS,
/**
* Set fail report to warning (<--)
*/
M_SET_FAIL_TO_WARNING,
/**
* Send on test start and received from the runner for sych (<-->)
*/
M_TEST_START,
/**
* Send to runner to notify on test end (<--)
*/
M_TEST_END,
/**
* Send to the runner on failure (<--)
*/
M_ADD_FAILURE,
/**
* Send to the runner on error (<--)
*/
M_ADD_ERROR,
/**
* Send to the runner on warning (<--)
*/
M_ADD_WARNING,
/**
* Notify the runner on start fixture (<--)
*/
M_FIXTURE_START,
/**
* Notify the runner on end fixture (<--)
*/
M_FIXTURE_END,
/**
* Notify the runner on about to change fixture (<--)
*/
M_FIXTURE_ABOUT,
/**
* Notify the runner on fixture changed (<--)
*/
M_FIXTURE_CHANGED,
/**
* Received when the remote test should exit (<-->)
*/
M_EXIT,
/**
* Signal the runner when operation failed (<--)
*/
M_OPERATION_FAIL,
/**
* Signal the runner that the SUT changed (<--)
*/
M_SUT_CHANGED,
/**
* Interrupt the current execution (-->)
*/
M_INTERRUPT,
/**
* Pause the current execution (-->)
*/
M_PAUSE,
/**
* Stop the current execution (-->)
*/
M_GRACEFUL_STOP,
/**
* Resume the current execution (-->)
*/
M_RESUME,
/**
* Approved the pause operation
*/
M_PAUSED,
/**
* Change the report level
*/
M_LEVEL,
/**
* end current report level
*/
M_STOP_LEVEL,
/**
* end current report level
*/
M_CLOSE_ALL_LEVELS,
/**
* /** Build start, send the ant notification to the remote side (<--)
*/
M_BUILD_START,
/**
* Build finish
*/
M_BUILD_FINISH,
/**
* Target start, send the ant notification to the remote side (<--)
*/
M_TARGET_START,
/**
* Target finish
*/
M_TARGET_FINISH,
/**
* Task start, send the ant notification to the remote side (<--)
*/
M_TASK_START,
/**
* Task finished
*/
M_TASK_FINISH,
/**
* Message logged,
*/
M_ANT_MESSAGE_LOGED,
/**
* Synchronization request
*/
M_SYNCH,
/**
* Synchronization response
*/
M_SYNCHED,
/**
* Property message consisted of key and value
*/
M_PROPERTY,
/**
* Indicate a show confirm dialog request or dialog confirmed
*/
M_SHOW_CONFIRM_DIALOG,
/**
* Check system object message
*/
M_CHECK_SYSTEM_OBJECT,
/**
* save runner engine state
* @see RunnerStatePersistencyManager
*/
M_SAVE_STATE,
/**
* Property message consisted of key and value
*/
M_CONTAINER_PROPERTY,
}
/**
* The current test result
*/
private TestResult fTestResult;
/**
* The client socket.
*/
private Socket fClientSocket;
/**
* Print writer for sending messages
*/
private ObjectOutputStream fWriter;
/**
* Reader for incoming messages
*/
private ObjectInputStream fReader;
/**
* Host to connect to, default is the localhost
*/
private String fHost = ""; //$NON-NLS-1$
/**
* Port to connect to.
*/
private int fPort = -1;
/**
* Port to connect for reporting.
*/
// private int rPort= -1;
/**
* Is the debug mode enabled?
*/
private boolean fDebugMode = false;
/**
* Keep the test run server alive after a test run has finished. This allows
* to rerun tests.
*/
private boolean fKeepAlive = false;
/**
* Thread reading from the socket
*/
private ReaderThread fReaderThread;
/**
* The scenario beeing executed
*/
Scenario scenario = null;
/**
* The tests indexes to be execute
*/
int[] testRunIndexes;
/**
* block all messages
*/
private boolean blockAllMessages = false;
private boolean interrupted = false;
/**
* Set the true if the request for a message was confirmed
*/
private volatile boolean messageConfirmed = false;
/*
* Hold the dialog return value
*/
private int messageConfermedReturn = -1;
/**
* if set to true will print all the messages send and received
*/
private boolean debugMessages = false;
/**
* Set to true when the connected to the remote runner
*/
private boolean connected = false;
/**
* Set to true when the remote VM is synchronized
*/
private boolean synchronize = false;
/**
* Singletone object
*/
private static RemoteTestRunner rtrunner = null;
/**
* contains the message that RemoteExecutor reply. we use it only with
* M_PUBLISH message it contains the data on the scenario that run like -
* run index,number of tests, user and etc.
*/
private Message sendEmailRunDetails = null;
public static RemoteTestRunner getInstance() {
return rtrunner;
}
/**
* Private constructor to init the object use static method getInstance
*
* @throws Exception
*
*/
public RemoteTestRunner() throws Exception {
/*
* Extract the runner host and port from the system environment
*/
String rp = System.getenv(RunningProperties.RUNNER_PORT);
String rh = System.getenv(RunningProperties.RUNNER_HOST);
if (rp == null || rh == null) { // if the environment is not set
JSystemProperties.getInstance(true).setJsystemRunner(false);
// (execute directly from ant)
launchReporter();
} else {
JSystemProperties.getInstance(false).setJsystemRunner(false);
init(new String[] { "-port", rp, "-host", rh });
connect();
}
rtrunner = this;
Runtime.getRuntime().addShutdownHook(new ShutdownThread(fWriter));
}
public void launchReporter() throws Exception {
// throw new Exception("Launch reporter mode not supported yet");
}
/**
* Reader thread that processes messages from the client.
*/
private class ReaderThread extends Thread {
public ReaderThread() {
super("ReaderThread"); //$NON-NLS-1$
}
public void run() {
try {
while (true) {
Message m = (Message) fReader.readObject();
if (debugMessages) {
System.err.println("Rcv: R-->T " + m.getType().name());
System.err.flush();
}
if (m == null) {
processExit();
return;
}
switch (m.getType()) {
case M_EXIT:
log.fine("got exit message.");
processExit();
log.fine("exit process ended.");
break;
case M_INTERRUPT:
log.fine("got interrupt message.");
interrupted = true;
processExit();
log.fine("exit process after interrupt ended.");
break;
case M_PAUSE:
log.fine("got pause message.");
((ListenerstManager) ListenerstManager.getInstance()).pause();
break;
case M_GRACEFUL_STOP:
log.fine("got graceful stop message.");
((ListenerstManager) ListenerstManager.getInstance()).gracefulStop();
break;
case M_RESUME:
log.fine("got resume message.");
((ListenerstManager) ListenerstManager.getInstance()).resume();
break;
case M_SYNCHED:
synchronize = true;
log.fine("Got M_SYNCHED message");
synchronized (fWriter) {
fWriter.notifyAll();
}
log.fine("M_SYNCHED message after notify all");
break;
case M_SYNCH:
Message mm = new Message();
mm.setType(RemoteMessage.M_SYNCHED);
sendMessage(mm);
log.fine("Send M_SYNCHED message");
break;
case M_SHOW_CONFIRM_DIALOG:
/*
* The test get the return value of the message and
* notify to the wait method
*/
messageConfermedReturn = Integer.parseInt(m.getField(0));
synchronized (fWriter) {
messageConfirmed = true;
fWriter.notifyAll();
}
break;
default:
System.err.println("Unkown message type: " + m.getType());
}
}
} catch (Exception e) {
interrupted = true;
processExit();
RemoteTestRunner.this.stop();
}
}
}
/**
* Parse command line arguments. Hook for subclasses to process additional
* arguments.
*/
protected void init(String[] args) {
defaultInit(args);
}
/**
* The class loader to be used for loading tests. Subclasses may override to
* use another class loader.
*/
protected ClassLoader getClassLoader() {
return getClass().getClassLoader();
}
/**
* Process the default arguments.
*/
protected final void defaultInit(String[] args) {
for (int i = 0; i < args.length; i++) {
if (args[i].toLowerCase().equals("-port")) { //$NON-NLS-1$
fPort = Integer.parseInt(args[i + 1]);
i++;
} else if (args[i].toLowerCase().equals("-host")) { //$NON-NLS-1$
fHost = args[i + 1];
i++;
} else if (args[i].toLowerCase().equals("-keepalive")) { //$NON-NLS-1$
fKeepAlive = true;
} else if (args[i].toLowerCase().equals("-debugging") || args[i].toLowerCase().equals("-debug")) { //$NON-NLS-1$ //$NON-NLS-2$
fDebugMode = true;
}
}
if (fPort == -1)
throw new IllegalArgumentException("The -port option wasn't found"); //$NON-NLS-1$
if (fDebugMode)
System.out.println("keepalive " + fKeepAlive); //$NON-NLS-1$
}
protected void runFailed(String message, Throwable exception) {
System.err.println(message);
if (exception != null)
exception.printStackTrace();
}
/*
* @see TestListener#addError(Test, Throwable)
*/
public final void addError(Test test, Throwable throwable) {
Message m = new Message();
m.setType(RemoteMessage.M_ADD_ERROR);
m.addField(getTestFullId(test));
m.addField(throwable.getMessage());
m.addField(StringUtils.getStackTrace(throwable));
sendMessage(m);
}
/*
* @see TestListener#addFailure(Test, AssertionFailedError)
*/
public final void addFailure(Test test, AssertionFailedError assertionFailedError) {
Message m = new Message();
m.setType(RemoteMessage.M_ADD_FAILURE);
m.addField(getTestFullId(test));
m.addField(assertionFailedError.getMessage());
m.addField(StringUtils.getStackTrace(assertionFailedError));
m.addField(Boolean.toString(assertionFailedError instanceof AnalyzerException));
sendMessage(m);
}
/*
* @see TestListener#endTest(Test)
*/
public void endTest(Test test) {
Message m = new Message();
m.setType(RemoteMessage.M_TEST_END);
m.addField(getTestFullId(test));
sendMessage(m);
}
public void initReporters(){
Message m = new Message();
m.setType(RemoteMessage.M_INIT_REPORTER);
sendMessage(m);
}
public void flushReporters() {
Message m = new Message();
m.setType(RemoteMessage.M_FLUSH_REPORTER);
sendMessage(m);
}
public void endScenario() {
Message m = new Message();
m.setType(RemoteMessage.M_TEST_END);
m.addField("-1");
sendMessage(m);
}
/*
* @see TestListener#startTest(Test)
*/
public void startTest(Test test) {
this.currentTest = test;
/*
* Send notification that the test was started
*/
Message m = new Message();
m.setType(RemoteMessage.M_TEST_START);
m.addField(getTestFullId(test));
sendMessage(m);
/*
* Wait for the runner synch message
*/
synchronized (fWriter) {
synchronize();
}
}
/**
* Stop the current test run.
*/
protected void stop() {
if (fTestResult != null) {
fTestResult.stop();
}
}
/**
* Connect to the remote test listener.
*/
private boolean connect() {
if (fDebugMode)
System.out.println("RemoteTestRunner: trying to connect " + fHost + ":" + fPort); //$NON-NLS-1$ //$NON-NLS-2$
Exception exception = null;
for (int i = 1; i < 20; i++) {
try {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// ignore
}
fClientSocket = new Socket(fHost, fPort);
fWriter = new ObjectOutputStream(fClientSocket.getOutputStream()); //$NON-NLS-1$
fReader = new ObjectInputStream(fClientSocket.getInputStream());
fReaderThread = new ReaderThread();
fReaderThread.start();
connected = true;
return true;
} catch (IOException e) {
exception = e;
}
}
runFailed("Fail to connect to host: " + fHost + ", on port: " + fPort, exception); //$NON-NLS-1$
return false;
}
/**
* Close all the system object and wait on the close process
*
*/
private void closeAllSystemObjects() {
Thread t = new Thread() {
public void run() {
SystemManagerImpl.getInstance().closeAllObjects();
}
};
t.start();
try {
t.join();
} catch (Exception ignore) {
// ignore
}
}
private void synchronize() {
synchronized (fWriter) {
synchronize = false;
Message m = new Message();
m.setType(RemoteMessage.M_SYNCH);
sendMessage(m);
log.fine("Sent M_SYNCH message");
try {
while (!synchronize) {
try {
fWriter.wait(1000);
} catch (InterruptedException e) {
return;
}
}
} finally {
synchronize = false;
}
}
}
public void processExit() {
closeAllSystemObjects();
blockAllMessages = true;
synchronized (fWriter) {
waitForExit = false;
fWriter.notifyAll();
if (interrupted) {
System.exit(0);
}
}
}
/**
* Shuts down the connection to the remote test listener.
*/
public static Object getField(Object object, String fieldName) {
Class<?> currentClass = object.getClass();
try {
Field field = currentClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
// fall through
}
return null;
}
public void setSilent(boolean status) {
Message m = new Message();
m.setType(RemoteMessage.M_SET_SILENT);
m.addField(Boolean.toString(status));
sendMessage(m);
silent = status;
}
public boolean isSilent() {
return silent;
}
public void setTimeStamp(boolean enable) {
Message m = new Message();
m.setType(RemoteMessage.M_SET_TIME_STAMP);
m.addField(Boolean.toString(enable));
sendMessage(m);
}
public void saveFile(String fileName, byte[] content) {
Message m = new Message();
m.setType(RemoteMessage.M_SAVE_FILE);
m.addField(fileName);
m.addField(StringUtils.bytesToString(content));
sendMessage(m);
}
public void setData(String data) {
Message m = new Message();
m.setType(RemoteMessage.M_SET_DATA);
m.addField(data);
sendMessage(m);
}
public void startReport(String methodName, String parameters, String classDoc, String testDoc) {
Message m = new Message();
m.setType(RemoteMessage.M_START_REPORT);
m.addField(methodName);
m.addField(parameters);
m.addField(classDoc);
m.addField(testDoc);
sendMessage(m);
}
public void endReport(String steps, String failCause) {
Message m = new Message();
m.setType(RemoteMessage.M_END_REPORT);
m.addField(steps);
m.addField(failCause);
sendMessage(m);
}
public void report(String title, String message, int status, boolean bold, boolean html, boolean step, boolean link, long time) {
Message m = new Message();
m.setType(RemoteMessage.M_REPORT);
m.addField(title);
m.addField(String.valueOf(message));
m.addField(Integer.toString(status));
m.addField(Boolean.toString(bold));
m.addField(Boolean.toString(html));
m.addField(Boolean.toString(step));
m.addField(Boolean.toString(link));
m.addField(Long.toString(time));
sendMessage(m);
}
public void startLevel(String level, int place) throws IOException {
Message m = new Message();
m.setType(RemoteMessage.M_LEVEL);
m.addField(level);
m.addField(Integer.toString(place));
m.addField(Integer.toString(0));
m.addField(Boolean.toString(true));
m.addField(Boolean.toString(false));
m.addField(Boolean.toString(false));
m.addField(Boolean.toString(false));
sendMessage(m);
}
public void startLevel(String level, EnumReportLevel place)
throws IOException {
startLevel(level, place.value());
}
public void stopLevel() throws IOException {
Message m = new Message();
m.setType(RemoteMessage.M_STOP_LEVEL);
m.addField(Integer.toString(0));
m.addField(Integer.toString(0));
m.addField(Integer.toString(0));
m.addField(Boolean.toString(true));
m.addField(Boolean.toString(false));
m.addField(Boolean.toString(false));
m.addField(Boolean.toString(false));
sendMessage(m);
}
public void setFailToPass(boolean failToPass) {
super.setFailToPass(failToPass);
Message m = new Message();
m.setType(RemoteMessage.M_SET_FAIL_TO_PASS);
m.addField(Boolean.toString(failToPass));
sendMessage(m);
}
public void setFailToWarning(boolean failToWarning) {
super.setFailToWarning(failToWarning);
Message m = new Message();
m.setType(RemoteMessage.M_SET_FAIL_TO_WARNING);
m.addField(Boolean.toString(failToWarning));
sendMessage(m);
}
public void addWarning(Test test) {
Message m = new Message();
m.setType(RemoteMessage.M_ADD_WARNING);
m.addField(getTestFullId(test));
sendMessage(m);
}
public void startTest(TestInfo testInfo) {
// not called
}
public void endRun() {
// Message m = new Message();
// m.setType(RemoteMessage.M_RUN_END);
// sendMessage(m);
}
public void aboutToChangeTo(Fixture fixture) {
Message m = new Message();
m.setType(RemoteMessage.M_FIXTURE_ABOUT);
m.addField(fixture.getClass().getName());
sendMessage(m);
}
public void fixtureChanged(Fixture fixture) {
Message m = new Message();
m.setType(RemoteMessage.M_FIXTURE_CHANGED);
m.addField(fixture.getClass().getName());
sendMessage(m);
}
public void startFixturring() {
Message m = new Message();
m.setType(RemoteMessage.M_FIXTURE_START);
sendMessage(m);
}
public void endFixturring() {
Message m = new Message();
m.setType(RemoteMessage.M_FIXTURE_END);
sendMessage(m);
}
public void operationFail(String title, String message) {
Message m = new Message();
m.setType(RemoteMessage.M_OPERATION_FAIL);
m.addField(title);
m.addField(message);
sendMessage(m);
}
public void sutChanged(String sutName) {
Message m = new Message();
m.setType(RemoteMessage.M_SUT_CHANGED);
m.addField(sutName);
sendMessage(m);
}
public void paused() {
Message m3 = new Message();
m3.setType(RemoteMessage.M_PAUSED);
sendMessage(m3);
log.fine("Paused event send");
}
/**
* Send message to the runner
*
* @param message
* the message to send
*/
private void sendMessage(Message message) {
if (blockAllMessages) {
return;
}
if (fWriter == null) {
return;
}
if (debugMessages) {
System.err.println("Snd: T-->R " + message.getType().name());
System.err.flush();
}
synchronized (fWriter) {
try {
fWriter.writeObject(message);
fWriter.flush();
/*
* Fix the object output stream memory issue
*/
fWriter.reset();
} catch (IOException e) {
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Fail to send message", e);
}
}
}
boolean waitForExit = false;
private void waitForExit() {
if (!connected) {
return;
}
waitForExit = true;
synchronized (fWriter) {
while (waitForExit) {
try {
fWriter.wait();
} catch (InterruptedException e) {
return;
}
}
}
}
public void buildFinished(BuildEvent event) {
Message m = new Message();
m.setType(RemoteMessage.M_BUILD_FINISH);
sendMessage(m);
log.fine("sent buildFinished message.");
new ExitWatcher().start();
if (interrupted) {
blockAllMessages = true;
} else {
log.fine("started wait for exit.");
waitForExit();
log.fine("ended wait for exit.");
}
}
public void buildStarted(BuildEvent event) {
String currentFixture = System.getProperty(RunningProperties.CURRENT_FIXTURE_BASE);
log.info("Current fixture: " + currentFixture);
if (currentFixture != null) {
try {
FixtureManager.getInstance().setCurrentFixture(currentFixture);
} catch (Exception e) {
log.log(Level.WARNING, "Fail to set current fixture", e);
}
}
FixtureManager.getInstance().addListener(ListenerstManager.getInstance());
Message m = new Message();
m.setType(RemoteMessage.M_BUILD_START);
sendMessage(m);
}
public void messageLogged(BuildEvent event) {
// ignore
}
public void targetFinished(BuildEvent event) {
Message m = new Message();
m.setType(RemoteMessage.M_TARGET_FINISH);
m.addField(event.getTarget().getName());
m.addField(event.getTarget().getProject().getName());
sendMessage(m);
}
public void addProperty(String key, String value) {
Message m = new Message();
m.setType(RemoteMessage.M_PROPERTY);
m.addField(key);
m.addField(value);
sendMessage(m);
}
public void targetStarted(BuildEvent event) {
Message m = new Message();
m.setType(RemoteMessage.M_TARGET_START);
m.addField(event.getTarget().getName());
m.addField(event.getTarget().getProject().getName());
sendMessage(m);
}
public void taskFinished(BuildEvent event) {
Message m = new Message();
m.setType(RemoteMessage.M_TASK_FINISH);
m.addField(event.getTask().getTaskName());
sendMessage(m);
}
public void taskStarted(BuildEvent event) {
Message m = new Message();
m.setType(RemoteMessage.M_TASK_START);
m.addField(event.getTask().getTaskName());
sendMessage(m);
}
public String getTestFullId(Test test) {
if (test == null) {
test = currentTest;
}
String uuid = "";
if (test instanceof NamedTest) {
uuid = ((NamedTest) test).getFullUUID();
}
return uuid;
}
public int showConfirmDialog(String title, String message, int optionType, int messageType) {
/*
* Send the conferm dialog information and wait for a response
*/
messageConfirmed = false;
Message m = new Message();
m.setType(RemoteMessage.M_SHOW_CONFIRM_DIALOG);
m.addField(title);
m.addField(message);
m.addField(Integer.toString(optionType));
m.addField(Integer.toString(messageType));
sendMessage(m);
while (!messageConfirmed) {
synchronized (fWriter) {
try {
fWriter.wait();
} catch (InterruptedException e) {
break;
}
}
}
return messageConfermedReturn;
}
public void checkSystemObjectStatus(String soName, SOCheckStatus status, String errorMessage) {
Message m = new Message();
m.setType(RemoteMessage.M_CHECK_SYSTEM_OBJECT);
m.addField(soName);
m.addField(status.name());
m.addField(errorMessage);
sendMessage(m);
}
public void exit() {
Message m = new Message();
m.setType(RemoteMessage.M_EXIT);
sendMessage(m);
}
public void saveState(Test t) {
Message m = new Message();
m.setType(RemoteMessage.M_SAVE_STATE);
m.addField(getTestFullId(t));
sendMessage(m);
}
/**
* create and send publish message
*
* @param p
* properties that contains the description, setup name, version
* and build (field name and values)
* @param test
* the test that calls this method (for the Full Unique ID)
* @throws Exception
*/
public Message sendPublishMessage(Message m, Test test) throws Exception {
messageConfirmed = false;
sendMessage(m);
while (!messageConfirmed) {
synchronized (fWriter) {
try {
fWriter.wait();
} catch (InterruptedException e) {
break;
}
}
}
return sendEmailRunDetails;
}
public Message getSendEmailRunDetails() {
return sendEmailRunDetails;
}
public void setSendEmailRunDetails(Message sendEmailRunDetails) {
this.sendEmailRunDetails = sendEmailRunDetails;
}
@Override
public void endContainer(JTestContainer container) {
// TODO Auto-generated method stub
}
@Override
public void endLoop(AntForLoop loop, int count) {
// TODO Auto-generated method stub
}
@Override
public void startContainer(JTestContainer container) {
// TODO Auto-generated method stub
}
@Override
public void startLoop(AntForLoop loop, int count) {
// TODO Auto-generated method stub
}
@Override
public void closeAllLevels() throws IOException {
Message m = new Message();
m.setType(RemoteMessage.M_CLOSE_ALL_LEVELS);
sendMessage(m);
}
@Override
public void setContainerProperties(int ancestorLevel, String key,
String value) {
Message m = new Message();
m.setType(RemoteMessage.M_CONTAINER_PROPERTY);
m.addField("" + ancestorLevel);
m.addField(key);
m.addField(value);
sendMessage(m);
}
}
/**
* Will be added to shutdownhook and will be execute on vm exit
*
* @author guy.arieli
*
*/
class ShutdownThread extends Thread {
ObjectOutputStream out;
// ObjectInputStream in;
public ShutdownThread(ObjectOutputStream out) {
this.out = out;
// this.in = in;
}
public void run() {
try {
if (out != null) {
Message m = new Message();
m.setType(RemoteTestRunner.RemoteMessage.M_EXIT);
out.writeObject(m);
out.flush();
RemoteTestRunner.log.fine("Shutdown thread - sent exit.");
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
// ignore
}
}
out.close();
} catch (Throwable t) {
// ignore
}
}
}
/**
* Verify that the VM will exit in 8 sec.
*
* @author guy.arieli
*
*/
class ExitWatcher extends Thread {
public void run() {
RemoteTestRunner.log.fine("Exit watcher started");
long exitTimeout = JSystemProperties.getInstance().getLongPreference(FrameworkOptions.EXIT_TIMEOUT, 15000);
if (exitTimeout == 0) {
RemoteTestRunner.log.fine("Exit watcher exittimeout=0 before system.exit");
System.exit(0);
}
if (exitTimeout < 0) {
RemoteTestRunner.log.fine("Exit watcher exittimeout<0 before return");
return;
}
try {
Thread.sleep(exitTimeout);
} catch (InterruptedException e) {
return;
}
RemoteTestRunner.log.fine("Exit watcher exittimeout>0 after sleep before system.exit");
System.exit(0);
}
}