Do not output error diagnostics when there is an infoset

- In cases where a element in a sequence's prefix separator is not found
  use the AbsentRep error instead of MissingSeparator. This causes us to
  reset to a PoU rather than just continuing - throwing out the error
  from finding out of scope separators.
- Discard error messages caught in the ScalarParser section of parse
  under cases where we were using setSuccess to mask errors. When
  masking errors, we also need to mask related diagnostics.
- Add assert.invariant to catch any errors in the TDML runner if we also
  return an infoset.
- Modify delimiterParser to not create PE errors when returning
  AbsentRep.
- Add commented out tests related to discriminated unordered sequences
  that show incorrect behavior that fixing this made more obvious.

DAFFODIL-2399
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedParseHelper.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedParseHelper.scala
index 6e04248..e430ad8 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedParseHelper.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedParseHelper.scala
@@ -96,11 +96,34 @@
 
     val sepStatus =
       if (shouldParseTheSep) {
-        sep.parse1(pstate)
-        if (pstate.processorStatus eq Success)
-          SeparatorParseStatus.SeparatorFound
-        else
-          SeparatorParseStatus.SeparatorFailed
+
+        // If a separator is expected, but optional, we may generate errors
+        // while searching for it which should not be propagated upward
+        requiredOptional match {
+          case _: RequiredOptionalStatus.Optional => {
+            // Create a point of uncertainty with which to reset if we find errors
+            pstate.withPointOfUncertainty("parseOneWithInfixOrPrefixSeparator",childParser.context) { pou =>
+              sep.parse1(pstate)
+
+              val rv = if (pstate.processorStatus eq Success) {
+                SeparatorParseStatus.SeparatorFound
+              } else {
+                // reset to the point of uncertainty to discard the errors
+                pstate.resetToPointOfUncertainty(pou)
+                SeparatorParseStatus.SeparatorFailed
+              }
+              rv
+
+            }
+          }
+          case _ => {
+            sep.parse1(pstate)
+            if (pstate.processorStatus eq Success)
+              SeparatorParseStatus.SeparatorFound
+            else
+              SeparatorParseStatus.SeparatorFailed
+          }
+        }
       } else
         SeparatorParseStatus.SeparatorNotNeeded
 
@@ -117,7 +140,12 @@
         pas
       }
       case _ => {
-        failedSeparator(pstate, kind)
+        requiredOptional match {
+          case _: RequiredOptionalStatus.Required => {
+            failedSeparator(pstate, kind)
+          }
+          case _ => // No action
+        }
         scParser.parseResultHelper.computeFailedSeparatorParseAttemptStatus(
           scParser,
           prevBitPosBeforeChild, pstate,
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
index 4a79538..572335a 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
@@ -279,7 +279,7 @@
     if (isModelGroupRepPossiblyZeroLength &&
       !isModelGroupRepNonZeroLength) {
       pstate.setSuccess()
-      ParseAttemptStatus.MissingSeparator
+      ParseAttemptStatus.AbsentRep
     } else
       ParseAttemptStatus.FailureUnspecified
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
index 08ab5f6..86ae202 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
@@ -243,6 +243,7 @@
           // We do NOT move over the group index state for non-represented things.
         }
         case scalarParser => {
+          val diagnosticsBeforeAttempt = pstate.diagnostics
           val roStatus = scalarParser.maybeStaticRequiredOptionalStatus.get
           val (_, nextResultOfTry) = parseOneInstance(scalarParser, pstate, roStatus)
           priorResultOfTry = resultOfTry
@@ -261,6 +262,10 @@
               // So we mask the failure, and exit the sequence successfully
               pstate.setSuccess()
               isDone = true
+              // If we're masking the failure, we don't want the error dianostics
+              // to flow up. Restore the diagnostics from before the parse
+              // attempt
+              pstate.diagnostics = diagnosticsBeforeAttempt
             }
 
             // We successfully parsed a discriminator, but failed to parse the discriminated content.
@@ -272,6 +277,10 @@
               // the sequence succesfully
               isDone = true
               pstate.setSuccess()
+              // If we're masking the failure, we don't want the error dianostics
+              // to flow up. Restore the diagnostics from before the parse
+              // attempt
+              pstate.diagnostics = diagnosticsBeforeAttempt
             }
 
             case _ => // ok.
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index 5acb095..9538876 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -958,13 +958,21 @@
       toss(optExtVarDiag.get, implString)
     } else {
       val actual = processor.parse(new ByteArrayInputStream(testData), testDataLength)
+      val diagObjs = actual.getDiagnostics
 
       if (actual.isProcessingError) {
         // Means there was an error, not just warnings.
-        val diagObjs = actual.getDiagnostics
         if (diagObjs.length == 1) throw TDMLException(diagObjs.head, implString)
         val diags = actual.getDiagnostics.map(_.getMessage()).mkString("\n")
         throw TDMLException(diags, implString)
+      } else {
+        // If we think we've succeeded, verify there are no errors
+        // captured in the diagnostics. Otherwise there's probably
+        // an internal bug causing us to miss setting isProcessingError
+        val hasErrorDiags = diagObjs.exists { diag =>
+          diag.isError && !diag.isValidation
+        }
+        Assert.invariant(!hasErrorDiags)
       }
       actual
     }
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
index 8fa7b71..acfff7b 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
@@ -891,7 +891,7 @@
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
     <dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
       lengthKind="delimited" occursCountKind="parsed" />
