001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.ext.controller;
066:
067: import com.jcorporate.expresso.core.controller.ControllerException;
068: import com.jcorporate.expresso.core.controller.ControllerRequest;
069: import com.jcorporate.expresso.core.controller.ControllerResponse;
070: import com.jcorporate.expresso.core.controller.DBController;
071: import com.jcorporate.expresso.core.controller.Input;
072: import com.jcorporate.expresso.core.controller.NonHandleableException;
073: import com.jcorporate.expresso.core.controller.Output;
074: import com.jcorporate.expresso.core.controller.State;
075: import com.jcorporate.expresso.core.controller.Transition;
076: import com.jcorporate.expresso.core.db.DBException;
077: import com.jcorporate.expresso.core.misc.DateTime;
078: import com.jcorporate.expresso.core.misc.EventHandler;
079: import com.jcorporate.expresso.core.misc.StringUtil;
080: import com.jcorporate.expresso.ext.dbobj.PerfTestResult;
081: import com.jcorporate.expresso.ext.dbobj.PerfTestSet;
082: import com.jcorporate.expresso.kernel.util.FastStringBuffer;
083: import com.jcorporate.expresso.services.dbobj.Event;
084:
085: import java.util.Enumeration;
086: import java.util.Iterator;
087: import java.util.StringTokenizer;
088: import java.util.Vector;
089:
090: /**
091: * RunTests is a stand-alone application that allows sets of
092: * tests to be run
093: *
094: * @author Michael Nash
095: */
096: public class RunTests extends DBController {
097:
098: public RunTests() {
099: State prompt = new State("prompt", "Prompt for Command");
100: addState(prompt);
101: setInitialState("prompt");
102:
103: State runtests = new State("runtests", "Run Tests");
104: runtests.addRequiredParameter("sets");
105: runtests.addRequiredParameter("repeats");
106: runtests.addRequiredParameter("threads");
107: addState(runtests);
108: this
109: .setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
110: }
111:
112: /**
113: * Transition to a new state
114: *
115: * @param newState The new state to transition into
116: */
117: public ControllerResponse newState(String newState,
118: ControllerRequest params) throws ControllerException,
119: NonHandleableException {
120: ControllerResponse myResponse = super
121: .newState(newState, params);
122:
123: if (newState.equals("prompt")) {
124: promptState(myResponse, params);
125: } else if (newState.equals("runtests")) {
126: runTestsState(myResponse, params);
127: }
128:
129: return myResponse;
130: } /* newState() */
131:
132: private void promptState(ControllerResponse myResponse,
133: ControllerRequest params) throws ControllerException {
134: myResponse.addInput(new Input("sets",
135: "Test Sets To Run (Comma separator)"));
136: myResponse.addInput(new Input("repeats", "Repeats"));
137: myResponse.addInput(new Input("threads", "Threads"));
138:
139: Transition runTests = new Transition("Run Tests", getClass()
140: .getName());
141: runTests.setName("runtests");
142: runTests.addParam(STATE_PARAM_KEY, "runtests");
143: myResponse.addTransition(runTests);
144: }
145:
146: /**
147: * @return java.lang.String The Title of the controller
148: */
149: public String getTitle() {
150: return "Run Performance Test Sets";
151: }
152:
153: /**
154: * Perform a series of tests to try to determine if all of the
155: * components of the system are operating correctly
156: *
157: * @param args[]
158: */
159: private void runTestsState(ControllerResponse myResponse,
160: ControllerRequest params) throws ControllerException {
161: try {
162: FastStringBuffer mailMessage = new FastStringBuffer(1024);
163: mailMessage.append("Tests Start at "
164: + DateTime.getDateTimeString() + "\n");
165: myResponse.addOutput(new Output("Test Start - db '"
166: + params.getDataContext() + "'"));
167:
168: StringBuffer message = new StringBuffer("RunTests\n");
169: message.append("\nRunTests at "
170: + DateTime
171: .getDateTimeForDB(params.getDataContext())
172: + "\n");
173: message.append("For database/context '"
174: + params.getDataContext() + "'\n\n");
175:
176: String setsToRunString = StringUtil.notNull((String) params
177: .getParameter("sets"));
178:
179: if (setsToRunString.equals("")) {
180: setsToRunString = "all";
181: }
182:
183: String repeatsStr = StringUtil.notNull((String) params
184: .getParameter("repeats"));
185:
186: if (repeatsStr.equals("")) {
187: repeatsStr = "1";
188: }
189:
190: String threadCountStr = StringUtil.notNull((String) params
191: .getParameter("threads"));
192:
193: if (threadCountStr.equals("")) {
194: threadCountStr = "1";
195: }
196:
197: int repeats = 1;
198:
199: try {
200: repeats = new Integer(repeatsStr).intValue();
201: } catch (NumberFormatException ne) {
202: myResponse.addOutput(new Output("Number of repeats '"
203: + repeatsStr
204: + "' not valid. Running only once."));
205: }
206:
207: int threadCount = 1;
208:
209: try {
210: threadCount = new Integer(threadCountStr).intValue();
211: } catch (NumberFormatException ne) {
212: myResponse.addOutput(new Output("Number of threads '"
213: + threadCountStr
214: + "' not valid. Running only one thread."));
215: }
216:
217: Vector setsToRun = new Vector();
218: boolean noProblems = true;
219: PerfTestResult overallResult = new PerfTestResult();
220:
221: try {
222: if (setsToRunString.equals("all")) {
223: PerfTestSet ps = new PerfTestSet();
224: ps.setDataContext(params.getDataContext());
225:
226: PerfTestSet oneSet = null;
227:
228: for (Iterator eps = ps.searchAndRetrieveList()
229: .iterator(); eps.hasNext();) {
230: oneSet = (PerfTestSet) eps.next();
231: setsToRun.addElement(oneSet
232: .getField("SetNumber"));
233: }
234: } else {
235: StringTokenizer stk = new StringTokenizer(
236: setsToRunString, ",");
237:
238: while (stk.hasMoreTokens()) {
239: setsToRun.addElement(stk.nextElement());
240: }
241: }
242:
243: myResponse.addOutput(new Output("Running tests "
244: + repeats + " time(s)"));
245: message.append("\nRunning " + setsToRun.size()
246: + " test sets.");
247:
248: int activeThreads = 0;
249: Vector threadVector = new Vector();
250:
251: for (int i = 1; i <= threadCount; i++) {
252: RunTestThread rt = new RunTestThread();
253: threadVector.addElement(rt);
254: rt.setDBName(params.getDataContext());
255: rt.setTests((Vector) setsToRun.clone());
256: rt.setThreadNumber(i);
257: rt.setRepeats(repeats);
258: rt.start();
259: activeThreads++;
260: } /* for each repitition */
261:
262: myResponse.addOutput(new Output("" + activeThreads
263: + " threads started"));
264:
265: RunTestThread oneThread = null;
266:
267: while (activeThreads > 0) {
268:
269: //yield();
270: //sleep(5000);
271: // Got to make a utility class here to do delays, now that Controller no longer inherits from Thread
272: activeThreads = 0;
273:
274: for (Enumeration te = threadVector.elements(); te
275: .hasMoreElements();) {
276: oneThread = (RunTestThread) te.nextElement();
277:
278: if (!oneThread.isAlive()) {
279: myResponse.addOutput(new Output("Thread "
280: + oneThread.getThreadNumber()
281: + " completed."));
282:
283: if (activeThreads > 0) {
284: activeThreads--;
285: }
286: } else {
287: activeThreads++;
288: }
289: }
290:
291: System.gc();
292:
293: //myResponse.addOutput(new Output("" + activeThreads + " threads running"));
294: }
295: for (Enumeration te = threadVector.elements(); te
296: .hasMoreElements();) {
297: oneThread = (RunTestThread) te.nextElement();
298: overallResult.add(oneThread.getResults());
299: }
300:
301: message.append(overallResult.getMessage());
302: message.append("\nThere were ");
303:
304: if (overallResult.getFailureCount() > 0) {
305: if (overallResult.getFailureCount() == 1) {
306: message.append("was 1 failure, ");
307: } else {
308: message.append("were "
309: + overallResult.getFailureCount()
310: + " failures, ");
311: }
312: } else {
313: message.append("no failures, ");
314: }
315: if (overallResult.getWarningCount() > 0) {
316: if (overallResult.getWarningCount() == 1) {
317: message.append("1 warning, ");
318: } else {
319: message.append(""
320: + overallResult.getWarningCount()
321: + " warnings, ");
322: }
323: } else {
324: message.append("no warnings, ");
325: }
326:
327: message.append("and ");
328:
329: if (overallResult.getCautionCount() > 0) {
330: if (overallResult.getCautionCount() == 1) {
331: message.append("1 caution, ");
332: } else {
333: message.append("were "
334: + overallResult.getCautionCount()
335: + " cautions, ");
336: }
337: } else {
338: message.append("no cautions.");
339: }
340:
341: message.append("\n");
342: message.append("There were "
343: + overallResult.getCurrentUsers()
344: + " users logged in during tests\n");
345: message.append("Total execution time: "
346: + overallResult.getRunTime() + " milliseconds");
347:
348: if ((overallResult.getFailureCount() > 0)
349: || (overallResult.getWarningCount() > 0)
350: || (overallResult.getCautionCount() > 0)) {
351: noProblems = false;
352: }
353: try {
354: new Event(params.getDataContext(), "SYSERROR",
355: message.toString(), noProblems);
356: EventHandler.flush();
357: } catch (Exception me) {
358: myResponse.addOutput(new Output(
359: "WARNING: Unble to send email of test results:"
360: + me.getMessage()));
361: me.printStackTrace(System.out);
362: }
363:
364: myResponse.addOutput(new Output(message.toString()));
365: } catch (Exception de) {
366: de.printStackTrace(System.err);
367: throw new ControllerException(de);
368: }
369:
370: myResponse.addOutput(new Output("All Tests Complete."));
371: } catch (DBException dbe) {
372: throw new ControllerException(dbe);
373: }
374: } /* runTestsState() */
375:
376: } /* RunTests */
|