[Stage2/Testing] ZIR tests for expected errors
parent
e7207bc267
commit
c92816fbef
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const link = @import("link.zig");
|
const link = @import("link.zig");
|
||||||
const Module = @import("Module.zig");
|
const Module = @import("Module.zig");
|
||||||
|
const ErrorMsg = Module.ErrorMsg;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const zir = @import("zir.zig");
|
const zir = @import("zir.zig");
|
||||||
const Package = @import("Package.zig");
|
const Package = @import("Package.zig");
|
||||||
|
@ -18,6 +19,7 @@ test "self-hosted" {
|
||||||
pub const TestContext = struct {
|
pub const TestContext = struct {
|
||||||
zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
|
zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
|
||||||
zir_transform_cases: std.ArrayList(ZIRTransformCase),
|
zir_transform_cases: std.ArrayList(ZIRTransformCase),
|
||||||
|
zir_error_cases: std.ArrayList(ZIRErrorCase),
|
||||||
|
|
||||||
pub const ZIRCompareOutputCase = struct {
|
pub const ZIRCompareOutputCase = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
@ -55,6 +57,15 @@ pub const TestContext = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ZIRErrorCase = struct {
|
||||||
|
name: []const u8,
|
||||||
|
src: [:0]const u8,
|
||||||
|
expected_file_errors: []const ErrorMsg,
|
||||||
|
expected_decl_errors: []const ErrorMsg,
|
||||||
|
expected_export_errors: []const ErrorMsg,
|
||||||
|
cross_target: std.zig.CrossTarget,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn addZIRCompareOutput(
|
pub fn addZIRCompareOutput(
|
||||||
ctx: *TestContext,
|
ctx: *TestContext,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
@ -87,30 +98,38 @@ pub const TestContext = struct {
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addZIRMulti(
|
pub fn addZIRError(
|
||||||
ctx: *TestContext,
|
ctx: *TestContext,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
cross_target: std.zig.CrossTarget,
|
cross_target: std.zig.CrossTarget,
|
||||||
) *ZIRTransformCase {
|
src: [:0]const u8,
|
||||||
const case = ctx.zir_transform_cases.addOne() catch unreachable;
|
expected_file_errors: []const ErrorMsg,
|
||||||
case.* = .{
|
expected_decl_errors: []const ErrorMsg,
|
||||||
|
expected_export_errors: []const ErrorMsg,
|
||||||
|
) void {
|
||||||
|
ctx.zir_error_cases.append(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
|
.src = src,
|
||||||
|
.expected_file_errors = expected_file_errors,
|
||||||
|
.expected_decl_errors = expected_decl_errors,
|
||||||
|
.expected_export_errors = expected_export_errors,
|
||||||
.cross_target = cross_target,
|
.cross_target = cross_target,
|
||||||
.updates = std.ArrayList(ZIRTransformCase.Update).init(std.heap.page_allocator),
|
}) catch unreachable;
|
||||||
};
|
|
||||||
return case;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(self: *TestContext) !void {
|
fn init(self: *TestContext) !void {
|
||||||
|
const allocator = std.heap.page_allocator;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(std.heap.page_allocator),
|
.zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(allocator),
|
||||||
.zir_transform_cases = std.ArrayList(ZIRTransformCase).init(std.heap.page_allocator),
|
.zir_transform_cases = std.ArrayList(ZIRTransformCase).init(allocator),
|
||||||
|
.zir_error_cases = std.ArrayList(ZIRErrorCase).init(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *TestContext) void {
|
fn deinit(self: *TestContext) void {
|
||||||
self.zir_cmp_output_cases.deinit();
|
self.zir_cmp_output_cases.deinit();
|
||||||
self.zir_transform_cases.deinit();
|
self.zir_transform_cases.deinit();
|
||||||
|
self.zir_error_cases.deinit();
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +152,12 @@ pub const TestContext = struct {
|
||||||
try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, info.target);
|
try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, info.target);
|
||||||
try std.testing.allocator_instance.validate();
|
try std.testing.allocator_instance.validate();
|
||||||
}
|
}
|
||||||
|
for (self.zir_error_cases.items) |case| {
|
||||||
|
std.testing.base_allocator_instance.reset();
|
||||||
|
const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.cross_target);
|
||||||
|
try self.runOneZIRErrorCase(std.testing.allocator, root_node, case, info.target);
|
||||||
|
try std.testing.allocator_instance.validate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runOneZIRCmpOutputCase(
|
fn runOneZIRCmpOutputCase(
|
||||||
|
@ -300,6 +325,105 @@ pub const TestContext = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn runOneZIRErrorCase(
|
||||||
|
self: *TestContext,
|
||||||
|
allocator: *Allocator,
|
||||||
|
root_node: *std.Progress.Node,
|
||||||
|
case: ZIRErrorCase,
|
||||||
|
target: std.Target,
|
||||||
|
) !void {
|
||||||
|
var tmp = std.testing.tmpDir(.{});
|
||||||
|
defer tmp.cleanup();
|
||||||
|
|
||||||
|
var prg_node = root_node.start(case.name, 1);
|
||||||
|
prg_node.activate();
|
||||||
|
defer prg_node.end();
|
||||||
|
|
||||||
|
const tmp_src_path = "test-case.zir";
|
||||||
|
try tmp.dir.writeFile(tmp_src_path, case.src);
|
||||||
|
|
||||||
|
const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
|
||||||
|
defer root_pkg.destroy();
|
||||||
|
|
||||||
|
var module = try Module.init(allocator, .{
|
||||||
|
.target = target,
|
||||||
|
.output_mode = .Obj,
|
||||||
|
.optimize_mode = .Debug,
|
||||||
|
.bin_file_dir = tmp.dir,
|
||||||
|
.bin_file_path = "test-case.o",
|
||||||
|
.root_pkg = root_pkg,
|
||||||
|
});
|
||||||
|
defer module.deinit();
|
||||||
|
|
||||||
|
var module_node = prg_node.start("parse/analysis/codegen", null);
|
||||||
|
module_node.activate();
|
||||||
|
const failed = f: {
|
||||||
|
module.update() catch break :f true;
|
||||||
|
break :f false;
|
||||||
|
};
|
||||||
|
if (!failed) {
|
||||||
|
return error.DidNotFail;
|
||||||
|
}
|
||||||
|
module_node.end();
|
||||||
|
{
|
||||||
|
var i = module.failed_files.iterator();
|
||||||
|
var index: usize = 0;
|
||||||
|
while (i.next()) |pair| : (index += 1) {
|
||||||
|
if (index == case.expected_file_errors.len) {
|
||||||
|
return error.UnexpectedError;
|
||||||
|
}
|
||||||
|
const v1 = pair.value.*;
|
||||||
|
const v2 = case.expected_file_errors[index];
|
||||||
|
if (v1.byte_offset != v2.byte_offset) {
|
||||||
|
std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
|
||||||
|
return error.ExpectedErrorElsewhere;
|
||||||
|
}
|
||||||
|
if (!std.mem.eql(u8, v1.msg, v2.msg)) {
|
||||||
|
std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
|
||||||
|
return error.ExpectedOtherError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var i = module.failed_decls.iterator();
|
||||||
|
var index: usize = 0;
|
||||||
|
while (i.next()) |pair| : (index += 1) {
|
||||||
|
if (index == case.expected_decl_errors.len) {
|
||||||
|
return error.UnexpectedError;
|
||||||
|
}
|
||||||
|
const v1 = pair.value.*;
|
||||||
|
const v2 = case.expected_decl_errors[index];
|
||||||
|
if (v1.byte_offset != v2.byte_offset) {
|
||||||
|
std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
|
||||||
|
return error.ExpectedErrorElsewhere;
|
||||||
|
}
|
||||||
|
if (!std.mem.eql(u8, v1.msg, v2.msg)) {
|
||||||
|
std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
|
||||||
|
return error.ExpectedOtherError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var i = module.failed_exports.iterator();
|
||||||
|
var index: usize = 0;
|
||||||
|
while (i.next()) |pair| : (index += 1) {
|
||||||
|
if (index == case.expected_export_errors.len) {
|
||||||
|
return error.UnexpectedError;
|
||||||
|
}
|
||||||
|
const v1 = pair.value.*;
|
||||||
|
const v2 = case.expected_export_errors[index];
|
||||||
|
if (v1.byte_offset != v2.byte_offset) {
|
||||||
|
std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
|
||||||
|
return error.ExpectedErrorElsewhere;
|
||||||
|
}
|
||||||
|
if (!std.mem.eql(u8, v1.msg, v2.msg)) {
|
||||||
|
std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
|
||||||
|
return error.ExpectedOtherError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn debugPrintErrors(src: []const u8, errors: var) void {
|
fn debugPrintErrors(src: []const u8, errors: var) void {
|
||||||
|
|
|
@ -1,8 +1,29 @@
|
||||||
const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
|
const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg;
|
||||||
|
|
||||||
|
const linux_x64 = std.zig.CrossTarget{
|
||||||
|
.cpu_arch = .x86_64,
|
||||||
|
.os_tag = .linux,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn addCases(ctx: *TestContext) !void {
|
pub fn addCases(ctx: *TestContext) !void {
|
||||||
// TODO: re-enable these tests.
|
// TODO: re-enable these tests.
|
||||||
// https://github.com/ziglang/zig/issues/1364
|
// https://github.com/ziglang/zig/issues/1364
|
||||||
|
ctx.addZIRError("test", linux_x64,
|
||||||
|
\\@noreturn = primitive(noreturn)
|
||||||
|
\\@void = primitive(void)
|
||||||
|
\\@usize = primitive(usize)
|
||||||
|
\\
|
||||||
|
\\@start_fnty = fntype([], @noreturn, cc=Naked)
|
||||||
|
\\@start = fn(@start_fnty, {
|
||||||
|
\\ %0 = call(%test, [])
|
||||||
|
\\})
|
||||||
|
, &[_]ErrorMsg{.{
|
||||||
|
.byte_offset = 168,
|
||||||
|
.msg = "unrecognized identifier: %test",
|
||||||
|
}}, &[_]ErrorMsg{}, &[_]ErrorMsg{});
|
||||||
|
|
||||||
//try ctx.testCompileError(
|
//try ctx.testCompileError(
|
||||||
// \\export fn entry() void {}
|
// \\export fn entry() void {}
|
||||||
|
|
Loading…
Reference in New Issue