Files
vmux/proc_test.go
Pierre Martin 81ee7dc49d test(01-01): add failing tests for proc scanning and path encoding
- TestFindClaudeProcesses with fake /proc (2 claude + 1 bash)
- TestFindClaudeProcesses_PermissionDenied (silent skip)
- TestFindClaudeProcesses_EmptyProc (empty slice)
- TestEncodePath and TestEncodePath_DotDir

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 13:24:59 +01:00

135 lines
3.2 KiB
Go

package main
import (
"fmt"
"os"
"path/filepath"
"testing"
)
type fakeProcEntry struct {
cmdline string // raw content with \x00 separators
cwd string // symlink target
}
// createFakeProc builds a temporary /proc-like directory structure.
func createFakeProc(t *testing.T, entries map[int]fakeProcEntry) string {
t.Helper()
dir := t.TempDir()
for pid, entry := range entries {
pidDir := filepath.Join(dir, fmt.Sprintf("%d", pid))
if err := os.MkdirAll(pidDir, 0o755); err != nil {
t.Fatal(err)
}
// Write cmdline file
if err := os.WriteFile(filepath.Join(pidDir, "cmdline"), []byte(entry.cmdline), 0o644); err != nil {
t.Fatal(err)
}
// Create cwd symlink
if err := os.Symlink(entry.cwd, filepath.Join(pidDir, "cwd")); err != nil {
t.Fatal(err)
}
}
return dir
}
func TestFindClaudeProcesses(t *testing.T) {
fakeProc := createFakeProc(t, map[int]fakeProcEntry{
100: {cmdline: "claude\x00-c\x00", cwd: "/home/user/project-a"},
200: {cmdline: "claude\x00", cwd: "/home/user/project-b"},
300: {cmdline: "bash\x00-l\x00", cwd: "/home/user"},
})
procs, err := FindClaudeProcesses(fakeProc)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(procs) != 2 {
t.Fatalf("expected 2 claude processes, got %d", len(procs))
}
// Build a map by PID for order-independent assertions
byPID := make(map[int]Process)
for _, p := range procs {
byPID[p.PID] = p
}
p100, ok := byPID[100]
if !ok {
t.Fatal("expected process with PID 100")
}
if p100.Cwd != "/home/user/project-a" {
t.Errorf("PID 100 cwd = %q, want %q", p100.Cwd, "/home/user/project-a")
}
if len(p100.Cmd) != 2 || p100.Cmd[0] != "claude" || p100.Cmd[1] != "-c" {
t.Errorf("PID 100 cmd = %v, want [claude -c]", p100.Cmd)
}
p200, ok := byPID[200]
if !ok {
t.Fatal("expected process with PID 200")
}
if p200.Cwd != "/home/user/project-b" {
t.Errorf("PID 200 cwd = %q, want %q", p200.Cwd, "/home/user/project-b")
}
if _, ok := byPID[300]; ok {
t.Error("bash process (PID 300) should not be in results")
}
}
func TestFindClaudeProcesses_PermissionDenied(t *testing.T) {
dir := t.TempDir()
// Create a PID directory with unreadable cmdline
pidDir := filepath.Join(dir, "999")
if err := os.MkdirAll(pidDir, 0o755); err != nil {
t.Fatal(err)
}
cmdlinePath := filepath.Join(pidDir, "cmdline")
if err := os.WriteFile(cmdlinePath, []byte("claude\x00"), 0o000); err != nil {
t.Fatal(err)
}
procs, err := FindClaudeProcesses(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(procs) != 0 {
t.Errorf("expected 0 processes (permission denied), got %d", len(procs))
}
}
func TestFindClaudeProcesses_EmptyProc(t *testing.T) {
dir := t.TempDir()
procs, err := FindClaudeProcesses(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(procs) != 0 {
t.Errorf("expected 0 processes, got %d", len(procs))
}
}
func TestEncodePath(t *testing.T) {
got := EncodePath("/home/pierre/Code/vibe/vmux")
want := "-home-pierre-Code-vibe-vmux"
if got != want {
t.Errorf("EncodePath = %q, want %q", got, want)
}
}
func TestEncodePath_DotDir(t *testing.T) {
got := EncodePath("/home/pierre/.config/app")
want := "-home-pierre--config-app"
if got != want {
t.Errorf("EncodePath = %q, want %q", got, want)
}
}