Test that declarationWith sets modules and builds for a node that reads them (issue 1145); the Approve of a head it did not cover refuses a new module, heads keyed by the repository (issue 1146)
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
//go:build integration
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/novox/mesh-controller/internal/link"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 1145/AC1 on a store: declarationWith itself sets the module of each resource and the build of each module for a
|
||||||
|
// node recorded as reading them, and for no other. Skips without a store.
|
||||||
|
func TestAComposedDeclarationCarriesModulesAndBuildsOnlyForANodeThatReadsThem(t *testing.T) {
|
||||||
|
open := aMesh(t)
|
||||||
|
ctx := t.Context()
|
||||||
|
inv := open.inventory
|
||||||
|
start := time.Now().Add(-time.Hour)
|
||||||
|
manifest := resticFixture(false)
|
||||||
|
manifest["module"], manifest["version"] = "restic", "1"
|
||||||
|
raw, _ := json.Marshal(manifest)
|
||||||
|
b := link.BuildResult{ID: link.NewBuildID(start), Repository: "novox/mesh-catalog", Path: "modules/restic",
|
||||||
|
On: "anchor", Module: "restic", Commit: "c1", Manifest: raw,
|
||||||
|
Source: &link.SourceOnSeat{Seat: "git", Repository: "novox/mesh-catalog"}}
|
||||||
|
if _, _, err := takeIn(ctx, inv, asTheOperator(t, inv, b)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, n := range []string{"anchor", "laptop"} {
|
||||||
|
if _, err := inv.Assign(ctx, n, "restic"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anchor, err := inv.NodeByName(ctx, "anchor")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := inv.RecordReadsModules(ctx, anchor.ID, true); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
wantBuild, err := inv.BuildOf(ctx, "restic", "c1")
|
||||||
|
if err != nil || wantBuild == "" {
|
||||||
|
t.Fatalf("the build of restic at c1 is %q (%v)", wantBuild, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
declare := func(node string) sendable {
|
||||||
|
t.Helper()
|
||||||
|
plan, settings, err := planFor(ctx, open, node)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gens, err := generators(ctx, open)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d, err := declarationWith(ctx, open, node, plan, settings, gens, Allocating)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
reads := bodyKeys(t, declare("anchor"))
|
||||||
|
builds, _ := reads["builds"].(map[string]any)
|
||||||
|
if builds["restic"] != wantBuild {
|
||||||
|
t.Errorf("1145/AC1: anchor reads modules and was sent builds %v, want restic at %s", reads["builds"], wantBuild)
|
||||||
|
}
|
||||||
|
owned := 0
|
||||||
|
for _, r := range reads["resources"].([]any) {
|
||||||
|
r := r.(map[string]any)
|
||||||
|
if strings.HasPrefix(r["id"].(string), "restic.") {
|
||||||
|
owned++
|
||||||
|
if r["module"] != "restic" {
|
||||||
|
t.Errorf("1145/AC1: resource %v carries module %v, want restic", r["id"], r["module"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if owned == 0 {
|
||||||
|
t.Fatal("1145/AC1: no resource of restic was composed")
|
||||||
|
}
|
||||||
|
|
||||||
|
plain := bodyKeys(t, declare("laptop"))
|
||||||
|
if _, there := plain["builds"]; there {
|
||||||
|
t.Errorf("1145/AC1: laptop never said it reads modules and was sent builds %v", plain["builds"])
|
||||||
|
}
|
||||||
|
for _, r := range plain["resources"].([]any) {
|
||||||
|
if _, there := r.(map[string]any)["module"]; there {
|
||||||
|
t.Fatalf("1145/AC1: laptop was sent a module on %v", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,24 @@ func (m *anEmptyMesh) MergeOf(context.Context, string, string) (inventory.Batche
|
|||||||
return m.merge, true, nil
|
return m.merge, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// aDeliveryMergeOf is the Approved merge of a pull request of novox/mesh-delivery, its heads keyed by that repository,
|
||||||
|
// and the ask and warrant bound to exactly those heads (the digest the Approve left covers them).
|
||||||
|
func aDeliveryMergeOf(t *testing.T, head string, covered map[string]string) anApprovedMerge {
|
||||||
|
t.Helper()
|
||||||
|
a := approvedMerge(t)
|
||||||
|
a.merge.Owner, a.merge.Repo, a.merge.Number, a.merge.HeadSHA = "novox", "mesh-delivery", 7, head
|
||||||
|
a.merge.Heads = covered
|
||||||
|
for n := range a.ask.Options {
|
||||||
|
d, err := asks.ActDigest(mergeAct(a.merge.AskID, a.ask.Options[n].ID, covered))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
a.ask.Options[n].Binds = d
|
||||||
|
}
|
||||||
|
a.warrant.AskDigest = a.ask.Digest()
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
func TestANewModuleIsRegisteredOnTheOperatorsApproveOfItsMergeAndRefusedOtherwise(t *testing.T) {
|
func TestANewModuleIsRegisteredOnTheOperatorsApproveOfItsMergeAndRefusedOtherwise(t *testing.T) {
|
||||||
const commit, head = "c0ffee0123456789", "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"
|
const commit, head = "c0ffee0123456789", "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"
|
||||||
built := inventory.Source{Repository: "novox/mesh-delivery", Seat: "git"}
|
built := inventory.Source{Repository: "novox/mesh-delivery", Seat: "git"}
|
||||||
@@ -53,8 +71,12 @@ func TestANewModuleIsRegisteredOnTheOperatorsApproveOfItsMergeAndRefusedOtherwis
|
|||||||
{what: "the Approve of the merged head, a protected trunk on the forge", request: "merge", accepted: true, ac: "1146/AC1"},
|
{what: "the Approve of the merged head, a protected trunk on the forge", request: "merge", accepted: true, ac: "1146/AC1"},
|
||||||
{what: "a build asked through a verb", request: "build", ac: "1146/AC2"},
|
{what: "a build asked through a verb", request: "build", ac: "1146/AC2"},
|
||||||
{what: "a merge with no warrant", request: "merge", unkept: true, ac: "1146/AC2"},
|
{what: "a merge with no warrant", request: "merge", unkept: true, ac: "1146/AC2"},
|
||||||
{what: "a warrant of another head", request: "merge", ac: "1146/AC2", change: func(a *anApprovedMerge) {
|
{what: "a merged head the Approve did not cover", request: "merge", ac: "1146/AC2", change: func(a *anApprovedMerge) {
|
||||||
a.merge.Heads = map[string]string{"novox/mesh-host@aaaaaaaaaaaa": "e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5"}
|
*a = aDeliveryMergeOf(t, head, map[string]string{
|
||||||
|
"novox/mesh-delivery@eeeeeeeeeeee": "e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5"})
|
||||||
|
}},
|
||||||
|
{what: "heads other than the ones the Approve was bound to", request: "merge", ac: "1146/AC2", change: func(a *anApprovedMerge) {
|
||||||
|
a.merge.Heads = map[string]string{"novox/mesh-delivery@eeeeeeeeeeee": "e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5"}
|
||||||
}},
|
}},
|
||||||
{what: "a repository not on the mesh's forge", request: "merge", ac: "1146/AC3",
|
{what: "a repository not on the mesh's forge", request: "merge", ac: "1146/AC3",
|
||||||
built: &inventory.Source{Repository: "http://elsewhere.example/x/y.git"}},
|
built: &inventory.Source{Repository: "http://elsewhere.example/x/y.git"}},
|
||||||
@@ -62,8 +84,7 @@ func TestANewModuleIsRegisteredOnTheOperatorsApproveOfItsMergeAndRefusedOtherwis
|
|||||||
{what: "an unprotected trunk", request: "merge", ac: "1146/AC3", forge: forgeFacts{ID: 9, Guarded: false, Why: "direct push"}},
|
{what: "an unprotected trunk", request: "merge", ac: "1146/AC3", forge: forgeFacts{ID: 9, Guarded: false, Why: "direct push"}},
|
||||||
} {
|
} {
|
||||||
t.Run(c.ac+" "+c.what, func(t *testing.T) {
|
t.Run(c.ac+" "+c.what, func(t *testing.T) {
|
||||||
a := approvedMerge(t)
|
a := aDeliveryMergeOf(t, head, map[string]string{"novox/mesh-delivery@a1a1a1a1a1a1": head})
|
||||||
a.merge.Owner, a.merge.Repo, a.merge.Number, a.merge.HeadSHA = "novox", "mesh-delivery", 7, head
|
|
||||||
if c.change != nil {
|
if c.change != nil {
|
||||||
c.change(&a)
|
c.change(&a)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ func TestANewModuleFromANewRepositoryIsRegisteredOnlyOnTheOperatorsApproveOnTheB
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := approvedMerge(t)
|
a := aDeliveryMergeOf(t, "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
|
||||||
a.merge.Owner, a.merge.Repo, a.merge.Number = "novox", "mesh-delivery", 7
|
map[string]string{"novox/mesh-delivery@a1a1a1a1a1a1": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"})
|
||||||
if c.answer {
|
if c.answer {
|
||||||
record, _ := json.Marshal(map[string]any{"state": "closed", "ask": a.ask, "warrant": a.warrant})
|
record, _ := json.Marshal(map[string]any{"state": "closed", "ask": a.ask, "warrant": a.warrant})
|
||||||
if _, err := records.Put(ctx, theDelivery+"."+a.merge.AskID, record); err != nil {
|
if _, err := records.Put(ctx, theDelivery+"."+a.merge.AskID, record); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user