authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-04 15:32:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-04 15:32:16-07:00
logc594f8dc26cebbcd371c0136da5ee7bb0eaca2b3
treed6c5691ec7c7d0d73c918672e905c43ae9f897e2
parent02d09d13281a10dbab0d80d07935712b1fc50756

stage2 tests: support the -Denable-qemu options and friends


4 files changed, 113 insertions(+), 55 deletions(-)

build.zig+6
...@@ -107,6 +107,12 @@ pub fn build(b: *Builder) !void {...@@ -107,6 +107,12 @@ pub fn build(b: *Builder) !void {
107 const is_wasmtime_enabled = b.option(bool, "enable-wasmtime", "Use Wasmtime to enable and run WASI libstd tests") orelse false;107 const is_wasmtime_enabled = b.option(bool, "enable-wasmtime", "Use Wasmtime to enable and run WASI libstd tests") orelse false;
108 const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc");108 const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc");
109109
110
111 test_stage2.addBuildOption(bool, "enable_qemu", is_qemu_enabled);
112 test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled);
113 test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled);
114 test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir);
115
110 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");116 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
111 test_stage2_step.dependOn(&test_stage2.step);117 test_stage2_step.dependOn(&test_stage2.step);
112 test_step.dependOn(test_stage2_step);118 test_step.dependOn(test_stage2_step);
lib/std/build.zig+4-4
...@@ -1857,10 +1857,10 @@ pub const LibExeObjStep = struct {...@@ -1857,10 +1857,10 @@ pub const LibExeObjStep = struct {
1857 zig_args.append(builder.zig_exe) catch unreachable;1857 zig_args.append(builder.zig_exe) catch unreachable;
18581858
1859 const cmd = switch (self.kind) {1859 const cmd = switch (self.kind) {
1860 Kind.Lib => "build-lib",1860 .Lib => "build-lib",
1861 Kind.Exe => "build-exe",1861 .Exe => "build-exe",
1862 Kind.Obj => "build-obj",1862 .Obj => "build-obj",
1863 Kind.Test => "test",1863 .Test => "test",
1864 };1864 };
1865 zig_args.append(cmd) catch unreachable;1865 zig_args.append(cmd) catch unreachable;
18661866
src-self-hosted/test.zig+66-14
...@@ -4,6 +4,11 @@ const Module = @import("Module.zig");...@@ -4,6 +4,11 @@ const Module = @import("Module.zig");
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const zir = @import("zir.zig");5const zir = @import("zir.zig");
6const Package = @import("Package.zig");6const Package = @import("Package.zig");
7const build_options = @import("build_options");
8const enable_qemu: bool = build_options.enable_qemu;
9const enable_wine: bool = build_options.enable_wine;
10const enable_wasmtime: bool = build_options.enable_wasmtime;
11const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir;
712
8const cheader = @embedFile("cbe.h");13const cheader = @embedFile("cbe.h");
914
...@@ -401,8 +406,6 @@ pub const TestContext = struct {...@@ -401,8 +406,6 @@ pub const TestContext = struct {
401 const root_node = try progress.start("tests", self.cases.items.len);406 const root_node = try progress.start("tests", self.cases.items.len);
402 defer root_node.end();407 defer root_node.end();
403408
404 const native_info = try std.zig.system.NativeTargetInfo.detect(std.heap.page_allocator, .{});
405
406 for (self.cases.items) |case| {409 for (self.cases.items) |case| {
407 std.testing.base_allocator_instance.reset();410 std.testing.base_allocator_instance.reset();
408411
...@@ -415,13 +418,19 @@ pub const TestContext = struct {...@@ -415,13 +418,19 @@ pub const TestContext = struct {
415 progress.initial_delay_ns = 0;418 progress.initial_delay_ns = 0;
416 progress.refresh_rate_ns = 0;419 progress.refresh_rate_ns = 0;
417420
418 const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.target);421 try self.runOneCase(std.testing.allocator, &prg_node, case);
419 try self.runOneCase(std.testing.allocator, &prg_node, case, info.target);
420 try std.testing.allocator_instance.validate();422 try std.testing.allocator_instance.validate();
421 }423 }
422 }424 }
423425
424 fn runOneCase(self: *TestContext, allocator: *Allocator, root_node: *std.Progress.Node, case: Case, target: std.Target) !void {426 fn runOneCase(self: *TestContext, allocator: *Allocator, root_node: *std.Progress.Node, case: Case) !void {
427 const target_info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.target);
428 const target = target_info.target;
429
430 var arena_allocator = std.heap.ArenaAllocator.init(allocator);
431 defer arena_allocator.deinit();
432 const arena = &arena_allocator.allocator;
433
425 var tmp = std.testing.tmpDir(.{});434 var tmp = std.testing.tmpDir(.{});
426 defer tmp.cleanup();435 defer tmp.cleanup();
427436
...@@ -429,8 +438,7 @@ pub const TestContext = struct {...@@ -429,8 +438,7 @@ pub const TestContext = struct {
429 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);438 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
430 defer root_pkg.destroy();439 defer root_pkg.destroy();
431440
432 const bin_name = try std.zig.binNameAlloc(allocator, "test_case", target, case.output_mode, null);441 const bin_name = try std.zig.binNameAlloc(arena, "test_case", target, case.output_mode, null);
433 defer allocator.free(bin_name);
434442
435 var module = try Module.init(allocator, .{443 var module = try Module.init(allocator, .{
436 .root_name = "test_case",444 .root_name = "test_case",
...@@ -485,8 +493,7 @@ pub const TestContext = struct {...@@ -485,8 +493,7 @@ pub const TestContext = struct {
485 // incremental updates493 // incremental updates
486 var file = try tmp.dir.openFile(bin_name, .{ .read = true });494 var file = try tmp.dir.openFile(bin_name, .{ .read = true });
487 defer file.close();495 defer file.close();
488 var out = file.reader().readAllAlloc(allocator, 1024 * 1024) catch @panic("Unable to read C output!");496 var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read C output!");
489 defer allocator.free(out);
490497
491 if (expected_output.len != out.len) {498 if (expected_output.len != out.len) {
492 std.debug.warn("\nTransformed C length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });499 std.debug.warn("\nTransformed C length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
...@@ -533,8 +540,7 @@ pub const TestContext = struct {...@@ -533,8 +540,7 @@ pub const TestContext = struct {
533 var test_node = update_node.start("assert", null);540 var test_node = update_node.start("assert", null);
534 test_node.activate();541 test_node.activate();
535 defer test_node.end();542 defer test_node.end();
536 var handled_errors = try allocator.alloc(bool, e.len);543 var handled_errors = try arena.alloc(bool, e.len);
537 defer allocator.free(handled_errors);
538 for (handled_errors) |*h| {544 for (handled_errors) |*h| {
539 h.* = false;545 h.* = false;
540 }546 }
...@@ -569,10 +575,56 @@ pub const TestContext = struct {...@@ -569,10 +575,56 @@ pub const TestContext = struct {
569 exec_node.activate();575 exec_node.activate();
570 defer exec_node.end();576 defer exec_node.end();
571577
572 try module.makeBinFileExecutable();578 var argv = std.ArrayList([]const u8).init(allocator);
579 defer argv.deinit();
580
581 const exe_path = try std.fmt.allocPrint(arena, "." ++ std.fs.path.sep_str ++ "{}", .{bin_name});
582
583 switch (case.target.getExternalExecutor()) {
584 .native => try argv.append(exe_path),
585 .unavailable => return, // No executor available; pass test.
586
587 .qemu => |qemu_bin_name| {
588 if (enable_qemu) qemu: {
589 // TODO Ability for test cases to specify whether to link libc.
590 const need_cross_glibc = false; // target.isGnuLibC() and self.is_linking_libc;
591 const glibc_dir_arg = if (need_cross_glibc)
592 glibc_multi_install_dir orelse break :qemu
593 else
594 null;
595 try argv.append(qemu_bin_name);
596 if (glibc_dir_arg) |dir| {
597 const linux_triple = try target.linuxTriple(arena);
598 const full_dir = try std.fs.path.join(arena, &[_][]const u8{
599 dir,
600 linux_triple,
601 });
602
603 try argv.append("-L");
604 try argv.append(full_dir);
605 }
606 try argv.append(exe_path);
607 }
608 return; // QEMU not available; pass test.
609 },
610
611 .wine => |wine_bin_name| if (enable_wine) {
612 try argv.append(wine_bin_name);
613 try argv.append(exe_path);
614 } else {
615 return; // Wine not available; pass test.
616 },
617
618 .wasmtime => |wasmtime_bin_name| if (enable_wasmtime) {
619 try argv.append(wasmtime_bin_name);
620 try argv.append("--dir=.");
621 try argv.append(exe_path);
622 } else {
623 return; // wasmtime not available; pass test.
624 },
625 }
573626
574 const exe_path = try std.fmt.allocPrint(allocator, "." ++ std.fs.path.sep_str ++ "{}", .{bin_name});627 try module.makeBinFileExecutable();
575 defer allocator.free(exe_path);
576628
577 break :x try std.ChildProcess.exec(.{629 break :x try std.ChildProcess.exec(.{
578 .allocator = allocator,630 .allocator = allocator,
test/stage2/compare_output.zig+37-37
...@@ -7,7 +7,7 @@ const linux_x64 = std.zig.CrossTarget{...@@ -7,7 +7,7 @@ const linux_x64 = std.zig.CrossTarget{
7 .os_tag = .linux,7 .os_tag = .linux,
8};8};
99
10const riscv64 = std.zig.CrossTarget{10const linux_riscv64 = std.zig.CrossTarget{
11 .cpu_arch = .riscv64,11 .cpu_arch = .riscv64,
12 .os_tag = .linux,12 .os_tag = .linux,
13};13};
...@@ -123,6 +123,42 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -123,6 +123,42 @@ pub fn addCases(ctx: *TestContext) !void {
123 \\123 \\
124 );124 );
125 }125 }
126
127 {
128 var case = ctx.exe("hello world", linux_riscv64);
129 // Regular old hello world
130 case.addCompareOutput(
131 \\export fn _start() noreturn {
132 \\ print();
133 \\
134 \\ exit();
135 \\}
136 \\
137 \\fn print() void {
138 \\ asm volatile ("ecall"
139 \\ :
140 \\ : [number] "{a7}" (64),
141 \\ [arg1] "{a0}" (1),
142 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
143 \\ [arg3] "{a2}" ("Hello, World!\n".len)
144 \\ : "rcx", "r11", "memory"
145 \\ );
146 \\ return;
147 \\}
148 \\
149 \\fn exit() noreturn {
150 \\ asm volatile ("ecall"
151 \\ :
152 \\ : [number] "{a7}" (94),
153 \\ [arg1] "{a0}" (0)
154 \\ : "rcx", "r11", "memory"
155 \\ );
156 \\ unreachable;
157 \\}
158 ,
159 "Hello, World!\n",
160 );
161 }
126162
127 {163 {
128 var case = ctx.exe("adding numbers at comptime", linux_x64);164 var case = ctx.exe("adding numbers at comptime", linux_x64);
...@@ -403,40 +439,4 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -403,40 +439,4 @@ pub fn addCases(ctx: *TestContext) !void {
403 "",439 "",
404 );440 );
405 }441 }
406
407 {
408 var case = ctx.exe("hello world with updates", riscv64);
409 // Regular old hello world
410 case.addCompareOutput(
411 \\export fn _start() noreturn {
412 \\ print();
413 \\
414 \\ exit();
415 \\}
416 \\
417 \\fn print() void {
418 \\ asm volatile ("ecall"
419 \\ :
420 \\ : [number] "{a7}" (64),
421 \\ [arg1] "{a0}" (1),
422 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
423 \\ [arg3] "{a2}" ("Hello, World!\n".len)
424 \\ : "rcx", "r11", "memory"
425 \\ );
426 \\ return;
427 \\}
428 \\
429 \\fn exit() noreturn {
430 \\ asm volatile ("ecall"
431 \\ :
432 \\ : [number] "{a7}" (94),
433 \\ [arg1] "{a0}" (0)
434 \\ : "rcx", "r11", "memory"
435 \\ );
436 \\ unreachable;
437 \\}
438 ,
439 "Hello, World!\n",
440 );
441 }
442}442}