diff options
| author | Michael Williamson <mike@zwobble.org> | 2025-01-01 01:39:18 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2025-01-01 09:45:58 +0000 |
| commit | b65c719e2b65a9662b6170b0b53dfed9f1a3edcd (patch) | |
| tree | 6700b1a717d01a83b644dd06eb508e12a43b492c /src/test/java/org | |
| parent | 0df6725da8a0953c5643c5692c5244826e448d09 (diff) | |
Use JSON5 instead of TOML for config
Diffstat (limited to 'src/test/java/org')
7 files changed, 539 insertions, 446 deletions
diff --git a/src/test/java/org/shedlang/compiler/config/BinConfigTests.java b/src/test/java/org/shedlang/compiler/config/BinConfigTests.java index aead8546..d909bb84 100644 --- a/src/test/java/org/shedlang/compiler/config/BinConfigTests.java +++ b/src/test/java/org/shedlang/compiler/config/BinConfigTests.java @@ -2,7 +2,7 @@ package org.shedlang.compiler.config; import org.junit.jupiter.api.Test; import org.shedlang.compiler.config.errors.ConfigError; -import org.shedlang.compiler.config.toml.TomlTableWithSource; +import org.shedlang.compiler.config.json.Json5ObjectWithSource; import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.types.NamespaceName; @@ -14,11 +14,13 @@ public class BinConfigTests { @Test public void canParseBinConfigWithNameAndMainNamespace() { var source = Sources.string(""" - name = "one" - main-namespace = "A/B" + { + name: "one", + mainNamespace: "A/B", + } """); - var config = BinConfig.fromToml(TomlTableWithSource.parse(source)); + var config = BinConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, allOf( has("name", x -> x.name(), equalTo("one")), @@ -28,13 +30,15 @@ public class BinConfigTests { @Test public void whenMainNamespaceHasSyntaxErrorThenErrorIsThrown() { var source = Sources.string(""" - name = "one" - main-namespace = "A.B" + { + name: "one", + mainNamespace: "A.B", + } """); var error = assertThrows( ConfigError.class, - () -> BinConfig.fromToml(TomlTableWithSource.parse(source)) + () -> BinConfig.fromJson5(Json5ObjectWithSource.parse(source)) ); assertThat(error.getMessage(), equalTo(""" @@ -46,8 +50,8 @@ public class BinConfigTests { A.B ^""")); assertThat(error.source().describe(), equalTo(""" - <string>:2:1 - main-namespace = "A.B" - ^""")); + <string>:3:20 + mainNamespace: "A.B", + ^""")); } } diff --git a/src/test/java/org/shedlang/compiler/config/GcConfigTests.java b/src/test/java/org/shedlang/compiler/config/GcConfigTests.java index 6803cf70..351d3d5b 100644 --- a/src/test/java/org/shedlang/compiler/config/GcConfigTests.java +++ b/src/test/java/org/shedlang/compiler/config/GcConfigTests.java @@ -1,7 +1,7 @@ package org.shedlang.compiler.config; import org.junit.jupiter.api.Test; -import org.shedlang.compiler.config.toml.TomlTableWithSource; +import org.shedlang.compiler.config.json.Json5ObjectWithSource; import org.shedlang.compiler.sources.Sources; import java.util.OptionalLong; @@ -14,12 +14,14 @@ public class GcConfigTests { @Test public void whenNameIsUnrecognisedThenErrorIsThrown() { var source = Sources.string(""" - name = "huh" + { + name: "huh", + } """); var error = assertThrows( IllegalArgumentException.class, - () -> GcConfig.fromToml(TomlTableWithSource.parse(source)) + () -> GcConfig.fromJson5(Json5ObjectWithSource.parse(source)) ); assertThat(error.getMessage(), equalTo("Unrecognised GC name: \"huh\"")); @@ -28,10 +30,12 @@ public class GcConfigTests { @Test public void canParseConfigForBump() { var source = Sources.string(""" - name = "bump" + { + "name": "bump", + } """); - var config = GcConfig.fromToml(TomlTableWithSource.parse(source)); + var config = GcConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, instanceOf(GcBumpConfig.class)); } @@ -39,10 +43,12 @@ public class GcConfigTests { @Test public void canParseMinimalConfigForMarkAndSweep() { var source = Sources.string(""" - name = "mark-and-sweep" + { + name: "mark-and-sweep", + } """); - var config = GcConfig.fromToml(TomlTableWithSource.parse(source)); + var config = GcConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, instanceOf(GcMarkAndSweepConfig.class)); } @@ -50,11 +56,13 @@ public class GcConfigTests { @Test public void additionalFieldsCanBeUsedBySpecificGcConfig() { var source = Sources.string(""" - name = "mark-and-sweep" - collect-interval = 10000 + { + name: "mark-and-sweep", + collectInterval: 10000, + } """); - var config = GcConfig.fromToml(TomlTableWithSource.parse(source)); + var config = GcConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, instanceOf( GcMarkAndSweepConfig.class, diff --git a/src/test/java/org/shedlang/compiler/config/GcMarkAndSweepConfigTests.java b/src/test/java/org/shedlang/compiler/config/GcMarkAndSweepConfigTests.java index 91d0d234..551c29d6 100644 --- a/src/test/java/org/shedlang/compiler/config/GcMarkAndSweepConfigTests.java +++ b/src/test/java/org/shedlang/compiler/config/GcMarkAndSweepConfigTests.java @@ -1,7 +1,7 @@ package org.shedlang.compiler.config; import org.junit.jupiter.api.Test; -import org.shedlang.compiler.config.toml.TomlTableWithSource; +import org.shedlang.compiler.config.json.Json5ObjectWithSource; import org.shedlang.compiler.sources.Sources; import java.util.OptionalLong; @@ -13,9 +13,9 @@ import static org.zwobble.precisely.Matchers.has; public class GcMarkAndSweepConfigTests { @Test public void collectIntervalCanBeMissing() { - var source = Sources.string(""); + var source = Sources.string("{}"); - var config = GcMarkAndSweepConfig.fromToml(TomlTableWithSource.parse(source)); + var config = GcMarkAndSweepConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, has( "collectInterval", @@ -27,11 +27,13 @@ public class GcMarkAndSweepConfigTests { @Test public void additionalFieldsCanBeUsedBySpecificGcConfig() { var source = Sources.string(""" - name = "mark-and-sweep" - collect-interval = 10000 + { + name: "mark-and-sweep", + collectInterval: 10000, + } """); - var config = GcMarkAndSweepConfig.fromToml(TomlTableWithSource.parse(source)); + var config = GcMarkAndSweepConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, has( "collectInterval", diff --git a/src/test/java/org/shedlang/compiler/config/ProfileConfigTests.java b/src/test/java/org/shedlang/compiler/config/ProfileConfigTests.java index 7e779252..d7e5ac6f 100644 --- a/src/test/java/org/shedlang/compiler/config/ProfileConfigTests.java +++ b/src/test/java/org/shedlang/compiler/config/ProfileConfigTests.java @@ -1,7 +1,7 @@ package org.shedlang.compiler.config; import org.junit.jupiter.api.Test; -import org.shedlang.compiler.config.toml.TomlTableWithSource; +import org.shedlang.compiler.config.json.Json5ObjectWithSource; import org.shedlang.compiler.sources.Sources; import static org.zwobble.precisely.AssertThat.assertThat; @@ -11,10 +11,12 @@ public class ProfileConfigTests { @Test public void canParseProfileConfigWithName() { var source = Sources.string(""" - name = "one" + { + name: "one", + } """); - var config = ProfileConfig.fromToml(TomlTableWithSource.parse(source)); + var config = ProfileConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, has("name", x -> x.name(), equalTo("one"))); } @@ -22,10 +24,12 @@ public class ProfileConfigTests { @Test public void canParseProfileConfigWithoutGc() { var source = Sources.string(""" - name = "one" + { + name: "one", + } """); - var config = ProfileConfig.fromToml(TomlTableWithSource.parse(source)); + var config = ProfileConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, has("name", x -> x.gc(), isOptionalEmpty())); } @@ -33,11 +37,15 @@ public class ProfileConfigTests { @Test public void canParseProfileConfigWithGc() { var source = Sources.string(""" - name = "one" - gc.name = "bump" + { + name: "one", + gc: { + "name": "bump", + }, + } """); - var config = ProfileConfig.fromToml(TomlTableWithSource.parse(source)); + var config = ProfileConfig.fromJson5(Json5ObjectWithSource.parse(source)); assertThat(config, has( "gc", diff --git a/src/test/java/org/shedlang/compiler/config/ProjectConfigTests.java b/src/test/java/org/shedlang/compiler/config/ProjectConfigTests.java index 10397acf..f0deac1e 100644 --- a/src/test/java/org/shedlang/compiler/config/ProjectConfigTests.java +++ b/src/test/java/org/shedlang/compiler/config/ProjectConfigTests.java @@ -2,7 +2,7 @@ package org.shedlang.compiler.config; import org.junit.jupiter.api.Test; import org.shedlang.compiler.config.errors.ConfigError; -import org.shedlang.compiler.config.errors.TomlSyntaxConfigError; +import org.shedlang.compiler.config.errors.Json5SyntaxConfigError; import org.shedlang.compiler.types.NamespaceName; import java.nio.file.Path; @@ -17,14 +17,14 @@ public class ProjectConfigTests { @Test public void whenProjectConfigHasSyntaxErrorsOnFirstLineThenErrorIsThrown() { var error = assertThrows( - TomlSyntaxConfigError.class, - () -> ProjectConfig.fromString(PROJECT_PATH, "[x] ]x") + Json5SyntaxConfigError.class, + () -> ProjectConfig.fromString(PROJECT_PATH, "[1] ]1") ); - assertThat(error.getMessage(), equalTo("Unexpected ']', expected a newline or end-of-input")); + assertThat(error.getMessage(), equalTo("Expected end of document, but was ']'")); assertThat(error.source().describe(), equalTo(""" <string>:1:5 - [x] ]x + [1] ]1 ^""" )); } @@ -32,38 +32,21 @@ public class ProjectConfigTests { @Test public void whenProjectConfigHasSyntaxErrorsOnNonFirstLineThenErrorIsThrown() { var error = assertThrows( - TomlSyntaxConfigError.class, - () -> ProjectConfig.fromString(PROJECT_PATH, "[a]\n[x] ]x") + Json5SyntaxConfigError.class, + () -> ProjectConfig.fromString(PROJECT_PATH, "[\n1\n]\n 2") ); - assertThat(error.getMessage(), equalTo("Unexpected ']', expected a newline or end-of-input")); + assertThat(error.getMessage(), equalTo("Expected end of document, but was number '2'")); assertThat(error.source().describe(), equalTo(""" - <string>:2:5 - [x] ]x - ^""" - )); - } - - @Test - public void whenProjectConfigHasShedThatArentArrayThenErrorIsThrown() { - var error = assertThrows( - ConfigError.class, - () -> ProjectConfig.fromString(PROJECT_PATH, """ - shed = true""" - ) - ); - - assertThat(error.getMessage(), equalTo("Expected shed to be a table, but was Boolean")); - assertThat(error.source().describe(), equalTo(""" - <string>:1:1 - shed = true - ^""" + <string>:4:3 + 2 + ^""" )); } @Test public void canParseProjectConfigWithNoBins() { - var config = ProjectConfig.fromString(PROJECT_PATH, ""); + var config = ProjectConfig.fromString(PROJECT_PATH, "{}"); assertThat(config.bins(), isSequence()); } @@ -71,13 +54,18 @@ public class ProjectConfigTests { @Test public void canParseProjectConfigWithBins() { var config = ProjectConfig.fromString(PROJECT_PATH, """ - [[shed.bins]] - name = "one" - main-namespace = "One" - - [[shed.bins]] - name = "two" - main-namespace = "Two" + { + bins: [ + { + name: "one", + mainNamespace: "One", + }, + { + name: "two", + mainNamespace: "Two", + }, + ], + } """); assertThat(config.bins(), isSequence( @@ -99,40 +87,40 @@ public class ProjectConfigTests { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - bins = true""" + {bins: true}""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.bins to be an array, but was Boolean")); + assertThat(error.getMessage(), equalTo("Expected bins to be array, but was boolean")); assertThat(error.source().describe(), equalTo(""" - <string>:2:1 - bins = true - ^""" + <string>:1:8 + {bins: true} + ^""" )); } @Test - public void whenProjectConfigHasBinThatIsntTableThenErrorIsThrown() { + public void whenProjectConfigHasBinThatIsntObjectThenErrorIsThrown() { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - bins = [1]""" + { + bins: [1], + }""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.bins[0] to be a table, but was Long")); + assertThat(error.getMessage(), equalTo("Expected bins[0] to be object, but was finite number")); assertThat(error.source().describe(), equalTo(""" - <string>:2:9 - bins = [1] - ^""" + <string>:2:12 + bins: [1], + ^""" )); } @Test public void canParseProjectConfigWithNoExamples() { - var config = ProjectConfig.fromString(PROJECT_PATH, ""); + var config = ProjectConfig.fromString(PROJECT_PATH, "{}"); assertThat(config.examples(), isSequence()); } @@ -140,11 +128,12 @@ public class ProjectConfigTests { @Test public void canParseProjectConfigWithExamples() { var config = ProjectConfig.fromString(PROJECT_PATH, """ - [[shed.examples]] - bin = "one" - - [[shed.examples]] - bin = "two" + { + examples: [ + {bin: "one"}, + {bin: "two"}, + ], + } """); assertThat(config.examples(), isSequence( @@ -164,40 +153,40 @@ public class ProjectConfigTests { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - examples = true""" + {examples: true}""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.examples to be an array, but was Boolean")); + assertThat(error.getMessage(), equalTo("Expected examples to be array, but was boolean")); assertThat(error.source().describe(), equalTo(""" - <string>:2:1 - examples = true - ^""" + <string>:1:12 + {examples: true} + ^""" )); } @Test - public void whenProjectConfigHasExampleThatIsntTableThenErrorIsThrown() { + public void whenProjectConfigHasExampleThatIsntObjectThenErrorIsThrown() { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - examples = [1]""" + { + examples: [1], + }""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.examples[0] to be a table, but was Long")); + assertThat(error.getMessage(), equalTo("Expected examples[0] to be object, but was finite number")); assertThat(error.source().describe(), equalTo(""" - <string>:2:13 - examples = [1] - ^""" + <string>:2:16 + examples: [1], + ^""" )); } @Test public void canParseProjectConfigWithNoProfiles() { - var config = ProjectConfig.fromString(PROJECT_PATH, ""); + var config = ProjectConfig.fromString(PROJECT_PATH, "{}"); assertThat(config.profiles(), isSequence()); } @@ -205,11 +194,12 @@ public class ProjectConfigTests { @Test public void canParseProjectConfigWithProfiles() { var config = ProjectConfig.fromString(PROJECT_PATH, """ - [[shed.profiles]] - name = "one" - - [[shed.profiles]] - name = "two" + { + profiles: [ + {name: "one"}, + {name: "two"}, + ], + } """); assertThat(config.profiles(), isSequence( @@ -229,34 +219,34 @@ public class ProjectConfigTests { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - profiles = true""" + {profiles: true}""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.profiles to be an array, but was Boolean")); + assertThat(error.getMessage(), equalTo("Expected profiles to be array, but was boolean")); assertThat(error.source().describe(), equalTo(""" - <string>:2:1 - profiles = true - ^""" + <string>:1:12 + {profiles: true} + ^""" )); } @Test - public void whenProjectConfigHasProfileThatIsntTableThenErrorIsThrown() { + public void whenProjectConfigHasProfileThatIsntObjectThenErrorIsThrown() { var error = assertThrows( ConfigError.class, () -> ProjectConfig.fromString(PROJECT_PATH, """ - [shed] - profiles = [1]""" + { + profiles: [1], + }""" ) ); - assertThat(error.getMessage(), equalTo("Expected shed.profiles[0] to be a table, but was Long")); + assertThat(error.getMessage(), equalTo("Expected profiles[0] to be object, but was finite number")); assertThat(error.source().describe(), equalTo(""" - <string>:2:13 - profiles = [1] - ^""" + <string>:2:16 + profiles: [1], + ^""" )); } } diff --git a/src/test/java/org/shedlang/compiler/config/json/Json5ObjectWithSourceTests.java b/src/test/java/org/shedlang/compiler/config/json/Json5ObjectWithSourceTests.java new file mode 100644 index 00000000..ad7f7c1c --- /dev/null +++ b/src/test/java/org/shedlang/compiler/config/json/Json5ObjectWithSourceTests.java @@ -0,0 +1,406 @@ +package org.shedlang.compiler.config.json; + +import org.junit.jupiter.api.Test; +import org.shedlang.compiler.config.errors.ConfigError; +import org.shedlang.compiler.sources.Sources; + +import java.util.Optional; +import java.util.OptionalLong; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class Json5ObjectWithSourceTests { + @Test + public void whenMemberIsMissingThenGetLongThrowsError() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLong("x") + ); + + assertThat(error.getMessage(), equalTo("a.b[1] is missing x")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:13 + {}, + ^""" + )); + } + + @Test + public void whenMemberIsNotNumberFiniteThenGetLongThrowsError() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {x: true}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLong("x") + ); + + assertThat(error.getMessage(), equalTo("Expected a.b[1].x to be finite number, but was boolean")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:17 + {x: true}, + ^""" + )); + } + + @Test + public void whenMemberIsFiniteNumberButIsNotLongThenGetLongThrowsError() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {x: 1.2}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLong("x") + ); + + assertThat(error.getMessage(), equalTo("a.b[1].x must be a 64-bit integer")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:17 + {x: 1.2}, + ^""" + )); + } + + @Test + public void whenMemberIsLongThenGetLongReturnsValue() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {x : 2}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLong("x"); + + assertThat(result, equalTo(2L)); + } + @Test + public void whenMemberIsMissingThenGetLongOrNoneReturnsEmptyOptional() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLongOrNone("x"); + + assertThat(result, equalTo(OptionalLong.empty())); + } + + @Test + public void whenMemberIsNotLongThenGetLongOrNoneThrowsError() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {x: true}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLongOrNone("x") + ); + + assertThat(error.getMessage(), equalTo("Expected a.b[1].x to be finite number, but was boolean")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:17 + {x: true}, + ^""" + )); + } + + @Test + public void whenMemberIsLongOrNoneThenGetLongReturnsValue() { + var source = Sources.string(""" + { + a: { + b: [ + {x: 1}, + {x: 2}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("a") + .orElseThrow() + .getArrayOfObjects("b") + .orElseThrow() + .get(1) + .getLongOrNone("x"); + + assertThat(result, equalTo(OptionalLong.of(2L))); + } + + @Test + public void whenMemberIsMissingThenGetStringThrowsError() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getString("name") + ); + + assertThat(error.getMessage(), equalTo("shed.bins[1] is missing name")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:13 + {}, + ^""" + )); + } + + @Test + public void whenMemberIsNotStringThenGetStringThrowsError() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {name: true}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getString("name") + ); + + assertThat(error.getMessage(), equalTo("Expected shed.bins[1].name to be string, but was boolean")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:20 + {name: true}, + ^""" + )); + } + + @Test + public void whenMemberIsStringThenGetStringReturnsValue() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {name: "two"}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getString("name"); + + assertThat(result.value(), equalTo("two")); + assertThat(result.source().describe(), equalTo( + """ + <string>:5:20 + {name: "two"}, + ^""" + )); + } + + @Test + public void whenMemberIsMissingThenGetStringOrNoneReturnsEmptyOptional() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getStringOrNone("name"); + + assertThat(result, equalTo(Optional.empty())); + } + + @Test + public void whenMemberIsNotStringThenGetStringOrNoneThrowsError() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {name: true}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var error = assertThrows( + ConfigError.class, + () -> object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getStringOrNone("name") + ); + + assertThat(error.getMessage(), equalTo("Expected shed.bins[1].name to be string, but was boolean")); + assertThat(error.source().describe(), equalTo(""" + <string>:5:20 + {name: true}, + ^""" + )); + } + + @Test + public void whenMemberIsStringThenGetStringOrNoneReturnsValue() { + var source = Sources.string(""" + { + shed: { + bins: [ + {name: "one"}, + {name: "two"}, + ], + }, + } + """); + var object = Json5ObjectWithSource.parse(source); + + var result = object + .getObject("shed") + .orElseThrow() + .getArrayOfObjects("bins") + .orElseThrow() + .get(1) + .getStringOrNone("name"); + + assertThat(result.orElseThrow().value(), equalTo("two")); + assertThat(result.orElseThrow().source().describe(), equalTo( + """ + <string>:5:20 + {name: "two"}, + ^""" + )); + } +} diff --git a/src/test/java/org/shedlang/compiler/config/toml/TomlTableWithSourceTests.java b/src/test/java/org/shedlang/compiler/config/toml/TomlTableWithSourceTests.java deleted file mode 100644 index 1086671c..00000000 --- a/src/test/java/org/shedlang/compiler/config/toml/TomlTableWithSourceTests.java +++ /dev/null @@ -1,325 +0,0 @@ -package org.shedlang.compiler.config.toml; - -import org.junit.jupiter.api.Test; -import org.shedlang.compiler.config.errors.ConfigError; -import org.shedlang.compiler.sources.Sources; - -import java.util.Optional; -import java.util.OptionalLong; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.equalTo; - -public class TomlTableWithSourceTests { - @Test - public void whenKeyIsMissingThenGetLongThrowsError() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLong("x") - ); - - assertThat(error.getMessage(), equalTo("a.b[1] is missing x")); - assertThat(error.source().describe(), equalTo(""" - <string>:4:1 - [[a.b]] - ^""" - )); - } - - @Test - public void whenKeyIsNotLongThenGetLongThrowsError() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - x = true - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLong("x") - ); - - assertThat(error.getMessage(), equalTo("Expected a.b[1].x to be a long, but was Boolean")); - assertThat(error.source().describe(), equalTo(""" - <string>:5:1 - x = true - ^""" - )); - } - - @Test - public void whenKeyIsLongThenGetLongReturnsValue() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - x = 2 - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLong("x"); - - assertThat(result, equalTo(2L)); - } - @Test - public void whenKeyIsMissingThenGetLongOrNoneReturnsEmptyOptional() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLongOrNone("x"); - - assertThat(result, equalTo(OptionalLong.empty())); - } - - @Test - public void whenKeyIsNotLongThenGetLongOrNoneThrowsError() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - x = true - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLongOrNone("x") - ); - - assertThat(error.getMessage(), equalTo("Expected a.b[1].x to be a long, but was Boolean")); - assertThat(error.source().describe(), equalTo(""" - <string>:5:1 - x = true - ^""" - )); - } - - @Test - public void whenKeyIsLongOrNoneThenGetLongReturnsValue() { - var source = Sources.string(""" - [[a.b]] - x = 1 - - [[a.b]] - x = 2 - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("a") - .orElseThrow() - .getArrayOfTables("b") - .orElseThrow() - .get(1) - .getLongOrNone("x"); - - assertThat(result, equalTo(OptionalLong.of(2L))); - } - - @Test - public void whenKeyIsMissingThenGetStringThrowsError() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getString("name") - ); - - assertThat(error.getMessage(), equalTo("shed.bins[1] is missing name")); - assertThat(error.source().describe(), equalTo(""" - <string>:4:1 - [[shed.bins]] - ^""" - )); - } - - @Test - public void whenKeyIsNotStringThenGetStringThrowsError() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - name = true - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getString("name") - ); - - assertThat(error.getMessage(), equalTo("Expected shed.bins[1].name to be a string, but was Boolean")); - assertThat(error.source().describe(), equalTo(""" - <string>:5:1 - name = true - ^""" - )); - } - - @Test - public void whenKeyIsStringThenGetStringReturnsValue() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - name = "two" - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getString("name"); - - assertThat(result, equalTo( - new TomlString("two", source.at(42, 42)) - )); - } - - @Test - public void whenKeyIsMissingThenGetStringOrNoneReturnsEmptyOptional() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getStringOrNone("name"); - - assertThat(result, equalTo(Optional.empty())); - } - - @Test - public void whenKeyIsNotStringThenGetStringOrNoneThrowsError() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - name = true - """); - var table = TomlTableWithSource.parse(source); - - var error = assertThrows( - ConfigError.class, - () -> table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getStringOrNone("name") - ); - - assertThat(error.getMessage(), equalTo("Expected shed.bins[1].name to be a string, but was Boolean")); - assertThat(error.source().describe(), equalTo(""" - <string>:5:1 - name = true - ^""" - )); - } - - @Test - public void whenKeyIsStringThenGetStringOrNoneReturnsValue() { - var source = Sources.string(""" - [[shed.bins]] - name = "one" - - [[shed.bins]] - name = "two" - """); - var table = TomlTableWithSource.parse(source); - - var result = table - .getTable("shed") - .orElseThrow() - .getArrayOfTables("bins") - .orElseThrow() - .get(1) - .getStringOrNone("name"); - - assertThat(result, equalTo(Optional.of( - new TomlString("two", source.at(42, 42)) - ))); - } -} |
