The asks state gains the kind revert, keyed revert.<node>.<module>.<hex> after the reverted build's fingerprint; like the backup ask it needs no proof of who answered, so the view may answer it, and an asking that ends unanswered while the hold stands is written again. Builds: design 47 G §710, §300 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
90 lines
3.8 KiB
Go
90 lines
3.8 KiB
Go
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)
|
|
assignments, _ := AssignmentsAskKey("p-20261028t183000-1a2b3c")
|
|
record, _ := RecordAskKey("n1", "gitea", digest)
|
|
revert, _ := RevertAskKey("n1", "nats", fp)
|
|
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}},
|
|
"assignments": {assignments, AskKey{Kind: "assignments", Proposal: "p-20261028t183000-1a2b3c"}},
|
|
"record": {record, AskKey{Kind: "record", Node: "n1", Module: "gitea", Composed: digest}},
|
|
"revert": {revert, AskKey{Kind: "revert", Node: "n1", Module: "nats", FP: fp}},
|
|
} {
|
|
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,
|
|
assignments: "assignments.p-20261028t183000-1a2b3c", record: "record.n1.gitea." + strings.Repeat("cd", 32), revert: "revert.n1.nats." + hex} {
|
|
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],
|
|
"assignment.AB", "record.n1.gitea." + hex[:10], "record.n1.node." + hex, "merge.g", "revert.n1.node", "revert.n1.nats." + hex[:60]} {
|
|
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")
|
|
}
|
|
for _, kind := range []string{"hold", "revert"} {
|
|
if proof, err := AskNeedsProof(kind); err != nil || proof {
|
|
t.Errorf("a %s ask needs no proof", kind)
|
|
}
|
|
}
|
|
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)
|
|
}
|
|
}
|