From fea574bac8464f07a72862e1a4f92e9b62e464e4 Mon Sep 17 00:00:00 2001 From: Klas Johansson Date: Sun, 12 Feb 2012 18:24:53 +0100 Subject: 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. --- lib/eunit/src/eunit_lib.erl | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'lib') 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 -- cgit v1.2.3