1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 1996-2013. 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(eprof_SUITE).
   20: 
   21: -include_lib("test_server/include/test_server.hrl").
   22: 
   23: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   24: 	init_per_group/2,end_per_group/2]).
   25: 
   26: -export([tiny/1,eed/1,basic/1,basic_option/1]).
   27: 
   28: suite() -> [{ct_hooks,[ts_install_cth]}].
   29: 
   30: all() -> 
   31:     [basic, basic_option, tiny, eed].
   32: 
   33: groups() -> 
   34:     [].
   35: 
   36: init_per_suite(Config) ->
   37:     Config.
   38: 
   39: end_per_suite(_Config) ->
   40:     ok.
   41: 
   42: init_per_group(_GroupName, Config) ->
   43:     Config.
   44: 
   45: end_per_group(_GroupName, Config) ->
   46:     Config.
   47: 
   48: 
   49: basic(suite) -> [];
   50: basic(Config) when is_list(Config) ->
   51: 
   52:     %% load eprof_test and change directory
   53: 
   54:     {ok, OldCurDir} = file:get_cwd(),
   55:     Datadir = ?config(data_dir, Config),
   56:     Privdir = ?config(priv_dir, Config),
   57:     {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"),
   58: 					       [trace,{outdir, Privdir}]),
   59:     ok = file:set_cwd(Privdir),
   60:     code:purge(eprof_test),
   61:     {module,eprof_test} = code:load_file(eprof_test),
   62: 
   63:     %% rootset profiling
   64: 
   65:     ensure_eprof_stopped(),
   66:     profiling = eprof:profile([self()]),
   67:     {error, already_profiling} = eprof:profile([self()]),
   68:     profiling_stopped = eprof:stop_profiling(),
   69:     profiling_already_stopped = eprof:stop_profiling(),
   70:     profiling = eprof:start_profiling([self(),self(),self()]),
   71:     profiling_stopped = eprof:stop_profiling(),
   72: 
   73:     %% with patterns
   74: 
   75:     profiling = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
   76:     {error, already_profiling} = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
   77:     profiling_stopped = eprof:stop_profiling(),
   78:     profiling = eprof:start_profiling([self()], {?MODULE, start_stop, '_'}),
   79:     profiling_stopped = eprof:stop_profiling(),
   80:     profiling = eprof:start_profiling([self()], {?MODULE, start_stop, 1}),
   81:     profiling_stopped = eprof:stop_profiling(),
   82: 
   83:     %% with fun
   84: 
   85:     {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
   86:     profiling = eprof:profile([self()]),
   87:     {error, already_profiling} = eprof:profile(fun() -> eprof_test:go(10) end),
   88:     profiling_stopped = eprof:stop_profiling(),
   89:     {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
   90:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end),
   91:     Pid     = whereis(eprof),
   92:     {ok, _} = eprof:profile(erlang:processes() -- [Pid], fun() -> eprof_test:go(10) end),
   93:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
   94:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, '_'}),
   95:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, 1}),
   96:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, dec, 1}),
   97: 
   98:     %% error case
   99: 
  100:     error     = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
  101:     Pid       = whereis(eprof),
  102:     error     = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
  103:     A         = spawn(fun() -> receive _ -> ok end end),
  104:     profiling = eprof:profile([A]),
  105:     true      = exit(A, kill_it),
  106:     profiling_stopped = eprof:stop_profiling(),
  107:     {error,_} = eprof:profile(fun() -> a = b end),
  108: 
  109:     %% with mfa
  110: 
  111:     {ok, _} = eprof:profile([], eprof_test, go, [10]),
  112:     {ok, _} = eprof:profile([], eprof_test, go, [10], {eprof_test, dec, 1}),
  113: 
  114:     %% dump
  115: 
  116:     {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
  117:     [{_, Mfas}] = eprof:dump(),
  118:     Dec_mfa = {eprof_test, dec, 1},
  119:     Go_mfa  = {eprof_test, go,  1},
  120:     {value, {Go_mfa,  { 1, _Time1}}} = lists:keysearch(Go_mfa,  1, Mfas),
  121:     {value, {Dec_mfa, {11, _Time2}}} = lists:keysearch(Dec_mfa, 1, Mfas),
  122: 
  123:     %% change current working directory
  124: 
  125:     ok = file:set_cwd(OldCurDir),
  126:     stopped = eprof:stop(),
  127:     ok.
  128: 
  129: basic_option(Config) when is_list(Config) ->
  130:     %% load eprof_test and change directory
  131: 
  132:     {ok, OldCurDir} = file:get_cwd(),
  133:     Datadir = ?config(data_dir, Config),
  134:     Privdir = ?config(priv_dir, Config),
  135:     {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"),
  136: 					       [trace,{outdir, Privdir}]),
  137:     ok = file:set_cwd(Privdir),
  138:     code:purge(eprof_test),
  139:     {module,eprof_test} = code:load_file(eprof_test),
  140: 
  141:     % vanilla
  142:     {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [{set_on_spawn, true}]),
  143: 
  144:     [{_, MfasDo1},{_, MfasLists1}] = eprof:dump(),
  145:     Mfas1 = MfasDo1 ++ MfasLists1,
  146: 
  147:     {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1},  1, Mfas1),
  148:     {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1},  1, Mfas1),
  149:     {value, {_, { 9, _}}} = lists:keysearch({lists, split_2,5},  1, Mfas1),
  150:     {value, {_, { 4, _}}} = lists:keysearch({lists, seq_loop,3}, 1, Mfas1),
  151: 
  152:     {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [set_on_spawn]),
  153: 
  154:     [{_, MfasDo2},{_, MfasLists2}] = eprof:dump(),
  155:     Mfas2 = MfasDo2 ++ MfasLists2,
  156:     {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1},  1, Mfas2),
  157:     {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1},  1, Mfas2),
  158:     {value, {_, { 9, _}}} = lists:keysearch({lists, split_2,5},  1, Mfas2),
  159:     {value, {_, { 4, _}}} = lists:keysearch({lists, seq_loop,3}, 1, Mfas2),
  160: 
  161:     % disable trace set_on_spawn
  162:     {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, []),
  163:     [{_, Mfas3}] = eprof:dump(),
  164:     {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas3),
  165:     {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas3),
  166:     false = lists:keysearch({lists, split_2,5},  1, Mfas3),
  167:     false = lists:keysearch({lists, seq_loop,3}, 1, Mfas3),
  168: 
  169:     %% change current working directory
  170:     ok = file:set_cwd(OldCurDir),
  171:     stopped = eprof:stop(),
  172:     ok.
  173: 
  174: tiny(suite) -> [];
  175: tiny(Config) when is_list(Config) -> 
  176:     ensure_eprof_stopped(),
  177:     {ok, OldCurDir} = file:get_cwd(),
  178:     Datadir = ?config(data_dir, Config),
  179:     Privdir = ?config(priv_dir, Config),
  180:     TTrap=?t:timetrap(60*1000),
  181:     % (Trace)Compile to priv_dir and make sure the correct version is loaded.
  182:     {ok,eprof_suite_test} = compile:file(filename:join(Datadir,
  183: 							     "eprof_suite_test"),
  184: 					       [trace,{outdir, Privdir}]),
  185:     ok = file:set_cwd(Privdir),
  186:     code:purge(eprof_suite_test),
  187:     {module,eprof_suite_test} = code:load_file(eprof_suite_test),
  188:     {ok,_Pid} = eprof:start(),
  189:     nothing_to_analyze = eprof:analyze(),
  190:     nothing_to_analyze = eprof:analyze(total),
  191:     eprof:profile([], eprof_suite_test, test, [Config]),
  192:     ok = eprof:analyze(),
  193:     ok = eprof:analyze(total),
  194:     ok = eprof:log("eprof_SUITE_logfile"),
  195:     stopped = eprof:stop(),
  196:     ?t:timetrap_cancel(TTrap),
  197:     ok = file:set_cwd(OldCurDir),
  198:     ok.
  199: 
  200: eed(suite) -> [];
  201: eed(Config) when is_list(Config) ->
  202:     ensure_eprof_stopped(),
  203:     Datadir = ?config(data_dir, Config),
  204:     Privdir = ?config(priv_dir, Config),
  205:     TTrap=?t:timetrap(5*60*1000),
  206: 
  207:     %% (Trace)Compile to priv_dir and make sure the correct version is loaded.
  208:     code:purge(eed),
  209:     {ok,eed} = c:c(filename:join(Datadir, "eed"), [trace,{outdir,Privdir}]),
  210:     {ok,_Pid} = eprof:start(),
  211:     Script = filename:join(Datadir, "ed.script"),
  212:     ok = file:set_cwd(Datadir),
  213:     {T1,_} = statistics(runtime),
  214:     ok = eed:file(Script),
  215:     ok = eed:file(Script),
  216:     ok = eed:file(Script),
  217:     ok = eed:file(Script),
  218:     ok = eed:file(Script),
  219:     ok = eed:file(Script),
  220:     ok = eed:file(Script),
  221:     ok = eed:file(Script),
  222:     ok = eed:file(Script),
  223:     ok = eed:file(Script),
  224:     {T2,_} = statistics(runtime),
  225:     {ok,ok} = eprof:profile([], eed, file, [Script]),
  226:     {T3,_} = statistics(runtime),
  227:     profiling_already_stopped = eprof:stop_profiling(),
  228:     ok = eprof:analyze(),
  229:     ok = eprof:analyze(total),
  230:     ok = eprof:log("eprof_SUITE_logfile"),
  231:     stopped = eprof:stop(),
  232:     ?t:timetrap_cancel(TTrap),
  233:     try
  234: 	S = lists:flatten(io_lib:format("~p times slower",
  235: 					[10*(T3-T2)/(T2-T1)])),
  236: 	{comment,S}
  237:     catch
  238: 	error:badarith ->
  239: 	    {comment,"No time elapsed. Bad clock? Fast computer?"}
  240:     end.
  241: 
  242: ensure_eprof_stopped() ->
  243:     Pid = whereis(eprof),
  244:     case whereis(eprof) of
  245: 	undefined ->
  246: 	    ok;
  247: 	Pid ->
  248: 	    stopped=eprof:stop()
  249:     end.