This is an automated email from the ASF dual-hosted git repository.
mbeckerle pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new 3955ba507 Improve diagnostic in TDML Runner
3955ba507 is described below
commit 3955ba507d5034d94907fe7f6d549d110ceecec7
Author: Michael Beckerle <[email protected]>
AuthorDate: Fri Nov 1 17:11:14 2024 -0400
Improve diagnostic in TDML Runner
Note that this change enforces the syntax of TDML better.
The dfdlInfoset element used to tolerate having spurious text in it,
so long as it also had a root element.
Two TDML files had to be fixed in Daffodil.
If TDML files in schema projects have these spurious characters that
were formerly ignored, this change will break
those tests.
DAFFODIL-533
---
.../resources/org/apache/daffodil/xsd/tdml.xsd | 10 ++-
.../org/apache/daffodil/tdml/TDMLRunner.scala | 82 ++++++++++++----------
.../apache/daffodil/tdml/UnitTestTDMLRunner.scala | 12 ++++
.../daffodil/processor/tdml/TestTDMLRunner.scala | 29 ++++++++
.../section15/choice_groups/HiddenChoices.tdml | 2 +-
5 files changed, 94 insertions(+), 41 deletions(-)
diff --git a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
index 6d4562f39..8a8441a1e 100644
--- a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
+++ b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
@@ -308,7 +308,15 @@
<complexType name="dfdlInfosetType" mixed="true">
<sequence>
- <any namespace="##any" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
+ <!--
+ Can be empty if type is 'file'.
+ Otherwise, can be any single element (maxOccurs unbounded removed),
+ which is the root element of the infoset.
+
+ Mixed="true" because when type='file' the content is just a string
+ that is the file path
+ -->
+ <any namespace="##any" processContents="lax" minOccurs="0"
maxOccurs="1"/>
</sequence>
<attribute name="type" use="optional" default="infoset">
<simpleType>
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 0cfe487d4..ad25deacf 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
@@ -31,6 +31,7 @@ import java.nio.charset.StandardCharsets
import scala.collection.mutable
import scala.language.postfixOps
import scala.util.Try
+import scala.xml.Elem
import scala.xml.Node
import scala.xml.NodeSeq
import scala.xml.NodeSeq.seqToNodeSeq
@@ -2769,41 +2770,52 @@ case class Infoset(i: NodeSeq, parent: TestCase) {
case class DFDLInfoset(di: Node, parent: Infoset) {
- private lazy val infosetNodeSeq = {
- val testCase: TestCase = parent.parent
- val loader = testCase.parent.loader
- val optDataSchema: Option[URI] = {
- testCase.optSchemaFileURI.orElse(testCase.optEmbeddedSchema.map {
_.uriForLoading })
- }
- val src =
- (di \ "@type").toString match {
- case "infoset" | "" => {
- val rawElem = di.child.filter {
- _.isInstanceOf[scala.xml.Elem]
- }.head
- UnitTestSchemaSource(rawElem, testCase.tcName)
- }
- case "file" => {
- val path = di.text.trim()
- val maybeURI = parent.parent.parent.findTDMLResource(path)
- val uri = maybeURI.getOrElse(
- throw new FileNotFoundException(
- "TDMLRunner: infoset file '" + path + "' was not found"
- )
- )
- URISchemaSource(uriToDiagnosticFile(uri), uri)
- }
- case value => Assert.abort("Unknown value for type attribute on
dfdlInfoset: " + value)
- }
+ private lazy val testCase: TestCase = parent.parent
+ private lazy val loader = testCase.parent.loader
+ private val ty: String = {
+ val t = (di \ "@type").text.trim
+ if (t.isEmpty) "infoset" else t
+ }
+
+ private val elemOrStr: Either[Elem, String] = {
+ val (elems, others) = di.child.partition(_.isInstanceOf[scala.xml.Elem])
+ (elems, others.text.trim) match {
+ case (Seq(elem: Elem), "") if (ty == "infoset") => Left(elem)
+ case (Seq(), str) if (ty == "file") => Right(str)
+ case _ =>
+ Assert.usageError(
+ """dfdlInfoset element must contain a single root element or a file
path (when 'type="file"')."""
+ )
+ }
+ }
+
+ lazy val contents: Elem = {
+ elemOrStr match {
+ case Left(elem) => elem
+ case Right(path) => infosetNodeFromFile(path)
+ }
+ }
+
+ private def infosetNodeFromFile(path: String): Elem = {
+
+ val maybeURI = parent.parent.parent.findTDMLResource(path)
+ val uri = maybeURI.getOrElse(
+ throw new FileNotFoundException(
+ "TDMLRunner: infoset file '" + path + "' was not found"
+ )
+ )
+ val infosetSrc = URISchemaSource(uriToDiagnosticFile(uri), uri)
+
+ val testSuite = testCase.parent
+ val before = testSuite.loadingExceptions.clone()
+
+ val elem = loader.load(infosetSrc, None) // no schema
//
// TODO: DAFFODIL-288 validate the infoset also
// You can pass the optDataSchema, which appears to be the correct thing
// but in many cases it doesn't seem to be able to resolve things.
//
- val testSuite = testCase.parent
- val before = testSuite.loadingExceptions.clone()
- // val elem: Node = loader.load(src, optDataSchema)
- val elem = loader.load(src, None) // no schema
+ // val elem: Node = loader.load(infosetSrc, optDataSchema)
// The expected infoset is loaded using the normalizeCRLFtoLF mode (which
// is the default), so MS-DOS/Windows CRLFs in expected data XML files will
@@ -2818,17 +2830,9 @@ case class DFDLInfoset(di: Node, parent: Infoset) {
val newExceptions = (testSuite.loadingExceptions -- before).toSeq
testCase.toss(TDMLException(newExceptions, None), None)
}
- elem
+ elem.asInstanceOf[Elem]
}
- lazy val contents = {
- Assert.usage(
- infosetNodeSeq.size == 1,
- "dfdlInfoset element must contain a single root element"
- )
- val c = infosetNodeSeq.head
- c
- }
}
object DiagnosticType extends Enumeration {
diff --git
a/daffodil-tdml-lib/src/test/scala/org/apache/daffodil/tdml/UnitTestTDMLRunner.scala
b/daffodil-tdml-lib/src/test/scala/org/apache/daffodil/tdml/UnitTestTDMLRunner.scala
index e4299c1a2..c71ae205f 100644
---
a/daffodil-tdml-lib/src/test/scala/org/apache/daffodil/tdml/UnitTestTDMLRunner.scala
+++
b/daffodil-tdml-lib/src/test/scala/org/apache/daffodil/tdml/UnitTestTDMLRunner.scala
@@ -21,6 +21,7 @@ import java.io.File
import org.apache.daffodil.lib.Implicits._
import org.apache.daffodil.lib.Implicits.using
+import org.apache.daffodil.lib.exceptions.UsageException
import org.apache.daffodil.lib.util._
import org.apache.daffodil.lib.xml.XMLUtils
@@ -336,6 +337,17 @@ class UnitTestTDMLRunner {
assertEquals(expected, actual.toList)
}
+ @Test def testDFDLInfosetEmptyDiagnosticMsg(): Unit = {
+ val xml = <tdml:dfdlInfoset/>
+ val exc = intercept[UsageException] {
+ val di = new DFDLInfoset(xml, null)
+ di.contents
+ }
+ val m = exc.getMessage
+ assertTrue(m.contains("dfdlInfoset"))
+ assertTrue(m.contains("single root element"))
+ }
+
@Test def testLSB1(): Unit = {
val xml = <document bitOrder="LSBFirst">
<documentPart type="bits">00000010</documentPart>
diff --git
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala
index e2f346f23..1d4ccf74d 100644
---
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala
+++
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala
@@ -18,6 +18,7 @@
package org.apache.daffodil.processor.tdml
import java.io.File
+import java.io.FileNotFoundException
import org.apache.daffodil.lib.Implicits._
import org.apache.daffodil.lib.Implicits.using
@@ -1061,4 +1062,32 @@ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
assertTrue(exc.getMessage.contains("Either tdml:infoset or tdml:error"))
assertTrue(exc.getMessage.contains("must be present in the test"))
}
+
+ @Test def testInfosetFileNotFound() = {
+ val testSuite =
+ <tdml:testSuite suiteName="theSuiteName" xmlns:tdml={tdml}
xmlns:dfdl={dfdl}
+ xmlns:xs={xsd}>
+ <tdml:defineSchema name="mySchema">
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="GeneralFormat"/>
+ <xs:element name="data" type="xs:int" dfdl:lengthKind="delimited"/>
+ </tdml:defineSchema>
+ <tdml:unparserTestCase name="infosetFileNotFound" root="data"
model="mySchema">
+ <tdml:infoset>
+ <tdml:dfdlInfoset
type="file">/this/does/not/exist.xml</tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document/>
+ </tdml:unparserTestCase>
+ </tdml:testSuite>
+
+ val runner = new Runner(testSuite)
+ val e = intercept[FileNotFoundException] {
+ runner.runOneTest("infosetFileNotFound")
+ }
+ runner.reset
+ val msg = e.getMessage()
+ assertTrue(msg.contains("not found"))
+ assertTrue(msg.contains("/this/does/not/exist.xml"))
+ }
+
}
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
index e4094ac65..f0b199022 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
@@ -217,7 +217,7 @@
<tdml:unparserTestCase name="nestedNoOVCinHiddenContext" root="e7"
model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
<tdml:infoset>
- <tdml:dfdlInfoset>)
+ <tdml:dfdlInfoset>
<ex:e7/>
</tdml:dfdlInfoset>
</tdml:infoset>