1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
import { test, before, after, describe } from "node:test";
import assert from "node:assert/strict";
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { homedir, tmpdir } from "node:os";
import { join } from "node:path";
import {
parseUserDataDirFlag,
rankBrowserCandidate,
resolveBrowserExecutable,
spawnableExePath,
stripDeletedSuffix,
} from "../../src/profile/browser-process";
describe("browser-process parsing and candidate ranking", () => {
test("B1: bare value parsed", () => {
assert.equal(parseUserDataDirFlag("/opt/google/chrome/chrome --user-data-dir=/tmp/x --foo"), "/tmp/x");
});
test("B1: double-quoted value with spaces parsed", () => {
assert.equal(
parseUserDataDirFlag('chrome.exe --user-data-dir="C:\\Users\\Some Name\\Data" --bar'),
"C:\\Users\\Some Name\\Data",
);
});
test("B1: single-quoted value parsed", () => {
assert.equal(parseUserDataDirFlag("chrome --user-data-dir='/home/u/my dir'"), "/home/u/my dir");
});
test("B1: absent flag → undefined", () => {
assert.equal(parseUserDataDirFlag("/opt/google/chrome/chrome"), undefined);
});
test("B1: empty value → undefined", () => {
assert.equal(parseUserDataDirFlag("chrome --user-data-dir="), undefined);
});
test("B2: exact user-data-dir match outranks a flagless process", () => {
const target = "/tmp/pi-e2e-abc";
const match = rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome", explicitUserDataDir: target }, target);
const noFlag = rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }, target);
assert.ok(match > noFlag);
});
test("B2: a DIFFERENT explicit user-data-dir ranks below a flagless process", () => {
const target = "/tmp/pi-e2e-abc";
const other = rankBrowserCandidate(
{ exePath: "/opt/google/chrome/chrome", explicitUserDataDir: "/tmp/somewhere-else" },
target,
);
const noFlag = rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }, target);
assert.ok(other < noFlag);
});
test("B2: a different explicit dir is disqualified outright", () => {
const target = "/tmp/pi-e2e-abc";
const other = rankBrowserCandidate(
{ exePath: "/opt/google/chrome/chrome", explicitUserDataDir: "/tmp/somewhere-else" },
target,
);
assert.equal(other, 0);
});
test("B3: Brave wins for a Brave user-data-dir", () => {
const braveDir = join(homedir(), ".config/BraveSoftware/Brave-Browser");
const brave = rankBrowserCandidate({ exePath: "/usr/bin/brave-browser" }, braveDir);
const chrome = rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }, braveDir);
assert.ok(brave > chrome);
});
test("B3: Chrome wins for a Chrome user-data-dir", () => {
const chromeDir = join(homedir(), ".config/google-chrome");
assert.ok(
rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }, chromeDir) >
rankBrowserCandidate({ exePath: "/usr/bin/brave-browser" }, chromeDir),
);
});
test("B3: Chromium is not mistaken for Chrome", () => {
const chromiumDir = join(homedir(), ".config/chromium");
assert.ok(
rankBrowserCandidate({ exePath: "/usr/bin/chromium" }, chromiumDir) >
rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }, chromiumDir),
);
});
test("B4: without a target dir, candidates rank equally", () => {
assert.equal(
rankBrowserCandidate({ exePath: "/usr/bin/brave-browser" }),
rankBrowserCandidate({ exePath: "/opt/google/chrome/chrome" }),
);
});
test("B5 win: case and separator differences still match", { skip: process.platform !== "win32" }, () => {
assert.equal(
rankBrowserCandidate(
{
exePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
explicitUserDataDir: "C:\\Users\\U\\Data",
},
"c:/users/u/data",
),
4,
);
});
test("B6: marker stripped from a replaced binary's path", () => {
assert.equal(stripDeletedSuffix("/opt/google/chrome/chrome (deleted)"), "/opt/google/chrome/chrome");
});
test("B6: unmarked path left alone", () => {
assert.equal(stripDeletedSuffix("/opt/google/chrome/chrome"), undefined);
});
test("B6: marker alone is not a path", () => {
assert.equal(stripDeletedSuffix(" (deleted)"), undefined);
});
describe("B7", () => {
let root: string;
let real: string;
let literal: string;
before(() => {
root = mkdtempSync(join(tmpdir(), "pi-exe-"));
real = join(root, "chrome");
writeFileSync(real, "#!/bin/sh\n");
chmodSync(real, 0o755);
});
after(() => {
rmSync(root, { recursive: true, force: true });
});
test("B7: an existing path is returned unchanged", async () => {
assert.equal(await spawnableExePath(real), real);
});
test("B7: a replaced binary resolves to the live install path", async () => {
assert.equal(await spawnableExePath(`${real} (deleted)`), real);
});
test("B7: a missing path yields undefined", async () => {
assert.equal(await spawnableExePath(join(root, "absent")), undefined);
});
test("B7: an empty path yields undefined", async () => {
assert.equal(await spawnableExePath(""), undefined);
});
test("B7: resolveBrowserExecutable repairs a replaced-binary path", async () => {
assert.equal(await resolveBrowserExecutable({ running: true, exePath: `${real} (deleted)` }), real);
});
test(
"B7: an unspawnable path is not passed on as usable",
{ skip: process.platform === "win32" },
async () => {
assert.equal(await resolveBrowserExecutable({ running: true, exePath: join(root, "absent") }), undefined);
},
);
// A binary genuinely named "… (deleted)" must win over the stripped form; created last so the checks above see only the ordinary case.
test("B7: a real file named '… (deleted)' is preferred over stripping", async () => {
literal = join(root, "chrome (deleted)");
writeFileSync(literal, "#!/bin/sh\n");
chmodSync(literal, 0o755);
assert.equal(await spawnableExePath(literal), literal);
});
});
});
|