aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/test/httpc_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/test/httpc_SUITE.erl')
-rw-r--r--lib/inets/test/httpc_SUITE.erl794
1 files changed, 554 insertions, 240 deletions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 3485966307..4914a16264 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,25 +1,28 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
+%%
+%% ts:run(inets, httpc_SUITE, [batch]).
+%%
+
-module(httpc_SUITE).
--author('[email protected]').
-include("test_server.hrl").
-include("test_server_line.hrl").
@@ -55,6 +58,7 @@
%% Description: Returns documentation/test cases in this test suite
%% or a skip tuple if the platform is not supported.
%%--------------------------------------------------------------------
+
all(doc) ->
["Test the http client in the intes application."];
all(suite) ->
@@ -93,7 +97,7 @@ all(suite) ->
http_server_does_not_exist,
http_invalid_http,
http_emulate_lower_versions,
- http_relaxed,
+ http_relaxed,
page_does_not_exist,
proxy_page_does_not_exist,
proxy_https_not_supported,
@@ -138,12 +142,12 @@ init_per_suite(Config) ->
end,
{ok, FileInfo} = file:read_file_info(Cgi),
- ok = file:write_file_info(Cgi,
- FileInfo#file_info{mode = 8#00755}),
+ ok = file:write_file_info(Cgi, FileInfo#file_info{mode = 8#00755}),
- [{server_root, ServerRoot}, {doc_root, DocRoot},
- {local_port, ?IP_PORT}, {local_ssl_port, ?SSL_PORT}
- | Config].
+ [{server_root, ServerRoot},
+ {doc_root, DocRoot},
+ {local_port, ?IP_PORT},
+ {local_ssl_port, ?SSL_PORT} | Config].
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
@@ -170,11 +174,17 @@ end_per_suite(Config) ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
+init_per_testcase(otp_8154_1 = Case, Config) ->
+ init_per_testcase(Case, 5, Config);
init_per_testcase(Case, Config) ->
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
+ init_per_testcase(Case, 2, Config).
+
+init_per_testcase(Case, Timeout, Config) ->
+ io:format(user, "~n~n*** INIT ~w:~w[~w] ***~n~n",
+ [?MODULE, Timeout, Case]),
PrivDir = ?config(priv_dir, Config),
application:stop(inets),
- Dog = test_server:timetrap(inets_test_lib:minutes(10)),
+ Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
TmpConfig = lists:keydelete(watchdog, 1, Config),
IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
@@ -185,11 +195,10 @@ init_per_testcase(Case, Config) ->
application:stop(ssl),
TmpConfig2 =
lists:keydelete(local_ssl_server, 1, TmpConfig),
+ %% Will start inets
Server =
- %% Will start inets
- inets_test_lib:start_http_server(
- filename:join(PrivDir,
- SslConfFile)),
+ inets_test_lib:start_http_server(
+ filename:join(PrivDir, SslConfFile)),
[{watchdog, Dog}, {local_ssl_server, Server} | TmpConfig2];
"proxy" ++ Rest ->
case Rest of
@@ -224,7 +233,8 @@ init_per_testcase(Case, Config) ->
http:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
["localhost", ?IPV6_LOCAL_HOST]}}]),
- inets:enable_trace(max, io),
+ inets:enable_trace(max, io, httpc),
+ %% snmp:set_trace([gen_tcp, inet_tcp, prim_inet]),
NewConfig.
%%--------------------------------------------------------------------
@@ -269,7 +279,10 @@ tickets(suite) ->
no_content_204_otp_6982,
missing_CR_otp_7304,
otp_7883,
- otp_8154
+ otp_8154,
+ otp_8106,
+ otp_8056,
+ otp_8371
].
@@ -295,9 +308,9 @@ http_head(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], []}} ->
ok;
{ok, WrongReply} ->
- test_server:fail({wrong_reply, WrongReply});
+ tsf({wrong_reply, WrongReply});
Error ->
- test_server:fail({failed, Error})
+ tsf({failed, Error})
end;
_ ->
{skip, "Failed to start local http-server"}
@@ -308,28 +321,47 @@ http_get(doc) ->
http_get(suite) ->
[];
http_get(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
+ tsp("http_get -> entry with"
+ "~n Config: ~p", [Config]),
+ case ?config(local_server, Config) of
ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Timeout = timer:seconds(1),
- ConnTimeout = Timeout + timer:seconds(1),
- {ok, {{_,200,_}, [_ | _], Body = [_ | _]}} =
- http:request(get, {URL, []},
- [{timeout, Timeout}, {connect_timeout, ConnTimeout}], []),
- %% eqvivivalent to http:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(Body),
- {ok, {{_,200,_}, [_ | _], Bin}} =
- http:request(get, {URL, []}, [], [{body_format, binary}]),
- case Bin of
- Bin when is_binary(Bin) ->
- ok;
- _ ->
- test_server:fail(body_format_not_binary)
- end;
- _ ->
- {skip, "Failed to start local http-server"}
- end.
+ tsp("local-server running"),
+ Method = get,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ Timeout = timer:seconds(1),
+ ConnTimeout = Timeout + timer:seconds(1),
+ HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
+ Options1 = [],
+ Body =
+ case http:request(Method, Request, HttpOptions1, Options1) of
+ {ok, {{_,200,_}, [_ | _], ReplyBody = [_ | _]}} ->
+ ReplyBody;
+ {ok, UnexpectedReply1} ->
+ tsf({unexpected_reply, UnexpectedReply1});
+ {error, _} = Error1 ->
+ tsf({bad_reply, Error1})
+ end,
+
+ %% eqvivivalent to http:request(get, {URL, []}, [], []),
+ inets_test_lib:check_body(Body),
+
+ HttpOptions2 = [],
+ Options2 = [{body_format, binary}],
+ case http:request(Method, Request, HttpOptions2, Options2) of
+ {ok, {{_,200,_}, [_ | _], Bin}} when is_binary(Bin) ->
+ ok;
+ {ok, {{_,200,_}, [_ | _], BadBin}} ->
+ tsf({body_format_not_binary, BadBin});
+ {ok, UnexpectedReply2} ->
+ tsf({unexpected_reply, UnexpectedReply2});
+ {error, _} = Error2 ->
+ tsf({bad_reply, Error2})
+ end;
+ _ ->
+ {skip, "Failed to start local http-server"}
+ end.
%%-------------------------------------------------------------------------
http_post(doc) ->
@@ -389,7 +421,9 @@ http_emulate_lower_versions(Config) when is_list(Config) ->
{skip, "Failed to start local http-server"}
end.
+
%%-------------------------------------------------------------------------
+
http_relaxed(doc) ->
["Test relaxed mode"];
http_relaxed(suite) ->
@@ -397,12 +431,7 @@ http_relaxed(suite) ->
http_relaxed(Config) when is_list(Config) ->
ok = http:set_options([{ipv6, disabled}]), % also test the old option
%% ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++
"/missing_reason_phrase.html",
@@ -428,13 +457,8 @@ http_dummy_pipe(suite) ->
[];
http_dummy_pipe(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
-
URL = ?URL_START ++ integer_to_list(Port) ++ "/foobar.html",
test_pipeline(URL),
@@ -451,78 +475,126 @@ http_inets_pipe(Config) when is_list(Config) ->
case ?config(local_server, Config) of
ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
test_pipeline(URL);
_ ->
{skip, "Failed to start local http-server"}
end.
test_pipeline(URL) ->
-
+ p("test_pipeline -> entry with"
+ "~n URL: ~p", [URL]),
+
http:set_options([{pipeline_timeout, 50000}]),
+ p("test_pipeline -> issue (async) request 1"),
{ok, RequestId1} =
http:request(get, {URL, []}, [], [{sync, false}]),
test_server:format("RequestId1: ~p~n", [RequestId1]),
+ p("test_pipeline -> RequestId1: ~p", [RequestId1]),
%% Make sure pipeline is initiated
+ p("test_pipeline -> sleep some", []),
test_server:sleep(4000),
+ p("test_pipeline -> issue (async) request 2"),
{ok, RequestId2} =
http:request(get, {URL, []}, [], [{sync, false}]),
- test_server:format("RequestId2: ~p~n", [RequestId2]),
+ tsp("RequestId2: ~p", [RequestId2]),
+ p("test_pipeline -> RequestId2: ~p", [RequestId2]),
- {ok, {{_,200,_}, [_ | _], [_ | _]}}
- = http:request(get, {URL, []}, [], []),
+ p("test_pipeline -> issue (sync) request 3"),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ http:request(get, {URL, []}, [], []),
+
+ p("test_pipeline -> expect reply for (async) request 1 or 2"),
receive
{http, {RequestId1, {{_, 200, _}, _, _}}} ->
+ p("test_pipeline -> received reply for (async) request 1 - now wait for 2"),
receive
{http, {RequestId2, {{_, 200, _}, _, _}}} ->
+ p("test_pipeline -> received reply for (async) request 2"),
ok;
{http, Msg1} ->
test_server:fail(Msg1)
end;
{http, {RequestId2, {{_, 200, _}, _, _}}} ->
+ io:format("test_pipeline -> received reply for (async) request 2 - now wait for 1"),
receive
{http, {RequestId1, {{_, 200, _}, _, _}}} ->
+ io:format("test_pipeline -> received reply for (async) request 1"),
ok;
{http, Msg2} ->
test_server:fail(Msg2)
end;
{http, Msg3} ->
- test_server:fail(Msg3)
+ test_server:fail(Msg3)
+ after 60000 ->
+ receive Any1 ->
+ tsp("received crap after timeout: ~n ~p", [Any1]),
+ test_server:fail({error, {timeout, Any1}})
+ end
end,
+ p("test_pipeline -> sleep some"),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request 4"),
{ok, RequestId3} =
- http:request(get, {URL, []}, [], [{sync, false}]),
- test_server:format("RequestId3: ~p~n", [RequestId3]),
+ http:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestId3: ~p", [RequestId3]),
+ p("test_pipeline -> RequestId3: ~p", [RequestId3]),
+
+ p("test_pipeline -> issue (async) request 5"),
{ok, RequestId4} =
http:request(get, {URL, []}, [], [{sync, false}]),
- test_server:format("RequestId4: ~p~n", [RequestId4]),
+ tsp("RequestId4: ~p~n", [RequestId4]),
+ p("test_pipeline -> RequestId4: ~p", [RequestId4]),
+
+ p("test_pipeline -> cancel (async) request 4"),
ok = http:cancel_request(RequestId3),
+
+ p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"),
receive
{http, {RequestId3, _}} ->
- test_server:fail(http_cancel_request_failed)
+ test_server:fail(http_cancel_request_failed)
after 3000 ->
ok
end,
+
+ p("test_pipeline -> expect reply for (async) request 4"),
Body =
receive
- Res = {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} ->
- test_server:format(" Receive : ~p~n", [Res]),
+ {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res ->
+ p("test_pipeline -> received reply for (async) request 5"),
+ tsp("Receive : ~p", [Res]),
BinBody4;
{http, Msg4} ->
test_server:fail(Msg4)
+ after 60000 ->
+ receive Any2 ->
+ tsp("received crap after timeout: ~n ~p", [Any2]),
+ test_server:fail({error, {timeout, Any2}})
+ end
end,
+
+ p("test_pipeline -> check reply for (async) request 5"),
inets_test_lib:check_body(binary_to_list(Body)),
+ p("test_pipeline -> ensure no unexpected incomming"),
receive
{http, Any} ->
test_server:fail({unexpected_message, Any})
after 500 ->
ok
- end.
+ end,
+
+ p("test_pipeline -> done"),
+ ok.
+
+
+
%%-------------------------------------------------------------------------
http_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -700,12 +772,7 @@ http_headers_dummy(suite) ->
[];
http_headers_dummy(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy_headers.html",
@@ -770,12 +837,7 @@ http_bad_response(suite) ->
[];
http_bad_response(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_crlf.html",
@@ -868,64 +930,90 @@ http_redirect(doc) ->
http_redirect(suite) ->
[];
http_redirect(Config) when is_list(Config) ->
+ tsp("http_redirect -> entry with"
+ "~n Config: ~p", [Config]),
case ?config(local_server, Config) of
ok ->
+ tsp("http_redirect -> set ipfamily option to inet"),
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+
+ tsp("http_redirect -> start dummy server inet"),
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ tsp("http_redirect -> server port = ~p", [Port]),
URL300 = ?URL_START ++ integer_to_list(Port) ++ "/300.html",
+ tsp("http_redirect -> issue request 1: "
+ "~n ~p", [URL300]),
{ok, {{_,200,_}, [_ | _], [_|_]}}
= http:request(get, {URL300, []}, [], []),
- {ok, {{_,300,_}, [_ | _], _}}
- = http:request(get, {URL300, []}, [{autoredirect, false}],
- []),
+ tsp("http_redirect -> issue request 2: "
+ "~n ~p", [URL300]),
+ {ok, {{_,300,_}, [_ | _], _}} =
+ http:request(get, {URL300, []}, [{autoredirect, false}], []),
URL301 = ?URL_START ++ integer_to_list(Port) ++ "/301.html",
-
+ tsp("http_redirect -> issue request 3: "
+ "~n ~p", [URL301]),
{ok, {{_,200,_}, [_ | _], [_|_]}}
= http:request(get, {URL301, []}, [], []),
+ tsp("http_redirect -> issue request 4: "
+ "~n ~p", [URL301]),
{ok, {{_,200,_}, [_ | _], []}}
= http:request(head, {URL301, []}, [], []),
+ tsp("http_redirect -> issue request 5: "
+ "~n ~p", [URL301]),
{ok, {{_,301,_}, [_ | _], [_|_]}}
= http:request(post, {URL301, [],"text/plain", "foobar"},
[], []),
URL302 = ?URL_START ++ integer_to_list(Port) ++ "/302.html",
+ tsp("http_redirect -> issue request 6: "
+ "~n ~p", [URL302]),
{ok, {{_,200,_}, [_ | _], [_|_]}}
= http:request(get, {URL302, []}, [], []),
+ tsp("http_redirect -> issue request 7: "
+ "~n ~p", [URL302]),
{ok, {{_,200,_}, [_ | _], []}}
= http:request(head, {URL302, []}, [], []),
+ tsp("http_redirect -> issue request 8: "
+ "~n ~p", [URL302]),
{ok, {{_,302,_}, [_ | _], [_|_]}}
= http:request(post, {URL302, [],"text/plain", "foobar"},
[], []),
URL307 = ?URL_START ++ integer_to_list(Port) ++ "/307.html",
+ tsp("http_redirect -> issue request 9: "
+ "~n ~p", [URL307]),
{ok, {{_,200,_}, [_ | _], [_|_]}}
= http:request(get, {URL307, []}, [], []),
+ tsp("http_redirect -> issue request 10: "
+ "~n ~p", [URL307]),
{ok, {{_,200,_}, [_ | _], []}}
= http:request(head, {URL307, []}, [], []),
+ tsp("http_redirect -> issue request 11: "
+ "~n ~p", [URL307]),
{ok, {{_,307,_}, [_ | _], [_|_]}}
= http:request(post, {URL307, [],"text/plain", "foobar"},
[], []),
+ tsp("http_redirect -> stop dummy server"),
DummyServerPid ! stop,
- ok = http:set_options([{ipfamily, inet6fb4}]); % ********** ipfamily = inet6 *************
+ tsp("http_redirect -> reset ipfamily option (to inet6fb4)"),
+ ok = http:set_options([{ipfamily, inet6fb4}]), % ********** ipfamily = inet6 *************
+ tsp("http_redirect -> done"),
+ ok;
+
_ ->
{skip, "Failed to start local http-server"}
end.
@@ -938,12 +1026,7 @@ http_redirect_loop(suite) ->
[];
http_redirect_loop(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/redirectloop.html",
@@ -960,12 +1043,7 @@ http_internal_server_error(suite) ->
[];
http_internal_server_error(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL500 = ?URL_START ++ integer_to_list(Port) ++ "/500.html",
@@ -1001,12 +1079,7 @@ http_userinfo(suite) ->
http_userinfo(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URLAuth = "http://alladin:sesame@localhost:"
++ integer_to_list(Port) ++ "/userinfo.html",
@@ -1032,12 +1105,7 @@ http_cookie(suite) ->
[];
http_cookie(Config) when is_list(Config) ->
ok = http:set_options([{cookies, enabled}, {ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URLStart = ?URL_START
++ integer_to_list(Port),
@@ -1335,8 +1403,8 @@ proxy_https_not_supported(doc) ->
proxy_https_not_supported(suite) ->
[];
proxy_https_not_supported(Config) when is_list(Config) ->
- {error, https_through_proxy_is_not_currently_supported}
- = http:request(get, {"https://login.yahoo.com", []}, [], []),
+ {error, {failed_connecting, https_through_proxy_is_not_currently_supported}} =
+ http:request(get, {"https://login.yahoo.com", []}, [], []),
ok.
@@ -1374,51 +1442,68 @@ http_stream_once(doc) ->
http_stream_once(suite) ->
[];
http_stream_once(Config) when is_list(Config) ->
+ p("http_stream_once -> entry with"
+ "~n Config: ~p", [Config]),
+
+ p("http_stream_once -> set ipfamily to inet", []),
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ p("http_stream_once -> start dummy server", []),
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
PortStr = integer_to_list(Port),
+ p("http_stream_once -> once", []),
once(?URL_START ++ PortStr ++ "/once.html"),
+ p("http_stream_once -> once_chunked", []),
once(?URL_START ++ PortStr ++ "/once_chunked.html"),
+ p("http_stream_once -> dummy", []),
once(?URL_START ++ PortStr ++ "/dummy.html"),
+ p("http_stream_once -> stop dummy server", []),
DummyServerPid ! stop,
+ p("http_stream_once -> set ipfamily to inet6fb4", []),
ok = http:set_options([{ipfamily, inet6fb4}]), % ********** ipfamily = inet6 *************
+ p("http_stream_once -> done", []),
ok.
once(URL) ->
+ p("once -> issue sync request for ~p", [URL]),
{ok, {{_,200,_}, [_ | _], Body}} =
http:request(get, {URL, []}, [], []),
+ p("once -> issue async (self stream) request for ~p", [URL]),
{ok, RequestId} =
http:request(get, {URL, []}, [], [{sync, false},
{stream, {self, once}}]),
- NewPid = receive
- {http, {RequestId, stream_start, _Headers, Pid}} ->
- Pid;
- {http, Msg} ->
- test_server:fail(Msg)
- end,
+ p("once -> await stream_start reply for (async) request ~p", [RequestId]),
+ NewPid =
+ receive
+ {http, {RequestId, stream_start, _Headers, Pid}} ->
+ p("once -> received stream_start reply for (async) request ~p: ~p",
+ [RequestId, Pid]),
+ Pid;
+ {http, Msg} ->
+ test_server:fail(Msg)
+ end,
- test_server:format("Request handler: ~p~n", [NewPid]),
+ tsp("once -> request handler: ~p", [NewPid]),
+ p("once -> await stream reply for (async) request ~p", [RequestId]),
BodyPart =
receive
{http, {RequestId, stream, BinBodyPart}} ->
+ p("once -> received stream reply for (async) request ~p: "
+ "~n~p", [RequestId, binary_to_list(BinBodyPart)]),
BinBodyPart
end,
- test_server:format("First body part: ~p~n",
- [binary_to_list(BodyPart)]),
+ tsp("once -> first body part '~p' received", [binary_to_list(BodyPart)]),
StreamedBody = receive_streamed_body(RequestId, BinBodyPart, NewPid),
Body = binary_to_list(StreamedBody),
+
+ p("once -> done when Bode: ~p", [Body]),
ok.
@@ -1509,12 +1594,7 @@ ipv6(Config) when is_list(Config) ->
case lists:member(list_to_atom(Hostname),
?config(ipv6_hosts, Config)) of
true ->
- DummyServerPid = dummy_server(self(), ipv6),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv6),
URL = "http://[" ++ ?IPV6_LOCAL_HOST ++ "]:" ++
integer_to_list(Port) ++ "/foobar.html",
@@ -1576,12 +1656,7 @@ http_invalid_http(suite) ->
[];
http_invalid_http(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/invalid_http.html",
@@ -1638,12 +1713,7 @@ transfer_encoding_otp_6807(suite) ->
[];
transfer_encoding_otp_6807(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++
"/capital_transfer_encoding.html",
@@ -1676,12 +1746,7 @@ empty_response_header_otp_6830(suite) ->
[];
empty_response_header_otp_6830(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/no_headers.html",
{ok, {{_,200,_}, [], [_ | _]}} = http:request(URL),
@@ -1698,12 +1763,7 @@ no_content_204_otp_6982(suite) ->
[];
no_content_204_otp_6982(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/no_content.html",
{ok, {{_,204,_}, [], []}} = http:request(URL),
@@ -1721,12 +1781,7 @@ missing_CR_otp_7304(suite) ->
[];
missing_CR_otp_7304(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
-
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_CR.html",
{ok, {{_,200,_}, _, [_ | _]}} = http:request(URL),
@@ -1747,13 +1802,8 @@ otp_7883_1(suite) ->
otp_7883_1(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
-
URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
{error, socket_closed_remotely} = http:request(URL),
DummyServerPid ! stop,
@@ -1768,13 +1818,8 @@ otp_7883_2(suite) ->
otp_7883_2(Config) when is_list(Config) ->
ok = http:set_options([{ipfamily, inet}]),
- DummyServerPid = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
- Port = receive
- {port, ServerPort} ->
- ServerPort
- end,
-
URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
Method = get,
Request = {URL, []},
@@ -1810,7 +1855,7 @@ otp_8154_1(Config) when is_list(Config) ->
{ok, Server, Port} = start_slow_server(RespSeqNumServer),
Clients = run_clients(105, Port, ReqSeqNumServer),
%% ok = wait_for_clients(Clients),
- ok = wait4clients(Clients, timer:minutes(2)),
+ ok = wait4clients(Clients, timer:minutes(3)),
Server ! shutdown,
RespSeqNumServer ! shutdown,
ReqSeqNumServer ! shutdown,
@@ -1820,6 +1865,7 @@ start_inets() ->
inets:start(),
ok.
+
%% -----------------------------------------------------
%% A sequence number handler
%% The purpose is to be able to pair requests with responses.
@@ -1886,25 +1932,25 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
end,
lists:seq(1, NumClients)).
-wait_for_clients(Clients) ->
- lists:foreach(
- fun({Id, Pid, MRef}) ->
- io:format("waiting for client ~w termination~n", [Id]),
- receive
- {'DOWN', MRef, process, Pid, normal} ->
- io:format("waiting for clients: "
- "normal exit from ~w (~p)~n",
- [Id, Pid]),
- ok;
- {'DOWN', MRef, process, Pid, Reason} ->
- io:format("waiting for clients: "
- "unexpected exit from ~w (~p):"
- "~n Reason: ~p"
- "~n", [Id, Pid, Reason]),
- erlang:error(Reason)
- end
- end,
- Clients).
+%% wait_for_clients(Clients) ->
+%% lists:foreach(
+%% fun({Id, Pid, MRef}) ->
+%% io:format("waiting for client ~w termination~n", [Id]),
+%% receive
+%% {'DOWN', MRef, process, Pid, normal} ->
+%% io:format("waiting for clients: "
+%% "normal exit from ~w (~p)~n",
+%% [Id, Pid]),
+%% ok;
+%% {'DOWN', MRef, process, Pid, Reason} ->
+%% io:format("waiting for clients: "
+%% "unexpected exit from ~w (~p):"
+%% "~n Reason: ~p"
+%% "~n", [Id, Pid, Reason]),
+%% erlang:error(Reason)
+%% end
+%% end,
+%% Clients).
wait4clients([], _Timeout) ->
@@ -2074,6 +2120,201 @@ f(F, A) -> lists:flatten(io_lib:format(F,A)).
+%%-------------------------------------------------------------------------
+
+otp_8106(suite) ->
+ [
+ otp_8106_pid,
+ otp_8106_fun,
+ otp_8106_mfa
+ ].
+
+
+otp_8106_pid(doc) ->
+ ["OTP-8106 - deliver reply info using \"other\" pid"];
+otp_8106_pid(suite) ->
+ [];
+otp_8106_pid(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(pid),
+ Receiver = ReceiverPid,
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ {skip, "Failed to start local http-server"}
+ end.
+
+
+otp_8106_fun(doc) ->
+ ["OTP-8106 - deliver reply info using fun"];
+otp_8106_fun(suite) ->
+ [];
+otp_8106_fun(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(function),
+ Receiver = otp_8106_deliver_fun(ReceiverPid),
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ {skip, "Failed to start local http-server"}
+ end.
+
+
+otp_8106_mfa(doc) ->
+ ["OTP-8106 - deliver reply info using mfa callback"];
+otp_8106_mfa(suite) ->
+ [];
+otp_8106_mfa(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(mfa),
+ Receiver = {?MODULE, otp_8106_deliver, [mfa, ReceiverPid]},
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ {skip, "Failed to start local http-server"}
+ end.
+
+
+ otp8106(ReceiverPid, Receiver, Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HTTPOptions = [],
+ Options = [{sync, false}, {receiver, Receiver}],
+
+ {ok, RequestId} =
+ httpc:request(get, Request, HTTPOptions, Options),
+
+ Body =
+ receive
+ {reply, ReceiverPid, {RequestId, {{_, 200, _}, _, B}}} ->
+ B;
+ {reply, ReceiverPid, Msg} ->
+ tsf(Msg);
+ {bad_reply, ReceiverPid, Msg} ->
+ tsf(Msg)
+ end,
+
+ inets_test_lib:check_body(binary_to_list(Body)),
+ ok.
+
+
+create_receiver(Type) ->
+ Parent = self(),
+ Receiver = fun() -> receiver(Type, Parent) end,
+ spawn_link(Receiver).
+
+stop_receiver(Pid) ->
+ Pid ! {stop, self()}.
+
+receiver(Type, Parent) ->
+ receive
+ {stop, Parent} ->
+ exit(normal);
+
+ {http, ReplyInfo} when (Type =:= pid) ->
+ Parent ! {reply, self(), ReplyInfo},
+ receiver(Type, Parent);
+
+ {Type, ReplyInfo} ->
+ Parent ! {reply, self(), ReplyInfo},
+ receiver(Type, Parent);
+
+ Crap ->
+ Parent ! {reply, self(), {bad_reply, Crap}},
+ receiver(Type, Parent)
+ end.
+
+
+otp_8106_deliver_fun(ReceiverPid) ->
+ fun(ReplyInfo) -> otp_8106_deliver(ReplyInfo, function, ReceiverPid) end.
+
+otp_8106_deliver(ReplyInfo, Type, ReceiverPid) ->
+ ReceiverPid ! {Type, ReplyInfo},
+ ok.
+
+
+
+%%-------------------------------------------------------------------------
+
+otp_8056(doc) ->
+ "OTP-8056";
+otp_8056(suite) ->
+ [];
+otp_8056(Config) when is_list(Config) ->
+ Method = get,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HTTPOptions = [],
+ Options1 = [{sync, true}, {stream, {self, once}}],
+ Options2 = [{sync, true}, {stream, self}],
+ {error, streaming_error} = httpc:request(Method, Request,
+ HTTPOptions, Options1),
+ tsp("request 1 failed as expected"),
+ {error, streaming_error} = httpc:request(Method, Request,
+ HTTPOptions, Options2),
+ tsp("request 2 failed as expected"),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+otp_8371(doc) ->
+ ["OTP-8371"];
+otp_8371(suite) ->
+ [];
+otp_8371(Config) when is_list(Config) ->
+ ok = http:set_options([{ipv6, disabled}]), % also test the old option
+ {DummyServerPid, Port} = dummy_server(self(), ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++
+ "/ensure_host_header_with_port.html",
+
+ case http:request(get, {URL, []}, [], []) of
+ {ok, Result} ->
+ case Result of
+ {{_, 200, _}, _Headers, Body} ->
+ tsp("expected response with"
+ "~n Body: ~p", [Body]),
+ ok;
+ {StatusLine, Headers, Body} ->
+ tsp("expected response with"
+ "~n StatusLine: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p", [StatusLine, Headers, Body]),
+ tsf({unexpected_result,
+ [{status_line, StatusLine},
+ {headers, Headers},
+ {body, Body}]});
+ _ ->
+ tsf({unexpected_result, Result})
+ end;
+ Error ->
+ tsf({request_failed, Error})
+ end,
+
+ DummyServerPid ! stop,
+ ok = http:set_options([{ipv6, enabled}]),
+ ok.
+
+
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
@@ -2171,7 +2412,7 @@ receive_streamed_body(RequestId, Body) ->
receive_streamed_body(RequestId, Body, Pid) ->
http:stream_next(Pid),
- test_server:format("Requested next stream ~n", []),
+ test_server:format("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
receive
{http, {RequestId, stream, BinBodyPart}} ->
receive_streamed_body(RequestId,
@@ -2186,7 +2427,11 @@ receive_streamed_body(RequestId, Body, Pid) ->
dummy_server(Caller, IpV) ->
- spawn(httpc_SUITE, dummy_server_init, [Caller, IpV]).
+ Pid = spawn(httpc_SUITE, dummy_server_init, [Caller, IpV]),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
dummy_server_init(Caller, IpV) ->
{ok, ListenSocket} =
@@ -2201,7 +2446,7 @@ dummy_server_init(Caller, IpV) ->
{active, false}])
end,
{ok, Port} = inet:port(ListenSocket),
- test_server:format("Port: ~p~n", [Port]),
+ tsp("dummy_server_init -> Port: ~p", [Port]),
Caller ! {port, Port},
dummy_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
[], ListenSocket).
@@ -2209,8 +2454,7 @@ dummy_server_init(Caller, IpV) ->
dummy_server_loop(MFA, Handlers, ListenSocket) ->
receive
stop ->
- lists:foreach(fun(Handler) -> Handler ! stop end,
- Handlers)
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers)
after 0 ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
HandlerPid = dummy_request_handler(MFA, Socket),
@@ -2231,9 +2475,13 @@ dummy_request_handler_init(MFA, Socket) ->
dummy_request_handler_loop(MFA, Socket).
dummy_request_handler_loop({Module, Function, Args}, Socket) ->
+ tsp("dummy_request_handler_loop -> entry with"
+ "~n Module: ~p"
+ "~n Function: ~p"
+ "~n Args: ~p", [Module, Function, Args]),
receive
{tcp, _, Data} ->
- test_server:format("dummy_request_handler_loop -> Data ~p~n", [Data]),
+ tsp("dummy_request_handler_loop -> Data ~p", [Data]),
case handle_request(Module, Function, [Data | Args], Socket) of
stop ->
gen_tcp:close(Socket);
@@ -2245,48 +2493,59 @@ dummy_request_handler_loop({Module, Function, Args}, Socket) ->
end.
handle_request(Module, Function, Args, Socket) ->
+ tsp("handle_request -> entry with"
+ "~n Module: ~p"
+ "~n Function: ~p"
+ "~n Args: ~p", [Module, Function, Args]),
case Module:Function(Args) of
{ok, Result} ->
- case handle_http_msg(Result, Socket) of
+ tsp("handle_request -> ok"
+ "~n Result: ~p", [Result]),
+ case (catch handle_http_msg(Result, Socket)) of
stop ->
stop;
<<>> ->
- {httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]};
+ tsp("handle_request -> empty data"),
+ {httpd_request, parse, [[<<>>, ?HTTP_MAX_HEADER_SIZE]]};
Data ->
handle_request(httpd_request, parse,
- [Data |[?HTTP_MAX_HEADER_SIZE]],
- Socket)
+ [Data |[?HTTP_MAX_HEADER_SIZE]], Socket)
end;
NewMFA ->
+ tsp("handle_request -> "
+ "~n NewMFA: ~p", [NewMFA]),
NewMFA
end.
handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
-
- NextRequest = case RelUri of
- "/dummy_headers.html" ->
- <<>>;
- "/no_headers.html" ->
- stop;
- "/just_close.html" ->
- stop;
- _ ->
- ContentLength = content_length(Headers),
- case size(Body) - ContentLength of
- 0 ->
- <<>>;
- _ ->
- <<_BodyThisReq:ContentLength/binary,
- Next/binary>> = Body,
- Next
- end
- end,
+ tsp("handle_http_msg -> entry with: "
+ "~n RelUri: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p", [RelUri, Headers, Body]),
+ NextRequest =
+ case RelUri of
+ "/dummy_headers.html" ->
+ <<>>;
+ "/no_headers.html" ->
+ stop;
+ "/just_close.html" ->
+ stop;
+ _ ->
+ ContentLength = content_length(Headers),
+ case size(Body) - ContentLength of
+ 0 ->
+ <<>>;
+ _ ->
+ <<_BodyThisReq:ContentLength/binary,
+ Next/binary>> = Body,
+ Next
+ end
+ end,
- test_server:format("NextRequest: ~p~n", [NextRequest]),
-
+ tsp("handle_http_msg -> NextRequest: ~p", [NextRequest]),
case (catch ets:lookup(cookie, cookies)) of
[{cookies, true}]->
- test_server:format("Headers ~p~n", [Headers]),
+ tsp("handle_http_msg -> check cookies ~p", []),
check_cookie(Headers);
_ ->
ok
@@ -2304,6 +2563,26 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
"HTTP/1.0 204 No Content\r\n\r\n";
"/no_headers.html" ->
"HTTP/1.0 200 OK\r\n\r\nTEST";
+ "/ensure_host_header_with_port.html" ->
+ %% tsp("handle_http_msg -> validate host with port"),
+ case ensure_host_header_with_port(Headers) of
+ true ->
+ B =
+ "<HTML><BODY>" ++
+ "host with port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B;
+ false ->
+ B =
+ "<HTML><BODY>" ++
+ "Internal Server Error - host without port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end;
"/300.html" ->
NewUri = ?URL_START ++
integer_to_list(?IP_PORT) ++ "/dummy.html",
@@ -2337,7 +2616,7 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
"/500.html" ->
"HTTP/1.1 500 Internal Server Error\r\n" ++
"Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY<</HTML>";
+ "<HTML><BODY>Internal Server Error</BODY></HTML>";
"/503.html" ->
case ets:lookup(unavailable, 503) of
[{503, unavailable}] ->
@@ -2452,16 +2731,35 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
DefaultResponse
end,
- test_server:format("Msg: ~p~n", [Msg]),
+ tsp("handle_http_msg -> Msg: ~p", [Msg]),
case Msg of
+ ok ->
+ %% Previously, this resulted in an {error, einval}. Now what?
+ ok;
close ->
%% Nothing to send, just close
gen_tcp:close(Socket);
- _ ->
+ _ when is_list(Msg) orelse is_binary(Msg) ->
gen_tcp:send(Socket, Msg)
end,
+ tsp("handle_http_msg -> done"),
NextRequest.
+ensure_host_header_with_port([]) ->
+ false;
+ensure_host_header_with_port(["host: " ++ Host| _]) ->
+ case string:tokens(Host, [$:]) of
+ [ActualHost, Port] ->
+ tsp("ensure_host_header_with_port -> "
+ "~n ActualHost: ~p"
+ "~n Port: ~p", [ActualHost, Port]),
+ true;
+ _ ->
+ false
+ end;
+ensure_host_header_with_port([_|T]) ->
+ ensure_host_header_with_port(T).
+
auth_header([]) ->
auth_header_not_found;
auth_header(["authorization:" ++ Value | _]) ->
@@ -2507,9 +2805,10 @@ provocate_not_modified_bug(Url) ->
[]) of
{ok, {{_, 304, _}, _, _}} -> %% The expected reply
page_unchanged;
- {ok, {{_, 200, _}, _, _}} -> %% If the page has changed since the
- %% last request we retry to
- %% trigger the bug
+ {ok, {{_, 200, _}, _, _}} ->
+ %% If the page has changed since the
+ %% last request we retry to
+ %% trigger the bug
provocate_not_modified_bug(Url);
{error, timeout} ->
%% Not what we expected. Tcpdump can be used to
@@ -2528,5 +2827,20 @@ pick_header(Headers, Name) ->
end.
-%% p(F, A) ->
-%% io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
+not_implemented_yet() ->
+ exit(not_implemented_yet).
+
+
+p(F) ->
+ p(F, []).
+
+p(F, A) ->
+ io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
+
+tsp(F) ->
+ tsp(F, []).
+tsp(F, A) ->
+ test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+
+tsf(Reason) ->
+ test_server:fail(Reason).