Files
mesh-sdk/go/delivery/stepasks_test.go
T

148 lines
5.3 KiB
Go

package delivery
import (
"errors"
"reflect"
"strings"
"testing"
"time"
)
const askCommit = "0123456789abcdef0123456789abcdef01234567"
func buildAsk() StepAsk {
return StepAsk{ID: "mh3k2x9qa1b2c3", Kind: AskDelivery, Language: AskGo, Asker: "mesh-delivery-builder",
At: time.Date(2026, 10, 23, 13, 0, 0, 0, time.UTC),
Build: &BuildJob{Module: "mesh-delivery-view", Path: "modules/mesh-delivery-view", FP: "ab12",
Fetch: map[string]any{"repository": "novox/mesh-delivery", "commit": askCommit, "dir": "modules/mesh-delivery-view", "paths": []any{"cmd"}},
Artifacts: []AskArtifact{{Artifact: "bundle"}, {Artifact: "base", From: "registry/x@sha256:00"}},
Publish: true, Toolchain: &ToolchainUsed{Version: "go1.26.0", Recipe: "3"}}}
}
func checkAsk() StepAsk {
return StepAsk{ID: "mh3k2x9qa1b2c4", Kind: AskCheck, Language: AskNode, Asker: "mesh-delivery-checker",
At: time.Date(2026, 10, 23, 13, 0, 0, 0, time.UTC),
Check: &CheckJob{Fetch: map[string]any{"repository": "novox/mesh-catalog", "commit": askCommit, "ref": "refs/pull/3/head", "base": askCommit},
Level: LevelUnit, Kept: true, Runner: "workspace", RunnerWhen: "modules/mesh-build-go/", Run: ""}}
}
// 1887/A1a: an ask encodes and decodes with every field.
func TestAskRoundTrips(t *testing.T) {
for _, a := range []StepAsk{buildAsk(), checkAsk()} {
raw, err := EncodeStepAsk(a)
if err != nil {
t.Fatal(err)
}
got, err := DecodeStepAsk(raw)
if err != nil {
t.Fatal(err)
}
a.V = StepAskVersion
if !reflect.DeepEqual(got, a) {
t.Fatalf("round trip:\n got %+v\nwant %+v", got, a)
}
}
}
// 1887/A1a: an ask with an unknown kind or language is refused.
func TestAskRefusesUnknownKindAndLanguage(t *testing.T) {
cases := map[string]func(*StepAsk){
"kind": func(a *StepAsk) { a.Kind = "build" },
"language": func(a *StepAsk) { a.Language = "typescript" },
"id": func(a *StepAsk) { a.ID = "postgres" },
"neither": func(a *StepAsk) { a.Build = nil },
"both": func(a *StepAsk) { a.Check = &CheckJob{Level: LevelUnit, Fetch: a.Build.Fetch} },
"recheck": func(a *StepAsk) { a.Kind = AskRecheck },
"commit": func(a *StepAsk) { a.Build.Fetch = map[string]any{"repository": "novox/x", "commit": "main"} },
"path": func(a *StepAsk) { a.Build.Path = "" },
}
for name, change := range cases {
a := buildAsk()
change(&a)
if _, err := EncodeStepAsk(a); err == nil {
t.Errorf("%s: encoded", name)
}
}
// A copy alone fetches nothing and needs no path.
a := buildAsk()
a.Build.Fetch, a.Build.Path, a.Build.Artifacts = nil, "", []AskArtifact{{Artifact: "base", From: "registry/x@sha256:00"}}
if _, err := EncodeStepAsk(a); err != nil {
t.Errorf("a copy alone: %v", err)
}
c := checkAsk()
c.Kind = AskDelivery
if _, err := EncodeStepAsk(c); err == nil {
t.Error("a check on the delivery stream encoded")
}
c = checkAsk()
c.Language = AskImage
if _, err := EncodeStepAsk(c); err == nil {
t.Error("a check of an image encoded")
}
raw, _ := EncodeStepAsk(buildAsk())
for _, bad := range []string{
strings.Replace(string(raw), `"kind":"delivery"`, `"kind":"queue"`, 1),
strings.Replace(string(raw), `"language":"go"`, `"language":"rust"`, 1),
} {
if _, err := DecodeStepAsk([]byte(bad)); err == nil {
t.Errorf("decoded %s", bad)
}
}
if _, err := DecodeStepAsk([]byte(strings.Replace(string(raw), `"v":1`, `"v":2`, 1))); !errors.Is(err, ErrUnknownVersion) {
t.Errorf("version 2: %v", err)
}
}
// 1887/A1a: the subjects, stream and workers are the seat's, as the broker derives them.
func TestAskSubjects(t *testing.T) {
s, err := AskSubject(AskGo, AskCheck)
if err != nil || s != "mesh.seat.node-build-go.accept.check" {
t.Fatalf("AskSubject = %q, %v", s, err)
}
language, kind, err := ParseAskSubject("mesh.seat.node-build-image.accept.delivery")
if err != nil || language != AskImage || kind != AskDelivery {
t.Fatalf("ParseAskSubject = %q %q %v", language, kind, err)
}
for _, bad := range []string{"mesh.seat.node-build-agent.accept.build", "mesh.seat.node-build-go.accept.queue", "mesh.seat.node-build-go.event.x"} {
if _, _, err := ParseAskSubject(bad); err == nil {
t.Errorf("parsed %s", bad)
}
}
if st, _ := AskStream(AskNode); st != "SEAT_NODE_BUILD_NODE" {
t.Errorf("AskStream = %q", st)
}
if w, _ := AskWorker(AskGo, AskRecheck); w != "SEAT_NODE_BUILD_GO_RECHECK_worker" {
t.Errorf("AskWorker = %q", w)
}
if seat, _ := BuildSeat(AskImage); seat != "node-build-image" {
t.Errorf("BuildSeat = %q", seat)
}
if m, _ := BuildModuleOf(AskNode); m != "mesh-build-node" {
t.Errorf("BuildModuleOf = %q", m)
}
if _, err := BuildSeat("agent"); err == nil {
t.Error("BuildSeat(agent)")
}
}
// 1887/A4b: a building key names the asks put for it; a done key or a name that is no ask id is refused.
func TestABuildingKeyNamesItsAsks(t *testing.T) {
b := BuilderBuild{State: BuildBuilding, By: "novox.builder", Asks: []string{"mh3k2x9qa1b2c3"}}
raw, err := EncodeBuilderBuild(b)
if err != nil {
t.Fatal(err)
}
got, err := DecodeBuilderBuild(raw)
if err != nil || len(got.Asks) != 1 || got.Asks[0] != "mh3k2x9qa1b2c3" {
t.Fatalf("decoded %+v, %v", got, err)
}
for _, bad := range []BuilderBuild{
{State: BuildBuilding, Asks: []string{"postgres"}},
{State: BuildFailed, Error: "x", Asks: []string{"mh3k2x9qa1b2c3"}},
} {
if _, err := EncodeBuilderBuild(bad); err == nil {
t.Errorf("encoded %+v", bad)
}
}
}