This is an automated email from the ASF dual-hosted git repository.

olabusayo 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 176ac737f Add ability to specify errors/warnings/validationErrors 
should not occur
176ac737f is described below

commit 176ac737f6620f6f078580422851299b6d9ec784
Author: olabusayoT <[email protected]>
AuthorDate: Wed Apr 3 10:00:11 2024 -0400

    Add ability to specify errors/warnings/validationErrors should not occur
    
    - using warnings/errors match attribute, specify whether all/none of the 
messages should match
    - allow multiple sets of warnings, errors or validation errors
    - support empty tag to indicate unexpected validation errors shouldn't be 
ignored
    - tdml:warnings and tdml:errors must have a child element (in 
ExpectedErrors and ExpectedWarnings)
    - add ignoreUnexpectedWarnings testcase/testsuite attribute
    - filter actual diags type to match expected diags type in 
CheckDiagnosticMessages
    - add DiagnosticType enum
    - remove verifyNoValidationErrorsFound logic
    - add tests for ignoreUnexpectedWarnings
    - add tdml tests
    
    DAFFODIL-864
---
 .../resources/org/apache/daffodil/xsd/tdml.xsd     |   4 +-
 .../org/apache/daffodil/tdml/RunnerFactory.scala   |   6 +-
 .../org/apache/daffodil/tdml/TDMLRunner.scala      | 416 ++++++++++++---------
 .../daffodil/processor/tdml/TestRunnerFactory.java |   3 +-
 .../tdml/testTDMLErrorsWarningsMatchAttribute.tdml | 188 ++++++++++
 .../daffodil/processor/tdml/TestTDMLRunner2.scala  |   7 +-
 .../tdml/TestTDMLRunnerMatchAttributes.scala       | 169 +++++++++
 .../section02/validation_errors/Validation.tdml    |   8 -
 .../text_number_props/TextNumberProps.tdml         |   6 +-
 9 files changed, 619 insertions(+), 188 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 5a9c157e3..39d4eb9c6 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
@@ -75,6 +75,7 @@
       <attribute name="defaultValidation" type="tns:validationType" 
use="optional"/>
       <attribute name="defaultConfig" type="xs:string" use="optional"/>
       <attribute name="defaultImplementations" type="tns:implementationsType" 
use="optional"/>
+      <attribute name="defaultIgnoreUnexpectedWarnings" type="xs:boolean" 
use="optional"/>
     </complexType>
     <unique name="unique-parserTestCase-name">
       <selector xpath="parserTestCase"/>
@@ -184,6 +185,7 @@
     <attribute name="unsupported" type="xs:boolean" use="optional" 
default="false"/>
     <attribute name="validation" type="tns:validationType" use="optional"/>
     <attribute name="implementations" type="tns:implementationsType" 
use="optional"/>
+    <attribute name="ignoreUnexpectedWarnings" type="xs:boolean" 
use="optional"/>
 
   </attributeGroup>
 
@@ -348,7 +350,7 @@
       <xs:simpleType>
         <xs:restriction base="xs:string">
           <xs:enumeration value="all"/>
-          <xs:enumeration value="any"/>
+          <xs:enumeration value="none"/>
         </xs:restriction>
       </xs:simpleType>
     </xs:attribute>
