package registry import "testing" func claimFingerprints(t *testing.T, r *Registry) (string, string) { t.Helper() f, err := r.Fingerprint() if err != nil { t.Fatal(err) } s, err := r.SnapshotFingerprint() if err != nil { t.Fatal(err) } return f, s } // Each ownership column moves both fingerprints on its own, partial // ownership included, and clearing it returns the exact default digests. func TestFingerprintsSeeEachClaimOwnershipField(t *testing.T) { reg := openTestRegistry(t) if err := reg.Upsert(Route{Host: "c", Kind: "instance", Socket: "/s", App: "a", CreatedAt: 1700000000}); err != nil { t.Fatal(err) } defF, defS := claimFingerprints(t, reg) set := func(assign string, args ...any) { t.Helper() if _, err := reg.sql.Exec(`UPDATE routes SET `+assign+` WHERE host = 'c'`, args...); err != nil { t.Fatal(err) } } const clear = `claim_incarnation = '', claim_stamp = 0, claim_owner = '', claim_row_id = ''` cases := []struct { name string assign string args []any }{ {"incarnation", `claim_incarnation = ?`, []any{"i1"}}, {"zero-incarnation", `claim_incarnation = ?`, []any{"0"}}, {"zero-owner", `claim_owner = ?`, []any{"0"}}, {"zero-row_id", `claim_row_id = ?`, []any{"0"}}, {"stamp", `claim_stamp = ?`, []any{7}}, {"owner", `claim_owner = ?`, []any{"o1"}}, {"row_id", `claim_row_id = ?`, []any{"r1"}}, {"incarnation+owner", `claim_incarnation = ?, claim_owner = ?`, []any{"i1", "o1"}}, {"stamp+row_id", `claim_stamp = ?, claim_row_id = ?`, []any{7, "r1"}}, {"full", `claim_incarnation = ?, claim_stamp = ?, claim_owner = ?, claim_row_id = ?`, []any{"i1", 7, "o1", "r1"}}, } seenF := map[string]string{} seenS := map[string]string{} for _, c := range cases { set(c.assign, c.args...) f, s := claimFingerprints(t, reg) if f == defF { t.Errorf("%s: Fingerprint did not change", c.name) } if s == defS { t.Errorf("%s: SnapshotFingerprint did not change", c.name) } if prev, dup := seenF[f]; dup { t.Errorf("%s: Fingerprint collides with %s", c.name, prev) } if prev, dup := seenS[s]; dup { t.Errorf("%s: SnapshotFingerprint collides with %s", c.name, prev) } seenF[f], seenS[s] = c.name, c.name set(clear) if f, s := claimFingerprints(t, reg); f != defF || s != defS { t.Errorf("%s: cleared ownership did not restore default digests", c.name) } } } // The same value in different ownership fields must not hash alike. func TestFingerprintsDistinguishClaimFieldsHoldingSameValue(t *testing.T) { reg := openTestRegistry(t) if err := reg.Upsert(Route{Host: "c", Kind: "instance", Socket: "/s", CreatedAt: 1700000000}); err != nil { t.Fatal(err) } digests := func(assign string) (string, string) { t.Helper() if _, err := reg.sql.Exec(`UPDATE routes SET claim_incarnation = '', claim_owner = '', claim_row_id = '', ` + assign + ` WHERE host = 'c'`); err != nil { t.Fatal(err) } return claimFingerprints(t, reg) } fa, sa := digests(`claim_owner = 'x'`) fb, sb := digests(`claim_row_id = 'x'`) fc, sc := digests(`claim_incarnation = 'x'`) if fa == fb || fa == fc || fb == fc { t.Error("Fingerprint aliases ownership fields") } if sa == sb || sa == sc || sb == sc { t.Error("SnapshotFingerprint aliases ownership fields") } }