okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
0ca1666
main
1//// Timeout and reply/death ordering require process monitors and controlled 2//// acknowledgments that the external E2E API cannot arrange. 3 4import albedo/actor_call 5import gleam/erlang/process .{ type Subject } 6import gleam/otp/actor 7import gleeunit/should 8 9type Ping { 10Ping ( reply : Subject ( String )) 11Die 12} 13 14fn server ( mode : fn ( message) -> actor . Next ( Nil , message)) -> Subject ( message) { 15let assert Ok ( started ) = 16actor . new ( Nil ) 17|> actor . on_message ( fn ( _ , message ) { mode ( message ) }) 18|> actor . start 19started . data 20} 21 22fn answers ( message : Ping ) -> actor . Next ( Nil , Ping ) { 23case message { 24Ping ( reply ) -> { 25process . send ( reply , "pong" ) 26actor . continue ( Nil ) 27} 28_ -> actor . continue ( Nil ) 29} 30} 31 32fn never_replies ( _message : Ping ) -> actor . Next ( Nil , Ping ) { 33actor . continue ( Nil ) 34} 35 36fn dies_on_call ( message : Ping ) -> actor . Next ( Nil , Ping ) { 37case message { 38Die -> actor . stop () 39_ -> actor . continue ( Nil ) 40} 41} 42 43pub fn a_reply_in_time_is_returned_test () -> Nil { 44let subject = server ( answers ) 45actor_call . try_call ( subject , 2000 , Ping ) 46|> should . equal ( Ok ( "pong" )) 47} 48 49pub fn a_stalled_callee_reports_a_timeout_test () -> Nil { 50let subject = server ( never_replies ) 51actor_call . try_call ( subject , 20 , Ping ) 52|> should . equal ( Error ( actor_call . TimedOut )) 53} 54 55pub fn a_dead_callee_reports_the_death_test () -> Nil { 56let subject = server ( dies_on_call ) 57actor_call . try_call ( subject , 2000 , fn ( _reply ) { Die }) 58|> should . equal ( Error ( actor_call . CalleeDown )) 59} 60 61pub fn a_reply_that_races_the_callee_exit_still_arrives_test () -> Nil { 62let subject = 63server ( fn ( message ) { 64case message { 65Ping ( reply ) -> { 66process . send ( reply , "last words" ) 67actor . stop () 68} 69_ -> actor . continue ( Nil ) 70} 71}) 72actor_call . try_call ( subject , 2000 , Ping ) 73|> should . equal ( Ok ( "last words" )) 74} 75 76pub fn an_unregistered_named_callee_reports_death_test () -> Nil { 77let subject = 78process . new_name ( "actor_call_test_missing" ) |> process . named_subject 79actor_call . try_call ( subject , 2000 , Ping ) 80|> should . equal ( Error ( actor_call . CalleeDown )) 81} 82 83pub fn finite_calls_remove_monitors_and_down_messages_test () -> Nil { 84let before = monitor_state () 85let replying = server ( answers ) 86actor_call . try_call ( replying , 2000 , Ping ) |> should . equal ( Ok ( "pong" )) 87monitor_state () |> should . equal ( before ) 88let stalled = server ( never_replies ) 89actor_call . try_call ( stalled , 20 , Ping ) 90|> should . equal ( Error ( actor_call . TimedOut )) 91monitor_state () |> should . equal ( before ) 92let dying = server ( dies_on_call ) 93actor_call . try_call ( dying , 2000 , fn ( _ ) { Die }) 94|> should . equal ( Error ( actor_call . CalleeDown )) 95monitor_state () |> should . equal ( before ) 96} 97 98@external ( erlang , "albedo_actor_call_test_support" , "monitor_state" ) 99fn monitor_state () -> #( Int , Int )