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 6d4562f39c..8a8441a1e2 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 @@ - + + 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 0cfe487d4f..ad25deacf6 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 e4299c1a2f..c71ae205ff 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 = + 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 = 00000010 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 e2f346f23d..1d4ccf74d1 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 = + + + + + + + + + /this/does/not/exist.xml + + + + + + 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 e4094ac652..f0b199022f 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 @@ - ) +