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())
216 					{
217 						properties.put( TestRunContext.THREAD_INDEX, testRunContext.getProperty( TestRunContext.THREAD_INDEX ) );
218 						properties.put( TestRunContext.TOTAL_RUN_COUNT, testRunContext.getProperty( TestRunContext.TOTAL_RUN_COUNT ) );
219 						properties.put( TestRunContext.LOAD_TEST_CONTEXT, testRunContext.getProperty( TestRunContext.LOAD_TEST_CONTEXT ) );
220 						properties.put( TestRunContext.LOAD_TEST_RUNNER, testRunContext.getProperty( TestRunContext.LOAD_TEST_RUNNER ) );
221 						properties.put( TestRunContext.RUN_COUNT, testRunContext.getProperty( TestRunContext.RUN_COUNT ) );
222 					}
223 					
224 					if( isCopyHttpSession())
225 					{
226 						properties.put( TestRunContext.HTTP_STATE_PROPERTY, testRunContext.getProperty( TestRunContext.HTTP_STATE_PROPERTY ) );
227 					}
228 
229 					properties.put( TestRunContext.INTERACTIVE, testRunContext.getProperty( TestRunContext.INTERACTIVE ) );
230 
231 					properties.put( "#CallingRunTestCaseStep#", this );
232 					properties.put( "#CallingTestCaseRunner#", testRunner );
233 					properties.put( "#CallingTestRunContext#", testRunContext );
234 					
235 					testCaseRunner = runningTestCase.run( properties, true );
236 					testCaseRunner.waitUntilFinished();
237 					result.stopTimer();
238 
239 					for( String key : returnProperties )
240 					{
241 						if( runningTestCase.hasProperty( key ) )
242 							setPropertyValue( key, runningTestCase.getPropertyValue( key ) );
243 					}
244 
245 					// aggregate results
246 					for( TestStepResult testStepResult : testCaseRunner.getResults() )
247 					{
248 						result.addMessage( testStepResult.getTestStep().getName() + " - " + testStepResult.getStatus() + " - " + testStepResult.getTimeTaken());
249 						for( String msg : testStepResult.getMessages())
250 						{
251 							result.addMessage( "- " + msg );
252 						}
253 
254 						if( testStepResult instanceof MessageExchangeTestStepResult )
255 						{
256 							result.addMessages( ( ( MessageExchangeTestStepResult )testStepResult ).getMessageExchanges() );
257 						}
258 					}
259 
260 					switch( testCaseRunner.getStatus() )
261 					{
262 					case CANCELED :
263 						result.setStatus( TestStepStatus.CANCELED );
264 						break;
265 					case FAILED :
266 						result.setStatus( TestStepStatus.FAILED );
267 						break;
268 					case FINISHED :
269 						result.setStatus( TestStepStatus.OK );
270 						break;
271 					default :
272 						result.setStatus( TestStepStatus.UNKNOWN );
273 						break;
274 					}
275 
276 					for( TestRunListener listener : testRunListeners )
277 						runningTestCase.removeTestRunListener( listener );
278 
279 					if( runMode == RunTestCaseRunModeTypeConfig.PARALLELL )
280 						runningTestCase.release();
281 
282 					runningTestCase = null;
283 					testCaseRunner = null;
284 				}
285 			}
286 		}
287 		else
288 		{
289 			result.setStatus( TestStepStatus.FAILED );
290 			result.addMessage( "Missing testCase in project" );
291 			result.stopTimer();
292 		}
293 
294 		return result;
295 	}
296 
297 	@Override
298 	public String getLabel()
299 	{
300 		String name = getName();
301 
302 		if( testCaseRunner != null )
303 		{
304 			name += " - [" + testCaseRunner.getStatus() + "]";
305 		}
306 
307 		if( isDisabled() )
308 			return name + " (disabled)";
309 		else
310 			return name;
311 	}
312 
313 	@Override
314 	public boolean cancel()
315 	{
316 		if( testCaseRunner != null )
317 		{
318 			testCaseRunner.cancel( "Canceled by calling TestCase" );
319 		}
320 
321 		return true;
322 	}
323 
324 	private String getTestCaseId()
325 	{
326 		return stepConfig.getTargetTestCase();
327 	}
328 
329 	public void setTargetTestCase( WsdlTestCase testCase )
330 	{
331 		if( targetTestCase != null )
332 		{
333 			targetTestCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
334 			targetTestCase.removeTestPropertyListener( testPropertyListener );
335 		}
336 
337 		WsdlTestCase oldTestCase = this.targetTestCase;
338 		this.targetTestCase = testCase;
339 
340 		if( testCase != null )
341 		{
342 			stepConfig.setTargetTestCase( testCase.getId() );
343 
344 			targetTestCase.getTestSuite().addTestSuiteListener( testSuiteListener );
345 			targetTestCase.addTestPropertyListener( testPropertyListener );
346 
347 			syncProperties();
348 		}
349 
350 		notifyPropertyChanged( TARGET_TESTCASE, oldTestCase, testCase );
351 	}
352 
353 	
354 	public boolean isCopyHttpSession()
355 	{
356 		return stepConfig.getCopyHttpSession();
357 	}
358 
359 	public boolean isCopyLoadTestProperties()
360 	{
361 		return stepConfig.getCopyLoadTestProperties();
362 	}
363 
364 	public boolean isIgnoreEmptyProperties()
365 	{
366 		return stepConfig.getIgnoreEmptyProperties();
367 	}
368 
369 	public void setCopyHttpSession( boolean arg0 )
370 	{
371 		if( arg0 == isCopyHttpSession())
372 			return;
373 		
374 		stepConfig.setCopyHttpSession( arg0 );
375 		notifyPropertyChanged( "copyHttpSession", !arg0, arg0 );
376 	}
377 
378 	public void setCopyLoadTestProperties( boolean arg0 )
379 	{
380 		if( arg0 == isCopyLoadTestProperties())
381 			return;
382 		
383 		stepConfig.setCopyLoadTestProperties( arg0 );
384 		notifyPropertyChanged( "copyLoadTestProperties", !arg0, arg0 );
385 	}
386 
387 	public void setIgnoreEmptyProperties( boolean arg0 )
388 	{
389 		if( arg0 == isIgnoreEmptyProperties())
390 			return;
391 		
392 		stepConfig.setIgnoreEmptyProperties( arg0 );
393 		notifyPropertyChanged( "ignoreEmptyProperties", !arg0, arg0 );
394 	}
395 
396 	/***
397 	 * Creates a copy of the underlying WsdlTestCase with all LoadTests removed
398 	 * and configured for LoadTesting
399 	 */
400 
401 	private WsdlTestCase createTestCase( WsdlTestCase testCase )
402 	{
403 		// clone config and remove and loadtests
404 		testCase.beforeSave();
405 
406 		try
407 		{
408 			TestCaseConfig config = TestCaseConfig.Factory.parse( testCase.getConfig().xmlText() );
409 			config.setLoadTestArray( new LoadTestConfig[0] );
410 
411 			// clone entire testCase
412 			WsdlTestCase wsdlTestCase = testCase.getTestSuite().buildTestCase( config, true );
413 			wsdlTestCase.afterLoad();
414 			return wsdlTestCase;
415 		}
416 		catch( Throwable e )
417 		{
418 			SoapUI.logError( e );
419 		}
420 
421 		return null;
422 	}
423 
424 	public void addTestPropertyListener( TestPropertyListener listener )
425 	{
426 		propertyHolderSupport.addTestPropertyListener( listener );
427 	}
428 
429 	public Map<String, TestProperty> getProperties()
430 	{
431 		return propertyHolderSupport.getProperties();
432 	}
433 
434 	public PropertiesStepProperty getProperty( String name )
435 	{
436 		return propertyHolderSupport.getProperty( name );
437 	}
438 
439 	public String[] getPropertyNames()
440 	{
441 		return propertyHolderSupport.getPropertyNames();
442 	}
443 
444 	public List<TestProperty> getPropertyList()
445 	{
446 		return propertyHolderSupport.getPropertyList();
447 	}
448 
449 	public String getPropertyValue( String name )
450 	{
451 		return propertyHolderSupport.getPropertyValue( name );
452 	}
453 
454 	public boolean hasProperty( String name )
455 	{
456 		return propertyHolderSupport.hasProperty( name );
457 	}
458 
459 	public void removeTestPropertyListener( TestPropertyListener listener )
460 	{
461 		propertyHolderSupport.removeTestPropertyListener( listener );
462 	}
463 
464 	public void setPropertyValue( String name, String value )
465 	{
466 		propertyHolderSupport.setPropertyValue( name, value );
467 	}
468 
469 	private void updateLabelDuringRun()
470 	{
471 		notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, currentLabel, getLabel() );
472 		currentLabel = getLabel();
473 	}
474 
475 	private final class InternalTestPropertyListener extends TestPropertyListenerAdapter
476 	{
477 		@Override
478 		public void propertyAdded( String name )
479 		{
480 			propertyHolderSupport.addProperty( name );
481 		}
482 
483 		@Override
484 		public void propertyRemoved( String name )
485 		{
486 			propertyHolderSupport.removeProperty( name );
487 		}
488 
489 		@Override
490 		public void propertyRenamed( String oldName, String newName )
491 		{
492 			propertyHolderSupport.renameProperty( oldName, newName );
493 		}
494 
495 		@Override
496 		public void propertyMoved( String name, int oldIndex, int newIndex )
497 		{
498 			propertyHolderSupport.moveProperty( name, newIndex );
499 		}
500 	}
501 
502 	private final class InternalTestRunListener extends TestRunListenerAdapter
503 	{
504 		@Override
505 		public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
506 		{
507 			updateLabelDuringRun();
508 		}
509 
510 		@Override
511 		public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
512 		{
513 			updateLabelDuringRun();
514 		}
515 
516 		@Override
517 		public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
518 		{
519 			updateLabelDuringRun();
520 		}
521 
522 		@Override
523 		public void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep )
524 		{
525 			updateLabelDuringRun();
526 		}
527 	}
528 
529 	@Override
530 	public void resetConfigOnMove( TestStepConfig config )
531 	{
532 		super.resetConfigOnMove( config );
533 
534 		stepConfig = ( RunTestCaseStepConfig )config.getConfig().changeType( RunTestCaseStepConfig.type );
535 		propertyHolderSupport.resetPropertiesConfig( stepConfig.getProperties() );
536 	}
537 
538 	@Override
539 	public void release()
540 	{
541 		if( targetTestCase != null )
542 		{
543 			targetTestCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
544 			targetTestCase.removeTestPropertyListener( testPropertyListener );
545 		}
546 
547 		super.release();
548 	}
549 
550 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
551 	{
552 		@Override
553 		public void testCaseRemoved( TestCase testCase )
554 		{
555 			setTargetTestCase( findTargetTestCase() );
556 		}
557 	}
558 
559 	public WsdlTestCase getTargetTestCase()
560 	{
561 		return targetTestCase;
562 	}
563 
564 	public void addTestRunListener( TestRunListener listener )
565 	{
566 		testRunListeners.add( listener );
567 	}
568 
569 	public void removeTestRunListener( TestRunListener listener )
570 	{
571 		testRunListeners.remove( listener );
572 	}
573 
574 	public WsdlTestCase getRunningTestCase()
575 	{
576 		return runningTestCase;
577 	}
578 
579 	public WsdlTestCaseRunner getTestCaseRunner()
580 	{
581 		return testCaseRunner;
582 	}
583 
584 	public RunTestCaseRunModeTypeConfig.Enum getRunMode()
585 	{
586 		return stepConfig.getRunMode();
587 	}
588 
589 	public void setRunMode( RunTestCaseRunModeTypeConfig.Enum runMode )
590 	{
591 		stepConfig.setRunMode( runMode );
592 	}
593 
594 	public TestProperty getPropertyAt( int index )
595 	{
596 		return propertyHolderSupport.getPropertyAt( index );
597 	}
598 
599 	public int getPropertyCount()
600 	{
601 		return propertyHolderSupport.getPropertyCount();
602 	}
603 
604 	@Override
605 	public void resolve( ResolveContext<?> context )
606 	{
607 		super.resolve( context );
608 
609 		if( targetTestCase == null )
610 		{
611 			if( context.hasThisModelItem( this, "Missing Test Case", getTestStepTitle() + "/"
612 					+ stepConfig.getTargetTestCase() ) )
613 				return;
614 			context
615 					.addPathToResolve( this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase() )
616 					.addResolvers( new RunTestCaseRemoveResolver( this ), new ChooseAnotherTestCase( this ),
617 							new CreateNewEmptyTestCase( this ) );
618 		}
619 		else
620 		{
621 			targetTestCase.resolve( context );
622 			if( context.hasThisModelItem( this, "Missing Test Case", getTestStepTitle() + "/"
623 					+ stepConfig.getTargetTestCase() ) )
624 			{
625 				context.getPath( this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase() )
626 						.setSolved( true );
627 			}
628 		}
629 	}
630 }