package config import ( "os" "testing" "time" ) func TestDefaultConfig(t *testing.T) { cfg := DefaultConfig() if cfg == nil { t.Fatal("Expected DefaultConfig to return non-nil config") } // Test default values if cfg.Agent.ID == "" { t.Error("Expected Agent.ID to be set in default config") } if cfg.P2P.ListenAddress == "" { t.Error("Expected P2P.ListenAddress to be set in default config") } if cfg.DHT.BootstrapPeers == nil { t.Error("Expected DHT.BootstrapPeers to be initialized") } if cfg.Security.Encryption.Enabled != true { t.Error("Expected encryption to be enabled by default") } } func TestLoadConfig(t *testing.T) { // Test loading config with empty path (should return default) cfg, err := LoadConfig("") if err != nil { t.Fatalf("Failed to load default config: %v", err) } if cfg == nil { t.Fatal("Expected LoadConfig to return non-nil config") } // Verify it's the default config if cfg.Agent.ID == "" { t.Error("Expected Agent.ID to be set") } } func TestConfig_Validate(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ ID: "test-agent", Role: "test-role", }, P2P: P2PConfig{ ListenAddress: "/ip4/0.0.0.0/tcp/9000", Port: 9000, }, DHT: DHTConfig{ Enabled: true, BootstrapPeers: []string{}, }, Security: SecurityConfig{ Encryption: EncryptionConfig{ Enabled: true, Algorithm: "age", }, }, } err := cfg.Validate() if err != nil { t.Errorf("Expected valid config to pass validation, got error: %v", err) } } func TestConfig_ValidateInvalidAgent(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ ID: "", // Invalid - empty ID Role: "test-role", }, P2P: P2PConfig{ ListenAddress: "/ip4/0.0.0.0/tcp/9000", Port: 9000, }, DHT: DHTConfig{ Enabled: true, }, Security: SecurityConfig{ Encryption: EncryptionConfig{ Enabled: true, Algorithm: "age", }, }, } err := cfg.Validate() if err == nil { t.Error("Expected validation to fail with empty Agent.ID") } } func TestConfig_ValidateInvalidP2P(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ ID: "test-agent", Role: "test-role", }, P2P: P2PConfig{ ListenAddress: "", // Invalid - empty address Port: 9000, }, DHT: DHTConfig{ Enabled: true, }, Security: SecurityConfig{ Encryption: EncryptionConfig{ Enabled: true, Algorithm: "age", }, }, } err := cfg.Validate() if err == nil { t.Error("Expected validation to fail with empty P2P.ListenAddress") } } func TestConfig_ValidateInvalidSecurity(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ ID: "test-agent", Role: "test-role", }, P2P: P2PConfig{ ListenAddress: "/ip4/0.0.0.0/tcp/9000", Port: 9000, }, DHT: DHTConfig{ Enabled: true, }, Security: SecurityConfig{ Encryption: EncryptionConfig{ Enabled: true, Algorithm: "invalid", // Invalid algorithm }, }, } err := cfg.Validate() if err == nil { t.Error("Expected validation to fail with invalid encryption algorithm") } } func TestConfig_GetNodeID(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ ID: "test-node-123", }, } nodeID := cfg.GetNodeID() if nodeID != "test-node-123" { t.Errorf("Expected GetNodeID to return 'test-node-123', got %s", nodeID) } } func TestConfig_GetRole(t *testing.T) { cfg := &Config{ Agent: AgentConfig{ Role: "backend_developer", }, } role := cfg.GetRole() if role != "backend_developer" { t.Errorf("Expected GetRole to return 'backend_developer', got %s", role) } } func TestConfig_IsEncryptionEnabled(t *testing.T) { cfg := &Config{ Security: SecurityConfig{ Encryption: EncryptionConfig{ Enabled: true, }, }, } if !cfg.IsEncryptionEnabled() { t.Error("Expected IsEncryptionEnabled to return true") } cfg.Security.Encryption.Enabled = false if cfg.IsEncryptionEnabled() { t.Error("Expected IsEncryptionEnabled to return false") } } func TestConfig_GetListenAddress(t *testing.T) { cfg := &Config{ P2P: P2PConfig{ ListenAddress: "/ip4/127.0.0.1/tcp/8080", }, } addr := cfg.GetListenAddress() if addr != "/ip4/127.0.0.1/tcp/8080" { t.Errorf("Expected GetListenAddress to return '/ip4/127.0.0.1/tcp/8080', got %s", addr) } } func TestConfig_GetBootstrapPeers(t *testing.T) { bootstrapPeers := []string{ "/ip4/127.0.0.1/tcp/9000/p2p/12D3KooWExample1", "/ip4/127.0.0.1/tcp/9001/p2p/12D3KooWExample2", } cfg := &Config{ DHT: DHTConfig{ BootstrapPeers: bootstrapPeers, }, } peers := cfg.GetBootstrapPeers() if len(peers) != 2 { t.Errorf("Expected 2 bootstrap peers, got %d", len(peers)) } for i, peer := range peers { if peer != bootstrapPeers[i] { t.Errorf("Expected bootstrap peer %d to be %s, got %s", i, bootstrapPeers[i], peer) } } } func TestConfigWithEnvironmentOverrides(t *testing.T) { // Set environment variables os.Setenv("CHORUS_AGENT_ID", "env-test-agent") os.Setenv("CHORUS_P2P_PORT", "9999") os.Setenv("CHORUS_ENCRYPTION_ENABLED", "false") defer func() { os.Unsetenv("CHORUS_AGENT_ID") os.Unsetenv("CHORUS_P2P_PORT") os.Unsetenv("CHORUS_ENCRYPTION_ENABLED") }() cfg := DefaultConfig() // Apply environment overrides err := cfg.ApplyEnvironmentOverrides() if err != nil { t.Fatalf("Failed to apply environment overrides: %v", err) } // Verify overrides were applied if cfg.Agent.ID != "env-test-agent" { t.Errorf("Expected Agent.ID to be 'env-test-agent', got %s", cfg.Agent.ID) } if cfg.P2P.Port != 9999 { t.Errorf("Expected P2P.Port to be 9999, got %d", cfg.P2P.Port) } if cfg.Security.Encryption.Enabled != false { t.Errorf("Expected Encryption.Enabled to be false, got %t", cfg.Security.Encryption.Enabled) } } func TestConfigTimeouts(t *testing.T) { cfg := DefaultConfig() // Test that timeout values are reasonable if cfg.P2P.ConnectionTimeout == 0 { t.Error("Expected P2P.ConnectionTimeout to be set") } if cfg.P2P.ConnectionTimeout > 60*time.Second { t.Error("Expected P2P.ConnectionTimeout to be reasonable (< 60s)") } if cfg.DHT.QueryTimeout == 0 { t.Error("Expected DHT.QueryTimeout to be set") } } func TestConfigCopy(t *testing.T) { original := DefaultConfig() original.Agent.ID = "original-id" // Create a copy copy := *original // Modify the copy copy.Agent.ID = "copy-id" // Verify original is unchanged if original.Agent.ID != "original-id" { t.Error("Expected original config to be unchanged") } if copy.Agent.ID != "copy-id" { t.Error("Expected copy config to be modified") } } func TestConfigMerge(t *testing.T) { base := &Config{ Agent: AgentConfig{ ID: "base-id", Role: "base-role", }, P2P: P2PConfig{ Port: 8000, }, } override := &Config{ Agent: AgentConfig{ ID: "override-id", // Should override // Role not set - should keep base value }, P2P: P2PConfig{ Port: 9000, // Should override }, } // Test merge functionality if it exists if merger, ok := interface{}(base).(interface{ Merge(*Config) }); ok { merger.Merge(override) if base.Agent.ID != "override-id" { t.Errorf("Expected Agent.ID to be overridden to 'override-id', got %s", base.Agent.ID) } if base.Agent.Role != "base-role" { t.Errorf("Expected Agent.Role to remain 'base-role', got %s", base.Agent.Role) } if base.P2P.Port != 9000 { t.Errorf("Expected P2P.Port to be overridden to 9000, got %d", base.P2P.Port) } } }