authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-15 20:25:13-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-15 20:33:43-04:00
logadb21f1cafb4cf5e2a64ff9d8262c2506d72208b
treeb0a73be38cfa090e63aa08f29dcc7d64176ed3e0
parent7ee0462f5f8b4ec5ff824b38821d8f1b79e5ba63
signaturelock-open Commit is signed but in an unrecognized format.

Stage2/Testing: Add error tests to ZIRCase


1 files changed, 69 insertions(+), 43 deletions(-)

src-self-hosted/test.zig+69-43
...@@ -114,7 +114,37 @@ pub const TestContext = struct {...@@ -114,7 +114,37 @@ pub const TestContext = struct {
114 }) catch unreachable;114 }) catch unreachable;
115 }115 }
116116
117 pub fn addError(self: *ZIRCase, src: [:0]const u8, errors: []const []const u8) void {}117 pub fn addError(self: *ZIRCase, src: [:0]const u8, errors: []const []const u8) void {
118 var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch unreachable;
119 for (errors) |e, i| {
120 var cur = e[1..];
121 var line_index = std.mem.indexOf(u8, cur, ":");
122 if (line_index == null) {
123 std.debug.panic("Invalid test: error must be specified as ':line:column: error: msg', found '{}'", .{e});
124 }
125 const line = std.fmt.parseInt(u32, cur[0..line_index.?], 10) catch @panic("Unable to parse line number");
126 cur = cur[line_index.? + 1 ..];
127 const column_index = std.mem.indexOf(u8, cur, ":");
128 if (column_index == null) {
129 std.debug.panic("Invalid test: error must be specified as ':line:column: error: msg', found '{}'", .{e});
130 }
131 const column = std.fmt.parseInt(u32, cur[0..column_index.?], 10) catch @panic("Unable to parse column number");
132 cur = cur[column_index.? + 2 ..];
133 std.debug.assert(std.mem.eql(u8, cur[0..7], "error: "));
134 const msg = cur[7..];
135
136 if (line == 0 or column == 0) {
137 @panic("Invalid test: error line and column must be specified starting at one!");
138 }
139
140 array[i] = .{
141 .msg = msg,
142 .line = line - 1,
143 .column = column - 1,
144 };
145 }
146 self.updates.append(.{ .src = src, .case = .{ .Error = array } }) catch unreachable;
147 }
118 };148 };
119149
120 pub fn addZIRMulti(150 pub fn addZIRMulti(
...@@ -161,42 +191,7 @@ pub const TestContext = struct {...@@ -161,42 +191,7 @@ pub const TestContext = struct {
161 cross_target: std.zig.CrossTarget,191 cross_target: std.zig.CrossTarget,
162 src: [:0]const u8,192 src: [:0]const u8,
163 expected_errors: []const []const u8,193 expected_errors: []const []const u8,
164 ) void {194 ) void {}
165 var array = std.ArrayList(ErrorMsg).init(ctx.zir_error_cases.allocator);
166 for (expected_errors) |e| {
167 var cur = e;
168 var line_index = std.mem.indexOf(u8, cur, ":");
169 if (line_index == null) {
170 std.debug.panic("Invalid test: error must be specified as 'line:column: error: msg', found '{}'", .{e});
171 }
172 const line = std.fmt.parseInt(u32, cur[0..line_index.?], 10) catch @panic("Unable to parse line number");
173 cur = cur[line_index.? + 1 ..];
174 const column_index = std.mem.indexOf(u8, cur, ":");
175 if (column_index == null) {
176 std.debug.panic("Invalid test: error must be specified as 'line:column: error: msg', found '{}'", .{e});
177 }
178 const column = std.fmt.parseInt(u32, cur[0..column_index.?], 10) catch @panic("Unable to parse column number");
179 cur = cur[column_index.? + 2 ..];
180 std.debug.assert(std.mem.eql(u8, cur[0..7], "error: "));
181 const msg = cur[7..];
182
183 if (line == 0 or column == 0) {
184 @panic("Invalid test: error line and column must be specified starting at one!");
185 }
186
187 array.append(.{
188 .msg = msg,
189 .line = line - 1,
190 .column = column - 1,
191 }) catch unreachable;
192 }
193 ctx.zir_error_cases.append(.{
194 .name = name,
195 .src = src,
196 .expected_errors = array.toOwnedSlice(),
197 .cross_target = cross_target,
198 }) catch unreachable;
199 }
200195
201 fn init(self: *TestContext) !void {196 fn init(self: *TestContext) !void {
202 const allocator = std.heap.page_allocator;197 const allocator = std.heap.page_allocator;
...@@ -214,6 +209,11 @@ pub const TestContext = struct {...@@ -214,6 +209,11 @@ pub const TestContext = struct {
214 }209 }
215 self.zir_error_cases.deinit();210 self.zir_error_cases.deinit();
216 for (self.zir_cases.items) |c| {211 for (self.zir_cases.items) |c| {
212 for (c.updates.items) |u| {
213 if (u.case == .Error) {
214 c.updates.allocator.free(u.case.Error);
215 }
216 }
217 c.updates.deinit();217 c.updates.deinit();
218 }218 }
219 self.zir_cases.deinit();219 self.zir_cases.deinit();
...@@ -268,11 +268,11 @@ pub const TestContext = struct {...@@ -268,11 +268,11 @@ pub const TestContext = struct {
268 // TODO: support tests for object file building, and library builds268 // TODO: support tests for object file building, and library builds
269 // and linking. This will require a rework to support multi-file269 // and linking. This will require a rework to support multi-file
270 // tests.270 // tests.
271 .output_mode = .Exe,271 .output_mode = .Obj,
272 // TODO: support testing optimizations272 // TODO: support testing optimizations
273 .optimize_mode = .Debug,273 .optimize_mode = .Debug,
274 .bin_file_dir = tmp.dir,274 .bin_file_dir = tmp.dir,
275 .bin_file_path = "test_case",275 .bin_file_path = "test_case.o",
276 .root_pkg = root_pkg,276 .root_pkg = root_pkg,
277 });277 });
278 defer module.deinit();278 defer module.deinit();
...@@ -312,6 +312,35 @@ pub const TestContext = struct {...@@ -312,6 +312,35 @@ pub const TestContext = struct {
312312
313 std.testing.expectEqualSlices(u8, expected_output, out_zir.items);313 std.testing.expectEqualSlices(u8, expected_output, out_zir.items);
314 },314 },
315 .Error => |e| {
316 var handled_errors = try allocator.alloc(bool, e.len);
317 defer allocator.free(handled_errors);
318 for (handled_errors) |*h| {
319 h.* = false;
320 }
321 var all_errors = try module.getAllErrorsAlloc();
322 defer all_errors.deinit(allocator);
323 for (all_errors.list) |a| {
324 for (e) |ex, i| {
325 if (a.line == ex.line and a.column == ex.column and std.mem.eql(u8, ex.msg, a.msg)) {
326 handled_errors[i] = true;
327 break;
328 }
329 } else {
330 std.debug.warn("{}\nUnexpected error:\n================\n{}:{}: {}\n================\nTest failed.\n", .{ case.name, a.line + 1, a.column + 1, a.msg });
331 std.process.exit(1);
332 }
333 }
334
335 for (handled_errors) |h, i| {
336 if (!h) {
337 const er = e[i];
338 std.debug.warn("{}\nDid not receive error:\n================\n{}:{}: {}\n================\nTest failed.\n", .{ case.name, er.line, er.column, er.msg });
339 std.process.exit(1);
340 }
341 }
342 },
343
315 else => return error.unimplemented,344 else => return error.unimplemented,
316 }345 }
317 }346 }
...@@ -423,10 +452,7 @@ pub const TestContext = struct {...@@ -423,10 +452,7 @@ pub const TestContext = struct {
423452
424 var module_node = prg_node.start("parse/analysis/codegen", null);453 var module_node = prg_node.start("parse/analysis/codegen", null);
425 module_node.activate();454 module_node.activate();
426 const failed = f: {455 try module.update();
427 module.update() catch break :f true;
428 break :f false;
429 };
430 module_node.end();456 module_node.end();
431 var err: ?anyerror = null;457 var err: ?anyerror = null;
432458