View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.teststeps;
14  
15  import java.util.HashSet;
16  import java.util.List;
17  import java.util.Map;
18  import java.util.Set;
19  
20  import com.eviware.soapui.SoapUI;
21  import com.eviware.soapui.config.LoadTestConfig;
22  import com.eviware.soapui.config.RunTestCaseRunModeTypeConfig;
23  import com.eviware.soapui.config.RunTestCaseStepConfig;
24  import com.eviware.soapui.config.TestCaseConfig;
25  import com.eviware.soapui.config.TestStepConfig;
26  import com.eviware.soapui.config.RunTestCaseRunModeTypeConfig.Enum;
27  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
28  import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder;
29  import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder.PropertiesStepProperty;
30  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
31  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
32  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
33  import com.eviware.soapui.model.support.ModelSupport;
34  import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
35  import com.eviware.soapui.model.support.TestRunListenerAdapter;
36  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
37  import com.eviware.soapui.model.testsuite.MessageExchangeTestStepResult;
38  import com.eviware.soapui.model.testsuite.TestCase;
39  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
40  import com.eviware.soapui.model.testsuite.TestCaseRunner;
41  import com.eviware.soapui.model.testsuite.TestProperty;
42  import com.eviware.soapui.model.testsuite.TestPropertyListener;
43  import com.eviware.soapui.model.testsuite.TestRunListener;
44  import com.eviware.soapui.model.testsuite.TestRunner;
45  import com.eviware.soapui.model.testsuite.TestStep;
46  import com.eviware.soapui.model.testsuite.TestStepResult;
47  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
48  import com.eviware.soapui.support.UISupport;
49  import com.eviware.soapui.support.resolver.ChooseAnotherTestCase;
50  import com.eviware.soapui.support.resolver.CreateNewEmptyTestCase;
51  import com.eviware.soapui.support.resolver.ResolveContext;
52  import com.eviware.soapui.support.resolver.RunTestCaseRemoveResolver;
53  import com.eviware.soapui.support.types.StringList;
54  import com.eviware.soapui.support.types.StringToObjectMap;
55  
56  public class WsdlRunTestCaseTestStep extends WsdlTestStep
57  {
58  	public static final String TARGET_TESTCASE = WsdlRunTestCaseTestStep.class.getName() + "@target_testcase";
59  
60  	private RunTestCaseStepConfig stepConfig;
61  	private WsdlTestCaseRunner testCaseRunner;
62  	private XmlBeansPropertiesTestPropertyHolder propertyHolderSupport;
63  	private String currentLabel;
64  	private WsdlTestCase targetTestCase;
65  	private InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
66  	private InternalTestRunListener testRunListener = new InternalTestRunListener();
67  	private InternalTestPropertyListener testPropertyListener = new InternalTestPropertyListener();
68  	private Set<TestRunListener> testRunListeners = new HashSet<TestRunListener>();
69  	private WsdlTestCase runningTestCase;
70  
71  	public WsdlRunTestCaseTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
72  	{
73  		super( testCase, config, true, forLoadTest );
74  
75  		if( config.getConfig() == null )
76  		{
77  			stepConfig = ( RunTestCaseStepConfig )config.addNewConfig().changeType( RunTestCaseStepConfig.type );
78  			stepConfig.addNewProperties();
79  			stepConfig.addNewReturnProperties();
80  		}
81  		else
82  		{
83  			stepConfig = ( RunTestCaseStepConfig )config.getConfig().changeType( RunTestCaseStepConfig.type );
84  		}
85  
86  		if( stepConfig.getRunMode() == null )
87  		{
88  			stepConfig.setRunMode( RunTestCaseRunModeTypeConfig.PARALLELL );
89  		}
90  
91  		setIcon( UISupport.createImageIcon( "/run_testcase_step.gif" ) );
92  
93  		propertyHolderSupport = new XmlBeansPropertiesTestPropertyHolder( this, stepConfig.getProperties() );
94  	}
95  
96  	/***
97  	 * We need to check that we are not pointing at testcase in original
98  	 * testsuite
99  	 */
100 
101 	public void afterCopy( WsdlTestSuite oldTestSuite, WsdlTestCase oldTestCase )
102 	{
103 		super.afterCopy( oldTestSuite, oldTestCase );
104 
105 		if( targetTestCase != null && oldTestSuite == targetTestCase.getTestSuite() )
106 		{
107 			setTargetTestCase( getTestCase().getTestSuite().getTestCaseByName( targetTestCase.getName() ) );
108 		}
109 	}
110 
111 	@Override
112 	public void afterLoad()
113 	{
114 		setTargetTestCase( findTargetTestCase() );
115 
116 		super.afterLoad();
117 	}
118 
119 	private void syncProperties()
120 	{
121 		for( String name : propertyHolderSupport.getPropertyNames() )
122 		{
123 			if( !targetTestCase.hasProperty( name ) )
124 				propertyHolderSupport.removeProperty( name );
125 		}
126 
127 		for( String name : targetTestCase.getPropertyNames() )
128 		{
129 			if( !propertyHolderSupport.hasProperty( name ) )
130 				propertyHolderSupport.addProperty( name );
131 		}
132 	}
133 
134 	private WsdlTestCase findTargetTestCase()
135 	{
136 		return ModelSupport.findModelItemById( getTestCaseId(), getTestCase().getTestSuite().getProject() );
137 	}
138 
139 	public StringList getReturnProperties()
140 	{
141 		return new StringList( stepConfig.getReturnProperties().getEntryList() );
142 	}
143 
144 	public void setReturnProperties( StringList returnProperties )
145 	{
146 		stepConfig.getReturnProperties().setEntryArray( returnProperties.toStringArray() );
147 	}
148 
149 	public TestStepResult run( TestCaseRunner testRunner, TestCaseRunContext testRunContext )
150 	{
151 		WsdlMessageExchangeTestStepResult result = new WsdlMessageExchangeTestStepResult( this );
152 
153 		testCaseRunner = null;
154 
155 		if( targetTestCase != null )
156 		{
157 			Enum runMode = getRunMode();
158 
159 			if( runMode == RunTestCaseRunModeTypeConfig.PARALLELL )
160 			{
161 				runningTestCase = createTestCase( targetTestCase );
162 			}
163 			else
164 			{
165 				runningTestCase = targetTestCase;
166 				
167 				TestCaseRunner targetTestRunner = SoapUI.getTestMonitor().getTestRunner( targetTestCase );
168 				if( targetTestRunner != null && targetTestRunner.getStatus() == TestRunner.Status.RUNNING )
169 				{
170 					if( runMode == RunTestCaseRunModeTypeConfig.SINGLETON_AND_FAIL )
171 					{
172 						result.setStatus( TestStepStatus.FAILED );
173 						result.addMessage( "Target TestCase is already running" );
174 						result.stopTimer();
175 						runningTestCase = null;
176 					}
177 					else
178 					{
179 						targetTestRunner.waitUntilFinished();
180 					}
181 				}
182 			}
183 
184 			if( runningTestCase != null )
185 			{
186 				synchronized( runningTestCase )
187 				{
188 					for( TestRunListener listener : testRunListeners )
189 						runningTestCase.addTestRunListener( listener );
190 
191 					StringList returnProperties = getReturnProperties();
192 					Map<String, TestProperty> props = getProperties();
193 					for( String key : props.keySet() )
194 					{
195 						if( runningTestCase.hasProperty( key ) && !returnProperties.contains( key ) )
196 						{
197 							String value = props.get( key ).getValue();
198 							runningTestCase.setPropertyValue( key, PropertyExpander.expandProperties( testRunContext, value ) );
199 						}
200 					}
201 
202 					currentLabel = getLabel();
203 					runningTestCase.addTestRunListener( testRunListener );
204 
205 					// StringToObjectMap properties = new StringToObjectMap();
206 					// for( String name : testRunContext.getPropertyNames() )
207 					// properties.put( name, testRunContext.getProperty( name ));
208 
209 					result.startTimer();
210 					testCaseRunner = runningTestCase.run( new StringToObjectMap(), true );
211 					testCaseRunner.waitUntilFinished();
212 					result.stopTimer();
213 
214 					for( String key : returnProperties )
215 					{
216 						if( runningTestCase.hasProperty( key ) )
217 							setPropertyValue( key, runningTestCase.getPropertyValue( key ) );
218 					}
219 
220 					// aggregate results
221 					for( TestStepResult testStepResult : testCaseRunner.getResults() )
222 					{
223 						result.addMessage( testStepResult.getTestStep().getName() + " - " + testStepResult.getStatus() + " - " + testStepResult.getTimeTaken());
224 						for( String msg : testStepResult.getMessages())
225 						{
226 							result.addMessage( "- " + msg );
227 						}
228 
229 						if( testStepResult instanceof MessageExchangeTestStepResult )
230 						{
231 							result.addMessages( ( ( MessageExchangeTestStepResult )testStepResult ).getMessageExchanges() );
232 						}
233 					}
234 
235 					switch( testCaseRunner.getStatus() )
236 					{
237 					case CANCELED :
238 						result.setStatus( TestStepStatus.CANCELED );
239 						break;
240 					case FAILED :
241 						result.setStatus( TestStepStatus.FAILED );
242 						break;
243 					case FINISHED :
244 						result.setStatus( TestStepStatus.OK );
245 						break;
246 					default :
247 						result.setStatus( TestStepStatus.UNKNOWN );
248 						break;
249 					}
250 
251 					for( TestRunListener listener : testRunListeners )
252 						runningTestCase.removeTestRunListener( listener );
253 
254 					if( runMode == RunTestCaseRunModeTypeConfig.PARALLELL )
255 						runningTestCase.release();
256 
257 					runningTestCase = null;
258 					testCaseRunner = null;
259 				}
260 			}
261 		}
262 		else
263 		{
264 			result.setStatus( TestStepStatus.FAILED );
265 			result.addMessage( "Missing testCase in project" );
266 			result.stopTimer();
267 		}
268 
269 		return result;
270 	}
271 
272 	@Override
273 	public String getLabel()
274 	{
275 		String name = getName();
276 
277 		if( testCaseRunner != null )
278 		{
279 			name += " - [" + testCaseRunner.getStatus() + "]";
280 		}
281 
282 		if( isDisabled() )
283 			return name + " (disabled)";
284 		else
285 			return name;
286 	}
287 
288 	@Override
289 	public boolean cancel()
290 	{
291 		if( testCaseRunner != null )
292 		{
293 			testCaseRunner.cancel( "Canceled by calling TestCase" );
294 		}
295 
296 		return true;
297 	}
298 
299 	private String getTestCaseId()
300 	{
301 		return stepConfig.getTargetTestCase();
302 	}
303 
304 	public void setTargetTestCase( WsdlTestCase testCase )
305 	{
306 		if( targetTestCase != null )
307 		{
308 			targetTestCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
309 			targetTestCase.removeTestPropertyListener( testPropertyListener );
310 		}
311 
312 		WsdlTestCase oldTestCase = this.targetTestCase;
313 		this.targetTestCase = testCase;
314 
315 		if( testCase != null )
316 		{
317 			stepConfig.setTargetTestCase( testCase.getId() );
318 
319 			targetTestCase.getTestSuite().addTestSuiteListener( testSuiteListener );
320 			targetTestCase.addTestPropertyListener( testPropertyListener );
321 
322 			syncProperties();
323 		}
324 
325 		notifyPropertyChanged( TARGET_TESTCASE, oldTestCase, testCase );
326 	}
327 
328 	/***
329 	 * Creates a copy of the underlying WsdlTestCase with all LoadTests removed
330 	 * and configured for LoadTesting
331 	 */
332 
333 	private WsdlTestCase createTestCase( WsdlTestCase testCase )
334 	{
335 		// clone config and remove and loadtests
336 		testCase.beforeSave();
337 
338 		try
339 		{
340 			TestCaseConfig config = TestCaseConfig.Factory.parse( testCase.getConfig().xmlText() );
341 			config.setLoadTestArray( new LoadTestConfig[0] );
342 
343 			// clone entire testCase
344 			WsdlTestCase wsdlTestCase = testCase.getTestSuite().buildTestCase( config, true );
345 			wsdlTestCase.afterLoad();
346 			return wsdlTestCase;
347 		}
348 		catch( Throwable e )
349 		{
350 			SoapUI.logError( e );
351 		}
352 
353 		return null;
354 	}
355 
356 	public void addTestPropertyListener( TestPropertyListener listener )
357 	{
358 		propertyHolderSupport.addTestPropertyListener( listener );
359 	}
360 
361 	public Map<String, TestProperty> getProperties()
362 	{
363 		return propertyHolderSupport.getProperties();
364 	}
365 
366 	public PropertiesStepProperty getProperty( String name )
367 	{
368 		return propertyHolderSupport.getProperty( name );
369 	}
370 
371 	public String[] getPropertyNames()
372 	{
373 		return propertyHolderSupport.getPropertyNames();
374 	}
375 
376 	public List<TestProperty> getPropertyList()
377 	{
378 		return propertyHolderSupport.getPropertyList();
379 	}
380 
381 	public String getPropertyValue( String name )
382 	{
383 		return propertyHolderSupport.getPropertyValue( name );
384 	}
385 
386 	public boolean hasProperty( String name )
387 	{
388 		return propertyHolderSupport.hasProperty( name );
389 	}
390 
391 	public void removeTestPropertyListener( TestPropertyListener listener )
392 	{
393 		propertyHolderSupport.removeTestPropertyListener( listener );
394 	}
395 
396 	public void setPropertyValue( String name, String value )
397 	{
398 		propertyHolderSupport.setPropertyValue( name, value );
399 	}
400 
401 	private void updateLabelDuringRun()
402 	{
403 		notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, currentLabel, getLabel() );
404 		currentLabel = getLabel();
405 	}
406 
407 	private final class InternalTestPropertyListener extends TestPropertyListenerAdapter
408 	{
409 		@Override
410 		public void propertyAdded( String name )
411 		{
412 			propertyHolderSupport.addProperty( name );
413 		}
414 
415 		@Override
416 		public void propertyRemoved( String name )
417 		{
418 			propertyHolderSupport.removeProperty( name );
419 		}
420 
421 		@Override
422 		public void propertyRenamed( String oldName, String newName )
423 		{
424 			propertyHolderSupport.renameProperty( oldName, newName );
425 		}
426 
427 		@Override
428 		public void propertyMoved( String name, int oldIndex, int newIndex )
429 		{
430 			propertyHolderSupport.moveProperty( name, newIndex );
431 		}
432 	}
433 
434 	private final class InternalTestRunListener extends TestRunListenerAdapter
435 	{
436 		@Override
437 		public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
438 		{
439 			updateLabelDuringRun();
440 		}
441 
442 		@Override
443 		public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
444 		{
445 			updateLabelDuringRun();
446 		}
447 
448 		@Override
449 		public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
450 		{
451 			updateLabelDuringRun();
452 		}
453 
454 		@Override
455 		public void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep )
456 		{
457 			updateLabelDuringRun();
458 		}
459 	}
460 
461 	@Override
462 	public void resetConfigOnMove( TestStepConfig config )
463 	{
464 		super.resetConfigOnMove( config );
465 
466 		stepConfig = ( RunTestCaseStepConfig )config.getConfig().changeType( RunTestCaseStepConfig.type );
467 		propertyHolderSupport.resetPropertiesConfig( stepConfig.getProperties() );
468 	}
469 
470 	@Override
471 	public void release()
472 	{
473 		if( targetTestCase != null )
474 		{
475 			targetTestCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
476 			targetTestCase.removeTestPropertyListener( testPropertyListener );
477 		}
478 
479 		super.release();
480 	}
481 
482 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
483 	{
484 		@Override
485 		public void testCaseRemoved( TestCase testCase )
486 		{
487 			setTargetTestCase( findTargetTestCase() );
488 		}
489 	}
490 
491 	public WsdlTestCase getTargetTestCase()
492 	{
493 		return targetTestCase;
494 	}
495 
496 	public void addTestRunListener( TestRunListener listener )
497 	{
498 		testRunListeners.add( listener );
499 	}
500 
501 	public void removeTestRunListener( TestRunListener listener )
502 	{
503 		testRunListeners.remove( listener );
504 	}
505 
506 	public WsdlTestCase getRunningTestCase()
507 	{
508 		return runningTestCase;
509 	}
510 
511 	public WsdlTestCaseRunner getTestCaseRunner()
512 	{
513 		return testCaseRunner;
514 	}
515 
516 	public RunTestCaseRunModeTypeConfig.Enum getRunMode()
517 	{
518 		return stepConfig.getRunMode();
519 	}
520 
521 	public void setRunMode( RunTestCaseRunModeTypeConfig.Enum runMode )
522 	{
523 		stepConfig.setRunMode( runMode );
524 	}
525 
526 	public TestProperty getPropertyAt( int index )
527 	{
528 		return propertyHolderSupport.getPropertyAt( index );
529 	}
530 
531 	public int getPropertyCount()
532 	{
533 		return propertyHolderSupport.getPropertyCount();
534 	}
535 
536 	@Override
537 	public void resolve( ResolveContext<?> context )
538 	{
539 		super.resolve( context );
540 
541 		if( targetTestCase == null )
542 		{
543 			if( context.hasThisModelItem( this, "Missing Test Case", getTestStepTitle() + "/"
544 					+ stepConfig.getTargetTestCase() ) )
545 				return;
546 			context
547 					.addPathToResolve( this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase() )
548 					.addResolvers( new RunTestCaseRemoveResolver( this ), new ChooseAnotherTestCase( this ),
549 							new CreateNewEmptyTestCase( this ) );
550 		}
551 		else
552 		{
553 			targetTestCase.resolve( context );
554 			if( context.hasThisModelItem( this, "Missing Test Case", getTestStepTitle() + "/"
555 					+ stepConfig.getTargetTestCase() ) )
556 			{
557 				context.getPath( this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase() )
558 						.setSolved( true );
559 			}
560 		}
561 	}
562 }