404 lines
18 KiB
Go
404 lines
18 KiB
Go
package build
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// R4e: references in the key (novox/hq ADR 0498), upstream copies, packages published from the trunk, the package wait
|
|
// (ADR 0500 clause 6) and one node per fingerprint (ADR 0478 clause 4).
|
|
|
|
func TestACandidatesBundleKeyNamesItsReferenceAndTheTrunkBuildsItNoMore(t *testing.T) { // B1, ADR 0498 clause 3 and its check 3
|
|
r := newRig(t, goBundle, archiveA)
|
|
trunkModule(t, r)
|
|
r.b.Candidate(context.Background(), "feat%2Fx", candidateValue(t, "feat/x", 7, headX))
|
|
r.b.Wait()
|
|
v := valueOf(t, r.st, r.key)
|
|
if v.State != delivery.BuildDone {
|
|
t.Fatalf("build = %+v, want done", v)
|
|
}
|
|
if ok, missing := v.Referenced(); !ok {
|
|
t.Fatalf("a candidate's bundle and archive name no reference: %v (%+v)", missing, v.Artifacts)
|
|
}
|
|
rev := r.st.revs[r.key]
|
|
r.bm.mu.Lock()
|
|
r.bm.calls = nil
|
|
r.bm.mu.Unlock()
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m")) // the merge: the trunk now names the same fingerprint
|
|
r.b.Wait()
|
|
if n := len(r.bm.calls); n != 0 || r.st.revs[r.key] != rev {
|
|
t.Errorf("the trunk built its candidate's fingerprint again: %d calls, revision %d (was %d)", n, r.st.revs[r.key], rev)
|
|
}
|
|
}
|
|
|
|
func TestABundleWhosePushAnsweredNoReferenceFailsNotStoredAndIsBuiltAgain(t *testing.T) { // B1, ADR 0498 clauses 1 and 2
|
|
r := newRig(t, goBundle)
|
|
r.bm.noRef["ace/tool"] = true
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildFailed || !strings.HasPrefix(v.Error, delivery.NotStored) || !strings.Contains(v.Error, "tool") {
|
|
t.Fatalf("build = %+v, want failed opening %q and naming the artifact", v, delivery.NotStored)
|
|
}
|
|
delete(r.bm.noRef, "ace/tool")
|
|
if v = r.consider(t, "modules/m"); v.State != delivery.BuildDone {
|
|
t.Errorf("build = %+v, want a not-stored key built again as a new revision", v)
|
|
}
|
|
}
|
|
|
|
func TestAPushRefusedByTheStoreFailsTheKeyOpeningNotStored(t *testing.T) { // B1, ADR 0498 clause 2
|
|
r := newRig(t, goBundle)
|
|
r.bm.fails["ace/build_go_build"] = delivery.NotStored + "tool: the artifact store answered 507 insufficient storage"
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildFailed || !strings.HasPrefix(v.Error, delivery.NotStored) || !strings.Contains(v.Error, "507") || !strings.Contains(v.Error, "ace") {
|
|
t.Fatalf("build = %+v, want failed opening %q with the store's words and the node", v, delivery.NotStored)
|
|
}
|
|
}
|
|
|
|
func TestOnlyATrunkKeysBuildsAreAskedToPublish(t *testing.T) { // B1, the lead's interface (a): publish only for a trunk key
|
|
r := newRig(t, goBundle)
|
|
r.consider(t, "modules/m")
|
|
for _, c := range r.bm.callsOf("build_go_build") {
|
|
if c.body.(map[string]any)["publish"] != true {
|
|
t.Errorf("trunk build args = %+v, want publish", c.body)
|
|
}
|
|
}
|
|
c := newRig(t, goBundle)
|
|
trunkModule(t, c)
|
|
c.b.Candidate(context.Background(), "feat%2Fx", candidateValue(t, "feat/x", 7, headX))
|
|
c.b.Wait()
|
|
for _, call := range c.bm.callsOf("build_go_build") {
|
|
if _, ok := call.body.(map[string]any)["publish"]; ok {
|
|
t.Errorf("candidate build args = %+v, want no publish", call.body)
|
|
}
|
|
}
|
|
}
|
|
|
|
// putBuild writes a builder key's value as the store would hold it.
|
|
func putBuild(t *testing.T, st *memStore, key string, b delivery.BuilderBuild) uint64 {
|
|
t.Helper()
|
|
data, err := delivery.EncodeBuilderBuild(b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
st.mu.Lock()
|
|
defer st.mu.Unlock()
|
|
return st.put(key, data)
|
|
}
|
|
|
|
func TestADoneKeyWrittenBeforeR4eIsBuiltAgainOnceAsANewRevision(t *testing.T) { // B2, ADR 0498 clause 8
|
|
r := newRig(t, goBundle, archiveA)
|
|
rev := putBuild(t, r.st, r.key, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.builder", Manifest: manifestD, Step: "built mesh-build-go on ace and novox",
|
|
Artifacts: []delivery.BuiltArtifact{{Name: "files", Kind: "archive", Digest: digest}, {Name: "tool", Kind: "bundle", Digest: digest}}})
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildDone || r.st.revs[r.key] <= rev {
|
|
t.Fatalf("build = %+v at revision %d (was %d), want built again as a new revision", v, r.st.revs[r.key], rev)
|
|
}
|
|
if ok, missing := v.Referenced(); !ok {
|
|
t.Fatalf("the new revision names no reference for %v", missing)
|
|
}
|
|
rev = r.st.revs[r.key]
|
|
r.b.tried = map[string]bool{} // a builder started anew looks again
|
|
r.consider(t, "modules/m")
|
|
if r.st.revs[r.key] != rev {
|
|
t.Errorf("a key whose artifacts all name references was built again (revision %d, was %d): once only", r.st.revs[r.key], rev)
|
|
}
|
|
}
|
|
|
|
func TestAPinnedUpstreamIsCopiedOnceOnOneImageNodeWithNoFetchAndItsKeyNamesTheReference(t *testing.T) { // B4, ADR 0498 clause 4
|
|
up := catalogue.Artifact{Name: "up", Kind: "upstream", From: "nats:2.11.17-alpine@" + digest}
|
|
r := newRig(t, up)
|
|
r.puller = "ace"
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildDone || len(v.Artifacts) != 1 {
|
|
t.Fatalf("build = %+v, want done with the copy", v)
|
|
}
|
|
if a := v.Artifacts[0]; a.Kind != "upstream" || a.Digest != digest || a.Reference != "registry.example/m/up@"+digest {
|
|
t.Errorf("artifact = %+v, want the upstream's digest and the registry's reference", a)
|
|
}
|
|
copies := r.bm.callsOf("build_image_copy")
|
|
if len(copies) != 1 {
|
|
t.Fatalf("%d copies, want one on one node", len(copies))
|
|
}
|
|
if args := copies[0].body.(map[string]any); args["module"] != "m" || args["artifact"] != "up" || args["from"] != up.From || len(args) != 3 {
|
|
t.Errorf("copy args = %+v, want the module's name, the artifact and the pinned reference", args)
|
|
}
|
|
if n := len(r.bm.callsOf("build_image_fetch")) + len(r.bm.callsOf("build_image_build")); n != 0 {
|
|
t.Errorf("%d fetch or build calls for a copy, want none", n)
|
|
}
|
|
}
|
|
|
|
func TestAnUpstreamBesideAnImageIsCopiedAndTheImageFetchedAndBuiltOnTheSameNode(t *testing.T) { // B4
|
|
r := newRig(t, imageArt, catalogue.Artifact{Name: "up", Kind: "upstream", From: "nats:2.11.17-alpine@" + digest})
|
|
r.puller = "ace"
|
|
v := r.consider(t, "modules/m")
|
|
if ok, missing := v.Referenced(); !ok {
|
|
t.Fatalf("build = %+v, missing references %v", v, missing)
|
|
}
|
|
if f, b, c := len(r.bm.callsOf("build_image_fetch")), len(r.bm.callsOf("build_image_build")), len(r.bm.callsOf("build_image_copy")); f != 1 || b != 1 || c != 1 {
|
|
t.Errorf("fetch %d, build %d, copy %d; want one each", f, b, c)
|
|
}
|
|
}
|
|
|
|
func TestACopyThatFailsNotStoredFailsTheKeyAndIsBuiltAgain(t *testing.T) { // B4, ADR 0498 clause 2
|
|
r := newRig(t, catalogue.Artifact{Name: "up", Kind: "upstream", From: "nats:2.11.17-alpine@" + digest})
|
|
r.puller = "ace"
|
|
r.bm.fails["ace/build_image_copy"] = delivery.NotStored + "up: the registry answered 500"
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildFailed || !strings.HasPrefix(v.Error, delivery.NotStored) || delivery.FailedUntilChanged(v.Error) {
|
|
t.Fatalf("build = %+v, want failed 'not stored:' and built again", v)
|
|
}
|
|
delete(r.bm.fails, "ace/build_image_copy")
|
|
if v = r.consider(t, "modules/m"); v.State != delivery.BuildDone {
|
|
t.Errorf("build = %+v, want done on the new revision", v)
|
|
}
|
|
}
|
|
|
|
var tsPackage = catalogue.Artifact{Name: "lib", Kind: "package", Language: "typescript"}
|
|
|
|
func TestATypeScriptPackageIsBuiltByTheNodeModuleAndPublishedOnlyForTheTrunk(t *testing.T) { // B5, ADR 0498 clause 5, ADR 0500 clause 4
|
|
c := newRig(t, tsPackage)
|
|
c.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
trunkModule(t, c)
|
|
c.b.Candidate(context.Background(), "feat%2Fx", candidateValue(t, "feat/x", 7, headX))
|
|
c.b.Wait()
|
|
v := valueOf(t, c.st, c.key)
|
|
if v.State != delivery.BuildDone || len(v.Artifacts) != 1 || v.Artifacts[0].Kind != "package" || v.Artifacts[0].Reference != "" {
|
|
t.Fatalf("candidate build = %+v, want done with the packed digest and no reference", v)
|
|
}
|
|
for _, call := range c.bm.callsOf("build_node_build") {
|
|
if _, ok := call.body.(map[string]any)["publish"]; ok {
|
|
t.Errorf("a candidate's package build was asked to publish: %+v", call.body)
|
|
}
|
|
}
|
|
|
|
r := newRig(t, tsPackage)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
v = r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildDone || v.Artifacts[0].Reference != "@novox/mesh-sdk@0.1.15" {
|
|
t.Fatalf("trunk build = %+v, want done naming the published version", v)
|
|
}
|
|
if n := len(r.bm.callsOf("build_node_build")); n == 0 {
|
|
t.Error("the package was not built by the Node build module")
|
|
}
|
|
}
|
|
|
|
func TestAVersionTakenFailsTheKeyUntilTheFingerprintChanges(t *testing.T) { // B5, ADR 0498 clause 5
|
|
r := newRig(t, tsPackage)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
r.bm.fails["ace/build_node_build"] = delivery.VersionTaken + "@novox/mesh-sdk@0.1.15 is published with another packed file"
|
|
r.bm.fails["novox/build_node_build"] = r.bm.fails["ace/build_node_build"]
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildFailed || !strings.HasPrefix(v.Error, delivery.VersionTaken) || !strings.Contains(v.Error, "0.1.15") {
|
|
t.Fatalf("build = %+v, want failed opening %q naming the version", v, delivery.VersionTaken)
|
|
}
|
|
writes := r.st.writes
|
|
r.consider(t, "modules/m")
|
|
if r.st.writes != writes {
|
|
t.Errorf("a version-taken key was built again (%d writes, was %d)", r.st.writes, writes)
|
|
}
|
|
}
|
|
|
|
func TestACandidatesPackageIsPublishedOnceWhenTheTrunkNamesItsFingerprint(t *testing.T) { // B6, ADR 0498 clause 6
|
|
r := newRig(t, tsPackage, tsBundle)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
trunkModule(t, r)
|
|
r.b.Candidate(context.Background(), "feat%2Fx", candidateValue(t, "feat/x", 7, headX))
|
|
r.b.Wait()
|
|
if v := valueOf(t, r.st, r.key); v.State != delivery.BuildDone {
|
|
t.Fatalf("candidate build = %+v", v)
|
|
}
|
|
rev := r.st.revs[r.key]
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m")) // the merge names the candidate's fingerprint
|
|
r.b.Wait()
|
|
v := valueOf(t, r.st, r.key)
|
|
if r.st.revs[r.key] <= rev {
|
|
t.Fatalf("the trunk did not build the unpublished package again (revision %d, was %d)", r.st.revs[r.key], rev)
|
|
}
|
|
if ok, missing := v.Referenced(); !ok {
|
|
t.Fatalf("build = %+v, missing references %v", v, missing)
|
|
}
|
|
rev = r.st.revs[r.key]
|
|
r.b.tried = map[string]bool{}
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m"))
|
|
r.b.Wait()
|
|
if r.st.revs[r.key] != rev {
|
|
t.Error("a published package was built again: once only")
|
|
}
|
|
}
|
|
|
|
func TestAPublishThatFailsVersionTakenOnTheTrunkKeepsThePrefixFirst(t *testing.T) { // B6, ADR 0498 clauses 5 and 6
|
|
r := newRig(t, tsPackage)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
trunkModule(t, r)
|
|
r.b.Candidate(context.Background(), "feat%2Fx", candidateValue(t, "feat/x", 7, headX))
|
|
r.b.Wait()
|
|
for _, n := range []string{"ace", "novox"} {
|
|
r.bm.fails[n+"/build_node_build"] = delivery.VersionTaken + "@novox/mesh-sdk@0.1.15 is published with another packed file"
|
|
}
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m"))
|
|
r.b.Wait()
|
|
if v := valueOf(t, r.st, r.key); v.State != delivery.BuildFailed || !strings.HasPrefix(v.Error, delivery.VersionTaken) {
|
|
t.Errorf("build = %+v, want failed opening %q", v, delivery.VersionTaken)
|
|
}
|
|
}
|
|
|
|
// sdkModule adds to the rig a module "sdk" whose manifest (digest b) holds the TypeScript package lib, published as ref.
|
|
func sdkModule(t *testing.T, r *rig, ref string) []byte {
|
|
t.Helper()
|
|
r.mf.byDigest[mdigest('b')] = catalogue.Manifest{Module: "sdk", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{tsPackage}}}
|
|
r.bm.packages["lib"] = ref
|
|
data, err := delivery.EncodeModule(delivery.Module{Repository: "novox/mesh-sdk", Commit: "8a74cee83f88e6585a5511c3cc53bdf0f5303d20", FP2: "src2:" + hex64('5'),
|
|
Manifest: mdigest('b'), Path: ".", Toolchains: agreedToolchains})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func TestAModuleWhoseLockNamesAnUnpublishedPackageWaitsQueuedAndIsBuiltOncePublished(t *testing.T) { // B7, ADR 0500 clause 6
|
|
const ref = "@novox/mesh-sdk@0.1.15"
|
|
r := newRig(t, tsBundle)
|
|
for _, n := range []string{"ace", "novox"} {
|
|
r.bm.fails[n+"/build_node_fetch"] = waitsFor + ref + ": the lock names a version the registry does not hold"
|
|
}
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildQueued || v.Waits != ref || v.Error != "" {
|
|
t.Fatalf("build = %+v, want queued, waiting for %s, not failed", v, ref)
|
|
}
|
|
delete(r.bm.fails, "ace/build_node_fetch")
|
|
delete(r.bm.fails, "novox/build_node_fetch")
|
|
writes := r.st.writes
|
|
r.b.tried = map[string]bool{}
|
|
r.consider(t, "modules/m")
|
|
if r.st.writes != writes {
|
|
t.Fatalf("a key waiting for an unpublished package was claimed (%d writes, was %d)", r.st.writes, writes)
|
|
}
|
|
r.b.Module(context.Background(), "sdk", sdkModule(t, r, ref)) // the package's trunk key is built and published
|
|
r.b.Wait()
|
|
if v = valueOf(t, r.st, r.key); v.State != delivery.BuildDone || v.Waits != "" {
|
|
t.Errorf("build = %+v, want built once the package it waits for is published", v)
|
|
}
|
|
}
|
|
|
|
func TestAKeyWaitingForAPackageAlreadyPublishedIsBuiltWhenTheBuilderStarts(t *testing.T) { // B7: the scan at start
|
|
const ref = "@novox/mesh-sdk@0.1.15"
|
|
r := newRig(t, tsBundle)
|
|
putBuild(t, r.st, r.key, delivery.BuilderBuild{State: delivery.BuildQueued, By: "novox.builder", Manifest: manifestD, Waits: ref, Step: "waits"})
|
|
sdkKey, _ := delivery.BuilderBuildKey("sdk", "src2:"+hex64('5'))
|
|
putBuild(t, r.st, sdkKey, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.builder", Manifest: mdigest('b'), Step: "built",
|
|
Artifacts: []delivery.BuiltArtifact{{Name: "lib", Kind: "package", Digest: digest, Reference: ref}}})
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m"))
|
|
if err := r.b.Sweep(context.Background()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r.b.Wait()
|
|
if v := valueOf(t, r.st, r.key); v.State != delivery.BuildDone {
|
|
t.Errorf("build = %+v, want built: the package it waits for was published before the builder started", v)
|
|
}
|
|
}
|
|
|
|
func TestTheFetchOfAModuleNamingItsPathsCarriesItsDirectoryAndThosePaths(t *testing.T) { // the lead's interface (c), ADR 0499 clause 4
|
|
r := newRig(t, tsPackage)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
paths := map[string]string{"src": hex40('1'), "package.json": hex40('2')}
|
|
tree, err := delivery.NamedTree(manifestD, paths)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := delivery.EncodeModule(delivery.Module{Repository: "novox/mesh-sdk", Commit: "7a74cee83f88e6585a5511c3cc53bdf0f5303d20", FP2: fp1, Manifest: manifestD, Path: ".",
|
|
Toolchains: agreedToolchains, Inputs2: &delivery.KeptInputs2{Tree: tree, Paths: paths}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r.b.Module(context.Background(), "m", data)
|
|
r.b.Wait()
|
|
f := r.bm.callsOf("build_node_fetch")
|
|
if len(f) == 0 {
|
|
t.Fatal("no fetch")
|
|
}
|
|
req, err := buildstep.ParseFetchRequest(f[0].body.(map[string]any))
|
|
if err != nil || req.Dir != "." || strings.Join(req.Paths, ",") != "package.json,src" || req.Commit != "7a74cee83f88e6585a5511c3cc53bdf0f5303d20" {
|
|
t.Errorf("fetch request = %+v, %v; want dir . and the kept paths, sorted", req, err)
|
|
}
|
|
r2 := newRig(t, goBundle)
|
|
r2.consider(t, "modules/m")
|
|
if a := r2.bm.callsOf("build_go_fetch")[0].body.(map[string]any); a["dir"] != nil || a["paths"] != nil {
|
|
t.Errorf("fetch args = %+v, want no dir or paths for a module naming none", a)
|
|
}
|
|
}
|
|
|
|
func hex40(c byte) string { return strings.Repeat(string(c), 40) }
|
|
|
|
func TestOneNodeBuildsEachFingerprint(t *testing.T) { // B9, ADR 0478 clause 4: "From R4e one node builds each fingerprint"
|
|
r := newRig(t, goBundle, archiveA, tsBundle) // ace and novox both qualify for both build modules
|
|
v := r.consider(t, "modules/m")
|
|
if v.State != delivery.BuildDone || strings.Contains(v.Step, " and ") || strings.HasPrefix(v.Step, "one node (") {
|
|
t.Fatalf("build = %+v, want done on one node of each build module, unmarked", v)
|
|
}
|
|
if f, b := len(r.bm.callsOf("build_go_fetch")), len(r.bm.callsOf("build_go_build")); f != 1 || b != 2 {
|
|
t.Errorf("go fetches %d, builds %d; want one fetch and one build of each artifact, on one node", f, b)
|
|
}
|
|
if f := len(r.bm.callsOf("build_node_fetch")); f != 1 {
|
|
t.Errorf("node fetches %d, want one", f)
|
|
}
|
|
}
|
|
|
|
func TestAKeyDoneOnOneNodeIsNeverBuiltAgainForASecondNode(t *testing.T) { // B9: the second-node retake is gone
|
|
r := newRig(t, goBundle)
|
|
putBuild(t, r.st, r.key, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.builder", Manifest: manifestD,
|
|
Step: "one node (mesh-build-go): built mesh-build-go on one node, novox",
|
|
Artifacts: []delivery.BuiltArtifact{{Name: "tool", Kind: "bundle", Digest: digest, Reference: "artifact-store://m/tool/blobs/" + digest}}})
|
|
writes := r.st.writes
|
|
r.b.Module(context.Background(), "m", moduleValue(t, "modules/m"))
|
|
r.b.NodesChanged(context.Background())
|
|
r.b.Wait()
|
|
if r.st.writes != writes || len(r.bm.calls) != 0 {
|
|
t.Errorf("a key done on one node was built again (%d writes, was %d; %d calls)", r.st.writes, writes, len(r.bm.calls))
|
|
}
|
|
}
|
|
|
|
func TestACandidatesFetchNamesTheNamedPathsTheIndexerGaveIt(t *testing.T) { // ADR 0499 clause 4, mesh-sdk CandidateModule.Paths
|
|
r := newRig(t, tsPackage)
|
|
r.bm.packages["lib"] = "@novox/mesh-sdk@0.1.15"
|
|
trunkModule(t, r)
|
|
pulls := []delivery.CandidatePull{{Head: delivery.Head{Repository: "novox/mesh-catalog", Number: 7, Head: headX}, Modules: []string{"m"},
|
|
Fps: map[string]delivery.CandidateModule{"m": {FP2: fp1, Manifest: mdigest('a'), Paths: map[string]string{"src": hex40('1'), "package.json": hex40('2')}}}}}
|
|
hash, _ := delivery.HeadsHash([]delivery.Head{pulls[0].Head})
|
|
data, err := delivery.EncodeCandidate(delivery.Candidate{V: delivery.Version, Group: "feat/x", HeadsHash: hash, Pulls: pulls, FPSet: delivery.FingerprintSet(pulls)})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r.b.Candidate(context.Background(), "feat%2Fx", data)
|
|
r.b.Wait()
|
|
f := r.bm.callsOf("build_node_fetch")
|
|
if len(f) == 0 {
|
|
t.Fatal("no fetch")
|
|
}
|
|
req, err := buildstep.ParseFetchRequest(f[0].body.(map[string]any))
|
|
if err != nil || req.Dir != "modules/m" || strings.Join(req.Paths, ",") != "package.json,src" || req.Base == "" {
|
|
t.Errorf("fetch request = %+v, %v; want the candidate's base, the module's directory and its named paths", req, err)
|
|
}
|
|
}
|
|
|
|
// 1886/AC5: the builder tells who answered a reference: the build module whose step named one, and none for a step that
|
|
// answered a digest alone (a build module from before R4e).
|
|
func TestTheBuilderTellsWhichBuildModuleAnsweredAReference(t *testing.T) {
|
|
r := newRig(t, goBundle)
|
|
var answered []string
|
|
r.b.Answered = func(module string) { answered = append(answered, module) }
|
|
r.bm.noRef["ace/tool"] = true
|
|
r.consider(t, "modules/m")
|
|
if len(answered) != 0 {
|
|
t.Fatalf("a step that answered no reference was told as one: %v", answered)
|
|
}
|
|
delete(r.bm.noRef, "ace/tool")
|
|
r.consider(t, "modules/m")
|
|
if len(answered) != 1 || answered[0] != "mesh-build-go" {
|
|
t.Fatalf("the build module that answered a reference: %v, want mesh-build-go", answered)
|
|
}
|
|
}
|