Revert the revert of G's mesh-sdk merge (#191): G's sdk stands again over reader release 3
Main reverted G's half merge (#189, reverted by8afc3ebin #191) and then took the reader release's S1-S5, which copied G's code. G's form holds where they differ (process_bus.go, seats.go, state.go and their tests); the release's kept names stay so main's callers keep building: SeatViewPrefix beside SeatReadPrefix, and QueueInvoke's empty strings on not-ok (with its test TestQueueInvoke). The tree differs from G's headf30dee54only by those and the release's two tests (objects cap option, seat states and stream kinds). Builds: design 47 G (the milestone's sdk part, as atf30dee54) Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package stateobjects
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 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 subABodyOverTheMessageLimitIsSentAsAReference(t *testing.T) {
|
||||
m := newMemory()
|
||||
s := Sender{Objects: memObjects{m}, Store: "m_sent-objects"}
|
||||
fetch := ProcessFetch(memObjects{m})
|
||||
for _, label := range []string{"reply.list", "event.done"} {
|
||||
body := []byte(`{"text":"` + strings.Repeat("y", 3<<20) + `"}`)
|
||||
sent, err := s.Send(label, body)
|
||||
if err != nil || len(sent) > MessageLimit {
|
||||
t.Fatalf("%s: sent %d bytes, %v", label, len(sent), err)
|
||||
}
|
||||
if _, isRef := ReadRef(sent); !isRef {
|
||||
t.Fatalf("%s: a 3 MiB body was sent whole", label)
|
||||
}
|
||||
got, err := Receive(sent, fetch)
|
||||
if err != nil || !bytes.Equal(got, body) {
|
||||
t.Fatalf("%s: received %d bytes, %v", label, len(got), err)
|
||||
}
|
||||
}
|
||||
small := []byte(`{"a":1}`)
|
||||
if sent, err := s.Send("x", small); err != nil || !bytes.Equal(sent, small) {
|
||||
t.Fatalf("a small body: %s, %v", sent, err)
|
||||
}
|
||||
if got, err := Receive(small, fetch); err != nil || !bytes.Equal(got, small) {
|
||||
t.Fatalf("receive a small body: %s, %v", got, err)
|
||||
}
|
||||
// an object that is not the one the reference names is refused
|
||||
sent, _ := s.Send("reply.again", bytes.Repeat([]byte("z"), 2<<20))
|
||||
ref, _ := ReadRef(sent)
|
||||
m.objects[ref.Object] = []byte("tampered")
|
||||
if _, err := Receive(sent, fetch); err == nil {
|
||||
t.Fatal("a tampered object was accepted")
|
||||
}
|
||||
// a bundle's store is bounded by its cap alone, and the tool runner refuses at the chunk that passes it (design 47 G §518)
|
||||
if (BundleObjects{}).MostBytes() != 0 {
|
||||
t.Fatal("a bundle's value is refused by a number of its own")
|
||||
}
|
||||
}
|
||||
|
||||
// A bundle reads a sent object through the runtime's sent-get.
|
||||
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)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := runtimeOf(t, m, func() (any, error) {
|
||||
got, err := Receive(sent, BundleFetch)
|
||||
if err != nil || !bytes.Equal(got, body) {
|
||||
t.Errorf("received %d bytes, %v", len(got), err)
|
||||
}
|
||||
return "done", nil
|
||||
})
|
||||
if !strings.Contains(out.(string), "done") {
|
||||
t.Fatalf("the bundle answered %v", out)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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 }}
|
||||
var first string
|
||||
for i := 0; i < 25; i++ {
|
||||
sent, err := s.Send("reply."+string(rune('a'+i)), bytes.Repeat([]byte{byte('a' + i)}, 2<<20))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ref, _ := ReadRef(sent); i == 0 {
|
||||
first = ref.Object
|
||||
}
|
||||
}
|
||||
if len(m.objects) != 25 {
|
||||
t.Fatalf("%d objects within 7 days, want 25", len(m.objects))
|
||||
}
|
||||
clock = clock.Add(SentMaxAge + time.Hour)
|
||||
if _, err := s.Send("reply.late", bytes.Repeat([]byte("z"), 2<<20)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, kept := m.objects[first]; kept || len(m.objects) != 6 {
|
||||
t.Fatalf("after a late send %d objects remain (the first kept: %v), want 6", len(m.objects), kept)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user