"use strict"; // Swap priority model of chj.system-monitor: effective (kernel) vs configured (fstab pri=) priority, precedence, // and request validation before anything is sent to a server. const test = require("node:test"); const assert = require("node:assert/strict"); const { parseLinuxInspect, VirtualMemoryService } = require("../src/main/system/virtualMemoryService"); const inspect = ({ swaps, fstab = [] }) => [ "\x1eCHJ_SECTION=meta\nroot=1\nsystemd=1\nbtrfsMkswapfile=0\nos=Ubuntu 24.04\n", "\x1eCHJ_SECTION=swaps\nFilename\tType\tSize\tUsed\tPriority\n" + swaps.map((row) => row.join("\t")).join("\n") + "\n", "\x1eCHJ_SECTION=meminfo\nMemTotal: 4000000 kB\nMemAvailable: 2000000 kB\n", "\x1eCHJ_SECTION=fstab\n" + fstab.join("\n") + (fstab.length ? "\n" : ""), "\x1eCHJ_SECTION=units\n\x1eCHJ_SECTION=files\n\x1eCHJ_SECTION=locations\n\x1eCHJ_SECTION=zram\n\x1eCHJ_SECTION=end\n" ].join(""); const area = (state, name) => state.swapAreas.find((entry) => entry.path === name); test("two swaps with automatic negative priorities are shown as automatic, not as user input", () => { const state = parseLinuxInspect(inspect({ swaps: [["/swapfile-chj", "file", 1048576, 268, -2], ["/swapfile-chj2", "file", 2097152, 0, -3]], fstab: ["3|/swapfile-chj|/swapfile-chj none swap sw 0 0 # CH-J chj.system-monitor", "4|/swapfile-chj2|/swapfile-chj2 none swap sw 0 0 # CH-J chj.system-monitor"] })); const first = area(state, "/swapfile-chj"), second = area(state, "/swapfile-chj2"); assert.equal(first.effectivePriority, -2); assert.equal(first.persistentPriority, null); assert.equal(first.priorityMode, "auto"); assert.equal(first.priorityPending, false); assert.equal(first.precedence, 1); assert.equal(second.precedence, 2); assert.equal(first.persistentByChj, true); }); test("explicit 100/10 saved and active: higher priority first; saved-but-not-yet-active is flagged", () => { let state = parseLinuxInspect(inspect({ swaps: [["/swapfile-chj2", "file", 2097152, 0, 10], ["/swapfile-chj", "file", 1048576, 0, 100]], fstab: ["4|/swapfile-chj2|/swapfile-chj2 none swap sw,pri=10 0 0 # CH-J chj.system-monitor", "3|/swapfile-chj|/swapfile-chj none swap sw,pri=100 0 0 # CH-J chj.system-monitor"] })); assert.equal(area(state, "/swapfile-chj").precedence, 1); assert.equal(area(state, "/swapfile-chj2").precedence, 2); assert.equal(area(state, "/swapfile-chj").priorityMode, "custom"); assert.equal(area(state, "/swapfile-chj").priorityPending, false); state = parseLinuxInspect(inspect({ swaps: [["/swapfile-chj", "file", 1048576, 0, -2]], fstab: ["3|/swapfile-chj|/swapfile-chj none swap sw,pri=100 0 0"] })); assert.equal(area(state, "/swapfile-chj").priorityPending, true); assert.equal(area(state, "/swapfile-chj").persistentPriority, 100); }); test("equal explicit priorities share precedence; runtime-only and fstab-only areas are both listed", () => { const state = parseLinuxInspect(inspect({ swaps: [["/swap/a", "file", 1048576, 0, 5], ["/swap/b", "file", 1048576, 0, 5]], fstab: ["7|/dev/sda2|UUID=1234 none swap sw,pri=1 0 0"] })); assert.equal(area(state, "/swap/a").sharedPriority, true); assert.equal(area(state, "/swap/a").precedence, 1); assert.equal(area(state, "/swap/a").persistent, false); assert.equal(area(state, "/swap/a").priorityMode, "custom"); const partition = area(state, "/dev/sda2"); assert.equal(partition.active, false); assert.equal(partition.persistentSpec, "UUID=1234"); assert.equal(partition.persistentPriority, 1); assert.equal(partition.management, "partition"); }); test("UUID entries match the active device through the canonical identity; old line|raw format still parses", () => { let state = parseLinuxInspect(inspect({ swaps: [["/dev/sda2", "partition", 1048576, 0, -2]], fstab: ["7|/dev/sda2|UUID=1234 none swap sw,pri=40 0 0"] })); assert.equal(area(state, "/dev/sda2").persistent, true); assert.equal(area(state, "/dev/sda2").persistentPriority, 40); assert.equal(state.swapAreas.length, 1); state = parseLinuxInspect(inspect({ swaps: [["/swapfile", "file", 1048576, 0, -2]], fstab: ["3|/swapfile none swap sw 0 0"] })); assert.equal(area(state, "/swapfile").persistent, true); }); test("requests: automatic/explicit/keep priorities and apply mode are validated before the server is contacted", async () => { const calls = []; const service = new VirtualMemoryService({ sessionManager: { _requireConnected: () => ({}), _platform: async () => ({ os: "linux" }) }, privilegedExecutor: { run: async (_id, request) => { calls.push(request.args); return { stdout: "" }; }, probe: async () => ({ mode: "root" }) } }); for (const [payload, code] of [[{ priority: -3 }, "VM_SWAP_PRIORITY_INVALID"], [{ priority: 32768 }, "VM_SWAP_PRIORITY_INVALID"], [{ priority: 1.5 }, "VM_SWAP_PRIORITY_INVALID"], [{ priority: "abc" }, "VM_SWAP_PRIORITY_INVALID"], [{ priority: "keep" }, "VM_SWAP_PRIORITY_INVALID"], [{ priority: 5, apply: "soon" }, "VM_ARGUMENTS_INVALID"]]) { await assert.rejects(service.manage("s", { action: "priority", path: "/swapfile-chj", ...payload }), { code }); } await service.manage("s", { action: "priority", path: "/swapfile-chj", priority: 100, apply: "later" }); await service.manage("s", { action: "priority", path: "/swapfile-chj", priority: "auto" }); await service.manage("s", { action: "activate", path: "/swapfile-chj", priority: "keep" }); assert.deepEqual(calls.filter((args) => args[0] === "manage").map((args) => args.slice(1)), [["priority", "/swapfile-chj", "0", "100", "keep", "later"], ["priority", "/swapfile-chj", "0", "-1", "keep", "now"], ["activate", "/swapfile-chj", "0", "keep", "keep", "now"]]); });