| ... | ... | @@ -96,6 +96,10 @@ pub const TestContext = struct { |
| 96 | 96 | /// stdout against the expected results |
| 97 | 97 | /// This is a slice containing the expected message. |
| 98 | 98 | Execution: []const u8, |
| 99 | /// A header update compiles the input with the equivalent of |
| 100 | /// `-Demit_h=true` and tests the produced header against the |
| 101 | /// expected result |
| 102 | Header: []const u8, |
| 99 | 103 | }, |
| 100 | 104 | }; |
| 101 | 105 | |
| ... | ... | @@ -138,6 +142,15 @@ pub const TestContext = struct { |
| 138 | 142 | }) catch unreachable; |
| 139 | 143 | } |
| 140 | 144 | |
| 145 | /// Adds a subcase in which the module is updated with `src`, and a C |
| 146 | /// header is generated. |
| 147 | pub fn addHeader(self: *Case, src: [:0]const u8, result: [:0]const u8) void { |
| 148 | self.updates.append(.{ |
| 149 | .src = src, |
| 150 | .case = .{ .Header = result }, |
| 151 | }) catch unreachable; |
| 152 | } |
| 153 | |
| 141 | 154 | /// Adds a subcase in which the module is updated with `src`, compiled, |
| 142 | 155 | /// run, and the output is tested against `result`. |
| 143 | 156 | pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void { |
| ... | ... | @@ -269,6 +282,10 @@ pub const TestContext = struct { |
| 269 | 282 | ctx.addC(name, target, .Zig).addTransform(src, cheader ++ out); |
| 270 | 283 | } |
| 271 | 284 | |
| 285 | pub fn h(ctx: *TestContext, name: []const u8, target: std.zig.CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 286 | ctx.addC(name, target, .Zig).addHeader(src, cheader ++ out); |
| 287 | } |
| 288 | |
| 272 | 289 | pub fn addCompareOutput( |
| 273 | 290 | ctx: *TestContext, |
| 274 | 291 | name: []const u8, |
| ... | ... | @@ -547,6 +564,10 @@ pub const TestContext = struct { |
| 547 | 564 | .directory = emit_directory, |
| 548 | 565 | .basename = bin_name, |
| 549 | 566 | }; |
| 567 | const emit_h: Compilation.EmitLoc = .{ |
| 568 | .directory = emit_directory, |
| 569 | .basename = "test_case.h", |
| 570 | }; |
| 550 | 571 | const comp = try Compilation.create(allocator, .{ |
| 551 | 572 | .local_cache_directory = zig_cache_directory, |
| 552 | 573 | .global_cache_directory = zig_cache_directory, |
| ... | ... | @@ -561,6 +582,7 @@ pub const TestContext = struct { |
| 561 | 582 | // TODO: support testing optimizations |
| 562 | 583 | .optimize_mode = .Debug, |
| 563 | 584 | .emit_bin = emit_bin, |
| 585 | .emit_h = emit_h, |
| 564 | 586 | .root_pkg = &root_pkg, |
| 565 | 587 | .keep_source_files_loaded = true, |
| 566 | 588 | .object_format = ofmt, |
| ... | ... | @@ -616,6 +638,22 @@ pub const TestContext = struct { |
| 616 | 638 | } |
| 617 | 639 | |
| 618 | 640 | switch (update.case) { |
| 641 | .Header => |expected_output| { |
| 642 | var file = try tmp.dir.openFile("test_case.h", .{ .read = true }); |
| 643 | defer file.close(); |
| 644 | var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read headeroutput!"); |
| 645 | |
| 646 | if (expected_output.len != out.len) { |
| 647 | std.debug.print("\nTransformed header length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out }); |
| 648 | std.process.exit(1); |
| 649 | } |
| 650 | for (expected_output) |e, i| { |
| 651 | if (out[i] != e) { |
| 652 | std.debug.print("\nTransformed header differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out }); |
| 653 | std.process.exit(1); |
| 654 | } |
| 655 | } |
| 656 | }, |
| 619 | 657 | .Transformation => |expected_output| { |
| 620 | 658 | if (case.cbe) { |
| 621 | 659 | // The C file is always closed after an update, because we don't support |
| ... | ... | @@ -670,8 +708,8 @@ pub const TestContext = struct { |
| 670 | 708 | test_node.activate(); |
| 671 | 709 | defer test_node.end(); |
| 672 | 710 | var handled_errors = try arena.alloc(bool, e.len); |
| 673 | | for (handled_errors) |*h| { |
| 674 | | h.* = false; |
| 711 | for (handled_errors) |*handled| { |
| 712 | handled.* = false; |
| 675 | 713 | } |
| 676 | 714 | var all_errors = try comp.getAllErrorsAlloc(); |
| 677 | 715 | defer all_errors.deinit(allocator); |
| ... | ... | @@ -709,8 +747,8 @@ pub const TestContext = struct { |
| 709 | 747 | } |
| 710 | 748 | } |
| 711 | 749 | |
| 712 | | for (handled_errors) |h, i| { |
| 713 | | if (!h) { |
| 750 | for (handled_errors) |handled, i| { |
| 751 | if (!handled) { |
| 714 | 752 | const er = e[i]; |
| 715 | 753 | std.debug.print( |
| 716 | 754 | "{s}\nDid not receive error:\n================\n{}\n================\nTest failed.\n", |