Browse Source

Test that warnings are logged

Viktor Söderqvist 10 years ago
parent
commit
c624359703
2 changed files with 98 additions and 2 deletions
  1. 91 0
      test/error_logger_acc.erl
  2. 7 2
      test/mysql_tests.erl

+ 91 - 0
test/error_logger_acc.erl

@@ -0,0 +1,91 @@
+%% @doc A error_logger report handler that be used to capture expected errors in
+%% tests. The current error report handlers are disabled during the execution
+%% of a function. Afterwards, they are restored and the errors that occered are
+%% returned along with the return value of the fun.
+-module(error_logger_acc).
+
+%% Public API
+-export([capture/1]).
+
+-behaviour(gen_event).
+-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2,
+         code_change/3]).
+
+%% @doc Executes `Fun' and captures all logged errors returns as well as
+%% uncaught errors in `Fun'.
+-spec capture(fun (() -> ResultOfFun)) ->
+    {ok, ResultOfFun, AccumulatedErrors} |
+    {throw | error | exit, Reason, Trace, AccumulatedErrors}
+  when ResultOfFun :: term(),
+       Reason :: term(),
+       Trace :: list(),
+       AccumulatedErrors :: [{error|warning_msg|info_msg, string()} |
+                             {error_report|warning_report|info_report, term()}].
+capture(Fun) when is_function(Fun, 0) ->
+    OldHandlers = gen_event:which_handlers(error_logger),
+    error_logger:add_report_handler(?MODULE),
+    lists:foreach(fun error_logger:delete_report_handler/1, OldHandlers),
+    try Fun() of
+        Result ->
+            lists:foreach(fun error_logger:add_report_handler/1, OldHandlers),
+            {ok, Result, error_logger:delete_report_handler(?MODULE)}
+    catch
+        Class:Error ->
+            Trace = erlang:get_stacktrace(),
+            lists:foreach(fun error_logger:add_report_handler/1, OldHandlers),
+            AccumulatedErrors = error_logger:delete_report_handler(?MODULE),
+            {Class, Error, Trace, AccumulatedErrors}
+    end.
+
+%% --- gen_event callbacks ---
+
+init([]) ->
+    {ok, []}.
+
+handle_event({ErrorType, _Gleader, {_Pid, Format, Data}}, State) ->
+    ShortError = if
+        ErrorType == error; ErrorType == warning_msg; ErrorType == info_msg ->
+            {ErrorType, lists:flatten(io_lib:format(Format, Data))};
+        true ->
+            {ErrorType, {Format, Data}}
+    end,
+    {ok, [ShortError | State]};
+handle_event(_OtherEvent, State) ->
+    {ok, State}.
+
+handle_call(_Call, State) ->
+    {ok, ignored, State}.
+
+handle_info(_Info, State) ->
+    {ok, State}.
+
+terminate([], State) ->
+    %% error_logger:delete_report_handler/1 called
+    lists:reverse(State);
+terminate(_Arg, _State) ->
+    %% terminating for some other reason.
+    error_logger:info_msg("Accumulating error handler shutting down"),
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+capture_success_test() ->
+    Result = ?MODULE:capture(fun () ->
+        error_logger:info_msg("Hello ~p", [world]),
+        error_logger:info_msg("Hello ~p", [again]),
+        foo
+    end),
+    ?assertEqual({ok, foo, [{info_msg, "Hello world"}, {info_msg, "Hello again"}]}, Result).
+
+capture_failure_test() ->
+    Result = ?MODULE:capture(fun () ->
+        error_logger:info_msg("Hello ~p", [world]),
+        throw(foo)
+    end),
+    ?assertMatch({throw, foo, _Trace, [{info_msg, "Hello world"}]}, Result).
+
+-endif.

+ 7 - 2
test/mysql_tests.erl

@@ -88,8 +88,13 @@ connect_with_db(_Pid) ->
                                   {database, "otptest"}]),
     ?assertMatch({ok, _, [[<<"otptest">>]]},
                  mysql:query(Pid, "SELECT DATABASE()")),
-    %% Check that we get a warning logged
-    ok = mysql:query(Pid, <<"DROP TABLE IF EXISTS dummy">>),
+    %% Capture error log to check that we get a warning logged
+    {ok, ok, LoggedErrors} = error_logger_acc:capture(fun () ->
+        mysql:query(Pid, <<"DROP TABLE IF EXISTS dummy">>)
+    end),
+    ?assertMatch([{_, "Note 1051: Unknown table 'dummy'\n"
+                      " in DROP TABLE IF EXISTS dummy" ++ _}],
+                 LoggedErrors),
     exit(Pid, normal).
 
 autocommit(Pid) ->