Decode every AlgebraicType, with a fixture module that exercises all of them #26
Labels
No labels
area:defold
area:docs
area:infra
area:protocol
area:testing
kind:bug
kind:chore
phase:breadth
phase:core
phase:hardening
phase:slice
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
yuris/spacetimedb-defold#26
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The SDK decodes rows structurally and hands values through untouched. That is correct for scalars and strings — every column the
chattest module has — and wrong or unusable for everything else. Nobody has hit it because the only module under test has three columns:u64,string,string.What breaks today
From v2.8.2 source plus a compiled probe of the sats serializer:
[tag, value]arrays, because rows serialized from table pages callserialize_variant(tag, None, value)with no variant name (crates/table/src/bflatn_from.rs,serialize_sum). An enum column therefore reaches the consumer as{1, {...}}— a Lua array with a zero-based tag and no variant name anywhere. Unusable without the schema.Option<T>is a sum ofsome/none, and the deserializer also accepts JSONnullfor none. Two encodings for one concept, neither normalised.i256/u256come across as hex strings ("-0x18ee90ff..."), not numbers.u128/i128are emitted as full-precision JSON numbers via serde arbitrary precision. Lua 5.1's number is a double, sou128::MAXsilently loses precision on decode. This one cannot be fixed by decoding alone — it needs a documented representation choice (string? hi/lo pair?).Timestampcolumn decodes to{ __timestamp_micros_since_unix_epoch__ = 1700000000123456 }rather than anything a game can use. That is #23 seen from the wire side.The real problem: no coverage
dev/server/index.jsexercises three scalar columns. Every claim above about how the server encodes these types is read from source, not from captured bytes — and this project's history is a list of cases where the wire disagreed with the documentation: theSubscribeAppliedvsSubscribeMultiAppliednesting, the double-encoded procedure return, and upstream's own doc comment being wrong about overlapping subscribes.So the work is fixture-first, mirroring the strategy the Godot SDK uses (a Rust test module deliberately full of exotic types):
dev/server/index.jswith a column of every type: all int widths including 128/256-bit, floats, bool, string, bytes, an enum,Option<T>of a scalar and of a product, an array, a nested product,Identity,ConnectionId,Timestamp,TimeDuration,ScheduleAt,Uuiddev/test/fixtures/Acceptance
A fixture-replay test that decodes every type from real captured server output and asserts the resulting Lua value. For enums that means a named variant (
{ tag = "Ready", value = ... }), not a bare positional array. For 128-bit integers it means an explicit, tested, documented lossy-or-string decision rather than silent precision loss.Priority
Blocker for 1.0. A consumer whose module has an enum or a timestamp column currently gets garbage, and the SDK's own test module is too simple to notice.