G B-1 (Go): the tests G added are merged into existing ones as subtests, so mesh-sdk ends G with the tests it started with

unit 302 and integration 34, as at the merge base 45e143f; the buscalls test moves beside busstate's.

Builds: design 47 G §419, §626
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 22:03:15 +01:00
parent adf7392651
commit 63a290db3d
25 changed files with 167 additions and 72 deletions
+8 -1
View File
@@ -9,7 +9,7 @@ import (
// A bus function called before Serve waits for Serve and proceeds (issue 1966): a module that starts a goroutine
// before stdio.Serve and calls the bus there is no longer refused. It is refused only when the process never serves.
// The test drives the wait itself: serveWait is the test's own timer channel, no row sleeps on a clock.
func TestBusFunctionsWaitForServe(t *testing.T) {
func subBusFunctionsWaitForServe(t *testing.T) {
const refusal = "before Serve: a bundle reaches the bus through the runtime that launched it"
for _, tc := range []struct {
name string
@@ -72,3 +72,10 @@ func TestBusFunctionsWaitForServe(t *testing.T) {
})
}
}
// TestBusFunctionsWaitForServe runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestBusFunctionsWaitForServe(t *testing.T) {
t.Run("BusFunctionsWaitForServe", subBusFunctionsWaitForServe)
t.Run("ACapabilityWordIsReadOnceAndNamedWhenNotStated", subACapabilityWordIsReadOnceAndNamedWhenNotStated)
t.Run("ABundleAsksAnAcknowledgedPublishAndASubscriptionForNewMessages", subABundleAsksAnAcknowledgedPublishAndASubscriptionForNewMessages)
}
+14 -5
View File
@@ -80,7 +80,7 @@ func put(t *testing.T, dir, name string, b []byte, at time.Time) {
os.Chtimes(p, at, at)
}
func TestAGoodSnapshotPassesAndSaysItsStreams(t *testing.T) {
func subAGoodSnapshotPassesAndSaysItsStreams(t *testing.T) {
dir := t.TempDir()
good := snapshotTar(t, nil)
put(t, dir, "bus.tar", good, time.Now())
@@ -99,7 +99,7 @@ func TestAGoodSnapshotPassesAndSaysItsStreams(t *testing.T) {
}
}
func TestACorruptedChecksumFailsNamingTheFile(t *testing.T) {
func subACorruptedChecksumFailsNamingTheFile(t *testing.T) {
dir := t.TempDir()
put(t, dir, "bus.tar", snapshotTar(t, func(m *Manifest, files map[string][]byte) {
m.Streams[1].ArchiveSHA256 = sum([]byte("something else"))
@@ -116,7 +116,7 @@ func TestACorruptedChecksumFailsNamingTheFile(t *testing.T) {
}
}
func TestATruncatedSnapshotFails(t *testing.T) {
func subATruncatedSnapshotFails(t *testing.T) {
dir := t.TempDir()
good := snapshotTar(t, nil)
put(t, dir, "bus.tar", good[:len(good)*2/3], time.Now())
@@ -129,7 +129,7 @@ func TestATruncatedSnapshotFails(t *testing.T) {
}
}
func TestAnArchiveThatDoesNotReadToItsEndFailsEvenWithMatchingChecksums(t *testing.T) {
func subAnArchiveThatDoesNotReadToItsEndFailsEvenWithMatchingChecksums(t *testing.T) {
dir := t.TempDir()
put(t, dir, "bus.tar", snapshotTar(t, func(m *Manifest, files map[string][]byte) {
bad := []byte("not an s2 stream at all")
@@ -143,7 +143,7 @@ func TestAnArchiveThatDoesNotReadToItsEndFailsEvenWithMatchingChecksums(t *testi
}
}
func TestTheNewestTarIsVerifiedAndOnlyInsideTheDirectory(t *testing.T) {
func subTheNewestTarIsVerifiedAndOnlyInsideTheDirectory(t *testing.T) {
dir := t.TempDir()
now := time.Now()
put(t, dir, "old.tar", []byte("junk"), now.Add(-48*time.Hour))
@@ -171,3 +171,12 @@ func TestTheNewestTarIsVerifiedAndOnlyInsideTheDirectory(t *testing.T) {
t.Error("an empty directory is not a snapshot")
}
}
// TestAGoodSnapshotPassesAndSaysItsStreams runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestAGoodSnapshotPassesAndSaysItsStreams(t *testing.T) {
t.Run("AGoodSnapshotPassesAndSaysItsStreams", subAGoodSnapshotPassesAndSaysItsStreams)
t.Run("ACorruptedChecksumFailsNamingTheFile", subACorruptedChecksumFailsNamingTheFile)
t.Run("ATruncatedSnapshotFails", subATruncatedSnapshotFails)
t.Run("AnArchiveThatDoesNotReadToItsEndFailsEvenWithMatchingChecksums", subAnArchiveThatDoesNotReadToItsEndFailsEvenWithMatchingChecksums)
t.Run("TheNewestTarIsVerifiedAndOnlyInsideTheDirectory", subTheNewestTarIsVerifiedAndOnlyInsideTheDirectory)
}
-28
View File
@@ -1,28 +0,0 @@
package buscalls
import (
"encoding/json"
"testing"
)
// Design 47 G §587, §622: the ledger's upkeep calls have their requests and answers, and every family its word.
func TestTheLedgerUpkeepCallsAndTheirWords(t *testing.T) {
var removal LedgerRemoveRequest
if err := json.Unmarshal([]byte(`{"ledger":"records","instance":"r1"}`), &removal); err != nil || removal.Ledger != "records" || removal.Instance != "r1" {
t.Errorf("the removal read as %+v (%v)", removal, err)
}
raw, _ := json.Marshal(LedgerRemoved{Instance: "r1", Operations: 3, Bytes: 900})
if string(raw) != `{"instance":"r1","operations":3,"bytes":900}` {
t.Errorf("the removal's answer reads %s", raw)
}
raw, _ = json.Marshal(Fill{Count: 2, Bytes: 10, MaxBytes: 100})
if string(raw) != `{"count":2,"bytes":10,"max_bytes":100}` || LedgerFill != "mesh/ledger.fill" || LedgerRemove != "mesh/ledger.remove" {
t.Errorf("the fill reads %s, calls %s %s", raw, LedgerFill, LedgerRemove)
}
for word, want := range map[string]string{BusStateCalls: "bus-state-calls", LedgerCalls: "ledger-calls",
LedgerUpkeepCalls: "ledger-upkeep-calls", SentObjectsCalls: "sent-objects-calls"} {
if word != want {
t.Errorf("the word %q is %q", want, word)
}
}
}
+8 -2
View File
@@ -14,7 +14,7 @@ import (
// Issue 774 (bus blackouts at every user-list reload): only a request that reached no one is asked again, within the
// bound; a blackout probe that says the bus answers ends the wait at once.
func TestABusThatAnswersNothingIsWaitedOut(t *testing.T) {
func subABusThatAnswersNothingIsWaitedOut(t *testing.T) {
for _, row := range []struct {
name string
errs []error // what each try answers; the last repeats
@@ -71,7 +71,7 @@ func TestABusThatAnswersNothingIsWaitedOut(t *testing.T) {
// Design 47 G §351, §460: a kept call is asked again only while its key is open and not replaced; an error of `open` is
// logged naming the key and the ask is made again.
func TestAKeptCallIsAskedAgainOnlyWhileItsKeyIsOpen(t *testing.T) {
func subAKeptCallIsAskedAgainOnlyWhileItsKeyIsOpen(t *testing.T) {
for _, row := range []struct {
name string
open func(n int) (bool, error) // by the number of asks made so far
@@ -109,3 +109,9 @@ func TestAKeptCallIsAskedAgainOnlyWhileItsKeyIsOpen(t *testing.T) {
t.Errorf("a kept call with no open function was made")
}
}
// TestABusThatAnswersNothingIsWaitedOut runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestABusThatAnswersNothingIsWaitedOut(t *testing.T) {
t.Run("ABusThatAnswersNothingIsWaitedOut", subABusThatAnswersNothingIsWaitedOut)
t.Run("AKeptCallIsAskedAgainOnlyWhileItsKeyIsOpen", subAKeptCallIsAskedAgainOnlyWhileItsKeyIsOpen)
}
+30
View File
@@ -0,0 +1,30 @@
package busstate
import (
"encoding/json"
"testing"
"git.novox.be/novox/mesh-sdk/go/buscalls"
)
// Design 47 G §587, §622: the ledger's upkeep calls have their requests and answers, and every family its word.
func subTheLedgerUpkeepCallsAndTheirWords(t *testing.T) {
var removal buscalls.LedgerRemoveRequest
if err := json.Unmarshal([]byte(`{"ledger":"records","instance":"r1"}`), &removal); err != nil || removal.Ledger != "records" || removal.Instance != "r1" {
t.Errorf("the removal read as %+v (%v)", removal, err)
}
raw, _ := json.Marshal(buscalls.LedgerRemoved{Instance: "r1", Operations: 3, Bytes: 900})
if string(raw) != `{"instance":"r1","operations":3,"bytes":900}` {
t.Errorf("the removal's answer reads %s", raw)
}
raw, _ = json.Marshal(buscalls.Fill{Count: 2, Bytes: 10, MaxBytes: 100})
if string(raw) != `{"count":2,"bytes":10,"max_bytes":100}` || buscalls.LedgerFill != "mesh/ledger.fill" || buscalls.LedgerRemove != "mesh/ledger.remove" {
t.Errorf("the fill reads %s, calls %s %s", raw, buscalls.LedgerFill, buscalls.LedgerRemove)
}
for word, want := range map[string]string{buscalls.BusStateCalls: "bus-state-calls", buscalls.LedgerCalls: "ledger-calls",
buscalls.LedgerUpkeepCalls: "ledger-upkeep-calls", buscalls.SentObjectsCalls: "sent-objects-calls"} {
if word != want {
t.Errorf("the word %q is %q", want, word)
}
}
}
+8 -1
View File
@@ -14,7 +14,7 @@ import (
// A bundle keeps objects in its own object store through the runtime (ADR 0595 §2, §9; A3's request for distribution's
// incoming): each call is the runtime's method of buscalls, naming the store by its local name, and answers as the
// runtime answered; a method that is no bus-state call is refused before the runtime is asked.
func TestABundleKeepsObjectsThroughTheRuntime(t *testing.T) {
func subABundleKeepsObjectsThroughTheRuntime(t *testing.T) {
t.Setenv(stdio.ServedAs, "distribution")
inR, inW := io.Pipe()
outR, outW := io.Pipe()
@@ -100,3 +100,10 @@ func TestABundleKeepsObjectsThroughTheRuntime(t *testing.T) {
t.Errorf("put asked %v", p)
}
}
// TestABundleKeepsObjectsThroughTheRuntime runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestABundleKeepsObjectsThroughTheRuntime(t *testing.T) {
t.Run("ABundleKeepsObjectsThroughTheRuntime", subABundleKeepsObjectsThroughTheRuntime)
t.Run("TheLedgerUpkeepCallsAndTheirWords", subTheLedgerUpkeepCallsAndTheirWords)
t.Run("AValueLargerThanOneChunkIsPutAndGotBySession", subAValueLargerThanOneChunkIsPutAndGotBySession)
}
+1 -1
View File
@@ -62,7 +62,7 @@ func serveRuntime(t *testing.T, fn func(), handle func(method string, params map
// Design 47 G §518, §345, §490 (A-21): a value larger than one chunk is put as chunks in order under one call id, each
// answered before the next, with the store named in each; a get the runtime answers as a session is read chunk by chunk and
// checked against its digest.
func TestAValueLargerThanOneChunkIsPutAndGotBySession(t *testing.T) {
func subAValueLargerThanOneChunkIsPutAndGotBySession(t *testing.T) {
value := bytes.Repeat([]byte("0123456789abcdef"), (2*buscalls.ChunkBytes+1000)/16)
sum := sha256.Sum256(value)
digest := "sha256:" + hex.EncodeToString(sum[:])
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// Design 47 G §576: the words are read once, an unknown-call answer reads as none, and a word not stated fails naming it
// and the node (from MESH_NODE).
func TestACapabilityWordIsReadOnceAndNamedWhenNotStated(t *testing.T) {
func subACapabilityWordIsReadOnceAndNamedWhenNotStated(t *testing.T) {
t.Setenv("MESH_NODE", "ace")
asked := 0
var c capabilityWords
+8 -1
View File
@@ -54,7 +54,7 @@ func indexOf(out []map[string]any, id string) int {
// otherwise — and the controller declares the verbs it answers as tools. Its service bundle is run
// by its own process; launched a second time by the runtime it would be a second controller
// pretending to be an MCP server.
func TestABundleItsOwnProcessRunsIsNotServedByTheRuntime(t *testing.T) {
func subABundleItsOwnProcessRunsIsNotServedByTheRuntime(t *testing.T) {
m := aServiceModule(t)
if len(m.Bundles) != 1 {
t.Fatalf("the service's bundle was not kept: %+v", m.Bundles)
@@ -75,3 +75,10 @@ func TestABundleItsOwnProcessRunsIsNotServedByTheRuntime(t *testing.T) {
t.Fatalf("a tools bundle nothing runs is no longer served: %v", loads)
}
}
// TestABundleItsOwnProcessRunsIsNotServedByTheRuntime runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestABundleItsOwnProcessRunsIsNotServedByTheRuntime(t *testing.T) {
t.Run("ABundleItsOwnProcessRunsIsNotServedByTheRuntime", subABundleItsOwnProcessRunsIsNotServedByTheRuntime)
t.Run("TheBusNamesOfAnEntryAreOneRule", subTheBusNamesOfAnEntryAreOneRule)
t.Run("AStarEmitterHearsEachDeclaringModulesUnrestrictedStream", subAStarEmitterHearsEachDeclaringModulesUnrestrictedStream)
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
// ADR 0666 §16: the bus names of an entry are one rule. A state entry answers its bucket's stream and the stream of
// its object store; a local name that meets a name the mesh makes is a clash for the judge.
func TestTheBusNamesOfAnEntryAreOneRule(t *testing.T) {
func subTheBusNamesOfAnEntryAreOneRule(t *testing.T) {
state := BusStateEntry{Name: "views", Storage: StorageKeyValue, Template: TemplateState}
rows := []struct {
name string
+1 -1
View File
@@ -155,7 +155,7 @@ func TestNarrowingTwoPatterns(t *testing.T) {
// Design 47 G §386: `*.<event>` reaches the unrestricted stream of each module that declares the event, and never a
// restricted one; a wildcard before anything wider still reaches none.
func TestAStarEmitterHearsEachDeclaringModulesUnrestrictedStream(t *testing.T) {
func subAStarEmitterHearsEachDeclaringModulesUnrestrictedStream(t *testing.T) {
mail, err := decodeForTest([]byte(mailManifest(t, mailStream, `"emits":["account.added"],`)))
if err != nil {
t.Fatal(err)
+8 -2
View File
@@ -19,7 +19,7 @@ import (
// 1171/AC2: given an account file broker-<process id> in the controller's form {url, fingerprint, node,
// module, user, password, claims}, when the process package reads it, then it yields those fields and
// tolerates claims.
func TestReadAccountYieldsEveryFieldAndToleratesClaims(t *testing.T) {
func subReadAccountYieldsEveryFieldAndToleratesClaims(t *testing.T) {
path := writeAccount(t, map[string]any{
"url": "nats://novox:4222", "fingerprint": "sha256:ab", "node": "novox", "module": "mesh-mail",
"user": "novox.mesh-mail.send", "password": "secret-pw",
@@ -297,7 +297,7 @@ func TestModuleAccountNamesAndDialOptions(t *testing.T) {
// W1.3 (design 47 *The fingerprint handover*): a process's own build is the fingerprint the node-engine handed it, read
// once at its start; with none, or with one that is no single word, it says its own build is unknown and why.
func TestTheOwnBuildIsTheFingerprintTheProcessWasStartedWith(t *testing.T) {
func subTheOwnBuildIsTheFingerprintTheProcessWasStartedWith(t *testing.T) {
for _, c := range []struct{ name, env, fp, unknown string }{
{"handed", "src2:1480985e", "src2:1480985e", ""},
{"handed with spaces around", " src2:1480985e\n", "src2:1480985e", ""},
@@ -341,3 +341,9 @@ func TestTheOwnBuildIsTheFingerprintTheProcessWasStartedWith(t *testing.T) {
}
}
}
// TestReadAccountYieldsEveryFieldAndToleratesClaims runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestReadAccountYieldsEveryFieldAndToleratesClaims(t *testing.T) {
t.Run("ReadAccountYieldsEveryFieldAndToleratesClaims", subReadAccountYieldsEveryFieldAndToleratesClaims)
t.Run("TheOwnBuildIsTheFingerprintTheProcessWasStartedWith", subTheOwnBuildIsTheFingerprintTheProcessWasStartedWith)
}
+8 -2
View File
@@ -17,7 +17,7 @@ import (
// A module whose consumer the bus makes after the module started is not lost for that order: the hub tries again after
// each wait and calls live once it is bound (the checker's "until it starts again" hole).
func TestTheHubBindsALateConsumerAndSaysItIsLive(t *testing.T) {
func subTheHubBindsALateConsumerAndSaysItIsLive(t *testing.T) {
nc, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
@@ -69,7 +69,7 @@ func TestTheHubBindsALateConsumerAndSaysItIsLive(t *testing.T) {
// W1.12: a module hears a seat's event kept last per subject on its own stream through its durable, made by the maker
// after the events were said, and is handed the last of each subject; without the consumer the call says so.
func TestAModuleHearsASeatEventKeptOnItsOwnStream(t *testing.T) {
func subAModuleHearsASeatEventKeptOnItsOwnStream(t *testing.T) {
nc, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
@@ -141,3 +141,9 @@ func TestAModuleHearsASeatEventKeptOnItsOwnStream(t *testing.T) {
t.Fatal("the durable was not followed after the read")
}
}
// TestTheHubBindsALateConsumerAndSaysItIsLive runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestTheHubBindsALateConsumerAndSaysItIsLive(t *testing.T) {
t.Run("TheHubBindsALateConsumerAndSaysItIsLive", subTheHubBindsALateConsumerAndSaysItIsLive)
t.Run("AModuleHearsASeatEventKeptOnItsOwnStream", subAModuleHearsASeatEventKeptOnItsOwnStream)
}
+8 -1
View File
@@ -6,7 +6,7 @@ import (
)
// A verb's schema has its named types in place (the seat list's readers take one schema, not a schema and its types).
func TestResolveRefsPutsNamedTypesInPlace(t *testing.T) {
func subResolveRefsPutsNamedTypesInPlace(t *testing.T) {
defs := map[string]map[string]any{
"id": {"type": "string"},
"row": {"type": "object", "properties": map[string]any{"id": map[string]any{"$ref": "#/defs/id"}}},
@@ -34,3 +34,10 @@ func TestResolveRefsPutsNamedTypesInPlace(t *testing.T) {
}
}
}
// TestResolveRefsPutsNamedTypesInPlace runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestResolveRefsPutsNamedTypesInPlace(t *testing.T) {
t.Run("ResolveRefsPutsNamedTypesInPlace", subResolveRefsPutsNamedTypesInPlace)
t.Run("AVerbWithoutCallersTakesItsClassDefault", subAVerbWithoutCallersTakesItsClassDefault)
t.Run("AKeptEventsStreamIsNamedAndBoundedByItsKeep", subAKeptEventsStreamIsNamedAndBoundedByItsKeep)
}
+2 -2
View File
@@ -290,7 +290,7 @@ func TestAKeptEventsStreamIsNamedFromTheSeatAndTheEvent(t *testing.T) {
}
// Design 47 G §391: a verb that names no callers takes its class's default, a verb that names them keeps them.
func TestAVerbWithoutCallersTakesItsClassDefault(t *testing.T) {
func subAVerbWithoutCallersTakesItsClassDefault(t *testing.T) {
for _, c := range []struct {
verb Verb
want string
@@ -310,7 +310,7 @@ func TestAVerbWithoutCallersTakesItsClassDefault(t *testing.T) {
// Design 47 G §260, §396, §331: a kept event's stream is named from the seat and the event, 90 days and 16 MiB unless
// the keep says otherwise, and 0 is no age limit.
func TestAKeptEventsStreamIsNamedAndBoundedByItsKeep(t *testing.T) {
func subAKeptEventsStreamIsNamedAndBoundedByItsKeep(t *testing.T) {
d, err := Parse([]byte(`{"format":1,"seat":"mesh-delivery","scope":"mesh","grain":"seat-list","domain":"Delivery","decision":"x",
"events":[{"name":"owed","keep":{"max-age-days":7,"max-mib":64}},{"name":"toolchain-agreed","keep":{}},
{"name":"versions-filled","keep":{"max-age-days":0,"max-mib":1}}]}`))
+13 -1
View File
@@ -6,7 +6,7 @@ import (
)
// ADR 0666 §16: a body is a reference when it is exactly `{"mesh-object": Ref}`; anything else is a value.
func TestABodyIsAReferenceOnlyWhenItIsExactlyOne(t *testing.T) {
func subABodyIsAReferenceOnlyWhenItIsExactlyOne(t *testing.T) {
good := Ref{Store: "views-objects", Object: "k." + strings.Repeat("a", 64), Size: 3 << 20, Digest: strings.Repeat("a", 64), Form: FormVersion}
got, ok := ReadRef(Wrap(good))
if !ok || got != good {
@@ -29,3 +29,15 @@ func TestABodyIsAReferenceOnlyWhenItIsExactlyOne(t *testing.T) {
}
}
}
// TestABodyIsAReferenceOnlyWhenItIsExactlyOne runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestABodyIsAReferenceOnlyWhenItIsExactlyOne(t *testing.T) {
t.Run("ABodyIsAReferenceOnlyWhenItIsExactlyOne", subABodyIsAReferenceOnlyWhenItIsExactlyOne)
t.Run("ABodyOverTheMessageLimitIsSentAsAReference", subABodyOverTheMessageLimitIsSentAsAReference)
t.Run("ABundleReadsASentObjectThroughTheRuntime", subABundleReadsASentObjectThroughTheRuntime)
t.Run("AFoundationPartsSentStoreAgesFromItsSendLog", subAFoundationPartsSentStoreAgesFromItsSendLog)
t.Run("TheObjectToolsReadEverythingAndDropOnlyWhatIsNotLive", subTheObjectToolsReadEverythingAndDropOnlyWhatIsNotLive)
t.Run("ValuesOfAnySizeThroughTheRuntime", subValuesOfAnySizeThroughTheRuntime)
t.Run("AWriteLostLeavesNoObjectBehind", subAWriteLostLeavesNoObjectBehind)
t.Run("AValueLargerThanTheStoreTakesIsRefused", subAValueLargerThanTheStoreTakesIsRefused)
}
+3 -3
View File
@@ -9,7 +9,7 @@ import (
// ADR 0666 §16: a reply or an event over the per-message limit carries the name of an object, and the receiver reads it
// back whole; one that fits is sent as it is.
func TestABodyOverTheMessageLimitIsSentAsAReference(t *testing.T) {
func subABodyOverTheMessageLimitIsSentAsAReference(t *testing.T) {
m := newMemory()
s := Sender{Objects: memObjects{m}, Store: "m_sent-objects"}
fetch := ProcessFetch(memObjects{m})
@@ -48,7 +48,7 @@ func TestABodyOverTheMessageLimitIsSentAsAReference(t *testing.T) {
}
// A bundle reads a sent object through the runtime's sent-get.
func TestABundleReadsASentObjectThroughTheRuntime(t *testing.T) {
func subABundleReadsASentObjectThroughTheRuntime(t *testing.T) {
m := newMemory()
body := []byte(`{"text":"` + strings.Repeat("y", 3<<20) + `"}`)
sent, err := Sender{Objects: memObjects{m}, Store: "m_sent-objects"}.Send("reply.list", body)
@@ -69,7 +69,7 @@ func TestABundleReadsASentObjectThroughTheRuntime(t *testing.T) {
// Design 47 G §410, §330: a foundation part's sender keeps the sequence of its sends in its old state section
// `sent-log` and deletes the sent objects past 7 days at a later send, at most 20 a send.
func TestAFoundationPartsSentStoreAgesFromItsSendLog(t *testing.T) {
func subAFoundationPartsSentStoreAgesFromItsSendLog(t *testing.T) {
m := newMemory()
clock := time.Date(2026, 11, 1, 0, 0, 0, 0, time.UTC)
s := Sender{Objects: memObjects{m}, Store: "m_sent-objects", Log: m, Node: "n1", Now: func() time.Time { return clock }}
+1 -1
View File
@@ -25,7 +25,7 @@ func (a *acts) RecordHandAct(h views.HandAct) error {
// ADR 0666 §25: the four tools read what each store holds and drop only what is no longer live, each drop only with who
// asks and why, recorded as a hand act first.
func TestTheObjectToolsReadEverythingAndDropOnlyWhatIsNotLive(t *testing.T) {
func subTheObjectToolsReadEverythingAndDropOnlyWhatIsNotLive(t *testing.T) {
m := newMemory()
m.modified = map[string]time.Time{}
v := m.values()
+3 -3
View File
@@ -104,7 +104,7 @@ func valueRows(t *testing.T, v Values, multiples ...int) {
}
// ADR 0666 §16, C-S3, C-S5: values of 1x, 10x and 100x the limit through a bundle's runtime, whole.
func TestValuesOfAnySizeThroughTheRuntime(t *testing.T) {
func subValuesOfAnySizeThroughTheRuntime(t *testing.T) {
m := newMemory()
out := runtimeOf(t, m, func() (any, error) {
v := ForState("views")
@@ -117,7 +117,7 @@ func TestValuesOfAnySizeThroughTheRuntime(t *testing.T) {
}
// A write another writer won first leaves the object it put removed and the key as it found it.
func TestAWriteLostLeavesNoObjectBehind(t *testing.T) {
func subAWriteLostLeavesNoObjectBehind(t *testing.T) {
m := newMemory()
v := m.values()
if err := v.Put("k", big(3*kvlimit.ModuleStateValueBytes)); err != nil {
@@ -158,7 +158,7 @@ func (r *raceKV) Get(key string) (*Entry, error) {
}
// A store that takes no object as large as the value refuses it, loudly, and writes nothing.
func TestAValueLargerThanTheStoreTakesIsRefused(t *testing.T) {
func subAValueLargerThanTheStoreTakesIsRefused(t *testing.T) {
m := newMemory()
m.most = 100_000
v := m.values()
+1 -1
View File
@@ -346,7 +346,7 @@ func servesAlone(t *testing.T) {
// Design 47 G §559: a bundle's acknowledged publish asks `ack: true` and fails on the runtime's `{error}`; its
// subscription for new messages asks `deliver: new`.
func TestABundleAsksAnAcknowledgedPublishAndASubscriptionForNewMessages(t *testing.T) {
func subABundleAsksAnAcknowledgedPublishAndASubscriptionForNewMessages(t *testing.T) {
servesAlone(t)
t.Setenv(ServedAs, "keeper")
inR, inW := io.Pipe()
+9 -2
View File
@@ -22,7 +22,7 @@ import (
// An owner's change is an ordinary event on the shared events stream (novox/hq ADR 0635 §5): a reader that follows the
// owner's state by its read tool hears it on the module's durable consumer of that stream, with no stream of the owner's,
// and a message that is no views event goes to Other.
func TestAReaderHearsAnOwnersChangesAsOrdinaryEvents(t *testing.T) {
func subAReaderHearsAnOwnersChangesAsOrdinaryEvents(t *testing.T) {
nc, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
@@ -135,7 +135,7 @@ func TestAReaderHearsAnOwnersChangesAsOrdinaryEvents(t *testing.T) {
// A module has one durable consumer on the shared events stream, so the loops that hear events in one module must share
// one pull (process.EventHub): two handlers and the views reader on the hub each get their own messages and no other's,
// and a message nobody takes is acknowledged.
func TestTheViewsReaderAndTwoHandlersShareTheModulesOneDurable(t *testing.T) {
func subTheViewsReaderAndTwoHandlersShareTheModulesOneDurable(t *testing.T) {
nc, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
@@ -237,3 +237,10 @@ func TestTheViewsReaderAndTwoHandlersShareTheModulesOneDurable(t *testing.T) {
t.Fatal("the hub started late heard nothing")
}
}
// TestAReaderHearsAnOwnersChangesAsOrdinaryEvents runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestAReaderHearsAnOwnersChangesAsOrdinaryEvents(t *testing.T) {
t.Run("AReaderHearsAnOwnersChangesAsOrdinaryEvents", subAReaderHearsAnOwnersChangesAsOrdinaryEvents)
t.Run("TheViewsReaderAndTwoHandlersShareTheModulesOneDurable", subTheViewsReaderAndTwoHandlersShareTheModulesOneDurable)
t.Run("WriterSaysItsEventsAndHearsAsksOnTheBus", subWriterSaysItsEventsAndHearsAsksOnTheBus)
}
+1 -1
View File
@@ -38,7 +38,7 @@ type swAsked struct {
// A stdio module's writer says each of its events through the module's own publish, acknowledged, under the writer's
// message id, and hears the asks through the module's subscription (design 47 G A-16).
func TestStdioWriterPublishesAndListensThroughTheModulesOwnPlumbing(t *testing.T) {
func subStdioWriterPublishesAndListensThroughTheModulesOwnPlumbing(t *testing.T) {
type said struct {
event string
body string
+7 -1
View File
@@ -55,7 +55,7 @@ func markOf(state string, rev uint64, made time.Time) Entry {
// The owners' and the readers' side of a first view (ADR 0615 §4-§6, ADR 0621 §2-§3, ADR 0622): one table of cases,
// since mesh-delivery is over its test budget.
func TestViews(t *testing.T) {
func subViews(t *testing.T) {
made := time.Date(2026, 11, 4, 12, 0, 0, 0, time.UTC)
now := func() time.Time { return made.Add(time.Hour) }
written := made.Add(-time.Minute)
@@ -1210,3 +1210,9 @@ func (s *pagedSource) Page(after string, _ int, _ time.Duration) ([]KeyedEntry,
}
return out, "", nil
}
// TestViews runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestViews(t *testing.T) {
t.Run("Views", subViews)
t.Run("StdioWriterPublishesAndListensThroughTheModulesOwnPlumbing", subStdioWriterPublishesAndListensThroughTheModulesOwnPlumbing)
}
+1 -1
View File
@@ -18,7 +18,7 @@ import (
// Against a real bus: the writer's events are acknowledged by their stream, a start states what the observer observes, an
// ask published before the writer's consumer existed is never answered, one published after is, and after the connection
// is made again (Reconnected) the consumer is made again from the newest ask (design 47 G §383, §390, §485).
func TestWriterSaysItsEventsAndHearsAsksOnTheBus(t *testing.T) {
func subWriterSaysItsEventsAndHearsAsksOnTheBus(t *testing.T) {
nc, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
+22 -9
View File
@@ -81,7 +81,7 @@ var subjects = views.FindingSubjects("m", "n1")
// asked is the subject the module gives the writer for findings-asked, as its seat's generated contract has it (design 47 G A-17).
const asked = "mesh.seat.s.event.findings-asked"
func TestFindingSubjectsAreTheEventsStreamForm(t *testing.T) {
func subFindingSubjectsAreTheEventsStreamForm(t *testing.T) {
want := views.WriterSubjects{
Written: "mesh.stream.m.event.finding-written.n1", Cleared: "mesh.stream.m.event.finding-cleared.n1",
Stated: "mesh.stream.m.event.findings-stated.n1",
@@ -154,7 +154,7 @@ func finding(id, summary string) testFinding {
// A finding written says its event with the layout whole after the key, keeps the key's since, and says again only when
// what it says changed; a finding cleared says its event, also of a key that does not exist (design 47 G §383, §485).
func TestWriterWritesAndClearsFindingsAsEvents(t *testing.T) {
func subWriterWritesAndClearsFindingsAsEvents(t *testing.T) {
r := newRig(t)
ctx := context.Background()
first := r.now
@@ -202,7 +202,7 @@ func TestWriterWritesAndClearsFindingsAsEvents(t *testing.T) {
// An event the bus does not acknowledge is sent again for one minute, then written in the journal as an error naming the
// finding (design 47 G §383).
func TestWriterSendsAgainForAMinuteThenLogs(t *testing.T) {
func subWriterSendsAgainForAMinuteThenLogs(t *testing.T) {
r := newRig(t)
r.fail = 2
if err := r.w.Write(context.Background(), finding("a", "one")); err != nil || len(r.events()) != 1 {
@@ -225,7 +225,7 @@ func TestWriterSendsAgainForAMinuteThenLogs(t *testing.T) {
// rest; an ask naming another module is not answered, one naming none or this one is, with its id; an observe that fails
// says no set and is called again once a minute until a set is said; a connection made again makes the consumer again and
// states again (design 47 G §384, §461, §485).
func TestWriterStatesAtStartAndOnAsksAndRecovers(t *testing.T) {
func subWriterStatesAtStartAndOnAsksAndRecovers(t *testing.T) {
r := newRig(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -298,7 +298,7 @@ func waitEvent(t *testing.T, r *rig, n int) said {
}
// A write asked during a statement waits for it, so the statement never deletes the key the write made (design 47 G §485).
func TestWriterRunsOneActAtATime(t *testing.T) {
func subWriterRunsOneActAtATime(t *testing.T) {
r := newRig(t)
inside, release := make(chan struct{}), make(chan struct{})
r.observe = func(context.Context) (testObserved, error) {
@@ -329,7 +329,7 @@ func TestWriterRunsOneActAtATime(t *testing.T) {
// A writer owns its kinds (design 47 G §580), states them, deletes no key of another kind, and covers a views reader's
// findings written through it beside observe's (§639); an owner or waiting-on of no form is refused, naming the field (§678).
func TestWriterKindsAndReaderFindings(t *testing.T) {
func subWriterKindsAndReaderFindings(t *testing.T) {
ctx := context.Background()
r := newRigKinds(t, "k")
other := finding("x", "another bundle's")
@@ -396,7 +396,7 @@ func TestWriterKindsAndReaderFindings(t *testing.T) {
// kind, the scope module, the id escaped as a key's name is, a warning but urgent for view-too-large, the source views, the
// subject the module on its node; and CheckFinding refuses a finding breaking a rule before it is written, naming the field
// (§689).
func TestReaderFindingsAreLaidOutAndCheckFindingRefuses(t *testing.T) {
func subReaderFindingsAreLaidOutAndCheckFindingRefuses(t *testing.T) {
r := newRig(t)
for _, kind := range views.ViewKinds {
if err := views.PutViewFinding(r.w, kind, "o.s.main", "sum "+kind, "head"); err != nil {
@@ -441,7 +441,7 @@ func TestReaderFindingsAreLaidOutAndCheckFindingRefuses(t *testing.T) {
// A finding body whose wire form lacks a field the contract names is refused when the writer is made, naming the field
// (design 47 G A-3).
func TestWriterRefusesABodyWithoutAContractField(t *testing.T) {
func subWriterRefusesABodyWithoutAContractField(t *testing.T) {
type noSince struct {
Kind, Scope, ID, Observer string
At time.Time `json:"at"`
@@ -467,7 +467,7 @@ func TestWriterRefusesABodyWithoutAContractField(t *testing.T) {
// A part whose findings are raised as they happen holds them in a writer that observes from its own state (design 47 G A-29):
// the findings standing in the state are seeded before it starts, a statement says what is held, Write and Clear keep the held
// set, and an Observe of the part's own is refused.
func TestHeldWriterStatesWhatItHoldsFromItsOwnState(t *testing.T) {
func subHeldWriterStatesWhatItHoldsFromItsOwnState(t *testing.T) {
state := &fakeState{m: map[string][]byte{}}
raw, _ := json.Marshal(finding("seeded", "stood"))
state.m["module.seeded.k"] = raw
@@ -508,3 +508,16 @@ func TestHeldWriterStatesWhatItHoldsFromItsOwnState(t *testing.T) {
t.Fatalf("the statement says %+v after %d events", stated, len(sent))
}
}
// TestFindingSubjectsAreTheEventsStreamForm runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
func TestFindingSubjectsAreTheEventsStreamForm(t *testing.T) {
t.Run("FindingSubjectsAreTheEventsStreamForm", subFindingSubjectsAreTheEventsStreamForm)
t.Run("WriterWritesAndClearsFindingsAsEvents", subWriterWritesAndClearsFindingsAsEvents)
t.Run("WriterSendsAgainForAMinuteThenLogs", subWriterSendsAgainForAMinuteThenLogs)
t.Run("WriterStatesAtStartAndOnAsksAndRecovers", subWriterStatesAtStartAndOnAsksAndRecovers)
t.Run("WriterRunsOneActAtATime", subWriterRunsOneActAtATime)
t.Run("WriterKindsAndReaderFindings", subWriterKindsAndReaderFindings)
t.Run("ReaderFindingsAreLaidOutAndCheckFindingRefuses", subReaderFindingsAreLaidOutAndCheckFindingRefuses)
t.Run("WriterRefusesABodyWithoutAContractField", subWriterRefusesABodyWithoutAContractField)
t.Run("HeldWriterStatesWhatItHoldsFromItsOwnState", subHeldWriterStatesWhatItHoldsFromItsOwnState)
}