From daff072af2afe794d516b1406073ada877e4b1ab Mon Sep 17 00:00:00 2001 From: Lachlan Easton Date: Mon, 9 Mar 2020 13:53:20 +1100 Subject: [PATCH 1/3] Add visible newlines to parser_test output when there's a failure. Also print first line that differs between expected and result. --- lib/std/mem.zig | 19 ++++++++++++++ lib/std/zig/parser_test.zig | 49 +++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a21626e3a1..8dcd60bb82 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -492,6 +492,25 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { return true; } +/// Compares two slices and returns the index of the first inequality. +/// Returns the length of the slices if they are equal. +pub fn diffIndex(comptime T: type, a: []const T, b: []const T) usize { + const shortest = math.min(a.len, b.len); + if (a.ptr == b.ptr) + return shortest; + var index: usize = 0; + while (index < shortest) : (index += 1) if (a[index] != b[index]) return index; + return shortest; +} + +test "diffIndex" { + testing.expectEqual(diffIndex(u8, "one", "one"), 3); + testing.expectEqual(diffIndex(u8, "one two", "one"), 3); + testing.expectEqual(diffIndex(u8, "one", "one two"), 3); + testing.expectEqual(diffIndex(u8, "one twx", "one two"), 6); + testing.expectEqual(diffIndex(u8, "xne", "one"), 0); +} + pub const toSliceConst = @compileError("deprecated; use std.mem.spanZ"); pub const toSlice = @compileError("deprecated; use std.mem.spanZ"); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 91921786a2..c2f29d213b 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2960,6 +2960,36 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b return buffer.toOwnedSlice(); } +fn printLine(line: []const u8) void { + warn("{}⏎\n", .{line}); // Carriage return symbol +} + +fn printIndicatorLine(source: []const u8, indicator_index: usize) void { + const line_begin_index = if (mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin| + line_begin + 1 + else + 0; + const line_end_index = if (mem.indexOfScalar(u8, source[indicator_index..], '\n')) |line_end| + (indicator_index + line_end) + else + (source.len - 1); + printLine(source[line_begin_index..line_end_index]); + { + var i: usize = line_begin_index; + while (i < indicator_index) : (i += 1) + warn(" ", .{}); + } + warn("^~~~~\n", .{}); +} + +fn printWithVisibleNewlines(source: []const u8) void { + var i: usize = 0; + while (mem.indexOf(u8, source[i..], "\n")) |nl| : (i += nl + 1) { + printLine(source[i .. i + nl]); + } + warn("{}{}\n", .{ source[i..], "\u{2403}" }); // End of Text symbol (ETX) +} + fn testTransform(source: []const u8, expected_source: []const u8) !void { const needed_alloc_count = x: { // Try it once with unlimited memory, make sure it works @@ -2969,10 +2999,25 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed); if (!mem.eql(u8, result_source, expected_source)) { warn("\n====== expected this output: =========\n", .{}); - warn("{}", .{expected_source}); + printWithVisibleNewlines(expected_source); warn("\n======== instead found this: =========\n", .{}); - warn("{}", .{result_source}); + printWithVisibleNewlines(result_source); warn("\n======================================\n", .{}); + + const diff_index = mem.diffIndex(u8, result_source, expected_source); + + var diff_line_number: usize = 1; + for (expected_source[0..diff_index]) |value| { + if (value == '\n') diff_line_number += 1; + } + warn("First difference occurs on line {}:\n", .{diff_line_number}); + + warn("expected:\n", .{}); + printIndicatorLine(expected_source, diff_index); + + warn("found:\n", .{}); + printIndicatorLine(result_source, diff_index); + return error.TestFailed; } const changes_expected = source.ptr != expected_source.ptr; From 2d06e731ec4feee03a2a9bc79eb44b15e2db2488 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 29 Apr 2020 14:09:12 +0300 Subject: [PATCH 2/3] rename diffIndex to indexOfDiff --- lib/std/mem.zig | 20 ++++++++++---------- lib/std/zig/parser_test.zig | 4 +--- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8dcd60bb82..b7df43799b 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -493,22 +493,22 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { } /// Compares two slices and returns the index of the first inequality. -/// Returns the length of the slices if they are equal. -pub fn diffIndex(comptime T: type, a: []const T, b: []const T) usize { +/// Returns null if the slices are equal. +pub fn indexOfDiff(comptime T: type, a: []const T, b: []const T) ?usize { const shortest = math.min(a.len, b.len); if (a.ptr == b.ptr) - return shortest; + return if (a.len == b.len) null else shortest; var index: usize = 0; while (index < shortest) : (index += 1) if (a[index] != b[index]) return index; - return shortest; + return if (a.len == b.len) null else shortest; } -test "diffIndex" { - testing.expectEqual(diffIndex(u8, "one", "one"), 3); - testing.expectEqual(diffIndex(u8, "one two", "one"), 3); - testing.expectEqual(diffIndex(u8, "one", "one two"), 3); - testing.expectEqual(diffIndex(u8, "one twx", "one two"), 6); - testing.expectEqual(diffIndex(u8, "xne", "one"), 0); +test "indexOfDiff" { + testing.expectEqual(indexOfDiff(u8, "one", "one"), null); + testing.expectEqual(indexOfDiff(u8, "one two", "one"), 3); + testing.expectEqual(indexOfDiff(u8, "one", "one two"), 3); + testing.expectEqual(indexOfDiff(u8, "one twx", "one two"), 6); + testing.expectEqual(indexOfDiff(u8, "xne", "one"), 0); } pub const toSliceConst = @compileError("deprecated; use std.mem.spanZ"); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index c2f29d213b..81e5d6cdda 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2997,15 +2997,13 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize)); var anything_changed: bool = undefined; const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed); - if (!mem.eql(u8, result_source, expected_source)) { + if (mem.indexOfDiff(u8, result_source, expected_source)) |diff_index| { warn("\n====== expected this output: =========\n", .{}); printWithVisibleNewlines(expected_source); warn("\n======== instead found this: =========\n", .{}); printWithVisibleNewlines(result_source); warn("\n======================================\n", .{}); - const diff_index = mem.diffIndex(u8, result_source, expected_source); - var diff_line_number: usize = 1; for (expected_source[0..diff_index]) |value| { if (value == '\n') diff_line_number += 1; From 87c9696121048fe9c14b898e26037f939d7959f0 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 29 Apr 2020 14:40:52 +0300 Subject: [PATCH 3/3] move printWithVisibleNewlines to testing.expectEqualStrings --- lib/std/testing.zig | 63 +++++++++++++++++++++++++++++++++++++ lib/std/zig/parser_test.zig | 52 +----------------------------- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 4b629156f6..fed2b15bf5 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -1,4 +1,5 @@ const std = @import("std.zig"); +const warn = std.debug.warn; pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator; pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator; @@ -212,3 +213,65 @@ test "expectEqual vector" { expectEqual(a, b); } + +pub fn expectEqualStrings(expected: []const u8, actual: []const u8) void { + if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| { + warn("\n====== expected this output: =========\n", .{}); + printWithVisibleNewlines(expected); + warn("\n======== instead found this: =========\n", .{}); + printWithVisibleNewlines(actual); + warn("\n======================================\n", .{}); + + var diff_line_number: usize = 1; + for (expected[0..diff_index]) |value| { + if (value == '\n') diff_line_number += 1; + } + warn("First difference occurs on line {}:\n", .{diff_line_number}); + + warn("expected:\n", .{}); + printIndicatorLine(expected, diff_index); + + warn("found:\n", .{}); + printIndicatorLine(actual, diff_index); + + @panic("test failure"); + } +} + +fn printIndicatorLine(source: []const u8, indicator_index: usize) void { + const line_begin_index = if (std.mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin| + line_begin + 1 + else + 0; + const line_end_index = if (std.mem.indexOfScalar(u8, source[indicator_index..], '\n')) |line_end| + (indicator_index + line_end) + else + source.len; + + printLine(source[line_begin_index..line_end_index]); + { + var i: usize = line_begin_index; + while (i < indicator_index) : (i += 1) + warn(" ", .{}); + } + warn("^\n", .{}); +} + +fn printWithVisibleNewlines(source: []const u8) void { + var i: usize = 0; + while (std.mem.indexOf(u8, source[i..], "\n")) |nl| : (i += nl + 1) { + printLine(source[i .. i + nl]); + } + warn("{}␃\n", .{source[i..]}); // End of Text symbol (ETX) +} + +fn printLine(line: []const u8) void { + switch (line[line.len - 1]) { + ' ', '\t' => warn("{}⏎\n", .{line}), // Carriage return symbol, + else => warn("{}\n", .{line}), + } +} + +test "" { + expectEqualStrings("foo", "foo"); +} diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 81e5d6cdda..d3ae599c6e 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2960,36 +2960,6 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b return buffer.toOwnedSlice(); } -fn printLine(line: []const u8) void { - warn("{}⏎\n", .{line}); // Carriage return symbol -} - -fn printIndicatorLine(source: []const u8, indicator_index: usize) void { - const line_begin_index = if (mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin| - line_begin + 1 - else - 0; - const line_end_index = if (mem.indexOfScalar(u8, source[indicator_index..], '\n')) |line_end| - (indicator_index + line_end) - else - (source.len - 1); - printLine(source[line_begin_index..line_end_index]); - { - var i: usize = line_begin_index; - while (i < indicator_index) : (i += 1) - warn(" ", .{}); - } - warn("^~~~~\n", .{}); -} - -fn printWithVisibleNewlines(source: []const u8) void { - var i: usize = 0; - while (mem.indexOf(u8, source[i..], "\n")) |nl| : (i += nl + 1) { - printLine(source[i .. i + nl]); - } - warn("{}{}\n", .{ source[i..], "\u{2403}" }); // End of Text symbol (ETX) -} - fn testTransform(source: []const u8, expected_source: []const u8) !void { const needed_alloc_count = x: { // Try it once with unlimited memory, make sure it works @@ -2997,27 +2967,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { var failing_allocator = std.testing.FailingAllocator.init(&fixed_allocator.allocator, maxInt(usize)); var anything_changed: bool = undefined; const result_source = try testParse(source, &failing_allocator.allocator, &anything_changed); - if (mem.indexOfDiff(u8, result_source, expected_source)) |diff_index| { - warn("\n====== expected this output: =========\n", .{}); - printWithVisibleNewlines(expected_source); - warn("\n======== instead found this: =========\n", .{}); - printWithVisibleNewlines(result_source); - warn("\n======================================\n", .{}); - - var diff_line_number: usize = 1; - for (expected_source[0..diff_index]) |value| { - if (value == '\n') diff_line_number += 1; - } - warn("First difference occurs on line {}:\n", .{diff_line_number}); - - warn("expected:\n", .{}); - printIndicatorLine(expected_source, diff_index); - - warn("found:\n", .{}); - printIndicatorLine(result_source, diff_index); - - return error.TestFailed; - } + std.testing.expectEqualStrings(expected_source, result_source); const changes_expected = source.ptr != expected_source.ptr; if (anything_changed != changes_expected) { warn("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });