| ... | @@ -125,6 +125,7 @@ pub const TestContext = struct { | ... | @@ -125,6 +125,7 @@ pub const TestContext = struct { |
| 125 | /// you can keep it mostly consistent, with small changes, testing the | 125 | /// you can keep it mostly consistent, with small changes, testing the |
| 126 | /// effects of the incremental compilation. | 126 | /// effects of the incremental compilation. |
| 127 | src: [:0]const u8, | 127 | src: [:0]const u8, |
| | 128 | name: []const u8, |
| 128 | case: union(enum) { | 129 | case: union(enum) { |
| 129 | /// Check the main binary output file against an expected set of bytes. | 130 | /// Check the main binary output file against an expected set of bytes. |
| 130 | /// This is most useful with, for example, `-ofmt=c`. | 131 | /// This is most useful with, for example, `-ofmt=c`. |
| ... | @@ -190,6 +191,7 @@ pub const TestContext = struct { | ... | @@ -190,6 +191,7 @@ pub const TestContext = struct { |
| 190 | self.emit_h = true; | 191 | self.emit_h = true; |
| 191 | self.updates.append(.{ | 192 | self.updates.append(.{ |
| 192 | .src = src, | 193 | .src = src, |
| | 194 | .name = "update", |
| 193 | .case = .{ .Header = result }, | 195 | .case = .{ .Header = result }, |
| 194 | }) catch @panic("out of memory"); | 196 | }) catch @panic("out of memory"); |
| 195 | } | 197 | } |
| ... | @@ -199,6 +201,7 @@ pub const TestContext = struct { | ... | @@ -199,6 +201,7 @@ pub const TestContext = struct { |
| 199 | pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void { | 201 | pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void { |
| 200 | self.updates.append(.{ | 202 | self.updates.append(.{ |
| 201 | .src = src, | 203 | .src = src, |
| | 204 | .name = "update", |
| 202 | .case = .{ .Execution = result }, | 205 | .case = .{ .Execution = result }, |
| 203 | }) catch @panic("out of memory"); | 206 | }) catch @panic("out of memory"); |
| 204 | } | 207 | } |
| ... | @@ -208,15 +211,25 @@ pub const TestContext = struct { | ... | @@ -208,15 +211,25 @@ pub const TestContext = struct { |
| 208 | pub fn addCompareObjectFile(self: *Case, src: [:0]const u8, result: []const u8) void { | 211 | pub fn addCompareObjectFile(self: *Case, src: [:0]const u8, result: []const u8) void { |
| 209 | self.updates.append(.{ | 212 | self.updates.append(.{ |
| 210 | .src = src, | 213 | .src = src, |
| | 214 | .name = "update", |
| 211 | .case = .{ .CompareObjectFile = result }, | 215 | .case = .{ .CompareObjectFile = result }, |
| 212 | }) catch @panic("out of memory"); | 216 | }) catch @panic("out of memory"); |
| 213 | } | 217 | } |
| 214 | | 218 | |
| | 219 | pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void { |
| | 220 | return self.addErrorNamed("update", src, errors); |
| | 221 | } |
| | 222 | |
| 215 | /// Adds a subcase in which the module is updated with `src`, which | 223 | /// Adds a subcase in which the module is updated with `src`, which |
| 216 | /// should contain invalid input, and ensures that compilation fails | 224 | /// should contain invalid input, and ensures that compilation fails |
| 217 | /// for the expected reasons, given in sequential order in `errors` in | 225 | /// for the expected reasons, given in sequential order in `errors` in |
| 218 | /// the form `:line:column: error: message`. | 226 | /// the form `:line:column: error: message`. |
| 219 | pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void { | 227 | pub fn addErrorNamed( |
| | 228 | self: *Case, |
| | 229 | name: []const u8, |
| | 230 | src: [:0]const u8, |
| | 231 | errors: []const []const u8, |
| | 232 | ) void { |
| 220 | var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch @panic("out of memory"); | 233 | var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch @panic("out of memory"); |
| 221 | for (errors) |err_msg_line, i| { | 234 | for (errors) |err_msg_line, i| { |
| 222 | if (std.mem.startsWith(u8, err_msg_line, "error: ")) { | 235 | if (std.mem.startsWith(u8, err_msg_line, "error: ")) { |
| ... | @@ -279,7 +292,11 @@ pub const TestContext = struct { | ... | @@ -279,7 +292,11 @@ pub const TestContext = struct { |
| 279 | }, | 292 | }, |
| 280 | }; | 293 | }; |
| 281 | } | 294 | } |
| 282 | self.updates.append(.{ .src = src, .case = .{ .Error = array } }) catch @panic("out of memory"); | 295 | self.updates.append(.{ |
| | 296 | .src = src, |
| | 297 | .name = name, |
| | 298 | .case = .{ .Error = array }, |
| | 299 | }) catch @panic("out of memory"); |
| 283 | } | 300 | } |
| 284 | | 301 | |
| 285 | /// Adds a subcase in which the module is updated with `src`, and | 302 | /// Adds a subcase in which the module is updated with `src`, and |
| ... | @@ -616,7 +633,7 @@ pub const TestContext = struct { | ... | @@ -616,7 +633,7 @@ pub const TestContext = struct { |
| 616 | if (skip_compile_errors) return; | 633 | if (skip_compile_errors) return; |
| 617 | | 634 | |
| 618 | const gpa = general_purpose_allocator.allocator(); | 635 | const gpa = general_purpose_allocator.allocator(); |
| 619 | var case: ?*Case = null; | 636 | var opt_case: ?*Case = null; |
| 620 | | 637 | |
| 621 | var it = dir.iterate(); | 638 | var it = dir.iterate(); |
| 622 | while (try it.next()) |entry| { | 639 | while (try it.next()) |entry| { |
| ... | @@ -671,10 +688,9 @@ pub const TestContext = struct { | ... | @@ -671,10 +688,9 @@ pub const TestContext = struct { |
| 671 | // The entire file contents is the source, including the manifest | 688 | // The entire file contents is the source, including the manifest |
| 672 | const src = try gpa.dupeZ(u8, contents); | 689 | const src = try gpa.dupeZ(u8, contents); |
| 673 | | 690 | |
| 674 | // Create a new test case, if necessary | 691 | const case = opt_case orelse case: { |
| 675 | case = if (one_test_case_per_file or case == null) blk: { | | |
| 676 | ctx.cases.append(TestContext.Case{ | 692 | ctx.cases.append(TestContext.Case{ |
| 677 | .name = if (one_test_case_per_file) case_name else name, | 693 | .name = name, |
| 678 | .target = .{}, | 694 | .target = .{}, |
| 679 | .backend = backend, | 695 | .backend = backend, |
| 680 | .updates = std.ArrayList(TestContext.Update).init(ctx.cases.allocator), | 696 | .updates = std.ArrayList(TestContext.Update).init(ctx.cases.allocator), |
| ... | @@ -682,11 +698,15 @@ pub const TestContext = struct { | ... | @@ -682,11 +698,15 @@ pub const TestContext = struct { |
| 682 | .output_mode = output_mode, | 698 | .output_mode = output_mode, |
| 683 | .files = std.ArrayList(TestContext.File).init(ctx.cases.allocator), | 699 | .files = std.ArrayList(TestContext.File).init(ctx.cases.allocator), |
| 684 | }) catch @panic("out of memory"); | 700 | }) catch @panic("out of memory"); |
| 685 | break :blk &ctx.cases.items[ctx.cases.items.len - 1]; | 701 | break :case &ctx.cases.items[ctx.cases.items.len - 1]; |
| 686 | } else case.?; | 702 | }; |
| 687 | | 703 | if (one_test_case_per_file) { |
| 688 | // Add our update + expected errors | 704 | case.name = case_name; |
| 689 | case.?.addError(src, errors.items); | 705 | case.addError(src, errors.items); |
| | 706 | opt_case = null; |
| | 707 | } else { |
| | 708 | case.addErrorNamed(case_name, src, errors.items); |
| | 709 | } |
| 690 | } else { | 710 | } else { |
| 691 | return error.InvalidFile; // Manifests are currently mandatory | 711 | return error.InvalidFile; // Manifests are currently mandatory |
| 692 | } | 712 | } |
| ... | @@ -1018,7 +1038,7 @@ pub const TestContext = struct { | ... | @@ -1018,7 +1038,7 @@ pub const TestContext = struct { |
| 1018 | defer comp.destroy(); | 1038 | defer comp.destroy(); |
| 1019 | | 1039 | |
| 1020 | for (case.updates.items) |update, update_index| { | 1040 | for (case.updates.items) |update, update_index| { |
| 1021 | var update_node = root_node.start("update", 3); | 1041 | var update_node = root_node.start(update.name, 3); |
| 1022 | update_node.activate(); | 1042 | update_node.activate(); |
| 1023 | defer update_node.end(); | 1043 | defer update_node.end(); |
| 1024 | | 1044 | |