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