View Javadoc

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