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.LinkedList;
023 import java.util.List;
024
025 import org.apache.log4j.Logger;
026 import org.mactor.framework.TestEngineThreadPool.TestRunnable;
027 import org.mactor.framework.data.DataTable;
028 import org.mactor.framework.spec.GlobalConfig;
029 import org.mactor.framework.spec.ProjectContext;
030 import org.mactor.framework.spec.TestSpec;
031
032 /**
033 *
034 * @author Lars Ivar Almli
035 */
036 public class TestRunner {
037 protected static Logger log = Logger.getLogger(TestRunner.class);
038 private boolean terminate = false;
039 int numberOfTestThreads;
040 TestSpec testSpec;
041 DataTable testData;
042 private String instanceId = AppUtil.getNextId("TR");
043 TestEngineThreadPool pool;
044 int errorCount = 0;
045 List<TestRunnable> jobs = new LinkedList<TestRunnable>();
046 GlobalConfig gc;
047 EventReporter reporter;
048 public TestRunner(int numberOfTestThreads, TestSpec testSpec, DataTable testData, TestFeedbackListener fl) throws MactorException {
049 super();
050 if (numberOfTestThreads < 1)
051 numberOfTestThreads = 1;
052 reporter = new EventReporter(instanceId, fl);
053 this.numberOfTestThreads = numberOfTestThreads;
054 this.testSpec = testSpec;
055 this.testData = testData;
056 pool = new TestEngineThreadPool(numberOfTestThreads);
057 gc = ProjectContext.getGlobalInstance().loadGlobalConfig();
058 }
059 boolean started = false;
060 private Object lock = new Object();
061 private boolean completed = false;
062 public void start() throws MactorException {
063 if (started)
064 throw new MactorException("The test runner can only be used once");
065 started = true;
066 new Thread(new Runnable() {
067 public void run() {
068 reporter.start();
069 try {
070 try {
071 int dataCount = testData.getRowCount();
072 for (int i = 0; (i < dataCount) && !terminate; i++) {
073 TestContextImpl context = new TestContextImpl(gc, testSpec);
074 context.setValues(testData.getRowData(i));
075 TestRunnable r = new TestRunnable(i, new TestEngine(instanceId, context, reporter));
076 jobs.add(r);
077 pool.addJob(r);
078 }
079 } catch (MactorException me) {
080 log.warn("Exception while initializing test", me);
081 }
082 pool.join();
083 for (TestRunnable runnable : jobs) {
084 if (!runnable.isSucces())
085 errorCount++;
086 }
087 } finally {
088 reporter.stop();
089 synchronized (lock) {
090 completed = true;
091 lock.notifyAll();
092 }
093 }
094 }
095 }).start();
096 }
097 public int waitForCompletion() {
098 try {
099 synchronized (lock) {
100 if (!completed)
101 lock.wait();
102 }
103 } catch (InterruptedException ie) {
104 }
105 return errorCount;
106 }
107 public void stop() {
108 terminate = true;
109 pool.terminate();
110 reporter.stop();
111 }
112 @Override
113 protected void finalize() throws Throwable {
114 super.finalize();
115 }
116 }