diff --git a/src/main/java/com/amazon/ion/impl/IonReaderTreeUserX.java b/src/main/java/com/amazon/ion/impl/IonReaderTreeUserX.java index 2e572aeba..d02853211 100644 --- a/src/main/java/com/amazon/ion/impl/IonReaderTreeUserX.java +++ b/src/main/java/com/amazon/ion/impl/IonReaderTreeUserX.java @@ -101,10 +101,9 @@ boolean next_helper_user() sid = _system_symtab.findSymbol(name); } } - boolean isIVM = isIonVersionMarker(sym.symbolValue().getText()) || sid == ION_1_0_SID; - if (isIVM + if ((sid == ION_1_0_SID || isIonVersionMarker(sym.symbolValue().getText())) && _next.getTypeAnnotationSymbols().length == 0) { - // $ion_1_0 is read as an IVM only if it is not annotated + // $ion_1_0 and other version markers are read as an IVM only if unannotated SymbolTable symbols = _system_symtab; _symbols = symbols; push_symbol_table(symbols); diff --git a/src/test/java/com/amazon/ion/Ion_1_1_RoundTripTest.kt b/src/test/java/com/amazon/ion/Ion_1_1_RoundTripTest.kt index 242e814f9..0e48bfa5b 100644 --- a/src/test/java/com/amazon/ion/Ion_1_1_RoundTripTest.kt +++ b/src/test/java/com/amazon/ion/Ion_1_1_RoundTripTest.kt @@ -57,8 +57,8 @@ class Ion_1_1_RoundTripTest { override val writerFn: (OutputStream) -> IonWriter = builder::build @Disabled("Ion binary reader can't seem to discover symbol tables with inline annotations") - override fun testUserValuesArePreservedWhenTranscodingSystemValues(name: String, ion: ByteArray) { - super.testUserValuesArePreservedWhenTranscodingSystemValues(name, ion) + override fun testUserValuesArePreservedWhenTransferringSystemValues(name: String, ion: ByteArray) { + super.testUserValuesArePreservedWhenTransferringSystemValues(name, ion) } } @@ -71,8 +71,8 @@ class Ion_1_1_RoundTripTest { override val writerFn: (OutputStream) -> IonWriter = builder::build @Disabled("Ion binary reader can't seem to discover symbol tables with inline annotations") - override fun testUserValuesArePreservedWhenTranscodingSystemValues(name: String, ion: ByteArray) { - super.testUserValuesArePreservedWhenTranscodingSystemValues(name, ion) + override fun testUserValuesArePreservedWhenTransferringSystemValues(name: String, ion: ByteArray) { + super.testUserValuesArePreservedWhenTransferringSystemValues(name, ion) } } @@ -121,10 +121,10 @@ abstract class Ion_1_1_RoundTripBase { @ParameterizedTest(name = "{0}") @MethodSource("testData") - fun testUserValuesArePreservedWhenTranscodingUserValues(name: String, ion: ByteArray) { + fun testUserValuesArePreservedWhenTransferringUserValues(name: String, ion: ByteArray) { // Read and compare the data. - val actual = copyUserData(ion).toByteArray() + val actual = roundTrip { w -> newReader(ion).let(::iterate).forEach { it.writeTo(w) } } println("Expected:") ion.printDisplayString() println("Actual:") @@ -138,7 +138,40 @@ abstract class Ion_1_1_RoundTripBase { @ParameterizedTest(name = "{0}") @MethodSource("testData") - open fun testUserValuesArePreservedWhenTranscodingSystemValues(name: String, ion: ByteArray) { + fun testUserValuesArePreservedWhenTransferringUserValuesUsingWriteValueForReader(name: String, ion: ByteArray) { + + // Read and compare the data. + val actual = roundTrip { w -> newReader(ion).let { r -> while (r.next() != null) w.writeValue(r) } } + println("Expected:") + ion.printDisplayString() + println("Actual:") + actual.printDisplayString() + + assertReadersHaveEquivalentValues( + ION.newReader(ion), + ION.newReader(actual) + ) + } + + @ParameterizedTest(name = "{0}") + @MethodSource("testData") + fun testUserValuesArePreservedWhenTransferringUserValuesUsingWriteValueForIonValue(name: String, ion: ByteArray) { + // Read and compare the data. + val actual = roundTrip { w -> newReader(ion).let(::iterate).forEach { w.writeValue(it) } } + println("Expected:") + ion.printDisplayString() + println("Actual:") + actual.printDisplayString() + + assertReadersHaveEquivalentValues( + ION.newReader(ion), + ION.newReader(actual) + ) + } + + @ParameterizedTest(name = "{0}") + @MethodSource("testData") + open fun testUserValuesArePreservedWhenTransferringSystemValues(name: String, ion: ByteArray) { // Read and compare the data. val actual = copySystemData(ion).toByteArray() @@ -156,7 +189,7 @@ abstract class Ion_1_1_RoundTripBase { @ParameterizedTest(name = "{0}") @MethodSource("testData") - open fun testSystemValuesArePreservedWhenTranscodingSystemValues(name: String, ion: ByteArray) { + open fun testSystemValuesArePreservedWhenTransferringSystemValues(name: String, ion: ByteArray) { // Read and compare the data. val actual = copySystemData(ion).toByteArray() @@ -174,15 +207,24 @@ abstract class Ion_1_1_RoundTripBase { } private fun copyUserData(f: ByteArray): ByteArrayOutputStream { - val data: Iterator = ION.iterate(ION.newReader(f.inputStream())) // Create a new copy of the data in Ion 1.1 val baos = ByteArrayOutputStream() val writer = writerFn(baos) - data.forEach { it.writeTo(writer) } + ION.iterate(ION.newReader(f.inputStream())).forEach { it.writeTo(writer) } writer.close() return baos } + private fun roundTrip(block: _Private_IonSystem.(IonWriter) -> Unit): ByteArray { + // val data: Iterator = ION.systemIterate(ION.newSystemReader(f)) + // Create a new copy of the data in Ion 1.1 + val baos = ByteArrayOutputStream() + val writer = writerFn(baos) + block(ION, writer) + writer.close() + return baos.toByteArray() + } + private fun copySystemData(f: ByteArray): ByteArrayOutputStream { // val data: Iterator = ION.systemIterate(ION.newSystemReader(f)) // Create a new copy of the data in Ion 1.1 diff --git a/src/test/java/com/amazon/ion/impl/IonRawTextWriterTest_1_1.kt b/src/test/java/com/amazon/ion/impl/IonRawTextWriterTest_1_1.kt index 8ae1ef935..f77c1a5b4 100644 --- a/src/test/java/com/amazon/ion/impl/IonRawTextWriterTest_1_1.kt +++ b/src/test/java/com/amazon/ion/impl/IonRawTextWriterTest_1_1.kt @@ -6,7 +6,6 @@ import com.amazon.ion.* import com.amazon.ion.system.* import java.math.BigDecimal import java.math.BigInteger -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue diff --git a/src/test/java/com/amazon/ion/impl/bin/IonManagedWriter_1_1_Test.kt b/src/test/java/com/amazon/ion/impl/bin/IonManagedWriter_1_1_Test.kt new file mode 100644 index 000000000..658c6cd87 --- /dev/null +++ b/src/test/java/com/amazon/ion/impl/bin/IonManagedWriter_1_1_Test.kt @@ -0,0 +1,46 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package com.amazon.ion.impl.bin + +import com.amazon.ion.* +import com.amazon.ion.IonEncodingVersion.* +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +internal class IonManagedWriter_1_1_Test { + + val appendable = StringBuilder() + val writer = ION_1_1.textWriterBuilder() + .withSymbolInliningStrategy(SymbolInliningStrategy.ALWAYS_INLINE) + .build(appendable) as IonManagedWriter_1_1 + + @Test + fun `attempting to manually write a symbol table throws an exception`() { + writer.addTypeAnnotation(SystemSymbols.ION_SYMBOL_TABLE) + assertThrows { writer.stepIn(IonType.STRUCT) } + } + + @Test + fun `attempting to step into a scalar type throws an exception`() { + assertThrows { writer.stepIn(IonType.NULL) } + } + + @Test + fun `write an IVM`() { + writer.writeIonVersionMarker() + writer.close() + assertEquals("\$ion_1_1 \$ion_1_1", appendable.toString().trim()) + } + + @Test + fun `write an IVM in a container should write a symbol`() { + with(writer) { + stepIn(IonType.LIST) + writeIonVersionMarker() + stepOut() + close() + } + assertEquals("\$ion_1_1 [\$ion_1_1]", appendable.toString().trim()) + } +} diff --git a/src/test/java/com/amazon/ion/impl/bin/IonRawBinaryWriterTest_1_1.kt b/src/test/java/com/amazon/ion/impl/bin/IonRawBinaryWriterTest_1_1.kt index 9740cca76..1f39798d3 100644 --- a/src/test/java/com/amazon/ion/impl/bin/IonRawBinaryWriterTest_1_1.kt +++ b/src/test/java/com/amazon/ion/impl/bin/IonRawBinaryWriterTest_1_1.kt @@ -26,7 +26,6 @@ class IonRawBinaryWriterTest_1_1 { lengthPrefixPreallocation = 1, ) - private inline fun writeAsHexString(autoClose: Boolean = true, block: IonRawBinaryWriter_1_1.() -> Unit): String { val baos = ByteArrayOutputStream() val rawWriter = ionWriter(baos)