1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2016. 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(memsup_SUITE). 21-include_lib("common_test/include/ct.hrl"). 22 23%% Test server specific exports 24-export([all/0, suite/0]). 25-export([init_per_suite/1, end_per_suite/1]). 26-export([init_per_testcase/2, end_per_testcase/2]). 27 28%% Test cases 29-export([api/1, alarm1/1, alarm2/1, process/1]). 30-export([config/1, timeout/1, unavailable/1, port/1]). 31-export([otp_5910/1, improved_system_memory_data/1]). 32 33 34-define(SYSTEM_MEMORY_DATA_TAGS, 35 [total_memory, 36 free_memory, 37 system_total_memory, 38 largest_free, 39 number_of_free, 40 free_swap, 41 total_swap, 42 cached_memory, 43 buffered_memory, 44 shared_memory]). 45 46-define(IMPROVED_SYSTEM_MEMORY_DATA_TAGS, 47 [available_memory | ?SYSTEM_MEMORY_DATA_TAGS]). 48 49 50init_per_suite(Config) when is_list(Config) -> 51 ok = application:start(os_mon), 52 Config. 53 54end_per_suite(Config) when is_list(Config) -> 55 ok = application:stop(os_mon), 56 Config. 57 58init_per_testcase(_Case, Config) -> 59 Config. 60 61end_per_testcase(_Case, _Config) -> 62 ok. 63 64suite() -> 65 [{ct_hooks,[ts_install_cth]}, 66 {timetrap,{minutes,1}}]. 67 68all() -> 69 All = case test_server:os_type() of 70 {unix, sunos} -> 71 [api, alarm1, alarm2, process, config, timeout, 72 unavailable, port]; 73 {unix, linux} -> 74 [api, alarm1, alarm2, process, timeout]; 75 _OS -> [api, alarm1, alarm2, process] 76 end, 77 Bugs = [otp_5910], 78 All ++ Bugs ++ [improved_system_memory_data]. 79 80 81%% Test of API functions 82api(Config) when is_list(Config) -> 83 84 %% get_memory_data() 85 RegMemData = memsup:get_memory_data(), 86 case RegMemData of 87 {TotMem, AllBytes, {Pid, PidBytes}} when is_integer(TotMem), 88 is_integer(AllBytes), 89 is_pid(Pid), 90 is_integer(PidBytes) -> 91 ok; 92 {0, 0, _WorstPid} -> 93 ct:fail(first_data_collection_failed); 94 _ -> 95 ct:fail({bad_return, RegMemData}) 96 end, 97 98 %% get_system_memory_data() 99 ExtMemData = memsup:get_system_memory_data(), 100 Tags = ?SYSTEM_MEMORY_DATA_TAGS, 101 102 true = lists:all(fun({Tag,Value}) when is_atom(Tag), 103 is_integer(Value) -> 104 lists:member(Tag, Tags); 105 (_) -> 106 false 107 end, ExtMemData), 108 109 %% get_os_wordsize() 110 ok = case memsup:get_os_wordsize() of 111 32 -> 112 32 = 8*erlang:system_info({wordsize,external}), 113 ok; 114 64 -> 115 % No reliable test here 116 ok; 117 unsupported_os -> 118 ok; 119 _ -> 120 error 121 end, 122 123 %% get_check_interval() 124 60000 = memsup:get_check_interval(), 125 126 %% set_check_interval(Minutes) 127 ok = memsup:set_check_interval(2), 128 120000 = memsup:get_check_interval(), 129 {'EXIT',{badarg,_}} = 130 (catch memsup:set_check_interval(0.2)), 131 120000 = memsup:get_check_interval(), 132 ok = memsup:set_check_interval(1), 133 134 %% get_procmem_high_watermark() 135 5 = memsup:get_procmem_high_watermark(), 136 137 %% set_procmem_high_watermark() 138 ok = memsup:set_procmem_high_watermark(0.1), 139 10 = memsup:get_procmem_high_watermark(), 140 {'EXIT',{badarg,_}} = 141 (catch memsup:set_procmem_high_watermark(-0.1)), 142 10 = memsup:get_procmem_high_watermark(), 143 ok = memsup:set_procmem_high_watermark(0.05), 144 145 %% get_sysmem_high_watermark() 146 80 = memsup:get_sysmem_high_watermark(), 147 148 %% set_sysmem_high_watermark() 149 ok = memsup:set_sysmem_high_watermark(0.9), 150 90 = memsup:get_sysmem_high_watermark(), 151 {'EXIT',{badarg,_}} = 152 (catch memsup:set_sysmem_high_watermark(-0.9)), 153 90 = memsup:get_sysmem_high_watermark(), 154 ok = memsup:set_sysmem_high_watermark(0.8), 155 156 %% get|set_helper_timeout 157 30 = memsup:get_helper_timeout(), 158 ok = memsup:set_helper_timeout(29), 159 29 = memsup:get_helper_timeout(), 160 {'EXIT',{badarg,_}} = (catch memsup:set_helper_timeout(31.0)), 161 29 = memsup:get_helper_timeout(), 162 ok. 163 164%%---------------------------------------------------------------------- 165%% NOTE: The test case is a bit weak as it will fail if the memory 166%% usage changes too much during its course. 167%%---------------------------------------------------------------------- 168 169%% Test alarms when memsup_system_only==false 170alarm1(Config) when is_list(Config) -> 171 172 %% If system memory usage is too high, the testcase cannot 173 %% be run correctly 174 {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), 175 io:format("alarm1: Total: ~p, Alloc: ~p~n", [Total, Alloc]), 176 SysUsage = Alloc/Total, 177 if 178 SysUsage > 0.99 -> 179 {skip, sys_mem_too_high}; 180 true -> 181 alarm1(Config, SysUsage) 182 end. 183 184alarm1(_Config, SysUsage) -> 185 %% Set a long memory check interval, we will force memory checks 186 %% instead 187 ok = memsup:set_check_interval(60), 188 189 %% Check thresholds 190 SysThreshold = (memsup:get_sysmem_high_watermark()/100), 191 ProcThreshold = (memsup:get_procmem_high_watermark()/100), 192 193 %% Check if a system alarm already should be set or not 194 SysP = if 195 SysUsage>SysThreshold -> true; 196 SysUsage=<SysThreshold -> false 197 end, 198 199 %% If system memory is higher than threshold, make sure the system 200 %% alarm is set. Otherwise, make sure it is not set 201 case alarm_set(system_memory_high_watermark) of 202 {true, []} when SysP -> 203 ok; 204 false when not SysP -> 205 ok; 206 _ -> 207 ct:fail({sys_alarm, SysUsage, SysThreshold}) 208 end, 209 210 %% Lower/raise the threshold to clear/set the alarm 211 NewSysThreshold = if 212 SysP -> 213 Value = 1.1*SysUsage, 214 if 215 Value > 0.99 -> 0.99; 216 true -> Value 217 end; 218 not SysP -> 0.9*SysUsage 219 end, 220 221 ok = memsup:set_sysmem_high_watermark(NewSysThreshold), 222 223 %% Initiate and wait for a new data collection 224 ok = force_collection(), 225 226 %% Make sure the alarm is cleared/set 227 ct:sleep({seconds,5}), 228 case alarm_set(system_memory_high_watermark) of 229 {true, []} when not SysP -> 230 ok; 231 false when SysP -> 232 ok; 233 _ -> 234 ct:fail({sys_alarm, SysUsage, NewSysThreshold}) 235 end, 236 237 %% Reset the threshold to set/clear the alarm again 238 ok = memsup:set_sysmem_high_watermark(SysThreshold), 239 ok = force_collection(), 240 ct:sleep({seconds,1}), 241 case alarm_set(system_memory_high_watermark) of 242 {true, []} when SysP -> 243 ok; 244 false when not SysP -> 245 ok; 246 _ -> 247 ct:fail({sys_alarm, SysUsage, SysThreshold}) 248 end, 249 250 %% Check memory usage 251 {Total2, _, {WorstPid, PidAlloc}} = memsup:get_memory_data(), 252 253 %% Check if a process alarm already should be set or not 254 PidUsage = PidAlloc/Total2, 255 ProcP = if 256 PidUsage>ProcThreshold -> true; 257 PidUsage=<ProcThreshold -> false 258 end, 259 260 %% Make sure the process alarm is set/not set accordingly 261 case alarm_set(process_memory_high_watermark) of 262 {true, WorstPid} when ProcP -> 263 ok; 264 false when not ProcP -> 265 ok; 266 {true, BadPid1} when ProcP -> 267 ct:fail({proc_alarm, WorstPid, BadPid1}); 268 _ -> 269 ct:fail({proc_alarm, PidUsage, ProcThreshold}) 270 end, 271 272 %% Lower/raise the threshold to clear/set the alarm 273 NewProcThreshold = if 274 ProcP -> 1.1*PidUsage; 275 not ProcP -> 0.9*PidUsage 276 end, 277 ok = memsup:set_procmem_high_watermark(NewProcThreshold), 278 ok = force_collection(), 279 ct:sleep({seconds,1}), 280 case alarm_set(process_memory_high_watermark) of 281 {true, WorstPid} when not ProcP -> 282 ok; 283 false when ProcP -> 284 ok; 285 {true, BadPid2} when not ProcP -> 286 ct:fail({proc_alarm, WorstPid, BadPid2}); 287 _ -> 288 ct:fail({proc_alarm, PidUsage, ProcThreshold}) 289 end, 290 291 %% Reset the threshold to clear/set the alarm 292 ok = memsup:set_procmem_high_watermark(ProcThreshold), 293 ok = force_collection(), 294 ct:sleep({seconds,1}), 295 case alarm_set(process_memory_high_watermark) of 296 {true, WorstPid} when ProcP -> 297 ok; 298 false when not ProcP -> 299 ok; 300 {true, BadPid3} when ProcP -> 301 ct:fail({proc_alarm, WorstPid, BadPid3}); 302 _ -> 303 ct:fail({proc_alarm, PidUsage, ProcThreshold}) 304 end, 305 306 %% Reset memory check interval 307 ok = memsup:set_check_interval(1), 308 ok. 309 310%% Test alarms when memsup_system_only==true 311alarm2(Config) when is_list(Config) -> 312 313 %% If system memory usage is too high, the testcase cannot 314 %% be run correctly 315 {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), 316 SysUsage = Alloc/Total, 317 if 318 SysUsage>0.99 -> 319 {skip, sys_mem_too_high}; 320 true -> 321 alarm2(Config, SysUsage) 322 end. 323 324alarm2(_Config, _SysUsage) -> 325 326 %% Change memsup_system_only and restart memsup 327 ok = application:set_env(os_mon, memsup_system_only, true), 328 ok = supervisor:terminate_child(os_mon_sup, memsup), 329 {ok, _Memsup1} = supervisor:restart_child(os_mon_sup, memsup), 330 331 %% Set a long memory check interval, we will force memory checks 332 %% instead 333 ok = memsup:set_check_interval(60), 334 335 %% Check data and thresholds 336 {Total, Alloc, undefined} = memsup:get_memory_data(), 337 SysThreshold = (memsup:get_sysmem_high_watermark()/100), 338 true = is_integer(memsup:get_procmem_high_watermark()), 339 340 %% Check if a system alarm already should be set or not 341 SysUsage = Alloc/Total, 342 SysP = if 343 SysUsage>SysThreshold -> true; 344 SysUsage=<SysThreshold -> false 345 end, 346 347 %% If system memory is higher than threshold, make sure the system 348 %% alarm is set. Otherwise, make sure it is not set 349 case alarm_set(system_memory_high_watermark) of 350 {true, []} when SysP -> 351 ok; 352 false when not SysP -> 353 ok; 354 _ -> 355 ct:fail({sys_alarm, SysUsage, SysThreshold}) 356 end, 357 358 %% Lower/raise the threshold to clear/set the alarm 359 NewSysThreshold = if 360 SysP -> 361 Value = 1.1*SysUsage, 362 if 363 Value > 0.99 -> 0.99; 364 true -> Value 365 end; 366 not SysP -> 0.9*SysUsage 367 end, 368 369 ok = memsup:set_sysmem_high_watermark(NewSysThreshold), 370 371 %% Initiate and wait for a new data collection 372 ok = force_collection(), 373 374 %% Make sure the alarm is cleared/set 375 ct:sleep({seconds,1}), 376 case alarm_set(system_memory_high_watermark) of 377 {true, []} when not SysP -> 378 ok; 379 false when SysP -> 380 ok; 381 _ -> 382 ct:fail({sys_alarm, SysUsage, NewSysThreshold}) 383 end, 384 385 %% Reset the threshold to set/clear the alarm again 386 ok = memsup:set_sysmem_high_watermark(SysThreshold), 387 ok = force_collection(), 388 ct:sleep({seconds,1}), 389 case alarm_set(system_memory_high_watermark) of 390 {true, []} when SysP -> 391 ok; 392 false when not SysP -> 393 ok; 394 _ -> 395 ct:fail({sys_alarm, SysUsage, SysThreshold}) 396 end, 397 398 %% Reset memsup_system_only and restart memsup 399 %% (memory check interval is then automatically reset) 400 ok = application:set_env(os_mon, memsup_system_only, false), 401 ok = supervisor:terminate_child(os_mon_sup, memsup), 402 {ok, _Memsup2} = supervisor:restart_child(os_mon_sup, memsup), 403 404 ok. 405 406alarm_set(Alarm) -> 407 alarm_set(Alarm, alarm_handler:get_alarms()). 408alarm_set(Alarm, [{Alarm,Data}|_]) -> 409 {true,Data}; 410alarm_set(Alarm, [_|T]) -> 411 alarm_set(Alarm, T); 412alarm_set(_Alarm, []) -> 413 false. 414 415%% Make sure memsup discovers a process grown very large 416process(Config) when is_list(Config) -> 417 418 %% Set a long memory check interval, we will force memory checks 419 %% instead 420 ok = memsup:set_check_interval(60), 421 422 %% Collect data 423 MemData = memsup:get_memory_data(), 424 io:format("process: memsup:get_memory_data() = ~p~n", [MemData]), 425 {_Total,_Free,{_,Bytes}} = MemData, 426 427 %% Start a new process larger than Worst 428 WorsePid = spawn(fun() -> new_hog(Bytes) end), 429 ct:sleep({seconds,1}), 430 431 %% Initiate and wait for a new data collection 432 ok = force_collection(), 433 434 %% Check that get_memory_data() returns updated result 435 case memsup:get_memory_data() of 436 {_, _, {WorsePid, _MoreBytes}} -> 437 ok; 438 {_, _, BadWorst} -> 439 ct:fail({worst_pid, BadWorst}) 440 end, 441 442 %% Reset memory check interval 443 exit(WorsePid, done), 444 ok = memsup:set_check_interval(1), 445 ok. 446 447new_hog(Bytes) -> 448 WordSize = erlang:system_info(wordsize), 449 N = (Bytes+200) div WordSize div 2, 450 List = lists:duplicate(N, a), 451 new_hog_1(List). 452 453new_hog_1(List) -> 454 receive 455 _Any -> exit(List) 456 end. 457 458%% Test configuration 459config(Config) when is_list(Config) -> 460 461 %% Change configuration parameters and make sure change is reflected 462 %% when memsup is restarted 463 ok = application:set_env(os_mon, memory_check_interval, 2), 464 ok = 465 application:set_env(os_mon, system_memory_high_watermark, 0.9), 466 ok = 467 application:set_env(os_mon, process_memory_high_watermark, 0.1), 468 ok = application:set_env(os_mon, memsup_helper_timeout, 35), 469 ok = application:set_env(os_mon, memsup_system_only, true), 470 471 ok = supervisor:terminate_child(os_mon_sup, memsup), 472 {ok, _Child1} = supervisor:restart_child(os_mon_sup, memsup), 473 474 120000 = memsup:get_check_interval(), 475 90 = memsup:get_sysmem_high_watermark(), 476 10 = memsup:get_procmem_high_watermark(), 477 35 = memsup:get_helper_timeout(), 478 479 %% Also try this with bad parameter values, should be ignored 480 ok = application:set_env(os_mon, memory_check_interval, 0.2), 481 ok = 482 application:set_env(os_mon, system_memory_high_watermark, -0.9), 483 ok = 484 application:set_env(os_mon, process_memory_high_watermark,-0.1), 485 ok = application:set_env(os_mon, memsup_helper_timeout, 0.35), 486 ok = application:set_env(os_mon, memsup_system_only, arne), 487 488 ok = supervisor:terminate_child(os_mon_sup, memsup), 489 {ok, _Child2} = supervisor:restart_child(os_mon_sup, memsup), 490 491 60000 = memsup:get_check_interval(), 492 80 = memsup:get_sysmem_high_watermark(), 493 5 = memsup:get_procmem_high_watermark(), 494 30 = memsup:get_helper_timeout(), 495 496 %% Reset configuration parameters 497 ok = application:set_env(os_mon, memory_check_interval, 1), 498 ok = 499 application:set_env(os_mon, system_memory_high_watermark, 0.8), 500 ok = 501 application:set_env(os_mon, process_memory_high_watermark,0.05), 502 ok = application:set_env(os_mon, memsup_helper_timeout, 30), 503 ok = application:set_env(os_mon, memsup_system_only, false), 504 505 ok. 506 507%% Test correct behaviour when service is unavailable 508unavailable(Config) when is_list(Config) -> 509 510 %% Close memsup 511 ok = application:set_env(os_mon, start_memsup, false), 512 ok = supervisor:terminate_child(os_mon_sup, memsup), 513 514 %% Make sure all API functions return their dummy values 515 {0,0,{_Pid,0}} = memsup:get_memory_data(), 516 ok = application:set_env(os_mon, memsup_system_only, true), 517 {0,0,undefined} = memsup:get_memory_data(), 518 ok = application:set_env(os_mon, memsup_system_only, false), 519 [] = memsup:get_system_memory_data(), 520 0 = memsup:get_os_wordsize(), 521 60000 = memsup:get_check_interval(), 522 ok = memsup:set_check_interval(2), 523 5 = memsup:get_procmem_high_watermark(), 524 ok = memsup:set_procmem_high_watermark(0.10), 525 80 = memsup:get_sysmem_high_watermark(), 526 ok = memsup:set_sysmem_high_watermark(0.90), 527 30 = memsup:get_helper_timeout(), 528 ok = memsup:set_helper_timeout(35), 529 530 %% Start memsup again, 531 ok = application:set_env(os_mon, start_memsup, true), 532 {ok, _Child} = supervisor:restart_child(os_mon_sup, memsup), 533 534 ok. 535 536%% Test stability of memsup when data collection times out 537timeout(Config) when is_list(Config) -> 538 539 %% Set a long memory check interval and memsup_helper timeout, 540 %% we will force memory checks instead and fake timeouts 541 ok = memsup:set_check_interval(60), 542 ok = memsup:set_helper_timeout(3600), 543 544 %% Provoke a timeout during memory collection 545 memsup ! time_to_collect, 546 memsup ! reg_collection_timeout, 547 548 %% Not much we can check though, except that memsup is still running 549 {_,_,_} = memsup:get_memory_data(), 550 551 %% Provoke a timeout during extensive memory collection 552 %% We fake a gen_server:call/2 to be able to send a timeout message 553 %% while the request is being handled 554 555 %% Linux should be handled the same way as solaris. 556 557 % TimeoutMsg = case ?t:os_type() of 558 % {unix, sunos} -> ext_collection_timeout; 559 % {unix, linux} -> reg_collection_timeout 560 % end, 561 562 TimeoutMsg = ext_collection_timeout, 563 564 Pid = whereis(memsup), 565 Mref = erlang:monitor(process, Pid), 566 Pid ! {'$gen_call', {self(), Mref}, get_system_memory_data}, 567 Pid ! TimeoutMsg, 568 receive 569 {Mref, []} -> 570 erlang:demonitor(Mref), 571 ok; 572 {Mref, Res} -> 573 erlang:demonitor(Mref), 574 ct:fail({unexpected_result, Res}); 575 {'DOWN', Mref, _, _, _} -> 576 ct:fail(no_result) 577 end, 578 579 %% Reset memory check interval and memsup_helper timeout 580 ok = memsup:set_check_interval(1), 581 ok = memsup:set_helper_timeout(30), 582 memsup ! time_to_collect, 583 584 [_|_] = memsup:get_system_memory_data(), 585 586 ok. 587 588%% Test that memsup handles a terminating port program 589port(Config) when is_list(Config) -> 590 Str = os:cmd("ps -e | grep '[m]emsup'"), 591 case io_lib:fread("~s", Str) of 592 {ok, [Pid], _Rest} -> 593 594 %% Monitor memsup 595 MonRef = erlang:monitor(process, memsup), 596 {Total1,_Alloc1,_Worst1} = memsup:get_memory_data(), 597 true = Total1>0, 598 599 %% Kill the port program 600 case os:cmd("kill -9 " ++ Pid) of 601 [] -> 602 603 %% memsup should now terminate 604 receive 605 {'DOWN', MonRef, _, _, {port_died, _Reason}} -> 606 ok; 607 {'DOWN', MonRef, _, _, Reason} -> 608 ct:fail({unexpected_exit_reason, Reason}) 609 after 610 3000 -> 611 ct:fail(still_alive) 612 end, 613 614 %% Give os_mon_sup time to restart memsup 615 ct:sleep({seconds,3}), 616 {Total2,_Alloc2,_Worst2} = 617 memsup:get_memory_data(), 618 true = Total2>0, 619 620 ok; 621 622 Line -> 623 erlang:demonitor(MonRef), 624 {skip, {not_killed, Line}} 625 end; 626 _ -> 627 {skip, {os_pid_not_found, Str}} 628 end. 629 630%% Test that alarms are cleared and not set twice 631otp_5910(Config) when is_list(Config) -> 632 Alarms = 633 [system_memory_high_watermark, process_memory_high_watermark], 634 635 %% Make sure memsup sets both alarms 636 ok = application:set_env(os_mon, memory_check_interval, 60), 637 ok = memsup:set_check_interval(60), 638 SysThreshold = (memsup:get_sysmem_high_watermark()/100), 639 ProcThreshold = (memsup:get_procmem_high_watermark()/100), 640 641 MemData = memsup:get_memory_data(), 642 643 io:format("otp_5910: memsup:get_memory_data() = ~p~n", [MemData]), 644 {Total, Alloc, {_Pid, _Bytes}} = MemData, 645 Pid = spawn_opt(fun() -> 646 receive 647 die -> ok 648 end 649 end, [{min_heap_size, 1000}]), 650 %% Create a process guaranteed to live, be constant and 651 %% break memsup process limit 652 {memory, Bytes} = erlang:process_info(Pid,memory), 653 SysUsage = Alloc/Total, 654 ProcUsage = Bytes/Total, 655 656 if 657 SysUsage>SysThreshold -> 658 ok; 659 SysUsage=<SysThreshold -> 660 ok = application:set_env(os_mon, 661 sys_mem_high_watermark, 662 0.5 * SysUsage), 663 ok = memsup:set_sysmem_high_watermark(0.5 * SysUsage) 664 end, 665 if 666 ProcUsage>ProcThreshold -> 667 ok; 668 ProcUsage=<ProcThreshold -> 669 ok = application:set_env(os_mon, 670 proc_mem_high_watermark, 671 0.5 * ProcUsage), 672 ok = memsup:set_procmem_high_watermark(0.5 *ProcUsage) 673 end, 674 ok = force_collection(), 675 ct:sleep({seconds,1}), 676 lists:foreach(fun(AlarmId) -> 677 case alarm_set(AlarmId) of 678 {true, _} -> ok; 679 false -> 680 ct:fail({alarm_not_set, AlarmId}) 681 end 682 end, 683 Alarms), 684 685 %% Kill guaranteed process... 686 Pid ! die, 687 %% Kill memsup 688 exit(whereis(memsup), faked_memsup_crash), 689 %% Wait a little to make sure memsup has been restarted, 690 %% then make sure the alarms are set once, but not twice 691 ct:sleep({seconds,1}), 692 MemUsage = memsup:get_memory_data(), 693 SetAlarms = alarm_handler:get_alarms(), 694 case lists:foldl(fun(system_memory_high_watermark, {S, P}) -> 695 {S+1, P}; 696 (process_memory_high_watermark, {S, P}) -> 697 {S, P+1}; 698 (_AlarmId, Acc0) -> 699 Acc0 700 end, 701 {0, 0}, 702 SetAlarms) of 703 {0, 0} -> 704 ok; 705 _ -> 706 ct:fail({bad_number_of_alarms, SetAlarms, MemUsage}) 707 end, 708 709 %% Stop OS_Mon and make sure all memsup alarms are cleared 710 ok = application:stop(os_mon), 711 ct:sleep({seconds,1}), 712 lists:foreach(fun(AlarmId) -> 713 case alarm_set(AlarmId) of 714 false -> ok; 715 {true, _} -> 716 ct:fail({alarm_is_set, AlarmId}) 717 end 718 end, 719 Alarms), 720 721 %% Reset configuration and restart OS_Mon 722 ok = application:set_env(os_mon,memory_check_interval,1), 723 ok = application:set_env(os_mon,sys_mem_high_watermark,0.8), 724 ok = application:set_env(os_mon,proc_mem_high_watermark,0.05), 725 ok = application:start(os_mon), 726 ok. 727 728improved_system_memory_data(Config) -> 729 {ok, Node} = start_node(Config, "-os_mon memsup_improved_system_memory_data true"), 730 ok = rpc:call(Node, application, start, [sasl]), 731 ok = rpc:call(Node, application, start, [os_mon]), 732 733 ExtMemData = rpc:call(Node, memsup, get_system_memory_data, []), 734 735 stop_node(Node), 736 737 Tags = ?IMPROVED_SYSTEM_MEMORY_DATA_TAGS, 738 AvailableMemoryPresent 739 = lists:foldl(fun ({Tag,Value}, AMP) when is_atom(Tag), 740 is_integer(Value), 741 Value >= 0 -> 742 true = lists:member(Tag, Tags), 743 case Tag of 744 available_memory -> 745 false = AMP, 746 true; 747 _ -> 748 AMP 749 end 750 end, 751 false, 752 ExtMemData), 753 754 case os:type() of 755 {unix,linux} -> 756 {ok, Data} = file:read_file("/proc/meminfo"), 757 case re:run(Data, <<"MemAvailable">>) of 758 {match, _} -> 759 true = AvailableMemoryPresent, 760 {comment, "available_memory present in result"}; 761 _ -> 762 {comment, "No available_memory present in result"} 763 end; 764 _ -> 765 ok 766 end. 767 768 769%%---------------------------------------------------------------------- 770%% Auxiliary 771%%---------------------------------------------------------------------- 772 773force_collection() -> 774 erlang:trace(whereis(memsup), true, ['receive']), 775 memsup ! time_to_collect, 776 TimerRef = erlang:send_after(5000, self(), timeout), 777 force_collection(TimerRef). 778 779force_collection(TimerRef) -> 780 receive 781 {trace, _Pid, 'receive', {collected_sys, _Sys}} -> 782 erlang:cancel_timer(TimerRef), 783 erlang:trace(whereis(memsup), false, ['receive']), 784 flush(), 785 ok; 786 {trace, _Pid, 'receive', reg_collection_timeout} -> 787 erlang:cancel_timer(TimerRef), 788 erlang:trace(whereis(memsup), false, ['receive']), 789 flush(), 790 collection_timeout; 791 timout -> 792 erlang:trace(whereis(memsup), false, ['receive']), 793 flush(), 794 timeout; 795 _Msg -> 796 force_collection(TimerRef) 797 end. 798 799flush() -> 800 receive 801 {trace, _, _, _} -> 802 flush(); 803 timeout -> 804 flush() 805 after 0 -> 806 ok 807 end. 808 809start_node(Config) -> 810 start_node(Config, ""). 811 812start_node(Config, Args) when is_list(Config) -> 813 Pa = filename:dirname(code:which(?MODULE)), 814 Name = list_to_atom(atom_to_list(?MODULE) 815 ++ "-" 816 ++ atom_to_list(proplists:get_value(testcase, Config)) 817 ++ "-" 818 ++ integer_to_list(erlang:system_time(second)) 819 ++ "-" 820 ++ integer_to_list(erlang:unique_integer([positive]))), 821 test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). 822 823stop_node(Node) -> 824 test_server:stop_node(Node). 825