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>
This commit is contained in:
134
proc_test.go
Normal file
134
proc_test.go
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user