| ... | ... | @@ -533,6 +533,98 @@ pub fn init(gpa: Allocator, arena: Allocator) Cases { |
| 533 | 533 | }; |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | pub const TranslateCOptions = struct { |
| 537 | skip_translate_c: bool = false, |
| 538 | skip_run_translated_c: bool = false, |
| 539 | }; |
| 540 | pub fn lowerToTranslateCSteps( |
| 541 | self: *Cases, |
| 542 | b: *std.Build, |
| 543 | parent_step: *std.Build.Step, |
| 544 | test_filters: []const []const u8, |
| 545 | target: std.Build.ResolvedTarget, |
| 546 | translate_c_options: TranslateCOptions, |
| 547 | ) void { |
| 548 | const host = std.zig.system.resolveTargetQuery(.{}) catch |err| |
| 549 | std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)}); |
| 550 | |
| 551 | const tests = @import("../tests.zig"); |
| 552 | const test_translate_c_step = b.step("test-translate-c", "Run the C translation tests"); |
| 553 | if (!translate_c_options.skip_translate_c) { |
| 554 | tests.addTranslateCTests(b, test_translate_c_step, test_filters); |
| 555 | parent_step.dependOn(test_translate_c_step); |
| 556 | } |
| 557 | |
| 558 | const test_run_translated_c_step = b.step("test-run-translated-c", "Run the Run-Translated-C tests"); |
| 559 | if (!translate_c_options.skip_run_translated_c) { |
| 560 | tests.addRunTranslatedCTests(b, test_run_translated_c_step, test_filters, target); |
| 561 | parent_step.dependOn(test_run_translated_c_step); |
| 562 | } |
| 563 | |
| 564 | for (self.translate.items) |case| switch (case.kind) { |
| 565 | .run => |output| { |
| 566 | if (translate_c_options.skip_run_translated_c) continue; |
| 567 | const annotated_case_name = b.fmt("run-translated-c {s}", .{case.name}); |
| 568 | for (test_filters) |test_filter| { |
| 569 | if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; |
| 570 | } else if (test_filters.len > 0) continue; |
| 571 | if (!std.process.can_spawn) { |
| 572 | std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)}); |
| 573 | continue; // Pass test. |
| 574 | } |
| 575 | |
| 576 | if (getExternalExecutor(host, &case.target.result, .{ .link_libc = true }) != .native) { |
| 577 | // We wouldn't be able to run the compiled C code. |
| 578 | continue; // Pass test. |
| 579 | } |
| 580 | |
| 581 | const write_src = b.addWriteFiles(); |
| 582 | const file_source = write_src.add("tmp.c", case.input); |
| 583 | |
| 584 | const translate_c = b.addTranslateC(.{ |
| 585 | .root_source_file = file_source, |
| 586 | .optimize = .Debug, |
| 587 | .target = case.target, |
| 588 | .link_libc = case.link_libc, |
| 589 | .use_clang = case.c_frontend == .clang, |
| 590 | }); |
| 591 | translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name}); |
| 592 | |
| 593 | const run_exe = translate_c.addExecutable(.{}); |
| 594 | run_exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name}); |
| 595 | run_exe.linkLibC(); |
| 596 | const run = b.addRunArtifact(run_exe); |
| 597 | run.step.name = b.fmt("{s} run", .{annotated_case_name}); |
| 598 | run.expectStdOutEqual(output); |
| 599 | |
| 600 | test_run_translated_c_step.dependOn(&run.step); |
| 601 | }, |
| 602 | .translate => |output| { |
| 603 | if (translate_c_options.skip_translate_c) continue; |
| 604 | const annotated_case_name = b.fmt("zig translate-c {s}", .{case.name}); |
| 605 | for (test_filters) |test_filter| { |
| 606 | if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; |
| 607 | } else if (test_filters.len > 0) continue; |
| 608 | |
| 609 | const write_src = b.addWriteFiles(); |
| 610 | const file_source = write_src.add("tmp.c", case.input); |
| 611 | |
| 612 | const translate_c = b.addTranslateC(.{ |
| 613 | .root_source_file = file_source, |
| 614 | .optimize = .Debug, |
| 615 | .target = case.target, |
| 616 | .link_libc = case.link_libc, |
| 617 | .use_clang = case.c_frontend == .clang, |
| 618 | }); |
| 619 | translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name}); |
| 620 | |
| 621 | const check_file = translate_c.addCheckFile(output); |
| 622 | check_file.step.name = b.fmt("{s} CheckFile", .{annotated_case_name}); |
| 623 | test_translate_c_step.dependOn(&check_file.step); |
| 624 | }, |
| 625 | }; |
| 626 | } |
| 627 | |
| 536 | 628 | pub fn lowerToBuildSteps( |
| 537 | 629 | self: *Cases, |
| 538 | 630 | b: *std.Build, |
| ... | ... | @@ -681,66 +773,6 @@ pub fn lowerToBuildSteps( |
| 681 | 773 | .Header => @panic("TODO"), |
| 682 | 774 | } |
| 683 | 775 | } |
| 684 | | |
| 685 | | for (self.translate.items) |case| switch (case.kind) { |
| 686 | | .run => |output| { |
| 687 | | const annotated_case_name = b.fmt("run-translated-c {s}", .{case.name}); |
| 688 | | for (test_filters) |test_filter| { |
| 689 | | if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; |
| 690 | | } else if (test_filters.len > 0) continue; |
| 691 | | if (!std.process.can_spawn) { |
| 692 | | std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)}); |
| 693 | | continue; // Pass test. |
| 694 | | } |
| 695 | | |
| 696 | | if (getExternalExecutor(host, &case.target.result, .{ .link_libc = true }) != .native) { |
| 697 | | // We wouldn't be able to run the compiled C code. |
| 698 | | continue; // Pass test. |
| 699 | | } |
| 700 | | |
| 701 | | const write_src = b.addWriteFiles(); |
| 702 | | const file_source = write_src.add("tmp.c", case.input); |
| 703 | | |
| 704 | | const translate_c = b.addTranslateC(.{ |
| 705 | | .root_source_file = file_source, |
| 706 | | .optimize = .Debug, |
| 707 | | .target = case.target, |
| 708 | | .link_libc = case.link_libc, |
| 709 | | .use_clang = case.c_frontend == .clang, |
| 710 | | }); |
| 711 | | translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name}); |
| 712 | | |
| 713 | | const run_exe = translate_c.addExecutable(.{}); |
| 714 | | run_exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name}); |
| 715 | | run_exe.linkLibC(); |
| 716 | | const run = b.addRunArtifact(run_exe); |
| 717 | | run.step.name = b.fmt("{s} run", .{annotated_case_name}); |
| 718 | | run.expectStdOutEqual(output); |
| 719 | | |
| 720 | | parent_step.dependOn(&run.step); |
| 721 | | }, |
| 722 | | .translate => |output| { |
| 723 | | const annotated_case_name = b.fmt("zig translate-c {s}", .{case.name}); |
| 724 | | for (test_filters) |test_filter| { |
| 725 | | if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; |
| 726 | | } else if (test_filters.len > 0) continue; |
| 727 | | |
| 728 | | const write_src = b.addWriteFiles(); |
| 729 | | const file_source = write_src.add("tmp.c", case.input); |
| 730 | | |
| 731 | | const translate_c = b.addTranslateC(.{ |
| 732 | | .root_source_file = file_source, |
| 733 | | .optimize = .Debug, |
| 734 | | .target = case.target, |
| 735 | | .link_libc = case.link_libc, |
| 736 | | .use_clang = case.c_frontend == .clang, |
| 737 | | }); |
| 738 | | translate_c.step.name = annotated_case_name; |
| 739 | | |
| 740 | | const check_file = translate_c.addCheckFile(output); |
| 741 | | parent_step.dependOn(&check_file.step); |
| 742 | | }, |
| 743 | | }; |
| 744 | 776 | } |
| 745 | 777 | |
| 746 | 778 | /// Sort test filenames in-place, so that incremental test cases ("foo.0.zig", |
| ... | ... | @@ -961,6 +993,15 @@ const TestManifest = struct { |
| 961 | 993 | config_map: std.StringHashMap([]const u8), |
| 962 | 994 | trailing_bytes: []const u8 = "", |
| 963 | 995 | |
| 996 | const valid_keys = std.ComptimeStringMap(void, .{ |
| 997 | .{ "is_test", {} }, |
| 998 | .{ "output_mode", {} }, |
| 999 | .{ "target", {} }, |
| 1000 | .{ "c_frontend", {} }, |
| 1001 | .{ "link_libc", {} }, |
| 1002 | .{ "backend", {} }, |
| 1003 | }); |
| 1004 | |
| 964 | 1005 | const Type = enum { |
| 965 | 1006 | @"error", |
| 966 | 1007 | run, |
| ... | ... | @@ -1059,6 +1100,7 @@ const TestManifest = struct { |
| 1059 | 1100 | // Parse key=value(s) |
| 1060 | 1101 | var kv_it = std.mem.splitScalar(u8, trimmed, '='); |
| 1061 | 1102 | const key = kv_it.first(); |
| 1103 | if (!valid_keys.has(key)) return error.InvalidKey; |
| 1062 | 1104 | try manifest.config_map.putNoClobber(key, kv_it.next() orelse return error.MissingValuesForConfig); |
| 1063 | 1105 | } |
| 1064 | 1106 | |