CH-J Server Managerserver management over SSH
Menu
Published source

CH-J Server Manager

Browse directories and files for a specific application release.

Download source ZIP
CH-J Proprietary Software License 1.14

Source is provided under the CH-J Proprietary Software License 1.14. Its availability does not change the license terms or grant additional rights.

3,9 KB · 103 linesDownload file
1"use strict";
3const test = require("node:test");
4const assert = require("node:assert/strict");
5const { EventEmitter } = require("node:events");
6const fs = require("node:fs");
7const os = require("node:os");
8const path = require("node:path");
9const { PassThrough } = require("node:stream");
10const { UpdateInstallerLauncher } = require("../src/main/updates/updateInstallerLauncher");
11const posixOnly = { skip: process.platform === "win32" && "Requires a POSIX executable with Unix ownership and permissions." };
13function fixture(t) {
14 const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-linux-installer-"));
15 t.after(() => fs.rmSync(root, { recursive: true, force: true }));
16 const artifactPath = path.join(root, "verified update;not-a-command.deb");
17 fs.writeFileSync(artifactPath, "deb fixture", { mode: 0o400 });
18 return { root, artifactPath };
21function fakeChild(onStart) {
22 const child = new EventEmitter();
23 child.stdout = new PassThrough();
24 child.stderr = new PassThrough();
25 child.kill = () => true;
26 process.nextTick(() => onStart(child));
27 return child;
30test("Linux installs only the verified deb with fixed pkexec and apt-get arguments", posixOnly, async (t) => {
31 const { artifactPath } = fixture(t);
32 let invocation;
33 const launcher = new UpdateInstallerLauncher({
34 platform: "linux",
35 pkexecPath: "/usr/bin/true",
36 aptGetPath: "/usr/bin/true",
37 spawnImpl(command, args, options) {
38 invocation = { command, args, options };
39 return fakeChild((child) => child.emit("close", 0, null));
40 }
41 });
43 assert.deepEqual(await launcher.install(artifactPath), {
44 launched: true,
45 installed: true,
46 restartApplication: true
47 });
48 assert.equal(invocation.command, "/usr/bin/true");
49 assert.deepEqual(invocation.args, [
50 "/usr/bin/true",
51 "install",
52 "--reinstall",
53 "--yes",
54 artifactPath
55 ]);
56 assert.equal(invocation.options.shell, false);
57 assert.deepEqual(invocation.options.stdio, ["ignore", "pipe", "pipe"]);
58});
60test("Linux refuses relative, non-deb, missing, and symlink package paths", async (t) => {
61 const { root, artifactPath } = fixture(t);
62 const launcher = new UpdateInstallerLauncher({
63 platform: "linux",
64 pkexecPath: "/usr/bin/true",
65 aptGetPath: "/usr/bin/true",
66 spawnImpl() { throw new Error("must not spawn"); }
67 });
68 await assert.rejects(() => launcher.install("relative.deb"), { code: "UPDATE_INSTALL_UNSAFE_PATH" });
69 await assert.rejects(() => launcher.install(path.join(root, "update.exe")), { code: "UPDATE_INSTALL_UNSUPPORTED_PACKAGE" });
70 await assert.rejects(() => launcher.install(path.join(root, "missing.deb")), { code: "UPDATE_INSTALL_FILE_MISSING" });
71 const symlink = path.join(root, "linked.deb");
72 fs.symlinkSync(artifactPath, symlink);
73 await assert.rejects(() => launcher.install(symlink), { code: "UPDATE_INSTALL_UNSAFE_PATH" });
74});
76test("Linux fails closed when authorization is denied or installation fails", posixOnly, async (t) => {
77 const { artifactPath } = fixture(t);
78 for (const [exitCode, expectedCode] of [[126, "UPDATE_INSTALL_AUTHORIZATION_DENIED"], [100, "UPDATE_INSTALL_FAILED"]]) {
79 const launcher = new UpdateInstallerLauncher({
80 platform: "linux",
81 pkexecPath: "/usr/bin/true",
82 aptGetPath: "/usr/bin/true",
83 spawnImpl() { return fakeChild((child) => child.emit("close", exitCode, null)); }
84 });
85 await assert.rejects(() => launcher.install(artifactPath), { code: expectedCode });
86 }
87});
89test("macOS and Windows retain the native installer handoff", async (t) => {
90 const { artifactPath } = fixture(t);
91 let opened = null;
92 const launcher = new UpdateInstallerLauncher({
93 platform: "win32",
94 shell: { async openPath(value) { opened = value; return ""; } },
95 spawnImpl() { throw new Error("must not spawn"); }
96 });
97 assert.deepEqual(await launcher.install(artifactPath), {
98 launched: true,
99 installed: false,
100 restartApplication: false
101 });
102 assert.equal(opened, artifactPath);
103});

SHA-256: 551238267402f7179b31fdcca06399822f163e858518a208345a9523957c487e

Archive SHA-256: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0