testing: move cleanup of execveZ into the test code

This commit is contained in:
Anund
2024-12-26 23:12:35 +11:00
parent 184db2654c
commit b2cb80dfbb

View File

@ -182,10 +182,9 @@ fn startPosix(self: *Command, arena: Allocator) !void {
_ = posix.execveZ(pathZ, argsZ, envp) catch null; _ = posix.execveZ(pathZ, argsZ, envp) catch null;
// If we are executing this code, the exec failed. In that scenario, // If we are executing this code, the exec failed. In that scenario,
// terminate so we don't duplicate the original process // we return a very specific error that can be detected to determine
// note: returning to test code from this point would run 2 copies of the test suite // we're in the child.
std.debug.print("failed to execveZ as child process, terminating", .{}); return error.ExecFailedInChild;
std.process.exit(1);
} }
fn startWindows(self: *Command, arena: Allocator) !void { fn startWindows(self: *Command, arena: Allocator) !void {
@ -599,7 +598,7 @@ test "Command: pre exec" {
}).do, }).do,
}; };
try cmd.start(testing.allocator); try cmd.testingStart();
try testing.expect(cmd.pid != null); try testing.expect(cmd.pid != null);
const exit = try cmd.wait(true); const exit = try cmd.wait(true);
try testing.expect(exit == .Exited); try testing.expect(exit == .Exited);
@ -635,7 +634,7 @@ test "Command: redirect stdout to file" {
.stdout = stdout, .stdout = stdout,
}; };
try cmd.start(testing.allocator); try cmd.testingStart();
try testing.expect(cmd.pid != null); try testing.expect(cmd.pid != null);
const exit = try cmd.wait(true); const exit = try cmd.wait(true);
try testing.expect(exit == .Exited); try testing.expect(exit == .Exited);
@ -670,7 +669,7 @@ test "Command: custom env vars" {
.env = &env, .env = &env,
}; };
try cmd.start(testing.allocator); try cmd.testingStart();
try testing.expect(cmd.pid != null); try testing.expect(cmd.pid != null);
const exit = try cmd.wait(true); const exit = try cmd.wait(true);
try testing.expect(exit == .Exited); try testing.expect(exit == .Exited);
@ -706,7 +705,7 @@ test "Command: custom working directory" {
.cwd = "/usr/bin", .cwd = "/usr/bin",
}; };
try cmd.start(testing.allocator); try cmd.testingStart();
try testing.expect(cmd.pid != null); try testing.expect(cmd.pid != null);
const exit = try cmd.wait(true); const exit = try cmd.wait(true);
try testing.expect(exit == .Exited); try testing.expect(exit == .Exited);
@ -724,12 +723,12 @@ test "Command: custom working directory" {
} }
} }
// Duplicating a test process via fork does unexepected things. // Test validate an execveZ failure correctly terminates when error.ExecFailedInChild is correctly handled
//
// Incorrectly handling an error.ExecFailedInChild results in a second copy of the test process running.
// Duplicating the test process leads to weird behavior
// zig build test will hang // zig build test will hang
// test binary created via -Demit-test-exe will run 2 copies of the test suite // test binary created via -Demit-test-exe will run 2 copies of the test suite
//
// This test relys on cmd.start -> posix.start terminating the child process rather
// than returning to avoid those two strange behaviours
test "Command: posix fork handles execveZ failure" { test "Command: posix fork handles execveZ failure" {
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
return error.SkipZigTest; return error.SkipZigTest;
@ -746,9 +745,22 @@ test "Command: posix fork handles execveZ failure" {
.cwd = "/bin", .cwd = "/bin",
}; };
try cmd.start(testing.allocator); try cmd.testingStart();
try testing.expect(cmd.pid != null); try testing.expect(cmd.pid != null);
const exit = try cmd.wait(true); const exit = try cmd.wait(true);
try testing.expect(exit == .Exited); try testing.expect(exit == .Exited);
try testing.expect(exit.Exited == 1); try testing.expect(exit.Exited == 1);
} }
// If cmd.start fails with error.ExecFailedInChild it's the _child_ process that is running. If it does not
// terminate in response to that error both the parent and child will continue as if they _are_ the test suite
// process.
fn testingStart(self: *Command) !void {
self.start(testing.allocator) catch |err| {
if (err == error.ExecFailedInChild) {
// I am a child process, I must not get confused and continue running the rest of the test suite.
posix.exit(1);
}
return err;
};
}