001 /******************************************************************************
002 * Copyright (C) MActor Developers. All rights reserved. *
003 * ---------------------------------------------------------------------------*
004 * This file is part of MActor. *
005 * *
006 * MActor is free software; you can redistribute it and/or modify *
007 * it under the terms of the GNU General Public License as published by *
008 * the Free Software Foundation; either version 2 of the License, or *
009 * (at your option) any later version. *
010 * *
011 * MActor is distributed in the hope that it will be useful, *
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
014 * GNU General Public License for more details. *
015 * *
016 * You should have received a copy of the GNU General Public License *
017 * along with MActor; if not, write to the Free Software *
018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
019 ******************************************************************************/
020 package org.mactor.framework;
021
022 import java.util.List;
023
024 import org.apache.log4j.Logger;
025 import org.mactor.framework.TestEngineThreadPool.TestRunnable;
026 import org.mactor.framework.spec.GlobalConfig;
027 import org.mactor.framework.spec.ProjectContext;
028 import org.mactor.framework.spec.TestSpec;
029
030 /**
031 *
032 * @author Lars Ivar Almli
033 */
034 public class MockRunner {
035 protected static Logger log = Logger.getLogger(MockRunner.class);
036 private boolean stopped = false;
037 int numberOfTestThreads;
038 List<TestSpec> testSpecs;
039 TestEngineThreadPool pool;
040 int errorCount = 0;
041 GlobalConfig gc;
042 EventReporter reporter;
043 private String mockInstanceId = AppUtil.getNextId("M");
044 public MockRunner(int numberOfTestThreads, List<TestSpec> testSpecs, TestFeedbackListener fl) throws MactorException {
045 super();
046 if (numberOfTestThreads < 1)
047 numberOfTestThreads = 1;
048 reporter = new EventReporter(mockInstanceId, fl);
049 this.numberOfTestThreads = numberOfTestThreads;
050 this.testSpecs = testSpecs;
051 pool = new TestEngineThreadPool(numberOfTestThreads);
052 gc = ProjectContext.getGlobalInstance().loadGlobalConfig();
053 }
054 boolean started = false;
055 public void start() throws MactorException {
056 if (started)
057 throw new MactorException("The mock runner can only be used once");
058 started = true;
059 new Thread(new Runnable() {
060 public void run() {
061 runMock();
062 }
063 }).start();
064 }
065 private void runMock() {
066 try {
067 reporter.start();
068 while (!stopped) {
069 for (TestSpec ts : testSpecs) {
070 if (stopped)
071 break;
072 TestContextImpl context = new TestContextImpl(gc, ts);
073 TestRunnable r = new TestRunnable(0, new TestEngine(mockInstanceId, context, reporter));
074 pool.addJob(r); // blocks until a thread is available..
075 }
076 }
077 } catch (Throwable t) {
078 if (stopped)
079 log.info("Mock runner stopped");
080 else
081 log.error("Mock runner terminated due to an unhandled exception:" + t.getMessage(), t);
082 } finally {
083 reporter.stop();
084 }
085 }
086 private Object lock = new Object();
087 public void waitForCompletion() {
088 synchronized (lock) {
089 if (stopped)
090 return;
091 try {
092 lock.wait();
093 } catch (InterruptedException ie) {
094 }
095 }
096 }
097 public void stop() {
098 stopped = true;
099 try {
100 pool.terminate();
101 reporter.stop();
102 } finally {
103 synchronized (lock) {
104 lock.notifyAll();
105 }
106 }
107 }
108 @Override
109 protected void finalize() throws Throwable {
110 super.finalize();
111 }
112 }