some tests
This commit is contained in:
48
build.zig
48
build.zig
@@ -47,8 +47,56 @@ pub fn build(b: *std.Build) !void {
|
|||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try compileTestApplications(b, target, optimize, false, false);
|
||||||
|
try compileTestApplications(b, target, optimize, false, true);
|
||||||
|
try compileTestApplications(b, target, optimize, true, true);
|
||||||
|
|
||||||
const exe_tests = b.addTest(.{ .root_module = mod });
|
const exe_tests = b.addTest(.{ .root_module = mod });
|
||||||
const run_exe_tests = b.addRunArtifact(exe_tests);
|
const run_exe_tests = b.addRunArtifact(exe_tests);
|
||||||
const test_step = b.step("test", "Run tests");
|
const test_step = b.step("test", "Run tests");
|
||||||
|
test_step.dependOn(b.getInstallStep());
|
||||||
test_step.dependOn(&run_exe_tests.step);
|
test_step.dependOn(&run_exe_tests.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compileTestApplications(
|
||||||
|
b: *std.Build,
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
comptime link_libc: bool,
|
||||||
|
comptime pie: bool,
|
||||||
|
) !void {
|
||||||
|
// Compile test applications
|
||||||
|
const test_path = "src/test/";
|
||||||
|
const test_prefix = prefix: {
|
||||||
|
const p1 = "test_" ++ if (link_libc) "libc_" else "nolibc_";
|
||||||
|
const p2 = p1 ++ if (pie) "pie_" else "nopie_";
|
||||||
|
break :prefix p2;
|
||||||
|
};
|
||||||
|
var test_dir = try std.fs.cwd().openDir(test_path, .{ .iterate = true });
|
||||||
|
defer test_dir.close();
|
||||||
|
var iterator = test_dir.iterate();
|
||||||
|
while (try iterator.next()) |entry| {
|
||||||
|
if (entry.kind != .file) continue;
|
||||||
|
if (!std.mem.endsWith(u8, entry.name, ".zig")) continue;
|
||||||
|
|
||||||
|
const name = try std.mem.concat(b.allocator, u8, &.{
|
||||||
|
test_prefix, entry.name[0 .. entry.name.len - 4], // strip .zig suffix
|
||||||
|
});
|
||||||
|
const test_executable = b.addExecutable(.{
|
||||||
|
.name = name,
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path(b.pathJoin(&.{ test_path, entry.name })),
|
||||||
|
.optimize = optimize,
|
||||||
|
.target = target,
|
||||||
|
.link_libc = link_libc,
|
||||||
|
.link_libcpp = false,
|
||||||
|
.pic = pie,
|
||||||
|
}),
|
||||||
|
.linkage = if (link_libc) .dynamic else .static,
|
||||||
|
.use_llvm = true,
|
||||||
|
.use_lld = true,
|
||||||
|
});
|
||||||
|
test_executable.pie = pie;
|
||||||
|
b.installArtifact(test_executable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
93
src/main.zig
93
src/main.zig
@@ -274,3 +274,96 @@ test {
|
|||||||
_ = @import("Range.zig");
|
_ = @import("Range.zig");
|
||||||
_ = @import("PatchLocationIterator.zig");
|
_ = @import("PatchLocationIterator.zig");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: make this be passed in from the build system
|
||||||
|
const bin_path = "zig-out/bin/";
|
||||||
|
fn getTestExePath(comptime name: []const u8) []const u8 {
|
||||||
|
return bin_path ++ "test_" ++ name;
|
||||||
|
}
|
||||||
|
const flicker_path = bin_path ++ "flicker";
|
||||||
|
|
||||||
|
test "nolibc_nopie_exit" {
|
||||||
|
try testHelper(&.{ flicker_path, getTestExePath("nolibc_nopie_exit") }, "");
|
||||||
|
}
|
||||||
|
test "nolibc_pie_exit" {
|
||||||
|
try testHelper(&.{ flicker_path, getTestExePath("nolibc_pie_exit") }, "");
|
||||||
|
}
|
||||||
|
// BUG: This one is flaky
|
||||||
|
// test "libc_pie_exit" {
|
||||||
|
// try testHelper(&.{ flicker_path, getTestExePath("libc_pie_exit") }, "");
|
||||||
|
// }
|
||||||
|
|
||||||
|
test "nolibc_nopie_helloWorld" {
|
||||||
|
try testHelper(&.{ flicker_path, getTestExePath("nolibc_nopie_helloWorld") }, "Hello World!\n");
|
||||||
|
}
|
||||||
|
test "nolibc_pie_helloWorld" {
|
||||||
|
try testHelper(&.{ flicker_path, getTestExePath("nolibc_pie_helloWorld") }, "Hello World!\n");
|
||||||
|
}
|
||||||
|
// BUG: This one is flaky
|
||||||
|
// test "libc_pie_helloWorld" {
|
||||||
|
// try testHelper(&.{ flicker_path, getTestExePath("libc_pie_helloWorld") }, "Hello World!\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
test "nolibc_nopie_printArgs" {
|
||||||
|
try testPrintArgs("nolibc_nopie_printArgs");
|
||||||
|
}
|
||||||
|
test "nolibc_pie_printArgs" {
|
||||||
|
try testPrintArgs("nolibc_pie_printArgs");
|
||||||
|
}
|
||||||
|
// BUG: This one is flaky
|
||||||
|
// test "libc_pie_printArgs" {
|
||||||
|
// try testPrintArgs("libc_pie_printArgs");
|
||||||
|
// }
|
||||||
|
|
||||||
|
test "nolibc_nopie_readlink" {
|
||||||
|
try testReadlink("nolibc_nopie_readlink");
|
||||||
|
}
|
||||||
|
test "nolibc_pie_readlink" {
|
||||||
|
try testReadlink("nolibc_pie_readlink");
|
||||||
|
}
|
||||||
|
// BUG: This one just outputs the path to the flicker executable and is likely also flaky
|
||||||
|
// test "libc_pie_readlink" {
|
||||||
|
// try testReadlink("libc_pie_readlink");
|
||||||
|
// }
|
||||||
|
|
||||||
|
test "echo" {
|
||||||
|
try testHelper(&.{ "echo", "Hello", "There" }, "Hello There\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testPrintArgs(comptime name: []const u8) !void {
|
||||||
|
const exe_path = getTestExePath(name);
|
||||||
|
const loader_argv: []const []const u8 = &.{ flicker_path, exe_path, "foo", "bar", "baz hi" };
|
||||||
|
const target_argv = loader_argv[1..];
|
||||||
|
const expected_stout = try mem.join(testing.allocator, " ", target_argv);
|
||||||
|
defer testing.allocator.free(expected_stout);
|
||||||
|
try testHelper(loader_argv, expected_stout);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testReadlink(comptime name: []const u8) !void {
|
||||||
|
const exe_path = getTestExePath(name);
|
||||||
|
const loader_argv: []const []const u8 = &.{ flicker_path, exe_path };
|
||||||
|
const cwd_path = try std.fs.cwd().realpathAlloc(testing.allocator, ".");
|
||||||
|
defer testing.allocator.free(cwd_path);
|
||||||
|
const expected_path = try std.fs.path.join(testing.allocator, &.{ cwd_path, exe_path });
|
||||||
|
defer testing.allocator.free(expected_path);
|
||||||
|
try testHelper(loader_argv, expected_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testHelper(
|
||||||
|
argv: []const []const u8,
|
||||||
|
expected_stdout: []const u8,
|
||||||
|
) !void {
|
||||||
|
const result = try std.process.Child.run(.{
|
||||||
|
.allocator = testing.allocator,
|
||||||
|
.argv = argv,
|
||||||
|
});
|
||||||
|
defer testing.allocator.free(result.stdout);
|
||||||
|
defer testing.allocator.free(result.stderr);
|
||||||
|
errdefer std.log.err("term: {}", .{result.term});
|
||||||
|
errdefer std.log.err("stdout: {s}", .{result.stdout});
|
||||||
|
errdefer std.log.err("stderr: {s}", .{result.stderr});
|
||||||
|
|
||||||
|
try testing.expectEqualStrings(expected_stdout, result.stdout);
|
||||||
|
try testing.expect(result.term == .Exited);
|
||||||
|
try testing.expectEqual(0, result.term.Exited);
|
||||||
|
}
|
||||||
|
|||||||
3
src/test/exit.zig
Normal file
3
src/test/exit.zig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub fn main() void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
9
src/test/helloWorld.zig
Normal file
9
src/test/helloWorld.zig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var stdout_buffer: [64]u8 = undefined;
|
||||||
|
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||||
|
const stdout = &stdout_writer.interface;
|
||||||
|
try stdout.print("Hello World!\n", .{});
|
||||||
|
try stdout.flush();
|
||||||
|
}
|
||||||
17
src/test/printArgs.zig
Normal file
17
src/test/printArgs.zig
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var stdout_buffer: [64]u8 = undefined;
|
||||||
|
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||||
|
const stdout = &stdout_writer.interface;
|
||||||
|
|
||||||
|
// It is done this way to remove the trailing space with a naive implementation.
|
||||||
|
var args = std.process.args();
|
||||||
|
if (args.next()) |arg| {
|
||||||
|
try stdout.print("{s}", .{arg});
|
||||||
|
}
|
||||||
|
while (args.next()) |arg| {
|
||||||
|
try stdout.print(" {s}", .{arg});
|
||||||
|
}
|
||||||
|
try stdout.flush();
|
||||||
|
}
|
||||||
13
src/test/readlink.zig
Normal file
13
src/test/readlink.zig
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
// We use /proc/self/exe to test if the loader interception works.
|
||||||
|
// const path = try std.posix.readlink("/proc/self/exe", &buf);
|
||||||
|
const size = std.posix.system.readlink("/proc/self/exe", &buf, buf.len);
|
||||||
|
var stdout_buffer: [64]u8 = undefined;
|
||||||
|
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||||
|
const stdout = &stdout_writer.interface;
|
||||||
|
try stdout.print("{s}", .{buf[0..@intCast(size)]});
|
||||||
|
try stdout.flush();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user