Step 03 — CLI + cross-language interop
Wrap the library in a uniform CLI and prove that all three implementations produce byte-identical dumps for the same scripted scenario.
The memtable binary
Every language exposes the same subcommands so the cross-test can drive them uniformly:
memtable new PATH
memtable put PATH KEY VALUE
memtable del PATH KEY
memtable get PATH KEY
memtable iter PATH
memtable bulk PATH N
memtable size PATH
KEYandVALUEare passed as raw command-line strings. They may contain printable bytes; for testing we stick to ASCII to avoid shell quoting issues.iterandgetprint hex (lowercase, no separator) so output is shell-safe.
Output formats
# iter
V <hex-key> <hex-value>
T <hex-key>
# get
value: <hex-value>
tombstone
absent
# size
entries=<N> size_bytes=<B>
The scripted scenario
scripts/cross_test.sh drives every language through this sequence:
new # 8 bytes, empty
bulk 100 # 100 entries key0..key99 / val0..val99
put key50 REPLACED # overwrite
del key10 # tombstone
put "" empty-key-value # empty key as a valid key
del key99 # tombstone at the tail
Then it dumps rust.bin, go.bin, cpp.bin and asserts:
shasum -a 256 rust.bin go.bin cpp.bin
# all three hashes must be identical
3×3 reader matrix
For every writer × reader combination, the script runs
$READER iter $WRITER.bin > out.${reader}.${writer}.txt
and diffs pairs of outputs. All nine outputs must agree byte-for-byte.
Why a bulk subcommand
Running 100 separate memtable put PATH key0 val0 … invocations would (a) thrash
the disk and (b) test the CLI's argument parsing more than the data structure.
bulk exists so the cross-test can build a non-trivial table in one process per
language.
Spot-check get results
After the scenario the script also runs
get key50 # expect 'value: 5245504c41434544' (REPLACED in hex)
get key10 # expect 'tombstone'
get key99 # expect 'tombstone'
get "" # expect 'value: 656d7074792d6b65792d76616c7565' (empty-key-value)
get nonexistent # expect 'absent'
across all three readers.
Failure messages worth designing for
$ memtable get /tmp/m bogus
absent
$ memtable get /tmp/no-such-file foo
error: read /tmp/no-such-file: No such file or directory
$ memtable get /tmp/garbage.bin foo
error: bad magic
A consistent error vocabulary across languages makes the cross-test's grep patterns simpler.
Tying it together
scripts/verify.sh runs:
- Rust tests (
cargo test --release). - Go tests (
go test ./...). - C++ tests (
cmake -S . -B build && cmake --build build && ctest). - The cross-language script.
Final stdout must end with ALL GREEN.