diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Scope.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Scope.java index 42241416a53..53d4b5f6c1c 100644 --- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Scope.java +++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Scope.java @@ -17,7 +17,7 @@ import java.util.ArrayDeque; import java.util.Deque; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; import java.util.function.Supplier; @@ -81,7 +81,7 @@ public U inScope(Supplier func) { @Override public String toString() { - HashMap toPrint = new HashMap<>(); + Map toPrint = new LinkedHashMap<>(); for (ScopeLayer layer : scope) { toPrint.putAll(layer.getTypes()); } diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Type.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Type.java index ee4542f7f04..327382c2d86 100644 --- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Type.java +++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Type.java @@ -15,6 +15,7 @@ package software.amazon.smithy.rulesengine.language.eval; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -389,7 +390,7 @@ final class Record implements Type { private final Map shape; public Record(Map shape) { - this.shape = shape; + this.shape = new LinkedHashMap<>(shape); } @Override diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Value.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Value.java index 6617c00e8c0..6ac85ec764b 100644 --- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Value.java +++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/eval/Value.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -83,7 +84,7 @@ public Value numberNode(NumberNode node) { @Override public Value objectNode(ObjectNode node) { - HashMap out = new HashMap<>(); + HashMap out = new LinkedHashMap<>(); node.getMembers().forEach((name, member) -> out.put(Identifier.of(name), Value.fromNode(member))); return Value.record(out); } diff --git a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expr/Literal.java b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expr/Literal.java index fa5a64dc834..9c44605056e 100644 --- a/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expr/Literal.java +++ b/smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expr/Literal.java @@ -16,7 +16,9 @@ package software.amazon.smithy.rulesengine.language.syntax.expr; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -142,7 +144,7 @@ public ILiteral numberNode(NumberNode numberNode) { @Override public ILiteral objectNode(ObjectNode objectNode) { - Map obj = new HashMap<>(); + Map obj = new LinkedHashMap<>(); objectNode.getMembers().forEach((k, v) -> { obj.put(Identifier.of(k), new Literal(v.accept(this), v)); }); @@ -245,7 +247,7 @@ public Type visitString(Template value) { @Override public Type visitRecord(Map members) { - Map tpe = new HashMap<>(); + Map tpe = new LinkedHashMap<>(); ((Record) value).members.forEach((k, v) -> { tpe.put(k, v.typeCheck(scope)); }); @@ -543,7 +545,7 @@ static final class Record implements ILiteral { private final Map members; Record(Map members) { - this.members = members; + this.members = Collections.unmodifiableMap(new LinkedHashMap<>(members)); } public Map members() { diff --git a/smithy-rules-engine/src/main/resources/software/amazon/smithy/rulesengine/testutil/valid-rules/minimal-ruleset.json b/smithy-rules-engine/src/main/resources/software/amazon/smithy/rulesengine/testutil/valid-rules/minimal-ruleset.json index 8c629f84230..92b6d8292e5 100644 --- a/smithy-rules-engine/src/main/resources/software/amazon/smithy/rulesengine/testutil/valid-rules/minimal-ruleset.json +++ b/smithy-rules-engine/src/main/resources/software/amazon/smithy/rulesengine/testutil/valid-rules/minimal-ruleset.json @@ -1,15 +1,16 @@ { + "version": "1.3", "parameters": { "Region": { - "type": "string", "builtIn": "AWS::Region", - "required": true + "required": true, + "type": "String" } }, "rules": [ { - "documentation": "base rule", "conditions": [], + "documentation": "base rule", "endpoint": { "url": "https://{Region}.amazonaws.com", "properties": { @@ -20,10 +21,10 @@ "signingRegion": "{Region}" } ] - } + }, + "headers": {} }, "type": "endpoint" } - ], - "version": "1.3" + ] } diff --git a/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/RulesetTestUtil.java b/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/RulesetTestUtil.java index 34db2b855c5..0d524ccaa37 100644 --- a/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/RulesetTestUtil.java +++ b/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/RulesetTestUtil.java @@ -2,9 +2,11 @@ import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.rulesengine.language.EndpointRuleSet; +import software.amazon.smithy.utils.IoUtils; public class RulesetTestUtil { public static EndpointRuleSet loadRuleSet(String resourceId) { diff --git a/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/language/EndpointRuleSetTest.java b/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/language/EndpointRuleSetTest.java index 4b604feb5aa..d6976809be6 100644 --- a/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/language/EndpointRuleSetTest.java +++ b/smithy-rules-engine/src/test/java/software/amazon/smithy/rulesengine/language/EndpointRuleSetTest.java @@ -33,6 +33,7 @@ import software.amazon.smithy.rulesengine.language.syntax.parameters.ParameterType; import software.amazon.smithy.rulesengine.language.syntax.parameters.Parameters; import software.amazon.smithy.rulesengine.language.syntax.rule.Rule; +import software.amazon.smithy.utils.IoUtils; import software.amazon.smithy.utils.MapUtils; class EndpointRuleSetTest { @@ -54,6 +55,14 @@ void testRuleEval() { assertEquals(expected, result.expectEndpoint()); } + @Test + void testDeterministicSerde() { + String resourceId = "software/amazon/smithy/rulesengine/testutil/valid-rules/minimal-ruleset.json"; + EndpointRuleSet actual = RulesetTestUtil.loadRuleSet(resourceId); + String asString = IoUtils.readUtf8Resource(RulesetTestUtil.class.getClassLoader(), resourceId); + assertEquals(Node.prettyPrintJson(Node.parseJsonWithComments(asString)), Node.prettyPrintJson(actual.toNode())); + } + @Test void testMinimalRuleset() { EndpointRuleSet actual = RulesetTestUtil.minimalRuleSet();