From 07c21b45307351c15d2c1789d5f7ed1c529dd064 Mon Sep 17 00:00:00 2001 From: Rene Schneider Date: Thu, 21 Feb 2019 16:06:20 +0100 Subject: [PATCH] fixes #225: added Optional support (including JUnit tests) --- .../DefaultModularValueConverter.java | 4 + .../java/other/OptionalToContainedObject.java | 55 ++++++++ .../java/other/OptionalToFormattedString.java | 40 ++++++ .../callbacks/xml/XmlWriterTestCallback.java | 65 +++++---- .../comparator/DefaultResultComparator.java | 59 +++++++- .../fixtures/OptionalTestFixture.integrity | 6 + .../basic/optionals/optionals.integrity | 80 +++++++++++ .../junit/basic/optionals/OptionalTest.java | 73 ++++++++++ .../results/integrity.basic.nullChecks.xml | 84 +++++------ ...c.optionals.optionalTestsWithVariables.xml | 107 ++++++++++++++ ....basic.optionals.optionalsAsParameters.xml | 133 ++++++++++++++++++ ...ty.basic.optionals.simpleOptionalTests.xml | 53 +++++++ ...grity.basic.parameterizedConstantNoDef.xml | 16 +-- ....suitecalls.suiteCallWithNullParameter.xml | 30 ++-- ...ty.basic.variableAttributeAccessNested.xml | 34 ++--- .../fixtures/basic/OptionalTestFixture.java | 37 +++++ 16 files changed, 757 insertions(+), 119 deletions(-) create mode 100644 de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToContainedObject.java create mode 100644 de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToFormattedString.java create mode 100644 de.gebit.integrity.tests/integrity/fixtures/OptionalTestFixture.integrity create mode 100644 de.gebit.integrity.tests/integrity/suites/basic/optionals/optionals.integrity create mode 100644 de.gebit.integrity.tests/junit/de/gebit/integrity/tests/junit/basic/optionals/OptionalTest.java create mode 100644 de.gebit.integrity.tests/results/integrity.basic.optionals.optionalTestsWithVariables.xml create mode 100644 de.gebit.integrity.tests/results/integrity.basic.optionals.optionalsAsParameters.xml create mode 100644 de.gebit.integrity.tests/results/integrity.basic.optionals.simpleOptionalTests.xml create mode 100644 de.gebit.integrity.tests/src/de/gebit/integrity/tests/fixtures/basic/OptionalTestFixture.java diff --git a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/DefaultModularValueConverter.java b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/DefaultModularValueConverter.java index d060079eb..d901dbef4 100644 --- a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/DefaultModularValueConverter.java +++ b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/DefaultModularValueConverter.java @@ -146,6 +146,8 @@ import de.gebit.integrity.parameter.conversion.conversions.java.other.ObjectToFormattedString; import de.gebit.integrity.parameter.conversion.conversions.java.other.ObjectToMap; import de.gebit.integrity.parameter.conversion.conversions.java.other.ObjectToString; +import de.gebit.integrity.parameter.conversion.conversions.java.other.OptionalToContainedObject; +import de.gebit.integrity.parameter.conversion.conversions.java.other.OptionalToFormattedString; import de.gebit.integrity.parameter.conversion.conversions.java.other.SQLDateToCalendar; import de.gebit.integrity.parameter.conversion.conversions.java.other.SQLDateToTimestamp; import de.gebit.integrity.parameter.conversion.conversions.java.other.SQLTimeToCalendar; @@ -244,6 +246,8 @@ protected void initializeConversions() { addConversion(SQLTimeToTimestamp.class); addConversion(SQLTimeToCalendar.class); addConversion(TimestampToCalendar.class); + addConversion(OptionalToFormattedString.class); + addConversion(OptionalToContainedObject.class); // identity conversions, Java -> Java addConversion(StringToString.class); diff --git a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToContainedObject.java b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToContainedObject.java new file mode 100644 index 000000000..2de10a9f2 --- /dev/null +++ b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToContainedObject.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.parameter.conversion.conversions.java.other; + +import java.util.Optional; + +import de.gebit.integrity.operations.UnexecutableException; +import de.gebit.integrity.parameter.conversion.Conversion; +import de.gebit.integrity.parameter.conversion.ConversionContext; +import de.gebit.integrity.parameter.conversion.ConversionFailedException; +import de.gebit.integrity.string.FormattedString; +import de.gebit.integrity.utils.ParameterUtil; +import de.gebit.integrity.utils.ParameterUtil.UnresolvableVariableException; + +/** + * This conversion is necessary to allow {@link Optional}s to be used as parameters. It basically resolves them to the + * contained object (which may have to be converted further afterwards). + * + * @author Rene Schneider - initial API and implementation + * + */ +@SuppressWarnings("rawtypes") +@de.gebit.integrity.parameter.conversion.Conversion.Priority(Integer.MIN_VALUE + 1) +public class OptionalToContainedObject extends Conversion { + + @Override + public Object convert(Optional aSource, Class aTargetType, ConversionContext aConversionContext) + throws ConversionFailedException { + if (aSource.isPresent()) { + try { + return convertValueRecursive(aTargetType, null, aSource.get(), aConversionContext); + } catch (UnresolvableVariableException | ClassNotFoundException | InstantiationException + | UnexecutableException exc) { + throw new ConversionFailedException(aSource.getClass(), aTargetType, + "Failed recursive conversion of Optional content", exc); + } + } else { + if (aTargetType == null || FormattedString.class.isAssignableFrom(aTargetType)) { + return new FormattedString(ParameterUtil.INEXISTENT_VALUE); + } else if (String.class.isAssignableFrom(aTargetType)) { + return ParameterUtil.INEXISTENT_VALUE; + } else { + // We can't convert this to any value with which we may preserve the knowledge about the "empty + // Optional". So we fall back to "null". + return null; + } + } + } + +} diff --git a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToFormattedString.java b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToFormattedString.java new file mode 100644 index 000000000..37f69308a --- /dev/null +++ b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/OptionalToFormattedString.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.parameter.conversion.conversions.java.other; + +import java.util.Optional; + +import de.gebit.integrity.parameter.conversion.Conversion; +import de.gebit.integrity.parameter.conversion.ConversionContext; +import de.gebit.integrity.parameter.conversion.ConversionFailedException; +import de.gebit.integrity.string.FormattedString; +import de.gebit.integrity.utils.ParameterUtil; + +/** + * This conversion is necessary to allow {@link Optional}s to be displayed correctly in test results. For actual value + * comparison, the value comparator will already handle Optional resolution, because for that job, non-present optionals + * must be handled in a special way. + * + * @author Rene Schneider - initial API and implementation + * + */ +@SuppressWarnings("rawtypes") +@de.gebit.integrity.parameter.conversion.Conversion.Priority(Integer.MIN_VALUE + 1) +public class OptionalToFormattedString extends Conversion { + + @Override + public FormattedString convert(Optional aSource, Class aTargetType, + ConversionContext aConversionContext) throws ConversionFailedException { + if (aSource.isPresent()) { + return (FormattedString) convertValueToFormattedStringArrayRecursive(aSource.get(), aConversionContext)[0]; + } else { + return new FormattedString(ParameterUtil.INEXISTENT_VALUE); + } + } + +} diff --git a/de.gebit.integrity.runner/src/de/gebit/integrity/runner/callbacks/xml/XmlWriterTestCallback.java b/de.gebit.integrity.runner/src/de/gebit/integrity/runner/callbacks/xml/XmlWriterTestCallback.java index a75722af8..b31390586 100644 --- a/de.gebit.integrity.runner/src/de/gebit/integrity/runner/callbacks/xml/XmlWriterTestCallback.java +++ b/de.gebit.integrity.runner/src/de/gebit/integrity/runner/callbacks/xml/XmlWriterTestCallback.java @@ -568,8 +568,8 @@ public class XmlWriterTestCallback extends AbstractTestRunnerCallback { /** * The generally used timestamp format (fine-grained date/time). */ - protected static final DateFormat TIMESTAMP_FORMAT = DateFormat.getDateTimeInstance(DateFormat.SHORT, - DateFormat.MEDIUM); + protected static final DateFormat TIMESTAMP_FORMAT + = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); static { if (TIMESTAMP_FORMAT instanceof SimpleDateFormat) { @@ -614,8 +614,8 @@ public class XmlWriterTestCallback extends AbstractTestRunnerCallback { /** * The name of the XSLT script resource. */ - protected static final String XSLT_RESOURCE_NAME = System.getProperty(SYSPARAM_XSLT_RESOURCE, - "resource/xhtml.xslt"); + protected static final String XSLT_RESOURCE_NAME + = System.getProperty(SYSPARAM_XSLT_RESOURCE, "resource/xhtml.xslt"); /** * The XSLT transformer factory property. @@ -719,8 +719,8 @@ public void onExecutionStart(TestModel aModel, VariantDefinition aVariant) { HashMap tempProcessingInstructionMap = new HashMap(2); tempProcessingInstructionMap.put("type", "text/xsl"); tempProcessingInstructionMap.put("href", "#xhtmltransform"); - ProcessingInstruction tempProcessingInstruction = new ProcessingInstruction("xml-stylesheet", - tempProcessingInstructionMap); + ProcessingInstruction tempProcessingInstruction + = new ProcessingInstruction("xml-stylesheet", tempProcessingInstructionMap); document.addContent(0, tempProcessingInstruction); } catch (JDOMException exc) { exc.printStackTrace(); @@ -1008,9 +1008,9 @@ public void onTableTestStart(TableTest aTest) { addCurrentTime(tempTestElement); try { - Map tempParameterMap = parameterResolver.createParameterMap(aTest, null, - TableTestParameterResolveMethod.ONLY_COMMON, true, - UnresolvableVariableHandling.RESOLVE_TO_NULL_VALUE); + Map tempParameterMap + = parameterResolver.createParameterMap(aTest, null, TableTestParameterResolveMethod.ONLY_COMMON, + true, UnresolvableVariableHandling.RESOLVE_TO_NULL_VALUE); Element tempParameterCollectionElement = new Element(PARAMETER_COLLECTION_ELEMENT); for (Entry tempEntry : tempParameterMap.entrySet()) { @@ -1239,8 +1239,8 @@ public void onTableTestFinish(TableTest aTableTest, TestResult aResult) { if (tempPostInvocationResult != null) { tempPostInvocationResultElement = new Element(POST_INVOCATION_RESULT_ELEMENT); if (tempPostInvocationResult instanceof TestExecutedSubResult) { - TestComparisonResult tempPostInvocationComparisonResult = tempPostInvocationResult - .getComparisonResults().get(ParameterUtil.DEFAULT_PARAMETER_NAME); + TestComparisonResult tempPostInvocationComparisonResult + = tempPostInvocationResult.getComparisonResults().get(ParameterUtil.DEFAULT_PARAMETER_NAME); if (tempPostInvocationComparisonResult.getResult().isSuccessful()) { setAttributeGuarded(tempPostInvocationResultElement, RESULT_TYPE_ATTRIBUTE, RESULT_TYPE_SUCCESS); @@ -1375,13 +1375,11 @@ protected void onAnyKindOfSubTestFinish(MethodReference aMethod, SuiteStatementW .convertValueToFormattedString((tempExpectedValue == null ? true : tempExpectedValue), false, new ConversionContext().withComparisonResult(tempEntry.getValue().getResult())) .toFormattedString()); - if (tempEntry.getValue().getActualValue() != null) { - setAttributeGuarded(tempComparisonResultElement, RESULT_REAL_VALUE_ATTRIBUTE, - convertResultValueToFormattedStringGuarded(tempEntry.getValue().getActualValue(), - aSubResult, tempExpectedIsNestedObject, - new ConversionContext().withComparisonResult(tempEntry.getValue().getResult())) - .toFormattedString()); - } + setAttributeGuarded(tempComparisonResultElement, RESULT_REAL_VALUE_ATTRIBUTE, + convertResultValueToFormattedStringGuarded(tempEntry.getValue().getActualValue(), aSubResult, + tempExpectedIsNestedObject, + new ConversionContext().withComparisonResult(tempEntry.getValue().getResult())) + .toFormattedString()); if (tempEntry.getValue() instanceof TestComparisonSuccessResult) { setAttributeGuarded(tempComparisonResultElement, RESULT_TYPE_ATTRIBUTE, RESULT_TYPE_SUCCESS); @@ -1497,7 +1495,8 @@ public void onCallFinish(Call aCall, CallResult aResult) { if (aResult instanceof de.gebit.integrity.runner.results.call.SuccessResult) { setAttributeGuarded(tempCallResultElement, RESULT_TYPE_ATTRIBUTE, RESULT_TYPE_SUCCESS); - de.gebit.integrity.runner.results.call.SuccessResult tempResult = (de.gebit.integrity.runner.results.call.SuccessResult) aResult; + de.gebit.integrity.runner.results.call.SuccessResult tempResult + = (de.gebit.integrity.runner.results.call.SuccessResult) aResult; for (UpdatedVariable tempUpdatedVariable : tempResult.getUpdatedVariables()) { Element tempVariableUpdateElement = new Element(VARIABLE_UPDATE_ELEMENT); setAttributeGuarded(tempVariableUpdateElement, VARIABLE_NAME_ATTRIBUTE, @@ -1879,8 +1878,8 @@ public void onReturnVariableAssignment(SuiteReturn aReturn, VariableEntity aSour @Override public void onTimeSetStart(TimeSet aTimeSet, SuiteDefinition aSuite, List someForks) { - String tempStartTime = valueConverter.convertValueToString(aTimeSet.getStartTime(), false, - new ConversionContext() + String tempStartTime + = valueConverter.convertValueToString(aTimeSet.getStartTime(), false, new ConversionContext() .withUnresolvableVariableHandlingPolicy(UnresolvableVariableHandling.RESOLVE_TO_NULL_VALUE)); String tempProgressionFactor = null; if (aTimeSet.getProgressionMode() != null) { @@ -1941,8 +1940,8 @@ public void onTimeSetFinish(TimeSet aTimeSet, TimeSetResult aResult) { setAttributeGuarded(tempTimeSetElement, RESULT_EXCEPTION_TRACE_ATTRIBUTE, ((TimeSetExceptionResult) aResult).getExceptionStackTrace()); } else { - String tempExtendedResultString = testFormatter - .testTimeInfoSetToHumanReadableString(aResult.getCurrentDateTimes().entrySet()); + String tempExtendedResultString + = testFormatter.testTimeInfoSetToHumanReadableString(aResult.getCurrentDateTimes().entrySet()); Element tempExtendedResultCollection = new Element(EXTENDED_RESULT_COLLECTION_ELEMENT); Element tempResultElement = new Element(EXTENDED_RESULT_TEXT_ELEMENT); @@ -2070,8 +2069,8 @@ protected void internalOnVariableDefinition(Element aVariableElement, boolean aG /** * The pattern for Markdown-style URL detection. */ - protected static final Pattern MARKDOWN_URL_PATTERN = Pattern - .compile("(.*?)\\[(.*?)\\]\\(((?:(?:\\w+://)|(?:\\./)).+?)\\)(.*)"); + protected static final Pattern MARKDOWN_URL_PATTERN + = Pattern.compile("(.*?)\\[(.*?)\\]\\(((?:(?:\\w+://)|(?:\\./)).+?)\\)(.*)"); /** * Parses a comment into a list of {@link Content} elements. This takes care of URLs embedded in the comment. @@ -2477,12 +2476,12 @@ void addConsoleOutput(Element anElement) { } else { tempMerged = true; tempLineCount = Integer.parseInt(tempLineElements.getAttributeValue(CONSOLE_LINECOUNT_ATTRIBUTE)); - tempTruncatedCount = Integer - .parseInt(tempLineElements.getAttributeValue(CONSOLE_TRUNCATED_ATTRIBUTE)); - tempLowerTimeBound = Long - .parseLong(tempLineElements.getAttributeValue(CONSOLE_TEMP_STARTTIME_ATTRIBUTE)); - tempUpperTimeBound = Long - .parseLong(tempLineElements.getAttributeValue(CONSOLE_TEMP_ENDTIME_ATTRIBUTE)); + tempTruncatedCount + = Integer.parseInt(tempLineElements.getAttributeValue(CONSOLE_TRUNCATED_ATTRIBUTE)); + tempLowerTimeBound + = Long.parseLong(tempLineElements.getAttributeValue(CONSOLE_TEMP_STARTTIME_ATTRIBUTE)); + tempUpperTimeBound + = Long.parseLong(tempLineElements.getAttributeValue(CONSOLE_TEMP_ENDTIME_ATTRIBUTE)); } int tempEarliestPossiblePosition = 0; @@ -2533,8 +2532,8 @@ void addConsoleOutput(Element anElement) { // data is already well-ordered, and any new data is also well-ordered, so they just need to // be merged. while (tempEarliestPossiblePosition < tempLineElements.getChildren().size()) { - Element tempChild = (Element) tempLineElements.getChildren() - .get(tempEarliestPossiblePosition); + Element tempChild + = (Element) tempLineElements.getChildren().get(tempEarliestPossiblePosition); if (Long.parseLong(tempChild.getAttributeValue(CONSOLE_LINE_TIME_ATTRIBUTE)) > tempLine .getTimestamp()) { // The new line is to be added right before the current earliest possible position diff --git a/de.gebit.integrity.runner/src/de/gebit/integrity/runner/comparator/DefaultResultComparator.java b/de.gebit.integrity.runner/src/de/gebit/integrity/runner/comparator/DefaultResultComparator.java index 57b83c75e..51fe4d923 100644 --- a/de.gebit.integrity.runner/src/de/gebit/integrity/runner/comparator/DefaultResultComparator.java +++ b/de.gebit.integrity.runner/src/de/gebit/integrity/runner/comparator/DefaultResultComparator.java @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import com.google.inject.Inject; @@ -48,6 +49,7 @@ import de.gebit.integrity.parameter.resolving.ParameterResolver; import de.gebit.integrity.utils.DateUtil; import de.gebit.integrity.utils.IntegrityDSLUtil; +import de.gebit.integrity.utils.ParameterUtil; import de.gebit.integrity.utils.ParameterUtil.UnresolvableVariableException; /** @@ -208,6 +210,20 @@ public ComparisonResult compareResult(Object aFixtureResult, ValueOrEnumValueOrO } } + // If now the conversion target type happens to be Optional, we need to find something else to + // convert to, because an Optional is just a wrapper + if (tempConversionTargetType == Optional.class) { + tempConversionTargetType = null; + if (tempSingleFixtureResult instanceof Optional) { + if (((Optional) tempSingleFixtureResult).isPresent()) { + Object tempContainedObject = ((Optional) tempSingleFixtureResult).get(); + if (tempContainedObject != null) { + tempConversionTargetType = tempContainedObject.getClass(); + } + } + } + } + return convertAndPerformEqualityCheck(tempSingleFixtureResult, tempSingleExpectedResult, tempConversionTargetType); } @@ -264,8 +280,43 @@ protected ComparisonResult convertAndPerformEqualityCheck(Object aSingleFixtureR } } + // If the expected result is an Optional, we must resolve that optional to an actual value first + boolean tempExpectedResultIsEmptyOptional = false; + if (tempSingleExpectedResult instanceof Optional) { + if (((Optional) tempSingleExpectedResult).isPresent()) { + tempSingleExpectedResult = ((Optional) tempSingleExpectedResult).get(); + } else { + tempExpectedResultIsEmptyOptional = true; + tempSingleExpectedResult = ParameterUtil.INEXISTENT_VALUE; + } + } + + // Now sort out cases in which Optional results have been provided by the fixture. In those cases, it may be + // the case that a non-existent result is actually expected by the test (via an Inexistent value), which means a + // successful comparison. Otherwise we will have to resolve the optional to some concrete value and continue + // with that. In all this action, we need to see if we have to shortcut the comparison because the expected + // result is an Optional, too. + if (tempConvertedFixtureResult instanceof Optional) { + boolean tempWeExpectNoValue + = (tempExpectedResultIsEmptyOptional || (tempSingleExpectedResult instanceof InexistentValue)); + if (((Optional) tempConvertedFixtureResult).isPresent()) { + // If the Optional has a value, but we explicitly don't expect one, the comparison has already failed + if (tempWeExpectNoValue) { + return new SimpleComparisonResult(false); + } + + // The Optional contains a value and we seem to expect one -> just resolve to that value and continue + tempConvertedFixtureResult = ((Optional) tempConvertedFixtureResult).get(); + } else { + // The Optional does not contain a value. If we explicitly don't expect one, that's great (successful + // comparison), otherwise it's a failed comparison. In any case, the comparison is over at this point. + return new SimpleComparisonResult(tempWeExpectNoValue); + } + } + if (((tempSingleExpectedResult instanceof NestedObject) - || (tempSingleExpectedResult instanceof TypedNestedObject)) && !(aSingleFixtureResult instanceof Map)) { + || (tempSingleExpectedResult instanceof TypedNestedObject)) + && !(tempConvertedFixtureResult instanceof Map)) { // if the expected result is a (typed) nested object, and the fixture has NOT returned a // map, we assume the fixture result to be a bean class/instance. We'll convert both to maps // for comparison! @@ -276,16 +327,16 @@ protected ComparisonResult convertAndPerformEqualityCheck(Object aSingleFixtureR tempNestedObject = (NestedObject) tempSingleExpectedResult; } - tempConvertedFixtureResult = valueConverter.convertValue(Map.class, aSingleFixtureResult, null); + tempConvertedFixtureResult = valueConverter.convertValue(Map.class, tempConvertedFixtureResult, null); // Keeping Inexistent values as they are (= the InexistentValue model class instance) is necessary so that // we can check for them later in map comparison. Otherwise they would be converted to strings. tempConvertedExpectedResult = valueConverter.convertValue(Map.class, tempNestedObject, new ConversionContext().withInexistentValueHandling(InexistentValueHandling.KEEP_AS_IS)); } else { - if (tempSingleExpectedResult instanceof Map && !(aSingleFixtureResult instanceof Map)) { + if (tempSingleExpectedResult instanceof Map && !(tempConvertedFixtureResult instanceof Map)) { // if the expected result is a map, and the fixture has NOT returned a map, we also assume the fixture // result to be a bean class/instance. But we only need to convert that to a map for comparison. - tempConvertedFixtureResult = valueConverter.convertValue(Map.class, aSingleFixtureResult, null); + tempConvertedFixtureResult = valueConverter.convertValue(Map.class, tempConvertedFixtureResult, null); tempConvertedExpectedResult = tempSingleExpectedResult; } else { // no special bean-related cases apply: convert the expected result to match the given fixture result diff --git a/de.gebit.integrity.tests/integrity/fixtures/OptionalTestFixture.integrity b/de.gebit.integrity.tests/integrity/fixtures/OptionalTestFixture.integrity new file mode 100644 index 000000000..c7dd9c78d --- /dev/null +++ b/de.gebit.integrity.tests/integrity/fixtures/OptionalTestFixture.integrity @@ -0,0 +1,6 @@ +packagedef integrity.fixtures.basic.optionaltest with + + testdef echoNumber uses de.gebit.integrity.tests.fixtures.basic.OptionalTestFixture#echoNumber + calldef echoNumberCall uses de.gebit.integrity.tests.fixtures.basic.OptionalTestFixture#echoNumber + +packageend \ No newline at end of file diff --git a/de.gebit.integrity.tests/integrity/suites/basic/optionals/optionals.integrity b/de.gebit.integrity.tests/integrity/suites/basic/optionals/optionals.integrity new file mode 100644 index 000000000..9377b0c7d --- /dev/null +++ b/de.gebit.integrity.tests/integrity/suites/basic/optionals/optionals.integrity @@ -0,0 +1,80 @@ +import integrity.fixtures.basic.optionaltest.* + +packagedef integrity.basic.optionals with + + suitedef simpleOptionalTests with + + -- This should succeed, because we actually return the value "null" + test echoNumber number: null = null + + -- This should also succeed, because the empty optional that's returned equals "inexistent" + test echoNumber number: 1 = inexistent + + -- This should fail, because an empty optional means the value does not exist, and "null" is an existing value + test echoNumber number: 1 = null + + suiteend + + + suitedef optionalTestsWithVariables with + + variable emptyOptional + variable filledOptional + variable nullVariable + + call echoNumberCall number: 1 -> emptyOptional + call echoNumberCall number: 2 -> filledOptional + call echoNumberCall number: null -> nullVariable + + -- This should succeed, because we actually return the value "null" + test echoNumber number: null = nullVariable + + -- This should also succeed, because the empty optional that's returned equals the empty optional provided + test echoNumber number: 1 = emptyOptional + + -- This should fail, because the filled optional does not equal the empty optional + test echoNumber number: 2 = emptyOptional + + -- This should succeed, because the returned filled optional equals the provided one + test echoNumber number: 2 = filledOptional + + -- This should fail, because the filled optional does not equal the empty optional + test echoNumber number: 1 = filledOptional + + suiteend + + + suitedef optionalsAsParameters with + + variable emptyOptional + variable filledOptional + variable nullVariable + + call echoNumberCall number: 1 -> emptyOptional + call echoNumberCall number: 2 -> filledOptional + call echoNumberCall number: null -> nullVariable + + -- This should succeed, because we actually return the value "null" + test echoNumber number: nullVariable = null + + -- This should fail, because the empty optional that's provided will convert to "null" for lack of better options, which does trigger a null return, which does not equal the empty optional + test echoNumber number: emptyOptional = emptyOptional + + -- This should succeed, because the empty optional that's provided will convert to "null" for lack of better options, which does trigger a null return + test echoNumber number: emptyOptional = null + + -- This should fail, because the filled optional does not equal the empty optional, which resolves to null in this case + test echoNumber number: emptyOptional = filledOptional + + -- This should fail, because the filled optional which resolves to its content does not equal the empty optional + test echoNumber number: filledOptional = emptyOptional + + -- This should succeed, because the returned filled optional contains a number that equals the provided one + test echoNumber number: filledOptional = 2 + + -- This should fail, because the filled optionals' contents do not equal the content provided + test echoNumber number: filledOptional = 1 + + suiteend + +packageend \ No newline at end of file diff --git a/de.gebit.integrity.tests/junit/de/gebit/integrity/tests/junit/basic/optionals/OptionalTest.java b/de.gebit.integrity.tests/junit/de/gebit/integrity/tests/junit/basic/optionals/OptionalTest.java new file mode 100644 index 000000000..467021f2a --- /dev/null +++ b/de.gebit.integrity.tests/junit/de/gebit/integrity/tests/junit/basic/optionals/OptionalTest.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.tests.junit.basic.optionals; + +import java.io.IOException; + +import org.jdom.Document; +import org.jdom.JDOMException; +import org.junit.Test; + +import de.gebit.integrity.runner.exceptions.ModelLoadException; +import de.gebit.integrity.tests.junit.IntegrityJUnitTest; + +/** + * JUnit test which checks Optional support. + * + * + * @author Rene Schneider - initial API and implementation + * + */ +public class OptionalTest extends IntegrityJUnitTest { + + /** + * Performs a suite which does fixture calls with optional values and checks the resulting XML document. + * + * @throws ModelLoadException + * @throws IOException + * @throws JDOMException + */ + @Test + public void testSimpleOptionalTests() throws ModelLoadException, IOException, JDOMException { + Document tempResult + = executeIntegritySuite(new String[] { "integrity/suites/basic/optionals/optionals.integrity" }, + "integrity.basic.optionals.simpleOptionalTests", null); + assertDocumentMatchesReference(tempResult); + } + + /** + * Performs a suite which does fixture calls with optional values and checks the resulting XML document. + * + * @throws ModelLoadException + * @throws IOException + * @throws JDOMException + */ + @Test + public void testOptionalTestsWithVariables() throws ModelLoadException, IOException, JDOMException { + Document tempResult + = executeIntegritySuite(new String[] { "integrity/suites/basic/optionals/optionals.integrity" }, + "integrity.basic.optionals.optionalTestsWithVariables", null); + assertDocumentMatchesReference(tempResult); + } + + /** + * Performs a suite which does fixture calls with optional values and checks the resulting XML document. + * + * @throws ModelLoadException + * @throws IOException + * @throws JDOMException + */ + @Test + public void testOptionalsAsParameters() throws ModelLoadException, IOException, JDOMException { + Document tempResult + = executeIntegritySuite(new String[] { "integrity/suites/basic/optionals/optionals.integrity" }, + "integrity.basic.optionals.optionalsAsParameters", null); + assertDocumentMatchesReference(tempResult); + } + +} diff --git a/de.gebit.integrity.tests/results/integrity.basic.nullChecks.xml b/de.gebit.integrity.tests/results/integrity.basic.nullChecks.xml index e4fadd1c7..7d867ebe3 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.nullChecks.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.nullChecks.xml @@ -1,25 +1,25 @@ - + - + - - - + + + - + - - - + + + @@ -29,9 +29,9 @@ - - - + + + @@ -41,21 +41,21 @@ - - - + + + - + - - - + + + @@ -65,9 +65,9 @@ - - - + + + @@ -77,9 +77,9 @@ - - - + + + @@ -89,9 +89,9 @@ - - - + + + @@ -101,24 +101,24 @@ - - - + + + - - + + - - - + + + @@ -133,16 +133,16 @@ - - - + + + - - + + @@ -150,7 +150,7 @@ - + diff --git a/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalTestsWithVariables.xml b/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalTestsWithVariables.xml new file mode 100644 index 000000000..ffd7e2193 --- /dev/null +++ b/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalTestsWithVariables.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This should succeed, because we actually return the value "null" + + + + + + + + + + + + + This should also succeed, because the empty optional that's returned equals the empty optional provided + + + + + + + + + + + + + This should fail, because the filled optional does not equal the empty optional + + + + + + + + + + + + + This should succeed, because the returned filled optional equals the provided one + + + + + + + + + + + + + This should fail, because the filled optional does not equal the empty optional + + + + + + + + + + + + + + + + + + + diff --git a/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalsAsParameters.xml b/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalsAsParameters.xml new file mode 100644 index 000000000..444f82aee --- /dev/null +++ b/de.gebit.integrity.tests/results/integrity.basic.optionals.optionalsAsParameters.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This should succeed, because we actually return the value "null" + + + + + + + + + + + + + This should fail, because the empty optional that's provided will convert to "null" for lack of better options, which does trigger a null return, which does not equal the empty optional + + + + + + + + + + + + + This should succeed, because the empty optional that's provided will convert to "null" for lack of better options, which does trigger a null return + + + + + + + + + + + + + This should fail, because the filled optional does not equal the empty optional, which resolves to null in this case + + + + + + + + + + + + + This should fail, because the filled optional which resolves to its content does not equal the empty optional + + + + + + + + + + + + + This should succeed, because the returned filled optional contains a number that equals the provided one + + + + + + + + + + + + + This should fail, because the filled optionals' contents do not equal the content provided + + + + + + + + + + + + + + + + + + + diff --git a/de.gebit.integrity.tests/results/integrity.basic.optionals.simpleOptionalTests.xml b/de.gebit.integrity.tests/results/integrity.basic.optionals.simpleOptionalTests.xml new file mode 100644 index 000000000..354e5fa7b --- /dev/null +++ b/de.gebit.integrity.tests/results/integrity.basic.optionals.simpleOptionalTests.xml @@ -0,0 +1,53 @@ + + + + + + + + This should succeed, because we actually return the value "null" + + + + + + + + + + + + + This should also succeed, because the empty optional that's returned equals "inexistent" + + + + + + + + + + + + + This should fail, because an empty optional means the value does not exist, and "null" is an existing value + + + + + + + + + + + + + + + + + + + diff --git a/de.gebit.integrity.tests/results/integrity.basic.parameterizedConstantNoDef.xml b/de.gebit.integrity.tests/results/integrity.basic.parameterizedConstantNoDef.xml index 444e22baf..1d0d171f4 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.parameterizedConstantNoDef.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.parameterizedConstantNoDef.xml @@ -1,21 +1,21 @@ - + - + - + - - - + + + - + @@ -23,7 +23,7 @@ - + diff --git a/de.gebit.integrity.tests/results/integrity.basic.suitecalls.suiteCallWithNullParameter.xml b/de.gebit.integrity.tests/results/integrity.basic.suitecalls.suiteCallWithNullParameter.xml index c8fd4d1dd..a96c9d5ef 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.suitecalls.suiteCallWithNullParameter.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.suitecalls.suiteCallWithNullParameter.xml @@ -1,24 +1,24 @@ - + - + - + - - - + + + - + @@ -26,22 +26,22 @@ - + - + - - - + + + - + @@ -49,12 +49,12 @@ - + - + diff --git a/de.gebit.integrity.tests/results/integrity.basic.variableAttributeAccessNested.xml b/de.gebit.integrity.tests/results/integrity.basic.variableAttributeAccessNested.xml index 7d77e46a4..87d2875a9 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.variableAttributeAccessNested.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.variableAttributeAccessNested.xml @@ -1,24 +1,24 @@ - + - + - + - + - - + + - - - + + + @@ -28,20 +28,20 @@ - + - - + + - - - + + + - + @@ -49,7 +49,7 @@ - + diff --git a/de.gebit.integrity.tests/src/de/gebit/integrity/tests/fixtures/basic/OptionalTestFixture.java b/de.gebit.integrity.tests/src/de/gebit/integrity/tests/fixtures/basic/OptionalTestFixture.java new file mode 100644 index 000000000..b84fc5398 --- /dev/null +++ b/de.gebit.integrity.tests/src/de/gebit/integrity/tests/fixtures/basic/OptionalTestFixture.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * 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.tests.fixtures.basic; + +import java.util.Optional; + +import de.gebit.integrity.fixtures.FixtureMethod; +import de.gebit.integrity.fixtures.FixtureParameter; + +/** + * A simple test fixture which provides methods using {@link Optional}. + * + * + * @author Rene Schneider - initial API and implementation + * + */ +// SUPPRESS CHECKSTYLE LONG Javadoc +public class OptionalTestFixture { + + @FixtureMethod(description = "Echoes a number (maybe...only if it is even!)") + public Optional echoNumber(@FixtureParameter(name = "number") Integer anInput) { + if (anInput == null) { + // In case of "null", we return "null". This is deliberate, so we can also test on "null" vs. "inexistent". + return null; + } else if (anInput % 2 == 0) { + return Optional.of(anInput); + } else { + return Optional.empty(); + } + } + +}