View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.loadtest;
14  
15  import com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.config.LoadTestLimitTypesConfig;
17  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
18  import com.eviware.soapui.impl.wsdl.actions.loadtest.LoadTestOptionsAction;
19  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
20  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTestRunner;
21  import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics;
22  import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics.Statistic;
23  import com.eviware.soapui.impl.wsdl.loadtest.data.actions.ExportStatisticsAction;
24  import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
25  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
26  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
27  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
28  import com.eviware.soapui.impl.wsdl.panels.support.MockLoadTestRunContext;
29  import com.eviware.soapui.impl.wsdl.panels.support.MockLoadTestRunner;
30  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
31  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
32  import com.eviware.soapui.model.ModelItem;
33  import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
34  import com.eviware.soapui.model.testsuite.LoadTestRunContext;
35  import com.eviware.soapui.model.testsuite.LoadTestRunListener;
36  import com.eviware.soapui.model.testsuite.LoadTestRunner;
37  import com.eviware.soapui.model.testsuite.LoadTestRunner.Status;
38  import com.eviware.soapui.support.UISupport;
39  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
40  import com.eviware.soapui.support.components.*;
41  import com.eviware.soapui.ui.desktop.DesktopPanel;
42  import com.eviware.soapui.ui.support.DesktopListenerAdapter;
43  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
44  import com.jgoodies.forms.builder.ButtonBarBuilder;
45  
46  import javax.swing.*;
47  import javax.swing.event.ChangeEvent;
48  import javax.swing.event.ChangeListener;
49  import java.awt.*;
50  import java.awt.event.ActionEvent;
51  import java.awt.event.ItemEvent;
52  import java.awt.event.ItemListener;
53  import java.beans.PropertyChangeEvent;
54  import java.beans.PropertyChangeListener;
55  
56  /***
57   * Desktop panel for LoadTests
58   * 
59   * @author Ole.Matzura
60   */
61  
62  public class WsdlLoadTestDesktopPanel extends ModelItemDesktopPanel<WsdlLoadTest> implements PropertyChangeListener
63  {
64  	private static final String SECONDS_LIMIT = "Seconds";
65  	private static final String RUNS_LIMIT = "Total Runs";
66  	private JPanel contentPanel;
67  	@SuppressWarnings("unused")
68  	private JSplitPane mainSplit;
69  	@SuppressWarnings("unused")
70  	private JTabbedPane mainTabs;
71  	@SuppressWarnings("unused")
72  	private JPanel graphPanel;
73  	private JButton runButton;
74  	private JButton cancelButton;
75  	private JButton statisticsGraphButton;
76  	private WsdlLoadTestRunner runner;
77  	private JSpinner threadsSpinner;
78  	private LoadTestRunListener internalLoadTestListener = new InternalLoadTestListener();
79  	private JComboBox strategyCombo;
80  	private JPanel loadStrategyConfigurationPanel;
81  	private JButton resetButton;
82  	private LoadTestLog loadTestLog;
83  	private JButton optionsButton;
84  	private JButton testTimesGraphButton;
85  	@SuppressWarnings("unused")
86  	private Object limit;
87  	private JSpinner limitSpinner;
88  	private JComboBox limitTypeCombo;
89  	private SpinnerNumberModel limitSpinnerModel;
90  	private JProgressBar progressBar;
91  	private long loadTestStartTime;
92  	private StatisticsDesktopPanel statisticsDesktopPanel;
93  	private StatisticsHistoryDesktopPanel statisticsHistoryDesktopPanel;
94  	
95  	public boolean loadTestIsRunning;
96  	private InternalDesktopListener desktopListener;
97  	private JButton exportButton;
98  	private JLoadTestAssertionsTable assertionsTable;
99  	private JStatisticsTable statisticsTable;
100 	private GroovyEditorComponent tearDownGroovyEditor;
101 	private GroovyEditorComponent setupGroovyEditor;
102 	
103 	public WsdlLoadTestDesktopPanel(WsdlLoadTest loadTest)
104 	{
105 		super( loadTest );
106 		
107 		loadTestLog = loadTest.getLoadTestLog();
108 		loadTest.addPropertyChangeListener( this );
109 		loadTest.addLoadTestRunListener( internalLoadTestListener );
110 		
111 		desktopListener = new InternalDesktopListener();
112 	   SoapUI.getDesktop().addDesktopListener( desktopListener );
113 		
114 		buildUI();
115 	}
116 
117 	private void buildUI()
118 	{
119 		contentPanel = new JPanel( new BorderLayout());
120 		
121 		contentPanel.add( buildToolbar(), BorderLayout.NORTH );
122 		contentPanel.add( buildContent(), BorderLayout.CENTER );
123 		
124 		contentPanel.setPreferredSize( new Dimension( 600, 500 ));
125 	}
126 
127 	private JComponent buildContent()
128 	{
129 		JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( buildStatistics() );
130 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildLog(), "LoadTest Log", "The current LoadTest execution log", true ) );
131 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildAssertions(), "LoadTest Assertions", "The assertions for this LoadTest", true ));
132 		inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script", "Script to run before tunning a TestCase" ) );
133 		inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script", "Script to run after a TestCase Run" ) );
134 		inspectorPanel.setDefaultDividerLocation( 0.6F );
135 		inspectorPanel.setCurrentInspector( "LoadTest Log" );
136 		
137 		return inspectorPanel.getComponent();
138 	}
139 
140 	protected GroovyEditorComponent buildTearDownScriptPanel()
141 	{
142 		tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
143 		return tearDownGroovyEditor;
144 	}
145 
146 	protected GroovyEditorComponent buildSetupScriptPanel()
147 	{
148 		setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
149 		return setupGroovyEditor;
150 	}
151 	
152 	protected JComponent buildStatistics(	)
153 	{
154 		statisticsTable = new JStatisticsTable( getModelItem() );
155 		return statisticsTable;
156 	}
157 
158 	protected JComponent buildLog()
159 	{
160 		JLoadTestLogTable loadTestLogTable = new JLoadTestLogTable( loadTestLog );
161 		return loadTestLogTable;
162 	}
163 
164 	protected JComponent buildAssertions()
165 	{
166 		assertionsTable = new JLoadTestAssertionsTable( getModelItem() );
167 		return assertionsTable;
168 	}
169 
170 	protected JComponent buildToolbar()
171 	{
172 		WsdlLoadTest loadTest = getModelItem();
173 		
174 		JXToolBar toolbar = UISupport.createToolbar();
175 		
176 		//ButtonBarBuilder builder = new ButtonBarBuilder();
177       runButton = UISupport.createToolbarButton( new RunLoadTestAction());
178       cancelButton = UISupport.createToolbarButton( new CancelRunTestCaseAction(), false );
179       resetButton = UISupport.createToolbarButton( new ResetAction() );
180       exportButton = UISupport.createToolbarButton( new ExportStatisticsAction( loadTest.getStatisticsModel() ) );
181       
182       statisticsGraphButton = UISupport.createToolbarButton( new ShowStatisticsGraphAction() );
183       testTimesGraphButton = UISupport.createToolbarButton( new ShowTestTimesGraphAction() );
184       
185       statisticsGraphButton.setEnabled( getModelItem().getHistoryLimit() != 0 );
186 		testTimesGraphButton.setEnabled( getModelItem().getHistoryLimit() != 0  );
187       
188       AbstractAction optionsDelegate = SwingActionDelegate.createDelegate( LoadTestOptionsAction.SOAPUI_ACTION_ID, loadTest );
189       optionsDelegate.putValue( Action.SMALL_ICON,	UISupport.createImageIcon( "/options.gif" ));
190 		optionsButton = UISupport.createToolbarButton( optionsDelegate );
191       
192       strategyCombo = new JComboBox( LoadStrategyRegistry.getInstance().getStrategies() );
193       strategyCombo.setToolTipText( "Selects which LoadTest Strategy to use" );
194       UISupport.setPreferredHeight( strategyCombo, 18 );
195 		strategyCombo.setSelectedItem( loadTest.getLoadStrategy().getType());
196 		strategyCombo.addItemListener( new ItemListener() 
197 				{
198 					public void itemStateChanged(ItemEvent e)
199 					{
200 						Object item = e.getItem();
201 						if( item == null ) 
202 							return;
203 						
204 						setLoadStrategy(item.toString());
205 					}} );
206       
207 		toolbar.add( runButton );
208 		toolbar.add( cancelButton );
209 		toolbar.add( statisticsGraphButton );
210 		toolbar.add( testTimesGraphButton );
211 		toolbar.add( resetButton );
212 		toolbar.add( exportButton );
213      
214 		toolbar.add( optionsButton );
215 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.LOADTESTEDITOR_HELP_URL )));
216 		toolbar.add( Box.createHorizontalGlue() );
217 		buildLimitBar( toolbar );
218       toolbar.addSeparator();
219 		
220 		progressBar = new JProgressBar( 0, 100 );
221 		progressBar.setPreferredSize( new Dimension( 70, 20 ));
222 
223 		toolbar.addFixed( progressBar );
224 		
225 		ButtonBarBuilder builder = new ButtonBarBuilder();
226 		
227 		builder.addFixed( new JLabel( "Threads:" ));
228       builder.addRelatedGap();
229 		
230 		threadsSpinner = new JSpinner( new SpinnerNumberModel(getModelItem().getThreadCount(), 1, 9999, 1) );
231 		threadsSpinner.setToolTipText( "Sets the number of threads (\"Virtual Users\") to run this TestCase" );
232 		UISupport.setPreferredHeight( threadsSpinner, 18 );
233       threadsSpinner.getModel().addChangeListener( new ChangeListener() {
234 
235 			public void stateChanged(ChangeEvent e)
236 			{
237 				getModelItem().setThreadCount( ((SpinnerNumberModel) threadsSpinner.getModel()).getNumber().intValue() );
238 			}} );
239       
240 		builder.addFixed( threadsSpinner);
241 		builder.addUnrelatedGap();
242 		
243 		LoadStrategy loadStrategy = loadTest.getLoadStrategy();
244 		
245 		builder.addFixed( new JLabel( "Strategy" ));
246       builder.addRelatedGap();
247       builder.addFixed( strategyCombo );
248       builder.addUnrelatedGap();
249 		
250       loadStrategyConfigurationPanel = new JPanel( new BorderLayout() );
251 		loadStrategyConfigurationPanel.add( loadStrategy.getConfigurationPanel(), BorderLayout.CENTER );
252       
253       builder.addFixed( loadStrategyConfigurationPanel );
254       builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
255       
256 		return UISupport.buildPanelWithToolbar( toolbar, builder.getPanel() );
257 	}
258 	
259 	public void buildLimitBar( JXToolBar toolbar )
260 	{
261 		limitSpinnerModel = new SpinnerNumberModel(getModelItem().getTestLimit(), 0, Long.MAX_VALUE, 100 );
262 		
263 		limitSpinner = new JSpinner( limitSpinnerModel );
264 		limitSpinner.setPreferredSize( new Dimension( 70, 20 ));
265 		limitSpinner.setToolTipText( "Sets the limit for this test; total number of requests or seconds to run" );
266 		limitSpinner.getModel().addChangeListener( new ChangeListener() {
267 
268 			public void stateChanged(ChangeEvent e)
269 			{
270 				int intValue = ((SpinnerNumberModel) limitSpinner.getModel()).getNumber().intValue();
271 				getModelItem().setTestLimit( intValue );
272 			}} );
273 		
274 		toolbar.addSeparator();
275 		toolbar.addFixed( new JLabel( "Limit:" ));
276 		toolbar.addSeparator();
277 		toolbar.addFixed(limitSpinner );
278 		toolbar.addSeparator();
279 		
280 		limitTypeCombo = new JComboBox( new String[] { WsdlLoadTestDesktopPanel.RUNS_LIMIT, WsdlLoadTestDesktopPanel.SECONDS_LIMIT});
281 		
282 		if( getModelItem().getLimitType() == LoadTestLimitTypesConfig.TIME )
283 			limitTypeCombo.setSelectedIndex( 1 );
284 		
285 		toolbar.addFixed( limitTypeCombo);
286 		toolbar.addSeparator();
287 		
288 		limitTypeCombo.addItemListener( new ItemListener() 
289 		{
290 			public void itemStateChanged(ItemEvent e)
291 			{
292 				Object item = e.getItem();
293 				if( WsdlLoadTestDesktopPanel.RUNS_LIMIT.equals( item ))
294 				{
295 					getModelItem().setLimitType( LoadTestLimitTypesConfig.COUNT );
296 				}
297 				else if( WsdlLoadTestDesktopPanel.SECONDS_LIMIT.equals( item ))
298 				{
299 					getModelItem().setLimitType( LoadTestLimitTypesConfig.TIME );
300 				}
301 			}} );
302 	}
303 
304 	public boolean onClose( boolean canCancel )
305 	{
306 		if( runner != null && runner.getStatus() == Status.RUNNING )
307 		{
308 			if( !UISupport.confirm( "Running test will be canceled when closing window. Close anyway?", "Close LoadTest" ))
309 				return false;
310 		}
311 		
312 		getModelItem().removeLoadTestRunListener( internalLoadTestListener );
313 		getModelItem().removePropertyChangeListener( this );
314 		getModelItem().getStatisticsModel().reset();
315 		
316 		if( runner != null && runner.getStatus() == Status.RUNNING )
317 			runner.cancel( "closing window" );
318 		
319 		if( statisticsDesktopPanel != null )
320 			SoapUI.getDesktop().closeDesktopPanel( statisticsDesktopPanel );
321 		
322 		if( statisticsHistoryDesktopPanel != null )
323 			SoapUI.getDesktop().closeDesktopPanel( statisticsHistoryDesktopPanel );
324 		
325 		assertionsTable.release();
326 		loadStrategyConfigurationPanel.removeAll();
327 		SoapUI.getDesktop().removeDesktopListener( desktopListener );
328 		
329 		statisticsTable.release();
330 		
331 		return release();
332 	}
333 
334 	public JComponent getComponent()
335 	{
336 		return contentPanel;
337 	}
338 
339    private final class InternalDesktopListener extends DesktopListenerAdapter
340 	{
341 		public void desktopPanelClosed(DesktopPanel desktopPanel)
342 		{
343 			if( desktopPanel == statisticsDesktopPanel )
344 				statisticsDesktopPanel = null;
345 			else if( desktopPanel == statisticsHistoryDesktopPanel )
346 				statisticsHistoryDesktopPanel = null;
347 		}
348 	}
349 
350 	public class RunLoadTestAction extends AbstractAction
351    {
352 		public RunLoadTestAction()
353       {
354          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif"));
355          putValue( Action.SHORT_DESCRIPTION, "Runs this LoadTest" );
356       }
357 
358 		public void actionPerformed(ActionEvent e)
359 		{
360 			WsdlLoadTest loadtest = getModelItem();
361 			if( loadtest.getTestCase().getTestStepCount() == 0 )
362 			{
363 				UISupport.showErrorMessage( "Missing TestSteps for testing!");
364 				return;
365 			}
366 			
367 			if( loadtest.getLimitType() == LoadTestLimitTypesConfig.COUNT && 
368 				 loadtest.getTestLimit() < loadtest.getThreadCount() )
369 			{
370 				if( !UISupport.confirm( "The run limit is set to a lower count than number of threads\nRun Anyway?", 
371 							"Run LoadTest" ))
372 				{
373 					return;
374 				}
375 			}
376 			
377 			runButton.setEnabled( false );
378          runner = loadtest.run();
379 		}
380    }
381 
382    public class ResetAction extends AbstractAction
383    {
384 		public ResetAction()
385       {
386          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/reset_loadtest_statistics.gif"));
387          putValue( Action.SHORT_DESCRIPTION, "Resets statistics for this LoadTest" );
388       }
389 
390 		public void actionPerformed(ActionEvent e)
391 		{
392 			getModelItem().getStatisticsModel().reset();
393 		}
394    }
395    
396    public class ShowStatisticsGraphAction extends AbstractAction
397    {
398 		public ShowStatisticsGraphAction()
399       {
400          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stats_graph.gif"));
401          putValue( Action.SHORT_DESCRIPTION, "Shows the statistics graph" );
402       }
403 
404 		public void actionPerformed(ActionEvent e)
405 		{
406 			if( statisticsDesktopPanel == null )
407 				statisticsDesktopPanel = new StatisticsDesktopPanel( getModelItem() );
408 			
409          UISupport.showDesktopPanel( statisticsDesktopPanel );
410 		}
411    }
412 
413    public class ShowTestTimesGraphAction extends AbstractAction
414    {
415 		public ShowTestTimesGraphAction()
416       {
417          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/samples_graph.gif"));
418          putValue( Action.SHORT_DESCRIPTION, "Shows the Statistics History graph" );
419       }
420 
421 		public void actionPerformed(ActionEvent e)
422 		{
423 			if( statisticsHistoryDesktopPanel == null )
424 				statisticsHistoryDesktopPanel = new StatisticsHistoryDesktopPanel( getModelItem() );
425 			
426          UISupport.showDesktopPanel( statisticsHistoryDesktopPanel );
427 		}
428    }
429    
430    public class CancelRunTestCaseAction extends AbstractAction
431    {
432 
433 		public CancelRunTestCaseAction()
434       {
435          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif"));
436          putValue( Action.SHORT_DESCRIPTION, "Stops running this LoadTest" );
437       }
438       
439 		public void actionPerformed(ActionEvent e)
440 		{
441       	if( runner != null )
442       	{
443       		runner.cancel( "Canceled" );
444       		cancelButton.setEnabled( false );
445       	}
446       }
447    }
448 
449    public boolean dependsOn(ModelItem modelItem)
450 	{
451    	WsdlLoadTest loadTest = getModelItem();
452    	
453 		return modelItem == loadTest || modelItem == loadTest.getTestCase() || 
454 			modelItem == loadTest.getTestCase().getTestSuite() || 
455 			modelItem == loadTest.getTestCase().getTestSuite().getProject();
456 	}
457 	
458 	public void setLoadStrategy(String type)
459 	{
460 		LoadStrategyFactory factory = LoadStrategyRegistry.getInstance().getFactory( type );
461 		LoadStrategy loadStrategy = factory.create( getModelItem() );
462 		getModelItem().setLoadStrategy( loadStrategy );
463 		loadStrategyConfigurationPanel.removeAll();
464 		loadStrategyConfigurationPanel.add( loadStrategy.getConfigurationPanel(), BorderLayout.CENTER );
465 		loadStrategyConfigurationPanel.revalidate();
466 	}
467 
468 	private class InternalLoadTestListener extends LoadTestRunListenerAdapter
469 	{
470 		public void beforeLoadTest( LoadTestRunner testRunner, LoadTestRunContext context )
471 		{
472          loadTestLog.clear();
473 			
474 			loadTestStartTime = System.currentTimeMillis();
475 			loadTestIsRunning = true;
476 			if( getModelItem().getTestLimit() > 0 )
477 			{
478 				progressBar.setValue(0);
479 				progressBar.setString( null );
480 			}
481 			else
482 			{
483 				progressBar.setString("...");
484 			}
485 			
486 			progressBar.setStringPainted(true);
487 
488 			runButton.setEnabled( false );
489 			cancelButton.setEnabled( true );
490 			strategyCombo.setEnabled( false );
491 			limitTypeCombo.setEnabled( false );
492 			optionsButton.setEnabled( false );
493 			threadsSpinner.setEnabled( getModelItem().getLoadStrategy().allowThreadCountChangeDuringRun() );
494 			
495 			new Thread( new ProgressBarUpdater(), getModelItem().getName() + " ProgressBarUpdater" ).start();
496 		}
497 
498 		public void afterLoadTest( LoadTestRunner testRunner, LoadTestRunContext context )
499 		{
500 			runButton.setEnabled( true );
501 			
502 			cancelButton.setEnabled( false );
503 			strategyCombo.setEnabled( true );
504 			limitTypeCombo.setEnabled( true );
505 			threadsSpinner.setEnabled( true );
506 			optionsButton.setEnabled( true );
507 			
508 			runner = null;
509 			loadTestIsRunning = false;
510 			
511 			if( progressBar.isIndeterminate() )
512 			{
513 				progressBar.setIndeterminate( false );
514 				progressBar.setValue(0);
515 			}
516 			else if( testRunner.getStatus() == Status.FINISHED )
517 			{
518 				progressBar.setValue( 100 );
519 			}
520 			
521 			if( testRunner.getStatus() == Status.FAILED )
522 			{
523 				UISupport.showErrorMessage( "LoadTest failed; " + testRunner.getReason() );
524 			}
525 		}
526 		
527 		
528 	}
529 
530 	private class ProgressBarUpdater implements Runnable
531 	{
532 		public void run()
533 		{
534 			while( true )
535 			{
536 				if( !loadTestIsRunning )
537 					break;
538 
539 				if( getModelItem().getTestLimit() == 0 )
540 				{
541 					if( loadTestIsRunning && !progressBar.isIndeterminate())
542 					{
543 						progressBar.setIndeterminate( true );
544 						progressBar.setString("...");
545 					}
546 				}
547 				else if( getModelItem().getLimitType() == LoadTestLimitTypesConfig.TIME )
548 				{
549 					if( loadTestIsRunning && progressBar.isIndeterminate())
550 					{
551 						progressBar.setIndeterminate( false );
552 						progressBar.setString(null);
553 					}
554 					
555 					long timePassed = System.currentTimeMillis()-loadTestStartTime;
556 					int value = (int) ((timePassed*100)/(getModelItem().getTestLimit()*1000));
557 					progressBar.setValue( value );
558 				}
559 				else if( getModelItem().getLimitType() == LoadTestLimitTypesConfig.COUNT )
560 				{
561 					if( loadTestIsRunning && progressBar.isIndeterminate())
562 					{
563 						progressBar.setIndeterminate( false );
564 						progressBar.setString(null);
565 					}
566 					
567 					long counts = getModelItem().getStatisticsModel().getStatistic( LoadTestStatistics.TOTAL, Statistic.COUNT );
568 					if( counts > 0 )
569 						progressBar.setValue(  (int) ((counts*100)/getModelItem().getTestLimit()) );
570 				}
571 
572 				try
573 				{
574 					Thread.sleep( 500 );
575 				}
576 				catch (InterruptedException e)
577 				{
578 					SoapUI.logError( e );
579 				}
580 			}
581 		}
582 	}
583 
584 	public void propertyChange(PropertyChangeEvent evt)
585 	{
586 		if( evt.getPropertyName().equals( WsdlLoadTest.THREADCOUNT_PROPERTY ))
587 		{
588 			threadsSpinner.setValue( evt.getNewValue() );
589 		}
590 		else if( evt.getPropertyName().equals( WsdlLoadTest.HISTORYLIMIT_PROPERTY ))
591 		{
592 			long lng = (Long)evt.getNewValue();
593 			
594 			statisticsGraphButton.setEnabled( lng != 0 );
595 			testTimesGraphButton.setEnabled( lng != 0 );
596 		}
597 	}
598 	
599 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
600 	{
601 		@Override
602 		public Action createRunAction()
603 		{
604 			return new AbstractAction(){
605 
606 				public void actionPerformed( ActionEvent e )
607 				{
608 					try
609 					{
610 						MockLoadTestRunner mockTestRunner = new MockLoadTestRunner( getModelItem(), SoapUI.ensureGroovyLog() );
611 						getModelItem().runSetupScript( new MockLoadTestRunContext(mockTestRunner), mockTestRunner );
612 					}
613 					catch( Exception e1 )
614 					{
615 						UISupport.showErrorMessage( e1 );
616 					}
617 				}};
618 		}
619 
620 		public SetupScriptGroovyEditorModel()
621 		{
622 			super( new String[] {"log", "context", "loadTestRunner" }, getModelItem().getSettings(), "Setup" );
623 		}
624 		
625 		public String getScript()
626 		{
627 			return getModelItem().getSetupScript();
628 		}
629 
630 		public void setScript( String text )
631 		{
632 			getModelItem().setSetupScript( text );
633 		}
634 	}
635 	
636 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
637 	{
638 		@Override
639 		public Action createRunAction()
640 		{
641 			return new AbstractAction(){
642 
643 				public void actionPerformed( ActionEvent e )
644 				{
645 					try
646 					{
647 						MockLoadTestRunner mockTestRunner = new MockLoadTestRunner( getModelItem(), SoapUI.ensureGroovyLog() );
648 						getModelItem().runTearDownScript( new MockLoadTestRunContext(mockTestRunner), mockTestRunner );
649 					}
650 					catch( Exception e1 )
651 					{
652 						UISupport.showErrorMessage( e1 );
653 					}
654 				}};
655 		}
656 		
657 		public TearDownScriptGroovyEditorModel()
658 		{
659 			super( new String[] {"log", "context", "loadTestRunner" }, getModelItem().getSettings(), "TearDown" );
660 		}
661 		
662 		public String getScript()
663 		{
664 			return getModelItem().getTearDownScript();
665 		}
666 
667 		public void setScript( String text )
668 		{
669 			getModelItem().setTearDownScript( text );
670 		}
671 	}
672 }