test(trust): red for #27 — stranger gating, open-request claim, directed claims
This commit is contained in:
1 parent
b43294341d
commit
c23fcdd73c
3 files changed
+135
-2
No files matched your search
@@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type gateBrain struct {
|
||||
mu sync.Mutex
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (b *gateBrain) Name() string { return "gate" }
|
||||
func (b *gateBrain) Ask(ctx context.Context, system, prompt string) (string, int, error) {
|
||||
b.mu.Lock()
|
||||
b.calls = append(b.calls, system+"\n"+prompt)
|
||||
b.mu.Unlock()
|
||||
return "KIND: claim\nOn it.", 10, nil
|
||||
}
|
||||
|
||||
func newGateServer(t *testing.T) (*httptest.Server, *Server, *gateBrain) {
|
||||
t.Helper()
|
||||
ts, s := newTestNestServer(t)
|
||||
gb := &gateBrain{}
|
||||
s.p.Flock.brain = gb
|
||||
return ts, s, gb
|
||||
}
|
||||
|
||||
func TestStrangerOnlyWhenAddressed(t *testing.T) {
|
||||
ts, s, gb := newGateServer(t)
|
||||
id := newNest(t, ts, "Lab", `"Hugin","Munin","Soot"`)
|
||||
promote(s, "Munin", "Soot") // Hugin stays a stranger
|
||||
code, _ := post(t, ts.URL+"/api/nests/"+id+"/messages",
|
||||
`{"author":"owner","kind":"request","mode":"conspiracy","text":"is this risky"}`)
|
||||
if code != http.StatusCreated {
|
||||
t.Fatalf("post: %d", code)
|
||||
}
|
||||
awaitMessages(t, ts, id, 3) // request + 2 claims (Munin, Soot)
|
||||
|
||||
gb.mu.Lock()
|
||||
defer gb.mu.Unlock()
|
||||
for _, call := range gb.calls {
|
||||
if strings.Contains(call, "You are Hugin,") {
|
||||
t.Fatal("a stranger must not be invited for open work")
|
||||
}
|
||||
}
|
||||
names := 0
|
||||
for _, n := range []string{"You are Munin,", "You are Soot,"} {
|
||||
for _, call := range gb.calls {
|
||||
if strings.Contains(call, n) {
|
||||
names++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if names != 2 {
|
||||
t.Fatalf("both regular crows should be invited, calls: %v", gb.calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegularMayClaimOpen(t *testing.T) {
|
||||
ts, s, gb := newGateServer(t)
|
||||
id := newNest(t, ts, "Lab", `"Hugin","Munin"`)
|
||||
promote(s, "Hugin") // only Hugin is a regular
|
||||
post(t, ts.URL+"/api/nests/"+id+"/messages",
|
||||
`{"author":"owner","kind":"request","text":"tidy the branch notes"}`) // no to, no mode header
|
||||
awaitMessages(t, ts, id, 2)
|
||||
|
||||
gb.mu.Lock()
|
||||
defer gb.mu.Unlock()
|
||||
if len(gb.calls) != 1 {
|
||||
t.Fatalf("an open request invites exactly one eligible crow, calls: %v", gb.calls)
|
||||
}
|
||||
if !strings.Contains(gb.calls[0], "You are Hugin,") {
|
||||
t.Fatalf("the eligible crow should be invited, got %q", gb.calls[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllStrangersStayOpen(t *testing.T) {
|
||||
ts, _, gb := newGateServer(t)
|
||||
id := newNest(t, ts, "Lab", `"Hugin","Munin"`)
|
||||
code, out := post(t, ts.URL+"/api/nests/"+id+"/messages",
|
||||
`{"author":"owner","kind":"request","text":"do the thing"}`)
|
||||
if code != http.StatusCreated {
|
||||
t.Fatalf("post: %d %v", code, out)
|
||||
}
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
gb.mu.Lock()
|
||||
defer gb.mu.Unlock()
|
||||
if len(gb.calls) != 0 {
|
||||
t.Fatalf("a nest of only strangers must not be summoned, calls: %v", gb.calls)
|
||||
}
|
||||
if len(nestMessages(t, ts, id)) != 1 {
|
||||
t.Fatal("the request must stay open until addressed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaimAuthorHolds(t *testing.T) {
|
||||
ts, s := newScriptedServer(t, "hmm idle chatter", "still not an answer") // addressee stays silent
|
||||
id := newNest(t, ts, "Lab", `"Hugin","Munin"`)
|
||||
code, req := post(t, ts.URL+"/api/nests/"+id+"/messages",
|
||||
`{"author":"owner","kind":"request","to":"Hugin","text":"count the eggs"}`)
|
||||
if code != http.StatusCreated {
|
||||
t.Fatalf("request: %d", code)
|
||||
}
|
||||
// Munin cannot claim what owner asked Hugin.
|
||||
c2, out := post(t, ts.URL+"/api/nests/"+id+"/messages",
|
||||
`{"author":"Munin","kind":"claim","refers_to":"`+req["msg_id"].(string)+`","text":"mine"}`)
|
||||
// give the addressee's must-respond (and its flag) time to settle first
|
||||
awaitMessages(t, ts, id, 2)
|
||||
if c2 != http.StatusConflict {
|
||||
t.Fatalf("directed assignment must refuse a non-addressee claim, got %d %v", c2, out)
|
||||
}
|
||||
if msg, _ := out["message"].(string); !strings.Contains(msg, "Hugin") {
|
||||
t.Fatalf("refusal must name the asked crow, got %q", msg)
|
||||
}
|
||||
_ = s
|
||||
}
|
||||
Reference in new issue
Block a user