aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-08-06 15:16:01 +0200
committerLoïc Hoguin <[email protected]>2018-08-06 15:16:01 +0200
commit29d347bf5bed001ae8d8763e6af53950c190de40 (patch)
tree347663d67e47ced5994fbeb5ad5bdd68330a7a29
parent820456b71fd3ce61df9d5f32280f42cf871ea80b (diff)
downloadgun-29d347bf5bed001ae8d8763e6af53950c190de40.tar.gz
gun-29d347bf5bed001ae8d8763e6af53950c190de40.tar.bz2
gun-29d347bf5bed001ae8d8763e6af53950c190de40.zip
Rewrite the SSE suite using Cowboy
-rw-r--r--Makefile3
-rw-r--r--test/gun_ct_hook.erl2
-rw-r--r--test/gun_test.erl24
-rw-r--r--test/handlers/sse_clock_h.erl21
-rw-r--r--test/sse_SUITE.erl44
5 files changed, 82 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index 3f11643..53c6417 100644
--- a/Makefile
+++ b/Makefile
@@ -17,8 +17,9 @@ dep_cowlib = git https://github.com/ninenines/cowlib 2.5.1
DOC_DEPS = asciideck
-TEST_DEPS = $(if $(CI_ERLANG_MK),ci.erlang.mk) ct_helper
+TEST_DEPS = $(if $(CI_ERLANG_MK),ci.erlang.mk) ct_helper cowboy
dep_ct_helper = git https://github.com/extend/ct_helper.git master
+dep_cowboy_commit = master
# CI configuration.
diff --git a/test/gun_ct_hook.erl b/test/gun_ct_hook.erl
index bf71530..8a2f0a5 100644
--- a/test/gun_ct_hook.erl
+++ b/test/gun_ct_hook.erl
@@ -17,6 +17,6 @@
-export([init/2]).
init(_, _) ->
- ct_helper:start([gun]),
+ ct_helper:start([cowboy, gun]),
ct_helper:make_certs_in_ets(),
{ok, undefined}.
diff --git a/test/gun_test.erl b/test/gun_test.erl
new file mode 100644
index 0000000..4e9aedd
--- /dev/null
+++ b/test/gun_test.erl
@@ -0,0 +1,24 @@
+%% Copyright (c) 2018, 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(gun_test).
+-compile(export_all).
+-compile(nowarn_export_all).
+
+%% Cowboy listeners.
+
+init_cowboy_tls(Ref, ProtoOpts, Config) ->
+ Opts = ct_helper:get_certs_from_ets(),
+ {ok, _} = cowboy:start_tls(Ref, Opts ++ [{port, 0}], ProtoOpts),
+ [{ref, Ref}, {port, ranch:get_port(Ref)}|Config].
diff --git a/test/handlers/sse_clock_h.erl b/test/handlers/sse_clock_h.erl
new file mode 100644
index 0000000..23b834f
--- /dev/null
+++ b/test/handlers/sse_clock_h.erl
@@ -0,0 +1,21 @@
+%% This module implements a loop handler that sends
+%% the current time every second using SSE.
+
+-module(sse_clock_h).
+
+-export([init/2]).
+-export([info/3]).
+
+init(Req, State) ->
+ self() ! timeout,
+ {cowboy_loop, cowboy_req:stream_reply(200, #{
+ <<"content-type">> => <<"text/event-stream">>
+ }, Req), State}.
+
+info(timeout, Req, State) ->
+ erlang:send_after(1000, self(), timeout),
+ Time = calendar:system_time_to_rfc3339(erlang:system_time(second)),
+ cowboy_req:stream_events(#{
+ data => Time
+ }, nofin, Req),
+ {ok, Req, State}.
diff --git a/test/sse_SUITE.erl b/test/sse_SUITE.erl
index d9ffeda..ce4dae3 100644
--- a/test/sse_SUITE.erl
+++ b/test/sse_SUITE.erl
@@ -16,19 +16,37 @@
-compile(export_all).
-compile(nowarn_export_all).
+-import(ct_helper, [config/2]).
+
all() ->
[http, http2].
-http(_) ->
- {ok, Pid} = gun:open("sse.now.sh", 443, #{
+init_per_suite(Config) ->
+ gun_test:init_cowboy_tls(?MODULE, #{
+ env => #{dispatch => cowboy_router:compile(init_routes())}
+ }, Config).
+
+end_per_suite(Config) ->
+ cowboy:stop_listener(config(ref, Config)).
+
+init_routes() -> [
+ {"localhost", [
+ {"/", sse_clock_h, []}
+ ]}
+].
+
+http(Config) ->
+ {ok, Pid} = gun:open("localhost", config(port, Config), #{
+ transport => tls,
protocols => [http],
http_opts => #{content_handlers => [gun_sse_h, gun_data_h]}
}),
{ok, http} = gun:await_up(Pid),
common(Pid).
-http2(_) ->
- {ok, Pid} = gun:open("sse.now.sh", 443, #{
+http2(Config) ->
+ {ok, Pid} = gun:open("localhost", config(port, Config), #{
+ transport => tls,
protocols => [http2],
http2_opts => #{content_handlers => [gun_sse_h, gun_data_h]}
}),
@@ -37,23 +55,29 @@ http2(_) ->
common(Pid) ->
Ref = gun:get(Pid, "/", [
- {<<"host">>, <<"sse.now.sh">>},
+ {<<"host">>, <<"localhost">>},
{<<"accept">>, <<"text/event-stream">>}
]),
receive
- {gun_response, Pid, Ref, nofin, Status, Headers} ->
- ct:print("response ~p ~p", [Status, Headers]),
+ {gun_response, Pid, Ref, nofin, 200, Headers} ->
+ {_, <<"text/event-stream">>}
+ = lists:keyfind(<<"content-type">>, 1, Headers),
event_loop(Pid, Ref, 3)
after 5000 ->
error(timeout)
end.
-event_loop(_, _, 0) ->
- ok;
+event_loop(Pid, _, 0) ->
+ gun:close(Pid);
event_loop(Pid, Ref, N) ->
receive
{gun_sse, Pid, Ref, Event} ->
- ct:print("event ~p", [Event]),
+ #{
+ last_event_id := <<>>,
+ event_type := <<"message">>,
+ data := Data
+ } = Event,
+ true = is_list(Data) orelse is_binary(Data),
event_loop(Pid, Ref, N - 1)
after 10000 ->
error(timeout)