You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by sl...@apache.org on 2020/06/23 13:09:59 UTC

[incubator-daffodil] branch master updated: Implemented dfdl:assert failureType="recoverableError"

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

slawrence 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 492e048  Implemented dfdl:assert failureType="recoverableError"
492e048 is described below

commit 492e04808d048766eeff45564e1253c341717b4f
Author: Josh Adams <ja...@tresys.com>
AuthorDate: Tue Jun 16 15:08:31 2020 -0400

    Implemented dfdl:assert failureType="recoverableError"
    
    Simple addition of allowing recoverable errors to occur from
    dfdl:assert. Right now it is simply creating a runtime Schema Definition
    Warning with the assert failure message.
    
    DAFFODIL-357
---
 .../org/apache/daffodil/dsom/DFDLAssertion.scala   |  6 ++
 .../grammar/primitives/PrimitivesExpressions.scala | 15 +++--
 .../apache/daffodil/xsd/DFDL_part1_simpletypes.xsd |  7 +++
 .../org/apache/daffodil/xsd/DFDL_part3_model.xsd   |  1 +
 .../processors/parsers/AssertPatternParsers.scala  | 11 +++-
 .../parsers/ExpressionEvaluatingParsers.scala      | 11 +++-
 .../daffodil/section07/assertions/assert.tdml      | 69 ++++++++++++++++++++++
 .../section07/assertions/TestAssertions.scala      |  2 +
 8 files changed, 110 insertions(+), 12 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
index 04787c8..f885753 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
@@ -21,6 +21,7 @@ import scala.xml.Node
 import scala.xml.NodeSeq.seqToNodeSeq
 import org.apache.daffodil.exceptions._
 import org.apache.daffodil.schema.annotation.props.gen.TestKind
+import org.apache.daffodil.schema.annotation.props.gen.FailureType
 import com.ibm.icu.impl.UnicodeRegex
 import java.util.regex.PatternSyntaxException
 import java.util.regex.Pattern
@@ -105,6 +106,11 @@ abstract class DFDLAssertionBase(node: Node, decl: AnnotatedSchemaComponent)
     case None => TestKind.Expression
   }
 
+  final lazy val failureType = getAttributeOption("failureType") match {
+    case Some(str) => FailureType(str, decl)
+    case None => FailureType.ProcessingError
+  }
+
   lazy val messageAttrib = getAttributeOption("message")
 
   final lazy val testTxt = {
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 2a5efc7..9950389 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
@@ -38,6 +38,7 @@ import org.apache.daffodil.processors.unparsers.NewVariableInstanceStartUnparser
 import org.apache.daffodil.compiler.ForParser
 import org.apache.daffodil.schema.annotation.props.PropertyLookupResult
 import org.apache.daffodil.schema.annotation.props.Found
+import org.apache.daffodil.schema.annotation.props.gen.FailureType
 import org.apache.daffodil.dsom.ExpressionCompilers
 import org.apache.daffodil.dsom.DFDLSetVariable
 import org.apache.daffodil.dsom.DFDLNewVariableInstance
@@ -59,7 +60,8 @@ abstract class AssertBase(
   scWherePropertyWasLocated: AnnotatedSchemaComponent,
   msgOpt: Option[String],
   discrim: Boolean, // are we a discriminator or not.
-  assertKindName: String)
+  assertKindName: String,
+  failureType: FailureType)
   extends ExpressionEvaluatorBase(scWherePropertyWasLocated) {
 
   def this(
@@ -67,8 +69,9 @@ abstract class AssertBase(
     foundProp: Found,
     msgOpt: Option[String],
     discrim: Boolean, // are we a discriminator or not.
-    assertKindName: String) =
-    this(decl, foundProp.value, foundProp.location.namespaces, decl, msgOpt, discrim, assertKindName)
+    assertKindName: String,
+    failureType: FailureType) =
+    this(decl, foundProp.value, foundProp.location.namespaces, decl, msgOpt, discrim, assertKindName, failureType)
 
   override val baseName = assertKindName
   override lazy val exprText = exprWithBraces
@@ -88,7 +91,7 @@ abstract class AssertBase(
     }
   }
 
-  lazy val parser: DaffodilParser = new AssertExpressionEvaluationParser(msgExpr, discrim, decl.runtimeData, expr)
+  lazy val parser: DaffodilParser = new AssertExpressionEvaluationParser(msgExpr, discrim, decl.runtimeData, expr, failureType)
 
   override def unparser: DaffodilUnparser = hasNoUnparser
 
