diff --git a/modules/mesh-delivery-indexer/judge/rules.go b/modules/mesh-delivery-indexer/judge/rules.go index 5e32d375..affc57b8 100644 --- a/modules/mesh-delivery-indexer/judge/rules.go +++ b/modules/mesh-delivery-indexer/judge/rules.go @@ -2938,7 +2938,6 @@ func parseManifest(raw []byte, predefined catalogue.PredefinedList) (catalogue.M } } problems = append(problems, invokeProblems(m)...) - problems = append(problems, waitProblems(m)...) problems = append(problems, replacesProblems(m)...) problems = append(problems, UnitSettingProblems(m)...) problems = append(problems, OwnerSettingProblems(m)...) @@ -3390,43 +3389,6 @@ func replacesProblems(m catalogue.Manifest) []string { return problems } -// waitProblems judges the event families a module says a session may wait on (novox/hq ADR 0367 §2, §6): -// the tool runner's alone, each named whole — emitter and event, with no wildcard — and each once. Refused -// here, in the manifest's words, rather than at the composition of the bus's users. -func waitProblems(m catalogue.Manifest) []string { - if len(m.Waits) == 0 { - return nil - } - if !catalogue.IsToolRunner(m) { - return []string{fmt.Sprintf("%s says what a session waits on; only the tool runner's module (it says "+ - "\"tool-runner\": true) declares waits (novox/hq ADR 0367 §2)", m.Module)} - } - var problems []string - seen := map[string]bool{} - for _, w := range m.Waits { - if strings.ContainsAny(w, "*>") { - problems = append(problems, fmt.Sprintf("%s waits on %q: a family is named one by one, never a "+ - "wildcard (novox/hq ADR 0367 §2)", m.Module, w)) - continue - } - tokens := strings.Split(w, ".") - whole := len(tokens) >= 2 && name.MatchString(tokens[0]) - for _, t := range tokens[1:] { - whole = whole && waitToken.MatchString(t) - } - if !whole { - problems = append(problems, fmt.Sprintf("%s waits on %q, which does not name an emitter and an "+ - "event: a family is ., as consumes names one", m.Module, w)) - continue - } - if seen[w] { - problems = append(problems, fmt.Sprintf("%s waits on %q twice", m.Module, w)) - } - seen[w] = true - } - return problems -} - // whileStoppedProblems judges one container's maintenance window against its own definition // (novox/hq ADR 0189). // @@ -3646,8 +3608,6 @@ var renamed = map[string]string{ var toolName = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`) -var waitToken = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`) - var engineGeneric = map[string]string{ "database": "postgres-database, mssql-database, mariadb-database", "db": "postgres-database, mssql-database, mariadb-database", diff --git a/modules/mesh-delivery-indexer/judge/rules_test.go b/modules/mesh-delivery-indexer/judge/rules_test.go index 92b0d9fb..15b0f1c6 100644 --- a/modules/mesh-delivery-indexer/judge/rules_test.go +++ b/modules/mesh-delivery-indexer/judge/rules_test.go @@ -3156,29 +3156,20 @@ func caseAVerbWithAnUnknownKeyIsRefused(t *testing.T) { } } -// A family is named one by one, never by a wildcard, and only by the tool runner's module (ADR 0367 §2, §6): -// each refusal is said in the manifest's words, at parse, rather than at the composition of the bus's users. -func caseAWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner(t *testing.T) { - for manifest, want := range map[string]string{ - `{"module":"shop","version":"1.0","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module", - `{"module":"node-tools","version":"1.0","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module", // its name says nothing (issue 774) - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.*"]}`: "never a wildcard", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["**"]}`: "never a wildcard", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.>"]}`: "never a wildcard", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["*.reviewed"]}`: "never a wildcard", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["reviewed"]}`: "does not name an emitter and an event", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge..reviewed"]}`: "does not name an emitter and an event", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["Mesh-Knowledge.reviewed x"]}`: "does not name an emitter and an event", - `{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["a.b","a.b"]}`: "twice", - } { - _, err := ParseManifest([]byte(manifest)) - if err == nil { - t.Errorf("accepted: %s", manifest) - continue - } - if !strings.Contains(err.Error(), want) { - t.Errorf("%s refused for the wrong reason (want %q): %v", manifest, want, err) - } +// EE-D4 (design 34 every-event §10; ADR 0670 §2, ADR 0578 §1): the manifest no longer names what a session waits on, so +// `waits` is a field the validator does not know: refused by the checker's Shelf naming it, set aside to wait by the +// indexer's ShelfWaiting; the tool runner's manifest without it is accepted. +func caseAManifestCarryingWaitsIsAFieldNotKnown(t *testing.T) { + raws := map[string][]byte{ + "node-tools": []byte(`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.reviewed"]}`), + "runner": []byte(`{"module":"runner","version":"1.0","tool-runner":true}`), + } + if strict, _ := Shelf(raws, nil, 0); len(strict) != 1 || !strings.Contains(strings.Join(strict["node-tools"], " "), "waits") { + t.Errorf("Shelf on a manifest carrying waits: %v", strict) + } + if refused, waits, _ := ShelfWaiting(raws, nil, 0, nil, nil); len(refused) != 0 || + !reflect.DeepEqual(waits, map[string][]string{"node-tools": {"waits"}}) { + t.Errorf("ShelfWaiting on a manifest carrying waits: refused %v, waits %v", refused, waits) } } @@ -6355,7 +6346,7 @@ func TestRulesBus(t *testing.T) { t.Run("AServedValueNamingSomethingTheMeshDoesNotHaveIsRefused", caseAServedValueNamingSomethingTheMeshDoesNotHaveIsRefused) t.Run("ASiteScopedProvisionIsRefused", caseASiteScopedProvisionIsRefused) t.Run("AStateNameIsLocalAndOneToken", caseAStateNameIsLocalAndOneToken) - t.Run("AWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner", caseAWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner) + t.Run("AManifestCarryingWaitsIsAFieldNotKnown", caseAManifestCarryingWaitsIsAFieldNotKnown) t.Run("AWorkQueueStreamIsReadByExactlyOneProcessOfItsModule", caseAWorkQueueStreamIsReadByExactlyOneProcessOfItsModule) t.Run("AWorkQueueStreamsValuesAreBounded", caseAWorkQueueStreamsValuesAreBounded) t.Run("AZoneMustNameOneOfTheModulesListens", caseAZoneMustNameOneOfTheModulesListens)