1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2003-2020. 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 21%% 22%%---------------------------------------------------------------------- 23%% Purpose: Test suite of the agent mib-server. 24%% Some of these tests should really be in a mib-storage suite. 25%%---------------------------------------------------------------------- 26 27-module(snmp_agent_mibs_SUITE). 28 29 30%%---------------------------------------------------------------------- 31%% Include files 32%%---------------------------------------------------------------------- 33 34-include_lib("common_test/include/ct.hrl"). 35-include("snmp_test_lib.hrl"). 36-include_lib("snmp/include/snmp_types.hrl"). 37-include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). 38-include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). 39-include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). 40-include("snmp_test_data/Test2.hrl"). 41 42 43%%---------------------------------------------------------------------- 44%% External exports 45%%---------------------------------------------------------------------- 46 47-export([ 48 suite/0, all/0, groups/0, 49 init_per_suite/1, end_per_suite/1, 50 init_per_group/2, end_per_group/2, 51 init_per_testcase/2, end_per_testcase/2, 52 53 start_and_stop/1, 54 55 size_check_ets1/1, 56 size_check_ets2/1, 57 size_check_ets2_bad_file1/1, 58 size_check_ets3/1, 59 size_check_ets3_bad_file1/1, 60 size_check_dets/1, 61 size_check_mnesia/1, 62 load_unload/1, 63 me_lookup/1, 64 which_mib/1, 65 cache_test/1 66 67 ]). 68 69 70-define(ALIB, snmp_agent_test_lib). 71 72 73%%====================================================================== 74%% Common Test interface functions 75%%====================================================================== 76 77suite() -> 78 [{ct_hooks, [ts_install_cth]}]. 79 80all() -> 81 [ 82 start_and_stop, 83 load_unload, 84 {group, size_check}, 85 me_lookup, 86 which_mib, 87 cache_test 88 ]. 89 90groups() -> 91 [ 92 {size_check, [], size_check_cases()} 93 ]. 94 95size_check_cases() -> 96 [ 97 size_check_ets1, % Plain ets 98 size_check_ets2, % ets with a file 99 size_check_ets2_bad_file1, % ets with a bad file 100 size_check_ets3, % ets with a checksummed file 101 size_check_ets3_bad_file1, % ets with bad file (checksummed) 102 size_check_dets, % Plain dets 103 size_check_mnesia % Plain mnesia 104 ]. 105 106 107 108%% 109%% ----- 110%% 111 112init_per_suite(Config0) when is_list(Config0) -> 113 114 ?DBG("init_per_suite -> entry with" 115 "~n Config0: ~p", [Config0]), 116 117 case snmp_test_lib:init_per_suite(Config0) of 118 {skip, _} = SKIP -> 119 SKIP; 120 121 Config1 when is_list(Config1) -> 122 Config2 = ?LIB:init_suite_top_dir(?MODULE, Config1), 123 124 %% We need a monitor on this node also 125 snmp_test_sys_monitor:start(), 126 127 ?DBG("init_per_suite -> done when" 128 "~n Config: ~p", [Config]), 129 130 Config2 131 end. 132 133end_per_suite(Config) when is_list(Config) -> 134 135 ?DBG("end_per_suite -> entry with" 136 "~n Config: ~p", [Config]), 137 138 snmp_test_sys_monitor:stop(), 139 140 ?LIB:end_per_suite(Config). 141 142 143 144%% 145%% ----- 146%% 147 148init_per_group(GroupName, Config) -> 149 ?LIB:init_group_top_dir(GroupName, Config). 150 151end_per_group(_GroupName, Config) -> 152 Config. 153 154 155 156 157%% 158%% ----- 159%% 160 161init_per_testcase(Case, Config0) when is_list(Config0) -> 162 snmp_test_global_sys_monitor:reset_events(), 163 Config1 = ?LIB:fix_data_dir(Config0), 164 CaseTopDir = ?LIB:init_testcase_top_dir(Case, Config1), 165 DbDir = join(CaseTopDir, "db_dir/"), 166 ?line ok = file:make_dir(DbDir), 167 init_per_testcase2(Case, [{db_dir, DbDir}, 168 {case_top_dir, CaseTopDir} | Config1]). 169 170init_per_testcase2(size_check_ets2_bad_file1, Config) when is_list(Config) -> 171 DbDir = ?config(db_dir, Config), 172 %% Create a bad file 173 ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"), 174 "calvin and hoppes play chess"), 175 Config; 176init_per_testcase2(size_check_ets3_bad_file1, Config) when is_list(Config) -> 177 DbDir = ?config(db_dir, Config), 178 %% Create a bad file 179 ok = file:write_file(join(DbDir, "snmpa_symbolic_store.db"), 180 "calvin and hoppes play chess"), 181 Config; 182init_per_testcase2(size_check_mnesia, Config) when is_list(Config) -> 183 Config; 184init_per_testcase2(cache_test, Config) when is_list(Config) -> 185 Min = ?MINS(10), 186 Timeout = 187 case lists:keysearch(tc_timeout, 1, Config) of 188 {value, {tc_timeout, TcTimeout}} when TcTimeout < Min -> 189 Min; 190 {value, {tc_timeout, TcTimeout}} -> 191 TcTimeout; 192 _ -> 193 Min 194 end, 195 Dog = test_server:timetrap(Timeout), 196 [{watchdog, Dog} | Config]; 197init_per_testcase2(_Case, Config) when is_list(Config) -> 198 Config. 199 200 201end_per_testcase(Case, Config) when is_list(Config) -> 202 ?IPRINT("system events during test: " 203 "~n ~p", [snmp_test_global_sys_monitor:events()]), 204 end_per_testcase1(Case, Config). 205 206end_per_testcase1(size_check_mnesia, Config) when is_list(Config) -> 207 mnesia_stop(), 208 Config; 209end_per_testcase1(cache_test, Config) when is_list(Config) -> 210 Dog = ?config(watchdog, Config), 211 test_server:timetrap_cancel(Dog), 212 Config; 213end_per_testcase1(_Case, Config) when is_list(Config) -> 214 Config. 215 216 217%%====================================================================== 218%% Test functions 219%%====================================================================== 220 221start_and_stop(suite) -> []; 222start_and_stop(Config) when is_list(Config) -> 223 Prio = normal, 224 Verbosity = trace, 225 226 ?line sym_start(Prio, Verbosity), 227 ?line MibsPid = mibs_start(Prio, Verbosity), 228 229 ?line mibs_info(MibsPid), 230 231 ?line mibs_stop(MibsPid), 232 ?line sym_stop(), 233 234 ok. 235 236 237%% --------------------------------------------------------------------- 238 239load_unload(suite) -> []; 240load_unload(Config) when is_list(Config) -> 241 ?DBG("load_unload -> start", []), 242 243 Prio = normal, 244 Verbosity = log, 245 MibDir = ?config(data_dir, Config), 246 247 ?DBG("load_unload -> start symbolic store", []), 248 ?line sym_start(Prio, Verbosity), 249 250 ?DBG("load_unload -> start mib server", []), 251 ?line MibsPid = mibs_start(Prio, Verbosity), 252 253 ?DBG("load_unload -> load one not already loaded mib", []), 254 ?line ok = verify_loaded_mibs(MibsPid, MibDir, []), 255 ?line ok = load_mibs(MibsPid, MibDir, ["Test2"]), 256 ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]), 257 258 ?DBG("load_unload -> try load one *already loaded* mib", []), 259 EMib = join(MibDir, "Test2"), 260 ?line {error, {'load aborted at', EMib, already_loaded}} = 261 load_mibs(MibsPid, MibDir, ["Test2"]), 262 263 ?DBG("load_unload -> load 2 not already loaded mibs", []), 264 ?line ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]), 265 ?line ok = verify_loaded_mibs(MibsPid, MibDir, 266 ["Test2", "TestTrap", "TestTrapv2"]), 267 268 ?DBG("load_unload -> unload one loaded mib", []), 269 ?line ok = unload_mibs(MibsPid, ["Test2"]), 270 ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]), 271 272 ?DBG("load_unload -> try unload two loaded mibs and one not loaded", []), 273 ?line {error, {'unload aborted at', "Test2", not_loaded}} = 274 unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]), 275 ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]), 276 277 ?DBG("load_unload -> unload the remaining loaded mib", []), 278 ?line ok = unload_mibs(MibsPid, ["TestTrapv2"]), 279 ?line ok = verify_loaded_mibs(MibsPid, MibDir, []), 280 281 ?DBG("load_unload -> stop mib server", []), 282 ?line mibs_stop(MibsPid), 283 284 ?DBG("load_unload -> stop symbolic store", []), 285 ?line sym_stop(), 286 287 ?DBG("load_unload -> done", []), 288 ok. 289 290 291%% --------------------------------------------------------------------- 292 293 294size_check_ets1(suite) -> 295 []; 296size_check_ets1(Config) when is_list(Config) -> 297 MibStorage = [{module, snmpa_mib_storage_ets}], 298 do_size_check(size_check_ets1, 299 [{mib_storage, MibStorage}|Config]). 300 301size_check_ets2(suite) -> 302 []; 303size_check_ets2(Config) when is_list(Config) -> 304 Dir = ?config(db_dir, Config), 305 MibStorage = [{module, snmpa_mib_storage_ets}, 306 {options, [{dir, Dir}]}], 307 do_size_check(size_check_ets2, 308 [{mib_storage, MibStorage}|Config]). 309 310size_check_ets2_bad_file1(suite) -> 311 []; 312size_check_ets2_bad_file1(Config) when is_list(Config) -> 313 Dir = ?config(db_dir, Config), 314 %% Ensure that the bad file does not cause any problems (action = clear) 315 MibStorage = [{module, snmpa_mib_storage_ets}, 316 {options, [{dir, Dir}, 317 {action, clear}]}], 318 do_size_check(size_check_ets2_bad_file1, 319 [{mib_storage, MibStorage}|Config]). 320 321size_check_ets3(suite) -> 322 []; 323size_check_ets3(Config) when is_list(Config) -> 324 Dir = ?config(db_dir, Config), 325 MibStorage = [{module, snmpa_mib_storage_ets}, 326 {options, [{dir, Dir}, 327 {checksum, true}]}], 328 do_size_check(size_check_ets3, 329 [{mib_storage, MibStorage}|Config]). 330 331size_check_ets3_bad_file1(suite) -> 332 []; 333size_check_ets3_bad_file1(Config) when is_list(Config) -> 334 Dir = ?config(db_dir, Config), 335 %% Ensure that the bad file does not cause any problems (action = clear) 336 MibStorage = [{module, snmpa_mib_storage_ets}, 337 {options, [{dir, Dir}, 338 {action, clear}, 339 {checksum, true}]}], 340 do_size_check(size_check_ets3_bad_file1, 341 [{mib_storage, MibStorage}|Config]). 342 343size_check_dets(suite) -> 344 []; 345size_check_dets(Config) when is_list(Config) -> 346 Dir = ?config(db_dir, Config), 347 MibStorage = [{module, snmpa_mib_storage_dets}, 348 {options, [{dir, Dir}]}], 349 do_size_check(size_check_dets, 350 [{mib_storage, MibStorage}|Config]). 351 352size_check_mnesia(suite) -> 353 []; 354size_check_mnesia(Config) when is_list(Config) -> 355 MibStorage = [{module, snmpa_mib_storage_mnesia}, 356 {options, [{nodes, []}]}], 357 DbDir = ?config(db_dir, Config), 358 Init = fun() -> mnesia_start([{dir, DbDir}]), ok end, 359 do_size_check(size_check_mnesia, 360 Init, 361 [{mib_storage, MibStorage}|Config]). 362 363do_size_check(Name, Config) -> 364 Init = fun() -> ok end, 365 do_size_check(Name, Init, Config). 366 367do_size_check(Name, Init, Config) -> 368 Pre = fun() -> 369 {ok, Node} = ?ALIB:start_node(unique(Name)), 370 ok = run_on(Node, Init), 371 Node 372 end, 373 Case = fun(Node) -> 374 monitor_node(Node, true), 375 Pid = spawn_link(Node, fun() -> do_size_check(Config) end), 376 receive 377 {nodedown, Node} = N -> 378 exit(N); 379 {'EXIT', Pid, normal} -> 380 monitor_node(Node, false), 381 ok; 382 {'EXIT', Pid, ok} -> 383 monitor_node(Node, false), 384 ok; 385 {'EXIT', Pid, Reason} -> 386 monitor_node(Node, false), 387 exit(Reason) 388 end 389 end, 390 Post = fun({Node, _}) -> 391 ?STOP_NODE(Node) 392 end, 393 ?TC_TRY(Name, Pre, Case, Post). 394 395run_on(Node, F) when is_atom(Node) andalso is_function(F, 0) -> 396 monitor_node(Node, true), 397 Pid = spawn_link(Node, F), 398 receive 399 {nodedown, Node} = N -> 400 exit(N); 401 {'EXIT', Pid, normal} -> 402 monitor_node(Node, false), 403 ok; 404 {'EXIT', Pid, Reason} -> 405 monitor_node(Node, false), 406 Reason 407 end. 408 409unique(PreName) -> 410 list_to_atom(?F("~w_~w", [PreName, erlang:system_time(millisecond)])). 411 412do_size_check(Config) -> 413 ?IPRINT("do_size_check -> start with" 414 "~n Config: ~p", [Config]), 415 Prio = normal, 416 Verbosity = trace, 417 418 MibStorage = ?config(mib_storage, Config), 419 ?DBG("do_size_check -> MibStorage: ~p", [MibStorage]), 420 MibDir = ?config(data_dir, Config), 421 StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", 422 423 ?DBG("do_size_check -> start symbolic store", []), 424 ?line sym_start(Prio, MibStorage, Verbosity), 425 ?DBG("do_size_check -> start mib server", []), 426 ?line MibsPid = mibs_start(Prio, MibStorage, Verbosity), 427 428 Mibs = ["Test2", "TestTrap", "TestTrapv2"], 429 StdMibs = ["OTP-SNMPEA-MIB", 430 "SNMP-COMMUNITY-MIB", 431 "SNMP-FRAMEWORK-MIB", 432 "SNMP-MPD-MIB", 433 "SNMP-NOTIFICATION-MIB", 434 "SNMP-TARGET-MIB", 435 "SNMP-USER-BASED-SM-MIB", 436 "SNMP-VIEW-BASED-ACM-MIB", 437 "SNMPv2-MIB", 438 "SNMPv2-TC", 439 "SNMPv2-TM"], 440 441 ?DBG("do_size_check -> load mibs", []), 442 ?line load_mibs(MibsPid, MibDir, Mibs), 443 ?DBG("do_size_check -> load std mibs", []), 444 ?line load_mibs(MibsPid, StdMibDir, StdMibs), 445 446 ?SLEEP(2000), 447 ?DBG("do_size_check -> display mem usage", []), 448 ?line display_memory_usage(MibsPid), 449 450 ?DBG("do_size_check -> unload std mibs", []), 451 ?line unload_mibs(MibsPid, StdMibs), 452 ?DBG("do_size_check -> unload mibs", []), 453 ?line unload_mibs(MibsPid, Mibs), 454 455 ?DBG("do_size_check -> stop mib server", []), 456 ?line mibs_stop(MibsPid), 457 ?DBG("do_size_check -> stop symbolic store", []), 458 ?line sym_stop(), 459 460 ?IPRINT("do_size_check -> done", []), 461 ok. 462 463 464%% --------------------------------------------------------------------- 465 466me_lookup(suite) -> []; 467me_lookup(Config) when is_list(Config) -> 468 Prio = normal, 469 Verbosity = trace, 470 MibDir = ?config(data_dir, Config), 471 StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", 472 Mibs = ["Test2", "TestTrap", "TestTrapv2"], 473 StdMibs = ["OTP-SNMPEA-MIB", 474 "SNMP-COMMUNITY-MIB", 475 "SNMP-FRAMEWORK-MIB", 476 "SNMP-MPD-MIB", 477 "SNMP-NOTIFICATION-MIB", 478 "SNMP-TARGET-MIB", 479 %% "SNMP-USER-BASED-SM-MIB", 480 "SNMP-VIEW-BASED-ACM-MIB", 481 "SNMPv2-MIB", 482 "SNMPv2-TC", 483 "SNMPv2-TM"], 484 485 ?DBG("me_lookup -> start symbolic store", []), 486 ?line sym_start(Prio, Verbosity), 487 488 ?DBG("me_lookup -> start mib server", []), 489 ?line MibsPid = mibs_start(Prio, Verbosity), 490 491 ?DBG("me_lookup -> load mibs", []), 492 ?line load_mibs(MibsPid, MibDir, Mibs), 493 ?DBG("me_lookup -> load std mibs", []), 494 ?line load_mibs(MibsPid, StdMibDir, StdMibs), 495 496 ?DBG("me_lookup -> find ~w from SNMP-COMMUNITY-MIB", 497 [?snmpTrapCommunity_instance]), 498 ?line ok = me_lookup(MibsPid, ?snmpTrapCommunity_instance), 499 500 ?DBG("me_lookup -> find ~w from SNMP-VIEW-BASED-ACM-MIB", 501 [?vacmViewSpinLock_instance]), 502 ?line ok = me_lookup(MibsPid, ?vacmViewSpinLock_instance), 503 504 ?DBG("me_lookup -> find ~w from SNMP-USER-BASED-SM-MIB", 505 [?usmStatsNotInTimeWindows_instance]), 506 ?line {error, _} = me_lookup(MibsPid, ?usmStatsNotInTimeWindows_instance), 507 508 ?DBG("me_lookup -> stop mib server", []), 509 ?line mibs_stop(MibsPid), 510 511 ?DBG("me_lookup -> stop symbolic store", []), 512 ?line sym_stop(), 513 514 ok. 515 516 517%% --------------------------------------------------------------------- 518 519which_mib(suite) -> []; 520which_mib(Config) when is_list(Config) -> 521 Prio = normal, 522 Verbosity = trace, 523 MibDir = ?config(data_dir, Config), 524 StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", 525 Mibs = ["Test2", "TestTrap", "TestTrapv2"], 526 StdMibs = ["OTP-SNMPEA-MIB", 527 "SNMP-COMMUNITY-MIB", 528 "SNMP-FRAMEWORK-MIB", 529 "SNMP-MPD-MIB", 530 "SNMP-NOTIFICATION-MIB", 531 "SNMP-TARGET-MIB", 532 %% "SNMP-USER-BASED-SM-MIB", 533 "SNMP-VIEW-BASED-ACM-MIB", 534 "SNMPv2-MIB", 535 "SNMPv2-TC", 536 "SNMPv2-TM"], 537 538 ?DBG("which_mib -> start symbolic store", []), 539 ?line sym_start(Prio, Verbosity), 540 541 ?DBG("which_mib -> start mib server", []), 542 ?line MibsPid = mibs_start(Prio, Verbosity), 543 544 ?DBG("which_mib -> load mibs", []), 545 ?line load_mibs(MibsPid, MibDir, Mibs), 546 ?DBG("which_mib -> load std mibs", []), 547 ?line load_mibs(MibsPid, StdMibDir, StdMibs), 548 549 ?DBG("which_mib -> find ~w from SNMP-COMMUNITY-MIB", 550 [?snmpTrapCommunity_instance]), 551 ?line ok = which_mib(MibsPid, ?snmpTrapCommunity_instance, 552 "SNMP-COMMUNITY-MIB"), 553 554 ?DBG("which_mib -> find ~w from SNMP-VIEW-BASED-ACM-MIB", 555 [?vacmViewSpinLock_instance]), 556 ?line ok = which_mib(MibsPid, ?vacmViewSpinLock_instance, 557 "SNMP-VIEW-BASED-ACM-MIB"), 558 559 ?DBG("which_mib -> find ~w from SNMP-USER-BASED-SM-MIB (not loaded)", 560 [?usmStatsNotInTimeWindows_instance]), 561 ?line {error, _} = which_mib(MibsPid, ?usmStatsNotInTimeWindows_instance, 562 "SNMP-USER-BASED-SM-MIB"), 563 564 ?DBG("which_mib -> stop mib server", []), 565 ?line mibs_stop(MibsPid), 566 567 ?DBG("which_mib -> stop symbolic store", []), 568 ?line sym_stop(), 569 570 ok. 571 572 573%% --------------------------------------------------------------------- 574 575cache_test(suite) -> []; 576cache_test(Config) when is_list(Config) -> 577 ?IPRINT("cache_test -> start"), 578 Prio = normal, 579 %% Verbosity = trace, 580 Verbosity = info, 581 MibStorage = [{module, snmpa_mib_storage_ets}], 582 MibDir = ?config(data_dir, Config), 583 StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", 584 Mibs = ["Test2", "TestTrap", "TestTrapv2"], 585 StdMibs = ["OTP-SNMPEA-MIB", 586 "SNMP-COMMUNITY-MIB", 587 "SNMP-FRAMEWORK-MIB", 588 "SNMP-MPD-MIB", 589 "SNMP-NOTIFICATION-MIB", 590 "SNMP-TARGET-MIB", 591 "SNMP-USER-BASED-SM-MIB", 592 "SNMP-VIEW-BASED-ACM-MIB", 593 "SNMPv2-MIB", 594 "SNMPv2-TC", 595 "SNMPv2-TM"], 596 597 ?IPRINT("cache_test -> start symbolic store"), 598 ?line sym_start(Prio, MibStorage, silence), % Verbosity), 599 600 ?IPRINT("cache_test -> start mib server"), 601 GcLimit = 3, 602 Age = timer:seconds(10), 603 CacheOpts = [{autogc, false}, 604 {age, Age}, 605 {gclimit, GcLimit}, 606 {gcverbose, true}], 607 ?line MibsPid = mibs_start(Prio, MibStorage, [], Verbosity, CacheOpts), 608 609 ?NPRINT("Info before load mibs: " 610 "~n ~p", [snmpa_mib:info(MibsPid)]), 611 612 ?IPRINT("cache_test -> load mibs"), 613 ?line load_mibs(MibsPid, MibDir, Mibs), 614 615 ?NPRINT("Info before load std mibs: " 616 "~n ~p", [snmpa_mib:info(MibsPid)]), 617 618 ?IPRINT("cache_test -> load std mibs"), 619 ?line load_mibs(MibsPid, StdMibDir, StdMibs), 620 621 ?NPRINT("Info (after mibs load but) before populate: " 622 "~n ~p", [snmpa_mib:info(MibsPid)]), 623 624 ?IPRINT("cache_test -> populate the cache"), 625 ?line ok = populate(MibsPid), 626 627 ?NPRINT("Info after populate: " 628 "~n ~p", [snmpa_mib:info(MibsPid)]), 629 630 Sz1 = cache_sz_verify(1, MibsPid, any), 631 632 ?IPRINT("cache_test -> sleep 5 secs"), 633 ?SLEEP(timer:seconds(5)), 634 635 _ = cache_gc_verify(1, MibsPid), 636 637 ?NPRINT("Info after 5 sec sleep: " 638 "~n ~p", [snmpa_mib:info(MibsPid)]), 639 640 ?IPRINT("cache_test -> sleep 10 secs"), 641 ?SLEEP(timer:seconds(10)), 642 643 ?NPRINT("Info after 10 sec sleep: " 644 "~n ~p", [snmpa_mib:info(MibsPid)]), 645 646 GcLimit1 = cache_gc_verify(2, MibsPid, Age, GcLimit + 1), 647 648 Sz2 = cache_sz_verify(2, MibsPid, Sz1 - GcLimit1), 649 650 651 ?IPRINT("cache_test -> subscribe to GC events"), 652 ?line ok = snmpa_mib:subscribe_gc_events(MibsPid), 653 654 ?IPRINT("cache_test -> enable cache autogc"), 655 ?line ok = snmpa_mib:enable_cache_autogc(MibsPid), 656 657 ?IPRINT("cache_test -> wait 65 seconds to allow gc to happen"), 658 ?SLEEP(timer:seconds(65)), 659 660 ?NPRINT("Info after 65 sec sleep: " 661 "~n ~p", [snmpa_mib:info(MibsPid)]), 662 663 ?IPRINT("cache_test -> [1] flush expected GC events"), 664 {NumEvents1, TotGC1} = cache_flush_gc_events(MibsPid), 665 ?IPRINT("cache_test -> GC events: " 666 "~n Number of Events: ~p" 667 "~n Total elements GCed: ~p", [NumEvents1, TotGC1]), 668 669 _ = cache_sz_verify(3, MibsPid, Sz2 - GcLimit), 670 671 ?IPRINT("cache_test -> " 672 "wait 2 minutes to allow gc to happen, expect empty cache"), 673 ?SLEEP(timer:minutes(2)), 674 675 ?NPRINT("Info after 2 min sleep: " 676 "~n ~p", [snmpa_mib:info(MibsPid)]), 677 678 _ = cache_sz_verify(4, MibsPid, 0), 679 680 681 ?IPRINT("cache_test -> change gclimit to infinity"), 682 snmpa_mib:update_cache_gclimit(MibsPid, infinity), 683 684 ?IPRINT("cache_test -> change age to ~w mins", [3]), 685 snmpa_mib:update_cache_age(MibsPid, ?MINS(3)), 686 687 ?IPRINT("cache_test -> [2] flush expected GC events"), 688 {NumEvents2, TotGC2} = cache_flush_gc_events(MibsPid), 689 ?IPRINT("cache_test -> GC events: " 690 "~n Number of Events: ~p" 691 "~n Total elements GCed: ~p", [NumEvents2, TotGC2]), 692 693 ?IPRINT("cache_test -> populate the cache again"), 694 populate(MibsPid), 695 696 ?IPRINT("cache_test -> validate cache size"), 697 {ok, Sz4} = snmpa_mib:which_cache_size(MibsPid), 698 if (Sz4 > 0) -> 699 ?IPRINT("cache_test -> expected cache size: ~w > 0", [Sz4]); 700 true -> 701 ?EPRINT("cache_test -> cache *not* populated"), 702 ?FAIL(cache_not_populated) 703 end, 704 705 ?NPRINT("Info after poulated: " 706 "~n ~p", [snmpa_mib:info(MibsPid)]), 707 708 ?IPRINT("cache_test -> wait 2 mins - before tuching some entries"), 709 ?SLEEP(?MINS(2)), 710 711 %% There should not be anything GC:ed 712 713 receive 714 {MibsPid, gc_result, {ok, NGC1}} -> 715 ?EPRINT("cache_test -> unexpected GC of ~w elements", [NGC1]), 716 exit({unexpected_gc_result, NGC1}) 717 after 0 -> 718 ok 719 end, 720 721 ?IPRINT("cache_test -> touch some elements again (update the cache)"), 722 populate_lookup(MibsPid), 723 724 ?IPRINT("cache_test -> await partial GC"), 725 NumGC2 = 726 receive 727 {MibsPid, gc_result, {ok, NGC2}} 728 when (NGC2 > 0) andalso (Sz4 > NGC2) -> 729 ?NPRINT("cache_test -> " 730 "received partial GC result of ~w elements", [NGC2]), 731 NGC2 732 end, 733 734 ?NPRINT("Info after partial GC: " 735 "~n ~p", [snmpa_mib:info(MibsPid)]), 736 737 738 ?IPRINT("cache_test -> await final GC"), 739 receive 740 {MibsPid, gc_result, {ok, NGC3}} 741 when (NGC3 > 0) andalso ((Sz4 - NumGC2) =:= NGC3) -> 742 ?NPRINT("cache_test -> " 743 "received final GC result of ~w elements", [NGC3]), 744 NGC3; 745 Any -> 746 ?EPRINT("cache_test -> unexpected message: " 747 "~n ~p", [Any]), 748 ?FAIL({unexpected, Any}) 749 end, 750 751 ?NPRINT("Info after final GC: " 752 "~n ~p", [snmpa_mib:info(MibsPid)]), 753 754 ?IPRINT("cache_test -> validate cache size (expect empty)"), 755 {ok, Sz5} = snmpa_mib:which_cache_size(MibsPid), 756 if (Sz5 =:= 0) -> 757 ?IPRINT("cache_test -> expected cache size: 0"); 758 true -> 759 ?EPRINT("cache_test -> cache *not* empty (~w)", [Sz5]), 760 ?FAIL({cache_populated, Sz5}) 761 end, 762 763 764 ?IPRINT("cache_test -> stop mib server"), 765 ?line mibs_stop(MibsPid), 766 767 ?IPRINT("cache_test -> stop symbolic store"), 768 ?line sym_stop(), 769 770 ?IPRINT("cache_test -> end"), 771 ok. 772 773populate(MibsPid) -> 774 %% Make some lookups 775 populate_lookup(MibsPid), 776 %% Make some walk's 777 populate_walk(MibsPid). 778 779populate_lookup(MibsPid) -> 780 {variable, _} = snmpa_mib:lookup(MibsPid, ?snmpTrapCommunity_instance), 781 {variable, _} = snmpa_mib:lookup(MibsPid, ?vacmViewSpinLock_instance), 782 {variable, _} = snmpa_mib:lookup(MibsPid, ?usmStatsNotInTimeWindows_instance), 783 {variable, _} = snmpa_mib:lookup(MibsPid, ?tDescr_instance), 784 ok. 785 786populate_walk(MibsPid) -> 787 MibView = snmpa_acm:get_root_mib_view(), 788 walk(MibsPid, ?snmpTrapCommunity_instance, MibView), 789 walk(MibsPid, ?vacmViewSpinLock_instance, MibView), 790 walk(MibsPid, ?usmStatsNotInTimeWindows_instance, MibView), 791 walk(MibsPid, ?tDescr_instance, MibView), 792 ok. 793 794walk(MibsPid, Oid, MibView) -> 795 ?IPRINT("walk -> entry with" 796 "~n Oid: ~p", [Oid]), 797 do_walk(MibsPid, Oid, MibView). 798 799do_walk(MibsPid, Oid, MibView) -> 800 case snmpa_mib:next(MibsPid, Oid, MibView) of 801 {table, _, _, #me{oid = Oid}} -> 802 ?IPRINT("do_walk -> table done"), 803 ok; 804 {table, _, _, #me{oid = Next}} -> 805 ?IPRINT("do_walk -> table next ~p", [Next]), 806 do_walk(MibsPid, Next, MibView); 807 {variable, #me{oid = Oid}, _} -> 808 ?IPRINT("do_walk -> variable done"), 809 ok; 810 {variable, #me{oid = Next}, _} -> 811 ?IPRINT("do_walk -> variable next ~p", [Next]), 812 do_walk(MibsPid, Next, MibView) 813 end. 814 815 816cache_gc_verify(ID, MibsPid) -> 817 GC = fun() -> snmpa_mib:gc_cache(MibsPid) end, 818 cache_gc_verify(ID, GC, 0). 819 820cache_gc_verify(ID, MibsPid, Age, ExpectedGcLimit) -> 821 GC = fun() -> snmpa_mib:gc_cache(MibsPid, Age, ExpectedGcLimit) end, 822 cache_gc_verify(ID, GC, ExpectedGcLimit). 823 824cache_gc_verify(ID, GC, ExpectedGc) -> 825 ?IPRINT("cache_gc_verify -> [~w] perform gc, expect ~w", [ID, ExpectedGc]), 826 case GC() of 827 {ok, ExpectedGc} -> 828 ?IPRINT("cache_gc_verify -> [~w] gc => ok", [ID]), 829 ExpectedGc; 830 {ok, OtherGc} -> 831 ?IPRINT("cache_gc_verify -> [~w] invalid GC limit: " 832 "~n Expected: ~p" 833 "~n Got: ~p" 834 "~n ~p", 835 [ID, 0, OtherGc]), 836 exit({ID, invalid_gc_limit, {ExpectedGc, OtherGc}}); 837 Unexpected -> 838 ?IPRINT("cache_gc_verify -> [~w] unexpected: " 839 "~n ~p", 840 [ID, Unexpected]), 841 exit({ID, unexpected, Unexpected}) 842 end. 843 844 845cache_sz_verify(ID, MibsPid, ExpectedSz) -> 846 ?IPRINT("cache_sz_verify -> [~w] expect size ~w", [ID, ExpectedSz]), 847 case snmpa_mib:which_cache_size(MibsPid) of 848 {ok, ExpectedSz} -> 849 ?IPRINT("cache_sz_verify -> [~w] sz => ok", [ID]), 850 ExpectedSz; 851 {ok, UnexpectedSz} when (ExpectedSz =:= any) -> 852 ?IPRINT("cache_sz_verify -> [~w] sz => ok (~w)", [ID, UnexpectedSz]), 853 UnexpectedSz; 854 {ok, UnexpectedSz} -> 855 ?IPRINT("cache_sz_verify -> [~w] invalid size: " 856 "~n Expected: ~p" 857 "~n Got: ~p", 858 [ID, ExpectedSz, UnexpectedSz]), 859 exit({ID, invalid_size, {ExpectedSz, UnexpectedSz}}); 860 Unexpected -> 861 ?IPRINT("cache_sz_verify -> [~w] unexpected: " 862 "~n ~p", 863 [ID, Unexpected]), 864 exit({ID, unexpected, Unexpected}) 865 end. 866 867 868cache_flush_gc_events(MibServer) -> 869 cache_flush_gc_events(MibServer, 0, 0). 870 871cache_flush_gc_events(MibServer, NumEvents, TotGC) -> 872 receive 873 {MibServer, gc_result, {ok, NumGC}} -> 874 ?IPRINT("cache_flush_gc_events -> GC event ~w (~w)", 875 [NumGC, NumEvents]), 876 cache_flush_gc_events(MibServer, NumEvents+1, TotGC+NumGC) 877 after 0 -> 878 if 879 (NumEvents =:= 0) andalso (TotGC =:= 0) -> 880 ?IPRINT("cache_flush_gc_events -> no GC events"), 881 exit(no_gc_events); 882 true -> 883 {NumEvents, TotGC} 884 end 885 end. 886 887 888%%====================================================================== 889%% Internal functions 890%%====================================================================== 891 892%% -- Mnesia functions 893 894mnesia_start(Opts) -> 895 mnesia_start(Opts, [node()]). 896 897mnesia_start(Opts, Nodes) -> 898 %% We can accept mnesia beeing loaded but *not* started. 899 %% If its started it *may* contain data that will invalidate 900 %% this test case. 901 ?IPRINT("mnesia_start -> try load mnesia when:" 902 "~n Loaded: ~p" 903 "~n Running: ~p", [apps_loaded(), apps_running()]), 904 ?line ok = case application:load(mnesia) of 905 ok -> 906 ok; 907 {error, {already_loaded, mnesia}} -> 908 ok; 909 {error, _} = ERROR -> 910 ERROR 911 end, 912 F = fun({Key, Val}) -> 913 ?IPRINT("mnesia_start -> try set mnesia env: " 914 "~n ~p -> ~p", [Key, Val]), 915 ?line application_controller:set_env(mnesia, Key, Val) 916 end, 917 lists:foreach(F, Opts), 918 ?IPRINT("mnesia_start -> create mnesia schema on ~p", [Nodes]), 919 ?line case mnesia:create_schema(Nodes) of 920 ok -> 921 ok; 922 {error, {_, {already_exist, _}}} -> 923 throw({skip, "Mnesia schema already exists"}); 924 {error, SchemaReason} -> 925 throw({skip, 926 ?F("Failed create mnesia schema: ~p", [SchemaReason])}) 927 end, 928 ?IPRINT("mnesia_start -> start mnesia", []), 929 ?line case application:start(mnesia) of 930 ok -> 931 ok; 932 {error, {already_started, mnesia}} -> 933 throw({skip, "Mnesia already started"}); 934 {error, StartReason} -> 935 throw({skip, 936 ?F("Failed starting mnesia: ~p", [StartReason])}) 937 end, 938 ?IPRINT("mnesia_start -> mnesia started", []), 939 ok. 940 941mnesia_stop() -> 942 ?IPRINT("mnesia_stop -> try stop mnesia when:" 943 "~n Loaded: ~p" 944 "~n Running: ~p", [apps_loaded(), apps_running()]), 945 application:stop(mnesia), 946 ?IPRINT("mnesia_stop -> try unload mnesia when" 947 "~n Loaded: ~p" 948 "~n Running: ~p", [apps_loaded(), apps_running()]), 949 application:unload(mnesia), 950 ?IPRINT("mnesia_stop -> done when:" 951 "~n Loaded: ~p" 952 "~n Running: ~p", [apps_loaded(), apps_running()]), 953 ok. 954 955apps_loaded() -> 956 [App || {App, _, _} <- application:loaded_applications()]. 957 958apps_running() -> 959 [App || {App, _, _} <- application:which_applications()]. 960 961 962%% - Symbolic Store mini interface 963 964sym_start(Prio, Verbosity) -> 965 sym_start(Prio, mib_storage(), Verbosity). 966 967sym_start(Prio, MibStorage, Verbosity) -> 968 Opts = [{mib_storage, MibStorage}, {verbosity,Verbosity}], 969 {ok, _Pid} = snmpa_symbolic_store:start_link(Prio, Opts), 970 ok. 971 972sym_stop() -> 973 ok = snmpa_symbolic_store:stop(). 974 975sym_info() -> 976 snmpa_symbolic_store:info(). 977 978 979%% -- MIB server mini interface 980 981mibs_start(Prio, Verbosity) when is_atom(Prio) andalso is_atom(Verbosity) -> 982 mibs_start(Prio, mib_storage(), [], Verbosity). 983 984mibs_start(Prio, MibStorage, Verbosity) 985 when is_atom(Prio) andalso is_atom(Verbosity) -> 986 mibs_start(Prio, MibStorage, [], Verbosity). 987 988mibs_start(Prio, MibStorage, Mibs, Verbosity) 989 when is_atom(Prio) andalso 990 is_list(Mibs) andalso 991 is_atom(Verbosity) -> 992 mibs_start(Prio, MibStorage, Mibs, Verbosity, []). 993 994mibs_start(Prio, MibStorage, Mibs, Verbosity, CacheOpts) 995 when is_atom(Prio) andalso 996 is_list(Mibs) andalso 997 is_atom(Verbosity) andalso 998 is_list(CacheOpts) -> 999 Opts = [{mib_storage, MibStorage}, 1000 {verbosity, Verbosity}, 1001 {cache, CacheOpts}], 1002 {ok, Pid} = snmpa_mib:start_link(Prio, Mibs, Opts), 1003 Pid. 1004 1005mibs_stop(Pid) -> 1006 ok = snmpa_mib:stop(Pid). 1007 1008mibs_info(Pid) -> 1009 snmpa_mib:info(Pid). 1010 1011load_mibs(Pid, Dir, Mibs0) -> 1012 Mibs = [join(Dir, Mib) || Mib <- Mibs0], 1013 Res = snmpa_mib:load_mibs(Pid, Mibs), 1014 %% ?DBG("load_mibs -> " 1015 %% "~n Res: ~p", [Res]), 1016 Res. 1017 1018unload_mibs(Pid, Mibs) -> 1019 Res = snmpa_mib:unload_mibs(Pid, Mibs), 1020 %% ?DBG("unload_mibs -> " 1021 %% "~n Res: ~p", [Res]), 1022 Res. 1023 1024verify_loaded_mibs(Pid, Dir, ExpectedMibs0) -> 1025 ExpectedMibs = [join(Dir, Mib) || Mib <- ExpectedMibs0], 1026 case snmpa_mib:info(Pid, loaded_mibs) of 1027 ExpectedMibs -> 1028 ok; 1029 LoadedMibs0 -> 1030 ?DBG("verify_loaded_mibs -> LoadedMibs0: ~p", [LoadedMibs0]), 1031 LoadedMibs = [filename:rootname(FN, ".bin") || FN <- LoadedMibs0], 1032 ?DBG("verify_loaded_mibs -> LoadedMibs: ~p", [LoadedMibs]), 1033 ExpNotLoadedMibs = ExpectedMibs -- LoadedMibs, 1034 LoadedNotExpMibs = LoadedMibs -- ExpectedMibs, 1035 ?DBG("verify_loaded_mibs -> " 1036 "~n ExpNotLoadedMibs: ~p" 1037 "~n LoadedNotExpMibs: ~p", 1038 [ExpNotLoadedMibs, LoadedNotExpMibs]), 1039 case ExpNotLoadedMibs of 1040 [] -> 1041 case LoadedNotExpMibs of 1042 [] -> 1043 ok; 1044 _ -> 1045 {error, {unexpected_loaded_mibs, LoadedNotExpMibs}} 1046 end; 1047 _ -> 1048 case LoadedNotExpMibs of 1049 [] -> 1050 {error, {not_loaded_mibs, ExpNotLoadedMibs}}; 1051 _ -> 1052 {error, {unexpected_mibs, 1053 ExpNotLoadedMibs, LoadedNotExpMibs}} 1054 end 1055 end 1056 1057 end. 1058 1059me_lookup(Pid, Oid) -> 1060 case snmpa_mib:lookup(Pid, Oid) of 1061 {variable, #me{oid = Oid}} -> 1062 ok; 1063 {variable, #me{oid = OtherOid}} -> 1064 case lists:reverse(Oid) of 1065 [0|Rest] -> 1066 case lists:reverse(Rest) of 1067 OtherOid -> 1068 ok; 1069 AnotherOid -> 1070 {error, {invalid_oid, Oid, AnotherOid}} 1071 end; 1072 _ -> 1073 {error, {invalid_oid, Oid, OtherOid}} 1074 end; 1075 {table_column, _ME, _TableEntryOid} -> 1076 ok; 1077 {subagent, SubAgentPid, _SANextOid} -> 1078 {error, {subagent, SubAgentPid}}; 1079 {false, Reason} -> 1080 {error, Reason}; 1081 Else -> 1082 {error, Else} 1083 end. 1084 1085 1086which_mib(Pid, Oid, Mib1) -> 1087 case snmpa_mib:which_mib(Pid, Oid) of 1088 {ok, Mib2} when is_atom(Mib2) -> 1089 Mib3 = atom_to_list(Mib2), 1090 which_mib(Mib1, Mib3); 1091 {ok, Mib2} -> 1092 which_mib(Mib1, Mib2); 1093 {error, Reason} -> 1094 {error, Reason}; 1095 Else -> 1096 {error, Else} 1097 end. 1098 1099which_mib(M, M) -> 1100 ok; 1101which_mib(M1, M2) -> 1102 {error, {invalid_mib, M1, M2}}. 1103 1104 1105%% Default mib-storage 1106mib_storage() -> 1107 [{module, snmpa_mib_storage_ets}]. 1108 1109 1110%% -- 1111 1112display_memory_usage(MibsPid) -> 1113 SymInfo = sym_info(), 1114 SymProcSize = key1search(process_memory, SymInfo), 1115 DbSize = key1search(db_memory, SymInfo), 1116 MibsInfo = mibs_info(MibsPid), 1117 TreeSize = key1search(tree_size_bytes, MibsInfo), 1118 MibsProcMem = key1search(process_memory, MibsInfo), 1119 MibDbSize = key1search([db_memory,mib], MibsInfo), 1120 NodeDbSize = key1search([db_memory,node], MibsInfo), 1121 TreeDbSize = key1search([db_memory,tree], MibsInfo), 1122 ?IPRINT("Symbolic store memory usage: " 1123 "~n Process memory size: ~p" 1124 "~n Db size: ~p" 1125 "~n" 1126 "~nMib server memory usage: " 1127 "~n Tree size: ~p" 1128 "~n Process memory size: ~p" 1129 "~n Mib db size: ~p" 1130 "~n Node db size: ~p" 1131 "~n Tree db size: ~p" 1132 "~n", 1133 [SymProcSize, DbSize, 1134 TreeSize, MibsProcMem, MibDbSize, NodeDbSize, TreeDbSize]). 1135 1136key1search([], Res) -> 1137 Res; 1138key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> 1139 case lists:keysearch(Key, 1, List) of 1140 {value, {Key, Val}} -> 1141 key1search(Keys, Val); 1142 false -> 1143 undefined 1144 end; 1145key1search(Key, List) when is_atom(Key) -> 1146 case lists:keysearch(Key, 1, List) of 1147 {value, {Key, Val}} -> 1148 Val; 1149 false -> 1150 undefined 1151 end. 1152 1153join(Dir, File) -> 1154 filename:join(Dir, File). 1155