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.erl612
1 files changed, 527 insertions, 85 deletions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 6e69c9a469..a116edef77 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. 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
@@ -90,6 +90,7 @@ all() ->
parse_url,
options,
headers_as_is,
+ selecting_session,
{group, proxy},
{group, ssl},
{group, stream},
@@ -145,6 +146,20 @@ groups() ->
].
+init_per_group(ipv6 = _GroupName, Config) ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ Config;
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end;
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -155,6 +170,9 @@ groups() ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+
+ ?PRINT_SYSTEM_INFO([]),
+
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
ServerRoot = filename:join(PrivDir, "server_root"),
@@ -178,10 +196,11 @@ init_per_suite(Config) ->
{ok, FileInfo} = file:read_file_info(Cgi),
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].
+ [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
+ {server_root, ServerRoot},
+ {doc_root, DocRoot},
+ {local_port, ?IP_PORT},
+ {local_ssl_port, ?SSL_PORT} | Config].
%%--------------------------------------------------------------------
@@ -197,6 +216,7 @@ end_per_suite(Config) ->
application:stop(ssl),
ok.
+
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
%% Case - atom()
@@ -228,12 +248,12 @@ init_per_testcase(initial_server_connect = Case, Config) ->
"~n ~p", [Case, App, ActualError]),
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
+ skip(SkipString);
_:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
init_per_testcase(Case, Config) ->
@@ -243,6 +263,7 @@ init_per_testcase(Case, Timeout, Config) ->
io:format(user,
"~n~n*** INIT ~w:~w[~w] ***"
"~n~n", [?MODULE, Case, Timeout]),
+
PrivDir = ?config(priv_dir, Config),
application:stop(inets),
Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
@@ -252,7 +273,7 @@ init_per_testcase(Case, Timeout, Config) ->
%% inets:enable_trace(max, io, httpd),
%% inets:enable_trace(max, io, httpc),
- inets:enable_trace(max, io, all),
+ %% inets:enable_trace(max, io, all),
NewConfig =
case atom_to_list(Case) of
@@ -336,7 +357,8 @@ init_per_testcase(Case, Timeout, Config) ->
inets:start(httpc,
[{profile, Profile},
{data_dir, PrivDir}], stand_alone),
- httpc:set_options([{ipfamily, inet6}], ProfilePid),
+ ok = httpc:set_options([{ipfamily, inet6}],
+ ProfilePid),
tsp("httpc profile pid: ~p", [ProfilePid]),
[{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
catch
@@ -345,27 +367,67 @@ init_per_testcase(Case, Timeout, Config) ->
"~n ~p", [Case, App, ActualError]),
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
+ skip(SkipString);
_:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
_ ->
+ %% Try inet6fb4 on windows...
+ %% No need? Since it is set above?
+
+ %% tsp("init_per_testcase -> allways try IPv6 on windows"),
+ %% ?RUN_ON_WINDOWS(
+ %% fun() ->
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "set-option ipfamily to inet6fb4"),
+ %% Res = httpc:set_options([{ipfamily, inet6fb4}]),
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "~n Res: ~p", [Res]),
+ %% Res
+ %% end),
+
TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
%% Will start inets
+ tsp("init_per_testcase -> try start server"),
Server = start_http_server(PrivDir, IpConfFile),
[{watchdog, Dog}, {local_server, Server} | TmpConfig2]
end,
+ %% <IPv6>
+ %% Set default ipfamily to the same as the main server has by default
+ %% This makes the client try w/ ipv6 before falling back to ipv4,
+ %% as that is what the server is configured to do.
+ %% Note that this is required for the tests to run on *BSD w/ ipv6 enabled
+ %% as well as on Windows. The Linux behaviour of allowing ipv4 connects
+ %% to ipv6 sockets is not required or even encouraged.
+
+ tsp("init_per_testcase -> Options before ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("init_per_testcase -> Options after ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+
+ %% Note that the IPv6 test case(s) *must* use inet6,
+ %% so this value will be overwritten (see "ipv6_" below).
+ %% </IPv6>
+
%% This will fail for the ipv6_ - cases (but that is ok)
ProxyExceptions = ["localhost", ?IPV6_LOCAL_HOST],
- httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT}, ProxyExceptions}}]),
+ tsp("init_per_testcase -> Options before proxy set: ~n~p",
+ [httpc:get_options(all)]),
+ ok = httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT}, ProxyExceptions}}]),
+ tsp("init_per_testcase -> Options after proxy set: ~n~p",
+ [httpc:get_options(all)]),
inets:enable_trace(max, io, httpc),
%% inets:enable_trace(max, io, all),
%% snmp:set_trace([gen_tcp]),
+ tsp("init_per_testcase(~w) -> done when"
+ "~n NewConfig: ~p"
+ "~n~n", [Case, NewConfig]),
NewConfig.
@@ -404,6 +466,7 @@ end_per_testcase(http_save_to_file = Case, Config) ->
end_per_testcase(Case, Config) ->
io:format(user, "~n~n*** END ~w:~w ***~n~n",
[?MODULE, Case]),
+ dbg:stop(), % ?
case atom_to_list(Case) of
"ipv6_" ++ _Rest ->
tsp("end_per_testcase(~w) -> stop ssl", [Case]),
@@ -448,29 +511,39 @@ http_options(doc) ->
http_options(suite) ->
[];
http_options(Config) when is_list(Config) ->
- {skip, "Not supported by httpd"}.
+ skip("Not supported by httpd").
http_head(doc) ->
["Test http head request against local server."];
http_head(suite) ->
[];
http_head(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",
- case httpc:request(head, {URL, []}, [], []) of
- {ok, {{_,200,_}, [_ | _], []}} ->
- ok;
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- _ ->
- {skip, "Failed to start local http-server"}
- end.
+ tsp("http_head -> entry with"
+ "~n Config: ~p", [Config]),
+ Method = head,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HttpOpts = [],
+ Opts = [],
+ VerifyResult =
+ fun({ok, {{_,200,_}, [_ | _], []}}) ->
+ ok;
+ ({ok, UnexpectedReply}) ->
+ tsp("http_head:verify_fun -> Unexpected Reply: "
+ "~n ~p", [UnexpectedReply]),
+ tsf({unexpected_reply, UnexpectedReply});
+ ({error, Reason} = Error) ->
+ tsp("http_head:verify_fun -> Error reply: "
+ "~n Reason: ~p", [Reason]),
+ tsf({bad_reply, Error})
+ end,
+ simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult).
+
+
%%-------------------------------------------------------------------------
+
http_get(doc) ->
["Test http get request against local server"];
http_get(suite) ->
@@ -487,7 +560,8 @@ http_get(Config) when is_list(Config) ->
Request = {URL, []},
Timeout = timer:seconds(1),
ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
+ HttpOptions1 = [{timeout, Timeout},
+ {connect_timeout, ConnTimeout}],
Options1 = [],
Body =
case httpc:request(Method, Request, HttpOptions1, Options1) of
@@ -515,14 +589,15 @@ http_get(Config) when is_list(Config) ->
tsf({bad_reply, Error2})
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
+
http_post(doc) ->
- ["Test http post request against local server. We do in this case"
- " only care about the client side of the the post. The server"
- " script will not actually use the post data."];
+ ["Test http post request against local server. We do in this case "
+ "only care about the client side of the the post. The server "
+ "script will not actually use the post data."];
http_post(suite) ->
[];
http_post(Config) when is_list(Config) ->
@@ -550,7 +625,7 @@ http_post(Config) when is_list(Config) ->
httpc:request(post, {URL, [{"expect","100-continue"}],
"text/plain", "foobar"}, [], []);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -596,7 +671,7 @@ http_post_streaming(Config) when is_list(Config) ->
"text/plain", {BodyFun, 10}}, [], []);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -620,7 +695,7 @@ http_emulate_lower_versions(Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
inets_test_lib:check_body(Body2);
_->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -681,7 +756,7 @@ http_inets_pipe(Config) when is_list(Config) ->
URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
test_pipeline(URL);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -817,7 +892,7 @@ http_trace(Config) when is_list(Config) ->
tsf({failed, Error})
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
http_async(doc) ->
@@ -852,7 +927,7 @@ http_async(Config) when is_list(Config) ->
ok
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -873,7 +948,7 @@ http_save_to_file(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
Bin == Body;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -903,7 +978,7 @@ http_save_to_file_async(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
Bin == Body;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
http_headers(doc) ->
@@ -960,7 +1035,7 @@ http_headers(Config) when is_list(Config) ->
]}, [], []),
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -1095,9 +1170,9 @@ ssl_head(SslTag, Config) ->
{ok, {{_,200, _}, [_ | _], []}} =
httpc:request(head, {URL, []}, [{ssl, SSLConfig}], []);
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1135,13 +1210,24 @@ ssl_get(SslTag, Config) when is_list(Config) ->
"~n URL: ~p"
"~n SslTag: ~p"
"~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} =
- httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []),
- inets_test_lib:check_body(Body);
+ case httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []) of
+ {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} ->
+ inets_test_lib:check_body(Body),
+ ok;
+ {ok, {StatusLine, Headers, _Body}} ->
+ tsp("ssl_get -> unexpected result: "
+ "~n StatusLine: ~p"
+ "~n Headers: ~p", [StatusLine, Headers]),
+ tsf({unexpected_response, StatusLine, Headers});
+ {error, Reason} ->
+ tsp("ssl_get -> request failed: "
+ "~n Reason: ~p", [Reason]),
+ tsf({request_failed, Reason})
+ end;
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1190,9 +1276,9 @@ ssl_trace(SslTag, Config) when is_list(Config) ->
tsf({failed, Error})
end;
{ok, _} ->
- {skip, "local http-server not started"};
+ skip("local http-server not started");
_ ->
- {skip, "SSL not started"}
+ skip("SSL not started")
end.
@@ -1207,8 +1293,8 @@ http_redirect(Config) when is_list(Config) ->
"~n Config: ~p", [Config]),
case ?config(local_server, Config) of
ok ->
- tsp("http_redirect -> set ipfamily option to inet"),
- ok = httpc:set_options([{ipfamily, inet}]),
+ %% tsp("http_redirect -> set ipfamily option to inet"),
+ %% ok = httpc:set_options([{ipfamily, inet}]),
tsp("http_redirect -> start dummy server inet"),
{DummyServerPid, Port} = dummy_server(ipv4),
@@ -1311,7 +1397,7 @@ http_redirect(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -1448,7 +1534,7 @@ proxy_options(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1469,7 +1555,7 @@ proxy_head(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1488,7 +1574,7 @@ proxy_get(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
%%-------------------------------------------------------------------------
@@ -1529,12 +1615,13 @@ proxy_emulate_lower_versions(Config) when is_list(Config) ->
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
pelv_get(Version) ->
httpc:request(get, {?PROXY_URL, []}, [{version, Version}], []).
+
%%-------------------------------------------------------------------------
proxy_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -1543,8 +1630,8 @@ proxy_trace(suite) ->
proxy_trace(Config) when is_list(Config) ->
%%{ok, {{_,200,_}, [_ | _], "TRACE " ++ _}} =
%% httpc:request(trace, {?PROXY_URL, []}, [], []),
- {skip, "HTTP TRACE is no longer allowed on the ?PROXY_URL server due "
- "to security reasons"}.
+ skip("HTTP TRACE is no longer allowed on the ?PROXY_URL server due "
+ "to security reasons").
%%-------------------------------------------------------------------------
@@ -1567,7 +1654,7 @@ proxy_post(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1592,7 +1679,7 @@ proxy_put(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1617,7 +1704,7 @@ proxy_delete(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1651,9 +1738,10 @@ proxy_headers(Config) when is_list(Config) ->
]}, [], []),
ok;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
+
%%-------------------------------------------------------------------------
proxy_auth(doc) ->
["Test the code for sending of proxy authorization."];
@@ -1673,7 +1761,7 @@ proxy_auth(Config) when is_list(Config) ->
tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1717,7 +1805,7 @@ proxy_page_does_not_exist(Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [], []),
ok;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1736,6 +1824,7 @@ proxy_https_not_supported(Config) when is_list(Config) ->
tsf({unexpected_reason, Result})
end.
+
%%-------------------------------------------------------------------------
http_stream(doc) ->
@@ -1765,6 +1854,7 @@ http_stream(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+
http_stream_once(doc) ->
["Test the option stream for asynchrony requests"];
http_stream_once(suite) ->
@@ -1772,12 +1862,12 @@ 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 = httpc:set_options([{ipfamily, inet}]),
p("http_stream_once -> start dummy server", []),
{DummyServerPid, Port} = dummy_server(ipv4),
-
+
PortStr = integer_to_list(Port),
p("http_stream_once -> once", []),
once(?URL_START ++ PortStr ++ "/once.html"),
@@ -1785,14 +1875,14 @@ http_stream_once(Config) when is_list(Config) ->
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 = httpc:set_options([{ipfamily, inet6fb4}]),
p("http_stream_once -> done", []),
ok.
-
+
once(URL) ->
p("once -> issue sync request for ~p", [URL]),
{ok, {{_,200,_}, [_ | _], Body}} =
@@ -1861,7 +1951,7 @@ proxy_stream(Config) when is_list(Config) ->
Body == binary_to_list(StreamedBody);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1884,7 +1974,7 @@ parse_url(Config) when is_list(Config) ->
http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
[{foo, false}]),
{error,
- {malformed_url,"http://2010:836B:4179::836B:4179/foobar.html"}} =
+ {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
%% ipv4
@@ -1900,8 +1990,8 @@ parse_url(Config) when is_list(Config) ->
http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
%% Scheme error
- {error,no_scheme} = http_uri:parse("localhost/foobar.html"),
- {error,{not_supported_scheme,localhost}} =
+ {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
+ {error, {malformed_url, _, _}} =
http_uri:parse("localhost:8888/foobar.html"),
%% Query
@@ -1964,7 +2054,7 @@ ipv6_essl(Config) when is_list(Config) ->
ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
%% Check if we are a IPv6 host
- tsp("ipv6 -> verify ipv6 support", []),
+ tsp("ipv6 -> verify ipv6 support"),
case inets_test_lib:has_ipv6_support(Config) of
{ok, Addr} ->
tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
@@ -1995,12 +2085,13 @@ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
end,
ok;
_ ->
- tsp("ipv6 -> ipv6 not supported", []),
- {skip, "Host does not support IPv6"}
+ tsp("ipv6 -> ipv6 not supported"),
+ skip("Host does not support IPv6")
end.
%%-------------------------------------------------------------------------
+
headers_as_is(doc) ->
["Test the option headers_as_is"];
headers_as_is(suite) ->
@@ -2018,6 +2109,321 @@ headers_as_is(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+
+selecting_session(doc) ->
+ ["Test selection of sessions - OTP-9847"];
+selecting_session(suite) ->
+ [];
+selecting_session(Config) when is_list(Config) ->
+ tsp("selecting_session -> entry with"
+ "~n Config: ~p", [Config]),
+
+ tsp("selecting_session -> set ipfamily to inet"),
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ tsp("selecting_session -> start server"),
+ {ServerPid, Port} = otp_9847_server(),
+
+ PortStr = integer_to_list(Port),
+ URL = ?URL_START ++ PortStr ++ "/index.html",
+
+ tsp("selecting_session -> issue the first batch (three) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun1 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 3, 3, false)),
+ tsp("selecting_session -> sleep some (1) to make sure nothing lingers"),
+ ?SLEEP(5000),
+ tsp("selecting_session -> "
+ "instruct the server to reply to the first request"),
+ ServerPid ! {answer, true},
+ receive
+ {answer, true} ->
+ tsp("selecting_session -> "
+ "received ack from server to reply to the first request"),
+ ok
+ end,
+ tsp("selecting_session -> issue the second batch (four) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun2 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 4, 1, true)),
+ tsp("selecting_session -> sleep some (2) to make sure nothing lingers"),
+ ?SLEEP(5000),
+
+ tsp("selecting_session -> stop server"),
+ ServerPid ! stop,
+ tsp("selecting_session -> set ipfamily (back) to inet6fb4"),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("selecting_session -> done"),
+ ok.
+
+reqs(URL, ServerPid, NumReqs, NumHandlers, InitialSync) ->
+ tsp("reqs -> entry with"
+ "~n URL: ~p"
+ "~n ServerPid: ~w"
+ "~n NumReqs: ~w"
+ "~n NumHandlers: ~w"
+ "~n InitialSync: ~w",
+ [URL, ServerPid, NumReqs, NumHandlers, InitialSync]),
+ Handlers = reqs2(URL, NumReqs, [], InitialSync),
+ tsp("reqs -> "
+ "~n Handlers: ~w", [Handlers]),
+ case length(Handlers) of
+ NumHandlers ->
+ tsp("reqs -> "
+ "~n NumHandlers: ~w", [NumHandlers]),
+ ServerPid ! num_handlers,
+ receive
+ {num_handlers, NumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n NumHandlers: ~w", [NumHandlers]),
+ Handlers;
+ {num_handlers, WrongNumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers1, WrongNumHandlers, NumHandlers})
+ end;
+ WrongNumHandlers ->
+ tsp("reqs -> "
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers2, WrongNumHandlers, NumHandlers})
+ end.
+
+
+reqs2(_URL, 0, Acc, _Sync) ->
+ lists:reverse(Acc);
+reqs2(URL, Num, Acc, Sync) ->
+ tsp("reqs2 -> entry with"
+ "~n Num: ~w"
+ "~n Sync: ~w", [Num, Sync]),
+ case httpc:request(get, {URL, []}, [], [{sync, Sync}]) of
+ {ok, _Reply} ->
+ tsp("reqs2 -> successful request: ~p", [_Reply]),
+ receive
+ {handler, Handler, _Manager} ->
+ %% This is when a new handler is created
+ tsp("reqs2 -> received handler: ~p", [Handler]),
+ case lists:member(Handler, Acc) of
+ true ->
+ tsp("reqs2 -> duplicate handler"),
+ exit({duplicate_handler, Handler, Num, Acc});
+ false ->
+ tsp("reqs2 -> wait for data ack"),
+ receive
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ case Sync of
+ true ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ false);
+ false ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ Sync)
+ end
+ end
+ end;
+
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ reqs2(URL, Num-1, Acc, false)
+
+ end;
+
+ {error, Reason} ->
+ tsp("reqs2 -> request ~w failed: ~p", [Num, Reason]),
+ exit({request_failed, Reason, Num, Acc})
+ end.
+
+otp_9847_server() ->
+ TC = self(),
+ Pid = spawn_link(fun() -> otp_9847_server_init(TC) end),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+otp_9847_server_init(TC) ->
+ tsp("otp_9847_server_init -> entry with"
+ "~n TC: ~p", [TC]),
+ {ok, ListenSocket} =
+ gen_tcp:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ tsp("otp_9847_server_init -> listen socket created: "
+ "~n ListenSocket: ~p", [ListenSocket]),
+ {ok, Port} = inet:port(ListenSocket),
+ tsp("otp_9847_server_init -> Port: ~p", [Port]),
+ TC ! {port, Port},
+ otp_9847_server_main(TC, ListenSocket, false, []).
+
+otp_9847_server_main(TC, ListenSocket, Answer, Handlers) ->
+ tsp("otp_9847_server_main -> entry with"
+ "~n TC: ~p"
+ "~n ListenSocket: ~p"
+ "~n Answer: ~p"
+ "~n Handlers: ~p", [TC, ListenSocket, Answer, Handlers]),
+ case gen_tcp:accept(ListenSocket, 1000) of
+ {ok, Sock} ->
+ tsp("otp_9847_server_main -> accepted"
+ "~n Sock: ~p", [Sock]),
+ {Handler, Mon, Port} = otp_9847_handler(TC, Sock, Answer),
+ tsp("otp_9847_server_main -> handler ~p created for ~w",
+ [Handler, Port]),
+ gen_tcp:controlling_process(Sock, Handler),
+ tsp("otp_9847_server_main -> control transfer"),
+ Handler ! owner,
+ tsp("otp_9847_server_main -> "
+ "handler ~p informed of owner transfer", [Handler]),
+ TC ! {handler, Handler, self()},
+ tsp("otp_9847_server_main -> "
+ "TC ~p informed of handler ~p", [TC, Handler]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ [{Handler, Mon, Sock, Port}|Handlers]);
+
+ {error, timeout} ->
+ tsp("otp_9847_server_main -> timeout"),
+ receive
+ {answer, true} ->
+ tsp("otp_9847_server_main -> received answer request"),
+ TC ! {answer, true},
+ otp_9847_server_main(TC, ListenSocket, true, Handlers);
+
+ {'DOWN', _Mon, process, Pid, _Reason} ->
+ %% Could be one of the handlers
+ tsp("otp_9847_server_main -> received DOWN for ~p", [Pid]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ lists:keydelete(Pid, 1, Handlers));
+
+ num_handlers ->
+ tsp("otp_9847_server_main -> "
+ "received request for number of handlers (~w)",
+ [length(Handlers)]),
+ TC ! {num_handlers, length(Handlers)},
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers);
+
+ stop ->
+ tsp("otp_9847_server_main -> received stop request"),
+ %% Stop all handlers (just in case)
+ Pids = [Handler || {Handler, _, _} <- Handlers],
+ lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
+ exit(normal);
+
+ Any ->
+ tsp("otp_9847_server_main -> received"
+ "~n Any: ~p", [Any]),
+ exit({crap, Any})
+
+ after 0 ->
+ tsp("otp_9847_server_main -> nothing in queue"),
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers)
+ end;
+
+ Error ->
+ exit(Error)
+ end.
+
+
+otp_9847_handler(TC, Sock, Answer) ->
+ tsp("otp_9847_handler -> entry with"
+ "~n TC: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Sock, Answer]),
+ Self = self(),
+ {Pid, Mon} =
+ spawn_opt(fun() ->
+ otp_9847_handler_init(TC, Self, Sock, Answer)
+ end,
+ [monitor]),
+ receive
+ {port, Port} ->
+ tsp("otp_9847_handler -> received port message (from ~p)"
+ "~n Port: ~p", [Pid, Port]),
+ {Pid, Mon, Port}
+ end.
+
+
+otp_9847_handler_init(TC, Server, Sock, Answer) ->
+ tsp("otp_9847_handler_init -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Server, Sock, Answer]),
+ {ok, Port} = inet:port(Sock),
+ Server ! {port, Port},
+ receive
+ owner ->
+ tsp("otp_9847_handler_init -> "
+ "received owner message - activate socket"),
+ inet:setopts(Sock, [{active, true}]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, [?HTTP_MAX_HEADER_SIZE])
+ end.
+
+otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs) ->
+ tsp("otp_9847_handler_main -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p"
+ "~n ParseArgs: ~p", [TC, Server, Sock, Answer, ParseArgs]),
+ receive
+ stop ->
+ tsp("otp_9847_handler_main -> received stop request"),
+ exit(normal);
+
+ {tcp, Sock, _Data} when Answer =:= false ->
+ tsp("otp_9847_handler_main -> received tcp data - no answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ %% Ignore all data
+ otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs);
+
+ {tcp, Sock, Data} when Answer =:= true ->
+ tsp("otp_9847_handler_main -> received tcp data - answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ NewParseArgs = otp_9847_handler_request(Sock, [Data|ParseArgs]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, NewParseArgs);
+
+ {tcp_closed, Sock} ->
+ tsp("otp_9847_handler_main -> received tcp socket closed"),
+ exit(normal);
+
+ {tcp_error, Sock, Reason} ->
+ tsp("otp_9847_handler_main -> socket error: ~p", [Reason]),
+ (catch gen_tcp:close(Sock)),
+ exit(normal)
+
+ %% after 30000 ->
+ %% gen_tcp:close(Sock),
+ %% exit(normal)
+ end.
+
+otp_9847_handler_request(Sock, Args) ->
+ Msg =
+ case httpd_request:parse(Args) of
+ {ok, {_, "/index.html" = _RelUrl, _, _, _}} ->
+ B =
+ "<HTML><BODY>" ++
+ "...some body part..." ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end,
+ gen_tcp:send(Sock, Msg),
+ [?HTTP_MAX_HEADER_SIZE].
+
+
+
+%%-------------------------------------------------------------------------
+
options(doc) ->
["Test the option parameters."];
options(suite) ->
@@ -2037,11 +2443,12 @@ options(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [{timeout, infinity}],
[{full_result, false}]);
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
+
http_invalid_http(doc) ->
["Test parse error"];
http_invalid_http(suite) ->
@@ -2149,7 +2556,7 @@ proxy_not_modified_otp_6821(Config) when is_list(Config) ->
undefined ->
provocate_not_modified_bug(?PROXY_URL);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -2551,7 +2958,7 @@ otp_8106_pid(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2571,7 +2978,7 @@ otp_8106_fun(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2591,7 +2998,7 @@ otp_8106_mfa(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2740,7 +3147,7 @@ otp_8352(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2855,6 +3262,7 @@ otp_8739_dummy_server_main(_Parent, ListenSocket) ->
exit(Error)
end.
+
%%-------------------------------------------------------------------------
initial_server_connect(doc) ->
@@ -2934,7 +3342,11 @@ create_config(FileName, ComType, Port, PrivDir, ServerRoot, DocRoot,
" mod_include mod_dir mod_get mod_head"
" mod_log mod_disk_log mod_trace",
+ %% BindAddress = "*|inet", % Force the use of IPv4
+ BindAddress = "*", % This corresponds to using IpFamily inet6fb4
+
HttpConfig = [
+ cline(["BindAddress ", BindAddress]),
cline(["Port ", integer_to_list(Port)]),
cline(["ServerName ", "httpc_test"]),
cline(["SocketType ", atom_to_list(ComType)]),
@@ -3493,6 +3905,34 @@ pick_header(Headers, Name) ->
Val
end.
+
+%% -------------------------------------------------------------------------
+
+simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult)
+ when (is_list(Config) andalso
+ is_atom(Method) andalso
+ is_list(HttpOpts) andalso
+ is_list(Opts) andalso
+ is_function(VerifyResult, 1)) ->
+ tsp("request_and_verify -> entry with"
+ "~n Method: ~p"
+ "~n Request: ~p"
+ "~n HttpOpts: ~p"
+ "~n Opts: ~p", [Method, Request, HttpOpts, Opts]),
+ case ?config(local_server, Config) of
+ ok ->
+ tsp("request_and_verify -> local-server running"),
+ Result = (catch httpc:request(Method, Request, HttpOpts, Opts)),
+ VerifyResult(Result);
+ _ ->
+ tsp("request_and_verify -> local-server *not* running - skip"),
+ hard_skip("Local http-server not running")
+ end.
+
+
+
+
not_implemented_yet() ->
exit(not_implemented_yet).
@@ -3503,9 +3943,9 @@ p(F, A) ->
io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
tsp(F) ->
- inets_test_lib:tsp(F).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
tsp(F, A) ->
- inets_test_lib:tsp(F, A).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
tsf(Reason) ->
test_server:fail(Reason).
@@ -3544,6 +3984,8 @@ dummy_ssl_server_hang_loop(_) ->
ok
end.
+hard_skip(Reason) ->
+ throw(skip(Reason)).
skip(Reason) ->
{skip, Reason}.