1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2019. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(gen_event_SUITE). 21 22-include_lib("common_test/include/ct.hrl"). 23 24-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 25 init_per_group/2,end_per_group/2, init_per_testcase/2, 26 end_per_testcase/2]). 27-export([start/1, add_handler/1, add_sup_handler/1, 28 delete_handler/1, swap_handler/1, swap_sup_handler/1, 29 notify/1, sync_notify/1, call/1, info/1, hibernate/1, auto_hibernate/1, 30 call_format_status/1, call_format_status_anon/1, 31 error_format_status/1, get_state/1, replace_state/1, 32 start_opt/1, 33 undef_init/1, undef_handle_call/1, undef_handle_event/1, 34 undef_handle_info/1, undef_code_change/1, undef_terminate/1, 35 undef_in_terminate/1, format_log_1/1, format_log_2/1]). 36 37suite() -> [{ct_hooks,[ts_install_cth]}]. 38 39all() -> 40 [start, {group, test_all}, hibernate, auto_hibernate, 41 call_format_status, call_format_status_anon, error_format_status, 42 get_state, replace_state, 43 start_opt, {group, undef_callbacks}, undef_in_terminate, 44 format_log_1, format_log_2]. 45 46groups() -> 47 [{test_all, [], 48 [add_handler, add_sup_handler, delete_handler, 49 swap_handler, swap_sup_handler, notify, sync_notify, 50 call, info]}, 51 {undef_callbacks, [], 52 [undef_init, undef_handle_call, undef_handle_event, undef_handle_info, 53 undef_code_change, undef_terminate]}]. 54 55init_per_suite(Config) -> 56 Config. 57 58end_per_suite(_Config) -> 59 ok. 60 61init_per_group(undef_callbacks, Config) -> 62 DataDir = ?config(data_dir, Config), 63 Event1 = filename:join(DataDir, "oc_event.erl"), 64 {ok, oc_event} = compile:file(Event1), 65 Config; 66init_per_group(_GroupName, Config) -> 67 Config. 68 69end_per_group(_GroupName, Config) -> 70 Config. 71 72init_per_testcase(Case, Config) when Case == undef_handle_call; 73 Case == undef_handle_info; 74 Case == undef_handle_event; 75 Case == undef_code_change; 76 Case == undef_terminate -> 77 {ok, Pid} = oc_event:start(), 78 [{event_pid, Pid}|Config]; 79init_per_testcase(undef_init, Config) -> 80 {ok, Pid} = gen_event:start({local, oc_init_event}), 81 [{event_pid, Pid}|Config]; 82init_per_testcase(_Case, Config) -> 83 Config. 84 85end_per_testcase(Case, Config) when Case == undef_init; 86 Case == undef_handle_call; 87 Case == undef_handle_info; 88 Case == undef_handle_event; 89 Case == undef_code_change; 90 Case == undef_terminate -> 91 Pid = ?config(event_pid, Config), 92 gen_event:stop(Pid); 93end_per_testcase(_Case, _Config) -> 94 ok. 95 96%% -------------------------------------- 97%% Start an event manager. 98%% -------------------------------------- 99 100-define(LMGR, {local, my_dummy_name}). 101-define(GMGR, {global, my_dummy_name}). 102 103start(Config) when is_list(Config) -> 104 OldFl = process_flag(trap_exit, true), 105 106 dummy_via:reset(), 107 108 {ok, Pid0} = gen_event:start(), %anonymous 109 [] = gen_event:which_handlers(Pid0), 110 ok = gen_event:stop(Pid0), 111 112 {ok, Pid1} = gen_event:start_link(), %anonymous 113 [] = gen_event:which_handlers(Pid1), 114 ok = gen_event:stop(Pid1), 115 116 {ok, {Pid1b,Mon1b}} = gen_event:start_monitor(), %anonymous 117 [] = gen_event:which_handlers(Pid1b), 118 ok = gen_event:stop(Pid1b), 119 receive {'DOWN',Mon1b,process,Pid1b,_} -> ok end, 120 121 {ok, Pid2} = gen_event:start(?LMGR), 122 [] = gen_event:which_handlers(my_dummy_name), 123 [] = gen_event:which_handlers(Pid2), 124 ok = gen_event:stop(my_dummy_name), 125 126 {ok, Pid3} = gen_event:start_link(?LMGR), 127 [] = gen_event:which_handlers(my_dummy_name), 128 [] = gen_event:which_handlers(Pid3), 129 ok = gen_event:stop(my_dummy_name), 130 131 {ok, {Pid3b,Mon3b}} = gen_event:start_monitor(?LMGR), 132 [] = gen_event:which_handlers(my_dummy_name), 133 [] = gen_event:which_handlers(Pid3b), 134 ok = gen_event:stop(my_dummy_name), 135 receive {'DOWN',Mon3b,process,Pid3b,_} -> ok end, 136 137 {ok, Pid4} = gen_event:start_link(?GMGR), 138 [] = gen_event:which_handlers(?GMGR), 139 [] = gen_event:which_handlers(Pid4), 140 ok = gen_event:stop(?GMGR), 141 142 {ok, {Pid4b,Mon4b}} = gen_event:start_monitor(?GMGR), 143 [] = gen_event:which_handlers(?GMGR), 144 [] = gen_event:which_handlers(Pid4b), 145 ok = gen_event:stop(?GMGR), 146 receive {'DOWN',Mon4b,process,Pid4b,_} -> ok end, 147 148 {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}), 149 [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}), 150 [] = gen_event:which_handlers(Pid5), 151 ok = gen_event:stop({via, dummy_via, my_dummy_name}), 152 153 {ok, {Pid5b,Mon5b}} = gen_event:start_monitor({via, dummy_via, my_dummy_name}), 154 [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}), 155 [] = gen_event:which_handlers(Pid5b), 156 ok = gen_event:stop({via, dummy_via, my_dummy_name}), 157 receive {'DOWN',Mon5b,process,Pid5b,_} -> ok end, 158 159 {ok, _} = gen_event:start_link(?LMGR), 160 {error, {already_started, _}} = gen_event:start_link(?LMGR), 161 {error, {already_started, _}} = gen_event:start(?LMGR), 162 ok = gen_event:stop(my_dummy_name), 163 164 {ok, {Pid5c,Mon5c}} = gen_event:start_monitor(?LMGR), 165 {error, {already_started, Pid5c}} = gen_event:start_monitor(?LMGR), 166 {error, {already_started, Pid5c}} = gen_event:start(?LMGR), 167 ok = gen_event:stop(my_dummy_name), 168 receive {'DOWN',Mon5c,process,Pid5c,_} -> ok end, 169 170 {ok, Pid6} = gen_event:start_link(?GMGR), 171 {error, {already_started, _}} = gen_event:start_link(?GMGR), 172 {error, {already_started, _}} = gen_event:start(?GMGR), 173 174 ok = gen_event:stop(?GMGR, shutdown, 10000), 175 receive 176 {'EXIT', Pid6, shutdown} -> ok 177 after 10000 -> 178 ct:fail(exit_gen_event) 179 end, 180 181 {ok, {Pid6b,Mon6b}} = gen_event:start_monitor(?GMGR), 182 {error, {already_started, _}} = gen_event:start_monitor(?GMGR), 183 {error, {already_started, _}} = gen_event:start(?GMGR), 184 185 ok = gen_event:stop(?GMGR, shutdown, 10000), 186 receive 187 {'DOWN', Mon6b, process, Pid6b, shutdown} -> ok 188 after 10000 -> 189 ct:fail(exit_gen_event) 190 end, 191 192 {ok, Pid7} = gen_event:start_link({via, dummy_via, my_dummy_name}), 193 {error, {already_started, _}} = gen_event:start_link({via, dummy_via, my_dummy_name}), 194 {error, {already_started, _}} = gen_event:start({via, dummy_via, my_dummy_name}), 195 196 exit(Pid7, shutdown), 197 receive 198 {'EXIT', Pid7, shutdown} -> ok 199 after 10000 -> 200 ct:fail(exit_gen_event) 201 end, 202 203 {ok, {Pid7b,Mon7b}} = gen_event:start_monitor({via, dummy_via, my_dummy_name}), 204 {error, {already_started, _}} = gen_event:start_monitor({via, dummy_via, my_dummy_name}), 205 {error, {already_started, _}} = gen_event:start({via, dummy_via, my_dummy_name}), 206 207 exit(Pid7b, shutdown), 208 receive 209 {'DOWN', Mon7b, process, Pid7b, shutdown} -> ok 210 after 10000 -> 211 ct:fail(exit_gen_event) 212 end, 213 214 process_flag(trap_exit, OldFl), 215 ok. 216 217start_opt(Config) when is_list(Config) -> 218 OldFl = process_flag(trap_exit, true), 219 220 dummy_via:reset(), 221 222 {ok, Pid0} = gen_event:start([]), %anonymous 223 [] = gen_event:which_handlers(Pid0), 224 ok = gen_event:stop(Pid0), 225 226 {ok, Pid1} = gen_event:start_link([]), %anonymous 227 [] = gen_event:which_handlers(Pid1), 228 ok = gen_event:stop(Pid1), 229 230 {ok, Pid2} = gen_event:start(?LMGR, []), 231 [] = gen_event:which_handlers(my_dummy_name), 232 [] = gen_event:which_handlers(Pid2), 233 ok = gen_event:stop(my_dummy_name), 234 235 {ok, Pid3} = gen_event:start_link(?LMGR, []), 236 [] = gen_event:which_handlers(my_dummy_name), 237 [] = gen_event:which_handlers(Pid3), 238 ok = gen_event:stop(my_dummy_name), 239 240 {ok, Pid4} = gen_event:start_link(?GMGR, []), 241 [] = gen_event:which_handlers(?GMGR), 242 [] = gen_event:which_handlers(Pid4), 243 ok = gen_event:stop(?GMGR), 244 245 {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}, []), 246 [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}), 247 [] = gen_event:which_handlers(Pid5), 248 ok = gen_event:stop({via, dummy_via, my_dummy_name}), 249 250 {ok, _} = gen_event:start_link(?LMGR, []), 251 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 252 {error, {already_started, _}} = gen_event:start(?LMGR, []), 253 ok = gen_event:stop(my_dummy_name), 254 255 {ok, Pid7} = gen_event:start_link(?GMGR), 256 {error, {already_started, _}} = gen_event:start_link(?GMGR, []), 257 {error, {already_started, _}} = gen_event:start(?GMGR, []), 258 259 ok = gen_event:stop(?GMGR, shutdown, 10000), 260 receive 261 {'EXIT', Pid7, shutdown} -> ok 262 after 10000 -> 263 ct:fail(exit_gen_event) 264 end, 265 266 {ok, Pid8} = gen_event:start_link({via, dummy_via, my_dummy_name}), 267 {error, {already_started, _}} = gen_event:start_link({via, dummy_via, my_dummy_name}, []), 268 {error, {already_started, _}} = gen_event:start({via, dummy_via, my_dummy_name}, []), 269 270 exit(Pid8, shutdown), 271 receive 272 {'EXIT', Pid8, shutdown} -> ok 273 after 10000 -> 274 ct:fail(exit_gen_event) 275 end, 276 277 %% test spawn_opt 278 MinHeapSz = 10000, 279 {ok, Pid9} = gen_event:start_link(?LMGR, [{spawn_opt, [{min_heap_size, MinHeapSz}]}]), 280 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 281 {error, {already_started, _}} = gen_event:start(?LMGR, []), 282 {heap_size, HeapSz} = erlang:process_info(Pid9, heap_size), 283 true = HeapSz > MinHeapSz, 284 ok = gen_event:stop(my_dummy_name), 285 286 %% test debug opt 287 {ok, _} = gen_event:start_link(?LMGR, [{debug,[debug]}]), 288 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 289 {error, {already_started, _}} = gen_event:start(?LMGR, []), 290 ok = gen_event:stop(my_dummy_name), 291 292 process_flag(trap_exit, OldFl), 293 ok. 294 295hibernate(Config) when is_list(Config) -> 296 {ok,Pid} = gen_event:start({local, my_dummy_handler}), 297 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 298 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 299 true = gen_event:call(my_dummy_handler, dummy_h, hibernate), 300 is_in_erlang_hibernate(Pid), 301 302 Pid ! wake, 303 is_not_in_erlang_hibernate(Pid), 304 later = gen_event:call(my_dummy_handler, dummy_h, hibernate_later), 305 true = ({current_function,{erlang,hibernate,3}} =/= 306 erlang:process_info(Pid, current_function)), 307 is_in_erlang_hibernate(Pid), 308 309 Pid ! wake, 310 is_not_in_erlang_hibernate(Pid), 311 gen_event:notify(my_dummy_handler, hibernate), 312 is_in_erlang_hibernate(Pid), 313 gen_event:notify(my_dummy_handler, wakeup), 314 is_not_in_erlang_hibernate(Pid), 315 gen_event:notify(my_dummy_handler, hibernate), 316 is_in_erlang_hibernate(Pid), 317 gen_event:sync_notify(my_dummy_handler, wakeup), 318 true = ({current_function,{erlang,hibernate,3}} =/= 319 erlang:process_info(Pid, current_function)), 320 ok = gen_event:sync_notify(my_dummy_handler, hibernate), 321 is_in_erlang_hibernate(Pid), 322 323 Pid ! wake, 324 is_not_in_erlang_hibernate(Pid), 325 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [self()]), 326 [_,_] = gen_event:which_handlers(my_dummy_handler), 327 gen_event:notify(my_dummy_handler, hibernate), 328 is_in_erlang_hibernate(Pid), 329 gen_event:notify(my_dummy_handler, wakeup), 330 is_in_erlang_hibernate(Pid), 331 332 Pid ! wake, 333 is_not_in_erlang_hibernate(Pid), 334 335 Pid ! gnurf, 336 is_in_erlang_hibernate(Pid), 337 338 Pid ! sleep, 339 is_in_erlang_hibernate(Pid), 340 341 Pid ! wake, 342 is_not_in_erlang_hibernate(Pid), 343 ok = gen_event:stop(my_dummy_handler), 344 345 {ok,Pid2} = gen_event:start({local, my_dummy_handler}), 346 ok = gen_event:add_handler(my_dummy_handler, dummy_h, 347 [self(),hibernate]), 348 is_in_erlang_hibernate(Pid2), 349 sys:suspend(my_dummy_handler), 350 is_in_erlang_hibernate(Pid2), 351 sys:resume(my_dummy_handler), 352 is_in_erlang_hibernate(Pid2), 353 354 Pid2 ! wake, 355 is_not_in_erlang_hibernate(Pid2), 356 357 ok = gen_event:stop(my_dummy_handler), 358 359 ok. 360 361auto_hibernate(Config) when is_list(Config) -> 362 HibernateAfterTimeout = 100, 363 State = {auto_hibernate_state}, 364 {ok,Pid} = gen_event:start({local, auto_hibernate_handler}, [{hibernate_after, HibernateAfterTimeout}]), 365 %% After init test 366 is_not_in_erlang_hibernate(Pid), 367 timer:sleep(HibernateAfterTimeout), 368 is_in_erlang_hibernate(Pid), 369 ok = gen_event:add_handler(auto_hibernate_handler, dummy_h, [State]), 370 %% Get state test 371 [{dummy_h,false,State}] = sys:get_state(Pid), 372 is_in_erlang_hibernate(Pid), 373 %% Call test 374 {ok, hejhopp} = gen_event:call(auto_hibernate_handler, dummy_h, hejsan), 375 is_not_in_erlang_hibernate(Pid), 376 timer:sleep(HibernateAfterTimeout), 377 is_in_erlang_hibernate(Pid), 378 %% Event test 379 ok = gen_event:notify(auto_hibernate_handler, {self(), handle_event}), 380 receive 381 handled_event -> 382 ok 383 after 1000 -> 384 ct:fail(event) 385 end, 386 is_not_in_erlang_hibernate(Pid), 387 timer:sleep(HibernateAfterTimeout), 388 is_in_erlang_hibernate(Pid), 389 %% Info test 390 Pid ! {self(), handle_info}, 391 receive 392 handled_info -> 393 ok 394 after 1000 -> 395 ct:fail(info) 396 end, 397 is_not_in_erlang_hibernate(Pid), 398 timer:sleep(HibernateAfterTimeout), 399 is_in_erlang_hibernate(Pid), 400 ok = gen_event:stop(auto_hibernate_handler), 401 ok. 402 403is_in_erlang_hibernate(Pid) -> 404 receive after 1 -> ok end, 405 is_in_erlang_hibernate_1(200, Pid). 406 407is_in_erlang_hibernate_1(0, Pid) -> 408 io:format("~p\n", [erlang:process_info(Pid, current_function)]), 409 ct:fail(not_in_erlang_hibernate_3); 410is_in_erlang_hibernate_1(N, Pid) -> 411 {current_function,MFA} = erlang:process_info(Pid, current_function), 412 case MFA of 413 {erlang,hibernate,3} -> 414 ok; 415 _ -> 416 receive after 10 -> ok end, 417 is_in_erlang_hibernate_1(N-1, Pid) 418 end. 419 420is_not_in_erlang_hibernate(Pid) -> 421 receive after 1 -> ok end, 422 is_not_in_erlang_hibernate_1(200, Pid). 423 424is_not_in_erlang_hibernate_1(0, Pid) -> 425 io:format("~p\n", [erlang:process_info(Pid, current_function)]), 426 ct:fail(not_in_erlang_hibernate_3); 427is_not_in_erlang_hibernate_1(N, Pid) -> 428 {current_function,MFA} = erlang:process_info(Pid, current_function), 429 case MFA of 430 {erlang,hibernate,3} -> 431 receive after 10 -> ok end, 432 is_not_in_erlang_hibernate_1(N-1, Pid); 433 _ -> 434 ok 435 end. 436 437 438add_handler(Config) when is_list(Config) -> 439 {ok,_} = gen_event:start({local, my_dummy_handler}), 440 {error, my_error} = 441 gen_event:add_handler(my_dummy_handler, dummy_h, make_error), 442 [] = gen_event:which_handlers(my_dummy_handler), 443 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 444 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 445 446 {error, my_error} = 447 gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error), 448 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 449 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,self()}, 450 [self()]), 451 Self = self(), 452 [{dummy_h, Self}, dummy_h] = 453 gen_event:which_handlers(my_dummy_handler), 454 ok = gen_event:stop(my_dummy_handler), 455 ok. 456 457add_sup_handler(Config) when is_list(Config) -> 458 {ok,Pid} = gen_event:start({local, my_dummy_handler}), 459 {error, my_error} = 460 gen_event:add_sup_handler(my_dummy_handler, dummy_h, make_error), 461 [] = gen_event:which_handlers(my_dummy_handler), 462 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 463 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 464 exit(Pid, sup_died), 465 ct:sleep(1000), 466 [] = gen_event:which_handlers(my_dummy_handler), 467 468 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 469 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 470 471 {error, my_error} = 472 gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error), 473 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 474 ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,self()}, 475 [self()]), 476 Self = self(), 477 [{dummy_h, Self}, dummy_h] = 478 gen_event:which_handlers(my_dummy_handler), 479 ok = gen_event:stop(my_dummy_handler), 480 481 receive 482 {gen_event_EXIT, dummy_h, shutdown} -> 483 ok 484 after 1000 -> 485 ct:fail({no,{gen_event_EXIT, dummy_h, shutdown}}) 486 end, 487 488 receive 489 {gen_event_EXIT, {dummy_h,Self}, shutdown} -> 490 ok 491 after 1000 -> 492 ct:fail({no,{gen_event_EXIT, {dummy_h,Self}, 493 shutdown}}) 494 end, 495 ok. 496 497delete_handler(Config) when is_list(Config) -> 498 {ok,_} = gen_event:start({local, my_dummy_handler}), 499 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 500 {error, module_not_found} = 501 gen_event:delete_handler(my_dummy_handler, duuuuuuuuumy, []), 502 return_hej = 503 gen_event:delete_handler(my_dummy_handler, dummy_h, return_hej), 504 [] = gen_event:which_handlers(my_dummy_handler), 505 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 506 ok = 507 gen_event:delete_handler(my_dummy_handler, dummy_h, []), 508 [] = gen_event:which_handlers(my_dummy_handler), 509 510 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 511 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]), 512 {error, module_not_found} = 513 gen_event:delete_handler(my_dummy_handler, {duuuuuuuuumy,1}, []), 514 return_hej = 515 gen_event:delete_handler(my_dummy_handler, {dummy_h,1}, return_hej), 516 return_hej = 517 gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, return_hej), 518 [] = gen_event:which_handlers(my_dummy_handler), 519 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]), 520 ok = 521 gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, []), 522 [] = gen_event:which_handlers(my_dummy_handler), 523 524 ok = gen_event:stop(my_dummy_handler), 525 ok. 526 527swap_handler(Config) when is_list(Config) -> 528 {ok,_} = gen_event:start({local, my_dummy_handler}), 529 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 530 {error, non_existing} = 531 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 532 {dummy1_h, []}), 533 ok = 534 gen_event:swap_handler(my_dummy_handler, {dummy_h, swap}, 535 {dummy1_h, swap}), 536 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 537 538 ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []), 539 540 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 541 {error, non_existing} = 542 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 543 {dummy1_h, []}), 544 ok = 545 gen_event:swap_handler(my_dummy_handler, {{dummy_h,3}, swap}, 546 {{dummy1_h,4}, swap}), 547 [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler), 548 549 ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []), 550 551 ok = gen_event:stop(my_dummy_handler), 552 ok. 553 554swap_sup_handler(Config) when is_list(Config) -> 555 {ok,_} = gen_event:start({local, my_dummy_handler}), 556 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 557 {error, non_existing} = 558 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 559 {dummy1_h, []}), 560 ok = 561 gen_event:swap_handler(my_dummy_handler, {dummy_h, swap}, 562 {dummy1_h, swap}), 563 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 564 565 ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []), 566 receive 567 {gen_event_EXIT, dummy1_h, normal} -> 568 ok 569 after 1000 -> 570 ct:fail({no,{gen_event_EXIT, dummy1_h, normal}}) 571 end, 572 573 ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,3}, 574 [self()]), 575 {error, non_existing} = 576 gen_event:swap_sup_handler(my_dummy_handler, {faulty_h, swap}, 577 {dummy1_h, []}), 578 ok = 579 gen_event:swap_sup_handler(my_dummy_handler, {{dummy_h,3}, swap}, 580 {{dummy1_h,4}, swap}), 581 [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler), 582 583 ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []), 584 receive 585 {gen_event_EXIT, {dummy1_h,4}, normal} -> 586 ok 587 after 1000 -> 588 ct:fail({no,{gen_event_EXIT, {dummy1_h,4}, normal}}) 589 end, 590 591 ok = gen_event:stop(my_dummy_handler), 592 ok. 593 594notify(Config) when is_list(Config) -> 595 {ok,_} = gen_event:start({local, my_dummy_handler}), 596 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 597 Event = {event, self()}, 598 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 599 ok = gen_event:notify(my_dummy_handler, Event), 600 receive 601 {dummy_h, Event} -> 602 ok 603 end, 604 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 605 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 606 ok = gen_event:notify(my_dummy_handler, Event), 607 receive 608 {dummy1_h, Event} -> 609 ok 610 end, 611 ok = gen_event:notify(my_dummy_handler, delete_event), 612 receive 613 {dummy1_h, removed} -> 614 ok 615 end, 616 [] = gen_event:which_handlers(my_dummy_handler), 617 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 618 619 ok = gen_event:notify(my_dummy_handler, error_event), 620 receive 621 {dummy_h, returned_error} -> 622 ok 623 end, 624 [] = gen_event:which_handlers(my_dummy_handler), 625 626 %% Handler with id, {Mod,Id} 627 628 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]), 629 [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler), 630 ok = gen_event:notify(my_dummy_handler, Event), 631 receive 632 {dummy_h, Event} -> 633 ok 634 end, 635 ok = gen_event:notify(my_dummy_handler, 636 {swap_event, {dummy1_h, 9}, swap}), 637 [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), 638 ok = gen_event:notify(my_dummy_handler, Event), 639 receive 640 {dummy1_h, Event} -> 641 ok 642 end, 643 ok = gen_event:notify(my_dummy_handler, delete_event), 644 receive 645 {dummy1_h, removed} -> 646 ok 647 end, 648 [] = gen_event:which_handlers(my_dummy_handler), 649 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]), 650 651 ok = gen_event:notify(my_dummy_handler, error_event), 652 receive 653 {dummy_h, returned_error} -> 654 ok 655 end, 656 [] = gen_event:which_handlers(my_dummy_handler), 657 658 %% Supervised handler. 659 660 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 661 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 662 ok = gen_event:notify(my_dummy_handler, Event), 663 receive 664 {dummy_h, Event} -> 665 ok 666 end, 667 668 ok = gen_event:notify(my_dummy_handler, do_crash), 669 receive 670 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 671 ok 672 end, 673 674 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 675 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 676 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 677 678 ok = gen_event:notify(my_dummy_handler, do_crash), 679 receive 680 {gen_event_EXIT, dummy1_h, {'EXIT',_}} -> 681 ok 682 end, 683 684 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 685 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 686 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 687 688 ok = gen_event:notify(my_dummy_handler, delete_event), 689 receive 690 {dummy1_h, removed} -> 691 ok 692 end, 693 694 receive 695 {gen_event_EXIT, dummy1_h, normal} -> 696 ok 697 end, 698 699 [] = gen_event:which_handlers(my_dummy_handler), 700 701 ok = gen_event:stop(my_dummy_handler), 702 ok. 703 704sync_notify(Config) when is_list(Config) -> 705 {ok,_} = gen_event:start({local, my_dummy_handler}), 706 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 707 Event = {event, self()}, 708 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 709 ok = gen_event:sync_notify(my_dummy_handler, Event), 710 receive 711 {dummy_h, Event} -> 712 ok 713 end, 714 ok = gen_event:sync_notify(my_dummy_handler, 715 {swap_event, dummy1_h, swap}), 716 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 717 ok = gen_event:sync_notify(my_dummy_handler, Event), 718 receive 719 {dummy1_h, Event} -> 720 ok 721 end, 722 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 723 receive 724 {dummy1_h, removed} -> 725 ok 726 end, 727 [] = gen_event:which_handlers(my_dummy_handler), 728 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 729 730 ok = gen_event:sync_notify(my_dummy_handler, error_event), 731 receive 732 {dummy_h, returned_error} -> 733 ok 734 end, 735 [] = gen_event:which_handlers(my_dummy_handler), 736 737 %% Handler with id, {Mod,Id} 738 739 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]), 740 [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler), 741 ok = gen_event:sync_notify(my_dummy_handler, Event), 742 receive 743 {dummy_h, Event} -> 744 ok 745 end, 746 ok = gen_event:sync_notify(my_dummy_handler, 747 {swap_event, {dummy1_h, 9}, swap}), 748 [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), 749 ok = gen_event:sync_notify(my_dummy_handler, Event), 750 receive 751 {dummy1_h, Event} -> 752 ok 753 end, 754 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 755 receive 756 {dummy1_h, removed} -> 757 ok 758 end, 759 [] = gen_event:which_handlers(my_dummy_handler), 760 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]), 761 762 ok = gen_event:sync_notify(my_dummy_handler, error_event), 763 receive 764 {dummy_h, returned_error} -> 765 ok 766 end, 767 [] = gen_event:which_handlers(my_dummy_handler), 768 769 %% Supervised handler. 770 771 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 772 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 773 ok = gen_event:sync_notify(my_dummy_handler, Event), 774 receive 775 {dummy_h, Event} -> 776 ok 777 end, 778 779 ok = gen_event:sync_notify(my_dummy_handler, do_crash), 780 receive 781 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 782 ok 783 end, 784 785 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 786 ok = gen_event:sync_notify(my_dummy_handler, 787 {swap_event,dummy1_h,swap}), 788 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 789 790 ok = gen_event:sync_notify(my_dummy_handler, do_crash), 791 receive 792 {gen_event_EXIT, dummy1_h, {'EXIT',_}} -> 793 ok 794 end, 795 796 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 797 ok = gen_event:sync_notify(my_dummy_handler, 798 {swap_event,dummy1_h,swap}), 799 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 800 801 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 802 receive 803 {dummy1_h, removed} -> 804 ok 805 end, 806 807 receive 808 {gen_event_EXIT, dummy1_h, normal} -> 809 ok 810 end, 811 812 [] = gen_event:which_handlers(my_dummy_handler), 813 814 ok = gen_event:stop(my_dummy_handler), 815 ok. 816 817call(Config) when is_list(Config) -> 818 Async = fun(Mgr,H,Req) -> 819 try 820 Promise = gen_event:send_request(Mgr,H,Req), 821 gen_event:wait_response(Promise, infinity) 822 catch _:Reason -> 823 {'did_exit', Reason} 824 end 825 end, 826 {ok,_} = gen_event:start({local, my_dummy_handler}), 827 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 828 ok = gen_event:add_handler(my_dummy_handler, {dummy_h, 1}, [self()]), 829 [{dummy_h, 1}, dummy_h] = gen_event:which_handlers(my_dummy_handler), 830 {'EXIT',_} = (catch gen_event:call(non_exist, dummy_h, hejsan)), 831 {error, _} = Async(non_exist, dummy_h, hejsan), 832 {error, bad_module} = gen_event:call(my_dummy_handler, bad_h, hejsan), 833 {error, bad_module} = Async(my_dummy_handler, bad_h, hejsan), 834 835 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan), 836 {reply, {ok, hejhopp}} = Async(my_dummy_handler, dummy_h, hejsan), 837 {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h, 1}, hejsan), 838 {reply, {ok, hejhopp}} = Async(my_dummy_handler, {dummy_h, 1}, hejsan), 839 {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h, 1}, hejsan), 840 {reply, {ok, hejhopp}} = Async(my_dummy_handler, {dummy_h, 1}, hejsan), 841 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan, 10000), 842 {'EXIT', {timeout, _}} = 843 (catch gen_event:call(my_dummy_handler, dummy_h, hejsan, 0)), 844 flush(), 845 P1 = gen_event:send_request(my_dummy_handler, dummy_h, hejsan), 846 timeout = gen_event:wait_response(P1, 0), 847 {reply, {ok, hejhopp}} = gen_event:wait_response(P1, infinity), 848 849 flush(), 850 P2 = gen_event:send_request(my_dummy_handler, dummy_h, hejsan), 851 no_reply = gen_event:check_response({other,msg}, P2), 852 {reply, {ok, hejhopp}} = receive Msg -> gen_event:check_response(Msg, P2) 853 after 1000 -> exit(tmo) end, 854 855 ok = gen_event:delete_handler(my_dummy_handler, {dummy_h, 1}, []), 856 {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h, 857 {swap_call,dummy1_h,swap}), 858 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 859 {error, bad_module} = gen_event:call(my_dummy_handler, dummy_h, hejsan), 860 {error, bad_module} = Async(my_dummy_handler, dummy_h, hejsan), 861 ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call), 862 receive 863 {dummy1_h, removed} -> 864 ok 865 end, 866 [] = gen_event:which_handlers(my_dummy_handler), 867 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 868 869 {error, {return, faulty}} = 870 gen_event:call(my_dummy_handler, dummy_h, error_call), 871 receive 872 {dummy_h, returned_error} -> 873 ok 874 end, 875 [] = gen_event:which_handlers(my_dummy_handler), 876 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 877 878 {error, {'EXIT', _}} = 879 gen_event:call(my_dummy_handler, dummy_h, exit_call), 880 881 [] = gen_event:which_handlers(my_dummy_handler), 882 883 %% Handler with id, {Mod,Id} 884 885 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 886 [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler), 887 {error, bad_module} = 888 gen_event:call(my_dummy_handler, bad_h, hejsan), 889 {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h,1}, 890 hejsan), 891 {ok, swapped} = gen_event:call(my_dummy_handler, {dummy_h,1}, 892 {swap_call,{dummy1_h,2},swap}), 893 [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), 894 {error, bad_module} = 895 gen_event:call(my_dummy_handler, dummy_h, hejsan), 896 ok = gen_event:call(my_dummy_handler, {dummy1_h,2}, delete_call), 897 receive 898 {dummy1_h, removed} -> 899 ok 900 end, 901 [] = gen_event:which_handlers(my_dummy_handler), 902 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 903 904 {error, {return, faulty}} = 905 gen_event:call(my_dummy_handler, {dummy_h,3}, error_call), 906 receive 907 {dummy_h, returned_error} -> 908 ok 909 end, 910 [] = gen_event:which_handlers(my_dummy_handler), 911 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,4}, [self()]), 912 913 {error, {'EXIT', _}} = 914 gen_event:call(my_dummy_handler, {dummy_h,4}, exit_call), 915 916 [] = gen_event:which_handlers(my_dummy_handler), 917 918 %% Supervised handler. 919 920 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 921 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 922 {error, bad_module} = 923 gen_event:call(my_dummy_handler, bad_h, hejsan), 924 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan), 925 {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h, 926 {swap_call,dummy1_h,swap}), 927 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 928 {error, bad_module} = 929 gen_event:call(my_dummy_handler, dummy_h, hejsan), 930 ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call), 931 receive 932 {dummy1_h, removed} -> 933 ok 934 end, 935 936 receive 937 {gen_event_EXIT, dummy1_h, normal} -> 938 ok 939 end, 940 941 [] = gen_event:which_handlers(my_dummy_handler), 942 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 943 944 {error, {return, faulty}} = 945 gen_event:call(my_dummy_handler, dummy_h, error_call), 946 receive 947 {dummy_h, returned_error} -> 948 ok 949 end, 950 951 receive 952 {gen_event_EXIT, dummy_h, {return,faulty}} -> 953 ok 954 after 1000 -> 955 ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}}) 956 end, 957 958 [] = gen_event:which_handlers(my_dummy_handler), 959 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 960 961 {error, {'EXIT', _}} = 962 gen_event:call(my_dummy_handler, dummy_h, exit_call), 963 964 receive 965 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 966 ok 967 after 1000 -> 968 ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}}) 969 end, 970 971 [] = gen_event:which_handlers(my_dummy_handler), 972 973 ok = gen_event:stop(my_dummy_handler), 974 ok. 975 976flush() -> 977 receive _ -> flush() after 0 -> ok end. 978 979info(Config) when is_list(Config) -> 980 {ok,_} = gen_event:start({local, my_dummy_handler}), 981 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 982 Info = {info, self()}, 983 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 984 my_dummy_handler ! Info, 985 receive 986 {dummy_h, Info} -> 987 ok 988 end, 989 my_dummy_handler ! {swap_info,dummy1_h,swap}, 990 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 991 my_dummy_handler ! Info, 992 receive 993 {dummy1_h, Info} -> 994 ok 995 end, 996 my_dummy_handler ! delete_info, 997 receive 998 {dummy1_h, removed} -> 999 ok 1000 end, 1001 [] = gen_event:which_handlers(my_dummy_handler), 1002 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 1003 1004 my_dummy_handler ! error_info, 1005 receive 1006 {dummy_h, returned_error} -> 1007 ok 1008 end, 1009 [] = gen_event:which_handlers(my_dummy_handler), 1010 1011 %% Handler with id, {Mod,Id} 1012 1013 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 1014 [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler), 1015 my_dummy_handler ! Info, 1016 receive 1017 {dummy_h, Info} -> 1018 ok 1019 end, 1020 my_dummy_handler ! {swap_info,{dummy1_h,2},swap}, 1021 [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), 1022 my_dummy_handler ! Info, 1023 receive 1024 {dummy1_h, Info} -> 1025 ok 1026 end, 1027 my_dummy_handler ! delete_info, 1028 receive 1029 {dummy1_h, removed} -> 1030 ok 1031 end, 1032 [] = gen_event:which_handlers(my_dummy_handler), 1033 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 1034 1035 my_dummy_handler ! error_info, 1036 receive 1037 {dummy_h, returned_error} -> 1038 ok 1039 end, 1040 [] = gen_event:which_handlers(my_dummy_handler), 1041 1042 %% Supervised handler 1043 1044 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 1045 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 1046 my_dummy_handler ! Info, 1047 receive 1048 {dummy_h, Info} -> 1049 ok 1050 end, 1051 my_dummy_handler ! {swap_info,dummy1_h,swap}, 1052 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 1053 my_dummy_handler ! Info, 1054 receive 1055 {dummy1_h, Info} -> 1056 ok 1057 end, 1058 my_dummy_handler ! delete_info, 1059 receive 1060 {dummy1_h, removed} -> 1061 ok 1062 end, 1063 1064 receive 1065 {gen_event_EXIT, dummy1_h, normal} -> 1066 ok 1067 after 1000 -> 1068 ct:fail({no, {gen_event_EXIT, dummy1_h, normal}}) 1069 end, 1070 1071 [] = gen_event:which_handlers(my_dummy_handler), 1072 1073 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 1074 1075 my_dummy_handler ! error_info, 1076 receive 1077 {dummy_h, returned_error} -> 1078 ok 1079 end, 1080 1081 receive 1082 {gen_event_EXIT, dummy_h, {return,faulty}} -> 1083 ok 1084 after 1000 -> 1085 ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}}) 1086 end, 1087 1088 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 1089 my_dummy_handler ! do_crash, 1090 1091 receive 1092 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 1093 ok 1094 after 1000 -> 1095 ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}}) 1096 end, 1097 1098 [] = gen_event:which_handlers(my_dummy_handler), 1099 1100 ok = gen_event:stop(my_dummy_handler), 1101 ok. 1102 1103%% Test that sys:get_status/1,2 calls format_status/2. 1104call_format_status(Config) when is_list(Config) -> 1105 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1106 %% State here intentionally differs from what we expect from format_status 1107 State = self(), 1108 FmtState = "dummy1_h handler state", 1109 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State]), 1110 Status1 = sys:get_status(Pid), 1111 Status2 = sys:get_status(Pid, 5000), 1112 ok = gen_event:stop(Pid), 1113 {status, Pid, _, [_, _, Pid, [], Data1]} = Status1, 1114 HandlerInfo1 = proplists:get_value(items, Data1), 1115 {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo1, 1116 {status, Pid, _, [_, _, Pid, [], Data2]} = Status2, 1117 HandlerInfo2 = proplists:get_value(items, Data2), 1118 {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2, 1119 ok. 1120 1121%% Test that sys:get_status/1,2 calls format_status/2 for anonymous 1122%% gen_event processes. 1123call_format_status_anon(Config) when is_list(Config) -> 1124 {ok, Pid} = gen_event:start(), 1125 %% The 'Name' of the gen_event process will be a pid() here, so 1126 %% the next line will crash if format_status can't string-ify pids. 1127 Status1 = sys:get_status(Pid), 1128 ok = gen_event:stop(Pid), 1129 Header = "Status for event handler " ++ pid_to_list(Pid), 1130 {status, Pid, _, [_, _, Pid, [], Data1]} = Status1, 1131 Header = proplists:get_value(header, Data1), 1132 ok. 1133 1134 1135%% Test that a handler error calls format_status/2. 1136error_format_status(Config) when is_list(Config) -> 1137 error_logger_forwarder:register(), 1138 OldFl = process_flag(trap_exit, true), 1139 State = self(), 1140 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1141 ok = gen_event:add_sup_handler(my_dummy_handler, dummy1_h, [State]), 1142 ok = gen_event:notify(my_dummy_handler, do_crash), 1143 receive 1144 {gen_event_EXIT,dummy1_h,{'EXIT',_}} -> ok 1145 after 5000 -> 1146 ct:fail(exit_gen_event) 1147 end, 1148 FmtState = "dummy1_h handler state", 1149 receive 1150 {error,_GroupLeader, {Pid, 1151 "** gen_event handler"++_, 1152 [dummy1_h,my_dummy_handler,do_crash, 1153 FmtState, _]}} -> 1154 ok; 1155 Other -> 1156 io:format("Unexpected: ~p", [Other]), 1157 ct:fail(failed) 1158 end, 1159 ok = gen_event:stop(Pid), 1160 process_flag(trap_exit, OldFl), 1161 ok. 1162 1163%% Test that sys:get_state/1,2 return the gen_event state. 1164get_state(Config) when is_list(Config) -> 1165 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1166 State1 = self(), 1167 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), 1168 [{dummy1_h,false,State1}] = sys:get_state(Pid), 1169 [{dummy1_h,false,State1}] = sys:get_state(Pid, 5000), 1170 State2 = {?MODULE, self()}, 1171 ok = gen_event:add_handler(my_dummy_handler, {dummy1_h,id}, [State2]), 1172 Result1 = sys:get_state(Pid), 1173 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result1), 1174 Result2 = sys:get_state(Pid, 5000), 1175 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result2), 1176 ok = sys:suspend(Pid), 1177 Result3 = sys:get_state(Pid), 1178 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result3), 1179 ok = sys:resume(Pid), 1180 ok = gen_event:stop(Pid), 1181 ok. 1182 1183%% Test that replace_state/2,3 replace the gen_event state. 1184replace_state(Config) when is_list(Config) -> 1185 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1186 State1 = self(), 1187 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), 1188 [{dummy1_h,false,State1}] = sys:get_state(Pid), 1189 NState1 = "replaced", 1190 Replace1 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState1) end, 1191 [{dummy1_h,false,NState1}] = sys:replace_state(Pid, Replace1), 1192 [{dummy1_h,false,NState1}] = sys:get_state(Pid), 1193 NState2 = "replaced again", 1194 Replace2 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState2) end, 1195 [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace2, 5000), 1196 [{dummy1_h,false,NState2}] = sys:get_state(Pid), 1197 %% verify no change in state if replace function crashes 1198 Replace3 = fun(_) -> exit(fail) end, 1199 [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace3), 1200 [{dummy1_h,false,NState2}] = sys:get_state(Pid), 1201 %% verify state replaced if process sys suspended 1202 NState3 = "replaced again and again", 1203 Replace4 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState3) end, 1204 ok = sys:suspend(Pid), 1205 [{dummy1_h,false,NState3}] = sys:replace_state(Pid, Replace4), 1206 ok = sys:resume(Pid), 1207 [{dummy1_h,false,NState3}] = sys:get_state(Pid), 1208 ok. 1209 1210%% No default provided for init, so it should fail 1211undef_init(Config) -> 1212 Pid = ?config(event_pid, Config), 1213 {'EXIT', {undef, [{oc_init_event, init, [_], _}|_]}} 1214 = gen_event:add_handler(Pid, oc_init_event, []), 1215 ok. 1216 1217%% No default provided for init, so it should fail 1218undef_handle_call(Config) when is_list(Config) -> 1219 Pid = ?config(event_pid, Config), 1220 {error, {'EXIT', {undef, [{oc_event, handle_call, _, _}|_]}}} 1221 = gen_event:call(Pid, oc_event, call_msg), 1222 [] = gen_event:which_handlers(Pid), 1223 ok. 1224 1225%% No default provided for init, so it should fail 1226undef_handle_event(Config) -> 1227 Pid = ?config(event_pid, Config), 1228 ok = gen_event:sync_notify(Pid, event_msg), 1229 [] = gen_event:which_handlers(Pid), 1230 1231 gen_event:add_handler(oc_event, oc_event, []), 1232 [oc_event] = gen_event:which_handlers(Pid), 1233 1234 ok = gen_event:notify(Pid, event_msg), 1235 [] = gen_event:which_handlers(Pid), 1236 ok. 1237 1238%% Defaulting to doing nothing with a log warning. 1239undef_handle_info(Config) when is_list(Config) -> 1240 error_logger_forwarder:register(), 1241 Pid = ?config(event_pid, Config), 1242 Pid ! hej, 1243 wait_until_processed(Pid, hej, 10), 1244 [oc_event] = gen_event:which_handlers(Pid), 1245 receive 1246 {warning_msg, _GroupLeader, 1247 {Pid, "** Undefined handle_info in " ++ _, [oc_event, hej]}} -> 1248 ok; 1249 Other -> 1250 io:format("Unexpected: ~p", [Other]), 1251 ct:fail(failed) 1252 end. 1253 1254wait_until_processed(_Pid, _Message, 0) -> 1255 ct:fail(not_processed); 1256wait_until_processed(Pid, Message, N) -> 1257 {messages, Messages} = erlang:process_info(Pid, messages), 1258 case lists:member(Message, Messages) of 1259 true -> 1260 timer:sleep(100), 1261 wait_until_processed(Pid, Message, N-1); 1262 false -> 1263 ok 1264 end. 1265 1266%% No default provided for init, so it should fail 1267undef_code_change(Config) when is_list(Config) -> 1268 Pid = ?config(event_pid, Config), 1269 {error, {'EXIT', {undef, [{oc_event, code_change, [_, _, _], _}|_]}}} = 1270 fake_upgrade(Pid, oc_event), 1271 [oc_event] = gen_event:which_handlers(Pid), 1272 ok. 1273 1274%% Defaulting to doing nothing. Test that it works when not defined. 1275undef_terminate(Config) when is_list(Config) -> 1276 Pid = ?config(event_pid, Config), 1277 ok = gen_event:delete_handler(Pid, oc_event, []), 1278 [] = gen_event:which_handlers(Pid), 1279 ok. 1280 1281%% Test that the default implementation doesn't catch the wrong undef error 1282undef_in_terminate(_Config) -> 1283 {ok, Pid} = gen_event:start({local, dummy}), 1284 State = {undef_in_terminate, {dummy_h, terminate}}, 1285 ok = gen_event:add_handler(Pid, dummy_h, {state, State}), 1286 [dummy_h] = gen_event:which_handlers(Pid), 1287 {'EXIT', {undef, [{dummy_h, terminate, [], []}|_]}} 1288 = gen_event:delete_handler(Pid, dummy_h, []), 1289 [] = gen_event:which_handlers(Pid), 1290 ok. 1291 1292fake_upgrade(Pid, Mod) -> 1293 sys:suspend(Pid), 1294 sys:replace_state(Pid, fun(S) -> {new, S} end), 1295 Ret = sys:change_code(Pid, Mod, old_vsn, []), 1296 ok = sys:resume(Pid), 1297 Ret. 1298 1299%% Test report callback for Logger handler error_logger 1300format_log_1(_Config) -> 1301 FD = application:get_env(kernel, error_logger_format_depth), 1302 application:unset_env(kernel, error_logger_format_depth), 1303 Term = lists:seq(1, 15), 1304 Handler = my_handler, 1305 Name = self(), 1306 Report = #{label=>{gen_event,terminate}, 1307 handler=>Handler, 1308 name=>Name, 1309 last_message=>Term, 1310 state=>Term, 1311 reason=>Term}, 1312 {F1, A1} = gen_event:format_log(Report), 1313 FExpected1 = "** gen_event handler ~tp crashed.\n" 1314 "** Was installed in ~tp\n" 1315 "** Last event was: ~tp\n" 1316 "** When handler state == ~tp\n" 1317 "** Reason == ~tp\n", 1318 ct:log("F1: ~ts~nA1: ~tp", [F1,A1]), 1319 FExpected1 = F1, 1320 [Handler,Name,Term,Term,Term] = A1, 1321 1322 Warning = #{label=>{gen_event,no_handle_info}, 1323 module=>?MODULE, 1324 message=>Term}, 1325 {WF1,WA1} = gen_event:format_log(Warning), 1326 WFExpected1 = "** Undefined handle_info in ~p\n" 1327 "** Unhandled message: ~tp\n", 1328 ct:log("WF1: ~ts~nWA1: ~tp", [WF1,WA1]), 1329 WFExpected1 = WF1, 1330 [?MODULE,Term] = WA1, 1331 1332 Depth = 10, 1333 ok = application:set_env(kernel, error_logger_format_depth, Depth), 1334 Limited = [1,2,3,4,5,6,7,8,9,'...'], 1335 {F2,A2} = gen_event:format_log(#{label=>{gen_event,terminate}, 1336 handler=>Handler, 1337 name=>Name, 1338 last_message=>Term, 1339 state=>Term, 1340 reason=>Term}), 1341 FExpected2 = "** gen_event handler ~tP crashed.\n" 1342 "** Was installed in ~tP\n" 1343 "** Last event was: ~tP\n" 1344 "** When handler state == ~tP\n" 1345 "** Reason == ~tP\n", 1346 ct:log("F2: ~ts~nA2: ~tp", [F2,A2]), 1347 FExpected2 = F2, 1348 [Handler,Depth,Name,Depth,Limited,Depth,Limited,Depth,Limited,Depth] = A2, 1349 1350 {WF2,WA2} = gen_event:format_log(Warning), 1351 WFExpected2 = "** Undefined handle_info in ~p\n" 1352 "** Unhandled message: ~tP\n", 1353 ct:log("WF2: ~ts~nWA2: ~tp", [WF2,WA2]), 1354 WFExpected2 = WF2, 1355 [?MODULE,Limited,Depth] = WA2, 1356 1357 case FD of 1358 undefined -> 1359 application:unset_env(kernel, error_logger_format_depth); 1360 _ -> 1361 application:set_env(kernel, error_logger_format_depth, FD) 1362 end, 1363 ok. 1364 1365%% Test report callback for any Logger handler 1366format_log_2(_Config) -> 1367 Term = lists:seq(1, 15), 1368 Handler = my_handler, 1369 Name = self(), 1370 NameStr = pid_to_list(Name), 1371 Report = #{label=>{gen_event,terminate}, 1372 handler=>Handler, 1373 name=>Name, 1374 last_message=>Term, 1375 state=>Term, 1376 reason=>Term}, 1377 FormatOpts1 = #{}, 1378 Str1 = flatten_format_log(Report, FormatOpts1), 1379 L1 = length(Str1), 1380 Expected1 = "** gen_event handler my_handler crashed.\n" 1381 "** Was installed in "++NameStr++"\n" 1382 "** Last event was: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]\n" 1383 "** When handler state == [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]\n" 1384 "** Reason == [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]\n", 1385 ct:log("Str1: ~ts", [Str1]), 1386 ct:log("length(Str1): ~p", [L1]), 1387 true = Expected1 =:= Str1, 1388 1389 Warning = #{label=>{gen_event,no_handle_info}, 1390 module=>?MODULE, 1391 message=>Term}, 1392 WStr1 = flatten_format_log(Warning, FormatOpts1), 1393 WL1 = length(WStr1), 1394 WExpected1 = "** Undefined handle_info in gen_event_SUITE\n" 1395 "** Unhandled message: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]\n", 1396 ct:log("WStr1: ~ts", [WStr1]), 1397 ct:log("length(WStr1): ~p", [WL1]), 1398 true = WExpected1 =:= WStr1, 1399 1400 Depth = 10, 1401 FormatOpts2 = #{depth=>Depth}, 1402 Str2 = flatten_format_log(Report, FormatOpts2), 1403 L2 = length(Str2), 1404 Expected2 = "** gen_event handler my_handler crashed.\n" 1405 "** Was installed in " ++ NameStr ++ "\n" 1406 "** Last event was: [1,2,3,4,5,6,7,8,9|...]\n" 1407 "** When handler state == [1,2,3,4,5,6,7,8,9|...]\n" 1408 "** Reason == [1,2,3,4,5,6,7,8,9|...]\n", 1409 ct:log("Str2: ~ts", [Str2]), 1410 ct:log("length(Str2): ~p", [L2]), 1411 true = Expected2 =:= Str2, 1412 1413 WStr2 = flatten_format_log(Warning, FormatOpts2), 1414 WL2 = length(WStr2), 1415 WExpected2 = "** Undefined handle_info in gen_event_SUITE\n" 1416 "** Unhandled message: [1,2,3,4,5,6,7,8,9|...]\n", 1417 ct:log("WStr2: ~ts", [WStr2]), 1418 ct:log("length(WStr2): ~p", [WL2]), 1419 true = WExpected2 =:= WStr2, 1420 1421 FormatOpts3 = #{chars_limit=>200}, 1422 Str3 = flatten_format_log(Report, FormatOpts3), 1423 L3 = length(Str3), 1424 Expected3 = "** gen_event handler my_handler crashed.\n" 1425 "** Was installed", 1426 ct:log("Str3: ~ts", [Str3]), 1427 ct:log("length(Str3): ~p", [L3]), 1428 true = lists:prefix(Expected3, Str3), 1429 true = L3 < L1, 1430 1431 WFormatOpts3 = #{chars_limit=>80}, 1432 WStr3 = flatten_format_log(Warning, WFormatOpts3), 1433 WL3 = length(WStr3), 1434 WExpected3 = "** Undefined handle_info in gen_event_SUITE\n" 1435 "** Unhandled message: ", 1436 ct:log("WStr3: ~ts", [WStr3]), 1437 ct:log("length(WStr3): ~p", [WL3]), 1438 true = lists:prefix(WExpected3, WStr3), 1439 true = WL3 < WL1, 1440 1441 FormatOpts4 = #{single_line=>true}, 1442 Str4 = flatten_format_log(Report, FormatOpts4), 1443 L4 = length(Str4), 1444 1445 Expected4 = "Generic event handler my_handler crashed. " 1446 "Installed: "++NameStr++". " 1447 "Last event: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]. " 1448 "State: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]. " 1449 "Reason: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].", 1450 ct:log("Str4: ~ts", [Str4]), 1451 ct:log("length(Str4): ~p", [L4]), 1452 true = Expected4 =:= Str4, 1453 1454 WStr4 = flatten_format_log(Warning, FormatOpts4), 1455 WL4 = length(WStr4), 1456 WExpected4 = "Undefined handle_info in gen_event_SUITE. " 1457 "Unhandled message: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].", 1458 ct:log("WStr4: ~ts", [WStr4]), 1459 ct:log("length(WStr4): ~p", [WL4]), 1460 true = WExpected4 =:= WStr4, 1461 1462 FormatOpts5 = #{single_line=>true, depth=>Depth}, 1463 Str5 = flatten_format_log(Report, FormatOpts5), 1464 L5 = length(Str5), 1465 Expected5 = "Generic event handler my_handler crashed. " 1466 "Installed: "++NameStr++". " 1467 "Last event: [1,2,3,4,5,6,7,8,9|...]. " 1468 "State: [1,2,3,4,5,6,7,8,9|...]. " 1469 "Reason: [1,2,3,4,5,6,7,8,9|...].", 1470 ct:log("Str5: ~ts", [Str5]), 1471 ct:log("length(Str5): ~p", [L5]), 1472 true = Expected5 =:= Str5, 1473 1474 WStr5 = flatten_format_log(Warning, FormatOpts5), 1475 WL5 = length(WStr5), 1476 WExpected5 = "Undefined handle_info in gen_event_SUITE. " 1477 "Unhandled message: [1,2,3,4,5,6,7,8,9|...].", 1478 ct:log("WStr5: ~ts", [WStr5]), 1479 ct:log("length(WStr5): ~p", [WL5]), 1480 true = WExpected5 =:= WStr5, 1481 1482 FormatOpts6 = #{single_line=>true, chars_limit=>200}, 1483 Str6 = flatten_format_log(Report, FormatOpts6), 1484 L6 = length(Str6), 1485 Expected6 = "Generic event handler my_handler crashed. Installed: ", 1486 ct:log("Str6: ~ts", [Str6]), 1487 ct:log("length(Str6): ~p", [L6]), 1488 true = lists:prefix(Expected6, Str6), 1489 true = L6 < L4, 1490 1491 WFormatOpts6 = #{single_line=>true, chars_limit=>80}, 1492 WStr6 = flatten_format_log(Warning, WFormatOpts6), 1493 WL6 = length(WStr6), 1494 WExpected6 = "Undefined handle_info in gen_event_SUITE. ", 1495 ct:log("WStr6: ~ts", [WStr6]), 1496 ct:log("length(WStr6): ~p", [WL6]), 1497 true = lists:prefix(WExpected6, WStr6), 1498 true = WL6 < WL4, 1499 1500 ok. 1501 1502flatten_format_log(Report, Format) -> 1503 lists:flatten(gen_event:format_log(Report, Format)). 1504