1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2002-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: -module(cpu_sup_SUITE). 20: -include_lib("test_server/include/test_server.hrl"). 21: 22: %% Test server specific exports 23: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). 24: -export([init_per_suite/1, end_per_suite/1]). 25: -export([init_per_testcase/2, end_per_testcase/2]). 26: 27: %% Test cases 28: -export([load_api/1]). 29: -export([util_api/1, util_values/1]). 30: -export([port/1]). 31: -export([terminate/1, unavailable/1, restart/1]). 32: 33: %% Default timetrap timeout (set in init_per_testcase) 34: -define(default_timeout, ?t:minutes(1)). 35: 36: init_per_suite(Config) when is_list(Config) -> 37: ?line ok = application:start(os_mon), 38: Config. 39: 40: end_per_suite(Config) when is_list(Config) -> 41: ?line ok = application:stop(os_mon), 42: Config. 43: 44: init_per_testcase(unavailable, Config) -> 45: terminate(Config), 46: init_per_testcase(dummy, Config); 47: init_per_testcase(_Case, Config) -> 48: Dog = ?t:timetrap(?default_timeout), 49: [{watchdog, Dog} | Config]. 50: 51: end_per_testcase(unavailable, Config) -> 52: restart(Config), 53: end_per_testcase(dummy, Config); 54: end_per_testcase(_Case, Config) -> 55: Dog = ?config(watchdog, Config), 56: ?t:timetrap_cancel(Dog), 57: ok. 58: 59: suite() -> [{ct_hooks,[ts_install_cth]}]. 60: 61: all() -> 62: case test_server:os_type() of 63: {unix, sunos} -> 64: [load_api, util_api, util_values, port, unavailable]; 65: {unix, linux} -> 66: [load_api, util_api, util_values, port, unavailable]; 67: {unix, _OSname} -> [load_api]; 68: _OS -> [unavailable] 69: end. 70: 71: groups() -> 72: []. 73: 74: init_per_group(_GroupName, Config) -> 75: Config. 76: 77: end_per_group(_GroupName, Config) -> 78: Config. 79: 80: 81: load_api(suite) -> 82: []; 83: load_api(doc) -> 84: ["Test of load API functions"]; 85: load_api(Config) when is_list(Config) -> 86: 87: %% nprocs() 88: ?line N = cpu_sup:nprocs(), 89: ?line true = is_integer(N), 90: ?line true = N>0, 91: ?line true = N<1000000, 92: 93: %% avg1() 94: ?line Load1 = cpu_sup:avg1(), 95: ?line true = is_integer(Load1), 96: ?line true = Load1>0, 97: 98: %% avg5() 99: ?line Load5 = cpu_sup:avg5(), 100: ?line true = is_integer(Load5), 101: ?line true = Load5>0, 102: 103: %% avg15() 104: ?line Load15 = cpu_sup:avg15(), 105: ?line true = is_integer(Load15), 106: ?line true = Load15>0, 107: 108: ok. 109: 110: util_api(suite) -> 111: []; 112: util_api(doc) -> 113: ["Test of utilization API functions"]; 114: util_api(Config) when is_list(Config) -> 115: %% Some useful funs when testing util/1 116: BusyP = fun({user, _Share}) -> true; 117: ({nice_user, _Share}) -> true; 118: ({kernel, _Share}) -> true; 119: ({hard_irq, _Share}) -> true; 120: ({soft_irq, _Share}) -> true; 121: (_) -> false 122: end, 123: NonBusyP = fun({wait, _Share}) -> true; 124: ({idle, _Share}) -> true; 125: ({steal, _Share}) -> true; 126: (_) -> false 127: end, 128: Sum = fun({_Tag, X}, Acc) -> Acc+X end, 129: 130: %% util() 131: ?line Util1 = cpu_sup:util(), 132: ?line true = is_number(Util1), 133: ?line true = Util1>0, 134: ?line Util2 = cpu_sup:util(), 135: ?line true = is_number(Util2), 136: ?line true = Util2>0, 137: 138: %% util([]) 139: ?line {all, Busy1, NonBusy1, []} = cpu_sup:util([]), 140: ?line 100.00 = Busy1 + NonBusy1, 141: 142: %% util([detailed]) 143: ?line {Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]), 144: ?line true = lists:all(fun(X) -> is_integer(X) end, Cpus2), 145: ?line true = lists:all(BusyP, Busy2), 146: ?line true = lists:all(NonBusyP, NonBusy2), 147: ?line 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2), 148: 149: %% util([per_cpu]) 150: ?line [{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]), 151: ?line true = is_integer(Cpu3), 152: ?line 100.00 = Busy3 + NonBusy3, 153: 154: %% util([detailed, per_cpu]) 155: ?line [{Cpu4, Busy4, NonBusy4, []}|_] = 156: cpu_sup:util([detailed, per_cpu]), 157: ?line true = is_integer(Cpu4), 158: ?line true = lists:all(BusyP, Busy2), 159: ?line true = lists:all(NonBusyP, NonBusy2), 160: ?line 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4), 161: 162: %% bad util/1 calls 163: ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)), 164: ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util([detialed])), 165: 166: ok. 167: 168: -define(SPIN_TIME, 1000). 169: 170: util_values(suite) -> 171: []; 172: util_values(doc) -> 173: ["Test utilization values"]; 174: util_values(Config) when is_list(Config) -> 175: 176: Tester = self(), 177: Ref = make_ref(), 178: Loop = fun (L) -> L(L) end, 179: Spinner = fun () -> 180: Looper = spawn_link(fun () -> Loop(Loop) end), 181: receive after ?SPIN_TIME -> ok end, 182: unlink(Looper), 183: exit(Looper, kill), 184: Tester ! Ref 185: end, 186: 187: ?line cpu_sup:util(), 188: 189: ?line spawn_link(Spinner), 190: ?line receive Ref -> ok end, 191: ?line HighUtil1 = cpu_sup:util(), 192: 193: ?line receive after ?SPIN_TIME -> ok end, 194: ?line LowUtil1 = cpu_sup:util(), 195: 196: ?line spawn_link(Spinner), 197: ?line receive Ref -> ok end, 198: ?line HighUtil2 = cpu_sup:util(), 199: 200: ?line receive after ?SPIN_TIME -> ok end, 201: ?line LowUtil2 = cpu_sup:util(), 202: 203: Utils = [{high1,HighUtil1}, {low1,LowUtil1}, 204: {high2,HighUtil2}, {low2,LowUtil2}], 205: ?t:format("Utils: ~p~n", [Utils]), 206: 207: ?line false = LowUtil1 > HighUtil1, 208: ?line false = LowUtil1 > HighUtil2, 209: ?line false = LowUtil2 > HighUtil1, 210: ?line false = LowUtil2 > HighUtil2, 211: 212: ok. 213: 214: 215: % Outdated 216: % The portprogram is now restarted if killed, and not by os_mon... 217: 218: port(suite) -> 219: []; 220: port(doc) -> 221: ["Test that cpu_sup handles a terminating port program"]; 222: port(Config) when is_list(Config) -> 223: case cpu_sup_os_pid() of 224: {ok, PidStr} -> 225: %% Monitor cpu_sup 226: ?line MonRef = erlang:monitor(process, cpu_sup), 227: ?line N1 = cpu_sup:nprocs(), 228: ?line true = N1>0, 229: 230: %% Kill the port program 231: case os:cmd("kill -9 " ++ PidStr) of 232: [] -> 233: %% cpu_sup should not terminate 234: receive 235: {'DOWN', MonRef, _, _, Reason} -> 236: ?line ?t:fail({unexpected_exit_reason, Reason}) 237: after 3000 -> 238: ok 239: end, 240: 241: %% Give cpu_sup time to restart cpu_sup port 242: ?t:sleep(?t:seconds(3)), 243: ?line N2 = cpu_sup:nprocs(), 244: ?line true = N2>0, 245: 246: erlang:demonitor(MonRef), 247: ok; 248: 249: Line -> 250: erlang:demonitor(MonRef), 251: {skip, {not_killed, Line}} 252: end; 253: _ -> 254: {skip, os_pid_not_found } 255: end. 256: 257: terminate(suite) -> 258: []; 259: terminate(Config) when is_list(Config) -> 260: ?line ok = application:set_env(os_mon, start_cpu_sup, false), 261: ?line ok = supervisor:terminate_child(os_mon_sup, cpu_sup), 262: ok. 263: 264: unavailable(suite) -> 265: []; 266: unavailable(doc) -> 267: ["Test correct behaviour when service is unavailable"]; 268: unavailable(Config) when is_list(Config) -> 269: 270: %% Make sure all API functions return their dummy values 271: ?line 0 = cpu_sup:nprocs(), 272: ?line 0 = cpu_sup:avg1(), 273: ?line 0 = cpu_sup:avg5(), 274: ?line 0 = cpu_sup:avg15(), 275: ?line 0 = cpu_sup:util(), 276: ?line {all,0,0,[]} = cpu_sup:util([]), 277: ?line {all,0,0,[]} = cpu_sup:util([detailed]), 278: ?line {all,0,0,[]} = cpu_sup:util([per_cpu]), 279: ?line {all,0,0,[]} = cpu_sup:util([detailed,per_cpu]), 280: 281: ok. 282: 283: restart(suite) -> 284: []; 285: restart(Config) when is_list(Config) -> 286: ?line ok = application:set_env(os_mon, start_cpu_sup, true), 287: ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, cpu_sup), 288: ok. 289: 290: %% Aux 291: 292: cpu_sup_os_pid() -> 293: Str = os:cmd("ps -e | grep '[c]pu_sup'"), 294: case io_lib:fread("~s", Str) of 295: {ok, [Pid], _Rest} -> {ok, Pid}; 296: _ -> {error, pid_not_found} 297: end.