/* * Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved. */ package jsystem.framework.report; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import jsystem.framework.JSystemProperties; import jsystem.framework.fixture.Fixture; import jsystem.framework.scenario.JTestContainer; import jsystem.framework.scenario.Parameter; import jsystem.framework.scenario.RunningProperties; import jsystem.framework.scenario.Scenario; import jsystem.framework.scenario.ScenarioChangeType; import jsystem.framework.scenario.flow_control.AntForLoop; import jsystem.framework.system.SystemManagerImpl; import jsystem.runner.ErrorLevel; import jsystem.runner.SOCheckStatus; import jsystem.runner.remote.RemoteTestRunner; import jsystem.utils.StringUtils; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestListener; /** * Manage the listeners in the framework: TestListener FixtureListener * TestReporter * <br> * <br> * The ListenersManager is a Reporter implementation on the test VM, when executing from the JRunner.<br> * It dispatches events to all Listeners registered to it and passes on events to the JRunner JVM * * @author Guy Arieli */ public class ListenerstManager extends DefaultReporterImpl implements JSystemListeners { private static Logger log = Logger.getLogger(ListenerstManager.class .getName()); private static JSystemListeners manager = null; ArrayList<Object> listeners = new ArrayList<Object>(); boolean silent = false; boolean timeStampEnabled = true; private static boolean lastTestFail = false; boolean isPause = false; Object pasueSynch = new Object(); RemoteTestRunner remoteRunner = null; boolean failDebug = false; /** * signals if stop was pressed */ volatile boolean isGracefulStop = false; /** * signals if an exception should be thrown (to stop the test) */ volatile boolean throwException = false; public void addListener(Object listener) { listeners.add(listener); } public void removeListener(Object listener) { listeners.remove(listener); } /** * A RunnerListenersManager will be returned if the JVM is the Reporter VM, * otherwise, if the executed from the JRunner and on the test VM, return ListenersManager instance * * @return */ public static JSystemListeners getInstance() { if (JSystemProperties.getInstance().isReporterVm() || !("true".equals(System .getProperty(RunningProperties.RUNNER_EXIST)))) { return RunnerListenersManager.getInstance(); } if (manager == null) { manager = new ListenerstManager(); } return manager; } public static boolean isInit() { return (manager != null); } private ListenerstManager() { remoteRunner = RemoteTestRunner.getInstance(); } public synchronized void addError(Test test, Throwable t) { if (isSilent()) { return; } if (!isFailToPass()) { if (failDebug) { writeToDebugFile("Test was set to fail from addError\n" + StringUtils.getStackTrace(t)); } setLastTestFailed(true); } for (int i = 0; i < listeners.size(); i++) { Object o = listeners.get(i); if (o instanceof TestListener) { TestListener tl = (TestListener) o; try { tl.addError(test, t); } catch (Throwable ex) { log.log(Level.SEVERE, "Fail to add error to testlistener", ex); } } } remoteRunner.addError(test, t); } public synchronized void addError(Test test, String message, String stack) { throw new RuntimeException("Unexpected call to addError"); } public synchronized void addFailure(Test test, AssertionFailedError t) { if (isSilent()) { return; } if (!isFailToPass()) { if (failDebug) { writeToDebugFile("Test was set to fail from addFailure\n" + StringUtils.getStackTrace(t)); } setLastTestFailed(true); } for (int i = 0; i < listeners.size(); i++) { Object o = listeners.get(i); if (o instanceof TestListener) { TestListener tl = (TestListener) o; try { tl.addFailure(test, t); } catch (Throwable ex) { log.log(Level.SEVERE, "Fail to add failure to testlistener", ex); } } } remoteRunner.addFailure(test, t); } public synchronized void addFailure(Test test, String message, String stack, boolean analyzerException) { throw new RuntimeException("Unexpected call to addFailure"); } /* * (non-Javadoc) * * @see * jsystem.framework.report.ExtendTestListener#addWarning(junit.framework * .Test) */ public synchronized void addWarning(Test test) { if (isSilent()) { return; } for (int i = 0; i < listeners.size(); i++) { Object o = listeners.get(i); if (o instanceof ExtendTestListener) { ExtendTestListener tl = (ExtendTestListener) o; try { tl.addWarning(test); } catch (Throwable ex) { log.log(Level.SEVERE, "Fail to add warning to testlistener", ex); } } } remoteRunner.addWarning(test); } public synchronized void endTest(Test test) { for (int i = 0; i < listeners.size(); i++) { Object o = listeners.get(i); TestListener tl = (TestListener) o; try { tl.endTest(test); } catch (Throwable ex) { log.log(Level.SEVERE, "Fail to add endTest", ex); } } remoteRunner.endTest(test); checkExecutionStatus(); } public void startTest(TestInfo testInfo) { // not implemented (will use startTest(Test test)) } public synchronized void startTest(Test test) { if (isGracefulStop) { remoteRunner.exit(); remoteRunner.processExit(); isGracefulStop = false; return; } if (failDebug) { writeToDebugFile("**** startTest: " + test.getClass().getName() + "." + ((TestCase) test).getName()); } /* * See that no reports are buffered */ stopBufferingReports(); clearReportsBuffer(); updateCurrentTest(test); setFailToPass(false); setFailToWarning(false); setLastTestFailed(false); this.silent = false; for (int i = 0; i < listeners.size(); i++) { Object o = listeners.get(i); if (o instanceof TestListener) { TestListener tl = (TestListener) o; try { tl.startTest(test); } catch (Throwable ex) { log.log(Level.SEVERE, "Fail to startTest", ex); } } } remoteRunner.startTest(test); } public synchronized void aboutToChangeTo(Fixture fixture) { remoteRunner.aboutToChangeTo(fixture); } public synchronized void fixtureChanged(Fixture fixture) { remoteRunner.fixtureChanged(fixture); } public synchronized void startFixturring() { remoteRunner.startFixturring(); } public synchronized void endFixturring() { remoteRunner.endFixturring(); } public void setSilent(boolean status) { this.silent = status; remoteRunner.setSilent(status); } public boolean isSilent() { return silent; } public void setTimeStamp(boolean enable) { timeStampEnabled = enable; remoteRunner.setTimeStamp(enable); } /* * (non-Javadoc) * * @see jsystem.framework.report.ExtendReporter#saveFile(java.lang.String, * java.io.InputStream) */ public synchronized void saveFile(String fileName, byte[] content) { try { File file = new File(getCurrentTestFolder(), fileName); file.getParentFile().mkdirs(); FileOutputStream out = new FileOutputStream(file); out.write(content); out.close(); } catch (IOException e) { log.log(Level.WARNING, "Fail to save file", e); } checkExecutionStatus(); ; } /* * (non-Javadoc) * * @see jsystem.framework.report.ExtendReporter#report(java.lang.String, * java.lang.String, int, boolean) */ public synchronized void setData(String data) { if (isSilent()) { return; } remoteRunner.setData(data); checkExecutionStatus(); } public synchronized void sutChanged(String sutName) { remoteRunner.sutChanged(sutName); } public synchronized void scenarioChanged(Scenario current, ScenarioChangeType changeType) { // for (int i = 0; i < listeners.size(); i++){ // Object o = listeners.get(i); // if (o instanceof ScenarioListener){ // try { // ((ScenarioListener)o).scenarioChanged(current); // } catch (Throwable ex){ // log.log(Level.SEVERE, "Fail to scenarioChanged", ex); // } // } // } } public synchronized void scenarioDirectoryChanged(File directory) { // for (int i = 0; i < listeners.size(); i++){ // Object o = listeners.get(i); // if (o instanceof ScenarioListener){ // try { // ((ScenarioListener)o).scenarioDirectoryChanged(directory); // } catch (Throwable ex){ // log.log(Level.SEVERE, "Fail to scenarioDirectoryChanged", ex); // } // } // } } public synchronized void startReport(String name, String parameters, String classDoc, String testDoc) { if (isSilent()) { return; } remoteRunner.startReport(name, parameters, classDoc, testDoc); checkExecutionStatus(); } public void startLevel(String level, int place) throws IOException { if (isSilent()) { return; } if (buffering) { if (reportsBuffer == null) { reportsBuffer = new ArrayList<ReportElement>(); } ReportElement re = new ReportElement(); re.setTitle(level); re.setOriginator(Thread.currentThread().getName()); re.setTime(System.currentTimeMillis()); re.setStartLevel(true); re.setLevelPlace(place); reportsBuffer.add(re); return; } remoteRunner.startLevel(level, place); } public void stopLevel() throws IOException { if (isSilent()) { return; } if (buffering) { if (reportsBuffer == null) { reportsBuffer = new ArrayList<ReportElement>(); } ReportElement re = new ReportElement(); re.setOriginator(Thread.currentThread().getName()); re.setTime(System.currentTimeMillis()); re.setStopLevel(true); reportsBuffer.add(re); return; } remoteRunner.stopLevel(); } public synchronized void endReport(String steps, String failCause) { if (isSilent()) { return; } remoteRunner.endReport(steps, failCause); checkExecutionStatus(); } /** * <b>NOTICE</b>: This event is not send to the system objects. */ public synchronized void endRun() { remoteRunner.endRun(); } public void setFailToPass(boolean status) { super.setFailToPass(status); remoteRunner.setFailToPass(status); } public void setFailToWarning(boolean status) { super.setFailToWarning(status); remoteRunner.setFailToWarning(status); } public void pause() throws Exception { SystemManagerImpl.getInstance().pausedAllObjects(); isPause = true; } /** * the stop button has been pressed - raise a gracefull stop flag<br> * next reporter action will throw an exception * * @throws Exception */ public void gracefulStop() throws Exception { isGracefulStop = true; throwException = true; } public boolean isPause() { return isPause; } /** * was graceful stop set (stop pressed) * * @return */ public boolean isGracefulStop() { return isGracefulStop; } /** * cancels the exception throwing due to graceful stop * */ public void cancelExceptionThrowing() { throwException = false; } public void resume() { isPause = false; paused = false; synchronized (pasueSynch) { pasueSynch.notifyAll(); } SystemManagerImpl.getInstance().resumeAllObjects(); } boolean paused = false; public boolean isPaused() { return paused; } private void checkExecutionStatus() { checkGracefulStop(); checkPause(); } /** * check if graceful stop flag has been raised.<br> * throw an exception if it was * */ private void checkGracefulStop() { if (throwException) { throwException = false; throw new GracefulStopException("User aborted test"); } } private void checkPause() { if (isPause) { remoteRunner.paused(); paused = true; synchronized (pasueSynch) { while (isPause) { try { pasueSynch.wait(5000); } catch (InterruptedException e) { // ignored } } } } } public synchronized void report(String title, String message, int status, boolean bold, boolean html, boolean step, boolean link, long time) { checkExecutionStatus(); if (isSilent()) { return; } if (buffering) { if (reportsBuffer == null) { reportsBuffer = new ArrayList<ReportElement>(); } ReportElement currentReportElement = new ReportElement(); currentReportElement.setTitle(title); currentReportElement.setMessage(message); currentReportElement.setStatus(status); currentReportElement.setBold(bold); currentReportElement.setHtml(html); currentReportElement.setStep(step); currentReportElement.setLink(link); currentReportElement .setOriginator(Thread.currentThread().getName()); currentReportElement.setTime(time); reportsBuffer.add(currentReportElement); if (!printBufferdReportsInRunTime) { return; } } remoteRunner.report(title, String.valueOf(message), status, bold, html, step, link, time); if (status == Reporter.FAIL && !isFailToPass() && !isFailToWarning() && !isSilent()) { if (failDebug) { writeToDebugFile("Test was set to fail from report"); } setLastTestFailed(true); if (systemTest != null) { systemTest.setPass(false); systemTest.addFailCause(title); } } if (step) { if (systemTest != null) { systemTest.addExecutedSteps(title); } } } public void blockReporters(boolean block) { // ignore } public boolean getLastTestFailed() { return lastTestFail; } public void setLastTestFailed(boolean fail) { lastTestFail = fail; } private void writeToDebugFile(String toWrite) { try { FileWriter fw = new FileWriter("debug.txt", true); fw.write(toWrite); fw.write("\n"); fw.flush(); fw.close(); } catch (IOException e) { log.log(Level.SEVERE, "couldn't close fileWriter"); } } public void addProperty(String key, String value) { checkExecutionStatus(); if (isSilent()) { return; } if (StringUtils.hasNotAllowedSpecialCharacters(key) || StringUtils.hasNotAllowedSpecialCharacters(value)) { String property = key + "=" + value; String title2 = "Warning: found unallowed characters from \"" + StringUtils.notAllowedCharacters + "\"" + " in property: " + property; report(title2, false); return; } remoteRunner.addProperty(key, value); } public int showConfirmDialog(String title, String message, int optionType, int messageType) { if (isSilent()) { return 0; } return remoteRunner.showConfirmDialog(title, message, optionType, messageType); } public void checkSystemObjectStatus(String soName, SOCheckStatus status, String errorMessage) { if (isSilent()) { return; } remoteRunner.checkSystemObjectStatus(soName, status, errorMessage); } public void startLevel(String level, EnumReportLevel place) throws IOException { startLevel(level, place.value()); } public void executionEnded(String scenarioName) { // TODO Auto-generated method stub } public void remoteExit() { // TODO Auto-generated method stub } public void errorOccured(String title, String message, ErrorLevel level) { // TODO Auto-generated method stub } public void remotePause() { // TODO Auto-generated method stub } @Override public void saveState(Test t) throws Exception { remoteRunner.saveState(t); } @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 { remoteRunner.closeAllLevels(); } @Override public void scenarioDirtyStateChanged(Scenario s, boolean isDirty) { // TODO Auto-generated method stub } @Override public void testParametersChanged(String testIIUUD, Parameter[] oldValues, Parameter[] newValues) { // TODO Auto-generated method stub } @Override public void initReporters() { remoteRunner.initReporters(); } @Override public void flushReporters() { remoteRunner.flushReporters(); } @Override public void setContainerProperties(int ancestorLevel, String key, String value) { remoteRunner.setContainerProperties(ancestorLevel, key, value); } }