Skip to content

Commit e9e0f39

Browse files
committed
Add readonly Playground mount integration test
1 parent 0416e08 commit e9e0f39

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"test:runtime-sources-materialization": "tsx tests/runtime-sources-materialization.test.ts",
9393
"test:runtime-sources-playground-integration": "tsx tests/runtime-sources-playground-integration.test.ts",
9494
"test:playground-readonly-mounts": "tsx tests/playground-readonly-mounts.test.ts",
95+
"test:playground-readonly-mounts-integration": "tsx tests/playground-readonly-mounts-integration.test.ts",
9596
"test:browser-task-builder": "tsx tests/browser-task-builder.test.ts",
9697
"test:browser-runtime-generic-invoker": "tsx tests/browser-runtime-generic-invoker.test.ts",
9798
"test:browser-runtime-file-ops": "tsx tests/browser-runtime-file-ops.test.ts",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import assert from "node:assert/strict"
2+
import { execFile } from "node:child_process"
3+
import { createHash } from "node:crypto"
4+
import { mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises"
5+
import { tmpdir } from "node:os"
6+
import { join } from "node:path"
7+
import { promisify } from "node:util"
8+
9+
const execFileAsync = promisify(execFile)
10+
const root = await mkdtemp(join(tmpdir(), "wp-codebox-readonly-mounts-integration-"))
11+
const readonlySource = join(root, "readonly.bin")
12+
const readwriteSource = join(root, "readwrite.bin")
13+
const recipePath = join(root, "recipe.json")
14+
const artifactsPath = join(root, "artifacts")
15+
const readonlyBytes = Buffer.from([0, 255, 1, 2, 3, 127, 128])
16+
const overwrittenBytes = Buffer.from([128, 127, 3, 2, 1, 255, 0])
17+
const stagingDirectoriesBefore = await readonlyStagingDirectories()
18+
19+
try {
20+
await writeFile(readonlySource, readonlyBytes)
21+
await writeFile(readwriteSource, readonlyBytes)
22+
await writeFile(recipePath, `${JSON.stringify({
23+
schema: "wp-codebox/workspace-recipe/v1",
24+
runtime: { backend: "wordpress-playground", wp: "6.5", blueprint: { steps: [] } },
25+
inputs: {
26+
mounts: [
27+
{ source: readonlySource, target: "/wordpress/readonly.bin", mode: "readonly" },
28+
{ source: readwriteSource, target: "/wordpress/readwrite.bin", mode: "readwrite" },
29+
],
30+
},
31+
workflow: {
32+
steps: [{
33+
command: "wordpress.run-php",
34+
args: [`code=$contents = base64_decode('${overwrittenBytes.toString("base64")}'); file_put_contents('/wordpress/readonly.bin', $contents); file_put_contents('/wordpress/readwrite.bin', $contents);`],
35+
}],
36+
},
37+
})}\n`)
38+
39+
const result = await execFileAsync(process.execPath, ["packages/cli/dist/index.js", "recipe-run", "--recipe", recipePath, "--artifacts", artifactsPath, "--json"], {
40+
cwd: process.cwd(),
41+
timeout: 300_000,
42+
maxBuffer: 2 * 1024 * 1024,
43+
})
44+
const output = JSON.parse(result.stdout)
45+
assert.equal(output.success, true, JSON.stringify(output))
46+
assert.equal(sha256(await readFile(readonlySource)), sha256(readonlyBytes), "readonly host bytes must survive an actual Playground PHP overwrite")
47+
assert.deepEqual(await readFile(readwriteSource), overwrittenBytes, "readwrite host bytes must reflect an actual Playground PHP overwrite")
48+
assert.deepEqual(await readonlyStagingDirectories(), stagingDirectoriesBefore, "recipe-run cleanup must remove readonly mount staging")
49+
} catch (error) {
50+
const message = error instanceof Error ? error.message : String(error)
51+
if (/fetch failed|Could not resolve host|Connection timed out|network is unreachable/i.test(message)) {
52+
console.log(`playground readonly mount integration skipped: WordPress runtime source was unreachable (${message})`)
53+
} else {
54+
throw error
55+
}
56+
} finally {
57+
await rm(root, { recursive: true, force: true })
58+
}
59+
60+
function sha256(bytes: Buffer): string {
61+
return createHash("sha256").update(bytes).digest("hex")
62+
}
63+
64+
async function readonlyStagingDirectories(): Promise<string[]> {
65+
return (await readdir(tmpdir())).filter((entry) => entry.startsWith("wp-codebox-readonly-mounts-")).sort()
66+
}
67+
68+
console.log("playground readonly mount integration ok")

0 commit comments

Comments
 (0)