authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-25 02:46:14+02:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-25 02:46:14+02:00
log40ad0920b37564a4c119fa6fa385b76a9c2b0c21
treeda95a55454700a826cab0a1a5af6bca10c4ea392
parent857d8ac650b3154bfd320911f8d8fd0bd7ed9ea7
parent960469dc8a3c132c95e51bad304a23811675472f

Merge pull request 'std.testing: various improvements' (#36138) from K4/zig:pub into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36138 Reviewed-by: Ryan Liptak <squeek502@noreply.codeberg.org>

1 files changed, 135 insertions(+), 109 deletions(-)

lib/std/testing.zig+135-109
......@@ -18,10 +18,7 @@ var failing_allocator_instance = FailingAllocator.init(base_allocator_instance.a
1818var base_allocator_instance = std.heap.FixedBufferAllocator.init("");
1919
2020pub var allocator_instance: std.heap.SafeAllocator = undefined;
21pub const allocator = if (builtin.is_test)
22 allocator_instance.allocator()
23else
24 @compileError("not testing");
21pub const allocator = if (builtin.is_test) allocator_instance.allocator() else @compileError("not testing");
2522
2623pub var io_instance: Io.Threaded = undefined;
2724pub const io = if (builtin.is_test) io_instance.io() else @compileError("not testing");
......@@ -42,7 +39,8 @@ pub const backend_can_print = switch (builtin.zig_backend) {
4239 else => true,
4340};
4441
45fn print(comptime fmt: []const u8, args: anytype) void {
42/// Helper function for printing test failure information.
43pub fn failPrint(comptime fmt: []const u8, args: anytype) void {
4644 if (@inComptime()) {
4745 @compileError(std.fmt.comptimePrint(fmt, args));
4846 } else if (backend_can_print) {
......@@ -50,23 +48,6 @@ fn print(comptime fmt: []const u8, args: anytype) void {
5048 }
5149}
5250
53/// This function is intended to be used only in tests. It prints diagnostics to stderr
54/// and then returns a test failure error when actual_error_union is not expected_error.
55pub fn expectError(expected_error: anyerror, actual_error_union: anytype) !void {
56 if (actual_error_union) |actual_payload| {
57 print("expected error.{s}, found {any}\n", .{ @errorName(expected_error), actual_payload });
58 return error.TestExpectedError;
59 } else |actual_error| {
60 if (expected_error != actual_error) {
61 print("expected error.{s}, found error.{s}\n", .{
62 @errorName(expected_error),
63 @errorName(actual_error),
64 });
65 return error.TestUnexpectedError;
66 }
67 }
68}
69
7051/// This function is intended to be used only in tests. When the two values are not
7152/// equal, prints diagnostics to stderr to show exactly how they are not equal,
7253/// then returns a test failure error.
......@@ -92,7 +73,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
9273
9374 .type => {
9475 if (actual != expected) {
95 print("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) });
76 failPrint("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) });
9677 return error.TestExpectedEqual;
9778 }
9879 },
......@@ -108,7 +89,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
10889 .error_set,
10990 => {
11091 if (actual != expected) {
111 print("expected {any}, found {any}\n", .{ expected, actual });
92 failPrint("expected {any}, found {any}\n", .{ expected, actual });
11293 return error.TestExpectedEqual;
11394 }
11495 },
......@@ -117,17 +98,17 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
11798 switch (pointer.size) {
11899 .one, .many, .c => {
119100 if (actual != expected) {
120 print("expected {*}, found {*}\n", .{ expected, actual });
101 failPrint("expected {*}, found {*}\n", .{ expected, actual });
121102 return error.TestExpectedEqual;
122103 }
123104 },
124105 .slice => {
125106 if (actual.ptr != expected.ptr) {
126 print("expected slice ptr {*}, found {*}\n", .{ expected.ptr, actual.ptr });
107 failPrint("expected slice ptr {*}, found {*}\n", .{ expected.ptr, actual.ptr });
127108 return error.TestExpectedEqual;
128109 }
129110 if (actual.len != expected.len) {
130 print("expected slice len {}, found {}\n", .{ expected.len, actual.len });
111 failPrint("expected slice len {}, found {}\n", .{ expected.len, actual.len });
131112 return error.TestExpectedEqual;
132113 }
133114 },
......@@ -188,12 +169,12 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
188169 if (actual) |actual_payload| {
189170 try expectEqual(expected_payload, actual_payload);
190171 } else {
191 print("expected {any}, found null\n", .{expected_payload});
172 failPrint("expected {any}, found null\n", .{expected_payload});
192173 return error.TestExpectedEqual;
193174 }
194175 } else {
195176 if (actual) |actual_payload| {
196 print("expected null, found {any}\n", .{actual_payload});
177 failPrint("expected null, found {any}\n", .{actual_payload});
197178 return error.TestExpectedEqual;
198179 }
199180 }
......@@ -204,12 +185,12 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
204185 if (actual) |actual_payload| {
205186 try expectEqual(expected_payload, actual_payload);
206187 } else |actual_err| {
207 print("expected {any}, found {}\n", .{ expected_payload, actual_err });
188 failPrint("expected {any}, found {}\n", .{ expected_payload, actual_err });
208189 return error.TestExpectedEqual;
209190 }
210191 } else |expected_err| {
211192 if (actual) |actual_payload| {
212 print("expected {}, found {any}\n", .{ expected_err, actual_payload });
193 failPrint("expected {}, found {any}\n", .{ expected_err, actual_payload });
213194 return error.TestExpectedEqual;
214195 } else |actual_err| {
215196 try expectEqual(expected_err, actual_err);
......@@ -219,7 +200,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
219200 }
220201}
221202
222test "expectEqual.union(enum)" {
203test "expectEqual union(enum)" {
223204 const T = union(enum) {
224205 a: i32,
225206 b: f32,
......@@ -268,20 +249,6 @@ test "expectEqual null" {
268249 try expectEqual(a, b);
269250}
270251
271/// This function is intended to be used only in tests. When the formatted result of the template
272/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
273/// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing
274/// diagnostics.
275pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
276 if (@inComptime()) {
277 var buffer: [std.fmt.count(template, args)]u8 = undefined;
278 return expectEqualStrings(expected, try std.fmt.bufPrint(&buffer, template, args));
279 }
280 const actual = try std.fmt.allocPrint(allocator, template, args);
281 defer allocator.free(actual);
282 return expectEqualStrings(expected, actual);
283}
284
285252/// This function is intended to be used only in tests. When the actual value is
286253/// not approximately equal to the expected value, prints diagnostics to stderr
287254/// to show exactly how they are not equal, then returns a test failure error.
......@@ -296,7 +263,7 @@ pub inline fn expectApproxEqAbs(expected: anytype, actual: anytype, tolerance: a
296263fn expectApproxEqAbsInner(comptime T: type, expected: T, actual: T, tolerance: T) !void {
297264 switch (@typeInfo(T)) {
298265 .float => if (!math.approxEqAbs(T, expected, actual, tolerance)) {
299 print("actual {}, not within absolute tolerance {} of expected {}\n", .{ actual, tolerance, expected });
266 failPrint("actual {}, not within absolute tolerance {} of expected {}\n", .{ actual, tolerance, expected });
300267 return error.TestExpectedApproxEqAbs;
301268 },
302269
......@@ -332,7 +299,7 @@ pub inline fn expectApproxEqRel(expected: anytype, actual: anytype, tolerance: a
332299fn expectApproxEqRelInner(comptime T: type, expected: T, actual: T, tolerance: T) !void {
333300 switch (@typeInfo(T)) {
334301 .float => if (!math.approxEqRel(T, expected, actual, tolerance)) {
335 print("actual {}, not within relative tolerance {} of expected {}\n", .{ actual, tolerance, expected });
302 failPrint("actual {}, not within relative tolerance {} of expected {}\n", .{ actual, tolerance, expected });
336303 return error.TestExpectedApproxEqRel;
337304 },
338305
......@@ -358,7 +325,7 @@ test expectApproxEqRel {
358325}
359326
360327/// This function is intended to be used only in tests. When the two slices are
361/// not equal, prints diagnostics to stderr to show exactly how they are not
328/// not equal, it prints diagnostics to stderr to show exactly how they are not
362329/// equal (with the differences highlighted in red), then returns a test
363330/// failure error.
364331pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {
......@@ -553,7 +520,7 @@ const BytesDiffer = struct {
553520 }
554521};
555522
556test {
523test expectEqualSlices {
557524 try expectEqualSlices(u8, "foo\x00", "foo\x00");
558525 try expectEqualSlices(u16, &[_]u16{ 100, 200, 300, 400 }, &[_]u16{ 100, 200, 300, 400 });
559526 const E = enum { foo, bar };
......@@ -567,8 +534,10 @@ test {
567534 );
568535}
569536
570/// This function is intended to be used only in tests. Checks that two slices or two arrays are equal,
571/// including that their sentinel (if any) are the same. Will error if given another type.
537/// This function is intended to be used only in tests. When the two slices or two arrays are not equal,
538/// or their sentinel (if any) are not the same, it prints diagnostics to stderr to show exactly how
539/// they are not equal (with the differences highlighted in red), then returns a test failure error.
540/// It partially depends on `expectEquaSlices` for printing diagnostics.
572541pub fn expectEqualSentinel(comptime T: type, comptime sentinel: T, expected: [:sentinel]const T, actual: [:sentinel]const T) !void {
573542 try expectEqualSlices(T, expected, actual);
574543
......@@ -599,12 +568,12 @@ pub fn expectEqualSentinel(comptime T: type, comptime sentinel: T, expected: [:s
599568 };
600569
601570 if (!std.meta.eql(sentinel, expected_value_sentinel)) {
602 print("expectEqualSentinel: 'expected' sentinel in memory is different from its type sentinel. type sentinel {}, in memory sentinel {}\n", .{ sentinel, expected_value_sentinel });
571 failPrint("expectEqualSentinel: 'expected' sentinel in memory is different from its type sentinel. type sentinel {}, in memory sentinel {}\n", .{ sentinel, expected_value_sentinel });
603572 return error.TestExpectedEqual;
604573 }
605574
606575 if (!std.meta.eql(sentinel, actual_value_sentinel)) {
607 print("expectEqualSentinel: 'actual' sentinel in memory is different from its type sentinel. type sentinel {}, in memory sentinel {}\n", .{ sentinel, actual_value_sentinel });
576 failPrint("expectEqualSentinel: 'actual' sentinel in memory is different from its type sentinel. type sentinel {}, in memory sentinel {}\n", .{ sentinel, actual_value_sentinel });
608577 return error.TestExpectedEqual;
609578 }
610579}
......@@ -654,6 +623,48 @@ pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir {
654623 };
655624}
656625
626/// This function is intended to be used only in tests. When `actual_error_union` is not
627/// `expected_error`, it prints diagnostics to stderr, then returns a test failure error.
628pub fn expectError(expected_error: anyerror, actual_error_union: anytype) !void {
629 if (actual_error_union) |actual_payload| {
630 failPrint("expected error.{s}, found {any}\n", .{ @errorName(expected_error), actual_payload });
631 return error.TestExpectedError;
632 } else |actual_error| {
633 if (expected_error != actual_error) {
634 failPrint("expected error.{s}, found error.{s}\n", .{
635 @errorName(expected_error),
636 @errorName(actual_error),
637 });
638 return error.TestUnexpectedError;
639 }
640 }
641}
642
643fn returnErrorUnion() !u8 {
644 return error.Expected;
645}
646
647test expectError {
648 const actualErrorUnion = returnErrorUnion();
649 try expectError(error.Expected, actualErrorUnion);
650}
651
652/// This function is intended to be used only in tests. When the formatted result of the template
653/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
654/// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing
655/// diagnostics.
656pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
657 if (@inComptime()) {
658 var buffer: [std.fmt.count(template, args)]u8 = undefined;
659 return expectEqualStrings(expected, try std.fmt.bufPrint(&buffer, template, args));
660 }
661 const actual = try std.fmt.allocPrint(allocator, template, args);
662 defer allocator.free(actual);
663 return expectEqualStrings(expected, actual);
664}
665
666// This function is intended to be used only in test. When the two strings are not equal,
667/// it prints diagnostics to stderr to show how they are not equal, then returns an error.
657668pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
658669 if (std.mem.findDiff(u8, actual, expected)) |diff_index| {
659670 if (@inComptime()) {
......@@ -661,28 +672,34 @@ pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
661672 expected, actual, diff_index,
662673 }));
663674 }
664 print("\n====== expected this output: =========\n", .{});
665 printWithVisibleNewlines(expected);
666 print("\n======== instead found this: =========\n", .{});
667 printWithVisibleNewlines(actual);
668 print("\n======================================\n", .{});
675 failPrint("\n====== expected this output: =========\n", .{});
676 failPrintWithVisibleNewlines(expected);
677 failPrint("\n======== instead found this: =========\n", .{});
678 failPrintWithVisibleNewlines(actual);
679 failPrint("\n======================================\n", .{});
669680
670681 var diff_line_number: usize = 1;
671682 for (expected[0..diff_index]) |value| {
672683 if (value == '\n') diff_line_number += 1;
673684 }
674 print("First difference occurs on line {d}:\n", .{diff_line_number});
685 failPrint("First difference occurs on line {d}:\n", .{diff_line_number});
675686
676 print("expected:\n", .{});
677 printIndicatorLine(expected, diff_index);
687 failPrint("expected:\n", .{});
688 failPrintIndicatorLine(expected, diff_index);
678689
679 print("found:\n", .{});
680 printIndicatorLine(actual, diff_index);
690 failPrint("found:\n", .{});
691 failPrintIndicatorLine(actual, diff_index);
681692
682693 return error.TestExpectedEqual;
683694 }
684695}
685696
697test expectEqualStrings {
698 try expectEqualStrings("foo", "foo");
699}
700
701/// This function is intended to be used only in test. When the start of `actual` and `expected_starts_with`
702/// are not equal, it prints diagnostics to stderr to show how they are not equal, then returns an error.
686703pub fn expectStringStartsWith(actual: []const u8, expected_starts_with: []const u8) !void {
687704 if (std.mem.startsWith(u8, actual, expected_starts_with))
688705 return;
......@@ -692,17 +709,23 @@ pub fn expectStringStartsWith(actual: []const u8, expected_starts_with: []const
692709 else
693710 actual;
694711
695 print("\n====== expected to start with: =========\n", .{});
696 printWithVisibleNewlines(expected_starts_with);
697 print("\n====== instead started with: ===========\n", .{});
698 printWithVisibleNewlines(shortened_actual);
699 print("\n========= full output: ==============\n", .{});
700 printWithVisibleNewlines(actual);
701 print("\n======================================\n", .{});
712 failPrint("\n====== expected to start with: =========\n", .{});
713 failPrintWithVisibleNewlines(expected_starts_with);
714 failPrint("\n====== instead started with: ===========\n", .{});
715 failPrintWithVisibleNewlines(shortened_actual);
716 failPrint("\n========= full output: ==============\n", .{});
717 failPrintWithVisibleNewlines(actual);
718 failPrint("\n======================================\n", .{});
702719
703720 return error.TestExpectedStartsWith;
704721}
705722
723test expectStringStartsWith {
724 try expectStringStartsWith("foobar", "foo");
725}
726
727/// This function is intended to be used only in test. When the end of `actual` and `expected_ends_with`
728/// are not equal, it prints diagnostics to stderr to show how they are not equal, then returns an error.
706729pub fn expectStringEndsWith(actual: []const u8, expected_ends_with: []const u8) !void {
707730 if (std.mem.endsWith(u8, actual, expected_ends_with))
708731 return;
......@@ -712,17 +735,21 @@ pub fn expectStringEndsWith(actual: []const u8, expected_ends_with: []const u8)
712735 else
713736 actual;
714737
715 print("\n====== expected to end with: =========\n", .{});
716 printWithVisibleNewlines(expected_ends_with);
717 print("\n====== instead ended with: ===========\n", .{});
718 printWithVisibleNewlines(shortened_actual);
719 print("\n========= full output: ==============\n", .{});
720 printWithVisibleNewlines(actual);
721 print("\n======================================\n", .{});
738 failPrint("\n====== expected to end with: =========\n", .{});
739 failPrintWithVisibleNewlines(expected_ends_with);
740 failPrint("\n====== instead ended with: ===========\n", .{});
741 failPrintWithVisibleNewlines(shortened_actual);
742 failPrint("\n========= full output: ==============\n", .{});
743 failPrintWithVisibleNewlines(actual);
744 failPrint("\n======================================\n", .{});
722745
723746 return error.TestExpectedEndsWith;
724747}
725748
749test expectStringEndsWith {
750 try expectStringEndsWith("foobar", "bar");
751}
752
726753/// This function is intended to be used only in tests. When the two values are not
727754/// deeply equal, prints diagnostics to stderr to show exactly how they are not equal,
728755/// then returns a test failure error.
......@@ -757,7 +784,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
757784
758785 .type => {
759786 if (actual != expected) {
760 print("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) });
787 failPrint("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) });
761788 return error.TestExpectedEqual;
762789 }
763790 },
......@@ -773,7 +800,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
773800 .error_set,
774801 => {
775802 if (actual != expected) {
776 print("expected {any}, found {any}\n", .{ expected, actual });
803 failPrint("expected {any}, found {any}\n", .{ expected, actual });
777804 return error.TestExpectedEqual;
778805 }
779806 },
......@@ -783,7 +810,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
783810 // We have no idea what is behind those pointers, so the best we can do is `==` check.
784811 .c, .many => {
785812 if (actual != expected) {
786 print("expected {*}, found {*}\n", .{ expected, actual });
813 failPrint("expected {*}, found {*}\n", .{ expected, actual });
787814 return error.TestExpectedEqual;
788815 }
789816 },
......@@ -792,7 +819,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
792819 switch (@typeInfo(pointer.child)) {
793820 .@"fn", .@"opaque" => {
794821 if (actual != expected) {
795 print("expected {*}, found {*}\n", .{ expected, actual });
822 failPrint("expected {*}, found {*}\n", .{ expected, actual });
796823 return error.TestExpectedEqual;
797824 }
798825 },
......@@ -801,13 +828,13 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
801828 },
802829 .slice => {
803830 if (expected.len != actual.len) {
804 print("Slice len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
831 failPrint("Slice len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
805832 return error.TestExpectedEqual;
806833 }
807834 var i: usize = 0;
808835 while (i < expected.len) : (i += 1) {
809836 expectEqualDeep(expected[i], actual[i]) catch |e| {
810 print("index {d} incorrect. expected {any}, found {any}\n", .{
837 failPrint("index {d} incorrect. expected {any}, found {any}\n", .{
811838 i, expected[i], actual[i],
812839 });
813840 return e;
......@@ -819,13 +846,13 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
819846
820847 .array => {
821848 if (expected.len != actual.len) {
822 print("Array len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
849 failPrint("Array len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
823850 return error.TestExpectedEqual;
824851 }
825852 var i: usize = 0;
826853 while (i < expected.len) : (i += 1) {
827854 expectEqualDeep(expected[i], actual[i]) catch |e| {
828 print("index {d} incorrect. expected {any}, found {any}\n", .{
855 failPrint("index {d} incorrect. expected {any}, found {any}\n", .{
829856 i, expected[i], actual[i],
830857 });
831858 return e;
......@@ -835,12 +862,12 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
835862
836863 .vector => |info| {
837864 if (info.len != @typeInfo(@TypeOf(actual)).vector.len) {
838 print("Vector len not the same, expected {d}, found {d}\n", .{ info.len, @typeInfo(@TypeOf(actual)).vector.len });
865 failPrint("Vector len not the same, expected {d}, found {d}\n", .{ info.len, @typeInfo(@TypeOf(actual)).vector.len });
839866 return error.TestExpectedEqual;
840867 }
841868 inline for (0..info.len) |i| {
842869 expectEqualDeep(expected[i], actual[i]) catch |e| {
843 print("index {d} incorrect. expected {any}, found {any}\n", .{
870 failPrint("index {d} incorrect. expected {any}, found {any}\n", .{
844871 i, expected[i], actual[i],
845872 });
846873 return e;
......@@ -851,7 +878,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
851878 .@"struct" => |structType| {
852879 inline for (structType.field_names) |field_name| {
853880 expectEqualDeep(@field(expected, field_name), @field(actual, field_name)) catch |e| {
854 print("Field {s} incorrect. expected {any}, found {any}\n", .{ field_name, @field(expected, field_name), @field(actual, field_name) });
881 failPrint("Field {s} incorrect. expected {any}, found {any}\n", .{ field_name, @field(expected, field_name), @field(actual, field_name) });
855882 return e;
856883 };
857884 }
......@@ -882,12 +909,12 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
882909 if (actual) |actual_payload| {
883910 try expectEqualDeep(expected_payload, actual_payload);
884911 } else {
885 print("expected {any}, found null\n", .{expected_payload});
912 failPrint("expected {any}, found null\n", .{expected_payload});
886913 return error.TestExpectedEqual;
887914 }
888915 } else {
889916 if (actual) |actual_payload| {
890 print("expected null, found {any}\n", .{actual_payload});
917 failPrint("expected null, found {any}\n", .{actual_payload});
891918 return error.TestExpectedEqual;
892919 }
893920 }
......@@ -898,12 +925,12 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
898925 if (actual) |actual_payload| {
899926 try expectEqualDeep(expected_payload, actual_payload);
900927 } else |actual_err| {
901 print("expected {any}, found {any}\n", .{ expected_payload, actual_err });
928 failPrint("expected {any}, found {any}\n", .{ expected_payload, actual_err });
902929 return error.TestExpectedEqual;
903930 }
904931 } else |expected_err| {
905932 if (actual) |actual_payload| {
906 print("expected {any}, found {any}\n", .{ expected_err, actual_payload });
933 failPrint("expected {any}, found {any}\n", .{ expected_err, actual_payload });
907934 return error.TestExpectedEqual;
908935 } else |actual_err| {
909936 try expectEqualDeep(expected_err, actual_err);
......@@ -999,7 +1026,8 @@ test "expectEqualDeep composite type" {
9991026 );
10001027}
10011028
1002fn printIndicatorLine(source: []const u8, indicator_index: usize) void {
1029/// Helper function for printing test failure information.
1030pub fn failPrintIndicatorLine(source: []const u8, indicator_index: usize) void {
10031031 const line_begin_index = if (std.mem.findScalarLast(u8, source[0..indicator_index], '\n')) |line_begin|
10041032 line_begin + 1
10051033 else
......@@ -1009,33 +1037,31 @@ fn printIndicatorLine(source: []const u8, indicator_index: usize) void {
10091037 else
10101038 source.len;
10111039
1012 printLine(source[line_begin_index..line_end_index]);
1040 failPrintLine(source[line_begin_index..line_end_index]);
10131041 for (line_begin_index..indicator_index) |_|
1014 print(" ", .{});
1042 failPrint(" ", .{});
10151043 if (indicator_index >= source.len)
1016 print("^ (end of string)\n", .{})
1044 failPrint("^ (end of string)\n", .{})
10171045 else
1018 print("^ ('\\x{x:0>2}')\n", .{source[indicator_index]});
1046 failPrint("^ ('\\x{x:0>2}')\n", .{source[indicator_index]});
10191047}
10201048
1021fn printWithVisibleNewlines(source: []const u8) void {
1049/// Helper function for printing test failure information.
1050pub fn failPrintWithVisibleNewlines(source: []const u8) void {
10221051 var i: usize = 0;
10231052 while (std.mem.findScalar(u8, source[i..], '\n')) |nl| : (i += nl + 1) {
1024 printLine(source[i..][0..nl]);
1053 failPrintLine(source[i..][0..nl]);
10251054 }
1026 print("{s}␃\n", .{source[i..]}); // End of Text symbol (ETX)
1055 failPrint("{s}␃\n", .{source[i..]}); // End of Text symbol (ETX)
10271056}
10281057
1029fn printLine(line: []const u8) void {
1058/// Helper function for printing test failure information.
1059pub fn failPrintLine(line: []const u8) void {
10301060 if (line.len != 0) switch (line[line.len - 1]) {
1031 ' ', '\t' => return print("{s}⏎\n", .{line}), // Return symbol
1061 ' ', '\t' => return failPrint("{s}⏎\n", .{line}), // Return symbol
10321062 else => {},
10331063 };
1034 print("{s}\n", .{line});
1035}
1036
1037test {
1038 try expectEqualStrings("foo", "foo");
1064 failPrint("{s}\n", .{line});
10391065}
10401066
10411067/// Exhaustively check that allocation failures within `test_fn` are handled without
......@@ -1140,7 +1166,7 @@ pub fn checkAllAllocationFailures(
11401166 } else |err| switch (err) {
11411167 error.OutOfMemory => {
11421168 if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
1143 print(
1169 failPrint(
11441170 "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}",
11451171 .{
11461172 fail_index,