package asks import ( "errors" "strings" "testing" "git.novox.be/novox/mesh-sdk/go/keys" ) // The keys equal what the assigner has always written (the expected strings are the trunk's own output for the same input), // and each reads back to its parts. func TestTheAssignersAskKeysKeepTheirFormsAndTheValueItsRules(t *testing.T) { fp := "src2:" + strings.Repeat("ab", 32) hex := strings.Repeat("ab", 32) digest := "sha256:" + strings.Repeat("cd", 32) hold, _ := HoldAskKey("gitea", fp) restore, _ := RestoreAskKey("n1", "gitea", fp) backup, _ := BackupAskKey("n1", "novox.be", fp) placement, _ := PlacementAskKey("p-20261028t183000-1a2b3c") record, _ := RecordAskKey("n1", "gitea", digest) for key, want := range map[string]struct { got string back AskKey }{ "hold": {hold, AskKey{Kind: "hold", Module: "gitea", FP: fp}}, "restore": {restore, AskKey{Kind: "restore", Node: "n1", Module: "gitea", FP: fp}}, "backup": {backup, AskKey{Kind: "backup", Node: "n1", Module: "novox.be", FP: fp}}, "placement": {placement, AskKey{Kind: "placement", Proposal: "p-20261028t183000-1a2b3c"}}, "record": {record, AskKey{Kind: "record", Node: "n1", Module: "gitea", Composed: digest}}, } { back, err := ParseAnyAskKey(want.got) if err != nil || back != want.back { t.Errorf("%s: ParseAnyAskKey(%q) = %+v, %v; want %+v", key, want.got, back, err, want.back) } } for got, want := range map[string]string{hold: "hold.gitea." + hex, restore: "restore.n1.gitea." + hex, backup: "backup.n1.novox=2ebe." + hex, placement: "placement.p-20261028t183000-1a2b3c", record: "record.n1.gitea." + strings.Repeat("cd", 32)} { if got != want { t.Errorf("key %q, want %q", got, want) } } merge, err := ParseAnyAskKey("merge.fix/1=2e2.d106c7950d28") if err != nil || merge.Kind != "merge" || merge.Group != "fix/1.2" || merge.Hash != "d106c7950d28" { t.Errorf("a merge ask key: %+v, %v", merge, err) } for _, bad := range []string{"", "other.x", "hold.gitea", "hold.gitea.src2:" + hex, "restore.n1", "backup.n1.node", "backup.n1.gitea." + hex[:60], "placement.AB", "record.n1.gitea." + hex[:10], "record.n1.node." + hex, "merge.g"} { if _, err := ParseAnyAskKey(bad); err == nil { t.Errorf("ParseAnyAskKey(%q) reads a wrong key", bad) } } if proof, err := AskNeedsProof("merge"); err != nil || !proof { t.Error("a merge ask needs proof") } if proof, err := AskNeedsProof("hold"); err != nil || proof { t.Error("a hold ask needs no proof") } if _, err := AskNeedsProof("view"); err == nil { t.Error("an unknown kind of ask is taken") } // The value: the router's ask whole; an ask of a kind that needs proof, a negative asking and no ask are refused. good := Ask{Ask: []byte(`{"id":"x"}`), Asking: 2} data, err := EncodeAsk(hold, good) if err != nil { t.Fatalf("EncodeAsk: %v", err) } back, err := DecodeAsk(hold, data) if err != nil || !SameAsk(back, Ask{V: keys.Version, Ask: []byte(` {"id": "x"} `), Asking: 2}) { t.Errorf("DecodeAsk = %+v, %v", back, err) } for name, c := range map[string]struct { key string a Ask }{"a merge ask": {"merge.g.d106c7950d28", good}, "a negative asking": {hold, Ask{Ask: good.Ask, Asking: -1}}, "no ask": {hold, Ask{}}, "a null ask": {hold, Ask{Ask: []byte("null")}}, "an unknown kind": {"other.x", good}} { if _, err := EncodeAsk(c.key, c.a); err == nil { t.Errorf("EncodeAsk takes %s", name) } } if _, err := DecodeAsk(hold, []byte(`{"v":2,"ask":{}}`)); !errors.Is(err, keys.ErrUnknownVersion) { t.Errorf("DecodeAsk of another version = %v", err) } }