diff options
Diffstat (limited to 'erts/emulator/test/trace_nif_SUITE.erl')
-rw-r--r-- | erts/emulator/test/trace_nif_SUITE.erl | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl new file mode 100644 index 0000000000..587cc08979 --- /dev/null +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -0,0 +1,292 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. 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_nif_SUITE). + +-include("test_server.hrl"). + +-export([all/1]). +-export([trace_nif/1, + trace_nif_timestamp/1, + trace_nif_local/1, + trace_nif_meta/1, + trace_nif_timestamp_local/1, + trace_nif_return/1, + not_run/1]). + +-export([nif_process/0, nif/0, nif/1]). + +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> + [trace_nif, + trace_nif_timestamp, + trace_nif_local, + trace_nif_meta, + trace_nif_timestamp_local, + trace_nif_return + ] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +trace_nif(doc) -> "Test tracing NIFs."; +trace_nif(Config) when is_list(Config) -> + load_nif(Config), + + do_trace_nif([]). + +trace_nif_local(doc) -> "Test tracing NIFs with local flag."; +trace_nif_local(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif([local]). + +trace_nif_meta(doc) -> "Test tracing NIFs with meta flag."; +trace_nif_meta(Config) when is_list(Config) -> + load_nif(Config), + ?line Pid=spawn_link(?MODULE, nif_process, []), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], [meta]), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + ok. +do_trace_nif(Flags) -> + ?line Pid = spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}), + + + %% Switch off + ?line 1 = erlang:trace(Pid, false, [call]), + + ?line Pid ! {apply_nif, nif, []}, + receive_nothing(), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + receive_nothing(), + ?line Pid ! {call_nif, nif, []}, + receive_nothing(), + ?line Pid ! {call_nif, nif, ["Arg1"]}, + receive_nothing(), + + %% Switch on again + ?line 1 = erlang:trace(Pid, true, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, false, Flags), + ?line exit(Pid, die), + ok. + +trace_nif_timestamp(doc) -> "Test tracing NIFs with timestamps."; +trace_nif_timestamp(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif_timestamp([]). + +trace_nif_timestamp_local(doc) -> + "Test tracing NIFs with timestamps and local flag."; +trace_nif_timestamp_local(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif_timestamp([local]). + +do_trace_nif_timestamp(Flags) -> + ?line Pid=spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + %% We should be able to turn off the timestamp. + ?line 1 = erlang:trace(Pid, false, [timestamp]), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {apply_nif, nif, ["tjoho"]}, + ?line receive_trace_msg({trace,Pid,call, + {?MODULE,nif, ["tjoho"]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags), + + ?line exit(Pid, die), + ok. + +trace_nif_return(doc) -> + "Test tracing NIF's with return/return_to trace."; +trace_nif_return(Config) when is_list(Config) -> + load_nif(Config), + + ?line Pid=spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [{'_',[],[{return_trace}]}], + [local]), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {?MODULE,nif,0}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, nif_process,0}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {?MODULE,nif,1}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, nif_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_nothing() -> + ?line timeout = receive M -> M after 100 -> timeout end. + +receive_trace_msg_ts({trace_ts, Pid, call, {M,F,A}}) -> + receive + {trace_ts, Pid, call, {M, F, A}, _Ts} -> + ok; + Other -> + io:format("Expected: {trace, ~p, call, {~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. + +receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {M,F,A}}) -> + receive + {trace_ts, Pid, return_from, {M, F, A}, _Value, _Ts} -> + ok; + Other -> + io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n" + "Got: ~p~n", + [Pid, M, 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. + +nif_process() -> + receive + {apply_nif, Name, Args} -> + ?line {ok,Args} = apply(?MODULE, Name, Args); + + {call_nif, Name, []} -> + ?line {ok, []} = ?MODULE:Name(); + + {call_nif, Name, [A1]} -> + ?line {ok, [A1]} = ?MODULE:Name(A1); + + {call_nif, Name, [A1,A2]} -> + ?line {ok,[A1,A2]} = ?MODULE:Name(A1,A2); + + {call_nif, Name, [A1,A2,A3]} -> + ?line {ok,[A1,A2,A3]} = ?MODULE:Name(A1,A2,A3) + end, + nif_process(). + +load_nif(Config) -> + ?line Path = ?config(data_dir, Config), + + ?line ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0). + + +nif() -> + {"Stub0",[]}. %exit("nif/0 stub called"). + +nif(A1) -> + {"Stub1",[A1]}. %exit(["nif/1 stub called",A1]). + |