authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-15 17:51:29-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-15 17:51:29-04:00
logc92816fbefe9d789d3f3c13f319c949c8b97ad01
treea6928681d1e8c010e20434377048239dd4f65867
parente7207bc267d90b5be009fcd937b86cde9bf9ae77
signaturelock-open Commit is signed but in an unrecognized format.

[Stage2/Testing] ZIR tests for expected errors


2 files changed, 154 insertions(+), 9 deletions(-)

src-self-hosted/test.zig+133-9
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const link = @import("link.zig");
33const Module = @import("Module.zig");
4const ErrorMsg = Module.ErrorMsg;
45const Allocator = std.mem.Allocator;
56const zir = @import("zir.zig");
67const Package = @import("Package.zig");
......@@ -18,6 +19,7 @@ test "self-hosted" {
1819pub const TestContext = struct {
1920 zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
2021 zir_transform_cases: std.ArrayList(ZIRTransformCase),
22 zir_error_cases: std.ArrayList(ZIRErrorCase),
2123
2224 pub const ZIRCompareOutputCase = struct {
2325 name: []const u8,
......@@ -55,6 +57,15 @@ pub const TestContext = struct {
5557 }
5658 };
5759
60 pub const ZIRErrorCase = struct {
61 name: []const u8,
62 src: [:0]const u8,
63 expected_file_errors: []const ErrorMsg,
64 expected_decl_errors: []const ErrorMsg,
65 expected_export_errors: []const ErrorMsg,
66 cross_target: std.zig.CrossTarget,
67 };
68
5869 pub fn addZIRCompareOutput(
5970 ctx: *TestContext,
6071 name: []const u8,
......@@ -87,30 +98,38 @@ pub const TestContext = struct {
8798 }) catch unreachable;
8899 }
89100
90 pub fn addZIRMulti(
101 pub fn addZIRError(
91102 ctx: *TestContext,
92103 name: []const u8,
93104 cross_target: std.zig.CrossTarget,
94 ) *ZIRTransformCase {
95 const case = ctx.zir_transform_cases.addOne() catch unreachable;
96 case.* = .{
105 src: [:0]const u8,
106 expected_file_errors: []const ErrorMsg,
107 expected_decl_errors: []const ErrorMsg,
108 expected_export_errors: []const ErrorMsg,
109 ) void {
110 ctx.zir_error_cases.append(.{
97111 .name = name,
112 .src = src,
113 .expected_file_errors = expected_file_errors,
114 .expected_decl_errors = expected_decl_errors,
115 .expected_export_errors = expected_export_errors,
98116 .cross_target = cross_target,
99 .updates = std.ArrayList(ZIRTransformCase.Update).init(std.heap.page_allocator),
100 };
101 return case;
117 }) catch unreachable;
102118 }
103119
104120 fn init(self: *TestContext) !void {
121 const allocator = std.heap.page_allocator;
105122 self.* = .{
106 .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(std.heap.page_allocator),
107 .zir_transform_cases = std.ArrayList(ZIRTransformCase).init(std.heap.page_allocator),
123 .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(allocator),
124 .zir_transform_cases = std.ArrayList(ZIRTransformCase).init(allocator),
125 .zir_error_cases = std.ArrayList(ZIRErrorCase).init(allocator),
108126 };
109127 }
110128
111129 fn deinit(self: *TestContext) void {
112130 self.zir_cmp_output_cases.deinit();
113131 self.zir_transform_cases.deinit();
132 self.zir_error_cases.deinit();
114133 self.* = undefined;
115134 }
116135
......@@ -133,6 +152,12 @@ pub const TestContext = struct {
133152 try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, info.target);
134153 try std.testing.allocator_instance.validate();
135154 }
155 for (self.zir_error_cases.items) |case| {
156 std.testing.base_allocator_instance.reset();
157 const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.cross_target);
158 try self.runOneZIRErrorCase(std.testing.allocator, root_node, case, info.target);
159 try std.testing.allocator_instance.validate();
160 }
136161 }
137162
138163 fn runOneZIRCmpOutputCase(
......@@ -300,6 +325,105 @@ pub const TestContext = struct {
300325 }
301326 }
302327 }
328
329 fn runOneZIRErrorCase(
330 self: *TestContext,
331 allocator: *Allocator,
332 root_node: *std.Progress.Node,
333 case: ZIRErrorCase,
334 target: std.Target,
335 ) !void {
336 var tmp = std.testing.tmpDir(.{});
337 defer tmp.cleanup();
338
339 var prg_node = root_node.start(case.name, 1);
340 prg_node.activate();
341 defer prg_node.end();
342
343 const tmp_src_path = "test-case.zir";
344 try tmp.dir.writeFile(tmp_src_path, case.src);
345
346 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
347 defer root_pkg.destroy();
348
349 var module = try Module.init(allocator, .{
350 .target = target,
351 .output_mode = .Obj,
352 .optimize_mode = .Debug,
353 .bin_file_dir = tmp.dir,
354 .bin_file_path = "test-case.o",
355 .root_pkg = root_pkg,
356 });
357 defer module.deinit();
358
359 var module_node = prg_node.start("parse/analysis/codegen", null);
360 module_node.activate();
361 const failed = f: {
362 module.update() catch break :f true;
363 break :f false;
364 };
365 if (!failed) {
366 return error.DidNotFail;
367 }
368 module_node.end();
369 {
370 var i = module.failed_files.iterator();
371 var index: usize = 0;
372 while (i.next()) |pair| : (index += 1) {
373 if (index == case.expected_file_errors.len) {
374 return error.UnexpectedError;
375 }
376 const v1 = pair.value.*;
377 const v2 = case.expected_file_errors[index];
378 if (v1.byte_offset != v2.byte_offset) {
379 std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
380 return error.ExpectedErrorElsewhere;
381 }
382 if (!std.mem.eql(u8, v1.msg, v2.msg)) {
383 std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
384 return error.ExpectedOtherError;
385 }
386 }
387 }
388 {
389 var i = module.failed_decls.iterator();
390 var index: usize = 0;
391 while (i.next()) |pair| : (index += 1) {
392 if (index == case.expected_decl_errors.len) {
393 return error.UnexpectedError;
394 }
395 const v1 = pair.value.*;
396 const v2 = case.expected_decl_errors[index];
397 if (v1.byte_offset != v2.byte_offset) {
398 std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
399 return error.ExpectedErrorElsewhere;
400 }
401 if (!std.mem.eql(u8, v1.msg, v2.msg)) {
402 std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
403 return error.ExpectedOtherError;
404 }
405 }
406 }
407 {
408 var i = module.failed_exports.iterator();
409 var index: usize = 0;
410 while (i.next()) |pair| : (index += 1) {
411 if (index == case.expected_export_errors.len) {
412 return error.UnexpectedError;
413 }
414 const v1 = pair.value.*;
415 const v2 = case.expected_export_errors[index];
416 if (v1.byte_offset != v2.byte_offset) {
417 std.debug.warn("Expected error at {}, found it at {}\n", .{ v2.byte_offset, v1.byte_offset });
418 return error.ExpectedErrorElsewhere;
419 }
420 if (!std.mem.eql(u8, v1.msg, v2.msg)) {
421 std.debug.warn("Expected '{}', found '{}'\n", .{ v2.msg, v1.msg });
422 return error.ExpectedOtherError;
423 }
424 }
425 }
426 }
303427};
304428
305429fn debugPrintErrors(src: []const u8, errors: var) void {
test/stage2/compile_errors.zig+21
......@@ -1,8 +1,29 @@
11const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
2const std = @import("std");
3
4const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg;
5
6const linux_x64 = std.zig.CrossTarget{
7 .cpu_arch = .x86_64,
8 .os_tag = .linux,
9};
210
311pub fn addCases(ctx: *TestContext) !void {
412 // TODO: re-enable these tests.
513 // https://github.com/ziglang/zig/issues/1364
14 ctx.addZIRError("test", linux_x64,
15 \\@noreturn = primitive(noreturn)
16 \\@void = primitive(void)
17 \\@usize = primitive(usize)
18 \\
19 \\@start_fnty = fntype([], @noreturn, cc=Naked)
20 \\@start = fn(@start_fnty, {
21 \\ %0 = call(%test, [])
22 \\})
23 , &[_]ErrorMsg{.{
24 .byte_offset = 168,
25 .msg = "unrecognized identifier: %test",
26 }}, &[_]ErrorMsg{}, &[_]ErrorMsg{});
627
728 //try ctx.testCompileError(
829 // \\export fn entry() void {}