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