


























1+import { spawnSync } from "node:child_process";
2+import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
3+import path from "node:path";
4+import { afterEach, describe, expect, it } from "vitest";
5+import { cleanupTempDirs, makeTempDir } from "../helpers/temp-dir.js";
6+7+const BUILD_INFO_COMMIT_SCRIPT = path.resolve(
8+"scripts/e2e/lib/parallels-package/build-info-commit.mjs",
9+);
10+const tempDirs: string[] = [];
11+12+afterEach(() => {
13+cleanupTempDirs(tempDirs);
14+});
15+16+function shellQuote(value: string): string {
17+return `'${value.replaceAll("'", "'\\''")}'`;
18+}
19+20+function runBash(script: string, env: NodeJS.ProcessEnv = {}) {
21+return spawnSync("/bin/bash", ["-c", script], {
22+cwd: process.cwd(),
23+encoding: "utf8",
24+env: { ...process.env, ...env },
25+});
26+}
27+28+describe("Parallels lib helpers", () => {
29+it("reads build-info commit metadata from the current package cwd", () => {
30+const root = makeTempDir(tempDirs, "openclaw-parallels-build-info-");
31+32+const missingResult = spawnSync(process.execPath, [BUILD_INFO_COMMIT_SCRIPT], {
33+cwd: root,
34+encoding: "utf8",
35+env: { ...process.env },
36+});
37+expect(missingResult.status).toBe(0);
38+expect(missingResult.stdout).toBe("\n");
39+40+mkdirSync(path.join(root, "dist"));
41+writeFileSync(
42+path.join(root, "dist", "build-info.json"),
43+`${JSON.stringify({ commit: "abc123" })}\n`,
44+);
45+const result = spawnSync(process.execPath, [BUILD_INFO_COMMIT_SCRIPT], {
46+cwd: root,
47+encoding: "utf8",
48+env: { ...process.env },
49+});
50+51+expect(result.status).toBe(0);
52+expect(result.stdout).toBe("abc123\n");
53+});
54+55+it("reclaims stale package shell locks and releases current locks", () => {
56+const root = makeTempDir(tempDirs, "openclaw-parallels-package-lock-");
57+const lockDir = path.join(root, "build.lock");
58+const result = runBash(`
59+set -euo pipefail
60+source scripts/e2e/lib/parallels-package-common.sh
61+lock_dir=${shellQuote(lockDir)}
62+mkdir -p "$lock_dir"
63+printf '%s\\n' 999999999 >"$lock_dir/pid"
64+parallels_package_acquire_build_lock "$lock_dir"
65+owner="$(cat "$lock_dir/pid")"
66+parallels_package_release_build_lock "$lock_dir"
67+printf 'owner=%s exists=%s\\n' "$owner" "$([[ -e "$lock_dir" ]] && echo yes || echo no)"
68+`);
69+70+expect(result.status).toBe(0);
71+expect(result.stderr).toContain("warn: Removing stale Parallels build lock");
72+expect(result.stdout).toMatch(/^owner=\d+ exists=no\n$/u);
73+expect(result.stdout).not.toContain("owner=999999999");
74+});
75+76+it("resolves macOS desktop users through prlctl fallbacks", () => {
77+const root = makeTempDir(tempDirs, "openclaw-parallels-macos-common-");
78+const binDir = path.join(root, "bin");
79+const macHome = `${"/"}Users/alice`;
80+mkdirSync(binDir);
81+const prlctlShim = path.join(binDir, "prlctl");
82+writeFileSync(
83+prlctlShim,
84+`#!/usr/bin/env bash
85+args="$*"
86+if [[ "$args" == *"/usr/bin/stat -f %Su /dev/console"* ]]; then
87+ printf 'loginwindow\\r\\n'
88+ exit 0
89+fi
90+if [[ "$args" == *"/usr/bin/dscl . -list /Users NFSHomeDirectory"* ]]; then
91+ printf '_daemon /var/root\\r\\nShared %s\\r\\nalice %s\\r\\n' "${`${"/"}Users/Shared`}" "${macHome}"
92+ exit 0
93+fi
94+if [[ "$args" == *"-read ${macHome} NFSHomeDirectory"* ]]; then
95+ printf 'NFSHomeDirectory: %s\\r\\n' "${macHome}"
96+ exit 0
97+fi
98+exit 1
99+`,
100+);
101+chmodSync(prlctlShim, 0o755);
102+103+const result = runBash(
104+`
105+set -euo pipefail
106+source scripts/e2e/lib/parallels-macos-common.sh
107+printf 'user=%s\\n' "$(parallels_macos_resolve_desktop_user macos-vm)"
108+printf 'home=%s\\n' "$(parallels_macos_resolve_desktop_home macos-vm alice)"
109+`,
110+{ PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ""}` },
111+);
112+113+expect(result.status).toBe(0);
114+expect(result.stdout).toBe(`user=alice\nhome=${macHome}\n`);
115+});
116+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。