gproc_dist_tests.erl 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. %% -*- erlang-indent-level: 4; indent-tabs-mode: nil -*-
  2. %% ``The contents of this file are subject to the Erlang Public License,
  3. %% Version 1.1, (the "License"); you may not use this file except in
  4. %% compliance with the License. You should have received a copy of the
  5. %% Erlang Public License along with this software. If not, it can be
  6. %% retrieved via the world wide web at http://www.erlang.org/.
  7. %%
  8. %% Software distributed under the License is distributed on an "AS IS"
  9. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  10. %% the License for the specific language governing rights and limitations
  11. %% under the License.
  12. %%
  13. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  14. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  15. %% AB. All Rights Reserved.''
  16. %%
  17. %% @author Ulf Wiger <ulf@wiger.net>
  18. %%
  19. -module(gproc_dist_tests).
  20. -ifdef(TEST).
  21. -include_lib("eunit/include/eunit.hrl").
  22. -export([t_spawn/1, t_spawn_reg/2]).
  23. -define(f(E), fun() -> ?debugVal(E) end).
  24. dist_test_() ->
  25. {timeout, 120,
  26. [
  27. %% {setup,
  28. %% fun dist_setup/0,
  29. %% fun dist_cleanup/1,
  30. %% fun(skip) -> [];
  31. %% (Ns) when is_list(Ns) ->
  32. %% {inorder, basic_tests(Ns)}
  33. %% end
  34. %% },
  35. {foreach,
  36. fun dist_setup/0,
  37. fun dist_cleanup/1,
  38. [
  39. fun(Ns) ->
  40. [{inorder, basic_tests(Ns)}]
  41. end,
  42. fun(Ns) ->
  43. tests(Ns, [?f(t_sync_cand_dies(Ns))])
  44. end,
  45. fun(Ns) ->
  46. tests(Ns, [?f(t_fail_node(Ns))])
  47. end,
  48. fun(Ns) ->
  49. tests(Ns, [?f(t_master_dies(Ns))])
  50. end
  51. ]}
  52. ]}.
  53. tests(skip, _) ->
  54. [];
  55. tests(_, L) ->
  56. L.
  57. basic_tests(skip) ->
  58. [];
  59. basic_tests(Ns) ->
  60. [
  61. ?f(t_simple_reg(Ns)),
  62. ?f(t_simple_reg_other(Ns)),
  63. ?f(t_simple_ensure(Ns)),
  64. ?f(t_simple_ensure_other(Ns)),
  65. ?f(t_simple_reg_or_locate(Ns)),
  66. ?f(t_simple_counter(Ns)),
  67. ?f(t_aggr_counter(Ns)),
  68. ?f(t_awaited_aggr_counter(Ns)),
  69. ?f(t_simple_resource_count(Ns)),
  70. ?f(t_awaited_resource_count(Ns)),
  71. ?f(t_resource_count_on_zero(Ns)),
  72. ?f(t_update_counters(Ns)),
  73. ?f(t_shared_counter(Ns)),
  74. ?f(t_prop(Ns)),
  75. ?f(t_mreg(Ns)),
  76. ?f(t_await_reg(Ns)),
  77. ?f(t_await_self(Ns)),
  78. ?f(t_await_reg_exists(Ns)),
  79. ?f(t_give_away(Ns)),
  80. ?f(t_sync(Ns)),
  81. ?f(t_monitor(Ns)),
  82. ?f(t_standby_monitor(Ns)),
  83. ?f(t_standby_monitor_unreg(Ns)),
  84. ?f(t_follow_monitor(Ns)),
  85. ?f(t_subscribe(Ns))
  86. ].
  87. dist_setup() ->
  88. case run_dist_tests() of
  89. true ->
  90. Ns = start_slaves([dist_test_n1, dist_test_n2, dist_test_n3]),
  91. ?assertMatch({[ok,ok,ok],[]},
  92. rpc:multicall(Ns, application, set_env,
  93. [gproc, gproc_dist, Ns])),
  94. ?assertMatch({[ok,ok,ok],[]},
  95. rpc:multicall(
  96. Ns, application, start, [gproc])),
  97. Ns;
  98. false ->
  99. skip
  100. end.
  101. dist_cleanup(skip) ->
  102. ok;
  103. dist_cleanup(Ns) ->
  104. [slave:stop(N) || N <- Ns],
  105. ok.
  106. run_dist_tests() ->
  107. case os:getenv("GPROC_DIST") of
  108. "true" -> true;
  109. "false" -> false;
  110. false ->
  111. case code:ensure_loaded(gen_leader) of
  112. {error, nofile} ->
  113. false;
  114. _ ->
  115. true
  116. end
  117. end.
  118. -define(T_NAME, {n, g, {?MODULE, ?LINE, os:timestamp()}}).
  119. -define(T_KVL, [{foo, "foo"}, {bar, "bar"}]).
  120. -define(T_COUNTER, {c, g, {?MODULE, ?LINE}}).
  121. -define(T_RESOURCE, {r, g, {?MODULE, ?LINE}}).
  122. -define(T_PROP, {p, g, ?MODULE}).
  123. t_simple_reg([H|_] = Ns) ->
  124. Name = ?T_NAME,
  125. P = t_spawn_reg(H, Name),
  126. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P)),
  127. ?assertMatch(true, t_call(P, {apply, gproc, unreg, [Name]})),
  128. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
  129. ?assertMatch(ok, t_call(P, die)).
  130. t_simple_reg_other([A, B|_] = Ns) ->
  131. Name = ?T_NAME,
  132. P1 = t_spawn(A),
  133. P2 = t_spawn(B),
  134. ?assertMatch(true, t_call(P1, {apply, gproc, reg_other, [Name, P2]})),
  135. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P2)),
  136. ?assertMatch(true, t_call(P1, {apply, gproc, unreg_other, [Name, P2]})),
  137. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
  138. ?assertMatch(ok, t_call(P1, die)),
  139. ?assertMatch(ok, t_call(P2, die)).
  140. t_simple_ensure([H|_] = Ns) ->
  141. Name = ?T_NAME,
  142. P = t_spawn_reg(H, Name),
  143. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P)),
  144. ?assertMatch(
  145. updated, t_call(
  146. P, {apply, gproc, ensure_reg, [Name, new_val, [{a,1}]]})),
  147. ?assertMatch(
  148. [{a,1}], t_call(
  149. P, {apply, gproc, get_attributes, [Name]})),
  150. ?assertMatch(ok, t_read_everywhere(Name, P, Ns, new_val)),
  151. ?assertMatch(true, t_call(P, {apply, gproc, unreg, [Name]})),
  152. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
  153. ?assertMatch(ok, t_call(P, die)).
  154. t_simple_ensure_other([A, B|_] = Ns) ->
  155. Name = ?T_NAME,
  156. P1 = t_spawn(A),
  157. P2 = t_spawn(B),
  158. ?assertMatch(true, t_call(P1, {apply, gproc, reg_other, [Name, P2]})),
  159. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P2)),
  160. ?assertMatch(
  161. updated, t_call(
  162. P1, {apply, gproc, ensure_reg_other, [Name, P2, new_val]})),
  163. ?assertMatch(ok, t_read_everywhere(Name, P2, Ns, new_val)),
  164. ?assertMatch(true, t_call(P1, {apply, gproc, unreg_other, [Name, P2]})),
  165. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
  166. ?assertMatch(ok, t_call(P1, die)),
  167. ?assertMatch(ok, t_call(P2, die)).
  168. t_simple_reg_or_locate([A,B|_] = _Ns) ->
  169. Name = ?T_NAME,
  170. P1 = t_spawn(A),
  171. Ref = erlang:monitor(process, P1),
  172. ?assertMatch({P1, the_value},
  173. t_call(P1, {apply, gproc, reg_or_locate, [Name, the_value]})),
  174. P2 = t_spawn(B),
  175. Ref2 = erlang:monitor(process, P2),
  176. ?assertMatch({P1, the_value},
  177. t_call(P2, {apply, gproc, reg_or_locate, [Name, other_value]})),
  178. ?assertMatch(ok, t_call(P1, die)),
  179. ?assertMatch(ok, t_call(P2, die)),
  180. flush_down(Ref),
  181. flush_down(Ref2).
  182. flush_down(Ref) ->
  183. receive
  184. {'DOWN', Ref, _, _, _} ->
  185. ok
  186. after 1000 ->
  187. erlang:error({timeout, [flush_down, Ref]})
  188. end.
  189. t_simple_counter([H|_] = Ns) ->
  190. Ctr = ?T_COUNTER,
  191. P = t_spawn_reg(H, Ctr, 3),
  192. ?assertMatch(ok, t_read_everywhere(Ctr, P, Ns, 3)),
  193. ?assertMatch(5, t_call(P, {apply, gproc, update_counter, [Ctr, 2]})),
  194. ?assertMatch(ok, t_read_everywhere(Ctr, P, Ns, 5)),
  195. ?assertMatch(ok, t_call(P, die)).
  196. t_shared_counter([H|_] = Ns) ->
  197. Ctr = ?T_COUNTER,
  198. P = t_spawn_reg_shared(H, Ctr, 3),
  199. ?assertMatch(ok, t_read_everywhere(Ctr, shared, Ns, 3)),
  200. ?assertMatch(5, t_call(P, {apply, gproc, update_shared_counter, [Ctr, 2]})),
  201. ?assertMatch(ok, t_read_everywhere(Ctr, shared, Ns, 5)),
  202. ?assertMatch(ok, t_call(P, die)),
  203. ?assertMatch(ok, t_read_everywhere(Ctr, shared, Ns, 5)),
  204. ?assertMatch(ok, t_read_everywhere(Ctr, shared, Ns, 5)), % twice
  205. P1 = t_spawn(H),
  206. ?assertMatch(true, t_call(P1, {apply, gproc, unreg_shared, [Ctr]})),
  207. ?assertMatch(ok, t_read_everywhere(Ctr, shared, Ns, badarg)).
  208. t_aggr_counter([H1,H2|_] = Ns) ->
  209. {c,g,Nm} = Ctr = ?T_COUNTER,
  210. Aggr = {a,g,Nm},
  211. Pc1 = t_spawn_reg(H1, Ctr, 3),
  212. Pa = t_spawn_reg(H2, Aggr),
  213. ?assertMatch(ok, t_read_everywhere(Ctr, Pc1, Ns, 3)),
  214. ?assertMatch(ok, t_read_everywhere(Aggr, Pa, Ns, 3)),
  215. Pc2 = t_spawn_reg(H2, Ctr, 3),
  216. ?assertMatch(ok, t_read_everywhere(Ctr, Pc2, Ns, 3)),
  217. ?assertMatch(ok, t_read_everywhere(Aggr, Pa, Ns, 6)),
  218. ?assertMatch(5, t_call(Pc1, {apply, gproc, update_counter, [Ctr, 2]})),
  219. ?assertMatch(ok, t_read_everywhere(Ctr, Pc1, Ns, 5)),
  220. ?assertMatch(ok, t_read_everywhere(Aggr, Pa, Ns, 8)),
  221. ?assertMatch(ok, t_call(Pc1, die)),
  222. ?assertMatch(ok, t_read_everywhere(Aggr, Pa, Ns, 3)),
  223. ?assertMatch(ok, t_call(Pc2, die)),
  224. ?assertMatch(ok, t_call(Pa, die)).
  225. t_awaited_aggr_counter([H1,H2|_] = Ns) ->
  226. {c,g,Nm} = Ctr = ?T_COUNTER,
  227. Aggr = {a,g,Nm},
  228. Pc1 = t_spawn_reg(H1, Ctr, 3),
  229. P = t_spawn(H2),
  230. Ref = erlang:monitor(process, P),
  231. P ! {self(), Ref, {apply, gproc, await, [Aggr]}},
  232. t_sleep(),
  233. P1 = t_spawn_reg(H2, Aggr),
  234. ?assert(P1 == receive
  235. {P, Ref, Res} ->
  236. element(1, Res);
  237. {'DOWN', Ref, _, _, Reason} ->
  238. erlang:error(Reason);
  239. Other ->
  240. erlang:error({received, Other})
  241. end),
  242. ?assertMatch(ok, t_read_everywhere(Aggr, P1, Ns, 3)),
  243. ?assertMatch(ok, t_call(Pc1, die)),
  244. ?assertMatch(ok, t_call(P, die)),
  245. flush_down(Ref),
  246. ?assertMatch(ok, t_call(P1, die)).
  247. t_simple_resource_count([H1,H2|_] = Ns) ->
  248. {r,g,Nm} = R = ?T_RESOURCE,
  249. RC = {rc,g,Nm},
  250. Pr1 = t_spawn_reg(H1, R, 3),
  251. Prc = t_spawn_reg(H2, RC),
  252. ?assertMatch(ok, t_read_everywhere(R, Pr1, Ns, 3)),
  253. ?assertMatch(ok, t_read_everywhere(RC, Prc, Ns, 1)),
  254. Pr2 = t_spawn_reg(H2, R, 4),
  255. ?assertMatch(ok, t_read_everywhere(R, Pr2, Ns, 4)),
  256. ?assertMatch(ok, t_read_everywhere(RC, Prc, Ns, 2)),
  257. ?assertMatch(ok, t_call(Pr1, die)),
  258. ?assertMatch(ok, t_read_everywhere(RC, Prc, Ns, 1)),
  259. ?assertMatch(ok, t_call(Pr2, die)),
  260. ?assertMatch(ok, t_call(Prc, die)).
  261. t_awaited_resource_count([H1,H2|_] = Ns) ->
  262. {r,g,Nm} = R = ?T_RESOURCE,
  263. RC = {rc,g,Nm},
  264. Pr1 = t_spawn_reg(H1, R, 3),
  265. P = t_spawn(H2),
  266. Ref = erlang:monitor(process, P),
  267. P ! {self(), Ref, {apply, gproc, await, [RC]}},
  268. t_sleep(),
  269. P1 = t_spawn_reg(H2, RC),
  270. ?assert(P1 == receive
  271. {P, Ref, Res} ->
  272. element(1, Res);
  273. {'DOWN', Ref, _, _, Reason} ->
  274. erlang:error(Reason);
  275. Other ->
  276. erlang:error({received, Other})
  277. end),
  278. ?assertMatch(ok, t_read_everywhere(RC, P1, Ns, 1)),
  279. ?assertMatch(ok, t_call(Pr1, die)),
  280. ?assertMatch(ok, t_call(P, die)),
  281. flush_down(Ref),
  282. ?assertMatch(ok, t_call(P1, die)).
  283. t_resource_count_on_zero([H1,H2|_] = Ns) ->
  284. {r,g,Nm} = R = ?T_RESOURCE,
  285. Prop = ?T_PROP,
  286. RC = {rc,g,Nm},
  287. Pr1 = t_spawn_reg(H1, R, 3),
  288. Pp = t_spawn_reg(H2, Prop),
  289. ?assertMatch(ok, t_call(Pp, {selective, true})),
  290. Prc = t_spawn_reg(H2, RC, undefined, [{on_zero, [{send, Prop}]}]),
  291. ?assertMatch(ok, t_read_everywhere(R, Pr1, Ns, 3)),
  292. ?assertMatch(ok, t_read_everywhere(RC, Prc, Ns, 1)),
  293. ?assertMatch(ok, t_call(Pr1, die)),
  294. ?assertMatch(ok, t_read_everywhere(RC, Prc, Ns, 0)),
  295. ?assertMatch({gproc, resource_on_zero, g, Nm, Prc},
  296. t_call(Pp, {apply_fun, fun() ->
  297. receive
  298. {gproc, _, _, _, _} = M ->
  299. M
  300. after 10000 ->
  301. timeout
  302. end
  303. end})),
  304. ?assertMatch(ok, t_call(Pp, {selective, false})),
  305. ?assertMatch(ok, t_call(Pp, die)),
  306. ?assertMatch(ok, t_call(Prc, die)).
  307. t_update_counters([H1,H2|_] = Ns) ->
  308. {c,g,N1} = C1 = ?T_COUNTER,
  309. A1 = {a,g,N1},
  310. C2 = ?T_COUNTER,
  311. P1 = t_spawn_reg(H1, C1, 2),
  312. P12 = t_spawn_reg(H2, C1, 2),
  313. P2 = t_spawn_reg(H2, C2, 1),
  314. Pa1 = t_spawn_reg(H2, A1),
  315. ?assertMatch(ok, t_read_everywhere(C1, P1, Ns, 2)),
  316. ?assertMatch(ok, t_read_everywhere(C1, P12, Ns, 2)),
  317. ?assertMatch(ok, t_read_everywhere(C2, P2, Ns, 1)),
  318. ?assertMatch(ok, t_read_everywhere(A1, Pa1, Ns, 4)),
  319. ?assertMatch([{C1,P1, 3},
  320. {C1,P12,4},
  321. {C2,P2, 0}], t_call(P1, {apply, gproc, update_counters,
  322. [g, [{C1,P1,1},{C1,P12,2},{C2,P2,{-2,0,0}}]]})),
  323. ?assertMatch(ok, t_read_everywhere(C1, P1, Ns, 3)),
  324. ?assertMatch(ok, t_read_everywhere(C1, P12, Ns, 4)),
  325. ?assertMatch(ok, t_read_everywhere(C2, P2, Ns, 0)),
  326. ?assertMatch(ok, t_read_everywhere(A1, Pa1, Ns, 7)),
  327. ?assertMatch(ok, t_call(P1, die)),
  328. ?assertMatch(ok, t_call(P12, die)),
  329. ?assertMatch(ok, t_call(P2, die)).
  330. t_prop([H1,H2|_] = Ns) ->
  331. {p, g, _} = P = ?T_PROP,
  332. P1 = t_spawn_reg(H1, P, 1),
  333. P2 = t_spawn_reg(H2, P, 2),
  334. ?assertMatch(ok, t_read_everywhere(P, P1, Ns, 1)),
  335. ?assertMatch(ok, t_read_everywhere(P, P2, Ns, 2)),
  336. ?assertMatch(ok, t_call(P1, die)),
  337. ?assertMatch(ok, t_read_everywhere(P, P1, Ns, badarg)),
  338. ?assertMatch(ok, t_call(P2, die)).
  339. t_mreg([H|_] = Ns) ->
  340. Kvl = ?T_KVL,
  341. Keys = [K || {K,_} <- Kvl],
  342. P = t_spawn_mreg(H, Kvl),
  343. [?assertMatch(ok, t_lookup_everywhere({n,g,K}, Ns, P)) || K <- Keys],
  344. ?assertMatch(true, t_call(P, {apply, gproc, munreg, [n, g, Keys]})),
  345. [?assertMatch(ok, t_lookup_everywhere({n,g,K},Ns,undefined)) || K <- Keys],
  346. ?assertMatch(ok, t_call(P, die)).
  347. t_await_reg([A,B|_] = Ns) ->
  348. Name = ?T_NAME,
  349. P = t_spawn(A),
  350. Ref = erlang:monitor(process, P),
  351. P ! {self(), Ref, {apply, gproc, await, [Name]}},
  352. t_sleep(),
  353. P1 = t_spawn_reg(B, Name),
  354. ?assert(P1 == receive
  355. {P, Ref, Res} ->
  356. element(1, Res);
  357. {'DOWN', Ref, _, _, Reason} ->
  358. erlang:error(Reason);
  359. Other ->
  360. erlang:error({received,Other})
  361. end),
  362. ?assertMatch(ok, t_call(P, die)),
  363. flush_down(Ref),
  364. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P1)),
  365. ?assertMatch(ok, t_call(P1, die)).
  366. t_await_self([A|_]) ->
  367. Name = ?T_NAME,
  368. P = t_spawn(A, false), % don't buffer unknowns
  369. Ref = t_call(P, {apply, gproc, nb_wait, [Name]}),
  370. ?assertMatch(ok, t_call(P, {selective, true})),
  371. ?assertMatch(true, t_call(P, {apply, gproc, reg, [Name, some_value]})),
  372. ?assertMatch({registered, {Name, P, some_value}},
  373. t_call(P, {apply_fun, fun() ->
  374. receive
  375. {gproc, Ref, R, Wh} ->
  376. {R, Wh}
  377. after 10000 ->
  378. timeout
  379. end
  380. end})),
  381. ?assertMatch(ok, t_call(P, {selective, false})),
  382. ?assertMatch(true, t_call(P, {apply, gproc, unreg, [Name]})).
  383. t_await_reg_exists([A,B|_]) ->
  384. Name = ?T_NAME,
  385. P = t_spawn(A),
  386. Ref = erlang:monitor(process, P),
  387. P1 = t_spawn_reg(B, Name),
  388. P ! {self(), Ref, {apply, gproc, await, [Name]}},
  389. ?assert(P1 == receive
  390. {P, Ref, Res} ->
  391. element(1, Res);
  392. {'DOWN', Ref, _, _, Reason} ->
  393. erlang:error(Reason);
  394. Other ->
  395. erlang:error({received,Other})
  396. end),
  397. ?assertMatch(ok, t_call(P, die)),
  398. ?assertMatch(ok, t_call(P1, die)).
  399. t_give_away([A,B|_] = Ns) ->
  400. Na = ?T_NAME,
  401. Nb = ?T_NAME,
  402. Pa = t_spawn_reg(A, Na),
  403. Pb = t_spawn_reg(B, Nb),
  404. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  405. ?assertMatch(ok, t_lookup_everywhere(Nb, Ns, Pb)),
  406. ?assertMatch(Pb, t_call(Pa, {apply, gproc, give_away, [Na, Nb]})),
  407. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pb)),
  408. ?assertMatch(Pa, t_call(Pb, {apply, gproc, give_away, [Na, Pa]})),
  409. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  410. ?assertMatch(ok, t_call(Pa, die)),
  411. ?assertMatch(ok, t_call(Pb, die)).
  412. t_sync(Ns) ->
  413. %% Don't really know how to test this...
  414. [?assertMatch(true, rpc:call(N, gproc_dist, sync, []))
  415. || N <- Ns].
  416. t_monitor([A,B|_]) ->
  417. Na = ?T_NAME,
  418. Pa = t_spawn_reg(A, Na),
  419. Pb = t_spawn(B, _Selective = true),
  420. Ref = t_call(Pb, {apply, gproc, monitor, [Na]}),
  421. ?assert(is_reference(Ref)),
  422. ?assertMatch(ok, t_call(Pa, die)),
  423. ?assertMatch({gproc,unreg,Ref,Na}, got_msg(Pb, gproc)),
  424. Pc = t_spawn_reg(A, Na),
  425. Ref1 = t_call(Pb, {apply, gproc, monitor, [Na]}),
  426. ?assertMatch(true, t_call(Pc, {apply, gproc, unreg, [Na]})),
  427. ?assertMatch({gproc,unreg,Ref1,Na}, got_msg(Pb, gproc)).
  428. t_standby_monitor([A,B|_] = Ns) ->
  429. Na = ?T_NAME,
  430. Pa = t_spawn_reg(A, Na),
  431. Pb = t_spawn(B, _Selective = true),
  432. Ref = t_call(Pb, {apply, gproc, monitor, [Na, standby]}),
  433. ?assert(is_reference(Ref)),
  434. ?assertMatch(ok, t_call(Pa, die)),
  435. ?assertMatch({gproc,{failover,Pb},Ref,Na}, got_msg(Pb, gproc)),
  436. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pb)),
  437. Pc = t_spawn(A, true),
  438. Ref1 = t_call(Pc, {apply, gproc, monitor, [Na, standby]}),
  439. ?assertMatch(true, t_call(Pb, {apply, gproc, unreg, [Na]})),
  440. ?assertMatch({gproc,unreg,Ref1,Na}, got_msg(Pc, gproc)),
  441. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, undefined)).
  442. t_standby_monitor_unreg([A,B|_] = Ns) ->
  443. Na = ?T_NAME,
  444. Pa = t_spawn(A, _Selective = true),
  445. Ref = t_call(Pa, {apply, gproc, monitor, [Na, standby]}),
  446. ?assert(is_reference(Ref)),
  447. ?assertMatch({gproc,{failover,Pa},Ref,Na}, got_msg(Pa, gproc)),
  448. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  449. ?assertMatch(ok, t_call(Pa, die)),
  450. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, undefined)).
  451. t_follow_monitor([A,B|_]) ->
  452. Na = ?T_NAME,
  453. Pa = t_spawn(A, _Selective = true),
  454. Ref = t_call(Pa, {apply, gproc, monitor, [Na, follow]}),
  455. Msg1 = {gproc,unreg,Ref,Na},
  456. {Msg1, Msg1} = {got_msg(Pa), Msg1},
  457. Pb = t_spawn_reg(B, Na),
  458. Msg2 = {gproc,registered,Ref,Na},
  459. {Msg2, Msg2} = {got_msg(Pa), Msg2},
  460. ok = t_call(Pb, die),
  461. ok = t_call(Pa, die).
  462. t_subscribe([A,B|_] = Ns) ->
  463. Na = ?T_NAME,
  464. Pb = t_spawn(B, _Selective = true),
  465. ?assertEqual(ok, t_call(Pb, {apply, gproc_monitor, subscribe, [Na]})),
  466. ?assertMatch({gproc_monitor, Na, undefined}, got_msg(Pb, gproc_monitor)),
  467. Pa = t_spawn_reg(A, Na),
  468. ?assertMatch({gproc_monitor, Na, Pa}, got_msg(Pb, gproc_monitor)),
  469. Pc = t_spawn(A),
  470. t_call(Pa, {apply, gproc, give_away, [Na, Pc]}),
  471. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pc)),
  472. ?assertEqual({gproc_monitor,Na,{migrated,Pc}}, got_msg(Pb, gproc_monitor)),
  473. ?assertEqual(ok, t_call(Pc, die)),
  474. ?assertEqual({gproc_monitor,Na,undefined}, got_msg(Pb, gproc_monitor)),
  475. ok.
  476. %% got_msg(Pb, Tag) ->
  477. %% t_call(Pb,
  478. %% {apply_fun,
  479. %% fun() ->
  480. %% receive
  481. %% M when element(1, M) == Tag ->
  482. %% M
  483. %% after 1000 ->
  484. %% erlang:error({timeout, got_msg, [Pb, Tag]})
  485. %% end
  486. %% end}).
  487. %% Verify that the gproc_dist:sync() call returns true even if a candidate dies
  488. %% while the sync is underway. This test makes use of sys:suspend() to ensure that
  489. %% the other candidate doesn't respond too quickly.
  490. t_sync_cand_dies([A,B|_]) ->
  491. Leader = rpc:call(A, gproc_dist, get_leader, []),
  492. Other = case Leader of
  493. A -> B;
  494. B -> A
  495. end,
  496. ?assertMatch(ok, rpc:call(Other, sys, suspend, [gproc_dist])),
  497. P = rpc:call(Other, erlang, whereis, [gproc_dist]),
  498. Key = rpc:async_call(Leader, gproc_dist, sync, []),
  499. %% The overall timeout for gproc_dist:sync() is 5 seconds. Here, we should
  500. %% still be waiting.
  501. ?assertMatch(timeout, rpc:nb_yield(Key, 1000)),
  502. exit(P, kill),
  503. %% The leader should detect that the other candidate died and respond
  504. %% immediately. Therefore, we should have our answer well within 1 sec.
  505. ?assertMatch({value, true}, rpc:nb_yield(Key, 1000)).
  506. t_fail_node([A,B|_] = Ns) ->
  507. Na = ?T_NAME,
  508. Nb = ?T_NAME,
  509. Pa = t_spawn_reg(A, Na),
  510. Pb = t_spawn_reg(B, Nb),
  511. ?assertMatch(ok, rpc:call(A, application, stop, [gproc])),
  512. ?assertMatch(ok, t_lookup_everywhere(Na, Ns -- [A], undefined)),
  513. ?assertMatch(ok, t_lookup_everywhere(Nb, Ns -- [A], Pb)),
  514. ?assertMatch(ok, rpc:call(A, application, start, [gproc])),
  515. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, undefined)),
  516. ?assertMatch(ok, t_lookup_everywhere(Nb, Ns, Pb)),
  517. ?assertMatch(ok, t_call(Pa, die)),
  518. ?assertMatch(ok, t_call(Pb, die)).
  519. t_master_dies([A,B,C] = Ns) ->
  520. Na = ?T_NAME,
  521. Nb = ?T_NAME,
  522. Nc = ?T_NAME,
  523. Pa = t_spawn_reg(A, Na),
  524. Pb = t_spawn_reg(B, Nb),
  525. Pc = t_spawn_reg(C, Nc),
  526. L = rpc:call(A, gproc_dist, get_leader, []),
  527. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  528. ?assertMatch(ok, t_lookup_everywhere(Nb, Ns, Pb)),
  529. ?assertMatch(ok, t_lookup_everywhere(Nc, Ns, Pc)),
  530. {Nl, Pl} = case L of
  531. A -> {Na, Pa};
  532. B -> {Nb, Pb};
  533. C -> {Nc, Pc}
  534. end,
  535. ?assertMatch(true, rpc:call(A, gproc_dist, sync, [])),
  536. ?assertMatch(ok, rpc:call(L, application, stop, [gproc])),
  537. Names = [{Na,Pa}, {Nb,Pb}, {Nc,Pc}] -- [{Nl, Pl}],
  538. RestNs = Ns -- [L],
  539. ?assertMatch(true, rpc:call(hd(RestNs), gproc_dist, sync, [])),
  540. ?assertMatch(ok, t_lookup_everywhere(Nl, RestNs, undefined)),
  541. [?assertMatch(ok, t_lookup_everywhere(Nx, RestNs, Px))
  542. || {Nx, Px} <- Names],
  543. ok.
  544. t_sleep() ->
  545. timer:sleep(500).
  546. t_lookup_everywhere(Key, Nodes, Exp) ->
  547. true = rpc:call(hd(Nodes), gproc_dist, sync, []),
  548. t_lookup_everywhere(Key, Nodes, Exp, 3).
  549. t_lookup_everywhere(Key, _, Exp, 0) ->
  550. {lookup_failed, Key, Exp};
  551. t_lookup_everywhere(Key, Nodes, Exp, I) ->
  552. Expected = [{N, Exp} || N <- Nodes],
  553. Found = [{N,rpc:call(N, gproc, where, [Key])} || N <- Nodes],
  554. if Expected =/= Found ->
  555. ?debugFmt("lookup ~p failed~n"
  556. "(Expected: ~p;~n"
  557. " Found : ~p), retrying...~n",
  558. [Key, Expected, Found]),
  559. t_sleep(),
  560. t_lookup_everywhere(Key, Nodes, Exp, I-1);
  561. true ->
  562. ok
  563. end.
  564. t_read_everywhere(Key, Pid, Nodes, Exp) ->
  565. true = rpc:call(hd(Nodes), gproc_dist, sync, []),
  566. t_read_everywhere(Key, Pid, Nodes, Exp, 3).
  567. t_read_everywhere(Key, _, _, Exp, 0) ->
  568. {read_failed, Key, Exp};
  569. t_read_everywhere(Key, Pid, Nodes, Exp, I) ->
  570. Expected = [{N, Exp} || N <- Nodes],
  571. Found = [{N, read_result(rpc:call(N, gproc, get_value, [Key, Pid]))}
  572. || N <- Nodes],
  573. if Expected =/= Found ->
  574. ?debugFmt("read ~p failed~n"
  575. "(Expected: ~p;~n"
  576. " Found : ~p), retrying...~n",
  577. [{Key, Pid}, Expected, Found]),
  578. t_sleep(),
  579. t_read_everywhere(Key, Pid, Nodes, Exp, I-1);
  580. true ->
  581. ok
  582. end.
  583. read_result({badrpc, {'EXIT', {badarg, _}}}) -> badarg;
  584. read_result(R) -> R.
  585. t_spawn(Node) -> gproc_test_lib:t_spawn(Node).
  586. t_spawn(Node, Selective) -> gproc_test_lib:t_spawn(Node, Selective).
  587. t_spawn_mreg(Node, KVL) -> gproc_test_lib:t_spawn_mreg(Node, KVL).
  588. t_spawn_reg(Node, N) -> gproc_test_lib:t_spawn_reg(Node, N).
  589. t_spawn_reg(Node, N, V) -> gproc_test_lib:t_spawn_reg(Node, N, V).
  590. t_spawn_reg(Node, N, V, As) -> gproc_test_lib:t_spawn_reg(Node, N, V, As).
  591. t_spawn_reg_shared(Node, N, V) -> gproc_test_lib:t_spawn_reg_shared(Node, N, V).
  592. got_msg(P) -> gproc_test_lib:got_msg(P).
  593. got_msg(P, Tag) -> gproc_test_lib:got_msg(P, Tag).
  594. t_call(P, Req) ->
  595. gproc_test_lib:t_call(P, Req).
  596. start_slaves(Ns) ->
  597. [H|T] = Nodes = [start_slave(N) || N <- Ns],
  598. _ = [rpc:call(H, net_adm, ping, [N]) || N <- T],
  599. Nodes.
  600. start_slave(Name) ->
  601. case node() of
  602. nonode@nohost ->
  603. os:cmd("epmd -daemon"),
  604. {ok, _} = net_kernel:start([gproc_master, shortnames]);
  605. _ ->
  606. ok
  607. end,
  608. {Pa, Pz} = paths(),
  609. Paths = "-pa ./ -pz ../ebin" ++
  610. lists:flatten([[" -pa " ++ Path || Path <- Pa],
  611. [" -pz " ++ Path || Path <- Pz]]),
  612. {ok, Node} = slave:start(host(), Name, Paths),
  613. Node.
  614. paths() ->
  615. Path = code:get_path(),
  616. {ok, [[Root]]} = init:get_argument(root),
  617. {Pas, Rest} = lists:splitwith(fun(P) ->
  618. not lists:prefix(Root, P)
  619. end, Path),
  620. {_, Pzs} = lists:splitwith(fun(P) ->
  621. lists:prefix(Root, P)
  622. end, Rest),
  623. {Pas, Pzs}.
  624. host() ->
  625. [_Name, Host] = re:split(atom_to_list(node()), "@", [{return, list}]),
  626. list_to_atom(Host).
  627. -endif.