View Javadoc

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