Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/manifests_test.go
T
jschoubben 9f7e082688 List a repository's modules from the merged message's manifests and the indexer's own bucket, not the controller's build records, so a new module gets a value and a key with no build asked (issue 1851, I1 I2 I4, ADR 0501 §6, ADR 0453 §6)
I1: a merge writes each module its manifests name, at its directory. I2: a pull request's changed directory, a
preview's touched module and a source revision's modules come from the modules bucket (a module a pull request adds is
found in the preview by its manifest). I4: the value of today's form (fp, none) is no longer written, since it was
computed from the build records; mesh-sdk keeps it readable until R4g. One commit: the three share applyMerged and its
tests. Pins mesh-sdk feat/r4e-sdk 9cb4d59.
2026-10-22 18:08:48 +02:00

104 lines
4.5 KiB
Go

package index
import (
"context"
"os"
"testing"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// The manifests these tests carry are real files, copied unchanged into testdata: the module.json of modules of
// mesh-catalog at its main commit a67f01963f0d9ef0913a63720b89e573ca7a16ef (testdata/catalogue-a67f0196-<module>.module.json)
// and of build-agent from mesh-controller at its main commit f2d7bc94 (testdata/controller-f2d7bc94-build-agent.module.json).
func fixture(t *testing.T, name string) string {
t.Helper()
b, err := os.ReadFile("testdata/" + name + ".module.json")
if err != nil {
t.Fatal(err)
}
return string(b)
}
func catalogueManifest(t *testing.T, module string) string {
return fixture(t, "catalogue-a67f0196-"+module)
}
// avahiGoSum is the sha256 of modules/avahi/go.sum in mesh-catalog at a67f0196 (sha256sum of that file).
const avahiGoSum = "3b5028f0c1e9bde04dd766abd63eb5931bc516bae695cf46f00abcd8510b0381"
const catalogueRepo = "novox/mesh-catalog"
func manifestsIndexer(t *testing.T, recs ...[2]any) (*Indexer, *memStore, *memStore) {
t.Helper()
ix, mods := modulesIndexer(t, recs...)
manifests := newMem()
ix.Manifests = manifests
return ix, mods, manifests
}
func withManifests(f delivery.Forge, manifests map[string]string, locks map[string]map[string]string) delivery.Forge {
f.Manifests, f.Locks = manifests, locks
return f
}
func TestAMergedManifestIsKeptByItsDigestAndNamedByTheModule(t *testing.T) { // 1449/AC1
avahi := catalogueManifest(t, "avahi")
ix, mods, manifests := manifestsIndexer(t, rec(t, "build-1", "avahi", catalogueRepo, "modules/avahi", "main", "", "2026-10-19T09:00:00Z", aInputs))
f := withManifests(mergedMsg(catalogueRepo, map[string]string{"modules/avahi": "newtree"}), map[string]string{"modules/avahi": avahi}, nil)
if err := ix.Apply(context.Background(), f); err != nil {
t.Fatal(err)
}
digest := delivery.ManifestDigest([]byte(avahi))
raw, ok := manifests.vals[digest]
if !ok || len(manifests.vals) != 1 {
t.Fatalf("manifests holds %d keys, want only %s", len(manifests.vals), digest)
}
m, err := delivery.DecodeManifest(raw)
if err != nil || m.Module != "avahi" || m.JSON != avahi {
t.Errorf("manifest = %+v err %v, want avahi and the bytes of the file", m, err)
}
if mod, ok := moduleOf(t, mods, "avahi"); !ok || mod.Manifest != digest {
t.Errorf("module = %+v (%v), want the manifest digest %s", mod, ok, digest)
}
}
func TestTheSameManifestAppliedAgainIsWrittenOnce(t *testing.T) { // 1449/AC2
avahi := catalogueManifest(t, "avahi")
ix, _, manifests := manifestsIndexer(t, rec(t, "build-1", "avahi", catalogueRepo, "modules/avahi", "main", "", "2026-10-19T09:00:00Z", aInputs))
f := withManifests(mergedMsg(catalogueRepo, map[string]string{"modules/avahi": "newtree"}), map[string]string{"modules/avahi": avahi}, nil)
if err := ix.Apply(context.Background(), f); err != nil {
t.Fatal(err)
}
// A second merge, and a pull message carrying it, the digest being the same.
f.Merge = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
if err := ix.Apply(context.Background(), f); err != nil {
t.Errorf("a second merge: %v", err)
}
pull := delivery.Forge{V: delivery.Version, Kind: delivery.ForgePull, Repository: catalogueRepo, Branch: "feat/x", Number: 301, Head: h1,
Action: delivery.PullUpdated, Dirs: []string{"modules/avahi"}, DirsKnown: true, Manifests: map[string]string{"modules/avahi": avahi}}
if err := ix.Apply(context.Background(), pull); err != nil {
t.Errorf("a pull message: %v", err)
}
if manifests.writes != 1 || len(manifests.vals) != 1 {
t.Errorf("manifests written %d times into %d keys, want once into one", manifests.writes, len(manifests.vals))
}
}
func TestAManifestThatCannotBeAValueIsLeftOutAndSaid(t *testing.T) { // 1449 (a manifest that is not JSON cannot be kept byte for byte)
var logs []string
ix, mods, manifests := manifestsIndexer(t, rec(t, "build-1", "avahi", catalogueRepo, "modules/avahi", "main", "", "2026-10-19T09:00:00Z", aInputs))
ix.Logf = func(format string, args ...any) { logs = append(logs, format) }
f := withManifests(mergedMsg(catalogueRepo, map[string]string{"modules/avahi": "newtree"}), map[string]string{"modules/avahi": "not json"}, nil)
if err := ix.Apply(context.Background(), f); err != nil {
t.Fatal(err)
}
if len(manifests.vals) != 0 || len(logs) == 0 {
t.Errorf("manifests %d keys, log %v", len(manifests.vals), logs)
}
// A manifest that is not JSON names no module (I1): nothing is written for its directory.
if mod, ok := moduleOf(t, mods, "avahi"); ok {
t.Errorf("module = %+v, want none written for a manifest naming no module", mod)
}
}