Files
mesh-sdk/go/delivery/published_packages_test.go
T
jschoubben 635aed57fd J3 (A2i finding 2): a build's end names the generated files its test step found out of step
delivery.BuildLogEntry gains out-of-step, an end's alone, as the build module's test step answers it, so the indexer
reads the field from the entry, not the raw message, and its trunk finding can be raised once the builder writes it.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:26:26 +01:00

117 lines
5.1 KiB
Go

package delivery
import (
"encoding/json"
"reflect"
"strings"
"testing"
"time"
)
// The packages state, the build end's imports and the kept imports (ADR 0593 §2) round-trip, and a reader refuses what it
// could not take, naming it.
func TestPublishedPackagesAndImportsRoundTripAndRefuse(t *testing.T) {
commit := strings.Repeat("a", 40)
sdk := "git.novox.be/novox/mesh-sdk/go"
good := PublishedPackages{Module: sdk, Repository: "novox/mesh-sdk", Dir: "go", Commit: commit, Requires: "sha256:01",
Packages: []PackageDigest{{Package: sdk, Digest: "d0"}, {Package: sdk + "/announce", Digest: "d1"}, {Package: sdk + "/internal/token", Digest: "d2"}},
At: time.Date(2026, 11, 2, 18, 0, 0, 0, time.UTC)}
raw, err := EncodePublishedPackages(good)
if err != nil {
t.Fatal(err)
}
back, err := DecodePublishedPackages(raw)
good.V = Version
if err != nil || !reflect.DeepEqual(back, good) {
t.Fatalf("round trip: %v, %+v", err, back)
}
if d, ok := back.DigestOf(sdk + "/announce"); !ok || d != "d1" {
t.Fatalf("DigestOf announce = %q, %v", d, ok)
}
if _, ok := back.DigestOf(sdk + "/buildstep"); ok {
t.Fatal("DigestOf finds a package the value does not hold")
}
if key, err := PackagesKey(sdk); err != nil || key != "git=2enovox=2ebe/novox/mesh-sdk/go" {
t.Fatalf("PackagesKey = %q, %v", key, err)
}
if _, err := PackagesKey("github.com/x/y"); err == nil {
t.Fatal("PackagesKey takes a path that is no mesh Go module's")
}
for name, mutate := range map[string]func(p *PublishedPackages){
"no mesh module": func(p *PublishedPackages) { p.Module = "github.com/x/y" },
"other repository": func(p *PublishedPackages) { p.Repository = "novox/mesh-host" },
"short commit": func(p *PublishedPackages) { p.Commit = "abc" },
"no requires": func(p *PublishedPackages) { p.Requires = "" },
"package elsewhere": func(p *PublishedPackages) {
p.Packages = []PackageDigest{{Package: "git.novox.be/novox/mesh-host/x", Digest: "d"}}
},
"unsorted": func(p *PublishedPackages) { p.Packages = []PackageDigest{p.Packages[1], p.Packages[0]} },
"no digest": func(p *PublishedPackages) { p.Packages = []PackageDigest{{Package: sdk}} },
} {
p := good
p.Packages = slicesClone(good.Packages)
mutate(&p)
if _, err := EncodePublishedPackages(p); err == nil {
t.Errorf("%s: encoded", name)
}
}
imports := []string{sdk, sdk + "/announce"}
outOfStep := []string{"go/seats/meshbroker/contract.go", "ts/seats/meshbroker/src/index.ts"}
end := BuildLogEntry{Event: BuildEndedEvent, Module: "netcheck", FP: "src2:x", Repository: "novox/mesh-catalog", Commit: commit,
Node: "ace", At: good.At, Outcome: "done", Imports: imports, OutOfStep: outOfStep}
raw, err = EncodeBuildLogEntry(end)
if err != nil {
t.Fatal(err)
}
if e, err := DecodeBuildLogEntry(raw); err != nil || !reflect.DeepEqual(e.Imports, imports) || !reflect.DeepEqual(e.OutOfStep, outOfStep) ||
!strings.Contains(string(raw), `"out-of-step":["go/seats/meshbroker/contract.go",`) {
t.Fatalf("build end round trip: %v, %v, %v in %s", err, e.Imports, e.OutOfStep, raw)
}
start := end
start.Event, start.Outcome, start.Imports = BuildStartedEvent, "", nil
if _, err := EncodeBuildLogEntry(start); err == nil {
t.Error("a build's start with files out of step encoded")
}
start.Imports, start.OutOfStep = imports, nil
if _, err := EncodeBuildLogEntry(start); err == nil {
t.Error("a build's start with imports encoded")
}
end.Imports = []string{sdk + "/announce", sdk}
if _, err := EncodeBuildLogEntry(end); err == nil {
t.Error("unsorted imports encoded")
}
// A build narrates between its start and its end (build.said): its module, fingerprint, line and why, nothing of an
// end; a start or end carries no line.
said := BuildLogEntry{Event: BuildSaidEvent, Module: "netcheck", FP: "src2:x", At: good.At,
Line: "waiting on container-image-registry", Why: "waiting"}
if raw, err := EncodeBuildLogEntry(said); err != nil {
t.Errorf("a narration refused: %v", err)
} else if e, err := DecodeBuildLogEntry(raw); err != nil || e.Line != said.Line || e.Why != "waiting" {
t.Errorf("a narration's round trip: %+v, %v", e, err)
}
for name, mutate := range map[string]func(e *BuildLogEntry){
"a narration with no line": func(e *BuildLogEntry) { e.Line = "" },
"a narration with an outcome": func(e *BuildLogEntry) { e.Outcome = "done" },
"a narration out of step": func(e *BuildLogEntry) { e.OutOfStep = outOfStep },
"an end with a line": func(e *BuildLogEntry) {
e.Event, e.Outcome, e.Node, e.Repository, e.Commit = BuildEndedEvent, "done", "ace", "novox/mesh-catalog", commit
},
} {
e := said
mutate(&e)
if _, err := EncodeBuildLogEntry(e); err == nil {
t.Errorf("%s encoded", name)
}
}
var answer BuildAnswer
if err := json.Unmarshal([]byte(`{"artifacts":[],"imports":["`+sdk+`"]}`), &answer); err != nil || len(answer.Imports) != 1 {
t.Fatalf("build answer imports: %v, %v", err, answer.Imports)
}
if err := CheckImports([]string{"fmt"}); err == nil {
t.Error("CheckImports takes a standard package")
}
}
func slicesClone(d []PackageDigest) []PackageDigest { return append([]PackageDigest(nil), d...) }