Knowledge base: progress is proven over the bus with the module started whole (issue 1947)
The verb asks three seats and the records module; only a run over a real bus shows its grants and subjects line up with what the manifest invokes.
This commit is contained in:
@@ -72,7 +72,7 @@ func newBusWorld(t *testing.T) *busWorld {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// What stands on the other side: the issue tracker, the records module, the agent's judgement.
|
||||
records := fixture()
|
||||
records := withDesigns{fixture(), progressRecords()}
|
||||
answer := func(key string, do func(body json.RawMessage) (any, error)) {
|
||||
if _, err := nc.Subscribe("ask."+key, func(m *nats.Msg) {
|
||||
w.mu.Lock()
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
// 1947/AC1: the knowledge base running whole, as the runtime launches it, answers progress over the bus: it reads
|
||||
// design 47 through the records module and asks the issue tracker and mesh-delivery on their seats' subjects,
|
||||
// played here from what the live seats answered (testdata/progress).
|
||||
func TestProgressOverTheBus(t *testing.T) {
|
||||
w := newBusWorld(t)
|
||||
seats := newSeatsWorld(t)
|
||||
for _, key := range []string{"seat:issue-tracker.list", "seat:issue-tracker.get", "seat:mesh-delivery.deliveries",
|
||||
"seat:mesh-delivery.groups", "seat:mesh-delivery.show"} {
|
||||
key := key
|
||||
if _, err := w.nc.Subscribe("ask."+key, func(m *nats.Msg) {
|
||||
var body map[string]any
|
||||
_ = json.Unmarshal(m.Data, &body)
|
||||
out, err := seats.ask(key, body)
|
||||
if err != nil {
|
||||
_ = m.Respond([]byte(`{"error":` + strconv.Quote(err.Error()) + `}`))
|
||||
return
|
||||
}
|
||||
raw, _ := json.Marshal(map[string]any{"result": json.RawMessage(out)})
|
||||
_ = m.Respond(raw)
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
b, _ := w.start(t)
|
||||
raw, err := b.call(Seat+".progress", map[string]any{"of": "design 47"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var p Progress
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lines := strings.Split(p.Tree, "\n")
|
||||
if len(raw) > DefaultBound || p.Detail != DetailMinimal || !strings.HasPrefix(lines[0], "✗ design 47 · Delivery: from a commit to delivered — ") ||
|
||||
!strings.Contains(p.Tree, "▶ R6 6/7 1945 fixing since") || !strings.Contains(strings.Join(p.Warnings, "\n"), "issue 1209 is in milestones R3b and R3c") {
|
||||
t.Fatalf("%d bytes:\n%s\n%v", len(raw), p.Tree, p.Warnings)
|
||||
}
|
||||
raw, err = b.call(Seat+".progress", map[string]any{"of": "milestone 47/R6", "detail": "detailed"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = json.Unmarshal(raw, &p)
|
||||
for _, want := range []string{"▶ milestone 47/R6 · ", "▶ 1945 ", "jschoubben/car-hunter@cc4c8ce12901 ready since", "depends on 1943", "✓ 1946 "} {
|
||||
if !strings.Contains(p.Tree, want) {
|
||||
t.Errorf("detailed: no %q in\n%s", want, p.Tree)
|
||||
}
|
||||
}
|
||||
if _, err := b.call(Seat+".progress", map[string]any{"of": "design 47", "by": "someone@else"}); err == nil {
|
||||
t.Error("an argument naming the caller was taken")
|
||||
}
|
||||
seats.mu.Lock()
|
||||
defer seats.mu.Unlock()
|
||||
if seats.asked["seat:issue-tracker.list"] != 2 || seats.asked["seat:mesh-delivery.groups"] != 1 {
|
||||
t.Fatalf("asked %v", seats.asked)
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,28 @@ func progressRecords() dirRecords {
|
||||
return dirRecords{dir: filepath.Join("testdata", "progress", "hq")}
|
||||
}
|
||||
|
||||
// withDesigns is the fixture's records with the captured designs beside them, as the bus test's records module
|
||||
// serves them: a folder or document the first does not hold is read from the second.
|
||||
type withDesigns struct{ base, designs dirRecords }
|
||||
|
||||
func (w withDesigns) Standing() (string, error) { return w.base.Standing() }
|
||||
|
||||
func (w withDesigns) List(folder string) ([]string, []string, error) {
|
||||
if f, d, err := w.base.List(folder); err == nil {
|
||||
return f, d, nil
|
||||
}
|
||||
return w.designs.List(folder)
|
||||
}
|
||||
|
||||
func (w withDesigns) Read(path string) (string, string, error) {
|
||||
if c, commit, err := w.base.Read(path); err == nil {
|
||||
return c, commit, nil
|
||||
}
|
||||
c, _, err := w.designs.Read(path)
|
||||
commit, _ := w.base.Standing()
|
||||
return c, commit, err
|
||||
}
|
||||
|
||||
// seatsWorld plays the issue tracker and mesh-delivery from the captured answers, and counts what it is asked.
|
||||
type seatsWorld struct {
|
||||
mu sync.Mutex
|
||||
|
||||
Reference in New Issue
Block a user