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)") } }