aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-11-24 00:16:19 +0100
committerLoïc Hoguin <[email protected]>2017-11-24 00:16:19 +0100
commitce32e1985afd6c629ed904a7cf2b3c119782e914 (patch)
treea63812736e4c297e7af3f88936534008ba07cb55
parent14173d592999bb0478d8e2a7d7334800ee26057c (diff)
downloadcowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.tar.gz
cowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.tar.bz2
cowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.zip
Add more tests to the rfc7230 suite
Found more bugs! Unfortunately no fix for them in this commit.
-rw-r--r--test/handlers/send_message_h.erl9
-rw-r--r--test/http_SUITE.erl2
-rw-r--r--test/rfc7230_SUITE.erl155
3 files changed, 120 insertions, 46 deletions
diff --git a/test/handlers/send_message_h.erl b/test/handlers/send_message_h.erl
new file mode 100644
index 0000000..02d2139
--- /dev/null
+++ b/test/handlers/send_message_h.erl
@@ -0,0 +1,9 @@
+%% This module sends a message to the pid passed in a header.
+
+-module(send_message_h).
+-export([init/2]).
+
+init(Req, State) ->
+ Pid = list_to_pid(binary_to_list(cowboy_req:header(<<"x-test-pid">>, Req))),
+ Pid ! {Pid, self(), init, Req, State},
+ {ok, cowboy_req:reply(200, Req), State}.
diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl
index 4370ab2..b4c6cc7 100644
--- a/test/http_SUITE.erl
+++ b/test/http_SUITE.erl
@@ -91,7 +91,7 @@ end_per_group(Name, _) ->
%% Dispatch configuration.
-init_dispatch(Config) ->
+init_dispatch(_) ->
cowboy_router:compile([
{"localhost", [
{"/chunked_response", http_chunked, []},
diff --git a/test/rfc7230_SUITE.erl b/test/rfc7230_SUITE.erl
index f6344c7..0f17133 100644
--- a/test/rfc7230_SUITE.erl
+++ b/test/rfc7230_SUITE.erl
@@ -24,7 +24,7 @@
all() -> [{group, http}].
-groups() -> [{http, [parallel], ct_helper:all(?MODULE)}]. %% @todo parallel
+groups() -> [{http, [parallel], ct_helper:all(?MODULE)}].
init_per_group(Name = http, Config) ->
cowboy_test:init_http(Name = http, #{
@@ -38,7 +38,8 @@ init_routes(_) -> [
{"localhost", [
{"/", hello_h, []},
{"/echo/:key[/:arg]", echo_h, []},
- {"/length/echo/:key", echo_h, []}
+ {"/length/echo/:key", echo_h, []},
+ {"/send_message", send_message_h, []}
%% @todo Something is clearly wrong about routing * right now.
%% {"*", asterisk_h, []}
]},
@@ -1443,22 +1444,66 @@ pipeline(Config) ->
%Abusive traffic can come from the form of too many requests in a
%given amount of time, or too many concurrent connections. Limits
%must be subject to configuration. (RFC7230 6.4)
-%
-%close_inactive_connections(Config) ->
-%The server must close inactive connections. The timeout
-%must be subject to configuration. (RFC7230 6.5)
-%
+
+close_inactive_connections(Config) ->
+ doc("The server must close inactive connections. The timeout "
+ "must be subject to configuration. (RFC7230 6.5)"),
+ Client = raw_open(Config),
+ {error, closed} = raw_recv(Client, 0, 6000).
+
%@todo
%The server must monitor connections for the close signal
%and close the socket on its end accordingly. (RFC7230 6.5)
%
%@todo
%A connection close may occur at any time. (RFC7230 6.5)
-%
-%ignore_requests_after_connection_close(Config) ->
-%The server must not process any request after sending or
-%receiving the "close" connection option. (RFC7230 6.6)
-%
+
+ignore_requests_after_request_connection_close(Config) ->
+ doc("The server must not process any request after "
+ "receiving the \"close\" connection option. (RFC7230 6.6)"),
+ Self = self(),
+ #{code := 200, client := Client} = do_raw(Config, [
+ "GET / HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ "GET /send_message HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "x-test-pid: ", pid_to_list(Self), "\r\n"
+ "\r\n"]),
+ {error, closed} = raw_recv(Client, 0, 1000),
+ %% We receive a message if the second request is wrongly processed.
+ receive
+ {Self, _, init, Req, Opts} ->
+ error({init, Req, Opts})
+ after 1000 ->
+ ok
+ end.
+
+ignore_requests_after_response_connection_close(Config) ->
+ doc("The server must not process any request after "
+ "sending the \"close\" connection option. (RFC7230 6.6)"),
+ Self = self(),
+ #{code := 200} = do_raw(Config, [
+ [
+ "GET / HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "\r\n"
+ || _ <- lists:seq(1, 100)],
+ "GET /send_message HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "x-test-pid: ", pid_to_list(Self), "\r\n"
+ "\r\n"]),
+ %% We have a separate test for the connection close so we don't
+ %% double check the connection gets closed here. We only need to
+ %% know whether the 101st request was wrongly processed.
+ receive
+ {Self, _, init, Req, Opts} ->
+ error({init, Req, Opts})
+ after 1000 ->
+ ok
+ end.
+
%@todo
%The server must close the connection in stages to avoid the
%TCP reset problem. The server starts by closing the write
@@ -1467,53 +1512,73 @@ pipeline(Config) ->
%last response has been received by the client, or until
%a close or timeout occurs. The server then fully close the
%connection. (6.6)
-%
-%%% Routing.
-%
+
+%% Routing.
+
%```
%Host = authority ; same as authority-form
%```
-%
-%reject_missing_host(Config) ->
-%An HTTP/1.1 request that lacks a host header must be rejected with
-%a 400 status code and the closing of the connection. (RFC7230 5.4)
-%
-%%% @todo http/1.0 missing_host(Config) ->
+
+reject_missing_host(Config) ->
+ doc("An HTTP/1.1 request that lacks a host header must be rejected with "
+ "a 400 status code and the closing of the connection. (RFC7230 5.4)"),
+ #{code := 400, client := Client} = do_raw(Config, [
+ "GET / HTTP/1.1\r\n"
+ "\r\n"]),
+ {error, closed} = raw_recv(Client, 0, 1000).
+
+%% @todo http/1.0 missing_host(Config) ->
%An HTTP/1.0 request that lack a host header is valid. Behavior
%for these requests is configuration dependent. (RFC7230 5.5)
-%
-%reject_invalid_host(Config) ->
-%A request with an invalid host header must be rejected with a
-%400 status code and the closing of the connection. (RFC7230 5.4)
-%
-%reject_userinfo(Config) ->
-%An authority component with a userinfo component (and its
-%"@" delimiter) is invalid. The request must be rejected with
-%a 400 status code and the closing of the connection. (RFC7230 2.7.1)
-%
-%reject_absolute_form_different_host(Config) ->
-%When using absolute-form the URI authority component must be
-%identical to the host header. Invalid requests must be rejected
-%with a 400 status code and the closing of the connection. (RFC7230 5.4)
-%
+
+reject_invalid_host(Config) ->
+ doc("A request with an invalid host header must be rejected with a "
+ "400 status code and the closing of the connection. (RFC7230 5.4)"),
+ #{code := 400, client := Client} = do_raw(Config, [
+ "GET / HTTP/1.1\r\n"
+ "Host: localhost:port\r\n"
+ "\r\n"]),
+ {error, closed} = raw_recv(Client, 0, 1000).
+
+reject_userinfo(Config) ->
+ doc("An authority component with a userinfo component (and its "
+ "\"@\" delimiter) is invalid. The request must be rejected with "
+ "a 400 status code and the closing of the connection. (RFC7230 2.7.1)"),
+ #{code := 400, client := Client} = do_raw(Config, [
+ "GET / HTTP/1.1\r\n"
+ "Host: user@localhost\r\n"
+ "\r\n"]),
+ {error, closed} = raw_recv(Client, 0, 1000).
+
+reject_absolute_form_different_host(Config) ->
+ doc("When using absolute-form the URI authority component must be "
+ "identical to the host header. Invalid requests must be rejected "
+ "with a 400 status code and the closing of the connection. (RFC7230 5.4)"),
+ #{code := 400, client := Client} = do_raw(Config, [
+ "GET http://example.org/ HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "\r\n"]),
+ {error, closed} = raw_recv(Client, 0, 1000).
+
%reject_authority_form_different_host(Config) ->
%When using authority-form the URI authority component must be
%identical to the host header. Invalid requests must be rejected
%with a 400 status code and the closing of the connection.
-%
+
%empty_host(Config) ->
%The host header is empty when the authority component is undefined. (RFC7230 5.4)
-%
-%@todo
-%The effective request URI can be rebuilt by concatenating scheme,
-%"://", authority, path and query components. (RFC7230 5.5)
-%
+
+%% The effective request URI can be rebuilt by concatenating scheme,
+%% "://", authority, path and query components. (RFC7230 5.5)
+%%
+%% This is covered in req_SUITE in the tests for cowboy_req:uri/1,2.
+
%@todo
%Resources with identical URI except for the scheme component
%must be treated as different. (RFC7230 2.7.2)
-%
-%%% Response.
-%
+
+%% Response.
+
%@todo
%A server can send more than one response per request only when a
%1xx response is sent preceding the final response. (RFC7230 5.6)