View Javadoc

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