package config import ( "os" "path/filepath" "testing" ) func TestConfig_SetHost(t *testing.T) { cfg := &Config{} hostConfig := HostConfig{ Hostname: "codeberg.org", Token: "test-token", User: "testuser", } cfg.SetHost("codeberg.org", hostConfig) if cfg.Hosts == nil { t.Fatal("Hosts map should not be nil") } if len(cfg.Hosts) != 1 { t.Errorf("Expected 1 host, got %d", len(cfg.Hosts)) } host, ok := cfg.Hosts["codeberg.org"] if !ok { t.Fatal("Host codeberg.org not found") } if host.Hostname != "codeberg.org" { t.Errorf("Expected hostname 'codeberg.org', got '%s'", host.Hostname) } if host.Token != "test-token" { t.Errorf("Expected token 'test-token', got '%s'", host.Token) } } func TestConfig_GetHost(t *testing.T) { cfg := &Config{ Hosts: map[string]HostConfig{ "codeberg.org": { Hostname: "codeberg.org", Token: "test-token", }, }, } host, err := cfg.GetHost("codeberg.org", "") if err != nil { t.Fatalf("Unexpected error: %v", err) } if host.Hostname != "codeberg.org" { t.Errorf("Expected hostname 'codeberg.org', got '%s'", host.Hostname) } _, err = cfg.GetHost("nonexistent.org", "") if err == nil { t.Error("Expected error for nonexistent host") } } func TestGetConfigDir(t *testing.T) { dir, err := GetConfigDir() if err != nil { t.Fatalf("Unexpected error: %v", err) } if dir == "" { t.Error("Config directory should not be empty") } } func TestGetConfigDir_XDG(t *testing.T) { t.Setenv("XDG_CONFIG_HOME", "/custom/config") dir, err := GetConfigDir() if err != nil { t.Fatalf("Unexpected error: %v", err) } expected := "/custom/config/fgj" if dir != expected { t.Errorf("Expected %q, got %q", expected, dir) } } func TestGetConfigPath(t *testing.T) { path, err := GetConfigPath() if err != nil { t.Fatalf("Unexpected error: %v", err) } if path == "" { t.Error("Config path should not be empty") } } func TestConfig_SaveAndLoad(t *testing.T) { // Create a temp directory for testing tempDir := t.TempDir() tempFile := filepath.Join(tempDir, "config.yaml") // Create a config with test data cfg := &Config{ Hosts: map[string]HostConfig{ "codeberg.org": { Hostname: "codeberg.org", Token: "test-token-123", User: "testuser", GitProtocol: "ssh", }, "github.com": { Hostname: "github.com", Token: "github-token-456", User: "githubuser", GitProtocol: "https", }, }, } // Test Save err := cfg.SaveToPath(tempFile) if err != nil { t.Fatalf("Failed to save config: %v", err) } // Verify file exists if _, err := os.Stat(tempFile); os.IsNotExist(err) { t.Fatal("Config file was not created") } // Test Load loadedCfg, err := LoadFromPath(tempFile) if err != nil { t.Fatalf("Failed to load config: %v", err) } // Verify loaded config matches saved config if len(loadedCfg.Hosts) != 2 { t.Errorf("Expected 2 hosts, got %d", len(loadedCfg.Hosts)) } // Check codeberg.org host codebergHost, ok := loadedCfg.Hosts["codeberg.org"] if !ok { t.Fatal("codeberg.org host not found in loaded config") } if codebergHost.Token != "test-token-123" { t.Errorf("Expected token 'test-token-123', got '%s'", codebergHost.Token) } if codebergHost.User != "testuser" { t.Errorf("Expected user 'testuser', got '%s'", codebergHost.User) } if codebergHost.GitProtocol != "ssh" { t.Errorf("Expected git_protocol 'ssh', got '%s'", codebergHost.GitProtocol) } // Check github.com host githubHost, ok := loadedCfg.Hosts["github.com"] if !ok { t.Fatal("github.com host not found in loaded config") } if githubHost.Token != "github-token-456" { t.Errorf("Expected token 'github-token-456', got '%s'", githubHost.Token) } } func TestConfig_LoadNonexistentFile(t *testing.T) { tempDir := t.TempDir() tempFile := filepath.Join(tempDir, "nonexistent.yaml") // Test Load with nonexistent file cfg, err := LoadFromPath(tempFile) if err != nil { t.Fatalf("Load should not error on nonexistent file: %v", err) } // Should return empty config if cfg == nil { t.Fatal("Config should not be nil") } if cfg.Hosts == nil { t.Fatal("Hosts map should be initialized") } if len(cfg.Hosts) != 0 { t.Errorf("Expected empty hosts map, got %d entries", len(cfg.Hosts)) } } func TestConfig_LoadInvalidYAML(t *testing.T) { tempDir := t.TempDir() tempFile := filepath.Join(tempDir, "invalid.yaml") // Write invalid YAML err := os.WriteFile(tempFile, []byte("invalid: yaml: content: [[["), 0600) if err != nil { t.Fatalf("Failed to write invalid YAML: %v", err) } // Test Load with invalid YAML _, err = LoadFromPath(tempFile) if err == nil { t.Error("Expected error when loading invalid YAML") } } func TestConfig_SaveCreatesDirectory(t *testing.T) { tempDir := t.TempDir() tempFile := filepath.Join(tempDir, "subdir", "config.yaml") cfg := &Config{ Hosts: map[string]HostConfig{ "test.org": { Hostname: "test.org", Token: "token", }, }, } // Save should create the directory err := cfg.SaveToPath(tempFile) if err != nil { t.Fatalf("Failed to save config: %v", err) } // Verify directory was created subdir := filepath.Dir(tempFile) if _, err := os.Stat(subdir); os.IsNotExist(err) { t.Error("Save() should have created the directory") } // Verify file exists if _, err := os.Stat(tempFile); os.IsNotExist(err) { t.Error("Config file was not created") } } func TestConfig_SetHost_NilMap(t *testing.T) { cfg := &Config{ Hosts: nil, } hostConfig := HostConfig{ Hostname: "test.org", Token: "test-token", } // Should not panic even with nil map cfg.SetHost("test.org", hostConfig) if cfg.Hosts == nil { t.Fatal("Hosts map should be initialized") } if len(cfg.Hosts) != 1 { t.Errorf("Expected 1 host, got %d", len(cfg.Hosts)) } } func TestConfig_GetHost_EmptyString(t *testing.T) { cfg := &Config{ Hosts: map[string]HostConfig{ "codeberg.org": { Hostname: "codeberg.org", Token: "test-token", }, }, } // Empty hostname should default to codeberg.org host, err := cfg.GetHost("", "") if err != nil { t.Fatalf("Unexpected error: %v", err) } if host.Hostname != "codeberg.org" { t.Errorf("Expected default hostname 'codeberg.org', got '%s'", host.Hostname) } } func TestConfig_GetHost_WhitespaceString(t *testing.T) { cfg := &Config{ Hosts: map[string]HostConfig{ "codeberg.org": { Hostname: "codeberg.org", Token: "test-token", }, }, } // Whitespace-only hostname should default to codeberg.org host, err := cfg.GetHost(" ", "") if err == nil { t.Logf("Got host: %+v (this may be expected behavior)", host) } else { t.Logf("Got error: %v (this may be expected behavior)", err) } } func TestConfig_SetHost_EmptyToken(t *testing.T) { cfg := &Config{} hostConfig := HostConfig{ Hostname: "codeberg.org", Token: "", // Empty token User: "testuser", } cfg.SetHost("codeberg.org", hostConfig) host, err := cfg.GetHost("codeberg.org", "") if err != nil { t.Fatalf("Unexpected error: %v", err) } if host.Token != "" { t.Errorf("Expected empty token, got '%s'", host.Token) } } func TestConfig_SetHost_OverwriteExisting(t *testing.T) { cfg := &Config{ Hosts: map[string]HostConfig{ "codeberg.org": { Hostname: "codeberg.org", Token: "old-token", User: "olduser", }, }, } // Overwrite with new config newConfig := HostConfig{ Hostname: "codeberg.org", Token: "new-token", User: "newuser", } cfg.SetHost("codeberg.org", newConfig) host, err := cfg.GetHost("codeberg.org", "") if err != nil { t.Fatalf("Unexpected error: %v", err) } if host.Token != "new-token" { t.Errorf("Expected token 'new-token', got '%s'", host.Token) } if host.User != "newuser" { t.Errorf("Expected user 'newuser', got '%s'", host.User) } } func TestConfig_MultipleHosts(t *testing.T) { cfg := &Config{} hosts := []struct { hostname string token string user string }{ {"codeberg.org", "token1", "user1"}, {"github.com", "token2", "user2"}, {"gitlab.com", "token3", "user3"}, } // Add multiple hosts for _, h := range hosts { cfg.SetHost(h.hostname, HostConfig{ Hostname: h.hostname, Token: h.token, User: h.user, }) } // Verify all hosts are stored if len(cfg.Hosts) != 3 { t.Errorf("Expected 3 hosts, got %d", len(cfg.Hosts)) } // Verify each host can be retrieved correctly for _, h := range hosts { host, err := cfg.GetHost(h.hostname, "") if err != nil { t.Errorf("Failed to get host %s: %v", h.hostname, err) continue } if host.Token != h.token { t.Errorf("Host %s: expected token '%s', got '%s'", h.hostname, h.token, host.Token) } if host.User != h.user { t.Errorf("Host %s: expected user '%s', got '%s'", h.hostname, h.user, host.User) } } } func TestConfig_GitProtocol(t *testing.T) { cfg := &Config{} // Test SSH protocol cfg.SetHost("test-ssh.org", HostConfig{ Hostname: "test-ssh.org", Token: "token", GitProtocol: "ssh", }) // Test HTTPS protocol cfg.SetHost("test-https.org", HostConfig{ Hostname: "test-https.org", Token: "token", GitProtocol: "https", }) // Verify protocols are stored correctly sshHost, _ := cfg.GetHost("test-ssh.org", "") if sshHost.GitProtocol != "ssh" { t.Errorf("Expected git_protocol 'ssh', got '%s'", sshHost.GitProtocol) } httpsHost, _ := cfg.GetHost("test-https.org", "") if httpsHost.GitProtocol != "https" { t.Errorf("Expected git_protocol 'https', got '%s'", httpsHost.GitProtocol) } }