2020-08-20 02:40:15 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-12-31 23:07:36 +00:00
|
|
|
// Copyright (c) 2015-2021 Zig Contributors
|
2020-08-20 02:40:15 +00:00
|
|
|
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
|
|
|
// The MIT license requires this copyright notice to be included in all copies
|
|
|
|
// and substantial portions of the software.
|
2017-10-31 08:47:55 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const io = std.io;
|
2017-05-01 17:12:38 +00:00
|
|
|
const builtin = @import("builtin");
|
2016-02-04 01:02:01 +00:00
|
|
|
|
2020-02-06 22:56:40 +00:00
|
|
|
pub const io_mode: io.Mode = builtin.test_io_mode;
|
2020-02-05 21:53:29 +00:00
|
|
|
|
2020-08-11 02:34:27 +00:00
|
|
|
var log_err_count: usize = 0;
|
|
|
|
|
2020-12-29 03:00:34 +00:00
|
|
|
var args_buffer: [std.fs.MAX_PATH_BYTES + std.mem.page_size]u8 = undefined;
|
|
|
|
var args_allocator = std.heap.FixedBufferAllocator.init(&args_buffer);
|
|
|
|
|
2021-05-11 18:47:22 +00:00
|
|
|
fn processArgs() void {
|
2020-12-29 03:00:34 +00:00
|
|
|
const args = std.process.argsAlloc(&args_allocator.allocator) catch {
|
|
|
|
@panic("Too many bytes passed over the CLI to the test runner");
|
|
|
|
};
|
|
|
|
std.testing.zig_exe_path = args[1];
|
2021-05-11 18:47:22 +00:00
|
|
|
}
|
2020-12-29 03:00:34 +00:00
|
|
|
|
2021-05-11 18:47:22 +00:00
|
|
|
pub fn main() anyerror!void {
|
2021-05-17 22:28:22 +00:00
|
|
|
if (builtin.zig_is_stage2) {
|
|
|
|
return main2();
|
|
|
|
}
|
2021-05-11 18:47:22 +00:00
|
|
|
processArgs();
|
2019-12-12 23:27:17 +00:00
|
|
|
const test_fn_list = builtin.test_functions;
|
2018-07-22 03:43:43 +00:00
|
|
|
var ok_count: usize = 0;
|
|
|
|
var skip_count: usize = 0;
|
2021-05-04 16:36:59 +00:00
|
|
|
var fail_count: usize = 0;
|
2019-10-18 01:46:41 +00:00
|
|
|
var progress = std.Progress{};
|
|
|
|
const root_node = progress.start("Test", test_fn_list.len) catch |err| switch (err) {
|
|
|
|
// TODO still run tests in this case
|
|
|
|
error.TimerUnsupported => @panic("timer unsupported"),
|
|
|
|
};
|
2016-02-04 01:02:01 +00:00
|
|
|
|
2020-02-06 22:56:40 +00:00
|
|
|
var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined;
|
|
|
|
// TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly
|
|
|
|
// ignores the alignment of the slice.
|
|
|
|
async_frame_buffer = &[_]u8{};
|
|
|
|
|
2020-08-08 06:26:58 +00:00
|
|
|
var leaks: usize = 0;
|
2019-10-18 01:46:41 +00:00
|
|
|
for (test_fn_list) |test_fn, i| {
|
2020-08-18 22:10:31 +00:00
|
|
|
std.testing.allocator_instance = .{};
|
2020-08-08 06:26:58 +00:00
|
|
|
defer {
|
|
|
|
if (std.testing.allocator_instance.deinit()) {
|
|
|
|
leaks += 1;
|
|
|
|
}
|
|
|
|
}
|
2020-07-09 04:01:13 +00:00
|
|
|
std.testing.log_level = .warn;
|
2020-01-29 19:18:04 +00:00
|
|
|
|
2020-12-19 04:51:18 +00:00
|
|
|
var test_node = root_node.start(test_fn.name, 0);
|
2019-10-18 01:46:41 +00:00
|
|
|
test_node.activate();
|
2019-10-21 23:01:08 +00:00
|
|
|
progress.refresh();
|
2019-12-12 23:27:17 +00:00
|
|
|
if (progress.terminal == null) {
|
2020-11-26 08:48:12 +00:00
|
|
|
std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name });
|
2019-12-12 23:27:17 +00:00
|
|
|
}
|
2020-02-06 22:56:40 +00:00
|
|
|
const result = if (test_fn.async_frame_size) |size| switch (io_mode) {
|
|
|
|
.evented => blk: {
|
|
|
|
if (async_frame_buffer.len < size) {
|
|
|
|
std.heap.page_allocator.free(async_frame_buffer);
|
|
|
|
async_frame_buffer = try std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size);
|
|
|
|
}
|
2020-05-04 15:49:27 +00:00
|
|
|
const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func);
|
2020-06-24 11:07:39 +00:00
|
|
|
break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{});
|
2020-02-06 22:56:40 +00:00
|
|
|
},
|
|
|
|
.blocking => {
|
|
|
|
skip_count += 1;
|
|
|
|
test_node.end();
|
2021-05-04 16:36:59 +00:00
|
|
|
progress.log("{s}... SKIP (async test)\n", .{test_fn.name});
|
2020-08-08 05:35:15 +00:00
|
|
|
if (progress.terminal == null) std.debug.print("SKIP (async test)\n", .{});
|
2020-02-06 22:56:40 +00:00
|
|
|
continue;
|
|
|
|
},
|
|
|
|
} else test_fn.func();
|
|
|
|
if (result) |_| {
|
2018-07-22 03:43:43 +00:00
|
|
|
ok_count += 1;
|
2019-10-18 01:46:41 +00:00
|
|
|
test_node.end();
|
2020-08-08 05:35:15 +00:00
|
|
|
if (progress.terminal == null) std.debug.print("OK\n", .{});
|
2018-07-22 03:43:43 +00:00
|
|
|
} else |err| switch (err) {
|
|
|
|
error.SkipZigTest => {
|
|
|
|
skip_count += 1;
|
2019-10-18 01:46:41 +00:00
|
|
|
test_node.end();
|
2021-05-04 16:36:59 +00:00
|
|
|
progress.log("{s}... SKIP\n", .{test_fn.name});
|
2020-08-08 05:35:15 +00:00
|
|
|
if (progress.terminal == null) std.debug.print("SKIP\n", .{});
|
2018-07-22 03:43:43 +00:00
|
|
|
},
|
2019-10-21 22:35:14 +00:00
|
|
|
else => {
|
2021-05-04 16:36:59 +00:00
|
|
|
fail_count += 1;
|
|
|
|
test_node.end();
|
|
|
|
progress.log("{s}... FAIL ({s})\n", .{ test_fn.name, @errorName(err) });
|
|
|
|
if (progress.terminal == null) std.debug.print("FAIL ({s})\n", .{@errorName(err)});
|
2021-05-11 17:50:17 +00:00
|
|
|
if (@errorReturnTrace()) |trace| {
|
|
|
|
std.debug.dumpStackTrace(trace.*);
|
|
|
|
}
|
2019-10-21 22:35:14 +00:00
|
|
|
},
|
2018-07-22 03:43:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-18 01:46:41 +00:00
|
|
|
root_node.end();
|
2019-10-22 02:20:45 +00:00
|
|
|
if (ok_count == test_fn_list.len) {
|
2020-11-26 08:48:12 +00:00
|
|
|
std.debug.print("All {d} tests passed.\n", .{ok_count});
|
2019-10-22 02:20:45 +00:00
|
|
|
} else {
|
2021-05-04 16:36:59 +00:00
|
|
|
std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count });
|
2016-02-04 01:02:01 +00:00
|
|
|
}
|
2020-08-11 02:34:27 +00:00
|
|
|
if (log_err_count != 0) {
|
2020-11-26 08:48:12 +00:00
|
|
|
std.debug.print("{d} errors were logged.\n", .{log_err_count});
|
2020-08-11 02:34:27 +00:00
|
|
|
}
|
2020-08-08 06:26:58 +00:00
|
|
|
if (leaks != 0) {
|
2020-11-26 08:48:12 +00:00
|
|
|
std.debug.print("{d} tests leaked memory.\n", .{leaks});
|
2020-08-11 02:34:27 +00:00
|
|
|
}
|
2021-05-04 16:36:59 +00:00
|
|
|
if (leaks != 0 or log_err_count != 0 or fail_count != 0) {
|
2020-08-08 06:26:58 +00:00
|
|
|
std.process.exit(1);
|
|
|
|
}
|
2016-02-04 01:02:01 +00:00
|
|
|
}
|
2020-07-09 04:01:13 +00:00
|
|
|
|
|
|
|
pub fn log(
|
|
|
|
comptime message_level: std.log.Level,
|
|
|
|
comptime scope: @Type(.EnumLiteral),
|
|
|
|
comptime format: []const u8,
|
2020-07-11 11:09:04 +00:00
|
|
|
args: anytype,
|
2020-07-09 04:01:13 +00:00
|
|
|
) void {
|
2020-08-11 02:34:27 +00:00
|
|
|
if (@enumToInt(message_level) <= @enumToInt(std.log.Level.err)) {
|
|
|
|
log_err_count += 1;
|
|
|
|
}
|
2020-07-09 04:01:13 +00:00
|
|
|
if (@enumToInt(message_level) <= @enumToInt(std.testing.log_level)) {
|
2020-11-26 08:48:12 +00:00
|
|
|
std.debug.print("[{s}] ({s}): " ++ format ++ "\n", .{ @tagName(scope), @tagName(message_level) } ++ args);
|
2020-07-09 04:01:13 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-17 22:28:22 +00:00
|
|
|
|
|
|
|
pub fn main2() anyerror!void {
|
|
|
|
// Simpler main(), exercising fewer language features, so that stage2 can handle it.
|
|
|
|
for (builtin.test_functions) |test_fn| {
|
|
|
|
try test_fn.func();
|
|
|
|
}
|
|
|
|
}
|