|
1 | 1 | // Parallels Npm Update Smoke tests cover parallels npm update smoke script behavior. |
2 | | -import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; |
| 2 | +import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; |
3 | 3 | import { tmpdir } from "node:os"; |
4 | 4 | import path from "node:path"; |
5 | 5 | import { afterEach, describe, expect, it } from "vitest"; |
@@ -121,6 +121,71 @@ describe("parallels npm update smoke", () => {
|
121 | 121 | expect(stopCalls).toBe(1); |
122 | 122 | }); |
123 | 123 | |
| 124 | +it("removes uploaded guest update scripts when chmod fails", () => { |
| 125 | +const root = makeTempDir(); |
| 126 | +const logPath = path.join(root, "prlctl.log"); |
| 127 | +const prlctlPath = path.join(root, "prlctl"); |
| 128 | +writeFileSync( |
| 129 | +prlctlPath, |
| 130 | +`#!/usr/bin/env bash |
| 131 | +set -euo pipefail |
| 132 | +log_path=${JSON.stringify(logPath)} |
| 133 | +printf '%s\\n' "$*" >>"$log_path" |
| 134 | +args=" $* " |
| 135 | +if [[ "$args" == *" /usr/bin/tee /tmp/openclaw-parallels-npm-update-linux-"* ]]; then |
| 136 | + cat >/dev/null |
| 137 | + exit 0 |
| 138 | +fi |
| 139 | +if [[ "$args" == *" /bin/chmod 755 /tmp/openclaw-parallels-npm-update-linux-"* ]]; then |
| 140 | + echo "chmod denied" >&2 |
| 141 | + exit 7 |
| 142 | +fi |
| 143 | +if [[ "$args" == *" /bin/rm -f /tmp/openclaw-parallels-npm-update-linux-"* ]]; then |
| 144 | + printf 'cleanup\\n' >>"$log_path" |
| 145 | + exit 0 |
| 146 | +fi |
| 147 | +exit 1 |
| 148 | +`, |
| 149 | +); |
| 150 | +chmodSync(prlctlPath, 0o755); |
| 151 | + |
| 152 | +withEnv( |
| 153 | +{ |
| 154 | +OPENAI_API_KEY: "test-key", |
| 155 | +PATH: `${root}${path.delimiter}${process.env.PATH ?? ""}`, |
| 156 | +}, |
| 157 | +() => { |
| 158 | +const smoke = new NpmUpdateSmoke({ |
| 159 | + ...TEST_AUTH, |
| 160 | +json: false, |
| 161 | +packageSpec: "openclaw@latest", |
| 162 | +platforms: new Set<Platform>(["linux"]), |
| 163 | +provider: "openai", |
| 164 | +updateTarget: "local-main", |
| 165 | +}); |
| 166 | +const writeGuestScript = Reflect.get(smoke, "writeGuestScript") as ( |
| 167 | +vm: string, |
| 168 | +script: string, |
| 169 | +prefix: string, |
| 170 | +) => string; |
| 171 | + |
| 172 | +expect(() => |
| 173 | +writeGuestScript.call( |
| 174 | +smoke, |
| 175 | +"Linux VM", |
| 176 | +"echo update", |
| 177 | +"openclaw-parallels-npm-update-linux", |
| 178 | +), |
| 179 | +).toThrow("failed to chmod guest script"); |
| 180 | +}, |
| 181 | +); |
| 182 | + |
| 183 | +const log = readFileSync(logPath, "utf8"); |
| 184 | +expect(log).toContain("/bin/chmod 755 /tmp/openclaw-parallels-npm-update-linux-"); |
| 185 | +expect(log).toContain("/bin/rm -f /tmp/openclaw-parallels-npm-update-linux-"); |
| 186 | +expect(log.match(/^cleanup$/gm)).toHaveLength(1); |
| 187 | +}); |
| 188 | + |
124 | 189 | it("has a one-command beta validation mode with fresh target coverage", () => { |
125 | 190 | const script = readFileSync(SCRIPT_PATH, "utf8"); |
126 | 191 | |
|