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.io.File;
18 import java.io.FileNotFoundException;
19 import java.io.PrintWriter;
20 import java.util.ArrayList;
21 import java.util.Date;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25
26 import org.apache.commons.collections.list.TreeList;
27 import org.apache.log4j.Logger;
28
29 import com.eviware.soapui.SoapUI;
30 import com.eviware.soapui.config.LoadStrategyConfig;
31 import com.eviware.soapui.config.LoadTestAssertionConfig;
32 import com.eviware.soapui.config.LoadTestConfig;
33 import com.eviware.soapui.config.LoadTestLimitTypesConfig;
34 import com.eviware.soapui.config.LoadTestLimitTypesConfig.Enum;
35 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
36 import com.eviware.soapui.impl.wsdl.loadtest.assertions.AbstractLoadTestAssertion;
37 import com.eviware.soapui.impl.wsdl.loadtest.assertions.LoadTestAssertionRegistry;
38 import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics;
39 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
40 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogErrorEntry;
41 import com.eviware.soapui.impl.wsdl.loadtest.strategy.BurstLoadStrategy;
42 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
43 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
44 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
45 import com.eviware.soapui.impl.wsdl.loadtest.strategy.SimpleLoadStrategy;
46 import com.eviware.soapui.impl.wsdl.support.Configurable;
47 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
48 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
49 import com.eviware.soapui.impl.wsdl.teststeps.SimplePathPropertySupport;
50 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
51 import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
52 import com.eviware.soapui.model.testsuite.LoadTest;
53 import com.eviware.soapui.model.testsuite.LoadTestRunContext;
54 import com.eviware.soapui.model.testsuite.LoadTestRunListener;
55 import com.eviware.soapui.model.testsuite.LoadTestRunner;
56 import com.eviware.soapui.model.testsuite.TestCaseRunContext;
57 import com.eviware.soapui.model.testsuite.TestCaseRunner;
58 import com.eviware.soapui.model.testsuite.TestRunnable;
59 import com.eviware.soapui.model.testsuite.TestRunner;
60 import com.eviware.soapui.model.testsuite.TestStepResult;
61 import com.eviware.soapui.model.testsuite.TestRunner.Status;
62 import com.eviware.soapui.settings.HttpSettings;
63 import com.eviware.soapui.support.StringUtils;
64 import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
65 import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
66 import com.eviware.soapui.support.types.StringList;
67 import com.eviware.soapui.support.types.StringToObjectMap;
68
69 /***
70 * TestCase implementation for LoadTests
71 *
72 * @author Ole.Matzura
73 * @todo add assertionFailed event to LoadTestListener
74 * @todo create and return LoadTestAssertionResult from load-test assertions
75 */
76
77 @SuppressWarnings( "unchecked" )
78 public class WsdlLoadTest extends AbstractWsdlModelItem<LoadTestConfig> implements LoadTest, TestRunnable
79 {
80 public final static String THREADCOUNT_PROPERTY = WsdlLoadTest.class.getName() + "@threadcount";
81 public final static String STARTDELAY_PROPERTY = WsdlLoadTest.class.getName() + "@startdelay";
82 public final static String TESTLIMIT_PROPERTY = WsdlLoadTest.class.getName() + "@testlimit";
83 public final static String HISTORYLIMIT_PROPERTY = WsdlLoadTest.class.getName() + "@historylimit";
84 public final static String LIMITTYPE_PROPERRY = WsdlLoadTest.class.getName() + "@limittype";
85 public final static String SAMPLEINTERVAL_PROPERRY = WsdlLoadTest.class.getName() + "@sample-interval";
86 public static final String MAXASSERTIONERRORS_PROPERTY = WsdlLoadTest.class.getName() + "@max-assertion-errors";
87 public final static String SETUP_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@setupScript";
88 public final static String TEARDOWN_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@tearDownScript";
89
90 private final static Logger logger = Logger.getLogger( WsdlLoadTest.class );
91 public static final int DEFAULT_STRATEGY_INTERVAL = 500;
92
93 private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
94
95 private WsdlTestCase testCase;
96 private LoadTestStatistics statisticsModel;
97 private LoadStrategy loadStrategy = new BurstLoadStrategy( this );
98 private LoadTestLog loadTestLog;
99
100 private LoadStrategyConfigurationChangeListener loadStrategyListener = new LoadStrategyConfigurationChangeListener();
101 private List<LoadTestAssertion> assertions = new ArrayList<LoadTestAssertion>();
102 private ConfigurationChangePropertyListener configurationChangeListener = new ConfigurationChangePropertyListener();
103 private Set<LoadTestListener> loadTestListeners = new HashSet<LoadTestListener>();
104 private Set<LoadTestRunListener> loadTestRunListeners = new HashSet<LoadTestRunListener>();
105 private List<LoadTestLogErrorEntry> assertionErrors = new TreeList();
106 private WsdlLoadTestRunner runner;
107 private StatisticsLogger statisticsLogger = new StatisticsLogger();
108 private SoapUIScriptEngine setupScriptEngine;
109 private SoapUIScriptEngine tearDownScriptEngine;
110 @SuppressWarnings( "unused" )
111 private SimplePathPropertySupport logFolder;
112 private LoadTestRunListener[] loadTestRunListenersArray;
113
114 public WsdlLoadTest( WsdlTestCase testCase, LoadTestConfig config )
115 {
116 super( config, testCase, "/loadTest.gif" );
117
118 this.testCase = testCase;
119
120 if( getConfig().getThreadCount() < 1 )
121 getConfig().setThreadCount( 5 );
122
123 if( getConfig().getLimitType() == null )
124 {
125 getConfig().setLimitType( LoadTestLimitTypesConfig.TIME );
126 getConfig().setTestLimit( 60 );
127 }
128
129 if( !getConfig().isSetHistoryLimit() )
130 {
131 getConfig().setHistoryLimit( -1 );
132 }
133
134 addLoadTestRunListener( internalTestRunListener );
135
136 LoadStrategyConfig ls = getConfig().getLoadStrategy();
137 if( ls == null )
138 {
139 ls = getConfig().addNewLoadStrategy();
140 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
141 }
142
143 LoadStrategyFactory factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
144 if( factory == null )
145 {
146 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
147 factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
148 }
149
150 loadStrategy = factory.build( ls.getConfig(), this );
151 loadStrategy.addConfigurationChangeListener( loadStrategyListener );
152
153 addLoadTestRunListener( loadStrategy );
154
155 statisticsModel = new LoadTestStatistics( this );
156
157 if( getConfig().xgetSampleInterval() == null )
158 setSampleInterval( LoadTestStatistics.DEFAULT_SAMPLE_INTERVAL );
159
160 statisticsModel.setUpdateFrequency( getSampleInterval() );
161
162 List<LoadTestAssertionConfig> assertionList = getConfig().getAssertionList();
163 for( LoadTestAssertionConfig assertionConfig : assertionList )
164 {
165 AbstractLoadTestAssertion assertion = LoadTestAssertionRegistry.buildAssertion( assertionConfig, this );
166 if( assertion != null )
167 {
168 assertions.add( assertion );
169 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
170 }
171 else
172 {
173 logger.warn( "Failed to build LoadTestAssertion from getConfig() [" + assertionConfig + "]" );
174 }
175 }
176
177 if( getConfig().xgetResetStatisticsOnThreadCountChange() == null )
178 getConfig().setResetStatisticsOnThreadCountChange( true );
179
180 if( getConfig().xgetCalculateTPSOnTimePassed() == null )
181 getConfig().setCalculateTPSOnTimePassed( true );
182
183 if( !getConfig().isSetMaxAssertionErrors() )
184 getConfig().setMaxAssertionErrors( 100 );
185
186 if( getConfig().xgetCancelExcessiveThreads() == null )
187 getConfig().setCancelExcessiveThreads( true );
188
189 if( getConfig().xgetStrategyInterval() == null )
190 getConfig().setStrategyInterval( DEFAULT_STRATEGY_INTERVAL );
191
192 loadTestLog = new LoadTestLog( this );
193
194 for( LoadTestRunListener listener : SoapUI.getListenerRegistry().getListeners( LoadTestRunListener.class ) )
195 {
196 addLoadTestRunListener( listener );
197 }
198
199
200 if( !getSettings().isSet( HttpSettings.CLOSE_CONNECTIONS ) )
201 getSettings().setBoolean( HttpSettings.CLOSE_CONNECTIONS,
202 SoapUI.getSettings().getBoolean( HttpSettings.CLOSE_CONNECTIONS ) );
203 }
204
205 public LoadTestStatistics getStatisticsModel()
206 {
207 return statisticsModel;
208 }
209
210 public StatisticsLogger getStatisticsLogger()
211 {
212 return statisticsLogger;
213 }
214
215 public long getThreadCount()
216 {
217 return getConfig().getThreadCount();
218 }
219
220 public void setThreadCount( long threadCount )
221 {
222 long oldCount = getThreadCount();
223 if( threadCount == oldCount )
224 return;
225
226 if( getLogStatisticsOnThreadChange() && isRunning() )
227 statisticsLogger.logStatistics( "ThreadCount change from " + oldCount + " to " + threadCount );
228
229 getConfig().setThreadCount( ( int )threadCount );
230 notifyPropertyChanged( THREADCOUNT_PROPERTY, oldCount, threadCount );
231 }
232
233 public boolean getResetStatisticsOnThreadCountChange()
234 {
235 return getConfig().getResetStatisticsOnThreadCountChange();
236 }
237
238 public void setResetStatisticsOnThreadCountChange( boolean value )
239 {
240 getConfig().setResetStatisticsOnThreadCountChange( value );
241 }
242
243 public boolean getCancelOnReachedLimit()
244 {
245 return getConfig().getCancelOnReachedLimit();
246 }
247
248 public void setCancelOnReachedLimit( boolean value )
249 {
250 getConfig().setCancelOnReachedLimit( value );
251 }
252
253 public boolean getCancelExcessiveThreads()
254 {
255 return getConfig().getCancelExcessiveThreads();
256 }
257
258 public void setCancelExcessiveThreads( boolean value )
259 {
260 getConfig().setCancelExcessiveThreads( value );
261 }
262
263 public boolean getLogStatisticsOnThreadChange()
264 {
265 return getConfig().getLogStatisticsOnThreadChange();
266 }
267
268 public void setLogStatisticsOnThreadChange( boolean value )
269 {
270 getConfig().setLogStatisticsOnThreadChange( value );
271 }
272
273 public String getStatisticsLogFolder()
274 {
275 return getConfig().getStatisticsLogFolder();
276 }
277
278 public void setStatisticsLogFolder( String value )
279 {
280 getConfig().setStatisticsLogFolder( value );
281 }
282
283 public boolean getCalculateTPSOnTimePassed()
284 {
285 return getConfig().getCalculateTPSOnTimePassed();
286 }
287
288 public void setCalculateTPSOnTimePassed( boolean value )
289 {
290 getConfig().setCalculateTPSOnTimePassed( value );
291 }
292
293 public int getStartDelay()
294 {
295 return getConfig().getStartDelay();
296 }
297
298 public void setStartDelay( int startDelay )
299 {
300 if( startDelay < 0 )
301 return;
302
303 int oldDelay = getStartDelay();
304 getConfig().setStartDelay( startDelay );
305 notifyPropertyChanged( STARTDELAY_PROPERTY, oldDelay, startDelay );
306 }
307
308 public long getHistoryLimit()
309 {
310 return getConfig().getHistoryLimit();
311 }
312
313 public void setHistoryLimit( long historyLimit )
314 {
315 long oldLimit = getHistoryLimit();
316 getConfig().setHistoryLimit( historyLimit );
317 if( historyLimit == 0 )
318
319 notifyPropertyChanged( HISTORYLIMIT_PROPERTY, oldLimit, historyLimit );
320 }
321
322 public long getTestLimit()
323 {
324 return getConfig().getTestLimit();
325 }
326
327 public void setTestLimit( long testLimit )
328 {
329 if( testLimit < 0 )
330 return;
331
332 long oldLimit = getTestLimit();
333 getConfig().setTestLimit( testLimit );
334 notifyPropertyChanged( TESTLIMIT_PROPERTY, oldLimit, testLimit );
335 }
336
337 public long getMaxAssertionErrors()
338 {
339 return getConfig().getMaxAssertionErrors();
340 }
341
342 public void setMaxAssertionErrors( long testLimit )
343 {
344 if( testLimit < 0 )
345 return;
346
347 long oldLimit = getMaxAssertionErrors();
348 getConfig().setMaxAssertionErrors( testLimit );
349 notifyPropertyChanged( MAXASSERTIONERRORS_PROPERTY, oldLimit, testLimit );
350 }
351
352 public long getStatisticsLogInterval()
353 {
354 return getConfig().getStatisticsLogInterval();
355 }
356
357 public void setStatisticsLogInterval( int sampleInterval )
358 {
359 if( sampleInterval < 0 )
360 return;
361
362 long oldInterval = getStatisticsLogInterval();
363 getConfig().setStatisticsLogInterval( sampleInterval );
364
365 notifyPropertyChanged( SAMPLEINTERVAL_PROPERRY, oldInterval, sampleInterval );
366
367 if( oldInterval == 0 && sampleInterval > 0 && isRunning() )
368 statisticsLogger.start();
369 }
370
371 public long getSampleInterval()
372 {
373 return getConfig().getSampleInterval();
374 }
375
376 public void setSampleInterval( int sampleInterval )
377 {
378 if( sampleInterval < 0 )
379 return;
380
381 long oldInterval = getSampleInterval();
382 getConfig().setSampleInterval( sampleInterval );
383
384 statisticsModel.setUpdateFrequency( sampleInterval );
385 notifyPropertyChanged( SAMPLEINTERVAL_PROPERRY, oldInterval, sampleInterval );
386 }
387
388 public Enum getLimitType()
389 {
390 return getConfig().getLimitType();
391 }
392
393 public void setLimitType( Enum limitType )
394 {
395 if( limitType == null )
396 return;
397
398 Enum oldType = getLimitType();
399 getConfig().setLimitType( limitType );
400 notifyPropertyChanged( LIMITTYPE_PROPERRY, oldType, limitType );
401 }
402
403 public WsdlTestCase getTestCase()
404 {
405 return testCase;
406 }
407
408 public synchronized WsdlLoadTestRunner run()
409 {
410 getStatisticsModel().reset();
411 if( runner != null && runner.getStatus() == Status.RUNNING )
412 return null;
413
414 if( runner != null )
415 runner.release();
416
417 assertionErrors.clear();
418 runner = new WsdlLoadTestRunner( this );
419 runner.start();
420 return runner;
421 }
422
423 private class InternalTestRunListener extends LoadTestRunListenerAdapter
424 {
425 @Override
426 public void afterLoadTest( LoadTestRunner loadTestRunner, LoadTestRunContext context )
427 {
428 statisticsLogger.finish();
429 }
430
431 @Override
432 public void beforeLoadTest( LoadTestRunner loadTestRunner, LoadTestRunContext context )
433 {
434 statisticsLogger.init( context );
435
436 if( getStatisticsLogInterval() > 0 )
437 statisticsLogger.start();
438 }
439
440 @Override
441 public void afterTestCase( LoadTestRunner loadTestRunner, LoadTestRunContext context, TestCaseRunner testRunner,
442 TestCaseRunContext runContext )
443 {
444 if( !assertions.isEmpty() )
445 {
446 for( LoadTestAssertion assertion : assertions )
447 {
448 String error = assertion.assertResults( loadTestRunner, context, testRunner, runContext );
449 if( error != null )
450 {
451 int threadIndex = 0;
452
453 try
454 {
455 threadIndex = Integer.parseInt( runContext.getProperty( "ThreadIndex" ).toString() );
456 }
457 catch( Throwable t )
458 {
459 }
460
461 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, assertion.getIcon(),
462 threadIndex ) );
463 statisticsModel.addError( LoadTestStatistics.TOTAL );
464 }
465 }
466 }
467 }
468
469 @Override
470 public void afterTestStep( LoadTestRunner loadTestRunner, LoadTestRunContext context, TestCaseRunner testRunner,
471 TestCaseRunContext runContext, TestStepResult result )
472 {
473 boolean added = false;
474
475 if( !assertions.isEmpty() )
476 {
477 for( LoadTestAssertion assertion : assertions )
478 {
479 String error = assertion.assertResult( loadTestRunner, context, result, testRunner, runContext );
480 if( error != null )
481 {
482 int indexOfTestStep = testRunner.getTestCase().getIndexOfTestStep( result.getTestStep() );
483 int threadIndex = 0;
484
485 try
486 {
487 threadIndex = Integer.parseInt( runContext.getProperty( "ThreadIndex" ).toString() );
488 }
489 catch( Throwable t )
490 {
491 }
492
493 LoadTestLogErrorEntry errorEntry = new LoadTestLogErrorEntry( assertion.getName(), error, result,
494 assertion.getIcon(), threadIndex );
495
496 loadTestLog.addEntry( errorEntry );
497 statisticsModel.addError( indexOfTestStep );
498
499 long maxAssertionErrors = getMaxAssertionErrors();
500 if( maxAssertionErrors > 0 )
501 {
502 synchronized( assertionErrors )
503 {
504 assertionErrors.add( errorEntry );
505 while( assertionErrors.size() > maxAssertionErrors )
506 {
507 assertionErrors.remove( 0 ).discard();
508 }
509 }
510 }
511
512 added = true;
513 }
514 }
515 }
516
517
518 if( !added )
519 {
520 if( getTestCase().getDiscardOkResults() || getTestCase().getMaxResults() == 0 )
521 {
522 result.discard();
523 }
524 else if( getTestCase().getMaxResults() > 0 && testRunner instanceof WsdlTestCaseRunner )
525 {
526 ( ( WsdlTestCaseRunner )testRunner ).enforceMaxResults( getTestCase().getMaxResults() );
527 }
528 }
529 }
530 }
531
532 public LoadStrategy getLoadStrategy()
533 {
534 return loadStrategy;
535 }
536
537 public void setLoadStrategy( LoadStrategy loadStrategy )
538 {
539 this.loadStrategy.removeConfigurationChangeListener( loadStrategyListener );
540 removeLoadTestRunListener( this.loadStrategy );
541
542 this.loadStrategy = loadStrategy;
543 this.loadStrategy.addConfigurationChangeListener( loadStrategyListener );
544 addLoadTestRunListener( this.loadStrategy );
545
546 getConfig().getLoadStrategy().setType( loadStrategy.getType() );
547 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
548 }
549
550 private class LoadStrategyConfigurationChangeListener implements PropertyChangeListener
551 {
552 public void propertyChange( PropertyChangeEvent evt )
553 {
554 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
555 }
556 }
557
558 public LoadTestAssertion addAssertion( String type, String targetStep, boolean showConfig )
559 {
560 LoadTestAssertion assertion = LoadTestAssertionRegistry.createAssertion( type, this );
561 assertion.setTargetStep( targetStep );
562
563 if( assertion instanceof Configurable && showConfig )
564 {
565 if( !( ( Configurable )assertion ).configure() )
566 return null;
567 }
568
569 assertions.add( assertion );
570
571 getConfig().addNewAssertion().set( assertion.getConfiguration() );
572 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
573 fireAssertionAdded( assertion );
574
575 return assertion;
576 }
577
578 public void removeAssertion( LoadTestAssertion assertion )
579 {
580 int ix = assertions.indexOf( assertion );
581 if( ix >= 0 )
582 {
583 try
584 {
585 assertions.remove( ix );
586 fireAssertionRemoved( assertion );
587 }
588 finally
589 {
590 assertion.removePropertyChangeListener( configurationChangeListener );
591 assertion.release();
592 getConfig().removeAssertion( ix );
593 }
594 }
595 }
596
597 private void fireAssertionRemoved( LoadTestAssertion assertion )
598 {
599 if( !loadTestListeners.isEmpty() )
600 {
601 LoadTestListener[] l = loadTestListeners.toArray( new LoadTestListener[loadTestListeners.size()] );
602 for( LoadTestListener listener : l )
603 {
604 listener.assertionRemoved( assertion );
605 }
606 }
607 }
608
609 private void fireAssertionAdded( LoadTestAssertion assertion )
610 {
611 if( !loadTestListeners.isEmpty() )
612 {
613 LoadTestListener[] l = loadTestListeners.toArray( new LoadTestListener[loadTestListeners.size()] );
614 for( LoadTestListener listener : l )
615 {
616 listener.assertionAdded( assertion );
617 }
618 }
619 }
620
621 public int getAssertionCount()
622 {
623 return assertions.size();
624 }
625
626 public LoadTestAssertion getAssertionAt( int index )
627 {
628 return index < 0 || index >= assertions.size() ? null : assertions.get( index );
629 }
630
631 public LoadTestAssertion getAssertionByName( String name )
632 {
633 for( LoadTestAssertion assertion : assertions )
634 {
635 if( assertion.getName().equals( name ) )
636 {
637 return assertion;
638 }
639 }
640 return null;
641 }
642
643 private class ConfigurationChangePropertyListener implements PropertyChangeListener
644 {
645 public void propertyChange( PropertyChangeEvent evt )
646 {
647 int ix = assertions.indexOf( evt.getSource() );
648 if( ix >= 0 )
649 {
650 getConfig().getAssertionArray( ix ).set( assertions.get( ix ).getConfiguration() );
651 }
652 }
653 }
654
655 public LoadTestLog getLoadTestLog()
656 {
657 return loadTestLog;
658 }
659
660 public List<LoadTestAssertion> getAssertionList()
661 {
662 return assertions;
663 }
664
665 public void addLoadTestListener( LoadTestListener listener )
666 {
667 loadTestListeners.add( listener );
668 }
669
670 public void removeLoadTestListener( LoadTestListener listener )
671 {
672 loadTestListeners.remove( listener );
673 }
674
675 public void addLoadTestRunListener( LoadTestRunListener listener )
676 {
677 loadTestRunListeners.add( listener );
678 loadTestRunListenersArray = null;
679 }
680
681 public void removeLoadTestRunListener( LoadTestRunListener listener )
682 {
683 loadTestRunListeners.remove( listener );
684 loadTestRunListenersArray = null;
685 }
686
687 public LoadTestRunListener[] getLoadTestRunListeners()
688 {
689 if( loadTestRunListenersArray == null )
690 {
691 loadTestRunListenersArray = loadTestRunListeners
692 .toArray( new LoadTestRunListener[loadTestRunListeners.size()] );
693 }
694
695 return loadTestRunListenersArray;
696 }
697
698 /***
699 * Release internal objects so they can remove listeners
700 */
701
702 @Override
703 public void release()
704 {
705 super.release();
706
707 statisticsModel.release();
708 loadTestLog.release();
709
710 for( LoadTestAssertion assertion : assertions )
711 assertion.release();
712
713 loadTestRunListeners.clear();
714 loadTestListeners.clear();
715 }
716
717 public boolean isRunning()
718 {
719 return runner != null && runner.getStatus() == LoadTestRunner.Status.RUNNING;
720 }
721
722 public WsdlLoadTestRunner getRunner()
723 {
724 return runner;
725 }
726
727 public void resetConfigOnMove( LoadTestConfig config )
728 {
729 setConfig( config );
730
731 loadStrategy.updateConfig( config.getLoadStrategy().getConfig() );
732
733 List<LoadTestAssertionConfig> assertionList = config.getAssertionList();
734 for( int c = 0; c < assertionList.size(); c++ )
735 {
736 assertions.get( c ).updateConfiguration( assertionList.get( c ) );
737 }
738 }
739
740 public class StatisticsLogger implements Runnable
741 {
742 private boolean stopped;
743 private List<PrintWriter> writers = new ArrayList<PrintWriter>();
744 private long startTime;
745
746 public void run()
747 {
748 stopped = false;
749
750 while( !stopped && getStatisticsLogInterval() > 0 )
751 {
752 try
753 {
754 long statisticsInterval = getStatisticsLogInterval();
755 Thread.sleep( statisticsInterval );
756 if( !stopped )
757 {
758 logStatistics( "Interval" );
759 }
760 }
761 catch( InterruptedException e )
762 {
763 e.printStackTrace();
764 }
765 }
766 }
767
768 public void start()
769 {
770 new Thread( this, "Statistics Logger for LoadTest [" + getName() + "]" ).start();
771 }
772
773 public void init( LoadTestRunContext context )
774 {
775 writers.clear();
776
777 String statisticsLogFolder = context.expand( getStatisticsLogFolder() );
778 if( StringUtils.isNullOrEmpty( statisticsLogFolder ) )
779 return;
780
781 File folder = new File( statisticsLogFolder );
782 if( !folder.exists() )
783 {
784 if( !folder.mkdirs() )
785 {
786 SoapUI
787 .logError( new Exception( "Failed to create statistics log folder [" + statisticsLogFolder + "]" ) );
788 return;
789 }
790 }
791
792 for( int c = 0; c < testCase.getTestStepCount(); c++ )
793 {
794 try
795 {
796 WsdlTestStep testStep = testCase.getTestStepAt( c );
797 String fileName = StringUtils.createFileName( testStep.getName(), '_' ) + ".log";
798 PrintWriter writer = new PrintWriter( new File( folder, fileName ) );
799 writers.add( writer );
800 addHeaders( writer );
801 }
802 catch( FileNotFoundException e )
803 {
804 e.printStackTrace();
805 writers.add( null );
806 }
807 }
808
809
810 try
811 {
812 String fileName = StringUtils.createFileName( testCase.getName(), '_' ) + ".log";
813 writers.add( new PrintWriter( new File( folder, fileName ) ) );
814 }
815 catch( FileNotFoundException e )
816 {
817 e.printStackTrace();
818 }
819
820 startTime = System.nanoTime();
821 }
822
823 private void addHeaders( PrintWriter writer )
824 {
825 writer.print( "date,threads,elapsed,min,max,avg,last,cnt,tps,bytes,bps,err,reason\n" );
826 }
827
828 public void finish()
829 {
830 stopped = true;
831
832 logStatistics( "Finished" );
833 for( PrintWriter writer : writers )
834 {
835 if( writer != null )
836 writer.close();
837 }
838 }
839
840 private synchronized void logStatistics( String trigger )
841 {
842 if( writers.isEmpty() )
843 return;
844
845 long timestamp = System.nanoTime();
846 String elapsedString = String.valueOf( ( timestamp - startTime ) / 1000000 );
847 String dateString = new Date().toString();
848 String threadCountString = String.valueOf( getThreadCount() );
849
850 StringList[] snapshot = statisticsModel.getSnapshot();
851 for( int c = 0; c < snapshot.length; c++ )
852 {
853 PrintWriter writer = writers.get( c );
854 if( writer == null )
855 continue;
856
857 StringList values = snapshot[c];
858 writer.append( dateString ).append( ',' );
859 writer.append( threadCountString ).append( ',' );
860 writer.append( elapsedString );
861
862 for( String value : values )
863 {
864 writer.append( ',' ).append( value );
865 }
866
867 writer.append( ',' ).append( trigger ).append( '\n' );
868 writer.flush();
869 }
870 }
871 }
872
873 public void setSetupScript( String script )
874 {
875 String oldScript = getSetupScript();
876
877 if( !getConfig().isSetSetupScript() )
878 getConfig().addNewSetupScript();
879
880 getConfig().getSetupScript().setStringValue( script );
881 if( setupScriptEngine != null )
882 setupScriptEngine.setScript( script );
883
884 notifyPropertyChanged( SETUP_SCRIPT_PROPERTY, oldScript, script );
885 }
886
887 public String getSetupScript()
888 {
889 return getConfig().isSetSetupScript() ? getConfig().getSetupScript().getStringValue() : null;
890 }
891
892 public void setTearDownScript( String script )
893 {
894 String oldScript = getTearDownScript();
895
896 if( !getConfig().isSetTearDownScript() )
897 getConfig().addNewTearDownScript();
898
899 getConfig().getTearDownScript().setStringValue( script );
900 if( tearDownScriptEngine != null )
901 tearDownScriptEngine.setScript( script );
902
903 notifyPropertyChanged( TEARDOWN_SCRIPT_PROPERTY, oldScript, script );
904 }
905
906 public String getTearDownScript()
907 {
908 return getConfig().isSetTearDownScript() ? getConfig().getTearDownScript().getStringValue() : null;
909 }
910
911 public Object runSetupScript( LoadTestRunContext runContext, LoadTestRunner runner ) throws Exception
912 {
913 String script = getSetupScript();
914 if( StringUtils.isNullOrEmpty( script ) )
915 return null;
916
917 if( setupScriptEngine == null )
918 {
919 setupScriptEngine = SoapUIScriptEngineRegistry.create( this );
920 setupScriptEngine.setScript( script );
921 }
922
923 setupScriptEngine.setVariable( "context", runContext );
924 setupScriptEngine.setVariable( "loadTestRunner", runner );
925 setupScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
926 return setupScriptEngine.run();
927 }
928
929 public Object runTearDownScript( LoadTestRunContext runContext, LoadTestRunner runner ) throws Exception
930 {
931 String script = getTearDownScript();
932 if( StringUtils.isNullOrEmpty( script ) )
933 return null;
934
935 if( tearDownScriptEngine == null )
936 {
937 tearDownScriptEngine = SoapUIScriptEngineRegistry.create( this );
938 tearDownScriptEngine.setScript( script );
939 }
940
941 tearDownScriptEngine.setVariable( "context", runContext );
942 tearDownScriptEngine.setVariable( "loadTestRunner", runner );
943 tearDownScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
944 return tearDownScriptEngine.run();
945 }
946
947 public int getStrategyInterval()
948 {
949 return getConfig().getStrategyInterval();
950 }
951
952 public void setStrategyInterval( int interval )
953 {
954 getConfig().setStrategyInterval( interval );
955 }
956
957 public boolean getUpdateStatisticsPerTestStep()
958 {
959 return getConfig().getUpdateStatisticsPerTestStep();
960 }
961
962 public void setUpdateStatisticsPerTestStep( boolean updateStatisticsPerTestStep )
963 {
964 getConfig().setUpdateStatisticsPerTestStep( updateStatisticsPerTestStep );
965 }
966
967 public TestRunner run( StringToObjectMap context, boolean async )
968 {
969
970 return null;
971 }
972 }