1: %%==============================================================================
    2: %% Copyright 2016 Erlang Solutions Ltd.
    3: %%
    4: %% Licensed under the Apache License, Version 2.0 (the "License");
    5: %% you may not use this file except in compliance with the License.
    6: %% You may obtain a copy of the License at
    7: %%
    8: %% http://www.apache.org/licenses/LICENSE-2.0
    9: %%
   10: %% Unless required by applicable law or agreed to in writing, software
   11: %% distributed under the License is distributed on an "AS IS" BASIS,
   12: %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13: %% See the License for the specific language governing permissions and
   14: %% limitations under the License.
   15: %%==============================================================================
   16: -module(http_client_SUITE).
   17: 
   18: -compile([export_all, nowarn_export_all]).
   19: 
   20: -include_lib("common_test/include/ct.hrl").
   21: -include_lib("eunit/include/eunit.hrl").
   22: 
   23: all() ->
   24:     [get_test,
   25:      no_pool_test,
   26:      post_test,
   27:      request_timeout_test,
   28:      pool_timeout_test
   29:     ].
   30: 
   31: init_per_suite(Config) ->
   32:     http_helper:start(8080, '_', fun process_request/1),
   33:     Pid = self(),
   34:     spawn(fun() ->
   35:                   register(test_helper, self()),
   36:                   mim_ct_sup:start_link(ejabberd_sup),
   37:                   mongoose_wpool:ensure_started(),
   38:                   Pid ! ready,
   39:                   receive stop -> ok end
   40:           end),
   41:     receive ready -> ok end,
   42:     Config.
   43: 
   44: process_request(Req) ->
   45:     QS = cowboy_req:parse_qs(Req),
   46:     case proplists:get_value(<<"sleep">>, QS) of
   47:         <<"true">> -> timer:sleep(100);
   48:         _ -> ok
   49:     end,
   50:     cowboy_req:reply(200, #{<<"content-type">> => <<"text/plain">>}, <<"OK">>, Req).
   51: 
   52: end_per_suite(_Config) ->
   53:     http_helper:stop(),
   54:     exit(whereis(ejabberd_sup), shutdown),
   55:     whereis(test_helper) ! stop.
   56: 
   57: init_per_testcase(request_timeout_test, Config) ->
   58:     mongoose_wpool:start_configured_pools([#{type => http, scope => global, tag => pool(),
   59:                                              opts => #{},
   60:                                              conn_opts => #{server => "http://localhost:8080",
   61:                                                             request_timeout => 10,
   62:                                                             path_prefix => "/"}}],
   63:                                           [<<"a.com">>]),
   64:     Config;
   65: init_per_testcase(pool_timeout_test, Config) ->
   66:     mongoose_wpool:start_configured_pools([#{type => http, scope => global, tag => pool(),
   67:                                              opts => #{workers => 1,
   68:                                                        max_overflow => 0,
   69:                                                        strategy => available_worker,
   70:                                                        call_timeout => 10},
   71:                                              conn_opts => #{server => "http://localhost:8080",
   72:                                                             request_timeout => 5000,
   73:                                                             path_prefix => "/"}}],
   74:                                           [<<"a.com">>]),
   75:     Config;
   76: init_per_testcase(_TC, Config) ->
   77:     mongoose_wpool:start_configured_pools([#{type => http, scope => global, tag => pool(),
   78:                                              opts => #{},
   79:                                              conn_opts => #{server => "http://localhost:8080",
   80:                                                             request_timeout => 1000,
   81:                                                             path_prefix => "/"}}],
   82:                                           [<<"a.com">>]),
   83:     Config.
   84: 
   85: end_per_testcase(_TC, _Config) ->
   86:     mongoose_wpool:stop(http, global, pool()).
   87: 
   88: get_test(_Config) ->
   89:     Result = mongoose_http_client:get(global, pool(), <<"some/path">>, []),
   90:     ?assertEqual({ok, {<<"200">>, <<"OK">>}}, Result).
   91: 
   92: no_pool_test(_Config) ->
   93:     Result = mongoose_http_client:get(global, non_existent_pool, <<"some/path">>, []),
   94:     ?assertEqual({error, pool_not_started}, Result).
   95: 
   96: post_test(_Config) ->
   97:     Result = mongoose_http_client:post(global, pool(), <<"some/path">>, [], <<"test request">>),
   98:     ?assertEqual({ok, {<<"200">>, <<"OK">>}}, Result).
   99: 
  100: request_timeout_test(_Config) ->
  101:     Result = mongoose_http_client:get(global, pool(), <<"some/path?sleep=true">>, []),
  102:     ?assertEqual({error, request_timeout}, Result).
  103: 
  104: pool_timeout_test(_Config) ->
  105:     Pid = self(),
  106:     spawn(fun() ->
  107:                   mongoose_http_client:get(global, pool(), <<"/some/path?sleep=true">>, []),
  108:                   Pid ! finished
  109:           end),
  110:     timer:sleep(10), % wait for the only pool worker to start handling the request
  111:     Result = mongoose_http_client:get(global, pool(), <<"some/path">>, []),
  112:     ?assertEqual({error, pool_timeout}, Result),
  113:     receive finished -> ok after 1000 -> error(no_finished_message) end.
  114: 
  115: pool() -> tmp_pool.