mesh/delivery closed: a newer head of the same pull request
mesh/check failed: unit: git.novox.be/novox/mesh-catalog/checks/nobinaries.TestTheCatalogueHoldsNoCompiledProgram: modules/mesh-config/cmd/mesh-config…
One commit for the branch feat/1126-nodes-compose of mesh-delivery: its 16 commits squashed so its history does not carry the 17.8 MB compiled mesh-delivery-assigner a commit added by mistake and a later one removed (issue 1577). The tree equals the former head ff6c038d. The operator allowed this rewrite of the feature branch on 2026-10-26.
239 lines
8.9 KiB
Go
239 lines
8.9 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
const (
|
|
trunkNow = "5555555555555555555555555555555555555555"
|
|
trunkOld = "4444444444444444444444444444444444444444"
|
|
mergeSha = "6666666666666666666666666666666666666666"
|
|
)
|
|
|
|
// A trunk of the catalogue with avahi (and the builder, a base and others) merged, the toolchain agreed, and the gate's source
|
|
// naming the catalogue's trunk head: avahi has a fingerprint of the new form at tree-avahi.
|
|
func previewBed(t *testing.T, report bool) (*Indexer, *memStore, *memStore) {
|
|
t.Helper()
|
|
ix, mods := newFormIndexer(t, builderModules(t)...)
|
|
if report {
|
|
reportToolchain(t, ix, "mesh-build-go", "novox", "go", "go1.27.1")
|
|
}
|
|
if err := ix.ApplySource(context.Background(), 5, delivery.Source{Group: "g", Heads: map[string]string{catalogueRepo: trunkNow}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return ix, mods, ix.Store.(*memStore)
|
|
}
|
|
|
|
// avahiOnTools is avahi's manifest as builderModules has it: standing on mesh-tools.
|
|
func avahiOnTools(t *testing.T) string {
|
|
return standingOn(t, catalogueManifest(t, "avahi"), "mesh-tools")
|
|
}
|
|
|
|
// avahiPull is the pull message of the catalogue's pull request 301 touching avahi, with its manifest.
|
|
func avahiPull(t *testing.T, head string) delivery.Forge {
|
|
t.Helper()
|
|
f := manifestPull(t, 301, head, avahiOnTools(t))
|
|
f.Manifests = map[string]string{"modules/avahi": avahiOnTools(t)}
|
|
return f
|
|
}
|
|
|
|
func avahiPreview(t *testing.T, trunk, head string) delivery.Preview {
|
|
return delivery.Preview{Repository: catalogueRepo, Head: head, Trunk: trunk, Merge: mergeSha, Modules: map[string]delivery.PreviewModule{
|
|
"modules/avahi": {Tree: "tree-avahi", Manifest: delivery.ManifestDigest([]byte(avahiOnTools(t))), Locks: map[string]string{"go.sum": avahiGoSum}}}}
|
|
}
|
|
|
|
func applyPreview(t *testing.T, ix *Indexer, pv delivery.Preview) {
|
|
t.Helper()
|
|
key, err := delivery.PreviewKey(pv.Repository, pv.Head, pv.Trunk)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := delivery.EncodePreview(pv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := ix.ApplyPreview(context.Background(), key, data, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func fpOf(t *testing.T, st *memStore) delivery.CandidateModule {
|
|
t.Helper()
|
|
c := candidateOf(t, st)
|
|
if len(c.Pulls) != 1 {
|
|
t.Fatalf("candidate = %+v", c)
|
|
}
|
|
return c.Pulls[0].Fps["avahi"]
|
|
}
|
|
|
|
func TestACandidatesModuleGetsTheFingerprintATrunkModuleOfTheSameTreeHas(t *testing.T) { // 1445/AC2
|
|
ix, mods, cands := previewBed(t, true)
|
|
trunk, _ := moduleOf(t, mods, "avahi")
|
|
if trunk.FP2 == "" {
|
|
t.Fatalf("the trunk's avahi has no fingerprint of the new form: %+v", trunk)
|
|
}
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := fpOf(t, cands); got.None2 != NoneNoPreview {
|
|
t.Fatalf("before the preview: %+v", got)
|
|
}
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
got := fpOf(t, cands)
|
|
if got.FP2 != trunk.FP2 || got.None2 != "" || got.Manifest != delivery.ManifestDigest([]byte(avahiOnTools(t))) {
|
|
t.Fatalf("candidate avahi = %+v, want the trunk's fingerprint %s", got, trunk.FP2)
|
|
}
|
|
c := candidateOf(t, cands)
|
|
if c.FPSet != delivery.FingerprintSet(c.Pulls) || c.FPSet == "" {
|
|
t.Errorf("fpset = %q", c.FPSet)
|
|
}
|
|
// The candidate names the source revision the preview was read onto (5, whose catalogue head is the preview's trunk):
|
|
// the builder merges the preview onto that head, never onto the module value's commit.
|
|
if c.Base != 5 {
|
|
t.Errorf("candidate base = %d, want the source revision 5 its preview was read onto", c.Base)
|
|
}
|
|
written(t, writtenCandidate{Source: sourceRev{Rev: 5, Heads: map[string]string{catalogueRepo: trunkNow}}, Candidate: c})
|
|
// Another tree gives another fingerprint.
|
|
pv := avahiPreview(t, trunkNow, h1)
|
|
m := pv.Modules["modules/avahi"]
|
|
m.Tree = "tree-changed"
|
|
pv.Modules["modules/avahi"] = m
|
|
pv.Merge = "7777777777777777777777777777777777777777"
|
|
applyPreview(t, ix, pv)
|
|
if other := fpOf(t, cands); other.FP2 == "" || other.FP2 == trunk.FP2 {
|
|
t.Errorf("a changed tree: %+v", other)
|
|
}
|
|
}
|
|
|
|
func TestAnUnknownToolchainLeavesTheCandidatesModuleNamingIt(t *testing.T) { // 1445/AC2
|
|
ix, _, cands := previewBed(t, false)
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
if got := fpOf(t, cands); got.FP2 != "" || !strings.Contains(got.None2, delivery.ToolchainNoReport) {
|
|
t.Errorf("candidate avahi = %+v, want none2 naming %q", got, delivery.ToolchainNoReport)
|
|
}
|
|
}
|
|
|
|
func TestAPreviewMadeOntoAnOldTrunkIsOutOfDate(t *testing.T) { // 1445/AC3
|
|
ix, _, cands := previewBed(t, true)
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
applyPreview(t, ix, avahiPreview(t, trunkOld, h1))
|
|
if got := fpOf(t, cands); got.FP2 != "" || got.None2 != NonePreviewStale {
|
|
t.Errorf("candidate avahi = %+v, want it out of date", got)
|
|
}
|
|
// A preview onto the trunk head now makes it good again, and the trunk moving again makes it stale.
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
if got := fpOf(t, cands); got.FP2 == "" {
|
|
t.Fatalf("after the right preview: %+v", got)
|
|
}
|
|
if err := ix.ApplySource(context.Background(), 6, delivery.Source{Group: "g", Heads: map[string]string{catalogueRepo: "8888888888888888888888888888888888888888"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := fpOf(t, cands); got.None2 != NonePreviewStale {
|
|
t.Errorf("after the trunk moved: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestAPreviewHeardBeforeItsPullRequestGivesTheFingerprintWhenTheCandidateIsWritten(t *testing.T) { // 1445/AC2
|
|
ix, mods, cands := previewBed(t, true)
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
trunk, _ := moduleOf(t, mods, "avahi")
|
|
if got := fpOf(t, cands); got.FP2 != trunk.FP2 {
|
|
t.Errorf("candidate avahi = %+v, want %s", got, trunk.FP2)
|
|
}
|
|
// The same pull request at a new head has no preview of it yet.
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h2)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := fpOf(t, cands); got.FP2 != "" || got.None2 != NoneNoPreview {
|
|
t.Errorf("a new head: %+v, want no preview", got)
|
|
}
|
|
}
|
|
|
|
func TestAPreviewNamingNoManifestOfTheModulesDirectoryGivesAReason(t *testing.T) {
|
|
t.Run("the same preview again", testTheSamePreviewAppliedAgainWritesNothing)
|
|
ix, _, cands := previewBed(t, true)
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pv := avahiPreview(t, trunkNow, h1)
|
|
pv.Modules = map[string]delivery.PreviewModule{"modules/other": pv.Modules["modules/avahi"]}
|
|
applyPreview(t, ix, pv)
|
|
if got := fpOf(t, cands); got.None2 != NonePreviewNoModule || !strings.Contains(NonePreviewNoModule, "manifest") {
|
|
t.Errorf("candidate avahi = %+v", got)
|
|
}
|
|
}
|
|
|
|
func testTheSamePreviewAppliedAgainWritesNothing(t *testing.T) {
|
|
ix, _, cands := previewBed(t, true)
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
w := cands.writes
|
|
applyPreview(t, ix, avahiPreview(t, trunkNow, h1))
|
|
if cands.writes != w {
|
|
t.Errorf("candidates written %d times for the same preview, want none", cands.writes-w)
|
|
}
|
|
}
|
|
|
|
func TestAPreviewOfConflictsGivesTheCandidatesModuleTheReasonItDoesNotMerge(t *testing.T) { // 1445/AC5
|
|
ix, _, cands := previewBed(t, true)
|
|
if err := ix.Apply(context.Background(), avahiPull(t, h1)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
applyPreview(t, ix, delivery.Preview{Repository: catalogueRepo, Head: h1, Trunk: trunkNow, Conflicts: []string{"modules/avahi/main.go", "go.mod"}})
|
|
got := fpOf(t, cands)
|
|
if got.FP2 != "" || !strings.HasPrefix(got.None2, "does not merge") || !strings.Contains(got.None2, "go.mod, modules/avahi/main.go") && !strings.Contains(got.None2, "modules/avahi/main.go, go.mod") {
|
|
t.Errorf("candidate avahi = %+v, want it not merging and naming the files", got)
|
|
}
|
|
}
|
|
|
|
// writtenCandidate is what the builder's tests read of the indexer (mesh-delivery-builder internal/build): a candidate as the
|
|
// indexer writes it and the gate's source revision it names, kept in testdata/candidate-written.json so the builder is tested
|
|
// on what the indexer writes, never on a candidate made by hand. MESH_WRITE_TESTDATA=1 writes it again.
|
|
type writtenCandidate struct {
|
|
Source sourceRev `json:"source"`
|
|
Candidate delivery.Candidate `json:"candidate"`
|
|
}
|
|
|
|
type sourceRev struct {
|
|
Rev uint64 `json:"rev"`
|
|
Heads map[string]string `json:"heads"`
|
|
}
|
|
|
|
func written(t *testing.T, w writtenCandidate) {
|
|
t.Helper()
|
|
data, err := json.MarshalIndent(w, "", " ")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data = append(data, '\n')
|
|
const file = "testdata/candidate-written.json"
|
|
if os.Getenv("MESH_WRITE_TESTDATA") == "1" {
|
|
if err := os.WriteFile(file, data, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
kept, err := os.ReadFile(file)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(kept) != string(data) {
|
|
t.Errorf("%s is not what the indexer writes now (MESH_WRITE_TESTDATA=1 writes it again):\n%s", file, data)
|
|
}
|
|
}
|