diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | test/cowboy_ct_hook.erl | 22 | ||||
-rw-r--r-- | test/cowboy_error_h.erl | 92 | ||||
-rw-r--r-- | test/http_SUITE_data/http_errors.erl | 12 | ||||
-rw-r--r-- | test/http_SUITE_data/rest_missing_callbacks.erl | 2 | ||||
-rw-r--r-- | test/http_SUITE_data/rest_resource_etags.erl | 2 |
6 files changed, 124 insertions, 7 deletions
@@ -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. diff --git a/test/cowboy_ct_hook.erl b/test/cowboy_ct_hook.erl new file mode 100644 index 0000000..5eb0587 --- /dev/null +++ b/test/cowboy_ct_hook.erl @@ -0,0 +1,22 @@ +%% Copyright (c) 2014, Loïc Hoguin <[email protected]> +%% +%% 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}. diff --git a/test/cowboy_error_h.erl b/test/cowboy_error_h.erl new file mode 100644 index 0000000..fe79645 --- /dev/null +++ b/test/cowboy_error_h.erl @@ -0,0 +1,92 @@ +%% Copyright (c) 2014, Loïc Hoguin <[email protected]> +%% +%% 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). diff --git a/test/http_SUITE_data/http_errors.erl b/test/http_SUITE_data/http_errors.erl index 8831362..35ac3bd 100644 --- a/test/http_SUITE_data/http_errors.erl +++ b/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). diff --git a/test/http_SUITE_data/rest_missing_callbacks.erl b/test/http_SUITE_data/rest_missing_callbacks.erl index 171c856..94bfbbd 100644 --- a/test/http_SUITE_data/rest_missing_callbacks.erl +++ b/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}. diff --git a/test/http_SUITE_data/rest_resource_etags.erl b/test/http_SUITE_data/rest_resource_etags.erl index 43f1e05..2652f57 100644 --- a/test/http_SUITE_data/rest_resource_etags.erl +++ b/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. |