mesh/merge-gate pass: builds mesh-issues, mesh-knowledge, records → novox; no bus step; every machine composes with the change as it did without (4 of 4 co…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
Once the records leave hq (issue 426), records_decisions would answer every topic empty, reserve would read 0 and hand out 0001 from a counter not started, and import would say it created nothing as a success. reserve now starts and raises its counters above mesh-knowledge's knowledge_highest, the floor alone starting one (with a warning) when it is silent and nothing spent with neither.
89 lines
2.9 KiB
Go
89 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// hq issue 488: the issue tracker's reserve takes the highest decision and research number from the knowledge base,
|
|
// which holds every record — reserved, withdrawn and proposed numbers included, since each is spent — rather than
|
|
// reading hq's folders, which empty when the records leave.
|
|
|
|
func TestTheHighestToolAnswersTheHighestNumberHeldPerKind(t *testing.T) {
|
|
eachStore(t, func(t *testing.T, s Store) {
|
|
w := imported(t, s)
|
|
tool := highestTool(w.k)
|
|
answer := func() Highest {
|
|
t.Helper()
|
|
out, err := tool.Run(map[string]any{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, _ := json.Marshal(out)
|
|
var h Highest
|
|
if err := json.Unmarshal(raw, &h); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return h
|
|
}
|
|
if h := answer(); h.Decision != 290 || h.Research != 45 || h.Records != 11 {
|
|
t.Fatalf("%+v", h)
|
|
}
|
|
// A number reserved, and later withdrawn, is spent: it is the highest.
|
|
w.reserved(t, "author@g14") // 300
|
|
w.clock = w.clock.Add(DefaultReservedFor + time.Hour)
|
|
if _, err := w.k.Withdraw(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h := answer(); h.Decision != 300 || h.Research != 45 {
|
|
t.Fatalf("after a reservation withdrawn: %+v", h)
|
|
}
|
|
if _, err := tool.Run(map[string]any{"kind": "decision"}); err == nil {
|
|
t.Fatal("an argument it does not take was taken")
|
|
}
|
|
})
|
|
// A knowledge base that holds nothing answers nothing: a 0 would start a counter at 1.
|
|
empty := newWorld(t, newMemStore(), fixture())
|
|
if _, err := highestTool(empty.k).Run(map[string]any{}); err == nil || !strings.Contains(err.Error(), "holds no record") {
|
|
t.Fatalf("an empty knowledge base: %v", err)
|
|
}
|
|
}
|
|
|
|
// hq issue 488: once the records have left hq, an import at a later commit finds none. It refuses, saying so,
|
|
// rather than reporting nothing created as a success.
|
|
func TestTheImportRefusesACommitWhereHqHoldsNoRecords(t *testing.T) {
|
|
dir := t.TempDir()
|
|
write := func(path, text string) {
|
|
t.Helper()
|
|
if err := writeFileAll(dir+"/"+path, text); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
write("COMMIT", "0123456789abcdef0123456789abcdef01234567\n")
|
|
write("02-DECISIONS/README.md", "# Decisions\n\nThey live in the knowledge base.\n")
|
|
write("01-RESEARCH/README.md", "# Research\n")
|
|
w := newWorld(t, newMemStore(), dirRecords{dir: dir})
|
|
for _, dry := range []bool{true, false} {
|
|
out, err := w.k.Import("import@test", ImportAsk{DryRun: dry}, dirRecords{dir: dir})
|
|
if err == nil || !strings.Contains(err.Error(), "holds no decision record or research effort") ||
|
|
!strings.Contains(err.Error(), "0123456789ab") {
|
|
t.Fatalf("dry %v: %+v %v", dry, out, err)
|
|
}
|
|
}
|
|
if all, _ := w.k.Store.All(context.Background()); len(all) != 0 {
|
|
t.Fatal("written")
|
|
}
|
|
}
|
|
|
|
func writeFileAll(path, text string) error {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(path, []byte(text), 0o644)
|
|
}
|