mymarkdown

My markdown
git clone https://git.grace.moe/mymarkdown
Log | Files | Refs

commit 200b8c58cce70c76e5665ff48fd52f1ba9938ef5
parent 9a3da9d4fa2075ca5a908dd115845df4e769c987
Author: gracefu <81774659+gracefuu@users.noreply.github.com>
Date:   Thu, 22 May 2025 03:28:13 +0800

Move to snapshot tests and remove old AstGens from test

Diffstat:
Msrc/test.zig | 564+++++++------------------------------------------------------------------------
Asrc/test/elaboration.my | 14++++++++++++++
Asrc/test/elaboration.my.ast | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test/empty.my | 0
Asrc/test/empty.my.ast | 1+
Asrc/test/heading.my | 31+++++++++++++++++++++++++++++++
Asrc/test/heading.my.ast | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test/list.my | 18++++++++++++++++++
Asrc/test/list.my.ast | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test/paragraph.my | 7+++++++
Asrc/test/paragraph.my.ast | 14++++++++++++++
Asrc/test/quote.my | 8++++++++
Asrc/test/quote.my.ast | 24++++++++++++++++++++++++
Asrc/test/thematic_break.my | 7+++++++
Asrc/test/thematic_break.my.ast | 16++++++++++++++++
15 files changed, 428 insertions(+), 518 deletions(-)

