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.testcase;
14  
15  import java.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.HashSet;
18  import java.util.List;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import org.apache.log4j.Logger;
23  
24  import com.eviware.soapui.SoapUI;
25  import com.eviware.soapui.config.LoadTestConfig;
26  import com.eviware.soapui.config.TestCaseConfig;
27  import com.eviware.soapui.config.TestStepConfig;
28  import com.eviware.soapui.impl.wsdl.AbstractTestPropertyHolderWsdlModelItem;
29  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
30  import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
31  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
32  import com.eviware.soapui.impl.wsdl.loadtest.assertions.TestStepStatusAssertion;
33  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
34  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
35  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
36  import com.eviware.soapui.model.ModelItem;
37  import com.eviware.soapui.model.testsuite.LoadTest;
38  import com.eviware.soapui.model.testsuite.TestCase;
39  import com.eviware.soapui.model.testsuite.TestRunContext;
40  import com.eviware.soapui.model.testsuite.TestRunListener;
41  import com.eviware.soapui.model.testsuite.TestRunner;
42  import com.eviware.soapui.model.testsuite.TestStep;
43  import com.eviware.soapui.support.StringUtils;
44  import com.eviware.soapui.support.UISupport;
45  import com.eviware.soapui.support.action.swing.ActionList;
46  import com.eviware.soapui.support.action.swing.DefaultActionList;
47  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
48  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
49  import com.eviware.soapui.support.types.StringToObjectMap;
50  
51  /***
52   * TestCase implementation for WSDL projects
53   * 
54   * @author Ole.Matzura
55   */
56  
57  public class WsdlTestCase extends AbstractTestPropertyHolderWsdlModelItem<TestCaseConfig> implements TestCase
58  {
59  	private final static Logger logger = Logger.getLogger( WsdlTestCase.class );
60  	public final static String KEEP_SESSION_PROPERTY = WsdlTestCase.class.getName() + "@keepSession";
61  	public final static String FAIL_ON_ERROR_PROPERTY = WsdlTestCase.class.getName() + "@failOnError";
62  	public final static String FAIL_ON_ERRORS_PROPERTY = WsdlTestCase.class.getName() + "@failOnErrors";
63  	public final static String DISCARD_OK_RESULTS = WsdlTestCase.class.getName() + "@discardOkResults";
64  	public final static String SETUP_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@setupScript";
65  	public final static String TEARDOWN_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@tearDownScript";
66  	public static final String TIMEOUT_PROPERTY = WsdlTestCase.class.getName() + "@timeout";
67  	public static final String SEARCH_PROPERTIES_PROPERTY = WsdlTestCase.class.getName() + "@searchProperties";
68  
69  	private final WsdlTestSuite testSuite;
70  	private List<WsdlTestStep> testSteps = new ArrayList<WsdlTestStep>();
71  	private List<WsdlLoadTest> loadTests = new ArrayList<WsdlLoadTest>();
72  	private Set<TestRunListener> testRunListeners = new HashSet<TestRunListener>();
73  	private DefaultActionList createActions;
74  	private final boolean forLoadTest;
75  	private SoapUIScriptEngine setupScriptEngine;
76  	private SoapUIScriptEngine tearDownScriptEngine;
77  
78  	public WsdlTestCase( WsdlTestSuite testSuite, TestCaseConfig config, boolean forLoadTest )
79  	{
80  		super( config, testSuite, "/testCase.gif" );
81  
82  		this.testSuite = testSuite;
83  		this.forLoadTest = forLoadTest;
84  
85  		List<TestStepConfig> testStepConfigs = config.getTestStepList();
86  		for( TestStepConfig tsc : testStepConfigs )
87  		{
88  			WsdlTestStep testStep = createTestStepFromConfig( tsc );
89  			if( testStep != null )
90  			{
91  				ensureUniqueName( testStep );
92  				testSteps.add( testStep );
93  			}
94  		}
95  
96  		if( !forLoadTest )
97  		{
98  			List<LoadTestConfig> loadTestConfigs = config.getLoadTestList();
99  			for( LoadTestConfig tsc : loadTestConfigs )
100 			{
101 				WsdlLoadTest loadTest = new WsdlLoadTest( this, tsc );
102 				loadTests.add( loadTest );
103 			}
104 		}
105 
106 		// init default configs
107 		if( !config.isSetFailOnError() )
108 			config.setFailOnError( true );
109 
110 		if( !config.isSetFailTestCaseOnErrors() )
111 			config.setFailTestCaseOnErrors( true );
112 
113 		if( !config.isSetKeepSession() )
114 			config.setKeepSession( false );
115 
116 		for( TestRunListener listener : SoapUI.getListenerRegistry().getListeners( TestRunListener.class ) )
117 		{
118 			addTestRunListener( listener );
119 		}
120 
121 		if( !getConfig().isSetProperties() )
122 			getConfig().addNewProperties();
123 
124 		setPropertiesConfig( getConfig().getProperties() );
125 
126 		for( TestStep step : testSteps )
127 		{
128 			WsdlTestStep testStep = ( WsdlTestStep ) step;
129 			try
130 			{
131 				testStep.afterLoad();
132 			}
133 			catch( Exception e )
134 			{
135 				// TODO Auto-generated catch block
136 				e.printStackTrace();
137 			}
138 		}
139 	}
140 
141 	public boolean getKeepSession()
142 	{
143 		return getConfig().getKeepSession();
144 	}
145 
146 	public void setKeepSession( boolean keepSession )
147 	{
148 		boolean old = getKeepSession();
149 		if( old != keepSession )
150 		{
151 			getConfig().setKeepSession( keepSession );
152 			notifyPropertyChanged( KEEP_SESSION_PROPERTY, old, keepSession );
153 		}
154 	}
155 
156 	public void setSetupScript( String script )
157 	{
158 		String oldScript = getSetupScript();
159 
160 		if( !getConfig().isSetSetupScript() )
161 			getConfig().addNewSetupScript();
162 
163 		getConfig().getSetupScript().setStringValue( script );
164 		if( setupScriptEngine != null )
165 			setupScriptEngine.setScript( script );
166 
167 		notifyPropertyChanged( SETUP_SCRIPT_PROPERTY, oldScript, script );
168 	}
169 
170 	public String getSetupScript()
171 	{
172 		return getConfig().isSetSetupScript() ? getConfig().getSetupScript().getStringValue() : null;
173 	}
174 
175 	public void setTearDownScript( String script )
176 	{
177 		String oldScript = getTearDownScript();
178 
179 		if( !getConfig().isSetTearDownScript() )
180 			getConfig().addNewTearDownScript();
181 
182 		getConfig().getTearDownScript().setStringValue( script );
183 		if( tearDownScriptEngine != null )
184 			tearDownScriptEngine.setScript( script );
185 
186 		notifyPropertyChanged( TEARDOWN_SCRIPT_PROPERTY, oldScript, script );
187 	}
188 
189 	public String getTearDownScript()
190 	{
191 		return getConfig().isSetTearDownScript() ? getConfig().getTearDownScript().getStringValue() : null;
192 	}
193 
194 	public boolean getFailOnError()
195 	{
196 		return getConfig().getFailOnError();
197 	}
198 
199 	public boolean getFailTestCaseOnErrors()
200 	{
201 		return getConfig().getFailTestCaseOnErrors();
202 	}
203 
204 	public void setFailOnError( boolean failOnError )
205 	{
206 		boolean old = getFailOnError();
207 		if( old != failOnError )
208 		{
209 			getConfig().setFailOnError( failOnError );
210 			notifyPropertyChanged( FAIL_ON_ERROR_PROPERTY, old, failOnError );
211 		}
212 	}
213 
214 	public void setFailTestCaseOnErrors( boolean failTestCaseOnErrors )
215 	{
216 		boolean old = getFailTestCaseOnErrors();
217 		if( old != failTestCaseOnErrors )
218 		{
219 			getConfig().setFailTestCaseOnErrors( failTestCaseOnErrors );
220 			notifyPropertyChanged( FAIL_ON_ERRORS_PROPERTY, old, failTestCaseOnErrors );
221 		}
222 	}
223 
224 	public boolean getSearchProperties()
225 	{
226 		return getConfig().getSearchProperties();
227 	}
228 
229 	public void setSearchProperties( boolean searchProperties )
230 	{
231 		boolean old = getSearchProperties();
232 		if( old != searchProperties )
233 		{
234 			getConfig().setSearchProperties( searchProperties );
235 			notifyPropertyChanged( SEARCH_PROPERTIES_PROPERTY, old, searchProperties );
236 		}
237 	}
238 
239 	public boolean getDiscardOkResults()
240 	{
241 		return getConfig().getDiscardOkResults();
242 	}
243 
244 	public void setDiscardOkResults( boolean discardOkResults )
245 	{
246 		boolean old = getDiscardOkResults();
247 		if( old != discardOkResults )
248 		{
249 			getConfig().setDiscardOkResults( discardOkResults );
250 			notifyPropertyChanged( DISCARD_OK_RESULTS, old, discardOkResults );
251 		}
252 	}
253 
254 	private WsdlTestStep createTestStepFromConfig( TestStepConfig tsc )
255 	{
256 		WsdlTestStepFactory factory = WsdlTestStepRegistry.getInstance().getFactory( tsc.getType() );
257 		if( factory != null )
258 		{
259 			WsdlTestStep testStep = factory.buildTestStep( this, tsc, forLoadTest );
260 			return testStep;
261 		}
262 		else
263 		{
264 			logger.error( "Failed to create test step for [" + tsc.getName() + "]" );
265 			return null;
266 		}
267 	}
268 
269 	private boolean ensureUniqueName( WsdlTestStep testStep )
270 	{
271 		String name = testStep.getName();
272 		while( name == null || getTestStepByName( name ) != null )
273 		{
274 			if( name == null )
275 				name = testStep.getName();
276 			else
277 			{
278 				int cnt = 0;
279 
280 				while( getTestStepByName( name ) != null )
281 				{
282 					cnt++;
283 					name = testStep.getName() + " " + cnt;
284 				}
285 
286 				if( cnt == 0 )
287 					break;
288 			}
289 
290 			name = UISupport.prompt( "TestStep name must be unique, please specify new name for step\n" + "["
291 						+ testStep.getName() + "] in TestCase [" + getTestSuite().getProject().getName() + "->"
292 						+ getTestSuite().getName() + "->" + getName() + "]", "Change TestStep name", name );
293 
294 			if( name == null )
295 				return false;
296 		}
297 
298 		if( !name.equals( testStep.getName() ) )
299 			testStep.setName( name );
300 
301 		return true;
302 	}
303 
304 	public WsdlLoadTest addNewLoadTest( String name )
305 	{
306 		WsdlLoadTest loadTest = new WsdlLoadTest( this, getConfig().addNewLoadTest() );
307 		loadTest.setStartDelay( 0 );
308 		loadTest.setName( name );
309 		loadTests.add( loadTest );
310 
311 		loadTest.addAssertion( TestStepStatusAssertion.STEP_STATUS_TYPE, LoadTestAssertion.ANY_TEST_STEP, false );
312 
313 		( getTestSuite() ).fireLoadTestAdded( loadTest );
314 
315 		return loadTest;
316 	}
317 
318 	public void removeLoadTest( WsdlLoadTest loadTest )
319 	{
320 		int ix = loadTests.indexOf( loadTest );
321 
322 		loadTests.remove( ix );
323 
324 		try
325 		{
326 			( getTestSuite() ).fireLoadTestRemoved( loadTest );
327 		}
328 		finally
329 		{
330 			loadTest.release();
331 			getConfig().removeLoadTest( ix );
332 		}
333 	}
334 
335 	public WsdlTestSuite getTestSuite()
336 	{
337 		return testSuite;
338 	}
339 
340 	public WsdlTestStep cloneStep( WsdlTestStep testStep, String name )
341 	{
342 		return testStep.clone( this, name );
343 	}
344 
345 	public WsdlTestStep getTestStepAt( int index )
346 	{
347 		return testSteps.get( index );
348 	}
349 
350 	public int getTestStepCount()
351 	{
352 		return testSteps.size();
353 	}
354 
355 	public WsdlLoadTest getLoadTestAt( int index )
356 	{
357 		return loadTests.get( index );
358 	}
359 
360 	public LoadTest getLoadTestByName( String loadTestName )
361 	{
362 		return ( LoadTest ) getWsdlModelItemByName( loadTests, loadTestName );
363 	}
364 
365 	public int getLoadTestCount()
366 	{
367 		return loadTests.size();
368 	}
369 
370 	public WsdlTestStep addTestStep( TestStepConfig stepConfig )
371 	{
372 		return insertTestStep( stepConfig, -1 );
373 	}
374 
375 	public WsdlTestStep addTestStep( String type, String name )
376 	{
377 		TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this,
378 					name );
379 		if( newStepConfig != null )
380 		{
381 			return addTestStep( newStepConfig );
382 		}
383 		else
384 			return null;
385 	}
386 
387 	public WsdlTestStep insertTestStep( String type, String name, int index )
388 	{
389 		TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this,
390 					name );
391 		if( newStepConfig != null )
392 		{
393 			return insertTestStep( newStepConfig, index );
394 		}
395 		else
396 			return null;
397 	}
398 
399 	public WsdlTestStep importTestStep( WsdlTestStep testStep, String name, int index, boolean createCopy )
400 	{
401 		testStep.beforeSave();
402 		TestStepConfig newStepConfig = ( TestStepConfig ) testStep.getConfig().copy();
403 		newStepConfig.setName( name );
404 		if( createCopy && newStepConfig.isSetId() )
405 			newStepConfig.unsetId();
406 
407 		return insertTestStep( newStepConfig, index );
408 	}
409 
410 	public WsdlTestStep[] importTestSteps( WsdlTestStep[] testSteps, int index, boolean createCopies )
411 	{
412 		TestStepConfig[] newStepConfigs = new TestStepConfig[testSteps.length];
413 
414 		for( int c = 0; c < testSteps.length; c++ )
415 		{
416 			testSteps[c].beforeSave();
417 			newStepConfigs[c] = ( TestStepConfig ) testSteps[c].getConfig().copy();
418 			if( createCopies && newStepConfigs[c].isSetId() )
419 				newStepConfigs[c].unsetId();
420 		}
421 
422 		return insertTestSteps( newStepConfigs, index );
423 	}
424 
425 	public WsdlTestStep insertTestStep( TestStepConfig stepConfig, int ix )
426 	{
427 		TestStepConfig newStepConfig = ix == -1 ? getConfig().addNewTestStep() : getConfig().insertNewTestStep( ix );
428 		newStepConfig.set( stepConfig );
429 		WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
430 
431 		if( !ensureUniqueName( testStep ) )
432 			return null;
433 
434 		if( ix == -1 )
435 			testSteps.add( testStep );
436 		else
437 			testSteps.add( ix, testStep );
438 
439 		try
440 		{
441 			testStep.afterLoad();
442 		}
443 		catch( Exception e )
444 		{
445 			// TODO Auto-generated catch block
446 			e.printStackTrace();
447 		}
448 
449 		if( getTestSuite() != null )
450 			( getTestSuite() ).fireTestStepAdded( testStep, ix == -1 ? testSteps.size() - 1 : ix );
451 
452 		return testStep;
453 	}
454 
455 	public WsdlTestStep[] insertTestSteps( TestStepConfig[] stepConfig, int ix )
456 	{
457 		WsdlTestStep[] result = new WsdlTestStep[stepConfig.length];
458 
459 		for( int c = 0; c < stepConfig.length; c++ )
460 		{
461 			TestStepConfig newStepConfig = ix == -1 ? getConfig().addNewTestStep() : getConfig()
462 						.insertNewTestStep( ix + c );
463 			newStepConfig.set( stepConfig[c] );
464 			WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
465 
466 			if( !ensureUniqueName( testStep ) )
467 				return null;
468 
469 			if( ix == -1 )
470 				testSteps.add( testStep );
471 			else
472 				testSteps.add( ix + c, testStep );
473 
474 			result[c] = testStep;
475 		}
476 
477 		for( int c = 0; c < result.length; c++ )
478 		{
479 			try
480 			{
481 				result[c].afterLoad();
482 			}
483 			catch( Exception e )
484 			{
485 				e.printStackTrace();
486 			}
487 
488 			if( getTestSuite() != null )
489 				( getTestSuite() ).fireTestStepAdded( result[c], getIndexOfTestStep( result[c] ) );
490 		}
491 
492 		return result;
493 	}
494 
495 	public void removeTestStep( WsdlTestStep testStep )
496 	{
497 		int ix = testSteps.indexOf( testStep );
498 		if( ix == -1 )
499 		{
500 			logger.error( "TestStep [" + testStep.getName() + "] passed to removeTestStep in testCase [" + getName()
501 						+ "] not found" );
502 			return;
503 		}
504 
505 		testSteps.remove( ix );
506 
507 		try
508 		{
509 			( getTestSuite() ).fireTestStepRemoved( testStep, ix );
510 		}
511 		finally
512 		{
513 			testStep.release();
514 
515 			for( int c = 0; c < getConfig().sizeOfTestStepArray(); c++ )
516 			{
517 				if( testStep.getConfig() == getConfig().getTestStepArray( c ) )
518 				{
519 					getConfig().removeTestStep( c );
520 					break;
521 				}
522 			}
523 		}
524 	}
525 
526 	public WsdlTestCaseRunner run( StringToObjectMap properties, boolean async )
527 	{
528 		WsdlTestCaseRunner runner = new WsdlTestCaseRunner( this, properties );
529 		runner.start( async );
530 		return runner;
531 	}
532 
533 	public void addTestRunListener( TestRunListener listener )
534 	{
535 		if( listener == null )
536 			throw new RuntimeException( "listener must not be null" );
537 
538 		testRunListeners.add( listener );
539 	}
540 
541 	public void removeTestRunListener( TestRunListener listener )
542 	{
543 		testRunListeners.remove( listener );
544 	}
545 
546 	public TestRunListener[] getTestRunListeners()
547 	{
548 		return testRunListeners.toArray( new TestRunListener[testRunListeners.size()] );
549 	}
550 
551 	public Map<String, TestStep> getTestSteps()
552 	{
553 		Map<String, TestStep> result = new HashMap<String, TestStep>();
554 		for( TestStep testStep : testSteps )
555 			result.put( testStep.getName(), testStep );
556 
557 		return result;
558 	}
559 
560 	public Map<String, LoadTest> getLoadTests()
561 	{
562 		Map<String, LoadTest> result = new HashMap<String, LoadTest>();
563 		for( LoadTest loadTest : loadTests )
564 			result.put( loadTest.getName(), loadTest );
565 
566 		return result;
567 	}
568 
569 	public int getIndexOfTestStep( TestStep step )
570 	{
571 		return testSteps.indexOf( step );
572 	}
573 
574 	/***
575 	 * Moves a step by the specified offset, a bit awkward since xmlbeans doesn't
576 	 * support reordering of arrays, we need to create copies of the contained
577 	 * XmlObjects
578 	 * 
579 	 * @param ix
580 	 * @param offset
581 	 */
582 
583 	public void moveTestStep( int ix, int offset )
584 	{
585 		if( offset == 0 )
586 			return;
587 		WsdlTestStep step = testSteps.get( ix );
588 
589 		if( ix + offset >= testSteps.size() )
590 			offset = testSteps.size() - ix - 1;
591 
592 		testSteps.remove( ix );
593 		testSteps.add( ix + offset, step );
594 
595 		TestStepConfig[] configs = new TestStepConfig[testSteps.size()];
596 
597 		TestCaseConfig conf = getConfig();
598 		for( int c = 0; c < testSteps.size(); c++ )
599 		{
600 			if( offset > 0 )
601 			{
602 				if( c < ix )
603 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c ).copy();
604 				else if( c < ( ix + offset ) )
605 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c + 1 ).copy();
606 				else if( c == ix + offset )
607 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( ix ).copy();
608 				else
609 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c ).copy();
610 			}
611 			else
612 			{
613 				if( c < ix + offset )
614 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c ).copy();
615 				else if( c == ix + offset )
616 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( ix ).copy();
617 				else if( c <= ix )
618 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c - 1 ).copy();
619 				else
620 					configs[c] = ( TestStepConfig ) conf.getTestStepArray( c ).copy();
621 			}
622 		}
623 
624 		conf.setTestStepArray( configs );
625 		for( int c = 0; c < configs.length; c++ )
626 		{
627 			( testSteps.get( c ) ).resetConfigOnMove( conf.getTestStepArray( c ) );
628 		}
629 
630 		( getTestSuite() ).fireTestStepMoved( step, ix, offset );
631 	}
632 
633 	public int getIndexOfLoadTest( LoadTest loadTest )
634 	{
635 		return loadTests.indexOf( loadTest );
636 	}
637 
638 	public int getTestStepIndexByName( String stepName )
639 	{
640 		for( int c = 0; c < testSteps.size(); c++ )
641 		{
642 			if( testSteps.get( c ).getName().equals( stepName ) )
643 				return c;
644 		}
645 
646 		return -1;
647 	}
648 
649 	public TestStep findPreviousStepOfType( TestStep referenceStep, Class stepClass )
650 	{
651 		int currentStepIndex = getIndexOfTestStep( referenceStep );
652 		int ix = currentStepIndex - 1;
653 		while( ix >= 0 && !getTestStepAt( ix ).getClass().equals( stepClass ) )
654 		{
655 			ix--;
656 		}
657 
658 		return ix < 0 ? null : getTestStepAt( ix );
659 	}
660 
661 	public TestStep findNextStepOfType( TestStep referenceStep, Class stepClass )
662 	{
663 		int currentStepIndex = getIndexOfTestStep( referenceStep );
664 		int ix = currentStepIndex + 1;
665 		while( ix < getTestStepCount() && !getTestStepAt( ix ).getClass().equals( stepClass ) )
666 		{
667 			ix++;
668 		}
669 
670 		return ix >= getTestStepCount() ? null : getTestStepAt( ix );
671 	}
672 
673 	public List<TestStep> getTestStepList()
674 	{
675 		List<TestStep> result = new ArrayList<TestStep>();
676 		for( TestStep step : testSteps )
677 			result.add( step );
678 
679 		return result;
680 	}
681 
682 	@SuppressWarnings( "unchecked" )
683 	public <T extends TestStep> List<T> getTestStepsOfType( Class<T> stepType )
684 	{
685 		List<T> result = new ArrayList<T>();
686 		for( TestStep step : testSteps )
687 			if( step.getClass().isAssignableFrom( stepType ) )
688 				result.add( ( T ) step );
689 
690 		return result;
691 	}
692 
693 	public WsdlTestStep getTestStepByName( String stepName )
694 	{
695 		return ( WsdlTestStep ) getWsdlModelItemByName( testSteps, stepName );
696 	}
697 
698 	public WsdlLoadTest cloneLoadTest( WsdlLoadTest loadTest, String name )
699 	{
700 		loadTest.beforeSave();
701 
702 		LoadTestConfig loadTestConfig = getConfig().addNewLoadTest();
703 		loadTestConfig.set( loadTest.getConfig().copy() );
704 
705 		WsdlLoadTest newLoadTest = new WsdlLoadTest( this, loadTestConfig );
706 		newLoadTest.setName( name );
707 		loadTests.add( newLoadTest );
708 
709 		( getTestSuite() ).fireLoadTestAdded( newLoadTest );
710 
711 		return newLoadTest;
712 	}
713 
714 	@Override
715    public void release()
716 	{
717 		super.release();
718 
719 		for( WsdlTestStep testStep : testSteps )
720 			testStep.release();
721 
722 		for( WsdlLoadTest loadTest : loadTests )
723 			loadTest.release();
724 
725 		testRunListeners.clear();
726 		
727 		if( setupScriptEngine != null )
728 			setupScriptEngine.release();
729 		
730 		if( tearDownScriptEngine != null )
731 			tearDownScriptEngine.release();
732 	}
733 
734 	public ActionList getCreateActions()
735 	{
736 		return createActions;
737 	}
738 
739 	public void resetConfigOnMove( TestCaseConfig testCaseArray )
740 	{
741 		setConfig( testCaseArray );
742 		int mod = 0;
743 
744 		List<TestStepConfig> configs = getConfig().getTestStepList();
745 		for( int c = 0; c < configs.size(); c++ )
746 		{
747 			if( WsdlTestStepRegistry.getInstance().hasFactory( configs.get( c ) ) )
748 			{
749 				( testSteps.get( c - mod ) ).resetConfigOnMove( configs.get( c ) );
750 			}
751 			else
752 				mod++;
753 		}
754 
755 		List<LoadTestConfig> loadTestConfigs = getConfig().getLoadTestList();
756 		for( int c = 0; c < loadTestConfigs.size(); c++ )
757 		{
758 			loadTests.get( c ).resetConfigOnMove( loadTestConfigs.get( c ) );
759 		}
760 	}
761 
762 	@Override
763 	public void beforeSave()
764 	{
765 		for( WsdlTestStep testStep : testSteps )
766 			testStep.beforeSave();
767 
768 		for( WsdlLoadTest loadTest : loadTests )
769 			loadTest.beforeSave();
770 	}
771 
772 	public List<LoadTest> getLoadTestList()
773 	{
774 		List<LoadTest> result = new ArrayList<LoadTest>();
775 		for( LoadTest loadTest : loadTests )
776 			result.add( loadTest );
777 
778 		return result;
779 	}
780 
781 	public Object runSetupScript( TestRunContext runContext, TestRunner runner ) throws Exception
782 	{
783 		String script = getSetupScript();
784 		if( StringUtils.isNullOrEmpty( script ))
785 			return null;
786 		
787 		if( setupScriptEngine == null )
788 		{
789 			setupScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
790 			setupScriptEngine.setScript( script );
791 		}
792 		
793 		setupScriptEngine.setVariable( "context", runContext );
794 		setupScriptEngine.setVariable( "testRunner", runner );
795 		setupScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
796 		return setupScriptEngine.run();
797 	}
798 
799 	public Object runTearDownScript( TestRunContext runContext, TestRunner runner ) throws Exception
800 	{
801 		String script = getTearDownScript();
802 		if( StringUtils.isNullOrEmpty( script ))
803 			return null;
804 		
805 		if( tearDownScriptEngine == null )
806 		{
807 			tearDownScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
808 			tearDownScriptEngine.setScript( script );
809 		}
810 		
811 		tearDownScriptEngine.setVariable( "context", runContext );
812 		tearDownScriptEngine.setVariable( "testRunner", runner );
813 		tearDownScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
814 		return tearDownScriptEngine.run();
815 	}
816 
817 	public List<? extends ModelItem> getChildren()
818    {
819       return getTestStepList();
820    }
821 	
822 	@Override
823 	public void setName( String name )
824 	{
825 		String oldLabel = getLabel();
826    	
827 		super.setName( name );
828 		
829 		String label = getLabel();
830 		if( oldLabel != null && !oldLabel.equals( label ))
831 		{
832 			notifyPropertyChanged( LABEL_PROPERTY, oldLabel, label );
833 		}
834 	}
835 
836 	public String getLabel()
837 	{
838 		String name = getName();
839 		if( isDisabled() )
840 			return name + " (disabled)";
841 		else
842 			return name;
843 	}
844 
845 	public boolean isDisabled()
846 	{
847 		return getConfig().getDisabled();
848 	}
849 	
850 	public void setDisabled( boolean disabled )
851 	{
852 		String oldLabel = getLabel();
853 		
854 		boolean oldDisabled = isDisabled();
855 		if( oldDisabled == disabled )
856 			return;
857 		
858 		if( disabled )
859 			getConfig().setDisabled( disabled );
860 		else if( getConfig().isSetDisabled() )
861 			getConfig().unsetDisabled();
862 		
863 		notifyPropertyChanged( DISABLED_PROPERTY, oldDisabled, disabled );
864 		
865 		String label = getLabel();
866 		if( !oldLabel.equals( label ))
867 			notifyPropertyChanged( LABEL_PROPERTY, oldLabel, label );
868 	}
869 	
870 	public long getTimeout()
871 	{
872 		return getConfig().getTimeout();
873 	}
874 	
875 	public void setTimeout( long timeout )
876 	{
877 		long old = getTimeout();
878 		getConfig().setTimeout( timeout );
879 		notifyPropertyChanged( TIMEOUT_PROPERTY, old, timeout );
880 	}
881 }