/*******************************************************************************
* Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package de.gebit.integrity.runner.callbacks.remoting;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import com.google.inject.Inject;
import com.google.inject.Provider;
import de.gebit.integrity.dsl.Call;
import de.gebit.integrity.dsl.ConstantEntity;
import de.gebit.integrity.dsl.MethodReference;
import de.gebit.integrity.dsl.Parameter;
import de.gebit.integrity.dsl.Suite;
import de.gebit.integrity.dsl.SuiteDefinition;
import de.gebit.integrity.dsl.SuiteReturn;
import de.gebit.integrity.dsl.SuiteStatementWithResult;
import de.gebit.integrity.dsl.TableTest;
import de.gebit.integrity.dsl.TableTestRow;
import de.gebit.integrity.dsl.Test;
import de.gebit.integrity.dsl.ValueOrEnumValueOrOperationCollection;
import de.gebit.integrity.dsl.Variable;
import de.gebit.integrity.dsl.VariableAssignment;
import de.gebit.integrity.dsl.VariableEntity;
import de.gebit.integrity.dsl.VariableOrConstantEntity;
import de.gebit.integrity.dsl.VariantDefinition;
import de.gebit.integrity.dsl.VisibleComment;
import de.gebit.integrity.dsl.VisibleDivider;
import de.gebit.integrity.exceptions.MethodNotFoundException;
import de.gebit.integrity.fixtures.ExtendedResultFixture.ExtendedResult;
import de.gebit.integrity.fixtures.ExtendedResultFixture.ExtendedResultHTML;
import de.gebit.integrity.fixtures.ExtendedResultFixture.ExtendedResultImage;
import de.gebit.integrity.fixtures.ExtendedResultFixture.ExtendedResultText;
import de.gebit.integrity.operations.UnexecutableException;
import de.gebit.integrity.parameter.conversion.ConversionContext;
import de.gebit.integrity.parameter.conversion.UnresolvableVariableHandling;
import de.gebit.integrity.parameter.resolving.ParameterResolver;
import de.gebit.integrity.parameter.resolving.TableTestParameterResolveMethod;
import de.gebit.integrity.remoting.entities.setlist.SetList;
import de.gebit.integrity.remoting.entities.setlist.SetListEntry;
import de.gebit.integrity.remoting.entities.setlist.SetListEntryAttributeKeys;
import de.gebit.integrity.remoting.entities.setlist.SetListEntryTypes;
import de.gebit.integrity.remoting.server.IntegrityRemotingServer;
import de.gebit.integrity.remoting.transport.enums.TestRunnerCallbackMethods;
import de.gebit.integrity.runner.TestModel;
import de.gebit.integrity.runner.callbacks.AbstractTestRunnerCallback;
import de.gebit.integrity.runner.callbacks.TestFormatter;
import de.gebit.integrity.runner.results.FixtureExecutionResult;
import de.gebit.integrity.runner.results.SuiteResult;
import de.gebit.integrity.runner.results.SuiteSummaryResult;
import de.gebit.integrity.runner.results.call.CallResult;
import de.gebit.integrity.runner.results.call.CallResult.UpdatedVariable;
import de.gebit.integrity.runner.results.test.TestComparisonFailureResult;
import de.gebit.integrity.runner.results.test.TestComparisonResult;
import de.gebit.integrity.runner.results.test.TestComparisonSuccessResult;
import de.gebit.integrity.runner.results.test.TestExceptionSubResult;
import de.gebit.integrity.runner.results.test.TestExecutedSubResult;
import de.gebit.integrity.runner.results.test.TestResult;
import de.gebit.integrity.runner.results.test.TestSubResult;
import de.gebit.integrity.utils.IntegrityDSLUtil;
/**
* Callback for creation and update of the {@link SetList} - a crucial part of Integritys' remoting system.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public class SetListCallback extends AbstractTestRunnerCallback {
/**
* The remoting server.
*/
private IntegrityRemotingServer remotingServer;
/**
* The setlist that this callback is updating.
*/
private SetList setList;
/**
* Stack of {@link SetListEntry}s. The stack grows when entering suites, and shrinks when returning from sub-suites.
*/
private Stack<SetListEntry> entryStack = new Stack<SetListEntry>();
/**
* The parameter resolver to use.
*/
@Inject
private ParameterResolver parameterResolver;
/**
* The test formatter to use.
*/
@Inject
private TestFormatter testFormatter;
/**
* The conversion context provider.
*/
@Inject
protected Provider<ConversionContext> conversionContextProvider;
/**
* Format used for execution time.
*/
private static final DecimalFormat EXECUTION_TIME_FORMAT = new DecimalFormat("0.000");
/**
* Creates a new instance.
*
* @param aSetList
* the setlist to update
* @param aRemotingServer
* the remoting server to use
*/
public SetListCallback(SetList aSetList, IntegrityRemotingServer aRemotingServer) {
setList = aSetList;
remotingServer = aRemotingServer;
}
@Override
public void onExecutionStart(TestModel aModel, VariantDefinition aVariant) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.EXECUTION);
entryStack.push(tempNewEntry);
}
@Override
public void onSuiteStart(Suite aSuite) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.SUITE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME,
IntegrityDSLUtil.getQualifiedSuiteName(aSuite.getDefinition()));
if (getForkInExecution() != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.FORK_NAME, getForkInExecution().getName());
if (getForkInExecution().getDescription() != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.FORK_DESCRIPTION,
getForkInExecution().getDescription());
}
}
addLinkToEntry(tempNewEntry, aSuite);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
entryStack.push(tempNewEntry);
}
@Override
public void onSetupStart(SuiteDefinition aSetupSuite) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.SUITE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME, IntegrityDSLUtil.getQualifiedSuiteName(aSetupSuite));
addLinkToEntry(tempNewEntry, aSetupSuite);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.SETUP, tempNewEntry);
entryStack.push(tempNewEntry);
}
@Override
public void onSetupFinish(SuiteDefinition aSetupSuite, SuiteResult aResult) {
onAnyKindOfSuiteFinish(aSetupSuite, aResult);
}
@Override
public void onTestStart(Test aTest) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.TEST);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME, aTest.getDefinition().getName());
SetListEntry[] tempParamEntries = addMethodAndParamsToTestOrCall(aTest.getDefinition().getFixtureMethod(),
aTest.getParameters(), tempNewEntry, aTest);
addLinkToEntry(tempNewEntry, aTest);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
entryStack.push(tempNewEntry);
setList.setEntryInExecutionReference(tempNewEntry.getId());
sendUpdateToClients(tempNewEntry.getId(), tempNewEntry, tempParamEntries);
}
@Override
public void onTableTestStart(TableTest aTableTest) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.TABLETEST);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME, aTableTest.getDefinition().getName());
SetListEntry[] tempParamEntries = addMethodAndParamsToTestOrCall(aTableTest.getDefinition().getFixtureMethod(),
aTableTest.getParameters(), tempNewEntry, aTableTest);
addLinkToEntry(tempNewEntry, aTableTest);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
entryStack.push(tempNewEntry);
setList.setEntryInExecutionReference(tempNewEntry.getId());
sendUpdateToClients(tempNewEntry.getId(), tempNewEntry, tempParamEntries);
}
@Override
public void onTableTestRowStart(TableTest aTableTest, TableTestRow aRow) {
// nothing to do here
}
@Override
public void onTableTestRowFinish(TableTest aTableTest, TableTestRow aRow, TestSubResult aSubResult) {
SetListEntry tempTestEntry = entryStack.peek();
List<SetListEntry> tempNewEntries = new LinkedList<SetListEntry>();
Map<String, Object> tempParameterMap = new HashMap<String, Object>();
try {
// TODO see if this can be forwarded to the callbacks from the test runner; right now it's calculated twice
tempParameterMap = parameterResolver.createParameterMap(aTableTest, aRow,
TableTestParameterResolveMethod.COMBINED, true,
createConversionContext().getUnresolvableVariableHandlingPolicy());
} catch (InstantiationException exc) {
exc.printStackTrace();
} catch (ClassNotFoundException exc) {
exc.printStackTrace();
} catch (UnexecutableException exc) {
exc.printStackTrace();
}
List<SetListEntry> tempResultEntries = onAnyKindOfSubTestFinish(aTableTest.getDefinition().getFixtureMethod(),
aTableTest, tempTestEntry, aSubResult, tempParameterMap);
// Add a link to the first entry from the list, which is the actual result entry
addLinkToEntry(tempResultEntries.get(0), aRow);
tempNewEntries.addAll(tempResultEntries);
sendUpdateToClients(null, tempNewEntries.toArray(new SetListEntry[0]));
}
@Override
public void onTableTestFinish(TableTest aTableTest, TestResult aResult) {
SetListEntry tempTestEntry = entryStack.pop();
if (aResult != null) {
if (aResult.getExecutionTime() != null) {
tempTestEntry.setAttribute(SetListEntryAttributeKeys.EXECUTION_TIME,
nanoTimeToString(aResult.getExecutionTime()));
tempTestEntry.setAttribute(SetListEntryAttributeKeys.SUCCESS_COUNT, aResult.getSubTestSuccessCount());
tempTestEntry.setAttribute(SetListEntryAttributeKeys.FAILURE_COUNT, aResult.getSubTestFailCount());
tempTestEntry.setAttribute(SetListEntryAttributeKeys.TEST_EXCEPTION_COUNT,
aResult.getSubTestExceptionCount());
tempTestEntry.setAttribute(SetListEntryAttributeKeys.CALL_EXCEPTION_COUNT, 0);
}
}
addExtendedResultDataToEntry(tempTestEntry, aResult);
sendUpdateToClients(null, tempTestEntry);
}
@Override
public void onTestFinish(Test aTest, TestResult aResult) {
SetListEntry tempTestEntry = entryStack.pop();
Map<String, Object> tempParameterMap = new HashMap<String, Object>();
try {
tempParameterMap = parameterResolver.createParameterMap(aTest, true,
createConversionContext().getUnresolvableVariableHandlingPolicy());
} catch (InstantiationException exc) {
exc.printStackTrace();
} catch (ClassNotFoundException exc) {
exc.printStackTrace();
} catch (UnexecutableException exc) {
exc.printStackTrace();
}
addExtendedResultDataToEntry(tempTestEntry, aResult);
List<SetListEntry> tempNewEntries = onAnyKindOfSubTestFinish(aTest.getDefinition().getFixtureMethod(), aTest,
tempTestEntry, aResult.getSubResults().get(0), tempParameterMap);
tempNewEntries.add(tempTestEntry);
sendUpdateToClients(null, tempNewEntries.toArray(new SetListEntry[0]));
}
/**
* This method is used to perform the actual sub-test result parsing, both for normal tests and tabletests (with the
* latter having more than one subtest).
*
* @param aMethod
* the fixture method
* @param aStatement
* the statement currently being executed
* @param aTestEntry
* the setlist entry for the test
* @param aSubResult
* the sub-result to analyze
* @param aParameterMap
* the parameters given to the test method
* @return a list of newly generated setlist entries (with the first being the result entry itself)
*/
protected List<SetListEntry> onAnyKindOfSubTestFinish(MethodReference aMethod, SuiteStatementWithResult aStatement,
SetListEntry aTestEntry, TestSubResult aSubResult, Map<String, Object> aParameterMap) {
List<SetListEntry> tempNewEntries = new LinkedList<SetListEntry>();
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.RESULT);
tempNewEntries.add(tempNewEntry);
if (aSubResult.getExecutionTime() != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.EXECUTION_TIME,
nanoTimeToString(aSubResult.getExecutionTime()));
}
for (Entry<String, Object> tempEntry : aParameterMap.entrySet()) {
SetListEntry tempParameterEntry = setList.createEntry(SetListEntryTypes.PARAMETER);
tempNewEntries.add(tempParameterEntry);
tempParameterEntry.setAttribute(SetListEntryAttributeKeys.NAME, tempEntry.getKey());
tempParameterEntry.setAttribute(SetListEntryAttributeKeys.VALUE,
valueConverter.convertValueToString(tempEntry.getValue(), false, createConversionContext()));
setList.addReference(tempNewEntry, SetListEntryAttributeKeys.PARAMETERS, tempParameterEntry);
}
try {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, testFormatter
.fixtureMethodToHumanReadableString(aMethod, aStatement, aParameterMap, createConversionContext()));
} catch (ClassNotFoundException exc) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
} catch (MethodNotFoundException exc) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
}
if (aSubResult instanceof TestExceptionSubResult) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.FALSE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.EXCEPTION,
stackTraceToString(((TestExceptionSubResult) aSubResult).getException()));
} else if (aSubResult instanceof TestExecutedSubResult) {
if (!aSubResult.isUndetermined()) {
if (aSubResult.wereAllComparisonsSuccessful()) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.TRUE);
} else {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.FALSE);
}
}
}
for (Entry<String, TestComparisonResult> tempEntry : aSubResult.getComparisonResults().entrySet()) {
SetListEntry tempComparisonEntry = setList.createEntry(SetListEntryTypes.COMPARISON);
tempNewEntries.add(tempComparisonEntry);
tempComparisonEntry.setAttribute(SetListEntryAttributeKeys.NAME, tempEntry.getKey());
// Either there is an expected value, or if there isn't, "true" is the default
ValueOrEnumValueOrOperationCollection tempExpectedValue = tempEntry.getValue().getExpectedValue();
boolean tempExpectedIsNestedObject = containsNestedObject(tempExpectedValue);
tempComparisonEntry.setAttribute(SetListEntryAttributeKeys.EXPECTED_RESULT,
valueConverter.convertValueToString((tempExpectedValue == null ? true : tempExpectedValue), false,
createConversionContext()));
if (tempEntry.getValue().getActualValue() != null) {
tempComparisonEntry.setAttribute(SetListEntryAttributeKeys.VALUE,
convertResultValueToStringGuarded(tempEntry.getValue().getActualValue(), aSubResult,
tempExpectedIsNestedObject,
createConversionContext().withComparisonResult(tempEntry.getValue().getResult())));
}
if (tempEntry.getValue() instanceof TestComparisonSuccessResult) {
tempComparisonEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.TRUE);
} else if (tempEntry.getValue() instanceof TestComparisonFailureResult) {
tempComparisonEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.FALSE);
}
setList.addReference(tempNewEntry, SetListEntryAttributeKeys.COMPARISONS, tempComparisonEntry);
}
setList.addReference(aTestEntry, SetListEntryAttributeKeys.RESULT, tempNewEntry);
return tempNewEntries;
}
@Override
public void onCallStart(Call aCall) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.CALL);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME, aCall.getDefinition().getName());
SetListEntry[] tempParamEntries = addMethodAndParamsToTestOrCall(aCall.getDefinition().getFixtureMethod(),
aCall.getParameters(), tempNewEntry, aCall);
addLinkToEntry(tempNewEntry, aCall);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
entryStack.push(tempNewEntry);
setList.setEntryInExecutionReference(tempNewEntry.getId());
sendUpdateToClients(tempNewEntry.getId(), tempNewEntry, tempParamEntries);
}
@Override
public void onCallFinish(Call aCall, CallResult aResult) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.RESULT);
if (aResult.getExecutionTime() != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.EXECUTION_TIME,
nanoTimeToString(aResult.getExecutionTime()));
}
if (aResult instanceof de.gebit.integrity.runner.results.call.SuccessResult) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.TRUE);
} else if (aResult instanceof de.gebit.integrity.runner.results.call.ExceptionResult) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.FALSE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.EXCEPTION, stackTraceToString(
((de.gebit.integrity.runner.results.call.ExceptionResult) aResult).getException()));
}
SetListEntry[] tempEntries = new SetListEntry[aResult.getUpdatedVariables().size()];
int tempCount = 0;
for (UpdatedVariable tempUpdatedVariable : aResult.getUpdatedVariables()) {
SetListEntry tempResultEntry = setList.createEntry(SetListEntryTypes.VARIABLE_UPDATE);
if (tempUpdatedVariable.getTargetVariable() != null) {
tempResultEntry.setAttribute(SetListEntryAttributeKeys.VARIABLE_NAME,
tempUpdatedVariable.getTargetVariable().getName());
}
if (tempUpdatedVariable.getValue() != null) {
tempResultEntry.setAttribute(SetListEntryAttributeKeys.VALUE, convertResultValueToStringGuarded(
tempUpdatedVariable.getValue(), aResult, false, createConversionContext()));
}
if (tempUpdatedVariable.getParameterName() != null) {
tempResultEntry.setAttribute(SetListEntryAttributeKeys.PARAMETER_NAME,
tempUpdatedVariable.getParameterName());
}
setList.addReference(tempNewEntry, SetListEntryAttributeKeys.VARIABLE_UPDATES, tempResultEntry);
tempEntries[tempCount] = tempResultEntry;
tempCount++;
}
SetListEntry tempCallEntry = entryStack.pop();
addExtendedResultDataToEntry(tempCallEntry, aResult);
setList.addReference(tempCallEntry, SetListEntryAttributeKeys.RESULT, tempNewEntry);
sendUpdateToClients(null, tempEntries, tempCallEntry, tempNewEntry);
}
@Override
public void onTearDownStart(SuiteDefinition aTearDownSuite) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.SUITE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME,
IntegrityDSLUtil.getQualifiedSuiteName(aTearDownSuite));
addLinkToEntry(tempNewEntry, aTearDownSuite);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.TEARDOWN, tempNewEntry);
entryStack.push(tempNewEntry);
sendUpdateToClients(null, tempNewEntry);
}
@Override
public void onTearDownFinish(SuiteDefinition aTearDownSuite, SuiteResult aResult) {
onAnyKindOfSuiteFinish(aTearDownSuite, aResult);
}
@Override
public void onSuiteFinish(Suite aSuite, SuiteSummaryResult aResult) {
onAnyKindOfSuiteFinish(aSuite.getDefinition(), aResult);
}
private void onAnyKindOfSuiteFinish(SuiteDefinition aSuite, SuiteSummaryResult aResult) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.RESULT);
if (aResult != null) {
if (aResult.getExecutionTime() != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.EXECUTION_TIME,
nanoTimeToString(aResult.getExecutionTime()));
}
tempNewEntry.setAttribute(SetListEntryAttributeKeys.SUCCESS_COUNT, aResult.getTestSuccessCount());
tempNewEntry.setAttribute(SetListEntryAttributeKeys.FAILURE_COUNT, aResult.getTestFailCount());
tempNewEntry.setAttribute(SetListEntryAttributeKeys.TEST_EXCEPTION_COUNT, aResult.getTestExceptionCount());
tempNewEntry.setAttribute(SetListEntryAttributeKeys.CALL_EXCEPTION_COUNT, aResult.getCallExceptionCount());
}
setList.addReference(entryStack.pop(), SetListEntryAttributeKeys.RESULT, tempNewEntry);
sendUpdateToClients(null, tempNewEntry);
}
@Override
public void onExecutionFinish(TestModel aModel, SuiteSummaryResult aResult) {
setList.setEntryInExecutionReference(null);
}
@Override
public void onVisibleComment(String aCommentText, boolean anIsTitle, VisibleComment aCommentElement) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.COMMENT);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.VALUE, aCommentText);
if (anIsTitle) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.TYPE, "title");
}
addLinkToEntry(tempNewEntry, aCommentElement);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
sendUpdateToClients(null, tempNewEntry);
}
@Override
public void onVisibleDivider(String aDividerText, VisibleDivider aDividerElement) {
// currently these are ignored here
}
@Override
public void onVariableDefinition(VariableEntity aDefinition, SuiteDefinition aSuite, Object anInitialValue) {
onVariableDefinitionInternal(aDefinition, aSuite, anInitialValue);
}
@Override
public void onConstantDefinition(ConstantEntity aDefinition, SuiteDefinition aSuite, Object aValue,
boolean aParameterizedFlag) {
// constants are handled like variables here (for now...)
onVariableDefinitionInternal(aDefinition, aSuite, aValue);
}
@Override
public void onVariableAssignment(VariableAssignment anAssignment, VariableEntity aVariableEntity,
SuiteDefinition aSuite, Object aValue) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.VARIABLE_ASSIGNMENT);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION,
testFormatter.variableAssignmentToHumanReadableString(anAssignment, createConversionContext()));
SetListEntry tempResultEntry = setList.createEntry(SetListEntryTypes.RESULT);
if (!isDryRun()) {
tempResultEntry.setAttribute(SetListEntryAttributeKeys.RESULT_SUCCESS_FLAG, Boolean.TRUE);
}
SetListEntry tempUpdateEntry = setList.createEntry(SetListEntryTypes.VARIABLE_UPDATE);
tempUpdateEntry.setAttribute(SetListEntryAttributeKeys.VARIABLE_NAME, aVariableEntity.getName());
tempUpdateEntry.setAttribute(SetListEntryAttributeKeys.VALUE,
valueConverter.convertValueToString(aValue, false, createConversionContext()));
setList.addReference(tempResultEntry, SetListEntryAttributeKeys.VARIABLE_UPDATES, tempUpdateEntry);
setList.addReference(tempNewEntry, SetListEntryAttributeKeys.RESULT, tempResultEntry);
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.STATEMENTS, tempNewEntry);
sendUpdateToClients(null, tempUpdateEntry, tempResultEntry, tempNewEntry);
}
@Override
public void onAbortExecution(String anAbortExecutionMessage, String anAbortExecutionStackTrace) {
// not used in this context
}
private void onVariableDefinitionInternal(VariableOrConstantEntity aDefinition, SuiteDefinition aSuite,
Object anInitialValue) {
SetListEntry tempNewEntry = setList.createEntry(SetListEntryTypes.VARIABLE);
tempNewEntry.setAttribute(SetListEntryAttributeKeys.NAME,
IntegrityDSLUtil.getQualifiedVariableEntityName(aDefinition, false));
if (anInitialValue != null) {
tempNewEntry.setAttribute(SetListEntryAttributeKeys.VALUE,
valueConverter.convertValueToString(anInitialValue, false, createConversionContext()));
}
setList.addReference(entryStack.peek(), SetListEntryAttributeKeys.VARIABLE_DEFINITIONS, tempNewEntry);
sendUpdateToClients(null, tempNewEntry);
}
@Override
public void onReturnVariableAssignment(SuiteReturn aReturn, VariableEntity aSource, VariableEntity aTarget,
Suite aSuite, Object aValue) {
// not used in this context
}
/**
* Determines the way unresolvable variables are to be handled.
*
* @return
*/
protected ConversionContext createConversionContext() {
if (isDryRun()) {
return conversionContextProvider.get().withUnresolvableVariableHandlingPolicy(
UnresolvableVariableHandling.RESOLVE_TO_UNRESOLVABLE_OBJECT);
} else {
return conversionContextProvider.get();
}
}
/**
* Adds information about the fixture method being called and the parameters given to it to a test or call entry.
*
* @param aMethod
* the fixture method
* @param aParamList
* the parameters
* @param anEntry
* the entry to add the information to
* @param aStatement
* the statement currently in execution
* @return the setlist entries created for the parameters
*/
protected SetListEntry[] addMethodAndParamsToTestOrCall(MethodReference aMethod, EList<Parameter> aParamList,
SetListEntry anEntry, SuiteStatementWithResult aStatement) {
try {
anEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION,
testFormatter.fixtureMethodToHumanReadableString(aMethod, aStatement,
parameterResolver.createParameterMap(aParamList, true,
createConversionContext().getUnresolvableVariableHandlingPolicy()),
createConversionContext()));
} catch (ClassNotFoundException exc) {
anEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
} catch (UnexecutableException exc) {
anEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
} catch (InstantiationException exc) {
anEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
} catch (MethodNotFoundException exc) {
anEntry.setAttribute(SetListEntryAttributeKeys.DESCRIPTION, exc.getMessage());
exc.printStackTrace();
}
anEntry.setAttribute(SetListEntryAttributeKeys.FIXTURE,
IntegrityDSLUtil.getQualifiedNameOfFixtureMethod(aMethod));
SetListEntry[] tempResultArray = new SetListEntry[aParamList.size()];
int tempParamCounter = 0;
for (Parameter tempParameter : aParamList) {
SetListEntry tempParamEntry = setList.createEntry(SetListEntryTypes.PARAMETER);
tempParamEntry.setAttribute(SetListEntryAttributeKeys.NAME,
IntegrityDSLUtil.getParamNameStringFromParameterName(tempParameter.getName()));
tempParamEntry.setAttribute(SetListEntryAttributeKeys.VALUE,
valueConverter.convertValueToString(tempParameter.getValue(), false, createConversionContext()));
if (tempParameter.getValue() instanceof Variable) {
tempParamEntry.setAttribute(SetListEntryAttributeKeys.VARIABLE_NAME,
((Variable) tempParameter.getValue()).getName().getName());
}
setList.addReference(anEntry, SetListEntryAttributeKeys.PARAMETERS, tempParamEntry);
tempResultArray[tempParamCounter] = tempParamEntry;
tempParamCounter++;
}
return tempResultArray;
}
/**
* Sends a setlist entry update to all clients of the remoting server.
*
* @param anEntryInExecution
* the entry that is currently in execution (may be null if that information shouldn't be included)
* @param someUpdatedEntries
* the actual updated entries
*/
protected void sendUpdateToClients(Integer anEntryInExecution, SetListEntry... someUpdatedEntries) {
if (remotingServer != null && !isDryRun()) {
remotingServer.updateSetList(anEntryInExecution, someUpdatedEntries);
}
}
/**
* Sends a setlist entry update to all clients of the remoting server. This is a convenience method and behaves much
* like {@link #sendUpdateToClients(Integer, SetListEntry...)}.
*
* @param anEntryInExecution
* the entry that is currently in execution (may be null if that information shouldn't be included)
* @param aSingleEntry
* one single updated entry
* @param someMoreEntries
* more updated entries
*/
protected void sendUpdateToClients(Integer anEntryInExecution, SetListEntry aSingleEntry,
SetListEntry[] someMoreEntries) {
SetListEntry[] tempCombined = new SetListEntry[someMoreEntries.length + 1];
tempCombined[0] = aSingleEntry;
System.arraycopy(someMoreEntries, 0, tempCombined, 1, someMoreEntries.length);
sendUpdateToClients(anEntryInExecution, tempCombined);
}
/**
* Sends a setlist entry update to all clients of the remoting server. This is a convenience method and behaves much
* like {@link #sendUpdateToClients(Integer, SetListEntry...)}.
*
* @param anEntryInExecution
* the entry that is currently in execution (may be null if that information shouldn't be included)
* @param someEntries
* some updated entries as an array
* @param someSingleEntries
* more updated entries
*/
protected void sendUpdateToClients(Integer anEntryInExecution, SetListEntry[] someEntries,
SetListEntry... someSingleEntries) {
SetListEntry[] tempCombined = new SetListEntry[someEntries.length + someSingleEntries.length];
System.arraycopy(someSingleEntries, 0, tempCombined, 0, someSingleEntries.length);
System.arraycopy(someEntries, 0, tempCombined, someSingleEntries.length, someEntries.length);
sendUpdateToClients(anEntryInExecution, tempCombined);
}
/**
* Utility method to convert a stack trace to a string to be included in a setlist entry.
*
* @param anException
* the exception from which to take the stack trace
* @return the formatted trace string
*/
protected static String stackTraceToString(Throwable anException) {
String tempResult = null;
StringWriter tempStringWriter = null;
PrintWriter tempPrintWriter = null;
try {
tempStringWriter = new StringWriter();
tempPrintWriter = new PrintWriter(tempStringWriter);
anException.printStackTrace(tempPrintWriter);
tempResult = tempStringWriter.toString();
} finally {
try {
if (tempPrintWriter != null) {
tempPrintWriter.close();
}
if (tempStringWriter != null) {
tempStringWriter.close();
}
} catch (IOException exc) {
// ignore, cannot happen
}
}
return tempResult;
}
/**
* Converts a nanosecond time value into a string according to the {@link #EXECUTION_TIME_FORMAT}.
*
* @param aNanosecondValue
* the time value
* @return the formatted string
*/
protected static String nanoTimeToString(long aNanosecondValue) {
return EXECUTION_TIME_FORMAT.format(((double) aNanosecondValue) / 1000000.0);
}
@Override
public void onMessageFromFork(TestRunnerCallbackMethods aMethod, Serializable... someObjects) {
// not used
}
/**
* Adds a link (to suite and line number) to the given {@link SetListEntry}.
*
* @param anEntry
* the entry to add the link to
* @param anObject
* the object to link to
*/
protected void addLinkToEntry(SetListEntry anEntry, EObject anObject) {
SuiteDefinition tempParentSuite = null;
EObject tempParent = anObject;
while (tempParentSuite == null && tempParent != null) {
if (tempParent instanceof SuiteDefinition) {
tempParentSuite = (SuiteDefinition) tempParent;
} else {
tempParent = tempParent.eContainer();
}
}
if (tempParentSuite != null) {
String tempLink = IntegrityDSLUtil.getQualifiedSuiteName(tempParentSuite);
if (!(anObject instanceof SuiteDefinition)) {
ICompositeNode tempNode = NodeModelUtils.getNode(anObject);
if (tempNode != null) {
int tempLine = tempNode.getStartLine();
tempLink += "#" + tempLine;
}
}
anEntry.setAttribute(SetListEntryAttributeKeys.LINK, tempLink);
}
}
/**
* Adds the extended result data in the {@link FixtureExecutionResult} object to the provided {@link SetListEntry}.
* If there's no extended results, this method does nothing.
*
* @param anEntry
* the entry to attach results to
* @param aResult
* the result to explore
*/
protected void addExtendedResultDataToEntry(SetListEntry anEntry, FixtureExecutionResult aResult) {
if (aResult.getExtendedResults() == null || aResult.getExtendedResults().size() == 0) {
return;
}
List<Object[]> tempTargetList = new ArrayList<Object[]>(aResult.getExtendedResults().size());
for (ExtendedResult tempExtResult : aResult.getExtendedResults()) {
if (tempExtResult instanceof ExtendedResultText) {
tempTargetList
.add(new Object[] { tempExtResult.getTitle(), ((ExtendedResultText) tempExtResult).getText() });
} else if (tempExtResult instanceof ExtendedResultHTML) {
tempTargetList.add(
new Object[] { tempExtResult.getTitle(), ((ExtendedResultHTML) tempExtResult).getHypertext() });
} else if (tempExtResult instanceof ExtendedResultImage) {
tempTargetList.add(new Object[] { tempExtResult.getTitle(),
((ExtendedResultImage) tempExtResult).getEncodedImage() });
}
}
if (tempTargetList.size() > 0) {
anEntry.setAttribute(SetListEntryAttributeKeys.EXTENDED_RESULT_DATA,
tempTargetList.toArray(new Object[tempTargetList.size()]));
}
}
}