zig/test/src/Libc.zig
2025-12-04 03:46:35 +01:00

124 lines
4.2 KiB
Zig

b: *std.Build,
options: Options,
root_step: *std.Build.Step,
libc_test_src_path: std.Build.LazyPath,
test_cases: std.ArrayList(TestCase) = .empty,
pub const Options = struct {
optimize_modes: []const std.builtin.OptimizeMode,
test_filters: []const []const u8,
test_target_filters: []const []const u8,
skip_wasm: bool,
max_rss: usize,
};
const TestCase = struct {
name: []const u8,
src_file: std.Build.LazyPath,
additional_src_file: ?std.Build.LazyPath,
supports_wasi_libc: bool,
};
pub const LibcTestCaseOption = struct {
additional_src_file: ?[]const u8 = null,
};
pub fn addLibcTestCase(
libc: *Libc,
path: []const u8,
supports_wasi_libc: bool,
options: LibcTestCaseOption,
) void {
const name = libc.b.dupe(path[0 .. path.len - std.fs.path.extension(path).len]);
std.mem.replaceScalar(u8, name, '/', '.');
libc.test_cases.append(libc.b.allocator, .{
.name = name,
.src_file = libc.libc_test_src_path.path(libc.b, path),
.additional_src_file = if (options.additional_src_file) |additional_src_file| libc.libc_test_src_path.path(libc.b, additional_src_file) else null,
.supports_wasi_libc = supports_wasi_libc,
}) catch @panic("OOM");
}
pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
if (libc.options.skip_wasm and target.query.cpu_arch != null and target.query.cpu_arch.?.isWasm()) return;
if (libc.options.test_target_filters.len > 0) {
const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM");
for (libc.options.test_target_filters) |filter| {
if (std.mem.indexOf(u8, triple_txt, filter)) |_| break;
} else return;
}
const common = libc.libc_test_src_path.path(libc.b, "common");
for (libc.options.optimize_modes) |optimize| {
const libtest_mod = libc.b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
});
var libtest_c_source_files: []const []const u8 = &.{ "print.c", "rand.c", "setrlim.c", "memfill.c", "vmfill.c", "fdfill.c", "utf8.c" };
libtest_mod.addCSourceFiles(.{
.root = common,
.files = libtest_c_source_files[0..if (target.result.isMuslLibC()) 7 else 2],
.flags = &.{"-fno-builtin"},
});
const libtest = libc.b.addLibrary(.{
.name = "test",
.root_module = libtest_mod,
});
for (libc.test_cases.items) |*test_case| {
if (target.result.isWasiLibC() and !test_case.supports_wasi_libc)
continue;
const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize });
for (libc.options.test_filters) |test_filter| {
if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
} else if (libc.options.test_filters.len > 0) continue;
const mod = libc.b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
});
mod.addIncludePath(common);
if (target.result.isWasiLibC())
mod.addCMacro("_WASI_EMULATED_SIGNAL", "");
mod.addCSourceFile(.{
.file = test_case.src_file,
.flags = &.{"-fno-builtin"},
});
if (test_case.additional_src_file) |additional_src_file| {
mod.addCSourceFile(.{
.file = additional_src_file,
.flags = &.{"-fno-builtin"},
});
}
mod.linkLibrary(libtest);
const exe = libc.b.addExecutable(.{
.name = test_case.name,
.root_module = mod,
.max_rss = libc.options.max_rss,
});
const run = libc.b.addRunArtifact(exe);
run.setName(annotated_case_name);
run.skip_foreign_checks = true;
run.expectStdErrEqual("");
run.expectStdOutEqual("");
run.expectExitCode(0);
run.step.max_rss = libc.options.max_rss;
libc.root_step.dependOn(&run.step);
}
}
}
const Libc = @This();
const std = @import("std");