| % 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). |