diff --git a/src/com/amazon/ion/benchmark/Format.java b/src/com/amazon/ion/benchmark/Format.java index 92ba902..3668ec2 100644 --- a/src/com/amazon/ion/benchmark/Format.java +++ b/src/com/amazon/ion/benchmark/Format.java @@ -24,7 +24,7 @@ Path convert(Path input, Path output, OptionsCombinationBase options) throws IOE || options.ionInlineSymbols != null || options.preallocation != null || options.floatWidth != null - || (options.ionMinorVersion != null && !IonUtilities.minorVersionsEqual(options.ionMinorVersion, input.toFile())) + || (options.ionMinorVersion != null && !IonUtilities.minorVersionsEqual(Format.ION_BINARY, options.ionMinorVersion, input.toFile())) || (options.importsForBenchmarkFile != null && !IonUtilities.importsEqual(options.importsForBenchmarkFile, input.toFile())) || !IonUtilities.importsFilesEqual(options.importsForInputFile, options.importsForBenchmarkFile); @@ -34,6 +34,12 @@ Path convert(Path input, Path output, OptionsCombinationBase options) throws IOE } else if (options.limit == Integer.MAX_VALUE) { // There are no settings that require mutating the original input. return input; + } else if (options.ionMinorVersion != null && options.ionMinorVersion > 0) { + // TODO this case is eligible for simple truncation (the 'else' below), but currently it does + // not work because the SpanProvider facet, which is used by our truncation implementation, + // can't handle macro invocations or delimited containers. If that changes, this branch will + // no longer be necessary. See https://github.com/amazon-ion/ion-java/issues/1011 + IonUtilities.rewriteIonFile(ION_BINARY, input, output, options, IonUtilities::newBinaryWriterSupplier); } else { // This combination of settings requires simple truncation. return IonUtilities.truncateBinaryIonFile(input, output, options.limit); @@ -86,8 +92,13 @@ Path convert(Path input, Path output, OptionsCombinationBase options) throws IOE Format sourceFormat = classify(input); switch (sourceFormat) { case ION_TEXT: - if (options.limit == Integer.MAX_VALUE && (getMinorVersion(ION_TEXT, input.toFile()) == options.ionMinorVersion)) { - // The input is already text in the requested minor version, and it is not being limited. + if ( + options.flushPeriod == null && + options.limit == Integer.MAX_VALUE && + (getMinorVersion(ION_TEXT, input.toFile()) == options.ionMinorVersion) + ) { + // The input is already text in the requested minor version, and it is not being limited or + // written with a specific flush period. return input; } IonUtilities.rewriteIonFile(ION_TEXT, input, output, options, IonUtilities::newTextWriterSupplier); diff --git a/src/com/amazon/ion/benchmark/IonUtilities.java b/src/com/amazon/ion/benchmark/IonUtilities.java index abc7e88..1d0de7a 100644 --- a/src/com/amazon/ion/benchmark/IonUtilities.java +++ b/src/com/amazon/ion/benchmark/IonUtilities.java @@ -175,13 +175,11 @@ static boolean isFormatHeaderPresent(byte[] formatHeader, File file) throws IOEx * @return true if the file contains binary Ion data of the given minor version; otherwise, false. * @throws IOException if thrown while reading the file. */ - static boolean minorVersionsEqual(int minorVersion, File input) throws IOException { - if (minorVersion == 1) { - return isFormatHeaderPresent(_Private_IonConstants.BINARY_VERSION_MARKER_1_1, input); - } else if (minorVersion == 0) { - return isFormatHeaderPresent(_Private_IonConstants.BINARY_VERSION_MARKER_1_0, input); + static boolean minorVersionsEqual(Format format, int minorVersion, File input) throws IOException { + if (!format.isIon()) { + return false; } - throw new IllegalStateException("Unknown Ion minor version: " + minorVersion); + return minorVersion == getMinorVersion(format, input); } /** @@ -210,6 +208,49 @@ static int getMinorVersion(Format inputFormat, File input) throws IOException { throw new IllegalStateException("File is either not Ion or has unknown minor version: " + input); } + /** + * Determine whether the given data starts with the given format header. + * @param formatHeader the format header to match. + * @param input the data. + * @return true if the first bytes in the data match the given format header; otherwise, false. + */ + private static boolean isFormatHeaderPresent(byte[] formatHeader, byte[] input) { + if (input.length < formatHeader.length) { + return false; + } + for (int i = 0; i < formatHeader.length; i++) { + if (input[i] != formatHeader[i]) { + return false; + } + } + return true; + } + + /** + * Get the minor version for the given text or binary Ion data. + * @param inputFormat the format of 'input'; must be ION_BINARY, ION_TEXT, or JSON. + * @param input the data to examine. + * @return the Ion minor version of the data. + */ + static int getMinorVersion(Format inputFormat, byte[] input) { + if (inputFormat == Format.ION_BINARY) { + if (isFormatHeaderPresent(_Private_IonConstants.BINARY_VERSION_MARKER_1_0, input)) { + return 0; + } + if (isFormatHeaderPresent(_Private_IonConstants.BINARY_VERSION_MARKER_1_1, input)) { + return 1; + } + } else if (inputFormat == Format.ION_TEXT) { + if (isFormatHeaderPresent(ION_1_1_TEXT_IVM, input)) { + return 1; + } + return 0; + } else if (inputFormat == Format.JSON) { + return 0; + } + throw new IllegalStateException("Input is either not Ion or has unknown minor version."); + } + /** * Supplies IonWriter instances. */ diff --git a/src/com/amazon/ion/benchmark/MeasurableWriteTask.java b/src/com/amazon/ion/benchmark/MeasurableWriteTask.java index 496c9fa..410a007 100644 --- a/src/com/amazon/ion/benchmark/MeasurableWriteTask.java +++ b/src/com/amazon/ion/benchmark/MeasurableWriteTask.java @@ -37,7 +37,7 @@ interface WriteInstruction { */ MeasurableWriteTask(Path inputPath, WriteOptionsCombination options) throws IOException { Format inputFormat = Format.classify(inputPath); - if (options.format.canParse(inputFormat)) { + if (options.format.canParse(inputFormat) && IonUtilities.minorVersionsEqual(inputFormat, options.ionMinorVersion, inputPath.toFile())) { this.inputFile = inputPath.toFile(); } else { this.inputFile = options.format.convert( diff --git a/tst/com/amazon/ion/benchmark/OptionsTest.java b/tst/com/amazon/ion/benchmark/OptionsTest.java index ba8d0c6..2665540 100644 --- a/tst/com/amazon/ion/benchmark/OptionsTest.java +++ b/tst/com/amazon/ion/benchmark/OptionsTest.java @@ -428,6 +428,33 @@ private static void assertImportsEqual(String expectedImportsFile, byte[] bytes) } } + /** + * Verifies that the given file in the given format has the expected Ion minor version (if it is Ion data). + * @param format the file's format. + * @param file the file to test. + * @param options the options containing the expected Ion minor version. + * @throws IOException if thrown when parsing the file. + */ + private static void verifyIonMinorVersion(Format format, File file, OptionsCombinationBase options) throws IOException { + if (format.isIon()) { + int expectedMinorVersion = options.ionMinorVersion == null ? 0 : options.ionMinorVersion; + assertEquals(expectedMinorVersion, IonUtilities.getMinorVersion(format, file)); + } + } + + /** + * Verifies that the given data in the given format has the expected Ion minor version (if it is Ion data). + * @param format the data's format. + * @param input the data to test. + * @param options the options containing the expected Ion minor version. + */ + private static void verifyIonMinorVersion(Format format, byte[] input, OptionsCombinationBase options) { + if (format.isIon()) { + int expectedMinorVersion = options.ionMinorVersion == null ? 0 : options.ionMinorVersion; + assertEquals(expectedMinorVersion, IonUtilities.getMinorVersion(format, input)); + } + } + /** * Asserts that a read task executes as expected. This includes assertions that temporary files are created only * when expected and are always cleaned up, that conversions between formats are correct and happen only when @@ -462,6 +489,7 @@ private static byte[] assertReadTaskExecutesCorrectly( streamBytes = task.buffer; } assertFormat(streamBytes, expectedFormat); + verifyIonMinorVersion(expectedFormat, streamBytes, optionsCombination); if (expectedFormat.canParse(Format.classify(inputPath))) { // If this is a conversion between two formats with the same data model (e.g. text Ion to binary Ion), // then they should compare equivalent. @@ -513,12 +541,15 @@ private static byte[] assertWriteTaskExecutesCorrectly( inputPath ); task.setUpTrial(); - if (expectedOutputFormat.canParse(Format.classify(inputPath))) { + Format inputFormat = Format.classify(inputPath); + if (expectedOutputFormat.canParse(inputFormat) && IonUtilities.minorVersionsEqual(inputFormat, optionsCombination.ionMinorVersion, inputPath.toFile())) { assertEquals(inputPath.toFile(), task.inputFile); } else { // If the input file's format cannot be read by parsers of the target format, then the input file must // first be converted to the target format. - assertEquals(expectedOutputFormat, Format.classify(task.inputFile.toPath())); + Format actualFormat = Format.classify(task.inputFile.toPath()); + assertEquals(expectedOutputFormat, actualFormat); + verifyIonMinorVersion(actualFormat, task.inputFile, optionsCombination); } // Ensure that the task executes without error. MeasurableTask.Task callable = task.getTask(); @@ -2461,215 +2492,338 @@ private static int countOccurrencesOfSubstring(String string, String substring) return count; } - @Test - public void writeIon11WithMacros() throws Exception { - WriteOptionsCombination optionsCombination = parseSingleOptionsCombination( + private void writeIon11WithMacros(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "write", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "buffer", - "binaryMacroInvocations.10n" + inputFile ); - byte[] data = assertWriteTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - IoType.BUFFER - ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (WriteOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertWriteTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + IoType.BUFFER + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void writeIon11WithMacrosAndLimit() throws Exception { - WriteOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void writeIon11WithMacrosFromBinary() throws Exception { + writeIon11WithMacros("binaryMacroInvocations.10n"); + } + + @Test + public void writeIon11WithMacrosFromText() throws Exception { + writeIon11WithMacros("textMacroInvocations.ion"); + } + + private void writeIon11WithMacrosAndLimit(String fileName) throws Exception { + List optionsCombinations = parseOptionsCombinations( "write", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "file", "--limit", "2", - "binaryMacroInvocations.10n" - ); - byte[] data = assertWriteTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - IoType.FILE + fileName ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(0, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (WriteOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertWriteTaskExecutesCorrectly( + fileName, + optionsCombination, + optionsCombination.format, + IoType.FILE + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(0, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void writeIon11WithMacrosAndFlushPeriod() throws Exception { - WriteOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void writeIon11WithMacrosAndLimitFromBinary() throws Exception { + writeIon11WithMacrosAndLimit("binaryMacroInvocations.10n"); + } + + @Test + public void writeIon11WithMacrosAndLimitFromText() throws Exception { + writeIon11WithMacrosAndLimit("textMacroInvocations.ion"); + } + + private void writeIon11WithMacrosAndFlushPeriod(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "write", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "file", "--ion-flush-period", "2", - "binaryMacroInvocations.10n" - ); - byte[] data = assertWriteTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - IoType.FILE + inputFile ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (WriteOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertWriteTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + IoType.FILE + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void writeIon11WithMacrosToIon10() throws Exception { - WriteOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void writeIon11WithMacrosAndFlushPeriodFromBinary() throws Exception { + writeIon11WithMacrosAndFlushPeriod("binaryMacroInvocations.10n"); + } + + @Test + public void writeIon11WithMacrosAndFlushPeriodFromText() throws Exception { + writeIon11WithMacrosAndFlushPeriod("textMacroInvocations.ion"); + } + + private void writeIon11WithMacrosToIon10(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "write", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "0", // This forces a conversion that cannot preserve the encoding directives or macro invocations. "--io-type", "buffer", - "binaryMacroInvocations.10n" - ); - assertWriteTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - IoType.BUFFER + inputFile ); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (WriteOptionsCombination optionsCombination : optionsCombinations) { + assertWriteTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + IoType.BUFFER + ); + } } @Test - public void readIon11WithMacros() throws Exception { - ReadOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void writeIon11WithMacrosToIon10FromBinary() throws Exception { + writeIon11WithMacrosToIon10("binaryMacroInvocations.10n"); + } + + @Test + public void writeIon11WithMacrosToIon10FromText() throws Exception { + writeIon11WithMacrosToIon10("textMacroInvocations.ion"); + } + + private void readIon11WithMacros(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "read", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "buffer", "binaryMacroInvocations.10n" ); - byte[] data = assertReadTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - true - ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (ReadOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertReadTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + // Conversion is only required if the requested format differs from the format of the input file. + optionsCombination.format != Format.classify(fileInTestDirectory(inputFile)) + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void readIon11WithMacrosAndLimit() throws Exception { - ReadOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void readIon11WithMacrosFromBinary() throws Exception { + readIon11WithMacros("binaryMacroInvocations.10n"); + } + + @Test + public void readIon11WithMacrosFromText() throws Exception { + readIon11WithMacros("textMacroInvocations.ion"); + } + + private void readIon11WithMacrosAndLimit(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "read", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "file", "--limit", "3", - "binaryMacroInvocations.10n" + inputFile ); - byte[] data = assertReadTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - true - ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (ReadOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertReadTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + true // --limit always requires conversion / truncation. + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(0, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void readIon11WithMacrosAndFlushPeriod() throws Exception { - ReadOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void readIon11WithMacrosAndLimitFromBinary() throws Exception { + readIon11WithMacrosAndLimit("binaryMacroInvocations.10n"); + } + + @Test + public void readIon11WithMacrosAndLimitFromText() throws Exception { + readIon11WithMacrosAndLimit("textMacroInvocations.ion"); + } + + private void readIon11WithMacrosAndFlushPeriod(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "read", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "1", "--io-type", "file", "--ion-flush-period", "2", - "binaryMacroInvocations.10n" + inputFile ); - byte[] data = assertReadTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - true - ); - String ion11Text = new String(data, StandardCharsets.UTF_8); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); - assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); - assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (ReadOptionsCombination optionsCombination : optionsCombinations) { + byte[] data = assertReadTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + true // Specifying a flush period always requires conversion. + ); + if (optionsCombination.format == Format.ION_TEXT) { + String ion11Text = new String(data, StandardCharsets.UTF_8); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "add_symbols")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "add_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_symbols")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "set_macros")); + assertEquals(1, countOccurrencesOfSubstring(ion11Text, "(:Pi)")); + assertEquals(2, countOccurrencesOfSubstring(ion11Text, "(:foo)")); + } + } } @Test - public void readIon10ConvertedFromIon11WithMacros() throws Exception { - ReadOptionsCombination optionsCombination = parseSingleOptionsCombination( + public void readIon11WithMacrosAndFlushPeriodFromBinary() throws Exception { + readIon11WithMacrosAndFlushPeriod("binaryMacroInvocations.10n"); + } + + @Test + public void readIon11WithMacrosAndFlushPeriodFromText() throws Exception { + readIon11WithMacrosAndFlushPeriod("textMacroInvocations.ion"); + } + + private void readIon10ConvertedFromIon11WithMacros(String inputFile) throws Exception { + List optionsCombinations = parseOptionsCombinations( "read", "--format", "ion_text", + "--format", + "ion_binary", "--ion-minor-version", "0", // This forces a conversion that cannot preserve the encoding directives or macro invocations. "--io-type", "buffer", - "binaryMacroInvocations.10n" - ); - assertReadTaskExecutesCorrectly( - "binaryMacroInvocations.10n", - optionsCombination, - Format.ION_TEXT, - true + inputFile ); + assertEquals(2, optionsCombinations.size()); // output format text, output format binary + for (ReadOptionsCombination optionsCombination : optionsCombinations) { + assertReadTaskExecutesCorrectly( + inputFile, + optionsCombination, + optionsCombination.format, + true + ); + } } - // TODO test writing Ion 1.1 binary from Ion 1.1 text input (once supported by IonJava). + @Test + public void readIon10ConvertedFromIon11WithMacrosFromBinary() throws Exception { + readIon10ConvertedFromIon11WithMacros("binaryMacroInvocations.10n"); + } + + @Test + public void readIon10ConvertedFromIon11WithMacrosFromText() throws Exception { + readIon10ConvertedFromIon11WithMacros("textMacroInvocations.ion"); + } } diff --git a/tst/com/amazon/ion/benchmark/binaryAllTypes11.10n b/tst/com/amazon/ion/benchmark/binaryAllTypes11.10n index 01b7504..e5f2fe6 100644 Binary files a/tst/com/amazon/ion/benchmark/binaryAllTypes11.10n and b/tst/com/amazon/ion/benchmark/binaryAllTypes11.10n differ diff --git a/tst/com/amazon/ion/benchmark/binaryMacroInvocations.10n b/tst/com/amazon/ion/benchmark/binaryMacroInvocations.10n index f563c29..492c40c 100644 Binary files a/tst/com/amazon/ion/benchmark/binaryMacroInvocations.10n and b/tst/com/amazon/ion/benchmark/binaryMacroInvocations.10n differ diff --git a/tst/com/amazon/ion/benchmark/textMacroInvocations.ion b/tst/com/amazon/ion/benchmark/textMacroInvocations.ion index bb3ec30..6efb724 100644 --- a/tst/com/amazon/ion/benchmark/textMacroInvocations.ion +++ b/tst/com/amazon/ion/benchmark/textMacroInvocations.ion @@ -7,12 +7,12 @@ $ion_1_1 (:$ion::add_macros ( macro - $66 + $64 () 3.14159 ) ) -$66 +$64 (:Pi) (:$ion::set_symbols (::