diff --git a/tests/executor.test.ts b/tests/executor.test.ts index af83c9d..ce0fd5e 100644 --- a/tests/executor.test.ts +++ b/tests/executor.test.ts @@ -49,6 +49,23 @@ async function eventually(done: () => boolean, ms = 30_000): Promise { while (Date.now() < deadline && !done()) await Bun.sleep(250); } +/** + * Empty a workspace root the way its files were made: from inside a container. + * + * The sandbox runs as root, so on Linux everything it wrote into the bind mount + * is root-owned and the test process cannot remove it. (On macOS the daemon's + * VM maps it back to the calling user, which is why a plain rm looks fine + * there.) Clearing the contents as root leaves an empty directory that belongs + * to whoever made it. + */ +async function clearAsRoot(root: string): Promise { + await Bun.spawn( + ["docker", "run", "--rm", "-v", `${root}:/x`, "alpine:3.20", "sh", "-c", "rm -rf /x/* /x/.??*"], + { stdout: "ignore", stderr: "ignore" }, + ).exited; + rmSync(root, { recursive: true, force: true }); +} + test("createExecutor returns null when the sandbox is disabled", () => { expect( createExecutor({ @@ -553,7 +570,7 @@ liveTest( expect(existsSync(join(root, session))).toBe(false); } finally { e.disposeSession(session); - rmSync(root, { recursive: true, force: true }); + await clearAsRoot(root); } }, 180_000, @@ -582,7 +599,7 @@ liveTest( expect(existsSync(join(root, live))).toBe(true); } finally { e.disposeSession(live); - rmSync(root, { recursive: true, force: true }); + await clearAsRoot(root); } }, 180_000,