diff options
author | Klas Johansson <[email protected]> | 2012-02-12 18:24:53 +0100 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2012-08-10 10:57:21 +0200 |
commit | fea574bac8464f07a72862e1a4f92e9b62e464e4 (patch) | |
tree | ca94a13cafe1f338581e07f784ecb10d2c8db0ca | |
parent | 6f5900f9b136ae9aa6b89877727f6dac9e782ea6 (diff) | |
download | otp-fea574bac8464f07a72862e1a4f92e9b62e464e4.tar.gz otp-fea574bac8464f07a72862e1a4f92e9b62e464e4.tar.bz2 otp-fea574bac8464f07a72862e1a4f92e9b62e464e4.zip |
Make EUnit print stacktraces with location information
The format of stacktraces was changed in Erlang/OTP R15, adding location
information. This had the effect that EUnit did not recognize stack traces
as such and only printed the exception term. This patch makes Eunit
recognize and print the new stacktrace format as well as the old.
-rw-r--r-- | lib/eunit/src/eunit_lib.erl | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl index 1c41e229c5..c700989bae 100644 --- a/lib/eunit/src/eunit_lib.erl +++ b/lib/eunit/src/eunit_lib.erl @@ -86,6 +86,12 @@ analyze_exit_term(Term) -> is_stacktrace([]) -> true; +is_stacktrace([{M,F,A,L}|Fs]) + when is_atom(M), is_atom(F), is_integer(A), is_list(L) -> + is_stacktrace(Fs); +is_stacktrace([{M,F,As,L}|Fs]) + when is_atom(M), is_atom(F), is_list(As), is_list(L) -> + is_stacktrace(Fs); is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) -> is_stacktrace(Fs); is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), is_list(As) -> @@ -96,10 +102,11 @@ is_stacktrace(_) -> format_stacktrace(Trace) -> format_stacktrace(Trace, "in function", "in call from"). -format_stacktrace([{M,F,A}|Fs], Pre, Pre1) when is_integer(A) -> - [io_lib:fwrite(" ~s ~w:~w/~w\n", [Pre, M, F, A]) +format_stacktrace([{M,F,A,L}|Fs], Pre, Pre1) when is_integer(A) -> + [io_lib:fwrite(" ~s ~w:~w/~w~s\n", + [Pre, M, F, A, format_stacktrace_location(L)]) | format_stacktrace(Fs, Pre1, Pre1)]; -format_stacktrace([{M,F,As}|Fs], Pre, Pre1) when is_list(As) -> +format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) -> A = length(As), C = case is_op(M,F,A) of true when A =:= 1 -> @@ -112,12 +119,23 @@ format_stacktrace([{M,F,As}|Fs], Pre, Pre1) when is_list(As) -> false -> io_lib:fwrite("~w(~s)", [F,format_arglist(As)]) end, - [io_lib:fwrite(" ~s ~w:~w/~w\n called as ~s\n", - [Pre,M,F,A,C]) + [io_lib:fwrite(" ~s ~w:~w/~w~s\n called as ~s\n", + [Pre,M,F,A,format_stacktrace_location(L),C]) | format_stacktrace(Fs,Pre1,Pre1)]; +format_stacktrace([{M,F,As}|Fs], Pre, Pre1) -> + format_stacktrace([{M,F,As,[]}|Fs], Pre, Pre1); format_stacktrace([],_Pre,_Pre1) -> "". +format_stacktrace_location(Location) -> + File = proplists:get_value(file, Location), + Line = proplists:get_value(line, Location), + if File =/= undefined, Line =/= undefined -> + io_lib:format(" (~s, line ~w)", [File, Line]); + true -> + "" + end. + format_arg(A) -> io_lib:format("~P",[A,15]). @@ -166,6 +184,21 @@ error_msg(Title, Fmt, Args) -> Msg = io_lib:format("::"++Fmt, Args), % gets indentation right io_lib:fwrite("*** ~s ***\n~s\n\n", [Title, Msg]). +-ifdef(TEST). +format_exception_test_() -> + [?_assertMatch( + "error:dummy"++_, + lists:flatten( + format_exception(try erlang:error(dummy) + catch C:R -> {C, R, erlang:get_stacktrace()} + end))), + ?_assertMatch( + "error:dummy"++_, + lists:flatten( + format_exception(try erlang:error(dummy, [a]) + catch C:R -> {C, R, erlang:get_stacktrace()} + end)))]. +-endif. %% --------------------------------------------------------------------- %% Deep list iterator; accepts improper lists/sublists, and also accepts |