%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
-module(trace_bif_SUITE).
-include_lib("test_server/include/test_server.hrl").
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-export([trace_bif/1, trace_bif_timestamp/1, trace_on_and_off/1, trace_bif_local/1,
trace_bif_timestamp_local/1, trace_bif_return/1, not_run/1,
trace_info_old_code/1]).
-export([bif_process/0]).
suite() -> [{suite_callbacks,[ts_install_scb]}].
all() ->
case test_server:is_native(trace_bif_SUITE) of
true -> [not_run];
false ->
[trace_bif, trace_bif_timestamp, trace_on_and_off,
trace_bif_local, trace_bif_timestamp_local,
trace_bif_return, trace_info_old_code]
end.
groups() ->
[].
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
not_run(Config) when is_list(Config) ->
{skipped,"Native code"}.
trace_on_and_off(doc) ->
"Tests switching tracing on and off.";
trace_on_and_off(Config) when is_list(Config) ->
?line Pid = spawn(?MODULE, bif_process, []),
?line Self = self(),
?line 1 = erlang:trace(Pid, true, [call,timestamp]),
?line {flags,[timestamp,call]} = erlang:trace_info(Pid,flags),
?line {tracer, Self} = erlang:trace_info(Pid,tracer),
?line 1 = erlang:trace(Pid, false, [timestamp]),
?line {flags,[call]} = erlang:trace_info(Pid,flags),
?line {tracer, Self} = erlang:trace_info(Pid,tracer),
?line 1 = erlang:trace(Pid, false, [call]),
?line {flags,[]} = erlang:trace_info(Pid,flags),
?line {tracer, []} = erlang:trace_info(Pid,tracer),
?line exit(Pid,kill),
ok.
trace_bif(doc) -> "Test tracing BIFs.";
trace_bif(Config) when is_list(Config) ->
do_trace_bif([]).
trace_bif_local(doc) -> "Test tracing BIFs with local flag.";
trace_bif_local(Config) when is_list(Config) ->
do_trace_bif([local]).
do_trace_bif(Flags) ->
?line Pid = spawn(?MODULE, bif_process, []),
?line 1 = erlang:trace(Pid, true, [call]),
?line erlang:trace_pattern({erlang,'_','_'}, [], Flags),
?line Pid ! {do_bif, time, []},
?line receive_trace_msg({trace,Pid,call,{erlang,time, []}}),
?line Pid ! {do_bif, statistics, [runtime]},
?line receive_trace_msg({trace,Pid,call,
{erlang,statistics, [runtime]}}),
?line Pid ! {do_time_bif},
?line receive_trace_msg({trace,Pid,call,
{erlang,time, []}}),
?line Pid ! {do_statistics_bif},
?line receive_trace_msg({trace,Pid,call,
{erlang,statistics, [runtime]}}),
?line 1 = erlang:trace(Pid, false, [call]),
?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
?line exit(Pid, die),
ok.
trace_bif_timestamp(doc) -> "Test tracing BIFs with timestamps.";
trace_bif_timestamp(Config) when is_list(Config) ->
do_trace_bif_timestamp([]).
trace_bif_timestamp_local(doc) ->
"Test tracing BIFs with timestamps and local flag.";
trace_bif_timestamp_local(Config) when is_list(Config) ->
do_trace_bif_timestamp([local]).
do_trace_bif_timestamp(Flags) ->
?line Pid=spawn(?MODULE, bif_process, []),
?line 1 = erlang:trace(Pid, true, [call,timestamp]),
?line erlang:trace_pattern({erlang,'_','_'}, [], Flags),
?line Pid ! {do_bif, time, []},
?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}),
?line Pid ! {do_bif, statistics, [runtime]},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,statistics, [runtime]}}),
?line Pid ! {do_time_bif},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,time, []}}),
?line Pid ! {do_statistics_bif},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,statistics, [runtime]}}),
%% We should be able to turn off the timestamp.
?line 1 = erlang:trace(Pid, false, [timestamp]),
?line Pid ! {do_statistics_bif},
?line receive_trace_msg({trace,Pid,call,
{erlang,statistics, [runtime]}}),
?line Pid ! {do_bif, statistics, [runtime]},
?line receive_trace_msg({trace,Pid,call,
{erlang,statistics, [runtime]}}),
?line 1 = erlang:trace(Pid, false, [call]),
?line erlang:trace_pattern({erlang,'_','_'}, false, Flags),
?line exit(Pid, die),
ok.
trace_bif_return(doc) ->
"Test tracing BIF's with return/return_to trace.";
trace_bif_return(Config) when is_list(Config) ->
?line Pid=spawn(?MODULE, bif_process, []),
?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]),
?line erlang:trace_pattern({erlang,'_','_'}, [{'_',[],[{return_trace}]}],
[local]),
?line Pid ! {do_bif, time, []},
?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}),
?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
{erlang,time,0}}),
?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
{?MODULE, bif_process,0}}),
?line Pid ! {do_bif, statistics, [runtime]},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,statistics, [runtime]}}),
?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
{erlang,statistics,1}}),
?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
{?MODULE, bif_process,0}}),
?line Pid ! {do_time_bif},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,time, []}}),
?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
{erlang,time,0}}),
?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
{?MODULE, bif_process,0}}),
?line Pid ! {do_statistics_bif},
?line receive_trace_msg_ts({trace_ts,Pid,call,
{erlang,statistics, [runtime]}}),
?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from,
{erlang,statistics,1}}),
?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to,
{?MODULE, bif_process,0}}),
ok.
receive_trace_msg(Mess) ->
receive
Mess ->
ok;
Other ->
io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]),
?t:fail()
after 5000 ->
io:format("Expected: ~p,~nGot: timeout~n", [Mess]),
?t:fail()
end.
receive_trace_msg_ts({trace_ts, Pid, call, {erlang,F,A}}) ->
receive
{trace_ts, Pid, call, {erlang, F, A}, _Ts} ->
ok;
Other ->
io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n"
"Got: ~p~n",
[Pid, erlang, F, A, Other]),
?t:fail()
after 5000 ->
io:format("Got timeout~n", []),
?t:fail()
end.
receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {erlang,F,A}}) ->
receive
{trace_ts, Pid, return_from, {erlang, F, A}, _Value, _Ts} ->
ok;
Other ->
io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n"
"Got: ~p~n",
[Pid, erlang, F, A, Other]),
?t:fail()
after 5000 ->
io:format("Got timeout~n", []),
?t:fail()
end.
receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}) ->
receive
{trace_ts, Pid, return_to, {M, F, A}, _Ts} ->
ok;
Other ->
io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n"
"Got: ~p~n",
[Pid, M, F, A, Other]),
?t:fail()
after 5000 ->
io:format("Got timeout~n", []),
?t:fail()
end.
bif_process() ->
receive
{do_bif, Name, Args} ->
apply(erlang, Name, Args),
bif_process();
{do_time_bif} ->
_ = time(), %Assignment tells compiler to keep call.
bif_process();
{do_statistics_bif} ->
statistics(runtime),
bif_process();
_Stuff ->
bif_process()
end.
trace_info_old_code(doc) -> "trace_info on deleted module (OTP-5057).";
trace_info_old_code(Config) when is_list(Config) ->
?line MFA = {M,F,0} = {test,foo,0},
?line Fname = atom_to_list(M)++".erl",
?line AbsForms =
[{attribute,1,module,M}, % -module(M).
{attribute,2,export,[{F,0}]}, % -export([F/0]).
{function,3,F,0, % F() ->
[{clause,4,[],[],[{atom,4,F}]}]}], % F.
%%
?line {ok,M,Mbin} = compile:forms(AbsForms),
?line {module,M} = code:load_binary(M, Fname, Mbin),
?line true = erlang:delete_module(M),
?line {traced,undefined} = erlang:trace_info(MFA, traced),
ok.