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