package operatorask import ( "encoding/json" "strings" "testing" stdio "git.novox.be/novox/mesh-sdk/go" ) type warrant struct { Ask string `json:"ask"` Choice string `json:"choice"` } // Design 47 G A-101: one asker finds the seat's holder, publishes, reads the warrant and hears decided. func TestTheAskerFindsTheHolderPublishesReadsTheWarrantAndHearsDecided(t *testing.T) { var asked []string call := func(key string, body any) (json.RawMessage, error) { asked = append(asked, key) return json.RawMessage(`{"seats":[{"seat":"other","holders":[{"module":"x"}]},{"seat":"router-seat","holders":[{"module":"holder"}]}]}`), nil } var bucket, id, subject string var published any var heard func(stdio.Envelope) error a := &Asker[warrant]{ Module: "me", Contract: Contract{Lists: "seat:lister.list", ListBody: map[string]bool{"seats": true}, Seat: "router-seat", StateAsks: "asks"}, Call: call, Record: func(b, i string) (*stdio.StateEntry, error) { bucket, id = b, i return &stdio.StateEntry{Value: json.RawMessage(`{"state":"chosen","warrant":{"ask":"a1","choice":"go"}}`)}, nil }, Publish: func(s string, body any, _ string) error { subject, published = s, body; return nil }, Subscribe: func(_ string, h func(stdio.Envelope) error) error { heard = h; return nil }, AskSubject: func(m string) string { return "ask." + m }, DecidedSubject: func(m string) string { return "decided." + m }, } if err := a.Ask("a1", "q"); err != nil || subject != "ask.me" || published != "q" { t.Errorf("Ask published %v on %q: %v", published, subject, err) } state, w, err := a.Where("a1") if err != nil || state != "chosen" || w == nil || w.Choice != "go" || bucket != "holder_asks" || id != "a1" || len(asked) != 1 || asked[0] != "seat:lister.list" { t.Errorf("Where = %q %+v %v, read %q %q after %v", state, w, err, bucket, id, asked) } var got []warrant if err := a.Hear(func(w warrant) error { got = append(got, w); return nil }); err != nil { t.Fatal(err) } if err := heard(stdio.Envelope{Key: "decided.me", Body: []byte(`{"ask":"a1","choice":"go"}`)}); err != nil || len(got) != 1 || got[0].Ask != "a1" { t.Errorf("heard %v: %v", got, err) } if err := heard(stdio.Envelope{Key: "decided.me", Body: []byte(`nope`)}); err == nil { t.Errorf("a body that is no warrant was taken") } // No holder: nothing is read and the reason is said. a.Call = func(string, any) (json.RawMessage, error) { return json.RawMessage(`{"seats":[]}`), nil } if _, _, err := a.Where("a1"); err == nil || !strings.Contains(err.Error(), "no module holds the seat router-seat") { t.Errorf("with no holder Where answered %v", err) } }