1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2002-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 21%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22%%% 23%%% Define to run outside of test server 24%%% 25%%% -define(STANDALONE,1). 26%%% 27%%% 28%%% Define for debug output 29%%% 30%%% -define(debug,1). 31 32-module(cprof_SUITE). 33 34%% Exported end user tests 35-export([basic_test/0, on_load_test/1, modules_test/1]). 36 37%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38%% Test server related stuff 39%% 40 41-ifdef(STANDALONE). 42-define(config(A,B),config(A,B)). 43-export([config/2]). 44-else. 45-include_lib("common_test/include/ct.hrl"). 46-endif. 47 48-ifdef(debug). 49-ifdef(STANDALONE). 50-define(line, erlang:display({?MODULE,?LINE}), ). 51-endif. 52-define(dbgformat(A,B),io:format(A,B)). 53-else. 54-ifdef(STANDALONE). 55-define(line, noop, ). 56-endif. 57-define(dbgformat(A,B),noop). 58-endif. 59 60-ifdef(STANDALONE). 61config(priv_dir, _) -> 62 "."; 63config(data_dir, _) -> 64 "cprof_SUITE_data". 65-else. 66%% When run in test server. 67-export([all/0, suite/0, 68 init_per_testcase/2, end_per_testcase/2, 69 not_run/1]). 70-export([basic/1, on_load/1, modules/1]). 71 72init_per_testcase(_Case, Config) -> 73 Config. 74 75end_per_testcase(_Case, _Config) -> 76 erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]), 77 erlang:trace_pattern(on_load, false, [local,meta,call_count]), 78 erlang:trace(all, false, [all]), 79 ok. 80 81suite() -> 82 [{ct_hooks,[ts_install_cth]}, 83 {timetrap,{seconds,30}}]. 84 85all() -> 86 case test_server:is_native(cprof_SUITE) of 87 true -> [not_run]; 88 false -> [basic, on_load, modules] 89 end. 90 91 92not_run(Config) when is_list(Config) -> 93 {skipped,"Native code"}. 94 95%% Tests basic profiling 96basic(Config) when is_list(Config) -> 97 basic_test(). 98 99%% Tests profiling of unloaded module 100on_load(Config) when is_list(Config) -> 101 on_load_test(Config). 102 103%% Tests profiling of several modules 104modules(Config) when is_list(Config) -> 105 modules_test(Config). 106 107-endif. %-ifdef(STANDALONE). ... -else. 108 109%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 110%%% The Tests 111%%% 112 113basic_test() -> 114 M = 1000, 115 %% 116 M2 = M*2, 117 M3 = M*3, 118 M2__1 = M2 + 1, 119 M3__1 = M3 + 1, 120 N = cprof:stop(), 121 %% 122 2 = cprof:start(?MODULE, seq_r), 123 1 = cprof:start(?MODULE, seq, 3), 124 L = seq(1, M, fun succ/1), 125 Lr = seq_r(1, M, fun succ/1), 126 L = lists:reverse(Lr), 127 %% 128 io:format("~p~n~p~n~p~n", 129 [erlang:trace_info({?MODULE,sec_r,3}, all), 130 erlang:trace_info({?MODULE,sec_r,4}, all), 131 erlang:trace_info({?MODULE,sec,3}, all)]), 132 %% 133 ModAna1 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, 134 {{?MODULE,seq,3},M}, 135 {{?MODULE,seq_r,3},1}]}, 136 ModAna1 = cprof:analyse(?MODULE,0), 137 {M2__1, [ModAna1]} = cprof:analyse(), 138 ModAna1 = cprof:analyse(?MODULE, 1), 139 {M2__1, [ModAna1]} = cprof:analyse(1), 140 %% 141 ModAna2 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, 142 {{?MODULE,seq,3},M}]}, 143 ModAna2 = cprof:analyse(?MODULE, 2), 144 {M2__1, [ModAna2]} = cprof:analyse(2), 145 %% 146 2 = cprof:pause(?MODULE, seq_r), 147 L = seq(1, M, fun succ/1), 148 Lr = seq_r(1, M, fun succ/1), 149 %% 150 ModAna3 = {?MODULE,M3__1,[{{?MODULE,seq,3},M2}, 151 {{?MODULE,seq_r,4},M}, 152 {{?MODULE,seq_r,3},1}]}, 153 ModAna3 = cprof:analyse(?MODULE), 154 %% 155 N = cprof:pause(), 156 L = seq(1, M, fun succ/1), 157 Lr = seq_r(1, M, fun succ/1), 158 %% 159 {M3__1, [ModAna3]} = cprof:analyse(), 160 %% 161 N = cprof:restart(), 162 L = seq(1, M, fun succ/1), 163 Lr = seq_r(1, M, fun succ/1), 164 %% 165 ModAna1 = cprof:analyse(?MODULE), 166 %% 167 N = cprof:stop(), 168 {?MODULE,0,[]} = cprof:analyse(?MODULE), 169 {0,[]} = cprof:analyse(), 170 ok. 171 172%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 173 174on_load_test(Config) -> 175 Priv = proplists:get_value(priv_dir, Config), 176 Data = proplists:get_value(data_dir, Config), 177 File = filename:join(Data, "cprof_SUITE_test"), 178 Module = cprof_SUITE_test, 179 M = 1000, 180 %% 181 M2 = M*2, 182 M2__1 = M2 + 1, 183 N1 = cprof:start(), 184 185 {ok,Module} = c:c(File, [{outdir,Priv}]), 186 187 %% If this system is hipe-enabled, the loader may have called module_info/1 188 %% when Module was loaded above. Reset the call count to avoid seeing 189 %% the call in the analysis below. 190 191 1 = cprof:restart(Module, module_info, 1), 192 193 L = Module:seq(1, M, fun succ/1), 194 Lr = Module:seq_r(1, M, fun succ/1), 195 Lr = lists:reverse(L), 196 N2 = cprof:pause(), 197 N3 = cprof:pause(Module), 198 {Module,M2__1,[{{Module,seq_r,4},M}, 199 {{Module,seq,3},M}, 200 {{Module,seq_r,3},1}]} = cprof:analyse(Module), 201 io:format("~p ~p ~p~n", [N1, N2, N3]), 202 code:purge(Module), 203 code:delete(Module), 204 N4 = N2 - N3, 205 %% 206 N4 = cprof:restart(), 207 {ok,Module} = c:c(File, [{outdir,Priv}]), 208 L = Module:seq(1, M, fun succ/1), 209 Lr = Module:seq_r(1, M, fun succ/1), 210 L = seq(1, M, fun succ/1), 211 Lr = seq_r(1, M, fun succ/1), 212 N2 = cprof:pause(), 213 {Module,0,[]} = cprof:analyse(Module), 214 M_1 = M - 1, 215 M4__4 = M*4 - 4, 216 M10_7 = M*10 - 7, 217 {?MODULE,M10_7,[{{?MODULE,succ,1},M4__4}, 218 {{?MODULE,seq_r,4},M}, 219 {{?MODULE,seq,3},M}, 220 {{?MODULE,'-on_load_test/1-fun-5-',1},M_1}, 221 {{?MODULE,'-on_load_test/1-fun-4-',1},M_1}, 222 {{?MODULE,'-on_load_test/1-fun-3-',1},M_1}, 223 {{?MODULE,'-on_load_test/1-fun-2-',1},M_1}, 224 {{?MODULE,seq_r,3},1}]} 225 = cprof:analyse(?MODULE), 226 N2 = cprof:stop(), 227 ok. 228 229%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 230 231modules_test(Config) -> 232 Priv = proplists:get_value(priv_dir, Config), 233 Data = proplists:get_value(data_dir, Config), 234 File = filename:join(Data, "cprof_SUITE_test"), 235 Module = cprof_SUITE_test, 236 {ok,Module} = c:c(File, [{outdir,Priv}]), 237 M = 10, 238 %% 239 M2 = M*2, 240 M2__1 = M2 + 1, 241 erlang:yield(), 242 N = cprof:start(), 243 L = Module:seq(1, M, fun succ/1), 244 Lr = Module:seq_r(1, M, fun succ/1), 245 L = seq(1, M, fun succ/1), 246 Lr = seq_r(1, M, fun succ/1), 247 N = cprof:pause(), 248 Lr = lists:reverse(L), 249 M_1 = M - 1, 250 M4_4 = M*4 - 4, 251 M10_7 = M*10 - 7, 252 M2__1 = M*2 + 1, 253 {Tot,ModList} = cprof:analyse(), 254 {value,{?MODULE,M10_7,[{{?MODULE,succ,1},M4_4}, 255 {{?MODULE,seq_r,4},M}, 256 {{?MODULE,seq,3},M}, 257 {{?MODULE,'-modules_test/1-fun-3-',1},M_1}, 258 {{?MODULE,'-modules_test/1-fun-2-',1},M_1}, 259 {{?MODULE,'-modules_test/1-fun-1-',1},M_1}, 260 {{?MODULE,'-modules_test/1-fun-0-',1},M_1}, 261 {{?MODULE,seq_r,3},1}]}} = 262 lists:keysearch(?MODULE, 1, ModList), 263 {value,{Module,M2__1,[{{Module,seq_r,4},M}, 264 {{Module,seq,3},M}, 265 {{Module,seq_r,3},1}]}} = 266 lists:keysearch(Module, 1, ModList), 267 Tot = lists:foldl(fun ({_,C,_}, A) -> C+A end, 0, ModList), 268 {cprof,_,Prof} = cprof:analyse(cprof), 269 {value,{{cprof,pause,0},1}} = lists:keysearch({cprof,pause,0}, 1, Prof), 270 N = cprof:stop(), 271 ok. 272 273 274 275%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 276%% Local helpers 277 278 279%% Stack recursive seq 280seq(Stop, Stop, Succ) when is_function(Succ) -> 281 [Stop]; 282seq(Start, Stop, Succ) when is_function(Succ) -> 283 [Start | seq(Succ(Start), Stop, Succ)]. 284 285 286 287%% Tail recursive seq, result list is reversed 288seq_r(Start, Stop, Succ) when is_function(Succ) -> 289 seq_r(Start, Stop, Succ, []). 290 291seq_r(Stop, Stop, _, R) -> 292 [Stop | R]; 293seq_r(Start, Stop, Succ, R) -> 294 seq_r(Succ(Start), Stop, Succ, [Start | R]). 295 296 297%% Successor 298succ(X) -> X+1. 299