gproc_dist_tests.erl 28 KB

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