blob: ea36f7f8c40dd8801838d142716f5bc925de7370 [file] [log] [blame]
% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.
-module(couch_replicator_httpc_pool_tests).
-include_lib("couch/include/couch_eunit.hrl").
-include_lib("couch/include/couch_db.hrl").
-define(TIMEOUT, 1000).
setup() ->
spawn_pool().
teardown(Pool) ->
stop_pool(Pool).
httpc_pool_test_() ->
{
"httpc pool tests",
{
setup,
fun test_util:start_couch/0, fun test_util:stop_couch/1,
{
foreach,
fun setup/0, fun teardown/1,
[
fun should_block_new_clients_when_full/1,
fun should_replace_worker_on_death/1
]
}
}
}.
should_block_new_clients_when_full(Pool) ->
?_test(begin
Client1 = spawn_client(Pool),
Client2 = spawn_client(Pool),
Client3 = spawn_client(Pool),
?assertEqual(ok, ping_client(Client1)),
?assertEqual(ok, ping_client(Client2)),
?assertEqual(ok, ping_client(Client3)),
Worker1 = get_client_worker(Client1, "1"),
Worker2 = get_client_worker(Client2, "2"),
Worker3 = get_client_worker(Client3, "3"),
?assert(is_process_alive(Worker1)),
?assert(is_process_alive(Worker2)),
?assert(is_process_alive(Worker3)),
?assertNotEqual(Worker1, Worker2),
?assertNotEqual(Worker2, Worker3),
?assertNotEqual(Worker3, Worker1),
Client4 = spawn_client(Pool),
?assertEqual(timeout, ping_client(Client4)),
?assertEqual(ok, stop_client(Client1)),
?assertEqual(ok, ping_client(Client4)),
Worker4 = get_client_worker(Client4, "4"),
?assertEqual(Worker1, Worker4),
lists:foreach(
fun(C) ->
?assertEqual(ok, stop_client(C))
end, [Client2, Client3, Client4])
end).
should_replace_worker_on_death(Pool) ->
?_test(begin
Client1 = spawn_client(Pool),
?assertEqual(ok, ping_client(Client1)),
Worker1 = get_client_worker(Client1, "1"),
?assert(is_process_alive(Worker1)),
?assertEqual(ok, kill_client_worker(Client1)),
?assertNot(is_process_alive(Worker1)),
?assertEqual(ok, stop_client(Client1)),
Client2 = spawn_client(Pool),
?assertEqual(ok, ping_client(Client2)),
Worker2 = get_client_worker(Client2, "2"),
?assert(is_process_alive(Worker2)),
?assertNotEqual(Worker1, Worker2),
?assertEqual(ok, stop_client(Client2))
end).
spawn_client(Pool) ->
Parent = self(),
Ref = make_ref(),
Pid = spawn(fun() ->
{ok, Worker} = couch_replicator_httpc_pool:get_worker(Pool),
loop(Parent, Ref, Worker, Pool)
end),
{Pid, Ref}.
ping_client({Pid, Ref}) ->
Pid ! ping,
receive
{pong, Ref} ->
ok
after ?TIMEOUT ->
timeout
end.
get_client_worker({Pid, Ref}, ClientName) ->
Pid ! get_worker,
receive
{worker, Ref, Worker} ->
Worker
after ?TIMEOUT ->
erlang:error(
{assertion_failed,
[{module, ?MODULE}, {line, ?LINE},
{reason, "Timeout getting client " ++ ClientName ++ " worker"}]})
end.
stop_client({Pid, Ref}) ->
Pid ! stop,
receive
{stop, Ref} ->
ok
after ?TIMEOUT ->
timeout
end.
kill_client_worker({Pid, Ref}) ->
Pid ! get_worker,
receive
{worker, Ref, Worker} ->
exit(Worker, kill),
ok
after ?TIMEOUT ->
timeout
end.
loop(Parent, Ref, Worker, Pool) ->
receive
ping ->
Parent ! {pong, Ref},
loop(Parent, Ref, Worker, Pool);
get_worker ->
Parent ! {worker, Ref, Worker},
loop(Parent, Ref, Worker, Pool);
stop ->
couch_replicator_httpc_pool:release_worker(Pool, Worker),
Parent ! {stop, Ref}
end.
spawn_pool() ->
Host = config:get("httpd", "bind_address", "127.0.0.1"),
Port = config:get("httpd", "port", "5984"),
{ok, Pool} = couch_replicator_httpc_pool:start_link(
"http://" ++ Host ++ ":" ++ Port, [{max_connections, 3}]),
Pool.
stop_pool(Pool) ->
ok = couch_replicator_httpc_pool:stop(Pool).