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") }