Update test-macos-app-sandbox.test.ts

This commit is contained in:
Jarred Sumner
2026-02-15 00:49:20 -08:00
parent e74a65ee22
commit f8efc63e2e

View File

@@ -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 = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>bun</string>
<key>CFBundleIdentifier</key>
<string>dev.bun.test.bun_sandboxed</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>bun_sandboxed</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>`;
const entitlementsPlist = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
@@ -45,12 +21,39 @@ const entitlementsPlist = `<?xml version="1.0" encoding="UTF-8"?>
</dict>
</plist>`;
async function createSandboxedApp(prefix: string) {
function makeInfoPlist(bundleId: string) {
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>bun</string>
<key>CFBundleIdentifier</key>
<string>${bundleId}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>bun_sandboxed</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>`;
}
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 });
}
});
});