Core features: - Microkernel architecture with Actor model - Session management with JSONL persistence - Tool system (5 built-in tools) - Skill system with SKILL.md parsing - Sandbox security execution - Ollama integration with gemma4:e4b - Prompt-based tool calling (compatible with native function calling) - REPL interface 11 packages, all tests passing
222 lines
6.5 KiB
Go
222 lines
6.5 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDefaultConfig(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
if cfg == nil {
|
|
t.Fatal("DefaultConfig() returned nil")
|
|
}
|
|
|
|
// Check Ollama defaults
|
|
if cfg.Ollama.BaseURL != "http://localhost:11434" {
|
|
t.Errorf("expected default Ollama BaseURL 'http://localhost:11434', got %q", cfg.Ollama.BaseURL)
|
|
}
|
|
if cfg.Ollama.Model != "gemma4:e4b" {
|
|
t.Errorf("expected default Ollama Model 'gemma4:e4b', got %q", cfg.Ollama.Model)
|
|
}
|
|
if cfg.Ollama.Timeout != 120*time.Second {
|
|
t.Errorf("expected default Ollama Timeout 120s, got %v", cfg.Ollama.Timeout)
|
|
}
|
|
|
|
// Check Sandbox defaults
|
|
if cfg.Sandbox.Timeout != 30*time.Second {
|
|
t.Errorf("expected default Sandbox Timeout 30s, got %v", cfg.Sandbox.Timeout)
|
|
}
|
|
if cfg.Sandbox.MaxMemory != 512*1024*1024 {
|
|
t.Errorf("expected default Sandbox MaxMemory 512MB, got %d", cfg.Sandbox.MaxMemory)
|
|
}
|
|
if cfg.Sandbox.WorkingDir != "/tmp/orca/sandbox" {
|
|
t.Errorf("expected default Sandbox WorkingDir '/tmp/orca/sandbox', got %q", cfg.Sandbox.WorkingDir)
|
|
}
|
|
|
|
// Check Session defaults
|
|
if cfg.Session.MaxHistory != 100 {
|
|
t.Errorf("expected default Session MaxHistory 100, got %d", cfg.Session.MaxHistory)
|
|
}
|
|
if cfg.Session.StorageDir == "" {
|
|
t.Error("expected non-empty Session StorageDir")
|
|
}
|
|
}
|
|
|
|
func TestDefaultConfigStorageDir(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
home, _ := os.UserHomeDir()
|
|
expected := home + "/.orca/sessions"
|
|
if cfg.Session.StorageDir != expected {
|
|
t.Errorf("expected StorageDir %q, got %q", expected, cfg.Session.StorageDir)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigFromEnv(t *testing.T) {
|
|
// Set environment variables
|
|
os.Setenv("ORCA_OLLAMA_BASE_URL", "http://custom:11434")
|
|
os.Setenv("ORCA_OLLAMA_MODEL", "codellama")
|
|
os.Setenv("ORCA_OLLAMA_TIMEOUT", "60s")
|
|
os.Setenv("ORCA_SANDBOX_TIMEOUT", "120s")
|
|
os.Setenv("ORCA_SANDBOX_MAX_MEMORY", "1073741824")
|
|
os.Setenv("ORCA_SANDBOX_WORKING_DIR", "/custom/sandbox")
|
|
os.Setenv("ORCA_SESSION_STORAGE_DIR", "/custom/sessions")
|
|
os.Setenv("ORCA_SESSION_MAX_HISTORY", "200")
|
|
|
|
defer func() {
|
|
os.Unsetenv("ORCA_OLLAMA_BASE_URL")
|
|
os.Unsetenv("ORCA_OLLAMA_MODEL")
|
|
os.Unsetenv("ORCA_OLLAMA_TIMEOUT")
|
|
os.Unsetenv("ORCA_SANDBOX_TIMEOUT")
|
|
os.Unsetenv("ORCA_SANDBOX_MAX_MEMORY")
|
|
os.Unsetenv("ORCA_SANDBOX_WORKING_DIR")
|
|
os.Unsetenv("ORCA_SESSION_STORAGE_DIR")
|
|
os.Unsetenv("ORCA_SESSION_MAX_HISTORY")
|
|
}()
|
|
|
|
cfg := LoadConfigFromEnv()
|
|
|
|
if cfg.Ollama.BaseURL != "http://custom:11434" {
|
|
t.Errorf("expected Ollama BaseURL 'http://custom:11434', got %q", cfg.Ollama.BaseURL)
|
|
}
|
|
if cfg.Ollama.Model != "codellama" {
|
|
t.Errorf("expected Ollama Model 'codellama', got %q", cfg.Ollama.Model)
|
|
}
|
|
if cfg.Ollama.Timeout != 60*time.Second {
|
|
t.Errorf("expected Ollama Timeout 60s, got %v", cfg.Ollama.Timeout)
|
|
}
|
|
if cfg.Sandbox.Timeout != 120*time.Second {
|
|
t.Errorf("expected Sandbox Timeout 120s, got %v", cfg.Sandbox.Timeout)
|
|
}
|
|
if cfg.Sandbox.MaxMemory != 1073741824 {
|
|
t.Errorf("expected Sandbox MaxMemory 1073741824, got %d", cfg.Sandbox.MaxMemory)
|
|
}
|
|
if cfg.Sandbox.WorkingDir != "/custom/sandbox" {
|
|
t.Errorf("expected Sandbox WorkingDir '/custom/sandbox', got %q", cfg.Sandbox.WorkingDir)
|
|
}
|
|
if cfg.Session.StorageDir != "/custom/sessions" {
|
|
t.Errorf("expected Session StorageDir '/custom/sessions', got %q", cfg.Session.StorageDir)
|
|
}
|
|
if cfg.Session.MaxHistory != 200 {
|
|
t.Errorf("expected Session MaxHistory 200, got %d", cfg.Session.MaxHistory)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigFromEnvPartial(t *testing.T) {
|
|
os.Setenv("ORCA_OLLAMA_MODEL", "mistral")
|
|
defer os.Unsetenv("ORCA_OLLAMA_MODEL")
|
|
|
|
cfg := LoadConfigFromEnv()
|
|
|
|
// Should use env override
|
|
if cfg.Ollama.Model != "mistral" {
|
|
t.Errorf("expected Model 'mistral', got %q", cfg.Ollama.Model)
|
|
}
|
|
// Should keep defaults for unset values
|
|
if cfg.Ollama.BaseURL != "http://localhost:11434" {
|
|
t.Errorf("expected default BaseURL, got %q", cfg.Ollama.BaseURL)
|
|
}
|
|
}
|
|
|
|
func TestConfigIsValid(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
if err := cfg.IsValid(); err != nil {
|
|
t.Errorf("default config should be valid: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidBaseURL(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Ollama.BaseURL = ""
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for empty BaseURL")
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidModel(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Ollama.Model = ""
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for empty Model")
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidOllamaTimeout(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Ollama.Timeout = 0
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for zero Ollama Timeout")
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidSandboxTimeout(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Sandbox.Timeout = -1
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for negative Sandbox Timeout")
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidMaxMemory(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Sandbox.MaxMemory = 0
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for zero MaxMemory")
|
|
}
|
|
}
|
|
|
|
func TestConfigInvalidMaxHistory(t *testing.T) {
|
|
cfg := DefaultConfig()
|
|
cfg.Session.MaxHistory = 0
|
|
if err := cfg.IsValid(); err == nil {
|
|
t.Error("expected error for zero MaxHistory")
|
|
}
|
|
}
|
|
|
|
func TestConfigError(t *testing.T) {
|
|
err := errConfig("test error")
|
|
if err.Error() != "config: test error" {
|
|
t.Errorf("unexpected error message: %s", err.Error())
|
|
}
|
|
|
|
ce, ok := err.(*ConfigError)
|
|
if !ok {
|
|
t.Fatal("expected ConfigError type")
|
|
}
|
|
if ce.Message != "test error" {
|
|
t.Errorf("expected Message 'test error', got %q", ce.Message)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigFromEnvInvalidTimeout(t *testing.T) {
|
|
os.Setenv("ORCA_OLLAMA_TIMEOUT", "not-a-duration")
|
|
defer os.Unsetenv("ORCA_OLLAMA_TIMEOUT")
|
|
|
|
cfg := LoadConfigFromEnv()
|
|
// Should keep default when env var is unparseable
|
|
if cfg.Ollama.Timeout != 120*time.Second {
|
|
t.Errorf("expected default 120s when env is invalid, got %v", cfg.Ollama.Timeout)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigFromEnvInvalidMaxMemory(t *testing.T) {
|
|
os.Setenv("ORCA_SANDBOX_MAX_MEMORY", "not-a-number")
|
|
defer os.Unsetenv("ORCA_SANDBOX_MAX_MEMORY")
|
|
|
|
cfg := LoadConfigFromEnv()
|
|
// Should keep default when env var is unparseable
|
|
if cfg.Sandbox.MaxMemory != 512*1024*1024 {
|
|
t.Errorf("expected default MaxMemory when env is invalid, got %d", cfg.Sandbox.MaxMemory)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigFromEnvInvalidMaxHistory(t *testing.T) {
|
|
os.Setenv("ORCA_SESSION_MAX_HISTORY", "not-a-number")
|
|
defer os.Unsetenv("ORCA_SESSION_MAX_HISTORY")
|
|
|
|
cfg := LoadConfigFromEnv()
|
|
if cfg.Session.MaxHistory != 100 {
|
|
t.Errorf("expected default MaxHistory when env is invalid, got %d", cfg.Session.MaxHistory)
|
|
}
|
|
}
|