1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2010-2018. 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-module(lcnt_SUITE). 22-include_lib("common_test/include/ct.hrl"). 23 24%% Test server specific exports 25-export([all/0, suite/0]). 26-export([init_per_testcase/2, end_per_testcase/2]). 27 28%% Test cases 29-export([t_load/1, 30 t_conflicts/1, 31 t_locations/1, 32 t_swap_keys/1, 33 t_implicit_start/1, 34 t_crash_before_collect/1, 35 smoke_lcnt/1]). 36 37init_per_testcase(_Case, Config) -> 38 Config. 39 40end_per_testcase(_Case, _Config) -> 41 catch lcnt:stop(), 42 ok. 43 44suite() -> 45 [{ct_hooks,[ts_install_cth]}, 46 {timetrap,{minutes,4}}]. 47 48all() -> 49 [t_load, t_conflicts, t_locations, t_swap_keys, t_implicit_start, 50 t_crash_before_collect, smoke_lcnt]. 51 52%%---------------------------------------------------------------------- 53%% Tests 54%%---------------------------------------------------------------------- 55 56%% Load data from file. 57t_load(Config) when is_list(Config) -> 58 Path = proplists:get_value(data_dir, Config), 59 Files = [filename:join([Path,"big_bang_40.lcnt"]), 60 filename:join([Path,"ehb_3_3_hist.lcnt"])], 61 ok = t_load_file(Files), 62 ok. 63 64t_load_file([]) -> ok; 65t_load_file([File|Files]) -> 66 {ok, _} = lcnt:start(), 67 ok = lcnt:load(File), 68 ok = lcnt:stop(), 69 t_load_file(Files). 70 71%% API: conflicts 72t_conflicts(Config) when is_list(Config) -> 73 Path = proplists:get_value(data_dir, Config), 74 Files = [filename:join([Path,"big_bang_40.lcnt"]), 75 filename:join([Path,"ehb_3_3_hist.lcnt"])], 76 ok = t_conflicts_file(Files), 77 ok. 78 79t_conflicts_file([]) -> ok; 80t_conflicts_file([File|Files]) -> 81 {ok, _} = lcnt:start(), 82 ok = lcnt:load(File), 83 ok = lcnt:conflicts(), 84 THs = [-1, 5], 85 Print = [name , id , type , entry , tries , colls , ratio , time , duration], 86 Opts = [ 87 [{sort, Sort}, {reverse, Rev}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, [Print]}] || 88 Sort <- [name , type , tries , colls , ratio , time], 89 ML <- [none, 32], 90 Combine <- [true, false], 91 TH <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs], 92 Rev <- [true, false] 93 ], 94 ok = test_conflicts_opts(Opts), 95 ok = lcnt:stop(), 96 t_conflicts_file(Files). 97 98 99test_conflicts_opts([]) -> ok; 100test_conflicts_opts([Opt|Opts]) -> 101 ok = lcnt:conflicts(Opt), 102 test_conflicts_opts(Opts). 103 104%% API: locations 105t_locations(Config) when is_list(Config) -> 106 Path = proplists:get_value(data_dir, Config), 107 Files = [filename:join([Path,"big_bang_40.lcnt"]), 108 filename:join([Path,"ehb_3_3_hist.lcnt"])], 109 ok = t_locations_file(Files), 110 ok. 111 112t_locations_file([]) -> ok; 113t_locations_file([File|Files]) -> 114 {ok, _} = lcnt:start(), 115 ok = lcnt:load(File), 116 ok = lcnt:locations(), 117 THs = [-1, 0, 100], 118 Print = [name , id , type , entry , tries , colls , ratio , time , duration], 119 Opts = [ 120 [{full_id, Id}, {sort, Sort}, {max_locks, ML}, {combine, Combine}, {thresholds, [TH]}, {print, Print}] || 121 Sort <- [name , id , type , tries , colls , ratio , time , entry], 122 ML <- [none, 64], 123 Combine <- [true, false], 124 TH <- [{tries, Tries} || Tries <- THs] ++ [{colls, Colls} || Colls <- THs] ++ [{time, Time} || Time <- THs], 125 Id <- [true, false] 126 ], 127 ok = test_locations_opts(Opts), 128 ok = lcnt:stop(), 129 t_locations_file(Files). 130 131test_locations_opts([]) -> ok; 132test_locations_opts([Opt|Opts]) -> 133 ok = lcnt:locations(Opt), 134 test_locations_opts(Opts). 135 136%% Test interchanging port/process id with class 137t_swap_keys(Config) when is_list(Config) -> 138 Path = proplists:get_value(data_dir, Config), 139 Files = [filename:join([Path,"big_bang_40.lcnt"]), 140 filename:join([Path,"ehb_3_3_hist.lcnt"])], 141 ok = t_swap_keys_file(Files), 142 ok. 143 144t_swap_keys_file([]) -> ok; 145t_swap_keys_file([File|Files]) -> 146 {ok, _} = lcnt:start(), 147 ok = lcnt:load(File), 148 ok = lcnt:conflicts(), 149 ok = lcnt:swap_pid_keys(), 150 ok = lcnt:conflicts(), 151 ok = lcnt:stop(), 152 t_swap_keys_file(Files). 153 154%% Prior to OTP-14913 this would crash with 'noproc' as the lcnt server hadn't 155%% been started yet. 156t_implicit_start(Config) when is_list(Config) -> 157 ok = lcnt:conflicts(). 158 159t_crash_before_collect(Config) when is_list(Config) -> 160 {ok, _} = lcnt:start(), 161 ok = lcnt:information(). 162 163%% Simple smoke test of actual lock-counting, if running on 164%% a run-time with lock-counting enabled. 165smoke_lcnt(Config) -> 166 case catch erlang:system_info(lock_counting) of 167 true -> 168 do_smoke_lcnt(Config); 169 _ -> 170 {skip,"Lock counting is not enabled"} 171 end. 172 173do_smoke_lcnt(Config) -> 174 PrivDir = proplists:get_value(priv_dir, Config), 175 SaveFile = filename:join(PrivDir, atom_to_list(?FUNCTION_NAME)), 176 {Time,ok} = timer:tc(fun() -> lcnt:apply(fun() -> big_bang(200) end) end), 177 io:format("~p ms\n", [Time]), 178 ok = lcnt:conflicts(), 179 ok = lcnt:save(SaveFile), 180 ok = lcnt:load(SaveFile), 181 ok = lcnt:conflicts(), 182 lcnt:stop(). 183 184 185%%% 186%%% A slightly modified version of Rickard Green's Big Bang benchmark. 187%%% 188 189big_bang(N) when is_integer(N) -> 190 Procs = spawn_procs(N), 191 RMsgs = lists:map(fun (P) -> {done, P} end, Procs), 192 send_procs(Procs, {procs, Procs, self()}), 193 receive_msgs(RMsgs), 194 lists:foreach(fun (P) -> exit(P, normal) end, Procs). 195 196pinger([], [], true) -> 197 receive 198 {procs, Procs, ReportTo} -> 199 pinger(Procs, [], ReportTo) 200 end; 201pinger([], [], false) -> 202 receive {ping, From} -> From ! {pong, self()} end, 203 pinger([],[],false); 204pinger([], [], ReportTo) -> 205 ReportTo ! {done, self()}, 206 pinger([],[],false); 207pinger([],[Po|Pos] = Pongers, ReportTo) -> 208 receive 209 {ping, From} -> 210 From ! {pong, self()}, 211 pinger([], Pongers, ReportTo); 212 {pong, Po} -> 213 pinger([], Pos, ReportTo) 214 end; 215pinger([Pi|Pis], Pongers, ReportTo) -> 216 receive {ping, From} -> From ! {pong, self()} 217 after 0 -> ok 218 end, 219 Pi ! {ping, self()}, 220 pinger(Pis, [Pi|Pongers], ReportTo). 221 222spawn_procs(N) when N =< 0 -> 223 []; 224spawn_procs(N) -> 225 [spawn_link(fun () -> pinger([], [], true) end) | spawn_procs(N-1)]. 226 227send_procs([], Msg) -> 228 Msg; 229send_procs([P|Ps], Msg) -> 230 P ! Msg, 231 send_procs(Ps, Msg). 232 233receive_msgs([]) -> 234 ok; 235receive_msgs([M|Ms]) -> 236 receive 237 M -> 238 receive_msgs(Ms) 239 end. 240