fix(browser_list): parse cmdline colapsado por espacios de Chromium
/proc/<pid>/cmdline normalmente separa argv por NUL, pero Chromium reescribe su titulo de proceso in-place colapsando la region de argv a una sola cadena separada por espacios. readProcCmdline asumia solo NUL, asi que para los masters de Chromium devolvia un unico argv[0] gigante: isChromiumExe y el prefijo --user-data-dir= fallaban y browser_list devolvia [] aunque hubiera navegadores vivos. Extrae parseCmdline (pura, testeable) con fallback a split por espacios cuando no hay NUL. Test cubre ambos formatos + regresion de deteccion de master. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -150,3 +150,48 @@ func TestMatchMaster(t *testing.T) {
|
||||
t.Errorf("unknown profile should not match")
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseCmdline cubre el parsing de /proc/<pid>/cmdline en sus dos formatos:
|
||||
// el canonico separado por NUL y el colapsado por espacios que produce Chromium
|
||||
// al reescribir su titulo de proceso in-place. El segundo caso es el que rompia
|
||||
// browser_list (los flags quedaban dentro de un unico argv[0] gigante).
|
||||
func TestParseCmdline(t *testing.T) {
|
||||
// Caso canonico: argv separado por NUL (proceso normal).
|
||||
nul := []byte("/usr/lib/chromium/chromium\x00--user-data-dir=/tmp/x\x00--remote-debugging-port=9333\x00")
|
||||
got := parseCmdline(nul)
|
||||
want := []string{"/usr/lib/chromium/chromium", "--user-data-dir=/tmp/x", "--remote-debugging-port=9333"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("NUL: got %v, want %v", got, want)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Errorf("NUL[%d]: got %q, want %q", i, got[i], want[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Caso Chromium: cmdline colapsado a una sola cadena separada por espacios.
|
||||
collapsed := []byte("/usr/lib/chromium/chromium --remote-debugging-port=9333 --user-data-dir=/tmp/browser_mcp_userdata --no-first-run https://www.alsa.es/")
|
||||
args := parseCmdline(collapsed)
|
||||
if len(args) == 1 {
|
||||
t.Fatalf("space-collapsed: parse devolvio un unico elemento gigante: %q", args[0])
|
||||
}
|
||||
if args[0] != "/usr/lib/chromium/chromium" {
|
||||
t.Errorf("space-collapsed argv[0]: got %q, want chromium binary", args[0])
|
||||
}
|
||||
|
||||
// El master debe detectarse a partir del cmdline colapsado (regresion de browser_list).
|
||||
m, ok := parseChromiumMaster(18148, args)
|
||||
if !ok {
|
||||
t.Fatalf("space-collapsed: parseChromiumMaster no detecto el master")
|
||||
}
|
||||
if m.UserDataDir != "/tmp/browser_mcp_userdata" {
|
||||
t.Errorf("space-collapsed udd: got %q, want /tmp/browser_mcp_userdata", m.UserDataDir)
|
||||
}
|
||||
if m.CDPPort != "9333" || !m.HasCDP {
|
||||
t.Errorf("space-collapsed cdp: got port=%q hasCDP=%v, want 9333/true", m.CDPPort, m.HasCDP)
|
||||
}
|
||||
|
||||
if parseCmdline([]byte("")) != nil || parseCmdline([]byte("\x00\x00")) != nil {
|
||||
t.Errorf("cmdline vacio debe devolver nil")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user