From e34034c5043310ce490aaaf16f2d17681af9bcb1 Mon Sep 17 00:00:00 2001 From: username is already taken Date: Tue, 27 Oct 2026 21:16:46 +0700 Subject: [PATCH 1/3] Make satellite tests more readable [no important files changed] --- .../practice/satellite/test_satellite.zig | 346 +++++++++--------- generators/exercises/satellite.py | 66 ++-- 2 files changed, 200 insertions(+), 212 deletions(-) diff --git a/exercises/practice/satellite/test_satellite.zig b/exercises/practice/satellite/test_satellite.zig index 002cef6a..7bcedc66 100644 --- a/exercises/practice/satellite/test_satellite.zig +++ b/exercises/practice/satellite/test_satellite.zig @@ -3,208 +3,198 @@ const testing = std.testing; const satellite = @import("satellite.zig"); const Tree = satellite.Tree; -const TraversalError = satellite.TraversalError; +const Result = (std.mem.Allocator.Error || satellite.TraversalError)!Tree; + +fn expectEqualChars(expected: u8, actual: u8) !void { + const fmtChar = std.zig.fmtChar; + if (actual != expected) { + testing.failPrint("expected '{f}', found '{f}'\n", .{ + fmtChar(expected), + fmtChar(actual), + }); + return error.TestExpectedEqual; + } +} test "Empty tree" { - const preorder = [_]u8{}; - const inorder = [_]u8{}; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - try testing.expectEqual(null, tree.root); + const preorder: []const u8 = ""; + const inorder: []const u8 = ""; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expectEqual(null, root); } test "Tree with one item" { - const preorder = [_]u8{'a'}; - const inorder = [_]u8{'a'}; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - if (tree.root) |o| { - try testing.expectEqual('a', o.data); - try testing.expectEqual(null, o.left); - try testing.expectEqual(null, o.right); - } else { - try testing.expectEqual(false, true); // tree.root should not be null - } + const preorder: []const u8 = "a"; + const inorder: []const u8 = "a"; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expect(root != null); + try expectEqualChars('a', root.?.data); + try testing.expectEqual(null, root.?.left); + try testing.expectEqual(null, root.?.right); } test "Tree with many items" { - const preorder = [_]u8{ 'a', 'i', 'x', 'f', 'r' }; - const inorder = [_]u8{ 'i', 'a', 'f', 'x', 'r' }; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - if (tree.root) |o| { - try testing.expectEqual('a', o.data); - if (o.left) |l| { - try testing.expectEqual('i', l.data); - try testing.expectEqual(null, l.left); - try testing.expectEqual(null, l.right); - } else { - try testing.expectEqual(false, true); // o.left should not be null - } - if (o.right) |r| { - try testing.expectEqual('x', r.data); - if (r.left) |rl| { - try testing.expectEqual('f', rl.data); - try testing.expectEqual(null, rl.left); - try testing.expectEqual(null, rl.right); - } else { - try testing.expectEqual(false, true); // r.left should not be null - } - if (r.right) |rr| { - try testing.expectEqual('r', rr.data); - try testing.expectEqual(null, rr.left); - try testing.expectEqual(null, rr.right); - } else { - try testing.expectEqual(false, true); // r.right should not be null - } - } else { - try testing.expectEqual(false, true); // o.right should not be null - } - } else { - try testing.expectEqual(false, true); // tree.root should not be null - } + const preorder: []const u8 = "aixfr"; + const inorder: []const u8 = "iafxr"; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expect(root != null); + try expectEqualChars('a', root.?.data); + try testing.expect(root.?.left != null); + try expectEqualChars('i', root.?.left.?.data); + try testing.expectEqual(null, root.?.left.?.left); + try testing.expectEqual(null, root.?.left.?.right); + try testing.expect(root.?.right != null); + try expectEqualChars('x', root.?.right.?.data); + try testing.expect(root.?.right.?.left != null); + try expectEqualChars('f', root.?.right.?.left.?.data); + try testing.expectEqual(null, root.?.right.?.left.?.left); + try testing.expectEqual(null, root.?.right.?.left.?.right); + try testing.expect(root.?.right.?.right != null); + try expectEqualChars('r', root.?.right.?.right.?.data); + try testing.expectEqual(null, root.?.right.?.right.?.left); + try testing.expectEqual(null, root.?.right.?.right.?.right); } test "Reject traversals of different length" { - const preorder = [_]u8{ 'a', 'b' }; - const inorder = [_]u8{ 'b', 'a', 'r' }; - try testing.expectError(TraversalError.DifferentLengths, Tree.initFromTraversals(testing.allocator, &preorder, &inorder)); + const preorder: []const u8 = "ab"; + const inorder: []const u8 = "bar"; + const actual: Result = .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer if (actual) |a| a.deinit() else |_| {}; + try testing.expectError(error.DifferentLengths, actual); } test "Reject inconsistent traversals of same length" { - const preorder = [_]u8{ 'x', 'y', 'z' }; - const inorder = [_]u8{ 'a', 'b', 'c' }; - try testing.expectError(TraversalError.DifferentItems, Tree.initFromTraversals(testing.allocator, &preorder, &inorder)); + const preorder: []const u8 = "xyz"; + const inorder: []const u8 = "abc"; + const actual: Result = .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer if (actual) |a| a.deinit() else |_| {}; + try testing.expectError(error.DifferentItems, actual); } test "Reject traversals with repeated items" { - const preorder = [_]u8{ 'a', 'b', 'a' }; - const inorder = [_]u8{ 'b', 'a', 'a' }; - try testing.expectError(TraversalError.NonUniqueItems, Tree.initFromTraversals(testing.allocator, &preorder, &inorder)); + const preorder: []const u8 = "aba"; + const inorder: []const u8 = "baa"; + const actual: Result = .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer if (actual) |a| a.deinit() else |_| {}; + try testing.expectError(error.NonUniqueItems, actual); } test "A degenerate binary tree" { - const preorder = [_]u8{ 'a', 'b', 'c', 'd' }; - const inorder = [_]u8{ 'd', 'c', 'b', 'a' }; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - if (tree.root) |o| { - try testing.expectEqual('a', o.data); - if (o.left) |l| { - try testing.expectEqual('b', l.data); - if (l.left) |ll| { - try testing.expectEqual('c', ll.data); - if (ll.left) |lll| { - try testing.expectEqual('d', lll.data); - try testing.expectEqual(null, lll.left); - try testing.expectEqual(null, lll.right); - } else { - try testing.expectEqual(false, true); // ll.left should not be null - } - try testing.expectEqual(null, ll.right); - } else { - try testing.expectEqual(false, true); // l.left should not be null - } - try testing.expectEqual(null, l.right); - } else { - try testing.expectEqual(false, true); // o.left should not be null - } - try testing.expectEqual(null, o.right); - } else { - try testing.expectEqual(false, true); // tree.root should not be null - } + const preorder: []const u8 = "abcd"; + const inorder: []const u8 = "dcba"; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expect(root != null); + try expectEqualChars('a', root.?.data); + try testing.expect(root.?.left != null); + try expectEqualChars('b', root.?.left.?.data); + try testing.expect(root.?.left.?.left != null); + try expectEqualChars('c', root.?.left.?.left.?.data); + try testing.expect(root.?.left.?.left.?.left != null); + try expectEqualChars('d', root.?.left.?.left.?.left.?.data); + try testing.expectEqual(null, root.?.left.?.left.?.left.?.left); + try testing.expectEqual(null, root.?.left.?.left.?.left.?.right); + try testing.expectEqual(null, root.?.left.?.left.?.right); + try testing.expectEqual(null, root.?.left.?.right); + try testing.expectEqual(null, root.?.right); } test "Another degenerate binary tree" { - const preorder = [_]u8{ 'a', 'b', 'c', 'd' }; - const inorder = [_]u8{ 'a', 'b', 'c', 'd' }; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - if (tree.root) |o| { - try testing.expectEqual('a', o.data); - try testing.expectEqual(null, o.left); - if (o.right) |r| { - try testing.expectEqual('b', r.data); - try testing.expectEqual(null, r.left); - if (r.right) |rr| { - try testing.expectEqual('c', rr.data); - try testing.expectEqual(null, rr.left); - if (rr.right) |rrr| { - try testing.expectEqual('d', rrr.data); - try testing.expectEqual(null, rrr.left); - try testing.expectEqual(null, rrr.right); - } else { - try testing.expectEqual(false, true); // rr.right should not be null - } - } else { - try testing.expectEqual(false, true); // r.right should not be null - } - } else { - try testing.expectEqual(false, true); // o.right should not be null - } - } else { - try testing.expectEqual(false, true); // tree.root should not be null - } + const preorder: []const u8 = "abcd"; + const inorder: []const u8 = "abcd"; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expect(root != null); + try expectEqualChars('a', root.?.data); + try testing.expectEqual(null, root.?.left); + try testing.expect(root.?.right != null); + try expectEqualChars('b', root.?.right.?.data); + try testing.expectEqual(null, root.?.right.?.left); + try testing.expect(root.?.right.?.right != null); + try expectEqualChars('c', root.?.right.?.right.?.data); + try testing.expectEqual(null, root.?.right.?.right.?.left); + try testing.expect(root.?.right.?.right.?.right != null); + try expectEqualChars('d', root.?.right.?.right.?.right.?.data); + try testing.expectEqual(null, root.?.right.?.right.?.right.?.left); + try testing.expectEqual(null, root.?.right.?.right.?.right.?.right); } test "Tree with many more items" { - const preorder = [_]u8{ 'a', 'b', 'd', 'g', 'h', 'c', 'e', 'f', 'i' }; - const inorder = [_]u8{ 'g', 'd', 'h', 'b', 'a', 'e', 'c', 'i', 'f' }; - var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder); - defer tree.deinit(); - if (tree.root) |o| { - try testing.expectEqual('a', o.data); - if (o.left) |l| { - try testing.expectEqual('b', l.data); - if (l.left) |ll| { - try testing.expectEqual('d', ll.data); - if (ll.left) |lll| { - try testing.expectEqual('g', lll.data); - try testing.expectEqual(null, lll.left); - try testing.expectEqual(null, lll.right); - } else { - try testing.expectEqual(false, true); // ll.left should not be null - } - if (ll.right) |llr| { - try testing.expectEqual('h', llr.data); - try testing.expectEqual(null, llr.left); - try testing.expectEqual(null, llr.right); - } else { - try testing.expectEqual(false, true); // ll.right should not be null - } - } else { - try testing.expectEqual(false, true); // l.left should not be null - } - try testing.expectEqual(null, l.right); - } else { - try testing.expectEqual(false, true); // o.left should not be null - } - if (o.right) |r| { - try testing.expectEqual('c', r.data); - if (r.left) |rl| { - try testing.expectEqual('e', rl.data); - try testing.expectEqual(null, rl.left); - try testing.expectEqual(null, rl.right); - } else { - try testing.expectEqual(false, true); // r.left should not be null - } - if (r.right) |rr| { - try testing.expectEqual('f', rr.data); - if (rr.left) |rrl| { - try testing.expectEqual('i', rrl.data); - try testing.expectEqual(null, rrl.left); - try testing.expectEqual(null, rrl.right); - } else { - try testing.expectEqual(false, true); // rr.left should not be null - } - try testing.expectEqual(null, rr.right); - } else { - try testing.expectEqual(false, true); // r.right should not be null - } - } else { - try testing.expectEqual(false, true); // o.right should not be null - } - } else { - try testing.expectEqual(false, true); // tree.root should not be null - } + const preorder: []const u8 = "abdghcefi"; + const inorder: []const u8 = "gdhbaecif"; + const actual: Tree = try .initFromTraversals( + testing.allocator, + preorder, + inorder, + ); + defer actual.deinit(); + const root = actual.root; + try testing.expect(root != null); + try expectEqualChars('a', root.?.data); + try testing.expect(root.?.left != null); + try expectEqualChars('b', root.?.left.?.data); + try testing.expect(root.?.left.?.left != null); + try expectEqualChars('d', root.?.left.?.left.?.data); + try testing.expect(root.?.left.?.left.?.left != null); + try expectEqualChars('g', root.?.left.?.left.?.left.?.data); + try testing.expectEqual(null, root.?.left.?.left.?.left.?.left); + try testing.expectEqual(null, root.?.left.?.left.?.left.?.right); + try testing.expect(root.?.left.?.left.?.right != null); + try expectEqualChars('h', root.?.left.?.left.?.right.?.data); + try testing.expectEqual(null, root.?.left.?.left.?.right.?.left); + try testing.expectEqual(null, root.?.left.?.left.?.right.?.right); + try testing.expectEqual(null, root.?.left.?.right); + try testing.expect(root.?.right != null); + try expectEqualChars('c', root.?.right.?.data); + try testing.expect(root.?.right.?.left != null); + try expectEqualChars('e', root.?.right.?.left.?.data); + try testing.expectEqual(null, root.?.right.?.left.?.left); + try testing.expectEqual(null, root.?.right.?.left.?.right); + try testing.expect(root.?.right.?.right != null); + try expectEqualChars('f', root.?.right.?.right.?.data); + try testing.expect(root.?.right.?.right.?.left != null); + try expectEqualChars('i', root.?.right.?.right.?.left.?.data); + try testing.expectEqual(null, root.?.right.?.right.?.left.?.left); + try testing.expectEqual(null, root.?.right.?.right.?.left.?.right); + try testing.expectEqual(null, root.?.right.?.right.?.right); } diff --git a/generators/exercises/satellite.py b/generators/exercises/satellite.py index 63ca8292..3519fdc3 100644 --- a/generators/exercises/satellite.py +++ b/generators/exercises/satellite.py @@ -1,7 +1,18 @@ from lib import is_error HEADER = """const Tree = satellite.Tree; -const TraversalError = satellite.TraversalError; +const Result = (std.mem.Allocator.Error || satellite.TraversalError)!Tree; + +fn expectEqualChars(expected: u8, actual: u8) !void { + const fmtChar = std.zig.fmtChar; + if (actual != expected) { + testing.failPrint("expected '{f}', found '{f}'\\n", .{ + fmtChar(expected), + fmtChar(actual), + }); + return error.TestExpectedEqual; + } +} """ _ERROR_MAP = { @@ -11,29 +22,18 @@ } -def _u8_array(name, chars): - if not chars: - return f"const {name} = [_]u8{{}};\n" - inner = ", ".join(f"'{c}'" for c in chars) - return f"const {name} = [_]u8{{ {inner} }};\n" - +def _u8_const_slice(name, chars): + inner = "".join(chars) + return f"const {name}: []const u8 = \"{inner}\";\n" -def _traverse(expr, name, node, out): +def _traverse(expr, node, out): if not node: out.append(f"try testing.expectEqual(null, {expr});\n") return - - if len(name) > 1 and name[0] == "o": - name = name[1:] - - out.append(f"if ({expr}) |{name}| {{\n") - out.append(f"try testing.expectEqual('{node['v']}', {name}.data);\n") - _traverse(name + ".left", name + "l", node.get("l"), out) - _traverse(name + ".right", name + "r", node.get("r"), out) - out.append("} else {\n") - out.append(f"try testing.expectEqual(false, true); // {expr} should not be null\n") - out.append("}\n") - + out.append(f"try testing.expect({expr} != null);\n") + out.append(f"try expectEqualChars('{node['v']}', {expr}.?.data);\n") + _traverse(expr + ".?.left", node['l'],out) + _traverse(expr + ".?.right", node['r'],out) def gen_case(case): inp = case["input"] @@ -41,24 +41,22 @@ def gen_case(case): preorder = inp["preorder"] inorder = inp["inorder"] - out = [_u8_array("preorder", preorder), _u8_array("inorder", inorder)] + out = [_u8_const_slice("preorder", preorder), _u8_const_slice("inorder", inorder)] if is_error(expected): + out.append("""const actual: Result = .initFromTraversals( + testing.allocator, preorder, inorder,); + defer if (actual) |a| a.deinit() else |_| {}; + """) err = _ERROR_MAP[expected["error"]] - out.append( - f"try testing.expectError(TraversalError.{err}, " - "Tree.initFromTraversals(testing.allocator, &preorder, &inorder));\n" - ) + out.append(f"try testing.expectError(error.{err}, actual);\n") return "".join(out) - out.append( - "var tree = try Tree.initFromTraversals(testing.allocator, &preorder, &inorder);\n" - ) - out.append("defer tree.deinit();\n") - - if not expected: - out.append("try testing.expectEqual(null, tree.root);\n") - else: - _traverse("tree.root", "o", expected, out) + out.append("""const actual: Tree = try .initFromTraversals( + testing.allocator, preorder, inorder,); + defer actual.deinit(); + const root = actual.root; + """) + _traverse("root", expected, out) return "".join(out) From 02f0c5cbb7f8b98d6bbf067b18e875b0d33ea1ad Mon Sep 17 00:00:00 2001 From: username is already taken Date: Thu, 29 Oct 2026 10:09:50 +0700 Subject: [PATCH 2/3] Make satellite tests more readable. Change Node.data from i32 to u8 in example.zig to allow the tests to use std.zig.fmtChar. [no important files changed] --- .../practice/satellite/.meta/example.zig | 6 +- .../practice/satellite/test_satellite.zig | 191 +++++++++--------- generators/exercises/satellite.py | 22 +- 3 files changed, 117 insertions(+), 102 deletions(-) diff --git a/exercises/practice/satellite/.meta/example.zig b/exercises/practice/satellite/.meta/example.zig index a76dcd06..80d9875e 100644 --- a/exercises/practice/satellite/.meta/example.zig +++ b/exercises/practice/satellite/.meta/example.zig @@ -10,9 +10,9 @@ pub const TraversalError = error{ pub const Node = struct { left: ?*Node, right: ?*Node, - data: i32, + data: u8, - fn init(allocator: mem.Allocator, left: ?*Node, right: ?*Node, data: i32) mem.Allocator.Error!*Node { + fn init(allocator: mem.Allocator, left: ?*Node, right: ?*Node, data: u8) mem.Allocator.Error!*Node { const self = try allocator.create(Node); self.left = left; self.right = right; @@ -30,7 +30,7 @@ pub const Node = struct { allocator.destroy(self); } - fn write(self: *const Node, list: *std.array_list.Managed(i32)) mem.Allocator.Error!void { + fn write(self: *const Node, list: *std.array_list.Managed(u8)) mem.Allocator.Error!void { if (self.left) |child| { try child.write(list); } diff --git a/exercises/practice/satellite/test_satellite.zig b/exercises/practice/satellite/test_satellite.zig index 7bcedc66..85b2dc39 100644 --- a/exercises/practice/satellite/test_satellite.zig +++ b/exercises/practice/satellite/test_satellite.zig @@ -3,6 +3,7 @@ const testing = std.testing; const satellite = @import("satellite.zig"); const Tree = satellite.Tree; +const Node = satellite.Node; const Result = (std.mem.Allocator.Error || satellite.TraversalError)!Tree; fn expectEqualChars(expected: u8, actual: u8) !void { @@ -16,185 +17,189 @@ fn expectEqualChars(expected: u8, actual: u8) !void { } } +fn expectNull(actual: ?*Node) !void { + const fmtChar = std.zig.fmtChar; + if (actual) |a| { + testing.failPrint("expected null, found node '{f}'\n", .{ + fmtChar(a.data), + }); + return error.TestExpectedNull; + } +} + test "Empty tree" { const preorder: []const u8 = ""; const inorder: []const u8 = ""; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expectEqual(null, root); + try expectNull(actual.root); } test "Tree with one item" { const preorder: []const u8 = "a"; const inorder: []const u8 = "a"; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expect(root != null); - try expectEqualChars('a', root.?.data); - try testing.expectEqual(null, root.?.left); - try testing.expectEqual(null, root.?.right); + try testing.expect(actual.root != null); + try expectEqualChars('a', actual.root.?.data); + try expectNull(actual.root.?.left); + try expectNull(actual.root.?.right); } test "Tree with many items" { const preorder: []const u8 = "aixfr"; const inorder: []const u8 = "iafxr"; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expect(root != null); - try expectEqualChars('a', root.?.data); - try testing.expect(root.?.left != null); - try expectEqualChars('i', root.?.left.?.data); - try testing.expectEqual(null, root.?.left.?.left); - try testing.expectEqual(null, root.?.left.?.right); - try testing.expect(root.?.right != null); - try expectEqualChars('x', root.?.right.?.data); - try testing.expect(root.?.right.?.left != null); - try expectEqualChars('f', root.?.right.?.left.?.data); - try testing.expectEqual(null, root.?.right.?.left.?.left); - try testing.expectEqual(null, root.?.right.?.left.?.right); - try testing.expect(root.?.right.?.right != null); - try expectEqualChars('r', root.?.right.?.right.?.data); - try testing.expectEqual(null, root.?.right.?.right.?.left); - try testing.expectEqual(null, root.?.right.?.right.?.right); + try testing.expect(actual.root != null); + try expectEqualChars('a', actual.root.?.data); + try testing.expect(actual.root.?.left != null); + try expectEqualChars('i', actual.root.?.left.?.data); + try expectNull(actual.root.?.left.?.left); + try expectNull(actual.root.?.left.?.right); + try testing.expect(actual.root.?.right != null); + try expectEqualChars('x', actual.root.?.right.?.data); + try testing.expect(actual.root.?.right.?.left != null); + try expectEqualChars('f', actual.root.?.right.?.left.?.data); + try expectNull(actual.root.?.right.?.left.?.left); + try expectNull(actual.root.?.right.?.left.?.right); + try testing.expect(actual.root.?.right.?.right != null); + try expectEqualChars('r', actual.root.?.right.?.right.?.data); + try expectNull(actual.root.?.right.?.right.?.left); + try expectNull(actual.root.?.right.?.right.?.right); } test "Reject traversals of different length" { const preorder: []const u8 = "ab"; const inorder: []const u8 = "bar"; - const actual: Result = .initFromTraversals( + var actual: Result = .initFromTraversals( testing.allocator, preorder, inorder, ); - defer if (actual) |a| a.deinit() else |_| {}; + defer if (actual) |*a| a.deinit() else |_| {}; try testing.expectError(error.DifferentLengths, actual); } test "Reject inconsistent traversals of same length" { const preorder: []const u8 = "xyz"; const inorder: []const u8 = "abc"; - const actual: Result = .initFromTraversals( + var actual: Result = .initFromTraversals( testing.allocator, preorder, inorder, ); - defer if (actual) |a| a.deinit() else |_| {}; + defer if (actual) |*a| a.deinit() else |_| {}; try testing.expectError(error.DifferentItems, actual); } test "Reject traversals with repeated items" { const preorder: []const u8 = "aba"; const inorder: []const u8 = "baa"; - const actual: Result = .initFromTraversals( + var actual: Result = .initFromTraversals( testing.allocator, preorder, inorder, ); - defer if (actual) |a| a.deinit() else |_| {}; + defer if (actual) |*a| a.deinit() else |_| {}; try testing.expectError(error.NonUniqueItems, actual); } test "A degenerate binary tree" { const preorder: []const u8 = "abcd"; const inorder: []const u8 = "dcba"; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expect(root != null); - try expectEqualChars('a', root.?.data); - try testing.expect(root.?.left != null); - try expectEqualChars('b', root.?.left.?.data); - try testing.expect(root.?.left.?.left != null); - try expectEqualChars('c', root.?.left.?.left.?.data); - try testing.expect(root.?.left.?.left.?.left != null); - try expectEqualChars('d', root.?.left.?.left.?.left.?.data); - try testing.expectEqual(null, root.?.left.?.left.?.left.?.left); - try testing.expectEqual(null, root.?.left.?.left.?.left.?.right); - try testing.expectEqual(null, root.?.left.?.left.?.right); - try testing.expectEqual(null, root.?.left.?.right); - try testing.expectEqual(null, root.?.right); + try testing.expect(actual.root != null); + try expectEqualChars('a', actual.root.?.data); + try testing.expect(actual.root.?.left != null); + try expectEqualChars('b', actual.root.?.left.?.data); + try testing.expect(actual.root.?.left.?.left != null); + try expectEqualChars('c', actual.root.?.left.?.left.?.data); + try testing.expect(actual.root.?.left.?.left.?.left != null); + try expectEqualChars('d', actual.root.?.left.?.left.?.left.?.data); + try expectNull(actual.root.?.left.?.left.?.left.?.left); + try expectNull(actual.root.?.left.?.left.?.left.?.right); + try expectNull(actual.root.?.left.?.left.?.right); + try expectNull(actual.root.?.left.?.right); + try expectNull(actual.root.?.right); } test "Another degenerate binary tree" { const preorder: []const u8 = "abcd"; const inorder: []const u8 = "abcd"; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expect(root != null); - try expectEqualChars('a', root.?.data); - try testing.expectEqual(null, root.?.left); - try testing.expect(root.?.right != null); - try expectEqualChars('b', root.?.right.?.data); - try testing.expectEqual(null, root.?.right.?.left); - try testing.expect(root.?.right.?.right != null); - try expectEqualChars('c', root.?.right.?.right.?.data); - try testing.expectEqual(null, root.?.right.?.right.?.left); - try testing.expect(root.?.right.?.right.?.right != null); - try expectEqualChars('d', root.?.right.?.right.?.right.?.data); - try testing.expectEqual(null, root.?.right.?.right.?.right.?.left); - try testing.expectEqual(null, root.?.right.?.right.?.right.?.right); + try testing.expect(actual.root != null); + try expectEqualChars('a', actual.root.?.data); + try expectNull(actual.root.?.left); + try testing.expect(actual.root.?.right != null); + try expectEqualChars('b', actual.root.?.right.?.data); + try expectNull(actual.root.?.right.?.left); + try testing.expect(actual.root.?.right.?.right != null); + try expectEqualChars('c', actual.root.?.right.?.right.?.data); + try expectNull(actual.root.?.right.?.right.?.left); + try testing.expect(actual.root.?.right.?.right.?.right != null); + try expectEqualChars('d', actual.root.?.right.?.right.?.right.?.data); + try expectNull(actual.root.?.right.?.right.?.right.?.left); + try expectNull(actual.root.?.right.?.right.?.right.?.right); } test "Tree with many more items" { const preorder: []const u8 = "abdghcefi"; const inorder: []const u8 = "gdhbaecif"; - const actual: Tree = try .initFromTraversals( + var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder, ); defer actual.deinit(); - const root = actual.root; - try testing.expect(root != null); - try expectEqualChars('a', root.?.data); - try testing.expect(root.?.left != null); - try expectEqualChars('b', root.?.left.?.data); - try testing.expect(root.?.left.?.left != null); - try expectEqualChars('d', root.?.left.?.left.?.data); - try testing.expect(root.?.left.?.left.?.left != null); - try expectEqualChars('g', root.?.left.?.left.?.left.?.data); - try testing.expectEqual(null, root.?.left.?.left.?.left.?.left); - try testing.expectEqual(null, root.?.left.?.left.?.left.?.right); - try testing.expect(root.?.left.?.left.?.right != null); - try expectEqualChars('h', root.?.left.?.left.?.right.?.data); - try testing.expectEqual(null, root.?.left.?.left.?.right.?.left); - try testing.expectEqual(null, root.?.left.?.left.?.right.?.right); - try testing.expectEqual(null, root.?.left.?.right); - try testing.expect(root.?.right != null); - try expectEqualChars('c', root.?.right.?.data); - try testing.expect(root.?.right.?.left != null); - try expectEqualChars('e', root.?.right.?.left.?.data); - try testing.expectEqual(null, root.?.right.?.left.?.left); - try testing.expectEqual(null, root.?.right.?.left.?.right); - try testing.expect(root.?.right.?.right != null); - try expectEqualChars('f', root.?.right.?.right.?.data); - try testing.expect(root.?.right.?.right.?.left != null); - try expectEqualChars('i', root.?.right.?.right.?.left.?.data); - try testing.expectEqual(null, root.?.right.?.right.?.left.?.left); - try testing.expectEqual(null, root.?.right.?.right.?.left.?.right); - try testing.expectEqual(null, root.?.right.?.right.?.right); + try testing.expect(actual.root != null); + try expectEqualChars('a', actual.root.?.data); + try testing.expect(actual.root.?.left != null); + try expectEqualChars('b', actual.root.?.left.?.data); + try testing.expect(actual.root.?.left.?.left != null); + try expectEqualChars('d', actual.root.?.left.?.left.?.data); + try testing.expect(actual.root.?.left.?.left.?.left != null); + try expectEqualChars('g', actual.root.?.left.?.left.?.left.?.data); + try expectNull(actual.root.?.left.?.left.?.left.?.left); + try expectNull(actual.root.?.left.?.left.?.left.?.right); + try testing.expect(actual.root.?.left.?.left.?.right != null); + try expectEqualChars('h', actual.root.?.left.?.left.?.right.?.data); + try expectNull(actual.root.?.left.?.left.?.right.?.left); + try expectNull(actual.root.?.left.?.left.?.right.?.right); + try expectNull(actual.root.?.left.?.right); + try testing.expect(actual.root.?.right != null); + try expectEqualChars('c', actual.root.?.right.?.data); + try testing.expect(actual.root.?.right.?.left != null); + try expectEqualChars('e', actual.root.?.right.?.left.?.data); + try expectNull(actual.root.?.right.?.left.?.left); + try expectNull(actual.root.?.right.?.left.?.right); + try testing.expect(actual.root.?.right.?.right != null); + try expectEqualChars('f', actual.root.?.right.?.right.?.data); + try testing.expect(actual.root.?.right.?.right.?.left != null); + try expectEqualChars('i', actual.root.?.right.?.right.?.left.?.data); + try expectNull(actual.root.?.right.?.right.?.left.?.left); + try expectNull(actual.root.?.right.?.right.?.left.?.right); + try expectNull(actual.root.?.right.?.right.?.right); } diff --git a/generators/exercises/satellite.py b/generators/exercises/satellite.py index 3519fdc3..94de1ab8 100644 --- a/generators/exercises/satellite.py +++ b/generators/exercises/satellite.py @@ -1,6 +1,7 @@ from lib import is_error HEADER = """const Tree = satellite.Tree; +const Node = satellite.Node; const Result = (std.mem.Allocator.Error || satellite.TraversalError)!Tree; fn expectEqualChars(expected: u8, actual: u8) !void { @@ -13,6 +14,16 @@ return error.TestExpectedEqual; } } + +fn expectNull(actual: ?*Node) !void { + const fmtChar = std.zig.fmtChar; + if (actual) |a| { + testing.failPrint("expected null, found node '{f}'\\n", .{ + fmtChar(a.data), + }); + return error.TestExpectedNull; + } +} """ _ERROR_MAP = { @@ -28,7 +39,7 @@ def _u8_const_slice(name, chars): def _traverse(expr, node, out): if not node: - out.append(f"try testing.expectEqual(null, {expr});\n") + out.append(f"try expectNull({expr});\n") return out.append(f"try testing.expect({expr} != null);\n") out.append(f"try expectEqualChars('{node['v']}', {expr}.?.data);\n") @@ -44,19 +55,18 @@ def gen_case(case): out = [_u8_const_slice("preorder", preorder), _u8_const_slice("inorder", inorder)] if is_error(expected): - out.append("""const actual: Result = .initFromTraversals( + out.append("""var actual: Result = .initFromTraversals( testing.allocator, preorder, inorder,); - defer if (actual) |a| a.deinit() else |_| {}; + defer if (actual) |*a| a.deinit() else |_| {}; """) err = _ERROR_MAP[expected["error"]] out.append(f"try testing.expectError(error.{err}, actual);\n") return "".join(out) - out.append("""const actual: Tree = try .initFromTraversals( + out.append("""var actual: Tree = try .initFromTraversals( testing.allocator, preorder, inorder,); defer actual.deinit(); - const root = actual.root; """) - _traverse("root", expected, out) + _traverse("actual.root", expected, out) return "".join(out) From 6a66c4891f0d9dda1046adcceb502dc6949c691b Mon Sep 17 00:00:00 2001 From: username is already taken Date: Tue, 3 Nov 2026 17:46:34 +0700 Subject: [PATCH 3/3] remove comma --- .../practice/satellite/test_satellite.zig | 36 ++++--------------- generators/exercises/satellite.py | 2 +- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/exercises/practice/satellite/test_satellite.zig b/exercises/practice/satellite/test_satellite.zig index 85b2dc39..c03155ab 100644 --- a/exercises/practice/satellite/test_satellite.zig +++ b/exercises/practice/satellite/test_satellite.zig @@ -30,11 +30,7 @@ fn expectNull(actual: ?*Node) !void { test "Empty tree" { const preorder: []const u8 = ""; const inorder: []const u8 = ""; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try expectNull(actual.root); } @@ -42,11 +38,7 @@ test "Empty tree" { test "Tree with one item" { const preorder: []const u8 = "a"; const inorder: []const u8 = "a"; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try testing.expect(actual.root != null); try expectEqualChars('a', actual.root.?.data); @@ -57,11 +49,7 @@ test "Tree with one item" { test "Tree with many items" { const preorder: []const u8 = "aixfr"; const inorder: []const u8 = "iafxr"; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try testing.expect(actual.root != null); try expectEqualChars('a', actual.root.?.data); @@ -120,11 +108,7 @@ test "Reject traversals with repeated items" { test "A degenerate binary tree" { const preorder: []const u8 = "abcd"; const inorder: []const u8 = "dcba"; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try testing.expect(actual.root != null); try expectEqualChars('a', actual.root.?.data); @@ -144,11 +128,7 @@ test "A degenerate binary tree" { test "Another degenerate binary tree" { const preorder: []const u8 = "abcd"; const inorder: []const u8 = "abcd"; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try testing.expect(actual.root != null); try expectEqualChars('a', actual.root.?.data); @@ -168,11 +148,7 @@ test "Another degenerate binary tree" { test "Tree with many more items" { const preorder: []const u8 = "abdghcefi"; const inorder: []const u8 = "gdhbaecif"; - var actual: Tree = try .initFromTraversals( - testing.allocator, - preorder, - inorder, - ); + var actual: Tree = try .initFromTraversals(testing.allocator, preorder, inorder); defer actual.deinit(); try testing.expect(actual.root != null); try expectEqualChars('a', actual.root.?.data); diff --git a/generators/exercises/satellite.py b/generators/exercises/satellite.py index 94de1ab8..a1db9836 100644 --- a/generators/exercises/satellite.py +++ b/generators/exercises/satellite.py @@ -64,7 +64,7 @@ def gen_case(case): return "".join(out) out.append("""var actual: Tree = try .initFromTraversals( - testing.allocator, preorder, inorder,); + testing.allocator, preorder, inorder); defer actual.deinit(); """) _traverse("actual.root", expected, out)