diff options
author | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
commit | 7c67bbddb53c364086f66260701bc54a61c9659c (patch) | |
tree | 92ab0d4b91d5e2f6e7a3f9d61ea25089e8a71fe0 /erts/emulator/test/call_trace_SUITE.erl | |
parent | 97dc5e7f396129222419811c173edc7fa767b0f8 (diff) | |
parent | 3b7a6ffddc819bf305353a593904cea9e932e7dc (diff) | |
download | otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.gz otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.bz2 otp-7c67bbddb53c364086f66260701bc54a61c9659c.zip |
Merge tag 'OTP-19.0' into sverker/19/binary_to_atom-utf8-crash/ERL-474/OTP-14590
Diffstat (limited to 'erts/emulator/test/call_trace_SUITE.erl')
-rw-r--r-- | erts/emulator/test/call_trace_SUITE.erl | 1647 |
1 files changed, 816 insertions, 831 deletions
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index eaecd32f95..6ba6301c7c 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. 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. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% @@ -20,66 +21,46 @@ -module(call_trace_SUITE). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2,end_per_testcase/2, - hipe/1,process_specs/1,basic/1,flags/1,errors/1,pam/1,change_pam/1, - return_trace/1,exception_trace/1,on_load/1,deep_exception/1, - upgrade/1, - exception_nocatch/1,bit_syntax/1]). +-export([all/0, suite/0, + init_per_testcase/2,end_per_testcase/2, + hipe/1,process_specs/1,basic/1,flags/1,errors/1,pam/1,change_pam/1, + return_trace/1,exception_trace/1,on_load/1,deep_exception/1, + upgrade/1, + exception_nocatch/1,bit_syntax/1]). %% Helper functions. -export([bar/0,foo/0,foo/1,foo/2,expect/1,worker_foo/1,pam_foo/2,nasty/0, - id/1,deep/3,deep_1/3,deep_2/2,deep_3/2,deep_4/1,deep_5/1, - bs_sum_a/2,bs_sum_b/2]). + id/1,deep/3,deep_1/3,deep_2/2,deep_3/2,deep_4/1,deep_5/1, + bs_sum_a/2,bs_sum_b/2]). %% Debug -export([abbr/1,abbr/2]). - --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(P, 20). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {seconds, 30}}]. all() -> Common = [errors, on_load], NotHipe = [process_specs, basic, flags, pam, change_pam, - upgrade, - return_trace, exception_trace, deep_exception, - exception_nocatch, bit_syntax], + upgrade, + return_trace, exception_trace, deep_exception, + exception_nocatch, bit_syntax], Hipe = [hipe], case test_server:is_native(call_trace_SUITE) of - true -> Hipe ++ Common; - false -> NotHipe ++ Common + true -> Hipe ++ Common; + false -> NotHipe ++ Common end. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> - Dog = ?t:timetrap(?t:seconds(30)), - [{watchdog, Dog}|Config]. + Config. end_per_testcase(_Func, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - %% Reloading the module will clear all trace patterns, and %% in a debug-compiled emulator run assertions of the counters %% for the number of traced exported functions in this module. @@ -87,51 +68,63 @@ end_per_testcase(_Func, Config) -> c:l(?MODULE). hipe(Config) when is_list(Config) -> - ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true), - ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true, [local]), - ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, true), + 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true), + 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true, [local]), + AllFuncs = erlang:trace_pattern({'_','_','_'}, true), %% Make sure that a traced, exported function can still be found. - ?line true = erlang:function_exported(error_handler, undefined_function, 3), - ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, false), + true = erlang:function_exported(error_handler, undefined_function, 3), + AllFuncs = erlang:trace_pattern({'_','_','_'}, false), ok. -process_specs(doc) -> - "Tests 'all', 'new', and 'existing' for specifying processes."; -process_specs(suite) -> []; +%% Tests 'all', 'new', and 'existing' for specifying processes. process_specs(Config) when is_list(Config) -> - ?line Tracer = start_tracer(), - ?line {flags,[call]} = trace_info(self(), flags), - ?line {tracer,Tracer} = trace_info(self(), tracer), - ?line trace_func({?MODULE,worker_foo,1}, []), - - %% Test the 'new' flag. - - ?line {Work1A,Work1B} = start_and_trace(new, [1,2,3], A1B={3,2,1}), - {flags,[]} = trace_info(Work1A, flags), - {tracer,[]} = trace_info(Work1A, tracer), - {tracer,Tracer} = trace_info(Work1B, tracer), - {flags,[call]} = trace_info(Work1B, flags), - ?line expect({trace,Work1B,call,{?MODULE,worker_foo,[A1B]}}), - ?line unlink(Work1B), - ?line Mref = erlang:monitor(process, Work1B), - ?line exit(Work1B, kill), - receive - {'DOWN',Mref,_,_,_} -> ok - end, - ?line undefined = trace_info(Work1B, flags), - ?line {flags,[]} = trace_info(new, flags), - ?line {tracer,[]} = trace_info(new, tracer), - - %% Test the 'existing' flag. - ?line {Work2A,_Work2B} = start_and_trace(existing, A2A=[5,6,7], [7,6,5]), - ?line expect({trace,Work2A,call,{?MODULE,worker_foo,[A2A]}}), - - %% Test the 'all' flag. - ?line {Work3A,Work3B} = start_and_trace(all, A3A=[12,13], A3B=[13,12]), - ?line expect({trace,Work3A,call,{?MODULE,worker_foo,[A3A]}}), - ?line expect({trace,Work3B,call,{?MODULE,worker_foo,[A3B]}}), - + Tracer = start_tracer(), + {flags,[call]} = trace_info(self(), flags), + {tracer,Tracer} = trace_info(self(), tracer), + trace_func({?MODULE,worker_foo,1}, []), + + %% Test the 'new' and 'new_processes' flags. + + New = fun(Flag) -> + {Work1A,Work1B} = start_and_trace(Flag, [1,2,3], A1B={3,2,1}), + {flags,[]} = trace_info(Work1A, flags), + {tracer,[]} = trace_info(Work1A, tracer), + {tracer,Tracer} = trace_info(Work1B, tracer), + {flags,[call]} = trace_info(Work1B, flags), + expect({trace,Work1B,call,{?MODULE,worker_foo,[A1B]}}), + unlink(Work1B), + Mref = erlang:monitor(process, Work1B), + exit(Work1B, kill), + receive + {'DOWN',Mref,_,_,_} -> ok + end, + undefined = trace_info(Work1B, flags), + {flags,[]} = trace_info(Flag, flags), + {tracer,[]} = trace_info(Flag, tracer) + end, + New(new), + New(new_processes), + + %% Test the 'existing' and 'existing_processes' flags. + Existing = + fun(Flag) -> + {Work2A,_Work2B} = start_and_trace(Flag, A2A=[5,6,7], [7,6,5]), + expect({trace,Work2A,call,{?MODULE,worker_foo,[A2A]}}) + end, + Existing(existing), + Existing(existing_processes), + + %% Test the 'all' and 'processes' flags. + All = + fun(Flag) -> + {Work3A,Work3B} = start_and_trace(Flag, A3A=[12,13], A3B=[13,12]), + expect({trace,Work3A,call,{?MODULE,worker_foo,[A3A]}}), + expect({trace,Work3B,call,{?MODULE,worker_foo,[A3B]}}) + end, + All(all), + All(processes), + ok. start_and_trace(Flag, A1, A2) -> @@ -141,33 +134,33 @@ start_and_trace(Flag, A1, A2) -> call_worker(W1, A1), call_worker(W2, A2), case Flag of - new -> - {flags,[call]} = trace_info(new, flags), - {tracer,_} = trace_info(new, tracer); - _Other -> - ok + new -> + {flags,[call]} = trace_info(new, flags), + {tracer,_} = trace_info(new, tracer); + _Other -> + ok end, trace_pid(Flag, false, [call]), {W1,W2}. start_worker() -> - ?line spawn(fun worker_loop/0). + spawn(fun worker_loop/0). call_worker(Pid, Arg) -> Pid ! {self(),{call,Arg}}, receive - {result,Res} -> Res + {result,Res} -> Res after 5000 -> - ?line ?t:fail(no_answer_from_worker) + ct:fail(no_answer_from_worker) end. worker_loop() -> receive - {From,{call,Arg}} -> - From ! {result,?MODULE:worker_foo(Arg)}, - worker_loop(); - Other -> - exit({unexpected_message,Other}) + {From,{call,Arg}} -> + From ! {result,?MODULE:worker_foo(Arg)}, + worker_loop(); + Other -> + exit({unexpected_message,Other}) end. worker_foo(_Arg) -> @@ -176,98 +169,98 @@ worker_foo(_Arg) -> %% Basic test of the call tracing (we trace one process). basic(_Config) -> case test_server:is_native(lists) of - true -> {skip,"lists is native"}; - false -> basic() + true -> {skip,"lists is native"}; + false -> basic() end. basic() -> - ?line start_tracer(), - ?line trace_info(self(), flags), - ?line trace_info(self(), tracer), - ?line 0 = trace_func({?MODULE,no_such_function,0}, []), - ?line {traced,undefined} = - trace_info({?MODULE,no_such_function,0}, traced), - ?line {match_spec, undefined} = - trace_info({?MODULE,no_such_function,0}, match_spec), + start_tracer(), + trace_info(self(), flags), + trace_info(self(), tracer), + 0 = trace_func({?MODULE,no_such_function,0}, []), + {traced,undefined} = + trace_info({?MODULE,no_such_function,0}, traced), + {match_spec, undefined} = + trace_info({?MODULE,no_such_function,0}, match_spec), %% Trace some functions... - ?line trace_func({lists,'_','_'}, []), + trace_func({lists,'_','_'}, []), %% Make sure that tracing the same functions more than once %% does not cause any problems. - ?line 3 = trace_func({?MODULE,foo,'_'}, true), - ?line 3 = trace_func({?MODULE,foo,'_'}, true), - ?line 1 = trace_func({?MODULE,bar,0}, true), - ?line 1 = trace_func({?MODULE,bar,0}, true), - ?line {traced,global} = trace_info({?MODULE,bar,0}, traced), - ?line 1 = trace_func({erlang,list_to_integer,1}, true), - ?line {traced,global} = trace_info({erlang,list_to_integer,1}, traced), + 3 = trace_func({?MODULE,foo,'_'}, true), + 3 = trace_func({?MODULE,foo,'_'}, true), + 1 = trace_func({?MODULE,bar,0}, true), + 1 = trace_func({?MODULE,bar,0}, true), + {traced,global} = trace_info({?MODULE,bar,0}, traced), + 1 = trace_func({erlang,list_to_integer,1}, true), + {traced,global} = trace_info({erlang,list_to_integer,1}, traced), %% ... and call them... - ?line AList = [x,y,z], - ?line true = lists:member(y, AList), - ?line foo0 = ?MODULE:foo(), - ?line 4 = ?MODULE:foo(3), - ?line 11 = ?MODULE:foo(7, 4), - ?line ok = ?MODULE:bar(), - ?line 42 = list_to_integer(non_literal("42")), + AList = [x,y,z], + true = lists:member(y, AList), + foo0 = ?MODULE:foo(), + 4 = ?MODULE:foo(3), + 11 = ?MODULE:foo(7, 4), + ok = ?MODULE:bar(), + 42 = list_to_integer(non_literal("42")), %% ... make sure the we got trace messages (but not for ?MODULE:expect/1). - ?line Self = self(), - ?line ?MODULE:expect({trace,Self,call,{lists,member,[y,AList]}}), - ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[]}}), - ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[3]}}), - ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[7,4]}}), - ?line ?MODULE:expect({trace,Self,call,{?MODULE,bar,[]}}), - ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["42"]}}), + Self = self(), + ?MODULE:expect({trace,Self,call,{lists,member,[y,AList]}}), + ?MODULE:expect({trace,Self,call,{?MODULE,foo,[]}}), + ?MODULE:expect({trace,Self,call,{?MODULE,foo,[3]}}), + ?MODULE:expect({trace,Self,call,{?MODULE,foo,[7,4]}}), + ?MODULE:expect({trace,Self,call,{?MODULE,bar,[]}}), + ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["42"]}}), %% Turn off trace for this module and call functions... - ?line trace_func({?MODULE,'_','_'}, false), - ?line {traced,false} = trace_info({?MODULE,bar,0}, traced), - ?line foo0 = ?MODULE:foo(), - ?line 4 = ?MODULE:foo(3), - ?line 11 = ?MODULE:foo(7, 4), - ?line ok = ?MODULE:bar(), - ?line [1,2,3,4,5,6,7,8,9,10] = lists:seq(1, 10), - ?line 777 = list_to_integer(non_literal("777")), + trace_func({?MODULE,'_','_'}, false), + {traced,false} = trace_info({?MODULE,bar,0}, traced), + foo0 = ?MODULE:foo(), + 4 = ?MODULE:foo(3), + 11 = ?MODULE:foo(7, 4), + ok = ?MODULE:bar(), + [1,2,3,4,5,6,7,8,9,10] = lists:seq(1, 10), + 777 = list_to_integer(non_literal("777")), %% ... turn on all trace messages... - ?line trace_func({'_','_','_'}, false), - ?line [b,a] = lists:reverse([a,b]), + trace_func({'_','_','_'}, false), + [b,a] = lists:reverse([a,b]), %% Read out the remaing trace messages. - ?line ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}), - ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}), + ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}), + ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}), receive - Any -> - ?line ?t:fail({unexpected_message,Any}) + Any -> + ct:fail({unexpected_message,Any}) after 1 -> - ok + ok end, %% Turn on and then off tracing on all external functions. %% This might cause the emulator to crasch later if it doesn't %% restore all export entries properly. - ?line AllFuncs = trace_func({'_','_','_'}, true), + AllFuncs = trace_func({'_','_','_'}, true), io:format("AllFuncs = ~p", [AllFuncs]), %% Make sure that a traced, exported function can still be found. - ?line true = erlang:function_exported(error_handler, undefined_function, 3), - ?line AllFuncs = trace_func({'_','_','_'}, false), - ?line erlang:trace_delivered(all), + true = erlang:function_exported(error_handler, undefined_function, 3), + AllFuncs = trace_func({'_','_','_'}, false), + erlang:trace_delivered(all), receive - {trace_delivered,_,_} -> ok + {trace_delivered,_,_} -> ok end, c:flush(), % Print the traces messages. c:flush(), % Print the traces messages. - ?line {traced,false} = trace_info({erlang,list_to_integer,1}, traced), + {traced,false} = trace_info({erlang,list_to_integer,1}, traced), ok. @@ -286,8 +279,8 @@ foo(X, Y) -> X+Y. %% This test case was written to verify that we do not change %% any behaviour with the introduction of "block-free" upgrade in R16. %% In short: Do not refer to this test case as an authority of how it must work. -upgrade(doc) -> - "Test tracing on module being upgraded"; + +%% Test tracing on module being upgraded upgrade(Config) when is_list(Config) -> V1 = compile_version(my_upgrade_test, 1, Config), V2 = compile_version(my_upgrade_test, 2, Config), @@ -303,8 +296,8 @@ upgrade_do(V1, V2, TraceLocalVersion) -> trace_func({my_upgrade_test,'_','_'}, [], [global]), case TraceLocalVersion of - true -> trace_func({my_upgrade_test,local_version,0}, [], [local]); - _ -> ok + true -> trace_func({my_upgrade_test,local_version,0}, [], [local]); + _ -> ok end, 1 = my_upgrade_test:version(), 1 = my_upgrade_test:do_local(), @@ -319,15 +312,15 @@ upgrade_do(V1, V2, TraceLocalVersion) -> expect({trace,Self,call,{my_upgrade_test,do_local,[]}}), expect({trace,Self,call,{my_upgrade_test,do_real_local,[]}}), case TraceLocalVersion of - true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); - _ -> ok + true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); + _ -> ok end, expect({trace,Self,call,{my_upgrade_test,make_fun_exp,[]}}), expect({trace,Self,call,{my_upgrade_test,make_fun_local,[]}}), expect({trace,Self,call,{my_upgrade_test,version,[]}}), % F1_exp case TraceLocalVersion of - true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F1_loc - _ -> ok + true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F1_loc + _ -> ok end, {module,my_upgrade_test} = erlang:load_module(my_upgrade_test, V2), @@ -349,8 +342,8 @@ upgrade_do(V1, V2, TraceLocalVersion) -> trace_func({my_upgrade_test,'_','_'}, [], [global]), case TraceLocalVersion of - true -> trace_func({my_upgrade_test,local_version,0}, [], [local]); - _ -> ok + true -> trace_func({my_upgrade_test,local_version,0}, [], [local]); + _ -> ok end, 2 = my_upgrade_test:version(), 2 = my_upgrade_test:do_local(), @@ -362,13 +355,13 @@ upgrade_do(V1, V2, TraceLocalVersion) -> expect({trace,Self,call,{my_upgrade_test,do_local,[]}}), expect({trace,Self,call,{my_upgrade_test,do_real_local,[]}}), case TraceLocalVersion of - true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); - _ -> ok + true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); + _ -> ok end, expect({trace,Self,call,{my_upgrade_test,version,[]}}), % F2_exp case TraceLocalVersion of - true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F2_loc - _ -> ok + true -> expect({trace,Self,call,{my_upgrade_test,local_version,[]}}); % F2_loc + _ -> ok end, true = erlang:delete_module(my_upgrade_test), @@ -384,10 +377,10 @@ upgrade_do(V1, V2, TraceLocalVersion) -> ok. compile_version(Module, Version, Config) -> - Data = ?config(data_dir, Config), + Data = proplists:get_value(data_dir, Config), File = filename:join(Data, atom_to_list(Module)), {ok,Module,Bin} = compile:file(File, [{d,'VERSION',Version}, - binary,report]), + binary,report]), Bin. @@ -396,162 +389,157 @@ compile_version(Module, Version, Config) -> %% Also, test the '{tracer,Pid}' option. flags(_Config) -> case test_server:is_native(filename) of - true -> {skip,"filename is native"}; - false -> flags() + true -> {skip,"filename is native"}; + false -> flags() end. flags() -> - ?line Tracer = start_tracer_loop(), - ?line trace_pid(self(), true, [call,{tracer,Tracer}]), + Tracer = start_tracer_loop(), + trace_pid(self(), true, [call,{tracer,Tracer}]), %% Trace some functions... - ?line trace_func({filename,'_','_'}, true), + trace_func({filename,'_','_'}, true), %% ... and call them... - ?line Self = self(), - ?line filename:absname("nisse"), - ?line ?MODULE:expect({trace,Self,call,{filename,absname,["nisse"]}}), - ?line trace_pid(Self, true, [call,arity]), - ?line filename:absname("kalle"), - ?line filename:absname("kalle", "/root"), - ?line ?MODULE:expect({trace,Self,call,{filename,absname,1}}), - ?line ?MODULE:expect({trace,Self,call,{filename,absname,2}}), - ?line trace_info(Self, flags), + Self = self(), + filename:absname("nisse"), + ?MODULE:expect({trace,Self,call,{filename,absname,["nisse"]}}), + trace_pid(Self, true, [call,arity]), + filename:absname("kalle"), + filename:absname("kalle", "/root"), + ?MODULE:expect({trace,Self,call,{filename,absname,1}}), + ?MODULE:expect({trace,Self,call,{filename,absname,2}}), + trace_info(Self, flags), %% Timestamp + arity. flag_test(fun() -> - ?line trace_pid(Self, true, [timestamp]), - ?line "dum" = filename:basename("/abcd/dum"), - ?line Ts = expect({trace_ts,Self,call,{filename,basename,1},ts}), - ?line trace_info(Self, flags), - Ts - end), + trace_pid(Self, true, [timestamp]), + "dum" = filename:basename("/abcd/dum"), + Ts = expect({trace_ts,Self,call,{filename,basename,1},ts}), + trace_info(Self, flags), + Ts + end), %% Timestamp. - ?line AnArg = "/abcd/hejsan", + AnArg = "/abcd/hejsan", flag_test(fun() -> - ?line trace_pid(Self, false, [arity]), - ?line "hejsan" = filename:basename(AnArg), - ?line Ts = expect({trace_ts,Self,call, - {filename,basename,[AnArg]},ts}), - ?line trace_info(Self, flags), - Ts - end), + trace_pid(Self, false, [arity]), + "hejsan" = filename:basename(AnArg), + Ts = expect({trace_ts,Self,call, + {filename,basename,[AnArg]},ts}), + trace_info(Self, flags), + Ts + end), %% All flags turned off. - ?line trace_pid(Self, false, [timestamp]), - ?line AnotherArg = filename:join(AnArg, "hoppsan"), - ?line "hoppsan" = filename:basename(AnotherArg), - ?line expect({trace,Self,call,{filename,join,[AnArg,"hoppsan"]}}), - ?line expect({trace,Self,call,{filename,basename,[AnotherArg]}}), - ?line trace_info(Self, flags), - + trace_pid(Self, false, [timestamp]), + AnotherArg = filename:join(AnArg, "hoppsan"), + "hoppsan" = filename:basename(AnotherArg), + expect({trace,Self,call,{filename,join,[AnArg,"hoppsan"]}}), + expect({trace,Self,call,{filename,basename,[AnotherArg]}}), + trace_info(Self, flags), + ok. flag_test(Test) -> Now = now(), Ts = Test(), case timer:now_diff(Ts, Now) of - Time when Time < 5*1000000 -> - %% Reasonable short time. - ok; - _Diff -> - %% Too large difference. - io:format("Now = ~p\n", [Now]), - io:format("Ts = ~p\n", [Ts]), - ?line ?t:fail() + Time when Time < 5*1000000 -> + %% Reasonable short time. + ok; + _Diff -> + %% Too large difference. + ct:fail("Now = ~p, Ts = ~p", [Now, Ts]) end, flag_test_cpu_timestamp(Test). flag_test_cpu_timestamp(Test) -> try erlang:trace(all, true, [cpu_timestamp]) of - _ -> - io:format("CPU timestamps"), - Ts = Test(), - erlang:trace(all, false, [cpu_timestamp]), - Origin = {0,0,0}, - Hour = 3600*1000000, - case timer:now_diff(Ts, Origin) of - Diff when Diff < 4*Hour -> - %% In the worst case, CPU timestamps count from when this - %% Erlang emulator was started. The above test is a conservative - %% test that all CPU timestamps should pass. - ok; - _Time -> - io:format("Strange CPU timestamp: ~p", [Ts]), - ?line ?t:fail() - end, - io:format("Turned off CPU timestamps") + _ -> + io:format("CPU timestamps"), + Ts = Test(), + erlang:trace(all, false, [cpu_timestamp]), + Origin = {0,0,0}, + Hour = 3600*1000000, + case timer:now_diff(Ts, Origin) of + Diff when Diff < 4*Hour -> + %% In the worst case, CPU timestamps count from when this + %% Erlang emulator was started. The above test is a conservative + %% test that all CPU timestamps should pass. + ok; + _Time -> + ct:fail("Strange CPU timestamp: ~p", [Ts]) + end, + io:format("Turned off CPU timestamps") catch - error:badarg -> ok + error:badarg -> ok end. -errors(doc) -> "Test bad arguments for trace/3 and trace_pattern/3."; -errors(suite) -> []; +%% Test bad arguments for trace/3 and trace_pattern/3. errors(Config) when is_list(Config) -> - ?line expect_badarg_pid(aaa, true, []), - ?line expect_badarg_pid({pid,dum}, false, []), - ?line expect_badarg_func({'_','_',1}, []), - ?line expect_badarg_func({'_',gosh,1}, []), - ?line expect_badarg_func({xxx,'_',2}, []), - ?line expect_badarg_func({xxx,yyy,b}, glurp), + expect_badarg_pid(aaa, true, []), + expect_badarg_pid({pid,dum}, false, []), + expect_badarg_func({'_','_',1}, []), + expect_badarg_func({'_',gosh,1}, []), + expect_badarg_func({xxx,'_',2}, []), + expect_badarg_func({xxx,yyy,b}, glurp), ok. expect_badarg_pid(What, How, Flags) -> case catch erlang:trace(What, How, Flags) of - {'EXIT',{badarg,Where}} -> - io:format("trace(~p, ~p, ~p) ->\n {'EXIT',{badarg,~p}}", - [What,How,Flags,Where]), - ok; - Other -> - io:format("trace(~p, ~p, ~p) -> ~p", - [What,How,Flags,Other]), - ?t:fail({unexpected,Other}) + {'EXIT',{badarg,Where}} -> + io:format("trace(~p, ~p, ~p) ->\n {'EXIT',{badarg,~p}}", + [What,How,Flags,Where]), + ok; + Other -> + io:format("trace(~p, ~p, ~p) -> ~p", + [What,How,Flags,Other]), + ct:fail({unexpected,Other}) end. expect_badarg_func(MFA, Pattern) -> case catch erlang:trace_pattern(MFA, Pattern) of - {'EXIT',{badarg,Where}} -> - io:format("trace_pattern(~p, ~p) ->\n {'EXIT',{badarg,~p}}", - [MFA,Pattern,Where]), - ok; - Other -> - io:format("trace_pattern(~p, ~p) -> ~p", - [MFA, Pattern, Other]), - ?t:fail({unexpected,Other}) + {'EXIT',{badarg,Where}} -> + io:format("trace_pattern(~p, ~p) ->\n {'EXIT',{badarg,~p}}", + [MFA,Pattern,Where]), + ok; + Other -> + io:format("trace_pattern(~p, ~p) -> ~p", + [MFA, Pattern, Other]), + ct:fail({unexpected,Other}) end. -pam(doc) -> "Basic test of PAM."; -pam(suite) -> []; +%% Basic test of PAM. pam(Config) when is_list(Config) -> - ?line start_tracer(), - ?line Self = self(), + start_tracer(), + Self = self(), %% Build the match program. - ?line Prog1 = {[{a,tuple},'$1'],[],[]}, - ?line Prog2 = {[{a,bigger,tuple},'$1'],[],[{message,'$1'}]}, - ?line MatchProg = [Prog1,Prog2], - ?line pam_trace(MatchProg), + Prog1 = {[{a,tuple},'$1'],[],[]}, + Prog2 = {[{a,bigger,tuple},'$1'],[],[{message,'$1'}]}, + MatchProg = [Prog1,Prog2], + pam_trace(MatchProg), %% Do some calls. - ?line ?MODULE:pam_foo(not_a_tuple, [a,b]), - ?line ?MODULE:pam_foo({a,tuple}, [a,list]), - ?line ?MODULE:pam_foo([this,one,will,'not',match], dummy_arg), - ?line LongList = lists:seq(1,10), - ?line ?MODULE:pam_foo({a,bigger,tuple}, LongList), + ?MODULE:pam_foo(not_a_tuple, [a,b]), + ?MODULE:pam_foo({a,tuple}, [a,list]), + ?MODULE:pam_foo([this,one,will,'not',match], dummy_arg), + LongList = lists:seq(1,10), + ?MODULE:pam_foo({a,bigger,tuple}, LongList), %% Check that we get the correct trace messages. - ?line expect({trace,Self,call,{?MODULE,pam_foo,[{a,tuple},[a,list]]}}), - ?line expect({trace,Self,call, - {?MODULE,pam_foo,[{a,bigger,tuple},LongList]}, - LongList}), + expect({trace,Self,call,{?MODULE,pam_foo,[{a,tuple},[a,list]]}}), + expect({trace,Self,call, + {?MODULE,pam_foo,[{a,bigger,tuple},LongList]}, + LongList}), - ?line trace_func({?MODULE,pam_foo,'_'}, false), + trace_func({?MODULE,pam_foo,'_'}, false), ok. pam_trace(Prog) -> @@ -566,38 +554,38 @@ pam_foo(A, B) -> %% Test changing PAM programs for a function. change_pam(_Config) -> case test_server:is_native(lists) of - true -> {skip,"lists is native"}; - false -> change_pam() + true -> {skip,"lists is native"}; + false -> change_pam() end. change_pam() -> - ?line start_tracer(), - ?line Self = self(), + start_tracer(), + Self = self(), %% Install the first match program. %% Test using timestamp at the same time. - ?line trace_pid(Self, true, [call,arity,timestamp]), - ?line Prog1 = [{['$1','$2'],[],[{message,'$1'}]}], - ?line change_pam_trace(Prog1), - ?line [x,y] = lists:append(id([x]), id([y])), - ?line {heap_size,_} = erlang:process_info(Self, heap_size), - ?line expect({trace_ts,Self,call,{lists,append,2},[x],ts}), - ?line expect({trace_ts,Self,call,{erlang,process_info,2},Self,ts}), + trace_pid(Self, true, [call,arity,timestamp]), + Prog1 = [{['$1','$2'],[],[{message,'$1'}]}], + change_pam_trace(Prog1), + [x,y] = lists:append(id([x]), id([y])), + {heap_size,_} = erlang:process_info(Self, heap_size), + expect({trace_ts,Self,call,{lists,append,2},[x],ts}), + expect({trace_ts,Self,call,{erlang,process_info,2},Self,ts}), %% Install a new PAM program. - ?line Prog2 = [{['$1','$2'],[],[{message,'$2'}]}], - ?line change_pam_trace(Prog2), - ?line [xx,yy] = lists:append(id([xx]), id([yy])), - ?line {current_function,_} = erlang:process_info(Self, current_function), - ?line expect({trace_ts,Self,call,{lists,append,2},[yy],ts}), - ?line expect({trace_ts,Self,call,{erlang,process_info,2},current_function,ts}), + Prog2 = [{['$1','$2'],[],[{message,'$2'}]}], + change_pam_trace(Prog2), + [xx,yy] = lists:append(id([xx]), id([yy])), + {current_function,_} = erlang:process_info(Self, current_function), + expect({trace_ts,Self,call,{lists,append,2},[yy],ts}), + expect({trace_ts,Self,call,{erlang,process_info,2},current_function,ts}), - ?line 1 = trace_func({lists,append,2}, false), - ?line 1 = trace_func({erlang,process_info,2}, false), - ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), - ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), + 1 = trace_func({lists,append,2}, false), + 1 = trace_func({erlang,process_info,2}, false), + {match_spec,false} = trace_info({lists,append,2}, match_spec), + {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), ok. @@ -610,71 +598,71 @@ change_pam_trace(Prog) -> return_trace(_Config) -> case test_server:is_native(lists) of - true -> {skip,"lists is native"}; - false -> return_trace() + true -> {skip,"lists is native"}; + false -> return_trace() end. return_trace() -> X = {save,me}, - ?line start_tracer(), - ?line Self = self(), + start_tracer(), + Self = self(), %% Test call and return trace and timestamp. - ?line trace_pid(Self, true, [call,timestamp]), + trace_pid(Self, true, [call,timestamp]), Stupid = {pointless,tuple}, - ?line Prog1 = [{['$1','$2'],[],[{return_trace},{message,{Stupid}}]}], - ?line 1 = trace_func({lists,append,2}, Prog1), - ?line 1 = trace_func({erlang,process_info,2}, Prog1), - ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), - ?line {match_spec,Prog1} = trace_info({erlang,process_info,2}, match_spec), + Prog1 = [{['$1','$2'],[],[{return_trace},{message,{Stupid}}]}], + 1 = trace_func({lists,append,2}, Prog1), + 1 = trace_func({erlang,process_info,2}, Prog1), + {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), + {match_spec,Prog1} = trace_info({erlang,process_info,2}, match_spec), - ?line [x,y] = lists:append(id([x]), id([y])), + [x,y] = lists:append(id([x]), id([y])), Current = {current_function,{?MODULE,return_trace,0}}, - ?line Current = erlang:process_info(Self, current_function), - ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), - ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), - ?line expect({trace_ts,Self,call,{erlang,process_info,[Self,current_function]}, - Stupid,ts}), - ?line expect({trace_ts,Self,return_from,{erlang,process_info,2},Current,ts}), + Current = erlang:process_info(Self, current_function), + expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), + expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), + expect({trace_ts,Self,call,{erlang,process_info,[Self,current_function]}, + Stupid,ts}), + expect({trace_ts,Self,return_from,{erlang,process_info,2},Current,ts}), %% Try catch/exit. - ?line 1 = trace_func({?MODULE,nasty,0}, [{[],[],[{return_trace},{message,false}]}]), - ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()), - ?line 1 = trace_func({?MODULE,nasty,0}, false), + 1 = trace_func({?MODULE,nasty,0}, [{[],[],[{return_trace},{message,false}]}]), + {'EXIT',good_bye} = (catch ?MODULE:nasty()), + 1 = trace_func({?MODULE,nasty,0}, false), %% Turn off trace. - ?line 1 = trace_func({lists,append,2}, false), - ?line 1 = trace_func({erlang,process_info,2}, false), - ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), - ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), + 1 = trace_func({lists,append,2}, false), + 1 = trace_func({erlang,process_info,2}, false), + {match_spec,false} = trace_info({lists,append,2}, match_spec), + {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), %% No timestamp, no trace message for call. - ?line trace_pid(Self, false, [timestamp]), - ?line Prog2 = [{['$1','$2'],[],[{return_trace},{message,false}]}, - {['$1'],[],[{return_trace},{message,false}]}], - ?line 1 = trace_func({lists,seq,2}, Prog2), - ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2), - ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), - ?line {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec), + trace_pid(Self, false, [timestamp]), + Prog2 = [{['$1','$2'],[],[{return_trace},{message,false}]}, + {['$1'],[],[{return_trace},{message,false}]}], + 1 = trace_func({lists,seq,2}, Prog2), + 1 = trace_func({erlang,atom_to_list,1}, Prog2), + {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), + {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec), - ?line lists:seq(2, 7), - ?line _ = atom_to_list(non_literal(nisse)), - ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), - ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), + lists:seq(2, 7), + _ = atom_to_list(non_literal(nisse)), + expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), + expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), %% Turn off trace. - ?line 1 = trace_func({lists,seq,2}, false), - ?line 1 = trace_func({erlang,atom_to_list,1}, false), - ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec), - ?line {match_spec,false} = trace_info({erlang,atom_to_list,1}, match_spec), + 1 = trace_func({lists,seq,2}, false), + 1 = trace_func({erlang,atom_to_list,1}, false), + {match_spec,false} = trace_info({lists,seq,2}, match_spec), + {match_spec,false} = trace_info({erlang,atom_to_list,1}, match_spec), + + {save,me} = X, - ?line {save,me} = X, - ok. nasty() -> @@ -682,396 +670,393 @@ nasty() -> exception_trace(_Config) -> case test_server:is_native(lists) of - true -> {skip,"lists is native"}; - false -> exception_trace() + true -> {skip,"lists is native"}; + false -> exception_trace() end. exception_trace() -> X = {save,me}, - ?line start_tracer(), - ?line Self = self(), + start_tracer(), + Self = self(), %% Test call and return trace and timestamp. - ?line trace_pid(Self, true, [call,timestamp]), + trace_pid(Self, true, [call,timestamp]), Stupid = {pointless,tuple}, - ?line Prog1 = [{['$1','$2'],[],[{exception_trace},{message,{Stupid}}]}], - ?line 1 = trace_func({lists,append,2}, Prog1), - ?line 1 = trace_func({erlang,process_info,2}, Prog1), - ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), - ?line {match_spec,Prog1} = - trace_info({erlang,process_info,2}, match_spec), - - ?line [x,y] = lists:append(id([x]), id([y])), + Prog1 = [{['$1','$2'],[],[{exception_trace},{message,{Stupid}}]}], + 1 = trace_func({lists,append,2}, Prog1), + 1 = trace_func({erlang,process_info,2}, Prog1), + {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), + {match_spec,Prog1} = + trace_info({erlang,process_info,2}, match_spec), + + [x,y] = lists:append(id([x]), id([y])), Current = {current_function,{?MODULE,exception_trace,0}}, - ?line Current = erlang:process_info(Self, current_function), - ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), - ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), - ?line expect({trace_ts,Self,call,{erlang,process_info, - [Self,current_function]}, - Stupid,ts}), - ?line expect({trace_ts,Self,return_from, - {erlang,process_info,2},Current,ts}), + Current = erlang:process_info(Self, current_function), + expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), + expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), + expect({trace_ts,Self,call,{erlang,process_info, + [Self,current_function]}, + Stupid,ts}), + expect({trace_ts,Self,return_from, + {erlang,process_info,2},Current,ts}), %% Try catch/exit. - ?line 1 = trace_func({?MODULE,nasty,0}, - [{[],[],[{exception_trace},{message,false}]}]), - ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()), - ?line expect({trace_ts,Self,exception_from, - {?MODULE,nasty,0},{exit,good_bye},ts}), - ?line 1 = trace_func({?MODULE,nasty,0}, false), + 1 = trace_func({?MODULE,nasty,0}, + [{[],[],[{exception_trace},{message,false}]}]), + {'EXIT',good_bye} = (catch ?MODULE:nasty()), + expect({trace_ts,Self,exception_from, + {?MODULE,nasty,0},{exit,good_bye},ts}), + 1 = trace_func({?MODULE,nasty,0}, false), %% Turn off trace. - ?line 1 = trace_func({lists,append,2}, false), - ?line 1 = trace_func({erlang,process_info,2}, false), - ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), - ?line {match_spec,false} = - trace_info({erlang,process_info,2}, match_spec), + 1 = trace_func({lists,append,2}, false), + 1 = trace_func({erlang,process_info,2}, false), + {match_spec,false} = trace_info({lists,append,2}, match_spec), + {match_spec,false} = + trace_info({erlang,process_info,2}, match_spec), %% No timestamp, no trace message for call. - ?line trace_pid(Self, false, [timestamp]), - ?line Prog2 = [{['$1','$2'],[],[{exception_trace},{message,false}]}, - {['$1'],[],[{exception_trace},{message,false}]}], - ?line 1 = trace_func({lists,seq,2}, Prog2), - ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2), - ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), - ?line {match_spec,Prog2} = - trace_info({erlang,atom_to_list,1}, match_spec), + trace_pid(Self, false, [timestamp]), + Prog2 = [{['$1','$2'],[],[{exception_trace},{message,false}]}, + {['$1'],[],[{exception_trace},{message,false}]}], + 1 = trace_func({lists,seq,2}, Prog2), + 1 = trace_func({erlang,atom_to_list,1}, Prog2), + {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), + {match_spec,Prog2} = + trace_info({erlang,atom_to_list,1}, match_spec), - ?line lists:seq(2, 7), - ?line _ = atom_to_list(non_literal(nisse)), - ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), - ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), + lists:seq(2, 7), + _ = atom_to_list(non_literal(nisse)), + expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), + expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), %% Turn off trace. - ?line 1 = trace_func({lists,seq,2}, false), - ?line 1 = trace_func({erlang,atom_to_list,1}, false), - ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec), - ?line {match_spec,false} = - trace_info({erlang,atom_to_list,1}, match_spec), + 1 = trace_func({lists,seq,2}, false), + 1 = trace_func({erlang,atom_to_list,1}, false), + {match_spec,false} = trace_info({lists,seq,2}, match_spec), + {match_spec,false} = + trace_info({erlang,atom_to_list,1}, match_spec), - ?line expect(), - ?line {save,me} = X, + expect(), + {save,me} = X, ok. -on_load(doc) -> "Test the on_load argument for trace_pattern/3."; -on_load(suite) -> []; +%% Test the on_load argument for trace_pattern/3. on_load(Config) when is_list(Config) -> - ?line 0 = erlang:trace_pattern(on_load, []), - ?line {traced,global} = erlang:trace_info(on_load, traced), - ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec), + 0 = erlang:trace_pattern(on_load, []), + {traced,global} = erlang:trace_info(on_load, traced), + {match_spec,[]} = erlang:trace_info(on_load, match_spec), - ?line 0 = erlang:trace_pattern(on_load, true, [local]), - ?line {traced,local} = erlang:trace_info(on_load, traced), - ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec), + 0 = erlang:trace_pattern(on_load, true, [local]), + {traced,local} = erlang:trace_info(on_load, traced), + {match_spec,[]} = erlang:trace_info(on_load, match_spec), - ?line 0 = erlang:trace_pattern(on_load, false, [local]), - ?line {traced,false} = erlang:trace_info(on_load, traced), - ?line {match_spec,false} = erlang:trace_info(on_load, match_spec), + 0 = erlang:trace_pattern(on_load, false, [local]), + {traced,false} = erlang:trace_info(on_load, traced), + {match_spec,false} = erlang:trace_info(on_load, match_spec), - ?line Pam1 = [{[],[],[{message,false}]}], - ?line 0 = erlang:trace_pattern(on_load, Pam1), - ?line {traced,global} = erlang:trace_info(on_load, traced), - ?line {match_spec,Pam1} = erlang:trace_info(on_load, match_spec), + Pam1 = [{[],[],[{message,false}]}], + 0 = erlang:trace_pattern(on_load, Pam1), + {traced,global} = erlang:trace_info(on_load, traced), + {match_spec,Pam1} = erlang:trace_info(on_load, match_spec), - ?line 0 = erlang:trace_pattern(on_load, true, [local]), - ?line 0 = erlang:trace_pattern(on_load, false, [local]), + 0 = erlang:trace_pattern(on_load, true, [local]), + 0 = erlang:trace_pattern(on_load, false, [local]), ok. -deep_exception(doc) -> "Test the new exception trace."; -deep_exception(suite) -> []; +%% Test the new exception trace. deep_exception(Config) when is_list(Config) -> deep_exception(). deep_exception() -> - ?line start_tracer(), - ?line Self = self(), - ?line N = 200000, - ?line LongImproperList = seq(1, N-1, N), - + start_tracer(), + Self = self(), + N = 200000, + LongImproperList = seq(1, N-1, N), + Prog = [{'_',[],[{exception_trace}]}], -%% ?line 1 = trace_pid(Self, true, [call]), - ?line 1 = trace_func({?MODULE,deep,'_'}, Prog), - ?line 1 = trace_func({?MODULE,deep_1,'_'}, Prog), - ?line 1 = trace_func({?MODULE,deep_2,'_'}, Prog), - ?line 1 = trace_func({?MODULE,deep_3,'_'}, Prog), - ?line 1 = trace_func({?MODULE,deep_4,'_'}, Prog), - ?line 1 = trace_func({?MODULE,deep_5,'_'}, Prog), - ?line 1 = trace_func({?MODULE,id,'_'}, Prog), - ?line 1 = trace_func({erlang,'++','_'}, Prog), - ?line 1 = trace_func({erlang,exit,1}, Prog), - ?line 1 = trace_func({erlang,throw,1}, Prog), - ?line 2 = trace_func({erlang,error,'_'}, Prog), - ?line 1 = trace_func({lists,reverse,2}, Prog), - - ?line deep_exception(?LINE, exit, [paprika], 1, - [{trace,Self,call,{erlang,exit,[paprika]}}, - {trace,Self,exception_from,{erlang,exit,1}, - {exit,paprika}}], - exception_from, {exit,paprika}), - ?line deep_exception(?LINE, throw, [3.14], 2, - [{trace,Self,call,{erlang,throw,[3.14]}}, - {trace,Self,exception_from,{erlang,throw,1}, - {throw,3.14}}], - exception_from, {throw,3.14}), - ?line deep_exception(?LINE, error, [{paprika}], 3, - [{trace,Self,call,{erlang,error,[{paprika}]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,{paprika}}}], - exception_from, {error,{paprika}}), - ?line deep_exception(?LINE, error, ["{paprika}",[]], 3, - [{trace,Self,call,{erlang,error,["{paprika}",[]]}}, - {trace,Self,exception_from,{erlang,error,2}, - {error,"{paprika}"}}], - exception_from, {error,"{paprika}"}), - ?line deep_exception(?LINE, id, [broccoli], 4, [], - return_from, broccoli), - ?line deep_exception( - ?LINE, append, [1,2], 5, - [{trace,Self,call,{erlang,'++',[1,2]}}, - {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], - exception_from, {error,badarg}), - ?line deep_exception(?LINE, '=', [1,2], 6, [], - exception_from, {error,{badmatch,2}}), + %% 1 = trace_pid(Self, true, [call]), + 1 = trace_func({?MODULE,deep,'_'}, Prog), + 1 = trace_func({?MODULE,deep_1,'_'}, Prog), + 1 = trace_func({?MODULE,deep_2,'_'}, Prog), + 1 = trace_func({?MODULE,deep_3,'_'}, Prog), + 1 = trace_func({?MODULE,deep_4,'_'}, Prog), + 1 = trace_func({?MODULE,deep_5,'_'}, Prog), + 1 = trace_func({?MODULE,id,'_'}, Prog), + 1 = trace_func({erlang,'++','_'}, Prog), + 1 = trace_func({erlang,exit,1}, Prog), + 1 = trace_func({erlang,throw,1}, Prog), + 2 = trace_func({erlang,error,'_'}, Prog), + 1 = trace_func({lists,reverse,2}, Prog), + + deep_exception(?LINE, exit, [paprika], 1, + [{trace,Self,call,{erlang,exit,[paprika]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,paprika}}], + exception_from, {exit,paprika}), + deep_exception(?LINE, throw, [3.14], 2, + [{trace,Self,call,{erlang,throw,[3.14]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,3.14}}], + exception_from, {throw,3.14}), + deep_exception(?LINE, error, [{paprika}], 3, + [{trace,Self,call,{erlang,error,[{paprika}]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,{paprika}}}], + exception_from, {error,{paprika}}), + deep_exception(?LINE, error, ["{paprika}",[]], 3, + [{trace,Self,call,{erlang,error,["{paprika}",[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,"{paprika}"}}], + exception_from, {error,"{paprika}"}), + deep_exception(?LINE, id, [broccoli], 4, [], + return_from, broccoli), + deep_exception( + ?LINE, append, [1,2], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + deep_exception(?LINE, '=', [1,2], 6, [], + exception_from, {error,{badmatch,2}}), %% - ?line io:format("== Subtest: ~w", [?LINE]), - ?line try lists:reverse(LongImproperList, []) of - R1 -> test_server:fail({returned,abbr(R1)}) - catch error:badarg -> ok - end, - ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) - when is_list(L1), is_list(L2), S == Self -> - next; - ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) - when S == Self -> - expected; - ('_') -> - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}; - (_) -> - {unexpected, - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}} - end), - ?line deep_exception(?LINE, deep_5, [1,2], 7, - [{trace,Self,call,{erlang,error,[undef]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,undef}}], - exception_from, {error,undef}), - ?line deep_exception(?LINE, deep_5, [undef], 8, - [{trace,Self,call,{?MODULE,deep_5,[undef]}}, - {trace,Self,exception_from,{?MODULE,deep_5,1}, - {error,function_clause}}], - exception_from, {error,function_clause}), - + io:format("== Subtest: ~w", [?LINE]), + try lists:reverse(LongImproperList, []) of + R1 -> ct:fail({returned,abbr(R1)}) + catch error:badarg -> ok + end, + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + deep_exception(?LINE, deep_5, [1,2], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + deep_exception(?LINE, deep_5, [undef], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), + %% Apply %% - ?line deep_exception(?LINE, apply, [erlang,error,[[mo|rot]]], 1, - [{trace,Self,call,{erlang,error,[[mo|rot]]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,[mo|rot]}}], - exception_from, {error,[mo|rot]}), - ?line deep_exception(?LINE, apply, [erlang,error,[[mo|"rot"],[]]], 1, - [{trace,Self,call,{erlang,error,[[mo|"rot"],[]]}}, - {trace,Self,exception_from,{erlang,error,2}, - {error,[mo|"rot"]}}], - exception_from, {error,[mo|"rot"]}), - ?line Morot = make_ref(), - ?line deep_exception(?LINE, apply, [erlang,throw,[Morot]], 3, - [{trace,Self,call,{erlang,throw,[Morot]}}, - {trace,Self,exception_from,{erlang,throw,1}, - {throw,Morot}}], - exception_from, {throw,Morot}), - ?line deep_exception(?LINE, apply, [erlang,exit,[["morot"|Morot]]], 2, - [{trace,Self,call,{erlang,exit,[["morot"|Morot]]}}, - {trace,Self,exception_from,{erlang,exit,1}, - {exit,["morot"|Morot]}}], - exception_from, {exit,["morot"|Morot]}), - ?line deep_exception( - ?LINE, apply, [?MODULE,id,[spenat]], 4, - [{trace,Self,call,{?MODULE,id,[spenat]}}, - {trace,Self,return_from,{?MODULE,id,1},spenat}], - return_from, spenat), - ?line deep_exception( - ?LINE, apply, [erlang,'++',[1,2]], 5, - [{trace,Self,call,{erlang,'++',[1,2]}}, - {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], - exception_from, {error,badarg}), - ?line io:format("== Subtest: ~w", [?LINE]), - ?line try apply(lists, reverse, [LongImproperList, []]) of - R2 -> test_server:fail({returned,abbr(R2)}) - catch error:badarg -> ok - end, - ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) - when is_list(L1), is_list(L2), S == Self -> - next; - ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) - when S == Self -> - expected; - ('_') -> - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}; - (_) -> - {unexpected, - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}} - end), - ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7, - [{trace,Self,call,{erlang,error,[undef]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,undef}}], - exception_from, {error,undef}), - ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[undef]], 8, - [{trace,Self,call,{?MODULE,deep_5,[undef]}}, - {trace,Self,exception_from,{?MODULE,deep_5,1}, - {error,function_clause}}], - exception_from, {error,function_clause}), + deep_exception(?LINE, apply, [erlang,error,[[mo|rot]]], 1, + [{trace,Self,call,{erlang,error,[[mo|rot]]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,[mo|rot]}}], + exception_from, {error,[mo|rot]}), + deep_exception(?LINE, apply, [erlang,error,[[mo|"rot"],[]]], 1, + [{trace,Self,call,{erlang,error,[[mo|"rot"],[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,[mo|"rot"]}}], + exception_from, {error,[mo|"rot"]}), + Morot = make_ref(), + deep_exception(?LINE, apply, [erlang,throw,[Morot]], 3, + [{trace,Self,call,{erlang,throw,[Morot]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,Morot}}], + exception_from, {throw,Morot}), + deep_exception(?LINE, apply, [erlang,exit,[["morot"|Morot]]], 2, + [{trace,Self,call,{erlang,exit,[["morot"|Morot]]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,["morot"|Morot]}}], + exception_from, {exit,["morot"|Morot]}), + deep_exception( + ?LINE, apply, [?MODULE,id,[spenat]], 4, + [{trace,Self,call,{?MODULE,id,[spenat]}}, + {trace,Self,return_from,{?MODULE,id,1},spenat}], + return_from, spenat), + deep_exception( + ?LINE, apply, [erlang,'++',[1,2]], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + io:format("== Subtest: ~w", [?LINE]), + try apply(lists, reverse, [LongImproperList, []]) of + R2 -> ct:fail({returned,abbr(R2)}) + catch error:badarg -> ok + end, + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + deep_exception(?LINE, apply, [?MODULE,deep_5,[undef]], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), %% Apply of fun %% - ?line deep_exception(?LINE, apply, - [fun () -> - erlang:error([{"palsternacka",3.14},17]) - end, []], 1, - [{trace,Self,call, - {erlang,error,[[{"palsternacka",3.14},17]]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,[{"palsternacka",3.14},17]}}], - exception_from, {error,[{"palsternacka",3.14},17]}), - ?line deep_exception(?LINE, apply, - [fun () -> - erlang:error(["palsternacka",17], []) - end, []], 1, - [{trace,Self,call, - {erlang,error,[["palsternacka",17],[]]}}, - {trace,Self,exception_from,{erlang,error,2}, - {error,["palsternacka",17]}}], - exception_from, {error,["palsternacka",17]}), - ?line deep_exception(?LINE, apply, - [fun () -> erlang:throw(Self) end, []], 2, - [{trace,Self,call,{erlang,throw,[Self]}}, - {trace,Self,exception_from,{erlang,throw,1}, - {throw,Self}}], - exception_from, {throw,Self}), - ?line deep_exception(?LINE, apply, - [fun () -> - erlang:exit({1,2,3,4,[5,palsternacka]}) - end, []], 3, - [{trace,Self,call, - {erlang,exit,[{1,2,3,4,[5,palsternacka]}]}}, - {trace,Self,exception_from,{erlang,exit,1}, - {exit,{1,2,3,4,[5,palsternacka]}}}], - exception_from, {exit,{1,2,3,4,[5,palsternacka]}}), - ?line deep_exception(?LINE, apply, - [fun () -> ?MODULE:id(bladsallad) end, []], 4, - [{trace,Self,call,{?MODULE,id,[bladsallad]}}, - {trace,Self,return_from,{?MODULE,id,1},bladsallad}], - return_from, bladsallad), - ?line deep_exception(?LINE, apply, - [fun (A, B) -> A ++ B end, [1,2]], 5, - [{trace,Self,call,{erlang,'++',[1,2]}}, - {trace,Self,exception_from, - {erlang,'++',2},{error,badarg}}], - exception_from, {error,badarg}), - ?line deep_exception(?LINE, apply, [fun (A, B) -> A = B end, [1,2]], 6, - [], - exception_from, {error,{badmatch,2}}), - ?line io:format("== Subtest: ~w", [?LINE]), - ?line try apply(fun() -> lists:reverse(LongImproperList, []) end, []) of - R3 -> test_server:fail({returned,abbr(R3)}) - catch error:badarg -> ok - end, - ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) - when is_list(L1), is_list(L2), S == Self -> - next; - ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) - when S == Self -> - expected; - ('_') -> - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}; - (_) -> - {unexpected, - {trace,Self,exception_from, - {lists,reverse,2},{error,badarg}}} - end), - ?line deep_exception(?LINE, apply, - [fun () -> ?MODULE:deep_5(1,2) end, []], 7, - [{trace,Self,call,{erlang,error,[undef]}}, - {trace,Self,exception_from,{erlang,error,1}, - {error,undef}}], - exception_from, {error,undef}), - ?line deep_exception(?LINE, apply, - [fun () -> ?MODULE:deep_5(undef) end, []], 8, - [{trace,Self,call,{?MODULE,deep_5,[undef]}}, - {trace,Self,exception_from,{?MODULE,deep_5,1}, - {error,function_clause}}], - exception_from, {error,function_clause}), - - ?line trace_func({?MODULE,'_','_'}, false), - ?line trace_func({erlang,'_','_'}, false), - ?line trace_func({lists,'_','_'}, false), - ?line expect(), - ?line ok. + deep_exception(?LINE, apply, + [fun () -> + erlang:error([{"palsternacka",3.14},17]) + end, []], 1, + [{trace,Self,call, + {erlang,error,[[{"palsternacka",3.14},17]]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,[{"palsternacka",3.14},17]}}], + exception_from, {error,[{"palsternacka",3.14},17]}), + deep_exception(?LINE, apply, + [fun () -> + erlang:error(["palsternacka",17], []) + end, []], 1, + [{trace,Self,call, + {erlang,error,[["palsternacka",17],[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,["palsternacka",17]}}], + exception_from, {error,["palsternacka",17]}), + deep_exception(?LINE, apply, + [fun () -> erlang:throw(Self) end, []], 2, + [{trace,Self,call,{erlang,throw,[Self]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,Self}}], + exception_from, {throw,Self}), + deep_exception(?LINE, apply, + [fun () -> + erlang:exit({1,2,3,4,[5,palsternacka]}) + end, []], 3, + [{trace,Self,call, + {erlang,exit,[{1,2,3,4,[5,palsternacka]}]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,{1,2,3,4,[5,palsternacka]}}}], + exception_from, {exit,{1,2,3,4,[5,palsternacka]}}), + deep_exception(?LINE, apply, + [fun () -> ?MODULE:id(bladsallad) end, []], 4, + [{trace,Self,call,{?MODULE,id,[bladsallad]}}, + {trace,Self,return_from,{?MODULE,id,1},bladsallad}], + return_from, bladsallad), + deep_exception(?LINE, apply, + [fun (A, B) -> A ++ B end, [1,2]], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from, + {erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + deep_exception(?LINE, apply, [fun (A, B) -> A = B end, [1,2]], 6, + [], + exception_from, {error,{badmatch,2}}), + io:format("== Subtest: ~w", [?LINE]), + try apply(fun() -> lists:reverse(LongImproperList, []) end, []) of + R3 -> ct:fail({returned,abbr(R3)}) + catch error:badarg -> ok + end, + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + deep_exception(?LINE, apply, + [fun () -> ?MODULE:deep_5(1,2) end, []], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + deep_exception(?LINE, apply, + [fun () -> ?MODULE:deep_5(undef) end, []], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), + + trace_func({?MODULE,'_','_'}, false), + trace_func({erlang,'_','_'}, false), + trace_func({lists,'_','_'}, false), + expect(), + ok. deep_exception(Line, B, Q, N, Extra, Tag, R) -> - ?line Self = self(), - ?line io:format("== Subtest: ~w", [Line]), - ?line Result = ?MODULE:deep(N, B, Q), - ?line Result = deep_expect(Self, B, Q, N, Extra, Tag, R). + Self = self(), + io:format("== Subtest: ~w", [Line]), + Result = ?MODULE:deep(N, B, Q), + Result = deep_expect(Self, B, Q, N, Extra, Tag, R). deep_expect(Self, B, Q, N, Extra, Tag, R) -> - ?line expect({trace,Self,call,{?MODULE,deep,[N,B,Q]}}), - ?line Result = deep_expect_N(Self, B, Q, N, Extra, Tag, R), - ?line expect({trace,Self,return_from,{?MODULE,deep,3},Result}), - ?line Result. + expect({trace,Self,call,{?MODULE,deep,[N,B,Q]}}), + Result = deep_expect_N(Self, B, Q, N, Extra, Tag, R), + expect({trace,Self,return_from,{?MODULE,deep,3},Result}), + Result. deep_expect_N(Self, B, Q, N, Extra, Tag, R) -> deep_expect_N(Self, B, Q, N, Extra, Tag, R, N). deep_expect_N(Self, B, Q, N, Extra, Tag, R, J) when J > 0 -> - ?line expect({trace,Self,call,{?MODULE,deep_1,[J,B,Q]}}), - ?line deep_expect_N(Self, B, Q, N, Extra, Tag, R, J-1); + expect({trace,Self,call,{?MODULE,deep_1,[J,B,Q]}}), + deep_expect_N(Self, B, Q, N, Extra, Tag, R, J-1); deep_expect_N(Self, B, Q, N, Extra, Tag, R, 0) -> - ?line expect({trace,Self,call,{?MODULE,deep_2,[B,Q]}}), - ?line expect({trace,Self,call,{?MODULE,deep_3,[B,Q]}}), - ?line expect({trace,Self,return_from,{?MODULE,deep_3,2},{B,Q}}), - ?line expect({trace,Self,call,{?MODULE,deep_4,[{B,Q}]}}), - ?line expect({trace,Self,call,{?MODULE,id,[{B,Q}]}}), - ?line expect({trace,Self,return_from,{?MODULE,id,1},{B,Q}}), - ?line deep_expect_Extra(Self, N, Extra, Tag, R), - ?line expect({trace,Self,Tag,{?MODULE,deep_4,1},R}), - ?line expect({trace,Self,Tag,{?MODULE,deep_2,2},R}), - ?line deep_expect_N(Self, N, Tag, R). + expect({trace,Self,call,{?MODULE,deep_2,[B,Q]}}), + expect({trace,Self,call,{?MODULE,deep_3,[B,Q]}}), + expect({trace,Self,return_from,{?MODULE,deep_3,2},{B,Q}}), + expect({trace,Self,call,{?MODULE,deep_4,[{B,Q}]}}), + expect({trace,Self,call,{?MODULE,id,[{B,Q}]}}), + expect({trace,Self,return_from,{?MODULE,id,1},{B,Q}}), + deep_expect_Extra(Self, N, Extra, Tag, R), + expect({trace,Self,Tag,{?MODULE,deep_4,1},R}), + expect({trace,Self,Tag,{?MODULE,deep_2,2},R}), + deep_expect_N(Self, N, Tag, R). deep_expect_Extra(Self, N, [E|Es], Tag, R) -> - ?line expect(E), - ?line deep_expect_Extra(Self, N, Es, Tag, R); + expect(E), + deep_expect_Extra(Self, N, Es, Tag, R); deep_expect_Extra(_Self, _N, [], _Tag, _R) -> - ?line ok. + ok. deep_expect_N(Self, N, Tag, R) when N > 0 -> - ?line expect({trace,Self,Tag,{?MODULE,deep_1,3},R}), - ?line deep_expect_N(Self, N-1, Tag, R); + expect({trace,Self,Tag,{?MODULE,deep_1,3},R}), + deep_expect_N(Self, N-1, Tag, R); deep_expect_N(_Self, 0, return_from, R) -> - ?line {value,R}; + {value,R}; deep_expect_N(_Self, 0, exception_from, R) -> - ?line R. + R. -exception_nocatch(doc) -> "Test the new exception trace."; -exception_nocatch(suite) -> []; +%% Test the new exception trace. exception_nocatch(Config) when is_list(Config) -> exception_nocatch(). @@ -1081,78 +1066,78 @@ exception_nocatch() -> Deep4LocBadmatch = get_deep_4_loc({'=',[a,b]}), Prog = [{'_',[],[{exception_trace}]}], - ?line 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog), - ?line 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog), - ?line 1 = erlang:trace_pattern({?MODULE,deep_3,'_'}, Prog), - ?line 1 = erlang:trace_pattern({?MODULE,deep_4,'_'}, Prog), - ?line 1 = erlang:trace_pattern({?MODULE,deep_5,'_'}, Prog), - ?line 1 = erlang:trace_pattern({?MODULE,id,'_'}, Prog), - ?line 1 = erlang:trace_pattern({erlang,exit,1}, Prog), - ?line 1 = erlang:trace_pattern({erlang,throw,1}, Prog), - ?line 2 = erlang:trace_pattern({erlang,error,'_'}, Prog), - ?line Q1 = {make_ref(),Prog}, - ?line T1 = - exception_nocatch(?LINE, exit, [Q1], 3, - [{trace,t1,call,{erlang,exit,[Q1]}}, - {trace,t1,exception_from,{erlang,exit,1}, - {exit,Q1}}], - exception_from, {exit,Q1}), - ?line expect({trace,T1,exit,Q1}), - ?line Q2 = {cake,14.125}, - ?line T2 = - exception_nocatch(?LINE, throw, [Q2], 2, - [{trace,t2,call,{erlang,throw,[Q2]}}, - {trace,t2,exception_from,{erlang,throw,1}, - {error,{nocatch,Q2}}}], - exception_from, {error,{nocatch,Q2}}), - ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]}, - {?MODULE,deep_4,1, - Deep4LocThrow}]}}), - ?line Q3 = {dump,[dump,{dump}]}, - ?line T3 = - exception_nocatch(?LINE, error, [Q3], 4, - [{trace,t3,call,{erlang,error,[Q3]}}, - {trace,t3,exception_from,{erlang,error,1}, - {error,Q3}}], - exception_from, {error,Q3}), - ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]}, - {?MODULE,deep_4,1,Deep4LocError}]}}), - ?line T4 = - exception_nocatch(?LINE, '=', [17,4711], 5, [], - exception_from, {error,{badmatch,4711}}), - ?line expect({trace,T4,exit,{{badmatch,4711}, - [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}), + 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog), + 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog), + 1 = erlang:trace_pattern({?MODULE,deep_3,'_'}, Prog), + 1 = erlang:trace_pattern({?MODULE,deep_4,'_'}, Prog), + 1 = erlang:trace_pattern({?MODULE,deep_5,'_'}, Prog), + 1 = erlang:trace_pattern({?MODULE,id,'_'}, Prog), + 1 = erlang:trace_pattern({erlang,exit,1}, Prog), + 1 = erlang:trace_pattern({erlang,throw,1}, Prog), + 2 = erlang:trace_pattern({erlang,error,'_'}, Prog), + Q1 = {make_ref(),Prog}, + T1 = + exception_nocatch(?LINE, exit, [Q1], 3, + [{trace,t1,call,{erlang,exit,[Q1]}}, + {trace,t1,exception_from,{erlang,exit,1}, + {exit,Q1}}], + exception_from, {exit,Q1}), + expect({trace,T1,exit,Q1}), + Q2 = {cake,14.125}, + T2 = + exception_nocatch(?LINE, throw, [Q2], 2, + [{trace,t2,call,{erlang,throw,[Q2]}}, + {trace,t2,exception_from,{erlang,throw,1}, + {error,{nocatch,Q2}}}], + exception_from, {error,{nocatch,Q2}}), + expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]}, + {?MODULE,deep_4,1, + Deep4LocThrow}]}}), + Q3 = {dump,[dump,{dump}]}, + T3 = + exception_nocatch(?LINE, error, [Q3], 4, + [{trace,t3,call,{erlang,error,[Q3]}}, + {trace,t3,exception_from,{erlang,error,1}, + {error,Q3}}], + exception_from, {error,Q3}), + expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]}, + {?MODULE,deep_4,1,Deep4LocError}]}}), + T4 = + exception_nocatch(?LINE, '=', [17,4711], 5, [], + exception_from, {error,{badmatch,4711}}), + expect({trace,T4,exit,{{badmatch,4711}, + [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}), %% - ?line erlang:trace_pattern({?MODULE,'_','_'}, false), - ?line erlang:trace_pattern({erlang,'_','_'}, false), - ?line expect(), - ?line ok. + erlang:trace_pattern({?MODULE,'_','_'}, false), + erlang:trace_pattern({erlang,'_','_'}, false), + expect(), + ok. get_deep_4_loc(Arg) -> try - deep_4(Arg), - ?t:fail(should_not_return_to_here) + deep_4(Arg), + ct:fail(should_not_return_to_here) catch - _:_ -> - [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(), - Loc0 + _:_ -> + [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(), + Loc0 end. exception_nocatch(Line, B, Q, N, Extra, Tag, R) -> - ?line io:format("== Subtest: ~w", [Line]), - ?line Go = make_ref(), - ?line Tracee = - spawn(fun () -> - receive - Go -> - deep_1(N, B, Q) - end - end), - ?line 1 = erlang:trace(Tracee, true, [call,return_to,procs]), - ?line Tracee ! Go, - ?line deep_expect_N(Tracee, B, Q, N-1, - [setelement(2, T, Tracee) || T <- Extra], Tag, R), - ?line Tracee. + io:format("== Subtest: ~w", [Line]), + Go = make_ref(), + Tracee = + spawn(fun () -> + receive + Go -> + deep_1(N, B, Q) + end + end), + 1 = erlang:trace(Tracee, true, [call,return_to,procs]), + Tracee ! Go, + deep_expect_N(Tracee, B, Q, N-1, + [setelement(2, T, Tracee) || T <- Extra], Tag, R), + Tracee. %% Make sure that code that uses the optimized bit syntax matching %% can be traced without crashing the emulator. (Actually, it seems @@ -1160,22 +1145,22 @@ exception_nocatch(Line, B, Q, N, Extra, Tag, R) -> %% will keep the test case anyway.) bit_syntax(Config) when is_list(Config) -> - ?line start_tracer(), - ?line 1 = trace_func({?MODULE,bs_sum_a,'_'}, []), - ?line 1 = trace_func({?MODULE,bs_sum_b,'_'}, []), + start_tracer(), + 1 = trace_func({?MODULE,bs_sum_a,'_'}, []), + 1 = trace_func({?MODULE,bs_sum_b,'_'}, []), - ?line 6 = call_bs_sum_a(<<1,2,3>>), - ?line 10 = call_bs_sum_b(<<1,2,3,4>>), + 6 = call_bs_sum_a(<<1,2,3>>), + 10 = call_bs_sum_b(<<1,2,3,4>>), - ?line trace_func({?MODULE,'_','_'}, false), - ?line erlang:trace_delivered(all), + trace_func({?MODULE,'_','_'}, false), + erlang:trace_delivered(all), receive - {trace_delivered,_,_} -> ok + {trace_delivered,_,_} -> ok end, - + Self = self(), - ?line expect({trace,Self,call,{?MODULE,bs_sum_a,[<<2,3>>,1]}}), - ?line expect({trace,Self,call,{?MODULE,bs_sum_b,[1,<<2,3,4>>]}}), + expect({trace,Self,call,{?MODULE,bs_sum_a,[<<2,3>>,1]}}), + expect({trace,Self,call,{?MODULE,bs_sum_b,[1,<<2,3,4>>]}}), ok. @@ -1190,106 +1175,106 @@ bs_sum_a(<<>>, Acc) -> Acc. bs_sum_b(Acc, <<H,T/binary>>) -> bs_sum_b(H+Acc, T); bs_sum_b(Acc, <<>>) -> Acc. - - + + %%% Help functions. expect() -> case flush() of - [] -> ok; - Msgs -> - test_server:fail({unexpected,abbr(Msgs)}) + [] -> ok; + Msgs -> + ct:fail({unexpected,abbr(Msgs)}) end. expect({trace_ts,Pid,Type,MFA,Term,ts}=Message) -> receive - M -> - case M of - {trace_ts,Pid,Type,MFA,Term,Ts}=MessageTs -> - ok = io:format("Expected and got ~p", [abbr(MessageTs)]), - Ts; - _ -> - io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), - test_server:fail({unexpected,abbr([M|flush()])}) - end + M -> + case M of + {trace_ts,Pid,Type,MFA,Term,Ts}=MessageTs -> + ok = io:format("Expected and got ~p", [abbr(MessageTs)]), + Ts; + _ -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + ct:fail({unexpected,abbr([M|flush()])}) + end after 5000 -> - io:format("Expected ~p; got nothing", [abbr(Message)]), - test_server:fail(no_trace_message) + io:format("Expected ~p; got nothing", [abbr(Message)]), + ct:fail(no_trace_message) end; expect({trace_ts,Pid,Type,MFA,ts}=Message) -> receive - M -> - case M of - {trace_ts,Pid,Type,MFA,Ts} -> - ok = io:format("Expected and got ~p", [abbr(M)]), - Ts; - _ -> - io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), - test_server:fail({unexpected,abbr([M|flush()])}) - end + M -> + case M of + {trace_ts,Pid,Type,MFA,Ts} -> + ok = io:format("Expected and got ~p", [abbr(M)]), + Ts; + _ -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + ct:fail({unexpected,abbr([M|flush()])}) + end after 5000 -> - io:format("Expected ~p; got nothing", [abbr(Message)]), - test_server:fail(no_trace_message) + io:format("Expected ~p; got nothing", [abbr(Message)]), + ct:fail(no_trace_message) end; expect(Validator) when is_function(Validator) -> receive - M -> - case Validator(M) of - expected -> - ok = io:format("Expected and got ~p", [abbr(M)]); - next -> - ok = io:format("Expected and got ~p", [abbr(M)]), - expect(Validator); - {unexpected,Message} -> - io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), - test_server:fail({unexpected,abbr([M|flush()])}) - end + M -> + case Validator(M) of + expected -> + ok = io:format("Expected and got ~p", [abbr(M)]); + next -> + ok = io:format("Expected and got ~p", [abbr(M)]), + expect(Validator); + {unexpected,Message} -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + ct:fail({unexpected,abbr([M|flush()])}) + end after 5000 -> - io:format("Expected ~p; got nothing", [abbr(Validator('_'))]), - test_server:fail(no_trace_message) + io:format("Expected ~p; got nothing", [abbr(Validator('_'))]), + ct:fail(no_trace_message) end; expect(Message) -> receive - M -> - case M of - Message -> - ok = io:format("Expected and got ~p", [abbr(Message)]); - Other -> - io:format("Expected ~p; got ~p", - [abbr(Message),abbr(Other)]), - test_server:fail({unexpected,abbr([Other|flush()])}) - end + M -> + case M of + Message -> + ok = io:format("Expected and got ~p", [abbr(Message)]); + Other -> + io:format("Expected ~p; got ~p", + [abbr(Message),abbr(Other)]), + ct:fail({unexpected,abbr([Other|flush()])}) + end after 5000 -> - io:format("Expected ~p; got nothing", [abbr(Message)]), - test_server:fail(no_trace_message) + io:format("Expected ~p; got nothing", [abbr(Message)]), + ct:fail(no_trace_message) end. trace_info(What, Key) -> get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}}, Res = receive - {apply_result,Result} -> Result - end, + {apply_result,Result} -> Result + end, ok = io:format("erlang:trace_info(~p, ~p) -> ~p", - [What,Key,Res]), + [What,Key,Res]), Res. - + trace_func(MFA, MatchSpec) -> trace_func(MFA, MatchSpec, []). trace_func(MFA, MatchSpec, Flags) -> get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA, MatchSpec, Flags]}}, Res = receive - {apply_result,Result} -> Result - end, + {apply_result,Result} -> Result + end, ok = io:format("trace_pattern(~p, ~p, ~p) -> ~p", [MFA,MatchSpec,Flags,Res]), Res. trace_pid(Pid, On, Flags) -> get(tracer) ! {apply,self(),{erlang,trace,[Pid,On,Flags]}}, Res = receive - {apply_result,Result} -> Result - end, + {apply_result,Result} -> Result + end, ok = io:format("trace(~p, ~p, ~p) -> ~p", [Pid,On,Flags,Res]), Res. @@ -1309,19 +1294,19 @@ tracer(RelayTo) -> tracer_loop(RelayTo) -> receive - {apply,From,{M,F,A}} -> - From ! {apply_result,apply(M, F, A)}, - tracer_loop(RelayTo); - Msg -> - RelayTo ! Msg, - tracer_loop(RelayTo) + {apply,From,{M,F,A}} -> + From ! {apply_result,apply(M, F, A)}, + tracer_loop(RelayTo); + Msg -> + RelayTo ! Msg, + tracer_loop(RelayTo) end. id(I) -> I. deep(N, Class, Reason) -> try ?MODULE:deep_1(N, Class, Reason) of - Value -> {value,Value} + Value -> {value,Value} catch C:R -> {C,R} end. @@ -1338,30 +1323,30 @@ deep_3(Class, Reason) -> deep_4(CR) -> case ?MODULE:id(CR) of - {exit,[Reason]} -> - erlang:exit(Reason); - {throw,[Reason]} -> - erlang:throw(Reason); - {error,[Reason,Arglist]} -> - erlang:error(Reason, Arglist); - {error,[Reason]} -> - erlang:error(Reason); - {id,[Reason]} -> - Reason; - {reverse,[A,B]} -> - lists:reverse(A, B); - {append,[A,B]} -> - A ++ B; - {apply,[Fun,Args]} -> - erlang:apply(Fun, Args); - {apply,[M,F,Args]} -> - erlang:apply(M, F, Args); - {deep_5,[A,B]} -> - ?MODULE:deep_5(A, B); - {deep_5,[A]} -> - ?MODULE:deep_5(A); - {'=',[A,B]} -> - A = B + {exit,[Reason]} -> + erlang:exit(Reason); + {throw,[Reason]} -> + erlang:throw(Reason); + {error,[Reason,Arglist]} -> + erlang:error(Reason, Arglist); + {error,[Reason]} -> + erlang:error(Reason); + {id,[Reason]} -> + Reason; + {reverse,[A,B]} -> + lists:reverse(A, B); + {append,[A,B]} -> + A ++ B; + {apply,[Fun,Args]} -> + erlang:apply(Fun, Args); + {apply,[M,F,Args]} -> + erlang:apply(M, F, Args); + {deep_5,[A,B]} -> + ?MODULE:deep_5(A, B); + {deep_5,[A]} -> + ?MODULE:deep_5(A); + {'=',[A,B]} -> + A = B end. deep_5(A) when is_integer(A) -> @@ -1369,9 +1354,9 @@ deep_5(A) when is_integer(A) -> flush() -> receive X -> - [X|flush()] + [X|flush()] after 1000 -> - [] + [] end. %% Abbreviate large complex terms @@ -1394,10 +1379,10 @@ abbr_tuple(_, _, _, R) -> %% abbr_list(_, 0, R) -> case io_lib:printable_list(R) of - true -> - reverse(R, "..."); - false -> - reverse(R, '...') + true -> + reverse(R, "..."); + false -> + reverse(R, '...') end; abbr_list([H|T], N, R) -> M = N-1, |