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 }