Browse Source

Silence expected test error reports from the console output

The errors are still logged by common_test to the report it creates.
The process that is going to crash has to call cowboy_error_h:ignore/3
with the MFA where the crash is expected to occur for it to be ignored.
Gun retry failures are also ignored. Only unexpected crashes are printed.
Loïc Hoguin 11 years ago
parent
commit
75218c4be0

+ 1 - 0
Makefile

@@ -8,6 +8,7 @@ ERLC_OPTS ?= -Werror +debug_info +warn_export_all +warn_export_vars \
 	+warn_shadow_vars +warn_obsolete_guard +warn_missing_spec
 COMPILE_FIRST = cowboy_middleware cowboy_sub_protocol
 CT_SUITES = eunit http spdy ws
+CT_OPTS += -pa test -ct_hooks cowboy_ct_hook []
 PLT_APPS = crypto public_key ssl
 
 # Dependencies.

+ 22 - 0
test/cowboy_ct_hook.erl

@@ -0,0 +1,22 @@
+%% Copyright (c) 2014, Loïc Hoguin <essen@ninenines.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(cowboy_ct_hook).
+
+-export([init/2]).
+
+init(_, _) ->
+	error_logger:tty(false),
+	error_logger:add_report_handler(cowboy_error_h),
+	{ok, undefined}.

+ 92 - 0
test/cowboy_error_h.erl

@@ -0,0 +1,92 @@
+%% Copyright (c) 2014, Loïc Hoguin <essen@ninenines.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(cowboy_error_h).
+-behaviour(gen_event).
+
+%% Public interface.
+-export([ignore/3]).
+
+%% gen_event.
+-export([init/1]).
+-export([handle_event/2]).
+-export([handle_call/2]).
+-export([handle_info/2]).
+-export([terminate/2]).
+-export([code_change/3]).
+
+%% Public interface.
+
+%% Ignore crashes from Pid occuring in M:F/A.
+ignore(M, F, A) ->
+	gen_event:call(error_logger, ?MODULE, {expect, self(), M, F, A}).
+
+%% gen_event.
+
+init(_) ->
+	{ok, []}.
+
+%% Ignore supervisor and progress reports.
+handle_event({info_report, _, {_, progress, _}}, State) ->
+	{ok, State};
+handle_event({info_report, _, {_, std_info, _}}, State) ->
+	{ok, State};
+handle_event({error_report, _, {_, supervisor_report, _}}, State) ->
+	{ok, State};
+%% Ignore gun retry failures.
+handle_event({error_report, _, {_, crash_report,
+		[[{initial_call, {gun, init, _}}, _, _,
+			{error_info, {error, gone, _}}|_]|_]}},
+		State) ->
+	{ok, State};
+%% Ignore emulator reports, they are a duplicate of what Ranch gives us.
+handle_event({error, _, {emulator, _, _}}, State) ->
+	{ok, State};
+handle_event(Event = {error, GL,
+		{_, "Ranch listener" ++ _, [_, _, Pid, {[_, _,
+			{stacktrace, [{M, F, A, _}|_]}|_], _}]}},
+		State) when node(GL) =:= node() ->
+	A2 = if is_list(A) -> length(A); true -> A end,
+	Crash = {Pid, M, F, A2},
+	case lists:member(Crash, State) of
+		true ->
+			{ok, lists:delete(Crash, State)};
+		false ->
+			write_event(Event),
+			{ok, State}
+	end;
+handle_event(Event = {_, GL, _}, State) when node(GL) =:= node() ->
+	write_event(Event),
+	{ok, State};
+handle_event(_, State) ->
+	{ok, State}.
+
+handle_call({expect, Pid, M, F, A}, State) ->
+	{ok, ok, [{Pid, M, F, A}|State]};
+handle_call(_, State) ->
+	{ok, {error, bad_query}, State}.
+
+handle_info(_, State) ->
+	{ok, State}.
+
+terminate(_, _) ->
+	ok.
+
+code_change(_, State, _) ->
+	{ok, State}.
+
+write_event(Event) ->
+	error_logger_tty_h:write_event(
+		{erlang:universaltime(), Event},
+		io).

+ 5 - 7
test/http_SUITE_data/http_errors.erl

@@ -9,30 +9,28 @@ init({_Transport, http}, Req, _Opts) ->
     case_init(Case, Req1).
 
 case_init(<<"init_before_reply">> = Case, _Req) ->
+	cowboy_error_h:ignore(?MODULE, case_init, 2),
     erlang:error(Case);
-
 case_init(<<"init_after_reply">> = Case, Req) ->
+	cowboy_error_h:ignore(?MODULE, case_init, 2),
     {ok, _Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
     erlang:error(Case);
-
 case_init(<<"init_reply_handle_error">> = Case, Req) ->
     {ok, Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
     {ok, Req1, Case};
-
 case_init(<<"handle_before_reply">> = Case, Req) ->
     {ok, Req, Case};
-
 case_init(<<"handle_after_reply">> = Case, Req) ->
     {ok, Req, Case}.
 
-
 handle(_Req, <<"init_reply_handle_error">> = Case) ->
+	cowboy_error_h:ignore(?MODULE, handle, 2),
     erlang:error(Case);
-
 handle(_Req, <<"handle_before_reply">> = Case) ->
+	cowboy_error_h:ignore(?MODULE, handle, 2),
     erlang:error(Case);
-
 handle(Req, <<"handle_after_reply">> = Case) ->
+	cowboy_error_h:ignore(?MODULE, handle, 2),
     {ok, _Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
     erlang:error(Case).
 

+ 2 - 0
test/http_SUITE_data/rest_missing_callbacks.erl

@@ -11,11 +11,13 @@ allowed_methods(Req, State) ->
 	{[<<"GET">>, <<"PUT">>], Req, State}.
 
 content_types_accepted(Req, State) ->
+	cowboy_error_h:ignore(cowboy_rest, process_content_type, 3),
 	{[
 		{<<"application/json">>, put_application_json}
 	], Req, State}.
 
 content_types_provided(Req, State) ->
+	cowboy_error_h:ignore(cowboy_rest, set_resp_body, 2),
 	{[
 		{<<"text/plain">>, get_text_plain}
 	], Req, State}.

+ 2 - 0
test/http_SUITE_data/rest_resource_etags.erl

@@ -18,8 +18,10 @@ generate_etag(Req, State) ->
 			{<<"\"etag-header-value\"">>, Req2, State};
 		%% Invalid return values from generate_etag/2.
 		{<<"binary-strong-unquoted">>, Req2} ->
+			cowboy_error_h:ignore(cowboy_http, quoted_string, 2),
 			{<<"etag-header-value">>, Req2, State};
 		{<<"binary-weak-unquoted">>, Req2} ->
+			cowboy_error_h:ignore(cowboy_http, quoted_string, 2),
 			{<<"W/etag-header-value">>, Req2, State}
 	end.