package registry import "testing" // TestPathRoundTrip: a written prefix row comes back, and a repoint of the // same (host, prefix) replaces rather than duplicates. func TestPathRoundTrip(t *testing.T) { reg := openTestRegistry(t) if err := reg.UpsertPath(RoutePath{ Host: "ti.to", Prefix: "paulca", Target: "go.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } got, err := reg.ListPaths() if err != nil { t.Fatal(err) } if len(got) != 1 { t.Fatalf("ListPaths returned %d rows, want 1", len(got)) } if got[0].Target != "go.tito.io" { t.Fatalf("target = %q, want go.tito.io", got[0].Target) } if err := reg.UpsertPath(RoutePath{ Host: "ti.to", Prefix: "paulca", Target: "beta.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } got, err = reg.ListPaths() if err != nil { t.Fatal(err) } if len(got) != 1 { t.Fatalf("repoint produced %d rows, want 1 — (host, prefix) is the key", len(got)) } if got[0].Target != "beta.tito.io" { t.Fatalf("target = %q, want beta.tito.io after repoint", got[0].Target) } } // TestDeletePathIsIdempotent: deleting a row that is already gone is a // success, the same contract DeleteAlias carries. The reconcile pass deletes // unconditionally, so this must not error. func TestDeletePathIsIdempotent(t *testing.T) { reg := openTestRegistry(t) if err := reg.DeletePath("ti.to", "nobody"); err != nil { t.Fatalf("deleting an absent path row: %v", err) } } // TestPathsAreScopedToTheirHost: two hosts may carry the same prefix without // colliding — the key is the pair, not the prefix. func TestPathsAreScopedToTheirHost(t *testing.T) { reg := openTestRegistry(t) for _, h := range []string{"ti.to", "other.example"} { if err := reg.UpsertPath(RoutePath{ Host: h, Prefix: "paulca", Target: "go.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } } got, err := reg.ListPaths() if err != nil { t.Fatal(err) } if len(got) != 2 { t.Fatalf("got %d rows, want 2 — (host, prefix) is the key, not prefix alone", len(got)) } } // TestFingerprintChangesOnPathMutation is the load-bearing test of this // task. Fingerprint() is the 2s content hash the edge polls; a route_paths // change it cannot see is a flip that reconciles perfectly and never reaches // the live map — a silent false negative, the failure class Fingerprint's own // header names as the one to engineer against. func TestFingerprintChangesOnPathMutation(t *testing.T) { reg := openTestRegistry(t) if err := reg.UpsertPath(RoutePath{ Host: "ti.to", Prefix: "paulca", Target: "go.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } before, err := reg.Fingerprint() if err != nil { t.Fatal(err) } if err := reg.UpsertPath(RoutePath{ Host: "ti.to", Prefix: "paulca", Target: "beta.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } after, err := reg.Fingerprint() if err != nil { t.Fatal(err) } if before == after { t.Fatalf("fingerprint unchanged across a route_paths repoint: %q", after) } } // TestFingerprintChangesOnPathRemoval: the un-flip direction. Rollback is a // row disappearing, and it must reach the edge on the same 2s bound as the // flip did. func TestFingerprintChangesOnPathRemoval(t *testing.T) { reg := openTestRegistry(t) if err := reg.UpsertPath(RoutePath{ Host: "ti.to", Prefix: "paulca", Target: "go.tito.io", Account: "tito", App: "classic", }); err != nil { t.Fatal(err) } before, err := reg.Fingerprint() if err != nil { t.Fatal(err) } if err := reg.DeletePath("ti.to", "paulca"); err != nil { t.Fatal(err) } after, err := reg.Fingerprint() if err != nil { t.Fatal(err) } if before == after { t.Fatalf("fingerprint unchanged across a route_paths removal: %q", after) } }