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

slawrence 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 39cc88cad Change recoverable errors to validation errors instead of 
schema definition warnings
39cc88cad is described below

commit 39cc88cad7e5e14815fe0234de5debd455265f1a
Author: Steve Lawrence <[email protected]>
AuthorDate: Mon Oct 24 15:13:22 2022 -0400

    Change recoverable errors to validation errors instead of schema definition 
warnings
    
    A dfdl:assert with failureType="recoverableError" currently results in a
    schema definition warning. However, SDW's are usually used for things
    that can be safely ignored, while these asserts are generally used for
    validation checking beyond the capabilities of XSD that should not be
    ignored, or should at least be treated differently than warnings so that
    a user can easily differentiate between the two.
    
    This modifies these recoverable errors to become validation errors,
    accessible just like those created when validation is turned on. This
    also refactors the handling of errors to avoid duplication between
    assert expressions and assert patterns, as well as changes to make error
    messages more consistent.
    
    Note that this is a non-backwards compatible change, but is arguably the
    more correct behavior since these asserts really are predominantly used
    for more complex validation checks.
    
    DAFFODIL-2357
---
 .../grammar/primitives/PrimitivesExpressions.scala |  8 +++--
 .../processors/parsers/AssertPatternParsers.scala  | 37 ++++++++++++----------
 .../parsers/ExpressionEvaluatingParsers.scala      | 15 ++-------
 .../org/apache/daffodil/tdml/TDMLRunner.scala      | 12 ++++---
 .../org/apache/daffodil/tdml/TestTDMLRunner2.scala | 19 +++++------
 .../resources/org/apache/daffodil/layers/IPv4.tdml |  6 ++--
 .../daffodil/section07/assertions/assert.tdml      |  6 ++--
 7 files changed, 52 insertions(+), 51 deletions(-)

diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
index ef71a9d85..3bd73ba6d 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
@@ -86,7 +86,9 @@ abstract class AssertBase(
         qn,
         NodeInfo.String, msgOpt.get, exprNamespaces, 
exprComponent.dpathCompileInfo, false, this, exprComponent.dpathCompileInfo)
     } else {
-      new ConstantExpression[String](qn, NodeInfo.String, exprWithBraces + " 
failed")
+      val typeString = if (discrim) "Discriminator" else "Assertion"
+      val defaultMessage = s"$typeString expression failed: $exprWithBraces"
+      new ConstantExpression[String](qn, NodeInfo.String, defaultMessage)
     }
   }
 
