001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program 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: * This program 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 this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: LoadTestRunner.java,v 1.3 2007/03/27 21:59:42 mlipp Exp $
021: *
022: * $Log: LoadTestRunner.java,v $
023: * Revision 1.3 2007/03/27 21:59:42 mlipp
024: * Fixed lots of checkstyle warnings.
025: *
026: * Revision 1.2 2006/09/29 12:32:11 drmlipp
027: * Consistently using WfMOpen as projct name now.
028: *
029: * Revision 1.1.1.1 2003/12/19 13:01:37 drmlipp
030: * Updated to 1.1rc1
031: *
032: * Revision 1.3 2003/10/22 10:53:02 lipp
033: * Updated documentation.
034: *
035: * Revision 1.2 2003/10/22 08:34:50 lipp
036: * Some fixes/additions.
037: *
038: * Revision 1.1 2003/10/21 20:25:36 lipp
039: * Added load test support classes.
040: *
041: * Revision 1.1 2003/10/21 15:51:42 lipp
042: * Specific load test output.
043: *
044: */
045: package de.danet.an.util.junit;
046:
047: import java.io.FileOutputStream;
048: import java.io.OutputStreamWriter;
049: import java.io.PrintWriter;
050:
051: import java.util.ArrayList;
052: import java.util.HashMap;
053: import java.util.Iterator;
054: import java.util.List;
055: import java.util.Map;
056:
057: import junit.framework.AssertionFailedError;
058: import junit.framework.Test;
059: import junit.framework.TestListener;
060: import junit.framework.TestResult;
061: import junit.textui.TestRunner;
062:
063: /**
064: * This class provides a runner for junit tests that writes additional
065: * execution time related information. The runner extends the JUnit
066: * text user interface runner. The only difference is that this runner
067: * adds an additional TestListener that outputs execution times in an
068: * XML format together with grouping information from
069: * <code>NamedTestGroup</code>s. <P>
070: *
071: * The output file can be specified with the system property
072: * <code>de.danet.an.util.junit.loadTestOut</code>. It defaults to
073: * "<code>loadTestResults.xml</code>".
074: *
075: * @author <a href="mailto:lipp@danet.de"></a>
076: * @version $Revision: 1.3 $
077: */
078:
079: public class LoadTestRunner extends TestRunner {
080:
081: private static OutputStreamWriter loadOut = null;
082: private static LoadListener loadListener = null;
083:
084: public class LoadListener implements TestListener {
085:
086: public class GroupData {
087: private NamedTestGroup group;
088: private List entries = new ArrayList();
089: private Map entriesIndex = new HashMap();
090:
091: public GroupData(NamedTestGroup g) {
092: group = g;
093: }
094:
095: public void addData(String test, long time) {
096: entries.add(new Object[] { test, new Long(time) });
097: }
098:
099: public GroupData getGroupData(NamedTestGroup[] groups) {
100: return getGroupData(groups, 0);
101: }
102:
103: private GroupData getGroupData(NamedTestGroup[] groups,
104: int idx) {
105: if (groups.length == idx) {
106: return this ;
107: }
108: GroupData gd = (GroupData) entriesIndex
109: .get(groups[idx]);
110: if (gd == null) {
111: gd = new GroupData(groups[idx]);
112: entries.add(gd);
113: entriesIndex.put(groups[idx], gd);
114: }
115: return gd.getGroupData(groups, idx + 1);
116: }
117:
118: public void print() {
119: print("");
120: }
121:
122: public void print(String indent) {
123: indent = indent + " ";
124: for (Iterator i = entries.iterator(); i.hasNext();) {
125: Object o = i.next();
126: if (o instanceof GroupData) {
127: GroupData gd = (GroupData) o;
128: out.print(indent + "<Group name=\""
129: + gd.group.groupName() + "\"");
130: Map m = gd.group.groupAttributes();
131: if (m != null) {
132: for (Iterator ai = m.entrySet().iterator(); ai
133: .hasNext();) {
134: Map.Entry e = (Map.Entry) ai.next();
135: out.print(" " + e.getKey() + "=\""
136: + e.getValue() + "\"");
137: }
138: }
139: out.println(">");
140: gd.print(indent);
141: out.println(indent + "</Group>");
142: continue;
143: }
144: Object[] data = (Object[]) o;
145: out.println(indent + "<TestCase name=\"" + data[0]
146: + "\" time=\""
147: + (((Long) data[1]).longValue() / 1000.0)
148: + "\"/>");
149: }
150: }
151: }
152:
153: private PrintWriter out = null;
154: private ThreadLocal startTime = new ThreadLocal();
155: private GroupData dataRoot = new GroupData(null);
156:
157: public LoadListener(OutputStreamWriter resultWriter) {
158: out = new PrintWriter(resultWriter);
159: String enc = resultWriter.getEncoding();
160: if (enc.equals("UTF8")) {
161: enc = "UTF-8";
162: }
163: out.println("<?xml version=\"1.0\" encoding=\"" + enc
164: + "\"?>");
165: }
166:
167: /**
168: * Finalize output.
169: */
170: public void close() {
171: out.println("<LoadTestResults>");
172: dataRoot.print();
173: out.println("</LoadTestResults>");
174: out.close();
175: }
176:
177: // Implementation of junit.framework.TestListener
178:
179: /**
180: * Describe <code>addError</code> method here.
181: *
182: * @param test a <code>Test</code> value
183: * @param throwable a <code>Throwable</code> value
184: */
185: public void addError(Test test, Throwable throwable) {
186: }
187:
188: /**
189: * Describe <code>addFailure</code> method here.
190: *
191: * @param test a <code>Test</code> value
192: * @param assertionFailedError an <code>AssertionFailedError</code> value
193: */
194: public void addFailure(Test test,
195: AssertionFailedError assertionFailedError) {
196: }
197:
198: /**
199: * Describe <code>startTest</code> method here.
200: *
201: * @param test a <code>Test</code> value
202: */
203: public void startTest(Test test) {
204: startTime.set(new Long(System.currentTimeMillis()));
205: }
206:
207: /**
208: * Describe <code>endTest</code> method here.
209: *
210: * @param test a <code>Test</code> value
211: */
212: public synchronized void endTest(Test test) {
213: long endTime = System.currentTimeMillis();
214: long spent = endTime - ((Long) startTime.get()).longValue();
215: NamedTestGroup[] groups = NamedTestGroup.getGroups();
216: GroupData gd = dataRoot.getGroupData(groups);
217: gd.addData(test.toString(), spent);
218: }
219: }
220:
221: /**
222: * Creates the TestResult to be used for the test run.
223: */
224: protected TestResult createTestResult() {
225: TestResult res = new TestResult();
226: loadListener = new LoadListener(loadOut);
227: res.addListener(loadListener);
228: return res;
229: }
230:
231: public static void main(String[] args) {
232: try {
233: LoadTestRunner aTestRunner = new LoadTestRunner();
234: loadOut = new OutputStreamWriter(new FileOutputStream(
235: System.getProperty(
236: "de.danet.an.util.junit.loadTestOut",
237: "loadTestResults.xml")), "UTF-8");
238: int exitCode;
239: try {
240: TestResult r = aTestRunner.start(args);
241: if (!r.wasSuccessful()) {
242: exitCode = FAILURE_EXIT;
243: }
244: exitCode = SUCCESS_EXIT;
245: } catch (Exception e) {
246: System.err.println(e.getMessage());
247: exitCode = EXCEPTION_EXIT;
248: } finally {
249: if (loadListener != null) {
250: loadListener.close();
251: }
252: }
253: System.exit(exitCode);
254: } catch (Exception e) {
255: e.printStackTrace();
256: }
257: }
258: }
|