This is an automated email from the ASF dual-hosted git repository.
olabusayo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new 11fcc71de Add support for escalating SDWs to Errors
11fcc71de is described below
commit 11fcc71de7427aebabcef01fded6d3e66d9c87ec
Author: olabusayoT <[email protected]>
AuthorDate: Thu Sep 26 16:56:49 2024 -0400
Add support for escalating SDWs to Errors
- add tunable 'escalateWarningsToErrors' to control escalation
- add new SchemaDefinitionErrorFromWarning class that extends SDW so any
changes to SDW in the future will be automatically inherited
- make RSDW and RSDE extend SDW and SDEs respectively
- suppress RSDE when using debugger
- add test to demonstrate tunable
- add test to demonstrate tunable ignored when warning is suppressed
- add test to demonstrate runtime SDW can be escalated as well
DAFFODIL-2810
---
.../resources/org/apache/daffodil/xsd/dafext.xsd | 7 +++
.../runtime1/debugger/InteractiveDebugger.scala | 4 +-
.../org/apache/daffodil/runtime1/dpath/DPath.scala | 1 -
.../org/apache/daffodil/runtime1/dsom/SDE.scala | 63 ++++++++++++----------
.../runtime1/processors/DataProcessor.scala | 8 +--
.../runtime1/processors/ProcessorStateBases.scala | 14 +++--
.../runtime1/processors/SuspensionTracker.scala | 11 +++-
.../runtime1/processors/parsers/ParseErrors.scala | 12 ++---
.../runtime1/processors/parsers/Parser.scala | 1 -
.../runtime1/processors/unparsers/Unparser.scala | 1 -
.../SchemaDefinitionErrors.tdml | 63 ++++++++++++++++++++++
.../daffodil/section07/variables/variables.tdml | 21 ++++++++
.../schema_definition_errors/TestSDE.scala | 8 +++
.../section07/variables/TestVariables.scala | 3 ++
14 files changed, 169 insertions(+), 48 deletions(-)
diff --git
a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
index 3d89c5661..fffa275bb 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
@@ -185,6 +185,13 @@
</xs:documentation>
</xs:annotation>
</xs:element>
+ <xs:element name="escalateWarningsToErrors" type="xs:boolean"
default="false" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>
+ This tunable allows the escalation of Schema Definition Warnings
to Errors.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
<xs:element name="generatedNamespacePrefixStem" type="xs:string"
default="tns" minOccurs="0">
<xs:annotation>
<xs:documentation>
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
index e51462160..4e50ca10c 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
@@ -355,8 +355,8 @@ class InteractiveDebugger(
// Most errors are coming back here as RSDE because that's what they
get upconverted into.
// Most expression problems are considered SDE.
//
- case _: RuntimeSchemaDefinitionError => {
- state.setSuccess()
+ case e: RuntimeSchemaDefinitionError => {
+ state.suppressDiagnosticAndSucceed(e)
false
}
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DPath.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DPath.scala
index 3e6ffca54..3e5a8f6e6 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DPath.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DPath.scala
@@ -394,7 +394,6 @@ final class RuntimeExpressionDPath[T <: AnyRef](
if (value.asInstanceOf[String].length == 0) {
val e = new RuntimeSchemaDefinitionError(
ci.schemaFileLocation,
- state,
"Non-empty string required."
)
doSDE(e, state)
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
index 0108e5f8a..145bccb3a 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
@@ -24,7 +24,6 @@ import org.apache.daffodil.lib.exceptions.SchemaFileLocation
import org.apache.daffodil.lib.exceptions._
import org.apache.daffodil.lib.util.Maybe
import org.apache.daffodil.lib.util.Maybe._
-import org.apache.daffodil.runtime1.processors.CompileState
import org.apache.daffodil.runtime1.processors.ParseOrUnparseState
class SchemaDefinitionError(
@@ -49,6 +48,20 @@ class SchemaDefinitionError(
}
+class SchemaDefinitionErrorFromWarning(sdw: SchemaDefinitionWarning)
+ extends SchemaDefinitionWarning(
+ sdw.warnID,
+ sdw.schemaContext,
+ sdw.annotationContext,
+ sdw.kind,
+ sdw.args: _*
+ ) {
+
+ override def isError = true
+ override def modeName = super.modeName + " Warning Escalated"
+
+}
+
/**
* Specific class used for this specific error, because we need to pick this
off
* in the debugger for special handling.
@@ -58,60 +71,51 @@ class RelativePathPastRootError(schemaContext:
SchemaFileLocation, kind: String,
class RuntimeSchemaDefinitionError(
schemaContext: SchemaFileLocation,
- runtimeContext: ParseOrUnparseState,
causedBy: Throwable,
fmtString: String,
args: Any*
-) extends SchemaDefinitionDiagnosticBase(
- Maybe(schemaContext),
- (runtimeContext match { // TODO: this is ugly.
- case cs: CompileState => Nope
- case _ => Maybe(runtimeContext)
- }),
+) extends SchemaDefinitionError(
+ Option(schemaContext),
None,
- Maybe(causedBy),
- Maybe(fmtString),
+ fmtString,
args: _*
) {
- override def isError = true
- override def modeName = "Runtime Schema Definition"
-
def this(
schemaContext: SchemaFileLocation,
- runtimeContext: ParseOrUnparseState,
fmtString: String,
args: Any*
) =
- this(schemaContext, runtimeContext, null, fmtString, args: _*)
+ this(schemaContext, null, fmtString, args: _*)
+
+ override def modeName = "Runtime Schema Definition"
+
+ override def getCause: Throwable = causedBy
}
class RuntimeSchemaDefinitionWarning(
warnID: WarnID,
schemaContext: SchemaFileLocation,
- runtimeContext: ParseOrUnparseState,
kind: String,
args: Any*
-) extends SchemaDefinitionDiagnosticBase(
+) extends SchemaDefinitionWarning(
+ warnID,
Some(schemaContext),
- Some(runtimeContext),
None,
- Nope,
- Maybe(kind + s" (id: ${warnID})"),
+ kind,
args: _*
) {
- override def isError = false
override def modeName = "Runtime Schema Definition"
}
class SchemaDefinitionWarning(
- warnID: WarnID,
- schemaContext: Option[SchemaFileLocation],
- annotationContext: Option[SchemaFileLocation],
- kind: String,
- args: Any*
+ val warnID: WarnID,
+ val schemaContext: Option[SchemaFileLocation],
+ val annotationContext: Option[SchemaFileLocation],
+ val kind: String,
+ val args: Any*
) extends SchemaDefinitionDiagnosticBase(
schemaContext,
None,
@@ -269,7 +273,12 @@ trait ImplementsThrowsOrSavesSDE extends
ImplementsThrowsSDE with SavesErrorsAnd
fmt,
args: _*
)
- warn(sdw)
+ if (tunable.escalateWarningsToErrors) {
+ val sde = new SchemaDefinitionErrorFromWarning(sdw)
+ toss(sde)
+ } else {
+ warn(sdw)
+ }
}
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/DataProcessor.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/DataProcessor.scala
index 2d325b564..752f59cc9 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/DataProcessor.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/DataProcessor.scala
@@ -513,9 +513,9 @@ class DataProcessor(
state.dataInputStream.inputSource.setInvalid
state.setFailed(sde)
}
- case rsde: RuntimeSchemaDefinitionError => {
+ case sdefw: SchemaDefinitionErrorFromWarning => {
state.dataInputStream.inputSource.setInvalid
- state.setFailed(rsde)
+ state.setFailed(sdefw)
}
case e: ErrorAlreadyHandled => {
state.setFailed(e.th)
@@ -574,8 +574,8 @@ class DataProcessor(
unparserState.setFailed(sde)
unparserState.unparseResult
}
- case rsde: RuntimeSchemaDefinitionError => {
- unparserState.setFailed(rsde)
+ case sdefw: SchemaDefinitionErrorFromWarning => {
+ unparserState.setFailed(sdefw)
unparserState.unparseResult
}
case e: ErrorAlreadyHandled => {
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
index 8789b11e2..62550b54a 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
@@ -53,6 +53,7 @@ import org.apache.daffodil.runtime1.dpath.DState
import org.apache.daffodil.runtime1.dsom.DPathCompileInfo
import org.apache.daffodil.runtime1.dsom.RuntimeSchemaDefinitionError
import org.apache.daffodil.runtime1.dsom.RuntimeSchemaDefinitionWarning
+import org.apache.daffodil.runtime1.dsom.SchemaDefinitionErrorFromWarning
import org.apache.daffodil.runtime1.dsom.ValidationError
import org.apache.daffodil.runtime1.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.runtime1.infoset._
@@ -555,13 +556,13 @@ abstract class ParseOrUnparseState protected (
final def SDE(str: String, args: Any*) = {
val ctxt = getContext()
- val rsde = new RuntimeSchemaDefinitionError(ctxt.schemaFileLocation, this,
str, args: _*)
+ val rsde = new RuntimeSchemaDefinitionError(ctxt.schemaFileLocation, str,
args: _*)
ctxt.toss(rsde)
}
final def SDEButContinue(str: String, args: Any*) = {
val ctxt = getContext()
- val rsde = new RuntimeSchemaDefinitionError(ctxt.schemaFileLocation, this,
str, args: _*)
+ val rsde = new RuntimeSchemaDefinitionError(ctxt.schemaFileLocation, str,
args: _*)
diagnostics = rsde :: diagnostics
}
@@ -573,8 +574,13 @@ abstract class ParseOrUnparseState protected (
tssdw.contains(warnID) || tssdw.contains(WarnID.All)
if (!suppress) {
val rsdw =
- new RuntimeSchemaDefinitionWarning(warnID, ctxt.schemaFileLocation,
this, str, args: _*)
- diagnostics = rsdw :: diagnostics
+ new RuntimeSchemaDefinitionWarning(warnID, ctxt.schemaFileLocation,
str, args: _*)
+ if (tunable.escalateWarningsToErrors) {
+ val sde = new SchemaDefinitionErrorFromWarning(rsdw)
+ ctxt.toss(sde)
+ } else {
+ diagnostics = rsdw :: diagnostics
+ }
}
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/SuspensionTracker.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/SuspensionTracker.scala
index 64d579f58..58c25c781 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/SuspensionTracker.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/SuspensionTracker.scala
@@ -120,7 +120,14 @@ class SuspensionTracker(suspensionWaitYoung: Int,
suspensionWaitOld: Int) {
class SuspensionDeadlockException(suspExprs: Seq[Suspension])
extends RuntimeSchemaDefinitionError(
suspExprs(0).rd.schemaFileLocation,
- suspExprs(0).savedUstate,
"Expressions/Unparsers are circularly deadlocked (mutually defined):\n%s",
- suspExprs.groupBy { _.rd }.mapValues { _(0) }.values.mkString(" - ", "\n -
", "")
+ suspExprs
+ .groupBy {
+ _.rd
+ }
+ .mapValues {
+ _(0)
+ }
+ .values
+ .mkString(" - ", "\n - ", "")
)
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParseErrors.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParseErrors.scala
index b82077f09..0540839a4 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParseErrors.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ParseErrors.scala
@@ -140,12 +140,12 @@ trait DoSDEMixin {
throw sde
}
case other => {
- val sde = new RuntimeSchemaDefinitionError(
- state.getContext().schemaFileLocation,
- state,
- e,
- null
- )
+ val sde =
+ new RuntimeSchemaDefinitionError(
+ state.getContext().schemaFileLocation,
+ e,
+ e.getMessage
+ )
state.setFailed(sde)
state.toss(sde)
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
index 033f6214a..50ddd5026 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
@@ -342,7 +342,6 @@ case class NotParsableParser(context: ElementRuntimeData)
extends PrimParserNoDa
// create an SDE and toss it
val rsde = new RuntimeSchemaDefinitionError(
context.schemaFileLocation,
- state,
"This schema was compiled without parse support. Check the
parseUnparsePolicy tunable or dfdlx:parseUnparsePolicy property."
)
context.toss(rsde)
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/unparsers/Unparser.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/unparsers/Unparser.scala
index d7ce1581f..a982ba91d 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/unparsers/Unparser.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/unparsers/Unparser.scala
@@ -201,7 +201,6 @@ case class NotUnparsableUnparser(override val context:
ElementRuntimeData)
// create an SDE and toss it
val rsde = new RuntimeSchemaDefinitionError(
context.schemaFileLocation,
- state,
"This schema was compiled without unparse support. Check the
parseUnparsePolicy tunable or dfdlx:parseUnparsePolicy property."
)
context.toss(rsde)
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
index 0489d4e4b..4b8bfc4cf 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
@@ -308,4 +308,67 @@
</tdml:infoset>
</tdml:parserTestCase>
+
+ <tdml:defineSchema name="warning_escalated">
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited"
encoding="utf-8" representation="text"/>
+ <xs:element name="elem" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/dfdl-1.0/" />
+ </xs:annotation>
+ </xs:element>
+
+ <xs:element name="elem2" type="xs:string"
daf:suppressSchemaDefinitionWarnings="appinfoDFDLSourceWrong">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/dfdl-1.0/" />
+ </xs:annotation>
+ </xs:element>
+ </tdml:defineSchema>
+
+
+ <tdml:defineConfig name="escalateWarnings">
+ <daf:tunables>
+ <daf:escalateWarningsToErrors>true</daf:escalateWarningsToErrors>
+ </daf:tunables>
+ </tdml:defineConfig>
+
+ <!--
+ Test Name: schema_warning_escalated_to_error
+ Schema: warning_escalated
+ Root: elem
+ Purpose: This test demonstrates escalating warnings to errors
+ -->
+
+ <tdml:parserTestCase name="schema_warning_escalated_to_error" root="elem"
+ model="warning_escalated"
+ ignoreUnexpectedWarnings="false"
+ config="escalateWarnings">
+ <tdml:document><![CDATA[test]]></tdml:document>
+ <tdml:errors>
+ <tdml:error>Schema Definition Warning Escalated Error</tdml:error>
+ <tdml:error>appinfoDFDLSourceWrong</tdml:error>
+ <tdml:error>xs:appinfo source attribute</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+<!--
+ Test Name: schema_warning_escalated_to_error2
+ Schema: warning_escalated
+ Root: elem2
+ Purpose: This test demonstrates escalating warnings to errors doesn't
happen when
+ warning is suppressed
+ -->
+
+ <tdml:parserTestCase name="schema_warning_escalated_to_error2" root="elem2"
+ model="warning_escalated"
+ ignoreUnexpectedWarnings="false"
+ config="escalateWarnings">
+ <tdml:document><![CDATA[test]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <elem2>test</elem2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml
index c7f581357..d8efc39c9 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml
@@ -23,6 +23,7 @@
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ct="http://w3.ibm.com/xmlns/dfdl/ctInfoset"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:ex="http://example.com"
+ xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
defaultRoundTrip="true">
<tdml:defineSchema name="v">
@@ -2221,6 +2222,26 @@
</tdml:parserTestCase>
+ <tdml:defineConfig name="escalateWarnings">
+ <daf:tunables>
+ <daf:escalateWarningsToErrors>true</daf:escalateWarningsToErrors>
+ </daf:tunables>
+ </tdml:defineConfig>
+
+ <tdml:parserTestCase name="defineVariable_nonConstantExpression_setVar_err2"
root="root"
+ model="defineVariable_nonConstantExpression_setVar" description="escalate
warning"
+ config="escalateWarnings">
+ <tdml:document/>
+ <tdml:errors>
+ <tdml:error>Schema Definition Warning Escalated Error</tdml:error>
+ <tdml:error>variableSet</tdml:error>
+ <tdml:error>Cannot set variable</tdml:error>
+ <tdml:error>after reading the default value</tdml:error>
+ <tdml:error>State was: VariableRead</tdml:error>
+ </tdml:errors>
+ </tdml:parserTestCase>
+
+
<tdml:defineSchema name="variable_direction_schema">
<xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat"
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
index e215b43a2..09566defb 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
@@ -57,4 +57,12 @@ class TestSDE {
@Test def test_schema_warning_locally_suppressed(): Unit = {
runner.runOneTest("schema_warning_locally_suppressed")
}
+
+ @Test def test_schema_warning_escalated_to_error(): Unit = {
+ runner.runOneTest("schema_warning_escalated_to_error")
+ }
+
+ @Test def test_schema_warning_escalated_to_error2(): Unit = {
+ runner.runOneTest("schema_warning_escalated_to_error2")
+ }
}
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala
index 166e0aa48..cd14d1d03 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala
@@ -90,6 +90,9 @@ class TestVariables {
@Test def test_defineVariable_nonConstantExpression_setVar_err(): Unit = {
runner.runOneTest("defineVariable_nonConstantExpression_setVar_err")
}
+ @Test def test_defineVariable_nonConstantExpression_setVar_err2(): Unit = {
+ runner.runOneTest("defineVariable_nonConstantExpression_setVar_err2")
+ }
// DAFFODIL-2444 - This test triggers an unhandled NoSuchElement exception,
which if handled then runs into an Assert.invariant
// @Test def test_defineVariable_ref_infoset_err(): Unit = {
runner.runOneTest("defineVariable_ref_infoset_err") }