/*
* Copyright 2004-2014 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.teststeps;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.LoadTestConfig;
import com.eviware.soapui.config.RunTestCaseRunModeTypeConfig;
import com.eviware.soapui.config.RunTestCaseRunModeTypeConfig.Enum;
import com.eviware.soapui.config.RunTestCaseStepConfig;
import com.eviware.soapui.config.TestCaseConfig;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder.PropertiesStepProperty;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.support.ModelSupport;
import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
import com.eviware.soapui.model.support.TestRunListenerAdapter;
import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
import com.eviware.soapui.model.testsuite.MessageExchangeTestStepResult;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.model.testsuite.TestRunContext;
import com.eviware.soapui.model.testsuite.TestRunListener;
import com.eviware.soapui.model.testsuite.TestRunner;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.resolver.ChooseAnotherTestCase;
import com.eviware.soapui.support.resolver.CreateNewEmptyTestCase;
import com.eviware.soapui.support.resolver.ResolveContext;
import com.eviware.soapui.support.resolver.RunTestCaseRemoveResolver;
import com.eviware.soapui.support.types.StringList;
import com.eviware.soapui.support.types.StringToObjectMap;
public class WsdlRunTestCaseTestStep extends WsdlTestStep {
public static final String TARGET_TESTCASE = WsdlRunTestCaseTestStep.class.getName() + "@target_testcase";
private RunTestCaseStepConfig stepConfig;
private WsdlTestCaseRunner testCaseRunner;
private XmlBeansPropertiesTestPropertyHolder propertyHolderSupport;
private String currentLabel;
private WsdlTestCase targetTestCase;
private InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
private InternalTestRunListener testRunListener = new InternalTestRunListener();
private InternalTestPropertyListener testPropertyListener = new InternalTestPropertyListener();
private Set<TestRunListener> testRunListeners = new HashSet<TestRunListener>();
private WsdlTestCase runningTestCase;
public WsdlRunTestCaseTestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest) {
super(testCase, config, true, forLoadTest);
if (config.getConfig() == null) {
stepConfig = (RunTestCaseStepConfig) config.addNewConfig().changeType(RunTestCaseStepConfig.type);
stepConfig.addNewProperties();
stepConfig.addNewReturnProperties();
} else {
stepConfig = (RunTestCaseStepConfig) config.getConfig().changeType(RunTestCaseStepConfig.type);
}
if (stepConfig.getRunMode() == null) {
stepConfig.setRunMode(RunTestCaseRunModeTypeConfig.PARALLELL);
}
setIcon(UISupport.createImageIcon("/run_testcase_step.gif"));
propertyHolderSupport = new XmlBeansPropertiesTestPropertyHolder(this, stepConfig.getProperties());
}
/**
* We need to check that we are not pointing at testcase in original
* testsuite
*/
public void afterCopy(WsdlTestSuite oldTestSuite, WsdlTestCase oldTestCase) {
super.afterCopy(oldTestSuite, oldTestCase);
if (targetTestCase != null && oldTestSuite == targetTestCase.getTestSuite()) {
setTargetTestCase(getTestCase().getTestSuite().getTestCaseByName(targetTestCase.getName()));
}
}
@Override
public void afterLoad() {
setTargetTestCase(findTargetTestCase());
super.afterLoad();
}
private void syncProperties() {
for (String name : propertyHolderSupport.getPropertyNames()) {
if (!targetTestCase.hasProperty(name)) {
propertyHolderSupport.removeProperty(name);
}
}
for (String name : targetTestCase.getPropertyNames()) {
if (!propertyHolderSupport.hasProperty(name)) {
propertyHolderSupport.addProperty(name);
}
}
}
private WsdlTestCase findTargetTestCase() {
return ModelSupport.findModelItemById(getTestCaseId(), getTestCase().getTestSuite().getProject());
}
public StringList getReturnProperties() {
return new StringList(stepConfig.getReturnProperties().getEntryList());
}
public void setReturnProperties(StringList returnProperties) {
stepConfig.getReturnProperties().setEntryArray(returnProperties.toStringArray());
}
public TestStepResult run(TestCaseRunner testRunner, TestCaseRunContext testRunContext) {
WsdlMessageExchangeTestStepResult result = new WsdlMessageExchangeTestStepResult(this);
testCaseRunner = null;
if (targetTestCase != null) {
Enum runMode = getRunMode();
if (runMode == RunTestCaseRunModeTypeConfig.PARALLELL) {
runningTestCase = createTestCase(targetTestCase);
} else {
runningTestCase = targetTestCase;
TestCaseRunner targetTestRunner = SoapUI.getTestMonitor().getTestRunner(targetTestCase);
if (targetTestRunner != null && targetTestRunner.getStatus() == TestRunner.Status.RUNNING) {
if (runMode == RunTestCaseRunModeTypeConfig.SINGLETON_AND_FAIL) {
result.setStatus(TestStepStatus.FAILED);
result.addMessage("Target TestCase is already running");
result.stopTimer();
runningTestCase = null;
} else {
targetTestRunner.waitUntilFinished();
}
}
}
if (runningTestCase != null) {
synchronized (runningTestCase) {
for (TestRunListener listener : testRunListeners) {
runningTestCase.addTestRunListener(listener);
}
StringList returnProperties = getReturnProperties();
Map<String, TestProperty> props = getProperties();
for (Map.Entry<String, TestProperty> entry : props.entrySet()) {
if (runningTestCase.hasProperty(entry.getKey()) && !returnProperties.contains(entry.getKey())) {
String value = PropertyExpander.expandProperties(testRunContext, entry.getValue().getValue());
if (StringUtils.hasContent(value) || !isIgnoreEmptyProperties()) {
runningTestCase.setPropertyValue(entry.getKey(), value);
}
}
}
currentLabel = getLabel();
runningTestCase.addTestRunListener(testRunListener);
// StringToObjectMap properties = new StringToObjectMap();
// for( String name : testRunContext.getPropertyNames() )
// properties.put( name, testRunContext.getProperty( name ));
result.startTimer();
StringToObjectMap properties = new StringToObjectMap();
if (isCopyLoadTestProperties() && properties.containsKey(TestRunContext.LOAD_TEST_CONTEXT)) {
properties
.put(TestRunContext.THREAD_INDEX, testRunContext.getProperty(TestRunContext.THREAD_INDEX));
properties.put(TestRunContext.TOTAL_RUN_COUNT,
testRunContext.getProperty(TestRunContext.TOTAL_RUN_COUNT));
properties.put(TestRunContext.LOAD_TEST_CONTEXT,
testRunContext.getProperty(TestRunContext.LOAD_TEST_CONTEXT));
properties.put(TestRunContext.LOAD_TEST_RUNNER,
testRunContext.getProperty(TestRunContext.LOAD_TEST_RUNNER));
properties.put(TestRunContext.RUN_COUNT, testRunContext.getProperty(TestRunContext.RUN_COUNT));
}
if (isCopyHttpSession() && testRunContext.hasProperty(TestRunContext.HTTP_STATE_PROPERTY)) {
properties.put(TestRunContext.HTTP_STATE_PROPERTY,
testRunContext.getProperty(TestRunContext.HTTP_STATE_PROPERTY));
}
properties.put(TestRunContext.INTERACTIVE, testRunContext.getProperty(TestRunContext.INTERACTIVE));
properties.put("#CallingRunTestCaseStep#", this);
properties.put("#CallingTestCaseRunner#", testRunner);
properties.put("#CallingTestRunContext#", testRunContext);
testCaseRunner = runningTestCase.run(properties, true);
testCaseRunner.waitUntilFinished();
result.stopTimer();
for (String key : returnProperties) {
if (runningTestCase.hasProperty(key)) {
setPropertyValue(key, runningTestCase.getPropertyValue(key));
}
}
// aggregate results
for (TestStepResult testStepResult : testCaseRunner.getResults()) {
result.addMessage(testStepResult.getTestStep().getName() + " - " + testStepResult.getStatus()
+ " - " + testStepResult.getTimeTaken());
for (String msg : testStepResult.getMessages()) {
result.addMessage("- " + msg);
}
if (testStepResult instanceof MessageExchangeTestStepResult) {
result.addMessages(((MessageExchangeTestStepResult) testStepResult).getMessageExchanges());
}
}
switch (testCaseRunner.getStatus()) {
case CANCELED:
result.setStatus(TestStepStatus.CANCELED);
break;
case FAILED:
result.setStatus(TestStepStatus.FAILED);
break;
case FINISHED:
result.setStatus(TestStepStatus.OK);
break;
default:
result.setStatus(TestStepStatus.UNKNOWN);
break;
}
for (TestRunListener listener : testRunListeners) {
runningTestCase.removeTestRunListener(listener);
}
if (runMode == RunTestCaseRunModeTypeConfig.PARALLELL) {
runningTestCase.release();
}
runningTestCase.removeTestRunListener(testRunListener);
runningTestCase = null;
testCaseRunner = null;
}
}
} else {
result.setStatus(TestStepStatus.FAILED);
result.addMessage("Missing testCase in project");
result.stopTimer();
}
return result;
}
@Override
public String getLabel() {
String name = getName();
if (testCaseRunner != null) {
name += " - [" + testCaseRunner.getStatus() + "]";
}
if (isDisabled()) {
return name + " (disabled)";
} else {
return name;
}
}
@Override
public boolean cancel() {
if (testCaseRunner != null) {
testCaseRunner.cancel("Canceled by calling TestCase");
}
return true;
}
private String getTestCaseId() {
return stepConfig.getTargetTestCase();
}
public void setTargetTestCase(WsdlTestCase testCase) {
if (targetTestCase != null) {
targetTestCase.getTestSuite().removeTestSuiteListener(testSuiteListener);
targetTestCase.removeTestPropertyListener(testPropertyListener);
}
WsdlTestCase oldTestCase = this.targetTestCase;
this.targetTestCase = testCase;
if (testCase != null) {
stepConfig.setTargetTestCase(testCase.getId());
targetTestCase.getTestSuite().addTestSuiteListener(testSuiteListener);
targetTestCase.addTestPropertyListener(testPropertyListener);
syncProperties();
}
notifyPropertyChanged(TARGET_TESTCASE, oldTestCase, testCase);
}
public boolean isCopyHttpSession() {
return stepConfig.getCopyHttpSession();
}
public boolean isCopyLoadTestProperties() {
return stepConfig.getCopyLoadTestProperties();
}
public boolean isIgnoreEmptyProperties() {
return stepConfig.getIgnoreEmptyProperties();
}
public void setCopyHttpSession(boolean arg0) {
if (arg0 == isCopyHttpSession()) {
return;
}
stepConfig.setCopyHttpSession(arg0);
notifyPropertyChanged("copyHttpSession", !arg0, arg0);
}
public void setCopyLoadTestProperties(boolean arg0) {
if (arg0 == isCopyLoadTestProperties()) {
return;
}
stepConfig.setCopyLoadTestProperties(arg0);
notifyPropertyChanged("copyLoadTestProperties", !arg0, arg0);
}
public void setIgnoreEmptyProperties(boolean arg0) {
if (arg0 == isIgnoreEmptyProperties()) {
return;
}
stepConfig.setIgnoreEmptyProperties(arg0);
notifyPropertyChanged("ignoreEmptyProperties", !arg0, arg0);
}
/**
* Creates a copy of the underlying WsdlTestCase with all LoadTests removed
* and configured for LoadTesting
*/
private WsdlTestCase createTestCase(WsdlTestCase testCase) {
// clone config and remove and loadtests
testCase.beforeSave();
try {
TestCaseConfig config = TestCaseConfig.Factory.parse(testCase.getConfig().xmlText());
config.setLoadTestArray(new LoadTestConfig[0]);
// clone entire testCase
WsdlTestCase wsdlTestCase = testCase.getTestSuite().buildTestCase(config, true);
wsdlTestCase.afterLoad();
return wsdlTestCase;
} catch (Throwable e) {
SoapUI.logError(e);
}
return null;
}
public void addTestPropertyListener(TestPropertyListener listener) {
propertyHolderSupport.addTestPropertyListener(listener);
}
public Map<String, TestProperty> getProperties() {
return propertyHolderSupport.getProperties();
}
public PropertiesStepProperty getProperty(String name) {
return propertyHolderSupport.getProperty(name);
}
public String[] getPropertyNames() {
return propertyHolderSupport.getPropertyNames();
}
public List<TestProperty> getPropertyList() {
return propertyHolderSupport.getPropertyList();
}
public String getPropertyValue(String name) {
return propertyHolderSupport.getPropertyValue(name);
}
public boolean hasProperty(String name) {
return propertyHolderSupport.hasProperty(name);
}
public void removeTestPropertyListener(TestPropertyListener listener) {
propertyHolderSupport.removeTestPropertyListener(listener);
}
public void setPropertyValue(String name, String value) {
propertyHolderSupport.setPropertyValue(name, value);
}
private void updateLabelDuringRun() {
notifyPropertyChanged(WsdlTestStep.LABEL_PROPERTY, currentLabel, getLabel());
currentLabel = getLabel();
}
private final class InternalTestPropertyListener extends TestPropertyListenerAdapter {
@Override
public void propertyAdded(String name) {
propertyHolderSupport.addProperty(name);
}
@Override
public void propertyRemoved(String name) {
propertyHolderSupport.removeProperty(name);
}
@Override
public void propertyRenamed(String oldName, String newName) {
propertyHolderSupport.renameProperty(oldName, newName);
}
@Override
public void propertyMoved(String name, int oldIndex, int newIndex) {
propertyHolderSupport.moveProperty(name, newIndex);
}
}
private final class InternalTestRunListener extends TestRunListenerAdapter {
@Override
public void beforeRun(TestCaseRunner testRunner, TestCaseRunContext runContext) {
updateLabelDuringRun();
}
@Override
public void afterRun(TestCaseRunner testRunner, TestCaseRunContext runContext) {
updateLabelDuringRun();
}
@Override
public void afterStep(TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result) {
updateLabelDuringRun();
}
@Override
public void beforeStep(TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep) {
updateLabelDuringRun();
}
}
@Override
public void resetConfigOnMove(TestStepConfig config) {
super.resetConfigOnMove(config);
stepConfig = (RunTestCaseStepConfig) config.getConfig().changeType(RunTestCaseStepConfig.type);
propertyHolderSupport.resetPropertiesConfig(stepConfig.getProperties());
}
@Override
public void release() {
if (targetTestCase != null) {
targetTestCase.getTestSuite().removeTestSuiteListener(testSuiteListener);
targetTestCase.removeTestPropertyListener(testPropertyListener);
}
super.release();
}
private final class InternalTestSuiteListener extends TestSuiteListenerAdapter {
@Override
public void testCaseRemoved(TestCase testCase) {
setTargetTestCase(findTargetTestCase());
}
}
public WsdlTestCase getTargetTestCase() {
return targetTestCase;
}
public void addTestRunListener(TestRunListener listener) {
testRunListeners.add(listener);
}
public void removeTestRunListener(TestRunListener listener) {
testRunListeners.remove(listener);
}
public WsdlTestCase getRunningTestCase() {
return runningTestCase;
}
public WsdlTestCaseRunner getTestCaseRunner() {
return testCaseRunner;
}
public RunTestCaseRunModeTypeConfig.Enum getRunMode() {
return stepConfig.getRunMode();
}
public void setRunMode(RunTestCaseRunModeTypeConfig.Enum runMode) {
stepConfig.setRunMode(runMode);
}
public TestProperty getPropertyAt(int index) {
return propertyHolderSupport.getPropertyAt(index);
}
public int getPropertyCount() {
return propertyHolderSupport.getPropertyCount();
}
@Override
public void resolve(ResolveContext<?> context) {
super.resolve(context);
if (targetTestCase == null) {
if (context.hasThisModelItem(this, "Missing Test Case",
getTestStepTitle() + "/" + stepConfig.getTargetTestCase())) {
return;
}
context
.addPathToResolve(this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase())
.addResolvers(new RunTestCaseRemoveResolver(this), new ChooseAnotherTestCase(this),
new CreateNewEmptyTestCase(this));
} else {
targetTestCase.resolve(context);
if (context.hasThisModelItem(this, "Missing Test Case",
getTestStepTitle() + "/" + stepConfig.getTargetTestCase())) {
context.getPath(this, "Missing Test Case", getTestStepTitle() + "/" + stepConfig.getTargetTestCase())
.setSolved(true);
}
}
}
}