Preserve approved pixel tower prototype as development baseline
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
extends SceneTree
|
||||
|
||||
var _checks := 0
|
||||
var _failures := 0
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
func _run() -> void:
|
||||
print("S0: domain events")
|
||||
_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)
|
||||
Reference in New Issue
Block a user