CultLib/packages/cultcache-py/tests/test_cultcache.py
2026-06-14 01:43:14 +01:00

1318 lines
58 KiB
Python

from __future__ import annotations
import json
import socket
import tempfile
import threading
import unittest
from dataclasses import asdict, dataclass
from datetime import UTC, datetime, timedelta
from pathlib import Path
from cultcache_py import (
CultCache,
JsonLinesBackingStore,
SingleFileMessagePackBackingStore,
define_database_entry_type,
define_document_type,
)
from cultcache_py.benchmark import run_benchmark
from cultcache_py.interop import read_note, write_note
from cultcache_py.verify import verify
from cultnet_py import (
compute_simulation_claim_hash,
CultNetClientAuthorityScope,
CultNetRawClient,
CultNetSimulationConsensusOptions,
apply_raw_snapshot,
apply_shard_log_response,
database_subscribe,
database_unsubscribe,
decode_frame,
decode_witness_artifact_bundle_payload,
document_delete,
document_put_raw,
encode_frame,
encode_witness_artifact_bundle_payload,
hello,
parse_message,
schema_catalog_request,
shard_catalog_request,
shard_log_request,
simulation_observation,
snapshot_request,
witness_artifact_bundle,
)
from cultnet_py.interop_peer import wire_message_schema_descriptors
from cultmesh_py import create_node
from cultmesh_py import (
CultMesh,
CultMeshGameSessionOptions,
CultMeshPeerCard,
CultMeshPeerCatalog,
CultMeshSimulationFact,
CultMeshAuthorityLease,
CultMeshAuthorityLeaseCatalog,
CultMeshDiscoveryClient,
CultMeshStreamCatalog,
CultMeshStreamConsumerProfile,
CultMeshStreamDescriptor,
CultMeshStreamFrameHandle,
CultMeshVerseCatalog,
CultMeshVerseCompatibility,
CultMeshVerseDescriptor,
peer_exchange_request,
simulation_fact_document,
verse_catalog_request,
)
@dataclass
class Item:
name: str
category: str
value: int
def item_doc():
return define_document_type(
"item",
encode=lambda item: asdict(item),
decode=lambda raw: Item(**raw),
name="name",
indexes={"category": "category"},
)
class CultCacheTests(unittest.TestCase):
def test_round_trips_registered_documents(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
document = item_doc()
cache = (
CultCache.builder()
.register_document_type(document)
.add_generic_store(JsonLinesBackingStore(Path(tmp) / "cache.jsonl"))
.build()
)
cache.pull_all_backing_stores()
cache.put(document, "item:potion", Item(name="Potion", category="Consumable", value=50))
loaded = (
CultCache.builder()
.register_document_type(document)
.add_generic_store(JsonLinesBackingStore(Path(tmp) / "cache.jsonl"))
.build()
)
loaded.pull_all_backing_stores()
self.assertEqual(loaded.get_required(document, "item:potion").value, 50)
self.assertEqual(loaded.get_key_by_name(document, "Potion"), "item:potion")
self.assertEqual(loaded.get_by_index(document, "category", "Consumable").name, "Potion")
def test_global_document_uses_singleton_key(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
settings = define_document_type("settings", global_document=True)
cache = (
CultCache.builder()
.register_document_type(settings)
.add_generic_store(JsonLinesBackingStore(Path(tmp) / "cache.jsonl"))
.build()
)
cache.pull_all_backing_stores()
cache.put_global(settings, {"theme": "ash"})
self.assertEqual(cache.get_required_global(settings)["theme"], "ash")
def test_update_and_delete(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
document = item_doc()
cache = (
CultCache.builder()
.register_document_type(document)
.add_generic_store(JsonLinesBackingStore(Path(tmp) / "cache.jsonl"))
.build()
)
cache.pull_all_backing_stores()
cache.put(document, "item:potion", Item(name="Potion", category="Consumable", value=50))
cache.update(document, "item:potion", lambda item: Item(item.name, item.category, item.value + 5))
self.assertEqual(cache.get_required(document, "item:potion").value, 55)
cache.delete(document, "item:potion")
self.assertIsNone(cache.get(document, "item:potion"))
def test_incremental_lookup_updates_replace_stale_name_and_index_entries(self) -> None:
document = item_doc()
cache = CultCache()
cache.register_document_type(document)
cache.put(document, "item:potion", Item(name="Potion", category="Consumable", value=50))
cache.put(document, "item:potion", Item(name="Elixir", category="Rare", value=80))
self.assertIsNone(cache.get_key_by_name(document, "Potion"))
self.assertIsNone(cache.get_key_by_index(document, "category", "Consumable"))
self.assertEqual(cache.get_key_by_name(document, "Elixir"), "item:potion")
self.assertEqual(cache.get_by_index(document, "category", "Rare").name, "Elixir")
def test_incremental_lookup_delete_restores_duplicate_owner(self) -> None:
document = item_doc()
cache = CultCache()
cache.register_document_type(document)
cache.put(document, "item:first", Item(name="Potion", category="Consumable", value=50))
cache.put(document, "item:second", Item(name="Potion", category="Consumable", value=60))
self.assertEqual(cache.get_key_by_name(document, "Potion"), "item:second")
self.assertEqual(cache.get_key_by_index(document, "category", "Consumable"), "item:second")
cache.delete(document, "item:second")
self.assertEqual(cache.get_key_by_name(document, "Potion"), "item:first")
self.assertEqual(cache.get_key_by_index(document, "category", "Consumable"), "item:first")
def test_database_entry_formatter_uses_slot_indexed_messagepack_array(self) -> None:
try:
import msgpack # type: ignore
except ModuleNotFoundError:
self.skipTest("msgpack optional dependency is not installed")
@dataclass
class Settings:
theme: str
retries: int = 0
document = define_database_entry_type(
"settings",
[
("theme", 0),
("retries", 2, 0),
],
cls=Settings,
)
payload = document.encode_payload(Settings(theme="ash", retries=3))
self.assertEqual(msgpack.unpackb(payload, raw=False), ["ash", None, 3])
self.assertEqual(document.decode_payload(msgpack.packb(["ash"], use_bin_type=True)).retries, 0)
def test_document_catalog_entry_is_cached_after_first_derivation(self) -> None:
document = define_database_entry_type(
"settings",
[
("theme", 0),
("retries", 2, 0),
],
)
first = document.catalog_entry()
second = document.catalog_entry()
self.assertIs(first, second)
self.assertEqual([member.slot for member in first.members], [0, 2])
def test_messagepack_store_writes_v1_snapshot(self) -> None:
try:
import msgpack # type: ignore
except ModuleNotFoundError:
self.skipTest("msgpack optional dependency is not installed")
with tempfile.TemporaryDirectory() as tmp:
document = define_database_entry_type(
"settings",
[("theme", 0)],
schema_id="settings",
schema_name="settings",
schema_version="settings.v1",
)
store_path = Path(tmp) / "cache.msgpack"
cache = (
CultCache.builder()
.register_document_type(document)
.add_generic_store(SingleFileMessagePackBackingStore(store_path))
.build()
)
cache.pull_all_backing_stores()
cache.put(document, "app", {"theme": "ash"})
raw = msgpack.unpackb(store_path.read_bytes(), raw=False)
self.assertEqual(raw[0], "cultcache.store.v1")
self.assertEqual(raw[1][0][0], "settings")
self.assertEqual(raw[2][0][0], "app")
self.assertEqual(raw[2][0][1], "settings")
def test_interop_cli_helpers_round_trip_v1_store(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
store_path = str(Path(tmp) / "cache.msgpack")
written = write_note(store_path, "python-test")
loaded = read_note(store_path)
self.assertEqual(loaded["documentId"], written["documentId"])
self.assertEqual(loaded["authorRuntimeId"], "python-test")
self.assertIn("interop", loaded["tags"])
def test_benchmark_reports_core_hot_path_metrics(self) -> None:
result = run_benchmark(8)
metric_names = {metric["name"] for metric in result["metrics"]}
self.assertEqual(result["records"], 8)
self.assertEqual(result["wireMessageCount"], 8)
self.assertEqual(metric_names, {
"database_entry_encode",
"database_entry_decode",
"cultnet_frame_parse",
"raw_snapshot_apply",
"cache_upsert",
"cache_get",
})
self.assertTrue(all(metric["opsPerSecond"] > 0 for metric in result["metrics"]))
def test_cache_put_without_backing_store_keeps_in_memory_value(self) -> None:
document = define_database_entry_type(
"bench.memory_item",
[
("name", 0),
("value", 1, 0),
],
)
cache = CultCache()
cache.register_document_type(document)
cache.put(document, "item:one", {"name": "one", "value": 1})
self.assertEqual(cache.get(document, "item:one"), {"name": "one", "value": 1})
self.assertEqual(cache.get_required_envelope(document, "item:one").key, "item:one")
def test_verify_reports_python_runtime_surface_health(self) -> None:
result = verify(records=4)
self.assertEqual(result["status"], "ok")
self.assertEqual({check["name"] for check in result["checks"]}, {"public_exports", "typed_markers", "benchmark_sanity"})
def test_cultnet_schema_message_frame_round_trip(self) -> None:
message = hello(runtime_id="python-test", supported_schema_versions=["cultnet.hello.v0"])
parsed = parse_message(decode_frame(encode_frame(message.to_bytes())))
self.assertEqual(parsed.schema_version, "cultnet.hello.v0")
self.assertEqual(parsed.body["runtimeId"], "python-test")
def test_cultnet_database_subscription_helpers_match_schema_v0_shape(self) -> None:
subscribe = database_subscribe(
message_id="sub-message",
subscription_id="sub-1",
schema_ids=["schema-a"],
record_keys=["record-a"],
include_snapshot=False,
).to_wire()
self.assertEqual(subscribe["schemaVersion"], "cultnet.database_subscribe.v0")
self.assertEqual(subscribe["messageId"], "sub-message")
self.assertEqual(subscribe["subscriptionId"], "sub-1")
self.assertEqual(subscribe["schemaIds"], ["schema-a"])
self.assertEqual(subscribe["recordKeys"], ["record-a"])
self.assertFalse(subscribe["includeSnapshot"])
unsubscribe = database_unsubscribe(message_id="unsub-message", subscription_id="sub-1").to_wire()
self.assertEqual(unsubscribe["schemaVersion"], "cultnet.database_unsubscribe.v0")
self.assertEqual(unsubscribe["messageId"], "unsub-message")
self.assertEqual(unsubscribe["subscriptionId"], "sub-1")
def test_cultnet_raw_put_helper_carries_message_id(self) -> None:
put = document_put_raw(
message_id="put-1",
key="record-a",
schema_id="schema-a",
stored_at="2026-06-13T00:00:00Z",
payload=b"payload",
source_runtime_id="python-test",
shard_id="interop",
shard_epoch=1,
).to_wire()
self.assertEqual(put["schemaVersion"], "cultnet.document_put_raw.v0")
self.assertEqual(put["messageId"], "put-1")
self.assertEqual(put["document"]["recordKey"], "record-a")
self.assertEqual(put["document"]["sourceRuntimeId"], "python-test")
self.assertEqual(put["shardId"], "interop")
self.assertEqual(put["shardEpoch"], 1)
def test_cultnet_catalog_and_snapshot_helpers_accept_filters(self) -> None:
catalog = schema_catalog_request(
message_id="catalog-1",
include_schema_json=True,
schema_ids=["schema-a"],
kinds=["wire_message"],
).to_wire()
self.assertEqual(catalog["schemaVersion"], "cultnet.schema_catalog_request.v0")
self.assertEqual(catalog["messageId"], "catalog-1")
self.assertTrue(catalog["includeSchemaJson"])
self.assertEqual(catalog["schemaIds"], ["schema-a"])
self.assertEqual(catalog["kinds"], ["wire_message"])
snapshot = snapshot_request(
message_id="snapshot-1",
schema_ids=["schema-a"],
record_keys=["record-a"],
shard_id="interop",
shard_epoch=1,
).to_wire()
self.assertEqual(snapshot["schemaVersion"], "cultnet.snapshot_request.v0")
self.assertEqual(snapshot["messageId"], "snapshot-1")
self.assertEqual(snapshot["schemaIds"], ["schema-a"])
self.assertEqual(snapshot["recordKeys"], ["record-a"])
self.assertEqual(snapshot["shardId"], "interop")
self.assertEqual(snapshot["shardEpoch"], 1)
def test_cultnet_raw_client_fetches_schema_snapshot_and_shard_reads(self) -> None:
import msgpack # type: ignore
from cultnet_py import read_frame, write_frame
received_versions: list[str] = []
ready = threading.Event()
server_error: list[BaseException] = []
port_holder: list[int] = []
def serve_requests() -> None:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 0))
port_holder.append(server.getsockname()[1])
server.listen(4)
ready.set()
for _ in range(4):
connection, _ = server.accept()
with connection:
stream = connection.makefile("rwb")
request = msgpack.unpackb(read_frame(stream), raw=False)
received_versions.append(request["schemaVersion"])
if request["schemaVersion"] == "cultnet.schema_catalog_request.v0":
self.assertEqual(request["kinds"], ["wire_message"])
response = {"schemaVersion": "cultnet.schema_catalog_response.v0", "messageId": request["messageId"], "schemas": []}
elif request["schemaVersion"] == "cultnet.snapshot_request.v0":
self.assertEqual(request["shardId"], "interop")
response = {"schemaVersion": "cultnet.snapshot_response_raw.v0", "messageId": request["messageId"], "documents": []}
elif request["schemaVersion"] == "cultnet.shard_catalog_request.v0":
response = {"schemaVersion": "cultnet.shard_catalog_response.v0", "messageId": request["messageId"], "shards": []}
elif request["schemaVersion"] == "cultnet.shard_log_request.v0":
self.assertEqual(request["afterSequence"], 7)
response = {
"schemaVersion": "cultnet.shard_log_response.v0",
"messageId": request["messageId"],
"shardId": request["shardId"],
"shardEpoch": request["shardEpoch"],
"entries": [],
"resyncRequired": False,
}
else:
raise AssertionError(f"unexpected request {request['schemaVersion']}")
write_frame(stream, msgpack.packb(response, use_bin_type=True))
stream.flush()
except BaseException as error:
server_error.append(error)
ready.set()
thread = threading.Thread(target=serve_requests, daemon=True)
thread.start()
self.assertTrue(ready.wait(2.0))
self.assertFalse(server_error)
client = CultNetRawClient("127.0.0.1", port_holder[0], timeout_seconds=2.0)
self.assertEqual(client.fetch_schema_catalog(kinds=["wire_message"])["schemaVersion"], "cultnet.schema_catalog_response.v0")
self.assertEqual(client.fetch_snapshot(shard_id="interop", shard_epoch=1)["schemaVersion"], "cultnet.snapshot_response_raw.v0")
self.assertEqual(client.fetch_shard_catalog(schema_ids=["schema-a"])["schemaVersion"], "cultnet.shard_catalog_response.v0")
self.assertEqual(client.fetch_shard_log(shard_id="interop", shard_epoch=1, after_sequence=7)["schemaVersion"], "cultnet.shard_log_response.v0")
thread.join(2.0)
self.assertFalse(server_error)
self.assertEqual(received_versions, [
"cultnet.schema_catalog_request.v0",
"cultnet.snapshot_request.v0",
"cultnet.shard_catalog_request.v0",
"cultnet.shard_log_request.v0",
])
def test_cultnet_database_subscription_reads_snapshot_and_change(self) -> None:
import msgpack # type: ignore
from cultnet_py import read_frame, write_frame
document = define_database_entry_type(
"sub.item",
[
("name", 0),
("category", 1),
("value", 2, 0),
],
cls=Item,
)
schema_id = document.catalog_entry().schema_id
ready = threading.Event()
server_error: list[BaseException] = []
port_holder: list[int] = []
received_versions: list[str] = []
def serve_subscription() -> None:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 0))
port_holder.append(server.getsockname()[1])
server.listen(1)
ready.set()
connection, _ = server.accept()
with connection:
stream = connection.makefile("rwb")
subscribe = msgpack.unpackb(read_frame(stream), raw=False)
received_versions.append(subscribe["schemaVersion"])
self.assertEqual(subscribe["subscriptionId"], "sub-1")
snapshot = {
"schemaVersion": "cultnet.snapshot_response_raw.v0",
"messageId": subscribe["messageId"],
"documents": [],
}
write_frame(stream, msgpack.packb(snapshot, use_bin_type=True))
stream.flush()
put = msgpack.unpackb(read_frame(stream), raw=False)
received_versions.append(put["schemaVersion"])
change = {
"schemaVersion": "cultnet.database_change_raw.v0",
"messageId": "change-1",
"subscriptionId": "sub-1",
"changeKind": "added",
"document": put["document"],
}
write_frame(stream, msgpack.packb(change, use_bin_type=True))
stream.flush()
unsubscribe = msgpack.unpackb(read_frame(stream), raw=False)
received_versions.append(unsubscribe["schemaVersion"])
except BaseException as error:
server_error.append(error)
ready.set()
thread = threading.Thread(target=serve_subscription, daemon=True)
thread.start()
self.assertTrue(ready.wait(2.0))
self.assertFalse(server_error)
client = CultNetRawClient("127.0.0.1", port_holder[0], timeout_seconds=2.0)
put = document_put_raw(
message_id="put-sub",
key="item:sub",
schema_id=schema_id,
stored_at="2026-06-14T00:00:00Z",
payload=document.encode_payload(Item("orb", "gear", 8)),
)
with client.subscribe_database(subscription_id="sub-1", schema_ids=[schema_id]) as subscription:
snapshot = subscription.read_next()
subscription.send(put)
change = subscription.read_next()
thread.join(2.0)
self.assertFalse(server_error)
self.assertEqual(snapshot["schemaVersion"], "cultnet.snapshot_response_raw.v0")
self.assertEqual(change["schemaVersion"], "cultnet.database_change_raw.v0")
self.assertEqual(change["document"]["recordKey"], "item:sub")
self.assertEqual(received_versions, [
"cultnet.database_subscribe.v0",
"cultnet.document_put_raw.v0",
"cultnet.database_unsubscribe.v0",
])
def test_cultnet_replication_helpers_apply_raw_snapshot_and_shard_log(self) -> None:
document = define_database_entry_type(
"replica.item",
[
("name", 0),
("category", 1),
("value", 2, 0),
],
cls=Item,
)
cache = CultCache()
cache.register_document_type(document)
schema_id = document.catalog_entry().schema_id
snapshot = {
"schemaVersion": "cultnet.snapshot_response_raw.v0",
"messageId": "snapshot-1",
"documents": [
{
"schemaId": schema_id,
"recordKey": "item:1",
"storedAt": "2026-06-13T00:00:00Z",
"payloadEncoding": "messagepack",
"payload": document.encode_payload(Item("sword", "gear", 3)),
}
],
}
applied_snapshot = apply_raw_snapshot(cache, [document], snapshot)
self.assertEqual(applied_snapshot[0].record_key, "item:1")
self.assertEqual(cache.get_required(document, "item:1").value, 3)
shard_log = {
"schemaVersion": "cultnet.shard_log_response.v0",
"messageId": "log-1",
"shardId": "interop",
"shardEpoch": 1,
"resyncRequired": False,
"entries": [
{
"sequence": 0,
"changeKind": "updated",
"put": {
"schemaVersion": "cultnet.document_put_raw.v0",
"messageId": "put-unknown",
"document": {
"schemaId": "replica.unknown.v1",
"recordKey": "unknown:1",
"storedAt": "2026-06-13T00:00:01Z",
"payloadEncoding": "messagepack",
"payload": document.encode_payload(Item("ignored", "unknown", 0)),
},
"shardId": "interop",
"shardEpoch": 1,
},
},
{
"sequence": 1,
"changeKind": "updated",
"put": {
"schemaVersion": "cultnet.document_put_raw.v0",
"messageId": "put-1",
"document": {
"schemaId": schema_id,
"recordKey": "item:1",
"storedAt": "2026-06-13T00:00:01Z",
"payloadEncoding": "messagepack",
"payload": document.encode_payload(Item("sword", "gear", 12)),
},
"shardId": "interop",
"shardEpoch": 1,
},
},
{
"sequence": 2,
"changeKind": "removed",
"delete": {
"schemaVersion": "cultnet.document_delete.v0",
"messageId": "delete-1",
"schemaId": schema_id,
"recordKey": "item:1",
"shardId": "interop",
"shardEpoch": 1,
},
},
],
}
applied_log = apply_shard_log_response(cache, [document], shard_log)
self.assertEqual([change.change_kind for change in applied_log], ["updated", "removed"])
self.assertIsNone(cache.get(document, "item:1"))
def test_cultmesh_node_syncs_snapshot_and_shard_log_through_cultnet_client(self) -> None:
import msgpack # type: ignore
from cultnet_py import read_frame, write_frame
document = define_database_entry_type(
"mesh.sync_item",
[
("name", 0),
("category", 1),
("value", 2, 0),
],
cls=Item,
)
node = create_node(runtime_id="python-node")
node.register_document(document)
schema_id = document.catalog_entry().schema_id
ready = threading.Event()
server_error: list[BaseException] = []
port_holder: list[int] = []
def serve_requests() -> None:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 0))
port_holder.append(server.getsockname()[1])
server.listen(2)
ready.set()
for _ in range(2):
connection, _ = server.accept()
with connection:
stream = connection.makefile("rwb")
request = msgpack.unpackb(read_frame(stream), raw=False)
if request["schemaVersion"] == "cultnet.snapshot_request.v0":
response = {
"schemaVersion": "cultnet.snapshot_response_raw.v0",
"messageId": request["messageId"],
"documents": [
{
"schemaId": schema_id,
"recordKey": "item:node",
"storedAt": "2026-06-13T00:00:00Z",
"payloadEncoding": "messagepack",
"payload": document.encode_payload(Item("node", "mesh", 1)),
}
],
}
elif request["schemaVersion"] == "cultnet.shard_log_request.v0":
response = {
"schemaVersion": "cultnet.shard_log_response.v0",
"messageId": request["messageId"],
"shardId": request["shardId"],
"shardEpoch": request["shardEpoch"],
"resyncRequired": False,
"entries": [
{
"sequence": 1,
"changeKind": "updated",
"put": {
"schemaVersion": "cultnet.document_put_raw.v0",
"messageId": "put-node",
"document": {
"schemaId": schema_id,
"recordKey": "item:node",
"storedAt": "2026-06-13T00:00:01Z",
"payloadEncoding": "messagepack",
"payload": document.encode_payload(Item("node", "mesh", 9)),
},
"shardId": request["shardId"],
"shardEpoch": request["shardEpoch"],
},
}
],
}
else:
raise AssertionError(f"unexpected request {request['schemaVersion']}")
write_frame(stream, msgpack.packb(response, use_bin_type=True))
stream.flush()
except BaseException as error:
server_error.append(error)
ready.set()
thread = threading.Thread(target=serve_requests, daemon=True)
thread.start()
self.assertTrue(ready.wait(2.0))
self.assertFalse(server_error)
client = CultNetRawClient("127.0.0.1", port_holder[0], timeout_seconds=2.0)
snapshot_changes = node.sync_snapshot(client, schema_ids=[schema_id])
log_changes = node.sync_shard_log(client, shard_id="mesh", shard_epoch=1)
thread.join(2.0)
self.assertFalse(server_error)
self.assertEqual(snapshot_changes[0].record_key, "item:node")
self.assertEqual(log_changes[0].change_kind, "updated")
self.assertEqual(node.get_required(document, "item:node").value, 9)
def test_cultmesh_node_emits_raw_put_and_delete_messages_for_local_writes(self) -> None:
document = define_database_entry_type(
"mesh.emit_item",
[
("name", 0),
("category", 1),
("value", 2, 0),
],
cls=Item,
)
node = create_node(runtime_id="python-node")
node.register_document(document)
put = node.put_raw_message(
document,
"item:emit",
Item("wand", "gear", 4),
message_id="put-emit",
shard_id="mesh",
shard_epoch=1,
).to_wire()
self.assertEqual(node.get_required(document, "item:emit").name, "wand")
self.assertEqual(put["schemaVersion"], "cultnet.document_put_raw.v0")
self.assertEqual(put["messageId"], "put-emit")
self.assertEqual(put["document"]["schemaId"], document.catalog_entry().schema_id)
self.assertEqual(put["document"]["recordKey"], "item:emit")
self.assertEqual(put["document"]["sourceRuntimeId"], "python-node")
self.assertEqual(put["shardId"], "mesh")
self.assertEqual(put["shardEpoch"], 1)
delete = node.delete_raw_message(
document,
"item:emit",
message_id="delete-emit",
shard_id="mesh",
shard_epoch=1,
).to_wire()
self.assertIsNone(node.get(document, "item:emit"))
self.assertEqual(delete["schemaVersion"], "cultnet.document_delete.v0")
self.assertEqual(delete["messageId"], "delete-emit")
self.assertEqual(delete["schemaId"], document.catalog_entry().schema_id)
self.assertEqual(delete["recordKey"], "item:emit")
self.assertEqual(delete["shardId"], "mesh")
self.assertEqual(delete["shardEpoch"], 1)
def test_cultnet_document_delete_helper_matches_schema_v0_shape(self) -> None:
message = document_delete(
message_id="delete-1",
schema_id="schema-a",
record_key="record-a",
shard_id="interop",
shard_epoch=1,
).to_wire()
self.assertEqual(message["schemaVersion"], "cultnet.document_delete.v0")
self.assertEqual(message["messageId"], "delete-1")
self.assertEqual(message["schemaId"], "schema-a")
self.assertEqual(message["recordKey"], "record-a")
self.assertEqual(message["shardId"], "interop")
self.assertEqual(message["shardEpoch"], 1)
def test_cultnet_wire_catalog_describes_python_handled_messages(self) -> None:
descriptors = wire_message_schema_descriptors(include_schema_json=True)
by_version = {descriptor["schemaVersion"]: descriptor for descriptor in descriptors}
for schema_version in [
"cultnet.document_delete.v0",
"cultnet.database_change_raw.v0",
"cultnet.shard_log_response.v0",
"cultnet.simulation_consensus_candidate.v0",
"cultmesh.peer_exchange_response.v0",
]:
self.assertIn(schema_version, by_version)
self.assertEqual(by_version[schema_version]["kind"], "wire_message")
self.assertIn("cultnet.schema.v0", by_version[schema_version]["wireContracts"])
self.assertIn(schema_version, by_version[schema_version]["schemaJson"])
self.assertEqual(len(by_version[schema_version]["contentHash"]), 64)
delete_schema = json.loads(by_version["cultnet.document_delete.v0"]["schemaJson"])
self.assertEqual(
delete_schema["required"],
["schemaVersion", "messageId", "schemaId", "recordKey"],
)
self.assertEqual(delete_schema["properties"]["recordKey"]["type"], "string")
change_schema = json.loads(by_version["cultnet.database_change_raw.v0"]["schemaJson"])
self.assertEqual(change_schema["properties"]["changeKind"]["enum"], ["added", "updated", "removed"])
self.assertIn("document", change_schema["properties"])
self.assertIn("schemaId", change_schema["properties"])
self.assertIn("recordKey", change_schema["properties"])
log_schema = json.loads(by_version["cultnet.shard_log_response.v0"]["schemaJson"])
self.assertIn("entries", log_schema["required"])
self.assertIn("resyncRequired", log_schema["required"])
self.assertIn("compactedThrough", log_schema["properties"])
consensus_schema = json.loads(by_version["cultnet.simulation_consensus_candidate.v0"]["schemaJson"])
for required_field in ["witnessCount", "supportWeight", "totalWeight", "hasQuorum", "confidence"]:
self.assertIn(required_field, consensus_schema["required"])
def test_cultnet_shard_helpers_match_schema_v0_shape(self) -> None:
catalog = shard_catalog_request(
message_id="catalog-1",
schema_ids=["schema-a"],
record_keys=["record-a"],
).to_wire()
self.assertEqual(catalog["schemaVersion"], "cultnet.shard_catalog_request.v0")
self.assertEqual(catalog["messageId"], "catalog-1")
self.assertEqual(catalog["schemaIds"], ["schema-a"])
self.assertEqual(catalog["recordKeys"], ["record-a"])
log = shard_log_request(
message_id="log-1",
shard_id="interop",
shard_epoch=7,
after_sequence=3,
limit=2,
).to_wire()
self.assertEqual(log["schemaVersion"], "cultnet.shard_log_request.v0")
self.assertEqual(log["messageId"], "log-1")
self.assertEqual(log["shardId"], "interop")
self.assertEqual(log["shardEpoch"], 7)
self.assertEqual(log["afterSequence"], 3)
self.assertEqual(log["limit"], 2)
def test_cultnet_simulation_observation_helper_matches_schema_v0_shape(self) -> None:
claim_hash = compute_simulation_claim_hash("frame:42", "subject:player-1", "hit")
self.assertEqual(len(claim_hash), 64)
message = simulation_observation(
message_id="obs-1",
witness_runtime_id="python-test",
shard_id="interop",
shard_epoch=1,
frame=42,
subject_id="player-1",
claim_kind="hit",
claim_hash=claim_hash,
claim_summary="player-1 hit target-a",
observed_at="2026-06-13T00:00:02Z",
).to_wire()
self.assertEqual(message["schemaVersion"], "cultnet.simulation_observation.v0")
self.assertEqual(message["messageId"], "obs-1")
self.assertEqual(message["observation"]["witnessRuntimeId"], "python-test")
self.assertEqual(message["observation"]["claimHash"], claim_hash)
self.assertEqual(message["observation"]["weight"], 1.0)
def test_cultnet_witness_artifact_bundle_uses_csharp_slot_order(self) -> None:
bundle = witness_artifact_bundle(
bundle_id="bundle-1",
witness_kind="interop-proof",
captured_at="2026-06-13T00:00:03Z",
subject={"documentType": "cultnet.interop-note", "subjectId": "note:python"},
contracts=[{"role": "payload", "schemaId": "schema-a"}],
artifacts=[{"role": "log", "uri": "cultcache://bundle-1/log", "mediaType": "text/plain"}],
timing_witnesses=[{"stage": "roundtrip", "startedAt": "2026-06-13T00:00:03Z", "completedAt": "2026-06-13T00:00:04Z", "latencyMs": 1.0}],
provenance={"pipelineId": "interop", "runId": "run-1", "runtimeId": "python-test"},
)
payload = encode_witness_artifact_bundle_payload(bundle)
decoded = decode_witness_artifact_bundle_payload(payload)
self.assertEqual(decoded["bundleId"], "bundle-1")
self.assertEqual(decoded["witnessKind"], "interop-proof")
self.assertEqual(decoded["subject"]["subjectId"], "note:python")
self.assertEqual(decoded["contracts"][0]["schemaId"], "schema-a")
self.assertEqual(decoded["artifacts"][0]["mediaType"], "text/plain")
self.assertEqual(decoded["provenance"]["runtimeId"], "python-test")
def test_cultmesh_node_uses_cultcache_store(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
document = define_database_entry_type("mesh.note", [("body", 0)])
store_path = Path(tmp) / "mesh.cc"
node = create_node(store_path, runtime_id="mesh-test")
node.register_document(document)
node.put(document, "note:1", {"body": "hello"})
reopened = create_node(store_path, runtime_id="mesh-test")
reopened.register_document(document)
reopened.pull()
self.assertEqual(reopened.get(document, "note:1")["body"], "hello")
def test_cultmesh_facade_matches_peer_runtime_entrypoints(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
store_path = Path(tmp) / "mesh.cc"
node = CultMesh.start_node(store_path, runtime_id="mesh-facade")
self.assertEqual(node.runtime_id, "mesh-facade")
self.assertIsInstance(CultMesh.create_node(), type(node))
self.assertIsInstance(CultMesh.create_verse_catalog(), CultMeshVerseCatalog)
self.assertIsInstance(CultMesh.create_peer_catalog(), CultMeshPeerCatalog)
self.assertIsInstance(CultMesh.create_authority_lease_catalog(), CultMeshAuthorityLeaseCatalog)
self.assertIsInstance(CultMesh.create_stream_catalog(), CultMeshStreamCatalog)
def test_cultmesh_simulation_fact_uses_csharp_slot_contract(self) -> None:
import msgpack # type: ignore
candidate = {
"shardId": "arena",
"shardEpoch": 4,
"frame": 100,
"subjectId": "bob",
"claimKind": "hit",
"claimHash": compute_simulation_claim_hash("hit", "alice", "bob", "frame:100"),
"claimSummary": "alice shot bob first",
"witnessCount": 2,
"supportWeight": 2.0,
"totalWeight": 2.0,
"confidence": 1.0,
"hasQuorum": True,
}
fact = CultMeshSimulationFact.from_candidate(candidate, committed_at="2026-06-13T00:00:00Z")
payload = simulation_fact_document.encode_payload(fact)
slots = msgpack.unpackb(payload, raw=False)
self.assertEqual(CultMeshSimulationFact.create_record_key(candidate), f"simulation:{fact.fact_id}")
self.assertEqual(slots[0], fact.fact_id)
self.assertEqual(slots[1], "arena")
self.assertEqual(slots[2], 4)
self.assertEqual(slots[3], 100)
self.assertEqual(slots[4], "bob")
self.assertEqual(slots[5], "hit")
self.assertEqual(slots[6], candidate["claimHash"])
self.assertEqual(slots[7], "alice shot bob first")
self.assertEqual(slots[8], 2)
self.assertEqual(slots[9], 2.0)
self.assertEqual(slots[10], 2.0)
self.assertEqual(slots[11], 1.0)
self.assertEqual(slots[12], "2026-06-13T00:00:00Z")
def test_cultmesh_simulation_fact_committer_rejects_without_quorum_and_stores_fact(self) -> None:
candidate = {
"shardId": "arena",
"shardEpoch": 4,
"frame": 100,
"subjectId": "bob",
"claimKind": "hit",
"claimHash": compute_simulation_claim_hash("hit", "alice", "bob", "frame:100"),
"claimSummary": "alice shot bob first",
"witnessCount": 2,
"supportWeight": 2.0,
"totalWeight": 2.0,
"confidence": 1.0,
"hasQuorum": True,
}
with tempfile.TemporaryDirectory() as tmp:
node = CultMesh.create_node(Path(tmp) / "facts.cc", runtime_id="mesh-facts")
committer = CultMesh.create_simulation_fact_committer(node)
rejected = dict(candidate)
rejected["hasQuorum"] = False
with self.assertRaisesRegex(ValueError, "before quorum"):
committer.commit(rejected)
committed = committer.commit(candidate, committed_at="2026-06-13T00:00:00Z")
stored = node.get_required(simulation_fact_document, committed.key)
self.assertEqual(stored.claim_hash, candidate["claimHash"])
self.assertEqual(stored.committed_at, "2026-06-13T00:00:00Z")
self.assertEqual(committed.fact.fact_id, stored.fact_id)
def test_cultnet_simulation_consensus_dedupes_witnesses_and_requires_quorum(self) -> None:
from cultnet_py import CultNetSimulationConsensus
consensus = CultNetSimulationConsensus(
CultNetSimulationConsensusOptions(minimum_witnesses=2, quorum_ratio=1.0)
)
claim_hash = compute_simulation_claim_hash("hit", "alice", "bob", "frame:100")
observations = [
{
"witnessRuntimeId": "watcher-1",
"shardId": "arena",
"shardEpoch": 4,
"frame": 100,
"subjectId": "bob",
"claimKind": "hit",
"claimHash": claim_hash,
"claimSummary": "alice shot bob first",
"weight": 1.0,
},
{
"witnessRuntimeId": "watcher-1",
"shardId": "arena",
"shardEpoch": 4,
"frame": 100,
"subjectId": "bob",
"claimKind": "hit",
"claimHash": "stale-duplicate",
"weight": 0.5,
},
{
"witnessRuntimeId": "watcher-2",
"shardId": "arena",
"shardEpoch": 4,
"frame": 100,
"subjectId": "bob",
"claimKind": "hit",
"claimHash": claim_hash,
"weight": 1.0,
},
]
candidates = consensus.build_candidates(observations)
self.assertEqual(len(candidates), 1)
self.assertEqual(candidates[0]["claimHash"], claim_hash)
self.assertEqual(candidates[0]["witnessCount"], 2)
self.assertEqual(candidates[0]["supportWeight"], 2.0)
self.assertTrue(candidates[0]["hasQuorum"])
def test_cultmesh_game_session_submits_observations_and_commits_quorum_once(self) -> None:
claim_hash = compute_simulation_claim_hash("hit", "alice", "bob", "frame:100")
first = simulation_observation(
message_id="obs-1",
witness_runtime_id="watcher-1",
shard_id="arena",
shard_epoch=4,
frame=100,
subject_id="bob",
claim_kind="hit",
claim_hash=claim_hash,
claim_summary="alice shot bob first",
).to_wire()
second = simulation_observation(
message_id="obs-2",
witness_runtime_id="watcher-2",
shard_id="arena",
shard_epoch=4,
frame=100,
subject_id="bob",
claim_kind="hit",
claim_hash=claim_hash,
claim_summary="alice shot bob first",
).to_wire()
with tempfile.TemporaryDirectory() as tmp:
node = CultMesh.create_node(Path(tmp) / "session.cc", runtime_id="mesh-session")
session = CultMesh.create_game_session(
node,
CultMeshGameSessionOptions(
consensus_options=CultNetSimulationConsensusOptions(minimum_witnesses=2, quorum_ratio=1.0)
),
)
self.assertEqual(session.submit_and_commit(first), [])
commits = session.submit_and_commit(second)
replay = session.commit_quorum_candidates(session.submit_observation(second))
self.assertEqual(len(commits), 1)
self.assertEqual(replay, [])
stored = node.get_required(simulation_fact_document, commits[0].key)
self.assertEqual(stored.claim_hash, claim_hash)
self.assertEqual(stored.witness_count, 2)
def test_cultmesh_game_session_prediction_requires_scope_and_reconciles_shard_log(self) -> None:
note_doc = define_database_entry_type(
"mesh.input",
[("body", 0)],
schema_id="mesh.input.v1",
)
with tempfile.TemporaryDirectory() as tmp:
node = CultMesh.create_node(Path(tmp) / "prediction.cc", runtime_id="client-a")
node.register_document(note_doc)
session = CultMesh.create_game_session(
node,
CultMeshGameSessionOptions(
client_authority_scopes=(
CultNetClientAuthorityScope(
"client-a",
schema_ids=("mesh.input.v1",),
key_prefix="input:client-a",
),
)
),
)
with self.assertRaisesRegex(ValueError, "does not have client prediction authority"):
session.predict(note_doc, "input:other", {"body": "nope"})
prediction = session.predict(note_doc, "input:client-a:move", {"body": "predicted"})
put = document_put_raw(
message_id="authoritative",
key=prediction.key,
schema_id=prediction.schema_id,
stored_at="2026-06-13T00:00:00Z",
payload=note_doc.encode_payload({"body": "authoritative"}),
shard_id="inputs",
shard_epoch=1,
)
changes = session.apply_shard_log_response({
"schemaVersion": "cultnet.shard_log_response.v0",
"messageId": "inputs-log",
"shardId": "inputs",
"shardEpoch": 1,
"entries": [
{
"sequence": 1,
"committedAt": "2026-06-13T00:00:00Z",
"changeKind": "updated",
"put": put.to_wire(),
}
],
"resyncRequired": False,
})
self.assertEqual(changes[0].change_kind, "reconciled")
self.assertEqual(node.get_required(note_doc, prediction.key)["body"], "authoritative")
def test_cultmesh_verse_catalog_response_matches_schema_v0_wire_shape(self) -> None:
import msgpack # type: ignore
catalog = CultMeshVerseCatalog()
catalog.upsert(
CultMeshVerseDescriptor(
verse_id="aetheria-main",
display_name="Aetheria",
authority_model="OperatorCluster",
compatibility=CultMeshVerseCompatibility(
transport_version="cultmesh.v0",
rules_hash="rules",
compatible_verse_ids=("aetheria-modded",),
required_plugin_ids=("core",),
optional_plugin_ids=("skylands",),
),
discovery_endpoints=("cultmesh://aetheria.example.test:3075",),
authority_runtime_ids=("runtime-a",),
description="main branch",
)
)
response = catalog.create_response(verse_catalog_request("verses-1"))
decoded = msgpack.unpackb(msgpack.packb(response, use_bin_type=True), raw=False)
self.assertEqual(decoded["schemaVersion"], "cultmesh.verse_catalog_response.v0")
self.assertEqual(decoded["messageId"], "verses-1")
self.assertEqual(decoded["verses"][0]["verseId"], "aetheria-main")
self.assertEqual(decoded["verses"][0]["compatibility"]["requiredPluginIds"], ["core"])
def test_cultmesh_peer_exchange_response_matches_schema_v0_wire_shape(self) -> None:
import msgpack # type: ignore
catalog = CultMeshPeerCatalog()
catalog.upsert(
CultMeshPeerCard(
peer_id="peer-a",
verse_id="aetheria-main",
endpoints=("cultnet://peer-a.example.test:3075",),
roles=("discovery", "read-replica"),
shard_ids=("players",),
region="eu-west",
authority_lease_id="lease-1",
expires_at="2026-05-20T12:00:00.0000000Z",
signature="sig",
)
)
response = catalog.create_response(
peer_exchange_request("pex-1", verse_id="aetheria-main", roles=["read-replica"])
)
decoded = msgpack.unpackb(msgpack.packb(response, use_bin_type=True), raw=False)
self.assertEqual(decoded["schemaVersion"], "cultmesh.peer_exchange_response.v0")
self.assertEqual(decoded["messageId"], "pex-1")
self.assertEqual(decoded["peers"][0]["peerId"], "peer-a")
self.assertIn("read-replica", decoded["peers"][0]["roles"])
self.assertEqual(decoded["peers"][0]["authorityLeaseId"], "lease-1")
def test_cultmesh_discovery_client_fetches_typed_catalogs_over_cultnet_frames(self) -> None:
import msgpack # type: ignore
from cultnet_py import read_frame, write_frame
verses = CultMeshVerseCatalog()
verses.upsert(
CultMeshVerseDescriptor(
verse_id="aetheria-main",
display_name="Aetheria",
authority_model="federated",
compatibility=CultMeshVerseCompatibility(
transport_version="cultmesh.v0",
rules_hash="rules-1",
required_plugin_ids=("core",),
),
discovery_endpoints=("cultmesh://aetheria.example.test:3075",),
authority_runtime_ids=("runtime-a",),
)
)
peers = CultMeshPeerCatalog()
peers.upsert(
CultMeshPeerCard(
peer_id="peer-a",
verse_id="aetheria-main",
endpoints=("cultnet://peer-a.example.test:3075",),
roles=("read-replica",),
shard_ids=("players",),
)
)
ready = threading.Event()
server_error: list[BaseException] = []
def serve_requests() -> None:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 0))
port_holder.append(server.getsockname()[1])
server.listen(2)
ready.set()
for _ in range(4):
connection, _ = server.accept()
with connection:
stream = connection.makefile("rwb")
request = msgpack.unpackb(read_frame(stream), raw=False)
if request["schemaVersion"] == "cultmesh.verse_catalog_request.v0":
response = verses.create_response(request)
elif request["schemaVersion"] == "cultmesh.peer_exchange_request.v0":
response = peers.create_response(request)
else:
raise AssertionError(f"unexpected request {request['schemaVersion']}")
write_frame(stream, msgpack.packb(response, use_bin_type=True))
stream.flush()
except BaseException as error:
server_error.append(error)
ready.set()
port_holder: list[int] = []
thread = threading.Thread(target=serve_requests, daemon=True)
thread.start()
self.assertTrue(ready.wait(2.0))
self.assertFalse(server_error)
client = CultMeshDiscoveryClient("127.0.0.1", port_holder[0], timeout_seconds=2.0)
fetched_verses = client.fetch_verses(transport_version="cultmesh.v0")
fetched_peers = client.fetch_peers(verse_id="aetheria-main", roles=["read-replica"])
local_verses = CultMeshVerseCatalog()
local_peers = CultMeshPeerCatalog()
synced_verses = client.sync_verse_catalog(local_verses, transport_version="cultmesh.v0")
synced_peers = client.sync_peer_catalog(local_peers, verse_id="aetheria-main", roles=["read-replica"])
thread.join(2.0)
self.assertFalse(server_error)
self.assertEqual(fetched_verses[0].verse_id, "aetheria-main")
self.assertEqual(fetched_verses[0].compatibility.required_plugin_ids, ("core",))
self.assertEqual(fetched_peers[0].peer_id, "peer-a")
self.assertEqual(fetched_peers[0].shard_ids, ("players",))
self.assertEqual(synced_verses[0].verse_id, "aetheria-main")
self.assertEqual(local_peers.find("aetheria-main", role="read-replica")[0].peer_id, "peer-a")
self.assertEqual(synced_peers[0].roles, ("read-replica",))
def test_cultmesh_authority_lease_requires_live_matching_lease(self) -> None:
peer = CultMeshPeerCard(
peer_id="voidbot-local",
verse_id="local",
endpoints=("cultmesh://localhost",),
roles=("shard-primary",),
authority_lease_id="lease:voidbot-local",
)
leases = CultMeshAuthorityLeaseCatalog()
now = datetime.now(UTC)
self.assertFalse(leases.is_authorized(peer, "shard-primary", at=now))
leases.upsert(
CultMeshAuthorityLease(
lease_id="lease:voidbot-local",
verse_id="local",
peer_id="voidbot-local",
roles=("shard-primary",),
valid_from=now - timedelta(seconds=1),
expires_at=now + timedelta(seconds=1),
)
)
self.assertTrue(leases.is_authorized(peer, "shard-primary", at=now))
self.assertFalse(leases.is_authorized(peer, "read-replica", at=now))
def test_cultmesh_stream_catalog_negotiates_transport_and_latest_frame(self) -> None:
streams = CultMeshStreamCatalog()
streams.declare(
CultMeshStreamDescriptor(
stream_id="mimir:kiyo-pro",
verse_id="studio",
owner_peer_id="starfire",
kind="video",
label="Kiyo Pro",
clock={"clockDomainId": "starfire-qpc", "confidence": 0.25},
video={"width": 1920, "height": 1080, "pixelFormat": "YUY2", "framesPerSecond": 30},
preferred_transports=("shared-d3d12-texture", "shared-memory", "cultcache-page"),
max_in_flight_frames=3,
)
)
negotiation = streams.negotiate(
"mimir:kiyo-pro",
CultMeshStreamConsumerProfile(
peer_id="fensalir",
verse_id="studio",
supported_transports=("shared-d3d12-texture", "cultcache-page"),
accepted_kinds=("video",),
can_import_gpu_handles=True,
max_in_flight_frames=2,
),
)
self.assertEqual(negotiation.transport, "shared-d3d12-texture")
self.assertEqual(negotiation.max_in_flight_frames, 2)
self.assertEqual(negotiation.copy_budget, "zero-copy-target")
streams.publish_frame(
CultMeshStreamFrameHandle(
stream_id="mimir:kiyo-pro",
sequence=42,
timestamp_ns=1_000_000_000,
duration_ns=33_333_334,
transport="shared-d3d12-texture",
native_handle="0xfeed",
fence_handle="0xbeef",
fence_value=7,
unavoidable_copy_count=0,
)
)
self.assertEqual(streams.latest_frame("mimir:kiyo-pro").sequence, 42)
if __name__ == "__main__":
unittest.main()