Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/validate_test.go
T
jschoubben c76d8ef381 IX5: the validation's request, run and verdict over the change and trunk cases
The running indexer's validation before take-in asks its own manifest
validator (cmd/mesh-judge under the indexer entry's Go module, at the
revision's head) over two cases and refuses only what the revision causes;
mesh-judge reads the file MESH_RUN_INPUT names, where a run writes its input.

Builds: design 47 G §712, A-213, A-232

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 06:24:19 +01:00

75 lines
3.4 KiB
Go

package index
import (
"encoding/json"
"strings"
"testing"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/buildstep"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/composer"
"mesh-delivery-indexer/judge"
)
// The validation refuses only what the revision causes (design 47 G §712, ADR 0579 §2), and its run names the indexer entry's
// repository, path and the revision's head, and no heads.
func TestValidationRefusesWhatTheRevisionCauses(t *testing.T) {
manifests := func(m map[string]string) map[string]composer.Manifest {
out := map[string]composer.Manifest{}
for k, v := range m {
out[k] = composer.Manifest{Raw: json.RawMessage(v)}
}
return out
}
req := composer.Request{Cases: []composer.Case{
{Name: "change", Manifests: manifests(map[string]string{"a": `{"module":"a","v":2}`, "b": `{"module":"b"}`})},
{Name: "trunk", Manifests: manifests(map[string]string{"a": `{"module":"a"}`, "b": `{"module":"b"}`})},
}}
verdict := func(change, trunk map[string]string) composer.Verdict {
read := func(m map[string]string) map[string]composer.ManifestRead {
out := map[string]composer.ManifestRead{"a": {Accepted: true}, "b": {Accepted: true}}
for k, v := range m {
out[k] = composer.ManifestRead{Refused: v}
}
return out
}
return composer.Verdict{Cases: []composer.CaseVerdict{{Name: "change", Manifests: read(change)}, {Name: "trunk", Manifests: read(trunk)}}}
}
for _, c := range []struct {
name string
v composer.Verdict
want, wantErr string
}{
{"a changed manifest gains a problem", verdict(map[string]string{"a": "new\nold"}, map[string]string{"a": "old"}), "a: new", ""},
{"an unchanged manifest's problem refuses nothing", verdict(map[string]string{"b": "bad"}, nil), "", ""},
{"a problem between manifests the trunk lacks", verdict(map[string]string{judge.Unnamed: "x\ny"}, map[string]string{judge.Unnamed: "y"}), judge.Unnamed + ": x", ""},
{"an answer with one case is no verdict", composer.Verdict{Cases: verdict(nil, nil).Cases[:1]}, "", "not both cases"},
} {
got, err := ValidationRefusal(req, c.v)
if c.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), c.wantErr) {
t.Errorf("%s: %v, want %q", c.name, err, c.wantErr)
}
continue
}
if err != nil || RefusedWords(got) != c.want {
t.Errorf("%s: %q, %v, want %q", c.name, RefusedWords(got), err, c.want)
}
}
head := strings.Repeat("a", 40)
entry := meshcatalog.CatalogEntry{Module: "mesh-delivery-indexer", Repository: "novox/mesh-delivery", Path: "modules/mesh-delivery-indexer",
Artifacts: []meshcatalog.Artifact{{Language: "go", Package: &meshcatalog.ArtifactPackage{Ecosystem: "go", Name: "mesh-delivery-indexer"}}}}
job, err := validationJob(entry, head, "main", 7, []byte(`{"v":1}`))
if err != nil {
t.Fatal(err)
}
want := buildstep.RunProgram{Repository: "novox/mesh-delivery", Commit: head, Dir: "modules/mesh-delivery-indexer", Package: "mesh-delivery-indexer/cmd/mesh-judge"}
if job.Program != want || len(job.Heads) != 0 || len(job.Args) != 0 || job.Input.Verb != "seat:mesh-catalog.input" || job.Reader != "manifest validator of main at 7" {
t.Errorf("the job %+v", job)
}
if _, err := validationJob(meshcatalog.CatalogEntry{}, head, "main", 7, nil); err == nil || !strings.Contains(err.Error(), "claims the seat mesh-catalog") {
t.Errorf("no indexer entry: %v", err)
}
}