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") }
+
+}
+

Reply via email to