authorgravatar for lachlan@lakebythewoods.xyzLachlan Easton <lachlan@lakebythewoods.xyz> 2020-03-09 13:53:20+11:00
committergravatar for lachlan@lakebythewoods.xyzLachlan Easton <lachlan@lakebythewoods.xyz> 2020-04-10 10:38:36+10:00
logdaff072af2afe794d516b1406073ada877e4b1ab
tree4520239a795e75c10d6284007dd95e45df10d262
parentbeae932e0f8ab39f97a142282c67c83c979f8be1

Add visible newlines to parser_test output when there's a failure.

Also print first line that differs between expected and result.

2 files changed, 66 insertions(+), 2 deletions(-)

lib/std/mem.zig+19
...@@ -492,6 +492,25 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {...@@ -492,6 +492,25 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
492 return true;492 return true;
493}493}
494494
495/// Compares two slices and returns the index of the first inequality.
496/// Returns the length of the slices if they are equal.
497pub fn diffIndex(comptime T: type, a: []const T, b: []const T) usize {
498 const shortest = math.min(a.len, b.len);
499 if (a.ptr == b.ptr)
500 return shortest;
501 var index: usize = 0;
502 while (index < shortest) : (index += 1) if (a[index] != b[index]) return index;
503 return shortest;
504}
505
506test "diffIndex" {
507 testing.expectEqual(diffIndex(u8, "one", "one"), 3);
508 testing.expectEqual(diffIndex(u8, "one two", "one"), 3);
509 testing.expectEqual(diffIndex(u8, "one", "one two"), 3);
510 testing.expectEqual(diffIndex(u8, "one twx", "one two"), 6);
511 testing.expectEqual(diffIndex(u8, "xne", "one"), 0);
512}
513
495pub const toSliceConst = @compileError("deprecated; use std.mem.spanZ");514pub const toSliceConst = @compileError("deprecated; use std.mem.spanZ");
496pub const toSlice = @compileError("deprecated; use std.mem.spanZ");515pub const toSlice = @compileError("deprecated; use std.mem.spanZ");
497516
lib/std/zig/parser_test.zig+47-2
...@@ -2960,6 +2960,36 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b...@@ -2960,6 +2960,36 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
2960 return buffer.toOwnedSlice();2960 return buffer.toOwnedSlice();
2961}2961}
29622962
2963fn printLine(line: []const u8) void {
2964 warn("{}⏎\n", .{line}); // Carriage return symbol
2965}
2966
2967fn printIndicatorLine(source: []const u8, indicator_index: usize) void {
2968 const line_begin_index = if (mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin|
2969 line_begin + 1
2970 else
2971 0;
2972 const line_end_index = if (mem.indexOfScalar(u8, source[indicator_index..], '\n')) |line_end|
2973 (indicator_index + line_end)
2974 else
2975 (source.len - 1);
2976 printLine(source[line_begin_index..line_end_index]);
2977 {
2978 var i: usize = line_begin_index;
2979 while (i < indicator_index) : (i += 1)
2980 warn(" ", .{});
2981 }
2982 warn("^~~~~\n", .{});
2983}
2984
2985fn printWithVisibleNewlines(source: []const u8) void {
2986 var i: usize = 0;
2987 while (mem.indexOf(u8, source[i..], "\n")) |nl| : (i += nl + 1) {
2988 printLine(source[i .. i + nl]);
2989 }
2990 warn("{}{}\n", .{ source[i..], "\u{2403}" }); // End of Text symbol (ETX)
2991}
2992
2963fn testTransform(source: []const u8, expected_source: []const u8) !void {2993fn testTransform(source: []const u8, expected_source: []const u8) !void {
2964 const needed_alloc_count = x: {2994 const needed_alloc_count = x: {
2965 // Try it once with unlimited memory, make sure it works2995 // Try it once with unlimited memory, make sure it works
...@@ -2969,10 +2999,25 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -2969,10 +2999,25 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
2969 const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed);2999 const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed);
2970 if (!mem.eql(u8, result_source, expected_source)) {3000 if (!mem.eql(u8, result_source, expected_source)) {
2971 warn("\n====== expected this output: =========\n", .{});3001 warn("\n====== expected this output: =========\n", .{});
2972 warn("{}", .{expected_source});3002 printWithVisibleNewlines(expected_source);
2973 warn("\n======== instead found this: =========\n", .{});3003 warn("\n======== instead found this: =========\n", .{});
2974 warn("{}", .{result_source});3004 printWithVisibleNewlines(result_source);
2975 warn("\n======================================\n", .{});3005 warn("\n======================================\n", .{});
3006
3007 const diff_index = mem.diffIndex(u8, result_source, expected_source);
3008
3009 var diff_line_number: usize = 1;
3010 for (expected_source[0..diff_index]) |value| {
3011 if (value == '\n') diff_line_number += 1;
3012 }
3013 warn("First difference occurs on line {}:\n", .{diff_line_number});
3014
3015 warn("expected:\n", .{});
3016 printIndicatorLine(expected_source, diff_index);
3017
3018 warn("found:\n", .{});
3019 printIndicatorLine(result_source, diff_index);
3020
2976 return error.TestFailed;3021 return error.TestFailed;
2977 }3022 }
2978 const changes_expected = source.ptr != expected_source.ptr;3023 const changes_expected = source.ptr != expected_source.ptr;