-    <xs:element name="R" dfdl:terminator="END">
+    <xs:element name="R" dfdl:terminator="FINAL">
       <xs:complexType>
         <xs:sequence dfdl:sequenceKind="unordered" dfdl:initiatedContent="yes"
           dfdl:separator="|" dfdl:separatorPosition="infix">
@@ -912,7 +912,7 @@
 
   <tdml:parserTestCase name="test_initiated_unordered1"
     model="initiated_content" root="R">
-    <tdml:document><![CDATA[X:not expected|Y:something else]]></tdml:document>
+    <tdml:document><![CDATA[X:not expected|Y:something elseFINAL]]></tdml:document>
     <tdml:errors>
       <tdml:error>Parse Error</tdml:error>
       <tdml:error>Assertion</tdml:error>
@@ -920,5 +920,26 @@
     </tdml:errors>
   </tdml:parserTestCase>
   
+  <tdml:parserTestCase name="test_initiated_unordered2"
+    model="initiated_content" root="R">
+    <tdml:document><![CDATA[X:expected|Y:something elseFINAL]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <R>
+          <X>expected</X>
+          <Y>something else</Y>
+        </R>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="test_initiated_unordered3"
+    model="initiated_content" root="R">
+    <tdml:document><![CDATA[X:not expectedFINAL]]></tdml:document>
+    <tdml:errors>
+      <tdml:error>Parse Error</tdml:error>
+      <tdml:error>FINAL</tdml:error>
+    </tdml:errors>
+  </tdml:parserTestCase>
 
 </tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/UserSubmittedTests.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/UserSubmittedTests.tdml
index 9e92844..c86aed7 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/UserSubmittedTests.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/UserSubmittedTests.tdml
@@ -132,6 +132,55 @@
     </tdml:infoset>
   </tdml:parserTestCase>
 
+  <!-- Schema for DFDL-2399 test-->
+ <tdml:defineSchema name="dfdl2399">
+  <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+
+  <dfdl:format ref="GeneralFormat"
+    lengthKind="delimited" 
+    separatorSuppressionPolicy="trailingEmpty" />
+
+  <xs:element name="message">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element ref="record"/>
+      </xs:sequence>
+    </xs:complexType> 
+  </xs:element>
+
+  <xs:element name="record" dfdl:initiator="record" dfdl:terminator="%NL;">
+    <xs:complexType>
+      <xs:sequence dfdl:separator="|" dfdl:separatorPosition="prefix">
+        <xs:sequence dfdl:separator="~" dfdl:separatorPosition="infix">
+          <xs:element name="field1" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+        <xs:sequence dfdl:separator="~" dfdl:separatorPosition="infix">
+          <xs:element name="field2" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+        <xs:sequence dfdl:separator="~" dfdl:separatorPosition="infix">
+          <xs:element name="field3" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+  </tdml:defineSchema>
+  
+  <tdml:parserTestCase name="test_DFDL_2399"
+    root="record" model="dfdl2399"
+    description="Demonstrate that a sequence which contains minOccurs=0, delimited sequences
+    which are empty do not return both a succesful parse and errors.">
+    <tdml:document>
+      <tdml:documentPart type="text" replaceDFDLEntities="true">record|field1%CR;%LF;</tdml:documentPart>
+    </tdml:document>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:record xmlns:ex="http://example.com"><ex:field1>field1</ex:field1></ex:record>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
 	<tdml:defineSchema name="dfdlwg1" elementFormDefault="unqualified">
 		<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
 
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
index e1af617..5b061c5 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
@@ -58,8 +58,11 @@
 
   @Test def test_empty_seq = { runner.runOneTest("test_empty_seq") }
 
-  // DAFFODIL-1034
-  @Test def test_initiated_unordered1 = { runner.runOneTest("test_initiated_unordered1") }
+  // DAFFODIL-2512
+  //@Test def test_initiated_unordered1 = { runner.runOneTest("test_initiated_unordered1") }
+  @Test def test_initiated_unordered2 = { runner.runOneTest("test_initiated_unordered2") }
+  // DAFFODIL-2512
+  //@Test def test_initiated_unordered3 = { runner.runOneTest("test_initiated_unordered3") }
 
   @Test def test_BE000 = { runnerBE.runOneTest("BE000") }
   @Test def test_BE001 = { runnerBE.runOneTest("BE001") }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestUserSubmittedTests.scala b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestUserSubmittedTests.scala
index dd2a3e7..85cd63b 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestUserSubmittedTests.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestUserSubmittedTests.scala
@@ -41,6 +41,7 @@
     runner.runOneTest("test_prefix_separator_as_variable")
   }
   @Test def test_DFDL_2262(): Unit = { runner.runOneTest("test_DFDL_2262") }
+  @Test def test_DFDL_2399(): Unit = { runner.runOneTest("test_DFDL_2399") }
 
   // DAFFODIL-2378 (decided as not a bug. These tests characterize that behavior.)
   @Test def testTextNumberPattern1(): Unit = { runner.runOneTest("textNumberPattern1") }