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 2019/03/08 13:28:12 UTC
[incubator-daffodil] branch master updated: Ensure
content/valueLength expressions are not considered constants
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 a6dc540 Ensure content/valueLength expressions are not considered constants
a6dc540 is described below
commit a6dc540fa13a45e119bbfda77ea4e514ccd1a88f
Author: Steve Lawrence <sl...@apache.org>
AuthorDate: Tue Mar 5 13:42:47 2019 -0500
Ensure content/valueLength expressions are not considered constants
Although it should result in an error, calling contentLength() or
valueLength() on an immediate parent does not always trigger the normal
code paths that determine that an expression is not a constant. This can
lead to an unknown state and ultimately a NullPointerException. By
overriding the contentLength and valueLength methods in the FakeDINode,
we ensure that if this special case occurs we correctly determine this
expression is not a constant.
Also removes debugging information from the error message that results
when this expression is eventually evaluated.
DAFFODIL-2078
---
.../org/apache/daffodil/infoset/InfosetImpl.scala | 15 ++---
.../section23/dfdl_functions/Functions.tdml | 70 ++++++++++++++++++++++
.../dfdl_expressions/TestDFDLExpressions.scala | 2 +
3 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
index 1aaabeb..df45c27 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
@@ -189,13 +189,8 @@ case class InfosetNoParentException(val diElement: DIElement, val erd: ElementRu
with InfosetException
sealed abstract class InfosetLengthUnknownException(lengthState: LengthState, kind: String, val diElement: DIElement, val erd: ElementRuntimeData)
- extends ProcessingError("Expression Evaluation", Nope, Nope, "%s length unknown for element %s.", kind, erd.namedQName)
- with InfosetException with RetryableException {
-
- lazy val blockingDOS = lengthState.diagnoseNoLength()
-
- override def componentText = "BlockingDOS(" + blockingDOS + ")"
-}
+ extends ProcessingError("Expression Evaluation", Nope, Nope, "%s length unknown for element '%s'.", kind, erd.namedQName)
+ with InfosetException with RetryableException
case class InfosetContentLengthUnknownException(lengthState: LengthState, override val diElement: DIElement, override val erd: ElementRuntimeData)
extends InfosetLengthUnknownException(lengthState, "Content", diElement, erd)
@@ -229,6 +224,8 @@ final class FakeDINode extends DISimple(null) {
override def children = die
+ override def contentLength: ContentLengthState = die
+ override def valueLength: ValueLengthState = die
}
/**
@@ -636,7 +633,7 @@ sealed trait DIElementSharedMembersMixin {
else _contentLength.clear()
}
- final def contentLength = {
+ def contentLength = {
if (_contentLength eq null) {
_contentLength = allocContentLength
}
@@ -648,7 +645,7 @@ sealed trait DIElementSharedMembersMixin {
else _valueLength.clear()
}
- final def valueLength = {
+ def valueLength = {
if (_valueLength eq null) {
_valueLength = allocValueLength
}
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
index f74396e..1033064 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
@@ -446,6 +446,21 @@
</xs:complexType>
</xs:element>
+ <xs:element name="valueLength13">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="x" dfdl:lengthKind="explicit" dfdl:length="{ 1 }">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="y" type="xs:int" maxOccurs="2" dfdl:occursCountKind="expression"
+ dfdl:occursCount='{ if(dfdl:valueLength(.., "bits") eq 0) then 1 else 2 }' />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
<xs:element name="contentLength">
<xs:complexType>
<xs:sequence dfdl:separator=",">
@@ -466,6 +481,21 @@
</xs:sequence>
</xs:complexType>
</xs:element>
+
+ <xs:element name="contentLength3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="x" dfdl:lengthKind="explicit" dfdl:length="{ 1 }">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="y" type="xs:int" maxOccurs="2" dfdl:occursCountKind="expression"
+ dfdl:occursCount='{ if (dfdl:contentLength(.., "bits") eq 0) then 1 else 2 }' />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
<xs:element name="e_concat">
<xs:complexType>
@@ -3850,6 +3880,26 @@
</tdml:parserTestCase>
<!--
+ Test Name: valueLength_6
+ Schema: Functions.dfdl.xsd
+ Root: valueLength13
+ Purpose: This test demonstrates the valueLength function throws a SDE when
+-->
+
+ <tdml:parserTestCase name="valueLength_6" root="valueLength13"
+ model="Functions.dfdl.xsd" description="Section 23 ">
+
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[test]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Runtime Schema Definition Error</tdml:error>
+ <tdml:error>Value length unknown</tdml:error>
+ <tdml:error>{http://example.com}x</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+<!--
Test Name: valueLength_unparse_0
Schema: Functions.dfdl.xsd
Root: valueLength5
@@ -4026,6 +4076,26 @@
</tdml:parserTestCase>
<!--
+ Test Name: contentLength_2
+ Schema: Functions.dfdl.xsd
+ Root: contentLength3
+ Purpose: This test demonstrates the contentLength function (formerly representationLength).
+-->
+
+ <tdml:parserTestCase name="contentLength_2" root="contentLength3"
+ model="Functions.dfdl.xsd" description="Section 23 " roundTrip="false">
+
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[////test////]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Runtime Schema Definition Error</tdml:error>
+ <tdml:error>Content length unknown</tdml:error>
+ <tdml:error>{http://example.com}x</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+<!--
Test Name: valueContentLength1
Schema: Functions.dfdl.xsd
Root: valueContentLength1
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
index a89c4e4..a2c0364 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
@@ -932,6 +932,7 @@ class TestDFDLExpressions {
@Test def test_valueLength_3() { runner2.runOneTest("valueLength_3") }
@Test def test_valueLength_4() { runner2.runOneTest("valueLength_4") }
@Test def test_valueLength_5() { runner2.runOneTest("valueLength_5") }
+ @Test def test_valueLength_6() { runner2.runOneTest("valueLength_6") }
@Test def test_valueLength_sde() { runner2.runOneTest("valueLength_sde") }
@Test def test_valueLength_unparse_0() { runner2.runOneTest("valueLength_unparse_0") }
// DFDL-1516:dfdl:contentLength & dfdl:valueLength specifying lengthUnits 'characters' and variable-width encodings
@@ -942,6 +943,7 @@ class TestDFDLExpressions {
@Test def test_contentLength_0() { runner2.runOneTest("contentLength_0") }
@Test def test_contentLength_1() { runner2.runOneTest("contentLength_1") }
+ @Test def test_contentLength_2() { runner2.runOneTest("contentLength_2") }
@Test def test_valueContentLength1() { runner2.runOneTest("valueContentLength1") }
@Test def test_valueContentLength2() { runner2.runOneTest("valueContentLength2") }