Files
TheTree_mock/tests/s0/test_domain_events.gd
T
Takeshi 5dde0c5ec2 Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
2026-09-30 23:52:24 +09:00

145 lines
6.9 KiB
GDScript

extends SceneTree
var _checks := 0
var _failures := 0
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
print("S0: domain events")
_test_snapshot_id_cache()
_test_single_publish_and_snapshot()
_test_atomic_batch_and_reentrant_delivery()
_test_batch_rejection_is_atomic()
if _failures == 0:
print("PASS: %d checks" % _checks)
else:
push_error("FAIL: %d of %d checks failed" % [_failures, _checks])
quit(_failures)
func _test_single_publish_and_snapshot() -> void:
var stream := DomainEventStream.new()
var delivery_order: Array[StringName] = []
stream.subscribe(&"SERVICE_COMPLETED", &"z_report", func(_event: SimulationDomainEvent) -> void: delivery_order.append(&"z_report"))
stream.subscribe(&"*", &"a_log", func(_event: SimulationDomainEvent) -> void: delivery_order.append(&"a_log"))
var event := SimulationDomainEvent.new(
&"domain_event.000000000001",
&"SERVICE_COMPLETED",
360,
&"facility_service",
[&"facility.000000000001"],
{&"quality": 80},
12
)
_expect(event.is_valid(), "complete domain event is valid")
_expect(stream.publish(event), "new fact is published")
_expect(delivery_order == [&"a_log", &"z_report"], "subscribers run in stable ID order")
_expect(not stream.publish(event), "same event ID cannot be applied twice")
_expect(delivery_order.size() == 2, "duplicate event is not redelivered")
var snapshot := stream.create_snapshot()
var restored := DomainEventStream.new()
_expect(restored.restore_snapshot(snapshot), "published event state restores")
_expect(restored.has_published(event.event_id), "deduplication IDs survive restore")
var recent := restored.recent_events()
_expect(recent.size() == 1 and recent[0].payload[&"quality"] == 80, "recent fact data survives restore")
func _test_atomic_batch_and_reentrant_delivery() -> void:
var stream := DomainEventStream.new()
var deliveries: Array[StringName] = []
var callback_probe := {
&"second_committed_before_delivery": false,
&"restore_rejected_during_delivery": false,
}
var event_a := _event(&"domain_event.batch.0001", &"A", 400)
var event_b := _event(&"domain_event.batch.0002", &"B", 400)
var event_c := _event(&"domain_event.batch.0003", &"C", 400)
var snapshot_before := stream.create_snapshot()
stream.subscribe(&"*", &"observer", func(event: SimulationDomainEvent) -> void:
deliveries.append(event.event_type)
if event.event_type == &"A":
callback_probe[&"second_committed_before_delivery"] = stream.has_published(event_b.event_id)
callback_probe[&"restore_rejected_during_delivery"] = not stream.restore_snapshot(snapshot_before)
_expect(stream.publish_batch([event_c]), "reentrant publication is accepted after the committed batch")
)
_expect(stream.publish_batch([event_a, event_b]), "valid event batch commits")
_expect(bool(callback_probe[&"second_committed_before_delivery"]), "every batch ID is committed before the first callback")
_expect(bool(callback_probe[&"restore_rejected_during_delivery"]), "subscriber cannot replace stream state during delivery")
_expect(deliveries == [&"A", &"B", &"C"], "reentrant event delivery waits behind the complete batch")
_expect(
stream.has_published(event_a.event_id) \
and stream.has_published(event_b.event_id) \
and stream.has_published(event_c.event_id),
"batch and reentrant event IDs are all retained"
)
stream.unsubscribe(&"*", &"observer")
func _test_batch_rejection_is_atomic() -> void:
var stream := DomainEventStream.new()
var deliveries: Array[StringName] = []
stream.subscribe(&"*", &"observer", func(event: SimulationDomainEvent) -> void:
deliveries.append(event.event_type)
)
var valid := _event(&"domain_event.reject.0001", &"VALID", 500)
var duplicate := _event(&"domain_event.reject.0001", &"DUPLICATE", 500)
var before := stream.create_snapshot()
_expect(not stream.publish_batch([valid, duplicate]), "duplicate ID inside a batch is rejected")
_expect(stream.create_snapshot() == before and deliveries.is_empty(), "duplicate batch rejection has no state or notification prefix")
var invalid := _event(&"domain_event.reject.0002", &"INVALID", 500)
invalid.event_type = &""
_expect(not stream.publish_batch([valid, invalid]), "invalid member rejects the whole batch")
_expect(stream.create_snapshot() == before and deliveries.is_empty(), "invalid batch rejection remains atomic")
_expect(stream.publish(valid), "single publish still delegates to the batch boundary")
var after_valid := stream.create_snapshot()
_expect(not stream.publish_batch([_event(&"domain_event.reject.0003", &"NEW", 500), valid]), "collision with published history rejects the whole batch")
_expect(stream.create_snapshot() == after_valid and deliveries == [&"VALID"], "history collision cannot commit a new prefix")
var oversized: Array = []
oversized.resize(DomainEventStream.MAX_BATCH_SIZE + 1)
_expect(not stream.publish_batch(oversized), "oversized batch is rejected before member access")
_expect(stream.create_snapshot() == after_valid, "oversized rejection preserves history")
func _event(event_id: StringName, event_type: StringName, minute: int) -> SimulationDomainEvent:
return SimulationDomainEvent.new(
event_id,
event_type,
minute,
&"test",
[],
{},
0
)
func _expect(condition: bool, label: String) -> void:
_checks += 1
if condition:
print(" ✓ %s" % label)
return
_failures += 1
push_error(" ✗ %s" % label)
func _test_snapshot_id_cache() -> void:
var stream := DomainEventStream.new()
var ids: Array[String] = ["z", "a", "A", "a10", "a2", String.chr(0x1f333), String.chr(0x3042)]
_expect(stream.restore_snapshot({"version":1,"published_ids":ids,"recent_events":[]}), "restore unsorted history fixture")
var expected := ids.duplicate()
expected.sort_custom(func(a: String,b: String):return a < b)
var first := stream.create_snapshot()
_expect(first["published_ids"] == expected, "native string sort preserves reference order including Unicode")
first["published_ids"].clear()
_expect(stream.create_snapshot()["published_ids"] == expected, "returned ID array cannot corrupt cached history")
var event := SimulationDomainEvent.new(&"new_id", &"TEST", 360, &"test", [], {}, 1)
_expect(stream.publish(event), "publish invalidates cached IDs")
expected.append("new_id");expected.sort()
_expect(stream.create_snapshot()["published_ids"] == expected, "new ID appears once after cached snapshot")
_expect(not stream.publish(event) and stream.create_snapshot()["published_ids"] == expected, "rejected duplicate preserves cached state")
_expect(stream.restore_snapshot({"version":1,"published_ids":["replacement"],"recent_events":[]}), "replace history through restore")
_expect(stream.create_snapshot()["published_ids"] == ["replacement"], "restore invalidates old sorted cache")
var valid := stream.create_snapshot()
_expect(not stream.restore_snapshot({"version":1,"published_ids":["duplicate","duplicate"],"recent_events":[]}), "invalid restore rejected")
_expect(stream.create_snapshot() == valid, "failed restore preserves canonical snapshot")