| 1 | import assert from "node:assert/strict"; |
| 2 | import { mkdtempSync, mkdirSync, realpathSync, rmSync, symlinkSync } from "node:fs"; |
| 3 | import { tmpdir } from "node:os"; |
| 4 | import { join } from "node:path"; |
| 5 | import { test } from "node:test"; |
| 6 | import { claimShellInstance } from "./singleInstance.js"; |
| 7 | |
| 8 | test("single-instance lock uses the selected canonical data home before acquisition", () => { |
| 9 | const root = mkdtempSync(join(tmpdir(), "reasonix-instance-")); |
| 10 | try { |
| 11 | const profiles = new Set<string>(); |
| 12 | const host = () => { |
| 13 | let profile = ""; |
| 14 | return { |
| 15 | setPath: (_name: "userData", path: string) => { profile = path; }, |
| 16 | requestSingleInstanceLock: () => { |
| 17 | assert.notEqual(profile, "", "userData must precede the lock request"); |
| 18 | if (profiles.has(profile)) return false; |
| 19 | profiles.add(profile); |
| 20 | return true; |
| 21 | }, |
| 22 | }; |
| 23 | }; |
| 24 | assert.equal(claimShellInstance(host(), join(root, "a"), false), true); |
| 25 | assert.equal(claimShellInstance(host(), join(root, "b"), false), true, "different homes coexist"); |
| 26 | assert.equal(claimShellInstance(host(), join(root, "a"), false), false, "same home reuses its instance"); |
| 27 | const alias = join(root, "alias"); |
| 28 | symlinkSync(join(root, "a"), alias, process.platform === "win32" ? "junction" : "dir"); |
| 29 | assert.equal(claimShellInstance(host(), alias, false), false, "a symlink is the same data home"); |
| 30 | mkdirSync(join(root, "dev")); |
| 31 | let seen = ""; |
| 32 | assert.equal(claimShellInstance({ setPath: (_name, path) => { seen = path; }, requestSingleInstanceLock: () => { throw new Error("dev must not lock"); } }, join(root, "dev"), true), true); |
| 33 | assert.equal(seen, realpathSync.native(join(root, "dev", "desktop-shell"))); |
| 34 | } finally { |
| 35 | rmSync(root, { recursive: true, force: true }); |
| 36 | } |
| 37 | }); |
| 38 |