///- --package .
arena_host (test)
test arena_host: prelude
///- --test static --symbol
:< testing
:< sm'_operators
:| host_event =
| WindowGranted
| WindowLost
| WorldReady
| WorldCrashed
| RunEnded : block_plan::run_outcome
| RunTimedOut
:| host_command =
| StartWorld
| RestartWorld
| ResetCharacter
| StartRun : i32 * i32
| StopRun
| Record : block_plan::run_fate
| ReleaseWindow
:| host_phase =
| AwaitingWindow
| StartingWorld
| Running
| Ended
:== host = { phase : host_phase; runs : array i32; progress : block_plan::progress }
:= opened (runs : array i32) : host = { phase = AwaitingWindow; runs = runs; progress = block_plan::starting () }
:= next_run (h : host) : list host_command = [ ResetCharacter; StartRun (h::progress::stage, h::progress::run) ]
:= closing (h : host) (fate : block_plan::run_fate) : host * list host_command =
? block_plan::finished h::runs h::progress ?> { h ?| phase = Ended }, [ Record fate; ReleaseWindow ]
|: h, Record fate :: next_run h
:= settled (h : host) (o : block_plan::run_outcome) : host * list host_command =
closing { h ?| progress = block_plan::after h::runs h::progress o } (block_plan::fate_of h::progress::retried o)
:= crashed () : block_plan::run_outcome = :< block_plan ;; Crashed
:= timed_out (h : host) : host * list host_command =
?= settled h (crashed ()) ?|
| after_crash, commands => after_crash, StopRun :: commands
:= restarted (h : host) (after_crash : host) : host * list host_command =
:= fate = block_plan::fate_of h::progress::retried (crashed ())
{ after_crash ?| phase = StartingWorld }, [ Record fate; RestartWorld ]
:= world_crashed (h : host) : host * list host_command =
?= settled h (crashed ()) ?|
| after_crash, commands =>
?= after_crash::phase ?|
| Ended => after_crash, commands
| _ => restarted h after_crash
:= awaiting_step (h : host) (e : host_event) : host * list host_command =
?= e ?|
| WindowGranted => { h ?| phase = StartingWorld }, [ StartWorld ]
| WindowLost => { h ?| phase = Ended }, []
| _ => h, []
:= starting_step (h : host) (e : host_event) : host * list host_command =
?= e ?|
| WorldReady => { h ?| phase = Running }, next_run h
| WorldCrashed => h, [ RestartWorld ]
| WindowLost => { h ?| phase = Ended }, []
| _ => h, []
:= running_step (h : host) (e : host_event) : host * list host_command =
?= e ?|
| RunEnded o => settled h o
| RunTimedOut => timed_out h
| WorldCrashed => world_crashed h
| WindowLost => { h ?| phase = Ended }, []
| _ => h, []
:= step (h : host) (e : host_event) : host * list host_command =
?= h::phase ?|
| Ended => h, []
| AwaitingWindow => awaiting_step h e
| StartingWorld => starting_step h e
| Running => running_step h e
:= fate_text (fate : block_plan::run_fate) : string =
:< block_plan
?= fate ?|
| Counted => "counted"
| Rerun => "rerun"
| Missing => "missing"
:= run_text (stage : i32) (run : i32) : string = "run " ++#? stage ++# "." ++#? run
:= character_command_text (c : host_command) : string =
?= c ?|
| ResetCharacter => "reset"
| StopRun => "stop"
| _ => "release"
:= command_text (c : host_command) : string =
?= c ?|
| StartWorld => "start-world"
| RestartWorld => "restart-world"
| StartRun (stage, run) => run_text stage run
| Record fate => fate_text fate
| _ => character_command_text c
:= with_command (line : string) (c : host_command) : string =
? line = "" ?> command_text c |: line ++# ", " ++# command_text c
:= logged (log : string) (commands : list host_command) : string =
:= text = listm::fold with_command "" commands
? text = "" ?> log |? log = "" ?> text |: log ++# " | " ++# text
:~ ^ played (h : host) (events : list host_event) (log : string) : string =
?= events ?|
| [] => log
| e :: rest =>
:= next, commands = step h e
played next rest (logged log commands)
:| world_reaction =
| Finishes : block_plan::run_outcome
| TimesOut
| CrashesWorld
:= reaction_event (r : world_reaction) : host_event =
?= r ?|
| Finishes o => RunEnded o
| TimesOut => RunTimedOut
| CrashesWorld => WorldCrashed
:== world_script = list world_reaction
:== reacting = list host_event * world_script
:= run_reaction (script : world_script) (events : list host_event) : reacting =
?= script ?|
| r :: later => reaction_event r :: events, later
| [] => WindowLost :: events, []
:= with_reaction (c : host_command) (script : world_script) (events : list host_event) : reacting =
?= c ?|
| StartWorld | RestartWorld => WorldReady :: events, script
| StartRun _ => run_reaction script events
| _ => events, script
:~ ^ reacted (commands : list host_command) (script : world_script) (events : list host_event) : reacting =
?= commands ?|
| [] => listm::rev events, script
| c :: rest =>
:= after, left = with_reaction c script events
reacted rest left after
:== simulation = { h : host; script : world_script; log : string }
:= reacted_turn (s : simulation) (commands : list host_command) (rest : list host_event)
: simulation * list host_event
=
:= queued, left = reacted commands s::script (listm::rev rest)
{ s ?| script = left; log = logged s::log commands }, queued
:~ ^ simulated (s : simulation) (pending : list host_event) : string =
?= pending ?|
| [] => s::log
| e :: rest =>
:= next, commands = step s::h e
:= after, queued = reacted_turn { s ?| h = next } commands rest
simulated after queued
:= simulate (h : host) (pending : list host_event) (script : world_script) : string =
simulated { h = h; script = script; log = "" } pending
:= block_of (first : i32) : host = opened (block_plan::stages_of first 1)
:= completed () : host_event = RunEnded (:< block_plan ;; Completed)
:= played_from (first : i32) (events : list host_event) : string = played (block_of first) events ""
:= finishes () : world_reaction = Finishes (:< block_plan ;; Completed)
:= clean_block_trace () : string =
"start-world | reset, run 0.0 | counted, reset, run 0.1 | counted, reset, run 1.0 | counted, release"
a_clean_block_resets_before_every_run_and_releases_its_window (test)
test a_clean_block_resets_before_every_run_and_releases_its_window: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 2i32
played_from first [ WindowGranted; WorldReady; completed (); completed (); completed () ]
|> _assert_eq (clean_block_trace ())
__assert_eq { expected = start-world | reset, run 0.0 | counted, reset, run 0.1 | counted, reset, run 1.0 | counted, release }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692047543-4/main.lua` was not found)
:= timed_out_trace () : string =
"start-world | reset, run 0.0 | stop, rerun, reset, run 0.0 | stop, missing, reset, run 1.0 | counted, release"
a_timed_out_run_is_stopped_and_rerun_once_then_counted_missing (test)
test a_timed_out_run_is_stopped_and_rerun_once_then_counted_missing: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 1i32
played_from first [ WindowGranted; WorldReady; RunTimedOut; RunTimedOut; completed () ]
|> _assert_eq (timed_out_trace ())
__assert_eq { expected = start-world | reset, run 0.0 | stop, rerun, reset, run 0.0 | stop, missing, reset, run 1.0 | counted, release }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692047546-68/main.lua` was not found)
:= world_crash_trace () : string =
"start-world | reset, run 0.0 | rerun, restart-world | reset, run 0.0 | counted, reset, run 1.0 | counted, release"
a_world_crash_restarts_the_world_and_resets_the_character_before_the_rerun (test)
test a_world_crash_restarts_the_world_and_resets_the_character_before_the_rerun: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 1i32
played_from first [ WindowGranted; WorldReady; WorldCrashed; WorldReady; completed (); completed () ]
|> _assert_eq (world_crash_trace ())
__assert_eq { expected = start-world | reset, run 0.0 | rerun, restart-world | reset, run 0.0 | counted, reset, run 1.0 | counted, release }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692047546-36/main.lua` was not found)
a_lost_window_ends_the_block_and_later_events_change_nothing (test)
test a_lost_window_ends_the_block_and_later_events_change_nothing: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 1i32
played_from first [ WindowGranted; WorldReady; WindowLost; completed (); WindowGranted ]
|> _assert_eq "start-world | reset, run 0.0"
__assert_eq { expected = start-world | reset, run 0.0 }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692047574-5442/main.lua` was not found)
:= scripted_block_trace () : string =
"start-world | reset, run 0.0 | counted, reset, run 0.1 | stop, rerun, reset, run 0.1 | "
^^ "counted, reset, run 1.0 | rerun, restart-world | reset, run 1.0 | counted, release"
a_scripted_world_drives_a_whole_block_through_the_executor (test)
test a_scripted_world_drives_a_whole_block_through_the_executor: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 2i32
simulate (block_of first) [ WindowGranted ] [ finishes (); TimesOut; finishes (); CrashesWorld; finishes () ]
|> _assert_eq (scripted_block_trace ())
__assert_eq { expected = start-world | reset, run 0.0 | counted, reset, run 0.1 | stop, rerun, reset, run 0.1 | counted, reset, run 1.0 | rerun, restart-world | reset, run 1.0 | counted, release }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692054567-259/main.lua` was not found)
a_world_that_stops_answering_ends_the_block (test)
test a_world_that_stops_answering_ends_the_block: passed
///- --test --symbol
///> lua
///> gleam
:= ~first = 1i32
simulate (block_of first) [ WindowGranted ] [ finishes () ]
|> _assert_eq "start-world | reset, run 0.0 | counted, reset, run 1.0"
__assert_eq { expected = start-world | reset, run 0.0 | counted, reset, run 1.0 }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692054568-291/main.lua` was not found)
:| host_message r =
| Event : host_event
| Trace : r
:~ ^ filled_runs (runs : array i32) (i : i32) (rest : list i32) : () =
?= rest ?|
| head :: tail =>
set runs i head
filled_runs runs (i + 1) tail
| [] => ()
:= runs_of_plan (plan : list i32) : array i32 =
:= runs : array i32 = create (listm::length plan)
filled_runs runs 0 plan
runs
:== host_state = list i32 * option host * string
:= current_host (kept_plan : list i32) (current : option host) : host =
?= current ?|
| Some running => running
| None => opened (runs_of_plan kept_plan)
:= opened_state (state : host_state) : list i32 * host * string =
:= kept_plan, current, log = state
kept_plan, current_host kept_plan current, log
:= on_event (kept_plan : list i32) (h : host) (log : string) (e : host_event) =
:= next, commands = step h e
step_runtime::Continue (kept_plan, Some next, logged log commands)
:= traced \* r. (answer : r -> string -> ()) (kept_plan : list i32) (h : host) (log : string) (to : r) =
answer to log
step_runtime::Continue (kept_plan, Some h, log)
:= handled \* r. (answer : r -> string -> ()) (state : host_state) (message : host_message r) =
:= kept_plan, h, log = opened_state state
?= message ?|
| Event e => on_event kept_plan h log e
| Trace to => traced answer kept_plan h log to
:= host_actor \* r. (answer : r -> string -> ()) (plan : list i32) : step_runtime::actor host_state (host_message r) =
{ init = \ () => plan, None, ""; handle = handled answer }
:= actor_trace \* a r.
(post : a -> host_message r -> ()) (ask : a -> (r -> host_message r) -> string) (actor : a)
(events : list host_event)
: string
=
listm::iter (\ (e : host_event) => post actor (Event e)) events
ask actor Trace
:= otp_trace (plan : list i32) (events : list host_event) : string =
:= actor = step_runtime::otp_start (host_actor erlang_process::send plan)
actor_trace otp_actor::send (\ inbox request => otp_actor::call inbox 10000i32 request) actor events
:= step_runtime_trace (plan : list i32) (events : list host_event) : string =
actor_trace step_runtime::send step_runtime::call (step_runtime::spawn (host_actor step_runtime::reply plan)) events
:= backend_trace (plan : list i32) (events : list host_event) : string =
run_target \|
| Gleam => \ () => otp_trace plan events
| _ => \ () => step_runtime_trace plan events
:= two_stage_trace () : string = "start-world | reset, run 0.0 | counted, reset, run 1.0 | counted, release"
the_host_step_runs_inside_an_actor_and_gives_the_same_trace_on_every_backend (test)
test the_host_step_runs_inside_an_actor_and_gives_the_same_trace_on_every_backend: passed
///- --test --symbol
///> gleam
///> lua
:= ~first = 1i32
backend_trace [ first; 1i32 ] [ WindowGranted; WorldReady; completed (); completed () ]
|> _assert_eq (two_stage_trace ())
__assert_eq { expected = start-world | reset, run 0.0 | counted, reset, run 1.0 | counted, release }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692056371-5666/main.lua` was not found)