gproc_dist_tests.erl 23 KB

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