mesh-delivery is over its budget (810 unit, 73 integration on main), so this branch adds none net: its new cases are subtests, the three work-queue process tests and the consumes test become one, the history stream bounds join the stream values table, and the go/-only mesh-sdk merge check joins the one new integration test. buildrun's 20 unit and 1 integration tests moved in from mesh-sdk with it. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
79 lines
3.5 KiB
Go
79 lines
3.5 KiB
Go
package judge
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// knowledge is mesh-knowledge's manifest as ADR 0592 has it: an object bucket granted by its trusted value readers (a
|
|
// trusted file takes it), and
|
|
// two streams that keep their history.
|
|
const knowledge = `{"module":"mesh-knowledge","version":"1",
|
|
"resources":[{"id":"state","type":"directory","mode":"0700","place":"."},
|
|
{"id":"readers","trusted":true,"type":"file","path":"${dir:state}/readers.json","mode":"0600",
|
|
"merge":"json","takes-settings":["readers"],"content":"{\"readers\": {}}"}],
|
|
"objects":[{"name":"sections","max-mib":2048,"grant":{"config":"readers"}}],
|
|
"streams":[{"name":"versions","retention":"history","max-mib":4096,"events":["version.stored"]},
|
|
{"name":"reviews","retention":"history","events":["review.stored"]}]}`
|
|
|
|
// ADR 0592 §5, §6, §9, §25: a module's own object bucket and a stream that keeps its history are taken as declared (the
|
|
// history stream's bounds are in TestAWorkQueueStreamsValuesAreBounded); each bound and form of a bucket is refused, a
|
|
// bucket's name has one owner on the bus, and a module reads another's bucket only where the owner grants it.
|
|
func TestObjectBucketsAreJudgedAsADR0592Says(t *testing.T) {
|
|
if _, err := ParseManifest([]byte(knowledge)); err != nil {
|
|
t.Fatalf("mesh-knowledge's manifest was refused: %v", err)
|
|
}
|
|
for _, c := range []struct{ change, want string }{
|
|
{`"max-mib":2048,"grant"`, `"max-mib":0,"grant"`}, // no size: there is no default
|
|
{`"max-mib":2048,"grant"`, `"max-mib":8193,"grant"`}, // over the bound
|
|
{`"name":"sections"`, `"name":"Sections"`}, // not a plain local name
|
|
{`"name":"sections"`, `"name":"sections"},{"name":"sections","max-mib":1`}, // one bucket per name
|
|
{`"grant":{"config":"readers"}`, `"grant":{"config":"nobody"}`}, // a grant not by a trusted value
|
|
} {
|
|
raw := strings.Replace(knowledge, c.change, c.want, 1)
|
|
if raw == knowledge {
|
|
t.Fatalf("the change %q found nothing to change", c.change)
|
|
}
|
|
if _, err := ParseManifest([]byte(raw)); err == nil {
|
|
t.Errorf("%s was taken", c.want)
|
|
}
|
|
}
|
|
// A bucket whose name on the bus starts with what the mesh derives names with is refused.
|
|
if _, err := ParseManifest([]byte(`{"module":"kv","version":"1","objects":[{"name":"x","max-mib":1}]}`)); err == nil ||
|
|
!strings.Contains(err.Error(), "KV_") {
|
|
t.Errorf("a bucket kv_x was taken: %v", err)
|
|
}
|
|
parse := func(raw string) catalogue.Manifest {
|
|
t.Helper()
|
|
m, err := ParseManifest([]byte(raw))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return m
|
|
}
|
|
owner := parse(knowledge)
|
|
reader := parse(`{"module":"records-page","version":"1","reads":["mesh-knowledge.sections"]}`)
|
|
shelf := catalogue.Shelf{"mesh-knowledge": owner, "records-page": reader}
|
|
if p := objectProblemsOf(CatalogueProblems(shelf)); len(p) > 0 {
|
|
t.Fatalf("a granted read was refused: %v", p)
|
|
}
|
|
ungranted := parse(strings.Replace(knowledge, `,"grant":{"config":"readers"}`, "", 1))
|
|
shelf["mesh-knowledge"] = ungranted
|
|
if p := objectProblemsOf(CatalogueProblems(shelf)); len(p) != 1 || !strings.Contains(p[0], "records-page") {
|
|
t.Errorf("a read of a bucket its owner grants nobody: %v", p)
|
|
}
|
|
}
|
|
|
|
// objectProblemsOf are the problems that name an object bucket or a history stream.
|
|
func objectProblemsOf(all []string) []string {
|
|
var out []string
|
|
for _, p := range all {
|
|
if strings.Contains(p, "object bucket") || strings.Contains(p, "history") {
|
|
out = append(out, p)
|
|
}
|
|
}
|
|
return out
|
|
}
|