gproc_dist_tests.erl 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. %% ``The contents of this file are subject to the Erlang Public License,
  2. %% Version 1.1, (the "License"); you may not use this file except in
  3. %% compliance with the License. You should have received a copy of the
  4. %% Erlang Public License along with this software. If not, it can be
  5. %% retrieved via the world wide web at http://www.erlang.org/.
  6. %%
  7. %% Software distributed under the License is distributed on an "AS IS"
  8. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %% the License for the specific language governing rights and limitations
  10. %% under the License.
  11. %%
  12. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. %% AB. All Rights Reserved.''
  15. %%
  16. %% @author Ulf Wiger <ulf.wiger@erlang-solutions.com>
  17. %%
  18. -module(gproc_dist_tests).
  19. -ifdef(TEST).
  20. -include_lib("eunit/include/eunit.hrl").
  21. -export([t_spawn/1, t_spawn_reg/2]).
  22. dist_test_() ->
  23. {timeout, 60,
  24. [{foreach,
  25. fun() ->
  26. Ns = start_slaves([n1, n2]),
  27. %% dbg:tracer(),
  28. %% [dbg:n(N) || N <- Ns],
  29. %% dbg:tpl(gproc_dist, x),
  30. %% dbg:p(all,[c]),
  31. Ns
  32. end,
  33. fun(Ns) ->
  34. [rpc:call(N, init, stop, []) || N <- Ns]
  35. end,
  36. [
  37. {with, [fun(_) -> {in_parallel, [fun(X) ->
  38. ?debugVal(t_simple_reg(X)) end,
  39. fun(X) ->
  40. ?debugVal(t_await_reg(X))
  41. end,
  42. fun(X) ->
  43. ?debugVal(t_give_away(X))
  44. end]
  45. }
  46. end]}
  47. ]}
  48. ]}.
  49. -define(T_NAME, {n, g, {?MODULE, ?LINE}}).
  50. t_simple_reg([H|_] = Ns) ->
  51. ?debugMsg(t_simple_reg),
  52. Name = ?T_NAME,
  53. P = t_spawn_reg(H, Name),
  54. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, P)),
  55. ?assertMatch(true, t_call(P, {apply, gproc, unreg, [Name]})),
  56. ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
  57. ?assertMatch(ok, t_call(P, die)).
  58. t_await_reg([A,B|_]) ->
  59. ?debugMsg(t_await_reg),
  60. Name = ?T_NAME,
  61. P = t_spawn(A),
  62. P ! {self(), {apply, gproc, await, [Name]}},
  63. P1 = t_spawn_reg(B, Name),
  64. ?assert(P1 == receive
  65. {P, Res} ->
  66. element(1, Res)
  67. end),
  68. ?assertMatch(ok, t_call(P, die)),
  69. ?assertMatch(ok, t_call(P1, die)).
  70. t_give_away([A,B|_] = Ns) ->
  71. ?debugMsg(t_give_away),
  72. Na = ?T_NAME,
  73. Nb = ?T_NAME,
  74. Pa = t_spawn_reg(A, Na),
  75. Pb = t_spawn_reg(B, Nb),
  76. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  77. ?assertMatch(ok, t_lookup_everywhere(Nb, Ns, Pb)),
  78. %% ?debugHere,
  79. ?assertMatch(Pb, t_call(Pa, {apply, {gproc, give_away, [Na, Nb]}})),
  80. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pb)),
  81. %% ?debugHere,
  82. ?assertMatch(Pa, t_call(Pa, {apply, {gproc, give_away, [Na, Pa]}})),
  83. ?assertMatch(ok, t_lookup_everywhere(Na, Ns, Pa)),
  84. %% ?debugHere,
  85. ?assertMatch(ok, t_call(Pa, die)),
  86. ?assertMatch(ok, t_call(Pb, die)).
  87. t_sleep() ->
  88. timer:sleep(1000).
  89. t_lookup_everywhere(Key, Nodes, Exp) ->
  90. t_lookup_everywhere(Key, Nodes, Exp, 3).
  91. t_lookup_everywhere(Key, _, Exp, 0) ->
  92. {lookup_failed, Key, Exp};
  93. t_lookup_everywhere(Key, Nodes, Exp, I) ->
  94. Expected = [{N, Exp} || N <- Nodes],
  95. Found = [{N,rpc:call(N, gproc, where, [Key])} || N <- Nodes],
  96. if Expected =/= Found ->
  97. ?debugFmt("lookup ~p failed (~p), retrying...~n", [Key, Found]),
  98. t_sleep(),
  99. t_lookup_everywhere(Key, Nodes, Exp, I-1);
  100. true ->
  101. ok
  102. end.
  103. t_spawn(Node) ->
  104. Me = self(),
  105. P = spawn(Node, fun() ->
  106. Me ! {self(), ok},
  107. t_loop()
  108. end),
  109. receive
  110. {P, ok} -> P
  111. end.
  112. t_spawn_reg(Node, Name) ->
  113. Me = self(),
  114. spawn(Node, fun() ->
  115. ?assertMatch(true, gproc:reg(Name)),
  116. Me ! {self(), ok},
  117. t_loop()
  118. end),
  119. receive
  120. {P, ok} -> P
  121. end.
  122. t_call(P, Req) ->
  123. P ! {self(), Req},
  124. receive
  125. {P, Res} ->
  126. Res
  127. end.
  128. t_loop() ->
  129. receive
  130. {From, die} ->
  131. From ! {self(), ok};
  132. {From, {apply, M, F, A}} ->
  133. From ! {self(), apply(M, F, A)},
  134. t_loop()
  135. end.
  136. start_slaves(Ns) ->
  137. [start_slave(N) || N <- Ns].
  138. start_slave(Name) ->
  139. case node() of
  140. nonode@nohost ->
  141. os:cmd("epmd -daemon"),
  142. {ok, _} = net_kernel:start([gproc_master, shortnames]);
  143. _ ->
  144. ok
  145. end,
  146. {ok, Node} = slave:start(
  147. host(), Name,
  148. "-pa . -pz ../ebin -pa ../deps/gen_leader/ebin "
  149. "-gproc gproc_dist all"),
  150. %% io:fwrite(user, "Slave node: ~p~n", [Node]),
  151. Node.
  152. host() ->
  153. [_Name, Host] = re:split(atom_to_list(node()), "@", [{return, list}]),
  154. list_to_atom(Host).
  155. -endif.