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.erl1009
1 files changed, 754 insertions, 255 deletions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index f95fb93669..1cdd96f0b0 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,7 +146,13 @@ 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.
@@ -163,6 +170,9 @@ end_per_group(_GroupName, Config) ->
%% 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"),
@@ -186,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].
%%--------------------------------------------------------------------
@@ -205,6 +216,7 @@ end_per_suite(Config) ->
application:stop(ssl),
ok.
+
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
%% Case - atom()
@@ -226,9 +238,7 @@ init_per_testcase(initial_server_connect = Case, Config) ->
%% this test case does not work unless it does
try
begin
- ensure_started(crypto),
- ensure_started(public_key),
- ensure_started(ssl),
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
inets:start(),
Config
end
@@ -238,22 +248,23 @@ 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) ->
init_per_testcase(Case, 2, Config).
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),
- tsp("init_per_testcase -> stop inets"),
+ 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)),
TmpConfig = lists:keydelete(watchdog, 1, Config),
@@ -262,15 +273,17 @@ 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
[$s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
[$e, $s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
init_per_testcase_ssl(essl, PrivDir, SslConfFile,
[{watchdog, Dog} | TmpConfig]);
@@ -282,19 +295,19 @@ init_per_testcase(Case, Timeout, Config) ->
inets:start(),
tsp("init_per_testcase -> "
"[proxy case] start crypto, public_key and ssl"),
- try ensure_started([crypto, public_key, ssl]) of
+ try ?ENSURE_STARTED([crypto, public_key, ssl]) of
ok ->
[{watchdog, Dog} | TmpConfig]
catch
throw:{error, {failed_starting, App, _}} ->
SkipString =
"Could not start " ++ atom_to_list(App),
- {skip, SkipString};
- _:X ->
+ skip(SkipString);
+ _:X ->
SkipString =
lists:flatten(
io_lib:format("Failed starting apps: ~p", [X])),
- {skip, SkipString}
+ skip(SkipString)
end;
_ ->
@@ -323,20 +336,20 @@ init_per_testcase(Case, Timeout, Config) ->
],
case lists:member(Rest, BadCases) of
true ->
- [{skip, "TC and server not compatible"}|
+ [skip("TC and server not compatible") |
TmpConfig];
false ->
inets:start(),
[{watchdog, Dog} | TmpConfig]
end;
false ->
- [{skip, "proxy not responding"} | TmpConfig]
+ [skip("proxy not responding") | TmpConfig]
end
end;
"ipv6_" ++ _Rest ->
- %% Ensure needed apps (crypto, public_key and ssl) started
- try ensure_started([crypto, public_key, ssl]) of
+ %% Ensure needed apps (crypto, public_key and ssl) are started
+ try ?ENSURE_STARTED([crypto, public_key, ssl]) of
ok ->
Profile = ipv6,
%% A stand-alone profile is represented by a pid()
@@ -344,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
@@ -353,28 +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),
- Server =
- %% Will start inets
- inets_test_lib:start_http_server(
- filename:join(PrivDir, IpConfFile)),
+ %% Will start inets
+ tsp("init_per_testcase -> try start server"),
+ Server = start_http_server(PrivDir, IpConfFile),
[{watchdog, Dog}, {local_server, Server} | TmpConfig2]
end,
- %% This will fail for the ipv6_ - cases (but that is ok)
- httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
- ["localhost", ?IPV6_LOCAL_HOST]}},
- {ipfamily, inet6fb4}]),
+ %% <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],
+ 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.
@@ -390,7 +443,10 @@ init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
[{local_ssl_server, Server} | Config2].
-
+start_http_server(ConfDir, ConfFile) ->
+ inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
+
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -410,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]),
@@ -454,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) ->
@@ -493,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
@@ -521,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) ->
@@ -556,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.
%%-------------------------------------------------------------------------
@@ -602,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.
@@ -626,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.
@@ -687,121 +756,163 @@ 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.
test_pipeline(URL) ->
- p("test_pipeline -> entry with"
- "~n URL: ~p", [URL]),
-
- httpc:set_options([{pipeline_timeout, 50000}]),
-
- p("test_pipeline -> issue (async) request 1"),
- {ok, RequestId1} =
+ p("test_pipeline -> entry with"
+ "~n URL: ~p", [URL]),
+
+ httpc:set_options([{pipeline_timeout, 50000}]),
+
+ p("test_pipeline -> issue (async) request 1"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA1} =
httpc: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} =
+ tsp("RequestIdA1: ~p", [RequestIdA1]),
+ p("test_pipeline -> RequestIdA1: ~p"
+ "~n when profile info: ~p", [RequestIdA1, httpc:info()]),
+
+ %% Make sure pipeline is initiated
+ p("test_pipeline -> sleep some", []),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA2} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId2: ~p", [RequestId2]),
- p("test_pipeline -> RequestId2: ~p", [RequestId2]),
-
- p("test_pipeline -> issue (sync) request 3"),
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ {ok, RequestIdA3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdA4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4]),
+ p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]),
+
+ p("test_pipeline -> issue (sync) request 3"),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
httpc: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)
- 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} =
+
+ p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ pipeline_await_async_reply([{RequestIdA1, a1, 200},
+ {RequestIdA2, a2, 200},
+ {RequestIdA3, a3, 200},
+ {RequestIdA4, a4, 200}], ?MINS(1)),
+
+ p("test_pipeline -> sleep some"
+ "~n when profile info: ~p", [httpc:info()]),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request B1, B2, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdB1} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId3: ~p", [RequestId3]),
- p("test_pipeline -> RequestId3: ~p", [RequestId3]),
-
- p("test_pipeline -> issue (async) request 5"),
- {ok, RequestId4} =
+ {ok, RequestIdB2} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId4: ~p~n", [RequestId4]),
- p("test_pipeline -> RequestId4: ~p", [RequestId4]),
-
- p("test_pipeline -> cancel (async) request 4"),
- ok = httpc: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)
- after 3000 ->
- ok
- end,
-
- p("test_pipeline -> expect reply for (async) request 4"),
- Body =
- receive
- {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"),
+ {ok, RequestIdB3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdB4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]),
+ p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]),
+
+ p("test_pipeline -> cancel (async) request B2"
+ "~n when profile info: ~p", [httpc:info()]),
+ ok = httpc:cancel_request(RequestIdB2),
+
+ p("test_pipeline -> "
+ "expect *no* reply for cancelled (async) request B2 (for 3 secs)"
+ "~n when profile info: ~p", [httpc:info()]),
+ receive
+ {http, {RequestIdB2, _}} ->
+ tsf(http_cancel_request_failed)
+ after 3000 ->
+ ok
+ end,
+
+ p("test_pipeline -> expect reply for (async) request B1, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200},
+ {RequestIdB3, b3, 200},
+ {RequestIdB4, b4, 200}], ?MINS(1)),
+ [{b1, Body}|_] = Bodies,
+
+ p("test_pipeline -> check reply for (async) request B1"
+ "~n when profile info: ~p", [httpc:info()]),
inets_test_lib:check_body(binary_to_list(Body)),
-
- p("test_pipeline -> ensure no unexpected incomming"),
+
+ p("test_pipeline -> ensure no unexpected incomming"
+ "~n when profile info: ~p", [httpc:info()]),
receive
{http, Any} ->
- test_server:fail({unexpected_message, Any})
+ tsf({unexpected_message, Any})
after 500 ->
ok
end,
-
- p("test_pipeline -> done"),
+
+ p("test_pipeline -> done"
+ "~n when profile info: ~p", [httpc:info()]),
ok.
+pipeline_await_async_reply(ReqIds, Timeout) ->
+ pipeline_await_async_reply(ReqIds, Timeout, []).
+
+pipeline_await_async_reply([], _, Acc) ->
+ lists:keysort(1, Acc);
+pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 ->
+ T1 = inets_test_lib:timestamp(),
+ p("pipeline_await_async_reply -> await replies"
+ "~n ReqIds: ~p"
+ "~n Timeout: ~p", [ReqIds, Timeout]),
+ receive
+ {http, {RequestId, {{_, Status, _}, _, Body}}} ->
+ p("pipeline_await_async_reply -> received reply for"
+ "~n RequestId: ~p"
+ "~n Status: ~p", [RequestId, Status]),
+ case lists:keysearch(RequestId, 1, ReqIds) of
+ {value, {RequestId, N, Status}} ->
+ p("pipeline_await_async_reply -> "
+ "found expected request ~w", [N]),
+ ReqIds2 = lists:keydelete(RequestId, 1, ReqIds),
+ NewTimeout = Timeout - (inets_test_lib:timestamp()-T1),
+ pipeline_await_async_reply(ReqIds2, NewTimeout,
+ [{N, Body} | Acc]);
+ {value, {RequestId, N, WrongStatus}} ->
+ p("pipeline_await_async_reply -> "
+ "found request ~w with wrong status", [N]),
+ tsf({reply_with_unexpected_status,
+ {RequestId, N, WrongStatus}});
+ false ->
+ tsf({unexpected_reply, {RequestId, Status}})
+ end;
+ {http, Msg} ->
+ tsf({unexpected_reply, Msg})
+ after Timeout ->
+ receive
+ Any ->
+ tsp("pipeline_await_async_reply -> "
+ "received unknown data after timeout: "
+ "~n ~p", [Any]),
+ tsf({timeout, {unknown, Any}})
+ end
+ end;
+pipeline_await_async_reply(ReqIds, _, Acc) ->
+ tsp("pipeline_await_async_reply -> "
+ "timeout: "
+ "~n ~p"
+ "~nwhen"
+ "~n ~p", [ReqIds, Acc]),
+ tsf({timeout, ReqIds, Acc}).
+
+
+
%%-------------------------------------------------------------------------
http_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -816,14 +927,14 @@ http_trace(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
ok;
{ok, {{_,200,_}, [_ | _], WrongBody}} ->
- test_server:fail({wrong_body, WrongBody});
+ tsf({wrong_body, WrongBody});
{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"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
http_async(doc) ->
@@ -843,7 +954,7 @@ http_async(Config) when is_list(Config) ->
{http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
BinBody;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
inets_test_lib:check_body(binary_to_list(Body)),
@@ -853,12 +964,12 @@ http_async(Config) when is_list(Config) ->
ok = httpc:cancel_request(NewRequestId),
receive
{http, {NewRequestId, _NewResult}} ->
- test_server:fail(http_cancel_request_failed)
+ tsf(http_cancel_request_failed)
after 3000 ->
ok
end;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -879,7 +990,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.
@@ -902,14 +1013,14 @@ http_save_to_file_async(Config) when is_list(Config) ->
{http, {RequestId, saved_to_file}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
{ok, Bin} = file:read_file(FilePath),
{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) ->
@@ -966,7 +1077,7 @@ http_headers(Config) when is_list(Config) ->
]}, [], []),
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
%%-------------------------------------------------------------------------
@@ -1101,9 +1212,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.
@@ -1141,13 +1252,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.
@@ -1196,9 +1318,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.
@@ -1213,8 +1335,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),
@@ -1317,7 +1439,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,13 +1570,13 @@ proxy_options(Config) when is_list(Config) ->
{value, {"allow", _}} ->
ok;
_ ->
- test_server:fail(http_options_request_failed)
+ tsf(http_options_request_failed)
end;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1472,10 +1594,10 @@ proxy_head(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], []}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1491,10 +1613,10 @@ proxy_get(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], Body = [_ | _]}} ->
inets_test_lib:check_body(Body);
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
%%-------------------------------------------------------------------------
@@ -1535,12 +1657,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."];
@@ -1549,8 +1672,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").
%%-------------------------------------------------------------------------
@@ -1570,10 +1693,10 @@ proxy_post(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1595,10 +1718,10 @@ proxy_put(Config) when is_list(Config) ->
{ok, {{_,405,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1620,10 +1743,10 @@ proxy_delete(Config) when is_list(Config) ->
{ok, {{_,404,_}, [_ | _], [_ | _]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1657,9 +1780,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."];
@@ -1676,10 +1800,10 @@ proxy_auth(Config) when is_list(Config) ->
{ok, {{_,200, _}, [_ | _], [_|_]}} ->
ok;
Unexpected ->
- test_server:fail({unexpected_result, Unexpected})
+ tsf({unexpected_result, Unexpected})
end;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1723,7 +1847,7 @@ proxy_page_does_not_exist(Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [], []),
ok;
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1742,6 +1866,7 @@ proxy_https_not_supported(Config) when is_list(Config) ->
tsf({unexpected_reason, Result})
end.
+
%%-------------------------------------------------------------------------
http_stream(doc) ->
@@ -1762,7 +1887,7 @@ http_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
@@ -1771,6 +1896,7 @@ http_stream(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+
http_stream_once(doc) ->
["Test the option stream for asynchrony requests"];
http_stream_once(suite) ->
@@ -1778,12 +1904,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"),
@@ -1791,14 +1917,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}} =
@@ -1817,7 +1943,7 @@ once(URL) ->
[RequestId, Pid]),
Pid;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
tsp("once -> request handler: ~p", [NewPid]),
@@ -1860,14 +1986,14 @@ proxy_stream(Config) when is_list(Config) ->
{http, {RequestId, stream_start, _Headers}} ->
ok;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end,
StreamedBody = receive_streamed_body(RequestId, <<>>),
Body == binary_to_list(StreamedBody);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -1878,42 +2004,53 @@ parse_url(suite) ->
[];
parse_url(Config) when is_list(Config) ->
%% ipv6
- {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}
- = http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ 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
- {http,[],"127.0.0.1",80,"/foobar.html",[]} =
+ {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
http_uri:parse("http://127.0.0.1/foobar.html"),
%% host
- {http,[],"localhost",8888,"/foobar.html",[]} =
+ {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
http_uri:parse("http://localhost:8888/foobar.html"),
%% Userinfo
- {http,"nisse:foobar","localhost",8888,"/foobar.html",[]} =
+ {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
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
- {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"} =
+ {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
%% Esc chars
- {http,[],"www.somedomain.com",80,"/%2Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {http,[],"www.somedomain.com",80,"/%252Eabc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {http,[],"www.somedomain.com",80,"/%25abc",[]} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
http_uri:parse("http://www.somedomain.com/%25abc"),
- {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"} =
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
+
+
ok.
@@ -1959,7 +2096,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]),
@@ -1990,12 +2127,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) ->
@@ -2013,6 +2151,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) ->
@@ -2032,11 +2485,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) ->
@@ -2058,12 +2512,14 @@ http_invalid_http(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+-define(GOOGLE, "www.google.com").
+
hexed_query_otp_6191(doc) ->
[];
hexed_query_otp_6191(suite) ->
[];
hexed_query_otp_6191(Config) when is_list(Config) ->
- Google = "www.google.com",
+ Google = ?GOOGLE,
GoogleSearch = "http://" ++ Google ++ "/search",
Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
URI1 = GoogleSearch ++ Search1,
@@ -2072,11 +2528,32 @@ hexed_query_otp_6191(Config) when is_list(Config) ->
Search3 = "?hl=en&q=%foo",
URI3 = GoogleSearch ++ Search3,
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI1),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI2),
- {http, [], Google, 80, "/search", _} = http_uri:parse(URI3),
+ Verify1 =
+ fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
+ (_) -> error
+ end,
+ Verify2 = Verify1,
+ Verify3 = Verify1,
+ verify_uri(URI1, Verify1),
+ verify_uri(URI2, Verify2),
+ verify_uri(URI3, Verify3),
ok.
+verify_uri(URI, Verify) ->
+ case http_uri:parse(URI) of
+ {ok, ParsedURI} ->
+ case Verify(ParsedURI) of
+ ok ->
+ ok;
+ error ->
+ Reason = {unexpected_parse_result, URI, ParsedURI},
+ ERROR = {error, Reason},
+ throw(ERROR)
+ end;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
%%-------------------------------------------------------------------------
@@ -2121,7 +2598,7 @@ proxy_not_modified_otp_6821(Config) when is_list(Config) ->
undefined ->
provocate_not_modified_bug(?PROXY_URL);
Reason ->
- {skip, Reason}
+ skip(Reason)
end.
@@ -2523,7 +3000,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.
@@ -2543,7 +3020,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.
@@ -2563,7 +3040,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.
@@ -2712,7 +3189,7 @@ otp_8352(Config) when is_list(Config) ->
ok;
_ ->
- {skip, "Failed to start local http-server"}
+ skip("Failed to start local http-server")
end.
@@ -2827,6 +3304,7 @@ otp_8739_dummy_server_main(_Parent, ListenSocket) ->
exit(Error)
end.
+
%%-------------------------------------------------------------------------
initial_server_connect(doc) ->
@@ -2906,7 +3384,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)]),
@@ -2945,7 +3427,7 @@ receive_streamed_body(RequestId, Body) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
receive_streamed_body(RequestId, Body, Pid) ->
@@ -2959,7 +3441,7 @@ receive_streamed_body(RequestId, Body, Pid) ->
{http, {RequestId, stream_end, _Headers}} ->
Body;
{http, Msg} ->
- test_server:fail(Msg)
+ tsf(Msg)
end.
%% Perform a synchronous stop
@@ -3417,7 +3899,7 @@ handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
end.
check_cookie([]) ->
- test_server:fail(no_cookie_header);
+ tsf(no_cookie_header);
check_cookie(["cookie:" ++ _Value | _]) ->
ok;
check_cookie([_Head | Tail]) ->
@@ -3465,6 +3947,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).
@@ -3475,9 +3985,9 @@ p(F, A) ->
io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
tsp(F) ->
- tsp(F, []).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
tsf(Reason) ->
test_server:fail(Reason).
@@ -3516,19 +4026,8 @@ dummy_ssl_server_hang_loop(_) ->
ok
end.
+hard_skip(Reason) ->
+ throw(skip(Reason)).
-ensure_started([]) ->
- ok;
-ensure_started([App|Apps]) ->
- ensure_started(App),
- ensure_started(Apps);
-ensure_started(App) when is_atom(App) ->
- case (catch application:start(App)) of
- ok ->
- ok;
- {error, {already_started, _}} ->
- ok;
- Error ->
- throw({error, {failed_starting, App, Error}})
- end.
-
+skip(Reason) ->
+ {skip, Reason}.