DLV-I14: the judge refuses a packages entry naming no declared package or an ill-formed series
Between the manifests (design 32): each name in a module's packages is a package some manifest declares, by the builder's name <module>/<artifact>, and each accepted series is <major>.<minor>. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -86,6 +86,8 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
// Between the manifests: two modules' names on the bus alike, and a read of bus state that moved (ADR 0596 §2).
|
||||
sdk := catalogue.Manifest{Module: "mesh-sdk", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{
|
||||
{Name: "go", Kind: catalogue.ArtifactPackage, Language: "go"}, {Name: "img", Kind: catalogue.ArtifactImage}}}}
|
||||
entry := func(name string) []catalogue.BusStateEntry {
|
||||
return []catalogue.BusStateEntry{{Name: name, Storage: catalogue.StorageKeyValue, Template: catalogue.TemplateState}}
|
||||
}
|
||||
@@ -99,8 +101,16 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
"reader": {Module: "reader", Reads: []string{"owner.cache"}}}, "reader reads \"owner.cache\", which owner has moved"},
|
||||
{"a read of state still kept", catalogue.Shelf{"owner": {Module: "owner", State: []catalogue.StateDeclaration{{Name: "cache"}}},
|
||||
"reader": {Module: "reader", Reads: []string{"owner.cache"}}}, ""},
|
||||
// DLV-I14 (design 32): the packages section names a declared package, by the builder's name, in a well-formed series.
|
||||
{"packages naming a declared package", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{"mesh-sdk/go": "0.2"}}}, ""},
|
||||
{"packages naming no declared package", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{"mesh-sdk": "0.1"}}},
|
||||
`user's packages name "mesh-sdk", which no manifest declares`},
|
||||
{"packages naming an image", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{"mesh-sdk/img": "0.1"}}},
|
||||
`name "mesh-sdk/img", which no manifest declares`},
|
||||
{"packages in an ill-formed series", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{"mesh-sdk/go": "v0.2"}}},
|
||||
`user's packages accept "mesh-sdk/go" in the series "v0.2"`},
|
||||
} {
|
||||
got := strings.Join(BusStateCatalogueProblems(c.shelf), "\n")
|
||||
got := strings.Join(append(BusStateCatalogueProblems(c.shelf), PackagesCatalogueProblems(c.shelf)...), "\n")
|
||||
if (c.want == "") != (got == "") || !strings.Contains(got, c.want) {
|
||||
t.Errorf("%s: between the manifests: %q, want %q", c.name, got, c.want)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package judge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
// PackagesCatalogueProblems are the rules of a manifest's `packages` no single manifest can be judged against (DLV-I14;
|
||||
// ADR 0606 §4, design 32 *A package, its series, and the series its users accept*): each name is a package some manifest
|
||||
// of the shelf declares, named as the builder names it (`<module>/<artifact>`), and each series is `<major>.<minor>`.
|
||||
func PackagesCatalogueProblems(shelf catalogue.Shelf) []string {
|
||||
declared := map[string]bool{}
|
||||
for _, module := range shelfOrder(shelf) {
|
||||
if b := shelf[module].Build; b != nil {
|
||||
for _, a := range b.Artifacts {
|
||||
if a.Kind == catalogue.ArtifactPackage {
|
||||
declared[module+"/"+a.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var problems []string
|
||||
for _, module := range shelfOrder(shelf) {
|
||||
accepts := shelf[module].Packages
|
||||
for _, name := range slices.Sorted(maps.Keys(accepts)) {
|
||||
if !declared[name] {
|
||||
problems = append(problems, fmt.Sprintf("%s's packages name %q, which no manifest declares as a package "+
|
||||
"(a package is named <module>/<artifact>; design 32)", module, name))
|
||||
}
|
||||
if s := strings.TrimSpace(accepts[name]); !seriesForm.MatchString(s) {
|
||||
problems = append(problems, fmt.Sprintf("%s's packages accept %q in the series %q, which is no <major>.<minor> "+
|
||||
"such as 0.1 (design 32)", module, name, accepts[name]))
|
||||
}
|
||||
}
|
||||
}
|
||||
return problems
|
||||
}
|
||||
@@ -4692,6 +4692,8 @@ func CatalogueProblems(shelf catalogue.Shelf) []string {
|
||||
problems = append(problems, ObjectsCatalogueProblems(shelf)...)
|
||||
// Bus state in `requires`: a name on the bus has one owner, and the new form has no readers (ADR 0595, ADR 0596 §2).
|
||||
problems = append(problems, BusStateCatalogueProblems(shelf)...)
|
||||
// A manifest's packages name a declared package in a well-formed series (design 32, DLV-I14).
|
||||
problems = append(problems, PackagesCatalogueProblems(shelf)...)
|
||||
// A module that hears a restricted stream runs as an account of its own (novox/hq ADR 0376 §2).
|
||||
problems = append(problems, RestrictedHearingProblems(shelf)...)
|
||||
// A work-queue stream is never asked for by another module's consumes (novox/hq ADR 0436 §6).
|
||||
|
||||
Reference in New Issue
Block a user