126 lines
5.4 KiB
Go
126 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
|
"git.novox.be/novox/mesh-sdk/go/composer"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
const composeCommit = "4444444444444444444444444444444444444444"
|
|
|
|
// indexerHolds is the delivery indexer's manifests state holding each body under its digest, as the indexer writes it.
|
|
func indexerHolds(t *testing.T, bodies ...string) (func(string) (json.RawMessage, error), []string) {
|
|
t.Helper()
|
|
kept, digests := map[string]json.RawMessage{}, []string{}
|
|
for _, b := range bodies {
|
|
d := delivery.ManifestDigest([]byte(b))
|
|
key, _ := delivery.ManifestsKey(d)
|
|
raw, err := delivery.EncodeManifest(delivery.Manifest{Module: "demo", JSON: b})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
kept[key], digests = raw, append(digests, d)
|
|
}
|
|
return func(key string) (json.RawMessage, error) { return kept[key], nil }, digests
|
|
}
|
|
|
|
func composeAskOf(t *testing.T, digest string) delivery.StepAsk {
|
|
t.Helper()
|
|
req, _ := json.Marshal(composer.Request{V: composer.Version, Cases: []composer.Case{{Name: "change",
|
|
Manifests: map[string]composer.Manifest{"demo": {Digest: digest}}}}})
|
|
return delivery.StepAsk{ID: buildstep.NewID(), Kind: delivery.AskCheck, Language: delivery.AskGo, Asker: "mesh-delivery-assigner",
|
|
At: time.Now(), Compose: &delivery.ComposeJob{Fetch: map[string]any{"repository": "novox/mesh-sdk", "commit": composeCommit},
|
|
Dir: "go", Package: composer.Package, Request: req}}
|
|
}
|
|
|
|
// composeModule is a module with work and cache directories of its own, running its commands as they are (Inside: a
|
|
// unit test has no bubblewrap to shut them off in).
|
|
func composeModule(t *testing.T) *Module {
|
|
t.Helper()
|
|
m := moduleWith(newStates(), "go1.26.0")
|
|
m.Work, m.Cache, m.Inside, m.Run = t.TempDir(), t.TempDir(), true, StepRunner(t.TempDir())
|
|
return m
|
|
}
|
|
|
|
// 1622/AC3: a composer kept under the ask's key is run again, nothing fetched or built: the answer says it was not
|
|
// built, names the key, and carries the composer's verdict whole; the request it read had its manifests filled from the
|
|
// indexer's state.
|
|
func TestAKeptComposerIsRunWithTheManifestsFilled(t *testing.T) {
|
|
m := composeModule(t)
|
|
read, digests := indexerHolds(t, `{"module":"demo","version":"1"}`)
|
|
m.ReadManifest = read
|
|
a := composeAskOf(t, digests[0])
|
|
key := delivery.ComposerKey("novox/mesh-sdk", composeCommit, "go", composer.Package, delivery.ToolchainUsed{Version: "go1.26.0", Recipe: m.Recipe.Version()})
|
|
exe := m.composerPath(key)
|
|
if err := os.MkdirAll(filepath.Dir(exe), 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// A composer that answers which manifests its request held, filled or not, as a verdict.
|
|
script := "#!/bin/sh\n" +
|
|
`if grep -q '"digest"' "$2"; then echo '{"v":1,"sdk":"stand-in","cases":[{"name":"unfilled","manifests":{}}]}'; ` +
|
|
`else echo '{"v":1,"sdk":"stand-in","cases":[{"name":"change","manifests":{"demo":{"accepted":true}}}]}'; fi` + "\n"
|
|
if err := os.WriteFile(exe, []byte(script), 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fetched := 0
|
|
fetch := func(context.Context, map[string]any) (any, error) { fetched++; return nil, nil }
|
|
out, err := m.compose(context.Background(), fetch, a)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ans := out.(delivery.ComposeAnswer)
|
|
var v composer.Verdict
|
|
if err := json.Unmarshal(ans.Verdict, &v); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if ans.Built || ans.Key != key || fetched != 0 || len(v.Cases) != 1 || v.Cases[0].Name != "change" || !v.Cases[0].Manifests["demo"].Accepted {
|
|
t.Fatalf("answer = %+v (fetched %d), verdict %+v", ans, fetched, v)
|
|
}
|
|
if entries, _ := os.ReadDir(m.Work); len(entries) != 0 {
|
|
t.Errorf("the run's workspace was left: %v", entries)
|
|
}
|
|
}
|
|
|
|
// 1622: a manifest the indexer does not keep fails the ask, naming its digest; a fetched commit with no go.mod where
|
|
// the ask builds fails it naming the directory, and its workspace is released.
|
|
func TestAComposeAskFailsLoudly(t *testing.T) {
|
|
m := composeModule(t)
|
|
m.ReadManifest, _ = indexerHolds(t)
|
|
a := composeAskOf(t, "feedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeedfeed")
|
|
key := delivery.ComposerKey("novox/mesh-sdk", composeCommit, "go", composer.Package, delivery.ToolchainUsed{Version: "go1.26.0", Recipe: m.Recipe.Version()})
|
|
os.MkdirAll(filepath.Dir(m.composerPath(key)), 0o700)
|
|
os.WriteFile(m.composerPath(key), []byte("#!/bin/sh\nexit 0\n"), 0o700)
|
|
if _, err := m.compose(context.Background(), nil, a); err == nil || !strings.Contains(err.Error(), "feedfeed") {
|
|
t.Errorf("an unkept manifest: %v", err)
|
|
}
|
|
m2 := composeModule(t)
|
|
fetch := func(context.Context, map[string]any) (any, error) {
|
|
if err := os.MkdirAll(filepath.Join(m2.Work, "ws0000000000a", "tree", "go"), 0o700); err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{"workspace": "ws0000000000a"}, nil
|
|
}
|
|
if _, err := m2.compose(context.Background(), fetch, composeAskOf(t, "x")); err == nil || !strings.Contains(err.Error(), "no go.mod in go") {
|
|
t.Errorf("a commit with no go.mod: %v", err)
|
|
}
|
|
if entries, _ := os.ReadDir(m2.Work); len(entries) != 0 {
|
|
t.Errorf("the fetched workspace was left: %v", entries)
|
|
}
|
|
}
|
|
|
|
// 1622: the module reads the delivery indexer's manifests, which a compose ask names by digest.
|
|
func TestTheModuleReadsTheIndexersManifests(t *testing.T) {
|
|
if m := readManifest(t); !slices.Contains(m.Reads, ManifestsState) {
|
|
t.Errorf("reads = %v, lacks %s", m.Reads, ManifestsState)
|
|
}
|
|
}
|