okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
8d97901
main
1%% E2E cannot hold an old owner's cleanup behind a replacement publication. 2%% Control owner publications and suspend the real progress monitor to verify 3%% reads remain safe even before queued death cleanup runs. 4- module ( albedo_running_test ). 5- include_lib ( "eunit/include/eunit.hrl" ). 6 7old_owner_cleanup_preserves_replacement_test () -> 8Session = make_ref (), 9{ Previous , PreviousWatcher } = owner ( Session ), 10{ Replacement , ReplacementWatcher } = owner ( Session ), 11try 12Previous ! { idle , self ()}, 13receive { idle , Previous } -> ok after 5000 -> error ( idle_stalled ) end , 14 ?assertEqual ([{ Session , Replacement }], ets : lookup ( albedo_running , Session )), 15nil = albedo_bus : forget ( Session , Previous ), 16 ?assert ( albedo_bus : running ( Session )), 17stop ( Previous ), 18wait_for_exit ( PreviousWatcher ), 19 ?assertEqual ([{ Session , Replacement }], ets : lookup ( albedo_running , Session )), 20 ?assertMatch ({ ok , { Replacement , _ }}, 21albedo_registry : lookup ( albedo_session_progress , Session )) 22after 23stop ( Previous ), 24stop ( Replacement ), 25wait_for_exit ( PreviousWatcher ), 26wait_for_exit ( ReplacementWatcher ) 27end , 28 ?assertEqual ([], ets : lookup ( albedo_running , Session )). 29 30dead_owner_reads_idle_before_monitor_removes_record_test () -> 31Session = make_ref (), 32{ Owner , Watcher } = owner ( Session ), 33true = erlang : suspend_process ( Watcher ), 34try 35 ?assert ( albedo_bus : running ( Session )), 36stop ( Owner ), 37 ?assertEqual ([{ Session , Owner }], ets : lookup ( albedo_running , Session )), 38 ?assertNot ( albedo_bus : running ( Session )) 39after 40erlang : resume_process ( Watcher ), 41stop ( Owner ), 42wait_for_exit ( Watcher ) 43end , 44 ?assertEqual ([], ets : lookup ( albedo_running , Session )), 45 ?assertEqual ( undefined , albedo_registry : lookup ( albedo_session_progress , Session )). 46 47owner ( Session ) -> 48%% Initialise detached tables before tracing, leaving only the progress 49%% monitor as a spawned child of the registering owner. 50nil = albedo_registry : register ( albedo_running , warmup , self ()), 51nil = albedo_registry : forget ( albedo_running , warmup ), 52nil = albedo_registry : register ( albedo_session_progress , warmup , self ()), 53nil = albedo_registry : forget ( albedo_session_progress , warmup ), 54Parent = self (), 55Owner = spawn ( fun () -> 56receive start -> ok end , 57nil = albedo_bus : register_progress ( Session , self (), fun ( _ ) -> nil end ), 58nil = albedo_bus : mark_running ( Session , true ), 59Parent ! { ready , self ()}, 60owner_loop ( Session ) 61end ), 62erlang : trace ( Owner , true , [ procs , { tracer , Parent }]), 63Owner ! start , 64Watcher = receive { trace , Owner , spawn , Child , _ } -> Child 65after 5000 -> error ( progress_monitor_missing ) end , 66receive { ready , Owner } -> ok after 5000 -> error ( owner_start_stalled ) end , 67erlang : trace ( Owner , false , [ procs ]), 68{ Owner , Watcher }. 69 70owner_loop ( Session ) -> 71receive 72{ idle , Parent } -> 73nil = albedo_bus : mark_running ( Session , false ), 74Parent ! { idle , self ()}, 75owner_loop ( Session ); 76stop -> ok 77end . 78 79stop ( Pid ) -> 80Monitor = monitor ( process , Pid ), 81Pid ! stop , 82receive { 'DOWN' , Monitor , process , Pid , _ } -> ok 83after 5000 -> error ({ owner_stop_stalled , Pid }) end . 84 85wait_for_exit ( Pid ) -> 86Monitor = monitor ( process , Pid ), 87receive { 'DOWN' , Monitor , process , Pid , _ } -> ok 88after 5000 -> error ({ monitor_cleanup_stalled , Pid }) end .