Fix tests

This commit is contained in:
2025-10-25 00:14:42 +02:00
parent 58f8861d17
commit 6a973fae2d
3 changed files with 201 additions and 143 deletions

View File

@@ -11,7 +11,8 @@ import (
) )
func TestNewInstance(t *testing.T) { func TestNewInstance(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "llama-server", Command: "llama-server",
Args: []string{}, Args: []string{},
@@ -24,13 +25,15 @@ func TestNewInstance(t *testing.T) {
Command: "vllm", Command: "vllm",
Args: []string{"serve"}, Args: []string{"serve"},
}, },
} },
Instances: config.InstancesConfig{
globalSettings := &config.InstancesConfig{
LogsDir: "/tmp/test", LogsDir: "/tmp/test",
DefaultAutoRestart: true, DefaultAutoRestart: true,
DefaultMaxRestarts: 3, DefaultMaxRestarts: 3,
DefaultRestartDelay: 5, DefaultRestartDelay: 5,
},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
options := &instance.Options{ options := &instance.Options{
@@ -46,7 +49,7 @@ func TestNewInstance(t *testing.T) {
// Mock onStatusChange function // Mock onStatusChange function
mockOnStatusChange := func(oldStatus, newStatus instance.Status) {} mockOnStatusChange := func(oldStatus, newStatus instance.Status) {}
inst := instance.New("test-instance", backendConfig, globalSettings, options, "main", mockOnStatusChange) inst := instance.New("test-instance", globalConfig, options, mockOnStatusChange)
if inst.Name != "test-instance" { if inst.Name != "test-instance" {
t.Errorf("Expected name 'test-instance', got %q", inst.Name) t.Errorf("Expected name 'test-instance', got %q", inst.Name)
@@ -89,7 +92,7 @@ func TestNewInstance(t *testing.T) {
}, },
} }
inst2 := instance.New("test-override", backendConfig, globalSettings, optionsWithOverrides, "main", mockOnStatusChange) inst2 := instance.New("test-override", globalConfig, optionsWithOverrides, mockOnStatusChange)
opts2 := inst2.GetOptions() opts2 := inst2.GetOptions()
if opts2.AutoRestart == nil || *opts2.AutoRestart { if opts2.AutoRestart == nil || *opts2.AutoRestart {
@@ -101,7 +104,8 @@ func TestNewInstance(t *testing.T) {
} }
func TestSetOptions(t *testing.T) { func TestSetOptions(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "llama-server", Command: "llama-server",
Args: []string{}, Args: []string{},
@@ -114,13 +118,15 @@ func TestSetOptions(t *testing.T) {
Command: "vllm", Command: "vllm",
Args: []string{"serve"}, Args: []string{"serve"},
}, },
} },
Instances: config.InstancesConfig{
globalSettings := &config.InstancesConfig{
LogsDir: "/tmp/test", LogsDir: "/tmp/test",
DefaultAutoRestart: true, DefaultAutoRestart: true,
DefaultMaxRestarts: 3, DefaultMaxRestarts: 3,
DefaultRestartDelay: 5, DefaultRestartDelay: 5,
},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
initialOptions := &instance.Options{ initialOptions := &instance.Options{
@@ -136,7 +142,7 @@ func TestSetOptions(t *testing.T) {
// Mock onStatusChange function // Mock onStatusChange function
mockOnStatusChange := func(oldStatus, newStatus instance.Status) {} mockOnStatusChange := func(oldStatus, newStatus instance.Status) {}
inst := instance.New("test-instance", backendConfig, globalSettings, initialOptions, "main", mockOnStatusChange) inst := instance.New("test-instance", globalConfig, initialOptions, mockOnStatusChange)
// Update options // Update options
newOptions := &instance.Options{ newOptions := &instance.Options{
@@ -166,7 +172,8 @@ func TestSetOptions(t *testing.T) {
} }
func TestGetProxy(t *testing.T) { func TestGetProxy(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "llama-server", Command: "llama-server",
Args: []string{}, Args: []string{},
@@ -179,10 +186,12 @@ func TestGetProxy(t *testing.T) {
Command: "vllm", Command: "vllm",
Args: []string{"serve"}, Args: []string{"serve"},
}, },
} },
Instances: config.InstancesConfig{
globalSettings := &config.InstancesConfig{
LogsDir: "/tmp/test", LogsDir: "/tmp/test",
},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
options := &instance.Options{ options := &instance.Options{
@@ -199,7 +208,7 @@ func TestGetProxy(t *testing.T) {
// Mock onStatusChange function // Mock onStatusChange function
mockOnStatusChange := func(oldStatus, newStatus instance.Status) {} mockOnStatusChange := func(oldStatus, newStatus instance.Status) {}
inst := instance.New("test-instance", backendConfig, globalSettings, options, "main", mockOnStatusChange) inst := instance.New("test-instance", globalConfig, options, mockOnStatusChange)
// Get proxy for the first time // Get proxy for the first time
proxy1, err := inst.GetProxy() proxy1, err := inst.GetProxy()
@@ -221,10 +230,14 @@ func TestGetProxy(t *testing.T) {
} }
func TestMarshalJSON(t *testing.T) { func TestMarshalJSON(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -235,7 +248,7 @@ func TestMarshalJSON(t *testing.T) {
}, },
} }
inst := instance.New("test-instance", backendConfig, globalSettings, options, "main", nil) inst := instance.New("test-instance", globalConfig, options, nil)
data, err := json.Marshal(inst) data, err := json.Marshal(inst)
if err != nil { if err != nil {
@@ -342,7 +355,8 @@ func TestCreateOptionsValidation(t *testing.T) {
}, },
} }
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "llama-server", Command: "llama-server",
Args: []string{}, Args: []string{},
@@ -355,10 +369,12 @@ func TestCreateOptionsValidation(t *testing.T) {
Command: "vllm", Command: "vllm",
Args: []string{"serve"}, Args: []string{"serve"},
}, },
} },
Instances: config.InstancesConfig{
globalSettings := &config.InstancesConfig{
LogsDir: "/tmp/test", LogsDir: "/tmp/test",
},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
for _, tt := range tests { for _, tt := range tests {
@@ -377,7 +393,7 @@ func TestCreateOptionsValidation(t *testing.T) {
// Mock onStatusChange function // Mock onStatusChange function
mockOnStatusChange := func(oldStatus, newStatus instance.Status) {} mockOnStatusChange := func(oldStatus, newStatus instance.Status) {}
instance := instance.New("test", backendConfig, globalSettings, options, "main", mockOnStatusChange) instance := instance.New("test", globalConfig, options, mockOnStatusChange)
opts := instance.GetOptions() opts := instance.GetOptions()
if opts.MaxRestarts == nil { if opts.MaxRestarts == nil {
@@ -396,10 +412,14 @@ func TestCreateOptionsValidation(t *testing.T) {
} }
func TestStatusChangeCallback(t *testing.T) { func TestStatusChangeCallback(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -418,7 +438,7 @@ func TestStatusChangeCallback(t *testing.T) {
callbackCalled = true callbackCalled = true
} }
inst := instance.New("test", backendConfig, globalSettings, options, "main", onStatusChange) inst := instance.New("test", globalConfig, options, onStatusChange)
inst.SetStatus(instance.Running) inst.SetStatus(instance.Running)
@@ -434,10 +454,14 @@ func TestStatusChangeCallback(t *testing.T) {
} }
func TestSetOptions_NodesPreserved(t *testing.T) { func TestSetOptions_NodesPreserved(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
tests := []struct { tests := []struct {
name string name string
@@ -477,7 +501,7 @@ func TestSetOptions_NodesPreserved(t *testing.T) {
}, },
} }
inst := instance.New("test", backendConfig, globalSettings, options, "main", nil) inst := instance.New("test", globalConfig, options, nil)
// Attempt to update nodes (should be ignored) // Attempt to update nodes (should be ignored)
updateOptions := &instance.Options{ updateOptions := &instance.Options{
@@ -512,10 +536,14 @@ func TestSetOptions_NodesPreserved(t *testing.T) {
} }
func TestProcessErrorCases(t *testing.T) { func TestProcessErrorCases(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -525,7 +553,7 @@ func TestProcessErrorCases(t *testing.T) {
}, },
} }
inst := instance.New("test", backendConfig, globalSettings, options, "main", nil) inst := instance.New("test", globalConfig, options, nil)
// Stop when not running should return error // Stop when not running should return error
err := inst.Stop() err := inst.Stop()
@@ -544,10 +572,14 @@ func TestProcessErrorCases(t *testing.T) {
} }
func TestRemoteInstanceOperations(t *testing.T) { func TestRemoteInstanceOperations(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
options := &instance.Options{ options := &instance.Options{
Nodes: map[string]struct{}{"remote-node": {}}, // Remote instance Nodes: map[string]struct{}{"remote-node": {}}, // Remote instance
BackendOptions: backends.Options{ BackendOptions: backends.Options{
@@ -558,7 +590,7 @@ func TestRemoteInstanceOperations(t *testing.T) {
}, },
} }
inst := instance.New("remote-test", backendConfig, globalSettings, options, "main", nil) inst := instance.New("remote-test", globalConfig, options, nil)
if !inst.IsRemote() { if !inst.IsRemote() {
t.Error("Expected instance to be remote") t.Error("Expected instance to be remote")
@@ -591,14 +623,18 @@ func TestRemoteInstanceOperations(t *testing.T) {
} }
func TestIdleTimeout(t *testing.T) { func TestIdleTimeout(t *testing.T) {
backendConfig := &config.BackendConfig{ globalConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{Command: "llama-server"}, LlamaCpp: config.BackendSettings{Command: "llama-server"},
},
Instances: config.InstancesConfig{LogsDir: "/tmp/test"},
Nodes: map[string]config.NodeConfig{},
LocalNode: "main",
} }
globalSettings := &config.InstancesConfig{LogsDir: "/tmp/test"}
t.Run("not running never times out", func(t *testing.T) { t.Run("not running never times out", func(t *testing.T) {
timeout := 1 timeout := 1
inst := instance.New("test", backendConfig, globalSettings, &instance.Options{ inst := instance.New("test", globalConfig, &instance.Options{
IdleTimeout: &timeout, IdleTimeout: &timeout,
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -606,7 +642,7 @@ func TestIdleTimeout(t *testing.T) {
Model: "/path/to/model.gguf", Model: "/path/to/model.gguf",
}, },
}, },
}, "main", nil) }, nil)
if inst.ShouldTimeout() { if inst.ShouldTimeout() {
t.Error("Non-running instance should never timeout") t.Error("Non-running instance should never timeout")
@@ -614,7 +650,7 @@ func TestIdleTimeout(t *testing.T) {
}) })
t.Run("no timeout configured", func(t *testing.T) { t.Run("no timeout configured", func(t *testing.T) {
inst := instance.New("test", backendConfig, globalSettings, &instance.Options{ inst := instance.New("test", globalConfig, &instance.Options{
IdleTimeout: nil, // No timeout IdleTimeout: nil, // No timeout
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -622,7 +658,7 @@ func TestIdleTimeout(t *testing.T) {
Model: "/path/to/model.gguf", Model: "/path/to/model.gguf",
}, },
}, },
}, "main", nil) }, nil)
inst.SetStatus(instance.Running) inst.SetStatus(instance.Running)
if inst.ShouldTimeout() { if inst.ShouldTimeout() {
@@ -632,15 +668,17 @@ func TestIdleTimeout(t *testing.T) {
t.Run("timeout exceeded", func(t *testing.T) { t.Run("timeout exceeded", func(t *testing.T) {
timeout := 1 // 1 minute timeout := 1 // 1 minute
inst := instance.New("test", backendConfig, globalSettings, &instance.Options{ inst := instance.New("test", globalConfig, &instance.Options{
IdleTimeout: &timeout, IdleTimeout: &timeout,
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
LlamaServerOptions: &backends.LlamaServerOptions{ LlamaServerOptions: &backends.LlamaServerOptions{
Model: "/path/to/model.gguf", Model: "/path/to/model.gguf",
Host: "localhost",
Port: 8080,
}, },
}, },
}, "main", nil) }, nil)
inst.SetStatus(instance.Running) inst.SetStatus(instance.Running)
// Use mock time provider // Use mock time provider

View File

@@ -14,11 +14,10 @@ import (
func TestManager_PersistsAndLoadsInstances(t *testing.T) { func TestManager_PersistsAndLoadsInstances(t *testing.T) {
tempDir := t.TempDir() tempDir := t.TempDir()
cfg := createPersistenceConfig(tempDir) appConfig := createTestAppConfig(tempDir)
backendConfig := createBackendConfig()
// Create instance and check file was created // Create instance and check file was created
manager1 := manager.New(backendConfig, cfg, map[string]config.NodeConfig{}, "main") manager1 := manager.New(appConfig)
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -40,7 +39,7 @@ func TestManager_PersistsAndLoadsInstances(t *testing.T) {
} }
// Load instances from disk // Load instances from disk
manager2 := manager.New(backendConfig, cfg, map[string]config.NodeConfig{}, "main") manager2 := manager.New(appConfig)
instances, err := manager2.ListInstances() instances, err := manager2.ListInstances()
if err != nil { if err != nil {
t.Fatalf("ListInstances failed: %v", err) t.Fatalf("ListInstances failed: %v", err)
@@ -55,10 +54,9 @@ func TestManager_PersistsAndLoadsInstances(t *testing.T) {
func TestDeleteInstance_RemovesPersistenceFile(t *testing.T) { func TestDeleteInstance_RemovesPersistenceFile(t *testing.T) {
tempDir := t.TempDir() tempDir := t.TempDir()
cfg := createPersistenceConfig(tempDir) appConfig := createTestAppConfig(tempDir)
backendConfig := createBackendConfig()
mgr := manager.New(backendConfig, cfg, map[string]config.NodeConfig{}, "main") mgr := manager.New(appConfig)
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{
BackendType: backends.BackendTypeLlamaCpp, BackendType: backends.BackendTypeLlamaCpp,
@@ -135,31 +133,46 @@ func TestConcurrentAccess(t *testing.T) {
} }
// Helper functions for test configuration // Helper functions for test configuration
func createBackendConfig() config.BackendConfig { func createTestAppConfig(instancesDir string) *config.AppConfig {
// Use 'sleep' as a test command instead of 'llama-server' // Use 'sleep' as a test command instead of 'llama-server'
// This allows tests to run in CI environments without requiring actual LLM binaries // This allows tests to run in CI environments without requiring actual LLM binaries
// The sleep command will be invoked with model paths and other args, which it ignores // The sleep command will be invoked with model paths and other args, which it ignores
return config.BackendConfig{ return &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "sleep", Command: "sleep",
}, },
MLX: config.BackendSettings{ MLX: config.BackendSettings{
Command: "sleep", Command: "sleep",
}, },
} },
} Instances: config.InstancesConfig{
func createPersistenceConfig(dir string) config.InstancesConfig {
return config.InstancesConfig{
PortRange: [2]int{8000, 9000}, PortRange: [2]int{8000, 9000},
InstancesDir: dir, InstancesDir: instancesDir,
LogsDir: instancesDir,
MaxInstances: 10, MaxInstances: 10,
MaxRunningInstances: 10,
DefaultAutoRestart: true,
DefaultMaxRestarts: 3,
DefaultRestartDelay: 5,
TimeoutCheckInterval: 5, TimeoutCheckInterval: 5,
},
LocalNode: "main",
Nodes: map[string]config.NodeConfig{},
} }
} }
func createTestManager() manager.InstanceManager { func createTestManager() manager.InstanceManager {
cfg := config.InstancesConfig{ appConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{
Command: "sleep",
},
MLX: config.BackendSettings{
Command: "sleep",
},
},
Instances: config.InstancesConfig{
PortRange: [2]int{8000, 9000}, PortRange: [2]int{8000, 9000},
LogsDir: "/tmp/test", LogsDir: "/tmp/test",
MaxInstances: 10, MaxInstances: 10,
@@ -168,6 +181,9 @@ func createTestManager() manager.InstanceManager {
DefaultMaxRestarts: 3, DefaultMaxRestarts: 3,
DefaultRestartDelay: 5, DefaultRestartDelay: 5,
TimeoutCheckInterval: 5, TimeoutCheckInterval: 5,
},
LocalNode: "main",
Nodes: map[string]config.NodeConfig{},
} }
return manager.New(createBackendConfig(), cfg, map[string]config.NodeConfig{}, "main") return manager.New(appConfig)
} }

View File

@@ -36,17 +36,21 @@ func TestCreateInstance_FailsWithDuplicateName(t *testing.T) {
} }
func TestCreateInstance_FailsWhenMaxInstancesReached(t *testing.T) { func TestCreateInstance_FailsWhenMaxInstancesReached(t *testing.T) {
backendConfig := config.BackendConfig{ appConfig := &config.AppConfig{
Backends: config.BackendConfig{
LlamaCpp: config.BackendSettings{ LlamaCpp: config.BackendSettings{
Command: "llama-server", Command: "llama-server",
}, },
} },
cfg := config.InstancesConfig{ Instances: config.InstancesConfig{
PortRange: [2]int{8000, 9000}, PortRange: [2]int{8000, 9000},
MaxInstances: 1, // Very low limit for testing MaxInstances: 1, // Very low limit for testing
TimeoutCheckInterval: 5, TimeoutCheckInterval: 5,
},
LocalNode: "main",
Nodes: map[string]config.NodeConfig{},
} }
limitedManager := manager.New(backendConfig, cfg, map[string]config.NodeConfig{}, "main") limitedManager := manager.New(appConfig)
options := &instance.Options{ options := &instance.Options{
BackendOptions: backends.Options{ BackendOptions: backends.Options{