@@ -98,7 +101,7 @@ abstract class AssertBooleanPrimBase(
   decl: AnnotatedSchemaComponent,
   stmt: DFDLAssertionBase,
   discrim: Boolean, // are we a discriminator or not.
-  assertKindName: String) extends AssertBase(decl, Found(stmt.testTxt, stmt, "test", false), stmt.messageAttrib, discrim, assertKindName)
+  assertKindName: String) extends AssertBase(decl, Found(stmt.testTxt, stmt, "test", false), stmt.messageAttrib, discrim, assertKindName, stmt.failureType)
 
 case class AssertBooleanPrim(
   decl: AnnotatedSchemaComponent,
@@ -302,7 +305,7 @@ abstract class AssertPatternPrimBase(decl: Term, stmt: DFDLAssertionBase, discri
 
   override val forWhat = ForParser
 
-  lazy val parser: DaffodilParser = new AssertPatternParser(decl.termRuntimeData, discrim, testPattern, msgExpr)
+  lazy val parser: DaffodilParser = new AssertPatternParser(decl.termRuntimeData, discrim, testPattern, msgExpr, stmt.failureType)
 
   override def unparser: DaffodilUnparser = Assert.invariantFailed("should not request unparser for asserts/discriminators")
 }
diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
index 5190d4f..d24b24d 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
@@ -587,6 +587,13 @@
     </xsd:restriction>
   </xsd:simpleType>
   
+  <xsd:simpleType name="FailureTypeEnum">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="processingError" />
+      <xsd:enumeration value="recoverableError" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
   <!-- A pattern is used instead of an enumeration for compactness -->
   <xsd:simpleType name="BinaryPackedSignCodes">
     <xsd:restriction base="dfdl:DFDLStringLiteral">
diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part3_model.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part3_model.xsd
index 4ebebce..7b6b18d 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part3_model.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part3_model.xsd
@@ -190,6 +190,7 @@
     <xsd:attribute name="testKind" type="dfdl:TestKindEnum" />
     <xsd:attribute name="testPattern" type="dfdl:DFDLRegularExpression" />
     <xsd:attribute name="message" type="xsd:string" />
+    <xsd:attribute name="failureType" type="dfdl:FailureTypeEnum" />
   </xsd:attributeGroup>
 
   <xsd:complexType name="TestCondition">
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 f2d523e..0549854 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
@@ -24,6 +24,7 @@ import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
 import org.apache.daffodil.processors._
 import org.apache.daffodil.util.LogLevel
 import org.apache.daffodil.util.OnStack
+import org.apache.daffodil.schema.annotation.props.gen.FailureType
 
 trait AssertMessageEvaluationMixin {
   def messageExpr: CompiledExpression[AnyRef]
@@ -53,7 +54,8 @@ class AssertPatternParser(
   override val context: TermRuntimeData,
   override val discrim: Boolean,
   testPattern: String,
-  override val messageExpr: CompiledExpression[AnyRef])
+  override val messageExpr: CompiledExpression[AnyRef],
+  failureType: FailureType)
   extends PrimParser
   with AssertMessageEvaluationMixin {
   override lazy val runtimeDependencies = Vector()
@@ -75,8 +77,11 @@ class AssertPatternParser(
       val isMatch = dis.lookingAt(m, start)
       if (!isMatch) {
         val message = getAssertFailureMessage(start)
-        val diag = new AssertionFailed(context.schemaFileLocation, start, message)
-        start.setFailed(diag)
+        if (failureType == FailureType.ProcessingError) {
+          val diag = new AssertionFailed(context.schemaFileLocation, start, message)
+          start.setFailed(diag)
+        } else
+          start.SDW(message)
       } else if (discrim) {
         // Only want to set the discriminator if there was a match.
         start.setDiscriminator(true)
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 47ff959..79f786e 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
@@ -33,6 +33,7 @@ import org.apache.daffodil.processors.Success
 import org.apache.daffodil.processors.TypeCalculator
 import org.apache.daffodil.processors.VariableRuntimeData
 import org.apache.daffodil.util.LogLevel
+import org.apache.daffodil.schema.annotation.props.gen.FailureType
 
 /**
  * Common parser base class for any parser that evaluates an expression.
@@ -175,7 +176,8 @@ class AssertExpressionEvaluationParser(
   override val messageExpr: CompiledExpression[String],
   override val discrim: Boolean, // are we a discriminator or not.
   decl: RuntimeData,
-  expr: CompiledExpression[AnyRef])
+  expr: CompiledExpression[AnyRef],
+  failureType: FailureType)
   extends ExpressionEvaluationParser(expr, decl)
   with AssertMessageEvaluationMixin {
 
@@ -209,8 +211,11 @@ class AssertExpressionEvaluationParser(
       start.setDiscriminator(discrim)
     } else {
       val message = getAssertFailureMessage(start)
-      val diag = new AssertionFailed(decl.schemaFileLocation, start, message)
-      start.setFailed(diag)
+      if (failureType == FailureType.ProcessingError) {
+        val diag = new AssertionFailed(decl.schemaFileLocation, start, message)
+        start.setFailed(diag)
+      } else
+        start.SDW("Assertion " + message)
     }
   }
 }
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 e693c67..8fd2ba4 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
@@ -76,6 +76,25 @@
       </xs:complexType>
     </xs:element>
 
+    <xs:element name="e3r"><!-- like e2, but assert uses a path to a
+        peer element and should just issue a warning -->
+      <xs:complexType>
+        <xs:sequence>
+          <xs:element name="v" type="xs:int"
+            dfdl:inputValueCalc="{ 42 }" />
+          <xs:element name="a" type="xs:string"
+            dfdl:inputValueCalc="{ 'ok' }">
+            <xs:annotation>
+              <xs:appinfo source="http://www.ogf.org/dfdl/">
+                <dfdl:assert failureType="recoverableError"><![CDATA[{ xs:int(../ex:v) ne 42 }]]></dfdl:assert>
+              </xs:appinfo>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+
     <xs:element name="e4" type="xs:int" dfdl:lengthKind="delimited">
       <xs:annotation>
         <xs:appinfo source="http://www.ogf.org/dfdl/">
@@ -104,6 +123,17 @@
         </xs:appinfo>
       </xs:annotation>
     </xs:element>
+    <xs:element name="e6r" type="xs:int" dfdl:lengthKind="pattern"
+      dfdl:lengthPattern="\d\d" dfdl:terminator=": ,">
+      <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/">
+          <dfdl:assert testKind="pattern" testPattern="\d\d" failureType="recoverableError"
+            message="Assertion failed for pattern '\d\d'" />
+          <dfdl:assert testKind="pattern" testPattern="\d\d:" failureType="recoverableError"
+            message="Assertion failed for pattern '\d\d:'" />
+        </xs:appinfo>
+      </xs:annotation>
+    </xs:element>
 
     <xs:element name="e7" type="xs:string" dfdl:lengthKind="delimited">
       <xs:annotation>
@@ -355,6 +385,23 @@
     </tdml:errors>
   </tdml:parserTestCase>
 
+  <tdml:parserTestCase name="assertFail2_recoverable" root="e3r"
+    model="s1" roundTrip="false"
+    description="Section 7 - negative test for assert expression - DFDL-7-043R">
+    <tdml:document />
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <e3r>
+          <v>42</v>
+          <a>ok</a>
+        </e3r>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:warnings>
+      <tdml:warning>Assertion</tdml:warning>
+    </tdml:warnings>
+  </tdml:parserTestCase>
+
   <!--
     Test name: assertFailShowsValue
     Schema: s1
@@ -603,6 +650,28 @@
   </tdml:parserTestCase>
 
   <!--
+    Test name: assertPatternFail2_recoverable
+    Schema: s1
+    Purpose: This document demonstrates the use of multiple pattern assertions
+    regarding a value in a document and should parse with a warning.
+  -->
+
+  <tdml:parserTestCase name="assertPatternFail2_recoverable"
+    root="e6r" model="s1" roundTrip="false"
+    description="Section 7 - assert pattern fail multiple assert - DFDL-7-053R">
+    <tdml:document>43,</tdml:document>
+    <tdml:warnings>
+      <tdml:warning>Assert</tdml:warning>
+      <tdml:warning>pattern</tdml:warning>
+    </tdml:warnings>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <e6r>43</e6r>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <!--
     Test name: assertPatternPass3
     Schema: s1
     Purpose: This document demonstrates the use of POSIX regex patterns in 
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section07/assertions/TestAssertions.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section07/assertions/TestAssertions.scala
index 0f7c18a..970d1db 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section07/assertions/TestAssertions.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section07/assertions/TestAssertions.scala
@@ -38,6 +38,7 @@ class TestAssertions {
   @Test def test_assertPass(): Unit = { runner.runOneTest("assertPass") }
   @Test def test_assertFail1(): Unit = { runner.runOneTest("assertFail1") }
   @Test def test_assertFail2(): Unit = { runner.runOneTest("assertFail2") }
+  @Test def test_assertFail2_recoverable(): Unit = { runner.runOneTest("assertFail2_recoverable") }
 
   // DAFFODIL-752
   //@Test def test_assertFailShowsValue() { runner.runOneTest("assertFailShowsValue") }
@@ -59,6 +60,7 @@ class TestAssertions {
   @Test def test_assertPatternPass2(): Unit = { runner.runOneTest("assertPatternPass2") }
   @Test def test_assertPatternPass3(): Unit = { runner.runOneTest("assertPatternPass3") }
   @Test def test_assertPatternFail2(): Unit = { runner.runOneTest("assertPatternFail2") }
+  @Test def test_assertPatternFail2_recoverable(): Unit = { runner.runOneTest("assertPatternFail2_recoverable") }
   @Test def test_assertPatternInitsTerms(): Unit = { runner.runOneTest("assertPatternInitsTerms") }
   @Test def test_assertOnSequence(): Unit = { runner.runOneTest("assertOnSequence") }