1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2017. 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]). 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 45groups() -> 46 [{test_all, [], 47 [add_handler, add_sup_handler, delete_handler, 48 swap_handler, swap_sup_handler, notify, sync_notify, 49 call, info]}, 50 {undef_callbacks, [], 51 [undef_init, undef_handle_call, undef_handle_event, undef_handle_info, 52 undef_code_change, undef_terminate]}]. 53 54init_per_suite(Config) -> 55 Config. 56 57end_per_suite(_Config) -> 58 ok. 59 60init_per_group(undef_callbacks, Config) -> 61 DataDir = ?config(data_dir, Config), 62 Event1 = filename:join(DataDir, "oc_event.erl"), 63 {ok, oc_event} = compile:file(Event1), 64 Config; 65init_per_group(_GroupName, Config) -> 66 Config. 67 68end_per_group(_GroupName, Config) -> 69 Config. 70 71init_per_testcase(Case, Config) when Case == undef_handle_call; 72 Case == undef_handle_info; 73 Case == undef_handle_event; 74 Case == undef_code_change; 75 Case == undef_terminate -> 76 {ok, Pid} = oc_event:start(), 77 [{event_pid, Pid}|Config]; 78init_per_testcase(undef_init, Config) -> 79 {ok, Pid} = gen_event:start({local, oc_init_event}), 80 [{event_pid, Pid}|Config]; 81init_per_testcase(_Case, Config) -> 82 Config. 83 84end_per_testcase(Case, Config) when Case == undef_init; 85 Case == undef_handle_call; 86 Case == undef_handle_info; 87 Case == undef_handle_event; 88 Case == undef_code_change; 89 Case == undef_terminate -> 90 Pid = ?config(event_pid, Config), 91 gen_event:stop(Pid); 92end_per_testcase(_Case, _Config) -> 93 ok. 94 95%% -------------------------------------- 96%% Start an event manager. 97%% -------------------------------------- 98 99-define(LMGR, {local, my_dummy_name}). 100-define(GMGR, {global, my_dummy_name}). 101 102start(Config) when is_list(Config) -> 103 OldFl = process_flag(trap_exit, true), 104 105 dummy_via:reset(), 106 107 {ok, Pid0} = gen_event:start(), %anonymous 108 [] = gen_event:which_handlers(Pid0), 109 ok = gen_event:stop(Pid0), 110 111 {ok, Pid1} = gen_event:start_link(), %anonymous 112 [] = gen_event:which_handlers(Pid1), 113 ok = gen_event:stop(Pid1), 114 115 {ok, Pid2} = gen_event:start(?LMGR), 116 [] = gen_event:which_handlers(my_dummy_name), 117 [] = gen_event:which_handlers(Pid2), 118 ok = gen_event:stop(my_dummy_name), 119 120 {ok, Pid3} = gen_event:start_link(?LMGR), 121 [] = gen_event:which_handlers(my_dummy_name), 122 [] = gen_event:which_handlers(Pid3), 123 ok = gen_event:stop(my_dummy_name), 124 125 {ok, Pid4} = gen_event:start_link(?GMGR), 126 [] = gen_event:which_handlers(?GMGR), 127 [] = gen_event:which_handlers(Pid4), 128 ok = gen_event:stop(?GMGR), 129 130 {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}), 131 [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}), 132 [] = gen_event:which_handlers(Pid5), 133 ok = gen_event:stop({via, dummy_via, my_dummy_name}), 134 135 {ok, _} = gen_event:start_link(?LMGR), 136 {error, {already_started, _}} = gen_event:start_link(?LMGR), 137 {error, {already_started, _}} = gen_event:start(?LMGR), 138 ok = gen_event:stop(my_dummy_name), 139 140 {ok, Pid6} = gen_event:start_link(?GMGR), 141 {error, {already_started, _}} = gen_event:start_link(?GMGR), 142 {error, {already_started, _}} = gen_event:start(?GMGR), 143 144 ok = gen_event:stop(?GMGR, shutdown, 10000), 145 receive 146 {'EXIT', Pid6, shutdown} -> ok 147 after 10000 -> 148 ct:fail(exit_gen_event) 149 end, 150 151 {ok, Pid7} = gen_event:start_link({via, dummy_via, my_dummy_name}), 152 {error, {already_started, _}} = gen_event:start_link({via, dummy_via, my_dummy_name}), 153 {error, {already_started, _}} = gen_event:start({via, dummy_via, my_dummy_name}), 154 155 exit(Pid7, shutdown), 156 receive 157 {'EXIT', Pid7, shutdown} -> ok 158 after 10000 -> 159 ct:fail(exit_gen_event) 160 end, 161 162 process_flag(trap_exit, OldFl), 163 ok. 164 165start_opt(Config) when is_list(Config) -> 166 OldFl = process_flag(trap_exit, true), 167 168 dummy_via:reset(), 169 170 {ok, Pid0} = gen_event:start([]), %anonymous 171 [] = gen_event:which_handlers(Pid0), 172 ok = gen_event:stop(Pid0), 173 174 {ok, Pid1} = gen_event:start_link([]), %anonymous 175 [] = gen_event:which_handlers(Pid1), 176 ok = gen_event:stop(Pid1), 177 178 {ok, Pid2} = gen_event:start(?LMGR, []), 179 [] = gen_event:which_handlers(my_dummy_name), 180 [] = gen_event:which_handlers(Pid2), 181 ok = gen_event:stop(my_dummy_name), 182 183 {ok, Pid3} = gen_event:start_link(?LMGR, []), 184 [] = gen_event:which_handlers(my_dummy_name), 185 [] = gen_event:which_handlers(Pid3), 186 ok = gen_event:stop(my_dummy_name), 187 188 {ok, Pid4} = gen_event:start_link(?GMGR, []), 189 [] = gen_event:which_handlers(?GMGR), 190 [] = gen_event:which_handlers(Pid4), 191 ok = gen_event:stop(?GMGR), 192 193 {ok, Pid5} = gen_event:start_link({via, dummy_via, my_dummy_name}, []), 194 [] = gen_event:which_handlers({via, dummy_via, my_dummy_name}), 195 [] = gen_event:which_handlers(Pid5), 196 ok = gen_event:stop({via, dummy_via, my_dummy_name}), 197 198 {ok, _} = gen_event:start_link(?LMGR, []), 199 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 200 {error, {already_started, _}} = gen_event:start(?LMGR, []), 201 ok = gen_event:stop(my_dummy_name), 202 203 {ok, Pid7} = gen_event:start_link(?GMGR), 204 {error, {already_started, _}} = gen_event:start_link(?GMGR, []), 205 {error, {already_started, _}} = gen_event:start(?GMGR, []), 206 207 ok = gen_event:stop(?GMGR, shutdown, 10000), 208 receive 209 {'EXIT', Pid7, shutdown} -> ok 210 after 10000 -> 211 ct:fail(exit_gen_event) 212 end, 213 214 {ok, Pid8} = gen_event:start_link({via, dummy_via, my_dummy_name}), 215 {error, {already_started, _}} = gen_event:start_link({via, dummy_via, my_dummy_name}, []), 216 {error, {already_started, _}} = gen_event:start({via, dummy_via, my_dummy_name}, []), 217 218 exit(Pid8, shutdown), 219 receive 220 {'EXIT', Pid8, shutdown} -> ok 221 after 10000 -> 222 ct:fail(exit_gen_event) 223 end, 224 225 %% test spawn_opt 226 MinHeapSz = 10000, 227 {ok, Pid9} = gen_event:start_link(?LMGR, [{spawn_opt, [{min_heap_size, MinHeapSz}]}]), 228 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 229 {error, {already_started, _}} = gen_event:start(?LMGR, []), 230 {heap_size, HeapSz} = erlang:process_info(Pid9, heap_size), 231 true = HeapSz > MinHeapSz, 232 ok = gen_event:stop(my_dummy_name), 233 234 %% test debug opt 235 {ok, _} = gen_event:start_link(?LMGR, [{debug,[debug]}]), 236 {error, {already_started, _}} = gen_event:start_link(?LMGR, []), 237 {error, {already_started, _}} = gen_event:start(?LMGR, []), 238 ok = gen_event:stop(my_dummy_name), 239 240 process_flag(trap_exit, OldFl), 241 ok. 242 243hibernate(Config) when is_list(Config) -> 244 {ok,Pid} = gen_event:start({local, my_dummy_handler}), 245 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 246 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 247 true = gen_event:call(my_dummy_handler, dummy_h, hibernate), 248 is_in_erlang_hibernate(Pid), 249 250 Pid ! wake, 251 is_not_in_erlang_hibernate(Pid), 252 later = gen_event:call(my_dummy_handler, dummy_h, hibernate_later), 253 true = ({current_function,{erlang,hibernate,3}} =/= 254 erlang:process_info(Pid, current_function)), 255 is_in_erlang_hibernate(Pid), 256 257 Pid ! wake, 258 is_not_in_erlang_hibernate(Pid), 259 gen_event:notify(my_dummy_handler, hibernate), 260 is_in_erlang_hibernate(Pid), 261 gen_event:notify(my_dummy_handler, wakeup), 262 is_not_in_erlang_hibernate(Pid), 263 gen_event:notify(my_dummy_handler, hibernate), 264 is_in_erlang_hibernate(Pid), 265 gen_event:sync_notify(my_dummy_handler, wakeup), 266 true = ({current_function,{erlang,hibernate,3}} =/= 267 erlang:process_info(Pid, current_function)), 268 ok = gen_event:sync_notify(my_dummy_handler, hibernate), 269 is_in_erlang_hibernate(Pid), 270 271 Pid ! wake, 272 is_not_in_erlang_hibernate(Pid), 273 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [self()]), 274 [_,_] = gen_event:which_handlers(my_dummy_handler), 275 gen_event:notify(my_dummy_handler, hibernate), 276 is_in_erlang_hibernate(Pid), 277 gen_event:notify(my_dummy_handler, wakeup), 278 is_in_erlang_hibernate(Pid), 279 280 Pid ! wake, 281 is_not_in_erlang_hibernate(Pid), 282 283 Pid ! gnurf, 284 is_in_erlang_hibernate(Pid), 285 286 Pid ! sleep, 287 is_in_erlang_hibernate(Pid), 288 289 Pid ! wake, 290 is_not_in_erlang_hibernate(Pid), 291 ok = gen_event:stop(my_dummy_handler), 292 293 {ok,Pid2} = gen_event:start({local, my_dummy_handler}), 294 ok = gen_event:add_handler(my_dummy_handler, dummy_h, 295 [self(),hibernate]), 296 is_in_erlang_hibernate(Pid2), 297 sys:suspend(my_dummy_handler), 298 is_in_erlang_hibernate(Pid2), 299 sys:resume(my_dummy_handler), 300 is_in_erlang_hibernate(Pid2), 301 302 Pid2 ! wake, 303 is_not_in_erlang_hibernate(Pid2), 304 305 ok = gen_event:stop(my_dummy_handler), 306 307 ok. 308 309auto_hibernate(Config) when is_list(Config) -> 310 HibernateAfterTimeout = 100, 311 State = {auto_hibernate_state}, 312 {ok,Pid} = gen_event:start({local, auto_hibernate_handler}, [{hibernate_after, HibernateAfterTimeout}]), 313 %% After init test 314 is_not_in_erlang_hibernate(Pid), 315 timer:sleep(HibernateAfterTimeout), 316 is_in_erlang_hibernate(Pid), 317 ok = gen_event:add_handler(auto_hibernate_handler, dummy_h, [State]), 318 %% Get state test 319 [{dummy_h,false,State}] = sys:get_state(Pid), 320 is_in_erlang_hibernate(Pid), 321 %% Call test 322 {ok, hejhopp} = gen_event:call(auto_hibernate_handler, dummy_h, hejsan), 323 is_not_in_erlang_hibernate(Pid), 324 timer:sleep(HibernateAfterTimeout), 325 is_in_erlang_hibernate(Pid), 326 %% Event test 327 ok = gen_event:notify(auto_hibernate_handler, {self(), handle_event}), 328 receive 329 handled_event -> 330 ok 331 after 1000 -> 332 ct:fail(event) 333 end, 334 is_not_in_erlang_hibernate(Pid), 335 timer:sleep(HibernateAfterTimeout), 336 is_in_erlang_hibernate(Pid), 337 %% Info test 338 Pid ! {self(), handle_info}, 339 receive 340 handled_info -> 341 ok 342 after 1000 -> 343 ct:fail(info) 344 end, 345 is_not_in_erlang_hibernate(Pid), 346 timer:sleep(HibernateAfterTimeout), 347 is_in_erlang_hibernate(Pid), 348 ok = gen_event:stop(auto_hibernate_handler), 349 ok. 350 351is_in_erlang_hibernate(Pid) -> 352 receive after 1 -> ok end, 353 is_in_erlang_hibernate_1(200, Pid). 354 355is_in_erlang_hibernate_1(0, Pid) -> 356 io:format("~p\n", [erlang:process_info(Pid, current_function)]), 357 ct:fail(not_in_erlang_hibernate_3); 358is_in_erlang_hibernate_1(N, Pid) -> 359 {current_function,MFA} = erlang:process_info(Pid, current_function), 360 case MFA of 361 {erlang,hibernate,3} -> 362 ok; 363 _ -> 364 receive after 10 -> ok end, 365 is_in_erlang_hibernate_1(N-1, Pid) 366 end. 367 368is_not_in_erlang_hibernate(Pid) -> 369 receive after 1 -> ok end, 370 is_not_in_erlang_hibernate_1(200, Pid). 371 372is_not_in_erlang_hibernate_1(0, Pid) -> 373 io:format("~p\n", [erlang:process_info(Pid, current_function)]), 374 ct:fail(not_in_erlang_hibernate_3); 375is_not_in_erlang_hibernate_1(N, Pid) -> 376 {current_function,MFA} = erlang:process_info(Pid, current_function), 377 case MFA of 378 {erlang,hibernate,3} -> 379 receive after 10 -> ok end, 380 is_not_in_erlang_hibernate_1(N-1, Pid); 381 _ -> 382 ok 383 end. 384 385 386add_handler(Config) when is_list(Config) -> 387 {ok,_} = gen_event:start({local, my_dummy_handler}), 388 {error, my_error} = 389 gen_event:add_handler(my_dummy_handler, dummy_h, make_error), 390 [] = gen_event:which_handlers(my_dummy_handler), 391 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 392 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 393 394 {error, my_error} = 395 gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error), 396 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 397 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,self()}, 398 [self()]), 399 Self = self(), 400 [{dummy_h, Self}, dummy_h] = 401 gen_event:which_handlers(my_dummy_handler), 402 ok = gen_event:stop(my_dummy_handler), 403 ok. 404 405add_sup_handler(Config) when is_list(Config) -> 406 {ok,Pid} = gen_event:start({local, my_dummy_handler}), 407 {error, my_error} = 408 gen_event:add_sup_handler(my_dummy_handler, dummy_h, make_error), 409 [] = gen_event:which_handlers(my_dummy_handler), 410 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 411 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 412 exit(Pid, sup_died), 413 ct:sleep(1000), 414 [] = gen_event:which_handlers(my_dummy_handler), 415 416 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 417 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 418 419 {error, my_error} = 420 gen_event:add_handler(my_dummy_handler, {dummy_h, self()}, make_error), 421 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 422 ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,self()}, 423 [self()]), 424 Self = self(), 425 [{dummy_h, Self}, dummy_h] = 426 gen_event:which_handlers(my_dummy_handler), 427 ok = gen_event:stop(my_dummy_handler), 428 429 receive 430 {gen_event_EXIT, dummy_h, shutdown} -> 431 ok 432 after 1000 -> 433 ct:fail({no,{gen_event_EXIT, dummy_h, shutdown}}) 434 end, 435 436 receive 437 {gen_event_EXIT, {dummy_h,Self}, shutdown} -> 438 ok 439 after 1000 -> 440 ct:fail({no,{gen_event_EXIT, {dummy_h,Self}, 441 shutdown}}) 442 end, 443 ok. 444 445delete_handler(Config) when is_list(Config) -> 446 {ok,_} = gen_event:start({local, my_dummy_handler}), 447 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 448 {error, module_not_found} = 449 gen_event:delete_handler(my_dummy_handler, duuuuuuuuumy, []), 450 return_hej = 451 gen_event:delete_handler(my_dummy_handler, dummy_h, return_hej), 452 [] = gen_event:which_handlers(my_dummy_handler), 453 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 454 ok = 455 gen_event:delete_handler(my_dummy_handler, dummy_h, []), 456 [] = gen_event:which_handlers(my_dummy_handler), 457 458 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 459 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]), 460 {error, module_not_found} = 461 gen_event:delete_handler(my_dummy_handler, {duuuuuuuuumy,1}, []), 462 return_hej = 463 gen_event:delete_handler(my_dummy_handler, {dummy_h,1}, return_hej), 464 return_hej = 465 gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, return_hej), 466 [] = gen_event:which_handlers(my_dummy_handler), 467 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,2}, [self()]), 468 ok = 469 gen_event:delete_handler(my_dummy_handler, {dummy_h,2}, []), 470 [] = gen_event:which_handlers(my_dummy_handler), 471 472 ok = gen_event:stop(my_dummy_handler), 473 ok. 474 475swap_handler(Config) when is_list(Config) -> 476 {ok,_} = gen_event:start({local, my_dummy_handler}), 477 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 478 {error, non_existing} = 479 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 480 {dummy1_h, []}), 481 ok = 482 gen_event:swap_handler(my_dummy_handler, {dummy_h, swap}, 483 {dummy1_h, swap}), 484 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 485 486 ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []), 487 488 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 489 {error, non_existing} = 490 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 491 {dummy1_h, []}), 492 ok = 493 gen_event:swap_handler(my_dummy_handler, {{dummy_h,3}, swap}, 494 {{dummy1_h,4}, swap}), 495 [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler), 496 497 ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []), 498 499 ok = gen_event:stop(my_dummy_handler), 500 ok. 501 502swap_sup_handler(Config) when is_list(Config) -> 503 {ok,_} = gen_event:start({local, my_dummy_handler}), 504 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 505 {error, non_existing} = 506 gen_event:swap_handler(my_dummy_handler, {faulty_h, swap}, 507 {dummy1_h, []}), 508 ok = 509 gen_event:swap_handler(my_dummy_handler, {dummy_h, swap}, 510 {dummy1_h, swap}), 511 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 512 513 ok = gen_event:delete_handler(my_dummy_handler, dummy1_h, []), 514 receive 515 {gen_event_EXIT, dummy1_h, normal} -> 516 ok 517 after 1000 -> 518 ct:fail({no,{gen_event_EXIT, dummy1_h, normal}}) 519 end, 520 521 ok = gen_event:add_sup_handler(my_dummy_handler, {dummy_h,3}, 522 [self()]), 523 {error, non_existing} = 524 gen_event:swap_sup_handler(my_dummy_handler, {faulty_h, swap}, 525 {dummy1_h, []}), 526 ok = 527 gen_event:swap_sup_handler(my_dummy_handler, {{dummy_h,3}, swap}, 528 {{dummy1_h,4}, swap}), 529 [{dummy1_h,4}] = gen_event:which_handlers(my_dummy_handler), 530 531 ok = gen_event:delete_handler(my_dummy_handler, {dummy1_h,4}, []), 532 receive 533 {gen_event_EXIT, {dummy1_h,4}, normal} -> 534 ok 535 after 1000 -> 536 ct:fail({no,{gen_event_EXIT, {dummy1_h,4}, normal}}) 537 end, 538 539 ok = gen_event:stop(my_dummy_handler), 540 ok. 541 542notify(Config) when is_list(Config) -> 543 {ok,_} = gen_event:start({local, my_dummy_handler}), 544 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 545 Event = {event, self()}, 546 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 547 ok = gen_event:notify(my_dummy_handler, Event), 548 receive 549 {dummy_h, Event} -> 550 ok 551 end, 552 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 553 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 554 ok = gen_event:notify(my_dummy_handler, Event), 555 receive 556 {dummy1_h, Event} -> 557 ok 558 end, 559 ok = gen_event:notify(my_dummy_handler, delete_event), 560 receive 561 {dummy1_h, removed} -> 562 ok 563 end, 564 [] = gen_event:which_handlers(my_dummy_handler), 565 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 566 567 ok = gen_event:notify(my_dummy_handler, error_event), 568 receive 569 {dummy_h, returned_error} -> 570 ok 571 end, 572 [] = gen_event:which_handlers(my_dummy_handler), 573 574 %% Handler with id, {Mod,Id} 575 576 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]), 577 [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler), 578 ok = gen_event:notify(my_dummy_handler, Event), 579 receive 580 {dummy_h, Event} -> 581 ok 582 end, 583 ok = gen_event:notify(my_dummy_handler, 584 {swap_event, {dummy1_h, 9}, swap}), 585 [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), 586 ok = gen_event:notify(my_dummy_handler, Event), 587 receive 588 {dummy1_h, Event} -> 589 ok 590 end, 591 ok = gen_event:notify(my_dummy_handler, delete_event), 592 receive 593 {dummy1_h, removed} -> 594 ok 595 end, 596 [] = gen_event:which_handlers(my_dummy_handler), 597 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]), 598 599 ok = gen_event:notify(my_dummy_handler, error_event), 600 receive 601 {dummy_h, returned_error} -> 602 ok 603 end, 604 [] = gen_event:which_handlers(my_dummy_handler), 605 606 %% Supervised handler. 607 608 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 609 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 610 ok = gen_event:notify(my_dummy_handler, Event), 611 receive 612 {dummy_h, Event} -> 613 ok 614 end, 615 616 ok = gen_event:notify(my_dummy_handler, do_crash), 617 receive 618 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 619 ok 620 end, 621 622 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 623 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 624 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 625 626 ok = gen_event:notify(my_dummy_handler, do_crash), 627 receive 628 {gen_event_EXIT, dummy1_h, {'EXIT',_}} -> 629 ok 630 end, 631 632 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 633 ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}), 634 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 635 636 ok = gen_event:notify(my_dummy_handler, delete_event), 637 receive 638 {dummy1_h, removed} -> 639 ok 640 end, 641 642 receive 643 {gen_event_EXIT, dummy1_h, normal} -> 644 ok 645 end, 646 647 [] = gen_event:which_handlers(my_dummy_handler), 648 649 ok = gen_event:stop(my_dummy_handler), 650 ok. 651 652sync_notify(Config) when is_list(Config) -> 653 {ok,_} = gen_event:start({local, my_dummy_handler}), 654 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 655 Event = {event, self()}, 656 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 657 ok = gen_event:sync_notify(my_dummy_handler, Event), 658 receive 659 {dummy_h, Event} -> 660 ok 661 end, 662 ok = gen_event:sync_notify(my_dummy_handler, 663 {swap_event, dummy1_h, swap}), 664 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 665 ok = gen_event:sync_notify(my_dummy_handler, Event), 666 receive 667 {dummy1_h, Event} -> 668 ok 669 end, 670 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 671 receive 672 {dummy1_h, removed} -> 673 ok 674 end, 675 [] = gen_event:which_handlers(my_dummy_handler), 676 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 677 678 ok = gen_event:sync_notify(my_dummy_handler, error_event), 679 receive 680 {dummy_h, returned_error} -> 681 ok 682 end, 683 [] = gen_event:which_handlers(my_dummy_handler), 684 685 %% Handler with id, {Mod,Id} 686 687 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,5}, [self()]), 688 [{dummy_h,5}] = gen_event:which_handlers(my_dummy_handler), 689 ok = gen_event:sync_notify(my_dummy_handler, Event), 690 receive 691 {dummy_h, Event} -> 692 ok 693 end, 694 ok = gen_event:sync_notify(my_dummy_handler, 695 {swap_event, {dummy1_h, 9}, swap}), 696 [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler), 697 ok = gen_event:sync_notify(my_dummy_handler, Event), 698 receive 699 {dummy1_h, Event} -> 700 ok 701 end, 702 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 703 receive 704 {dummy1_h, removed} -> 705 ok 706 end, 707 [] = gen_event:which_handlers(my_dummy_handler), 708 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,a}, [self()]), 709 710 ok = gen_event:sync_notify(my_dummy_handler, error_event), 711 receive 712 {dummy_h, returned_error} -> 713 ok 714 end, 715 [] = gen_event:which_handlers(my_dummy_handler), 716 717 %% Supervised handler. 718 719 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 720 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 721 ok = gen_event:sync_notify(my_dummy_handler, Event), 722 receive 723 {dummy_h, Event} -> 724 ok 725 end, 726 727 ok = gen_event:sync_notify(my_dummy_handler, do_crash), 728 receive 729 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 730 ok 731 end, 732 733 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 734 ok = gen_event:sync_notify(my_dummy_handler, 735 {swap_event,dummy1_h,swap}), 736 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 737 738 ok = gen_event:sync_notify(my_dummy_handler, do_crash), 739 receive 740 {gen_event_EXIT, dummy1_h, {'EXIT',_}} -> 741 ok 742 end, 743 744 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 745 ok = gen_event:sync_notify(my_dummy_handler, 746 {swap_event,dummy1_h,swap}), 747 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 748 749 ok = gen_event:sync_notify(my_dummy_handler, delete_event), 750 receive 751 {dummy1_h, removed} -> 752 ok 753 end, 754 755 receive 756 {gen_event_EXIT, dummy1_h, normal} -> 757 ok 758 end, 759 760 [] = gen_event:which_handlers(my_dummy_handler), 761 762 ok = gen_event:stop(my_dummy_handler), 763 ok. 764 765call(Config) when is_list(Config) -> 766 {ok,_} = gen_event:start({local, my_dummy_handler}), 767 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 768 ok = gen_event:add_handler(my_dummy_handler, {dummy_h, 1}, [self()]), 769 [{dummy_h, 1}, dummy_h] = gen_event:which_handlers(my_dummy_handler), 770 {'EXIT',_} = (catch gen_event:call(non_exist, dummy_h, hejsan)), 771 {error, bad_module} = 772 gen_event:call(my_dummy_handler, bad_h, hejsan), 773 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan), 774 {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h, 1}, 775 hejsan), 776 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan, 777 10000), 778 {'EXIT', {timeout, _}} = 779 (catch gen_event:call(my_dummy_handler, dummy_h, hejsan, 0)), 780 flush(), 781 ok = gen_event:delete_handler(my_dummy_handler, {dummy_h, 1}, []), 782 {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h, 783 {swap_call,dummy1_h,swap}), 784 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 785 {error, bad_module} = 786 gen_event:call(my_dummy_handler, dummy_h, hejsan), 787 ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call), 788 receive 789 {dummy1_h, removed} -> 790 ok 791 end, 792 [] = gen_event:which_handlers(my_dummy_handler), 793 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 794 795 {error, {return, faulty}} = 796 gen_event:call(my_dummy_handler, dummy_h, error_call), 797 receive 798 {dummy_h, returned_error} -> 799 ok 800 end, 801 [] = gen_event:which_handlers(my_dummy_handler), 802 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 803 804 {error, {'EXIT', _}} = 805 gen_event:call(my_dummy_handler, dummy_h, exit_call), 806 807 [] = gen_event:which_handlers(my_dummy_handler), 808 809 %% Handler with id, {Mod,Id} 810 811 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 812 [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler), 813 {error, bad_module} = 814 gen_event:call(my_dummy_handler, bad_h, hejsan), 815 {ok, hejhopp} = gen_event:call(my_dummy_handler, {dummy_h,1}, 816 hejsan), 817 {ok, swapped} = gen_event:call(my_dummy_handler, {dummy_h,1}, 818 {swap_call,{dummy1_h,2},swap}), 819 [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), 820 {error, bad_module} = 821 gen_event:call(my_dummy_handler, dummy_h, hejsan), 822 ok = gen_event:call(my_dummy_handler, {dummy1_h,2}, delete_call), 823 receive 824 {dummy1_h, removed} -> 825 ok 826 end, 827 [] = gen_event:which_handlers(my_dummy_handler), 828 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 829 830 {error, {return, faulty}} = 831 gen_event:call(my_dummy_handler, {dummy_h,3}, error_call), 832 receive 833 {dummy_h, returned_error} -> 834 ok 835 end, 836 [] = gen_event:which_handlers(my_dummy_handler), 837 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,4}, [self()]), 838 839 {error, {'EXIT', _}} = 840 gen_event:call(my_dummy_handler, {dummy_h,4}, exit_call), 841 842 [] = gen_event:which_handlers(my_dummy_handler), 843 844 %% Supervised handler. 845 846 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 847 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 848 {error, bad_module} = 849 gen_event:call(my_dummy_handler, bad_h, hejsan), 850 {ok, hejhopp} = gen_event:call(my_dummy_handler, dummy_h, hejsan), 851 {ok, swapped} = gen_event:call(my_dummy_handler, dummy_h, 852 {swap_call,dummy1_h,swap}), 853 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 854 {error, bad_module} = 855 gen_event:call(my_dummy_handler, dummy_h, hejsan), 856 ok = gen_event:call(my_dummy_handler, dummy1_h, delete_call), 857 receive 858 {dummy1_h, removed} -> 859 ok 860 end, 861 862 receive 863 {gen_event_EXIT, dummy1_h, normal} -> 864 ok 865 end, 866 867 [] = gen_event:which_handlers(my_dummy_handler), 868 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 869 870 {error, {return, faulty}} = 871 gen_event:call(my_dummy_handler, dummy_h, error_call), 872 receive 873 {dummy_h, returned_error} -> 874 ok 875 end, 876 877 receive 878 {gen_event_EXIT, dummy_h, {return,faulty}} -> 879 ok 880 after 1000 -> 881 ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}}) 882 end, 883 884 [] = gen_event:which_handlers(my_dummy_handler), 885 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 886 887 {error, {'EXIT', _}} = 888 gen_event:call(my_dummy_handler, dummy_h, exit_call), 889 890 receive 891 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 892 ok 893 after 1000 -> 894 ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}}) 895 end, 896 897 [] = gen_event:which_handlers(my_dummy_handler), 898 899 ok = gen_event:stop(my_dummy_handler), 900 ok. 901 902flush() -> 903 receive _ -> flush() after 0 -> ok end. 904 905info(Config) when is_list(Config) -> 906 {ok,_} = gen_event:start({local, my_dummy_handler}), 907 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 908 Info = {info, self()}, 909 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 910 my_dummy_handler ! Info, 911 receive 912 {dummy_h, Info} -> 913 ok 914 end, 915 my_dummy_handler ! {swap_info,dummy1_h,swap}, 916 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 917 my_dummy_handler ! Info, 918 receive 919 {dummy1_h, Info} -> 920 ok 921 end, 922 my_dummy_handler ! delete_info, 923 receive 924 {dummy1_h, removed} -> 925 ok 926 end, 927 [] = gen_event:which_handlers(my_dummy_handler), 928 ok = gen_event:add_handler(my_dummy_handler, dummy_h, [self()]), 929 930 my_dummy_handler ! error_info, 931 receive 932 {dummy_h, returned_error} -> 933 ok 934 end, 935 [] = gen_event:which_handlers(my_dummy_handler), 936 937 %% Handler with id, {Mod,Id} 938 939 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,1}, [self()]), 940 [{dummy_h,1}] = gen_event:which_handlers(my_dummy_handler), 941 my_dummy_handler ! Info, 942 receive 943 {dummy_h, Info} -> 944 ok 945 end, 946 my_dummy_handler ! {swap_info,{dummy1_h,2},swap}, 947 [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler), 948 my_dummy_handler ! Info, 949 receive 950 {dummy1_h, Info} -> 951 ok 952 end, 953 my_dummy_handler ! delete_info, 954 receive 955 {dummy1_h, removed} -> 956 ok 957 end, 958 [] = gen_event:which_handlers(my_dummy_handler), 959 ok = gen_event:add_handler(my_dummy_handler, {dummy_h,3}, [self()]), 960 961 my_dummy_handler ! error_info, 962 receive 963 {dummy_h, returned_error} -> 964 ok 965 end, 966 [] = gen_event:which_handlers(my_dummy_handler), 967 968 %% Supervised handler 969 970 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 971 [dummy_h] = gen_event:which_handlers(my_dummy_handler), 972 my_dummy_handler ! Info, 973 receive 974 {dummy_h, Info} -> 975 ok 976 end, 977 my_dummy_handler ! {swap_info,dummy1_h,swap}, 978 [dummy1_h] = gen_event:which_handlers(my_dummy_handler), 979 my_dummy_handler ! Info, 980 receive 981 {dummy1_h, Info} -> 982 ok 983 end, 984 my_dummy_handler ! delete_info, 985 receive 986 {dummy1_h, removed} -> 987 ok 988 end, 989 990 receive 991 {gen_event_EXIT, dummy1_h, normal} -> 992 ok 993 after 1000 -> 994 ct:fail({no, {gen_event_EXIT, dummy1_h, normal}}) 995 end, 996 997 [] = gen_event:which_handlers(my_dummy_handler), 998 999 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 1000 1001 my_dummy_handler ! error_info, 1002 receive 1003 {dummy_h, returned_error} -> 1004 ok 1005 end, 1006 1007 receive 1008 {gen_event_EXIT, dummy_h, {return,faulty}} -> 1009 ok 1010 after 1000 -> 1011 ct:fail({no, {gen_event_EXIT, dummy_h, {return,faulty}}}) 1012 end, 1013 1014 ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]), 1015 my_dummy_handler ! do_crash, 1016 1017 receive 1018 {gen_event_EXIT, dummy_h, {'EXIT',_}} -> 1019 ok 1020 after 1000 -> 1021 ct:fail({no, {gen_event_EXIT, dummy_h, {'EXIT','_'}}}) 1022 end, 1023 1024 [] = gen_event:which_handlers(my_dummy_handler), 1025 1026 ok = gen_event:stop(my_dummy_handler), 1027 ok. 1028 1029%% Test that sys:get_status/1,2 calls format_status/2. 1030call_format_status(Config) when is_list(Config) -> 1031 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1032 %% State here intentionally differs from what we expect from format_status 1033 State = self(), 1034 FmtState = "dummy1_h handler state", 1035 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State]), 1036 Status1 = sys:get_status(Pid), 1037 Status2 = sys:get_status(Pid, 5000), 1038 ok = gen_event:stop(Pid), 1039 {status, Pid, _, [_, _, Pid, [], Data1]} = Status1, 1040 HandlerInfo1 = proplists:get_value(items, Data1), 1041 {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo1, 1042 {status, Pid, _, [_, _, Pid, [], Data2]} = Status2, 1043 HandlerInfo2 = proplists:get_value(items, Data2), 1044 {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2, 1045 ok. 1046 1047%% Test that sys:get_status/1,2 calls format_status/2 for anonymous 1048%% gen_event processes. 1049call_format_status_anon(Config) when is_list(Config) -> 1050 {ok, Pid} = gen_event:start(), 1051 %% The 'Name' of the gen_event process will be a pid() here, so 1052 %% the next line will crash if format_status can't string-ify pids. 1053 Status1 = sys:get_status(Pid), 1054 ok = gen_event:stop(Pid), 1055 Header = "Status for event handler " ++ pid_to_list(Pid), 1056 {status, Pid, _, [_, _, Pid, [], Data1]} = Status1, 1057 Header = proplists:get_value(header, Data1), 1058 ok. 1059 1060 1061%% Test that a handler error calls format_status/2. 1062error_format_status(Config) when is_list(Config) -> 1063 error_logger_forwarder:register(), 1064 OldFl = process_flag(trap_exit, true), 1065 State = self(), 1066 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1067 ok = gen_event:add_sup_handler(my_dummy_handler, dummy1_h, [State]), 1068 ok = gen_event:notify(my_dummy_handler, do_crash), 1069 receive 1070 {gen_event_EXIT,dummy1_h,{'EXIT',_}} -> ok 1071 after 5000 -> 1072 ct:fail(exit_gen_event) 1073 end, 1074 FmtState = "dummy1_h handler state", 1075 receive 1076 {error,_GroupLeader, {Pid, 1077 "** gen_event handler"++_, 1078 [dummy1_h,my_dummy_handler,do_crash, 1079 FmtState, _]}} -> 1080 ok; 1081 Other -> 1082 io:format("Unexpected: ~p", [Other]), 1083 ct:fail(failed) 1084 end, 1085 ok = gen_event:stop(Pid), 1086 process_flag(trap_exit, OldFl), 1087 ok. 1088 1089%% Test that sys:get_state/1,2 return the gen_event state. 1090get_state(Config) when is_list(Config) -> 1091 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1092 State1 = self(), 1093 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), 1094 [{dummy1_h,false,State1}] = sys:get_state(Pid), 1095 [{dummy1_h,false,State1}] = sys:get_state(Pid, 5000), 1096 State2 = {?MODULE, self()}, 1097 ok = gen_event:add_handler(my_dummy_handler, {dummy1_h,id}, [State2]), 1098 Result1 = sys:get_state(Pid), 1099 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result1), 1100 Result2 = sys:get_state(Pid, 5000), 1101 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result2), 1102 ok = sys:suspend(Pid), 1103 Result3 = sys:get_state(Pid), 1104 [{dummy1_h,false,State1},{dummy1_h,id,State2}] = lists:sort(Result3), 1105 ok = sys:resume(Pid), 1106 ok = gen_event:stop(Pid), 1107 ok. 1108 1109%% Test that replace_state/2,3 replace the gen_event state. 1110replace_state(Config) when is_list(Config) -> 1111 {ok, Pid} = gen_event:start({local, my_dummy_handler}), 1112 State1 = self(), 1113 ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State1]), 1114 [{dummy1_h,false,State1}] = sys:get_state(Pid), 1115 NState1 = "replaced", 1116 Replace1 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState1) end, 1117 [{dummy1_h,false,NState1}] = sys:replace_state(Pid, Replace1), 1118 [{dummy1_h,false,NState1}] = sys:get_state(Pid), 1119 NState2 = "replaced again", 1120 Replace2 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState2) end, 1121 [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace2, 5000), 1122 [{dummy1_h,false,NState2}] = sys:get_state(Pid), 1123 %% verify no change in state if replace function crashes 1124 Replace3 = fun(_) -> exit(fail) end, 1125 [{dummy1_h,false,NState2}] = sys:replace_state(Pid, Replace3), 1126 [{dummy1_h,false,NState2}] = sys:get_state(Pid), 1127 %% verify state replaced if process sys suspended 1128 NState3 = "replaced again and again", 1129 Replace4 = fun({dummy1_h,false,_}=S) -> setelement(3,S,NState3) end, 1130 ok = sys:suspend(Pid), 1131 [{dummy1_h,false,NState3}] = sys:replace_state(Pid, Replace4), 1132 ok = sys:resume(Pid), 1133 [{dummy1_h,false,NState3}] = sys:get_state(Pid), 1134 ok. 1135 1136%% No default provided for init, so it should fail 1137undef_init(Config) -> 1138 Pid = ?config(event_pid, Config), 1139 {'EXIT', {undef, [{oc_init_event, init, [_], _}|_]}} 1140 = gen_event:add_handler(Pid, oc_init_event, []), 1141 ok. 1142 1143%% No default provided for init, so it should fail 1144undef_handle_call(Config) when is_list(Config) -> 1145 Pid = ?config(event_pid, Config), 1146 {error, {'EXIT', {undef, [{oc_event, handle_call, _, _}|_]}}} 1147 = gen_event:call(Pid, oc_event, call_msg), 1148 [] = gen_event:which_handlers(Pid), 1149 ok. 1150 1151%% No default provided for init, so it should fail 1152undef_handle_event(Config) -> 1153 Pid = ?config(event_pid, Config), 1154 ok = gen_event:sync_notify(Pid, event_msg), 1155 [] = gen_event:which_handlers(Pid), 1156 1157 gen_event:add_handler(oc_event, oc_event, []), 1158 [oc_event] = gen_event:which_handlers(Pid), 1159 1160 ok = gen_event:notify(Pid, event_msg), 1161 [] = gen_event:which_handlers(Pid), 1162 ok. 1163 1164%% Defaulting to doing nothing with a log warning. 1165undef_handle_info(Config) when is_list(Config) -> 1166 error_logger_forwarder:register(), 1167 Pid = ?config(event_pid, Config), 1168 Pid ! hej, 1169 wait_until_processed(Pid, hej, 10), 1170 [oc_event] = gen_event:which_handlers(Pid), 1171 receive 1172 {warning_msg, _GroupLeader, 1173 {Pid, "** Undefined handle_info in " ++ _, [oc_event, hej]}} -> 1174 ok; 1175 Other -> 1176 io:format("Unexpected: ~p", [Other]), 1177 ct:fail(failed) 1178 end. 1179 1180wait_until_processed(_Pid, _Message, 0) -> 1181 ct:fail(not_processed); 1182wait_until_processed(Pid, Message, N) -> 1183 {messages, Messages} = erlang:process_info(Pid, messages), 1184 case lists:member(Message, Messages) of 1185 true -> 1186 timer:sleep(100), 1187 wait_until_processed(Pid, Message, N-1); 1188 false -> 1189 ok 1190 end. 1191 1192%% No default provided for init, so it should fail 1193undef_code_change(Config) when is_list(Config) -> 1194 Pid = ?config(event_pid, Config), 1195 {error, {'EXIT', {undef, [{oc_event, code_change, [_, _, _], _}|_]}}} = 1196 fake_upgrade(Pid, oc_event), 1197 [oc_event] = gen_event:which_handlers(Pid), 1198 ok. 1199 1200%% Defaulting to doing nothing. Test that it works when not defined. 1201undef_terminate(Config) when is_list(Config) -> 1202 Pid = ?config(event_pid, Config), 1203 ok = gen_event:delete_handler(Pid, oc_event, []), 1204 [] = gen_event:which_handlers(Pid), 1205 ok. 1206 1207%% Test that the default implementation doesn't catch the wrong undef error 1208undef_in_terminate(_Config) -> 1209 {ok, Pid} = gen_event:start({local, dummy}), 1210 State = {undef_in_terminate, {dummy_h, terminate}}, 1211 ok = gen_event:add_handler(Pid, dummy_h, {state, State}), 1212 [dummy_h] = gen_event:which_handlers(Pid), 1213 {'EXIT', {undef, [{dummy_h, terminate, [], []}|_]}} 1214 = gen_event:delete_handler(Pid, dummy_h, []), 1215 [] = gen_event:which_handlers(Pid), 1216 ok. 1217 1218fake_upgrade(Pid, Mod) -> 1219 sys:suspend(Pid), 1220 sys:replace_state(Pid, fun(S) -> {new, S} end), 1221 Ret = sys:change_code(Pid, Mod, old_vsn, []), 1222 ok = sys:resume(Pid), 1223 Ret. 1224