Skip to content

Commit

Permalink
eunit: Do not call erlang:get_stacktrace()
Browse files Browse the repository at this point in the history
  • Loading branch information
uabboli authored and richcarl committed Feb 1, 2025
1 parent 8d37e87 commit 9df611d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/eunit_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ format_exception_test_() ->
"\nymmud:rorre"++_,
lists:reverse(lists:flatten(
format_exception(try erlang:error(dummy)
catch C:R -> {C, R, erlang:get_stacktrace()}
catch C:R:S -> {C, R, S}
end)))),
?_assertMatch(
"\nymmud:rorre"++_,
lists:reverse(lists:flatten(
format_exception(try erlang:error(dummy, [a])
catch C:R -> {C, R, erlang:get_stacktrace()}
catch C:R:S -> {C, R, S}
end))))].
-endif.

Expand Down
3 changes: 1 addition & 2 deletions src/eunit_listener.erl
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ call(F, As, St) when is_atom(F) ->
try apply(St#state.callback, F, As) of
Substate -> St#state{state = Substate}
catch
Class:Term ->
Trace = erlang:get_stacktrace(),
Class:Term:Trace ->
if F =/= terminate ->
call(terminate, [{error, {Class, Term, Trace}},
St#state.state], St);
Expand Down
2 changes: 1 addition & 1 deletion src/eunit_proc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ io_request({put_chars, M, F, As}, Buf) ->
try apply(M, F, As) of
Chars -> {ok, [Chars | Buf]}
catch
C:T -> {{error, {C,T,erlang:get_stacktrace()}}, Buf}
C:T:S -> {{error, {C,T,S}}, Buf}
end;
io_request({put_chars, _Enc, Chars}, Buf) ->
io_request({put_chars, Chars}, Buf);
Expand Down
51 changes: 27 additions & 24 deletions src/eunit_test.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
%% somewhat, but you can't have everything.) Note that we assume that
%% this particular module is the boundary between eunit and user code.

get_stacktrace() ->
get_stacktrace([]).
get_stacktrace(Trace) ->
get_stacktrace(Trace, []).

get_stacktrace(Ts) ->
eunit_lib:uniq(prune_trace(erlang:get_stacktrace(), Ts)).
get_stacktrace(Trace, Ts) ->
eunit_lib:uniq(prune_trace(Trace, Ts)).

-dialyzer({no_match, prune_trace/2}).
prune_trace([{eunit_data, _, _} | Rest], Tail) ->
Expand Down Expand Up @@ -75,8 +75,8 @@ run_testfun(F) ->
{eunit_internal, Term} ->
%% Internally generated: re-throw Term (lose the trace)
throw(Term);
Class:Reason ->
{error, {Class, Reason, get_stacktrace()}}
Class:Reason:Trace ->
{error, {Class, Reason, Trace}}
end.


Expand Down Expand Up @@ -272,7 +272,7 @@ mf_wrapper(M, F) ->
fun () ->
try M:F()
catch
error:undef ->
error:undef:Trace ->
%% Check if it was M:F/0 that was undefined
case erlang:module_loaded(M) of
false ->
Expand All @@ -282,14 +282,14 @@ mf_wrapper(M, F) ->
false ->
fail({no_such_function, {M,F,0}});
true ->
rethrow(error, undef, [{M,F,0}])
rethrow(error, undef, Trace, [{M,F,0}])
end
end
end
end.

rethrow(Class, Reason, Trace) ->
erlang:raise(Class, Reason, get_stacktrace(Trace)).
rethrow(Class, Reason, Trace, Ts) ->
erlang:raise(Class, Reason, get_stacktrace(Trace, Ts)).

fail(Term) ->
throw({eunit_internal, Term}).
Expand Down Expand Up @@ -332,12 +332,14 @@ enter_context(Setup, Cleanup, Instantiate, Callback) ->
T ->
case eunit_lib:is_not_test(T) of
true ->
catch throw(error), % generate a stack trace
{_, Stacktrace} =
erlang:process_info(self(),
current_stacktrace),
{module,M} = erlang:fun_info(Instantiate, module),
{name,N} = erlang:fun_info(Instantiate, name),
{arity,A} = erlang:fun_info(Instantiate, arity),
context_error({bad_instantiator, {{M,N,A},T}},
error, badarg);
error, Stacktrace, badarg);
false ->
ok
end,
Expand All @@ -346,21 +348,22 @@ enter_context(Setup, Cleanup, Instantiate, Callback) ->
%% Always run cleanup; client may be an idiot
try Cleanup(R)
catch
Class:Term ->
context_error(cleanup_failed, Class, Term)
Class:Term:Trace ->
context_error(cleanup_failed,
Class, Trace, Term)
end
end
catch
Class:Term ->
context_error(instantiation_failed, Class, Term)
Class:Term:Trace ->
context_error(instantiation_failed, Class, Trace, Term)
end
catch
Class:Term ->
context_error(setup_failed, Class, Term)
Class:Term:Trace ->
context_error(setup_failed, Class, Trace, Term)
end.

context_error(Type, Class, Term) ->
throw({context_error, Type, {Class, Term, get_stacktrace()}}).
context_error(Type, Class, Trace, Term) ->
throw({context_error, Type, {Class, Term, get_stacktrace(Trace)}}).

%% This generates single setup/cleanup functions from a list of tuples
%% on the form {Tag, Setup, Cleanup}, where the setup function always
Expand All @@ -378,8 +381,8 @@ multi_setup([{Tag, S, C} | Es], CleanupPrev) ->
try C(R) of
_ -> CleanupPrev(Rs)
catch
Class:Term ->
throw({Tag, {Class, Term, get_stacktrace()}})
Class:Term:Trace ->
throw({Tag, {Class, Term, Trace}})
end
end,
{SetupRest, CleanupAll} = multi_setup(Es, Cleanup),
Expand All @@ -388,9 +391,9 @@ multi_setup([{Tag, S, C} | Es], CleanupPrev) ->
R ->
SetupRest([R|Rs])
catch
Class:Term ->
Class:Term:Trace ->
CleanupPrev(Rs),
throw({Tag, {Class, Term, get_stacktrace()}})
throw({Tag, {Class, Term, Trace}})
end
end,
CleanupAll};
Expand Down

0 comments on commit 9df611d

Please sign in to comment.