aboutsummaryrefslogtreecommitdiffstats
path: root/test/gun_test.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-01-03 22:12:42 +0100
committerLoïc Hoguin <[email protected]>2019-01-03 22:12:42 +0100
commitfbe58ec837cc3c84b08d701c82b95222738c775f (patch)
treed0c34202fefe8c7aa8edf12128f03c360c320bc1 /test/gun_test.erl
parent8a30f96cf19f9104e3ae8df5f85df33b66b5bfc2 (diff)
downloadgun-fbe58ec837cc3c84b08d701c82b95222738c775f.tar.gz
gun-fbe58ec837cc3c84b08d701c82b95222738c775f.tar.bz2
gun-fbe58ec837cc3c84b08d701c82b95222738c775f.zip
Consolidate origin server test helpers
Also fixes an issue with switch_transport introduced when converting the Gun process to gen_statem.
Diffstat (limited to 'test/gun_test.erl')
-rw-r--r--test/gun_test.erl84
1 files changed, 84 insertions, 0 deletions
diff --git a/test/gun_test.erl b/test/gun_test.erl
index 4e9aedd..11a04e3 100644
--- a/test/gun_test.erl
+++ b/test/gun_test.erl
@@ -16,9 +16,93 @@
-compile(export_all).
-compile(nowarn_export_all).
+-ifdef(OTP_RELEASE).
+-compile({nowarn_deprecated_function, [{ssl, ssl_accept, 2}]}).
+-endif.
+
%% 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].
+
+%% Origin server helpers.
+
+init_origin(Transport) ->
+ init_origin(Transport, http).
+
+init_origin(Transport, Protocol) ->
+ init_origin(Transport, Protocol, fun loop_origin/3).
+
+init_origin(Transport, Protocol, Fun) ->
+ Pid = spawn_link(?MODULE, init_origin, [self(), Transport, Protocol, Fun]),
+ Port = receive_from(Pid),
+ {ok, Pid, Port}.
+
+init_origin(Parent, tcp, Protocol, Fun) ->
+ {ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]),
+ {ok, {_, Port}} = inet:sockname(ListenSocket),
+ Parent ! {self(), Port},
+ {ok, ClientSocket} = gen_tcp:accept(ListenSocket, 5000),
+ case Protocol of
+ http2 -> http2_handshake(ClientSocket, gen_tcp);
+ _ -> ok
+ end,
+ Fun(Parent, ClientSocket, gen_tcp);
+init_origin(Parent, tls, Protocol, Fun) ->
+ Opts0 = ct_helper:get_certs_from_ets(),
+ Opts = case Protocol of
+ http2 -> [{alpn_preferred_protocols, [<<"h2">>]}|Opts0];
+ _ -> Opts0
+ end,
+ {ok, ListenSocket} = ssl:listen(0, [binary, {active, false}|Opts]),
+ {ok, {_, Port}} = ssl:sockname(ListenSocket),
+ Parent ! {self(), Port},
+ {ok, ClientSocket} = ssl:transport_accept(ListenSocket, 5000),
+ ok = ssl:ssl_accept(ClientSocket, 5000),
+ case Protocol of
+ http2 ->
+ {ok, <<"h2">>} = ssl:negotiated_protocol(ClientSocket),
+ http2_handshake(ClientSocket, ssl);
+ _ ->
+ ok
+ end,
+ Fun(Parent, ClientSocket, ssl).
+
+http2_handshake(Socket, Transport) ->
+ %% Send a valid preface.
+ ok = Transport:send(Socket, cow_http2:settings(#{})),
+ %% Receive the fixed sequence from the preface.
+ Preface = <<"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n">>,
+ {ok, Preface} = Transport:recv(Socket, byte_size(Preface), 5000),
+ %% Receive the SETTINGS from the preface.
+ {ok, <<Len:24>>} = Transport:recv(Socket, 3, 5000),
+ {ok, <<4:8, 0:40, _:Len/binary>>} = Transport:recv(Socket, 6 + Len, 5000),
+ %% Send the SETTINGS ack.
+ ok = Transport:send(Socket, cow_http2:settings_ack()),
+ %% Receive the SETTINGS ack.
+ {ok, <<0:24, 4:8, 1:8, 0:32>>} = Transport:recv(Socket, 9, 5000),
+ ok.
+
+loop_origin(Parent, ClientSocket, ClientTransport) ->
+ case ClientTransport:recv(ClientSocket, 0, 5000) of
+ {ok, Data} ->
+ Parent ! {self(), Data},
+ loop_origin(Parent, ClientSocket, ClientTransport);
+ {error, closed} ->
+ ok
+ end.
+
+%% Common helpers.
+
+receive_from(Pid) ->
+ receive_from(Pid, 5000).
+
+receive_from(Pid, Timeout) ->
+ receive
+ {Pid, Msg} ->
+ Msg
+ after Timeout ->
+ error(timeout)
+ end.