A merged message is kept in the indexer's own state pending and the merges there are computed together on overlays of the indexer's states: taken in whole when the indexer's fingerprint is the running build, otherwise only the indexer's own entry, graph key and verdict are written and the rest waits for the named indexer. A group's members are gathered until its end. Waits are said on the stream take-in, read by indexer_pending and steered by indexer_take_in_pending and indexer_drop_pending. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
107 lines
4.5 KiB
Go
107 lines
4.5 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
const otherMerge = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
|
|
func sourceOf(repo, head string) delivery.Source {
|
|
return delivery.Source{Group: "g", Heads: map[string]string{repo: head}}
|
|
}
|
|
|
|
func TestASourceRevisionStampsTheModulesOfTheRepositoriesHeadItNames(t *testing.T) { // 1344/AC1
|
|
ix, mods := modulesIndexer(t)
|
|
ctx := context.Background()
|
|
if err := ix.Apply(ctx, mergedMsg("novox/mesh-delivery", map[string]string{"modules/a": "newtree"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before, _ := moduleOf(t, mods, "a")
|
|
if before.Src != 0 {
|
|
t.Fatalf("module before the source = %+v, want Src 0", before)
|
|
}
|
|
// The source names the head merged for the delivery repository, and another repository's head no module of ours is built from.
|
|
s := delivery.Source{Group: "g", Heads: map[string]string{"novox/mesh-delivery": merge, "novox/mesh-catalog": otherMerge}}
|
|
if err := ix.ApplySource(ctx, 7, s); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
m, ok := moduleOf(t, mods, "a")
|
|
want := before
|
|
want.Src, want.FPSrc = 7, 7 // its fingerprint moved at that merge (ADR 0601 §1)
|
|
if !ok || !reflect.DeepEqual(m, want) {
|
|
t.Errorf("module a = %+v (%v), want %+v: the fingerprint and the commit as the merge wrote them, with Src 7", m, ok, want)
|
|
}
|
|
if c, ok := moduleOf(t, mods, "c"); ok {
|
|
t.Errorf("module c = %+v: written for a head no merge message of the indexer carried", c)
|
|
}
|
|
// The same revision again changes nothing, and so does a later one: Src is the first revision naming the commit.
|
|
if err := ix.ApplySource(ctx, 7, s); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := ix.ApplySource(ctx, 9, s); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m, _ := moduleOf(t, mods, "a"); m.Src != 7 {
|
|
t.Errorf("module a Src = %d, want 7", m.Src)
|
|
}
|
|
}
|
|
|
|
func TestAMergeHeardAfterTheSourceNamesItsHeadIsStampedWhenWritten(t *testing.T) { // 1344/AC1 (the source first)
|
|
// A source revision older than the one held is left (merged here from a test of its own, for the test budget).
|
|
t.Run("an older source revision is left", func(t *testing.T) {
|
|
ix, mods := modulesIndexer(t, rec(t, "build-1", "a", "novox/mesh-delivery", "modules/a", "main", "", "2026-10-19T09:00:00Z", aInputs))
|
|
ctx := context.Background()
|
|
_ = ix.Apply(ctx, mergedMsg("novox/mesh-delivery", map[string]string{"modules/a": "newtree"}))
|
|
_ = ix.ApplySource(ctx, 9, sourceOf("novox/mesh-delivery", merge))
|
|
_ = ix.ApplySource(ctx, 7, sourceOf("novox/mesh-delivery", merge))
|
|
if m, _ := moduleOf(t, mods, "a"); m.Src != 9 {
|
|
t.Errorf("module a Src = %d, want 9", m.Src)
|
|
}
|
|
})
|
|
ix, mods := modulesIndexer(t, rec(t, "build-1", "a", "novox/mesh-delivery", "modules/a", "main", "", "2026-10-19T09:00:00Z", aInputs))
|
|
ctx := context.Background()
|
|
if err := ix.ApplySource(ctx, 7, sourceOf("novox/mesh-delivery", merge)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := moduleOf(t, mods, "a"); ok {
|
|
t.Fatal("a module was written from a source revision alone: its tree is the merge message's")
|
|
}
|
|
if err := ix.Apply(ctx, mergedMsg("novox/mesh-delivery", map[string]string{"modules/a": "newtree"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m, ok := moduleOf(t, mods, "a"); !ok || m.Src != 7 || m.Commit != merge || m.Path != "modules/a" {
|
|
t.Errorf("module a = %+v (%v), want the merge's fingerprint with Src 7", m, ok)
|
|
}
|
|
}
|
|
|
|
func TestAMergeThatNoSourceRevisionNamesIsWrittenAsToday(t *testing.T) { // 1344/AC2
|
|
ix, mods := modulesIndexer(t, rec(t, "build-1", "a", "novox/mesh-delivery", "modules/a", "main", "", "2026-10-19T09:00:00Z", aInputs))
|
|
ctx := context.Background()
|
|
// No source revision yet.
|
|
if err := ix.Apply(ctx, mergedMsg("novox/mesh-delivery", map[string]string{"modules/a": "newtree"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m, ok := moduleOf(t, mods, "a"); !ok || m.Src != 0 || m.Path != "modules/a" {
|
|
t.Fatalf("module a = %+v (%v), want the merge written with Src 0", m, ok)
|
|
}
|
|
// A source revision that names another head of the repository: a merge of the head it does not name keeps Src 0.
|
|
if err := ix.ApplySource(ctx, 7, sourceOf("novox/mesh-delivery", otherMerge)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m, _ := moduleOf(t, mods, "a"); m.Src != 0 {
|
|
t.Errorf("module a Src = %d after a source naming another head, want 0", m.Src)
|
|
}
|
|
merged := mergedMsg("novox/mesh-delivery", map[string]string{"modules/a": "newertree"})
|
|
merged.Merge = "cccccccccccccccccccccccccccccccccccccccc"
|
|
if err := ix.Apply(ctx, merged); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m, _ := moduleOf(t, mods, "a"); m.Src != 0 || m.Commit != merged.Merge {
|
|
t.Errorf("module a = %+v, want the new merge with Src 0", m)
|
|
}
|
|
}
|