Register a new module from the builder's first done key and ask no first build; its condition reads the key and names a manifest word this controller does not read (issue 1851, A5a, A5b)
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
"github.com/novox/mesh-controller/internal/broker"
|
||||
"github.com/novox/mesh-controller/internal/testbus"
|
||||
)
|
||||
|
||||
// builderOnTheBus is the builder's and the indexer's buckets on a test's own bus, which the controller's connection for
|
||||
// the moment (servingBus) reaches: what a take-in from a key reads (R4e, issue 1851).
|
||||
type builderOnTheBus struct {
|
||||
js *broker.JetStream
|
||||
builds, modules, manifests jetstream.KeyValue
|
||||
}
|
||||
|
||||
func aBuilderOnTheBus(t *testing.T) builderOnTheBus {
|
||||
t.Helper()
|
||||
js, err := broker.Dial(testbus.URL(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(js.Close)
|
||||
api, err := jetstream.New(js.Conn())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx := t.Context()
|
||||
b := builderOnTheBus{js: js}
|
||||
for _, c := range []struct {
|
||||
into *jetstream.KeyValue
|
||||
bucket string
|
||||
history uint8
|
||||
}{
|
||||
{&b.builds, sdkdelivery.BuilderBuildsBucket, sdkdelivery.BuilderBuildsHistory},
|
||||
{&b.modules, sdkdelivery.ModulesBucket, sdkdelivery.ModulesHistory},
|
||||
{&b.manifests, sdkdelivery.ManifestsBucket, 1},
|
||||
} {
|
||||
kv, err := api.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: c.bucket, History: c.history})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
*c.into = kv
|
||||
}
|
||||
servingBus.Store(js)
|
||||
t.Cleanup(func() { servingBus.Store(nil) })
|
||||
withTrunkList(t, true)
|
||||
return b
|
||||
}
|
||||
|
||||
// indexed writes the indexer's trunk value of module at commit, naming fp, and its manifest: a module of one archive.
|
||||
func (b builderOnTheBus) indexed(t *testing.T, module, version, repository, path, commit, fp string) string {
|
||||
t.Helper()
|
||||
keys, trunk := aKeyFor(module, version, fp, repository, path, commit)
|
||||
raw := keys.manifests[trunk.Manifest]
|
||||
value, err := sdkdelivery.EncodeManifest(sdkdelivery.Manifest{Module: module, JSON: raw})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := b.manifests.Put(context.Background(), trunk.Manifest, value); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
trunk.FP = "src1:" + fp[len("src2:"):]
|
||||
encoded, err := sdkdelivery.EncodeModule(trunk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := b.modules.Put(context.Background(), module, encoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return trunk.Manifest
|
||||
}
|
||||
|
||||
// built writes the builder's key of module at fp: done, its one archive named with a reference, or in another state.
|
||||
func (b builderOnTheBus) built(t *testing.T, module, version, fp, manifest, state string) {
|
||||
t.Helper()
|
||||
keys, _ := aKeyFor(module, version, fp, "", "", "")
|
||||
v := keys.keys[module].Build
|
||||
v.Manifest = manifest
|
||||
if state != sdkdelivery.BuildDone {
|
||||
v = sdkdelivery.BuilderBuild{State: state, By: "ace"}
|
||||
if state == sdkdelivery.BuildFailed {
|
||||
v.Error = "digests differ: ace sha256:1, g14 sha256:2"
|
||||
}
|
||||
}
|
||||
value, err := sdkdelivery.EncodeBuilderBuild(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key, err := sdkdelivery.BuilderBuildKey(module, fp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := b.builds.Put(context.Background(), key, value); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// noBuildAsked fails the test if anything asks build-agent for a build (ADR 0501 §6, ADR 0503 §6).
|
||||
func noBuildAsked(t *testing.T) {
|
||||
t.Helper()
|
||||
was := askABuild
|
||||
askABuild = func(_ context.Context, _ buildSource, path, _ string) (string, error) {
|
||||
t.Errorf("a build was asked of build-agent, at %q", path)
|
||||
return "", context.Canceled
|
||||
}
|
||||
t.Cleanup(func() { askABuild = was })
|
||||
}
|
||||
|
||||
// asksWithPaths records every build a merge asks for, as repository, path and ref. The merge window's goroutine and
|
||||
// the test's own may ask at once, so the record is written under a lock (issue 1543).
|
||||
func asksWithPaths(t *testing.T) *[][3]string {
|
||||
t.Helper()
|
||||
var asked [][3]string
|
||||
var mu sync.Mutex
|
||||
was := askABuild
|
||||
askABuild = func(_ context.Context, source buildSource, path, ref string) (string, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
asked = append(asked, [3]string{source.Repository, path, ref})
|
||||
return "b-" + path, nil
|
||||
}
|
||||
t.Cleanup(func() { askABuild = was })
|
||||
return &asked
|
||||
}
|
||||
Reference in New Issue
Block a user