Skip to content

Commit 87770c6

Browse files
committed
Fix test_supervisor:try_again_restart/0 test
Test was flappy but in fact it was succeeding because of a race condition. If intensity if 5, supervisor should not have 5 restarts in its children or will shut down. Make test more robust using monitors and add a new test to assert the number of restarts that cause a shutdown. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent b34c943 commit 87770c6

File tree

1 file changed

+87
-10
lines changed

1 file changed

+87
-10
lines changed

tests/libs/estdlib/test_supervisor.erl

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ test() ->
3838
ok = test_one_for_all(),
3939
ok = test_crash_limits(),
4040
ok = try_again_restart(),
41+
ok = try_again_restart4(),
4142
ok.
4243

4344
test_basic_supervisor() ->
@@ -603,24 +604,45 @@ try_again_restart() ->
603604
process_flag(trap_exit, true),
604605

605606
%% Intensity is 5, use the arbitrator to prevent the child from restarting
606-
%% 4 times. This should not exit the supervisor due to intensity.
607-
Arbitrator1 = erlang:spawn(fun() -> arbitrator_start(4) end),
607+
%% 3 times. With the other child, we'll have 4 restarts, and this should not
608+
% exit the supervisor due to intensity.
609+
Arbitrator1 = erlang:spawn(fun() -> arbitrator_start(3) end),
608610
{ok, SupPid1} = supervisor:start_link(
609611
{local, try_again_test1}, ?MODULE, {test_try_again, Arbitrator1, self()}
610612
),
611613
ChildPid = wait_child_pid("ChildPid"),
612614

615+
ChildMonitor = monitor(process, ChildPid),
613616
ChildPid ! stop,
614-
ChildPid1 = wait_child_pid("ChildPid1"),
617+
normal =
618+
receive
619+
{'DOWN', ChildMonitor, process, ChildPid, ChildReason} -> ChildReason
620+
after 5000 -> timeout
621+
end,
615622

623+
ChildPid1 = wait_child_pid("ChildPid1"),
624+
ChildMonitor1 = monitor(process, ChildPid1),
616625
ChildPid1 ! stop,
626+
normal =
627+
receive
628+
{'DOWN', ChildMonitor1, process, ChildPid1, ChildReason1} -> ChildReason1
629+
after 5000 -> timeout
630+
end,
631+
632+
ArbitratorMonitor1 = monitor(process, Arbitrator1),
617633
Arbitrator1 ! shutdown,
634+
normal =
635+
receive
636+
{'DOWN', ArbitratorMonitor1, process, Arbitrator1, ArbitratorReason1} ->
637+
ArbitratorReason1
638+
after 5000 -> timeout
639+
end,
618640
exit(SupPid1, normal),
619-
ok =
641+
normal =
620642
receive
621-
{'EXIT', SupPid1, normal} ->
622-
ok
623-
after 2000 ->
643+
{'EXIT', SupPid1, Reason} ->
644+
Reason
645+
after 5000 ->
624646
error({supervisor_not_stopped, normal})
625647
end,
626648

@@ -633,11 +655,18 @@ try_again_restart() ->
633655
),
634656
ChildPid2 = wait_child_pid("ChildPid2"),
635657

658+
ChildMonitor2 = monitor(process, ChildPid2),
636659
ChildPid2 ! stop,
637-
ok =
660+
normal =
638661
receive
639-
{'EXIT', SupPid2, shutdown} ->
640-
ok
662+
{'DOWN', ChildMonitor2, process, ChildPid2, ChildReason2} -> ChildReason2
663+
after 5000 -> timeout
664+
end,
665+
666+
shutdown =
667+
receive
668+
{'EXIT', SupPid2, ShutdownReason} ->
669+
ShutdownReason
641670
after 2000 ->
642671
error({supervisor_not_stopped, restart_try_again_exceeded})
643672
end,
@@ -677,6 +706,54 @@ try_again_restart() ->
677706
process_flag(trap_exit, false),
678707
ok.
679708

709+
try_again_restart4() ->
710+
process_flag(trap_exit, true),
711+
712+
%% Intensity is 5, use the arbitrator to prevent the child from restarting
713+
%% 4 times. With the other child, we'll have 4 restarts, so the supervisor
714+
%% will shutdown due to intensity
715+
Arbitrator1 = erlang:spawn(fun() -> arbitrator_start(4) end),
716+
{ok, SupPid1} = supervisor:start_link(
717+
{local, try_again_test1}, ?MODULE, {test_try_again, Arbitrator1, self()}
718+
),
719+
ChildPid = wait_child_pid("ChildPid"),
720+
721+
ChildMonitor = monitor(process, ChildPid),
722+
ChildPid ! stop,
723+
normal =
724+
receive
725+
{'DOWN', ChildMonitor, process, ChildPid, ChildReason} -> ChildReason
726+
after 5000 -> timeout
727+
end,
728+
729+
ChildPid1 = wait_child_pid("ChildPid1"),
730+
ChildMonitor1 = monitor(process, ChildPid1),
731+
ChildPid1 ! stop,
732+
normal =
733+
receive
734+
{'DOWN', ChildMonitor1, process, ChildPid1, ChildReason1} -> ChildReason1
735+
after 5000 -> timeout
736+
end,
737+
738+
ArbitratorMonitor1 = monitor(process, Arbitrator1),
739+
Arbitrator1 ! shutdown,
740+
normal =
741+
receive
742+
{'DOWN', ArbitratorMonitor1, process, Arbitrator1, ArbitratorReason1} ->
743+
ArbitratorReason1
744+
after 5000 -> timeout
745+
end,
746+
shutdown =
747+
receive
748+
{'EXIT', SupPid1, Reason} ->
749+
Reason
750+
after 5000 ->
751+
error({supervisor_not_stopped, normal})
752+
end,
753+
754+
process_flag(trap_exit, false),
755+
ok.
756+
680757
wait_child_pid(Name) ->
681758
receive
682759
Pid when is_pid(Pid) ->

0 commit comments

Comments
 (0)