diff options
Diffstat (limited to 'test/handlers')
-rw-r--r-- | test/handlers/content_types_provided_h.erl | 5 | ||||
-rw-r--r-- | test/handlers/crash_h.erl | 3 | ||||
-rw-r--r-- | test/handlers/read_body_h.erl | 15 | ||||
-rw-r--r-- | test/handlers/resp_h.erl | 17 | ||||
-rw-r--r-- | test/handlers/stream_hello_h.erl | 15 | ||||
-rw-r--r-- | test/handlers/ws_ignore.erl | 20 | ||||
-rw-r--r-- | test/handlers/ws_set_options_commands_h.erl | 19 | ||||
-rw-r--r-- | test/handlers/wt_echo_h.erl | 103 |
8 files changed, 193 insertions, 4 deletions
diff --git a/test/handlers/content_types_provided_h.erl b/test/handlers/content_types_provided_h.erl index 5220c19..397026b 100644 --- a/test/handlers/content_types_provided_h.erl +++ b/test/handlers/content_types_provided_h.erl @@ -11,9 +11,14 @@ init(Req, Opts) -> {cowboy_rest, Req, Opts}. +content_types_provided(Req=#{qs := <<"invalid-type">>}, State) -> + ct_helper:ignore(cowboy_rest, normalize_content_types, 2), + {[{{'*', '*', '*'}, get_text_plain}], Req, State}; content_types_provided(Req=#{qs := <<"wildcard-param">>}, State) -> {[{{<<"text">>, <<"plain">>, '*'}, get_text_plain}], Req, State}. +get_text_plain(Req=#{qs := <<"invalid-type">>}, State) -> + {<<"invalid-type">>, Req, State}; get_text_plain(Req=#{qs := <<"wildcard-param">>}, State) -> {_, _, Param} = maps:get(media_type, Req), Body = if diff --git a/test/handlers/crash_h.erl b/test/handlers/crash_h.erl index b687aba..57d4d85 100644 --- a/test/handlers/crash_h.erl +++ b/test/handlers/crash_h.erl @@ -7,6 +7,9 @@ -export([init/2]). -spec init(_, _) -> no_return(). +init(_, external_exit) -> + ct_helper:ignore(?MODULE, init, 2), + exit(self(), ct_helper_ignore); init(_, no_reply) -> ct_helper:ignore(?MODULE, init, 2), error(crash); diff --git a/test/handlers/read_body_h.erl b/test/handlers/read_body_h.erl new file mode 100644 index 0000000..a0de3b3 --- /dev/null +++ b/test/handlers/read_body_h.erl @@ -0,0 +1,15 @@ +%% This module reads the request body fully and send a 204 response. + +-module(read_body_h). + +-export([init/2]). + +init(Req0, Opts) -> + {ok, Req} = read_body(Req0), + {ok, cowboy_req:reply(200, #{}, Req), Opts}. + +read_body(Req0) -> + case cowboy_req:read_body(Req0) of + {ok, _, Req} -> {ok, Req}; + {more, _, Req} -> read_body(Req) + end. diff --git a/test/handlers/resp_h.erl b/test/handlers/resp_h.erl index aae9eb9..d1c46e0 100644 --- a/test/handlers/resp_h.erl +++ b/test/handlers/resp_h.erl @@ -43,12 +43,27 @@ do(<<"set_resp_headers">>, Req0, Opts) -> <<"content-encoding">> => <<"compress">> }, Req0), {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"set_resp_headers_list">>, Req0, Opts) -> + Req = cowboy_req:set_resp_headers([ + {<<"content-type">>, <<"text/plain">>}, + {<<"test-header">>, <<"one">>}, + {<<"content-encoding">>, <<"compress">>}, + {<<"test-header">>, <<"two">>} + ], Req0), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; do(<<"set_resp_headers_cookie">>, Req0, Opts) -> ct_helper:ignore(cowboy_req, set_resp_headers, 2), Req = cowboy_req:set_resp_headers(#{ <<"set-cookie">> => <<"name=value">> }, Req0), {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"set_resp_headers_list_cookie">>, Req0, Opts) -> + ct_helper:ignore(cowboy_req, set_resp_headers_list, 3), + Req = cowboy_req:set_resp_headers([ + {<<"set-cookie">>, <<"name=value">>}, + {<<"set-cookie">>, <<"name2=value2">>} + ], Req0), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; do(<<"set_resp_headers_http11">>, Req0, Opts) -> Req = cowboy_req:set_resp_headers(#{ <<"connection">> => <<"custom-header, close">>, @@ -182,6 +197,7 @@ do(<<"reply2">>, Req0, Opts) -> <<"twice">> -> ct_helper:ignore(cowboy_req, reply, 4), Req1 = cowboy_req:reply(200, Req0), + timer:sleep(100), cowboy_req:reply(200, Req1); Status -> cowboy_req:reply(binary_to_integer(Status), Req0) @@ -245,6 +261,7 @@ do(<<"stream_reply2">>, Req0, Opts) -> <<"twice">> -> ct_helper:ignore(cowboy_req, stream_reply, 3), Req1 = cowboy_req:stream_reply(200, Req0), + timer:sleep(100), %% We will crash here so the body shouldn't be sent. Req = cowboy_req:stream_reply(200, Req1), stream_body(Req), diff --git a/test/handlers/stream_hello_h.erl b/test/handlers/stream_hello_h.erl new file mode 100644 index 0000000..e67e220 --- /dev/null +++ b/test/handlers/stream_hello_h.erl @@ -0,0 +1,15 @@ +%% This module is the fastest way of producing a Hello world! + +-module(stream_hello_h). + +-export([init/3]). +-export([terminate/3]). + +init(_, _, State) -> + {[ + {response, 200, #{<<"content-length">> => <<"12">>}, <<"Hello world!">>}, + stop + ], State}. + +terminate(_, _, _) -> + ok. diff --git a/test/handlers/ws_ignore.erl b/test/handlers/ws_ignore.erl new file mode 100644 index 0000000..9fe3322 --- /dev/null +++ b/test/handlers/ws_ignore.erl @@ -0,0 +1,20 @@ +%% Feel free to use, reuse and abuse the code in this file. + +-module(ws_ignore). + +-export([init/2]). +-export([websocket_handle/2]). +-export([websocket_info/2]). + +init(Req, _) -> + {cowboy_websocket, Req, undefined, #{ + compress => true + }}. + +websocket_handle({text, <<"CHECK">>}, State) -> + {[{text, <<"CHECK">>}], State}; +websocket_handle(_Frame, State) -> + {[], State}. + +websocket_info(_Info, State) -> + {[], State}. diff --git a/test/handlers/ws_set_options_commands_h.erl b/test/handlers/ws_set_options_commands_h.erl index 88d4e72..1ab0af4 100644 --- a/test/handlers/ws_set_options_commands_h.erl +++ b/test/handlers/ws_set_options_commands_h.erl @@ -11,10 +11,21 @@ init(Req, RunOrHibernate) -> {cowboy_websocket, Req, RunOrHibernate, #{idle_timeout => infinity}}. -websocket_handle(Frame={text, <<"idle_timeout_short">>}, State=run) -> - {[{set_options, #{idle_timeout => 500}}, Frame], State}; -websocket_handle(Frame={text, <<"idle_timeout_short">>}, State=hibernate) -> - {[{set_options, #{idle_timeout => 500}}, Frame], State, hibernate}. +%% Set the idle_timeout option dynamically. +websocket_handle({text, <<"idle_timeout_short">>}, State=run) -> + {[{set_options, #{idle_timeout => 500}}], State}; +websocket_handle({text, <<"idle_timeout_short">>}, State=hibernate) -> + {[{set_options, #{idle_timeout => 500}}], State, hibernate}; +%% Set the max_frame_size option dynamically. +websocket_handle({text, <<"max_frame_size_small">>}, State=run) -> + {[{set_options, #{max_frame_size => 1000}}], State}; +websocket_handle({text, <<"max_frame_size_small">>}, State=hibernate) -> + {[{set_options, #{max_frame_size => 1000}}], State, hibernate}; +%% We just echo binary frames. +websocket_handle(Frame={binary, _}, State=run) -> + {[Frame], State}; +websocket_handle(Frame={binary, _}, State=hibernate) -> + {[Frame], State, hibernate}. websocket_info(_Info, State) -> {[], State}. diff --git a/test/handlers/wt_echo_h.erl b/test/handlers/wt_echo_h.erl new file mode 100644 index 0000000..5198565 --- /dev/null +++ b/test/handlers/wt_echo_h.erl @@ -0,0 +1,103 @@ +%% This module echoes client events back, +%% including creating new streams. + +-module(wt_echo_h). +-behavior(cowboy_webtransport). + +-export([init/2]). +-export([webtransport_handle/2]). +-export([webtransport_info/2]). +-export([terminate/3]). + +%% -define(DEBUG, 1). +-ifdef(DEBUG). +-define(LOG(Fmt, Args), ct:pal(Fmt, Args)). +-else. +-define(LOG(Fmt, Args), _ = Fmt, _ = Args, ok). +-endif. + +init(Req0, _) -> + ?LOG("WT init ~p~n", [Req0]), + Req = case cowboy_req:parse_header(<<"wt-available-protocols">>, Req0) of + undefined -> + Req0; + [Protocol|_] -> + cowboy_req:set_resp_header(<<"wt-protocol">>, cow_http_hd:wt_protocol(Protocol), Req0) + end, + {cowboy_webtransport, Req, #{}}. + +webtransport_handle(Event = {stream_open, StreamID, bidi}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + {[], Streams#{StreamID => bidi}}; +webtransport_handle(Event = {stream_open, StreamID, unidi}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + OpenStreamRef = make_ref(), + {[{open_stream, OpenStreamRef, unidi, <<>>}], Streams#{ + StreamID => {unidi_remote, OpenStreamRef}, + OpenStreamRef => {unidi_local, StreamID}}}; +webtransport_handle(Event = {opened_stream_id, OpenStreamRef, OpenStreamID}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + case Streams of + #{OpenStreamRef := bidi} -> + {[], maps:remove(OpenStreamRef, Streams#{ + OpenStreamID => bidi + })}; + #{OpenStreamRef := {unidi_local, RemoteStreamID}} -> + #{RemoteStreamID := {unidi_remote, OpenStreamRef}} = Streams, + {[], maps:remove(OpenStreamRef, Streams#{ + RemoteStreamID => {unidi_remote, OpenStreamID}, + OpenStreamID => {unidi_local, RemoteStreamID} + })} + end; +webtransport_handle(Event = {stream_data, StreamID, _IsFin, <<"TEST:", Test/bits>>}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + case Test of + <<"open_bidi">> -> + OpenStreamRef = make_ref(), + {[{open_stream, OpenStreamRef, bidi, <<>>}], + Streams#{OpenStreamRef => bidi}}; + <<"initiate_close">> -> + {[initiate_close], Streams}; + <<"close">> -> + {[close], Streams}; + <<"close_app_code">> -> + {[{close, 1234567890}], Streams}; + <<"close_app_code_msg">> -> + {[{close, 1234567890, <<"onetwothreefourfivesixseveneightnineten">>}], Streams}; + <<"event_pid:", EventPidBin/bits>> -> + {[{send, StreamID, nofin, <<"event_pid_received">>}], + Streams#{event_pid => binary_to_term(EventPidBin)}} + end; +webtransport_handle(Event = {stream_data, StreamID, IsFin, Data}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + case Streams of + #{StreamID := bidi} -> + {[{send, StreamID, IsFin, Data}], Streams}; + #{StreamID := {unidi_remote, Ref}} when is_reference(Ref) -> + %% The stream isn't ready. We try again later. + erlang:send_after(100, self(), {try_again, Event}), + {[], Streams}; + #{StreamID := {unidi_remote, LocalStreamID}} -> + {[{send, LocalStreamID, IsFin, Data}], Streams} + end; +webtransport_handle(Event = {datagram, Data}, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + {[{send, datagram, Data}], Streams}; +webtransport_handle(Event = close_initiated, Streams) -> + ?LOG("WT handle ~p~n", [Event]), + {[{send, datagram, <<"TEST:close_initiated">>}], Streams}; +webtransport_handle(Event, Streams) -> + ?LOG("WT handle ignore ~p~n", [Event]), + {[], Streams}. + +webtransport_info({try_again, Event}, Streams) -> + ?LOG("WT try_again ~p", [Event]), + webtransport_handle(Event, Streams). + +terminate(Reason, Req, State=#{event_pid := EventPid}) -> + ?LOG("WT terminate ~0p~n~0p~n~0p", [Reason, Req, State]), + EventPid ! {'$wt_echo_h', terminate, Reason, Req, State}, + ok; +terminate(Reason, Req, State) -> + ?LOG("WT terminate ~0p~n~0p~n~0p", [Reason, Req, State]), + ok. |