This is an automated email from the ASF dual-hosted git repository.
mbeckerle pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
The following commit(s) were added to refs/heads/master by this push:
new 73a1c5b Fix TDML runner losing external var assignments in middle of
a round trip.
73a1c5b is described below
commit 73a1c5b2d0752c648d8b51ac51a00e44112dab04
Author: Michael Beckerle <[email protected]>
AuthorDate: Wed Apr 1 19:33:33 2020 -0400
Fix TDML runner losing external var assignments in middle of a round trip.
DAFFODIL-2311
---
.../org/apache/daffodil/tdml/TDMLRunner.scala | 71 ++++++-------
.../org/apache/daffodil/tdml/testExtVars1.tdml | 117 +++++++++++++++++++++
.../org/apache/daffodil/tdml/TestExtVars1.scala | 37 +++++++
3 files changed, 189 insertions(+), 36 deletions(-)
diff --git
a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index cad6f94..e86c35e 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -429,6 +429,17 @@ class DFDLTestSuite private[tdml] (
abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite)
extends Logging {
+ /**
+ * Test case execution is strongly sequentialized due to this central var.
+ *
+ * Whenever we compute a new processor we just side-effect this state.
+ *
+ * Note getting rid of this var would require substantial code
restructuring, which is why
+ * that wasn't done when this code was updated to call the processor.withXYZ
methods which return a
+ * new processor.
+ */
+ protected final var processor: TDMLDFDLProcessor = null
+
lazy val defaultRoundTrip: RoundTrip = parent.defaultRoundTrip
lazy val defaultValidation: String = parent.defaultValidation
@@ -804,8 +815,10 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
case (Some(_), None) => {
compileResult.left.foreach { diags => throw TDMLException(diags,
implString) }
compileResult.right.foreach {
- case (_, processor) =>
- runParseExpectSuccess(processor, dataToParse, nBits,
optExpectedWarnings, optExpectedValidationErrors, validationMode, roundTrip,
implString)
+ case (_, proc) => {
+ processor = proc
+ runParseExpectSuccess(dataToParse, nBits, optExpectedWarnings,
optExpectedValidationErrors, validationMode, roundTrip, implString)
+ }
}
}
@@ -814,8 +827,10 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
checkDiagnosticMessages(diags, errors, optExpectedWarnings,
implString)
}
compileResult.right.foreach {
- case (_, processor) =>
- runParseExpectErrors(processor, dataToParse, nBits,
optExpectedErrors.get, optExpectedWarnings, optExpectedValidationErrors,
validationMode, implString)
+ case (_, proc) => {
+ processor = proc
+ runParseExpectErrors(dataToParse, nBits, optExpectedErrors.get,
optExpectedWarnings, optExpectedValidationErrors, validationMode, implString)
+ }
}
}
@@ -824,7 +839,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
}
def runParseExpectErrors(
- processorArg: TDMLDFDLProcessor,
dataToParse: InputStream,
lengthLimitInBits: Long,
errors: ExpectedErrors,
@@ -833,8 +847,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
validationMode: ValidationMode.Type,
implString: Option[String]): Unit = {
- var processor = processorArg
-
val optExtVarDiag =
try {
processor = processor.withExternalDFDLVariables(externalVarBindings)
@@ -898,12 +910,9 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
private def doParseExpectSuccess(
testData: Array[Byte],
testInfoset: Infoset,
- processorArg: TDMLDFDLProcessor,
lengthLimitInBits: Long,
implString: Option[String]): TDMLParseResult = {
- var processor = processorArg
-
val testDataLength = lengthLimitInBits
val optExtVarDiag =
@@ -945,7 +954,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
}
private def verifyParseResults(
- processor: TDMLDFDLProcessor,
actual: TDMLParseResult,
testInfoset: Infoset,
implString: Option[String]) = {
@@ -976,7 +984,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
* the unparsed data output.
*/
private def doOnePassRoundTripUnparseExpectSuccess(
- processor: TDMLDFDLProcessor,
outStream: OutputStream, // stream where unparsed data is written
parseResult: TDMLParseResult, // result from prior parse.
implString: Option[String]): TDMLUnparseResult = {
@@ -996,13 +1003,12 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
private def doTwoPassRoundTripExpectSuccess(
implString: Option[String],
- processor: TDMLDFDLProcessor,
parseResult: TDMLParseResult,
firstParseTestData: Array[Byte],
testInfoset: Infoset,
passesLabel: String = TwoPassRoundTrip.propValueName): (TDMLParseResult,
Array[Byte], Long) = {
val outStream = new java.io.ByteArrayOutputStream()
- val unparseResult: TDMLUnparseResult =
doOnePassRoundTripUnparseExpectSuccess(processor, outStream, parseResult,
implString)
+ val unparseResult: TDMLUnparseResult =
doOnePassRoundTripUnparseExpectSuccess(outStream, parseResult, implString)
val isUnparseOutputDataMatching =
try {
VerifyTestCase.verifyUnparserTestData(new
ByteArrayInputStream(firstParseTestData), outStream, implString)
@@ -1031,12 +1037,11 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
reParseTestData.length, reParseTestDataLength, fullBytesNeeded),
implString)
}
}
- val actual = doParseExpectSuccess(reParseTestData, testInfoset, processor,
reParseTestDataLength, implString)
+ val actual = doParseExpectSuccess(reParseTestData, testInfoset,
reParseTestDataLength, implString)
(actual, reParseTestData, reParseTestDataLength)
}
def runParseExpectSuccess(
- processorArg: TDMLDFDLProcessor,
dataToParse: InputStream,
lengthLimitInBits: Long,
warnings: Option[ExpectedWarnings],
@@ -1045,8 +1050,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
roundTripArg: RoundTrip,
implString: Option[String]) {
- var processor = processorArg
-
val roundTrip = roundTripArg // change to OnePassRoundTrip to force all
parse tests to round trip (to see which fail to round trip)
if (processor.isError) {
@@ -1059,11 +1062,11 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
val firstParseTestData = IOUtils.toByteArray(dataToParse)
val testInfoset = optExpectedInfoset.get
- val firstParseResult = doParseExpectSuccess(firstParseTestData,
testInfoset, processor, lengthLimitInBits, implString)
+ val firstParseResult = doParseExpectSuccess(firstParseTestData,
testInfoset, lengthLimitInBits, implString)
roundTrip match {
case NoRoundTrip | OnePassRoundTrip => {
- verifyParseResults(processor, firstParseResult, testInfoset,
implString)
+ verifyParseResults(firstParseResult, testInfoset, implString)
verifyLeftOverData(firstParseResult, lengthLimitInBits, implString)
}
case TwoPassRoundTrip => {
@@ -1130,7 +1133,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
case OnePassRoundTrip => {
val outStream = new java.io.ByteArrayOutputStream()
- doOnePassRoundTripUnparseExpectSuccess(processor, outStream,
firstParseResult, implString)
+ doOnePassRoundTripUnparseExpectSuccess(outStream, firstParseResult,
implString)
// It has to work, as this is one pass round trip. We expect it to
unparse
// directly back to the original input form.
@@ -1157,11 +1160,10 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
val (actual, _, reParseTestDataLength) =
doTwoPassRoundTripExpectSuccess(
implString,
- processor,
firstParseResult,
firstParseTestData,
testInfoset)
- verifyParseResults(processor, actual, testInfoset, implString)
+ verifyParseResults(actual, testInfoset, implString)
verifyLeftOverData(actual, reParseTestDataLength, implString)
// if it doesn't pass, it will throw out of here.
@@ -1192,7 +1194,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
val (secondParseResult, reParseTestData, reParseTestDataLength) =
doTwoPassRoundTripExpectSuccess(
implString,
- processor,
firstParseResult,
firstParseTestData,
testInfoset,
@@ -1204,7 +1205,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
//
// So we just verify normally here.
//
- verifyParseResults(processor, secondParseResult, testInfoset,
implString)
+ verifyParseResults(secondParseResult, testInfoset, implString)
verifyLeftOverData(secondParseResult, reParseTestDataLength,
implString)
//
// So now we do the third pass unparse and compare this output with the
@@ -1212,7 +1213,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
//
// We get to reuse the one-pass code here.
val thirdPassOutStream = new java.io.ByteArrayOutputStream()
- doOnePassRoundTripUnparseExpectSuccess(processor, thirdPassOutStream,
firstParseResult, implString)
+ doOnePassRoundTripUnparseExpectSuccess(thirdPassOutStream,
firstParseResult, implString)
VerifyTestCase.verifyUnparserTestData(new
ByteArrayInputStream(reParseTestData), thirdPassOutStream, implString)
// Done with the first parse result and second parse results. Safe to
@@ -1252,8 +1253,10 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
case (Some(expectedData), None) => {
compileResult.left.foreach { diags => throw TDMLException(diags,
implString) }
compileResult.right.foreach {
- case (warnings, processor) =>
- runUnparserExpectSuccess(processor, expectedData, optWarnings,
roundTrip, implString)
+ case (warnings, proc) => {
+ processor = proc
+ runUnparserExpectSuccess(expectedData, optWarnings, roundTrip,
implString)
+ }
}
}
@@ -1262,8 +1265,10 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
checkDiagnosticMessages(diags, errors, optWarnings, implString)
}
compileResult.right.foreach {
- case (_, processor) =>
- runUnparserExpectErrors(processor, optExpectedData, errors,
optWarnings, implString)
+ case (_, proc) => {
+ processor = proc
+ runUnparserExpectErrors(optExpectedData, errors, optWarnings,
implString)
+ }
}
}
case _ => Assert.impossibleCase()
@@ -1272,14 +1277,11 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
}
def runUnparserExpectSuccess(
- processorArg: TDMLDFDLProcessor,
expectedData: InputStream,
optWarnings: Option[ExpectedWarnings],
roundTrip: RoundTrip,
implString: Option[String]) {
- var processor = processorArg
-
Assert.usage(roundTrip ne TwoPassRoundTrip) // not supported for unparser
test cases.
val infosetXML: Node = {
@@ -1386,14 +1388,11 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg:
DFDLTestSuite)
}
def runUnparserExpectErrors(
- processorArg: TDMLDFDLProcessor,
optExpectedData: Option[InputStream],
errors: ExpectedErrors,
optWarnings: Option[ExpectedWarnings],
implString: Option[String]) {
- var processor = processorArg
-
val optExtVarDiag =
try {
processor = processor.withExternalDFDLVariables(externalVarBindings)
diff --git
a/daffodil-tdml-processor/src/test/resources/org/apache/daffodil/tdml/testExtVars1.tdml
b/daffodil-tdml-processor/src/test/resources/org/apache/daffodil/tdml/testExtVars1.tdml
new file mode 100644
index 0000000..d8b7612
--- /dev/null
+++
b/daffodil-tdml-processor/src/test/resources/org/apache/daffodil/tdml/testExtVars1.tdml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<tdml:testSuite xmlns:ex="http://example.com"
+ xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+ defaultRoundTrip="onePass">
+
+ <tdml:defineConfig name="littleEndian">
+ <daf:externalVariableBindings>
+ <daf:bind name="dfdl:byteOrder">littleEndian</daf:bind>
+ </daf:externalVariableBindings>
+ </tdml:defineConfig>
+
+ <tdml:defineConfig name="bigEndian">
+ <daf:externalVariableBindings>
+ <daf:bind name="dfdl:byteOrder">bigEndian</daf:bind>
+ </daf:externalVariableBindings>
+ </tdml:defineConfig>
+
+ <tdml:defineSchema name="s1" elementFormDefault="unqualified">
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+ <dfdl:format ref="ex:GeneralFormat"
+ binaryNumberRep="binary"
+ representation="binary"
+ byteOrder="{ $dfdl:byteOrder }"/>
+
+ <xs:element name="r">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="MagicNumber" type="xs:unsignedInt"
dfdl:lengthKind="explicit" dfdl:length="4"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="configLittleEndian" model="s1"
config="littleEndian"
+ description="This test shows that we can set the
dfdl:byteOrder variable in a config.">
+ <tdml:document>
+ <tdml:documentPart type="byte">01000000</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:r><MagicNumber>1</MagicNumber></ex:r><!-- D4C3B2A1 = 3569595041
--><!-- A1B2C3D4 = 2712847316 -->
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:unparserTestCase name="unparseConfigLittleEndian" model="s1"
config="littleEndian"
+ description="This test shows that we can set the
dfdl:byteOrder variable in a config.">
+ <tdml:document>
+ <tdml:documentPart type="byte">01000000</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:r><MagicNumber>1</MagicNumber></ex:r>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseConfigBigEndian" model="s1"
config="bigEndian"
+ description="This test shows that we can set the
dfdl:byteOrder variable in a config.">
+ <tdml:document>
+ <tdml:documentPart type="byte">00000002</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:r><MagicNumber>2</MagicNumber></ex:r>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+ <tdml:parserTestCase name="configDefaultBigEndian" model="s1"
+ description="This test shows that the default
dfdl:byteOrder variable is used.">
+ <tdml:document>
+ <tdml:documentPart type="byte">00000002</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:r><MagicNumber>2</MagicNumber></ex:r>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:unparserTestCase name="unparseConfigDefaultBigEndian" model="s1"
+ description="This test shows that the default
dfdl:byteOrder variable is used.">
+ <tdml:document>
+ <tdml:documentPart type="byte">00000002</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:r><MagicNumber>2</MagicNumber></ex:r>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestExtVars1.scala
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestExtVars1.scala
new file mode 100644
index 0000000..a92707d
--- /dev/null
+++
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestExtVars1.scala
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.tdml
+
+import org.junit.Test
+
+object TestExtVars1 {
+ val testDir = "org/apache/daffodil/tdml/"
+ lazy val runner = Runner(testDir, "testExtVars1.tdml")
+}
+
+class TestExtVars1 {
+ import TestExtVars1._
+
+ @Test def test_configLittleEndian() = {
runner.runOneTest("configLittleEndian") }
+ @Test def test_unparseConfigLittleEndian() = {
runner.runOneTest("unparseConfigLittleEndian") }
+ @Test def test_unparseConfigBigEndian() = {
runner.runOneTest("unparseConfigBigEndian") }
+ @Test def test_configDefaultBigEndian() = {
runner.runOneTest("configDefaultBigEndian") }
+ @Test def test_unparseConfigDefaultBigEndian() = {
runner.runOneTest("unparseConfigDefaultBigEndian") }
+
+}
+