diff --git a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go index e1d58357..a0860700 100644 --- a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go +++ b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/integration_test.go @@ -686,8 +686,14 @@ func (l buildLog) end(t *testing.T, repo, module, path string) { // message on FORGE makes modules. within 20 s, the fingerprint of the merge's tree and the recorded inputs. func TestIndexerWritesModulesAtAMerge(t *testing.T) { // 1239/AC9; I1, I3: the modules are the merged message's, no build record names them (issue 1851) // The bucket holds only build-agent's record, which no fingerprint reads since R4g (ADR 0530 ยง1). + var asks jetstream.KeyValue js, ctx, _, modules := startIndexer(t, func(ctx context.Context, builds buildLog) { builds.end(t, "novox/mesh-controller", "build-agent", "modules/build-agent") + }, func(ctx context.Context, js jetstream.JetStream) { + var err error + if asks, err = js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: index.TakeInsBucket, History: 1}); err != nil { + t.Fatal(err) + } }) const merge = "89abcdef0123456789abcdef0123456789abcdef" data, err := forgemsg.EncodeForge(forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-delivery", Branch: "feat/x", Number: 12, @@ -710,6 +716,60 @@ func TestIndexerWritesModulesAtAMerge(t *testing.T) { // 1239/AC9; I1, I3: the m if m.Repository != "novox/mesh-delivery" || m.Commit != merge || m.Path != "modules/a" || m.Manifest == "" || m.Fp != "" || m.None != "" { // 1606/AC2 t.Errorf("module = %+v within 20 s, want path modules/a, its manifest, and no value of today's form", m) } + // Milestone 47/G W4.13 (design 47, the indexer whole): the source revision taken in is one catalog graph revision kept + // as objects, said as catalog-revision on the seat's subject, every entry it lists stored once by digest. + objects := newBusObjects(js, testAccount, index.CatalogRevisionsObjects) + list, err := index.ListRevisions(ctx, objects, false) + if err != nil || len(list.Revisions) != 1 || list.Revisions[0].Name != "trunk.1" || !list.Revisions[0].Current || + list.Entries != list.Revisions[0].Entries || len(list.Unlisted) != 0 || list.Fill.Bytes == 0 { + t.Fatalf("revisions kept = %+v (%v): want trunk.1 alone, current, each entry it lists stored once", list, err) + } + events, err := js.Stream(ctx, "EVENTS") + if err != nil { + t.Fatal(err) + } + if msg, err := events.GetLastMsgForSubject(ctx, "mesh.seat.mesh-catalog.event."+meshcatalog.EventCatalogRevision); err != nil || + !strings.Contains(string(msg.Data), `"revision":1`) { + t.Errorf("catalog-revision said: %v (%v): want revision 1", msg, err) + } + // W4.12 through the process: a recompute by hand moves nothing and answers equal; a candidate's half dropped by hand + // leaves the trunk's revision and its entries. + if err := index.KeepRevision(ctx, objects, meshcatalog.CatalogRevision{Kind: "candidate", Group: "g1", Heads: "h1", Revision: 1, + Entries: []meshcatalog.EntryRef{{Module: "x", Digest: "dx"}}}, map[string][]byte{"dx": []byte(`{"module":"x"}`)}); err != nil { + t.Fatal(err) + } + answer := func(key string, value []byte) index.TakenIn { + t.Helper() + w, err := asks.Watch(ctx, key, jetstream.UpdatesOnly()) + if err != nil { + t.Fatal(err) + } + defer w.Stop() + if _, err := asks.Put(ctx, key, value); err != nil { + t.Fatal(err) + } + for e := range w.Updates() { + if e == nil { + continue + } + if a, err := index.DecodeTakeIn(e.Value()); err == nil && a.Done() { + return *a.Result + } + } + t.Fatalf("%s is not answered", key) + return index.TakenIn{} + } + key, value, _ := index.NewRecomputeAsk("a check", "ctl", time.Now()) + if r := answer(key, value); !r.Stored || !strings.Contains(r.Answer, "equal to the kept revision 1") { + t.Errorf("indexer_recompute answered %+v: want equal to the kept revision 1", r) + } + key, value, _ = index.NewDropCandidateGraphAsk("g1", "h1", "its gate event never came", "ctl", time.Now()) + if r := answer(key, value); !r.Stored || !slices.Equal(r.Dropped, []string{"entry.dx"}) { + t.Errorf("indexer_drop_candidate_graph answered %+v: want candidate.g1.h1 dropped with entry.dx", r) + } + if after, err := index.ListRevisions(ctx, objects, false); err != nil || len(after.Revisions) != 1 || after.Entries != list.Entries { + t.Errorf("revisions after the drop = %+v (%v): want trunk.1 and its entries alone", after, err) + } } // TestIndexerKeepsManifestsAtAMerge: a merged message of mesh-catalog carrying the real manifest of the module avahi and the