Fix for #139 - file not being saved to disk when server does not respond with content-length
Project: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/commit/411468d7 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/tree/411468d7 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/diff/411468d7 Branch: refs/heads/upstream Commit: 411468d7490c4a66afb884cb59a6142c438ee8d0 Parents: a1be536 Author: Chandrashekhar Mullaparthi <[email protected]> Authored: Mon Jan 18 22:47:48 2016 +0000 Committer: Chandrashekhar Mullaparthi <[email protected]> Committed: Mon Jan 18 22:47:48 2016 +0000 ---------------------------------------------------------------------- test/Makefile | 10 ++ test/ibrowse_functional_tests.erl | 174 --------------------------------- test/ibrowse_tests.erl | 174 +++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 174 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/Makefile ---------------------------------------------------------------------- diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..c7d6f42 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,10 @@ +REBAR ?= $(shell which rebar3) + +all: compile + erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test local_unit_tests -s erlang halt + +compile: + erl -pa ../../ibrowse/ebin -make + +clean: + $(REBAR) clean http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/ibrowse_functional_tests.erl ---------------------------------------------------------------------- diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl deleted file mode 100644 index 3517011..0000000 --- a/test/ibrowse_functional_tests.erl +++ /dev/null @@ -1,174 +0,0 @@ -%%% File : ibrowse_functional_tests.erl -%%% Authors : Benjamin Lee <http://github.com/benjaminplee> -%%% Dan Schwabe <http://github.com/dfschwabe> -%%% Brian Richards <http://github.com/richbria> -%%% Description : Functional tests of the ibrowse library using a live test HTTP server -%%% Created : 18 November 2014 by Benjamin Lee <[email protected]> - --module(ibrowse_functional_tests). - --include_lib("eunit/include/eunit.hrl"). --define(PER_TEST_TIMEOUT_SEC, 60). --define(TIMEDTEST(Desc, Fun), {Desc, {timeout, ?PER_TEST_TIMEOUT_SEC, fun Fun/0}}). - --define(SERVER_PORT, 8181). --define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)). --define(SHORT_TIMEOUT_MS, 5000). --define(LONG_TIMEOUT_MS, 30000). --define(PAUSE_FOR_CONNECTIONS_MS, 2000). - --compile(export_all). - -setup() -> - application:start(crypto), - application:start(public_key), - application:start(ssl), - ibrowse_test_server:start_server(?SERVER_PORT, tcp), - ibrowse:start(), - ok. - -teardown(_) -> - ibrowse:stop(), - ibrowse_test_server:stop_server(?SERVER_PORT), - ok. - -running_server_fixture_test_() -> - {foreach, - fun setup/0, - fun teardown/1, - [ - ?TIMEDTEST("Simple request can be honored", simple_request), - ?TIMEDTEST("Slow server causes timeout", slow_server_timeout), - ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth), - ?TIMEDTEST("Pipelines refill", pipeline_refill), - ?TIMEDTEST("Timeout closes pipe", closing_pipes), - ?TIMEDTEST("Requests are balanced over connections", balanced_connections), - ?TIMEDTEST("Pipeline too small signals retries", small_pipeline), - ?TIMEDTEST("Dest status can be gathered", status) - ] - }. - -simple_request() -> - ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [])). - -slow_server_timeout() -> - ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)). - -pipeline_depth() -> - MaxSessions = 2, - MaxPipeline = 2, - RequestsSent = 2, - EmptyPipelineDepth = 0, - - ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), - - Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, - times(RequestsSent, fun() -> spawn_link(Fun) end), - - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), - - Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], - ?assertEqual(MaxSessions, length(Counts)), - ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts). - -pipeline_refill() -> - MaxSessions = 2, - MaxPipeline = 2, - RequestsToFill = MaxSessions * MaxPipeline, - - %% Send off enough requests to fill sessions and pipelines in rappid succession - Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, - times(RequestsToFill, fun() -> spawn_link(Fun) end), - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), - - % Verify that connections properly reported their completed responses and can still accept more - ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)), - - % and do it again to make sure we really are clear - times(RequestsToFill, fun() -> spawn_link(Fun) end), - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), - - % Verify that connections properly reported their completed responses and can still accept more - ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)). - -closing_pipes() -> - MaxSessions = 2, - MaxPipeline = 2, - RequestsSent = 2, - BalancedNumberOfRequestsPerConnection = 1, - - ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), - - Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, - times(RequestsSent, fun() -> spawn_link(Fun) end), - - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), - - Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], - ?assertEqual(MaxSessions, length(Counts)), - ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts), - - timer:sleep(?SHORT_TIMEOUT_MS), - - ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()). - -balanced_connections() -> - MaxSessions = 4, - MaxPipeline = 100, - RequestsSent = 80, - BalancedNumberOfRequestsPerConnection = 20, - - ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), - - Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end, - times(RequestsSent, fun() -> spawn_link(Fun) end), - - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), - - Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], - ?assertEqual(MaxSessions, length(Counts)), - - ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts). - -small_pipeline() -> - MaxSessions = 10, - MaxPipeline = 10, - RequestsSent = 100, - FullRequestsPerConnection = 10, - - ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), - - Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, - times(RequestsSent, fun() -> spawn(Fun) end), - - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), %% Wait for everyone to get in line - - ibrowse:show_dest_status("localhost", 8181), - Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], - ?assertEqual(MaxSessions, length(Counts)), - - ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts), - - Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS), - - ?assertEqual({error, retry_later}, Response). - -status() -> - MaxSessions = 10, - MaxPipeline = 10, - RequestsSent = 100, - - Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, - times(RequestsSent, fun() -> spawn(Fun) end), - - timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), %% Wait for everyone to get in line - - ibrowse:show_dest_status(), - ibrowse:show_dest_status("http://localhost:8181"). - - -times(0, _) -> - ok; -times(X, Fun) -> - Fun(), - times(X - 1, Fun). http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/ibrowse_tests.erl ---------------------------------------------------------------------- diff --git a/test/ibrowse_tests.erl b/test/ibrowse_tests.erl new file mode 100644 index 0000000..3517011 --- /dev/null +++ b/test/ibrowse_tests.erl @@ -0,0 +1,174 @@ +%%% File : ibrowse_functional_tests.erl +%%% Authors : Benjamin Lee <http://github.com/benjaminplee> +%%% Dan Schwabe <http://github.com/dfschwabe> +%%% Brian Richards <http://github.com/richbria> +%%% Description : Functional tests of the ibrowse library using a live test HTTP server +%%% Created : 18 November 2014 by Benjamin Lee <[email protected]> + +-module(ibrowse_functional_tests). + +-include_lib("eunit/include/eunit.hrl"). +-define(PER_TEST_TIMEOUT_SEC, 60). +-define(TIMEDTEST(Desc, Fun), {Desc, {timeout, ?PER_TEST_TIMEOUT_SEC, fun Fun/0}}). + +-define(SERVER_PORT, 8181). +-define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)). +-define(SHORT_TIMEOUT_MS, 5000). +-define(LONG_TIMEOUT_MS, 30000). +-define(PAUSE_FOR_CONNECTIONS_MS, 2000). + +-compile(export_all). + +setup() -> + application:start(crypto), + application:start(public_key), + application:start(ssl), + ibrowse_test_server:start_server(?SERVER_PORT, tcp), + ibrowse:start(), + ok. + +teardown(_) -> + ibrowse:stop(), + ibrowse_test_server:stop_server(?SERVER_PORT), + ok. + +running_server_fixture_test_() -> + {foreach, + fun setup/0, + fun teardown/1, + [ + ?TIMEDTEST("Simple request can be honored", simple_request), + ?TIMEDTEST("Slow server causes timeout", slow_server_timeout), + ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth), + ?TIMEDTEST("Pipelines refill", pipeline_refill), + ?TIMEDTEST("Timeout closes pipe", closing_pipes), + ?TIMEDTEST("Requests are balanced over connections", balanced_connections), + ?TIMEDTEST("Pipeline too small signals retries", small_pipeline), + ?TIMEDTEST("Dest status can be gathered", status) + ] + }. + +simple_request() -> + ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [])). + +slow_server_timeout() -> + ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)). + +pipeline_depth() -> + MaxSessions = 2, + MaxPipeline = 2, + RequestsSent = 2, + EmptyPipelineDepth = 0, + + ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), + + Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, + times(RequestsSent, fun() -> spawn_link(Fun) end), + + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), + + Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], + ?assertEqual(MaxSessions, length(Counts)), + ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts). + +pipeline_refill() -> + MaxSessions = 2, + MaxPipeline = 2, + RequestsToFill = MaxSessions * MaxPipeline, + + %% Send off enough requests to fill sessions and pipelines in rappid succession + Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, + times(RequestsToFill, fun() -> spawn_link(Fun) end), + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), + + % Verify that connections properly reported their completed responses and can still accept more + ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)), + + % and do it again to make sure we really are clear + times(RequestsToFill, fun() -> spawn_link(Fun) end), + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), + + % Verify that connections properly reported their completed responses and can still accept more + ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)). + +closing_pipes() -> + MaxSessions = 2, + MaxPipeline = 2, + RequestsSent = 2, + BalancedNumberOfRequestsPerConnection = 1, + + ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), + + Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, + times(RequestsSent, fun() -> spawn_link(Fun) end), + + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), + + Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], + ?assertEqual(MaxSessions, length(Counts)), + ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts), + + timer:sleep(?SHORT_TIMEOUT_MS), + + ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()). + +balanced_connections() -> + MaxSessions = 4, + MaxPipeline = 100, + RequestsSent = 80, + BalancedNumberOfRequestsPerConnection = 20, + + ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), + + Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end, + times(RequestsSent, fun() -> spawn_link(Fun) end), + + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), + + Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], + ?assertEqual(MaxSessions, length(Counts)), + + ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts). + +small_pipeline() -> + MaxSessions = 10, + MaxPipeline = 10, + RequestsSent = 100, + FullRequestsPerConnection = 10, + + ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()), + + Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, + times(RequestsSent, fun() -> spawn(Fun) end), + + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), %% Wait for everyone to get in line + + ibrowse:show_dest_status("localhost", 8181), + Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()], + ?assertEqual(MaxSessions, length(Counts)), + + ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts), + + Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS), + + ?assertEqual({error, retry_later}, Response). + +status() -> + MaxSessions = 10, + MaxPipeline = 10, + RequestsSent = 100, + + Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end, + times(RequestsSent, fun() -> spawn(Fun) end), + + timer:sleep(?PAUSE_FOR_CONNECTIONS_MS), %% Wait for everyone to get in line + + ibrowse:show_dest_status(), + ibrowse:show_dest_status("http://localhost:8181"). + + +times(0, _) -> + ok; +times(X, Fun) -> + Fun(), + times(X - 1, Fun).
