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    }