| /* |
| * 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. |
| */ |
| package org.apache.tuweni.toml; |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertFalse; |
| import static org.junit.jupiter.api.Assertions.assertNotNull; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| import static org.junit.jupiter.api.Assertions.fail; |
| |
| import java.io.InputStream; |
| import java.time.LocalDate; |
| import java.time.LocalDateTime; |
| import java.time.LocalTime; |
| import java.time.OffsetDateTime; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.params.ParameterizedTest; |
| import org.junit.jupiter.params.provider.Arguments; |
| import org.junit.jupiter.params.provider.MethodSource; |
| |
| class TomlTest { |
| |
| @Test |
| void shouldParseEmptyDocument() { |
| TomlParseResult result = Toml.parse("\n"); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| } |
| |
| @Test |
| void shouldParseSimpleKey() { |
| TomlParseResult result = Toml.parse("foo = 'bar'"); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals("bar", result.getString("foo")); |
| } |
| |
| @Test |
| void shouldParseQuotedKey() { |
| TomlParseResult result = Toml.parse("\"foo\\nba\\\"r\" = 0b11111111"); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(Long.valueOf(255), result.getLong(Collections.singletonList("foo\nba\"r"))); |
| } |
| |
| @Test |
| void shouldParseDottedKey() { |
| TomlParseResult result = Toml.parse(" foo . \" bar\\t\" . -baz = 0x000a"); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(Long.valueOf(10), result.getLong(Arrays.asList("foo", " bar\t", "-baz"))); |
| } |
| |
| @Test |
| void shouldNotParseDottedKeysAtV0_4_0OrEarlier() { |
| TomlParseResult result = Toml.parse("[foo]\n bar.baz = 1", TomlVersion.V0_4_0); |
| assertTrue(result.hasErrors()); |
| TomlParseError error = result.errors().get(0); |
| assertEquals("Dotted keys are not supported", error.getMessage()); |
| assertEquals(2, error.position().line()); |
| assertEquals(2, error.position().column()); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("stringSupplier") |
| void shouldParseString(String input, String expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getString("foo")); |
| } |
| |
| private static Stream<Arguments> stringSupplier() { |
| return Stream.of( |
| Arguments.of("foo = \"\"", ""), |
| Arguments.of("foo = \"\\\"\"", "\""), |
| Arguments.of("foo = \"bar \\b \\f \\n \\\\ \\u0053 \\U0010FfFf baz\"", "bar \b \f \n \\ S \uDBFF\uDFFF baz"), |
| Arguments.of("foo = \"\"\"\"\"\"", ""), |
| Arguments.of("foo = \"\"\" foo\nbar\"\"\"", " foo" + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"\"\"\n foobar\"\"\"", " foobar"), |
| Arguments.of("foo = \"\"\"\n foo\nbar\"\"\"", " foo" + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"\"\"\\n foo\nbar\"\"\"", "\n foo" + System.lineSeparator() + "bar"), |
| Arguments |
| .of("foo = \"\"\"\n\n foo\nbar\"\"\"", System.lineSeparator() + " foo" + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"\"\" foo \\ \nbar\"\"\"", " foo " + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"\"\" foo \\\nbar\"\"\"", " foo " + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"\"\" foo \\ \nbar\"\"\"", " foo " + System.lineSeparator() + "bar"), |
| Arguments.of("foo = \"foobar#\" # comment", "foobar#"), |
| Arguments.of("foo = \"foobar#\"", "foobar#"), |
| Arguments.of("foo = \"foo \\\" bar #\" # \"baz\"", "foo \" bar #"), |
| Arguments.of("foo = ''", ""), |
| Arguments.of("foo = '\"'", "\""), |
| Arguments.of("foo = 'foobar \\'", "foobar \\"), |
| Arguments.of("foo = '''foobar \n'''", "foobar " + System.lineSeparator()), |
| Arguments.of("foo = '''\nfoobar \n'''", "foobar " + System.lineSeparator()), |
| Arguments.of("foo = '''\nfoobar \\ \n'''", "foobar \\ " + System.lineSeparator()), |
| Arguments.of("# I am a comment. Hear me roar. Roar.\nfoo = \"value\" # Yeah, you can do this.", "value"), |
| Arguments.of( |
| "foo = \"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\"", |
| "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."), |
| Arguments.of( |
| "foo=\"\"\"\nRoses are red\nViolets are blue\"\"\"", |
| "Roses are red" + System.lineSeparator() + "Violets are blue")); |
| } |
| |
| @Test |
| void shouldFailForInvalidUnicodeEscape() { |
| TomlParseResult result = Toml.parse("foo = \"\\UFFFF00FF\""); |
| assertTrue(result.hasErrors()); |
| TomlParseError error = result.errors().get(0); |
| assertEquals("Invalid unicode escape sequence", error.getMessage()); |
| assertEquals(1, error.position().line()); |
| assertEquals(8, error.position().column()); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("integerSupplier") |
| void shouldParseInteger(String input, Long expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getLong("foo")); |
| } |
| |
| private static Stream<Arguments> integerSupplier() { |
| return Stream.of( |
| Arguments.of("foo = 1", 1L), |
| Arguments.of("foo = 0", 0L), |
| Arguments.of("foo = 100", 100L), |
| Arguments.of("foo = -9876", -9876L), |
| Arguments.of("foo = +5_433", 5433L), |
| Arguments.of("foo = 0xff", 255L), |
| Arguments.of("foo = 0xffbccd34", 4290563380L), |
| Arguments.of("foo = 0o7656", 4014L), |
| Arguments.of("foo = 0o0007_6543_21", 2054353L), |
| Arguments.of("foo = 0b11111100010101_0100000000111111111", 8466858495L), |
| Arguments.of("foo = 0b0000000_00000000000000000000000000", 0L), |
| Arguments.of("foo = 0b111111111111111111111111111111111", 8589934591L)); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("floatSupplier") |
| void shouldParseFloat(String input, Double expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getDouble("foo")); |
| } |
| |
| private static Stream<Arguments> floatSupplier() { |
| // @formatter:off |
| return Stream.of( |
| Arguments.of("foo = 0.0", 0D), |
| Arguments.of("foo = 0E100", 0D), |
| Arguments.of("foo = 0.00e+100", 0D), |
| Arguments.of("foo = 0.00e-100", 0D), |
| Arguments.of("foo = +0.0", 0D), |
| Arguments.of("foo = -0.0", -0D), |
| Arguments.of("foo = 0.000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000", 0D), |
| Arguments.of("foo = -0.0E999999999999999999999999999999999999999", -0D), |
| Arguments.of("foo = 1.0", 1D), |
| Arguments.of("foo = 43.55E34", 43.55E34D), |
| Arguments.of("foo = 43.557_654E-34", 43.557654E-34D), |
| Arguments.of("foo = inf", Double.POSITIVE_INFINITY), |
| Arguments.of("foo = +inf", Double.POSITIVE_INFINITY), |
| Arguments.of("foo = -inf", Double.NEGATIVE_INFINITY), |
| Arguments.of("foo = nan", Double.NaN), |
| Arguments.of("foo = +nan", Double.NaN), |
| Arguments.of("foo = -nan", Double.NaN) |
| ); |
| // @formatter:on |
| } |
| |
| @Test |
| void shouldParseBoolean() { |
| TomlParseResult result = Toml.parse("foo = true"); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(Boolean.TRUE, result.getBoolean("foo")); |
| TomlParseResult result2 = Toml.parse("\nfoo=false"); |
| assertFalse(result2.hasErrors(), () -> joinErrors(result2)); |
| assertEquals(Boolean.FALSE, result2.getBoolean("foo")); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("offsetDateSupplier") |
| void shouldParseOffsetDateTime(String input, OffsetDateTime expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getOffsetDateTime("foo")); |
| } |
| |
| private static Stream<Arguments> offsetDateSupplier() { |
| // @formatter:off |
| return Stream.of( |
| Arguments.of("foo = 1937-07-18T03:25:43-04:00", OffsetDateTime.parse("1937-07-18T03:25:43-04:00")), |
| Arguments.of("foo = 1937-07-18 11:44:02+18:00", OffsetDateTime.parse("1937-07-18T11:44:02+18:00")), |
| Arguments.of("foo = 0000-07-18 11:44:02.00+18:00", OffsetDateTime.parse("0000-07-18T11:44:02+18:00")), |
| Arguments.of("foo = 1979-05-27T07:32:00Z\nbar = 1979-05-27T00:32:00-07:00\n", |
| OffsetDateTime.parse("1979-05-27T07:32:00Z")), |
| Arguments.of("bar = 1979-05-27T07:32:00Z\nfoo = 1979-05-27T00:32:00-07:00\n", |
| OffsetDateTime.parse("1979-05-27T00:32:00-07:00")), |
| Arguments.of("foo = 1937-07-18 11:44:02.334543+18:00", |
| OffsetDateTime.parse("1937-07-18T11:44:02.334543+18:00")), |
| Arguments.of("foo = 1937-07-18 11:44:02Z", OffsetDateTime.parse("1937-07-18T11:44:02+00:00")) |
| ); |
| // @formatter:on |
| } |
| |
| @ParameterizedTest |
| @MethodSource("localDateTimeSupplier") |
| void shouldParseLocalDateTime(String input, LocalDateTime expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getLocalDateTime("foo")); |
| } |
| |
| private static Stream<Arguments> localDateTimeSupplier() { |
| return Stream.of( |
| Arguments.of("foo = 1937-07-18T03:25:43", LocalDateTime.parse("1937-07-18T03:25:43")), |
| Arguments.of("foo = 1937-07-18 11:44:02", LocalDateTime.parse("1937-07-18T11:44:02")), |
| Arguments.of("foo = 0000-07-18 11:44:02.00", LocalDateTime.parse("0000-07-18T11:44:02")), |
| Arguments.of("foo = 1937-07-18 11:44:02.334543", LocalDateTime.parse("1937-07-18T11:44:02.334543")), |
| Arguments.of("foo = 1937-07-18 11:44:02", LocalDateTime.parse("1937-07-18T11:44:02"))); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("localDateSupplier") |
| void shouldParseLocalDate(String input, LocalDate expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getLocalDate("foo")); |
| } |
| |
| private static Stream<Arguments> localDateSupplier() { |
| return Stream.of( |
| Arguments.of("foo = 1937-07-18", LocalDate.parse("1937-07-18")), |
| Arguments.of("foo = 1937-07-18", LocalDate.parse("1937-07-18")), |
| Arguments.of("foo = 0000-07-18", LocalDate.parse("0000-07-18")), |
| Arguments.of("foo = 1937-07-18", LocalDate.parse("1937-07-18")), |
| Arguments.of("foo = 1937-07-18", LocalDate.parse("1937-07-18"))); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("localTimeSupplier") |
| void shouldParseLocalTime(String input, LocalTime expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.getLocalTime("foo")); |
| } |
| |
| private static Stream<Arguments> localTimeSupplier() { |
| return Stream.of( |
| Arguments.of("foo = 03:25:43", LocalTime.parse("03:25:43")), |
| Arguments.of("foo = 11:44:02", LocalTime.parse("11:44:02")), |
| Arguments.of("foo = 11:44:02.00", LocalTime.parse("11:44:02")), |
| Arguments.of("foo = 11:44:02.334543", LocalTime.parse("11:44:02.334543")), |
| Arguments.of("foo = 11:44:02", LocalTime.parse("11:44:02"))); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("arraySupplier") |
| void shouldParseArray(String input, Object[] expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| TomlArray array = result.getArray("foo"); |
| assertNotNull(array); |
| assertEquals(expected.length, array.size()); |
| assertTomlArrayEquals(expected, array); |
| } |
| |
| private static Stream<Arguments> arraySupplier() { |
| return Stream.of( |
| Arguments.of("foo = []", new Object[0]), |
| Arguments.of("foo = [\n]", new Object[0]), |
| Arguments.of("foo = [1]", new Object[] {1L}), |
| Arguments.of("foo = [ \"bar\"\n]", new Object[] {"bar"}), |
| Arguments.of("foo = [11:44:02,]", new Object[] {LocalTime.parse("11:44:02")}), |
| Arguments.of("foo = [\n'bar', #baz\n]", new Object[] {"bar"}), |
| Arguments.of("foo = ['bar', 'baz']", new Object[] {"bar", "baz"}), |
| Arguments |
| .of("foo = [\n'''bar\nbaz''',\n'baz'\n]", new Object[] {"bar" + System.lineSeparator() + "baz", "baz"}), |
| Arguments.of("foo = [['bar']]", new Object[] {new Object[] {"bar"}})); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("tableSupplier") |
| void shouldParseTable(String input, String key, Object expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.get(key)); |
| } |
| |
| private static Stream<Arguments> tableSupplier() { |
| return Stream.of( |
| Arguments.of("[foo]\nbar = 'baz'", "foo.bar", "baz"), |
| Arguments.of("[foo] #foo.bar\nbar = 'baz'", "foo.bar", "baz"), |
| Arguments.of("[foo]\n[foo.bar]\nbaz = 'buz'", "foo.bar.baz", "buz"), |
| Arguments.of("[foo.bar]\nbaz=1\n[foo]\nbaz=2", "foo.baz", 2L)); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("inlineTableSupplier") |
| void shouldParseInlineTable(String input, String key, Object expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| assertEquals(expected, result.get(key)); |
| } |
| |
| private static Stream<Arguments> inlineTableSupplier() { |
| return Stream.of( |
| Arguments.of("foo = {}", "foo.bar", null), |
| Arguments.of("foo = { bar = 'baz' }", "foo.bar", "baz"), |
| Arguments.of("foo = { bar = 'baz', baz.buz = 2 }", "foo.baz.buz", 2L), |
| Arguments.of("foo = { bar = ['baz', 'buz'] , baz . buz = 2 }", "foo.baz.buz", 2L), |
| Arguments.of("foo = { bar = ['baz',\n'buz'\n], baz.buz = 2 }", "foo.baz.buz", 2L), |
| Arguments.of("bar = { bar = ['baz',\n'buz'\n], baz.buz = 2 }\nfoo=2\n", "foo", 2L)); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("arrayTableSupplier") |
| void shouldParseArrayTable(String input, Object[] path, Object expected) { |
| TomlParseResult result = Toml.parse(input); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| |
| Object element = result; |
| for (Object step : path) { |
| if (step instanceof String) { |
| assertTrue(element instanceof TomlTable); |
| element = ((TomlTable) element).get((String) step); |
| } else if (step instanceof Integer) { |
| assertTrue(element instanceof TomlArray); |
| element = ((TomlArray) element).get((Integer) step); |
| } else { |
| fail("path not found"); |
| } |
| } |
| assertEquals(expected, element); |
| } |
| |
| private static Stream<Arguments> arrayTableSupplier() { |
| return Stream.of( |
| Arguments.of("[[foo]]\nbar = 'baz'", new Object[] {"foo", 0, "bar"}, "baz"), |
| Arguments.of("[[foo]] #foo.bar\nbar = 'baz'", new Object[] {"foo", 0, "bar"}, "baz"), |
| Arguments.of("[[foo]] \n bar = 'buz'\nbuz=1\n", new Object[] {"foo", 0, "buz"}, 1L), |
| Arguments.of("[[foo]] \n bar = 'buz'\n[[foo]]\nbar=1\n", new Object[] {"foo", 0, "bar"}, "buz"), |
| Arguments.of("[[foo]] \n bar = 'buz'\n[[foo]]\nbar=1\n", new Object[] {"foo", 1, "bar"}, 1L), |
| Arguments.of("[[foo]]\nbar=1\n[[foo]]\nbar=2\n", new Object[] {"foo", 0, "bar"}, 1L), |
| Arguments.of("[[foo]]\nbar=1\n[[foo]]\nbar=2\n", new Object[] {"foo", 1, "bar"}, 2L), |
| Arguments.of("[[foo]]\n\n[foo.bar]\n\nbaz=2\n\n", new Object[] {"foo", 0, "bar", "baz"}, 2L), |
| Arguments.of( |
| "[[foo]]\n[[foo.bar]]\n[[foo.baz]]\n[foo.bar.baz]\nbuz=2\n[foo.baz.buz]\nbiz=3\n", |
| new Object[] {"foo", 0, "bar", 0, "baz", "buz"}, |
| 2L), |
| Arguments.of( |
| "[[foo]]\n[[foo.bar]]\n[[foo.baz]]\n[foo.bar.baz]\nbuz=2\n[foo.baz.buz]\nbiz=3\n", |
| new Object[] {"foo", 0, "baz", 0, "buz", "biz"}, |
| 3L)); |
| } |
| |
| @ParameterizedTest |
| @MethodSource("errorCaseSupplier") |
| void shouldHandleParseErrors(String input, int line, int column, String expected) { |
| TomlParseResult result = Toml.parse(input); |
| List<TomlParseError> errors = result.errors(); |
| assertFalse(errors.isEmpty()); |
| assertEquals(expected, errors.get(0).getMessage(), () -> joinErrors(result)); |
| assertEquals(line, errors.get(0).position().line()); |
| assertEquals(column, errors.get(0).position().column()); |
| } |
| |
| private static Stream<Arguments> errorCaseSupplier() { |
| // @formatter:off |
| return Stream.of( |
| Arguments.of("\"foo\"", 1, 6, "Unexpected end of input, expected . or ="), |
| Arguments.of("foo", 1, 4, "Unexpected end of input, expected . or ="), |
| Arguments.of("foo \n", 1, 6, "Unexpected end of line, expected . or ="), |
| Arguments.of("foo =", 1, 6, "Unexpected end of input, expected ', \", ''', \"\"\", a number, a boolean, a date/time, an array, or a table"), |
| Arguments.of("foo = 0b", 1, 8, "Unexpected 'b', expected a newline or end-of-input"), |
| Arguments.of("foo = +", 1, 7, "Unexpected '+', expected ', \", ''', \"\"\", a number, a boolean, a date/time, an array, or a table"), |
| Arguments.of("=", 1, 1, "Unexpected '=', expected a-z, A-Z, 0-9, ', \", a table key, a newline, or end-of-input"), |
| Arguments.of("\"foo\tbar\" = 1", 1, 5, "Unexpected '\\t', expected \" or a character"), |
| Arguments.of("\"foo \nbar\" = 1", 1, 6, "Unexpected end of line, expected \" or a character"), |
| Arguments.of("foo = \"bar \\y baz\"", 1, 12, "Invalid escape sequence '\\y'"), |
| Arguments.of("\u0011abc = 'foo'", 1, 1, "Unexpected '\\u0011', expected a-z, A-Z, 0-9, ', \", a table key, a newline, or end-of-input"), |
| Arguments.of(" \uDBFF\uDFFFAAabc='foo'", 1, 2, "Unexpected '\\U0010ffff', expected a-z, A-Z, 0-9, ', \", a table key, a newline, or end-of-input"), |
| |
| Arguments.of("foo = 1234567891234567891233456789", 1, 7, "Integer is too large"), |
| |
| Arguments.of("\n\nfoo = \t +1E1000", 3, 18, "Float is too large"), |
| Arguments.of("foo = +1E-1000", 1, 7, "Float is too small"), |
| Arguments.of("foo = 0.000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000000000" |
| + "000000000000000000000000000000000000000000000000000001", 1, 7, "Float is too small"), |
| |
| Arguments.of("\nfoo = 1937-47-18-00:00:00-04:00", 2, 17, "Unexpected '-', expected a newline or end-of-input"), |
| Arguments.of("\nfoo = 1937-47-18 00:00:00-04:00", 2, 19, "Unexpected '00', expected a newline or end-of-input"), |
| Arguments.of("\nfoo = 2334567891233457889-07-18T00:00:00-04:00", 2, 7, "Invalid year (valid range 0000..9999)"), |
| Arguments.of("\nfoo = 2-07-18T00:00:00-04:00", 2, 7, "Invalid year (valid range 0000..9999)"), |
| Arguments.of("\nfoo = -07-18T00:00:00-04:00", 2, 9, "Unexpected '7-18T00', expected a newline or end-of-input"), |
| Arguments.of("\nfoo = 1937-47-18T00:00:00-04:00", 2, 12, "Invalid month (valid range 01..12)"), |
| Arguments.of("\nfoo = 1937-7-18T00:00:00-04:00", 2, 12, "Invalid month (valid range 01..12)"), |
| Arguments.of("\nfoo = 1937-00-18T00:00:00-04:00", 2, 12, "Invalid month (valid range 01..12)"), |
| Arguments.of("\nfoo = 1937--18T00:00:00-04:00", 2, 12, "Unexpected '-', expected a date/time"), |
| Arguments.of("\nfoo = 1937-07-48T00:00:00-04:00", 2, 15, "Invalid day (valid range 01..28/31)"), |
| Arguments.of("\nfoo = 1937-07-8T00:00:00-04:00", 2, 15, "Invalid day (valid range 01..28/31)"), |
| Arguments.of("\nfoo = 1937-07-00T00:00:00-04:00", 2, 15, "Invalid day (valid range 01..28/31)"), |
| Arguments.of("\nfoo = 1937-02-30T00:00:00-04:00", 2, 15, "Invalid date 'FEBRUARY 30'"), |
| Arguments.of("\nfoo = 1937-07-18T30:00:00-04:00", 2, 18, "Invalid hour (valid range 00..23)"), |
| Arguments.of("\nfoo = 1937-07-18T3:00:00-04:00", 2, 18, "Invalid hour (valid range 00..23)"), |
| Arguments.of("\nfoo = 1937-07-18T13:70:00-04:00", 2, 21, "Invalid minutes (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:7:00-04:00", 2, 21, "Invalid minutes (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:92-04:00", 2, 24, "Invalid seconds (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:2-04:00", 2, 24, "Invalid seconds (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:02.0000000009-04:00", 2, 27, "Invalid nanoseconds (valid range 0..999999999)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:02.-04:00", 2, 27, "Unexpected '-', expected a date/time"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:26-25:00", 2, 26, "Invalid zone offset hours (valid range -18..+18)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:26-:00", 2, 27, "Unexpected ':', expected a date/time"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:26-04:60", 2, 30, "Invalid zone offset minutes (valid range 0..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:26-18:30", 2, 26, "Invalid zone offset (valid range -18:00..+18:00)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:26-18:", 2, 30, "Unexpected end of input, expected a date/time"), |
| |
| Arguments.of("\nfoo = 2334567891233457889-07-18T00:00:00", 2, 7, "Invalid year (valid range 0000..9999)"), |
| Arguments.of("\nfoo = 1937-47-18T00:00:00", 2, 12, "Invalid month (valid range 01..12)"), |
| Arguments.of("\nfoo = 1937-07-48T00:00:00", 2, 15, "Invalid day (valid range 01..28/31)"), |
| Arguments.of("\nfoo = 1937-07-18T30:00:00", 2, 18, "Invalid hour (valid range 00..23)"), |
| Arguments.of("\nfoo = 1937-07-18T13:70:00", 2, 21, "Invalid minutes (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:92", 2, 24, "Invalid seconds (valid range 00..59)"), |
| Arguments.of("\nfoo = 1937-07-18T13:55:02.0000000009", 2, 27, "Invalid nanoseconds (valid range 0..999999999)"), |
| |
| Arguments.of("\nfoo = 2334567891233457889-07-18", 2, 7, "Invalid year (valid range 0000..9999)"), |
| Arguments.of("\nfoo = 1937-47-18", 2, 12, "Invalid month (valid range 01..12)"), |
| Arguments.of("\nfoo = 1937-07-48", 2, 15, "Invalid day (valid range 01..28/31)"), |
| |
| Arguments.of("\nfoo = 30:00:00", 2, 7, "Invalid hour (valid range 00..23)"), |
| Arguments.of("\nfoo = 13:70:00", 2, 10, "Invalid minutes (valid range 00..59)"), |
| Arguments.of("\nfoo = 13:55:92", 2, 13, "Invalid seconds (valid range 00..59)"), |
| Arguments.of("\nfoo = 13:55:02.0000000009", 2, 16, "Invalid nanoseconds (valid range 0..999999999)"), |
| |
| Arguments.of("foo = [", 1, 8, "Unexpected end of input, expected ], ', \", ''', \"\"\", a number, a boolean, a date/time, an array, a table, or a newline"), |
| Arguments.of("foo = [ 1\n", 2, 1, "Unexpected end of input, expected ] or a newline"), |
| Arguments.of("foo = [ 1, 'bar' ]", 1, 12, "Cannot add a string to an array containing integers"), |
| Arguments.of("foo = [ 1, 'bar ]\n", 1, 18, "Unexpected end of line, expected '"), |
| |
| Arguments.of("[]", 1, 1, "Empty table key"), |
| Arguments.of("[foo] bar='baz'", 1, 7, "Unexpected 'bar', expected a newline or end-of-input"), |
| Arguments.of("foo='bar'\n[foo]\nbar='baz'", 2, 1, "foo previously defined at line 1, column 1"), |
| Arguments.of("[foo]\nbar='baz'\n[foo]\nbaz=1", 3, 1, "foo previously defined at line 1, column 1"), |
| Arguments.of("[foo]\nbar='baz'\n[foo.bar]\nbaz=1", 3, 1, "foo.bar previously defined at line 2, column 1"), |
| |
| Arguments.of("foo = {", 1, 8, "Unexpected end of input, expected a-z, A-Z, 0-9, }, ', or \""), |
| Arguments.of("foo = { bar = 1,\nbaz = 2 }", 1, 17, "Unexpected end of line, expected a-z, A-Z, 0-9, ', or \""), |
| Arguments.of("foo = { bar = 1\nbaz = 2 }", 1, 16, "Unexpected end of line, expected }"), |
| Arguments.of("foo = { bar = 1 baz = 2 }", 1, 17, "Unexpected 'baz', expected } or a comma"), |
| |
| Arguments.of("[foo]\nbar=1\n[[foo]]\nbar=2\n", 3, 1, "foo is not an array (previously defined at line 1, column 1)"), |
| Arguments.of("foo = [1]\n[[foo]]\nbar=2\n", 2, 1, "foo previously defined as a literal array at line 1, column 1"), |
| Arguments.of("foo = []\n[[foo]]\nbar=2\n", 2, 1, "foo previously defined as a literal array at line 1, column 1"), |
| Arguments.of("[[foo.bar]]\n[foo]\nbaz=2\nbar=3\n", 4, 1, "bar previously defined at line 1, column 1"), |
| Arguments.of("[[foo]]\nbaz=1\n[[foo.bar]]\nbaz=2\n[foo.bar]\nbaz=3\n", 5, 1, "foo.bar previously defined at line 3, column 1") |
| ); |
| // @formatter:on |
| } |
| |
| @Test |
| void testTomlV0_4_0Example() throws Exception { |
| InputStream is = this.getClass().getResourceAsStream("/org/apache/tuweni/toml/example-v0.4.0.toml"); |
| assertNotNull(is); |
| TomlParseResult result = Toml.parse(is, TomlVersion.V0_4_0); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| |
| assertEquals("value", result.getString("table.key")); |
| assertEquals("Preston-Werner", result.getString("table.inline.name.last")); |
| assertEquals("<\\i\\c*\\s*>", result.getString("string.literal.regex")); |
| assertEquals(2L, result.getArray("array.key5").getLong(1)); |
| assertEquals( |
| "granny smith", |
| result.getArray("fruit").getTable(0).getArray("variety").getTable(1).getString("name")); |
| } |
| |
| @Test |
| void testHardExample() throws Exception { |
| InputStream is = this.getClass().getResourceAsStream("/org/apache/tuweni/toml/hard_example.toml"); |
| assertNotNull(is); |
| TomlParseResult result = Toml.parse(is, TomlVersion.V0_4_0); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| |
| assertEquals("You'll hate me after this - #", result.getString("the.test_string")); |
| assertEquals(" And when \"'s are in the string, along with # \"", result.getString("the.hard.harder_test_string")); |
| assertEquals("]", result.getArray("the.hard.'bit#'.multi_line_array").getString(0)); |
| } |
| |
| @Test |
| void testHardExampleUnicode() throws Exception { |
| InputStream is = this.getClass().getResourceAsStream("/org/apache/tuweni/toml/hard_example_unicode.toml"); |
| assertNotNull(is); |
| TomlParseResult result = Toml.parse(is, TomlVersion.V0_4_0); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| |
| assertEquals("Ýôú'ℓℓ λáƭè ₥è áƒƭèř ƭλïƨ - #", result.getString("the.test_string")); |
| assertEquals(" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"", result.getString("the.hard.harder_test_string")); |
| assertEquals("]", result.getArray("the.hard.'βïƭ#'.multi_line_array").getString(0)); |
| } |
| |
| @Test |
| void testSpecExample() throws Exception { |
| InputStream is = this.getClass().getResourceAsStream("/org/apache/tuweni/toml/toml-v0.5.0-spec-example.toml"); |
| assertNotNull(is); |
| TomlParseResult result = Toml.parse(is, TomlVersion.V0_4_0); |
| assertFalse(result.hasErrors(), () -> joinErrors(result)); |
| |
| assertEquals("Tom Preston-Werner", result.getString("owner.name")); |
| assertEquals(OffsetDateTime.parse("1979-05-27T07:32:00-08:00"), result.getOffsetDateTime("owner.dob")); |
| |
| assertEquals("10.0.0.2", result.getString("servers.beta.ip")); |
| TomlArray clientHosts = result.getArray("clients.hosts"); |
| assertNotNull(clientHosts); |
| assertTrue(clientHosts.containsStrings()); |
| assertEquals(Arrays.asList("alpha", "omega"), clientHosts.toList()); |
| } |
| |
| @Test |
| void testDottedKeyOrder() throws Exception { |
| TomlParseResult result1 = Toml.parse("[dog.\"tater.man\"]\ntype.name = \"pug\""); |
| assertFalse(result1.hasErrors(), () -> joinErrors(result1)); |
| TomlParseResult result2 = Toml.parse("a.b.c = 1\na.d = 2\n"); |
| assertFalse(result2.hasErrors(), () -> joinErrors(result2)); |
| TomlParseResult result3 = Toml.parse("# THIS IS INVALID\na.b = 1\na.b.c = 2\n"); |
| assertTrue(result3.hasErrors()); |
| } |
| |
| private String joinErrors(TomlParseResult result) { |
| return result.errors().stream().map(TomlParseError::toString).collect(Collectors.joining("\n")); |
| } |
| |
| private static void assertTomlArrayEquals(Object[] expected, TomlArray array) { |
| for (int i = 0; i < expected.length; ++i) { |
| Object obj = array.get(i); |
| if (expected[i] instanceof Object[]) { |
| assertTrue(obj instanceof TomlArray); |
| assertTomlArrayEquals((Object[]) expected[i], (TomlArray) obj); |
| } else { |
| assertEquals(expected[i], obj); |
| } |
| } |
| } |
| } |