Merge branch 'feat/47-G-fix10-validator' into feat/47-G-join10
This commit is contained in:
@@ -1706,6 +1706,19 @@ func EventProblems(m catalogue.Manifest) []string {
|
||||
m.Module, c, catalogue.TheRest))
|
||||
continue
|
||||
}
|
||||
if seat, state, isSeat, err := catalogue.SeatViewConsume(c); isSeat {
|
||||
// A consumed view of a seat (design 47 G §616, §699, A-131): the seat offers the state as a view; the holder is
|
||||
// resolved where it is read.
|
||||
switch s, known := catalogue.SeatNamed(seat); {
|
||||
case err != nil:
|
||||
problems = append(problems, fmt.Sprintf("%s consumes %v", m.Module, err))
|
||||
case !known:
|
||||
problems = append(problems, fmt.Sprintf("%s consumes %q, a view of the seat %q, "+catalogue.UndeclaredSeat, m.Module, c, seat))
|
||||
case !slices.Contains(s.Views, state):
|
||||
problems = append(problems, fmt.Sprintf("%s consumes %q, and the seat %s does not offer the state %q as a view (design 47 G §699)", m.Module, c, seat, state))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := consumePattern(c); err != nil {
|
||||
problems = append(problems, fmt.Sprintf("%s consumes %q: %v", m.Module, c, err))
|
||||
}
|
||||
@@ -4497,7 +4510,7 @@ func seatInvokeProblems(shelf catalogue.Shelf, declared map[string]catalogue.Sea
|
||||
problems = append(problems, fmt.Sprintf("%s invokes %s, a verb of the seat %q, "+catalogue.UndeclaredSeat, module, invoke, seat))
|
||||
continue
|
||||
}
|
||||
if !slices.ContainsFunc(verbs, func(v catalogue.Verb) bool { return v.Name == verb }) {
|
||||
if !slices.ContainsFunc(verbs, func(v catalogue.Verb) bool { return v.Name == verb }) && !acceptsKind(seat, verb, declared) {
|
||||
problems = append(problems, fmt.Sprintf("%s invokes %s, and the seat %s serves no verb %q", module, invoke, seat, verb))
|
||||
continue
|
||||
}
|
||||
@@ -4509,6 +4522,15 @@ func seatInvokeProblems(shelf catalogue.Shelf, declared map[string]catalogue.Sea
|
||||
return problems
|
||||
}
|
||||
|
||||
// acceptsKind says the seat accepts the kind an invoke names after its seat (design 47 G A-102): `<kind>`, or
|
||||
// `<stream>.<kind>` for a kind that rides a stream. A module's own seat names its accepts by kind alone.
|
||||
func acceptsKind(seat, kind string, declared map[string]catalogue.SeatDeclaration) bool {
|
||||
if s, isMesh := catalogue.SeatNamed(seat); isMesh {
|
||||
return slices.Contains(s.Accepts, kind) || slices.Contains(s.AcceptedOn, kind)
|
||||
}
|
||||
return slices.Contains(declared[seat].Accepts, kind)
|
||||
}
|
||||
|
||||
// SeatPathProblems is what is wrong with the paths a set of the mesh's own seats names (novox/hq ADR
|
||||
// 0287): only a node seat names one, each absolute and literal; every path has exactly one seat naming it
|
||||
// without stepping back; and a seat steps back only for another node seat naming the same path without
|
||||
|
||||
@@ -6418,11 +6418,14 @@ func TestRulesOther(t *testing.T) {
|
||||
}
|
||||
|
||||
// A read of a seat holder's state, `seat:<seat>.<state>`, is accepted where the seat declares the state and refused, by name,
|
||||
// where it does not or the seat is unknown (design 47 G A-116, A-128).
|
||||
// where it does not or the seat is unknown (design 47 G A-116, A-128); a consumed view, `seat:<seat>.views.<state>`, where the
|
||||
// seat declares the state as a view (§616, §699, A-131); an invoke of an accepted kind, `seat:<seat>.<kind>` or
|
||||
// `seat:<seat>.<stream>.<kind>`, where the seat accepts it (A-102).
|
||||
func TestASeatNamedReadIsJudgedAgainstTheSeatsStates(t *testing.T) {
|
||||
was := catalogue.Seats()
|
||||
t.Cleanup(func() { catalogue.UseSeats(was) })
|
||||
catalogue.UseSeats([]catalogue.Seat{{Name: "mesh-provisioner", Scope: catalogue.ScopeMesh, Decision: "test", States: []string{"plans"}}})
|
||||
catalogue.UseSeats([]catalogue.Seat{{Name: "mesh-provisioner", Scope: catalogue.ScopeMesh, Decision: "test",
|
||||
States: []string{"plans", "other"}, Views: []string{"plans"}, Accepts: []string{"step", "step"}, AcceptedOn: []string{"check.step"}}})
|
||||
for _, row := range []struct{ read, says string }{
|
||||
{"seat:mesh-provisioner.plans", ""},
|
||||
{"seat:mesh-provisioner.nothing", `declares no state "nothing"`},
|
||||
@@ -6434,4 +6437,29 @@ func TestASeatNamedReadIsJudgedAgainstTheSeatsStates(t *testing.T) {
|
||||
t.Errorf("%s: problems %q, want %q", row.read, problems, row.says)
|
||||
}
|
||||
}
|
||||
for _, row := range []struct{ consume, says string }{
|
||||
{"seat:mesh-provisioner.views.plans", ""},
|
||||
{"seat:mesh-provisioner.views.other", "does not offer the state"},
|
||||
{"seat:mesh-provisioner.views.nothing", "does not offer the state"},
|
||||
{"seat:mesh-unknown.views.plans", "mesh-unknown"},
|
||||
{"seat:mesh-provisioner.plans", "does not name a seat and its view"},
|
||||
} {
|
||||
problems := strings.Join(EventProblems(catalogue.Manifest{Module: "reader", Consumes: []string{row.consume}}), "\n")
|
||||
if row.says == "" && problems != "" || row.says != "" && !strings.Contains(problems, row.says) {
|
||||
t.Errorf("%s: problems %q, want %q", row.consume, problems, row.says)
|
||||
}
|
||||
}
|
||||
shelf := catalogue.Shelf{"holder": {Module: "holder", Claims: []catalogue.Claim{{Name: "mesh-provisioner"}}}}
|
||||
for _, row := range []struct{ invoke, says string }{
|
||||
{"seat:mesh-provisioner.step", ""},
|
||||
{"seat:mesh-provisioner.check.step", ""},
|
||||
{"seat:mesh-provisioner.delivery.step", `serves no verb "delivery.step"`},
|
||||
{"seat:mesh-provisioner.check.other", `serves no verb "check.other"`},
|
||||
} {
|
||||
shelf["caller"] = catalogue.Manifest{Module: "caller", Invokes: []string{row.invoke}}
|
||||
problems := strings.Join(seatInvokeProblems(shelf, nil), "\n")
|
||||
if row.says == "" && problems != "" || row.says != "" && !strings.Contains(problems, row.says) {
|
||||
t.Errorf("%s: problems %q, want %q", row.invoke, problems, row.says)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000
|
||||
git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient v0.0.0-00010101000000-000000000000
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package nodebuildimage
|
||||
package buildstep
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
// The seat's `build` acting rule matches an artifact by its kind, an image having no language (design 47 G §324, §397).
|
||||
func TestTheSeatsBuildRuleActsOnTheKindImage(t *testing.T) {
|
||||
raw, err := os.ReadFile("../../../seats/node-build-image/seat.json")
|
||||
raw, err := os.ReadFile("../../contracts/seats/node-build-image/seat.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Reference in New Issue
Block a user