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 0b3faf187 Fix choice branch selection per errata 5.60
0b3faf187 is described below
commit 0b3faf1870fbd022c8ebfc4d8b66eca862310e74
Author: olabusayoT <[email protected]>
AuthorDate: Mon Oct 20 12:49:20 2025 -0400
Fix choice branch selection per errata 5.60
- Update unparser choice branch selection to match errata 5.60: prefer the
first branch fully defaultable/OVC/optional instead of the first empty one.
- Make required arrays return `true` for `isRequiredStreamingUnparserEvent`
for consistency with defaulting behavior.
- Add subset error when arrays with required elements have default values.
- Rename `canUnparseIfHidden` for clarity—it isn’t limited to hidden
elements.
- Mark required but empty arrays as `PossiblyZeroArrayOccurrencesDetector`
to suppress separators.
- Simplify `optDefaultBranch` logic: `canUnparseIfNoEvents` subsumes
`isOpen`/`isEmpty`.
- Remove `MultipleChoiceBranches` warning—multiple valid defaults are
allowed.
- In `pneResolver`, handle arrays using
`possibleSelfPlusNextLexicalSiblingStreamingUnparserElements`.
- For complex elements, check both element and member requiredness for
unparse eligibility.
- Update CLIDebugger test schema to cover suspension cases.
- Disallow hidden IVCs except in unselected choice branches; require IVCs
in the infoset.
- Remove support for hidden IVCs in sequences and add tests confirming
hidden IVCs aren’t selected by `optDefaultBranch`.
Discussion
Hidden IVCs are elements computed during parse but never represented in the
infoset or needed during unparse. They are not meaningful for unparsing
and
should not be supported. So we remove !e.isRepresented from the
ElementBase
case. Unparsing should instead require IVC elements (minOccurs =
maxOccurs = 1)
to appear in the infoset, even though their values are ignored at unparse
time. This behavior is more intuitive and is in line with IVC being
MustExist in
unparserInfosetElementDefaultingBehavior and preserves expected branch
selection semantics for
choice/dispatch constructs. Hidden IVCs remain permissible only within
choice branches that
are not selected during unparse. Note that we will never select a default
branch with a Hidden
IVC because it will always be canUnparseIfNoEvents=false
Deprecation/Compatibility
Per DFDL errata 5.60, the first branch that can be unparsed entirely
without any infoset events (i.e. made up of elements that are
dfdl:outputValueCalc, option branches, zero length arrays, or defaultable
elements) in a choice is selected, rather than prioritizing the first empty
branch. Also, required arrays are no longer treated as optional and hidden IVCs
are only permissible in choices.
DAFFODIL-2324
---
.../org/apache/daffodil/cli/input/input20.txt.xml | 21 ++
.../apache/daffodil/core/dsom/ElementBase.scala | 9 +
.../apache/daffodil/core/dsom/ParticleMixin.scala | 11 +-
.../scala/org/apache/daffodil/core/dsom/Term.scala | 19 +-
.../core/grammar/primitives/SequenceChild.scala | 6 +-
.../grammar/primitives/SequenceCombinator.scala | 8 +-
.../core/runtime1/ChoiceTermRuntime1Mixin.scala | 35 +-
.../daffodil/core/runtime1/TermRuntime1Mixin.scala | 18 +-
.../TestStreamingUnparserCompilerAttributes.scala | 22 +-
.../apache/daffodil/cliTest/TestCLIDebugger.scala | 17 +-
.../daffodil/section07/variables/variables.tdml | 6 -
.../section14/sequence_groups/SequenceGroup.tdml | 14 +-
.../section15/choice_groups/ChoiceBranches.tdml | 389 +++++++++++++++++++++
.../choice_groups/ChoicesInHiddenContexts.dfdl.xsd | 25 ++
.../section15/choice_groups/HiddenChoices.tdml | 26 ++
.../section15/choice_groups/choice-unparse2.tdml | 2 +-
...iddenChoices.scala => TestChoiceBranches.scala} | 44 +--
.../choice_groups/TestHiddenChoices.scala | 2 +
18 files changed, 575 insertions(+), 99 deletions(-)
diff --git
a/daffodil-cli/src/test/resources/org/apache/daffodil/cli/input/input20.txt.xml
b/daffodil-cli/src/test/resources/org/apache/daffodil/cli/input/input20.txt.xml
new file mode 100644
index 000000000..5a1bc7f3c
--- /dev/null
+++
b/daffodil-cli/src/test/resources/org/apache/daffodil/cli/input/input20.txt.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ex:c_2 xmlns:ex="http://example.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <d xsi:type="xsd:int">42</d>
+</ex:c_2>
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala
index 09e033114..29bf03b31 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala
@@ -436,6 +436,9 @@ trait ElementBase
else MustExist
}
+ /**
+ * is OVC, optional, or an array with no required elements
+ */
lazy val canBeAbsentFromUnparseInfoset: Boolean = {
import UnparserInfo.*
unparserInfosetElementDefaultingBehavior !=:= MustExist
@@ -1291,6 +1294,12 @@ trait ElementBase
case _ => // ok
}
}
+ if (isArrayWithAtLeastOneRequiredArrayElement && hasDefaultValue) {
+ subsetError(
+ "XSD default='%s' is not implemented.",
+ defaultValueAsString
+ )
+ }
Assert.invariant(hasDefaultValue)
!isOptional &&
(isScalar ||
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ParticleMixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ParticleMixin.scala
index 96a34210a..bac91f07a 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ParticleMixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ParticleMixin.scala
@@ -81,7 +81,7 @@ trait RequiredOptionalMixin { self: ElementBase =>
* This includes elements that have no representation in the
* data stream. That is, an element with dfdl:inputValueCalc will be
isRequiredStreamingUnparserEvent true.
*
- * All arrays/optionals are treated as not required because we tolerate
invalidity of the
+ * All optionals are treated as not required because we tolerate invalidity
of the
* data here.
*
* OutputValueCalc elements are treated as optional. If present they are
supposed to get their
@@ -91,8 +91,13 @@ trait RequiredOptionalMixin { self: ElementBase =>
val res = {
if (isScalar) !this.isOutputValueCalc
else if (isOptional) false
- // Treat all arrays as non-required so that we can tolerate invalid
- // infosets where the number of events is fewer than the array minimum
occurrences.
+ // Arrays with minOccurs = 0 are not required to be in the infoset.
+ // Arrays that have at least one required element (i.e. minOccurs > 0)
are required to
+ // have unparser events. Otherwise we could unparse malformed data. The
exception to this
+ // is required arrays that are defaultable (which is not yet
implemented, so will never be true
+ // at this point but will produce a subset error so people don't depend
on broken/nyi behavior).
+ else if (isArray && isDefaultable) false
+ else if (isArrayWithAtLeastOneRequiredArrayElement) true
else if (isArray) false
else if (minOccurs == 0 && maxOccurs == 0) false
else {
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
index 4641f9fba..7558483d5 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Term.scala
@@ -511,23 +511,32 @@ trait Term
* Note that this currently only requires OVC and Optionality since defaults
* aren't fully implemented everywhere. This function may need to change when
* defaults are fully implemented.
+ *
+ * Note that even though inputValueCalc elements are essentially ignored for
unparsing,
+ * they are still considered required elements
(canBeAbssentFromUnparseInfoset returns false)
+ * and so cannot be unparsed if they do not appear in the infoset (e.g.
inside a hidden group ref).
+ * This does not necessarily exclude inputValueCalc elements from appearing
in hidden groups,
+ * but they must be in the non-default branch of a choice, or a child to an
optional
+ * complex type or non-required array.
*/
- lazy val canUnparseIfHidden: Boolean = {
+ lazy val canUnparseIfNoEvents: Boolean = {
val res = this match {
case s: SequenceTermBase => {
s.groupMembers.forall { member =>
- val res = member.canUnparseIfHidden
+ val res = member.canUnparseIfNoEvents
res
}
}
case c: ChoiceTermBase => {
- c.groupMembers.exists { _.canUnparseIfHidden }
+ c.groupMembers.exists { _.canUnparseIfNoEvents }
}
case e: ElementBase if e.isComplexType => {
- e.complexType.group.canUnparseIfHidden
+ // it's either not required in the infoset, or it is and we can
unparse
+ // all of its children with no events
+ e.canBeAbsentFromUnparseInfoset ||
e.complexType.group.canUnparseIfNoEvents
}
case e: ElementBase => {
- !e.isRepresented || e.canBeAbsentFromUnparseInfoset
+ e.canBeAbsentFromUnparseInfoset
}
}
res
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala
index de489f22e..725eff536 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala
@@ -351,7 +351,11 @@ abstract class SequenceChild(protected val sq:
SequenceTermBase, child: Term, gr
if (!e.isRepresented)
NotRepresentedZeroLengthDetector
- else if (e.isArray && !e.isRequiredStreamingUnparserEvent)
+ else if (
+ e.isArray
+ && (!e.isRequiredStreamingUnparserEvent ||
e.isEmptyAnObservableConcept)
+ )
+ // optional or empty array
PossiblyZeroArrayOccurrencesDetector
else {
Assert.invariant(e.isRepresented)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
index d38190281..aab310aa2 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
@@ -94,10 +94,10 @@ class OrderedSequence(sq: SequenceTermBase,
sequenceChildrenArg: Seq[SequenceChi
* This is a requirement for all descendants of a hidden sequence, so
we
* SDE if all descendants are not fully defaultable, optional or OVC.
*/
- val nonUnparseableIfHidden =
sq.groupMembers.filter(!_.canUnparseIfHidden)
+ val nonUnparseableIfHidden =
sq.groupMembers.filter(!_.canUnparseIfNoEvents)
if (nonUnparseableIfHidden.nonEmpty) {
SDE(
- "Element(s) of hidden group must define dfdl:outputValueCalc,
dfdl:inputValueCalc, be defaultable or be optional:\n%s",
+ "Element(s) of hidden group must define dfdl:outputValueCalc, be
defaultable or be optional:\n%s",
nonUnparseableIfHidden.mkString("\n")
)
}
@@ -186,10 +186,10 @@ class UnorderedSequence(
* This is a requirement for all descendants of a hidden sequence, so
we
* SDE if all descendants are not fully defaultable, optional or OVC.
*/
- val nonUnparseableIfHidden =
sq.groupMembers.filter(!_.canUnparseIfHidden)
+ val nonUnparseableIfHidden =
sq.groupMembers.filter(!_.canUnparseIfNoEvents)
if (nonUnparseableIfHidden.nonEmpty) {
SDE(
- "Element(s) of hidden group must define dfdl:outputValueCalc,
dfdl:inputValueCalc, be defaultable or be optional:\n%s",
+ "Element(s) of hidden group must define dfdl:outputValueCalc, be
defaultable or be optional:\n%s",
nonUnparseableIfHidden.mkString("\n")
)
}
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ChoiceTermRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ChoiceTermRuntime1Mixin.scala
index 3c426a8e7..9aa556a86 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ChoiceTermRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ChoiceTermRuntime1Mixin.scala
@@ -80,36 +80,13 @@ trait ChoiceTermRuntime1Mixin { self: ChoiceTermBase =>
// element event to be in the infoset (for round-tripping from parse).
It's value will
// get recomputed, but it can appear with a stale value (left-over from
parse)
// in the arriving infoset for unparse.
- //
- val optDefaultBranch = {
- val optEmpty: Option[Term] = {
- val emptyBranches = groupMembers.filter { gm =>
- val ies = gm.identifyingEventsForChoiceBranch
- ies.pnes.isEmpty // empty event list makes it the default, not
simply isOpen
- }
- if (emptyBranches.length > 1)
- SDW(
- WarnID.MultipleChoiceBranches,
- "Multiple choice branches with no required elements detected and
the infoset does not specify a branch, selecting the first branch for unparsing"
- )
- emptyBranches.headOption
- }
- val optOpen: Option[Term] =
- optEmpty.orElse {
- groupMembers.find { gm =>
- val ies = gm.identifyingEventsForChoiceBranch
- ies.isOpen // first open one is used if there is no branch that
has empty event list. (test ptg_1u)
- }
- }
- val optDefault: Option[Term] =
- optOpen.orElse {
- groupMembers.find {
- _.canUnparseIfHidden
- } // optional, defaultable, OVC, or IVC
- }
- optDefault
+ // We default to the first branch can be unparsed entirely without any
infoset events
+ // (i.e. made up of elements that are dfdl:outputValueCalc,
+ // optional branches, zero length arrays, or defaultable elements)
+ val optDefaultBranch = groupMembers.find {
+ case gm if gm.canUnparseIfNoEvents => true
+ case _ => false
}
-
// converts a sequence of tuples into a multi-map
val eventMap =
eventTuples
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/TermRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/TermRuntime1Mixin.scala
index 6f2c206c5..ea8d62a3f 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/TermRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/TermRuntime1Mixin.scala
@@ -126,7 +126,7 @@ trait TermRuntime1Mixin { self: Term =>
//
// An array may be required in the infoset, but the array
// may also be terminated by finding the next element after the array,
- // so we get closed only if required and not an array.
+ // so we get closed only if required.
//
case eb: ElementBase if (eb.isRequiredStreamingUnparserEvent) =>
Closed(Seq(PNE(eb, true)))
@@ -234,6 +234,9 @@ trait TermRuntime1Mixin { self: Term =>
case stb: SequenceTermBase => {
followingLexicalSiblingStreamingUnparserElements
}
+ // if it's an array, we want itself and its following lexical siblings
+ case e: ElementBase if isArray =>
+ possibleSelfPlusNextLexicalSiblingStreamingUnparserElements
case _: ElementBase | _: ChoiceTermBase => {
// If this element is closed, we only want it and not it's siblings
if (possibleThisTermNextStreamingUnparserElements.isClosed)
@@ -280,7 +283,7 @@ trait TermRuntime1Mixin { self: Term =>
//
// An array may be required in the infoset, but the array
// may also be terminated by finding the next element after the array,
- // so we get closed only if required and not an array.
+ // so we get closed only if required.
//
case eb: ElementBase if (eb.isRequiredStreamingUnparserEvent) =>
Closed(Seq(PNE(eb, true)))
@@ -355,6 +358,10 @@ trait TermRuntime1Mixin { self: Term =>
case (Closed(pnes1), Open(List())) => {
thisItself // case of Closed(...) followed by empty list, which is
default for nothing
}
+ case (Closed(pnes1), Closed(pnes2)) if isArray => {
+ // if it's an array, it should return itself, and its following
lexical siblings
+ Closed((pnes1 ++ pnes2).distinct)
+ }
case (Closed(pnes1), Closed(pnes2)) => {
thisItself // When everything is closed, we only want thisItself
and not the entire list of Closed possibilities
}
@@ -451,6 +458,13 @@ trait TermRuntime1Mixin { self: Term =>
case _ => {
val trd = context.termRuntimeData
val (sibs, isRequiredStreamingUnparserEvent) = possibles match {
+ // if it's a required array, we have to account for the fact that
the array
+ // can be terminated by finding the next element after the array. In
that case,
+ // we wouldn't want isRequiredStreamingUnparserEvent to be true,
because that would
+ // cause the resolver to return an UnexpectedElementError when the
next element is found,
+ // and it wouldn't backtrack like we'd expect it to, so for required
arrays,
+ // we override the isRequiredStreamingUnparserEvent to be false.
+ case PossibleNextElements.Closed(sibs) if isArray => (sibs, false)
case PossibleNextElements.Closed(sibs) => (sibs, true)
case PossibleNextElements.Open(sibs) => (sibs, false)
case PossibleNextElements.DoNotUse =>
diff --git
a/daffodil-core/src/test/scala/org/apache/daffodil/core/runtime1/TestStreamingUnparserCompilerAttributes.scala
b/daffodil-core/src/test/scala/org/apache/daffodil/core/runtime1/TestStreamingUnparserCompilerAttributes.scala
index 14b06057c..12c323528 100644
---
a/daffodil-core/src/test/scala/org/apache/daffodil/core/runtime1/TestStreamingUnparserCompilerAttributes.scala
+++
b/daffodil-core/src/test/scala/org/apache/daffodil/core/runtime1/TestStreamingUnparserCompilerAttributes.scala
@@ -179,11 +179,11 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(a) match {
- case Closed(Seq(PNE(`a`, false), PNE(`b`, false), PNE(`c`, true))) =>
+ case Closed(Seq(PNE(`a`, false), PNE(`b`, true), PNE(`c`, true))) =>
case _ => fail()
}
poss(b) match {
- case Closed(Seq(PNE(`b`, false), PNE(`c`, true))) =>
+ case Closed(Seq(PNE(`b`, true), PNE(`c`, true))) =>
case _ => fail()
}
poss(c) match {
@@ -220,11 +220,11 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail(); null
}
poss(a) match {
- case Closed(Seq(PNE(`a`, false), PNE(`b`, false), PNE(`c`, false),
PNE(`d`, false))) =>
+ case Closed(Seq(PNE(`a`, false), PNE(`b`, true), PNE(`c`, false),
PNE(`d`, false))) =>
case _ => fail()
}
poss(b) match {
- case Closed(Seq(PNE(`b`, false), PNE(`c`, false), PNE(`d`, false))) =>
+ case Closed(Seq(PNE(`b`, true), PNE(`c`, false), PNE(`d`, false))) =>
case _ => fail()
}
poss(gr) match {
@@ -282,11 +282,11 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(a) match {
- case Open(Seq(PNE(`a`, false), PNE(`b`, false))) =>
+ case Closed(Seq(PNE(`a`, false), PNE(`b`, true))) =>
case _ => fail()
}
poss(b) match {
- case Open(Seq(PNE(`b`, false))) =>
+ case Closed(Seq(PNE(`b`, true))) =>
case _ => fail()
}
poss(cgr) match {
@@ -437,7 +437,7 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(rg) match {
- case Open(Seq(PNE(`c`, false), PNE(`d`, false), PNE(`e`, false))) =>
+ case Closed(Seq(PNE(`c`, false), PNE(`d`, false), PNE(`e`, false))) =>
case _ => fail()
}
poss(c) match {
@@ -588,7 +588,7 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(cgr) match {
- case Open(Seq(PNE(`c`, false), PNE(`d`, false), PNE(`e`, false))) =>
+ case Closed(Seq(PNE(`c`, false), PNE(`d`, false), PNE(`e`, false))) =>
case _ => fail()
}
poss(gr) match {
@@ -627,7 +627,7 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(b) match {
- case Closed(Seq(PNE(`b`, false), PNE(`c`, true))) =>
+ case Closed(Seq(PNE(`b`, true), PNE(`c`, true))) =>
case _ => fail()
}
poss(c) match {
@@ -685,7 +685,7 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
val (vg_inty, vg_stringy) = poss(g2c3) match {
- case Closed(Seq(PNE(`g2c3`, false), PNE(vg_inty, false), PNE(vg_stringy,
false))) =>
+ case Closed(Seq(PNE(`g2c3`, true), PNE(vg_inty, false), PNE(vg_stringy,
false))) =>
(vg_inty, vg_stringy)
case _ => fail(); null
}
@@ -1047,7 +1047,7 @@ class TestStreamingUnparserCompilerAttributes {
case _ => fail()
}
poss(pg) match {
- case Open(Seq(PNE(`b`, false))) =>
+ case Closed(Seq(PNE(`b`, true))) =>
case _ => fail()
}
poss(ag) match {
diff --git
a/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLIDebugger.scala
b/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLIDebugger.scala
index 3101a32e6..68c64e1b2 100644
---
a/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLIDebugger.scala
+++
b/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLIDebugger.scala
@@ -1178,13 +1178,13 @@ class TestCLIDebugger {
@Test def test_CLI_Debugger_info_diff_04(): Unit = {
val schema = path(
-
"daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd"
+
"daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables_01.dfdl.xsd"
)
val input = path(
-
"daffodil-cli/src/test/resources/org/apache/daffodil/cli/input/input1.txt.xml"
+
"daffodil-cli/src/test/resources/org/apache/daffodil/cli/input/input20.txt.xml"
)
- runCLI(args"unparse -d -s $schema -r matrix -o $devNull $input", fork =
true, envs = envs) {
+ runCLI(args"unparse -d -s $schema -r c_2 -o $devNull $input", fork = true,
envs = envs) {
cli =>
cli.expect("(debug)")
cli.sendLine("display info diff")
@@ -1192,14 +1192,15 @@ class TestCLIDebugger {
cli.sendLine("set diffExcludes childIndex")
cli.expect("(debug)")
cli.sendLine("step")
- cli.expect("bitPosition: 0 -> 8")
cli.sendLine("step")
cli.sendLine("step")
cli.sendLine("step")
cli.sendLine("step")
cli.sendLine("step")
+ cli.expect("bitPosition: 16 -> 0")
+ cli.expect(regexp("\\+ Suppressable.* for group"))
+ cli.sendLine("step")
cli.sendLine("step")
- cli.expect(regexp("\\+ Suppressable.* for cell"))
cli.sendLine("step")
cli.sendLine("step")
cli.sendLine("step")
@@ -1208,10 +1209,10 @@ class TestCLIDebugger {
cli.sendLine("step")
cli.sendLine("step")
cli.sendLine("step")
- cli.expect(regexp("RegionSplit.* for cell"))
+ cli.expect(regexp("RegionSplit.* for group"))
cli.sendLine("info suspensions")
- cli.expect(regexp("Suppressable.* for cell"))
- cli.expect(regexp("RegionSplit.* for cell"))
+ cli.expect(regexp("Suppressable.* for group"))
+ cli.expect(regexp("RegionSplit.* for group"))
cli.sendLine("quit")
}(ExitCode.Failure)
}
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 2cdf03ae4..cfa5a9ff7 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
@@ -1992,12 +1992,6 @@
</root>
</tdml:dfdlInfoset>
</tdml:infoset>
- <tdml:warnings>
- <tdml:warning>Multiple choice branches</tdml:warning>
- <tdml:warning>no required elements</tdml:warning>
- <tdml:warning>infoset does not specify</tdml:warning>
- <tdml:warning>selecting the first branch</tdml:warning>
- </tdml:warnings>
<tdml:errors>
<tdml:error>Schema Definition Error</tdml:error>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
index 1b809da88..f58c28f32 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
@@ -1661,13 +1661,13 @@
<tdml:document>
<tdml:documentPart type="text"><![CDATA[3]]></tdml:documentPart>
</tdml:document>
- <tdml:infoset>
- <tdml:dfdlInfoset>
- <e>
- <value>7</value>
- </e>
- </tdml:dfdlInfoset>
- </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>hidden group</tdml:error>
+ <tdml:error>must define</tdml:error>
+ <tdml:error>outputValueCalc</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>optional</tdml:error>
+ </tdml:errors>
</tdml:parserTestCase>
<tdml:defineSchema name="multipleElemSameName" xmlns:u="USMTF"
elementFormDefault="unqualified">
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceBranches.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceBranches.tdml
new file mode 100644
index 000000000..2ae602e45
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoiceBranches.tdml
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<tdml:testSuite suiteName="choiceBranches" description="Tests for choice
branch selection"
+ 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:ex="http://example.com"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns="http://example.com">
+
+ <tdml:defineSchema name="choiceBranches">
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat"/>
+
+ <xs:group name="group_a">
+ <xs:sequence>
+ <xs:element name="a" type="xs:string" minOccurs="0"
dfdl:lengthKind="explicit" dfdl:length="1"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:group name="group_b">
+ <xs:sequence>
+ <xs:element name="b" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1" dfdl:outputValueCalc="{'b'}"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:group name="choice_a">
+ <xs:choice>
+ <xs:element name="req_a" dfdl:initiator="first_required"
type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:outputValueCalc="{'a'}"
+ dfdl:length="1"/>
+ <xs:element name="req_b" dfdl:initiator="second_required"
type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:outputValueCalc="{'b'}"
+ dfdl:length="1"/>
+ </xs:choice>
+ </xs:group>
+
+ <xs:group name="optElement">
+ <xs:sequence>
+ <xs:element name="opt" type="xs:string" minOccurs="0"
dfdl:lengthKind="explicit" dfdl:length="1"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:group name="reqElements">
+ <xs:sequence>
+ <xs:element name="reqElements_a" type="xs:string"
dfdl:lengthKind="explicit" dfdl:outputValueCalc="{'a'}"
+ dfdl:length="1"/>
+ <xs:element name="reqElements_b" type="xs:string"
dfdl:lengthKind="explicit" dfdl:outputValueCalc="{'b'}"
+ dfdl:length="1"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:element name="e1" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:group dfdl:initiator="first_defaultable" ref="ex:optElement"/>
<!-- canUnparseIfHidden/isOpen -->
+ <xs:sequence dfdl:initiator="second_open">
<!--isOpen/canUnparseIfHidden-->
+ <xs:sequence dfdl:hiddenGroupRef="ex:reqElements"/>
+ <xs:element name="char_a" minOccurs="0" type="xs:string"
dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ </xs:sequence>
+ <xs:sequence dfdl:initiator="third_empty"> <!-- isOpen/isEmpty -->
+ <xs:choice>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_a"/>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_b"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:element name="req" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e2" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:sequence dfdl:initiator="first_open">
<!--isOpen/canUnparseIfHidden-->
+ <xs:sequence dfdl:hiddenGroupRef="ex:reqElements"/>
+ <xs:element name="char_a" minOccurs="0" type="xs:string"
dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ </xs:sequence>
+ <xs:group dfdl:initiator="second_defaultable"
ref="ex:optElement"/> <!-- canUnparseIfHidden/isOpen -->
+ <xs:sequence dfdl:initiator="third_empty"> <!-- isOpen/isEmpty -->
+ <xs:choice>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_a"/>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_b"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:element name="req" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e3" dfdl:lengthKind="implicit">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:sequence dfdl:initiator="first_empty"> <!-- isOpen/isEmpty -->
+ <xs:choice>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_a"/>
+ <xs:sequence dfdl:hiddenGroupRef="ex:group_b"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:sequence dfdl:initiator="second_open">
<!--isOpen/canUnparseIfHidden-->
+ <xs:sequence dfdl:hiddenGroupRef="ex:reqElements"/>
+ <xs:element name="char_a" minOccurs="0" type="xs:string"
dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ </xs:sequence>
+ <xs:group dfdl:initiator="third_defaultable" ref="ex:optElement"/>
<!-- canUnparseIfHidden/isOpen -->
+
+ <xs:element name="req" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e4">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="req_a" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="1"/>
+ <xs:element name="req_b" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e5">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="req_1"
+ maxOccurs="unbounded"
+ dfdl:initiator="first_required"
+ type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ <xs:element name="req_2"
+ maxOccurs="unbounded"
+ dfdl:initiator="second_required"
+ type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e6">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="req_1"
+ maxOccurs="unbounded"
+ dfdl:initiator="first_required"
+ default="1"
+ type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ <xs:element name="req_2"
+ maxOccurs="unbounded"
+ dfdl:initiator="second_required"
+ default="2"
+ type="xs:string"
+ dfdl:lengthKind="explicit"
+ dfdl:length="1"/>
+ </xs:choice>
+ <xs:element name="after" type="xs:string" dfdl:lengthKind="explicit"
dfdl:length="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ </tdml:defineSchema>
+
+ <tdml:unparserTestCase name="choiceBranch_e1" model="choiceBranches"
root="e1">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <after>1</after>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>first_defaultable1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e2" model="choiceBranches"
root="e2">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <after>1</after>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>first_openab1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e3" model="choiceBranches"
root="e3">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <after>1</after>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>first_empty1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e1_req" model="choiceBranches"
root="e1">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <req>0</req>
+ <after>1</after>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>01</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e2_req" model="choiceBranches"
root="e2">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <req>0</req>
+ <after>1</after>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>01</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e3_req" model="choiceBranches"
root="e3">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <req>0</req>
+ <after>1</after>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>01</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e1_opt" model="choiceBranches"
root="e1">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <opt>0</opt>
+ <after>1</after>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>first_defaultable01</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e2_opt" model="choiceBranches"
root="e2">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <opt>0</opt>
+ <after>1</after>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>second_defaultable01</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e3_opt" model="choiceBranches"
root="e3">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <opt>0</opt>
+ <after>1</after>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>third_defaultable01</tdml:document>
+ </tdml:unparserTestCase>
+
+
+ <tdml:unparserTestCase name="choiceBranch_e1_reqElements"
model="choiceBranches" root="e1">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <char_a>c</char_a>
+ <after>1</after>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>second_openabc1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e2_reqElements"
model="choiceBranches" root="e2">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <char_a>c</char_a>
+ <after>1</after>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>first_openabc1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e3_reqElements"
model="choiceBranches" root="e3">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <char_a>c</char_a>
+ <after>1</after>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>second_openabc1</tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e4" model="choiceBranches"
root="e4">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e4>
+ <after>1</after>
+ </e4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>expected one of</tdml:error>
+ <tdml:error>req_a</tdml:error>
+ <tdml:error>req_b</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e5" model="choiceBranches"
root="e5">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e5>
+ <after>1</after>
+ </e5>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>Found</tdml:error>
+ <tdml:error>after</tdml:error>
+ <tdml:error>expected one of</tdml:error>
+ <tdml:error>req_1</tdml:error>
+ <tdml:error>req_2</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="choiceBranch_e6" model="choiceBranches"
root="e6">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e6>
+ <after>1</after>
+ </e6>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>subset</tdml:error>
+ <tdml:error>default</tdml:error>
+ <tdml:error>not implemented</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
index 8449da74b..bb62d37e4 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
@@ -203,4 +203,29 @@
</xs:sequence>
</xs:complexType>
</xs:element>
+
+ <xs:group name="c5">
+ <xs:choice>
+ <xs:choice>
+ <xs:sequence dfdl:initiator="[">
+ <xs:element name="e1" type="xs:string"
+ dfdl:inputValueCalc="{ 'hello' }"/>
+ </xs:sequence>
+ <xs:sequence dfdl:initiator="]">
+ <xs:element name="f1" type="xs:int" dfdl:inputValueCalc="{ 1 }"/>
+ </xs:sequence>
+ </xs:choice>
+ <xs:sequence>
+ <xs:element name="g1" type="xs:string" dfdl:outputValueCalc="{ 'g1'
}"/>
+ </xs:sequence>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="e10" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c5"/>
+ <xs:group ref="ex:c5"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
</xs:schema>
\ No newline at end of file
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
index f0b199022..d1cf961f2 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
@@ -102,6 +102,20 @@
</tdml:infoset>
</tdml:parserTestCase>
+ <tdml:parserTestCase name="parseIVCHiddenGroupRefs" root="e10"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text">[~9</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e10>
+ <g1>9</g1>
+ </e10>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
<tdml:unparserTestCase name="unparseHiddenGroupRef" root="e1"
model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
<tdml:infoset>
@@ -229,4 +243,16 @@
</tdml:errors>
</tdml:unparserTestCase>
+ <tdml:unparserTestCase name="unparseIVCinHiddenContext" root="e10"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e10/>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text">g1~g1</tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
index 8680615ff..abc8eb6ff 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
@@ -123,7 +123,7 @@
</xs:complexType>
</xs:element>
</xs:sequence>
- <xs:sequence dfdl:hiddenGroupRef="ex:PI_false" />
+ <xs:sequence dfdl:hiddenGroupRef="ex:PI_false"/>
</xs:choice>
<xs:element maxOccurs="unbounded" minOccurs="1" name="mhg">
<xs:complexType>
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoiceBranches.scala
similarity index 51%
copy from
daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
copy to
daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoiceBranches.scala
index b52525567..ef11f7d04 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoiceBranches.scala
@@ -19,31 +19,31 @@ package org.apache.daffodil.section15.choice_groups
import org.apache.daffodil.junit.tdml.TdmlSuite
import org.apache.daffodil.junit.tdml.TdmlTests
-import org.apache.daffodil.tdml.Runner
import org.junit.Test
-object TestHiddenChoices extends TdmlSuite {
- val tdmlResource =
"/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml"
-
- override def createRunner() = Runner(tdmlDir, tdmlFile, validateTDMLFile =
false)
+object TestChoiceBranches extends TdmlSuite {
+ val tdmlResource =
+ "/org/apache/daffodil/section15/choice_groups/ChoiceBranches.tdml"
}
-class TestHiddenChoices extends TdmlTests {
- val tdmlSuite = TestHiddenChoices
-
- @Test def parseHiddenGroupRef = test
- @Test def parseRegularGroupRef = test
- @Test def parseSeqOfHiddenAndRegularRef = test
- @Test def parseNestedHiddenAndRegularRef = test
- @Test def parseNestedHiddenGroupRefs = test
-
- @Test def unparseHiddenGroupRef = test
- @Test def unparseRegularGroupRef = test
- @Test def unparseSeqOfHiddenAndRegularRef = test
- @Test def unparseNestedHiddenAndRegularRef = test
- @Test def unparseNestedRegularAndHiddenRef = test
- @Test def unparseNestedHiddenGroupRefs = test
- @Test def noOVCinHiddenContext = test
- @Test def nestedNoOVCinHiddenContext = test
+class TestChoiceBranches extends TdmlTests {
+
+ val tdmlSuite = TestChoiceBranches
+
+ @Test def choiceBranch_e1 = test
+ @Test def choiceBranch_e2 = test
+ @Test def choiceBranch_e3 = test
+ @Test def choiceBranch_e1_req = test
+ @Test def choiceBranch_e2_req = test
+ @Test def choiceBranch_e3_req = test
+ @Test def choiceBranch_e1_opt = test
+ @Test def choiceBranch_e2_opt = test
+ @Test def choiceBranch_e3_opt = test
+ @Test def choiceBranch_e1_reqElements = test
+ @Test def choiceBranch_e2_reqElements = test
+ @Test def choiceBranch_e3_reqElements = test
+ @Test def choiceBranch_e4 = test
+ @Test def choiceBranch_e5 = test
+ @Test def choiceBranch_e6 = test
}
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
index b52525567..bb0491f14 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
@@ -37,6 +37,7 @@ class TestHiddenChoices extends TdmlTests {
@Test def parseSeqOfHiddenAndRegularRef = test
@Test def parseNestedHiddenAndRegularRef = test
@Test def parseNestedHiddenGroupRefs = test
+ @Test def parseIVCHiddenGroupRefs = test
@Test def unparseHiddenGroupRef = test
@Test def unparseRegularGroupRef = test
@@ -46,4 +47,5 @@ class TestHiddenChoices extends TdmlTests {
@Test def unparseNestedHiddenGroupRefs = test
@Test def noOVCinHiddenContext = test
@Test def nestedNoOVCinHiddenContext = test
+ @Test def unparseIVCinHiddenContext = test
}