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")