@@ -343,7 +345,9 @@ abstract class AssertPatternPrimBase(decl: Term, stmt: 
DFDLAssertionBase, discri
     if (stmt.messageAttrib.isDefined) {
       expr
     } else {
-      new ConstantExpression[String](qn, NodeInfo.String, testPattern + " 
failed")
+      val typeString = if (discrim) "Discriminator" else "Assertion"
+      val defaultMessage = s"$typeString pattern failed: $testPattern"
+      new ConstantExpression[String](qn, NodeInfo.String, defaultMessage)
     }
 
   override val forWhat = ForParser
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/AssertPatternParsers.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/AssertPatternParsers.scala
index 408a2599f..e32246d9b 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/AssertPatternParsers.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/AssertPatternParsers.scala
@@ -25,11 +25,27 @@ import org.apache.daffodil.processors._
 import org.apache.daffodil.util.OnStack
 import org.apache.daffodil.schema.annotation.props.gen.FailureType
 
-trait AssertMessageEvaluationMixin {
+trait AssertParserMixin {
   def messageExpr: CompiledExpression[AnyRef]
   def discrim: Boolean
+  def failureType: FailureType
 
-  def getAssertFailureMessage(state: PState): String = {
+  def handleAssertionResult(res: Boolean, state: PState, context: 
RuntimeData): Unit = {
+    if (!res) {
+      val message = getAssertFailureMessage(state)
+      if (failureType == FailureType.ProcessingError) {
+        val diag = new AssertionFailed(context.schemaFileLocation, state, 
message)
+        state.setFailed(diag)
+      } else
+        state.validationError("%s", message)
+    } else if (discrim) {
+      // this is a discriminator. Successful assertion resolves the in scope
+      // point of uncertainty
+      state.resolvePointOfUncertainty()
+    }
+  }
+
+  private def getAssertFailureMessage(state: PState): String = {
     val message =
       try {
         messageExpr.evaluate(state).asInstanceOf[String]
@@ -54,9 +70,9 @@ class AssertPatternParser(
   override val discrim: Boolean,
   testPattern: String,
   override val messageExpr: CompiledExpression[AnyRef],
-  failureType: FailureType)
+  override val failureType: FailureType)
   extends PrimParser
-  with AssertMessageEvaluationMixin {
+  with AssertParserMixin {
   override lazy val runtimeDependencies = Vector()
 
   override def toBriefXML(depthLimit: Int = -1) = {
@@ -75,17 +91,6 @@ class AssertPatternParser(
     val isMatch = withMatcher { m => dis.lookingAt(m, start) }
     dis.resetPos(mark)
 
-    if (!isMatch) {
-      val message = getAssertFailureMessage(start)
-      if (failureType == FailureType.ProcessingError) {
-        val diag = new AssertionFailed(context.schemaFileLocation, start, 
message)
-        start.setFailed(diag)
-      } else
-        start.SDW(message)
-    } else if (discrim) {
-      // this is a pattern discriminator. Successful match resolves the in
-      // scope point of uncertainty
-      start.resolvePointOfUncertainty()
-    }
+    handleAssertionResult(isMatch, start, context)
   }
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
index 6ea2248b2..dab56a35a 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala
@@ -202,9 +202,9 @@ final class AssertExpressionEvaluationParser(
   override val discrim: Boolean, // are we a discriminator or not.
   decl: RuntimeData,
   expr: CompiledExpression[AnyRef],
-  failureType: FailureType)
+  override val failureType: FailureType)
   extends ExpressionEvaluationParser(expr, decl)
-  with AssertMessageEvaluationMixin {
+  with AssertParserMixin {
 
   def parse(start: PState): Unit = {
     Logger.log.debug(s"This is ${toString}")
@@ -232,15 +232,6 @@ final class AssertExpressionEvaluationParser(
     if (start.processorStatus ne Success) return
 
     val testResult = res.getBoolean
-    if (testResult) {
-      if (discrim) start.resolvePointOfUncertainty()
-    } else {
-      val message = getAssertFailureMessage(start)
-      if (failureType == FailureType.ProcessingError) {
-        val diag = new AssertionFailed(decl.schemaFileLocation, start, message)
-        start.setFailed(diag)
-      } else
-        start.SDW("Assertion " + message)
-    }
+    handleAssertionResult(testResult, start, context)
   }
 }
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 de897236b..8b2f02498 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
@@ -1059,7 +1059,10 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
     VerifyTestCase.verifyParserTestData(resultXmlNode, testInfoset, implString)
 
     (shouldValidate, expectsValidationError) match {
-      case (true, true) => {
+      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)
       }
@@ -1067,7 +1070,6 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
         VerifyTestCase.verifyNoValidationErrorsFound(actual, implString) // 
Verify no validation errors from parser
         Assert.invariant(!actual.isValidationError)
       }
-      case (false, true) => throw TDMLException("Test case invalid. Validation 
is off but the test expects an error.", implString)
       case (false, false) => // Nothing to do here.
     }
 
@@ -1447,7 +1449,10 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
         VerifyTestCase.verifyAllDiagnosticsFound(actual.getDiagnostics, 
optWarnings, implString)
 
       (shouldValidate, expectsValidationError) match {
-        case (true, true) => {
+        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)
         }
@@ -1455,7 +1460,6 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: 
DFDLTestSuite)
           VerifyTestCase.verifyNoValidationErrorsFound(actual, implString) // 
Verify no validation errors from parser
           Assert.invariant(!actual.isValidationError)
         }
-        case (false, true) => throw TDMLException("Test case invalid. 
Validation is off but the test expects an error.", implString)
         case (false, false) => // Nothing to do here.
       }
 
diff --git 
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestTDMLRunner2.scala
 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestTDMLRunner2.scala
index 13de56606..c7b1ee06f 100644
--- 
a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestTDMLRunner2.scala
+++ 
b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml/TestTDMLRunner2.scala
@@ -21,7 +21,6 @@ import org.apache.daffodil.Implicits.using
 import org.apache.daffodil.xml.XMLUtils
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
 import org.junit.Test
 import org.apache.daffodil.Implicits._
 import org.junit.AfterClass
@@ -52,8 +51,12 @@ class TestTDMLRunner2 {
    * Exception expected? Yes
    *
    * Reasoning: The data parses successfully and validation is 'off'.
-   * Demonstrates that when validation is off, no validation errors
-   * should be expected by the testcase.
+   * Demonstrates that when validation is off, no validation errors will be
+   * generated and so the test will fail because it expects them.
+   *
+   * Note that this test case is not considered invalid because there are ways
+   * to generate validation errors with validation being off, such as asserts
+   * with failureType="recoverableError"
    */
   @Test def testValidationOffValidationErrorGivenShouldError() = {
     val testSuite =
@@ -88,7 +91,7 @@ class TestTDMLRunner2 {
             </tdml:dfdlInfoset>
           </tdml:infoset>
           <tdml:validationErrors>
-            <tdml:error>Specifying this should throw exception</tdml:error>
+            <tdml:error>This error will not be found with validation 
disabled</tdml:error>
           </tdml:validationErrors>
         </tdml:parserTestCase>
       </tdml:testSuite>
@@ -99,13 +102,7 @@ class TestTDMLRunner2 {
     }
     runner.reset
     val msg = e.getMessage()
-    if (!msg.contains("Test case invalid")) {
-      println(msg)
-      fail("message did not contain expected contents")
-    }
-    assertTrue(msg.contains("Test case invalid"))
-    assertTrue(msg.contains("Validation is off"))
-    assertTrue(msg.contains("test expects an error"))
+    assertTrue(msg.contains("expected but not found"))
   }
 
   /**
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/layers/IPv4.tdml 
b/daffodil-test/src/test/resources/org/apache/daffodil/layers/IPv4.tdml
index 0118bc2bd..3e766b2da 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/layers/IPv4.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/layers/IPv4.tdml
@@ -181,9 +181,9 @@ c0a8 0001 c0a8 00c7
         </ipv4:IPv4Header>
       </tdml:dfdlInfoset>
     </tdml:infoset>
-    <tdml:warnings>
-      <tdml:warning>Assertion Incorrect checksum</tdml:warning>
-    </tdml:warnings>
+    <tdml:validationErrors>
+      <tdml:error>Incorrect checksum</tdml:error>
+    </tdml:validationErrors>
   </tdml:parserTestCase>
 
 
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/assertions/assert.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/assertions/assert.tdml
index 0e0bce583..a44320112 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/assertions/assert.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/assertions/assert.tdml
@@ -397,9 +397,9 @@
         </e3r>
       </tdml:dfdlInfoset>
     </tdml:infoset>
-    <tdml:warnings>
-      <tdml:warning>Assertion</tdml:warning>
-    </tdml:warnings>
+    <tdml:validationErrors>
+      <tdml:error>Assertion</tdml:error>
+    </tdml:validationErrors>
   </tdml:parserTestCase>
 
   <!--

Reply via email to