diff --git a/test/js/bun/test-macos-app-sandbox.test.ts b/test/js/bun/test-macos-app-sandbox.test.ts index c71e69732b..98d98974cf 100644 --- a/test/js/bun/test-macos-app-sandbox.test.ts +++ b/test/js/bun/test-macos-app-sandbox.test.ts @@ -1,33 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { copyFileSync } from "fs"; +import { copyFileSync, rmSync } from "fs"; +import { homedir } from "os"; import { bunEnv, bunExe, isMacOS, tempDir } from "harness"; import { join } from "path"; -const infoPlist = ` - - - - CFBundleExecutable - bun - CFBundleIdentifier - dev.bun.test.bun_sandboxed - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - bun_sandboxed - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - 1 - -`; - const entitlementsPlist = ` @@ -45,12 +21,39 @@ const entitlementsPlist = ` `; -async function createSandboxedApp(prefix: string) { +function makeInfoPlist(bundleId: string) { + return ` + + + + CFBundleExecutable + bun + CFBundleIdentifier + ${bundleId} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + bun_sandboxed + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + +`; +} + +async function createSandboxedApp(prefix: string, bundleId: string) { const dir = tempDir(prefix, { "entitlements.plist": entitlementsPlist, "bun_sandboxed.app": { "Contents": { - "Info.plist": infoPlist, + "Info.plist": makeInfoPlist(bundleId), "MacOS": {}, }, }, @@ -65,46 +68,60 @@ async function createSandboxedApp(prefix: string) { await using codesign = Bun.spawn({ cmd: ["/usr/bin/codesign", "--entitlements", entitlementsPath, "--force", "-s", "-", appBundlePath], env: bunEnv, - stderr: "pipe", + stdout: "pipe", + stderr: "inherit", }); expect(await codesign.exited).toBe(0); - return { dir, bunPath }; + return { dir, bunPath, bundleId, containerPath: join(homedir(), "Library", "Containers", bundleId) }; } // Modeled after Node.js's test/parallel/test-macos-app-sandbox.js describe.skipIf(!isMacOS)("macOS App Sandbox", () => { test.concurrent("bun can execute JavaScript inside the app sandbox", async () => { - const { dir, bunPath } = await createSandboxedApp("macos-sandbox-test"); + const { dir, bunPath, containerPath } = await createSandboxedApp("macos-sandbox-test", "dev.bun.test.sandbox_exec"); using _dir = dir; - await using proc = Bun.spawn({ - cmd: [bunPath, "-e", "console.log('hello sandbox')"], - env: bunEnv, - stderr: "pipe", - }); + try { + await using proc = Bun.spawn({ + cmd: [bunPath, "-e", "console.log('hello sandbox')"], + env: bunEnv, + stdout: "pipe", + stderr: "inherit", + }); - const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]); - expect(stdout.trim()).toBe("hello sandbox"); - expect(exitCode).toBe(0); + expect(stdout.trim()).toBe("hello sandbox"); + expect(exitCode).toBe(0); + } finally { + rmSync(containerPath, { recursive: true, force: true }); + } }); test.concurrent("sandboxed bun runs inside the sandbox container", async () => { - const { dir, bunPath } = await createSandboxedApp("macos-sandbox-test-container"); + const { dir, bunPath, bundleId, containerPath } = await createSandboxedApp( + "macos-sandbox-test-container", + "dev.bun.test.sandbox_container", + ); using _dir = dir; - // When running inside a macOS App Sandbox, os.homedir() should return - // the sandbox container path, not the real home directory. - await using proc = Bun.spawn({ - cmd: [bunPath, "-e", "console.log(require('os').homedir())"], - env: bunEnv, - stderr: "pipe", - }); + try { + // When running inside a macOS App Sandbox, os.homedir() should return + // the sandbox container path, not the real home directory. + await using proc = Bun.spawn({ + cmd: [bunPath, "-e", "console.log(require('os').homedir())"], + env: bunEnv, + stdout: "pipe", + stderr: "inherit", + }); - const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]); - expect(stdout.trim()).toContain("Library/Containers/dev.bun.test.bun_sandboxed"); - expect(exitCode).toBe(0); + expect(stdout.trim()).toContain(`Library/Containers/${bundleId}`); + expect(exitCode).toBe(0); + } finally { + rmSync(containerPath, { recursive: true, force: true }); + } }); });