1
2
3
4
5
6
7
8
9
10
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
209
210
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
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
404 testCase.beforeSave();
405
406 try
407 {
408 TestCaseConfig config = TestCaseConfig.Factory.parse( testCase.getConfig().xmlText() );
409 config.setLoadTestArray( new LoadTestConfig[0] );
410
411
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 }