1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.loadtest;
14
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.util.ArrayList;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21
22 import org.apache.log4j.Logger;
23
24 import com.eviware.soapui.config.LoadStrategyConfig;
25 import com.eviware.soapui.config.LoadTestAssertionConfig;
26 import com.eviware.soapui.config.LoadTestConfig;
27 import com.eviware.soapui.config.LoadTestLimitTypesConfig;
28 import com.eviware.soapui.config.LoadTestLimitTypesConfig.Enum;
29 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
30 import com.eviware.soapui.impl.wsdl.actions.loadtest.CloneLoadTestAction;
31 import com.eviware.soapui.impl.wsdl.actions.loadtest.RemoveLoadTestAction;
32 import com.eviware.soapui.impl.wsdl.actions.loadtest.RenameLoadTestAction;
33 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
34 import com.eviware.soapui.impl.wsdl.loadtest.assertions.AbstractLoadTestAssertion;
35 import com.eviware.soapui.impl.wsdl.loadtest.assertions.LoadTestAssertionRegistry;
36 import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics;
37 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
38 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogErrorEntry;
39 import com.eviware.soapui.impl.wsdl.loadtest.strategy.BurstLoadStrategy;
40 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
41 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
42 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
43 import com.eviware.soapui.impl.wsdl.loadtest.strategy.SimpleLoadStrategy;
44 import com.eviware.soapui.impl.wsdl.support.Configurable;
45 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
46 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
47 import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
48 import com.eviware.soapui.model.testsuite.LoadTest;
49 import com.eviware.soapui.model.testsuite.LoadTestRunContext;
50 import com.eviware.soapui.model.testsuite.LoadTestRunListener;
51 import com.eviware.soapui.model.testsuite.LoadTestRunner;
52 import com.eviware.soapui.model.testsuite.TestRunContext;
53 import com.eviware.soapui.model.testsuite.TestRunner;
54 import com.eviware.soapui.model.testsuite.TestStepResult;
55 import com.eviware.soapui.model.testsuite.LoadTestRunner.Status;
56 import com.eviware.soapui.support.action.ActionSupport;
57
58 /***
59 * TestCase implementation for LoadTests
60 *
61 * @todo add assertionFailed event to LoadTestListener
62 * @todo create and return LoadTestAssertionResult from load-test assertions
63 *
64 * @author Ole.Matzura
65 */
66
67 public class WsdlLoadTest extends AbstractWsdlModelItem<LoadTestConfig> implements LoadTest
68 {
69 public final static String THREADCOUNT_PROPERTY = WsdlLoadTest.class.getName() + "@threadcount";
70 public final static String STARTDELAY_PROPERTY = WsdlLoadTest.class.getName() + "@startdelay";
71 public final static String TESTLIMIT_PROPERTY = WsdlLoadTest.class.getName() + "@testlimit";
72 public final static String LIMITTYPE_PROPERRY = WsdlLoadTest.class.getName() + "@limittype";
73 public final static String SAMPLEINTERVAL_PROPERRY = WsdlLoadTest.class.getName() + "@sample-interval";
74
75 private final static Logger logger = Logger.getLogger( WsdlLoadTest.class );
76 private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
77
78 private WsdlTestCase testCase;
79 private LoadTestStatistics statisticsModel;
80 private LoadStrategy loadStrategy = new BurstLoadStrategy();
81 private LoadTestLog loadTestLog;
82
83 private LoadStrategyConfigurationChangeListener loadStrategyListener = new LoadStrategyConfigurationChangeListener();
84 private List<LoadTestAssertion> assertions = new ArrayList<LoadTestAssertion>();
85 private ConfigurationChangePropertyListener configurationChangeListener = new ConfigurationChangePropertyListener();
86 private Set<LoadTestListener> listeners = new HashSet<LoadTestListener>();
87 private Set<LoadTestRunListener> runListeners = new HashSet<LoadTestRunListener>();
88 private WsdlLoadTestRunner runner;
89
90 public WsdlLoadTest(WsdlTestCase testCase, LoadTestConfig config )
91 {
92 super( config, testCase, "/loadTest.gif" );
93
94 this.testCase = testCase;
95
96 if( getConfig().getThreadCount() < 1 )
97 getConfig().setThreadCount( 5 );
98
99 if( getConfig().getLimitType() == null )
100 {
101 getConfig().setLimitType( LoadTestLimitTypesConfig.TIME );
102 getConfig().setTestLimit( 60 );
103 }
104
105 addAction( new RenameLoadTestAction( this ));
106 addAction( new RemoveLoadTestAction( this ));
107 addAction( ActionSupport.SEPARATOR_ACTION );
108 addAction( new CloneLoadTestAction( this ));
109 addAction( ActionSupport.SEPARATOR_ACTION );
110 addAction( new ShowOnlineHelpAction( HelpUrls.LOADTEST_HELP_URL ));
111
112 addLoadTestRunListener( internalTestRunListener );
113
114 LoadStrategyConfig ls = getConfig().getLoadStrategy();
115 if( ls == null )
116 {
117 ls = getConfig().addNewLoadStrategy();
118 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
119 }
120
121 LoadStrategyFactory factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
122 if( factory == null )
123 {
124 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
125 factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
126 }
127
128 loadStrategy = factory.build( ls.getConfig() );
129 loadStrategy.addConfigurationChangeListener( loadStrategyListener );
130
131 addLoadTestRunListener( loadStrategy );
132
133 statisticsModel = new LoadTestStatistics( this );
134
135 if( getConfig().xgetSampleInterval() == null )
136 setSampleInterval( LoadTestStatistics.DEFAULT_SAMPLE_INTERVAL );
137
138 statisticsModel.setUpdateFrequency( getSampleInterval() );
139
140 List<LoadTestAssertionConfig> assertionList = getConfig().getAssertionList();
141 for( LoadTestAssertionConfig assertionConfig : assertionList )
142 {
143 AbstractLoadTestAssertion assertion = LoadTestAssertionRegistry.buildAssertion( assertionConfig, this );
144 if( assertion != null )
145 {
146 assertions.add( assertion);
147 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
148 }
149 else
150 {
151 logger.warn( "Failed to build LoadTestAssertion from getConfig() [" + assertionConfig + "]" );
152 }
153 }
154
155 if( getConfig().xgetResetStatisticsOnThreadCountChange() == null )
156 getConfig().setResetStatisticsOnThreadCountChange( true );
157
158 if( getConfig().xgetCalculateTPSOnTimePassed() == null )
159 getConfig().setCalculateTPSOnTimePassed( false );
160
161 loadTestLog = new LoadTestLog( this );
162 }
163
164 public LoadTestStatistics getStatisticsModel()
165 {
166 return statisticsModel;
167 }
168
169 public long getThreadCount()
170 {
171 return getConfig().getThreadCount();
172 }
173
174 public void setThreadCount( long threadCount )
175 {
176 if( threadCount < 1 || threadCount == getThreadCount() )
177 return;
178
179 long oldCount = getThreadCount();
180 getConfig().setThreadCount( (int) threadCount );
181 notifyPropertyChanged( THREADCOUNT_PROPERTY, oldCount, threadCount );
182 }
183
184 public boolean getResetStatisticsOnThreadCountChange()
185 {
186 return getConfig().getResetStatisticsOnThreadCountChange();
187 }
188
189 public void setResetStatisticsOnThreadCountChange( boolean value )
190 {
191 getConfig().setResetStatisticsOnThreadCountChange( value );
192 }
193
194 public boolean getCalculateTPSOnTimePassed()
195 {
196 return getConfig().getCalculateTPSOnTimePassed();
197 }
198
199 public void setCalculateTPSOnTimePassed( boolean value )
200 {
201 getConfig().setCalculateTPSOnTimePassed( value );
202 }
203
204 public int getStartDelay()
205 {
206 return getConfig().getStartDelay();
207 }
208
209 public void setStartDelay( int startDelay )
210 {
211 if( startDelay < 0 )
212 return;
213
214 int oldDelay = getStartDelay();
215 getConfig().setStartDelay( startDelay );
216 notifyPropertyChanged( STARTDELAY_PROPERTY, oldDelay, startDelay );
217 }
218
219 public long getTestLimit()
220 {
221 return getConfig().getTestLimit();
222 }
223
224 public void setTestLimit( long testLimit )
225 {
226 if( testLimit < 0 )
227 return;
228
229 long oldLimit = getTestLimit();
230 getConfig().setTestLimit( testLimit );
231 notifyPropertyChanged( TESTLIMIT_PROPERTY, oldLimit, testLimit );
232 }
233
234 public long getSampleInterval()
235 {
236 return getConfig().getSampleInterval();
237 }
238
239 public void setSampleInterval( int sampleInterval )
240 {
241 if( sampleInterval < 0 )
242 return;
243
244 long oldInterval = getSampleInterval();
245 getConfig().setSampleInterval( sampleInterval );
246
247 statisticsModel.setUpdateFrequency( sampleInterval );
248
249 notifyPropertyChanged( TESTLIMIT_PROPERTY, oldInterval, sampleInterval );
250 }
251
252 public Enum getLimitType()
253 {
254 return getConfig().getLimitType();
255 }
256
257 public void setLimitType( Enum limitType )
258 {
259 if( limitType == null )
260 return;
261
262 Enum oldType = getLimitType();
263 getConfig().setLimitType( limitType );
264 notifyPropertyChanged( LIMITTYPE_PROPERRY, oldType, limitType );
265 }
266
267 public WsdlTestCase getTestCase()
268 {
269 return testCase;
270 }
271
272 public synchronized LoadTestRunner run()
273 {
274 if( runner != null && runner.getStatus() == Status.RUNNING )
275 return null;
276
277 runner = new WsdlLoadTestRunner( this );
278 runner.start();
279 return runner;
280 }
281
282 private class InternalTestRunListener extends LoadTestRunListenerAdapter
283 {
284 public void afterTestCase(LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext)
285 {
286 if( !assertions.isEmpty() )
287 {
288 for( LoadTestAssertion assertion : assertions )
289 {
290 String error = assertion.assertResults( loadTestRunner, context, testRunner, runContext );
291 if( error != null )
292 {
293 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, assertion.getIcon() ));
294 statisticsModel.addError( LoadTestStatistics.TOTAL );
295 }
296 }
297 }
298 }
299
300 public void afterTestStep(LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext, TestStepResult result)
301 {
302 if( !assertions.isEmpty() )
303 {
304 boolean added = false;
305
306 for( LoadTestAssertion assertion : assertions )
307 {
308 String error = assertion.assertResult( loadTestRunner, context, result, testRunner, runContext );
309 if( error != null )
310 {
311 int indexOfTestStep = testRunner.getTestCase().getIndexOfTestStep( result.getTestStep() );
312
313 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, result, assertion.getIcon() ));
314 statisticsModel.addError( indexOfTestStep);
315
316 added = true;
317 }
318 }
319
320
321 if( !added )
322 {
323 result.discard();
324 }
325 }
326 else result.discard();
327 }
328 }
329
330 public LoadStrategy getLoadStrategy()
331 {
332 return loadStrategy;
333 }
334
335 public void setLoadStrategy( LoadStrategy loadStrategy )
336 {
337 this.loadStrategy.removeConfigurationChangeListener( loadStrategyListener );
338 removeLoadTestRunListener( this.loadStrategy );
339
340 this.loadStrategy = loadStrategy;
341 this.loadStrategy.addConfigurationChangeListener( loadStrategyListener );
342 addLoadTestRunListener( this.loadStrategy );
343
344 getConfig().getLoadStrategy().setType( loadStrategy.getType() );
345 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
346 }
347
348 private class LoadStrategyConfigurationChangeListener implements PropertyChangeListener
349 {
350 public void propertyChange(PropertyChangeEvent evt)
351 {
352 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
353 }
354 }
355
356 public LoadTestAssertion addAssertion( String type, String targetStep, boolean showConfig )
357 {
358 LoadTestAssertion assertion = LoadTestAssertionRegistry.createAssertion( type, this );
359 assertion.setTargetStep( targetStep );
360
361 if( assertion instanceof Configurable && showConfig )
362 {
363 if( !((Configurable)assertion).configure() )
364 return null;
365 }
366
367 assertions.add( assertion );
368
369 getConfig().addNewAssertion().set( assertion.getConfiguration() );
370 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
371 fireAssertionAdded( assertion );
372
373 return assertion;
374 }
375
376 public void removeAssertion( LoadTestAssertion assertion)
377 {
378 int ix = assertions.indexOf( assertion );
379 if( ix >= 0 )
380 {
381 try
382 {
383 assertions.remove( ix );
384 fireAssertionRemoved(assertion);
385 }
386 finally
387 {
388 assertion.removePropertyChangeListener( configurationChangeListener );
389 assertion.release();
390 getConfig().removeAssertion( ix );
391 }
392 }
393 }
394
395 private void fireAssertionRemoved(LoadTestAssertion assertion)
396 {
397 if( !listeners.isEmpty() )
398 {
399 LoadTestListener[] l = listeners.toArray( new LoadTestListener[listeners.size()] );
400 for( LoadTestListener listener : l )
401 {
402 listener.assertionRemoved( assertion );
403 }
404 }
405 }
406
407 private void fireAssertionAdded(LoadTestAssertion assertion)
408 {
409 if( !listeners.isEmpty() )
410 {
411 LoadTestListener[] l = listeners.toArray( new LoadTestListener[listeners.size()] );
412 for( LoadTestListener listener : l )
413 {
414 listener.assertionAdded( assertion );
415 }
416 }
417 }
418
419 public int getAssertionCount()
420 {
421 return assertions.size();
422 }
423
424 public LoadTestAssertion getAssertionAt( int index )
425 {
426 return assertions.get( index );
427 }
428
429 private class ConfigurationChangePropertyListener implements PropertyChangeListener
430 {
431 public void propertyChange(PropertyChangeEvent evt)
432 {
433 int ix = assertions.indexOf( evt.getSource() );
434 if( ix >= 0 )
435 {
436 getConfig().getAssertionArray( ix ).set( assertions.get( ix ).getConfiguration() );
437 }
438 }
439 }
440
441 public LoadTestLog getLoadTestLog()
442 {
443 return loadTestLog;
444 }
445
446 public List<LoadTestAssertion> getAssertionList()
447 {
448 return assertions;
449 }
450
451 public void addLoadTestListener( LoadTestListener listener )
452 {
453 listeners.add( listener );
454 }
455
456 public void removeLoadTestListener( LoadTestListener listener )
457 {
458 listeners.remove( listener );
459 }
460
461 public void addLoadTestRunListener(LoadTestRunListener listener)
462 {
463 runListeners.add( listener );
464 }
465
466 public void removeLoadTestRunListener(LoadTestRunListener listener)
467 {
468 runListeners.remove( listener );
469 }
470
471 public LoadTestRunListener [] getLoadTestRunListeners()
472 {
473 return runListeners.toArray( new LoadTestRunListener[runListeners.size()] );
474 }
475
476 /***
477 * Release internal objects so they can remove listeners
478 */
479
480 public void release()
481 {
482 super.release();
483
484 statisticsModel.release();
485 loadTestLog.release();
486
487 for( LoadTestAssertion assertion : assertions )
488 assertion.release();
489 }
490
491 public boolean isRunning()
492 {
493 return runner != null && runner.getStatus() == LoadTestRunner.Status.RUNNING;
494 }
495
496 public WsdlLoadTestRunner getRunner()
497 {
498 return runner;
499 }
500 }