diff options
Diffstat (limited to 'erts/emulator/test/monitor_SUITE.erl')
-rw-r--r-- | erts/emulator/test/monitor_SUITE.erl | 1094 |
1 files changed, 517 insertions, 577 deletions
diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl index 4db17969c0..8955e62df5 100644 --- a/erts/emulator/test/monitor_SUITE.erl +++ b/erts/emulator/test/monitor_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,21 +20,20 @@ -module(monitor_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1, - demon_2/1, demon_3/1, demonitor_flush/1, - local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1, - large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1, - monitor_time_offset/1]). - --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0, groups/0, + case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1, + demon_2/1, demon_3/1, demonitor_flush/1, + local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1, + large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1, + monitor_time_offset/1]). -export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 15}}]. all() -> [case_1, case_1a, case_2, case_2a, mon_e_1, demon_e_1, @@ -47,132 +46,103 @@ groups() -> [{remove_monitor, [], [local_remove_monitor, remote_remove_monitor]}]. -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog=?t:timetrap(?t:minutes(15)), - [{watchdog, Dog},{testcase, Func}|Config]. - -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). - -case_1(doc) -> - "A monitors B, B kills A and then exits (yielded core dump)"; -case_1(suite) -> []; +%% A monitors B, B kills A and then exits (yielded core dump) case_1(Config) when is_list(Config) -> - ?line process_flag(trap_exit, true), - ?line spawn_link(?MODULE, g0, []), - ?line receive _ -> ok end, + process_flag(trap_exit, true), + spawn_link(?MODULE, g0, []), + receive _ -> ok end, ok. -case_1a(doc) -> - "A monitors B, B kills A and then exits (yielded core dump)"; +%% A monitors B, B kills A and then exits (yielded core dump) case_1a(Config) when is_list(Config) -> - ?line process_flag(trap_exit, true), - ?line spawn_link(?MODULE, g1, []), - ?line receive _ -> ok end, + process_flag(trap_exit, true), + spawn_link(?MODULE, g1, []), + receive _ -> ok end, ok. g0() -> - ?line B = spawn(?MODULE, g, [self()]), - ?line erlang:monitor(process, B), - ?line B ! ok, - ?line receive ok -> ok end, + B = spawn(?MODULE, g, [self()]), + erlang:monitor(process, B), + B ! ok, + receive ok -> ok end, ok. g1() -> - ?line {B,_} = spawn_monitor(?MODULE, g, [self()]), - ?line B ! ok, - ?line receive ok -> ok end, + {B,_} = spawn_monitor(?MODULE, g, [self()]), + B ! ok, + receive ok -> ok end, ok. g(Parent) -> - ?line receive ok -> ok end, - ?line exit(Parent, foo), - ?line ok. + receive ok -> ok end, + exit(Parent, foo), + ok. -case_2(doc) -> - "A monitors B, B demonitors A (yielded core dump)"; +%% A monitors B, B demonitors A (yielded core dump) case_2(Config) when is_list(Config) -> - ?line B = spawn(?MODULE, y2, [self()]), - ?line R = erlang:monitor(process, B), - ?line B ! R, - ?line receive - {'EXIT', _} -> ok; - Other -> - test_server:fail({rec, Other}) - end, - ?line expect_down(R, B, normal), + B = spawn(?MODULE, y2, [self()]), + R = erlang:monitor(process, B), + B ! R, + receive + {'EXIT', _} -> ok; + Other -> + ct:fail({rec, Other}) + end, + expect_down(R, B, normal), ok. -case_2a(doc) -> - "A monitors B, B demonitors A (yielded core dump)"; +%% A monitors B, B demonitors A (yielded core dump) case_2a(Config) when is_list(Config) -> - ?line {B,R} = spawn_monitor(?MODULE, y2, [self()]), - ?line B ! R, - ?line receive - {'EXIT', _} -> ok; - Other -> - test_server:fail({rec, Other}) - end, - ?line expect_down(R, B, normal), + {B,R} = spawn_monitor(?MODULE, y2, [self()]), + B ! R, + receive + {'EXIT', _} -> ok; + Other -> + ct:fail({rec, Other}) + end, + expect_down(R, B, normal), ok. y2(Parent) -> - ?line R = receive T -> T end, - ?line Parent ! (catch erlang:demonitor(R)), + R = receive T -> T end, + Parent ! (catch erlang:demonitor(R)), ok. expect_down(Ref, P) -> receive - {'DOWN', Ref, process, P, Reason} -> - Reason; - Other -> - test_server:fail({rec, Other}) + {'DOWN', Ref, process, P, Reason} -> + Reason; + Other -> + ct:fail({rec, Other}) end. expect_down(Ref, P, Reason) -> receive - {'DOWN', Ref, process, P, Reason} -> - ok; - Other -> - test_server:fail({rec, Other}) + {'DOWN', Ref, process, P, Reason} -> + ok; + Other -> + ct:fail({rec, Other}) end. expect_no_msg() -> receive - Msg -> - test_server:fail({msg, Msg}) + Msg -> + ct:fail({msg, Msg}) after 0 -> - ok + ok end. %%% Error cases for monitor/2 -mon_e_1(doc) -> - "Error cases for monitor/2"; -mon_e_1(suite) -> []; mon_e_1(Config) when is_list(Config) -> - ?line {ok, N} = test_server:start_node(hej, slave, []), - ?line mon_error(plutt, self()), - ?line mon_error(process, [bingo]), - ?line mon_error(process, {rex, N, junk}), - ?line mon_error(process, 1), + {ok, N} = test_server:start_node(hej, slave, []), + mon_error(plutt, self()), + mon_error(process, [bingo]), + mon_error(process, {rex, N, junk}), + mon_error(process, 1), - ?line true = test_server:stop_node(N), + true = test_server:stop_node(N), ok. %%% We would also like to have a test case that tries to monitor something @@ -185,155 +155,142 @@ mon_e_1(Config) when is_list(Config) -> mon_error(Type, Item) -> case catch erlang:monitor(Type, Item) of - {'EXIT', _} -> - ok; - Other -> - test_server:fail({err, Other}) + {'EXIT', _} -> + ok; + Other -> + ct:fail({err, Other}) end. %%% Error cases for demonitor/1 -demon_e_1(doc) -> - "Error cases for demonitor/1"; -demon_e_1(suite) -> []; demon_e_1(Config) when is_list(Config) -> - ?line {ok, N} = test_server:start_node(hej, slave, []), - ?line demon_error(plutt, badarg), - ?line demon_error(1, badarg), + {ok, N} = test_server:start_node(hej, slave, []), + demon_error(plutt, badarg), + demon_error(1, badarg), %% Demonitor with ref created at other node - ?line R1 = rpc:call(N, erlang, make_ref, []), - ?line demon_error(R1, badarg), + R1 = rpc:call(N, erlang, make_ref, []), + demon_error(R1, badarg), %% Demonitor with ref created at wrong monitor link end - ?line P0 = self(), - ?line P2 = spawn( - fun() -> - P0 ! {self(), ref, erlang:monitor(process,P0)}, - receive {P0, stop} -> ok end - end ), - ?line receive - {P2, ref, R2} -> - ?line demon_error(R2, badarg), - ?line P2 ! {self(), stop}; - Other2 -> - test_server:fail({rec, Other2}) - end, - - ?line true = test_server:stop_node(N), + P0 = self(), + P2 = spawn( + fun() -> + P0 ! {self(), ref, erlang:monitor(process,P0)}, + receive {P0, stop} -> ok end + end ), + receive + {P2, ref, R2} -> + demon_error(R2, badarg), + P2 ! {self(), stop}; + Other2 -> + ct:fail({rec, Other2}) + end, + + true = test_server:stop_node(N), ok. demon_error(Ref, Reason) -> case catch erlang:demonitor(Ref) of - {'EXIT', {Reason, _}} -> - ok; - Other -> - test_server:fail({err, Other}) + {'EXIT', {Reason, _}} -> + ok; + Other -> + ct:fail({err, Other}) end. %%% No-op cases for demonitor/1 -demon_1(doc) -> - "demonitor/1"; -demon_1(suite) -> []; demon_1(Config) when is_list(Config) -> - ?line true = erlang:demonitor(make_ref()), + true = erlang:demonitor(make_ref()), ok. %%% Cases for demonitor/1 -demon_2(doc) -> - "Cases for demonitor/1"; -demon_2(suite) -> []; demon_2(Config) when is_list(Config) -> - ?line R1 = erlang:monitor(process, self()), - ?line true = erlang:demonitor(R1), + R1 = erlang:monitor(process, self()), + true = erlang:demonitor(R1), %% Extra demonitor - ?line true = erlang:demonitor(R1), - ?line expect_no_msg(), + true = erlang:demonitor(R1), + expect_no_msg(), %% Normal 'DOWN' - ?line P2 = spawn(timer, sleep, [1]), - ?line R2 = erlang:monitor(process, P2), - ?line case expect_down(R2, P2) of - normal -> ?line ok; - noproc -> ?line ok; - BadReason -> ?line ?t:fail({bad_reason, BadReason}) - end, - -%% OTP-5772 -% %% 'DOWN' before demonitor -% ?line P3 = spawn(timer, sleep, [100000]), -% ?line R3 = erlang:monitor(process, P3), -% ?line exit(P3, frop), -% ?line erlang:demonitor(R3), -% ?line expect_down(R3, P3, frop), + P2 = spawn(timer, sleep, [1]), + R2 = erlang:monitor(process, P2), + case expect_down(R2, P2) of + normal -> ok; + noproc -> ok; + BadReason -> ct:fail({bad_reason, BadReason}) + end, + + %% OTP-5772 + % %% 'DOWN' before demonitor + % P3 = spawn(timer, sleep, [100000]), + % R3 = erlang:monitor(process, P3), + % exit(P3, frop), + % erlang:demonitor(R3), + % expect_down(R3, P3, frop), %% Demonitor before 'DOWN' - ?line P4 = spawn(timer, sleep, [100000]), - ?line R4 = erlang:monitor(process, P4), - ?line erlang:demonitor(R4), - ?line exit(P4, frop), - ?line expect_no_msg(), + P4 = spawn(timer, sleep, [100000]), + R4 = erlang:monitor(process, P4), + erlang:demonitor(R4), + exit(P4, frop), + expect_no_msg(), ok. -demon_3(doc) -> - "Distributed case for demonitor/1 (OTP-3499)"; -demon_3(suite) -> []; +%% Distributed case for demonitor/1 (OTP-3499) demon_3(Config) when is_list(Config) -> - ?line {ok, N} = test_server:start_node(hej, slave, []), + {ok, N} = test_server:start_node(hej, slave, []), %% 'DOWN' before demonitor - ?line P2 = spawn(N, timer, sleep, [100000]), - ?line R2 = erlang:monitor(process, P2), - ?line true = test_server:stop_node(N), - ?line true = erlang:demonitor(R2), - ?line expect_down(R2, P2, noconnection), + P2 = spawn(N, timer, sleep, [100000]), + R2 = erlang:monitor(process, P2), + true = test_server:stop_node(N), + true = erlang:demonitor(R2), + expect_down(R2, P2, noconnection), - ?line {ok, N2} = test_server:start_node(hej, slave, []), + {ok, N2} = test_server:start_node(hej, slave, []), %% Demonitor before 'DOWN' - ?line P3 = spawn(N2, timer, sleep, [100000]), - ?line R3 = erlang:monitor(process, P3), - ?line true = erlang:demonitor(R3), - ?line true = test_server:stop_node(N2), - ?line expect_no_msg(), + P3 = spawn(N2, timer, sleep, [100000]), + R3 = erlang:monitor(process, P3), + true = erlang:demonitor(R3), + true = test_server:stop_node(N2), + expect_no_msg(), ok. -demonitor_flush(suite) -> []; -demonitor_flush(doc) -> []; demonitor_flush(Config) when is_list(Config) -> - ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)), - ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])), - ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])), - ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []), - ?line ok = demonitor_flush_test(N), - ?line true = test_server:stop_node(N), - ?line ok = demonitor_flush_test(node()). - + {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)), + {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])), + {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])), + {ok, N} = test_server:start_node(demonitor_flush, slave, []), + ok = demonitor_flush_test(N), + true = test_server:stop_node(N), + ok = demonitor_flush_test(node()). + demonitor_flush_test(Node) -> - ?line P = spawn(Node, timer, sleep, [100000]), - ?line M1 = erlang:monitor(process, P), - ?line M2 = erlang:monitor(process, P), - ?line M3 = erlang:monitor(process, P), - ?line M4 = erlang:monitor(process, P), - ?line true = erlang:demonitor(M1, [flush, flush]), - ?line exit(P, bang), - ?line receive {'DOWN', M2, process, P, bang} -> ok end, - ?line receive after 100 -> ok end, - ?line true = erlang:demonitor(M3, [flush]), - ?line true = erlang:demonitor(M4, []), - ?line receive {'DOWN', M4, process, P, bang} -> ok end, - ?line receive - {'DOWN', M, _, _, _} =DM when M == M1, - M == M3 -> - ?line ?t:fail({unexpected_down_message, DM}) - after 100 -> - ?line ok - end. + P = spawn(Node, timer, sleep, [100000]), + M1 = erlang:monitor(process, P), + M2 = erlang:monitor(process, P), + M3 = erlang:monitor(process, P), + M4 = erlang:monitor(process, P), + true = erlang:demonitor(M1, [flush, flush]), + exit(P, bang), + receive {'DOWN', M2, process, P, bang} -> ok end, + receive after 100 -> ok end, + true = erlang:demonitor(M3, [flush]), + true = erlang:demonitor(M4, []), + receive {'DOWN', M4, process, P, bang} -> ok end, + receive + {'DOWN', M, _, _, _} =DM when M == M1, + M == M3 -> + ct:fail({unexpected_down_message, DM}) + after 100 -> + ok + end. -define(RM_MON_GROUPS, 100). -define(RM_MON_GPROCS, 100). @@ -341,33 +298,33 @@ demonitor_flush_test(Node) -> local_remove_monitor(Config) when is_list(Config) -> Gs = generate(fun () -> start_remove_monitor_group(node()) end, - ?RM_MON_GROUPS), + ?RM_MON_GROUPS), {True, False} = lists:foldl(fun (G, {T, F}) -> - receive - {rm_mon_res, G, {GT, GF}} -> - {T+GT, F+GF} - end - end, - {0, 0}, - Gs), + receive + {rm_mon_res, G, {GT, GF}} -> + {T+GT, F+GF} + end + end, + {0, 0}, + Gs), erlang:display({local_remove_monitor, True, False}), {comment, "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. - + remote_remove_monitor(Config) when is_list(Config) -> - ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []), + {ok, N} = test_server:start_node(demonitor_flush, slave, []), Gs = generate(fun () -> start_remove_monitor_group(node()) end, - ?RM_MON_GROUPS), + ?RM_MON_GROUPS), {True, False} = lists:foldl(fun (G, {T, F}) -> - receive - {rm_mon_res, G, {GT, GF}} -> - {T+GT, F+GF} - end - end, - {0, 0}, - Gs), + receive + {rm_mon_res, G, {GT, GF}} -> + {T+GT, F+GF} + end + end, + {0, 0}, + Gs), erlang:display({remote_remove_monitor, True, False}), - ?line true = test_server:stop_node(N), + true = test_server:stop_node(N), {comment, "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. @@ -375,161 +332,153 @@ start_remove_monitor_group(Node) -> Master = self(), spawn_link( fun () -> - Ms = generate(fun () -> - P = spawn(Node, fun () -> ok end), - erlang:monitor(process, P) - end, ?RM_MON_GPROCS), - Res = lists:foldl(fun (M, {T, F}) -> - case erlang:demonitor(M, [info]) of - true -> - receive - {'DOWN', M, _, _, _} -> - exit(down_msg_found) - after 0 -> - ok - end, - {T+1, F}; - false -> - receive - {'DOWN', M, _, _, _} -> - ok - after 0 -> - exit(no_down_msg_found) - end, - {T, F+1} - end - end, - {0,0}, - Ms), - Master ! {rm_mon_res, self(), Res} + Ms = generate(fun () -> + P = spawn(Node, fun () -> ok end), + erlang:monitor(process, P) + end, ?RM_MON_GPROCS), + Res = lists:foldl(fun (M, {T, F}) -> + case erlang:demonitor(M, [info]) of + true -> + receive + {'DOWN', M, _, _, _} -> + exit(down_msg_found) + after 0 -> + ok + end, + {T+1, F}; + false -> + receive + {'DOWN', M, _, _, _} -> + ok + after 0 -> + exit(no_down_msg_found) + end, + {T, F+1} + end + end, + {0,0}, + Ms), + Master ! {rm_mon_res, self(), Res} end). - - + + %%% Cases for monitor/2 -mon_1(doc) -> - "Cases for monitor/2"; -mon_1(suite) -> []; mon_1(Config) when is_list(Config) -> %% Normal case - ?line P2 = spawn(timer, sleep, [1]), - ?line R2 = erlang:monitor(process, P2), - ?line case expect_down(R2, P2) of - normal -> ?line ok; - noproc -> ?line ok; - BadReason -> ?line ?t:fail({bad_reason, BadReason}) - end, - ?line {P2A,R2A} = spawn_monitor(timer, sleep, [1]), - ?line expect_down(R2A, P2A, normal), + P2 = spawn(timer, sleep, [1]), + R2 = erlang:monitor(process, P2), + case expect_down(R2, P2) of + normal -> ok; + noproc -> ok; + BadReason -> ct:fail({bad_reason, BadReason}) + end, + {P2A,R2A} = spawn_monitor(timer, sleep, [1]), + expect_down(R2A, P2A, normal), %% 'DOWN' with other reason - ?line P3 = spawn(timer, sleep, [100000]), - ?line R3 = erlang:monitor(process, P3), - ?line exit(P3, frop), - ?line expect_down(R3, P3, frop), - ?line {P3A,R3A} = spawn_monitor(timer, sleep, [100000]), - ?line exit(P3A, frop), - ?line expect_down(R3A, P3A, frop), + P3 = spawn(timer, sleep, [100000]), + R3 = erlang:monitor(process, P3), + exit(P3, frop), + expect_down(R3, P3, frop), + {P3A,R3A} = spawn_monitor(timer, sleep, [100000]), + exit(P3A, frop), + expect_down(R3A, P3A, frop), %% Monitor fails because process is dead - ?line R4 = erlang:monitor(process, P3), - ?line expect_down(R4, P3, noproc), + R4 = erlang:monitor(process, P3), + expect_down(R4, P3, noproc), %% Normal case (named process) - ?line P5 = start_jeeves(jeeves), - ?line R5 = erlang:monitor(process, jeeves), - ?line tell_jeeves(P5, stop), - ?line expect_down(R5, {jeeves, node()}, normal), + P5 = start_jeeves(jeeves), + R5 = erlang:monitor(process, jeeves), + tell_jeeves(P5, stop), + expect_down(R5, {jeeves, node()}, normal), %% 'DOWN' with other reason and node explicit activation - ?line P6 = start_jeeves(jeeves), - ?line R6 = erlang:monitor(process, {jeeves, node()}), - ?line tell_jeeves(P6, {exit, frop}), - ?line expect_down(R6, {jeeves, node()}, frop), + P6 = start_jeeves(jeeves), + R6 = erlang:monitor(process, {jeeves, node()}), + tell_jeeves(P6, {exit, frop}), + expect_down(R6, {jeeves, node()}, frop), %% Monitor (named process) fails because process is dead - ?line R7 = erlang:monitor(process, {jeeves, node()}), - ?line expect_down(R7, {jeeves, node()}, noproc), + R7 = erlang:monitor(process, {jeeves, node()}), + expect_down(R7, {jeeves, node()}, noproc), ok. -mon_2(doc) -> - "Distributed cases for monitor/2"; -mon_2(suite) -> []; +%% Distributed cases for monitor/2 mon_2(Config) when is_list(Config) -> - ?line {ok, N1} = test_server:start_node(hej1, slave, []), + {ok, N1} = test_server:start_node(hej1, slave, []), %% Normal case - ?line P2 = spawn(N1, timer, sleep, [4000]), - ?line R2 = erlang:monitor(process, P2), - ?line expect_down(R2, P2, normal), + P2 = spawn(N1, timer, sleep, [4000]), + R2 = erlang:monitor(process, P2), + expect_down(R2, P2, normal), %% 'DOWN' with other reason - ?line P3 = spawn(N1, timer, sleep, [100000]), - ?line R3 = erlang:monitor(process, P3), - ?line exit(P3, frop), - ?line expect_down(R3, P3, frop), + P3 = spawn(N1, timer, sleep, [100000]), + R3 = erlang:monitor(process, P3), + exit(P3, frop), + expect_down(R3, P3, frop), %% Monitor fails because process is dead - ?line R4 = erlang:monitor(process, P3), - ?line expect_down(R4, P3, noproc), + R4 = erlang:monitor(process, P3), + expect_down(R4, P3, noproc), %% Other node goes down - ?line P5 = spawn(N1, timer, sleep, [100000]), - ?line R5 = erlang:monitor(process, P5), + P5 = spawn(N1, timer, sleep, [100000]), + R5 = erlang:monitor(process, P5), - ?line true = test_server:stop_node(N1), + true = test_server:stop_node(N1), - ?line expect_down(R5, P5, noconnection), + expect_down(R5, P5, noconnection), %% Monitor fails because other node is dead - ?line P6 = spawn(N1, timer, sleep, [100000]), - ?line R6 = erlang:monitor(process, P6), - ?line R6_Reason = expect_down(R6, P6), - ?line true = (R6_Reason == noconnection) orelse (R6_Reason == noproc), + P6 = spawn(N1, timer, sleep, [100000]), + R6 = erlang:monitor(process, P6), + R6_Reason = expect_down(R6, P6), + true = (R6_Reason == noconnection) orelse (R6_Reason == noproc), %% Start a new node that can load code in this module - ?line PA = filename:dirname(code:which(?MODULE)), - ?line {ok, N2} = test_server:start_node - (hej2, slave, [{args, "-pa " ++ PA}]), + PA = filename:dirname(code:which(?MODULE)), + {ok, N2} = test_server:start_node + (hej2, slave, [{args, "-pa " ++ PA}]), %% Normal case (named process) - ?line P7 = start_jeeves({jeeves, N2}), - ?line R7 = erlang:monitor(process, {jeeves, N2}), - ?line tell_jeeves(P7, stop), - ?line expect_down(R7, {jeeves, N2}, normal), + P7 = start_jeeves({jeeves, N2}), + R7 = erlang:monitor(process, {jeeves, N2}), + tell_jeeves(P7, stop), + expect_down(R7, {jeeves, N2}, normal), %% 'DOWN' with other reason (named process) - ?line P8 = start_jeeves({jeeves, N2}), - ?line R8 = erlang:monitor(process, {jeeves, N2}), - ?line tell_jeeves(P8, {exit, frop}), - ?line expect_down(R8, {jeeves, N2}, frop), + P8 = start_jeeves({jeeves, N2}), + R8 = erlang:monitor(process, {jeeves, N2}), + tell_jeeves(P8, {exit, frop}), + expect_down(R8, {jeeves, N2}, frop), %% Monitor (named process) fails because process is dead - ?line R9 = erlang:monitor(process, {jeeves, N2}), - ?line expect_down(R9, {jeeves, N2}, noproc), + R9 = erlang:monitor(process, {jeeves, N2}), + expect_down(R9, {jeeves, N2}, noproc), %% Other node goes down (named process) - ?line _P10 = start_jeeves({jeeves, N2}), - ?line R10 = erlang:monitor(process, {jeeves, N2}), + _P10 = start_jeeves({jeeves, N2}), + R10 = erlang:monitor(process, {jeeves, N2}), - ?line true = test_server:stop_node(N2), + true = test_server:stop_node(N2), - ?line expect_down(R10, {jeeves, N2}, noconnection), + expect_down(R10, {jeeves, N2}, noconnection), %% Monitor (named process) fails because other node is dead - ?line R11 = erlang:monitor(process, {jeeves, N2}), - ?line expect_down(R11, {jeeves, N2}, noconnection), + R11 = erlang:monitor(process, {jeeves, N2}), + expect_down(R11, {jeeves, N2}, noconnection), ok. %%% Large exit reason. Crashed first attempt to release R5B. -large_exit(doc) -> - "Large exit reason"; -large_exit(suite) -> []; large_exit(Config) when is_list(Config) -> - ?line f(100), + f(100), ok. f(0) -> @@ -539,23 +488,23 @@ f(N) -> f(N-1). f() -> - ?line S0 = {big, tuple, with, [list, 4563784278]}, - ?line S = {S0, term_to_binary(S0)}, - ?line P = spawn(?MODULE, large_exit_sub, [S]), - ?line R = erlang:monitor(process, P), - ?line P ! hej, + S0 = {big, tuple, with, [list, 4563784278]}, + S = {S0, term_to_binary(S0)}, + P = spawn(?MODULE, large_exit_sub, [S]), + R = erlang:monitor(process, P), + P ! hej, receive - {'DOWN', R, process, P, X} -> - ?line io:format(" -> ~p~n", [X]), - if - X == S -> - ok; - true -> - test_server:fail({X, S}) - end; - Other -> - ?line io:format(" -> ~p~n", [Other]), - exit({answer, Other}) + {'DOWN', R, process, P, X} -> + io:format(" -> ~p~n", [X]), + if + X == S -> + ok; + true -> + ct:fail({X, S}) + end; + Other -> + io:format(" -> ~p~n", [Other]), + exit({answer, Other}) end. large_exit_sub(S) -> @@ -566,105 +515,99 @@ large_exit_sub(S) -> %%% by using erlang:process_info(self(), monitors) %%% and erlang:process_info(self(), monitored_by) -list_cleanup(doc) -> - "Testing of monitor link list cleanup by using " ++ - "erlang:process_info/2"; -list_cleanup(suite) -> []; list_cleanup(Config) when is_list(Config) -> - ?line P0 = self(), - ?line M = node(), - ?line PA = filename:dirname(code:which(?MODULE)), - ?line true = register(master_bertie, self()), + P0 = self(), + M = node(), + PA = filename:dirname(code:which(?MODULE)), + true = register(master_bertie, self()), %% Normal local case, monitor and demonitor - ?line P1 = start_jeeves(jeeves), - ?line {[], []} = monitors(), - ?line expect_jeeves(P1, monitors, {monitors, {[], []}}), - ?line R1a = erlang:monitor(process, P1), - ?line {[{process, P1}], []} = monitors(), - ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), - ?line true = erlang:demonitor(R1a), - ?line expect_no_msg(), - ?line {[], []} = monitors(), - ?line expect_jeeves(P1, monitors, {monitors, {[], []}}), + P1 = start_jeeves(jeeves), + {[], []} = monitors(), + expect_jeeves(P1, monitors, {monitors, {[], []}}), + R1a = erlang:monitor(process, P1), + {[{process, P1}], []} = monitors(), + expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), + true = erlang:demonitor(R1a), + expect_no_msg(), + {[], []} = monitors(), + expect_jeeves(P1, monitors, {monitors, {[], []}}), %% Remonitor named and try again, now exiting the monitored process - ?line R1b = erlang:monitor(process, jeeves), - ?line {[{process, {jeeves, M}}], []} = monitors(), - ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), - ?line tell_jeeves(P1, stop), - ?line expect_down(R1b, {jeeves, node()}, normal), - ?line {[], []} = monitors(), + R1b = erlang:monitor(process, jeeves), + {[{process, {jeeves, M}}], []} = monitors(), + expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), + tell_jeeves(P1, stop), + expect_down(R1b, {jeeves, node()}, normal), + {[], []} = monitors(), %% Slightly weird local case - the monitoring process crashes - ?line P2 = start_jeeves(jeeves), - ?line {[], []} = monitors(), - ?line expect_jeeves(P2, monitors, {monitors, {[], []}}), - ?line {monitor_process, _R2} = - ask_jeeves(P2, {monitor_process, master_bertie}), - ?line {[], [P2]} = monitors(), - ?line expect_jeeves(P2, monitors, - {monitors, {[{process, {master_bertie, node()}}], []}}), - ?line tell_jeeves(P2, {exit, frop}), + P2 = start_jeeves(jeeves), + {[], []} = monitors(), + expect_jeeves(P2, monitors, {monitors, {[], []}}), + {monitor_process, _R2} = + ask_jeeves(P2, {monitor_process, master_bertie}), + {[], [P2]} = monitors(), + expect_jeeves(P2, monitors, + {monitors, {[{process, {master_bertie, node()}}], []}}), + tell_jeeves(P2, {exit, frop}), timer:sleep(2000), - ?line {[], []} = monitors(), + {[], []} = monitors(), %% Start a new node that can load code in this module - ?line {ok, J} = test_server:start_node - (jeeves, slave, [{args, "-pa " ++ PA}]), + {ok, J} = test_server:start_node + (jeeves, slave, [{args, "-pa " ++ PA}]), %% Normal remote case, monitor and demonitor - ?line P3 = start_jeeves({jeeves, J}), - ?line {[], []} = monitors(), - ?line expect_jeeves(P3, monitors, {monitors, {[], []}}), - ?line R3a = erlang:monitor(process, P3), - ?line {[{process, P3}], []} = monitors(), - ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), - ?line true = erlang:demonitor(R3a), - ?line expect_no_msg(), - ?line {[], []} = monitors(), - ?line expect_jeeves(P3, monitors, {monitors, {[], []}}), + P3 = start_jeeves({jeeves, J}), + {[], []} = monitors(), + expect_jeeves(P3, monitors, {monitors, {[], []}}), + R3a = erlang:monitor(process, P3), + {[{process, P3}], []} = monitors(), + expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), + true = erlang:demonitor(R3a), + expect_no_msg(), + {[], []} = monitors(), + expect_jeeves(P3, monitors, {monitors, {[], []}}), %% Remonitor named and try again, now exiting the monitored process - ?line R3b = erlang:monitor(process, {jeeves, J}), - ?line {[{process, {jeeves, J}}], []} = monitors(), - ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), - ?line tell_jeeves(P3, stop), - ?line expect_down(R3b, {jeeves, J}, normal), - ?line {[], []} = monitors(), + R3b = erlang:monitor(process, {jeeves, J}), + {[{process, {jeeves, J}}], []} = monitors(), + expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), + tell_jeeves(P3, stop), + expect_down(R3b, {jeeves, J}, normal), + {[], []} = monitors(), %% Slightly weird remote case - the monitoring process crashes - ?line P4 = start_jeeves({jeeves, J}), - ?line {[], []} = monitors(), - ?line expect_jeeves(P4, monitors, {monitors, {[], []}}), - ?line {monitor_process, _R4} = - ask_jeeves(P4, {monitor_process, {master_bertie, M}}), - ?line {[], [P4]} = monitors(), - ?line expect_jeeves(P4, monitors, - {monitors, {[{process, {master_bertie, M}}], []}} ), - ?line tell_jeeves(P4, {exit, frop}), + P4 = start_jeeves({jeeves, J}), + {[], []} = monitors(), + expect_jeeves(P4, monitors, {monitors, {[], []}}), + {monitor_process, _R4} = + ask_jeeves(P4, {monitor_process, {master_bertie, M}}), + {[], [P4]} = monitors(), + expect_jeeves(P4, monitors, + {monitors, {[{process, {master_bertie, M}}], []}} ), + tell_jeeves(P4, {exit, frop}), timer:sleep(2000), - ?line {[], []} = monitors(), - + {[], []} = monitors(), + %% Now, the monitoring remote node crashes - ?line P5 = start_jeeves({jeeves, J}), - ?line {[], []} = monitors(), - ?line expect_jeeves(P5, monitors, {monitors, {[], []}}), - ?line {monitor_process, _R5} = - ask_jeeves(P5, {monitor_process, P0}), - ?line {[], [P5]} = monitors(), - ?line expect_jeeves(P5, monitors, - {monitors, {[{process, P0}], []}} ), - ?line test_server:stop_node(J), + P5 = start_jeeves({jeeves, J}), + {[], []} = monitors(), + expect_jeeves(P5, monitors, {monitors, {[], []}}), + {monitor_process, _R5} = + ask_jeeves(P5, {monitor_process, P0}), + {[], [P5]} = monitors(), + expect_jeeves(P5, monitors, + {monitors, {[{process, P0}], []}} ), + test_server:stop_node(J), timer:sleep(4000), - ?line {[], []} = monitors(), - - ?line true = unregister(master_bertie), + {[], []} = monitors(), + + true = unregister(master_bertie), ok. - + %%% Mixed internal and external monitors -mixer(doc) -> - "Test mixing of internal and external monitors."; mixer(Config) when is_list(Config) -> PA = filename:dirname(code:which(?MODULE)), NN = [j0,j1,j2], @@ -748,115 +691,112 @@ mixer(Config) when is_list(Config) -> [test_server:stop_node(K) || K <- NL0], ok. -named_down(doc) -> ["Test that DOWN message for a named monitor isn't" - " delivered until name has been unregistered"]; -named_down(suite) -> []; +%% Test that DOWN message for a named monitor isn't +%% delivered until name has been unregistered named_down(Config) when is_list(Config) -> - ?line Name = list_to_atom(atom_to_list(?MODULE) - ++ "-named_down-" - ++ integer_to_list(erlang:system_time(seconds)) - ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), - ?line Prio = process_flag(priority,high), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-named_down-" + ++ integer_to_list(erlang:system_time(seconds)) + ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), + Prio = process_flag(priority,high), %% Spawn a bunch of high prio cpu bound processes to prevent %% normal prio processes from terminating during the next %% 500 ms... - ?line Self = self(), - ?line spawn_opt(fun () -> - WFun = fun - (F, hej) -> F(F, hopp); - (F, hopp) -> F(F, hej) - end, - NoSchedulers = erlang:system_info(schedulers_online), - lists:foreach(fun (_) -> - spawn_opt(fun () -> - WFun(WFun, - hej) - end, - [{priority,high}, - link]) - end, - lists:seq(1, NoSchedulers)), - receive after 500 -> ok end, - unlink(Self), - exit(bang) - end, - [{priority,high}, link]), - ?line NamedProc = spawn_link(fun () -> - receive after infinity -> ok end - end), - ?line true = register(Name, NamedProc), - ?line unlink(NamedProc), - ?line exit(NamedProc, bang), - ?line Mon = erlang:monitor(process, Name), - ?line receive {'DOWN',Mon, _, _, _} -> ok end, - ?line true = register(Name, self()), - ?line true = unregister(Name), - ?line process_flag(priority,Prio), + Self = self(), + spawn_opt(fun () -> + WFun = fun + (F, hej) -> F(F, hopp); +(F, hopp) -> F(F, hej) + end, + NoSchedulers = erlang:system_info(schedulers_online), + lists:foreach(fun (_) -> + spawn_opt(fun () -> + WFun(WFun, + hej) + end, + [{priority,high}, + link]) + end, + lists:seq(1, NoSchedulers)), + receive after 500 -> ok end, + unlink(Self), + exit(bang) + end, + [{priority,high}, link]), + NamedProc = spawn_link(fun () -> + receive after infinity -> ok end + end), + true = register(Name, NamedProc), + unlink(NamedProc), + exit(NamedProc, bang), + Mon = erlang:monitor(process, Name), + receive {'DOWN',Mon, _, _, _} -> ok end, + true = register(Name, self()), + true = unregister(Name), + process_flag(priority,Prio), ok. -otp_5827(doc) -> []; -otp_5827(suite) -> []; otp_5827(Config) when is_list(Config) -> %% Make a pid with the same nodename but with another creation - ?line [CreEnd | RPTail] - = lists:reverse(binary_to_list(term_to_binary(self()))), - ?line NewCreEnd = case CreEnd of - 0 -> 1; - 1 -> 2; - _ -> CreEnd - 1 - end, - ?line OtherCreationPid - = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))), + [CreEnd | RPTail] + = lists:reverse(binary_to_list(term_to_binary(self()))), + NewCreEnd = case CreEnd of + 0 -> 1; + 1 -> 2; + _ -> CreEnd - 1 + end, + OtherCreationPid + = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))), %% If the bug is present erlang:monitor(process, OtherCreationPid) %% will hang... - ?line Parent = self(), - ?line Ok = make_ref(), - ?line spawn(fun () -> - Mon = erlang:monitor(process, OtherCreationPid), - % Should get the DOWN message right away - receive - {'DOWN', Mon, process, OtherCreationPid, noproc} -> - Parent ! Ok - end - end), - ?line receive - Ok -> - ?line ok - after 1000 -> - ?line ?t:fail("erlang:monitor/2 hangs") - end. + Parent = self(), + Ok = make_ref(), + spawn(fun () -> + Mon = erlang:monitor(process, OtherCreationPid), + % Should get the DOWN message right away + receive + {'DOWN', Mon, process, OtherCreationPid, noproc} -> + Parent ! Ok + end + end), + receive + Ok -> + ok + after 1000 -> + ct:fail("erlang:monitor/2 hangs") + end. monitor_time_offset(Config) when is_list(Config) -> {ok, Node} = start_node(Config, "+C single_time_warp"), Me = self(), PMs = lists:map(fun (_) -> - Pid = spawn(Node, - fun () -> - check_monitor_time_offset(Me) - end), - {Pid, erlang:monitor(process, Pid)} - end, - lists:seq(1, 100)), + Pid = spawn(Node, + fun () -> + check_monitor_time_offset(Me) + end), + {Pid, erlang:monitor(process, Pid)} + end, + lists:seq(1, 100)), lists:foreach(fun ({P, _M}) -> - P ! check_no_change_message - end, PMs), + P ! check_no_change_message + end, PMs), lists:foreach(fun ({P, M}) -> - receive - {no_change_message_received, P} -> - ok; - {'DOWN', M, process, P, Reason} -> - ?t:fail(Reason) - end - end, PMs), + receive + {no_change_message_received, P} -> + ok; + {'DOWN', M, process, P, Reason} -> + ct:fail(Reason) + end + end, PMs), preliminary = rpc:call(Node, erlang, system_flag, [time_offset, finalize]), lists:foreach(fun ({P, M}) -> - receive - {change_messages_received, P} -> - erlang:demonitor(M, [flush]); - {'DOWN', M, process, P, Reason} -> - ?t:fail(Reason) - end - end, PMs), + receive + {change_messages_received, P} -> + erlang:demonitor(M, [flush]); + {'DOWN', M, process, P, Reason} -> + ct:fail(Reason) + end + end, PMs), stop_node(Node), ok. @@ -867,42 +807,42 @@ check_monitor_time_offset(Leader) -> Mon4 = erlang:monitor(time_offset, clock_service), erlang:demonitor(Mon2, [flush]), - + Mon5 = erlang:monitor(time_offset, clock_service), Mon6 = erlang:monitor(time_offset, clock_service), Mon7 = erlang:monitor(time_offset, clock_service), receive check_no_change_message -> ok end, receive - {'CHANGE', _, time_offset, clock_service, _} -> - exit(unexpected_change_message_received) + {'CHANGE', _, time_offset, clock_service, _} -> + exit(unexpected_change_message_received) after 0 -> - Leader ! {no_change_message_received, self()} + Leader ! {no_change_message_received, self()} end, receive after 100 -> ok end, erlang:demonitor(Mon4, [flush]), receive - {'CHANGE', Mon3, time_offset, clock_service, _} -> - ok + {'CHANGE', Mon3, time_offset, clock_service, _} -> + ok end, receive - {'CHANGE', Mon6, time_offset, clock_service, _} -> - ok + {'CHANGE', Mon6, time_offset, clock_service, _} -> + ok end, erlang:demonitor(Mon5, [flush]), receive - {'CHANGE', Mon7, time_offset, clock_service, _} -> - ok + {'CHANGE', Mon7, time_offset, clock_service, _} -> + ok end, receive - {'CHANGE', Mon1, time_offset, clock_service, _} -> - ok + {'CHANGE', Mon1, time_offset, clock_service, _} -> + ok end, receive - {'CHANGE', _, time_offset, clock_service, _} -> - exit(unexpected_change_message_received) + {'CHANGE', _, time_offset, clock_service, _} -> + exit(unexpected_change_message_received) after 1000 -> - ok + ok end, Leader ! {change_messages_received, self()}. @@ -916,17 +856,17 @@ wait_for_m(Monitors, MonitoredBy, N) -> {monitors,M0} = process_info(self(),monitors), {monitored_by,MB0} = process_info(self(),monitored_by), case lists:sort(M0) of - Monitors -> - case lists:sort(MB0) of - MonitoredBy -> - ok; - _ -> - receive after 100 -> ok end, - wait_for_m(Monitors,MonitoredBy,N-1) - end; - _ -> - receive after 100 -> ok end, - wait_for_m(Monitors,MonitoredBy,N-1) + Monitors -> + case lists:sort(MB0) of + MonitoredBy -> + ok; + _ -> + receive after 100 -> ok end, + wait_for_m(Monitors,MonitoredBy,N-1) + end; + _ -> + receive after 100 -> ok end, + wait_for_m(Monitors,MonitoredBy,N-1) end. % All permutations of a list... @@ -950,32 +890,32 @@ jeeves(Parent, Name, Ref) when is_pid(Parent), (is_atom(Name) or (Name =:= [])), is_reference(Ref) -> %%io:format("monitor_SUITE:jeeves(~p, ~p)~n", [Parent, Name]), case Name of - Atom when is_atom(Atom) -> - register(Name, self()); - [] -> - ok + Atom when is_atom(Atom) -> + register(Name, self()); + [] -> + ok end, Parent ! {self(), Ref}, jeeves_loop(Parent). jeeves_loop(Parent) -> receive - {Parent, monitors} -> - Parent ! {self(), {monitors, monitors()}}, - jeeves_loop(Parent); - {Parent, {monitor_process, P}} -> - Parent ! {self(), {monitor_process, - catch erlang:monitor(process, P) }}, - jeeves_loop(Parent); - {Parent, {demonitor, Ref}} -> - Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}}, - jeeves_loop(Parent); - {Parent, stop} -> - ok; - {Parent, {exit, Reason}} -> - exit(Reason); - Other -> - io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other]) + {Parent, monitors} -> + Parent ! {self(), {monitors, monitors()}}, + jeeves_loop(Parent); + {Parent, {monitor_process, P}} -> + Parent ! {self(), {monitor_process, + catch erlang:monitor(process, P) }}, + jeeves_loop(Parent); + {Parent, {demonitor, Ref}} -> + Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}}, + jeeves_loop(Parent); + {Parent, stop} -> + ok; + {Parent, {exit, Reason}} -> + exit(Reason); + Other -> + io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other]) end. @@ -985,10 +925,10 @@ start_jeeves({Name, Node}) Ref = make_ref(), Pid = spawn(Node, fun() -> jeeves(Parent, Name, Ref) end), receive - {Pid, Ref} -> - ok; - Other -> - test_server:fail({rec, Other}) + {Pid, Ref} -> + ok; + Other -> + ct:fail({rec, Other}) end, Pid; start_jeeves(Name) when is_atom(Name) -> @@ -1002,20 +942,20 @@ tell_jeeves(Pid, What) when is_pid(Pid) -> ask_jeeves(Pid, Request) when is_pid(Pid) -> Pid ! {self(), Request}, receive - {Pid, Response} -> - Response; - Other -> - test_server:fail({rec, Other}) + {Pid, Response} -> + Response; + Other -> + ct:fail({rec, Other}) end. expect_jeeves(Pid, Request, Response) when is_pid(Pid) -> Pid ! {self(), Request}, receive - {Pid, Response} -> - ok; - Other -> - test_server:fail({rec, Other}) + {Pid, Response} -> + ok; + Other -> + ct:fail({rec, Other}) end. @@ -1036,20 +976,20 @@ start_node(Config) -> start_node(Config, ""). start_node(Config, Args) -> - TestCase = ?config(testcase, Config), + TestCase = proplists:get_value(testcase, Config), PA = filename:dirname(code:which(?MODULE)), ESTime = erlang:monotonic_time(1) + erlang:time_offset(1), Unique = erlang:unique_integer([positive]), Name = list_to_atom(atom_to_list(?MODULE) - ++ "-" - ++ atom_to_list(TestCase) - ++ "-" - ++ integer_to_list(ESTime) - ++ "-" - ++ integer_to_list(Unique)), + ++ "-" + ++ atom_to_list(TestCase) + ++ "-" + ++ integer_to_list(ESTime) + ++ "-" + ++ integer_to_list(Unique)), test_server:start_node(Name, - slave, - [{args, "-pa " ++ PA ++ " " ++ Args}]). + slave, + [{args, "-pa " ++ PA ++ " " ++ Args}]). stop_node(Node) -> test_server:stop_node(Node). |