Reverts the Go-bundle package of 53caa3ba; the run's program is the directory ./cmd/mesh-judge under the go.mod the build reads. Builds: design 47 G §712, §676, §491, A-268 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
131 lines
6.2 KiB
Go
131 lines
6.2 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-forge-bridge/forgemsg"
|
|
"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", Kind: "bundle"}}}
|
|
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: "./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)
|
|
}
|
|
}
|
|
|
|
// The validation's seats are the branch's revision's seat definitions with the merges' changed ones laid over them (A-241): a
|
|
// revision that touches no definition is judged against the whole seat list, and a merge's definition replaces its seat's.
|
|
func TestValidationSeatsAreTheRevisionsWithTheMergesOver(t *testing.T) {
|
|
ctx := context.Background()
|
|
defs := newMem()
|
|
for seat, raw := range map[string]string{"node-engine": `{"seat":"node-engine","verbs":[{"name":"old"}]}`, "git": `{"seat":"git"}`} {
|
|
v, _ := json.Marshal(SeatDefinitionEntry{Seat: seat, Source: SourceTrunk, Digest: "d-" + seat, Definition: json.RawMessage(raw)})
|
|
defs.put(SeatDefinitionKey(seat, SourceTrunk, "", 0), v)
|
|
}
|
|
v, _ := json.Marshal(SeatDefinitionEntry{Seat: "pulled", Source: SourcePull, Pull: 3, Digest: "d", Definition: json.RawMessage(`{"seat":"pulled"}`)})
|
|
defs.put(SeatDefinitionKey("pulled", SourcePull, "r", 3), v)
|
|
ix := &Indexer{SeatDefinitions: defs}
|
|
seatsOf := func(raws []json.RawMessage) map[string]string {
|
|
out := map[string]string{}
|
|
for _, raw := range raws {
|
|
var d struct {
|
|
Seat string `json:"seat"`
|
|
Verbs []struct {
|
|
Name string `json:"name"`
|
|
} `json:"verbs"`
|
|
}
|
|
if err := json.Unmarshal(raw, &d); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out[d.Seat] = ""
|
|
if len(d.Verbs) > 0 {
|
|
out[d.Seat] = d.Verbs[0].Name
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
got, err := ix.revisionDefinitions(ctx, nil)
|
|
if err != nil || !reflect.DeepEqual(seatsOf(got), map[string]string{"node-engine": "old", "git": ""}) {
|
|
t.Errorf("a revision touching no definition: %v (%v), want the trunk's whole list and no pull request's", seatsOf(got), err)
|
|
}
|
|
const contracts = "modules/seat-contracts"
|
|
f := forgemsg.Forge{Repository: "r", Merge: strings.Repeat("c", 40), Manifests: map[string]string{
|
|
contracts: `{"module":"seat-contracts","version":"1.0","build":{"artifacts":[{"name":"go-seats","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`}}
|
|
ix.Files = func(_ context.Context, _, _ string, dirs []string) (map[string]map[string]string, error) {
|
|
return map[string]map[string]string{dirs[0]: {"node-engine/seat.json": "1"}}, nil
|
|
}
|
|
ix.ReadFile = func(_ context.Context, _, _, p string) ([]byte, error) {
|
|
if p == contracts+"/seats/node-engine/seat.json" {
|
|
return []byte(`{"format":1,"seat":"node-engine","scope":"node","grain":"seat-list","decision":"d","domain":"Core","verbs":[{"name":"new"}]}`), nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
got, err = ix.revisionDefinitions(ctx, []PendingEntry{{Forge: f}})
|
|
if err != nil || !reflect.DeepEqual(seatsOf(got), map[string]string{"node-engine": "new", "git": ""}) {
|
|
t.Errorf("a merge changing a definition: %v (%v), want its definition over the trunk's and the rest kept", seatsOf(got), err)
|
|
}
|
|
}
|