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