package catalogue import ( "slices" "strings" "testing" ) // Issue 774 (ADR 0571 §13, ADR 0582 clause 2): the lease write's check judges every manifest's dependency on the // controller against the named list, at the write (the three kept to it alone) and before its delivery. Moved with the // judge from mesh-grants' leasecheck_test.go (TestTheLeaseCheckJudgesEveryDependencyOnTheController's manifest rows and // TestTheKeepListNamesItsRecordsAndThreeToTheWrite), whose manifests were mesh-grants' fixtures; the conditions row is // mesh-conditions' manifest at mesh-catalog ce3bedd5 (module.json:31-32). func TestTheLeaseWritesCheckJudgesEveryDependencyOnTheController(t *testing.T) { toTheWrite := 0 for _, k := range KeepList { if !strings.HasPrefix(k.Record, "ADR ") || k.Module == "" || k.What == "" { t.Errorf("entry %+v names no record, module or declaration", k) } if k.ToTheWrite { toTheWrite++ } } if toTheWrite != 3 { t.Errorf("%d entries kept to the write itself, ADR 0571 §13 names three", toTheWrite) } type want struct { deps []string // " ", kept by the record or "unkept" write string // a reason the check at the write names, or "" when it passes before string // a reason the check before the delivery names, or "" when it passes } for _, row := range []struct { name string manifests map[string]string want want }{ // 774/S4/AC2. {"a read of the lease alone is no dependency, and the controller's own manifest is not judged", map[string]string{"mod-l": `{"module":"mod-l","version":"1","reads":["mesh-controller.lease"]}`, "mesh-controller": `{"module":"mesh-controller","version":"1","invokes":["seat:mesh-controller.status"]}`}, want{}}, // 774/S4/AC1. {"the keeper's read of the controller's conditions is kept before the write's delivery and refused at the write", map[string]string{"mesh-conditions": `{"module":"mesh-conditions","version":"1","reads":["mesh-controller.conditions","mesh-controller.lease"]}`}, want{deps: []string{"mesh-conditions read mesh-controller.conditions kept by ADR 0564 §9"}, write: "mesh-conditions declares read mesh-controller.conditions, kept by ADR 0564 §9 only until the lease write's own delivery"}}, {"the builder's consume of artifacts-gone is kept to the write itself", map[string]string{"mesh-delivery-builder": `{"module":"mesh-delivery-builder","version":"1","consumes":["mesh-controller.artifacts-gone"]}`}, want{deps: []string{"mesh-delivery-builder consume mesh-controller.artifacts-gone kept by ADR 0571 §4, §13"}}}, {"a read no record keeps fails both phases, named", map[string]string{"mod-u": `{"module":"mod-u","version":"1","reads":["mesh-controller.declared-packages"]}`}, want{deps: []string{"mod-u read mesh-controller.declared-packages unkept"}, write: "mod-u declares read mesh-controller.declared-packages, which no record keeps until the lease write", before: "mod-u declares read mesh-controller.declared-packages, which no record keeps until the lease write"}}, {"a seat verb and a module tool of the controller's, a consume and a wait are each one; every tool (*) is none", map[string]string{"mod-i": `{"module":"mod-i","version":"1","invokes":["seat:mesh-controller.root-free","mesh-controller.status","*","nats.nats_users"],` + `"consumes":["mesh-controller.checked","mod-x.thing"],"uses":["mesh-controller"]}`, "node-tools": `{"module":"node-tools","version":"1","waits":["mesh-controller.checked"]}`}, want{deps: []string{"mod-i consume mesh-controller.checked unkept", "mod-i invoke mesh-controller.status unkept", "mod-i invoke seat:mesh-controller.root-free unkept", "mod-i uses mesh-controller unkept", "node-tools waits mesh-controller.checked unkept"}, write: "mod-i declares invoke seat:mesh-controller.root-free, which no record keeps until the lease write (ADR 0571 §13); ended by ADR 0571 §11", before: "node-tools declares waits mesh-controller.checked"}}, {"a process's own invoke of the controller is its module's dependency, named by the process", map[string]string{"mod-p": `{"module":"mod-p","version":"1","resources":[{"id":"account","type":"user","name":"mod-p"},{"id":"worker","type":"process","run":["./w"],"user":"mod-p",` + `"bus":{"invokes":["seat:mesh-controller.held"]}}]}`}, want{deps: []string{"mod-p invoke seat:mesh-controller.held unkept"}, write: "mod-p (process worker) declares invoke seat:mesh-controller.held", before: "mod-p (process worker)"}}, {"no manifest fails both phases", map[string]string{}, want{write: "no manifest was read", before: "no manifest was read"}}, } { manifests := map[string]Manifest{} for name, raw := range row.manifests { m, err := Decode([]byte(raw)) if err != nil { t.Fatalf("%s: %s: %v", row.name, name, err) } manifests[name] = m } var deps []string for _, d := range Dependencies(manifests) { kept := "unkept" if d.Kept != "" { kept = "kept by " + d.Kept } deps = append(deps, d.Module+" "+d.Kind+" "+d.What+" "+kept) } if !slices.Equal(deps, row.want.deps) { t.Errorf("%s: dependencies %q, want %q", row.name, deps, row.want.deps) } for phase, reason := range map[string]string{PhaseWrite: row.want.write, PhaseBefore: row.want.before} { got := ManifestRefusals(manifests, phase) if (reason == "") != (len(got) == 0) || !slices.ContainsFunc(got, func(r string) bool { return strings.Contains(r, reason) }) && reason != "" { t.Errorf("%s: at %s refused %q, want %q", row.name, phase, got, reason) } } } }