Files

44 lines
3.7 KiB
GDScript

extends SceneTree
const Weather = preload("res://scripts/environment/weather_timeline.gd")
var checks := 0
var failures := 0
func expect(ok: bool, message: String) -> void:
checks += 1
if not ok: failures += 1; push_error(message)
func _initialize() -> void:
var weather = Weather.new()
expect(not weather.permits_new_arrivals(), "uninitialized weather never grants admission")
expect(not weather.initialize(&"unknown", 360) and not weather.initialize(&"clear", 1.5), "invalid initial data rejected")
expect(weather.initialize(&"clear", 360), "caller explicitly chooses initial weather and time")
expect(not weather.initialize(&"storm", 400), "initialize cannot reset a live simulation")
expect(weather.schedule(&"clear", 390)[&"ok"] and weather.schedule(&"storm", 380)[&"ok"] and weather.schedule(&"rain", 370)[&"ok"], "out of order scheduling retains chronological execution")
expect(weather.schedule(&"storm", 380)[&"replayed"] and not weather.schedule(&"rain", 380)[&"ok"], "same boundary retry is idempotent and conflict rejected")
expect(not weather.schedule(&"storm", 360)[&"ok"], "past and current weather cannot be retroactively changed")
var checkpoint: Dictionary = weather.create_snapshot()
expect(weather.advance_to(379)[&"changes"] == [{&"from": &"clear", &"to": &"rain", &"minute": 370}], "rain changes at its scheduled time")
expect(weather.permits_new_arrivals(), "rain is not treated as a storm admission ban")
expect(weather.advance_to(380)[&"changes"].size() == 1 and not weather.permits_new_arrivals(), "storm blocks admission at exact boundary")
var storm: Dictionary = weather.create_snapshot()
var replay: Dictionary = weather.advance_to(380)
expect(replay[&"replayed"] and replay[&"changes"].is_empty() and weather.create_snapshot() == storm, "same minute cannot duplicate a transition")
expect(not weather.advance_to(379)[&"ok"] and weather.create_snapshot() == storm, "time reversal cannot change state")
expect(weather.advance_to(390)[&"ok"] and weather.permits_new_arrivals(), "clear restores admission")
var finished: Dictionary = weather.create_snapshot()
expect(weather.restore_snapshot(checkpoint), "restore earlier weather and pending schedule")
expect(weather.advance_to(390)[&"changes"].size() == 3 and weather.create_snapshot() == finished, "jump and minute-step replay produce identical weather state")
var encoded: Dictionary = bytes_to_var(var_to_bytes(storm))
expect(weather.restore_snapshot(encoded) and weather.get_kind() == &"storm", "production Variant codec preserves integer weather time and IDs")
var baseline: Dictionary = weather.create_snapshot()
for field: String in ["version", "minute", "kind", "since", "pending"]:
var bad := baseline.duplicate(true); bad.erase(field)
expect(not weather.restore_snapshot(bad) and weather.create_snapshot() == baseline, "missing field rejects atomically: " + field)
for change: Dictionary in [{"version": 3}, {"minute": 380.0}, {"kind": "snow"}, {"since": 381}, {"pending": [{"kind":"clear","minute":380}]}, {"pending": [{"kind":"clear","minute":400},{"kind":"rain","minute":390}]}, {"extra":true}]:
var bad := baseline.duplicate(true)
bad.merge(change, true)
expect(not weather.restore_snapshot(bad) and weather.create_snapshot() == baseline, "malformed or contradictory state rejects atomically")
var detached: Dictionary = weather.create_snapshot(); detached[&"pending"].clear()
expect(not weather.create_snapshot()[&"pending"].is_empty(), "caller cannot mutate pending weather through snapshot alias")
expect(weather.schedule(&"mana_fog", 400)[&"ok"] and weather.advance_to(400)[&"ok"] and weather.get_kind() == &"mana_fog", "mana fog is persisted without invented efficiency multipliers")
print("Weather timeline: %d checks, %d failures" % [checks, failures])
quit(failures)