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(5 * 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) } }