IX21: the validator reads a manifest's version MAJOR.MINOR and the finding stream and ask of a findings state
The refusal of a status in a manifest (IX20) relies on strict decoding: a manifest field naming a status is an unknown field and is refused. The `*` emitter of consumes (design 47 G §386) is held for the design writer's answer on model-usage's `*.usage.*`. Builds: design 47 G §89, §368, §387 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -206,7 +206,7 @@ func TestIndexerWhole(t *testing.T) { // 1238/AC2, AC10; 1585/T14, T15
|
||||
m1 := forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-delivery", Branch: "feat/x", Number: 12, Head: h1,
|
||||
Merge: "1111111111111111111111111111111111111111", Root: "r0",
|
||||
Trees: map[string]string{"modules/" + ix: "tree-indexer-2", "modules/a": "tree-a-2"},
|
||||
Manifests: map[string]string{"modules/" + ix: string(manifest), "modules/a": `{"module":"a","version":"1"}`},
|
||||
Manifests: map[string]string{"modules/" + ix: string(manifest), "modules/a": `{"module":"a","version":"1.0"}`},
|
||||
Locks: map[string]map[string]string{"modules/" + ix: {"go.sum": "3b5028f0c1e9bde04dd766abd63eb5931bc516bae695cf46f00abcd8510b0381"}}}
|
||||
merged := func(f forgemsg.Forge) uint64 {
|
||||
t.Helper()
|
||||
@@ -305,10 +305,10 @@ func TestIndexerWhole(t *testing.T) { // 1238/AC2, AC10; 1585/T14, T15
|
||||
{Repository: "novox/mesh-controller", Number: 41, Head: "4141414141414141414141414141414141414141"}}
|
||||
g1 := forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-catalog", Branch: "feat/g", Number: 40, Head: members[0].Head,
|
||||
Merge: "4000000000000000000000000000000000000000", Root: "r0", Trees: map[string]string{"modules/c": "tree-c-2"},
|
||||
Manifests: map[string]string{"modules/c": `{"module":"c","version":"1"}`}, Group: "feat/g", Members: members}
|
||||
Manifests: map[string]string{"modules/c": `{"module":"c","version":"1.0"}`}, Group: "feat/g", Members: members}
|
||||
g2 := forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-controller", Branch: "feat/g", Number: 41, Head: members[1].Head,
|
||||
Merge: "4100000000000000000000000000000000000000", Root: "r0", Trees: map[string]string{"modules/k": "tree-k-1"},
|
||||
Manifests: map[string]string{"modules/k": `{"module":"k","version":"1"}`}, Group: "feat/g", Members: members}
|
||||
Manifests: map[string]string{"modules/k": `{"module":"k","version":"1.0"}`}, Group: "feat/g", Members: members}
|
||||
g1Key, groupKey := takein.PendingKey(merged(g1)), takein.GroupTakeInKey("feat/g")
|
||||
if gathered, ok := said(takein.TakeInPending, groupKey); !ok || gathered.What != takein.TakeInGroup || len(gathered.Merges) != 1 {
|
||||
t.Fatalf("take-in.pending.%s = %+v (said %v) within 20 s, want the group with its first member", groupKey, gathered, ok)
|
||||
@@ -618,7 +618,7 @@ func TestIndexerWritesModulesAtAMerge(t *testing.T) { // 1239/AC9; I1, I3: the m
|
||||
const merge = "89abcdef0123456789abcdef0123456789abcdef"
|
||||
data, err := forgemsg.EncodeForge(forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-delivery", Branch: "feat/x", Number: 12,
|
||||
Head: "0123456789abcdef0123456789abcdef01234567", Merge: merge, Root: "r0", Trees: map[string]string{"modules/a": "newtree"},
|
||||
Manifests: map[string]string{"modules/a": `{"module":"a","version":"1"}`}})
|
||||
Manifests: map[string]string{"modules/a": `{"module":"a","version":"1.0"}`}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -655,9 +655,9 @@ func TestIndexerKeepsManifestsAtAMerge(t *testing.T) { // 1444/AC4, 1449/AC4, 15
|
||||
}
|
||||
const goSum = "3b5028f0c1e9bde04dd766abd63eb5931bc516bae695cf46f00abcd8510b0381"
|
||||
judged := map[string]string{
|
||||
"good": `{"module":"good","version":"1","resources":[{"id":"d","type":"directory","path":"/srv/good","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
"bad": `{"module":"bad","version":"1","provides":[{"name":"amqp"}],"resources":[{"id":"d","type":"directory","path":"/srv/bad","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
"later": `{"module":"later","version":"1","a-field-from-later":1,"resources":[{"id":"d","type":"directory","path":"/srv/later","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
"good": `{"module":"good","version":"1.0","resources":[{"id":"d","type":"directory","path":"/srv/good","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
"bad": `{"module":"bad","version":"1.0","provides":[{"name":"amqp"}],"resources":[{"id":"d","type":"directory","path":"/srv/bad","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
"later": `{"module":"later","version":"1.0","a-field-from-later":1,"resources":[{"id":"d","type":"directory","path":"/srv/later","mode":"0700"}],"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`,
|
||||
}
|
||||
js, ctx, _, modules := startIndexer(t, func(ctx context.Context, builds buildLog) {
|
||||
builds.end(t, "novox/mesh-catalog", "avahi", "modules/avahi")
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ func TestAMeshSDKMergeMovesOnlyTheModulesImportingAChangedPackage(t *testing.T)
|
||||
if got, err := index.SeatDefinitionsOf(jsSource{ctx, seatDefs}, nil, ""); err != nil || func() string { raw, _ := json.Marshal(got); return string(raw) }() != `{"revision":0,"seats":[]}` {
|
||||
t.Errorf("seat-definitions of an indexer that kept none = %+v, %v", got, err)
|
||||
}
|
||||
contracts := `{"module":"mesh-contracts","version":"1","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
contracts := `{"module":"mesh-contracts","version":"1.0","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
merged("novox/mesh-contracts", 80, contractsMerge, forgemsg.Forge{Root: "dddddddddddddddddddddddddddddddddddddddd",
|
||||
Trees: map[string]string{"": "dddddddddddddddddddddddddddddddddddddddd"}, Manifests: map[string]string{"": contracts}})
|
||||
entry := func(key string, ok func(index.SeatDefinitionEntry) bool) index.SeatDefinitionEntry {
|
||||
|
||||
@@ -76,8 +76,8 @@ func TestTheControlRecords(t *testing.T) {
|
||||
}
|
||||
modules[name] = &views.Entry{Value: raw, Revision: 1}
|
||||
}
|
||||
asks := `{"module":"cache","version":"1","requires":[{"name":"c","storage":"key-value","template":"state"}]}`
|
||||
for digest, raw := range map[string]string{dAsk: asks, dNone: `{"module":"plain","version":"1"}`, dRefused: asks} {
|
||||
asks := `{"module":"cache","version":"1.0","requires":[{"name":"c","storage":"key-value","template":"state"}]}`
|
||||
for digest, raw := range map[string]string{dAsk: asks, dNone: `{"module":"plain","version":"1.0"}`, dRefused: asks} {
|
||||
put(manifests, digest, 1, meshcatalog.ManifestsByDigestValue{V: keys.Version, Module: "m", Manifest: raw})
|
||||
}
|
||||
putVerdict(dAsk, 7, meshcatalog.VerdictsByDigestValue{Module: "cache", State: meshcatalogclient.VerdictAccepted, Judge: "j"})
|
||||
@@ -127,7 +127,7 @@ func TestTheControlRecords(t *testing.T) {
|
||||
// raises generated-types-out-of-step from a trunk build end, cleared only by a clean one of the same module.
|
||||
t.Run("seat definitions", func(t *testing.T) {
|
||||
const repo, m1, m2, m3, head = "novox/mesh-contracts", "m1", "m2", "m3", "h1"
|
||||
manifest := `{"module":"mesh-contracts","version":"1","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
manifest := `{"module":"mesh-contracts","version":"1.0","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
git := `{"format":1,"seat":"git","scope":"mesh","grain":"seat-list","decision":"novox/hq ADR 0111","domain":"Core","delivers":"git"}`
|
||||
files := map[string]map[string]string{
|
||||
m1: {"seats/git/seat.json": git, "seats/gone/seat.json": strings.Replace(git, `"git"`, `"gone"`, 1)},
|
||||
@@ -162,7 +162,7 @@ func TestTheControlRecords(t *testing.T) {
|
||||
merged := func(merge string) {
|
||||
t.Helper()
|
||||
if err := ix.ApplySeatDefinitions(ctx, forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: repo, Number: 1, Merge: merge,
|
||||
Manifests: map[string]string{meshcatalogclient.RootPath: manifest, "modules/other": `{"module":"other","version":"1"}`}}); err != nil {
|
||||
Manifests: map[string]string{meshcatalogclient.RootPath: manifest, "modules/other": `{"module":"other","version":"1.0"}`}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ func TestTheControlRecords(t *testing.T) {
|
||||
// Ruling (lead, on A2i's finding 3): indexer_seat_definitions_again for a pull request reads the head's own manifest's
|
||||
// generated-from: a trunk that names none, a head that names it, is read as the contracts module the head is.
|
||||
ix.Modules, ix.Manifests = newMem(), newMem()
|
||||
plain := `{"module":"mesh-contracts","version":"1"}`
|
||||
plain := `{"module":"mesh-contracts","version":"1.0"}`
|
||||
kept, _ := meshcatalogclient.EncodeManifest(meshcatalog.ManifestsByDigestValue{Module: "mesh-contracts", Manifest: plain})
|
||||
mkey, _ := meshcatalogclient.ManifestsKey(meshcatalogclient.ManifestDigest([]byte(plain)))
|
||||
ix.Manifests.(*memStore).vals[mkey] = kept
|
||||
@@ -425,7 +425,7 @@ func TestTheControlRecords(t *testing.T) {
|
||||
}
|
||||
return nil, nil
|
||||
}}
|
||||
sdk := `{"module":"mesh-sdk","version":"1","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"]},` +
|
||||
sdk := `{"module":"mesh-sdk","version":"1.0","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"]},` +
|
||||
`{"name":"ts","kind":"package","language":"typescript","paths":["src","package.json"],"series":"0.3"}]}}`
|
||||
if err := ix.KeepPackageNames(ctx, forgemsg.Forge{Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-sdk", Merge: "m1",
|
||||
Manifests: map[string]string{meshcatalogclient.RootPath: sdk}}); err != nil {
|
||||
@@ -498,11 +498,11 @@ func TestTheControlRecords(t *testing.T) {
|
||||
pkgs, imports []string
|
||||
pinned string
|
||||
}{
|
||||
"new": {"novox/mesh-catalog", `{"module":"new","version":"1","packages":{"git.novox.be/novox/mesh-sdk/go":"0.2","@novox/ui":"1.0"}}`, nil, nil, ""},
|
||||
"old": {"novox/mesh-catalog", `{"module":"old","version":"1"}`, []string{sdkGo}, nil, "v0.1.15"},
|
||||
"imports": {"novox/mesh-tools", `{"module":"imports","version":"1"}`, nil, []string{sdkGo + "/views"}, ""},
|
||||
"sibling": {"novox/mesh-sdk", `{"module":"sibling","version":"1"}`, []string{sdkGo}, nil, ""},
|
||||
"none": {"novox/mesh-catalog", `{"module":"none","version":"1"}`, nil, nil, ""},
|
||||
"new": {"novox/mesh-catalog", `{"module":"new","version":"1.0","packages":{"git.novox.be/novox/mesh-sdk/go":"0.2","@novox/ui":"1.0"}}`, nil, nil, ""},
|
||||
"old": {"novox/mesh-catalog", `{"module":"old","version":"1.0"}`, []string{sdkGo}, nil, "v0.1.15"},
|
||||
"imports": {"novox/mesh-tools", `{"module":"imports","version":"1.0"}`, nil, []string{sdkGo + "/views"}, ""},
|
||||
"sibling": {"novox/mesh-sdk", `{"module":"sibling","version":"1.0"}`, []string{sdkGo}, nil, ""},
|
||||
"none": {"novox/mesh-catalog", `{"module":"none","version":"1.0"}`, nil, nil, ""},
|
||||
} {
|
||||
digest := fmt.Sprintf("%064x", len(name)*16+int(name[0]))
|
||||
putJSON(manifests, digest, meshcatalog.ManifestsByDigestValue{V: keys.Version, Module: name, Manifest: u.manifest})
|
||||
@@ -569,7 +569,7 @@ func TestTheControlRecords(t *testing.T) {
|
||||
ix, _, _ := manifestsIndexer(t, rec(t, "build-1", "avahi", catalogueRepo, "modules/avahi", "main", "", "2026-10-19T09:00:00Z", aInputs))
|
||||
cands := newMem()
|
||||
ix.ConfigCandidates, ix.Now = cands, func() time.Time { return at }
|
||||
trunk := `{"module":"avahi","version":"1","config":{"port":{"type":"integer","default":5353,"why":"mDNS"}}}`
|
||||
trunk := `{"module":"avahi","version":"1.0","config":{"port":{"type":"integer","default":5353,"why":"mDNS"}}}`
|
||||
if err := ix.Apply(ctx, withManifests(mergedMsg(catalogueRepo, map[string]string{"modules/avahi": "t1"}), map[string]string{"modules/avahi": trunk}, nil)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ func (b fakeBounds) Disarm(_ context.Context, key string) error { delete(b, key)
|
||||
func storeHoldersNewManifestWaitsForEveryCountedEngine(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
const dir, dockerDir = "modules/distribution", "modules/docker"
|
||||
old := `{"module":"distribution","version":"1","listens":[{"name":"registry","port":5000,"from":"mesh"}]}`
|
||||
next := `{"module":"distribution","version":"1","claims":[{"name":"container-image-registry","scope":"mesh"}],` +
|
||||
old := `{"module":"distribution","version":"1.0","listens":[{"name":"registry","port":5000,"from":"mesh"}]}`
|
||||
next := `{"module":"distribution","version":"1.0","claims":[{"name":"container-image-registry","scope":"mesh"}],` +
|
||||
`"listens":[{"name":"registry","port":5000,"from":"mesh"}]}`
|
||||
docker := `{"module":"docker","version":"1","resources":[{"id":"daemon","type":"file","path":"/etc/docker/daemon.json","template":"files/daemon.json"}]}`
|
||||
docker := `{"module":"docker","version":"1.0","resources":[{"id":"daemon","type":"file","path":"/etc/docker/daemon.json","template":"files/daemon.json"}]}`
|
||||
dockerNeeds, _ := catalogue.ModuleNeeds([]byte(docker), map[string]string{"files/daemon.json": `"${seat:container-image-registry:reach}"`})
|
||||
if needs, _ := catalogue.ManifestNeeds([]byte(next)); !slices.Contains(needs, "form:seat-reach") || !slices.Contains(dockerNeeds, "form:seat-reach") {
|
||||
t.Fatalf("the new manifest needs %v and docker's %v, want form:seat-reach in both (mesh-sdk ecdbf1a, ModuleNeeds)", needs, dockerNeeds)
|
||||
|
||||
@@ -185,7 +185,7 @@ func TestModuleOfADirectory(t *testing.T) { // 1238/AC3, as R4e has it: the modu
|
||||
ctx := context.Background()
|
||||
// The trunk holds modules/odd as the module odd-name (its manifest names it so); modules/plain is held by none.
|
||||
merged := mergedMsg("novox/mesh-delivery", map[string]string{"modules/odd": "t"})
|
||||
merged.Manifests["modules/odd"] = `{"module":"odd-name","version":"1"}`
|
||||
merged.Manifests["modules/odd"] = `{"module":"odd-name","version":"1.0"}`
|
||||
if err := ix.Apply(ctx, merged); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func TestModuleOfADirectory(t *testing.T) { // 1238/AC3, as R4e has it: the modu
|
||||
}
|
||||
// A manifest the pull message carries names its module, whatever directory it is in.
|
||||
f := pull("novox/mesh-delivery", 13, "feat/y", h2, "modules/odd")
|
||||
f.Manifests = map[string]string{"modules/odd": `{"module":"renamed","version":"1"}`}
|
||||
f.Manifests = map[string]string{"modules/odd": `{"module":"renamed","version":"1.0"}`}
|
||||
if name := moduleOfDir(held, f, "modules/odd"); name != "renamed" {
|
||||
t.Errorf("modules/odd = %q, want the module its manifest names", name)
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ func TestAnArtifactOfNoToolchainHasNoLanguageAndNoLock(t *testing.T) { // 1450/A
|
||||
func TestAManifestTheParserRefusesLeavesNoInputsAndSaysWhy(t *testing.T) { // 1450/AC5
|
||||
for name, raw := range map[string]string{
|
||||
"not json": "not json",
|
||||
"unknown field": strings.Replace(catalogueManifest(t, "avahi"), `"version": "1",`, `"version": "1", "scope": "everything",`, 1),
|
||||
"unknown field": strings.Replace(catalogueManifest(t, "avahi"), `"version":"1.0",`, `"version":"1.0", "scope": "everything",`, 1),
|
||||
} {
|
||||
in := inputsOf("avahi", raw, "t", nil, noBases)
|
||||
if in.Kept != nil || !strings.HasPrefix(in.None2, "the manifest cannot be read: ") || len(in.None2) <= len("the manifest cannot be read: ") {
|
||||
|
||||
@@ -82,7 +82,7 @@ func rec(t *testing.T, id, module, repo, path, ref, state, at, inputs string) [2
|
||||
func mergedMsg(repo string, trees map[string]string) forgemsg.Forge {
|
||||
manifests := map[string]string{}
|
||||
for dir := range trees {
|
||||
manifests[dir] = `{"module":"` + nameOfDir(dir) + `","version":"1"}`
|
||||
manifests[dir] = `{"module":"` + nameOfDir(dir) + `","version":"1.0"}`
|
||||
}
|
||||
return forgemsg.Forge{V: keys.Version, Kind: forgemsg.ForgeMerged, Repository: repo, Branch: "feat/x", Number: 12, Head: h1, Merge: merge, Root: "r0", Trees: trees, Manifests: manifests}
|
||||
}
|
||||
@@ -515,7 +515,7 @@ func TestAModuleMovesBetweenRepositoriesOnlyWhenItsTrunkDropsIt(t *testing.T) {
|
||||
if repository != to || sha != toHead || dir != "modules/a" {
|
||||
t.Errorf("read %s at %s %q, want only %s at %s modules/a", repository, sha, dir, to, toHead)
|
||||
}
|
||||
return RepoRead{Root: "r2", Trees: map[string]string{dir: "t2"}, Manifests: map[string]string{dir: `{"module":"a","version":"1"}`}}, nil
|
||||
return RepoRead{Root: "r2", Trees: map[string]string{dir: "t2"}, Manifests: map[string]string{dir: `{"module":"a","version":"1.0"}`}}, nil
|
||||
}
|
||||
}
|
||||
for _, f := range tc.merges {
|
||||
|
||||
@@ -106,7 +106,7 @@ func TestTheIndexerAsksTheForgeForTheNamedPathsObjectsOfAMerge(t *testing.T) { /
|
||||
return map[string]map[string]string{"": sdkObjects}, nil
|
||||
}
|
||||
raw := fixture(t, "sdk-9cb4d59-mesh-sdk")
|
||||
f := withManifests(mergedMsg("novox/mesh-sdk", map[string]string{"": "roottree", "modules/a": "t"}), map[string]string{"": raw, "modules/a": `{"module":"a","version":"1"}`}, nil)
|
||||
f := withManifests(mergedMsg("novox/mesh-sdk", map[string]string{"": "roottree", "modules/a": "t"}), map[string]string{"": raw, "modules/a": `{"module":"a","version":"1.0"}`}, nil)
|
||||
if err := ix.Apply(context.Background(), f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633)
|
||||
f.Locks[d] = l
|
||||
}
|
||||
f.Locks[contracts] = map[string]string{}
|
||||
f.Manifests[contracts] = `{"module":"` + row.module + `","version":"1","build":{"artifacts":[{"name":"go-seats","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
f.Manifests[contracts] = `{"module":"` + row.module + `","version":"1.0","build":{"artifacts":[{"name":"go-seats","kind":"package","language":"go","paths":["go"],"series":"0.1","generated-from":"."}]}}`
|
||||
b.ix.Files = func(_ context.Context, repository, commit string, dirs []string) (map[string]map[string]string, error) {
|
||||
if repository != f.Repository || commit != f.Merge || !slices.Equal(dirs, []string{contracts + "/seats"}) {
|
||||
t.Errorf("listed %v of %s at %s", dirs, repository, commit)
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
func TestARegisteredModuleIsIndexedFromItsRepository(t *testing.T) { // the grants part's gaps: modules registered from their own repositories had no manifest here
|
||||
const forge = "http://novox.internal:20000/jschoubben/snake.git"
|
||||
snake := `{"module":"snake","version":"1"}`
|
||||
snake := `{"module":"snake","version":"1.0"}`
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
path string
|
||||
@@ -41,7 +41,7 @@ func TestARegisteredModuleIsIndexedFromItsRepository(t *testing.T) { // the gran
|
||||
{wantRead: true, name: "no manifest at the path", path: "modules/x",
|
||||
read: RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": snake}}},
|
||||
{wantRead: true, name: "a manifest of another module", path: "",
|
||||
read: RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": `{"module":"other","version":"1"}`}}},
|
||||
read: RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": `{"module":"other","version":"1.0"}`}}},
|
||||
{wantRead: true, name: "a repository whose default branch is master", path: "", ref: "master", want: true,
|
||||
read: RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": snake}}},
|
||||
{wantRead: true, name: "a repository built from a branch of its own (nox-mesh)", path: "", ref: "nox-mesh", want: true,
|
||||
@@ -151,7 +151,7 @@ func TestARegisteredModuleIsIndexedFromItsRepository(t *testing.T) { // the gran
|
||||
var asked []string
|
||||
ix.Read = func(_ context.Context, _, sha, dir string) (RepoRead, error) {
|
||||
asked = append(asked, sha+":"+dir)
|
||||
return RepoRead{Root: "r1", Trees: map[string]string{"modules/a": "treeA2"}, Manifests: map[string]string{"modules/a": `{"module":"a","version":"2"}`}}, nil
|
||||
return RepoRead{Root: "r1", Trees: map[string]string{"modules/a": "treeA2"}, Manifests: map[string]string{"modules/a": `{"module":"a","version":"2.0"}`}}, nil
|
||||
}
|
||||
got := ix.TakeIn(ctx, "a")
|
||||
m, ok := moduleOf(t, mods, "a")
|
||||
@@ -202,7 +202,7 @@ func TestARegistrationOfAnotherRepositoryDoesNotHideTheRealOne(t *testing.T) { /
|
||||
ix.Read = func(_ context.Context, repo, _, dir string) (RepoRead, error) {
|
||||
asked = append(asked, repo+":"+dir)
|
||||
if repo == "novox/Link2Pay" {
|
||||
return RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": `{"module":"link2pay","version":"1"}`}}, nil
|
||||
return RepoRead{Root: "r0", Trees: map[string]string{"": "t1"}, Manifests: map[string]string{"": `{"module":"link2pay","version":"1.0"}`}}, nil
|
||||
}
|
||||
return RepoRead{Root: "r0"}, nil
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func TestARegistrationOfAnotherRepositoryDoesNotHideTheRealOne(t *testing.T) { /
|
||||
func TestAForgeThatCannotSayLeavesTheModuleUnwrittenAndAsksAgain(t *testing.T) { // a timeout or a 404 at the head: no read at an older commit
|
||||
// Issue 1945: car-hunter and snake answered 404 until the forge's account could read them, and were read again only when
|
||||
// the indexer started again. Each row's trigger must now take the module in once the forge reads it.
|
||||
const snake = `{"module":"snake","version":"1"}`
|
||||
const snake = `{"module":"snake","version":"1.0"}`
|
||||
ctx := context.Background()
|
||||
for _, tc := range []struct{ failure, trigger string }{
|
||||
{"timeout", "the indexer starts again"},
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
// not read.
|
||||
func unreadableAvahi(t *testing.T) string {
|
||||
t.Helper()
|
||||
raw := strings.Replace(catalogueManifest(t, "avahi"), `"version": "1",`, `"version": "1", "scope": "everything",`, 1)
|
||||
raw := strings.Replace(catalogueManifest(t, "avahi"), `"version":"1.0",`, `"version":"1.0", "scope": "everything",`, 1)
|
||||
if raw == catalogueManifest(t, "avahi") {
|
||||
t.Fatal("the fixture has no version line")
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ func TestBasesAreComputedFirstAndNoFingerprintTakesTheBuilder(t *testing.T) { //
|
||||
// verb edges of two modules calling each other, from either side; a third calling one of them keeps its edge.
|
||||
invoking := func(name, invokes string) mod {
|
||||
raw := renamed(t, "avahi", name)
|
||||
return mod{name, strings.Replace(raw, `"version": "1",`, `"version": "1", "invokes": [`+invokes+`],`, 1)}
|
||||
return mod{name, strings.Replace(raw, `"version":"1.0",`, `"version":"1.0", "invokes": [`+invokes+`],`, 1)}
|
||||
}
|
||||
vx, _ := newFormIndexer(t, invoking("caller", `"callee.avahi_status"`), invoking("callee", `"caller.avahi_browse", "*"`),
|
||||
invoking("third", `"callee.avahi_status"`))
|
||||
@@ -505,7 +505,7 @@ func TestAModuleKeepsTheToolchainsItsFingerprintWasComputedWith(t *testing.T) {
|
||||
sdkMerge := func(commit, tree string) meshcatalog.ModulesByModuleValue {
|
||||
t.Helper()
|
||||
f := forgemsg.Forge{V: keys.Version, Kind: forgemsg.ForgeMerged, Repository: "novox/mesh-sdk", Branch: "feat/x", Number: 3, Head: h1,
|
||||
Merge: commit, Root: tree, Trees: map[string]string{"": tree}, Manifests: map[string]string{"": `{"module":"mesh-sdk","version":"1"}`}}
|
||||
Merge: commit, Root: tree, Trees: map[string]string{"": tree}, Manifests: map[string]string{"": `{"module":"mesh-sdk","version":"1.0"}`}}
|
||||
if err := ix.Apply(context.Background(), f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
ix.Modules.(*memStore).put(module, value)
|
||||
return digest
|
||||
}
|
||||
good := hold("good", `{"module":"good","version":"1"}`)
|
||||
bad := hold("bad", `{"module":"bad","version":"1","requires":["amqp"]}`)
|
||||
good := hold("good", `{"module":"good","version":"1.0"}`)
|
||||
bad := hold("bad", `{"module":"bad","version":"1.0","requires":["amqp"]}`)
|
||||
// Both taken in by a merge: judged in full.
|
||||
j, err := ix.JudgeAll(ctx, map[string]bool{good: true, bad: true})
|
||||
if err != nil || j.Judged != 2 || j.Written != 2 || len(j.Refused) != 1 {
|
||||
@@ -91,7 +91,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
t.Fatalf("the new indexer at its start: %+v %v, said %d, want both manifests judged and nothing written", j, err, len(said))
|
||||
}
|
||||
// The manifest mended: its new digest is accepted and the module's refusal goes.
|
||||
mended := hold("bad", `{"module":"bad","version":"2"}`)
|
||||
mended := hold("bad", `{"module":"bad","version":"2.0"}`)
|
||||
if j, err := ix.JudgeAll(ctx, map[string]bool{mended: true}); err != nil || j.Written != 1 || len(j.Refused) != 0 {
|
||||
t.Fatalf("mended: %+v %v", j, err)
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// ADR 0579 §1: a manifest held before any verdict (taken in under the judges until then), which this judge finds a
|
||||
// problem in, stays accepted with the problem as a warning, carried in its value and said nowhere as a refusal; the
|
||||
// same problem in a manifest a merge takes in now, or in one whose digest changed, is refused in full.
|
||||
old := hold("old", `{"module":"old","version":"1","requires":["amqp"]}`)
|
||||
old := hold("old", `{"module":"old","version":"1.0","requires":["amqp"]}`)
|
||||
if j, err := ix.JudgeAll(ctx, nil); err != nil || len(j.Outgrown) != 1 || j.Outgrown[0] != "old" {
|
||||
t.Fatalf("an outgrown manifest: %+v %v", j, err)
|
||||
}
|
||||
@@ -111,8 +111,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if m := module("old"); m.Verdict != "" || len(m.Warnings) != 1 || len(said) != 1 {
|
||||
t.Fatalf("modules.old carries %+v, said %d", m, len(said))
|
||||
}
|
||||
changed := hold("old", `{"module":"old","version":"2","requires":["amqp"]}`)
|
||||
fresh := hold("new", `{"module":"new","version":"1","requires":["amqp"]}`)
|
||||
changed := hold("old", `{"module":"old","version":"2.0","requires":["amqp"]}`)
|
||||
fresh := hold("new", `{"module":"new","version":"1.0","requires":["amqp"]}`)
|
||||
if j, err := ix.JudgeAll(ctx, map[string]bool{changed: true, fresh: true}); err != nil || len(j.Outgrown) != 0 {
|
||||
t.Fatalf("a changed and a new manifest: %+v %v", j, err)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// manifest a judge refuses in full, its judge pass fails on the verdicts state, and the next pass, which knows nothing
|
||||
// of that take-in (a start, a pass kicked by a message), still refuses it in full, never as a warning, and ends the key.
|
||||
ix.Unjudged = newMem()
|
||||
keptDigest, err := ix.keepManifest(ctx, "kept", `{"module":"kept","version":"1","requires":["amqp"]}`)
|
||||
keptDigest, err := ix.keepManifest(ctx, "kept", `{"module":"kept","version":"1.0","requires":["amqp"]}`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
accepted, ids = append(accepted, a), append(ids, id)
|
||||
return nil
|
||||
}
|
||||
moved := hold("moved", `{"module":"moved","version":"1","requires":[`+
|
||||
moved := hold("moved", `{"module":"moved","version":"1.0","requires":[`+
|
||||
`{"name":"cache","storage":"key-value","template":"state","options":{"history":8}},`+
|
||||
`{"name":"audit","storage":"stream","template":"log","options":{"max-mib":64}}]}`)
|
||||
for pass := 0; pass < 2; pass++ {
|
||||
@@ -208,7 +208,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
t.Fatalf("said accepted %+v", accepted)
|
||||
}
|
||||
// DLV-I9 (design 25 § 12.2): a manifest asking for none, newly accepted, is said too, its entries an empty list.
|
||||
plain := hold("plain", `{"module":"plain","version":"1"}`)
|
||||
plain := hold("plain", `{"module":"plain","version":"1.0"}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{plain: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -217,8 +217,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
// Review round 1 of issue 1966: a trunk's held manifest judged by its digest (indexer_judge, judgeStale) is said as the
|
||||
// full pass says it, accepted or refused; a candidate's digest judged over the trunk is said nowhere.
|
||||
byDigest := hold("bydigest", `{"module":"bydigest","version":"1"}`)
|
||||
refusedBy := hold("refusedby", `{"module":"refusedby","version":"1","requires":["amqp"]}`)
|
||||
byDigest := hold("bydigest", `{"module":"bydigest","version":"1.0"}`)
|
||||
refusedBy := hold("refusedby", `{"module":"refusedby","version":"1.0","requires":["amqp"]}`)
|
||||
saidBefore := len(said)
|
||||
for module, digest := range map[string]string{"bydigest": byDigest, "refusedby": refusedBy} {
|
||||
if _, err := ix.judgeOver(ctx, nil, module, digest); err != nil {
|
||||
@@ -228,7 +228,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if last := accepted[len(accepted)-1]; last.Digest != byDigest || len(said) != saidBefore+1 || said[len(said)-1].Digest != refusedBy {
|
||||
t.Fatalf("judged by its digest, the trunk's manifest was said as %+v, refusals %d (were %d)", last, len(said), saidBefore)
|
||||
}
|
||||
candidate, err := ix.keepManifest(ctx, "bydigest", `{"module":"bydigest","version":"2"}`)
|
||||
candidate, err := ix.keepManifest(ctx, "bydigest", `{"module":"bydigest","version":"2.0"}`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -239,12 +239,12 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// judging pass says again and clears.
|
||||
ix.Findings = newMem()
|
||||
failing = 1
|
||||
once := hold("once", `{"module":"once","version":"1"}`)
|
||||
once := hold("once", `{"module":"once","version":"1.0"}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{once: true}); err != nil || accepted[len(accepted)-1].Module != "once" {
|
||||
t.Fatalf("a publish failing once was not published again: %v %+v", err, accepted[len(accepted)-1])
|
||||
}
|
||||
failing = 2
|
||||
flaky := hold("flaky", `{"module":"flaky","version":"1"}`)
|
||||
flaky := hold("flaky", `{"module":"flaky","version":"1.0"}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{flaky: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -277,13 +277,13 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
// DLV-I15: a change's renamed-from is judged against the trunk's manifest of the module: a name the trunk declares is
|
||||
// accepted, one it does not is refused naming the key.
|
||||
trunkRenamer := hold("renamer", `{"module":"renamer","version":"1","config":{"font-name":{"type":"string","description":"The font.","required":true,"runtime":true}}}`)
|
||||
trunkRenamer := hold("renamer", `{"module":"renamer","version":"1.0","config":{"font-name":{"type":"string","description":"The font.","required":true,"runtime":true}}}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{trunkRenamer: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for raw, want := range map[string]string{
|
||||
`{"module":"renamer","version":"1","config":{"font":{"type":"string","description":"The font.","required":true,"runtime":true,"renamed-from":"font-name"}}}`: "",
|
||||
`{"module":"renamer","version":"1","config":{"font":{"type":"string","description":"The font.","required":true,"runtime":true,"renamed-from":"typeface"}}}`: `renamed from "typeface"`,
|
||||
`{"module":"renamer","version":"1.0","config":{"font":{"type":"string","description":"The font.","required":true,"runtime":true,"renamed-from":"font-name"}}}`: "",
|
||||
`{"module":"renamer","version":"1.0","config":{"font":{"type":"string","description":"The font.","required":true,"runtime":true,"renamed-from":"typeface"}}}`: `renamed from "typeface"`,
|
||||
} {
|
||||
head, err := ix.keepManifest(ctx, "renamer", raw)
|
||||
if err != nil {
|
||||
@@ -305,8 +305,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
ix.Packages.(*memStore).put(SeriesKey(sdkGo, "0.1"), value)
|
||||
}
|
||||
for raw, refusedAtMerge := range map[string]bool{
|
||||
`{"module":"pkguser","version":"1","packages":{"@novox/ui":"0.1"}}`: true,
|
||||
`{"module":"pkguser","version":"2","packages":{"` + sdkGo + `":"0.1"}}`: false,
|
||||
`{"module":"pkguser","version":"1.0","packages":{"@novox/ui":"0.1"}}`: true,
|
||||
`{"module":"pkguser","version":"2.0","packages":{"` + sdkGo + `":"0.1"}}`: false,
|
||||
} {
|
||||
head, err := ix.keepManifest(ctx, "pkguser", raw)
|
||||
if err != nil {
|
||||
@@ -328,8 +328,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// 1966/AC11: modules using state and none using logs but the foundation: logs counts 0, so a manifest of another
|
||||
// module using logs is refused and the foundation's is accepted.
|
||||
ix.OldSections = newMem()
|
||||
hold("user", `{"module":"user","version":"1","state":["x"]}`)
|
||||
hold("mesh-grants", `{"module":"mesh-grants","version":"1","logs":[{"name":"l"}]}`)
|
||||
hold("user", `{"module":"user","version":"1.0","state":["x"]}`)
|
||||
hold("mesh-grants", `{"module":"mesh-grants","version":"1.0","logs":[{"name":"l"}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -348,7 +348,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
t.Fatalf("the old sections count %v, want state 1 and the rest 0", c)
|
||||
}
|
||||
// DLV-J2, DLV-J3 (ADR 0615 §1): one reads entry on the assigner's state counts 1 for the assigner and 0 for the indexer.
|
||||
hold("reader", `{"module":"reader","version":"1","state":["x"],"reads":["mesh-delivery-assigner.wants"]}`)
|
||||
hold("reader", `{"module":"reader","version":"1.0","state":["x"],"reads":["mesh-delivery-assigner.wants"]}`)
|
||||
if _, err := ix.JudgeAll(ctx, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -362,7 +362,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// Design 47 *A module's registration* (b229f5c4 lines 480-481): a template in the manifest of every part on the list is
|
||||
// refused, the runner's included.
|
||||
for _, part := range []string{"mesh-config", "mesh-delivery-pipeline"} {
|
||||
d := hold(part, `{"module":"`+part+`","version":"1","requires":[{"name":"cache","storage":"key-value","template":"state"}]}`)
|
||||
d := hold(part, `{"module":"`+part+`","version":"1.0","requires":[{"name":"cache","storage":"key-value","template":"state"}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{d: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -374,8 +374,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
"mesh-delivery-builder", "mesh-delivery-checker", "mesh-config", "mesh-vault", "mesh-delivery-pipeline"}) {
|
||||
t.Fatalf("the foundation is %v, want exactly the nine of ADR 0619 and the pipeline runner (ADR 0666 §4)", judge.Foundation)
|
||||
}
|
||||
late := hold("late", `{"module":"late","version":"1","logs":[{"name":"l"}]}`)
|
||||
grants := hold("mesh-grants", `{"module":"mesh-grants","version":"2","logs":[{"name":"l"},{"name":"m"}]}`)
|
||||
late := hold("late", `{"module":"late","version":"1.0","logs":[{"name":"l"}]}`)
|
||||
grants := hold("mesh-grants", `{"module":"mesh-grants","version":"2.0","logs":[{"name":"l"},{"name":"m"}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{late: true, grants: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -387,11 +387,11 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
// 1966/AC11: the sole user of an old section changes its manifest and keeps the section: accepted, since it was accepted
|
||||
// with it (the count is the accepted set held from the last pass, not recounted from fresh digests).
|
||||
hold("solo", `{"module":"solo","version":"1","objects":[{"name":"o","max-mib":1}]}`)
|
||||
hold("solo", `{"module":"solo","version":"1.0","objects":[{"name":"o","max-mib":1}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
solo2 := hold("solo", `{"module":"solo","version":"2","objects":[{"name":"o","max-mib":2}]}`)
|
||||
solo2 := hold("solo", `{"module":"solo","version":"2.0","objects":[{"name":"o","max-mib":2}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{solo2: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
ix.Logf = func(f string, a ...any) { logged = append(logged, fmt.Sprintf(f, a...)) }
|
||||
held := ix.OldSections
|
||||
ix.OldSections = unreadable{held}
|
||||
retry := hold("late", `{"module":"late","version":"2","logs":[{"name":"l"}]}`)
|
||||
retry := hold("late", `{"module":"late","version":"2.0","logs":[{"name":"l"}]}`)
|
||||
if _, err := ix.JudgeAll(ctx, map[string]bool{retry: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -415,9 +415,9 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
// event) while a newer build of the indexer is on the trunk, and is judged again at the next judge; once this program's
|
||||
// build is the trunk's newest it is refused; a wait is written into the module's value as a refusal naming the fields.
|
||||
ownFP := "src2:" + strings.Repeat("e", 64)
|
||||
hold(Module, `{"module":"mesh-delivery-indexer","version":"1"}`)
|
||||
hold(Module, `{"module":"mesh-delivery-indexer","version":"1.0"}`)
|
||||
ix.ownFP = ownFP // this program started when the trunk held another build of the indexer than the one it holds now
|
||||
later := hold("later", `{"module":"later","version":"1","a-field-from-later":1,"another":{"x":1}}`)
|
||||
later := hold("later", `{"module":"later","version":"1.0","a-field-from-later":1,"another":{"x":1}}`)
|
||||
said = nil
|
||||
before := len(said)
|
||||
j, err = ix.JudgeAll(ctx, map[string]bool{later: true})
|
||||
@@ -450,7 +450,7 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
ix.ownFP = ownFP
|
||||
// A renamed field is a known mistake: refused at once.
|
||||
renamed := hold("renamed", `{"module":"renamed","version":"1","needs":{"x":"y"}}`)
|
||||
renamed := hold("renamed", `{"module":"renamed","version":"1.0","needs":{"x":"y"}}`)
|
||||
if j, err := ix.JudgeAll(ctx, map[string]bool{renamed: true}); err != nil || len(j.Waiting) != 1 || !meshcatalogclient.VerdictRefuses(verdict(renamed)) {
|
||||
t.Fatalf("a renamed field: %+v %v", j, err)
|
||||
}
|
||||
@@ -513,8 +513,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
}
|
||||
return digest
|
||||
}
|
||||
atStart := stale("tools", `{"module":"tools","version":"7"}`)
|
||||
ownRefusal := stale("client", `{"module":"client","version":"7"}`)
|
||||
atStart := stale("tools", `{"module":"tools","version":"7.0"}`)
|
||||
ownRefusal := stale("client", `{"module":"client","version":"7.0"}`)
|
||||
if _, _, err := ix.writeVerdict(ctx, ownRefusal, meshcatalog.VerdictsByDigestValue{Module: "client", State: meshcatalogclient.VerdictRefused,
|
||||
Problems: []string{"x"}, Judge: ix.judgeID(), At: ptr(time.Now())}); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -522,13 +522,13 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if _, err := ix.JudgeAtStart(ctx); err != nil || meshcatalogclient.VerdictRefuses(verdict(atStart)) || verdict(atStart).Judge != ix.judgeID() || !meshcatalogclient.VerdictRefuses(verdict(ownRefusal)) {
|
||||
t.Fatalf("the start pass: %+v, this judge's own refusal %+v (%v)", verdict(atStart), verdict(ownRefusal), err)
|
||||
}
|
||||
byPull := stale("tools", `{"module":"tools","version":"8"}`)
|
||||
byPull := stale("tools", `{"module":"tools","version":"8.0"}`)
|
||||
pull := forgemsg.Forge{Kind: forgemsg.ForgePull, Repository: "novox/mesh-tools", Number: 3, Branch: "main",
|
||||
Manifests: map[string]string{"modules/tools": `{"module":"tools","version":"8"}`}}
|
||||
Manifests: map[string]string{"modules/tools": `{"module":"tools","version":"8.0"}`}}
|
||||
if _, err := ix.ApplyMessage(ctx, pull); err != nil || meshcatalogclient.VerdictRefuses(verdict(byPull)) || verdict(byPull).Judge != ix.judgeID() {
|
||||
t.Fatalf("a pull carrying a digest an older judge refused: %+v %v", verdict(byPull), err)
|
||||
}
|
||||
byTool := stale("tools", `{"module":"tools","version":"9"}`)
|
||||
byTool := stale("tools", `{"module":"tools","version":"9.0"}`)
|
||||
if got := ix.JudgeAgain(ctx, "client", byTool); got.Stored || !strings.Contains(got.Answer, "tools's, not client's") || !meshcatalogclient.VerdictRefuses(verdict(byTool)) {
|
||||
t.Fatalf("indexer_judge with another module's digest: %+v", got)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
const ledger = `{"name":"records","storage":"ledger","template":"ledger","options":{"max-mib":512},"types":[` +
|
||||
`{"name":"decision","schema":{"title":{"type":"text"}},"operations":[{"name":"propose","effect":"set-fields","fields":["title"]}]}]}`
|
||||
manifest := func(entries string) string {
|
||||
return `{"module":"a","version":"1","requires":[` + entries + `]}`
|
||||
return `{"module":"a","version":"1.0","requires":[` + entries + `]}`
|
||||
}
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
@@ -30,7 +30,7 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
`{"name":"files","storage":"object-store","template":"objects","options":{"max-mib":2048}},` + ledger), nil},
|
||||
// Design 47: every kept data may say its form and its catch-up tool, in an old section and in `requires` by template,
|
||||
// and is accepted as read; one saying neither reads as before.
|
||||
{"a form and a catch-up tool on every kept kind", `{"module":"a","version":"1","tools":["a_take_in"],` +
|
||||
{"a form and a catch-up tool on every kept kind", `{"module":"a","version":"1.0","tools":["a_take_in"],` +
|
||||
`"state":["seen",{"name":"modules","form":1,"catch-up":"a_take_in"}],"logs":[{"name":"acts","form":2}],` +
|
||||
`"streams":[{"name":"forge","events":["merged"],"form":1,"catch-up":"a_take_in"}],` +
|
||||
`"objects":[{"name":"revisions","max-mib":64,"form":1,"catch-up":"a_take_in"}],"requires":[` +
|
||||
@@ -40,9 +40,9 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
`{"name":"blobs","storage":"object-store","template":"objects","options":{"max-mib":64},"form":4,"catch-up":"a_take_in"},` +
|
||||
`{"name":"records","storage":"ledger","template":"ledger","options":{"max-mib":512},"form":3,"catch-up":"a_take_in","types":[` +
|
||||
`{"name":"decision","schema":{"title":{"type":"text"}},"operations":[{"name":"propose","effect":"set-fields","fields":["title"]}]}]}]}`, nil},
|
||||
{"a catch-up tool the module lacks", `{"module":"a","version":"1","tools":["a_read"],"logs":[{"name":"acts","form":1,"catch-up":"a_take_in"}]}`,
|
||||
{"a catch-up tool the module lacks", `{"module":"a","version":"1.0","tools":["a_read"],"logs":[{"name":"acts","form":1,"catch-up":"a_take_in"}]}`,
|
||||
[]string{"a's kept log \"acts\"", "catch-up tool \"a_take_in\" is not among the module's tools (a_read)"}},
|
||||
{"a catch-up tool the module lacks, in requires", `{"module":"a","version":"1","tools":["a_read"],"requires":[` +
|
||||
{"a catch-up tool the module lacks, in requires", `{"module":"a","version":"1.0","tools":["a_read"],"requires":[` +
|
||||
`{"name":"holds","storage":"key-value","template":"state","form":1,"catch-up":"nonexistent"}]}`,
|
||||
[]string{"a's kept state \"holds\"", "catch-up tool \"nonexistent\""}},
|
||||
{"a form below 0", manifest(`{"name":"x","storage":"key-value","template":"state","form":-1}`), []string{"requires entry \"x\"", "its form is -1"}},
|
||||
@@ -127,13 +127,13 @@ func TestBusStateIsJudgedOnce(t *testing.T) {
|
||||
"reader": {Module: "reader", Reads: []string{"owner.cache"}}}, ""},
|
||||
// DLV-I14 (design 32): the packages section names a known package, by its name in its own language (the packages
|
||||
// state's names, and a group member's at its head: known), in a well-formed series; through a judge request too.
|
||||
{"packages naming a known package", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{sdkGo: "0.2"}}}, ""},
|
||||
{"packages naming a known package, by request", catalogue.Shelf{"user": {Module: "user", Packages: map[string]string{sdkGo: "0.2"}}}, ""},
|
||||
{"packages naming a package by the builder's name", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{"mesh-sdk/go": "0.1"}}},
|
||||
{"packages naming a known package", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Version: "1.0", Packages: map[string]string{sdkGo: "0.2"}}}, ""},
|
||||
{"packages naming a known package, by request", catalogue.Shelf{"user": {Module: "user", Version: "1.0", Packages: map[string]string{sdkGo: "0.2"}}}, ""},
|
||||
{"packages naming a package by the builder's name", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Version: "1.0", Packages: map[string]string{"mesh-sdk/go": "0.1"}}},
|
||||
`user's packages name "mesh-sdk/go", which no package of the mesh is named`},
|
||||
{"packages naming an unknown package, by request", catalogue.Shelf{"user": {Module: "user", Packages: map[string]string{"@novox/ui": "0.1"}}},
|
||||
{"packages naming an unknown package, by request", catalogue.Shelf{"user": {Module: "user", Version: "1.0", Packages: map[string]string{"@novox/ui": "0.1"}}},
|
||||
`user's packages name "@novox/ui", which no package of the mesh is named`},
|
||||
{"packages in an ill-formed series", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Packages: map[string]string{sdkGo: "v0.2"}}},
|
||||
{"packages in an ill-formed series", catalogue.Shelf{"mesh-sdk": sdk, "user": {Module: "user", Version: "1.0", Packages: map[string]string{sdkGo: "v0.2"}}},
|
||||
`user's packages accept "` + sdkGo + `" in the series "v0.2"`},
|
||||
} {
|
||||
got := strings.Join(append(BusStateCatalogueProblems(c.shelf), PackagesCatalogueProblems(c.shelf, known)...), "\n")
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package judge
|
||||
|
||||
import (
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Design 47 G §368, §386, §387, §89: the manifest validator reads the manifests' new words before any manifest uses them.
|
||||
func TestTheJudgeReadsMilestoneGsWords(t *testing.T) {
|
||||
for _, row := range []struct {
|
||||
name string
|
||||
raw string
|
||||
want string // a word of the first problem; empty: accepted
|
||||
}{
|
||||
{name: "MAJOR.MINOR", raw: `{"module":"a","version":"1.4"}`},
|
||||
{name: "a pre-release suffix", raw: `{"module":"a","version":"1.4-beta"}`, want: "version"},
|
||||
{name: "three numbers", raw: `{"module":"a","version":"1.4.2"}`, want: "version"},
|
||||
{name: "a findings state without its stream", raw: `{"module":"a","version":"1.0","state":["findings"]}`, want: "findings"},
|
||||
{name: "a findings state with its stream and ask", raw: `{"module":"a","version":"1.0","state":["findings"],` +
|
||||
`"streams":[{"name":"a-findings","events":["finding-written"],"retention":"history"}],"consumes":["mesh-conditions.findings-asked"]}`},
|
||||
} {
|
||||
raws := map[string][]byte{"a": []byte(row.raw)}
|
||||
var refused map[string][]string
|
||||
WithSeats([]catalogue.Seat{{Name: "thing", Scope: catalogue.ScopeMesh, Emits: []string{"finding-written"}}}, func() {
|
||||
refused, _ = Shelf(raws, nil, 0)
|
||||
})
|
||||
got := strings.Join(refused["a"], "\n")
|
||||
if (row.want == "") != (got == "") || !strings.Contains(got, row.want) {
|
||||
t.Errorf("%s: refused with %q, want %q", row.name, got, row.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package judge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
// The manifests' words milestone G adds, read before any manifest uses them (design 47 G §89: the manifest validator's
|
||||
// reading of the new words is an edge of kind 4 that the delivery plan derives).
|
||||
|
||||
// majorMinor is a manifest's version: two numbers (design 47 G §368). No pre-release or custom suffix exists.
|
||||
var majorMinor = regexp.MustCompile(`^[0-9]+\.[0-9]+$`)
|
||||
|
||||
// FindingsAsked is the event an observer consumes to say its findings again (design 47 G §387).
|
||||
const FindingsAsked = "mesh-conditions.findings-asked"
|
||||
|
||||
// FindingStreamOf is the stream an observer says its findings on (design 47 G §383).
|
||||
func FindingStreamOf(module string) string { return module + "-findings" }
|
||||
|
||||
// versionProblems refuses a manifest whose `version` is not two numbers MAJOR.MINOR, or is missing (design 47 G §368). The
|
||||
// judge's entry (Manifest) holds a manifest to it; the parser the inputs of a fingerprint are read by does not.
|
||||
func versionProblems(m catalogue.Manifest) []string {
|
||||
if majorMinor.MatchString(m.Version) {
|
||||
return nil
|
||||
}
|
||||
return []string{fmt.Sprintf("%s says its version as %q; a manifest names `version` as two numbers MAJOR.MINOR such as 1.4, "+
|
||||
"and no pre-release or custom suffix exists (design 47 G §368)", m.Module, m.Version)}
|
||||
}
|
||||
|
||||
// gWordsProblems are the problems of a manifest's words milestone G adds: the finding stream and
|
||||
// ask of a module that declares a state `findings` (§387). The `*` emitter of `consumes` (§386) is judged with the
|
||||
// other consumed patterns (consumePattern).
|
||||
func gWordsProblems(m catalogue.Manifest) []string {
|
||||
var problems []string
|
||||
for _, s := range m.State {
|
||||
if s.Name != "findings" {
|
||||
continue
|
||||
}
|
||||
stream := FindingStreamOf(m.Module)
|
||||
if !slices.ContainsFunc(m.Streams, func(d catalogue.StreamDeclaration) bool { return d.Name == stream }) {
|
||||
problems = append(problems, fmt.Sprintf("%s declares the state findings without the stream %q its findings are said on "+
|
||||
"(design 47 G §387)", m.Module, stream))
|
||||
}
|
||||
if !slices.Contains(m.Consumes, FindingsAsked) {
|
||||
problems = append(problems, fmt.Sprintf("%s declares the state findings without consuming %q, with which the "+
|
||||
"keeper asks its findings again (design 47 G §387)", m.Module, FindingsAsked))
|
||||
}
|
||||
break
|
||||
}
|
||||
return problems
|
||||
}
|
||||
@@ -45,6 +45,9 @@ func Manifest(raw []byte, predefined catalogue.PredefinedList) (m catalogue.Mani
|
||||
if err != nil {
|
||||
return catalogue.Manifest{}, problemsOf(err)
|
||||
}
|
||||
if problems = versionProblems(m); len(problems) > 0 {
|
||||
return catalogue.Manifest{}, problems
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,30 +20,30 @@ func TestTheJudge(t *testing.T) {
|
||||
raws map[string]string
|
||||
want map[string]string // module: a word of its first problem; absent: accepted
|
||||
}{
|
||||
{name: "a valid manifest", raws: map[string]string{"a": `{"module":"a","version":"1"}`}},
|
||||
{name: "a refused manifest", raws: map[string]string{"a": `{"module":"a","version":"1","provides":[{"name":"amqp"}]}`},
|
||||
{name: "a valid manifest", raws: map[string]string{"a": `{"module":"a","version":"1.0"}`}},
|
||||
{name: "a refused manifest", raws: map[string]string{"a": `{"module":"a","version":"1.0","provides":[{"name":"amqp"}]}`},
|
||||
want: map[string]string{"a": `provides "amqp", which is not a provision`}},
|
||||
{name: "a provision named as a credential's", raws: map[string]string{"a": `{"module":"a","version":"1","provides":[{"name":"secret-db","scope":"mesh"}]}`},
|
||||
{name: "a provision named as a credential's", raws: map[string]string{"a": `{"module":"a","version":"1.0","provides":[{"name":"secret-db","scope":"mesh"}]}`},
|
||||
want: map[string]string{"a": `secret-`}},
|
||||
{name: "an unknown field", raws: map[string]string{"a": `{"module":"a","version":"1","a-field-from-later":1}`},
|
||||
{name: "an unknown field", raws: map[string]string{"a": `{"module":"a","version":"1.0","a-field-from-later":1}`},
|
||||
want: map[string]string{"a": `"a-field-from-later"`}},
|
||||
// Design 47 G §23, §28: a step's status is kept in the registration and never in a manifest.
|
||||
{name: "a manifest naming a step's status", raws: map[string]string{"a": `{"module":"a","version":"1","policy":{"lint":"bypass"}}`},
|
||||
{name: "a manifest naming a step's status", raws: map[string]string{"a": `{"module":"a","version":"1.0","policy":{"lint":"bypass"}}`},
|
||||
want: map[string]string{"a": `"policy"`}},
|
||||
{name: "a manifest under another name", raws: map[string]string{"b": `{"module":"a","version":"1"}`},
|
||||
{name: "a manifest under another name", raws: map[string]string{"b": `{"module":"a","version":"1.0"}`},
|
||||
want: map[string]string{"b": `of module "a", not "b"`}},
|
||||
{name: "a seat declared twice",
|
||||
raws: map[string]string{
|
||||
"one": `{"module":"one","version":"1","seats":[{"name":"thing","scope":"mesh"}]}`,
|
||||
"two": `{"module":"two","version":"1","seats":[{"name":"thing","scope":"mesh"}]}`,
|
||||
"ok": `{"module":"ok","version":"1"}`},
|
||||
"one": `{"module":"one","version":"1.0","seats":[{"name":"thing","scope":"mesh"}]}`,
|
||||
"two": `{"module":"two","version":"1.0","seats":[{"name":"thing","scope":"mesh"}]}`,
|
||||
"ok": `{"module":"ok","version":"1.0"}`},
|
||||
want: map[string]string{"one": "already declares", "two": "already declares"}},
|
||||
// The lead's ruling 5 for A2h: a module that claims a seat and serves its verbs keeps tools of its own beside them
|
||||
// (the enrolment's first-view tools, DLV-M6), and the judge takes it.
|
||||
{name: "a claimed seat's module with tools of its own",
|
||||
raws: map[string]string{
|
||||
"def": `{"module":"def","version":"1","seats":[{"name":"enrolment","scope":"mesh","serves":["issue","again"]}]}`,
|
||||
"enrolment": `{"module":"enrolment","version":"1","claims":[{"name":"enrolment","scope":"mesh","serves":["issue","again"]}],` +
|
||||
"def": `{"module":"def","version":"1.0","seats":[{"name":"enrolment","scope":"mesh","serves":["issue","again"]}]}`,
|
||||
"enrolment": `{"module":"enrolment","version":"1.0","claims":[{"name":"enrolment","scope":"mesh","serves":["issue","again"]}],` +
|
||||
`"tools":["enrolment_first_views","enrolment_first_view_again"]}`}},
|
||||
} {
|
||||
raws := map[string][]byte{}
|
||||
@@ -67,10 +67,10 @@ func TestTheJudge(t *testing.T) {
|
||||
// A field the judge does not know waits in the indexer's judge and stays a refusal in the checker's (clause 3 of the
|
||||
// record on a release's Approve); a renamed field and any other problem are refused by both.
|
||||
waitRaws := map[string][]byte{
|
||||
"later": []byte(`{"module":"later","version":"1","later-field":true,"other":1}`),
|
||||
"renamed": []byte(`{"module":"renamed","version":"1","needs":{"x":"y"}}`),
|
||||
"bad": []byte(`{"module":"bad","version":"1","provides":[{"name":"amqp"}]}`),
|
||||
"ok": []byte(`{"module":"ok","version":"1"}`),
|
||||
"later": []byte(`{"module":"later","version":"1.0","later-field":true,"other":1}`),
|
||||
"renamed": []byte(`{"module":"renamed","version":"1.0","needs":{"x":"y"}}`),
|
||||
"bad": []byte(`{"module":"bad","version":"1.0","provides":[{"name":"amqp"}]}`),
|
||||
"ok": []byte(`{"module":"ok","version":"1.0"}`),
|
||||
}
|
||||
refused, waits, _ := ShelfWaiting(waitRaws, nil, 0, nil, nil)
|
||||
if !reflect.DeepEqual(waits, map[string][]string{"later": {"later-field", "other"}}) || len(refused) != 2 || refused["renamed"] == nil || refused["bad"] == nil {
|
||||
@@ -82,7 +82,7 @@ func TestTheJudge(t *testing.T) {
|
||||
// The private network's manifest, which the mesh provides itself, is accepted (moved from mesh-sdk overlay's test).
|
||||
if raw, err := json.Marshal(overlay.Manifest()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if _, problems := Manifest(raw, nil); len(problems) > 0 {
|
||||
} else if _, problems := Manifest(versioned(t, raw), nil); len(problems) > 0 {
|
||||
t.Errorf("the provided private network is refused: %v", problems)
|
||||
}
|
||||
shelf := catalogue.Shelf{"nats": {}, "mesh-nats": {}, "a.b": {}}
|
||||
@@ -103,8 +103,8 @@ func TestTheJudge(t *testing.T) {
|
||||
// What cmd/mesh-judge answers the checker (ADR 0578 §2): a composer request in, a verdict out, each manifest accepted
|
||||
// or refused; a manifest left as a digest is a request it cannot run.
|
||||
r := composer.Request{V: composer.Version, Cases: []composer.Case{{Name: "change", Manifests: map[string]composer.Manifest{
|
||||
"a": {Raw: json.RawMessage(`{"module":"a","version":"1"}`)},
|
||||
"b": {Raw: json.RawMessage(`{"module":"b","version":"1","requires":["amqp"]}`)},
|
||||
"a": {Raw: json.RawMessage(`{"module":"a","version":"1.0"}`)},
|
||||
"b": {Raw: json.RawMessage(`{"module":"b","version":"1.0","requires":["amqp"]}`)},
|
||||
}}}}
|
||||
v, err := Request(r)
|
||||
if err != nil || v.V != composer.Version || len(v.Cases) != 1 || v.SDK != Identity() || !v.Cases[0].Manifests["a"].Accepted ||
|
||||
@@ -116,13 +116,13 @@ func TestTheJudge(t *testing.T) {
|
||||
// state, which a trunk module uses, is accepted.
|
||||
old := composer.Request{V: composer.Version, Cases: []composer.Case{
|
||||
{Name: "change", Manifests: map[string]composer.Manifest{
|
||||
"user": {Raw: json.RawMessage(`{"module":"user","version":"1","state":["x"]}`)},
|
||||
"late": {Raw: json.RawMessage(`{"module":"late","version":"1","logs":[{"name":"l"}]}`)},
|
||||
"newer": {Raw: json.RawMessage(`{"module":"newer","version":"1","state":["y"]}`)},
|
||||
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1","logs":[{"name":"l"}]}`)}}},
|
||||
"user": {Raw: json.RawMessage(`{"module":"user","version":"1.0","state":["x"]}`)},
|
||||
"late": {Raw: json.RawMessage(`{"module":"late","version":"1.0","logs":[{"name":"l"}]}`)},
|
||||
"newer": {Raw: json.RawMessage(`{"module":"newer","version":"1.0","state":["y"]}`)},
|
||||
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1.0","logs":[{"name":"l"}]}`)}}},
|
||||
{Name: "trunk", Manifests: map[string]composer.Manifest{
|
||||
"user": {Raw: json.RawMessage(`{"module":"user","version":"1","state":["x"]}`)},
|
||||
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1","logs":[{"name":"l"}]}`)}}}}}
|
||||
"user": {Raw: json.RawMessage(`{"module":"user","version":"1.0","state":["x"]}`)},
|
||||
"mesh-grants": {Raw: json.RawMessage(`{"module":"mesh-grants","version":"1.0","logs":[{"name":"l"}]}`)}}}}}
|
||||
ov, err := Request(old)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -137,3 +137,19 @@ func TestTheJudge(t *testing.T) {
|
||||
t.Fatal("a manifest left as a digest was judged")
|
||||
}
|
||||
}
|
||||
|
||||
// versioned is a manifest whose `version` is a MAJOR.MINOR (design 47 G §368): the private network's manifest is
|
||||
// mesh-networking's, which G's change gives its version.
|
||||
func versioned(t *testing.T, raw []byte) []byte {
|
||||
t.Helper()
|
||||
var fields map[string]any
|
||||
if err := json.Unmarshal(raw, &fields); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fields["version"] = "1.0"
|
||||
out, err := json.Marshal(fields)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
// 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",
|
||||
const knowledge = `{"module":"mesh-knowledge","version":"1.0",
|
||||
"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\": {}}"}],
|
||||
@@ -41,7 +41,7 @@ func TestObjectBucketsAreJudgedAsADR0592Says(t *testing.T) {
|
||||
}
|
||||
}
|
||||
// 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 ||
|
||||
if _, err := ParseManifest([]byte(`{"module":"kv","version":"1.0","objects":[{"name":"x","max-mib":1}]}`)); err == nil ||
|
||||
!strings.Contains(err.Error(), "KV_") {
|
||||
t.Errorf("a bucket kv_x was taken: %v", err)
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func TestObjectBucketsAreJudgedAsADR0592Says(t *testing.T) {
|
||||
return m
|
||||
}
|
||||
owner := parse(knowledge)
|
||||
reader := parse(`{"module":"records-page","version":"1","reads":["mesh-knowledge.sections"]}`)
|
||||
reader := parse(`{"module":"records-page","version":"1.0","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)
|
||||
|
||||
@@ -2536,7 +2536,7 @@ func parseManifest(raw []byte, predefined catalogue.PredefinedList) (catalogue.M
|
||||
}
|
||||
m.SetPredefined(predefined)
|
||||
|
||||
var problems []string
|
||||
problems := gWordsProblems(m)
|
||||
if !name.MatchString(m.Module) {
|
||||
problems = append(problems, fmt.Sprintf(
|
||||
"%q is not a usable module name: lower-case letters, digits, dashes and dots", m.Module))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user