1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1996-2013. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: -module(gen_server_SUITE). 20: 21: -include_lib("test_server/include/test_server.hrl"). 22: -include_lib("kernel/include/inet.hrl"). 23: 24: -export([init_per_testcase/2, end_per_testcase/2]). 25: 26: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 27: init_per_group/2,end_per_group/2]). 28: -export([start/1, crash/1, call/1, cast/1, cast_fast/1, 29: info/1, abcast/1, multicall/1, multicall_down/1, 30: call_remote1/1, call_remote2/1, call_remote3/1, 31: call_remote_n1/1, call_remote_n2/1, call_remote_n3/1, spec_init/1, 32: spec_init_local_registered_parent/1, 33: spec_init_global_registered_parent/1, 34: otp_5854/1, hibernate/1, otp_7669/1, call_format_status/1, 35: error_format_status/1, get_state/1, replace_state/1, call_with_huge_message_queue/1 36: ]). 37: 38: % spawn export 39: -export([spec_init_local/2, spec_init_global/2, spec_init_via/2, 40: spec_init_default_timeout/2, spec_init_global_default_timeout/2, 41: spec_init_anonymous/1, 42: spec_init_anonymous_default_timeout/1, 43: spec_init_not_proc_lib/1, cast_fast_messup/0]). 44: 45: 46: % The gen_server behaviour 47: -export([init/1, handle_call/3, handle_cast/2, 48: handle_info/2, terminate/2, format_status/2]). 49: 50: suite() -> [{ct_hooks,[ts_install_cth]}]. 51: 52: all() -> 53: [start, crash, call, cast, cast_fast, info, abcast, 54: multicall, multicall_down, call_remote1, call_remote2, 55: call_remote3, call_remote_n1, call_remote_n2, 56: call_remote_n3, spec_init, 57: spec_init_local_registered_parent, 58: spec_init_global_registered_parent, otp_5854, hibernate, 59: otp_7669, call_format_status, error_format_status, 60: get_state, replace_state, 61: call_with_huge_message_queue]. 62: 63: groups() -> 64: []. 65: 66: init_per_suite(Config) -> 67: Config. 68: 69: end_per_suite(_Config) -> 70: ok. 71: 72: init_per_group(_GroupName, Config) -> 73: Config. 74: 75: end_per_group(_GroupName, Config) -> 76: Config. 77: 78: 79: -define(default_timeout, ?t:minutes(1)). 80: 81: init_per_testcase(Case, Config) when Case == call_remote1; 82: Case == call_remote2; 83: Case == call_remote3; 84: Case == call_remote_n1; 85: Case == call_remote_n2; 86: Case == call_remote_n3 -> 87: {ok,N} = start_node(hubba), 88: ?line Dog = ?t:timetrap(?default_timeout), 89: [{node,N},{watchdog, Dog} | Config]; 90: init_per_testcase(_Case, Config) -> 91: ?line Dog = ?t:timetrap(?default_timeout), 92: [{watchdog, Dog} | Config]. 93: end_per_testcase(_Case, Config) -> 94: case proplists:get_value(node, Config) of 95: undefined -> 96: ok; 97: N -> 98: test_server:stop_node(N) 99: end, 100: Dog = ?config(watchdog, Config), 101: test_server:timetrap_cancel(Dog), 102: ok. 103: 104: 105: %% -------------------------------------- 106: %% Start and stop a gen_server. 107: %% -------------------------------------- 108: 109: start(suite) -> []; 110: start(Config) when is_list(Config) -> 111: OldFl = process_flag(trap_exit, true), 112: 113: %% anonymous 114: ?line {ok, Pid0} = gen_server:start(gen_server_SUITE, [], []), 115: ?line ok = gen_server:call(Pid0, started_p), 116: ?line ok = gen_server:call(Pid0, stop), 117: ?line busy_wait_for_process(Pid0,600), 118: ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid0, started_p, 1)), 119: 120: %% anonymous with timeout 121: ?line {ok, Pid00} = gen_server:start(gen_server_SUITE, [], 122: [{timeout,1000}]), 123: ?line ok = gen_server:call(Pid00, started_p), 124: ?line ok = gen_server:call(Pid00, stop), 125: ?line {error, timeout} = gen_server:start(gen_server_SUITE, sleep, 126: [{timeout,100}]), 127: 128: %% anonymous with ignore 129: ?line ignore = gen_server:start(gen_server_SUITE, ignore, []), 130: 131: %% anonymous with stop 132: ?line {error, stopped} = gen_server:start(gen_server_SUITE, stop, []), 133: 134: %% anonymous linked 135: ?line {ok, Pid1} = 136: gen_server:start_link(gen_server_SUITE, [], []), 137: ?line ok = gen_server:call(Pid1, started_p), 138: ?line ok = gen_server:call(Pid1, stop), 139: ?line receive 140: {'EXIT', Pid1, stopped} -> 141: ok 142: after 5000 -> 143: test_server:fail(not_stopped) 144: end, 145: 146: %% local register 147: ?line {ok, Pid2} = 148: gen_server:start({local, my_test_name}, 149: gen_server_SUITE, [], []), 150: ?line ok = gen_server:call(my_test_name, started_p), 151: ?line {error, {already_started, Pid2}} = 152: gen_server:start({local, my_test_name}, 153: gen_server_SUITE, [], []), 154: ?line ok = gen_server:call(my_test_name, stop), 155: 156: ?line busy_wait_for_process(Pid2,600), 157: 158: ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid2, started_p, 10)), 159: 160: %% local register linked 161: ?line {ok, Pid3} = 162: gen_server:start_link({local, my_test_name}, 163: gen_server_SUITE, [], []), 164: ?line ok = gen_server:call(my_test_name, started_p), 165: ?line {error, {already_started, Pid3}} = 166: gen_server:start({local, my_test_name}, 167: gen_server_SUITE, [], []), 168: ?line ok = gen_server:call(my_test_name, stop), 169: ?line receive 170: {'EXIT', Pid3, stopped} -> 171: ok 172: after 5000 -> 173: test_server:fail(not_stopped) 174: end, 175: 176: %% global register 177: ?line {ok, Pid4} = 178: gen_server:start({global, my_test_name}, 179: gen_server_SUITE, [], []), 180: ?line ok = gen_server:call({global, my_test_name}, started_p), 181: ?line {error, {already_started, Pid4}} = 182: gen_server:start({global, my_test_name}, 183: gen_server_SUITE, [], []), 184: ?line ok = gen_server:call({global, my_test_name}, stop), 185: test_server:sleep(1), 186: ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid4, started_p, 10)), 187: 188: %% global register linked 189: ?line {ok, Pid5} = 190: gen_server:start_link({global, my_test_name}, 191: gen_server_SUITE, [], []), 192: ?line ok = gen_server:call({global, my_test_name}, started_p), 193: ?line {error, {already_started, Pid5}} = 194: gen_server:start({global, my_test_name}, 195: gen_server_SUITE, [], []), 196: ?line ok = gen_server:call({global, my_test_name}, stop), 197: ?line receive 198: {'EXIT', Pid5, stopped} -> 199: ok 200: after 5000 -> 201: test_server:fail(not_stopped) 202: end, 203: 204: %% via register 205: ?line dummy_via:reset(), 206: ?line {ok, Pid6} = 207: gen_server:start({via, dummy_via, my_test_name}, 208: gen_server_SUITE, [], []), 209: ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p), 210: ?line {error, {already_started, Pid6}} = 211: gen_server:start({via, dummy_via, my_test_name}, 212: gen_server_SUITE, [], []), 213: ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop), 214: test_server:sleep(1), 215: ?line {'EXIT', {noproc,_}} = (catch gen_server:call(Pid6, started_p, 10)), 216: 217: %% via register linked 218: ?line dummy_via:reset(), 219: ?line {ok, Pid7} = 220: gen_server:start_link({via, dummy_via, my_test_name}, 221: gen_server_SUITE, [], []), 222: ?line ok = gen_server:call({via, dummy_via, my_test_name}, started_p), 223: ?line {error, {already_started, Pid7}} = 224: gen_server:start({via, dummy_via, my_test_name}, 225: gen_server_SUITE, [], []), 226: ?line ok = gen_server:call({via, dummy_via, my_test_name}, stop), 227: ?line receive 228: {'EXIT', Pid7, stopped} -> 229: ok 230: after 5000 -> 231: test_server:fail(not_stopped) 232: end, 233: test_server:messages_get(), 234: 235: process_flag(trap_exit, OldFl), 236: ok. 237: 238: crash(Config) when is_list(Config) -> 239: ?line error_logger_forwarder:register(), 240: 241: process_flag(trap_exit, true), 242: 243: %% This crash should not generate a crash report. 244: ?line {ok,Pid0} = gen_server:start_link(?MODULE, [], []), 245: ?line {'EXIT',{{shutdown,reason},_}} = 246: (catch gen_server:call(Pid0, shutdown_reason)), 247: receive {'EXIT',Pid0,{shutdown,reason}} -> ok end, 248: 249: %% This crash should not generate a crash report. 250: ?line {ok,Pid1} = gen_server:start_link(?MODULE, {state,state1}, []), 251: ?line {'EXIT',{{shutdown,stop_reason},_}} = 252: (catch gen_server:call(Pid1, stop_shutdown_reason)), 253: receive {'EXIT',Pid1,{shutdown,stop_reason}} -> ok end, 254: 255: %% This crash should not generate a crash report. 256: ?line {ok,Pid2} = gen_server:start_link(?MODULE, [], []), 257: ?line {'EXIT',{shutdown,_}} = 258: (catch gen_server:call(Pid2, exit_shutdown)), 259: receive {'EXIT',Pid2,shutdown} -> ok end, 260: 261: %% This crash should not generate a crash report. 262: ?line {ok,Pid3} = gen_server:start_link(?MODULE, {state,state3}, []), 263: ?line {'EXIT',{shutdown,_}} = 264: (catch gen_server:call(Pid3, stop_shutdown)), 265: receive {'EXIT',Pid3,shutdown} -> ok end, 266: 267: process_flag(trap_exit, false), 268: 269: %% This crash should generate a crash report and a report 270: %% from gen_server. 271: ?line {ok,Pid4} = gen_server:start(?MODULE, {state,state4}, []), 272: ?line {'EXIT',{crashed,_}} = (catch gen_server:call(Pid4, crash)), 273: receive 274: {error,_GroupLeader4,{Pid4, 275: "** Generic server"++_, 276: [Pid4,crash,state4,crashed]}} -> 277: ok; 278: Other4a -> 279: ?line io:format("Unexpected: ~p", [Other4a]), 280: ?line ?t:fail() 281: end, 282: receive 283: {error_report,_,{Pid4,crash_report,[List4|_]}} -> 284: {exit,crashed,_} = proplists:get_value(error_info, List4), 285: Pid4 = proplists:get_value(pid, List4); 286: Other4 -> 287: ?line io:format("Unexpected: ~p", [Other4]), 288: ?line ?t:fail() 289: end, 290: 291: receive 292: Any -> 293: ?line io:format("Unexpected: ~p", [Any]), 294: ?line ?t:fail() 295: after 500 -> 296: ok 297: end, 298: 299: ok. 300: 301: %% -------------------------------------- 302: %% Test gen_server:call and handle_call. 303: %% Test all different return values from 304: %% handle_call. 305: %% -------------------------------------- 306: 307: call(suite) -> []; 308: call(Config) when is_list(Config) -> 309: OldFl = process_flag(trap_exit, true), 310: 311: ?line {ok, _Pid} = 312: gen_server:start_link({local, my_test_name}, 313: gen_server_SUITE, [], []), 314: 315: ?line ok = gen_server:call(my_test_name, started_p), 316: ?line delayed = gen_server:call(my_test_name, {delayed_answer,1}), 317: 318: %% two requests within a specified time. 319: ?line ok = gen_server:call(my_test_name, {call_within, 1000}), 320: test_server:sleep(500), 321: ?line ok = gen_server:call(my_test_name, next_call), 322: ?line ok = gen_server:call(my_test_name, {call_within, 1000}), 323: test_server:sleep(1500), 324: ?line false = gen_server:call(my_test_name, next_call), 325: 326: %% timeout call. 327: ?line delayed = gen_server:call(my_test_name, {delayed_answer,1}, 30), 328: ?line {'EXIT',{timeout,_}} = 329: (catch gen_server:call(my_test_name, {delayed_answer,30}, 1)), 330: 331: %% bad return value in the gen_server loop from handle_call. 332: ?line {'EXIT',{{bad_return_value, badreturn},_}} = 333: (catch gen_server:call(my_test_name, badreturn)), 334: 335: process_flag(trap_exit, OldFl), 336: ok. 337: 338: %% -------------------------------------- 339: %% Test call to nonexisting processes on remote nodes 340: %% -------------------------------------- 341: 342: start_node(Name) -> 343: ?line Pa = filename:dirname(code:which(?MODULE)), 344: ?line N = test_server:start_node(Name, slave, [{args, " -pa " ++ Pa}]), 345: %% After starting a slave, it takes a little while until global knows 346: %% about it, even if nodes() includes it, so we make sure that global 347: %% knows about it before registering something on all nodes. 348: global:sync(), 349: N. 350: 351: call_remote1(suite) -> []; 352: call_remote1(Config) when is_list(Config) -> 353: N = hubba, 354: ?line Node = proplists:get_value(node,Config), 355: ?line {ok, Pid} = rpc:call(Node, gen_server, start, 356: [{global, N}, ?MODULE, [], []]), 357: ?line ok = (catch gen_server:call({global, N}, started_p, infinity)), 358: ?line exit(Pid, boom), 359: ?line {'EXIT', {Reason, _}} = (catch gen_server:call({global, N}, 360: started_p, infinity)), 361: ?line true = (Reason == noproc) orelse (Reason == boom), 362: ok. 363: 364: call_remote2(suite) -> []; 365: call_remote2(Config) when is_list(Config) -> 366: ?line N = hubba, 367: ?line Node = proplists:get_value(node,Config), 368: 369: ?line {ok, Pid} = rpc:call(Node, gen_server, start, 370: [{global, N}, ?MODULE, [], []]), 371: ?line ok = (catch gen_server:call(Pid, started_p, infinity)), 372: ?line exit(Pid, boom), 373: ?line {'EXIT', {Reason, _}} = (catch gen_server:call(Pid, 374: started_p, infinity)), 375: ?line true = (Reason == noproc) orelse (Reason == boom), 376: ok. 377: 378: call_remote3(suite) -> []; 379: call_remote3(Config) when is_list(Config) -> 380: ?line Node = proplists:get_value(node,Config), 381: 382: ?line {ok, Pid} = rpc:call(Node, gen_server, start, 383: [{local, piller}, ?MODULE, [], []]), 384: ?line ok = (catch gen_server:call({piller, Node}, started_p, infinity)), 385: ?line exit(Pid, boom), 386: ?line {'EXIT', {Reason, _}} = (catch gen_server:call({piller, Node}, 387: started_p, infinity)), 388: ?line true = (Reason == noproc) orelse (Reason == boom), 389: ok. 390: 391: %% -------------------------------------- 392: %% Test call to nonexisting node 393: %% -------------------------------------- 394: 395: call_remote_n1(suite) -> []; 396: call_remote_n1(Config) when is_list(Config) -> 397: ?line N = hubba, 398: ?line Node = proplists:get_value(node,Config), 399: ?line {ok, _Pid} = rpc:call(Node, gen_server, start, 400: [{global, N}, ?MODULE, [], []]), 401: ?line _ = test_server:stop_node(Node), 402: ?line {'EXIT', {noproc, _}} = 403: (catch gen_server:call({global, N}, started_p, infinity)), 404: 405: ok. 406: 407: call_remote_n2(suite) -> []; 408: call_remote_n2(Config) when is_list(Config) -> 409: ?line N = hubba, 410: ?line Node = proplists:get_value(node,Config), 411: 412: ?line {ok, Pid} = rpc:call(Node, gen_server, start, 413: [{global, N}, ?MODULE, [], []]), 414: ?line _ = test_server:stop_node(Node), 415: ?line {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call(Pid, 416: started_p, infinity)), 417: 418: ok. 419: 420: call_remote_n3(suite) -> []; 421: call_remote_n3(Config) when is_list(Config) -> 422: ?line Node = proplists:get_value(node,Config), 423: 424: ?line {ok, _Pid} = rpc:call(Node, gen_server, start, 425: [{local, piller}, ?MODULE, [], []]), 426: ?line _ = test_server:stop_node(Node), 427: ?line {'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call({piller, Node}, 428: started_p, infinity)), 429: 430: ok. 431: 432: %% -------------------------------------- 433: %% Test gen_server:cast and handle_cast. 434: %% Test all different return values from 435: %% handle_cast. 436: %% -------------------------------------- 437: 438: cast(suite) -> []; 439: cast(Config) when is_list(Config) -> 440: ?line {ok, Pid} = 441: gen_server:start({local, my_test_name}, 442: gen_server_SUITE, [], []), 443: 444: ?line ok = gen_server:call(my_test_name, started_p), 445: 446: ?line ok = gen_server:cast(my_test_name, {self(),handle_cast}), 447: ?line receive 448: {Pid, handled_cast} -> 449: ok 450: after 1000 -> 451: test_server:fail(handle_cast) 452: end, 453: 454: ?line ok = gen_server:cast(my_test_name, {self(),delayed_cast,1}), 455: ?line receive 456: {Pid, delayed} -> 457: ok 458: after 1000 -> 459: test_server:fail(delayed_cast) 460: end, 461: 462: ?line ok = gen_server:cast(my_test_name, {self(),stop}), 463: ?line receive 464: {Pid, stopped} -> 465: ok 466: after 1000 -> 467: test_server:fail(stop) 468: end, 469: ok. 470: 471: cast_fast(suite) -> []; 472: cast_fast(doc) -> ["Test that cast really return immediately"]; 473: cast_fast(Config) when is_list(Config) -> 474: ?line {ok,Node} = start_node(hubba), 475: ?line {_,"@"++Host} = lists:splitwith(fun ($@) -> false; (_) -> true end, 476: atom_to_list(Node)), 477: ?line FalseNode = list_to_atom("hopp@"++Host), 478: ?line true = rpc:cast(Node, ?MODULE, cast_fast_messup, []), 479: % ?line io:format("Nodes ~p~n", [rpc:call(N, ?MODULE, cast_fast_messup, [])]), 480: ?line test_server:sleep(1000), 481: ?line [Node] = nodes(), 482: ?line {Time,ok} = test_server:timecall(gen_server, cast, 483: [{hopp,FalseNode},hopp]), 484: ?line true = test_server:stop_node(Node), 485: ?line if Time > 1.0 -> % Default listen timeout is about 7.0 s 486: test_server:fail(hanging_cast); 487: true -> 488: ok 489: end. 490: 491: cast_fast_messup() -> 492: %% Register a false node: hopp@hostname 493: unregister(erl_epmd), 494: erl_epmd:start_link(), 495: {ok,S} = gen_tcp:listen(0, []), 496: {ok,P} = inet:port(S), 497: {ok,_Creation} = erl_epmd:register_node(hopp, P), 498: receive after infinity -> ok end. 499: 500: %% -------------------------------------- 501: %% Test handle_info. 502: %% -------------------------------------- 503: 504: info(suite) -> []; 505: info(Config) when is_list(Config) -> 506: ?line {ok, Pid} = 507: gen_server:start({local, my_test_name}, 508: gen_server_SUITE, [], []), 509: 510: ?line ok = gen_server:call(my_test_name, started_p), 511: 512: ?line Pid ! {self(),handle_info}, 513: ?line receive 514: {Pid, handled_info} -> 515: ok 516: after 1000 -> 517: test_server:fail(handle_info) 518: end, 519: 520: ?line Pid ! {self(),delayed_info,1}, 521: ?line receive 522: {Pid, delayed_info} -> 523: ok 524: after 1000 -> 525: test_server:fail(delayed_info) 526: end, 527: 528: ?line Pid ! {self(),stop}, 529: ?line receive 530: {Pid, stopped_info} -> 531: ok 532: after 1000 -> 533: test_server:fail(stop_info) 534: end, 535: ok. 536: 537: hibernate(suite) -> []; 538: hibernate(Config) when is_list(Config) -> 539: OldFl = process_flag(trap_exit, true), 540: ?line {ok, Pid0} = 541: gen_server:start_link({local, my_test_name_hibernate0}, 542: gen_server_SUITE, hibernate, []), 543: ?line receive after 1000 -> ok end, 544: ?line {current_function,{erlang,hibernate,3}} = erlang:process_info(Pid0,current_function), 545: ?line ok = gen_server:call(my_test_name_hibernate0, stop), 546: receive 547: {'EXIT', Pid0, stopped} -> 548: ok 549: after 5000 -> 550: test_server:fail(gen_server_did_not_die) 551: end, 552: 553: ?line {ok, Pid} = 554: gen_server:start_link({local, my_test_name_hibernate}, 555: gen_server_SUITE, [], []), 556: 557: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 558: ?line true = gen_server:call(my_test_name_hibernate, hibernate), 559: ?line receive after 1000 -> ok end, 560: ?line {current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function), 561: ?line Parent = self(), 562: Fun = fun() -> 563: receive 564: go -> 565: ok 566: end, 567: receive 568: after 1000 -> 569: ok 570: end, 571: X = erlang:process_info(Pid,current_function), 572: Pid ! continue, 573: Parent ! {result,X} 574: end, 575: ?line Pid2 = spawn_link(Fun), 576: ?line true = gen_server:call(my_test_name_hibernate, {hibernate_noreply,Pid2}), 577: 578: ?line gen_server:cast(my_test_name_hibernate, hibernate_later), 579: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 580: ?line receive after 2000 -> ok end, 581: ?line ({current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function)), 582: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 583: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 584: ?line gen_server:cast(my_test_name_hibernate, hibernate_now), 585: ?line receive after 1000 -> ok end, 586: ?line ({current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function)), 587: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 588: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 589: ?line Pid ! hibernate_later, 590: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 591: ?line receive after 2000 -> ok end, 592: ?line ({current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function)), 593: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 594: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 595: ?line Pid ! hibernate_now, 596: ?line receive after 1000 -> ok end, 597: ?line ({current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function)), 598: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 599: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 600: ?line receive 601: {result,R} -> 602: ?line {current_function,{erlang,hibernate,3}} = R 603: end, 604: ?line true = gen_server:call(my_test_name_hibernate, hibernate), 605: ?line receive after 1000 -> ok end, 606: ?line {current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function), 607: ?line sys:suspend(my_test_name_hibernate), 608: ?line receive after 1000 -> ok end, 609: ?line {current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function), 610: ?line sys:resume(my_test_name_hibernate), 611: ?line receive after 1000 -> ok end, 612: ?line {current_function,{erlang,hibernate,3}} = erlang:process_info(Pid,current_function), 613: ?line ok = gen_server:call(my_test_name_hibernate, started_p), 614: ?line true = ({current_function,{erlang,hibernate,3}} =/= erlang:process_info(Pid,current_function)), 615: 616: ?line ok = gen_server:call(my_test_name_hibernate, stop), 617: receive 618: {'EXIT', Pid, stopped} -> 619: ok 620: after 5000 -> 621: test_server:fail(gen_server_did_not_die) 622: end, 623: process_flag(trap_exit, OldFl), 624: ok. 625: 626: %% -------------------------------------- 627: %% Test gen_server:abcast and handle_cast. 628: %% Test all different return values from 629: %% handle_cast. 630: %% -------------------------------------- 631: 632: abcast(suite) -> []; 633: abcast(Config) when is_list(Config) -> 634: ?line {ok, Pid} = 635: gen_server:start({local, my_test_name}, 636: gen_server_SUITE, [], []), 637: 638: ?line ok = gen_server:call(my_test_name, started_p), 639: 640: ?line abcast = gen_server:abcast(my_test_name, {self(),handle_cast}), 641: ?line receive 642: {Pid, handled_cast} -> 643: ok 644: after 1000 -> 645: test_server:fail(abcast) 646: end, 647: 648: ?line abcast = gen_server:abcast([node()], my_test_name, 649: {self(),delayed_cast,1}), 650: ?line receive 651: {Pid, delayed} -> 652: ok 653: after 1000 -> 654: test_server:fail(delayed_abcast) 655: end, 656: 657: ?line abcast = gen_server:abcast(my_test_name, {self(),stop}), 658: ?line receive 659: {Pid, stopped} -> 660: ok 661: after 1000 -> 662: test_server:fail(abcast_stop) 663: end, 664: ok. 665: 666: %% -------------------------------------- 667: %% Test gen_server:multicall and handle_call. 668: %% Test all different return values from 669: %% handle_call. 670: %% -------------------------------------- 671: 672: multicall(suite) -> []; 673: multicall(Config) when is_list(Config) -> 674: OldFl = process_flag(trap_exit, true), 675: 676: ?line {ok, Pid} = 677: gen_server:start_link({local, my_test_name}, 678: gen_server_SUITE, [], []), 679: 680: ?line ok = gen_server:call(my_test_name, started_p), 681: Nodes = nodes(), 682: Node = node(), 683: ?line {[{Node,delayed}],Nodes} = 684: gen_server:multi_call(my_test_name, {delayed_answer,1}), 685: 686: %% two requests within a specified time. 687: ?line {[{Node,ok}],[]} = 688: gen_server:multi_call([Node], my_test_name, {call_within, 1000}), 689: test_server:sleep(500), 690: ?line {[{Node,ok}],[]} = 691: gen_server:multi_call([Node], my_test_name, next_call), 692: ?line {[{Node,ok}],[]} = 693: gen_server:multi_call([Node], my_test_name, {call_within, 1000}), 694: test_server:sleep(1500), 695: ?line {[{Node,false}],[]} = 696: gen_server:multi_call([Node],my_test_name, next_call), 697: 698: %% Stop the server. 699: ?line {[{Node,ok}],[]} = 700: gen_server:multi_call([Node],my_test_name, stop), 701: receive 702: {'EXIT', Pid, stopped} -> ok 703: after 1000 -> 704: test_server:fail(multicall_stop) 705: end, 706: 707: process_flag(trap_exit, OldFl), 708: 709: ok. 710: 711: %% OTP-3587 712: multicall_down(suite) -> []; 713: multicall_down(Config) when is_list(Config) -> 714: %% We need a named host which is inaccessible. 715: ?line Name = node@test01, 716: 717: %% We use 'global' as a gen_server to call. 718: ?line {Good, Bad} = gen_server:multi_call([Name, node()], 719: global_name_server, 720: info, 721: 3000), 722: io:format("good = ~p, bad = ~p~n", [Good, Bad]), 723: ?line [Name] = Bad, 724: ok. 725: 726: busy_wait_for_process(Pid,N) -> 727: case erlang:is_process_alive(Pid) of 728: true -> 729: receive 730: after 100 -> 731: ok 732: end, 733: busy_wait_for_process(Pid,N-1); 734: _ -> 735: ok 736: end. 737: %%-------------------------------------------------------------- 738: spec_init(doc) -> 739: ["Test gen_server:enter_loop/[3,4,5]. Used when you want to write " 740: "your own special init-phase."]; 741: spec_init(suite) -> 742: []; 743: spec_init(Config) when is_list(Config) -> 744: 745: OldFlag = process_flag(trap_exit, true), 746: 747: ?line {ok, Pid0} = start_link(spec_init_local, [{ok, my_server}, []]), 748: ?line ok = gen_server:call(Pid0, started_p), 749: ?line ok = gen_server:call(Pid0, stop), 750: receive 751: {'EXIT', Pid0, stopped} -> 752: ok 753: after 5000 -> 754: test_server:fail(gen_server_did_not_die) 755: end, 756: 757: ?line {ok, Pid01} = start_link(spec_init_local, [{not_ok, my_server}, []]), 758: receive 759: {'EXIT', Pid01, process_not_registered} -> 760: ok 761: after 5000 -> 762: test_server:fail(gen_server_did_not_die) 763: end, 764: 765: ?line {ok, Pid1} = start_link(spec_init_global, [{ok, my_server}, []]), 766: ?line ok = gen_server:call(Pid1, started_p), 767: ?line ok = gen_server:call(Pid1, stop), 768: receive 769: {'EXIT', Pid1, stopped} -> 770: ok 771: after 5000 -> 772: test_server:fail(gen_server_did_not_die) 773: end, 774: 775: ?line {ok, Pid11} = 776: start_link(spec_init_global, [{not_ok, my_server}, []]), 777: 778: receive 779: {'EXIT', Pid11, process_not_registered_globally} -> 780: ok 781: after 5000 -> 782: test_server:fail(gen_server_did_not_die) 783: end, 784: 785: ?line {ok, Pid2} = start_link(spec_init_anonymous, [[]]), 786: ?line ok = gen_server:call(Pid2, started_p), 787: ?line ok = gen_server:call(Pid2, stop), 788: receive 789: {'EXIT', Pid2, stopped} -> 790: ok 791: after 5000 -> 792: test_server:fail(gen_server_did_not_die) 793: end, 794: 795: ?line {ok, Pid3} = start_link(spec_init_anonymous_default_timeout, [[]]), 796: ?line ok = gen_server:call(Pid3, started_p), 797: ?line ok = gen_server:call(Pid3, stop), 798: receive 799: {'EXIT', Pid3, stopped} -> 800: ok 801: after 5000 -> 802: test_server:fail(gen_server_did_not_die) 803: end, 804: 805: ?line {ok, Pid4} = 806: start_link(spec_init_default_timeout, [{ok, my_server}, []]), 807: ?line ok = gen_server:call(Pid4, started_p), 808: ?line ok = gen_server:call(Pid4, stop), 809: receive 810: {'EXIT', Pid4, stopped} -> 811: ok 812: after 5000 -> 813: test_server:fail(gen_server_did_not_die) 814: end, 815: 816: %% Before the OTP-10130 fix this failed because a timeout message 817: %% was generated as the spawned process crashed because a {global, Name} 818: %% was matched as a timeout value instead of matching on scope. 819: {ok, _PidHurra} = 820: start_link(spec_init_global_default_timeout, [{ok, hurra}, []]), 821: timer:sleep(1000), 822: ok = gen_server:call(_PidHurra, started_p), 823: 824: ?line Pid5 = 825: erlang:spawn_link(?MODULE, spec_init_not_proc_lib, [[]]), 826: receive 827: {'EXIT', Pid5, process_was_not_started_by_proc_lib} -> 828: ok 829: after 5000 -> 830: test_server:fail(gen_server_did_not_die) 831: end, 832: process_flag(trap_exit, OldFlag), 833: ok. 834: 835: %%-------------------------------------------------------------- 836: spec_init_local_registered_parent(doc) -> 837: ["Test that terminate is run when the parent is a locally registered " 838: "process OTP-4820"]; 839: spec_init_local_registered_parent(suite) -> []; 840: spec_init_local_registered_parent(Config) when is_list(Config) -> 841: 842: register(foobar, self()), 843: process_flag(trap_exit, true), 844: 845: ?line {ok, Pid} = start_link(spec_init_local, [{ok, my_server}, []]), 846: 847: ?line ok = gen_server:cast(my_server, {self(),stop}), 848: ?line receive 849: {Pid, stopped} -> 850: ok 851: after 1000 -> 852: test_server:fail(stop) 853: end, 854: unregister(foobar), 855: ok. 856: %%-------------------------------------------------------------- 857: spec_init_global_registered_parent(doc) -> 858: ["Test that terminate is run when the parent is a global registered " 859: "process OTP-4820"]; 860: spec_init_global_registered_parent(suite) -> []; 861: spec_init_global_registered_parent(Config) when is_list(Config) -> 862: 863: global:register_name(foobar, self()), 864: process_flag(trap_exit, true), 865: 866: ?line {ok, Pid} = start_link(spec_init_global, [{ok, my_server}, []]), 867: 868: ?line ok = gen_server:call(Pid, started_p), 869: ?line ok = gen_server:cast(Pid, {self(),stop}), 870: 871: ?line receive 872: {Pid, stopped} -> 873: ok 874: after 1000 -> 875: test_server:fail(stop) 876: end, 877: global:unregister_name(foobar), 878: ok. 879: %%-------------------------------------------------------------- 880: otp_5854(suite) -> 881: []; 882: otp_5854(doc) -> 883: ["Test check for registered name in enter_loop/3,4,5"]; 884: otp_5854(Config) when is_list(Config) -> 885: OldFlag = process_flag(trap_exit, true), 886: 887: ?line dummy_via:reset(), 888: 889: %% Make sure gen_server:enter_loop does not accept {local,Name} 890: %% when it's another process than the calling one which is 891: %% registered under that name 892: register(armitage, self()), 893: ?line {ok, Pid1} = 894: start_link(spec_init_local, [{not_ok, armitage}, []]), 895: receive 896: {'EXIT', Pid1, process_not_registered} -> 897: ok 898: after 1000 -> 899: ?line test_server:fail(gen_server_started) 900: end, 901: unregister(armitage), 902: 903: %% Make sure gen_server:enter_loop does not accept {global,Name} 904: %% when it's another process than the calling one which is 905: %% registered under that name 906: global:register_name(armitage, self()), 907: ?line {ok, Pid2} = 908: start_link(spec_init_global, [{not_ok, armitage}, []]), 909: receive 910: {'EXIT', Pid2, process_not_registered_globally} -> 911: ok 912: after 1000 -> 913: ?line test_server:fail(gen_server_started) 914: end, 915: global:unregister_name(armitage), 916: 917: %% (same for {via, Mod, Name}) 918: dummy_via:register_name(armitage, self()), 919: ?line {ok, Pid3} = 920: start_link(spec_init_via, [{not_ok, armitage}, []]), 921: receive 922: {'EXIT', Pid3, {process_not_registered_via, dummy_via}} -> 923: ok 924: after 1000 -> 925: ?line test_server:fail(gen_server_started) 926: end, 927: dummy_via:unregister_name(armitage), 928: 929: process_flag(trap_exit, OldFlag), 930: ok. 931: 932: %% If initialization fails (with ignore or {stop,Reason}), 933: %% make sure that the process is not registered when gen_server:start() 934: %% returns. 935: 936: otp_7669(Config) when is_list(Config) -> 937: ?line ?t:do_times(100, fun do_otp_7669_local_ignore/0), 938: ?line ?t:do_times(100, fun do_otp_7669_global_ignore/0), 939: ?line ?t:do_times(10, fun do_otp_7669_stop/0), 940: ok. 941: 942: do_otp_7669_local_ignore() -> 943: %% The name should never be registered after the return 944: %% from gen_server:start/3. 945: ?line ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []), 946: ?line undefined = whereis(?MODULE), 947: ?line ignore = gen_server:start({local,?MODULE}, ?MODULE, ignore, []), 948: ?line undefined = whereis(?MODULE), 949: ?line ignore = gen_server:start_link({local,?MODULE}, ?MODULE, ignore, []), 950: ?line undefined = whereis(?MODULE). 951: 952: do_otp_7669_global_ignore() -> 953: ?line ignore = gen_server:start({global,?MODULE}, ?MODULE, ignore, []), 954: ?line undefined = global:whereis_name(?MODULE), 955: ?line ignore = gen_server:start_link({global,?MODULE}, ?MODULE, ignore, []), 956: ?line undefined = global:whereis_name(?MODULE). 957: 958: do_otp_7669_stop() -> 959: %% The name should never be registered after the return 960: %% from gen_server:start/3. 961: ?line {error,stopped} = gen_server:start({local,?MODULE}, 962: ?MODULE, stop, []), 963: ?line undefined = whereis(?MODULE), 964: 965: ?line {error,stopped} = gen_server:start({global,?MODULE}, 966: ?MODULE, stop, []), 967: ?line undefined = global:whereis_name(?MODULE). 968: 969: %% Verify that sys:get_status correctly calls our format_status/2 fun 970: %% 971: call_format_status(suite) -> 972: []; 973: call_format_status(doc) -> 974: ["Test that sys:get_status/1,2 calls format_status/2"]; 975: call_format_status(Config) when is_list(Config) -> 976: ?line {ok, Pid} = gen_server:start_link({local, call_format_status}, 977: ?MODULE, [], []), 978: ?line Status1 = sys:get_status(call_format_status), 979: ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data1]} = Status1, 980: ?line [format_status_called | _] = lists:reverse(Data1), 981: ?line Status2 = sys:get_status(call_format_status, 5000), 982: ?line {status, Pid, _Mod, [_PDict, running, _Parent, _, Data2]} = Status2, 983: ?line [format_status_called | _] = lists:reverse(Data2), 984: 985: %% check that format_status can handle a name being a pid (atom is 986: %% already checked by the previous test) 987: ?line {ok, Pid3} = gen_server:start_link(gen_server_SUITE, [], []), 988: ?line Status3 = sys:get_status(Pid3), 989: ?line {status, Pid3, _Mod, [_PDict3, running, _Parent, _, Data3]} = Status3, 990: ?line [format_status_called | _] = lists:reverse(Data3), 991: 992: %% check that format_status can handle a name being a term other than a 993: %% pid or atom 994: GlobalName1 = {global, "CallFormatStatus"}, 995: ?line {ok, Pid4} = gen_server:start_link(GlobalName1, 996: gen_server_SUITE, [], []), 997: ?line Status4 = sys:get_status(Pid4), 998: ?line {status, Pid4, _Mod, [_PDict4, running, _Parent, _, Data4]} = Status4, 999: ?line [format_status_called | _] = lists:reverse(Data4), 1000: GlobalName2 = {global, {name, "term"}}, 1001: ?line {ok, Pid5} = gen_server:start_link(GlobalName2, 1002: gen_server_SUITE, [], []), 1003: ?line Status5 = sys:get_status(GlobalName2), 1004: ?line {status, Pid5, _Mod, [_PDict5, running, _Parent, _, Data5]} = Status5, 1005: ?line [format_status_called | _] = lists:reverse(Data5), 1006: ok. 1007: 1008: %% Verify that error termination correctly calls our format_status/2 fun 1009: %% 1010: error_format_status(suite) -> 1011: []; 1012: error_format_status(doc) -> 1013: ["Test that an error termination calls format_status/2"]; 1014: error_format_status(Config) when is_list(Config) -> 1015: ?line error_logger_forwarder:register(), 1016: OldFl = process_flag(trap_exit, true), 1017: State = "called format_status", 1018: ?line {ok, Pid} = gen_server:start_link(?MODULE, {state, State}, []), 1019: ?line {'EXIT',{crashed,_}} = (catch gen_server:call(Pid, crash)), 1020: receive 1021: {'EXIT', Pid, crashed} -> 1022: ok 1023: end, 1024: receive 1025: {error,_GroupLeader,{Pid, 1026: "** Generic server"++_, 1027: [Pid,crash,State,crashed]}} -> 1028: ok; 1029: Other -> 1030: ?line io:format("Unexpected: ~p", [Other]), 1031: ?line ?t:fail() 1032: end, 1033: ?t:messages_get(), 1034: process_flag(trap_exit, OldFl), 1035: ok. 1036: 1037: %% Verify that sys:get_state correctly returns gen_server state 1038: %% 1039: get_state(suite) -> 1040: []; 1041: get_state(doc) -> 1042: ["Test that sys:get_state/1,2 return the gen_server state"]; 1043: get_state(Config) when is_list(Config) -> 1044: State = self(), 1045: {ok, _Pid} = gen_server:start_link({local, get_state}, 1046: ?MODULE, {state,State}, []), 1047: State = sys:get_state(get_state), 1048: State = sys:get_state(get_state, 5000), 1049: {ok, Pid} = gen_server:start_link(?MODULE, {state,State}, []), 1050: State = sys:get_state(Pid), 1051: State = sys:get_state(Pid, 5000), 1052: ok. 1053: 1054: %% Verify that sys:replace_state correctly replaces gen_server state 1055: %% 1056: replace_state(suite) -> 1057: []; 1058: replace_state(doc) -> 1059: ["Test that sys:replace_state/1,2 replace the gen_server state"]; 1060: replace_state(Config) when is_list(Config) -> 1061: State = self(), 1062: {ok, _Pid} = gen_server:start_link({local, replace_state}, 1063: ?MODULE, {state,State}, []), 1064: State = sys:get_state(replace_state), 1065: NState1 = "replaced", 1066: Replace1 = fun(_) -> NState1 end, 1067: NState1 = sys:replace_state(replace_state, Replace1), 1068: NState1 = sys:get_state(replace_state), 1069: {ok, Pid} = gen_server:start_link(?MODULE, {state,NState1}, []), 1070: NState1 = sys:get_state(Pid), 1071: Suffix = " again", 1072: NState2 = NState1 ++ Suffix, 1073: Replace2 = fun(S) -> S ++ Suffix end, 1074: NState2 = sys:replace_state(Pid, Replace2, 5000), 1075: NState2 = sys:get_state(Pid, 5000), 1076: %% verify no change in state if replace function crashes 1077: Replace3 = fun(_) -> throw(fail) end, 1078: NState2 = sys:replace_state(Pid, Replace3), 1079: NState2 = sys:get_state(Pid, 5000), 1080: ok. 1081: 1082: %% Test that the time for a huge message queue is not 1083: %% significantly slower than with an empty message queue. 1084: call_with_huge_message_queue(Config) when is_list(Config) -> 1085: case test_server:is_native(gen) of 1086: true -> 1087: {skip, 1088: "gen is native - huge message queue optimization " 1089: "is not implemented"}; 1090: false -> 1091: do_call_with_huge_message_queue() 1092: end. 1093: 1094: do_call_with_huge_message_queue() -> 1095: ?line Pid = spawn_link(fun echo_loop/0), 1096: 1097: ?line {Time,ok} = tc(fun() -> calls(10000, Pid) end), 1098: 1099: ?line [self() ! {msg,N} || N <- lists:seq(1, 500000)], 1100: erlang:garbage_collect(), 1101: ?line {NewTime,ok} = tc(fun() -> calls(10000, Pid) end), 1102: io:format("Time for empty message queue: ~p", [Time]), 1103: io:format("Time for huge message queue: ~p", [NewTime]), 1104: 1105: IsCover = test_server:is_cover(), 1106: case (NewTime+1) / (Time+1) of 1107: Q when Q < 10; IsCover -> 1108: ok; 1109: Q -> 1110: io:format("Q = ~p", [Q]), 1111: ?line ?t:fail() 1112: end, 1113: ok. 1114: 1115: calls(0, _) -> ok; 1116: calls(N, Pid) -> 1117: {ultimate_answer,42} = call(Pid, {ultimate_answer,42}), 1118: calls(N-1, Pid). 1119: 1120: call(Pid, Msg) -> 1121: gen_server:call(Pid, Msg, infinity). 1122: 1123: tc(Fun) -> 1124: timer:tc(erlang, apply, [Fun,[]]). 1125: 1126: echo_loop() -> 1127: receive 1128: {'$gen_call',{Pid,Ref},Msg} -> 1129: Pid ! {Ref,Msg}, 1130: echo_loop() 1131: end. 1132: 1133: %%-------------------------------------------------------------- 1134: %% Help functions to spec_init_* 1135: start_link(Init, Options) -> 1136: proc_lib:start_link(?MODULE, Init, Options). 1137: 1138: spec_init_local({ok, Name}, Options) -> 1139: process_flag(trap_exit, true), 1140: register(Name, self()), 1141: proc_lib:init_ack({ok, self()}), 1142: %% Supervised init can occur here ... 1143: gen_server:enter_loop(?MODULE, Options, {}, {local, Name}, infinity); 1144: 1145: spec_init_local({not_ok, Name}, Options) -> 1146: process_flag(trap_exit, true), 1147: proc_lib:init_ack({ok, self()}), 1148: %% Supervised init can occur here ... 1149: gen_server:enter_loop(?MODULE, Options, {}, {local, Name}, infinity). 1150: 1151: spec_init_global({ok, Name}, Options) -> 1152: process_flag(trap_exit, true), 1153: global:register_name(Name, self()), 1154: proc_lib:init_ack({ok, self()}), 1155: %% Supervised init can occur here ... 1156: gen_server:enter_loop(?MODULE, Options, {}, {global, Name}, infinity); 1157: 1158: spec_init_global({not_ok, Name}, Options) -> 1159: process_flag(trap_exit, true), 1160: proc_lib:init_ack({ok, self()}), 1161: %% Supervised init can occur here ... 1162: gen_server:enter_loop(?MODULE, Options, {}, {global, Name}, infinity). 1163: 1164: spec_init_via({ok, Name}, Options) -> 1165: process_flag(trap_exit, true), 1166: dummy_via:register_name(Name, self()), 1167: proc_lib:init_ack({ok, self()}), 1168: %% Supervised init can occur here ... 1169: gen_server:enter_loop(?MODULE, Options, {}, 1170: {via, dummy_via, Name}, infinity); 1171: 1172: spec_init_via({not_ok, Name}, Options) -> 1173: process_flag(trap_exit, true), 1174: proc_lib:init_ack({ok, self()}), 1175: %% Supervised init can occur here ... 1176: gen_server:enter_loop(?MODULE, Options, {}, 1177: {via, dummy_via, Name}, infinity). 1178: 1179: spec_init_default_timeout({ok, Name}, Options) -> 1180: process_flag(trap_exit, true), 1181: register(Name, self()), 1182: proc_lib:init_ack({ok, self()}), 1183: %% Supervised init can occur here ... 1184: gen_server:enter_loop(?MODULE, Options, {}, {local, Name}). 1185: 1186: %% OTP-10130, A bug was introduced where global scope was not matched when 1187: %% enter_loop/4 was called (no timeout). 1188: spec_init_global_default_timeout({ok, Name}, Options) -> 1189: process_flag(trap_exit, true), 1190: global:register_name(Name, self()), 1191: proc_lib:init_ack({ok, self()}), 1192: %% Supervised init can occur here ... 1193: gen_server:enter_loop(?MODULE, Options, {}, {global, Name}). 1194: 1195: spec_init_anonymous(Options) -> 1196: process_flag(trap_exit, true), 1197: proc_lib:init_ack({ok, self()}), 1198: %% Supervised init can occur here ... 1199: gen_server:enter_loop(?MODULE, Options, {}, infinity). 1200: 1201: spec_init_anonymous_default_timeout(Options) -> 1202: process_flag(trap_exit, true), 1203: proc_lib:init_ack({ok, self()}), 1204: %% Supervised init can occur here ... 1205: gen_server:enter_loop(?MODULE, Options, {}). 1206: 1207: spec_init_not_proc_lib(Options) -> 1208: gen_server:enter_loop(?MODULE, Options, {}, infinity). 1209: 1210: %%% -------------------------------------------------------- 1211: %%% Here is the tested gen_server behaviour. 1212: %%% -------------------------------------------------------- 1213: 1214: init([]) -> 1215: {ok, []}; 1216: init(ignore) -> 1217: ignore; 1218: init(stop) -> 1219: {stop, stopped}; 1220: init(hibernate) -> 1221: {ok,[],hibernate}; 1222: init(sleep) -> 1223: test_server:sleep(1000), 1224: {ok, []}; 1225: init({state,State}) -> 1226: {ok, State}. 1227: 1228: handle_call(started_p, _From, State) -> 1229: io:format("FROZ"), 1230: {reply,ok,State}; 1231: handle_call({delayed_answer, T}, From, _State) -> 1232: {noreply,{reply_to,From},T}; 1233: handle_call({call_within, T}, _From, _) -> 1234: {reply,ok,call_within,T}; 1235: handle_call(next_call, _From, call_within) -> 1236: {reply,ok,[]}; 1237: handle_call(next_call, _From, State) -> 1238: {reply,false,State}; 1239: handle_call(badreturn, _From, _State) -> 1240: badreturn; 1241: handle_call(hibernate, _From, _State) -> 1242: {reply,true,[],hibernate}; 1243: handle_call({hibernate_noreply,Pid}, From, _State) -> 1244: Pid ! go, 1245: {noreply,From,hibernate}; 1246: handle_call(stop, _From, State) -> 1247: {stop,stopped,ok,State}; 1248: handle_call(crash, _From, _State) -> 1249: exit(crashed); 1250: handle_call(exit_shutdown, _From, _State) -> 1251: exit(shutdown); 1252: handle_call(stop_shutdown, _From, State) -> 1253: {stop,shutdown,State}; 1254: handle_call(shutdown_reason, _From, _State) -> 1255: exit({shutdown,reason}); 1256: handle_call(stop_shutdown_reason, _From, State) -> 1257: {stop,{shutdown,stop_reason},State}. 1258: 1259: handle_cast({From,handle_cast}, State) -> 1260: From ! {self(), handled_cast}, 1261: {noreply, State}; 1262: handle_cast({From,delayed_cast,T}, _State) -> 1263: {noreply, {delayed_cast,From}, T}; 1264: handle_cast(hibernate_now, _State) -> 1265: {noreply, [], hibernate}; 1266: handle_cast(hibernate_later, _State) -> 1267: timer:send_after(1000,self(),hibernate_now), 1268: {noreply, []}; 1269: handle_cast({From, stop}, State) -> 1270: io:format("BAZ"), 1271: {stop, {From,stopped}, State}. 1272: 1273: handle_info(timeout, {reply_to, From}) -> 1274: gen_server:reply(From, delayed), 1275: {noreply, []}; 1276: handle_info(timeout, hibernate_me) -> % Arrive here from 1277: % handle_info(hibernate_later,...) 1278: {noreply, [], hibernate}; 1279: handle_info(hibernate_now, _State) -> % Arrive here from 1280: % handle_cast({_,hibernate_later},...) 1281: % and by direct ! from testcase 1282: {noreply, [], hibernate}; 1283: handle_info(hibernate_later, _State) -> 1284: {noreply, hibernate_me, 1000}; 1285: handle_info(timeout, call_within) -> 1286: {noreply, []}; 1287: handle_info(timeout, {delayed_cast, From}) -> 1288: From ! {self(), delayed}, 1289: {noreply, []}; 1290: handle_info(timeout, {delayed_info, From}) -> 1291: From ! {self(), delayed_info}, 1292: {noreply, []}; 1293: handle_info({From, handle_info}, _State) -> 1294: From ! {self(), handled_info}, 1295: {noreply, []}; 1296: handle_info({From, delayed_info, T}, _State) -> 1297: {noreply, {delayed_info, From}, T}; 1298: handle_info(continue, From) -> 1299: gen_server:reply(From,true), 1300: {noreply, []}; 1301: handle_info({From, stop}, State) -> 1302: {stop, {From,stopped_info}, State}; 1303: handle_info(_Info, State) -> 1304: {noreply, State}. 1305: 1306: terminate({From, stopped}, _State) -> 1307: io:format("FOOBAR"), 1308: From ! {self(), stopped}, 1309: ok; 1310: terminate({From, stopped_info}, _State) -> 1311: From ! {self(), stopped_info}, 1312: ok; 1313: terminate(_Reason, _State) -> 1314: ok. 1315: 1316: format_status(terminate, [_PDict, State]) -> 1317: State; 1318: format_status(normal, [_PDict, _State]) -> 1319: format_status_called.