package storage import ( "encoding/xml" "strings" "testing" ) func TestFolderID_Deterministic(t *testing.T) { a := FolderID("team-alpha", "fp1") b := FolderID("team-alpha", "fp1") if a != b { t.Errorf("FolderID not deterministic: %q vs %q", a, b) } } func TestFolderID_DifferentNamespaces(t *testing.T) { a := FolderID("team-alpha", "fp1") b := FolderID("team-beta", "fp1") if a == b { t.Errorf("different namespaces produced same folder ID: %q", a) } } func TestFolderID_DifferentMasterKeys(t *testing.T) { a := FolderID("team-alpha", "fp1") b := FolderID("team-alpha", "fp2") if a == b { t.Errorf("different master keys produced same folder ID: %q", a) } } func TestFolderID_EmptyFingerprintUsesPlaceholder(t *testing.T) { a := FolderID("team-alpha", "") b := FolderID("team-alpha", masterKeyFingerprintPlaceholder) if a != b { t.Errorf("empty fingerprint did not match placeholder: %q vs %q", a, b) } } func TestFolderID_Length(t *testing.T) { id := FolderID("ns", "fp") if len(id) != 32 { t.Errorf("folder ID length = %d, want 32", len(id)) } } func TestRenderSyncthingConfig_OK(t *testing.T) { rep := VolumeReplication{ Namespace: "team-alpha", VolumeName: "data", SourcePath: "/var/lib/orca/volumes/data", ReplicateTo: []string{"peer-b", "peer-c"}, SyncMode: "sendreceive", } peers := []SyncthingDevice{ {ID: "dev-source", Name: "peer-a", Address: "dynamic"}, {ID: "dev-b", Name: "peer-b", Address: "tcp://peer-b:22000"}, {ID: "dev-c", Name: "peer-c", Address: "tcp://peer-c:22000"}, } cfg, err := RenderSyncthingConfig(rep, peers) if err != nil { t.Fatalf("RenderSyncthingConfig: %v", err) } if cfg.FolderID != FolderID("team-alpha", "") { t.Errorf("folder ID = %q, want %q", cfg.FolderID, FolderID("team-alpha", "")) } if cfg.Path != rep.SourcePath { t.Errorf("path = %q, want %q", cfg.Path, rep.SourcePath) } if len(cfg.Devices) != 3 { t.Errorf("devices = %d, want 3", len(cfg.Devices)) } if cfg.Devices[0].ID != "dev-source" { t.Errorf("first device = %q, want dev-source", cfg.Devices[0].ID) } } func TestRenderSyncthingConfig_Errors(t *testing.T) { peers := []SyncthingDevice{{ID: "d", Name: "n", Address: "dynamic"}} if _, err := RenderSyncthingConfig(VolumeReplication{}, peers); err == nil { t.Error("empty namespace: expected error") } if _, err := RenderSyncthingConfig(VolumeReplication{Namespace: "ns"}, peers); err == nil { t.Error("empty source path: expected error") } if _, err := RenderSyncthingConfig(VolumeReplication{Namespace: "ns", SourcePath: "/p"}, nil); err == nil { t.Error("no peers: expected error") } } func TestRenderSyncthingXML_Valid(t *testing.T) { cfg := &SyncthingConfig{ FolderID: "abcd1234abcd1234abcd1234abcd1234", Path: "/var/lib/orca/data", Devices: []SyncthingDevice{ {ID: "dev-source", Name: "peer-a", Address: "dynamic"}, {ID: "dev-b", Name: "peer-b", Address: "tcp://peer-b:22000"}, }, } out, err := RenderSyncthingXML(cfg) if err != nil { t.Fatalf("RenderSyncthingXML: %v", err) } if !strings.HasPrefix(out, xml.Header) { t.Errorf("output missing XML header") } if !strings.Contains(out, `id="abcd1234abcd1234abcd1234abcd1234"`) { t.Errorf("folder ID not in output") } if !strings.Contains(out, "dev-source") { t.Errorf("source device ID not in output") } if !strings.Contains(out, "dev-b") { t.Errorf("peer device ID not in output") } if !strings.Contains(out, "/var/lib/orca/data") { t.Errorf("path not in output") } if !strings.Contains(out, `tcp://peer-b:22000`) { t.Errorf("peer address not in output") } if !strings.Contains(out, `