CH-J Server Managergestione server su SSH
Menu
Sorgente pubblicata

CH-J Server Manager

Sfoglia directory e file per una specifica release di applicazioni.

Scarica sorgente ZIP
CH-J / Server Manager 377 file
core-20261019T111616Z-160a00bfcddc Aggiunto: · Costruito:
remoteSwap.test.js Aggiunto: Data non registrata 8,4 KB · 110 righe
Codice Scarica file
1"use strict";
3// Swapoff safety rule of the fixed remote swap helper, run locally with a fake /proc (no swap is touched).
4const test = require("node:test");
5const assert = require("node:assert/strict");
6const fs = require("node:fs");
7const os = require("node:os");
8const path = require("node:path");
9const { spawnSync } = require("node:child_process");
11const SCRIPT = path.join(__dirname, "../src/main/system/remoteSwap.sh");
12const MiB = 1024;
13// The helper is a POSIX shell script; Windows hosts have no /bin/sh.
14const skip = process.platform === "win32" ? "POSIX sh is not available on Windows." : false;
16function check({ totalMiB, availableMiB, areas }) {
17 const proc = fs.mkdtempSync(path.join(os.tmpdir(), "chj-swap-proc-"));
18 try {
19 fs.writeFileSync(path.join(proc, "meminfo"), `MemTotal: ${totalMiB * MiB} kB\nMemAvailable: ${availableMiB * MiB} kB\n`);
20 fs.writeFileSync(path.join(proc, "swaps"), "Filename\tType\tSize\tUsed\tPriority\n" + areas.map(([name, sizeMiB, usedMiB]) => `${name}\tfile\t${sizeMiB * MiB}\t${usedMiB * MiB}\t-2`).join("\n") + "\n");
21 const result = spawnSync("sh", [SCRIPT, "safety-check", areas[0][0]], { encoding: "utf8", env: { ...process.env, CHJ_SWAP_TEST_PROC: proc } });
22 return result.stdout.includes("safe\n") ? "safe" : (result.stdout.match(/CHJ_ERR=(\w+)/) || [])[1];
23 } finally { fs.rmSync(proc, { recursive: true, force: true }); }
26test("swapoff is refused when the used swap cannot fit into RAM minus the reserve", { skip }, () => {
27 assert.equal(check({ totalMiB: 4096, availableMiB: 1024, areas: [["/swapfile", 2048, 900]] }), "SWAPOFF_UNSAFE");
28 assert.equal(check({ totalMiB: 4096, availableMiB: 1024, areas: [["/swapfile", 2048, 400]] }), "safe");
29});
31test("free space in other active swap areas counts towards the room", { skip }, () => {
32 assert.equal(check({ totalMiB: 4096, availableMiB: 1024, areas: [["/swapfile", 2048, 900], ["/swap/b", 1024, 0]] }), "safe");
33});
35test("an unused swap area can always be deactivated, even on a small server", { skip }, () => {
36 assert.equal(check({ totalMiB: 468, availableMiB: 408, areas: [["/swapfile", 128, 0]] }), "safe");
37});
39test("the reserve never exceeds a quarter of RAM on small servers", { skip }, () => {
40 // 468 MiB RAM: reserve 117 MiB instead of 512 MiB.
41 assert.equal(check({ totalMiB: 468, availableMiB: 400, areas: [["/swapfile", 256, 200]] }), "safe");
42 assert.equal(check({ totalMiB: 468, availableMiB: 300, areas: [["/swapfile", 256, 200]] }), "SWAPOFF_UNSAFE");
43});
45test("the test-only operation is unavailable without the test /proc override", { skip }, () => {
46 const result = spawnSync("sh", [SCRIPT, "safety-check", "/swapfile"], { encoding: "utf8", env: { PATH: process.env.PATH } });
47 assert.match(result.stdout, /CHJ_ERR=ACTION_INVALID/);
48});
50// fstab priority handling of the helper on a temporary fstab copy (test-only operation; nothing on the host changes).
51function fstabRun(content, args, { swaps = "", canon = "" } = {}) {
52 const proc = fs.mkdtempSync(path.join(os.tmpdir(), "chj-swap-fstab-"));
53 try {
54 const fstab = path.join(proc, "fstab");
55 fs.writeFileSync(fstab, content); fs.writeFileSync(path.join(proc, "swaps"), "Filename\tType\tSize\tUsed\tPriority\n" + swaps); fs.writeFileSync(path.join(proc, "canon"), canon);
56 fs.writeFileSync(path.join(proc, "meminfo"), "MemTotal: 4194304 kB\nMemAvailable: 2097152 kB\n");
57 const result = spawnSync("sh", [SCRIPT, "fstab-test", ...args], { encoding: "utf8", env: { PATH: process.env.PATH, CHJ_SWAP_TEST_PROC: proc, CHJ_SWAP_TEST_FSTAB: fstab } });
58 return { out: result.stdout, error: (result.stdout.match(/CHJ_ERR=(\w+)/) || [])[1], fstab: fs.readFileSync(fstab, "utf8"), backups: fs.readdirSync(proc).filter((name) => name.startsWith("fstab.chj-backup-")).length };
59 } finally { fs.rmSync(proc, { recursive: true, force: true }); }
61const UBUNTU = "# /etc/fstab\nUUID=abc / ext4 errors=remount-ro 0 1\n/swapfile-chj none swap sw 0 0 # CH-J chj.system-monitor\n/swapfile-chj2 none swap sw 0 0 # CH-J chj.system-monitor\n";
63test("explicit priorities 100/10 update the existing entries in place, keep options, comments and order", { skip }, () => {
64 let result = fstabRun(UBUNTU, ["priority", "/swapfile-chj", "100"]);
65 assert.equal(result.error, undefined); assert.equal(result.backups, 1);
66 assert.equal(fstabRun(UBUNTU, ["priority", "/swapfile-chj", "100"]).backups, 1);
67 result = fstabRun(result.fstab, ["priority", "/swapfile-chj2", "10"]);
68 assert.equal(result.fstab, "# /etc/fstab\nUUID=abc / ext4 errors=remount-ro 0 1\n/swapfile-chj none swap sw,pri=100 0 0 # CH-J chj.system-monitor\n/swapfile-chj2 none swap sw,pri=10 0 0 # CH-J chj.system-monitor\n");
69 // Changing an existing pri= replaces it; repeating the same value creates no duplicates.
70 result = fstabRun(result.fstab, ["priority", "/swapfile-chj", "200"]); result = fstabRun(result.fstab, ["priority", "/swapfile-chj", "200"]);
71 assert.match(result.fstab, /^\/swapfile-chj none swap sw,pri=200 0 0 # CH-J chj\.system-monitor$/m); assert.equal((result.fstab.match(/swapfile-chj /g) || []).length, 1);
72 // Back to automatic removes pri= only.
73 result = fstabRun(result.fstab, ["priority", "/swapfile-chj", "-1"]);
74 assert.match(result.fstab, /^\/swapfile-chj none swap sw 0 0 # CH-J chj\.system-monitor$/m);
75});
76test("other options, foreign comments, tabs and unrelated lines survive; reversed order is matched by identity", { skip }, () => {
77 const source = "/swapfile-chj2\tnone\tswap\tdefaults,nofail,pri=3\t0\t0\n# comment line\nproc /proc proc defaults 0 0\n/swapfile-chj none swap sw,discard 0 0\n";
78 const result = fstabRun(source, ["priority", "/swapfile-chj2", "10"]);
79 assert.equal(result.fstab, "/swapfile-chj2 none swap defaults,nofail,pri=10 0 0\n# comment line\nproc /proc proc defaults 0 0\n/swapfile-chj none swap sw,discard 0 0\n");
80});
81test("UUID= partition entries are matched through their canonical device", { skip }, () => {
82 const source = "UUID=1234-ab none swap sw 0 0\n";
83 const result = fstabRun(source, ["priority", "/dev/sda2", "50"], { canon: "UUID=1234-ab|/dev/sda2\n" });
84 assert.equal(result.fstab, "UUID=1234-ab none swap sw,pri=50 0 0\n");
85});
86test("swap only active (no fstab entry) is not written by priority; persist appends once with the priority", { skip }, () => {
87 let result = fstabRun("proc /proc proc defaults 0 0\n", ["priority", "/swap/a", "5"]);
88 assert.equal(result.fstab, "proc /proc proc defaults 0 0\n"); assert.equal(result.backups, 0);
89 result = fstabRun(result.fstab, ["persist", "/swap/a", "5"]); result = fstabRun(result.fstab, ["persist", "/swap/a", "keep"]);
90 assert.equal(result.fstab, "proc /proc proc defaults 0 0\n/swap/a none swap sw,pri=5 0 0 # CH-J chj.system-monitor\n");
91 result = fstabRun(result.fstab, ["remove", "/swap/a", "keep"]); assert.equal(result.fstab, "proc /proc proc defaults 0 0\n");
92});
93test("duplicate entries for one swap area are refused instead of guessed", { skip }, () => {
94 const source = "/swapfile none swap sw 0 0\n/swapfile none swap sw,pri=4 0 0\n";
95 const result = fstabRun(source, ["priority", "/swapfile", "9"]);
96 assert.equal(result.error, "FSTAB_AMBIGUOUS"); assert.equal(result.fstab, source);
97});
98test("keep resolves fstab pri=, then explicit runtime priority, else automatic (auto negatives are never reused)", { skip }, () => {
99 assert.equal(fstabRun("/swapfile none swap sw,pri=100 0 0\n", ["resolve", "/swapfile", "keep"]).out.trim().split("\n").at(-1), "100");
100 assert.equal(fstabRun("", ["resolve", "/swapfile", "keep"], { swaps: "/swapfile\tfile\t1024\t0\t7\n" }).out.trim().split("\n").at(-1), "7");
101 assert.equal(fstabRun("", ["resolve", "/swapfile", "keep"], { swaps: "/swapfile\tfile\t1024\t0\t-3\n" }).out.trim().split("\n").at(-1), "-1");
102});
103test("a non-writable fstab is reported and left unchanged", { skip: skip || (process.getuid?.() === 0 && "root ignores permissions") }, () => {
104 const proc = fs.mkdtempSync(path.join(os.tmpdir(), "chj-swap-ro-"));
105 try {
106 const fstab = path.join(proc, "fstab"); fs.writeFileSync(fstab, UBUNTU); fs.writeFileSync(path.join(proc, "swaps"), "Filename\n"); fs.chmodSync(proc, 0o500);
107 const result = spawnSync("sh", [SCRIPT, "fstab-test", "priority", "/swapfile-chj", "100"], { encoding: "utf8", env: { PATH: process.env.PATH, CHJ_SWAP_TEST_PROC: proc, CHJ_SWAP_TEST_FSTAB: fstab } });
108 assert.match(result.stdout, /CHJ_ERR=FSTAB_(BACKUP|WRITE)_FAILED/); assert.equal(fs.readFileSync(fstab, "utf8"), UBUNTU);
109 } finally { fs.chmodSync(proc, 0o700); fs.rmSync(proc, { recursive: true, force: true }); }
110});
SHA-2565dec43574c824ead9afbc50792f8f22176a5504e137df34dc30dd258b3b4578c

CH-J Proprietary Software License 1.14 · La sorgente è fornita sotto CH-J Proprietary Software License 1.14. La sua disponibilità non modifica i termini di licenza o concede diritti aggiuntivi.

Archivio SHA-256a9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a
File