acceptor_SUITE.erl 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. %% Copyright (c) 2011-2012, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. -module(acceptor_SUITE).
  15. -include_lib("common_test/include/ct.hrl").
  16. %% ct.
  17. -export([all/0]).
  18. -export([groups/0]).
  19. -export([init_per_suite/1]).
  20. -export([end_per_suite/1]).
  21. -export([init_per_group/2]).
  22. -export([end_per_group/2]).
  23. %% misc.
  24. -export([misc_bad_transport/1]).
  25. %% ssl.
  26. -export([ssl_accept_error/1]).
  27. -export([ssl_accept_socket/1]).
  28. -export([ssl_active_echo/1]).
  29. -export([ssl_echo/1]).
  30. %% tcp.
  31. -export([tcp_accept_socket/1]).
  32. -export([tcp_active_echo/1]).
  33. -export([tcp_echo/1]).
  34. -export([tcp_max_connections/1]).
  35. -export([tcp_max_connections_and_beyond/1]).
  36. -export([tcp_upgrade/1]).
  37. %% ct.
  38. all() ->
  39. [{group, tcp}, {group, ssl}, {group, misc}].
  40. groups() ->
  41. [{tcp, [
  42. tcp_accept_socket,
  43. tcp_active_echo,
  44. tcp_echo,
  45. tcp_max_connections,
  46. tcp_max_connections_and_beyond,
  47. tcp_upgrade
  48. ]}, {ssl, [
  49. ssl_accept_error,
  50. ssl_accept_socket,
  51. ssl_active_echo,
  52. ssl_echo
  53. ]}, {misc, [
  54. misc_bad_transport
  55. ]}].
  56. init_per_suite(Config) ->
  57. ok = application:start(ranch),
  58. Config.
  59. end_per_suite(_) ->
  60. application:stop(ranch),
  61. ok.
  62. init_per_group(ssl, Config) ->
  63. application:start(crypto),
  64. application:start(public_key),
  65. application:start(ssl),
  66. Config;
  67. init_per_group(_, Config) ->
  68. Config.
  69. end_per_group(ssl, _) ->
  70. application:stop(ssl),
  71. application:stop(public_key),
  72. application:stop(crypto),
  73. ok;
  74. end_per_group(_, _) ->
  75. ok.
  76. %% misc.
  77. misc_bad_transport(_) ->
  78. {error, badarg} = ranch:start_listener(misc_bad_transport, 1,
  79. bad_transport, [{port, 0}],
  80. echo_protocol, []),
  81. ok.
  82. %% ssl.
  83. ssl_accept_error(Config) ->
  84. {ok, _} = ranch:start_listener(ssl_accept_error, 1,
  85. ranch_ssl, [{port, 0},
  86. {certfile, ?config(data_dir, Config) ++ "cert.pem"}],
  87. echo_protocol, []),
  88. Port = ranch:get_port(ssl_accept_error),
  89. [AcceptorPid] = ets:lookup_element(ranch_server,
  90. {acceptors, ssl_accept_error}, 2),
  91. true = is_process_alive(AcceptorPid),
  92. {ok, Socket} = gen_tcp:connect("localhost", Port,
  93. [binary, {active, false}, {packet, raw}]),
  94. ok = gen_tcp:close(Socket),
  95. receive after 500 -> ok end,
  96. true = is_process_alive(AcceptorPid).
  97. ssl_accept_socket(Config) ->
  98. %%% XXX we can't do the spawn to test the controlling process change
  99. %%% because of the bug in ssl
  100. {ok, S} = ssl:listen(0,
  101. [{certfile, ?config(data_dir, Config) ++ "cert.pem"}, binary,
  102. {active, false}, {packet, raw}, {reuseaddr, true}]),
  103. {ok, _} = ranch:start_listener(ssl_accept_socket, 1,
  104. ranch_ssl, [{socket, S}], echo_protocol, []),
  105. Port = ranch:get_port(ssl_accept_socket),
  106. {ok, Socket} = ssl:connect("localhost", Port,
  107. [binary, {active, false}, {packet, raw},
  108. {certfile, ?config(data_dir, Config) ++ "cert.pem"}]),
  109. ok = ssl:send(Socket, <<"TCP Ranch is working!">>),
  110. {ok, <<"TCP Ranch is working!">>} = ssl:recv(Socket, 21, 1000),
  111. ok = ranch:stop_listener(ssl_accept_socket),
  112. {error, closed} = ssl:recv(Socket, 0, 1000),
  113. %% Make sure the listener stopped.
  114. {'EXIT', _} = begin catch ranch:get_port(ssl_accept_socket) end,
  115. ok.
  116. ssl_active_echo(Config) ->
  117. {ok, _} = ranch:start_listener(ssl_active_echo, 1,
  118. ranch_ssl, [{port, 0},
  119. {certfile, ?config(data_dir, Config) ++ "cert.pem"}],
  120. active_echo_protocol, []),
  121. Port = ranch:get_port(ssl_active_echo),
  122. {ok, Socket} = ssl:connect("localhost", Port,
  123. [binary, {active, false}, {packet, raw},
  124. {certfile, ?config(data_dir, Config) ++ "cert.pem"}]),
  125. ok = ssl:send(Socket, <<"SSL Ranch is working!">>),
  126. {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket, 21, 1000),
  127. ok = ranch:stop_listener(ssl_active_echo),
  128. {error, closed} = ssl:recv(Socket, 0, 1000),
  129. %% Make sure the listener stopped.
  130. {'EXIT', _} = begin catch ranch:get_port(ssl_active_echo) end,
  131. ok.
  132. ssl_echo(Config) ->
  133. {ok, _} = ranch:start_listener(ssl_echo, 1,
  134. ranch_ssl, [{port, 0},
  135. {certfile, ?config(data_dir, Config) ++ "cert.pem"}],
  136. echo_protocol, []),
  137. Port = ranch:get_port(ssl_echo),
  138. {ok, Socket} = ssl:connect("localhost", Port,
  139. [binary, {active, false}, {packet, raw},
  140. {certfile, ?config(data_dir, Config) ++ "cert.pem"}]),
  141. ok = ssl:send(Socket, <<"SSL Ranch is working!">>),
  142. {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket, 21, 1000),
  143. ok = ranch:stop_listener(ssl_echo),
  144. {error, closed} = ssl:recv(Socket, 0, 1000),
  145. %% Make sure the listener stopped.
  146. {'EXIT', _} = begin catch ranch:get_port(ssl_echo) end,
  147. ok.
  148. %% tcp.
  149. tcp_accept_socket(_) ->
  150. Ref = make_ref(),
  151. Parent = self(),
  152. spawn(fun() ->
  153. {ok, S} = gen_tcp:listen(0, [binary, {active, false}, {packet, raw},
  154. {reuseaddr, true}]),
  155. {ok, _} = ranch:start_listener(tcp_accept_socket, 1,
  156. ranch_tcp, [{socket, S}], echo_protocol, []),
  157. Parent ! Ref
  158. end),
  159. receive
  160. Ref -> ok
  161. end,
  162. Port = ranch:get_port(tcp_accept_socket),
  163. {ok, Socket} = gen_tcp:connect("localhost", Port,
  164. [binary, {active, false}, {packet, raw}]),
  165. ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>),
  166. {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000),
  167. ok = ranch:stop_listener(tcp_accept_socket),
  168. {error, closed} = gen_tcp:recv(Socket, 0, 1000),
  169. %% Make sure the listener stopped.
  170. {'EXIT', _} = begin catch ranch:get_port(tcp_accept_socket) end,
  171. ok.
  172. tcp_active_echo(_) ->
  173. {ok, _} = ranch:start_listener(tcp_active_echo, 1,
  174. ranch_tcp, [{port, 0}], active_echo_protocol, []),
  175. Port = ranch:get_port(tcp_active_echo),
  176. {ok, Socket} = gen_tcp:connect("localhost", Port,
  177. [binary, {active, false}, {packet, raw}]),
  178. ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>),
  179. {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000),
  180. ok = ranch:stop_listener(tcp_active_echo),
  181. {error, closed} = gen_tcp:recv(Socket, 0, 1000),
  182. %% Make sure the listener stopped.
  183. {'EXIT', _} = begin catch ranch:get_port(tcp_active_echo) end,
  184. ok.
  185. tcp_echo(_) ->
  186. {ok, _} = ranch:start_listener(tcp_echo, 1,
  187. ranch_tcp, [{port, 0}], echo_protocol, []),
  188. Port = ranch:get_port(tcp_echo),
  189. {ok, Socket} = gen_tcp:connect("localhost", Port,
  190. [binary, {active, false}, {packet, raw}]),
  191. ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>),
  192. {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000),
  193. ok = ranch:stop_listener(tcp_echo),
  194. {error, closed} = gen_tcp:recv(Socket, 0, 1000),
  195. %% Make sure the listener stopped.
  196. {'EXIT', _} = begin catch ranch:get_port(tcp_echo) end,
  197. ok.
  198. tcp_max_connections(_) ->
  199. {ok, _} = ranch:start_listener(tcp_max_connections, 1,
  200. ranch_tcp, [{port, 0}, {max_connections, 10}],
  201. notify_and_wait_protocol, [{msg, connected}, {pid, self()}]),
  202. Port = ranch:get_port(tcp_max_connections),
  203. %% @todo We'll probably want a more direct interface to count_connections.
  204. ListenerPid = ranch_server:lookup_listener(tcp_max_connections),
  205. ok = connect_loop(Port, 11, 150),
  206. 10 = ranch_server:count_connections(ListenerPid),
  207. 10 = receive_loop(connected, 400),
  208. 1 = receive_loop(connected, 1000).
  209. tcp_max_connections_and_beyond(_) ->
  210. {ok, _} = ranch:start_listener(tcp_max_connections_and_beyond, 1,
  211. ranch_tcp, [{port, 0}, {max_connections, 10}],
  212. remove_conn_and_wait_protocol, [{remove, true}]),
  213. Port = ranch:get_port(tcp_max_connections_and_beyond),
  214. %% @todo We'll probably want a more direct interface to count_connections.
  215. ListenerPid = ranch_server:lookup_listener(tcp_max_connections_and_beyond),
  216. ok = connect_loop(Port, 10, 0),
  217. 0 = ranch_server:count_connections(ListenerPid),
  218. ranch:set_protocol_options(tcp_max_connections_and_beyond,
  219. [{remove, false}]),
  220. receive after 500 -> ok end,
  221. ok = connect_loop(Port, 10, 0),
  222. receive after 500 -> ok end,
  223. 10 = ranch_server:count_connections(ListenerPid).
  224. tcp_upgrade(_) ->
  225. receive after 20000 -> ok end,
  226. {ok, _} = ranch:start_listener(tcp_upgrade, 1,
  227. ranch_tcp, [{port, 0}],
  228. notify_and_wait_protocol, [{msg, connected}, {pid, self()}]),
  229. Port = ranch:get_port(tcp_upgrade),
  230. ok = connect_loop(Port, 1, 0),
  231. receive connected -> ok after 1000 -> error(timeout) end,
  232. ranch:set_protocol_options(tcp_upgrade, [{msg, upgraded}, {pid, self()}]),
  233. ok = connect_loop(Port, 1, 0),
  234. receive upgraded -> ok after 1000 -> error(timeout) end.
  235. %% Utility functions.
  236. connect_loop(_, 0, _) ->
  237. ok;
  238. connect_loop(Port, N, Sleep) ->
  239. {ok, _} = gen_tcp:connect("localhost", Port,
  240. [binary, {active, false}, {packet, raw}]),
  241. receive after Sleep -> ok end,
  242. connect_loop(Port, N - 1, Sleep).
  243. receive_loop(Message, Timeout) ->
  244. receive_loop(Message, Timeout, 0).
  245. receive_loop(Message, Timeout, N) ->
  246. receive Message ->
  247. receive_loop(Message, Timeout, N + 1)
  248. after Timeout ->
  249. N
  250. end.