refactor: migrate tests to new compiler context
This commit is contained in:
parent
c54d19bcf7
commit
ac30ea169c
@ -113,6 +113,7 @@ pub fn build(b: *std.Build) void {
|
||||
"src/01_lexic/root.zig",
|
||||
"src/02_syntax/root.zig",
|
||||
"src/errors/root.zig",
|
||||
"src/context/root.zig",
|
||||
};
|
||||
for (files) |file| {
|
||||
const file_unit_test = b.addTest(.{
|
||||
|
@ -208,6 +208,22 @@ pub const ErrorData = struct {
|
||||
// - Get previous, current and next line
|
||||
// - Display message
|
||||
|
||||
/// Writes this error as a JSON to the writer
|
||||
pub fn write_json(self: ErrorData, alloc: std.mem.Allocator, writer: anytype) !void {
|
||||
// get this as JSON
|
||||
const json_str = try std.json.stringifyAlloc(alloc, .{
|
||||
.reason = self.reason,
|
||||
.help = self.help,
|
||||
.start_position = self.start_position,
|
||||
.end_position = self.end_position,
|
||||
.labels = self.labels.items,
|
||||
}, .{});
|
||||
defer alloc.free(json_str);
|
||||
|
||||
// write the JSON to the writer
|
||||
try writer.writeAll(json_str);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *ErrorData, allocator: std.mem.Allocator) void {
|
||||
// Clean any labels. Those are assumed to have been initialized
|
||||
// by the same allocator this function receives
|
||||
@ -280,3 +296,188 @@ fn get_line(input: []const u8, at: usize) LineInfo {
|
||||
.column_number = column_number,
|
||||
};
|
||||
}
|
||||
|
||||
test {
|
||||
std.testing.refAllDecls(@This());
|
||||
}
|
||||
|
||||
test "should get a single line" {
|
||||
const input = "print(hello)";
|
||||
const at = 4;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(hello)", output.line);
|
||||
try std.testing.expectEqual(1, output.line_number);
|
||||
try std.testing.expectEqual(5, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (1)" {
|
||||
const input = "print(hello)\nprint(bye)";
|
||||
const at = 4;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(hello)", output.line);
|
||||
try std.testing.expectEqual(1, output.line_number);
|
||||
try std.testing.expectEqual(5, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (2)" {
|
||||
const input = "print(hello)\nprint(bye)";
|
||||
const at = 15;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(bye)", output.line);
|
||||
try std.testing.expectEqual(2, output.line_number);
|
||||
try std.testing.expectEqual(3, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (3)" {
|
||||
const input = "print(hello)\nprint(sure?)\nprint(bye!)";
|
||||
const at = 15;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(sure?)", output.line);
|
||||
try std.testing.expectEqual(2, output.line_number);
|
||||
try std.testing.expectEqual(3, output.column_number);
|
||||
}
|
||||
|
||||
test "should gen error message" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
};
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should gen error message with label (1)" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
};
|
||||
defer err.deinit(std.testing.allocator);
|
||||
|
||||
const label = .{
|
||||
.message = .{ .static = "This identifier was not found" },
|
||||
.start = 6,
|
||||
.end = 9,
|
||||
};
|
||||
try err.add_label(label);
|
||||
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
\\
|
||||
\\ 1 | print(ehh)
|
||||
\\ ╭──
|
||||
\\ ╰─ This identifier was not found
|
||||
\\
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should gen error message with label and help" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
};
|
||||
defer err.deinit(std.testing.allocator);
|
||||
|
||||
const label = .{
|
||||
.message = .{ .static = "This identifier was not found" },
|
||||
.start = 6,
|
||||
.end = 9,
|
||||
};
|
||||
try err.add_label(label);
|
||||
err.set_help("Define the identifier");
|
||||
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
\\
|
||||
\\ 1 | print(ehh)
|
||||
\\ ╭──
|
||||
\\ ╰─ This identifier was not found
|
||||
\\
|
||||
\\ Help: Define the identifier
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should serialize a minimal error" {
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
};
|
||||
defer err.deinit(std.testing.allocator);
|
||||
var out_writer = std.ArrayList(u8).init(std.testing.allocator);
|
||||
defer out_writer.deinit();
|
||||
|
||||
try err.write_json(std.testing.allocator, out_writer.writer());
|
||||
|
||||
const expected =
|
||||
\\{"reason":"Invalid identifier","help":null,"start_position":6,"end_position":9,"labels":[]}
|
||||
;
|
||||
try std.testing.expectEqualStrings(expected, out_writer.items);
|
||||
}
|
||||
|
||||
test "should serialize a complex error" {
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid \"hello\"",
|
||||
.help = "Try to do better",
|
||||
.start_position = 0,
|
||||
.end_position = 1,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
};
|
||||
defer err.deinit(std.testing.allocator);
|
||||
|
||||
try err.add_label(.{
|
||||
.message = .{ .static = "This one" },
|
||||
.start = 0,
|
||||
.end = 32,
|
||||
});
|
||||
try err.add_label(.{
|
||||
.message = .{ .static = "And this other" },
|
||||
.start = 32,
|
||||
.end = 64,
|
||||
});
|
||||
|
||||
var out_writer = std.ArrayList(u8).init(std.testing.allocator);
|
||||
defer out_writer.deinit();
|
||||
|
||||
try err.write_json(std.testing.allocator, out_writer.writer());
|
||||
|
||||
const expected =
|
||||
\\{"reason":"Invalid \"hello\"","help":"Try to do better","start_position":0,"end_position":1,"labels":[{"message":{"static":"This one"},"start":0,"end":32},{"message":{"static":"And this other"},"start":32,"end":64}]}
|
||||
;
|
||||
try std.testing.expectEqualStrings(expected, out_writer.items);
|
||||
}
|
||||
|
||||
// TODO: add more tests:
|
||||
// - when the error has len=1
|
||||
// - when the error has len=0
|
||||
// - when the error spans across 2 lines
|
||||
|
@ -220,175 +220,3 @@ fn get_line(input: []const u8, at: usize) LineInfo {
|
||||
.column_number = column_number,
|
||||
};
|
||||
}
|
||||
|
||||
test {
|
||||
std.testing.refAllDecls(@This());
|
||||
}
|
||||
|
||||
test "should get a single line" {
|
||||
const input = "print(hello)";
|
||||
const at = 4;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(hello)", output.line);
|
||||
try std.testing.expectEqual(1, output.line_number);
|
||||
try std.testing.expectEqual(5, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (1)" {
|
||||
const input = "print(hello)\nprint(bye)";
|
||||
const at = 4;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(hello)", output.line);
|
||||
try std.testing.expectEqual(1, output.line_number);
|
||||
try std.testing.expectEqual(5, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (2)" {
|
||||
const input = "print(hello)\nprint(bye)";
|
||||
const at = 15;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(bye)", output.line);
|
||||
try std.testing.expectEqual(2, output.line_number);
|
||||
try std.testing.expectEqual(3, output.column_number);
|
||||
}
|
||||
|
||||
test "should get line from 2 lines (3)" {
|
||||
const input = "print(hello)\nprint(sure?)\nprint(bye!)";
|
||||
const at = 15;
|
||||
const output = get_line(input, at);
|
||||
|
||||
try std.testing.expectEqualStrings("print(sure?)", output.line);
|
||||
try std.testing.expectEqual(2, output.line_number);
|
||||
try std.testing.expectEqual(3, output.column_number);
|
||||
}
|
||||
|
||||
test "should gen error message" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
.alloc = std.testing.allocator,
|
||||
};
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should gen error message with label (1)" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
.alloc = std.testing.allocator,
|
||||
};
|
||||
defer err.deinit();
|
||||
|
||||
try err.add_label("This identifier was not found", 6, 9);
|
||||
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
\\
|
||||
\\ 1 | print(ehh)
|
||||
\\ ╭──
|
||||
\\ ╰─ This identifier was not found
|
||||
\\
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should gen error message with label and help" {
|
||||
const source = "print(ehh)";
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
.alloc = std.testing.allocator,
|
||||
};
|
||||
defer err.deinit();
|
||||
|
||||
try err.add_label("This identifier was not found", 6, 9);
|
||||
err.set_help("Define the identifier");
|
||||
|
||||
const out = try err.get_error_str(source, "repl", std.testing.allocator);
|
||||
defer std.testing.allocator.free(out);
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\Error: Invalid identifier
|
||||
\\[repl:1:7]
|
||||
\\
|
||||
\\ 1 | print(ehh)
|
||||
\\ ╭──
|
||||
\\ ╰─ This identifier was not found
|
||||
\\
|
||||
\\ Help: Define the identifier
|
||||
, out);
|
||||
}
|
||||
|
||||
test "should serialize a minimal error" {
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid identifier",
|
||||
.help = null,
|
||||
.start_position = 6,
|
||||
.end_position = 9,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
.alloc = std.testing.allocator,
|
||||
};
|
||||
defer err.deinit();
|
||||
var out_writer = std.ArrayList(u8).init(std.testing.allocator);
|
||||
defer out_writer.deinit();
|
||||
|
||||
try err.write_json(std.testing.allocator, out_writer.writer());
|
||||
|
||||
const expected =
|
||||
\\{"reason":"Invalid identifier","help":null,"start_position":6,"end_position":9,"labels":[]}
|
||||
;
|
||||
try std.testing.expectEqualStrings(expected, out_writer.items);
|
||||
}
|
||||
|
||||
test "should serialize a complex error" {
|
||||
var err = ErrorData{
|
||||
.reason = "Invalid \"hello\"",
|
||||
.help = "Try to do better",
|
||||
.start_position = 0,
|
||||
.end_position = 1,
|
||||
.labels = std.ArrayList(ErrorLabel).init(std.testing.allocator),
|
||||
.alloc = std.testing.allocator,
|
||||
};
|
||||
defer err.deinit();
|
||||
|
||||
try err.add_label("This one", 0, 32);
|
||||
try err.add_label("And this other", 32, 64);
|
||||
|
||||
var out_writer = std.ArrayList(u8).init(std.testing.allocator);
|
||||
defer out_writer.deinit();
|
||||
|
||||
try err.write_json(std.testing.allocator, out_writer.writer());
|
||||
|
||||
const expected =
|
||||
\\{"reason":"Invalid \"hello\"","help":"Try to do better","start_position":0,"end_position":1,"labels":[{"message":"This one","start":0,"end":32},{"message":"And this other","start":32,"end":64}]}
|
||||
;
|
||||
try std.testing.expectEqualStrings(expected, out_writer.items);
|
||||
}
|
||||
|
||||
// TODO: add more tests:
|
||||
// - when the error has len=1
|
||||
// - when the error has len=0
|
||||
// - when the error spans across 2 lines
|
||||
|
Loading…
Reference in New Issue
Block a user