You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@daffodil.apache.org by GitBox <gi...@apache.org> on 2018/09/25 17:47:53 UTC

[GitHub] stevedlawrence closed pull request #117: Allow DFDL expressions in the message attribute of asserts/discrimina…

stevedlawrence closed pull request #117: Allow DFDL expressions in the message attribute of asserts/discrimina…
URL: https://github.com/apache/incubator-daffodil/pull/117
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 702a247ef..5c8ca5fff 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
@@ -107,12 +107,7 @@ abstract class DFDLAssertionBase(node: Node, decl: AnnotatedSchemaComponent)
     case None => TestKind.Expression
   }
 
-  private lazy val messageAttrib = getAttributeOption("message")
-
-  final lazy val message = messageAttrib match {
-    case None => "%s failed".format(testTxt)
-    case Some(s) => s
-  }
+  lazy val messageAttrib = getAttributeOption("message")
 
   final lazy val testTxt = {
     val rawTxt = (testKind, testBody, testAttrib, testPattern) match {
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 83a1f1653..3d1963034 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
@@ -29,8 +29,6 @@ import org.apache.daffodil.Implicits._
 import org.apache.daffodil.processors.parsers.NewVariableInstanceStartParser
 import org.apache.daffodil.processors.parsers.AssertExpressionEvaluationParser
 import org.apache.daffodil.dsom.ElementBase
-import org.apache.daffodil.processors.parsers.AssertPatternParser
-import org.apache.daffodil.processors.parsers.DiscriminatorPatternParser
 import org.apache.daffodil.processors.parsers.NewVariableInstanceEndParser
 import org.apache.daffodil.processors.parsers.SetVariableParser
 import org.apache.daffodil.processors.parsers.IVCParser
@@ -44,12 +42,13 @@ import org.apache.daffodil.dsom.ExpressionCompilers
 import org.apache.daffodil.dsom.DFDLSetVariable
 import org.apache.daffodil.dsom.ExpressionCompilers
 import org.apache.daffodil.dsom.DFDLNewVariableInstance
+import org.apache.daffodil.processors.parsers.AssertPatternParser
 
 abstract class AssertBase(decl: AnnotatedSchemaComponent,
   exprWithBraces: String,
   namespacesForNamespaceResolution: scala.xml.NamespaceBinding,
   scWherePropertyWasLocated: AnnotatedSchemaComponent,
-  msg: String,
+  msgOpt: Option[String],
   discrim: Boolean, // are we a discriminator or not.
   assertKindName: String)
   extends ExpressionEvaluatorBase(scWherePropertyWasLocated) {
@@ -57,10 +56,10 @@ abstract class AssertBase(decl: AnnotatedSchemaComponent,
   def this(
     decl: AnnotatedSchemaComponent,
     foundProp: Found,
-    msg: String,
+    msgOpt: Option[String],
     discrim: Boolean, // are we a discriminator or not.
     assertKindName: String) =
-    this(decl, foundProp.value, foundProp.location.namespaces, decl, msg, discrim, assertKindName)
+    this(decl, foundProp.value, foundProp.location.namespaces, decl, msgOpt, discrim, assertKindName)
 
   override val baseName = assertKindName
   override lazy val exprText = exprWithBraces
@@ -70,7 +69,16 @@ abstract class AssertBase(decl: AnnotatedSchemaComponent,
 
   override val forWhat = ForParser
 
-  lazy val parser: DaffodilParser = new AssertExpressionEvaluationParser(msg, discrim, decl.runtimeData, expr)
+  lazy val msgExpr ={
+    if (msgOpt.isDefined) {
+      ExpressionCompilers.String.compileExpression(qn,
+      NodeInfo.String, msgOpt.get, exprNamespaces, exprComponent.dpathCompileInfo, false, this)
+    } else {
+      new ConstantExpression[String](qn, NodeInfo.String, exprWithBraces + " failed")
+    }
+  }
+
+  lazy val parser: DaffodilParser = new AssertExpressionEvaluationParser(msgExpr, discrim, decl.runtimeData, expr)
 
   override def unparser: DaffodilUnparser = hasNoUnparser
 
@@ -80,7 +88,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.message, discrim, assertKindName)
+  assertKindName: String) extends AssertBase(decl, Found(stmt.testTxt, stmt, "test", false), stmt.messageAttrib, discrim, assertKindName)
 
 case class AssertBooleanPrim(
   decl: AnnotatedSchemaComponent,
@@ -102,7 +110,7 @@ case class InitiatedContent(
   extends AssertBase(decl,
     "{ fn:true() }", <xml xmlns:fn={ XMLUtils.XPATH_FUNCTION_NAMESPACE }/>.scope, decl,
     // always true. We're just an assertion that says an initiator was found.
-    "initiatedContent. This message should not be used.",
+    None,
     true,
     "initiatedContent") {
 }
@@ -163,7 +171,7 @@ abstract class ExpressionEvaluatorBase(e: AnnotatedSchemaComponent) extends Term
 
   def nodeKind: NodeInfo.Kind
 
-  private def qn = GlobalQName(Some("daf"), baseName, XMLUtils.dafintURI)
+  protected def qn = GlobalQName(Some("daf"), baseName, XMLUtils.dafintURI)
 
   lazy val expr = LV('expr) {
     ExpressionCompilers.AnyRef.compileExpression(qn,
@@ -254,38 +262,38 @@ case class InputValueCalc(e: ElementBase,
 //  }
 //}
 
-abstract class AssertPatternPrimBase(decl: Term, stmt: DFDLAssertionBase)
-  extends Terminal(decl, true) {
+abstract class AssertPatternPrimBase(decl: Term, stmt: DFDLAssertionBase, discrim: Boolean)
+  extends ExpressionEvaluatorBase(decl) {
+ 
+  override val baseName = if (discrim) "Discriminator" else "Assert"
+  override lazy val exprText = stmt.messageAttrib.get
+  override lazy val exprNamespaces = decl.namespaces
+  override lazy val exprComponent = decl
+
+  override def nodeKind = NodeInfo.String
 
-  lazy val eName = decl.diagnosticDebugName
   lazy val testPattern = {
     PatternChecker.checkPattern(stmt.testTxt, decl)
     stmt.testTxt
   }
 
+  lazy val msgExpr =
+    if (stmt.messageAttrib.isDefined) {
+      expr
+    } else {
+      new ConstantExpression[String](qn, NodeInfo.String, testPattern + " failed")
+    }
+
   override val forWhat = ForParser
 
-  def parser: DaffodilParser
+  lazy val parser: DaffodilParser = new AssertPatternParser(decl.termRuntimeData, discrim, testPattern, msgExpr)
 
   override def unparser: DaffodilUnparser = Assert.invariantFailed("should not request unparser for asserts/discriminators")
 }
 
 case class AssertPatternPrim(term: Term, stmt: DFDLAssert)
-  extends AssertPatternPrimBase(term, stmt) {
-
-  val kindString = "AssertPatternPrim"
+  extends AssertPatternPrimBase(term, stmt, false)
 
-  lazy val parser: DaffodilParser = {
-    new AssertPatternParser(eName, kindString, term.termRuntimeData, testPattern, stmt.message)
-  }
-
-}
-
-case class DiscriminatorPatternPrim(term: Term, stmt: DFDLAssertionBase)
-  extends AssertPatternPrimBase(term, stmt) {
-
-  val kindString = "DiscriminatorPatternPrim"
-
-  lazy val parser: DaffodilParser = new DiscriminatorPatternParser(testPattern, eName, kindString, term.termRuntimeData, stmt.message)
-}
 
+case class DiscriminatorPatternPrim(term: Term, stmt: DFDLDiscriminator)
+  extends AssertPatternPrimBase(term, stmt, true)
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
index 8de747863..2fca155f9 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
@@ -243,7 +243,7 @@ class TestDsomCompiler extends Logging {
     val Seq(b1, b2, _, b4) = st1.forElement(e1).annotationObjs // first one has 4 annotations
     assertEquals(AlignmentUnits.Bytes.toString.toLowerCase, b1.asInstanceOf[DFDLSimpleType].getPropertyForUnitTest("alignmentUnits")) // first has alignmentUnits
     assertEquals("tns:myVar1", b2.asInstanceOf[DFDLSetVariable].ref) // second is setVariable with a ref
-    assertEquals("yadda yadda yadda", b4.asInstanceOf[DFDLAssert].message) // fourth is an assert with yadda message
+    assertEquals("yadda yadda yadda", b4.asInstanceOf[DFDLAssert].messageAttrib.get) // fourth is an assert with yadda message
 
     // Explore define formats
     val Seq(df1, _) = sd.defineFormats // there are two
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 20c2f6299..f2d523eb6 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
@@ -17,83 +17,71 @@
 
 package org.apache.daffodil.processors.parsers
 
+import java.util.regex.Matcher
+
+import org.apache.daffodil.dsom.CompiledExpression
+import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
 import org.apache.daffodil.processors._
 import org.apache.daffodil.util.LogLevel
-import java.util.regex.Matcher
 import org.apache.daffodil.util.OnStack
 
-abstract class AssertPatternParserBase(
-  eName: String,
-  kindString: String,
+trait AssertMessageEvaluationMixin {
+  def messageExpr: CompiledExpression[AnyRef]
+  def discrim: Boolean
+
+  def getAssertFailureMessage(state: PState): String = {
+    val message =
+      try {
+        messageExpr.evaluate(state).asInstanceOf[String]
+      } catch {
+        // Note that we intentionally catch an SDE here. This effectively
+        // converts an SDE (which is usually considered fatal) to a ParseError
+        // (which isn't fatal). But section 7.3.1 of the DFDL specification
+        // states that both types of errors should be caught and replaced with
+        // a recoverable error and an implementation defined replacement
+        // message should be provided instead.
+        case e @ (_: ParseError | _: SchemaDefinitionDiagnosticBase) => {
+          val kindString = if (discrim) "Discriminator" else "Assertion"
+          kindString + " message expression evaluation failed: " + e.getMessage
+        }
+      }
+    message
+  }
+}
+
+class AssertPatternParser(
   override val context: TermRuntimeData,
+  override val discrim: Boolean,
   testPattern: String,
-  message: String)
-  extends PrimParser {
+  override val messageExpr: CompiledExpression[AnyRef])
+  extends PrimParser
+  with AssertMessageEvaluationMixin {
   override lazy val runtimeDependencies = Vector()
 
   override def toBriefXML(depthLimit: Int = -1) = {
+    val kindString = if (discrim) "Discriminator" else "Assertion"
     "<" + kindString + ">" + testPattern + "</" + kindString + ">"
   }
 
-  // private lazy val compiledPattern = ScalaPatternParser.compilePattern(testPattern, context)
-
   lazy val pattern = ("(?s)" + testPattern).r.pattern // imagine a really big expensive pattern to compile.
   object withMatcher extends OnStack[Matcher](pattern.matcher(""))
 
   final def parse(start: PState): Unit = {
     val bytePos = (start.bitPos >> 3).toInt
-    log(LogLevel.Debug, "%s - Starting at bit pos: %s", eName, start.bitPos)
-    log(LogLevel.Debug, "%s - Starting at byte pos: %s", eName, bytePos)
-
-    log(LogLevel.Debug, "%s - Looking for testPattern = %s", eName, testPattern)
 
     val dis = start.dataInputStream
     val mark = dis.markPos
     withMatcher { m =>
       val isMatch = dis.lookingAt(m, start)
-      afterParse(start, isMatch, m)
+      if (!isMatch) {
+        val message = getAssertFailureMessage(start)
+        val diag = new AssertionFailed(context.schemaFileLocation, start, message)
+        start.setFailed(diag)
+      } else if (discrim) {
+        // Only want to set the discriminator if there was a match.
+        start.setDiscriminator(true)
+      }
     }
     dis.resetPos(mark)
   }
-
-  protected def afterParse(start: PState, isMatch: Boolean, matcher: Matcher): Unit
-}
-
-class AssertPatternParser(
-  eName: String,
-  kindString: String,
-  rd: TermRuntimeData,
-  testPattern: String,
-  message: String)
-  extends AssertPatternParserBase(eName, kindString, rd, testPattern, message) {
-
-  def afterParse(start: PState, isMatch: Boolean, matcher: Matcher) {
-    if (isMatch) {
-      log(LogLevel.Debug, "Assert Pattern success for testPattern %s", testPattern)
-    } else {
-      log(LogLevel.Debug, "Assert Pattern fail for testPattern %s", testPattern)
-      val diag = new AssertionFailed(rd.schemaFileLocation, start, message)
-      start.setFailed(diag)
-    }
-  }
-}
-
-class DiscriminatorPatternParser(
-  testPattern: String,
-  eName: String,
-  kindString: String,
-  rd: TermRuntimeData,
-  message: String)
-  extends AssertPatternParserBase(eName, kindString, rd, testPattern, message) {
-
-  def afterParse(start: PState, isMatch: Boolean, matcher: Matcher) {
-    if (isMatch) {
-      // Only want to set the discriminator if it is true
-      // we do not want to modify it unless it's true
-      start.setDiscriminator(true)
-    } else {
-      val diag = new AssertionFailed(rd.schemaFileLocation, start, message)
-      start.setFailed(diag)
-    }
-  }
 }
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 9e22b08e3..3c49a47c4 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
@@ -20,6 +20,7 @@ package org.apache.daffodil.processors.parsers
 import org.apache.daffodil.dpath.ParserDiscriminatorNonBlocking
 import org.apache.daffodil.dpath.ParserNonBlocking
 import org.apache.daffodil.dsom.CompiledExpression
+import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.infoset.InfosetSimpleElement
 import org.apache.daffodil.processors.ElementRuntimeData
@@ -104,11 +105,12 @@ class NewVariableInstanceEndParser(
 }
 
 class AssertExpressionEvaluationParser(
-  msg: String,
-  discrim: Boolean, // are we a discriminator or not.
+  override val messageExpr: CompiledExpression[String],
+  override val discrim: Boolean, // are we a discriminator or not.
   decl: RuntimeData,
   expr: CompiledExpression[AnyRef])
-  extends ExpressionEvaluationParser(expr, decl) {
+  extends ExpressionEvaluationParser(expr, decl)
+  with AssertMessageEvaluationMixin {
 
   def parse(start: PState): Unit =
     // withLoggingLevel(LogLevel.Info)
@@ -140,8 +142,8 @@ class AssertExpressionEvaluationParser(
       if (testResult) {
         start.setDiscriminator(discrim)
       } else {
-        // The assertion failed. Prepare a failure message etc. in case backtracking ultimately fails from here.
-        val diag = new AssertionFailed(decl.schemaFileLocation, start, msg)
+        val message = getAssertFailureMessage(start)
+        val diag = new AssertionFailed(decl.schemaFileLocation, start, message)
         start.setFailed(diag)
       }
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
index ce0364819..25684afd4 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
@@ -39,7 +39,7 @@ class ParseError(rd: Maybe[SchemaFileLocation], val loc: Maybe[DataLocation], ca
 }
 
 class AssertionFailed(rd: SchemaFileLocation, state: PState, msg: String, details: Maybe[String] = Nope)
-  extends ParseError(One(rd), One(state.currentLocation), "Assertion failed. %s", msg) {
+  extends ParseError(One(rd), One(state.currentLocation), "Assertion failed: %s", msg) {
   override def componentText: String = {
 
     if (details.isDefined) "\nDetails: " + details.get
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
index 7f7d44470..9134ffbc9 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
@@ -4271,7 +4271,7 @@
 
     <tdml:document>1</tdml:document>
     <tdml:errors>
-     <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+     <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4353,7 +4353,7 @@
 
     <tdml:document>12</tdml:document>
     <tdml:errors>
-     <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+     <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4402,7 +4402,7 @@
 
     <tdml:document>123456</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4432,7 +4432,7 @@
 
     <tdml:document>0.123456</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4478,7 +4478,7 @@
 
     <tdml:document>9.12345</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4558,7 +4558,7 @@
 
     <tdml:document>-6</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4573,7 +4573,7 @@
 
     <tdml:document>6</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4712,7 +4712,7 @@
 
     <tdml:document>501</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4727,7 +4727,7 @@
 
     <tdml:document>1</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4759,7 +4759,7 @@
 
     <tdml:document>YELLOW</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4791,7 +4791,7 @@
 
     <tdml:document>MONDAY</tdml:document>
     <tdml:errors>
-      <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+      <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -4827,7 +4827,7 @@
 
     <tdml:document><![CDATA[2014-03-24T03:45:30]]></tdml:document>
     <tdml:errors>
-     <tdml:error>Assertion failed. Assertion failed for dfdl:checkConstraints(.)</tdml:error>
+     <tdml:error>Assertion failed: Assertion failed for dfdl:checkConstraints(.)</tdml:error>
     </tdml:errors>
   </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 07b461441..549370171 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
@@ -20,6 +20,7 @@
   xmlns:ex="http://example.com" xmlns="http://example.com"
   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:fn="http://www.w3.org/2005/xpath-functions"
   defaultRoundTrip="true">
 
   <tdml:defineSchema name="s1">
@@ -364,7 +365,8 @@
     description="Section 7 - negative test for assert expression - DFDL-7-043R">
     <tdml:document />
     <tdml:errors>
-      <tdml:error>Parse Error: Assertion failed.</tdml:error>
+      <tdml:error>Parse Error</tdml:error>
+      <tdml:error>Assertion failed</tdml:error>
       <tdml:error>Parsed value was:</tdml:error>
       <tdml:error>43</tdml:error>
     </tdml:errors>
@@ -379,7 +381,8 @@
     model="s1" description="Section 7 - negative test for assert expression - DFDL-7-043R">
     <tdml:document><![CDATA[1:2;3,4.]]></tdml:document>
     <tdml:errors>
-      <tdml:error>Parse Error: Assertion failed.</tdml:error>
+      <tdml:error>Parse Error</tdml:error>
+      <tdml:error>Assertion failed</tdml:error>
       <tdml:error>Parsed value was:</tdml:error>
       <tdml:error><![CDATA[<seq_02><e1>1</e1><e2>2</e2><e3>3</e3><e4>4</e4></seq_02>]]></tdml:error>
     </tdml:errors>
@@ -394,7 +397,8 @@
     model="s1" description="Section 7 - negative test for assert expression - DFDL-7-043R">
     <tdml:document><![CDATA[1:2;3;4.]]></tdml:document>
     <tdml:errors>
-      <tdml:error>Parse Error: Assertion failed.</tdml:error>
+      <tdml:error>Parse Error</tdml:error>
+      <tdml:error>Assertion failed</tdml:error>
       <tdml:error>Assertion failed for pattern '12345'</tdml:error>
       <!-- <tdml:error>\d:\d;\d,\d.</tdml:error> -->
     </tdml:errors>
@@ -1239,5 +1243,52 @@
   </tdml:errors>
  </tdml:parserTestCase>
  
+ 
+ <tdml:defineSchema name="assertsWithMessageExpression">
+  <dfdl:format
+   ref="ex:GeneralFormat"
+   lengthKind="delimited" />
+   
+  <xs:element name="e1">
+   <xs:complexType>
+    <xs:sequence>
+     <xs:element name="e2" type="xs:string">
+      <xs:annotation>
+       <xs:appinfo source="http://www.ogf.org/dfdl/">
+        <dfdl:assert message="{ fn:concat('Value was not 5 but was ', xs:int(.)) }">{ . eq '5' }</dfdl:assert>
+       </xs:appinfo>
+      </xs:annotation>
+     </xs:element>
+    </xs:sequence>
+   </xs:complexType>
+  </xs:element>
+
+ </tdml:defineSchema>
+ 
+ <tdml:parserTestCase
+  name="test_assertWithMessageExpression_01"
+  root="e1"
+  model="assertsWithMessageExpression"
+ >
+  <tdml:document>4</tdml:document>
+  <tdml:errors>
+   <tdml:error>Assertion failed</tdml:error>
+   <tdml:error>Value was not 5 but was 4</tdml:error>
+  </tdml:errors>
+ </tdml:parserTestCase>
+ 
+ <tdml:parserTestCase
+  name="test_assertWithMessageExpression_02"
+  root="e1"
+  model="assertsWithMessageExpression"
+ >
+  <tdml:document>not a number</tdml:document>
+  <tdml:errors>
+   <tdml:error>Assertion failed</tdml:error>
+   <tdml:error>Assertion message expression evaluation failed</tdml:error>
+   <tdml:error>Cannot convert</tdml:error>
+   <tdml:error>not a number</tdml:error>
+  </tdml:errors>
+ </tdml:parserTestCase>
 
 </tdml:testSuite>
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 2cfc74559..d852f76e7 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
@@ -93,4 +93,8 @@ class TestAssertions {
   // JIRA DFDL-1672
   @Test def testNumberFormatErrorInExprRuntime() { runner.runOneTest("testNumberFormatErrorInExprRuntime") }
   @Test def testNumberFormatErrorInExprCompileTime() { runner.runOneTest("testNumberFormatErrorInExprCompileTime") }
+
+
+  @Test def test_assertWithMessageExpression_01() { runner.runOneTest("test_assertWithMessageExpression_01") }
+  @Test def test_assertWithMessageExpression_02() { runner.runOneTest("test_assertWithMessageExpression_02") }
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services