diff options
Diffstat (limited to 'lib/inets/test/httpc_SUITE.erl')
-rw-r--r-- | lib/inets/test/httpc_SUITE.erl | 638 |
1 files changed, 387 insertions, 251 deletions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 63935a2352..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 @@ -114,13 +114,10 @@ groups() -> proxy_page_does_not_exist, proxy_https_not_supported]}, {ssl, [], [ssl_head, - ossl_head, essl_head, ssl_get, - ossl_get, essl_get, ssl_trace, - ossl_trace, essl_trace]}, {stream, [], [http_stream, http_stream_once, @@ -149,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. @@ -167,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"), @@ -190,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]. %%-------------------------------------------------------------------- @@ -209,6 +216,7 @@ end_per_suite(Config) -> application:stop(ssl), ok. + %%-------------------------------------------------------------------- %% Function: init_per_testcase(Case, Config) -> Config %% Case - atom() @@ -230,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 @@ -242,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) -> @@ -257,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)), @@ -271,14 +278,12 @@ init_per_testcase(Case, Timeout, Config) -> 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]); - [$o, $s, $s, $l | _] -> - init_per_testcase_ssl(ossl, 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]); @@ -290,7 +295,7 @@ 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 @@ -343,8 +348,8 @@ init_per_testcase(Case, Timeout, Config) -> 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() @@ -352,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 @@ -361,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], - http: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. @@ -420,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]), @@ -464,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) -> @@ -503,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 @@ -531,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) -> @@ -566,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. %%------------------------------------------------------------------------- @@ -612,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. @@ -636,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. @@ -697,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} -> - tsf(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} -> - tsf(Msg2) - end; - {http, Msg3} -> - tsf(Msg3) - after 60000 -> - receive Any1 -> - tsp("received crap after timeout: ~n ~p", [Any1]), - tsf({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, _}} -> - tsf(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} -> - tsf(Msg4) - after 60000 -> - receive Any2 -> - tsp("received crap after timeout: ~n ~p", [Any2]), - tsf({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} -> 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."]; @@ -833,7 +934,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) -> @@ -868,7 +969,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. %%------------------------------------------------------------------------- @@ -889,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. @@ -919,7 +1020,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) -> @@ -976,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. %%------------------------------------------------------------------------- @@ -1079,13 +1180,6 @@ ssl_head(suite) -> ssl_head(Config) when is_list(Config) -> ssl_head(ssl, Config). -ossl_head(doc) -> - ["Same as http_head/1 but over ssl sockets."]; -ossl_head(suite) -> - []; -ossl_head(Config) when is_list(Config) -> - ssl_head(ossl, Config). - essl_head(doc) -> ["Same as http_head/1 but over ssl sockets."]; essl_head(suite) -> @@ -1108,8 +1202,6 @@ ssl_head(SslTag, Config) -> case SslTag of ssl -> SSLOptions; - ossl -> - {ossl, SSLOptions}; essl -> {essl, SSLOptions} end, @@ -1120,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. @@ -1134,13 +1226,6 @@ ssl_get(suite) -> ssl_get(Config) when is_list(Config) -> ssl_get(ssl, Config). -ossl_get(doc) -> - ["Same as http_get/1 but over ssl sockets."]; -ossl_get(suite) -> - []; -ossl_get(Config) when is_list(Config) -> - ssl_get(ossl, Config). - essl_get(doc) -> ["Same as http_get/1 but over ssl sockets."]; essl_get(suite) -> @@ -1160,8 +1245,6 @@ ssl_get(SslTag, Config) when is_list(Config) -> case SslTag of ssl -> SSLOptions; - ossl -> - {ossl, SSLOptions}; essl -> {essl, SSLOptions} end, @@ -1169,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. @@ -1187,13 +1281,6 @@ ssl_trace(suite) -> ssl_trace(Config) when is_list(Config) -> ssl_trace(ssl, Config). -ossl_trace(doc) -> - ["Same as http_trace/1 but over ssl sockets."]; -ossl_trace(suite) -> - []; -ossl_trace(Config) when is_list(Config) -> - ssl_trace(ossl, Config). - essl_trace(doc) -> ["Same as http_trace/1 but over ssl sockets."]; essl_trace(suite) -> @@ -1213,8 +1300,6 @@ ssl_trace(SslTag, Config) when is_list(Config) -> case SslTag of ssl -> SSLOptions; - ossl -> - {ossl, SSLOptions}; essl -> {essl, SSLOptions} end, @@ -1233,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. @@ -1250,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), @@ -1354,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. @@ -1491,7 +1576,7 @@ proxy_options(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1512,7 +1597,7 @@ proxy_head(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1531,7 +1616,7 @@ proxy_get(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. %%------------------------------------------------------------------------- @@ -1572,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."]; @@ -1586,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"). %%------------------------------------------------------------------------- @@ -1610,7 +1696,7 @@ proxy_post(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1635,7 +1721,7 @@ proxy_put(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1660,7 +1746,7 @@ proxy_delete(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1694,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."]; @@ -1716,7 +1803,7 @@ proxy_auth(Config) when is_list(Config) -> tsf({unexpected_result, Unexpected}) end; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1760,7 +1847,7 @@ proxy_page_does_not_exist(Config) when is_list(Config) -> httpc:request(get, {URL, []}, [], []), ok; Reason -> - {skip, Reason} + skip(Reason) end. @@ -1779,6 +1866,7 @@ proxy_https_not_supported(Config) when is_list(Config) -> tsf({unexpected_reason, Result}) end. + %%------------------------------------------------------------------------- http_stream(doc) -> @@ -1905,7 +1993,7 @@ proxy_stream(Config) when is_list(Config) -> Body == binary_to_list(StreamedBody); Reason -> - {skip, Reason} + skip(Reason) end. @@ -1916,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. @@ -1997,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]), @@ -2028,8 +2127,8 @@ 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. @@ -2386,7 +2485,7 @@ 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. @@ -2413,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, @@ -2427,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. + %%------------------------------------------------------------------------- @@ -2476,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. @@ -2878,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. @@ -2898,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. @@ -2918,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. @@ -3067,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. @@ -3262,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)]), @@ -3360,10 +3486,6 @@ dummy_server_init(Caller, essl, IpV, SSLOptions) -> BaseOpts = [{ssl_imp, new}, {backlog, 128}, binary, {reuseaddr,true}, {active, false} | SSLOptions], - dummy_ssl_server_init(Caller, BaseOpts, IpV); -dummy_server_init(Caller, ossl, IpV, SSLOptions) -> - BaseOpts = [{ssl_imp, old}, - {backlog, 128}, binary, {active, false} | SSLOptions], dummy_ssl_server_init(Caller, BaseOpts, IpV). dummy_ssl_server_init(Caller, BaseOpts, IpV) -> @@ -3825,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). @@ -3835,9 +3985,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). @@ -3876,22 +4026,8 @@ dummy_ssl_server_hang_loop(_) -> ok end. - -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. - +hard_skip(Reason) -> + throw(skip(Reason)). skip(Reason) -> {skip, Reason}. |