def runUnparserExpectSuccess()

in daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala [1617:1724]


  def runUnparserExpectSuccess(
    expectedData: InputStream,
    optWarnings: Option[Seq[ExpectedWarnings]],
    optValidationErrors: Option[Seq[ExpectedValidationErrors]],
    roundTrip: RoundTrip,
    implString: Option[String],
    compileWarnings: Seq[Diagnostic]
  ): Unit = {

    Assert.usage(roundTrip ne TwoPassRoundTrip) // not supported for unparser test cases.

    val infosetXML: Node = inputInfoset.dfdlInfoset.contents

    val outStream = new java.io.ByteArrayOutputStream()
    val actual =
      try {
        processor = processor.withExternalDFDLVariables(externalVarBindings)
        processor.unparse(infosetXML, outStream)
      } catch {
        case t: Throwable => toss(t, implString)
      }
    if (actual.isProcessingError)
      throw TDMLException(actual.getDiagnostics, implString)

    //
    // Test that we are getting the number of full bytes needed.
    val testData = outStream.toByteArray
    val testDataLength = actual.finalBitPos0b
    if (testDataLength >= 0) {
      val fullBytesNeeded = (testDataLength + 7) / 8
      if (testData.length != fullBytesNeeded) {
        throw TDMLException(
          "Unparse result data was %d bytes, but the result length (%d bits) requires %d bytes."
            .format(testData.length, testDataLength, fullBytesNeeded),
          implString
        )
      }
    }

    if (actual.isScannable) {
      // all textual in one encoding, so we can do display of results
      // in terms of text so the user can see what is going on.
      VerifyTestCase.verifyTextData(expectedData, outStream, actual.encodingName, implString)
    } else {
      // data is not all textual, or in mixture of encodings
      // So while we can still use the encoding as a heuristic,
      // we will need to treat as Hex bytes as well.
      VerifyTestCase.verifyBinaryOrMixedData(expectedData, outStream, implString)
    }

    val allDiags = actual.getDiagnostics ++ compileWarnings
    checkDiagnosticMessages(
      allDiags,
      None,
      optWarnings,
      optValidationErrors,
      implString
    )

    if (roundTrip eq OnePassRoundTrip) {

      val parseActual =
        try {
          processor.parse(new ByteArrayInputStream(outStream.toByteArray), testDataLength)
        } catch {
          case t: Throwable => toss(t, implString)
        }

      if (parseActual.isProcessingError) {
        // Means there was an error, not just warnings.
        val diagObjs = parseActual.getDiagnostics
        if (diagObjs.length == 1) throw diagObjs.head
        val diags = parseActual.getDiagnostics.map(_.getMessage()).mkString("\n")
        throw TDMLException(diags, implString)
      }
      val loc: DataLocation = parseActual.currentLocation

      val leftOverException = if (loc.bitPos1b >= 0 && loc.bitPos1b < testDataLength) {
        //
        // For this to happen (and have test coverage) we need an unparserTestCase
        // which is roundTrip onePass, and where the parse doesn't consume all
        // the data.
        //
        val leftOverMsg =
          "Left over data. Consumed %s bit(s) with %s bit(s) remaining.".format(
            loc.bitPos1b - 1,
            testDataLength - (loc.bitPos1b - 1)
          )
        Some(TDMLException(leftOverMsg, implString))
      } else None

      val xmlNode = parseActual.getResult
      VerifyTestCase.verifyParserTestData(xmlNode, inputInfoset, implString)

      leftOverException.map {
        throw _
      } // if we get here, throw the left over data exception.

      // Done with the parse results, safe to clean up blobs if there was
      // success. This won't get called on failure, which is fine--leave blobs
      // around for debugging
      parseActual.cleanUp()
    }

    // Done with the unparse results, safe to clean up any temporary files
    // if they were not already cleaned up by parseActual.cleanUp() above
    actual.cleanUp()
  }