diff --git a/src/test.zig b/src/test.zig @@ -1,6 +1,4 @@ const std = @import("std"); -const parse = @import("AstGen.zig").parse; -const parse2 = @import("AstGen2.zig").parse; const parse3 = @import("AstGen3.zig").parse; const Ast = @import("Ast.zig"); const PADDING = @import("padded_str.zig").PADDING; @@ -8,11 +6,6 @@ const PADDING = @import("padded_str.zig").PADDING; const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator(.{}); const ArenaAllocator = std.heap.ArenaAllocator; -// This is in a function so the result is memoized. -fn padInput(comptime input: []const u8) []const u8 { - return input ++ "\n" ** 128; -} - fn readFile(path: []const u8) !std.ArrayList(u8) { var input_instance: std.ArrayList(u8) = .init(std.testing.allocator); errdefer input_instance.deinit(); @@ -21,549 +14,84 @@ fn readFile(path: []const u8) !std.ArrayList(u8) { const file_size = (try input_file.stat()).size; try input_instance.ensureTotalCapacity(file_size + PADDING); try input_file.reader().readAllArrayList(&input_instance, std.math.maxInt(u32) - PADDING); - try input_instance.appendNTimes('\n', PADDING); return input_instance; } -fn testParse(comptime input: []const u8, expected: []const u8) !void { - try testParseWithFn(input, expected, parse); - try testParseWithFn(input, expected, parse3); -} - -fn testParseWithFn(comptime input: []const u8, expected: []const u8, parseFn: anytype) !void { - var arena: ArenaAllocator = .init(std.testing.allocator); - defer arena.deinit(); - - const safe_input = padInput(input); - - const ast = try parseFn(std.testing.allocator, arena.allocator(), safe_input); - var ast_render: std.ArrayListUnmanaged(u8) = .empty; - defer ast_render.deinit(std.testing.allocator); - try ast.renderAst(ast_render.writer(std.testing.allocator), safe_input); - try std.testing.expectEqualStrings(expected, ast_render.items); +fn testSnapshot(comptime path: []const u8) !void { + const snapshot_path = path ++ ".ast"; + const wrong_path = path ++ ".wrong.ast"; + + var input_instance = try readFile(path); + defer input_instance.deinit(); + try input_instance.appendNTimes('\n', 128); + + const ast = try parse3(std.testing.allocator, null, input_instance.items); + defer ast.deinit(std.testing.allocator); + + var output_instance: std.ArrayList(u8) = .init(std.testing.allocator); + defer output_instance.deinit(); + try ast.renderAst(output_instance.writer(), input_instance.items); + + var snapshot_instance: std.ArrayList(u8) = readFile(snapshot_path) catch .init(std.testing.allocator); + defer snapshot_instance.deinit(); + + if (!std.mem.eql(u8, snapshot_instance.items, output_instance.items)) { + const wrong_file = try std.fs.cwd().createFile(wrong_path, .{}); + defer wrong_file.close(); + try wrong_file.writer().writeAll(output_instance.items); + std.debug.print( + \\Snapshot test for {[path]s} failed. + \\Generated output written to {[wrong_path]s}. + \\If changes are expected, copy {[wrong_path]s} to {[snapshot_path]s}. + \\ diff {[snapshot_path]s} {[wrong_path]s} + \\ mv {[wrong_path]s} {[snapshot_path]s} + \\ + , .{ .path = path, .wrong_path = wrong_path, .snapshot_path = snapshot_path }); + return error.TestFailed; + } } -test "Empty" { - try testParse("", - \\.document - \\ - ); +test "empty" { + try testSnapshot("src/test/empty.my"); } test "Happy path paragraph" { - try testParse( - \\text - \\ - \\text - \\text - \\ - \\text - \\ text - \\ - , - \\.document - \\ .paragraph - \\ .text - \\ "text" - \\ .paragraph - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .paragraph - \\ .text - \\ "text" - \\ .space_text - \\ " text" - \\ - ); + try testSnapshot("src/test/paragraph.my"); } test "Happy path headings" { - try testParse( - \\# text - \\# text - \\# text - \\ text - \\ - \\# text - \\ - \\# text - \\ text - \\ - \\# text - \\ text - \\ - \\## text - \\## text - \\## text - \\ text - \\ - \\## text - \\ - \\## text - \\ text - \\ - \\## text - \\ text - \\ - , - \\.document - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "text" - \\ .space_text - \\ " text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "text" - \\ .space_text - \\ " text" - \\ - ); + try testSnapshot("src/test/heading.my"); } test "Happy path quote" { - try testParse( - \\> text - \\ text - \\ - \\> text - \\ text - \\> text - \\> text - \\text - \\ - , - \\.document - \\ .quote - \\ .paragraph - \\ .text - \\ "text" - \\ .space_text - \\ "text" - \\ .quote - \\ .paragraph - \\ .text - \\ "text" - \\ .space_text - \\ " text" - \\ .quote - \\ .paragraph - \\ .text - \\ "text" - \\ .quote - \\ .paragraph - \\ .text - \\ "text" - \\ .paragraph - \\ .text - \\ "text" - \\ - ); + try testSnapshot("src/test/quote.my"); } test "Happy path list" { - try testParseWithFn( - \\- text - \\- [ ] text - \\. text - \\: text - \\-- text - \\-- [ ] text - \\.. text - \\:: text - \\ - , - \\.document - \\ .list - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .list - \\ .task_item - \\ .marker - \\ "- [ ]" - \\ .text - \\ "text" - \\ .list - \\ .ordered_item - \\ .marker - \\ "." - \\ .text - \\ "text" - \\ .list - \\ .term_item - \\ .marker - \\ ":" - \\ .text - \\ "text" - \\ .list - \\ .unordered_item - \\ .marker - \\ "--" - \\ .text - \\ "text" - \\ .list - \\ .task_item - \\ .marker - \\ "-- [ ]" - \\ .text - \\ "text" - \\ .list - \\ .ordered_item - \\ .marker - \\ ".." - \\ .text - \\ "text" - \\ .list - \\ .term_item - \\ .marker - \\ "::" - \\ .text - \\ "text" - \\ - , parse3); -} - -test "List grouping" { - try testParseWithFn( - \\- text - \\- text - \\-- text - \\- text - \\ - \\- text - \\paragraph - \\- text - \\. text - \\ - , - \\.document - \\ .list - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .unordered_item - \\ .marker - \\ "--" - \\ .text - \\ "text" - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .paragraph - \\ .text - \\ "paragraph" - \\ .list - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "text" - \\ .list - \\ .ordered_item - \\ .marker - \\ "." - \\ .text - \\ "text" - \\ - , parse3); + try testSnapshot("src/test/list.my"); } test "Happy path list elaboration" { - try testParseWithFn( - \\- a - \\+ bb - \\ - \\ ccc - \\+ dddd - \\## heading - \\++ subtitle - \\ - , - \\.document - \\ .list - \\ .unordered_item - \\ .marker - \\ "-" - \\ .text - \\ "a" - \\ .elaboration - \\ .marker - \\ "+" - \\ .paragraph - \\ .text - \\ "bb" - \\ .paragraph - \\ .text - \\ "ccc" - \\ .elaboration - \\ .marker - \\ "+" - \\ .paragraph - \\ .text - \\ "dddd" - \\ .heading - \\ .marker - \\ "##" - \\ .text - \\ "heading" - \\ .elaboration - \\ .marker - \\ "++" - \\ .paragraph - \\ .text - \\ "subtitle" - \\ - , parse3); -} - -test "Elaboration errors" { - try testParseWithFn( - \\- a - \\++ bb - \\-- ccc - \\+ dddd - \\paragraph - \\+ eeeee - \\ - , - \\.document - \\ .list - \\ .unordered_item - \\ .error .incorrect_elaboration_marker - \\ .marker - \\ "-" - \\ .text - \\ "a" - \\ .elaboration - \\ .marker - \\ "++" - \\ .paragraph - \\ .text - \\ "bb" - \\ .unordered_item - \\ .error .incorrect_elaboration_marker - \\ .marker - \\ "--" - \\ .text - \\ "ccc" - \\ .elaboration - \\ .marker - \\ "+" - \\ .paragraph - \\ .text - \\ "dddd" - \\ .paragraph - \\ .text - \\ "paragraph" - \\ .elaboration - \\ .error .elaboration_after_unelaboratable_node - \\ .marker - \\ "+" - \\ .paragraph - \\ .text - \\ "eeeee" - \\ - , parse3); + try testSnapshot("src/test/elaboration.my"); } test "Thematic break" { - try testParse( - \\a - \\*** - \\bb - \\* - \\ccc - \\ - \\**bold text** - \\ - , - \\.document - \\ .paragraph - \\ .text - \\ "a" - \\ .thematic_break - \\ "***" - \\ .paragraph - \\ .text - \\ "bb" - \\ .space_text - \\ "*" - \\ .space_text - \\ "ccc" - \\ .paragraph - \\ .text - \\ "**bold text**" - \\ - ); -} - -test "Mixed indentation" { - // AstGen1 used to try very hard to recover when it sees a tab - try testParseWithFn("" ++ - "> aaa\n" ++ - "\n" ++ - "\tbbbbb\n", - \\.document - \\ .quote - \\ .error .inconsistent_indentation at 3:1 - \\ .paragraph - \\ .text - \\ "aaa" - \\ .paragraph - \\ .text - \\ "bbbbb" - \\ - , parse); - - try testParseWithFn("" ++ - "> aaa\n" ++ - "\n" ++ - "\tbbbbb\n", - \\.document - \\ .quote - \\ .paragraph - \\ .text - \\ "aaa" - \\ .paragraph - \\ .error .inconsistent_indentation at 3:1 - \\ .text - \\ "bbbbb" - \\ - , parse3); -} - -test "Tabs in text" { - try testParse("" ++ - "aaa\n" ++ - "\tbbbbb\n", - \\.document - \\ .paragraph - \\ .text - \\ "aaa" - \\ .space_text - \\ "\tbbbbb" - \\ - ); -} - -test "Empty line in heading" { - try testParse( - \\# heading - \\ - \\ text - \\ - \\text - \\ - , - \\.document - \\ .heading - \\ .marker - \\ "#" - \\ .text - \\ "heading" - \\ .space_text - \\ .error .unexpected_block_in_inline_context - \\ "text" - \\ .paragraph - \\ .text - \\ "text" - \\ - ); + try testSnapshot("src/test/thematic_break.my"); } test "Super long line" { - const input = try std.testing.allocator.create([(1 << 24) * 4]u8); + const input = try std.testing.allocator.create([(1 << 24) * 4 + PADDING + 1]u8); defer std.testing.allocator.destroy(input); - @memset(input, 'a'); + @memset(input[0 .. (1 << 24) * 4], 'a'); + @memset(input[(1 << 24) * 4 ..], '\n'); var arena: ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - const ast = try parse(std.testing.allocator, arena.allocator(), input); + const ast = try parse3(std.testing.allocator, arena.allocator(), input); const taggedAst = try ast.toTagged(arena.allocator()); try std.testing.expectEqualDeep(@as(Ast.Tagged, .{ .nodes = &.{ .{ .document = .{ .num_children = 1 } }, - .{ .paragraph = .{ .off = 0, .num_children = 1 } }, + .{ .paragraph = .{ .off = 0, .num_children = 5 } }, .{ .text = .{ .off = 0, .len = 16777215 } }, .{ .text = .{ .off = 16777215, .len = 16777215 } }, .{ .text = .{ .off = 33554430, .len = 16777215 } }, @@ -583,7 +111,7 @@ test "Many short lines" { var arena: ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); - const ast = try parse(std.testing.allocator, arena.allocator(), input); + const ast = try parse3(std.testing.allocator, arena.allocator(), input); try std.testing.expectEqual(1 << 24, ast.nodes.len); try std.testing.expectEqual( diff --git a/src/test/elaboration.my b/src/test/elaboration.my @@ -0,0 +1,14 @@ +- a ++ bb + + ccc ++ dddd +## heading +++ subtitle + +- a +++ bb +-- ccc ++ dddd +paragraph ++ eeeee diff --git a/src/test/elaboration.my.ast b/src/test/elaboration.my.ast @@ -0,0 +1,68 @@ +.document + .list + .unordered_item + .marker + "-" + .text + "a" + .elaboration + .marker + "+" + .paragraph + .text + "bb" + .paragraph + .text + "ccc" + .elaboration + .marker + "+" + .paragraph + .text + "dddd" + .heading + .marker + "##" + .text + "heading" + .elaboration + .marker + "++" + .paragraph + .text + "subtitle" + .list + .unordered_item + .error .incorrect_elaboration_marker + .marker + "-" + .text + "a" + .elaboration + .marker + "++" + .paragraph + .text + "bb" + .unordered_item + .error .incorrect_elaboration_marker + .marker + "--" + .text + "ccc" + .elaboration + .marker + "+" + .paragraph + .text + "dddd" + .paragraph + .text + "paragraph" + .elaboration + .error .elaboration_after_unelaboratable_node + .marker + "+" + .paragraph + .text + "eeeee" diff --git a/src/test/empty.my b/src/test/empty.my diff --git a/src/test/empty.my.ast b/src/test/empty.my.ast @@ -0,0 +1 @@ +.document diff --git a/src/test/heading.my b/src/test/heading.my @@ -0,0 +1,31 @@ +# text +# text +# text + text + +# text + +# text + text + +# text + text + +## text +## text +## text + text + +## text + +## text + text + +## text + text + +# heading + + text + +text diff --git a/src/test/heading.my.ast b/src/test/heading.my.ast @@ -0,0 +1,84 @@ +.document + .heading + .marker + "#" + .text + "text" + .heading + .marker + "#" + .text + "text" + .heading + .marker + "#" + .text + "text" + .space_text + "text" + .heading + .marker + "#" + .text + "text" + .heading + .marker + "#" + .text + "text" + .space_text + "text" + .heading + .marker + "#" + .text + "text" + .space_text + " text" + .heading + .marker + "##" + .text + "text" + .heading + .marker + "##" + .text + "text" + .heading + .marker + "##" + .text + "text" + .space_text + "text" + .heading + .marker + "##" + .text + "text" + .heading + .marker + "##" + .text + "text" + .space_text + "text" + .heading + .marker + "##" + .text + "text" + .space_text + " text" + .heading + .marker + "#" + .text + "heading" + .space_text + .error .unexpected_block_in_inline_context + "text" + .paragraph + .text + "text" diff --git a/src/test/list.my b/src/test/list.my @@ -0,0 +1,18 @@ +- text +- [ ] text +. text +: text +-- text +-- [ ] text +.. text +:: text + +- text +- text +-- text +- text + +- text +paragraph +- text +. text diff --git a/src/test/list.my.ast b/src/test/list.my.ast @@ -0,0 +1,90 @@ +.document + .list + .unordered_item + .marker + "-" + .text + "text" + .list + .task_item + .marker + "- [ ]" + .text + "text" + .list + .ordered_item + .marker + "." + .text + "text" + .list + .term_item + .marker + ":" + .text + "text" + .list + .unordered_item + .marker + "--" + .text + "text" + .list + .task_item + .marker + "-- [ ]" + .text + "text" + .list + .ordered_item + .marker + ".." + .text + "text" + .list + .term_item + .marker + "::" + .text + "text" + .list + .unordered_item + .marker + "-" + .text + "text" + .unordered_item + .marker + "-" + .text + "text" + .unordered_item + .marker + "--" + .text + "text" + .unordered_item + .marker + "-" + .text + "text" + .unordered_item + .marker + "-" + .text + "text" + .paragraph + .text + "paragraph" + .list + .unordered_item + .marker + "-" + .text + "text" + .list + .ordered_item + .marker + "." + .text + "text" diff --git a/src/test/paragraph.my b/src/test/paragraph.my @@ -0,0 +1,7 @@ +text + +text +text + +text + text diff --git a/src/test/paragraph.my.ast b/src/test/paragraph.my.ast @@ -0,0 +1,14 @@ +.document + .paragraph + .text + "text" + .paragraph + .text + "text" + .space_text + "text" + .paragraph + .text + "text" + .space_text + " text" diff --git a/src/test/quote.my b/src/test/quote.my @@ -0,0 +1,8 @@ +> text + text + +> text + text +> text +> text +text diff --git a/src/test/quote.my.ast b/src/test/quote.my.ast @@ -0,0 +1,24 @@ +.document + .quote + .paragraph + .text + "text" + .space_text + "text" + .quote + .paragraph + .text + "text" + .space_text + " text" + .quote + .paragraph + .text + "text" + .quote + .paragraph + .text + "text" + .paragraph + .text + "text" diff --git a/src/test/thematic_break.my b/src/test/thematic_break.my @@ -0,0 +1,7 @@ +a +*** +bb +* +ccc + +**bold text** diff --git a/src/test/thematic_break.my.ast b/src/test/thematic_break.my.ast @@ -0,0 +1,16 @@ +.document + .paragraph + .text + "a" + .thematic_break + "***" + .paragraph + .text + "bb" + .space_text + "*" + .space_text + "ccc" + .paragraph + .text + "**bold text**"