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