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.teststeps.SimplePathPropertySupport;
31 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
32 import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
33 import com.eviware.soapui.model.testsuite.*;
34 import com.eviware.soapui.model.testsuite.LoadTestRunner.Status;
35 import com.eviware.soapui.settings.HttpSettings;
36 import com.eviware.soapui.support.StringUtils;
37 import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
38 import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
39 import com.eviware.soapui.support.types.StringList;
40 import org.apache.log4j.Logger;
41
42 import java.beans.PropertyChangeEvent;
43 import java.beans.PropertyChangeListener;
44 import java.io.File;
45 import java.io.FileNotFoundException;
46 import java.io.PrintWriter;
47 import java.util.*;
48
49 /***
50 * TestCase implementation for LoadTests
51 *
52 * @todo add assertionFailed event to LoadTestListener
53 * @todo create and return LoadTestAssertionResult from load-test assertions
54 *
55 * @author Ole.Matzura
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
92 public WsdlLoadTest(WsdlTestCase testCase, LoadTestConfig config )
93 {
94 super( config, testCase, "/loadTest.gif" );
95
96 this.testCase = testCase;
97
98 if( getConfig().getThreadCount() < 1 )
99 getConfig().setThreadCount( 5 );
100
101 if( getConfig().getLimitType() == null )
102 {
103 getConfig().setLimitType( LoadTestLimitTypesConfig.TIME );
104 getConfig().setTestLimit( 60 );
105 }
106
107 if( !getConfig().isSetHistoryLimit() )
108 {
109 getConfig().setHistoryLimit( -1 );
110 }
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(), this );
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( true );
160
161 if( !getConfig().isSetMaxAssertionErrors())
162 getConfig().setMaxAssertionErrors( 100 );
163
164 if( getConfig().xgetCancelExcessiveThreads() == null )
165 getConfig().setCancelExcessiveThreads( true );
166
167 if( getConfig().xgetStrategyInterval() == null )
168 getConfig().setStrategyInterval( DEFAULT_STRATEGY_INTERVAL );
169
170 loadTestLog = new LoadTestLog( this );
171
172 for (LoadTestRunListener listener : SoapUI.getListenerRegistry().getListeners( LoadTestRunListener.class ))
173 {
174 addLoadTestRunListener(listener);
175 }
176
177
178 if( !getSettings().isSet( HttpSettings.CLOSE_CONNECTIONS ))
179 getSettings().setBoolean( HttpSettings.CLOSE_CONNECTIONS,
180 SoapUI.getSettings().getBoolean( HttpSettings.CLOSE_CONNECTIONS ) );
181 }
182
183 public LoadTestStatistics getStatisticsModel()
184 {
185 return statisticsModel;
186 }
187
188 public StatisticsLogger getStatisticsLogger()
189 {
190 return statisticsLogger;
191 }
192
193 public long getThreadCount()
194 {
195 return getConfig().getThreadCount();
196 }
197
198 public void setThreadCount( long threadCount )
199 {
200 long oldCount = getThreadCount();
201 if( threadCount < 1 || threadCount == oldCount )
202 return;
203
204 if( getLogStatisticsOnThreadChange() && isRunning() )
205 statisticsLogger.logStatistics( "ThreadCount change from " + oldCount + " to " + threadCount );
206
207 getConfig().setThreadCount( (int) threadCount );
208 notifyPropertyChanged( THREADCOUNT_PROPERTY, oldCount, threadCount );
209 }
210
211 public boolean getResetStatisticsOnThreadCountChange()
212 {
213 return getConfig().getResetStatisticsOnThreadCountChange();
214 }
215
216 public void setResetStatisticsOnThreadCountChange( boolean value )
217 {
218 getConfig().setResetStatisticsOnThreadCountChange( value );
219 }
220
221 public boolean getCancelOnReachedLimit()
222 {
223 return getConfig().getCancelOnReachedLimit();
224 }
225
226 public void setCancelOnReachedLimit( boolean value )
227 {
228 getConfig().setCancelOnReachedLimit( value );
229 }
230
231 public boolean getCancelExcessiveThreads()
232 {
233 return getConfig().getCancelExcessiveThreads();
234 }
235
236 public void setCancelExcessiveThreads( boolean value )
237 {
238 getConfig().setCancelExcessiveThreads( value );
239 }
240
241 public boolean getLogStatisticsOnThreadChange()
242 {
243 return getConfig().getLogStatisticsOnThreadChange();
244 }
245
246 public void setLogStatisticsOnThreadChange( boolean value )
247 {
248 getConfig().setLogStatisticsOnThreadChange( value );
249 }
250
251 public String getStatisticsLogFolder()
252 {
253 return getConfig().getStatisticsLogFolder();
254 }
255
256 public void setStatisticsLogFolder( String value )
257 {
258 getConfig().setStatisticsLogFolder( value );
259 }
260
261 public boolean getCalculateTPSOnTimePassed()
262 {
263 return getConfig().getCalculateTPSOnTimePassed();
264 }
265
266 public void setCalculateTPSOnTimePassed( boolean value )
267 {
268 getConfig().setCalculateTPSOnTimePassed( value );
269 }
270
271 public int getStartDelay()
272 {
273 return getConfig().getStartDelay();
274 }
275
276 public void setStartDelay( int startDelay )
277 {
278 if( startDelay < 0 )
279 return;
280
281 int oldDelay = getStartDelay();
282 getConfig().setStartDelay( startDelay );
283 notifyPropertyChanged( STARTDELAY_PROPERTY, oldDelay, startDelay );
284 }
285
286 public long getHistoryLimit()
287 {
288 return getConfig().getHistoryLimit();
289 }
290
291 public void setHistoryLimit( long historyLimit )
292 {
293 long oldLimit = getHistoryLimit();
294 getConfig().setHistoryLimit( historyLimit );
295 if( historyLimit == 0 )
296
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 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, assertion.getIcon(), threadIndex ));
436 statisticsModel.addError( LoadTestStatistics.TOTAL );
437 }
438 }
439 }
440 }
441
442 @Override
443 public void afterTestStep(LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext, TestStepResult result)
444 {
445 if( !assertions.isEmpty() )
446 {
447 boolean added = false;
448
449 for( LoadTestAssertion assertion : assertions )
450 {
451 String error = assertion.assertResult( loadTestRunner, context, result, testRunner, runContext );
452 if( error != null )
453 {
454 int indexOfTestStep = testRunner.getTestCase().getIndexOfTestStep( result.getTestStep() );
455 int threadIndex = 0;
456
457 try
458 {
459 threadIndex = Integer.parseInt( runContext.getProperty( "ThreadIndex" ).toString());
460 }
461 catch( Throwable t )
462 {}
463
464 LoadTestLogErrorEntry errorEntry = new LoadTestLogErrorEntry( assertion.getName(), error, result,
465 assertion.getIcon(), threadIndex );
466
467 loadTestLog.addEntry( errorEntry);
468 statisticsModel.addError( indexOfTestStep );
469
470 long maxAssertionErrors = getMaxAssertionErrors();
471 if( maxAssertionErrors > 0 )
472 {
473 synchronized( assertionErrors )
474 {
475 assertionErrors.add( errorEntry );
476 while( assertionErrors.size() > maxAssertionErrors )
477 {
478 assertionErrors.remove( 0 ).discard();
479 }
480 }
481 }
482
483 added = true;
484 }
485 }
486
487
488 if( !added )
489 {
490 result.discard();
491 }
492 }
493 else result.discard();
494 }
495 }
496
497 public LoadStrategy getLoadStrategy()
498 {
499 return loadStrategy;
500 }
501
502 public void setLoadStrategy( LoadStrategy loadStrategy )
503 {
504 this.loadStrategy.removeConfigurationChangeListener( loadStrategyListener );
505 removeLoadTestRunListener( this.loadStrategy );
506
507 this.loadStrategy = loadStrategy;
508 this.loadStrategy.addConfigurationChangeListener( loadStrategyListener );
509 addLoadTestRunListener( this.loadStrategy );
510
511 getConfig().getLoadStrategy().setType( loadStrategy.getType() );
512 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
513 }
514
515 private class LoadStrategyConfigurationChangeListener implements PropertyChangeListener
516 {
517 public void propertyChange(PropertyChangeEvent evt)
518 {
519 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
520 }
521 }
522
523 public LoadTestAssertion addAssertion( String type, String targetStep, boolean showConfig )
524 {
525 LoadTestAssertion assertion = LoadTestAssertionRegistry.createAssertion( type, this );
526 assertion.setTargetStep( targetStep );
527
528 if( assertion instanceof Configurable && showConfig )
529 {
530 if( !((Configurable)assertion).configure() )
531 return null;
532 }
533
534 assertions.add( assertion );
535
536 getConfig().addNewAssertion().set( assertion.getConfiguration() );
537 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
538 fireAssertionAdded( assertion );
539
540 return assertion;
541 }
542
543 public void removeAssertion( LoadTestAssertion assertion)
544 {
545 int ix = assertions.indexOf( assertion );
546 if( ix >= 0 )
547 {
548 try
549 {
550 assertions.remove( ix );
551 fireAssertionRemoved(assertion);
552 }
553 finally
554 {
555 assertion.removePropertyChangeListener( configurationChangeListener );
556 assertion.release();
557 getConfig().removeAssertion( ix );
558 }
559 }
560 }
561
562 private void fireAssertionRemoved(LoadTestAssertion assertion)
563 {
564 if( !loadTestListeners.isEmpty() )
565 {
566 LoadTestListener[] l = loadTestListeners.toArray( new LoadTestListener[loadTestListeners.size()] );
567 for( LoadTestListener listener : l )
568 {
569 listener.assertionRemoved( assertion );
570 }
571 }
572 }
573
574 private void fireAssertionAdded(LoadTestAssertion assertion)
575 {
576 if( !loadTestListeners.isEmpty() )
577 {
578 LoadTestListener[] l = loadTestListeners.toArray( new LoadTestListener[loadTestListeners.size()] );
579 for( LoadTestListener listener : l )
580 {
581 listener.assertionAdded( assertion );
582 }
583 }
584 }
585
586 public int getAssertionCount()
587 {
588 return assertions.size();
589 }
590
591 public LoadTestAssertion getAssertionAt( int index )
592 {
593 return index < 0 || index >= assertions.size() ? null : assertions.get( index );
594 }
595
596 private class ConfigurationChangePropertyListener implements PropertyChangeListener
597 {
598 public void propertyChange(PropertyChangeEvent evt)
599 {
600 int ix = assertions.indexOf( evt.getSource() );
601 if( ix >= 0 )
602 {
603 getConfig().getAssertionArray( ix ).set( assertions.get( ix ).getConfiguration() );
604 }
605 }
606 }
607
608 public LoadTestLog getLoadTestLog()
609 {
610 return loadTestLog;
611 }
612
613 public List<LoadTestAssertion> getAssertionList()
614 {
615 return assertions;
616 }
617
618 public void addLoadTestListener( LoadTestListener listener )
619 {
620 loadTestListeners.add( listener );
621 }
622
623 public void removeLoadTestListener( LoadTestListener listener )
624 {
625 loadTestListeners.remove( listener );
626 }
627
628 public void addLoadTestRunListener(LoadTestRunListener listener)
629 {
630 loadTestRunListeners.add( listener );
631 }
632
633 public void removeLoadTestRunListener(LoadTestRunListener listener)
634 {
635 loadTestRunListeners.remove( listener );
636 }
637
638 public LoadTestRunListener [] getLoadTestRunListeners()
639 {
640 return loadTestRunListeners.toArray( new LoadTestRunListener[loadTestRunListeners.size()] );
641 }
642
643 /***
644 * Release internal objects so they can remove listeners
645 */
646
647 @Override
648 public void release()
649 {
650 super.release();
651
652 statisticsModel.release();
653 loadTestLog.release();
654
655 for( LoadTestAssertion assertion : assertions )
656 assertion.release();
657
658 loadTestRunListeners.clear();
659 loadTestListeners.clear();
660 }
661
662 public boolean isRunning()
663 {
664 return runner != null && runner.getStatus() == LoadTestRunner.Status.RUNNING;
665 }
666
667 public WsdlLoadTestRunner getRunner()
668 {
669 return runner;
670 }
671
672 public void resetConfigOnMove( LoadTestConfig config )
673 {
674 setConfig( config );
675
676 loadStrategy.updateConfig( config.getLoadStrategy().getConfig() );
677
678 List<LoadTestAssertionConfig> assertionList = config.getAssertionList();
679 for( int c = 0; c < assertionList.size(); c++ )
680 {
681 assertions.get( c ).updateConfiguration( assertionList.get( c ) );
682 }
683 }
684
685 public class StatisticsLogger implements Runnable
686 {
687 private boolean stopped;
688 private List<PrintWriter> writers = new ArrayList<PrintWriter>();
689 private long startTime;
690
691 public void run()
692 {
693 stopped = false;
694
695 while( !stopped && getStatisticsLogInterval() > 0 )
696 {
697 try
698 {
699 long statisticsInterval = getStatisticsLogInterval();
700 Thread.sleep( statisticsInterval );
701 if( !stopped )
702 {
703 logStatistics( "Interval" );
704 }
705 }
706 catch( InterruptedException e )
707 {
708 e.printStackTrace();
709 }
710 }
711 }
712
713 public void start()
714 {
715 new Thread( this, "Statistics Logger for LoadTest [" + getName() + "]" ).start();
716 }
717
718 public void init(LoadTestRunContext context)
719 {
720 writers.clear();
721
722 String statisticsLogFolder = context.expand( getStatisticsLogFolder() );
723 if( StringUtils.isNullOrEmpty( statisticsLogFolder ))
724 return;
725
726 File folder = new File( statisticsLogFolder );
727 if( !folder.exists() )
728 {
729 if( !folder.mkdirs())
730 {
731 SoapUI.logError( new Exception( "Failed to create statistics log folder [" + statisticsLogFolder + "]") );
732 return;
733 }
734 }
735
736 for( int c = 0; c < testCase.getTestStepCount(); c++ )
737 {
738 try
739 {
740 WsdlTestStep testStep = testCase.getTestStepAt( c );
741 String fileName = StringUtils.createFileName( testStep.getName(), '_' ) + ".log";
742 PrintWriter writer = new PrintWriter( new File( folder, fileName ));
743 writers.add( writer );
744 addHeaders( writer );
745 }
746 catch( FileNotFoundException e )
747 {
748 e.printStackTrace();
749 writers.add( null );
750 }
751 }
752
753
754 try
755 {
756 String fileName = StringUtils.createFileName( testCase.getName(), '_' ) + ".log";
757 writers.add( new PrintWriter( new File( folder, fileName )) );
758 }
759 catch( FileNotFoundException e )
760 {
761 e.printStackTrace();
762 }
763
764 startTime = System.nanoTime();
765 }
766
767 private void addHeaders( PrintWriter writer )
768 {
769 writer.print( "date,threads,elapsed,min,max,avg,last,cnt,tps,bytes,bps,err,reason\n" );
770 }
771
772 public void finish()
773 {
774 stopped = true;
775
776 logStatistics( "Finished" );
777 for( PrintWriter writer : writers )
778 {
779 if( writer != null )
780 writer.close();
781 }
782 }
783
784 private synchronized void logStatistics( String trigger )
785 {
786 if( writers.isEmpty() )
787 return;
788
789 long timestamp = System.nanoTime();
790 String elapsedString = String.valueOf( (timestamp-startTime)/100000 );
791 String dateString = new Date().toString();
792 String threadCountString = String.valueOf( getThreadCount());
793
794 StringList[] snapshot = statisticsModel.getSnapshot();
795 for( int c = 0; c < snapshot.length; c++ )
796 {
797 PrintWriter writer = writers.get( c );
798 if( writer == null )
799 continue;
800
801 StringList values = snapshot[c];
802 writer.append( dateString ).append( ',' );
803 writer.append( threadCountString).append( ',' );
804 writer.append( elapsedString );
805
806 for( String value : values )
807 {
808 writer.append( ',' ).append( value );
809 }
810
811 writer.append( ',' ).append( trigger ).append( '\n' );
812 writer.flush();
813 }
814 }
815 }
816
817 public void setSetupScript( String script )
818 {
819 String oldScript = getSetupScript();
820
821 if( !getConfig().isSetSetupScript() )
822 getConfig().addNewSetupScript();
823
824 getConfig().getSetupScript().setStringValue( script );
825 if( setupScriptEngine != null )
826 setupScriptEngine.setScript( script );
827
828 notifyPropertyChanged( SETUP_SCRIPT_PROPERTY, oldScript, script );
829 }
830
831 public String getSetupScript()
832 {
833 return getConfig().isSetSetupScript() ? getConfig().getSetupScript().getStringValue() : null;
834 }
835
836 public void setTearDownScript( String script )
837 {
838 String oldScript = getTearDownScript();
839
840 if( !getConfig().isSetTearDownScript() )
841 getConfig().addNewTearDownScript();
842
843 getConfig().getTearDownScript().setStringValue( script );
844 if( tearDownScriptEngine != null )
845 tearDownScriptEngine.setScript( script );
846
847 notifyPropertyChanged( TEARDOWN_SCRIPT_PROPERTY, oldScript, script );
848 }
849
850 public String getTearDownScript()
851 {
852 return getConfig().isSetTearDownScript() ? getConfig().getTearDownScript().getStringValue() : null;
853 }
854
855 public Object runSetupScript( LoadTestRunContext runContext, LoadTestRunner runner ) throws Exception
856 {
857 String script = getSetupScript();
858 if( StringUtils.isNullOrEmpty( script ))
859 return null;
860
861 if( setupScriptEngine == null )
862 {
863 setupScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
864 setupScriptEngine.setScript( script );
865 }
866
867 setupScriptEngine.setVariable( "context", runContext );
868 setupScriptEngine.setVariable( "loadTestRunner", runner );
869 setupScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
870 return setupScriptEngine.run();
871 }
872
873 public Object runTearDownScript( LoadTestRunContext runContext, LoadTestRunner runner ) throws Exception
874 {
875 String script = getTearDownScript();
876 if( StringUtils.isNullOrEmpty( script ))
877 return null;
878
879 if( tearDownScriptEngine == null )
880 {
881 tearDownScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
882 tearDownScriptEngine.setScript( script );
883 }
884
885 tearDownScriptEngine.setVariable( "context", runContext );
886 tearDownScriptEngine.setVariable( "loadTestRunner", runner );
887 tearDownScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
888 return tearDownScriptEngine.run();
889 }
890
891 public int getStrategyInterval()
892 {
893 return getConfig().getStrategyInterval();
894 }
895
896 public void setStrategyInterval( int interval )
897 {
898 getConfig().setStrategyInterval(interval);
899 }
900
901 public boolean getUpdateStatisticsPerTestStep()
902 {
903 return getConfig().getUpdateStatisticsPerTestStep();
904 }
905
906 public void setUpdateStatisticsPerTestStep( boolean updateStatisticsPerTestStep )
907 {
908 getConfig().setUpdateStatisticsPerTestStep( updateStatisticsPerTestStep );
909 }
910 }