001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.loadtest;
014:
015: import java.beans.PropertyChangeEvent;
016: import java.beans.PropertyChangeListener;
017: import java.util.ArrayList;
018: import java.util.HashSet;
019: import java.util.List;
020: import java.util.Set;
021:
022: import org.apache.log4j.Logger;
023:
024: import com.eviware.soapui.config.LoadStrategyConfig;
025: import com.eviware.soapui.config.LoadTestAssertionConfig;
026: import com.eviware.soapui.config.LoadTestConfig;
027: import com.eviware.soapui.config.LoadTestLimitTypesConfig;
028: import com.eviware.soapui.config.LoadTestLimitTypesConfig.Enum;
029: import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
030: import com.eviware.soapui.impl.wsdl.loadtest.assertions.AbstractLoadTestAssertion;
031: import com.eviware.soapui.impl.wsdl.loadtest.assertions.LoadTestAssertionRegistry;
032: import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics;
033: import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
034: import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogErrorEntry;
035: import com.eviware.soapui.impl.wsdl.loadtest.strategy.BurstLoadStrategy;
036: import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
037: import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
038: import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
039: import com.eviware.soapui.impl.wsdl.loadtest.strategy.SimpleLoadStrategy;
040: import com.eviware.soapui.impl.wsdl.support.Configurable;
041: import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
042: import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
043: import com.eviware.soapui.model.testsuite.LoadTest;
044: import com.eviware.soapui.model.testsuite.LoadTestRunContext;
045: import com.eviware.soapui.model.testsuite.LoadTestRunListener;
046: import com.eviware.soapui.model.testsuite.LoadTestRunner;
047: import com.eviware.soapui.model.testsuite.TestRunContext;
048: import com.eviware.soapui.model.testsuite.TestRunner;
049: import com.eviware.soapui.model.testsuite.TestStepResult;
050: import com.eviware.soapui.model.testsuite.LoadTestRunner.Status;
051:
052: /**
053: * TestCase implementation for LoadTests
054: *
055: * @todo add assertionFailed event to LoadTestListener
056: * @todo create and return LoadTestAssertionResult from load-test assertions
057: *
058: * @author Ole.Matzura
059: */
060:
061: public class WsdlLoadTest extends AbstractWsdlModelItem<LoadTestConfig>
062: implements LoadTest {
063: public final static String THREADCOUNT_PROPERTY = WsdlLoadTest.class
064: .getName()
065: + "@threadcount";
066: public final static String STARTDELAY_PROPERTY = WsdlLoadTest.class
067: .getName()
068: + "@startdelay";
069: public final static String TESTLIMIT_PROPERTY = WsdlLoadTest.class
070: .getName()
071: + "@testlimit";
072: public final static String HISTORYLIMIT_PROPERTY = WsdlLoadTest.class
073: .getName()
074: + "@historylimit";
075: public final static String LIMITTYPE_PROPERRY = WsdlLoadTest.class
076: .getName()
077: + "@limittype";
078: public final static String SAMPLEINTERVAL_PROPERRY = WsdlLoadTest.class
079: .getName()
080: + "@sample-interval";
081:
082: private final static Logger logger = Logger
083: .getLogger(WsdlLoadTest.class);
084: private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
085:
086: private WsdlTestCase testCase;
087: private LoadTestStatistics statisticsModel;
088: private LoadStrategy loadStrategy = new BurstLoadStrategy();
089: private LoadTestLog loadTestLog;
090:
091: private LoadStrategyConfigurationChangeListener loadStrategyListener = new LoadStrategyConfigurationChangeListener();
092: private List<LoadTestAssertion> assertions = new ArrayList<LoadTestAssertion>();
093: private ConfigurationChangePropertyListener configurationChangeListener = new ConfigurationChangePropertyListener();
094: private Set<LoadTestListener> listeners = new HashSet<LoadTestListener>();
095: private Set<LoadTestRunListener> runListeners = new HashSet<LoadTestRunListener>();
096: private WsdlLoadTestRunner runner;
097:
098: public WsdlLoadTest(WsdlTestCase testCase, LoadTestConfig config) {
099: super (config, testCase, "/loadTest.gif");
100:
101: this .testCase = testCase;
102:
103: if (getConfig().getThreadCount() < 1)
104: getConfig().setThreadCount(5);
105:
106: if (getConfig().getLimitType() == null) {
107: getConfig().setLimitType(LoadTestLimitTypesConfig.TIME);
108: getConfig().setTestLimit(60);
109: }
110:
111: if (!getConfig().isSetHistoryLimit()) {
112: getConfig().setHistoryLimit(-1);
113: }
114:
115: addLoadTestRunListener(internalTestRunListener);
116:
117: LoadStrategyConfig ls = getConfig().getLoadStrategy();
118: if (ls == null) {
119: ls = getConfig().addNewLoadStrategy();
120: ls.setType(SimpleLoadStrategy.STRATEGY_TYPE);
121: }
122:
123: LoadStrategyFactory factory = LoadStrategyRegistry
124: .getInstance().getFactory(ls.getType());
125: if (factory == null) {
126: ls.setType(SimpleLoadStrategy.STRATEGY_TYPE);
127: factory = LoadStrategyRegistry.getInstance().getFactory(
128: ls.getType());
129: }
130:
131: loadStrategy = factory.build(ls.getConfig());
132: loadStrategy
133: .addConfigurationChangeListener(loadStrategyListener);
134:
135: addLoadTestRunListener(loadStrategy);
136:
137: statisticsModel = new LoadTestStatistics(this );
138:
139: if (getConfig().xgetSampleInterval() == null)
140: setSampleInterval(LoadTestStatistics.DEFAULT_SAMPLE_INTERVAL);
141:
142: statisticsModel.setUpdateFrequency(getSampleInterval());
143:
144: List<LoadTestAssertionConfig> assertionList = getConfig()
145: .getAssertionList();
146: for (LoadTestAssertionConfig assertionConfig : assertionList) {
147: AbstractLoadTestAssertion assertion = LoadTestAssertionRegistry
148: .buildAssertion(assertionConfig, this );
149: if (assertion != null) {
150: assertions.add(assertion);
151: assertion.addPropertyChangeListener(
152: LoadTestAssertion.CONFIGURATION_PROPERTY,
153: configurationChangeListener);
154: } else {
155: logger
156: .warn("Failed to build LoadTestAssertion from getConfig() ["
157: + assertionConfig + "]");
158: }
159: }
160:
161: if (getConfig().xgetResetStatisticsOnThreadCountChange() == null)
162: getConfig().setResetStatisticsOnThreadCountChange(true);
163:
164: if (getConfig().xgetCalculateTPSOnTimePassed() == null)
165: getConfig().setCalculateTPSOnTimePassed(false);
166:
167: loadTestLog = new LoadTestLog(this );
168: }
169:
170: public LoadTestStatistics getStatisticsModel() {
171: return statisticsModel;
172: }
173:
174: public long getThreadCount() {
175: return getConfig().getThreadCount();
176: }
177:
178: public void setThreadCount(long threadCount) {
179: if (threadCount < 1 || threadCount == getThreadCount())
180: return;
181:
182: long oldCount = getThreadCount();
183: getConfig().setThreadCount((int) threadCount);
184: notifyPropertyChanged(THREADCOUNT_PROPERTY, oldCount,
185: threadCount);
186: }
187:
188: public boolean getResetStatisticsOnThreadCountChange() {
189: return getConfig().getResetStatisticsOnThreadCountChange();
190: }
191:
192: public void setResetStatisticsOnThreadCountChange(boolean value) {
193: getConfig().setResetStatisticsOnThreadCountChange(value);
194: }
195:
196: public boolean getCalculateTPSOnTimePassed() {
197: return getConfig().getCalculateTPSOnTimePassed();
198: }
199:
200: public void setCalculateTPSOnTimePassed(boolean value) {
201: getConfig().setCalculateTPSOnTimePassed(value);
202: }
203:
204: public int getStartDelay() {
205: return getConfig().getStartDelay();
206: }
207:
208: public void setStartDelay(int startDelay) {
209: if (startDelay < 0)
210: return;
211:
212: int oldDelay = getStartDelay();
213: getConfig().setStartDelay(startDelay);
214: notifyPropertyChanged(STARTDELAY_PROPERTY, oldDelay, startDelay);
215: }
216:
217: public long getHistoryLimit() {
218: return getConfig().getHistoryLimit();
219: }
220:
221: public void setHistoryLimit(long historyLimit) {
222: long oldLimit = getHistoryLimit();
223: getConfig().setHistoryLimit(historyLimit);
224: if (historyLimit == 0)
225:
226: notifyPropertyChanged(HISTORYLIMIT_PROPERTY, oldLimit,
227: historyLimit);
228: }
229:
230: public long getTestLimit() {
231: return getConfig().getTestLimit();
232: }
233:
234: public void setTestLimit(long testLimit) {
235: if (testLimit < 0)
236: return;
237:
238: long oldLimit = getTestLimit();
239: getConfig().setTestLimit(testLimit);
240: notifyPropertyChanged(TESTLIMIT_PROPERTY, oldLimit, testLimit);
241: }
242:
243: public long getSampleInterval() {
244: return getConfig().getSampleInterval();
245: }
246:
247: public void setSampleInterval(int sampleInterval) {
248: if (sampleInterval < 0)
249: return;
250:
251: long oldInterval = getSampleInterval();
252: getConfig().setSampleInterval(sampleInterval);
253:
254: statisticsModel.setUpdateFrequency(sampleInterval);
255:
256: notifyPropertyChanged(TESTLIMIT_PROPERTY, oldInterval,
257: sampleInterval);
258: }
259:
260: public Enum getLimitType() {
261: return getConfig().getLimitType();
262: }
263:
264: public void setLimitType(Enum limitType) {
265: if (limitType == null)
266: return;
267:
268: Enum oldType = getLimitType();
269: getConfig().setLimitType(limitType);
270: notifyPropertyChanged(LIMITTYPE_PROPERRY, oldType, limitType);
271: }
272:
273: public WsdlTestCase getTestCase() {
274: return testCase;
275: }
276:
277: public synchronized WsdlLoadTestRunner run() {
278: getStatisticsModel().reset();
279: if (runner != null && runner.getStatus() == Status.RUNNING)
280: return null;
281:
282: runner = new WsdlLoadTestRunner(this );
283: runner.start();
284: return runner;
285: }
286:
287: private class InternalTestRunListener extends
288: LoadTestRunListenerAdapter {
289: public void afterTestCase(LoadTestRunner loadTestRunner,
290: LoadTestRunContext context, TestRunner testRunner,
291: TestRunContext runContext) {
292: if (!assertions.isEmpty()) {
293: for (LoadTestAssertion assertion : assertions) {
294: String error = assertion.assertResults(
295: loadTestRunner, context, testRunner,
296: runContext);
297: if (error != null) {
298: loadTestLog.addEntry(new LoadTestLogErrorEntry(
299: assertion.getName(), error, assertion
300: .getIcon()));
301: statisticsModel
302: .addError(LoadTestStatistics.TOTAL);
303: }
304: }
305: }
306: }
307:
308: public void afterTestStep(LoadTestRunner loadTestRunner,
309: LoadTestRunContext context, TestRunner testRunner,
310: TestRunContext runContext, TestStepResult result) {
311: if (!assertions.isEmpty()) {
312: boolean added = false;
313:
314: for (LoadTestAssertion assertion : assertions) {
315: String error = assertion.assertResult(
316: loadTestRunner, context, result,
317: testRunner, runContext);
318: if (error != null) {
319: int indexOfTestStep = testRunner.getTestCase()
320: .getIndexOfTestStep(
321: result.getTestStep());
322:
323: loadTestLog.addEntry(new LoadTestLogErrorEntry(
324: assertion.getName(), error, result,
325: assertion.getIcon()));
326: statisticsModel.addError(indexOfTestStep);
327:
328: added = true;
329: }
330: }
331:
332: // always discard result if there were no errors
333: if (!added) {
334: result.discard();
335: }
336: } else
337: result.discard();
338: }
339: }
340:
341: public LoadStrategy getLoadStrategy() {
342: return loadStrategy;
343: }
344:
345: public void setLoadStrategy(LoadStrategy loadStrategy) {
346: this .loadStrategy
347: .removeConfigurationChangeListener(loadStrategyListener);
348: removeLoadTestRunListener(this .loadStrategy);
349:
350: this .loadStrategy = loadStrategy;
351: this .loadStrategy
352: .addConfigurationChangeListener(loadStrategyListener);
353: addLoadTestRunListener(this .loadStrategy);
354:
355: getConfig().getLoadStrategy().setType(loadStrategy.getType());
356: getConfig().getLoadStrategy().setConfig(
357: loadStrategy.getConfig());
358: }
359:
360: private class LoadStrategyConfigurationChangeListener implements
361: PropertyChangeListener {
362: public void propertyChange(PropertyChangeEvent evt) {
363: getConfig().getLoadStrategy().setConfig(
364: loadStrategy.getConfig());
365: }
366: }
367:
368: public LoadTestAssertion addAssertion(String type,
369: String targetStep, boolean showConfig) {
370: LoadTestAssertion assertion = LoadTestAssertionRegistry
371: .createAssertion(type, this );
372: assertion.setTargetStep(targetStep);
373:
374: if (assertion instanceof Configurable && showConfig) {
375: if (!((Configurable) assertion).configure())
376: return null;
377: }
378:
379: assertions.add(assertion);
380:
381: getConfig().addNewAssertion().set(assertion.getConfiguration());
382: assertion.addPropertyChangeListener(
383: LoadTestAssertion.CONFIGURATION_PROPERTY,
384: configurationChangeListener);
385: fireAssertionAdded(assertion);
386:
387: return assertion;
388: }
389:
390: public void removeAssertion(LoadTestAssertion assertion) {
391: int ix = assertions.indexOf(assertion);
392: if (ix >= 0) {
393: try {
394: assertions.remove(ix);
395: fireAssertionRemoved(assertion);
396: } finally {
397: assertion
398: .removePropertyChangeListener(configurationChangeListener);
399: assertion.release();
400: getConfig().removeAssertion(ix);
401: }
402: }
403: }
404:
405: private void fireAssertionRemoved(LoadTestAssertion assertion) {
406: if (!listeners.isEmpty()) {
407: LoadTestListener[] l = listeners
408: .toArray(new LoadTestListener[listeners.size()]);
409: for (LoadTestListener listener : l) {
410: listener.assertionRemoved(assertion);
411: }
412: }
413: }
414:
415: private void fireAssertionAdded(LoadTestAssertion assertion) {
416: if (!listeners.isEmpty()) {
417: LoadTestListener[] l = listeners
418: .toArray(new LoadTestListener[listeners.size()]);
419: for (LoadTestListener listener : l) {
420: listener.assertionAdded(assertion);
421: }
422: }
423: }
424:
425: public int getAssertionCount() {
426: return assertions.size();
427: }
428:
429: public LoadTestAssertion getAssertionAt(int index) {
430: return assertions.get(index);
431: }
432:
433: private class ConfigurationChangePropertyListener implements
434: PropertyChangeListener {
435: public void propertyChange(PropertyChangeEvent evt) {
436: int ix = assertions.indexOf(evt.getSource());
437: if (ix >= 0) {
438: getConfig().getAssertionArray(ix).set(
439: assertions.get(ix).getConfiguration());
440: }
441: }
442: }
443:
444: public LoadTestLog getLoadTestLog() {
445: return loadTestLog;
446: }
447:
448: public List<LoadTestAssertion> getAssertionList() {
449: return assertions;
450: }
451:
452: public void addLoadTestListener(LoadTestListener listener) {
453: listeners.add(listener);
454: }
455:
456: public void removeLoadTestListener(LoadTestListener listener) {
457: listeners.remove(listener);
458: }
459:
460: public void addLoadTestRunListener(LoadTestRunListener listener) {
461: runListeners.add(listener);
462: }
463:
464: public void removeLoadTestRunListener(LoadTestRunListener listener) {
465: runListeners.remove(listener);
466: }
467:
468: public LoadTestRunListener[] getLoadTestRunListeners() {
469: return runListeners
470: .toArray(new LoadTestRunListener[runListeners.size()]);
471: }
472:
473: /**
474: * Release internal objects so they can remove listeners
475: */
476:
477: public void release() {
478: super .release();
479:
480: statisticsModel.release();
481: loadTestLog.release();
482:
483: for (LoadTestAssertion assertion : assertions)
484: assertion.release();
485: }
486:
487: public boolean isRunning() {
488: return runner != null
489: && runner.getStatus() == LoadTestRunner.Status.RUNNING;
490: }
491:
492: public WsdlLoadTestRunner getRunner() {
493: return runner;
494: }
495:
496: public void resetConfigOnMove(LoadTestConfig config) {
497: setConfig(config);
498:
499: loadStrategy.updateConfig(config.getLoadStrategy().getConfig());
500:
501: List<LoadTestAssertionConfig> assertionList = config
502: .getAssertionList();
503: for (int c = 0; c < assertionList.size(); c++) {
504: assertions.get(c).updateConfiguration(assertionList.get(c));
505: }
506: }
507: }
|