| author | |
| committer | |
| log | 8082323dfd65c20328991d9a0d6740b779b26670 |
| tree | e689d430ba34ad788499fa85dff7ad4552dcc77e |
| parent | 5f6f38ff3160c75c03ce0477904051e6d8af0c80 |
| parent | a1b123bccbc2ae50442fcc1544b0da0595401038 |
| signature |
Custom test runner7 files changed, 100 insertions(+), 6 deletions(-)
lib/std/build.zig+12| ... | @@ -1509,6 +1509,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1509,6 +1509,7 @@ pub const LibExeObjStep = struct { |
| 1509 | name_prefix: []const u8, | 1509 | name_prefix: []const u8, |
| 1510 | filter: ?[]const u8, | 1510 | filter: ?[]const u8, |
| 1511 | test_evented_io: bool = false, | 1511 | test_evented_io: bool = false, |
| 1512 | test_runner: ?[]const u8, | ||
| 1512 | code_model: std.builtin.CodeModel = .default, | 1513 | code_model: std.builtin.CodeModel = .default, |
| 1513 | wasi_exec_model: ?std.builtin.WasiExecModel = null, | 1514 | wasi_exec_model: ?std.builtin.WasiExecModel = null, |
| 1514 | /// Symbols to be exported when compiling to wasm | 1515 | /// Symbols to be exported when compiling to wasm |
| ... | @@ -1771,6 +1772,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1771,6 +1772,7 @@ pub const LibExeObjStep = struct { |
| 1771 | .exec_cmd_args = null, | 1772 | .exec_cmd_args = null, |
| 1772 | .name_prefix = "", | 1773 | .name_prefix = "", |
| 1773 | .filter = null, | 1774 | .filter = null, |
| 1775 | .test_runner = null, | ||
| 1774 | .disable_stack_probing = false, | 1776 | .disable_stack_probing = false, |
| 1775 | .disable_sanitize_c = false, | 1777 | .disable_sanitize_c = false, |
| 1776 | .sanitize_thread = false, | 1778 | .sanitize_thread = false, |
| ... | @@ -2204,6 +2206,11 @@ pub const LibExeObjStep = struct { | ... | @@ -2204,6 +2206,11 @@ pub const LibExeObjStep = struct { |
| 2204 | self.filter = if (text) |t| self.builder.dupe(t) else null; | 2206 | self.filter = if (text) |t| self.builder.dupe(t) else null; |
| 2205 | } | 2207 | } |
| 2206 | 2208 | ||
| 2209 | pub fn setTestRunner(self: *LibExeObjStep, path: ?[]const u8) void { | ||
| 2210 | assert(self.kind == .@"test" or self.kind == .test_exe); | ||
| 2211 | self.test_runner = if (path) |p| self.builder.dupePath(p) else null; | ||
| 2212 | } | ||
| 2213 | |||
| 2207 | /// Handy when you have many C/C++ source files and want them all to have the same flags. | 2214 | /// Handy when you have many C/C++ source files and want them all to have the same flags. |
| 2208 | pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: []const []const u8) void { | 2215 | pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: []const []const u8) void { |
| 2209 | const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable; | 2216 | const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable; |
| ... | @@ -2669,6 +2676,11 @@ pub const LibExeObjStep = struct { | ... | @@ -2669,6 +2676,11 @@ pub const LibExeObjStep = struct { |
| 2669 | try zig_args.append(self.name_prefix); | 2676 | try zig_args.append(self.name_prefix); |
| 2670 | } | 2677 | } |
| 2671 | 2678 | ||
| 2679 | if (self.test_runner) |test_runner| { | ||
| 2680 | try zig_args.append("--test-runner"); | ||
| 2681 | try zig_args.append(builder.pathFromRoot(test_runner)); | ||
| 2682 | } | ||
| 2683 | |||
| 2672 | for (builder.debug_log_scopes) |log_scope| { | 2684 | for (builder.debug_log_scopes) |log_scope| { |
| 2673 | try zig_args.append("--debug-log"); | 2685 | try zig_args.append("--debug-log"); |
| 2674 | try zig_args.append(log_scope); | 2686 | try zig_args.append(log_scope); |
src/Compilation.zig+10-6| ... | @@ -994,6 +994,7 @@ pub const InitOptions = struct { | ... | @@ -994,6 +994,7 @@ pub const InitOptions = struct { |
| 994 | reference_trace: ?u32 = null, | 994 | reference_trace: ?u32 = null, |
| 995 | test_filter: ?[]const u8 = null, | 995 | test_filter: ?[]const u8 = null, |
| 996 | test_name_prefix: ?[]const u8 = null, | 996 | test_name_prefix: ?[]const u8 = null, |
| 997 | test_runner_path: ?[]const u8 = null, | ||
| 997 | subsystem: ?std.Target.SubSystem = null, | 998 | subsystem: ?std.Target.SubSystem = null, |
| 998 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). | 999 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). |
| 999 | wasi_exec_model: ?std.builtin.WasiExecModel = null, | 1000 | wasi_exec_model: ?std.builtin.WasiExecModel = null, |
| ... | @@ -1581,12 +1582,15 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1581,12 +1582,15 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1581 | errdefer std_pkg.destroy(gpa); | 1582 | errdefer std_pkg.destroy(gpa); |
| 1582 | 1583 | ||
| 1583 | const root_pkg = if (options.is_test) root_pkg: { | 1584 | const root_pkg = if (options.is_test) root_pkg: { |
| 1584 | const test_pkg = try Package.createWithDir( | 1585 | const test_pkg = if (options.test_runner_path) |test_runner| |
| 1585 | gpa, | 1586 | try Package.create(gpa, null, test_runner) |
| 1586 | options.zig_lib_directory, | 1587 | else |
| 1587 | null, | 1588 | try Package.createWithDir( |
| 1588 | "test_runner.zig", | 1589 | gpa, |
| 1589 | ); | 1590 | options.zig_lib_directory, |
| 1591 | null, | ||
| 1592 | "test_runner.zig", | ||
| 1593 | ); | ||
| 1590 | errdefer test_pkg.destroy(gpa); | 1594 | errdefer test_pkg.destroy(gpa); |
| 1591 | 1595 | ||
| 1592 | break :root_pkg test_pkg; | 1596 | break :root_pkg test_pkg; |
src/main.zig+5| ... | @@ -503,6 +503,7 @@ const usage_build_generic = | ... | @@ -503,6 +503,7 @@ const usage_build_generic = |
| 503 | \\ --test-cmd-bin Appends test binary path to test cmd args | 503 | \\ --test-cmd-bin Appends test binary path to test cmd args |
| 504 | \\ --test-evented-io Runs the test in evented I/O mode | 504 | \\ --test-evented-io Runs the test in evented I/O mode |
| 505 | \\ --test-no-exec Compiles test binary without running it | 505 | \\ --test-no-exec Compiles test binary without running it |
| 506 | \\ --test-runner [path] Specify a custom test runner | ||
| 506 | \\ | 507 | \\ |
| 507 | \\Debug Options (Zig Compiler Development): | 508 | \\Debug Options (Zig Compiler Development): |
| 508 | \\ -ftime-report Print timing diagnostics | 509 | \\ -ftime-report Print timing diagnostics |
| ... | @@ -726,6 +727,7 @@ fn buildOutputType( | ... | @@ -726,6 +727,7 @@ fn buildOutputType( |
| 726 | var runtime_args_start: ?usize = null; | 727 | var runtime_args_start: ?usize = null; |
| 727 | var test_filter: ?[]const u8 = null; | 728 | var test_filter: ?[]const u8 = null; |
| 728 | var test_name_prefix: ?[]const u8 = null; | 729 | var test_name_prefix: ?[]const u8 = null; |
| 730 | var test_runner_path: ?[]const u8 = null; | ||
| 729 | var override_local_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LOCAL_CACHE_DIR"); | 731 | var override_local_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LOCAL_CACHE_DIR"); |
| 730 | var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR"); | 732 | var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR"); |
| 731 | var override_lib_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIB_DIR"); | 733 | var override_lib_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIB_DIR"); |
| ... | @@ -1043,6 +1045,8 @@ fn buildOutputType( | ... | @@ -1043,6 +1045,8 @@ fn buildOutputType( |
| 1043 | test_filter = args_iter.nextOrFatal(); | 1045 | test_filter = args_iter.nextOrFatal(); |
| 1044 | } else if (mem.eql(u8, arg, "--test-name-prefix")) { | 1046 | } else if (mem.eql(u8, arg, "--test-name-prefix")) { |
| 1045 | test_name_prefix = args_iter.nextOrFatal(); | 1047 | test_name_prefix = args_iter.nextOrFatal(); |
| 1048 | } else if (mem.eql(u8, arg, "--test-runner")) { | ||
| 1049 | test_runner_path = args_iter.nextOrFatal(); | ||
| 1046 | } else if (mem.eql(u8, arg, "--test-cmd")) { | 1050 | } else if (mem.eql(u8, arg, "--test-cmd")) { |
| 1047 | try test_exec_args.append(args_iter.nextOrFatal()); | 1051 | try test_exec_args.append(args_iter.nextOrFatal()); |
| 1048 | } else if (mem.eql(u8, arg, "--cache-dir")) { | 1052 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| ... | @@ -2943,6 +2947,7 @@ fn buildOutputType( | ... | @@ -2943,6 +2947,7 @@ fn buildOutputType( |
| 2943 | .test_evented_io = test_evented_io, | 2947 | .test_evented_io = test_evented_io, |
| 2944 | .test_filter = test_filter, | 2948 | .test_filter = test_filter, |
| 2945 | .test_name_prefix = test_name_prefix, | 2949 | .test_name_prefix = test_name_prefix, |
| 2950 | .test_runner_path = test_runner_path, | ||
| 2946 | .disable_lld_caching = !have_enable_cache, | 2951 | .disable_lld_caching = !have_enable_cache, |
| 2947 | .subsystem = subsystem, | 2952 | .subsystem = subsystem, |
| 2948 | .wasi_exec_model = wasi_exec_model, | 2953 | .wasi_exec_model = wasi_exec_model, |
test/standalone.zig+1| ... | @@ -15,6 +15,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { | ... | @@ -15,6 +15,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 15 | cases.add("test/standalone/main_return_error/error_u8_non_zero.zig"); | 15 | cases.add("test/standalone/main_return_error/error_u8_non_zero.zig"); |
| 16 | cases.add("test/standalone/noreturn_call/inline.zig"); | 16 | cases.add("test/standalone/noreturn_call/inline.zig"); |
| 17 | cases.add("test/standalone/noreturn_call/as_arg.zig"); | 17 | cases.add("test/standalone/noreturn_call/as_arg.zig"); |
| 18 | cases.addBuildFile("test/standalone/test_runner_path/build.zig", .{ .requires_stage2 = true }); | ||
| 18 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); | 19 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); |
| 19 | cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); | 20 | cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); |
| 20 | cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); | 21 | cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); |
test/standalone/test_runner_path/build.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const Builder = @import("std").build.Builder; | ||
| 2 | |||
| 3 | pub fn build(b: *Builder) void { | ||
| 4 | const test_exe = b.addTestExe("test", "test.zig"); | ||
| 5 | test_exe.test_runner = "test_runner.zig"; | ||
| 6 | |||
| 7 | const test_run = test_exe.run(); | ||
| 8 | |||
| 9 | const test_step = b.step("test", "Test the program"); | ||
| 10 | test_step.dependOn(&test_run.step); | ||
| 11 | } | ||
test/standalone/test_runner_path/test.zig created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | test "test runner path pass" {} | ||
| 2 | |||
| 3 | test "test runner path fail" { | ||
| 4 | return error.Fail; | ||
| 5 | } | ||
| 6 | |||
| 7 | test "test runner path skip" { | ||
| 8 | return error.SkipZigTest; | ||
| 9 | } | ||
test/standalone/test_runner_path/test_runner.zig created+52| ... | @@ -0,0 +1,52 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const io = std.io; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | |||
| 5 | pub const io_mode: io.Mode = builtin.test_io_mode; | ||
| 6 | |||
| 7 | pub fn main() void { | ||
| 8 | const test_fn_list = builtin.test_functions; | ||
| 9 | var ok_count: usize = 0; | ||
| 10 | var skip_count: usize = 0; | ||
| 11 | var fail_count: usize = 0; | ||
| 12 | |||
| 13 | var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined; | ||
| 14 | // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly | ||
| 15 | // ignores the alignment of the slice. | ||
| 16 | async_frame_buffer = &[_]u8{}; | ||
| 17 | |||
| 18 | for (test_fn_list) |test_fn| { | ||
| 19 | const result = if (test_fn.async_frame_size) |size| switch (io_mode) { | ||
| 20 | .evented => blk: { | ||
| 21 | if (async_frame_buffer.len < size) { | ||
| 22 | std.heap.page_allocator.free(async_frame_buffer); | ||
| 23 | async_frame_buffer = std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size) catch @panic("out of memory"); | ||
| 24 | } | ||
| 25 | const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func); | ||
| 26 | break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{}); | ||
| 27 | }, | ||
| 28 | .blocking => { | ||
| 29 | skip_count += 1; | ||
| 30 | continue; | ||
| 31 | }, | ||
| 32 | } else test_fn.func(); | ||
| 33 | if (result) |_| { | ||
| 34 | ok_count += 1; | ||
| 35 | } else |err| switch (err) { | ||
| 36 | error.SkipZigTest => { | ||
| 37 | skip_count += 1; | ||
| 38 | }, | ||
| 39 | else => { | ||
| 40 | fail_count += 1; | ||
| 41 | }, | ||
| 42 | } | ||
| 43 | } | ||
| 44 | if (ok_count == test_fn_list.len) { | ||
| 45 | std.debug.print("All {d} tests passed.\n", .{ok_count}); | ||
| 46 | } else { | ||
| 47 | std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); | ||
| 48 | } | ||
| 49 | if (ok_count != 1 or skip_count != 1 or fail_count != 1) { | ||
| 50 | std.process.exit(1); | ||
| 51 | } | ||
| 52 | } | ||