1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 1998-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: 
   20: -module(trace_bif_SUITE).
   21: 
   22: -include_lib("test_server/include/test_server.hrl").
   23: 
   24: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   25: 	 init_per_group/2,end_per_group/2]).
   26: -export([trace_bif/1, trace_bif_timestamp/1, trace_on_and_off/1, 
   27: 	 trace_bif_local/1,
   28: 	 trace_bif_timestamp_local/1, trace_bif_return/1, not_run/1,
   29: 	 trace_info_old_code/1]).
   30: 
   31: -export([bif_process/0]).
   32: 
   33: suite() -> [{ct_hooks,[ts_install_cth]}].
   34: 
   35: all() -> 
   36:     case test_server:is_native(trace_bif_SUITE) of
   37: 	true -> [not_run];
   38: 	false ->
   39: 	    [trace_bif, trace_bif_timestamp, trace_on_and_off,
   40: 	     trace_bif_local, trace_bif_timestamp_local,
   41: 	     trace_bif_return, trace_info_old_code]
   42:     end.
   43: 
   44: groups() -> 
   45:     [].
   46: 
   47: init_per_suite(Config) ->
   48:     Config.
   49: 
   50: end_per_suite(_Config) ->
   51:     ok.
   52: 
   53: init_per_group(_GroupName, Config) ->
   54:     Config.
   55: 
   56: end_per_group(_GroupName, Config) ->
   57:     Config.
   58: 
   59: 
   60: not_run(Config) when is_list(Config) -> 
   61:     {skipped,"Native code"}.
   62: 
   63: trace_on_and_off(doc) -> 
   64:     "Tests switching tracing on and off.";
   65: trace_on_and_off(Config) when is_list(Config) ->
   66:     ?line Pid = spawn(?MODULE, bif_process, []),
   67:     ?line Self = self(),
   68:     ?line 1 = erlang:trace(Pid, true, [call,timestamp]),
   69:     ?line {flags,[timestamp,call]} =  erlang:trace_info(Pid,flags),
   70:     ?line {tracer, Self} = erlang:trace_info(Pid,tracer),
   71:     ?line 1 = erlang:trace(Pid, false, [timestamp]),
   72:     ?line {flags,[call]} =  erlang:trace_info(Pid,flags),
   73:     ?line {tracer, Self} = erlang:trace_info(Pid,tracer),
   74:     ?line 1 = erlang:trace(Pid, false, [call]),
   75:     ?line {flags,[]} =  erlang:trace_info(Pid,flags),
   76:     ?line {tracer, []} = erlang:trace_info(Pid,tracer),
   77:     ?line exit(Pid,kill),
   78:     ok.
   79: 
   80: trace_bif(doc) -> "Test tracing BIFs.";
   81: trace_bif(Config) when is_list(Config) ->
   82:     do_trace_bif([]).
   83: 
   84: trace_bif_local(doc) -> "Test tracing BIFs with local flag.";
   85: trace_bif_local(Config) when is_list(Config) ->
   86:     do_trace_bif([local]).
   87: 
   88: do_trace_bif(Flags) ->
   89:     ?line Pid = spawn(?MODULE, bif_process, []),
   90:     ?line 1 = erlang:trace(Pid, true, [call]),
   91:     ?line erlang:trace_pattern({erlang,'_','_'}, [], Flags),
   92:     ?line Pid ! {do_bif, time, []},
   93:     ?line receive_trace_msg({trace,Pid,call,{erlang,time, []}}),
   94:     ?line Pid ! {do_bif, statistics, [runtime]},
   95:     ?line receive_trace_msg({trace,Pid,call,
   96: 			     {erlang,statistics, [runtime]}}),
   97: 
   98:     ?line Pid ! {do_time_bif},
   99:     ?line receive_trace_msg({trace,Pid,call,
  100: 			     {erlang,time, []}}),
  101: 
  102:     ?line Pid ! {do_statistics_bif},
  103:     ?line receive_trace_msg({trace,Pid,call,
  104: 			     {erlang,statistics, [runtime]}}),
  105: 
  106:     ?line 1 = erlang:trace(Pid, false, [call]),
  107:     ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
  108:     ?line exit(Pid, die),
  109:     ok.
  110: 
  111: trace_bif_timestamp(doc) -> "Test tracing BIFs with timestamps.";
  112: trace_bif_timestamp(Config) when is_list(Config) ->
  113:     do_trace_bif_timestamp([]).
  114: 
  115: trace_bif_timestamp_local(doc) -> 
  116:     "Test tracing BIFs with timestamps and local flag.";
  117: trace_bif_timestamp_local(Config) when is_list(Config) ->
  118:     do_trace_bif_timestamp([local]).
  119: 
  120: do_trace_bif_timestamp(Flags) ->
  121:     ?line Pid=spawn(?MODULE, bif_process, []),
  122:     ?line 1 = erlang:trace(Pid, true, [call,timestamp]),
  123:     ?line erlang:trace_pattern({erlang,'_','_'}, [], Flags),
  124: 
  125:     ?line Pid ! {do_bif, time, []},
  126:     ?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}),
  127: 
  128:     ?line Pid ! {do_bif, statistics, [runtime]},
  129:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  130: 			     {erlang,statistics, [runtime]}}),
  131: 
  132:     ?line Pid ! {do_time_bif},
  133:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  134: 			     {erlang,time, []}}),
  135: 
  136:     ?line Pid ! {do_statistics_bif},
  137:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  138: 			     {erlang,statistics, [runtime]}}),
  139: 
  140:     %% We should be able to turn off the timestamp.
  141:     ?line 1 = erlang:trace(Pid, false, [timestamp]),
  142: 
  143:     ?line Pid ! {do_statistics_bif},
  144:     ?line receive_trace_msg({trace,Pid,call,
  145: 			     {erlang,statistics, [runtime]}}),
  146: 
  147:     ?line Pid ! {do_bif, statistics, [runtime]},
  148:     ?line receive_trace_msg({trace,Pid,call,
  149: 			     {erlang,statistics, [runtime]}}),
  150: 
  151:     ?line 1 = erlang:trace(Pid, false, [call]),
  152:     ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
  153: 
  154:     ?line exit(Pid, die),
  155:     ok.
  156: 
  157: trace_bif_return(doc) -> 
  158:     "Test tracing BIF's with return/return_to trace.";
  159: trace_bif_return(Config) when is_list(Config) ->
  160:     ?line Pid=spawn(?MODULE, bif_process, []),
  161:     ?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]),
  162:     ?line erlang:trace_pattern({erlang,'_','_'}, [{'_',[],[{return_trace}]}], 
  163: 			       [local]),
  164: 
  165: 
  166:     ?line Pid ! {do_bif, time, []},
  167:     ?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}),
  168:     ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
  169: 					    {erlang,time,0}}),
  170:     ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, 
  171: 					  {?MODULE, bif_process,0}}),
  172: 
  173: 
  174:     ?line Pid ! {do_bif, statistics, [runtime]},
  175:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  176: 			     {erlang,statistics, [runtime]}}),
  177:     ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
  178: 					    {erlang,statistics,1}}),
  179:     ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, 
  180: 					  {?MODULE, bif_process,0}}),
  181: 
  182: 
  183:     ?line Pid ! {do_time_bif},
  184:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  185: 			     {erlang,time, []}}),
  186:     ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
  187: 					    {erlang,time,0}}),
  188:     ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, 
  189: 					  {?MODULE, bif_process,0}}),
  190: 
  191: 
  192: 
  193:     ?line Pid ! {do_statistics_bif},
  194:     ?line receive_trace_msg_ts({trace_ts,Pid,call,
  195: 			     {erlang,statistics, [runtime]}}),
  196:     ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
  197: 					    {erlang,statistics,1}}),
  198:     ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, 
  199: 					  {?MODULE, bif_process,0}}),
  200:     ok.
  201:     
  202:     
  203: receive_trace_msg(Mess) ->
  204:     receive
  205: 	Mess ->
  206: 	    ok;
  207: 	Other ->
  208: 	    io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]),
  209: 	    ?t:fail()
  210:     after 5000 ->
  211: 	    io:format("Expected: ~p,~nGot: timeout~n", [Mess]),
  212: 	    ?t:fail()
  213:     end.
  214: 
  215: receive_trace_msg_ts({trace_ts, Pid, call, {erlang,F,A}}) ->
  216:     receive
  217: 	{trace_ts, Pid, call, {erlang, F, A}, _Ts} ->
  218: 	    ok;
  219: 	Other ->
  220: 	    io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
  221: 		      "Got: ~p~n",
  222: 		      [Pid, erlang, F, A, Other]),
  223: 	    ?t:fail()
  224: 	after 5000 ->
  225: 	    io:format("Got timeout~n", []),
  226: 	    ?t:fail()
  227:     end.
  228: 
  229: receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {erlang,F,A}}) ->
  230:     receive
  231: 	{trace_ts, Pid, return_from, {erlang, F, A}, _Value, _Ts} ->
  232: 	    ok;
  233: 	Other ->
  234: 	    io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
  235: 		      "Got: ~p~n",
  236: 		      [Pid, erlang, F, A, Other]),
  237: 	    ?t:fail()
  238: 	after 5000 ->
  239: 	    io:format("Got timeout~n", []),
  240: 	    ?t:fail()
  241:     end.
  242: 
  243: receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}) ->
  244:     receive
  245: 	{trace_ts, Pid, return_to, {M, F, A}, _Ts} ->
  246: 	    ok;
  247: 	Other ->
  248: 	    io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
  249: 		      "Got: ~p~n",
  250: 		      [Pid, M, F, A, Other]),
  251: 	    ?t:fail()
  252: 	after 5000 ->
  253: 	    io:format("Got timeout~n", []),
  254: 	    ?t:fail()
  255:     end.
  256: 
  257: bif_process() ->
  258:     receive
  259: 	{do_bif, Name, Args} ->
  260: 	    apply(erlang, Name, Args),
  261: 	    bif_process();
  262: 	{do_time_bif} ->
  263: 	    _ = time(),				%Assignment tells compiler to keep call.
  264: 	    bif_process();
  265: 	{do_statistics_bif} ->
  266: 	    statistics(runtime),
  267: 	    bif_process();
  268: 	_Stuff ->
  269: 	    bif_process()
  270:     end.
  271:     
  272: 
  273: 
  274: trace_info_old_code(doc) -> "trace_info on deleted module (OTP-5057).";
  275: trace_info_old_code(Config) when is_list(Config) ->
  276:     ?line MFA = {M,F,0} = {test,foo,0},
  277:     ?line Fname = atom_to_list(M)++".erl",
  278:     ?line AbsForms = 
  279: 	[{attribute,1,module,M},             % -module(M).
  280: 	 {attribute,2,export,[{F,0}]},       % -export([F/0]).
  281: 	 {function,3,F,0,                    % F() ->
  282: 	  [{clause,4,[],[],[{atom,4,F}]}]}], %     F.
  283:     %%
  284:     ?line {ok,M,Mbin} = compile:forms(AbsForms),
  285:     ?line {module,M} = code:load_binary(M, Fname, Mbin),
  286:     ?line true  = erlang:delete_module(M),
  287:     ?line {traced,undefined} = erlang:trace_info(MFA, traced),
  288:     ok.