Files
mesh-catalog/modules/mesh-build-image/cmd/mesh-build-image/capture_test.go
T

103 lines
3.4 KiB
Go

package main
// The shapes of what the module's steps end on in the steps state (novox/hq ADR 0487 §1, issue 1703e), kept as fixtures in
// testdata/captured for the builder's tests (mesh-delivery-builder copies them): the stored step of a fetch, of a
// candidate's build (no publish) and of a trunk build (publish). They are the step exactly as buildstep writes it to the
// state, with what differs between runs (ids, times, the workspace, the commit, digests, the registry's address) put
// to fixed words. This unit test regenerates them from the fake runner and compares (MESH_UPDATE_CAPTURED=1 rewrites
// them); the integration test through the real bus (bus_integration_test.go) compares the steps the real bus holds with
// the same files, so a change of shape fails in both places.
import (
"encoding/json"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
const capturedDir = "testdata/captured"
var hexDigest = regexp.MustCompile(`sha256:[0-9a-f]{64}`)
// normalized is a stored step with the words that differ between runs put to fixed ones.
func normalized(t *testing.T, st delivery.Step, workspace, commit, registry string) []byte {
t.Helper()
raw, err := json.Marshal(st)
if err != nil {
t.Fatal(err)
}
var v map[string]any
if err := json.Unmarshal(raw, &v); err != nil {
t.Fatal(err)
}
v["id"] = "STEPID"
v["started"], v["ended"] = "2026-10-22T08:00:00Z", "2026-10-22T08:00:01Z"
out, _ := json.MarshalIndent(v, "", " ")
s := string(out)
for from, to := range map[string]string{workspace: "WORKSPACE", commit: "COMMIT", registry: "REGISTRY"} {
if from != "" {
s = strings.ReplaceAll(s, from, to)
}
}
s = hexDigest.ReplaceAllString(s, imageDigest)
// The result is stored as a JSON string of an object in some encodings: keep the file readable by decoding it once.
var back map[string]any
if err := json.Unmarshal([]byte(s), &back); err != nil {
t.Fatal(err)
}
pretty, _ := json.MarshalIndent(back, "", " ")
return append(pretty, '\n')
}
func compareCaptured(t *testing.T, name string, got []byte) {
t.Helper()
path := filepath.Join(capturedDir, name)
if os.Getenv("MESH_UPDATE_CAPTURED") == "1" {
if err := os.WriteFile(path, got, 0o644); err != nil {
t.Fatal(err)
}
return
}
want, err := os.ReadFile(path)
if err != nil {
t.Fatalf("%s: %v (MESH_UPDATE_CAPTURED=1 writes it)", path, err)
}
if string(want) != string(got) {
t.Errorf("%s differs from what the step ended on:\n--- want\n%s--- got\n%s", name, want, got)
}
}
func workspaceOf(t *testing.T, st delivery.Step) string {
var r struct {
Workspace string `json:"workspace"`
}
json.Unmarshal(st.Result, &r)
return r.Workspace
}
func TestTheStoredStepsHaveTheCapturedShapes(t *testing.T) {
_ = time.Now
// fetch
{
f := newFake(t)
states := newStates()
m := moduleWith(t, f, states)
if _, err := tool(t, m, FetchTool)(map[string]any{"repository": "novox/mesh-catalog", "commit": commitSHA}); err != nil {
t.Fatal(err)
}
st := states.waitEnd(t)
compareCaptured(t, "fetch.json", normalized(t, st, workspaceOf(t, st), commitSHA, ""))
}
// a candidate's build and a trunk build
for name, extra := range map[string]map[string]any{"build-candidate.json": nil, "build-trunk.json": {"publish": true}} {
m, f, states := setup(t, same)
_, st := runBuild(t, m, states, extra)
compareCaptured(t, name, normalized(t, st, "", "", f.address()))
}
}