diff --git a/exercises/practice/tree-building/.meta/Example.cs b/exercises/practice/tree-building/.meta/Example.cs index c9024b0349..35d30fb3d3 100644 --- a/exercises/practice/tree-building/.meta/Example.cs +++ b/exercises/practice/tree-building/.meta/Example.cs @@ -58,7 +58,7 @@ private static void ValidateRecord(TreeBuildingRecord record, int previousRecord throw new ArgumentException(); else if (!record.IsRoot && record.ParentId >= record.RecordId) throw new ArgumentException(); - else if (!record.IsRoot && record.RecordId != previousRecordId + 1) + else if (record.RecordId != previousRecordId + 1) throw new ArgumentException(); } diff --git a/exercises/practice/tree-building/.meta/Generator.tpl b/exercises/practice/tree-building/.meta/Generator.tpl new file mode 100644 index 0000000000..646cb3f2f1 --- /dev/null +++ b/exercises/practice/tree-building/.meta/Generator.tpl @@ -0,0 +1,53 @@ +{{ func assertions(node, path) + id = node.id ?? node.recordId + children = node.children ?? [] + + assertion = children.empty? ? $"AssertTreeIsLeaf({path}, id: {id});" : $"AssertTreeIsBranch({path}, id: {id}, childCount: {children | array.size});" + checks = [assertion] + + for child in children + checks = array.add_range checks (assertions child $"{path}.Children[{for.index}]") + end + + ret checks +end }} + +public class {{ testClass }} +{ + {{- for test in tests }} + [Fact{{ if !for.first }}(Skip = "Remove this Skip property to run this test"){{ end }}] + public void {{ test.testMethod }}() + { + {{- if test.input.records.empty? }} + var records = Array.Empty(); + {{- else }} + var records = new[] + { + {{- for record in test.input.records }} + new TreeBuildingRecord { RecordId = {{ record.recordId }}, ParentId = {{ record.parentId }} }{{ if !for.last }},{{ end }} + {{- end }} + }; + {{- end }} + + {{- if test.expected.error || test.expected.empty? }} + Assert.Throws(() => TreeBuilder.BuildTree(records)); + {{- else }} + var tree = TreeBuilder.BuildTree(records); + + {{ test.expected.node | assertions "tree" | array.join "\n" }} + {{- end }} + } + {{ end }} + private static void AssertTreeIsBranch(Tree tree, int id, int childCount) + { + Assert.Equal(id, tree.Id); + Assert.False(tree.IsLeaf); + Assert.Equal(childCount, tree.Children.Count); + } + + private static void AssertTreeIsLeaf(Tree tree, int id) + { + Assert.Equal(id, tree.Id); + Assert.True(tree.IsLeaf); + } +} diff --git a/exercises/practice/tree-building/.meta/tests.toml b/exercises/practice/tree-building/.meta/tests.toml new file mode 100644 index 0000000000..fcdc1d508a --- /dev/null +++ b/exercises/practice/tree-building/.meta/tests.toml @@ -0,0 +1,58 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[761790a3-4c27-461a-b4e9-8bce8ccee5a1] +description = "empty list" + +[dcc89dc3-eb39-4f26-a3cd-964e607c95ff] +description = "single record" + +[dcdb80f0-e5da-43e1-8b8d-6f307be89c0e] +description = "three records in order" + +[2ff5b8f8-d95e-401e-9359-233919488d22] +description = "three records in reverse order" + +[de798d3b-8905-4446-a114-a0dd2476d945] +description = "more than two children" + +[13dd9b3c-6137-415f-b6fe-5044c1dfbc50] +description = "binary tree" + +[5cfd29dc-166b-47da-84ca-1c60b5ae5941] +description = "unbalanced tree" + +[a05ddb5d-2d11-4948-88d3-b5f18a44ddce] +description = "one root node and has parent" + +[9ed09df2-8fd6-4e37-aa37-e7753c057a1a] +description = "root node has parent" + +[8755a2c4-2c6b-4396-b155-b5bf4b6bc280] +description = "no root node" + +[c6ef8f9a-4045-4949-a1e1-e0ae804e4af4] +description = "duplicate node" + +[7a7b77a6-3447-4905-b79c-d22bfe43f408] +description = "duplicate root" + +[c6f51bd7-3608-4390-b446-dfd1bcbf3ddc] +description = "non-continuous" + +[1f3d1b50-4494-4b22-b88a-68f32f7d321d] +description = "cycle directly" + +[ac568b50-3f9b-4cb4-b602-e0eb13de4269] +description = "cycle indirectly" + +[cf954b21-3cef-420c-8e72-d19547505e1f] +description = "higher id parent of lower id" diff --git a/exercises/practice/tree-building/TreeBuildingTests.cs b/exercises/practice/tree-building/TreeBuildingTests.cs index 652562dda4..1202ea5622 100644 --- a/exercises/practice/tree-building/TreeBuildingTests.cs +++ b/exercises/practice/tree-building/TreeBuildingTests.cs @@ -1,20 +1,26 @@ public class TreeBuildingTests { [Fact] - public void One_node() + public void Empty_list() + { + var records = Array.Empty(); + Assert.Throws(() => TreeBuilder.BuildTree(records)); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Single_record() { var records = new[] { new TreeBuildingRecord { RecordId = 0, ParentId = 0 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsLeaf(tree, id: 0); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Three_nodes_in_order() + public void Three_records_in_order() { var records = new[] { @@ -22,7 +28,6 @@ public void Three_nodes_in_order() new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, new TreeBuildingRecord { RecordId = 2, ParentId = 0 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsBranch(tree, id: 0, childCount: 2); @@ -31,7 +36,7 @@ public void Three_nodes_in_order() } [Fact(Skip = "Remove this Skip property to run this test")] - public void Three_nodes_in_reverse_order() + public void Three_records_in_reverse_order() { var records = new[] { @@ -39,7 +44,6 @@ public void Three_nodes_in_reverse_order() new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, new TreeBuildingRecord { RecordId = 0, ParentId = 0 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsBranch(tree, id: 0, childCount: 2); @@ -52,12 +56,11 @@ public void More_than_two_children() { var records = new[] { - new TreeBuildingRecord { RecordId = 3, ParentId = 0 }, - new TreeBuildingRecord { RecordId = 2, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, - new TreeBuildingRecord { RecordId = 0, ParentId = 0 } + new TreeBuildingRecord { RecordId = 2, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 3, ParentId = 0 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsBranch(tree, id: 0, childCount: 3); @@ -79,15 +82,13 @@ public void Binary_tree() new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, new TreeBuildingRecord { RecordId = 6, ParentId = 2 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsBranch(tree, id: 0, childCount: 2); AssertTreeIsBranch(tree.Children[0], id: 1, childCount: 2); - AssertTreeIsBranch(tree.Children[1], id: 2, childCount: 2); - AssertTreeIsLeaf(tree.Children[0].Children[0], id: 4); AssertTreeIsLeaf(tree.Children[0].Children[1], id: 5); + AssertTreeIsBranch(tree.Children[1], id: 2, childCount: 2); AssertTreeIsLeaf(tree.Children[1].Children[0], id: 3); AssertTreeIsLeaf(tree.Children[1].Children[1], id: 6); } @@ -105,24 +106,24 @@ public void Unbalanced_tree() new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, new TreeBuildingRecord { RecordId = 6, ParentId = 2 } }; - var tree = TreeBuilder.BuildTree(records); AssertTreeIsBranch(tree, id: 0, childCount: 2); AssertTreeIsBranch(tree.Children[0], id: 1, childCount: 1); - AssertTreeIsBranch(tree.Children[1], id: 2, childCount: 3); - AssertTreeIsLeaf(tree.Children[0].Children[0], id: 4); + AssertTreeIsBranch(tree.Children[1], id: 2, childCount: 3); AssertTreeIsLeaf(tree.Children[1].Children[0], id: 3); AssertTreeIsLeaf(tree.Children[1].Children[1], id: 5); AssertTreeIsLeaf(tree.Children[1].Children[2], id: 6); } [Fact(Skip = "Remove this Skip property to run this test")] - public void Empty_input() + public void One_root_node_and_has_parent() { - var records = new TreeBuildingRecord[0]; - + var records = new[] + { + new TreeBuildingRecord { RecordId = 0, ParentId = 1 } + }; Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -134,7 +135,6 @@ public void Root_node_has_parent() new TreeBuildingRecord { RecordId = 0, ParentId = 1 }, new TreeBuildingRecord { RecordId = 1, ParentId = 0 } }; - Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -143,12 +143,34 @@ public void No_root_node() { var records = new[] { - new TreeBuildingRecord { RecordId = 1, ParentId = 0 } + new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 2, ParentId = 0 } }; + Assert.Throws(() => TreeBuilder.BuildTree(records)); + } + [Fact(Skip = "Remove this Skip property to run this test")] + public void Duplicate_node() + { + var records = new[] + { + new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 1, ParentId = 0 } + }; Assert.Throws(() => TreeBuilder.BuildTree(records)); } + [Fact(Skip = "Remove this Skip property to run this test")] + public void Duplicate_root() + { + var records = new[] + { + new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, + new TreeBuildingRecord { RecordId = 0, ParentId = 0 } + }; + Assert.Throws(() => TreeBuilder.BuildTree(records)); + } [Fact(Skip = "Remove this Skip property to run this test")] public void Non_continuous() @@ -160,7 +182,6 @@ public void Non_continuous() new TreeBuildingRecord { RecordId = 1, ParentId = 0 }, new TreeBuildingRecord { RecordId = 0, ParentId = 0 } }; - Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -177,7 +198,6 @@ public void Cycle_directly() new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, new TreeBuildingRecord { RecordId = 6, ParentId = 3 } }; - Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -194,7 +214,6 @@ public void Cycle_indirectly() new TreeBuildingRecord { RecordId = 0, ParentId = 0 }, new TreeBuildingRecord { RecordId = 6, ParentId = 3 } }; - Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -207,7 +226,6 @@ public void Higher_id_parent_of_lower_id() new TreeBuildingRecord { RecordId = 2, ParentId = 0 }, new TreeBuildingRecord { RecordId = 1, ParentId = 2 } }; - Assert.Throws(() => TreeBuilder.BuildTree(records)); } @@ -223,4 +241,4 @@ private static void AssertTreeIsLeaf(Tree tree, int id) Assert.Equal(id, tree.Id); Assert.True(tree.IsLeaf); } -} \ No newline at end of file +}