A test that slept a fixed time and then asserted what a goroutine, process or watcher did failed under the checker's load. Each now waits for its positive evidence (a started baseline, a call counted, a state reached) within 30 s, and the concurrency-limit tests meet at a barrier instead of overlapping by sleep. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
141 lines
5.0 KiB
Go
141 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
)
|
|
|
|
// served is the tracker's verbs served as the runtime launches them, over the SDK's stdio loop, with the caller
|
|
// read from the runtime (stdio.CallerOf): what reaches the module is what a tools/call carries.
|
|
type served struct {
|
|
in *io.PipeWriter
|
|
lines *bufio.Scanner
|
|
next int
|
|
}
|
|
|
|
func serve(t *testing.T, h *harness) *served {
|
|
t.Helper()
|
|
h.CallerOf = stdio.CallerOf
|
|
inR, inW := io.Pipe()
|
|
outR, outW := io.Pipe()
|
|
go func() { _ = stdio.ServeOn("mesh-issues", Tools(h.Tracker), inR, outW) }()
|
|
t.Cleanup(func() { _ = inW.Close() })
|
|
return &served{in: inW, lines: bufio.NewScanner(outR)}
|
|
}
|
|
|
|
// call sends one tools/call, with the runtime's `_meta` naming caller when one is given, and answers the
|
|
// verb's result or its refusal.
|
|
func (s *served) call(t *testing.T, verb, caller string, args map[string]any) (map[string]any, string) {
|
|
t.Helper()
|
|
s.next++
|
|
params := map[string]any{"name": Seat + "." + verb, "arguments": args}
|
|
if caller != "" {
|
|
params["_meta"] = map[string]any{stdio.MetaCaller: caller}
|
|
}
|
|
b, _ := json.Marshal(map[string]any{"jsonrpc": "2.0", "id": s.next, "method": "tools/call", "params": params})
|
|
_, _ = s.in.Write(append(b, '\n'))
|
|
done := make(chan []byte, 1)
|
|
go func() {
|
|
if s.lines.Scan() {
|
|
done <- append([]byte(nil), s.lines.Bytes()...)
|
|
}
|
|
}()
|
|
var line []byte
|
|
select {
|
|
case line = <-done:
|
|
case <-time.After(30 * time.Second):
|
|
t.Fatalf("%s was not answered", verb)
|
|
}
|
|
var m struct {
|
|
Result struct {
|
|
Content []struct {
|
|
Text string `json:"text"`
|
|
} `json:"content"`
|
|
IsError bool `json:"isError"`
|
|
} `json:"result"`
|
|
}
|
|
_ = json.Unmarshal(line, &m)
|
|
if len(m.Result.Content) == 0 {
|
|
t.Fatalf("%s was answered %s", verb, line)
|
|
}
|
|
text := m.Result.Content[0].Text
|
|
if m.Result.IsError {
|
|
return nil, text
|
|
}
|
|
var out map[string]any
|
|
_ = json.Unmarshal([]byte(text), &out)
|
|
return out, ""
|
|
}
|
|
|
|
// **Who acted is the caller the runtime proved** (novox/hq issue 365, ADR 0275 §5): a call whose subject named
|
|
// its caller is recorded as that bus user — on the issue it opened, the note, the link, the move and its event,
|
|
// the value set, and the number reserved.
|
|
func TestWhoActedIsTheCallerTheRuntimeProved(t *testing.T) {
|
|
h, _ := reserveHarness(t)
|
|
s := serve(t, h)
|
|
const who = "shanks.node-tools"
|
|
opened, refused := s.call(t, "open", who, map[string]any{"title": "a title", "report": "a report"})
|
|
if refused != "" || opened["by"] != who {
|
|
t.Fatalf("open answered %v %q, want by %s", opened, refused, who)
|
|
}
|
|
n := uint64(opened["number"].(float64))
|
|
other, _ := s.call(t, "open", who, map[string]any{"title": "another", "report": "another report"})
|
|
is, _ := h.Get(n)
|
|
if is.OpenedBy != who {
|
|
t.Errorf("the issue was opened by %q", is.OpenedBy)
|
|
}
|
|
if noted, refused := s.call(t, "note", who, map[string]any{"number": n, "text": "seen again"}); refused != "" || noted["by"] != who {
|
|
t.Errorf("note answered %v %q", noted, refused)
|
|
}
|
|
if linked, refused := s.call(t, "link", who, map[string]any{"number": n, "kind": "relates-to", "target": fmt.Sprint(other["number"])}); refused != "" || linked["by"] != who {
|
|
t.Errorf("link answered %v %q", linked, refused)
|
|
}
|
|
if _, refused := s.call(t, "set", who, map[string]any{"number": n, "severity": "minor"}); refused != "" {
|
|
t.Errorf("set refused: %s", refused)
|
|
}
|
|
if _, refused := s.call(t, "move", who, map[string]any{"number": n, "status": "fixing", "by": "fix-1@g14"}); refused != "" {
|
|
t.Errorf("move refused: %s", refused)
|
|
}
|
|
if reserved, refused := s.call(t, "reserve", who, map[string]any{"kind": "decision", "for": "a decision"}); refused != "" || reserved["by"] != who {
|
|
t.Errorf("reserve answered %v %q", reserved, refused)
|
|
}
|
|
is, _ = h.Get(n)
|
|
for _, note := range is.Notes {
|
|
if note.By != who {
|
|
t.Errorf("a note is by %q", note.By)
|
|
}
|
|
}
|
|
for _, e := range h.said() {
|
|
if e.Event == EventMoved && e.Body["caller"] != who {
|
|
t.Errorf("the move was said as by caller %v", e.Body["caller"])
|
|
}
|
|
}
|
|
}
|
|
|
|
// A caller named in the arguments is refused, whatever it names — an argument is the caller's to write — and a
|
|
// call the runtime proved no caller for is recorded Unproven, as it always was.
|
|
func TestACallerInTheArgumentsIsRefusedAndAnUnprovenCallSaysSo(t *testing.T) {
|
|
h := newHarness(t)
|
|
s := serve(t, h)
|
|
for _, args := range []map[string]any{
|
|
{"title": "t", "report": "r", "caller": "novox.node-tools"},
|
|
{"title": "t", "report": "r", "_meta": map[string]any{stdio.MetaCaller: "novox.node-tools"}},
|
|
{"title": "t", "report": "r", "by": "novox.node-tools"},
|
|
} {
|
|
if out, refused := s.call(t, "open", "shanks.node-tools", args); refused == "" || !strings.Contains(refused, "does not take") {
|
|
t.Errorf("an open naming a caller in its arguments %v was answered %v", args, out)
|
|
}
|
|
}
|
|
opened, refused := s.call(t, "open", "", map[string]any{"title": "t", "report": "r"})
|
|
if refused != "" || opened["by"] != Unproven {
|
|
t.Fatalf("an open the runtime named no caller for answered %v %q, want by %s", opened, refused, Unproven)
|
|
}
|
|
}
|