Files
mesh-catalog/modules/mesh-knowledge/cmd/mesh-knowledge/history_test.go
T
jschoubben 10ab959d0f
mesh/merge-gate pass: builds new: modules/mesh-knowledge, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compo…
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
Tighten who writes and reviews a record, date the rules, bound history (review of #206)
A revision came from anyone and a review was refused only to the first author,
so a co-writer could approve, and a record proposed before callers are proven
would later be reviewable by its own unproven author. Now a revision is taken
only from the proven author, a reserved number only from whoever reserved it,
and a review is refused from any writer of any version or for any record with
an unproven writer. The rules held records from no date, so a correction to an
older record was refused by rules hq never held it to; each dated rule now holds
from hq's own start date, and a new record cannot be dated before its
reservation. history and the question to ask are bounded like the other answers.
2026-10-11 05:10:02 +02:00

152 lines
5.3 KiB
Go

package main
import (
"fmt"
"reflect"
"strings"
"testing"
)
// to-be 55 §10: "Every version is kept and comparable — the module's test: three versions, history lists them,
// the difference of the first and third is exact."
func TestThreeVersionsAreKeptAndTheFirstAndThirdCompareExactly(t *testing.T) {
eachStore(t, func(t *testing.T, s Store) {
w := imported(t, s)
n := w.reserved(t, "author@g14") // version 1: the reservation
p := valid(n)
if _, err := w.k.Propose("author@g14", p); err != nil { // version 2
t.Fatal(err)
}
p.Clauses[1] = "**A batch is delivered by one walk.** At most one commit per repository."
p.Why = "the bound named"
if _, err := w.k.Propose("author@g14", p); err != nil { // version 3
t.Fatal(err)
}
h, err := w.k.History(Key{KindDecision, n}, 0, 0, 0)
if err != nil {
t.Fatal(err)
}
if len(h.Versions) != 3 || h.Versions[0].Status != StatusReserved || h.Versions[1].Why != "proposed" ||
h.Versions[2].Why != "the bound named" || !h.Versions[2].Served || h.Versions[0].By != "author@g14" {
t.Fatalf("history: %+v", h.Versions)
}
d, err := w.k.History(Key{KindDecision, n}, 1, 3, 0)
if err != nil {
t.Fatal(err)
}
vs, _ := s.Versions(t.Context(), Key{KindDecision, n})
// Exact: applying the difference to the first version's text gives the third's, line for line.
if got := applyDiff(Render(vs[0].Record), d.Diff); got != Render(vs[2].Record) {
t.Fatalf("the difference does not turn version 1 into version 3:\n%s\n---\n%s", got, Render(vs[2].Record))
}
// And it is the difference: what changed between the reservation and the revised proposal, nothing else.
want := []string{"-status: reserved", "+status: proposed", "+topic: the mesh", "+date: 2026-10-11"}
for _, line := range want {
if !containsLine(d.Diff, line) {
t.Errorf("the difference lacks %q: %v", line, d.Diff)
}
}
if containsLine(d.Diff, "-# "+strings.TrimPrefix(itoaKey(n), "ADR ")+". a test record") == false {
t.Errorf("the title's change is not in the difference: %v", d.Diff)
}
// Versions 2 and 3 differ in clause 2 alone.
d23, _ := w.k.History(Key{KindDecision, n}, 2, 3, 0)
var changed []string
for _, l := range d23.Diff {
if !strings.HasPrefix(l, "@@") {
changed = append(changed, l)
}
}
if !reflect.DeepEqual(changed, []string{"-2. **A batch is delivered by one walk.** One commit per repository.",
"+2. **A batch is delivered by one walk.** At most one commit per repository."}) {
t.Fatalf("2 to 3: %v", d23.Diff)
}
if d22, _ := w.k.History(Key{KindDecision, n}, 2, 2, 0); !d22.Same || len(d22.Diff) != 0 {
t.Fatalf("a version against itself: %+v", d22)
}
})
}
func containsLine(lines []string, s string) bool {
for _, l := range lines {
if l == s {
return true
}
}
return false
}
// applyDiff applies a difference as Diff writes it to the text it was taken from.
func applyDiff(a string, diff []string) string {
src := strings.Split(a, "\n")
var out []string
at := 0
for i := 0; i < len(diff); i++ {
var oa, ca, ob, cb int
if _, err := fmt.Sscanf(diff[i], "@@ -%d,%d +%d,%d @@", &oa, &ca, &ob, &cb); err != nil {
continue
}
for at < oa-1 {
out = append(out, src[at])
at++
}
for i+1 < len(diff) && !strings.HasPrefix(diff[i+1], "@@") {
i++
if strings.HasPrefix(diff[i], "-") {
at++
} else {
out = append(out, diff[i][1:])
}
}
}
out = append(out, src[at:]...)
return strings.Join(out, "\n")
}
func TestDiffIsExactOnSmallTexts(t *testing.T) {
for _, c := range [][2]string{{"a\nb\nc", "a\nc"}, {"a", "b"}, {"", "x\ny"}, {"x\ny", ""}, {"a\nb\nc\nd", "b\nc\nd\ne"}} {
if got := applyDiff(c[0], Diff(c[0], c[1])); got != c[1] {
t.Errorf("%q to %q: %q (%v)", c[0], c[1], got, Diff(c[0], c[1]))
}
}
}
// history is bounded like the other answers: its work, and its answer, with a cut notice (the review of #206).
func TestHistoryIsBounded(t *testing.T) {
w := imported(t, newMemStore())
n := w.reserved(t, "author@g14")
p := valid(n)
big := strings.Repeat("A line of reasoning that is long enough to count.\n", 3000)
p.Sections[0].Text = big
if _, err := w.k.Propose("author@g14", p); err != nil {
t.Fatal(err)
}
p.Sections[0].Text = strings.ReplaceAll(big, "long enough", "longer than")
if _, err := w.k.Propose("author@g14", p); err != nil {
t.Fatal(err)
}
h, err := w.k.History(Key{KindDecision, n}, 2, 3, 0)
if err != nil {
t.Fatal(err)
}
if size(h) > DefaultBound || h.Cut == "" {
t.Fatalf("a large difference: %d bytes, cut %q", size(h), h.Cut)
}
// The difference stays exact when it is not cut, however large: its work is bounded, not its truth.
whole, _ := w.k.History(Key{KindDecision, n}, 2, 3, MostBound)
vs, _ := w.k.Store.Versions(t.Context(), Key{KindDecision, n})
if whole.Cut == "" && applyDiff(Render(vs[1].Record), whole.Diff) != Render(vs[2].Record) {
t.Fatal("the bounded difference is not exact")
}
if d := Diff(strings.Repeat("a\n", 5000)+"x", strings.Repeat("b\n", 5000)+"y"); applyDiff(strings.Repeat("a\n", 5000)+"x", d) != strings.Repeat("b\n", 5000)+"y" {
t.Fatal("a difference past the work bound is not exact")
}
}
func TestAQuestionIsBounded(t *testing.T) {
w := imported(t, newMemStore())
if _, err := w.k.Ask(strings.Repeat("merge window ", 200), 0); err == nil || !strings.Contains(err.Error(), "at most") {
t.Fatalf("a question of 2600 characters: %v", err)
}
}