diff --git 
a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/RunnerFactory.scala 
b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/RunnerFactory.scala
index a223301e0..722bc4d41 100644
--- 
a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/RunnerFactory.scala
+++ 
b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/RunnerFactory.scala
@@ -149,7 +149,8 @@ class Runner private (
   compileAllTopLevel: Boolean = false,
   defaultRoundTripDefault: RoundTrip = Runner.defaultRoundTripDefaultDefault,
   defaultValidationDefault: String = Runner.defaultValidationDefaultDefault,
-  defaultImplementationsDefault: Seq[String] = 
Runner.defaultImplementationsDefaultDefault
+  defaultImplementationsDefault: Seq[String] = 
Runner.defaultImplementationsDefaultDefault,
+  defaultIgnoreUnexpectedWarningsDefault: Boolean = true
 ) {
 
   /**
@@ -220,7 +221,8 @@ class Runner private (
         defaultValidationDefault,
         defaultImplementationsDefault,
         Runner.defaultShouldDoErrorComparisonOnCrossTests,
-        Runner.defaultShouldDoWarningComparisonOnCrossTests
+        Runner.defaultShouldDoWarningComparisonOnCrossTests,
+        defaultIgnoreUnexpectedWarningsDefault
       )
     }
     ts
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 51a6a0ad1..152ed6360 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
@@ -73,11 +73,11 @@ import org.apache.daffodil.lib.util.Misc.uriToDiagnosticFile
 import org.apache.daffodil.lib.util.SchemaUtils
 import org.apache.daffodil.lib.xml.DaffodilXMLLoader
 import org.apache.daffodil.lib.xml.XMLUtils
+import org.apache.daffodil.tdml.DiagnosticType.DiagnosticType
 import org.apache.daffodil.tdml.processor.AbstractTDMLDFDLProcessorFactory
 import org.apache.daffodil.tdml.processor.TDML
 import org.apache.daffodil.tdml.processor.TDMLDFDLProcessor
 import org.apache.daffodil.tdml.processor.TDMLParseResult
-import org.apache.daffodil.tdml.processor.TDMLResult
 import org.apache.daffodil.tdml.processor.TDMLUnparseResult
 
 import org.apache.commons.io.IOUtils
@@ -169,6 +169,9 @@ private[tdml] object DFDLTestSuite {
  *
  * shouldDoWarningComparisonOnCrossTests controls whether test warning 
messages  are compared
  * during cross testing.
+ *
+ * defaultIgnoreUnexpectedWarningsDefault specifies whether a test should 
ignore unexpected warnings (i.e it creates
+ * warnings, but there is no tdml:warnings elements)
  */
 
 class DFDLTestSuite private[tdml] (
@@ -181,7 +184,8 @@ class DFDLTestSuite private[tdml] (
   val defaultValidationDefault: String,
   val defaultImplementationsDefault: Seq[String],
   val shouldDoErrorComparisonOnCrossTests: Boolean,
-  val shouldDoWarningComparisonOnCrossTests: Boolean
+  val shouldDoWarningComparisonOnCrossTests: Boolean,
+  val defaultIgnoreUnexpectedWarningsDefault: Boolean
 ) {
 
   val TMP_DIR = System.getProperty("java.io.tmpdir", ".")
@@ -415,6 +419,10 @@ class DFDLTestSuite private[tdml] (
       str.split("""\s+""").toSeq
     }
   }
+  lazy val defaultIgnoreUnexpectedWarnings = {
+    val str = (ts \ "@defaultIgnoreUnexpectedWarnings").text
+    if (str == "") defaultIgnoreUnexpectedWarningsDefault else str.toBoolean
+  }
 
   lazy val embeddedSchemas = {
     val res = (ts \ "defineSchema").map { node => DefinedSchema(node, this) }
@@ -610,6 +618,7 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: 
DFDLTestSuite) {
 
   lazy val defaultRoundTrip: RoundTrip = parent.defaultRoundTrip
   lazy val defaultValidationMode: ValidationMode.Type = 
parent.defaultValidationMode
+  lazy val defaultIgnoreUnexpectedWarnings: Boolean = 
parent.defaultIgnoreUnexpectedWarnings
 
   private lazy val defaultImplementations: Seq[String] = 
parent.defaultImplementations
   private lazy val tcImplementations = (testCaseXML \ "@implementations").text
@@ -634,15 +643,20 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: 
DFDLTestSuite) {
   lazy val optExpectedOrInputInfoset = (testCaseXML \ 
"infoset").headOption.map { node =>
     new Infoset(node, this)
   }
-  lazy val optExpectedErrors: Option[ExpectedErrors] = (testCaseXML \ 
"errors").headOption.map {
-    node => ExpectedErrors(node, this)
+  lazy val optExpectedErrors: Option[Seq[ExpectedErrors]] = {
+    val s = (testCaseXML \ "errors").map { node => ExpectedErrors(node, this) }
+    if (s.nonEmpty) Some(s) else None
   }
-  lazy val optExpectedWarnings: Option[ExpectedWarnings] =
-    (testCaseXML \ "warnings").headOption.map { node => ExpectedWarnings(node, 
this) }
-  lazy val optExpectedValidationErrors: Option[ExpectedValidationErrors] =
-    (testCaseXML \ "validationErrors").headOption.map { node =>
+  lazy val optExpectedWarnings: Option[Seq[ExpectedWarnings]] = {
+    val s = (testCaseXML \ "warnings").map { node => ExpectedWarnings(node, 
this) }
+    if (s.nonEmpty) Some(s) else None
+  }
+  lazy val optExpectedValidationErrors: Option[Seq[ExpectedValidationErrors]] 
= {
+    val s = (testCaseXML \ "validationErrors").map { node =>
       ExpectedValidationErrors(node, this)
     }
+    if (s.nonEmpty) Some(s) else None
+  }
 
   val tcName = (testCaseXML \ "@name").text
   lazy val tcID = (testCaseXML \ "@ID").text
@@ -712,6 +726,11 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: 
DFDLTestSuite) {
   lazy val tcRoundTrip: String = (testCaseXML \ "@roundTrip").text
   lazy val roundTrip: RoundTrip =
     if (tcRoundTrip == "") defaultRoundTrip else 
DFDLTestSuite.standardizeRoundTrip(tcRoundTrip)
+  lazy val tcIgnoreUnexpectedWarnings: String = (testCaseXML \ 
"@ignoreUnexpectedWarnings").text
+  lazy val ignoreUnexpectedWarnings: Boolean =
+    if (tcIgnoreUnexpectedWarnings == "") defaultIgnoreUnexpectedWarnings
+    else tcIgnoreUnexpectedWarnings.toBoolean
+
   lazy val description = (testCaseXML \ "@description").text
   lazy val unsupported = (testCaseXML \ "@unsupported").text match {
     case "true" => true
@@ -724,17 +743,26 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: 
DFDLTestSuite) {
   }
 
   lazy val shouldValidate = validationMode != ValidationMode.Off
+  lazy val ignoreUnexpectedValidationErrors = if 
(optExpectedValidationErrors.isDefined) {
+    optExpectedValidationErrors.get.exists(
+      _.hasDiagnostics
+    ) // ignore unexpected validation errors will be false if 
<tdml:validationErrors /> or true
+    // if there are children under validationErrors
+  } else {
+    true // ignore unexpected validation errors if there is no 
validationErrors element
+  }
   lazy val expectsValidationError =
-    if (optExpectedValidationErrors.isDefined) 
optExpectedValidationErrors.get.hasDiagnostics
+    if (optExpectedValidationErrors.isDefined)
+      optExpectedValidationErrors.get.exists(_.hasDiagnostics)
     else false
 
   protected def runProcessor(
     compileResult: TDML.CompileResult,
     expectedData: Option[InputStream],
     nBits: Option[Long],
-    errors: Option[ExpectedErrors],
-    warnings: Option[ExpectedWarnings],
-    validationErrors: Option[ExpectedValidationErrors],
+    errors: Option[Seq[ExpectedErrors]],
+    warnings: Option[Seq[ExpectedWarnings]],
+    validationErrors: Option[Seq[ExpectedValidationErrors]],
     validationMode: ValidationMode.Type,
     roundTrip: RoundTrip,
     implString: Option[String]
@@ -959,32 +987,51 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: 
DFDLTestSuite) {
 
   protected def checkDiagnosticMessages(
     diagnostics: Seq[Diagnostic],
-    errors: ExpectedErrors,
-    optWarnings: Option[ExpectedWarnings],
+    optErrors: Option[Seq[ExpectedErrors]],
+    optWarnings: Option[Seq[ExpectedWarnings]],
+    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
     implString: Option[String]
   ): Unit = {
-    Assert.usage(this.isNegativeTest)
 
     // check for any test-specified errors or warnings
     if (
       !isCrossTest(implString.get) ||
       parent.shouldDoErrorComparisonOnCrossTests
-    )
-      VerifyTestCase.verifyAllDiagnosticsFound(
-        diagnostics,
-        Some(errors),
+    ) {
+      val errorDiagnostics = diagnostics.filter(d => d.isError && 
!d.isValidation)
+      VerifyTestCase.verifyDiagnosticsFound(
+        errorDiagnostics,
+        optErrors,
+        ignoreUnexpectedDiags = false,
+        DiagnosticType.Error,
         implString
       )
+    }
 
     if (
       !isCrossTest(implString.get) ||
       parent.shouldDoWarningComparisonOnCrossTests
-    )
-      VerifyTestCase.verifyAllDiagnosticsFound(
-        diagnostics,
+    ) {
+      val warningDiagnostics = diagnostics.filterNot(d => d.isValidation || 
d.isError)
+      VerifyTestCase.verifyDiagnosticsFound(
+        warningDiagnostics,
         optWarnings,
+        ignoreUnexpectedWarnings,
+        DiagnosticType.Warning,
         implString
       )
+    }
+
+    if (!isCrossTest(implString.get)) {
+      val validationErrorDiagnostics = diagnostics.filter(diag => 
diag.isValidation)
+      VerifyTestCase.verifyDiagnosticsFound(
+        validationErrorDiagnostics,
+        optValidationErrors,
+        ignoreUnexpectedDiags = ignoreUnexpectedValidationErrors,
+        DiagnosticType.ValidationError,
+        implString
+      )
+    }
   }
 }
 
@@ -997,9 +1044,9 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
     compileResult: TDML.CompileResult,
     optDataToParse: Option[InputStream],
     optLengthLimitInBits: Option[Long],
-    optExpectedErrors: Option[ExpectedErrors],
-    optExpectedWarnings: Option[ExpectedWarnings],
-    optExpectedValidationErrors: Option[ExpectedValidationErrors],
+    optExpectedErrors: Option[Seq[ExpectedErrors]],
+    optExpectedWarnings: Option[Seq[ExpectedWarnings]],
+    optExpectedValidationErrors: Option[Seq[ExpectedValidationErrors]],
     validationMode: ValidationMode.Type,
     roundTrip: RoundTrip,
     implString: Option[String]
@@ -1033,16 +1080,22 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
         }
       }
 
-      case (None, Some(errors)) => {
+      case (None, Some(_)) => {
         compileResult match {
           case Left(diags) =>
-            checkDiagnosticMessages(diags, errors, optExpectedWarnings, 
implString)
+            checkDiagnosticMessages(
+              diags,
+              optExpectedErrors,
+              optExpectedWarnings,
+              optExpectedValidationErrors,
+              implString
+            )
           case Right((diags, proc)) => {
             processor = proc
             runParseExpectErrors(
               dataToParse,
               nBits,
-              optExpectedErrors.get,
+              optExpectedErrors,
               optExpectedWarnings,
               optExpectedValidationErrors,
               validationMode,
@@ -1063,9 +1116,9 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
   def runParseExpectErrors(
     dataToParse: InputStream,
     lengthLimitInBits: Long,
-    errors: ExpectedErrors,
-    optWarnings: Option[ExpectedWarnings],
-    optValidationErrors: Option[ExpectedValidationErrors],
+    optErrors: Option[Seq[ExpectedErrors]],
+    optWarnings: Option[Seq[ExpectedWarnings]],
+    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
     validationMode: ValidationMode.Type,
     implString: Option[String],
     compileWarnings: Seq[Diagnostic]
@@ -1128,7 +1181,13 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
       )
     }
 
-    checkDiagnosticMessages(diagnostics, errors, optWarnings, implString)
+    checkDiagnosticMessages(
+      diagnostics,
+      optErrors,
+      optWarnings,
+      optValidationErrors,
+      implString
+    )
   }
 
   /**
@@ -1198,38 +1257,18 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
     val resultXmlNode = actual.getResult
     VerifyTestCase.verifyParserTestData(resultXmlNode, testInfoset, implString)
 
-    (shouldValidate, expectsValidationError) match {
-      case (_, true) => {
-        // Note that even if shouldValidate is false, we still need to check
-        // for validation diagnostics because failed assertions with
-        // failureType="recoverableError" are treated as validation errors
-        VerifyTestCase.verifyAllDiagnosticsFound(
-          actual.getDiagnostics,
-          optExpectedValidationErrors,
-          implString
-        ) // verify all validation errors were found
-        Assert.invariant(actual.isValidationError)
-      }
-      case (true, false) => {
-        VerifyTestCase.verifyNoValidationErrorsFound(
-          actual,
-          implString
-        ) // Verify no validation errors from parser
-        Assert.invariant(!actual.isValidationError)
-      }
-      case (false, false) => // Nothing to do here.
-    }
-
     val allDiags = compileWarnings ++ actual.getDiagnostics
-    if (
-      !isCrossTest(implString.get) ||
-      parent.shouldDoWarningComparisonOnCrossTests
+    checkDiagnosticMessages(
+      allDiags,
+      None,
+      optExpectedWarnings,
+      optExpectedValidationErrors,
+      implString
     )
-      VerifyTestCase.verifyAllDiagnosticsFound(
-        allDiags,
-        optExpectedWarnings,
-        implString
-      )
+    if (shouldValidate && !expectsValidationError)
+      Assert.invariant(!actual.isValidationError)
+    else if (expectsValidationError)
+      Assert.invariant(actual.isValidationError)
   }
 
   /**
@@ -1309,8 +1348,8 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
   def runParseExpectSuccess(
     dataToParse: InputStream,
     lengthLimitInBits: Long,
-    warnings: Option[ExpectedWarnings],
-    validationErrors: Option[ExpectedValidationErrors],
+    warnings: Option[Seq[ExpectedWarnings]],
+    validationErrors: Option[Seq[ExpectedValidationErrors]],
     validationMode: ValidationMode.Type,
     roundTripArg: RoundTrip,
     implString: Option[String],
@@ -1504,9 +1543,9 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
     compileResult: TDML.CompileResult,
     optExpectedData: Option[InputStream],
     optNBits: Option[Long],
-    optErrors: Option[ExpectedErrors],
-    optWarnings: Option[ExpectedWarnings],
-    optValidationErrors: Option[ExpectedValidationErrors],
+    optErrors: Option[Seq[ExpectedErrors]],
+    optWarnings: Option[Seq[ExpectedWarnings]],
+    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
     validationMode: ValidationMode.Type,
     roundTrip: RoundTrip,
     implString: Option[String]
@@ -1518,17 +1557,38 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
           case Left(diags) => throw TDMLException(diags, implString)
           case Right((diags, proc)) => {
             processor = proc
-            runUnparserExpectSuccess(expectedData, optWarnings, roundTrip, 
implString, diags)
+            runUnparserExpectSuccess(
+              expectedData,
+              optWarnings,
+              optValidationErrors,
+              roundTrip,
+              implString,
+              diags
+            )
           }
         }
       }
 
-      case (_, Some(errors)) => {
+      case (_, Some(_)) => {
         compileResult match {
-          case Left(diags) => checkDiagnosticMessages(diags, errors, 
optWarnings, implString)
+          case Left(diags) =>
+            checkDiagnosticMessages(
+              diags,
+              optErrors,
+              optWarnings,
+              optValidationErrors,
+              implString
+            )
           case Right((diags, proc)) => {
             processor = proc
-            runUnparserExpectErrors(optExpectedData, errors, optWarnings, 
implString, diags)
+            runUnparserExpectErrors(
+              optExpectedData,
+              optErrors,
+              optWarnings,
+              optValidationErrors,
+              implString,
+              diags
+            )
           }
         }
       }
@@ -1539,7 +1599,8 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
 
   def runUnparserExpectSuccess(
     expectedData: InputStream,
-    optWarnings: Option[ExpectedWarnings],
+    optWarnings: Option[Seq[ExpectedWarnings]],
+    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
     roundTrip: RoundTrip,
     implString: Option[String],
     compileWarnings: Seq[Diagnostic]
@@ -1585,16 +1646,15 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
       // we will need to treat as Hex bytes as well.
       VerifyTestCase.verifyBinaryOrMixedData(expectedData, outStream, 
implString)
     }
+
     val allDiags = actual.getDiagnostics ++ compileWarnings
-    if (
-      !isCrossTest(implString.get) ||
-      parent.shouldDoWarningComparisonOnCrossTests
+    checkDiagnosticMessages(
+      allDiags,
+      None,
+      optWarnings,
+      optValidationErrors,
+      implString
     )
-      VerifyTestCase.verifyAllDiagnosticsFound(
-        allDiags,
-        optWarnings,
-        implString
-      )
 
     if (roundTrip eq OnePassRoundTrip) {
 
@@ -1630,37 +1690,11 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
 
       val xmlNode = parseActual.getResult
       VerifyTestCase.verifyParserTestData(xmlNode, inputInfoset, implString)
-      if (
-        !isCrossTest(implString.get) ||
-        parent.shouldDoWarningComparisonOnCrossTests
-      )
-        VerifyTestCase.verifyAllDiagnosticsFound(
-          actual.getDiagnostics,
-          optWarnings,
-          implString
-        )
 
-      (shouldValidate, expectsValidationError) match {
-        case (_, true) => {
-          // Note that even if shouldValidate is false, we still need to check
-          // for validation diagnostics because failed assertions with
-          // failureType="recoverableError" are treated as validation errors
-          VerifyTestCase.verifyAllDiagnosticsFound(
-            actual.getDiagnostics,
-            optExpectedValidationErrors,
-            implString
-          ) // verify all validation errors were found
-          Assert.invariant(actual.isValidationError)
-        }
-        case (true, false) => {
-          VerifyTestCase.verifyNoValidationErrorsFound(
-            actual,
-            implString
-          ) // Verify no validation errors from parser
-          Assert.invariant(!actual.isValidationError)
-        }
-        case (false, false) => // Nothing to do here.
-      }
+      if (shouldValidate && !expectsValidationError)
+        Assert.invariant(!actual.isValidationError)
+      else if (expectsValidationError)
+        Assert.invariant(actual.isValidationError)
 
       leftOverException.map {
         throw _
@@ -1679,8 +1713,9 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
 
   def runUnparserExpectErrors(
     optExpectedData: Option[InputStream],
-    errors: ExpectedErrors,
-    optWarnings: Option[ExpectedWarnings],
+    optErrors: Option[Seq[ExpectedErrors]],
+    optWarnings: Option[Seq[ExpectedWarnings]],
+    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
     implString: Option[String],
     compileWarnings: Seq[Diagnostic]
   ): Unit = {
@@ -1741,7 +1776,13 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
 
     if (diagnostics.isEmpty)
       throw TDMLException("Unparser test expected error. Didn't get one.", 
implString)
-    checkDiagnosticMessages(diagnostics, errors, optWarnings, implString)
+    checkDiagnosticMessages(
+      diagnostics,
+      optErrors,
+      optWarnings,
+      optValidationErrors,
+      implString
+    )
   }
 }
 
@@ -1802,86 +1843,96 @@ object VerifyTestCase {
   /**
    * Do diagnostics verification
    *
-   * @param actualDiags                               Actual diagnostics 
produced
+   * @param actualDiagsFiltered                       Actual diagnostics 
produced filtered by diagnostic type
    * @param expectedDiags                             Expected diagnostics 
from test cases
+   * @param ignoreUnexpectedDiags                     flag for ignoring 
unexpected diagnostics
+   * @param diagnosticType                            Enumeration (Warning, 
Error or ValidationError) describing the
+   *                                                  type of diagnostic being 
verified
    * @param implString                                Implementation string
    */
-  def verifyAllDiagnosticsFound(
-    actualDiags: Seq[Diagnostic],
-    expectedDiags: Option[ErrorWarningBase],
+  def verifyDiagnosticsFound(
+    actualDiagsFiltered: Seq[Diagnostic],
+    expectedDiags: Option[Seq[ErrorWarningBase]],
+    ignoreUnexpectedDiags: Boolean,
+    diagnosticType: DiagnosticType,
     implString: Option[String]
-  ) = {
+  ): Unit = {
 
-    val actualDiagMsgs = actualDiags.map {
-      _.toString()
-    }
     val expectedDiagMsgs = expectedDiags
-      .map {
-        _.messages
+      .map { d =>
+        d.flatMap(_.messages)
       }
       .getOrElse(Nil)
 
-    if (expectedDiags.isDefined && actualDiags.isEmpty) {
+    val actualDiagsFilteredMessages = actualDiagsFiltered.map(_.toString())
+
+    // throw exception if we have no actualDiags, but have expected diagnostics
+    val hasExpectedDiagnostics = (expectedDiags.isDefined
+      && expectedDiags.get.exists(_.hasDiagnostics))
+    if (hasExpectedDiagnostics && actualDiagsFiltered.isEmpty) {
       throw TDMLException(
         """"Diagnostic message(s) were expected but not found."""" +
           "\n" +
           """Expected: """ + expectedDiagMsgs.mkString("\n") +
-          (if (actualDiagMsgs.isEmpty)
-             "\n No diagnostic messages were issued."
+          (if (actualDiagsFiltered.isEmpty)
+             s"\n No ${diagnosticType} diagnostic messages were issued."
            else
-             "\n The actual diagnostics messages were: " + 
actualDiagMsgs.mkString("\n")),
+             "\n The actual diagnostics messages were: " + 
actualDiagsFilteredMessages.mkString(
+               "\n"
+             )),
         implString
       )
     }
 
-    // must find each expected warning message within some actual warning 
message.
-    expectedDiags.foreach { expectedDiag =>
-      {
-        expectedDiag.messages.foreach { expectedMsg =>
-          {
-            val wasFound = actualDiags.exists { actualDiag =>
-              val actualDiagMsg = actualDiag.getMessage()
-              actualDiag.isError == expectedDiag.isError &&
-              actualDiagMsg.toLowerCase.contains(expectedMsg.toLowerCase)
-            }
-            if (!wasFound) {
+    val hasUnexpectedDiags =
+      (expectedDiags.isEmpty || !expectedDiags.get.exists(_.hasDiagnostics)) &&
+        actualDiagsFiltered.nonEmpty
+    if (hasUnexpectedDiags && !ignoreUnexpectedDiags) {
+      throw TDMLException(
+        s"ignoreUnexpectedDiags = false and test does not expect 
${diagnosticType} diagnostics, but created the following: " +
+          s"${actualDiagsFilteredMessages.mkString("\n")}",
+        implString
+      )
+    }
+
+    expectedDiags.map { diags =>
+      diags.map { diag =>
+        val matchAttr = diag.matchAttrib
+        val diagsFound = diag.messages.map { d =>
+          // make case insensitive
+          val wasFound =
+            actualDiagsFilteredMessages.exists(ad => 
ad.toLowerCase.contains(d.toLowerCase))
+          (d, wasFound)
+        }
+        matchAttr match {
+          case "all" => {
+            if (!diagsFound.forall(_._2)) {
               throw TDMLException(
-                s"""Did not find diagnostic ${expectedDiag.diagnosticType} 
message """" +
-                  expectedMsg +
+                s"""Did not find diagnostic ${diag.diagnosticType} message 
"""" +
+                  diagsFound.find(_._2 == false).get._1 +
                   """" in any of the actual diagnostic messages: """ + "\n" +
-                  actualDiagMsgs.mkString("\n"),
+                  actualDiagsFilteredMessages.mkString("\n"),
                 implString
               )
             }
           }
+          case "none" => {
+            if (diagsFound.exists(_._2)) {
+              throw TDMLException(
+                s"""Found one of diagnostic ${diag.diagnosticType} message 
"""" +
+                  diagsFound.find(_._2 == true).get._1 +
+                  """" in one of the actual diagnostic messages: """ + "\n" +
+                  actualDiagsFilteredMessages.mkString("\n"),
+                implString
+              )
+            }
+          }
+          case _ => throw TDMLException("Only match=all or match=none 
supported", implString)
         }
       }
     }
   }
 
-  /**
-   * Strip location info from schema context off diag string message
-   * @param msg diag string message
-   * @return diag message without location information
-   */
-  def stripLocationInformation(msg: String): String = {
-    msg.replaceAll("Location line.*", "")
-  }
-
-  def verifyNoValidationErrorsFound(actual: TDMLResult, implString: 
Option[String]) = {
-    val actualDiags = actual.getDiagnostics.filter(d => d.isValidation)
-    if (actualDiags.nonEmpty) {
-      val actualDiagMsgs = actualDiags.map {
-        _.toString()
-      }
-      throw TDMLException(
-        "Validation errors found where none were expected by the test case.\n" 
+
-          actualDiagMsgs.mkString("\n"),
-        implString
-      )
-    }
-  }
-
   def decodeDataToString(decoder: BitsCharsetDecoder, bytes: Array[Byte]): 
String = {
     class FormatInfoForTDMLDecode extends FormatInfo {
       // Decoders don't actually need much of the formatinfo. Byte size
@@ -2780,11 +2831,20 @@ case class DFDLInfoset(di: Node, parent: Infoset) {
   }
 }
 
+object DiagnosticType extends Enumeration {
+  type DiagnosticType = Value
+  val Error, Warning, ValidationError = Value
+}
+
 abstract class ErrorWarningBase(n: NodeSeq, parent: TestCase) {
-  lazy val matchAttrib = (n \ "@match").text
+  lazy val matchAttrib = if ((n \ "@match").text == "") {
+    "all"
+  } else {
+    (n \ "@match").text
+  }
 
   def isError: Boolean
-  def diagnosticType: String
+  def diagnosticType: DiagnosticType
 
   protected def diagnosticNodes: Seq[Node]
 
@@ -2798,18 +2858,32 @@ abstract class ErrorWarningBase(n: NodeSeq, parent: 
TestCase) {
 case class ExpectedErrors(node: NodeSeq, parent: TestCase)
   extends ErrorWarningBase(node, parent) {
 
-  val diagnosticNodes = node \\ "error"
+  val diagnosticNodes = {
+    val nodes = (node \\ "error")
+    if (nodes.isEmpty) {
+      throw TDMLException("tdml:errors must have at least one child element", 
None)
+    } else {
+      nodes
+    }
+  }
   override def isError = true
-  override def diagnosticType = "error"
+  override def diagnosticType: DiagnosticType = DiagnosticType.Error
 
 }
 
 case class ExpectedWarnings(node: NodeSeq, parent: TestCase)
   extends ErrorWarningBase(node, parent) {
 
-  val diagnosticNodes = node \\ "warning"
+  val diagnosticNodes = {
+    val nodes = (node \\ "warning")
+    if (nodes.isEmpty) {
+      throw TDMLException("tdml:warnings must have at least one child 
element", None)
+    } else {
+      nodes
+    }
+  }
   override def isError = false
-  override def diagnosticType = "warning"
+  override def diagnosticType: DiagnosticType = DiagnosticType.Warning
 
 }
 
@@ -2818,7 +2892,7 @@ case class ExpectedValidationErrors(node: NodeSeq, 
parent: TestCase)
 
   val diagnosticNodes = node \\ "error"
   override def isError = true
-  override def diagnosticType = "validation error"
+  override def diagnosticType: DiagnosticType = DiagnosticType.ValidationError
 
 }
 
diff --git 
a/daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java
 
b/daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java
index 2b8009bcb..6506a87f3 100644
--- 
a/daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java
+++ 
b/daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java
@@ -50,7 +50,8 @@ public class TestRunnerFactory {
       false,
       NoRoundTrip$.MODULE$,
       "off",
-      JavaConverters.asScalaBufferConverter(Arrays.asList("daffodil", 
"ibm")).asScala());
+      JavaConverters.asScalaBufferConverter(Arrays.asList("daffodil", 
"ibm")).asScala(),
+      false);
     runner.runOneTest("testPass");
     runner.reset();
   }
diff --git 
a/daffodil-tdml-processor/src/test/resources/test/tdml/testTDMLErrorsWarningsMatchAttribute.tdml
 
b/daffodil-tdml-processor/src/test/resources/test/tdml/testTDMLErrorsWarningsMatchAttribute.tdml
new file mode 100644
index 000000000..eeb6eafee
--- /dev/null
+++ 
b/daffodil-tdml-processor/src/test/resources/test/tdml/testTDMLErrorsWarningsMatchAttribute.tdml
@@ -0,0 +1,188 @@
+<?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 
+  suiteName="tdml errors/warnings match attribute"
+  description="Tests for TDML Runner errors/warnings match attribute any, all 
and none"
+  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:ex="http://example.com"; 
+  xmlns:fn="http://www.w3.org/2005/xpath-functions";
+  defaultRoundTrip="false">
+
+  <tdml:defineSchema name="noWarnings">
+    <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited" 
encoding="utf-8" representation="text"/>
+    <xs:element name="elem" type="xs:string">
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/"; />
+      </xs:annotation>
+    </xs:element>
+  </tdml:defineSchema>
+
+  <tdml:defineSchema name="causesWarnings">
+    <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited" 
encoding="utf-8" representation="text"/>
+    <xs:element name="elem" type="xs:string">
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/dfdl-1.0/"; />
+      </xs:annotation>
+    </xs:element>
+  </tdml:defineSchema>
+
+  <tdml:parserTestCase name="getsWarningExpectsWarnings" root="elem"
+                       model="causesWarnings"
+                       description="">
+    <tdml:document><![CDATA[test]]></tdml:document>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <elem>test</elem>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+    <tdml:warnings match="none">
+      <tdml:warning>THIS WILL NOT MATCH</tdml:warning>
+    </tdml:warnings>
+
+    <tdml:warnings>
+      <tdml:warning>Schema Definition Warning</tdml:warning>
+      <tdml:warning>The xs:appinfo source attribute value 
'http://www.ogf.org/dfdl/dfdl-1.0/' should be 
'http://www.ogf.org/dfdl/'.</tdml:warning>
+    </tdml:warnings>
+
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase
+      name="getsWarningExpectsNoWarnings" root="elem"
+      model="causesWarnings"
+      description=""
+      ignoreUnexpectedWarnings="false">
+    <tdml:document><![CDATA[test]]></tdml:document>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <elem>test</elem>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase
+      name="noWarningExpectsNoWarnings" root="elem"
+      model="noWarnings"
+      description=""
+      ignoreUnexpectedWarnings="false">
+    <tdml:document><![CDATA[test]]></tdml:document>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <elem>test</elem>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:defineSchema name="causesErrors" elementFormDefault="unqualified">
+
+    <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <dfdl:format ref="ex:GeneralFormat" lengthKind="explicit" 
occursCountKind="implicit"/>
+
+    <xs:element name="causesUnparseError" dfdl:lengthKind="implicit">
+      <xs:complexType>
+        <xs:sequence>
+          <xs:element name="A" type="xs:string" dfdl:length="1"/>
+          <xs:element name="AmbigElt" type="xs:string" dfdl:length="1"/>
+          <xs:element name="B" type="xs:string" dfdl:length="1"/>
+          <xs:element name="AmbigElt" type="xs:string" dfdl:length="1" 
minOccurs="0"/>
+          <xs:element name="UnparseFails" type="xs:string" dfdl:length="1"
+                      dfdl:outputValueCalc="{ ../AmbigElt }"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+    <xs:element name="causesValidationError" dfdl:lengthKind="implicit">
+      <xs:complexType>
+        <xs:sequence>
+          <xs:element name="A" dfdl:length="1" dfdl:inputValueCalc="{ 'A' }">
+            <xs:simpleType>
+              <xs:restriction base="xs:string">
+                <xs:pattern value="[^A-FH-OQ-Z]"/>
+              </xs:restriction>
+            </xs:simpleType>
+          </xs:element>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+  </tdml:defineSchema>
+
+  <tdml:unparserTestCase name="getUnparserWarningWhenExpectingError"
+                         root="causesUnparseError" model="causesErrors">
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:causesUnparseError>
+          <A>1</A>
+          <AmbigElt>2</AmbigElt>
+          <B>3</B>
+          <AmbigElt>4</AmbigElt>
+        </ex:causesUnparseError>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+    <tdml:document><![CDATA[12344]]></tdml:document>
+
+    <tdml:errors>
+      <tdml:error>Schema Definition Error</tdml:error>
+    </tdml:errors>
+    <tdml:errors match="none">
+      <tdml:error>WILL NOT MATCH ON THIS</tdml:error>
+    </tdml:errors>
+
+    <tdml:warnings match="none">
+      <tdml:warning>WILL NOT MATCH ON THIS</tdml:warning>
+    </tdml:warnings>
+    <tdml:warnings>
+      <tdml:warning>Schema Definition Warning</tdml:warning>
+      <tdml:warning>AmbigElt</tdml:warning>
+      <tdml:warning>query-style</tdml:warning>
+    </tdml:warnings>
+  </tdml:unparserTestCase>
+
+
+  <tdml:parserTestCase name="expectsAnyValidationError" 
root="causesValidationError"
+                       model="causesErrors" validation="on">
+
+    <tdml:document/>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:causesValidationError>
+          <A>A</A>
+        </ex:causesValidationError>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+    <tdml:validationErrors>
+      <tdml:error>value 'A' of element 'A' is not valid</tdml:error>
+    </tdml:validationErrors>
+    <tdml:validationErrors match="none">
+      <tdml:error>WILL NOT MATCH ON THIS</tdml:error>
+    </tdml:validationErrors>
+  </tdml:parserTestCase>
+
+</tdml:testSuite>
diff --git 
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
index c611f7c1a..c187a25f7 100644
--- 
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
+++ 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
@@ -259,6 +259,7 @@ class TestTDMLRunner2 {
               </tns:array>
             </tdml:dfdlInfoset>
           </tdml:infoset>
+          <tdml:validationErrors/>
         </tdml:parserTestCase>
       </tdml:testSuite>
 
@@ -268,7 +269,11 @@ class TestTDMLRunner2 {
     }
     runner.reset
     val msg = e.getMessage()
-    assertTrue(msg.contains("Validation errors found where none were 
expected"))
+    assertTrue(
+      msg.contains(
+        "ignoreUnexpectedDiags = false and test does not expect 
ValidationError diagnostics"
+      )
+    )
   }
 
   /**
diff --git 
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerMatchAttributes.scala
 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerMatchAttributes.scala
new file mode 100644
index 000000000..2945c6648
--- /dev/null
+++ 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerMatchAttributes.scala
@@ -0,0 +1,169 @@
+/*
+ * 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.processor.tdml
+
+import org.apache.daffodil.lib.Implicits.intercept
+import org.apache.daffodil.lib.xml.XMLUtils
+import org.apache.daffodil.tdml.Runner
+import org.apache.daffodil.tdml.TDMLException
+
+import org.junit.AfterClass
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+object TestTDMLRunnerMatchAttributes {
+  val runner = Runner("/test/tdml/", 
"testTDMLErrorsWarningsMatchAttribute.tdml")
+
+  @AfterClass def shutDown(): Unit = {
+    runner.reset
+  }
+}
+
+class TestTDMLRunnerMatchAttributes {
+  import TestTDMLRunnerMatchAttributes._
+
+  // DAFFODIL-1583
+  @Test def test_getsWarningExpectsWarnings(): Unit = {
+    runner.runOneTest("getsWarningExpectsWarnings")
+  }
+  @Test def test_getUnparserWarningWhenExpectingError(): Unit = {
+    runner.runOneTest("getUnparserWarningWhenExpectingError")
+  }
+  @Test def test_expectsAnyValidationError() = {
+    runner.runOneTest("expectsAnyValidationError")
+  }
+
+  @Test def test_noWarningExpectsNoWarnings() = {
+    runner.runOneTest("noWarningExpectsNoWarnings")
+  }
+
+  @Test def test_getsWarningExpectsNoWarnings() = {
+    val e = intercept[TDMLException] {
+      runner.runOneTest("getsWarningExpectsNoWarnings")
+    }
+    val errMsg = e.getMessage()
+    assertTrue(
+      errMsg.contains(
+        "ignoreUnexpectedDiags = false and test does not expect Warning 
diagnostics"
+      )
+    )
+  }
+
+  lazy val testSuite =
+    <ts:testSuite xmlns:dfdl={XMLUtils.DFDL_NAMESPACE} xmlns:xs={
+      XMLUtils.XSD_NAMESPACE
+    } xmlns:ex={XMLUtils.EXAMPLE_NAMESPACE} xmlns:ts={
+      XMLUtils.TDML_NAMESPACE
+    } suiteName="theSuiteName"
+      defaultIgnoreUnexpectedWarnings="false">
+      <ts:defineSchema name="causesWarnings">
+        <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+        <dfdl:format ref="ex:GeneralFormat"/>
+        <xs:element name="r" type="xs:string" dfdl:lengthKind="delimited">
+          <xs:annotation>
+            <xs:appinfo source="http://www.ogf.org/dfdl/dfdl-1.0/"; />
+          </xs:annotation>
+        </xs:element>
+      </ts:defineSchema>
+      <ts:defineSchema name="noWarnings">
+        <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+        <dfdl:format ref="ex:GeneralFormat"/>
+        <xs:element name="r" type="xs:string" dfdl:lengthKind="delimited">
+          <xs:annotation>
+            <xs:appinfo source="http://www.ogf.org/dfdl/"; />
+          </xs:annotation>
+        </xs:element>
+      </ts:defineSchema>
+
+      <ts:parserTestCase name="expectsNoWarningGetsWarnings" root="r" 
model="causesWarnings" roundTrip="onePass">
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>foo</ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo</ts:document>
+      </ts:parserTestCase>
+
+      <ts:parserTestCase name="expectsWarningGetsNoWarnings" root="r" 
model="noWarnings" roundTrip="onePass">
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>foo</ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo</ts:document>
+
+        <ts:warnings>
+          <ts:warning>Schema Definition Warning</ts:warning>
+          <ts:warning>The xs:appinfo source attribute value 
'http://www.ogf.org/dfdl/dfdl-1.0/' should be 
'http://www.ogf.org/dfdl/'.</ts:warning>
+        </ts:warnings>
+      </ts:parserTestCase>
+
+      <ts:parserTestCase name="expectsWarningGetsWarning" root="r" 
model="causesWarnings" roundTrip="onePass">
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>foo</ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo</ts:document>
+
+        <ts:warnings>
+          <ts:warning>Schema Definition Warning</ts:warning>
+          <ts:warning>The xs:appinfo source attribute value 
'http://www.ogf.org/dfdl/dfdl-1.0/' should be 
'http://www.ogf.org/dfdl/'.</ts:warning>
+        </ts:warnings>
+      </ts:parserTestCase>
+
+      <ts:parserTestCase name="expectsNoWarningGetsNoWarnings" root="r" 
model="noWarnings" roundTrip="onePass">
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>foo</ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo</ts:document>
+      </ts:parserTestCase>
+    </ts:testSuite>
+
+  @Test def test_expectsNoWarningGetsWarnings(): Unit = {
+    val runner = new Runner(testSuite)
+    val e = intercept[TDMLException] {
+      runner.runOneTest("expectsNoWarningGetsWarnings")
+    }
+    runner.reset
+    val msg = e.getMessage()
+    assertTrue(
+      msg.contains("ignoreUnexpectedDiags = false and test does not expect 
Warning diagnostics")
+    )
+  }
+
+  @Test def test_expectsWarningGetsNoWarnings(): Unit = {
+    val runner = new Runner(testSuite)
+    val e = intercept[TDMLException] {
+      runner.runOneTest("expectsWarningGetsNoWarnings")
+    }
+    runner.reset
+    val msg = e.getMessage()
+    assertTrue(msg.contains("Diagnostic message(s) were expected but not 
found"))
+  }
+  @Test def test_expectsWarningGetsWarning(): Unit = {
+    val runner = new Runner(testSuite)
+    runner.runOneTest("expectsWarningGetsWarning")
+  }
+  @Test def test_expectsNoWarningGetsNoWarnings(): Unit = {
+    val runner = new Runner(testSuite)
+    runner.runOneTest("expectsNoWarningGetsNoWarnings")
+  }
+}
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
index 5dc760378..fe6ca88d7 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
@@ -1898,14 +1898,6 @@
       <tdml:error>Initiator 'C' not found</tdml:error>
     </tdml:errors>
 
-    <tdml:validationErrors>
-        
-      <!-- Validation error for branch1:e1  -->
-      <tdml:error>Validation Error</tdml:error>
-      <tdml:error>nonNegA failed facet checks due to: facet minInclusive 
(30)</tdml:error>
-
-    </tdml:validationErrors>
-
   </tdml:parserTestCase>
   
   <!--
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberProps.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberProps.tdml
index 6b28b9e54..69f99fa31 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberProps.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberProps.tdml
@@ -4089,14 +4089,13 @@
 
   <tdml:parserTestCase name="nanInvalidType" root="nanInvalidType"
     model="textprops"
+    ignoreUnexpectedWarnings="false"
     description="Attempt to read nan for an invalid type.">
 
     <tdml:document>
       <tdml:documentPart 
type="text"><![CDATA[NOTANUMBER]]]></tdml:documentPart>
     </tdml:document>
 
-    <tdml:warnings />
-
     <tdml:errors>
       <tdml:error>Parse Error</tdml:error>
       <tdml:error>NaN</tdml:error>
@@ -4108,14 +4107,13 @@
 
   <tdml:parserTestCase name="infInvalidType" root="infInvalidType"
     model="textprops"
+    ignoreUnexpectedWarnings="false"
     description="Attempt to read inf for an invalid type.">
 
     <tdml:document>
       <tdml:documentPart type="text"><![CDATA[INFINITY]]]></tdml:documentPart>
     </tdml:document>
 
-    <tdml:warnings />
-
     <tdml:errors>
       <tdml:error>Parse Error</tdml:error>
       <tdml:error>Infinity</tdml:error>


Reply via email to