yao/sandbox/config_test.go
Max b40cea6887 Enhance Sandbox Configuration for CI and Testing
- Updated CI workflows to set the YAO_SANDBOX_CONTAINER_USER environment variable, ensuring proper user permissions during sandbox tests.
- Modified the Config struct to include ContainerUser, allowing for user specification in container execution.
- Improved test setup in config_test.go to clear conflicting environment variables, enhancing test reliability.
- Refactored manager_test.go to utilize the new getContainerUser function for consistent user handling across tests.
2026-01-29 20:13:40 +08:00

234 lines
6.5 KiB
Go

package sandbox
import (
"os"
"testing"
"time"
)
func TestDefaultConfig(t *testing.T) {
cfg := DefaultConfig()
if cfg.Image != "yaoapp/sandbox-claude:latest" {
t.Errorf("expected default image 'yaoapp/sandbox-claude:latest', got '%s'", cfg.Image)
}
if cfg.MaxContainers != 100 {
t.Errorf("expected MaxContainers 100, got %d", cfg.MaxContainers)
}
if cfg.IdleTimeout != 30*time.Minute {
t.Errorf("expected IdleTimeout 30m, got %v", cfg.IdleTimeout)
}
if cfg.MaxMemory != "2g" {
t.Errorf("expected MaxMemory '2g', got '%s'", cfg.MaxMemory)
}
if cfg.MaxCPU != 1.0 {
t.Errorf("expected MaxCPU 1.0, got %f", cfg.MaxCPU)
}
}
func TestConfigInit(t *testing.T) {
// Clear any existing environment variables that might interfere
os.Unsetenv("YAO_SANDBOX_WORKSPACE")
os.Unsetenv("YAO_SANDBOX_IPC")
// Test with dataRoot
cfg := &Config{}
cfg.Init("/tmp/yao-test")
if cfg.WorkspaceRoot != "/tmp/yao-test/sandbox/workspace" {
t.Errorf("expected WorkspaceRoot '/tmp/yao-test/sandbox/workspace', got '%s'", cfg.WorkspaceRoot)
}
if cfg.IPCDir != "/tmp/yao-test/sandbox/ipc" {
t.Errorf("expected IPCDir '/tmp/yao-test/sandbox/ipc', got '%s'", cfg.IPCDir)
}
}
func TestConfigInitWithEnv(t *testing.T) {
// Set environment variables
os.Setenv("YAO_SANDBOX_IMAGE", "test/image:v1")
os.Setenv("YAO_SANDBOX_MAX", "50")
os.Setenv("YAO_SANDBOX_IDLE_TIMEOUT", "15m")
os.Setenv("YAO_SANDBOX_MEMORY", "4g")
os.Setenv("YAO_SANDBOX_CPU", "2.5")
defer func() {
os.Unsetenv("YAO_SANDBOX_IMAGE")
os.Unsetenv("YAO_SANDBOX_MAX")
os.Unsetenv("YAO_SANDBOX_IDLE_TIMEOUT")
os.Unsetenv("YAO_SANDBOX_MEMORY")
os.Unsetenv("YAO_SANDBOX_CPU")
}()
cfg := &Config{}
cfg.Init("/tmp/yao-test")
if cfg.Image != "test/image:v1" {
t.Errorf("expected Image 'test/image:v1', got '%s'", cfg.Image)
}
if cfg.MaxContainers != 50 {
t.Errorf("expected MaxContainers 50, got %d", cfg.MaxContainers)
}
if cfg.IdleTimeout != 15*time.Minute {
t.Errorf("expected IdleTimeout 15m, got %v", cfg.IdleTimeout)
}
if cfg.MaxMemory != "4g" {
t.Errorf("expected MaxMemory '4g', got '%s'", cfg.MaxMemory)
}
if cfg.MaxCPU != 2.5 {
t.Errorf("expected MaxCPU 2.5, got %f", cfg.MaxCPU)
}
}
func TestConfigInitWithWorkspaceEnv(t *testing.T) {
// Test YAO_SANDBOX_WORKSPACE env var
os.Setenv("YAO_SANDBOX_WORKSPACE", "/custom/workspace")
os.Setenv("YAO_SANDBOX_IPC", "/custom/ipc")
defer func() {
os.Unsetenv("YAO_SANDBOX_WORKSPACE")
os.Unsetenv("YAO_SANDBOX_IPC")
}()
cfg := &Config{}
cfg.Init("/tmp/yao-test")
if cfg.WorkspaceRoot != "/custom/workspace" {
t.Errorf("expected WorkspaceRoot '/custom/workspace', got '%s'", cfg.WorkspaceRoot)
}
if cfg.IPCDir != "/custom/ipc" {
t.Errorf("expected IPCDir '/custom/ipc', got '%s'", cfg.IPCDir)
}
}
func TestConfigInitWithPresetValues(t *testing.T) {
// Test that preset values are not overwritten by defaults
cfg := &Config{
Image: "preset/image:v2",
MaxContainers: 200,
IdleTimeout: 1 * time.Hour,
MaxMemory: "8g",
MaxCPU: 4.0,
WorkspaceRoot: "/preset/workspace",
IPCDir: "/preset/ipc",
}
cfg.Init("/tmp/yao-test")
if cfg.Image != "preset/image:v2" {
t.Errorf("expected Image 'preset/image:v2', got '%s'", cfg.Image)
}
if cfg.MaxContainers != 200 {
t.Errorf("expected MaxContainers 200, got %d", cfg.MaxContainers)
}
if cfg.IdleTimeout != 1*time.Hour {
t.Errorf("expected IdleTimeout 1h, got %v", cfg.IdleTimeout)
}
if cfg.MaxMemory != "8g" {
t.Errorf("expected MaxMemory '8g', got '%s'", cfg.MaxMemory)
}
if cfg.MaxCPU != 4.0 {
t.Errorf("expected MaxCPU 4.0, got %f", cfg.MaxCPU)
}
if cfg.WorkspaceRoot != "/preset/workspace" {
t.Errorf("expected WorkspaceRoot '/preset/workspace', got '%s'", cfg.WorkspaceRoot)
}
if cfg.IPCDir != "/preset/ipc" {
t.Errorf("expected IPCDir '/preset/ipc', got '%s'", cfg.IPCDir)
}
}
func TestConfigInitInvalidEnvValues(t *testing.T) {
// Test with invalid environment values
os.Setenv("YAO_SANDBOX_MAX", "invalid")
os.Setenv("YAO_SANDBOX_IDLE_TIMEOUT", "not-a-duration")
os.Setenv("YAO_SANDBOX_CPU", "not-a-float")
defer func() {
os.Unsetenv("YAO_SANDBOX_MAX")
os.Unsetenv("YAO_SANDBOX_IDLE_TIMEOUT")
os.Unsetenv("YAO_SANDBOX_CPU")
}()
cfg := &Config{}
cfg.Init("/tmp/yao-test")
// Invalid env values should fall back to defaults
if cfg.MaxContainers != 100 {
t.Errorf("expected MaxContainers 100 (default), got %d", cfg.MaxContainers)
}
if cfg.IdleTimeout != 30*time.Minute {
t.Errorf("expected IdleTimeout 30m (default), got %v", cfg.IdleTimeout)
}
if cfg.MaxCPU != 1.0 {
t.Errorf("expected MaxCPU 1.0 (default), got %f", cfg.MaxCPU)
}
}
func TestConfigInitNegativeValues(t *testing.T) {
// Test with negative/zero values in env
os.Setenv("YAO_SANDBOX_MAX", "-5")
os.Setenv("YAO_SANDBOX_CPU", "-1.0")
defer func() {
os.Unsetenv("YAO_SANDBOX_MAX")
os.Unsetenv("YAO_SANDBOX_CPU")
}()
cfg := &Config{}
cfg.Init("/tmp/yao-test")
// Negative values should fall back to defaults
if cfg.MaxContainers != 100 {
t.Errorf("expected MaxContainers 100 (default), got %d", cfg.MaxContainers)
}
if cfg.MaxCPU != 1.0 {
t.Errorf("expected MaxCPU 1.0 (default), got %f", cfg.MaxCPU)
}
}
func TestConfigInitZeroMax(t *testing.T) {
// Test with zero max containers
os.Setenv("YAO_SANDBOX_MAX", "0")
defer os.Unsetenv("YAO_SANDBOX_MAX")
cfg := &Config{}
cfg.Init("/tmp/yao-test")
// Zero is rejected by v > 0 check, should use default
if cfg.MaxContainers != 100 {
t.Errorf("expected MaxContainers 100 (default), got %d", cfg.MaxContainers)
}
}
func TestContainerName(t *testing.T) {
tests := []struct {
userID string
chatID string
expected string
}{
{"user1", "chat1", "yao-sandbox-user1-chat1"},
{"u123", "c456", "yao-sandbox-u123-c456"},
{"test-user", "test-chat", "yao-sandbox-test-user-test-chat"},
{"", "", "yao-sandbox--"},
{"user_with_underscore", "chat-with-dash", "yao-sandbox-user_with_underscore-chat-with-dash"},
{"UPPERCASE", "lowercase", "yao-sandbox-UPPERCASE-lowercase"},
}
for _, tt := range tests {
result := containerName(tt.userID, tt.chatID)
if result != tt.expected {
t.Errorf("containerName(%s, %s) = %s, want %s", tt.userID, tt.chatID, result, tt.expected)
}
}
}
func TestConfigEnvPriority(t *testing.T) {
// Env vars should override preset config values
os.Setenv("YAO_SANDBOX_IMAGE", "env/override:latest")
defer os.Unsetenv("YAO_SANDBOX_IMAGE")
cfg := &Config{
Image: "preset/image:v1",
}
cfg.Init("/tmp/yao-test")
// Env should win
if cfg.Image != "env/override:latest" {
t.Errorf("expected Image 'env/override:latest' (from env), got '%s'", cfg.Image)
}
}