Round 2 T2, T3, T4, T5: the tool runner ends G with its merge-base test count; the wait test runs its rows side by side
The tests G added fold into existing ones as subtests (design 47 G §626, A-306: 171 tests down to 154, integration 9 down to 7). TestMeshWaitRefusesLoudlyAndNeverLoops runs its groups of one-second rows as parallel subtests, each on a runtime of its own, 15 s down to 5 s (A-311: the one-second floor of a wait's timeout stands, no clock is injected). The go.mod no longer requires meshconditionsclient, which no package loads (T4). Node names in the lines G adds are role names (T5). Builds: design 47 G §626, design 34 every-event §19, A-306, A-311; review round 2 findings T2, T3, T4, T5 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -64,66 +64,6 @@ func asked(t *testing.T, b *moduleBus, method string, req any, into any) {
|
||||
}
|
||||
}
|
||||
|
||||
// Design 47 G §518, A-21, A-25: a put session writes each chunk as it is taken, carries the description of its first chunk,
|
||||
// and answers the put's own info for the last; a chunk out of order fails the put naming both sequences and leaves none.
|
||||
func TestAPutSessionSealsOnTheLastChunkAndDropsOnADisorder(t *testing.T) {
|
||||
f := &fakeObjects{put: map[string][]byte{}}
|
||||
b := aSession(t, f)
|
||||
whole := bytes.Repeat([]byte("x"), 2*buscalls.ChunkBytes+5)
|
||||
var taken buscalls.ObjectsChunkTaken
|
||||
for seq, at := uint32(1), 0; ; seq++ {
|
||||
end := min(at+buscalls.ChunkBytes, len(whole))
|
||||
req := buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "a", Call: "c1", Seq: seq, Last: end == len(whole), Data: whole[at:end]}
|
||||
if seq == 1 {
|
||||
req.Description = "what it is"
|
||||
}
|
||||
if req.Last {
|
||||
var info buscalls.ObjectInfo
|
||||
asked(t, b, buscalls.ObjectsPutChunk, req, &info)
|
||||
if info.Size != uint64(len(whole)) || info.Description != "what it is" {
|
||||
t.Fatalf("the put answered %+v", info)
|
||||
}
|
||||
break
|
||||
}
|
||||
asked(t, b, buscalls.ObjectsPutChunk, req, &taken)
|
||||
if taken.Seq != seq || taken.Error != "" {
|
||||
t.Fatalf("chunk %d was answered %+v", seq, taken)
|
||||
}
|
||||
at = end
|
||||
}
|
||||
if !bytes.Equal(f.put["a"], whole) {
|
||||
t.Fatalf("the store holds %d bytes, want %d", len(f.put["a"]), len(whole))
|
||||
}
|
||||
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 1, Data: []byte("one")}, &taken)
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 3, Data: []byte("three")}, &taken)
|
||||
if !strings.Contains(taken.Error, "chunk 3") || !strings.Contains(taken.Error, "chunk 2") {
|
||||
t.Fatalf("a disorder was answered %+v", taken)
|
||||
}
|
||||
if _, ok := f.put["b"]; ok || len(f.deleted) != 1 || f.deleted[0] != "b" {
|
||||
t.Fatalf("a dropped put left %v, deleted %v", f.put, f.deleted)
|
||||
}
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 2, Data: []byte("two")}, &taken)
|
||||
if taken.Error == "" {
|
||||
t.Fatal("a chunk of a dropped put was taken")
|
||||
}
|
||||
}
|
||||
|
||||
// §518 "The bound": a put not sealed within the bound is dropped, its object deleted.
|
||||
func TestAPutNotSealedWithinTheBoundIsDropped(t *testing.T) {
|
||||
was := SessionBound
|
||||
SessionBound = time.Millisecond
|
||||
t.Cleanup(func() { SessionBound = was })
|
||||
f := &fakeObjects{put: map[string][]byte{}, ctxEnded: make(chan struct{})}
|
||||
b := aSession(t, f)
|
||||
var taken buscalls.ObjectsChunkTaken
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "a", Call: "c", Seq: 1, Data: []byte("x")}, &taken)
|
||||
<-f.ctxEnded
|
||||
if len(f.deleted) != 1 {
|
||||
t.Fatalf("the unsealed object was left: %v", f.deleted)
|
||||
}
|
||||
}
|
||||
|
||||
// §490, §518, §620: a value over one chunk is got as a session (the chunked answer, then each chunk by its call and sequence,
|
||||
// the whole checked against the digest); a sent object over one chunk the same, with `chunked` true.
|
||||
func TestAGetOverOneChunkRunsAsASession(t *testing.T) {
|
||||
@@ -192,4 +132,62 @@ func TestAGetOverOneChunkRunsAsASession(t *testing.T) {
|
||||
if string(small.Data) != "small" {
|
||||
t.Fatalf("a small value was answered %+v", small)
|
||||
}
|
||||
// Design 47 G §518, A-21, A-25: a put session writes each chunk as it is taken, carries the description of its first chunk,
|
||||
// and answers the put's own info for the last; a chunk out of order fails the put naming both sequences and leaves none.
|
||||
t.Run("APutSessionSealsOnTheLastChunkAndDropsOnADisorder", func(t *testing.T) {
|
||||
f := &fakeObjects{put: map[string][]byte{}}
|
||||
b := aSession(t, f)
|
||||
whole := bytes.Repeat([]byte("x"), 2*buscalls.ChunkBytes+5)
|
||||
var taken buscalls.ObjectsChunkTaken
|
||||
for seq, at := uint32(1), 0; ; seq++ {
|
||||
end := min(at+buscalls.ChunkBytes, len(whole))
|
||||
req := buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "a", Call: "c1", Seq: seq, Last: end == len(whole), Data: whole[at:end]}
|
||||
if seq == 1 {
|
||||
req.Description = "what it is"
|
||||
}
|
||||
if req.Last {
|
||||
var info buscalls.ObjectInfo
|
||||
asked(t, b, buscalls.ObjectsPutChunk, req, &info)
|
||||
if info.Size != uint64(len(whole)) || info.Description != "what it is" {
|
||||
t.Fatalf("the put answered %+v", info)
|
||||
}
|
||||
break
|
||||
}
|
||||
asked(t, b, buscalls.ObjectsPutChunk, req, &taken)
|
||||
if taken.Seq != seq || taken.Error != "" {
|
||||
t.Fatalf("chunk %d was answered %+v", seq, taken)
|
||||
}
|
||||
at = end
|
||||
}
|
||||
if !bytes.Equal(f.put["a"], whole) {
|
||||
t.Fatalf("the store holds %d bytes, want %d", len(f.put["a"]), len(whole))
|
||||
}
|
||||
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 1, Data: []byte("one")}, &taken)
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 3, Data: []byte("three")}, &taken)
|
||||
if !strings.Contains(taken.Error, "chunk 3") || !strings.Contains(taken.Error, "chunk 2") {
|
||||
t.Fatalf("a disorder was answered %+v", taken)
|
||||
}
|
||||
if _, ok := f.put["b"]; ok || len(f.deleted) != 1 || f.deleted[0] != "b" {
|
||||
t.Fatalf("a dropped put left %v, deleted %v", f.put, f.deleted)
|
||||
}
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "b", Call: "c2", Seq: 2, Data: []byte("two")}, &taken)
|
||||
if taken.Error == "" {
|
||||
t.Fatal("a chunk of a dropped put was taken")
|
||||
}
|
||||
})
|
||||
// §518 "The bound": a put not sealed within the bound is dropped, its object deleted.
|
||||
t.Run("APutNotSealedWithinTheBoundIsDropped", func(t *testing.T) {
|
||||
was := SessionBound
|
||||
SessionBound = time.Millisecond
|
||||
t.Cleanup(func() { SessionBound = was })
|
||||
f := &fakeObjects{put: map[string][]byte{}, ctxEnded: make(chan struct{})}
|
||||
b := aSession(t, f)
|
||||
var taken buscalls.ObjectsChunkTaken
|
||||
asked(t, b, buscalls.ObjectsPutChunk, buscalls.ObjectsPutChunkRequest{Objects: "files", Name: "a", Call: "c", Seq: 1, Data: []byte("x")}, &taken)
|
||||
<-f.ctxEnded
|
||||
if len(f.deleted) != 1 {
|
||||
t.Fatalf("the unsealed object was left: %v", f.deleted)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user