Skip to main content
Glama
process_verification_test.go7.75 kB
package discovery import ( "os" "testing" "time" ) func TestIsProcessRunning(t *testing.T) { tempDir := t.TempDir() discovery := &Discovery{ instancesDir: tempDir, instances: make(map[string]*Instance), } // Test with current process (should be running) currentPID := os.Getpid() if !discovery.isProcessRunning(currentPID) { t.Errorf("Current process %d should be running", currentPID) } // Test with invalid PID (should not be running) if discovery.isProcessRunning(-1) { t.Error("Invalid PID -1 should not be running") } if discovery.isProcessRunning(0) { t.Error("PID 0 should not be running") } // Test with very high PID (very unlikely to exist on most systems) if discovery.isProcessRunning(999998) { t.Log("PID 999998 appears to be running (this is unusual but not necessarily an error)") } } func TestStaleInstanceCleanupWithProcessVerification(t *testing.T) { tempDir := t.TempDir() instancesDir := tempDir + "/instances" discovery, err := New(instancesDir) if err != nil { t.Fatalf("Failed to create discovery: %v", err) } defer discovery.Stop() // Register an instance with a non-existent PID deadInstance := &Instance{ ID: "dead-process", Name: "Dead Process", Directory: "/test", Port: 7777, StartedAt: time.Now(), LastPing: time.Now(), // Recent ping, but process is dead ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: 999999, // Very unlikely to exist Executable: "brum", }, } err = RegisterInstance(instancesDir, deadInstance) if err != nil { t.Fatalf("Failed to register dead instance: %v", err) } // Register an instance with the current process PID (alive) aliveInstance := &Instance{ ID: "alive-process", Name: "Alive Process", Directory: "/test", Port: 7778, StartedAt: time.Now(), LastPing: time.Now(), ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: os.Getpid(), // Current process Executable: "brum", }, } err = RegisterInstance(instancesDir, aliveInstance) if err != nil { t.Fatalf("Failed to register alive instance: %v", err) } // Initial scan to load instances discovery.Start() time.Sleep(100 * time.Millisecond) // Verify both instances are loaded instances := discovery.GetInstances() if len(instances) != 2 { t.Errorf("Expected 2 instances before cleanup, got %d", len(instances)) } // Run cleanup - should remove dead process but keep alive process err = discovery.CleanupStaleInstances() if err != nil { t.Errorf("CleanupStaleInstances should not return error: %v", err) } // Verify dead instance was removed but alive instance remains instances = discovery.GetInstances() if len(instances) != 1 { t.Errorf("Expected 1 instance after cleanup, got %d", len(instances)) } if _, exists := instances["dead-process"]; exists { t.Error("Dead process instance should have been removed") } if _, exists := instances["alive-process"]; !exists { t.Error("Alive process instance should still exist") } } func TestStaleInstanceCleanupWithTimeBasedStale(t *testing.T) { tempDir := t.TempDir() instancesDir := tempDir + "/instances" discovery, err := New(instancesDir) if err != nil { t.Fatalf("Failed to create discovery: %v", err) } defer discovery.Stop() // Register an instance with old ping time but valid PID staleInstance := &Instance{ ID: "stale-time", Name: "Stale Time", Directory: "/test", Port: 7777, StartedAt: time.Now(), LastPing: time.Now().Add(-StaleInstanceTimeout - time.Minute), // Very old ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: os.Getpid(), // Current process (alive) Executable: "brum", }, } err = RegisterInstance(instancesDir, staleInstance) if err != nil { t.Fatalf("Failed to register stale instance: %v", err) } // Register an instance with recent ping time and valid PID freshInstance := &Instance{ ID: "fresh-time", Name: "Fresh Time", Directory: "/test", Port: 7778, StartedAt: time.Now(), LastPing: time.Now(), // Recent ping ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: os.Getpid(), // Current process (alive) Executable: "brum", }, } err = RegisterInstance(instancesDir, freshInstance) if err != nil { t.Fatalf("Failed to register fresh instance: %v", err) } // Initial scan to load instances discovery.Start() time.Sleep(100 * time.Millisecond) // Verify both instances are loaded instances := discovery.GetInstances() if len(instances) != 2 { t.Errorf("Expected 2 instances before cleanup, got %d", len(instances)) } // Run cleanup - should remove stale instance but keep fresh instance err = discovery.CleanupStaleInstances() if err != nil { t.Errorf("CleanupStaleInstances should not return error: %v", err) } // Verify stale instance was removed but fresh instance remains instances = discovery.GetInstances() if len(instances) != 1 { t.Errorf("Expected 1 instance after cleanup, got %d", len(instances)) } if _, exists := instances["stale-time"]; exists { t.Error("Stale time instance should have been removed") } if _, exists := instances["fresh-time"]; !exists { t.Error("Fresh time instance should still exist") } } func TestStaleInstanceCleanupBothConditions(t *testing.T) { tempDir := t.TempDir() instancesDir := tempDir + "/instances" discovery, err := New(instancesDir) if err != nil { t.Fatalf("Failed to create discovery: %v", err) } defer discovery.Stop() // Register an instance that meets both stale conditions (old ping + dead process) doubleStaleInstance := &Instance{ ID: "double-stale", Name: "Double Stale", Directory: "/test", Port: 7777, StartedAt: time.Now(), LastPing: time.Now().Add(-StaleInstanceTimeout - time.Minute), // Very old ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: 999999, // Very unlikely to exist Executable: "brum", }, } err = RegisterInstance(instancesDir, doubleStaleInstance) if err != nil { t.Fatalf("Failed to register double stale instance: %v", err) } // Register a healthy instance healthyInstance := &Instance{ ID: "healthy", Name: "Healthy", Directory: "/test", Port: 7778, StartedAt: time.Now(), LastPing: time.Now(), // Recent ping ProcessInfo: struct { PID int `json:"pid"` Executable string `json:"executable"` }{ PID: os.Getpid(), // Current process (alive) Executable: "brum", }, } err = RegisterInstance(instancesDir, healthyInstance) if err != nil { t.Fatalf("Failed to register healthy instance: %v", err) } // Initial scan to load instances discovery.Start() time.Sleep(100 * time.Millisecond) // Verify both instances are loaded instances := discovery.GetInstances() if len(instances) != 2 { t.Errorf("Expected 2 instances before cleanup, got %d", len(instances)) } // Run cleanup err = discovery.CleanupStaleInstances() if err != nil { t.Errorf("CleanupStaleInstances should not return error: %v", err) } // Verify only healthy instance remains instances = discovery.GetInstances() if len(instances) != 1 { t.Errorf("Expected 1 instance after cleanup, got %d", len(instances)) } if _, exists := instances["double-stale"]; exists { t.Error("Double stale instance should have been removed") } if _, exists := instances["healthy"]; !exists { t.Error("Healthy instance should still exist") } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server