syn_groups_SUITE.erl 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397
  1. %% ==========================================================================================================
  2. %% Syn - A global Process Registry and Process Group manager.
  3. %%
  4. %% The MIT License (MIT)
  5. %%
  6. %% Copyright (c) 2015-2021 Roberto Ostinelli <roberto@ostinelli.net> and Neato Robotics, Inc.
  7. %%
  8. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  9. %% of this software and associated documentation files (the "Software"), to deal
  10. %% in the Software without restriction, including without limitation the rights
  11. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. %% copies of the Software, and to permit persons to whom the Software is
  13. %% furnished to do so, subject to the following conditions:
  14. %%
  15. %% The above copyright notice and this permission notice shall be included in
  16. %% all copies or substantial portions of the Software.
  17. %%
  18. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. %% THE SOFTWARE.
  25. %% ==========================================================================================================
  26. -module(syn_groups_SUITE).
  27. %% callbacks
  28. -export([all/0]).
  29. -export([init_per_suite/1, end_per_suite/1]).
  30. -export([groups/0, init_per_group/2, end_per_group/2]).
  31. -export([init_per_testcase/2, end_per_testcase/2]).
  32. %% tests
  33. -export([
  34. three_nodes_discover_default_scope/1,
  35. three_nodes_discover_custom_scope/1,
  36. three_nodes_join_leave_and_monitor_default_scope/1,
  37. three_nodes_join_leave_and_monitor_custom_scope/1,
  38. three_nodes_cluster_changes/1,
  39. three_nodes_custom_event_handler_joined_left/1
  40. ]).
  41. %% include
  42. -include_lib("common_test/include/ct.hrl").
  43. -include_lib("syn/src/syn.hrl").
  44. %% ===================================================================
  45. %% Callbacks
  46. %% ===================================================================
  47. %% -------------------------------------------------------------------
  48. %% Function: all() -> GroupsAndTestCases | {skip,Reason}
  49. %% GroupsAndTestCases = [{group,GroupName} | TestCase]
  50. %% GroupName = atom()
  51. %% TestCase = atom()
  52. %% Reason = any()
  53. %% -------------------------------------------------------------------
  54. all() ->
  55. [
  56. {group, three_nodes_groups}
  57. ].
  58. %% -------------------------------------------------------------------
  59. %% Function: groups() -> [Group]
  60. %% Group = {GroupName,Properties,GroupsAndTestCases}
  61. %% GroupName = atom()
  62. %% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
  63. %% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
  64. %% TestCase = atom()
  65. %% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
  66. %% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
  67. %% repeat_until_any_ok | repeat_until_any_fail
  68. %% N = integer() | forever
  69. %% -------------------------------------------------------------------
  70. groups() ->
  71. [
  72. {three_nodes_groups, [shuffle], [
  73. three_nodes_discover_default_scope,
  74. three_nodes_discover_custom_scope,
  75. three_nodes_join_leave_and_monitor_default_scope,
  76. three_nodes_join_leave_and_monitor_custom_scope,
  77. three_nodes_cluster_changes,
  78. three_nodes_custom_event_handler_joined_left
  79. ]}
  80. ].
  81. %% -------------------------------------------------------------------
  82. %% Function: init_per_suite(Config0) ->
  83. %% Config1 | {skip,Reason} |
  84. %% {skip_and_save,Reason,Config1}
  85. %% Config0 = Config1 = [tuple()]
  86. %% Reason = any()
  87. %% -------------------------------------------------------------------
  88. init_per_suite(Config) ->
  89. Config.
  90. %% -------------------------------------------------------------------
  91. %% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
  92. %% Config0 = Config1 = [tuple()]
  93. %% -------------------------------------------------------------------
  94. end_per_suite(_Config) ->
  95. ok.
  96. %% -------------------------------------------------------------------
  97. %% Function: init_per_group(GroupName, Config0) ->
  98. %% Config1 | {skip,Reason} |
  99. %% {skip_and_save,Reason,Config1}
  100. %% GroupName = atom()
  101. %% Config0 = Config1 = [tuple()]
  102. %% Reason = any()
  103. %% -------------------------------------------------------------------
  104. init_per_group(three_nodes_groups, Config) ->
  105. %% start slave
  106. {ok, SlaveNode1} = syn_test_suite_helper:start_slave(syn_slave_1),
  107. {ok, SlaveNode2} = syn_test_suite_helper:start_slave(syn_slave_2),
  108. syn_test_suite_helper:connect_node(SlaveNode1),
  109. syn_test_suite_helper:connect_node(SlaveNode2),
  110. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  111. %% wait full cluster
  112. case syn_test_suite_helper:wait_cluster_mesh_connected([node(), SlaveNode1, SlaveNode2]) of
  113. ok ->
  114. %% config
  115. [{slave_node_1, SlaveNode1}, {slave_node_2, SlaveNode2} | Config];
  116. Other ->
  117. ct:pal("*********** Could not get full cluster, skipping"),
  118. end_per_group(three_nodes_groups, Config),
  119. {skip, Other}
  120. end;
  121. init_per_group(_GroupName, Config) ->
  122. Config.
  123. %% -------------------------------------------------------------------
  124. %% Function: end_per_group(GroupName, Config0) ->
  125. %% void() | {save_config,Config1}
  126. %% GroupName = atom()
  127. %% Config0 = Config1 = [tuple()]
  128. %% -------------------------------------------------------------------
  129. end_per_group(three_nodes_groups, Config) ->
  130. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  131. syn_test_suite_helper:connect_node(SlaveNode1),
  132. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  133. syn_test_suite_helper:connect_node(SlaveNode2),
  134. syn_test_suite_helper:clean_after_test(),
  135. syn_test_suite_helper:stop_slave(syn_slave_1),
  136. syn_test_suite_helper:stop_slave(syn_slave_2),
  137. timer:sleep(1000);
  138. end_per_group(_GroupName, _Config) ->
  139. syn_test_suite_helper:clean_after_test().
  140. %% -------------------------------------------------------------------
  141. %% Function: init_per_testcase(TestCase, Config0) ->
  142. %% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
  143. %% TestCase = atom()
  144. %% Config0 = Config1 = [tuple()]
  145. %% Reason = any()
  146. %% -------------------------------------------------------------------
  147. init_per_testcase(TestCase, Config) ->
  148. ct:pal("Starting test: ~p", [TestCase]),
  149. Config.
  150. %% -------------------------------------------------------------------
  151. %% Function: end_per_testcase(TestCase, Config0) ->
  152. %% void() | {save_config,Config1} | {fail,Reason}
  153. %% TestCase = atom()
  154. %% Config0 = Config1 = [tuple()]
  155. %% Reason = any()
  156. %% -------------------------------------------------------------------
  157. end_per_testcase(_, _Config) ->
  158. syn_test_suite_helper:clean_after_test().
  159. %% ===================================================================
  160. %% Tests
  161. %% ===================================================================
  162. three_nodes_discover_default_scope(Config) ->
  163. %% get slaves
  164. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  165. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  166. %% start syn on nodes
  167. ok = syn:start(),
  168. ok = rpc:call(SlaveNode1, syn, start, []),
  169. ok = rpc:call(SlaveNode2, syn, start, []),
  170. %% check
  171. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  172. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  173. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  174. %% simulate full netsplit
  175. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  176. syn_test_suite_helper:disconnect_node(SlaveNode1),
  177. syn_test_suite_helper:disconnect_node(SlaveNode2),
  178. syn_test_suite_helper:assert_cluster(node(), []),
  179. %% check
  180. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, []),
  181. %% reconnect slave 1
  182. syn_test_suite_helper:connect_node(SlaveNode1),
  183. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1]),
  184. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  185. %% check
  186. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1]),
  187. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node()]),
  188. %% reconnect all
  189. syn_test_suite_helper:connect_node(SlaveNode2),
  190. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  191. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  192. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  193. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  194. %% check
  195. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  196. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  197. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  198. %% simulate full netsplit, again
  199. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  200. syn_test_suite_helper:disconnect_node(SlaveNode1),
  201. syn_test_suite_helper:disconnect_node(SlaveNode2),
  202. syn_test_suite_helper:assert_cluster(node(), []),
  203. %% check
  204. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, []),
  205. %% reconnect all, again
  206. syn_test_suite_helper:connect_node(SlaveNode2),
  207. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  208. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  209. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  210. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  211. %% check
  212. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  213. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  214. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  215. %% crash the scope process on local
  216. syn_test_suite_helper:kill_process(syn_registry_default),
  217. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  218. %% check, it should have rebuilt after supervisor restarts it
  219. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  220. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  221. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  222. %% crash scopes supervisor on local
  223. syn_test_suite_helper:kill_process(syn_scopes_sup),
  224. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  225. %% check
  226. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  227. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  228. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]).
  229. three_nodes_discover_custom_scope(Config) ->
  230. %% get slaves
  231. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  232. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  233. %% start syn on nodes
  234. ok = syn:start(),
  235. ok = rpc:call(SlaveNode1, syn, start, []),
  236. ok = rpc:call(SlaveNode2, syn, start, []),
  237. %% add custom scopes
  238. ok = syn:add_node_to_scope(custom_scope_ab),
  239. ok = syn:add_node_to_scope(custom_scope_all),
  240. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_ab, custom_scope_bc, custom_scope_all]]),
  241. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc, custom_scope_c, custom_scope_all]]),
  242. %% get_subcluster_nodes should return invalid errors
  243. {'EXIT', {{invalid_scope, custom_abcdef}, _}} = catch syn_registry:get_subcluster_nodes(custom_abcdef),
  244. %% check
  245. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  246. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  247. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  248. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  249. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  250. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  251. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_c, []),
  252. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  253. %% check default
  254. syn_test_suite_helper:assert_groups_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  255. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  256. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  257. %% disconnect node 2 (node 1 can still see node 2)
  258. syn_test_suite_helper:disconnect_node(SlaveNode2),
  259. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1]),
  260. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  261. %% check
  262. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  263. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_all, [SlaveNode1]),
  264. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  265. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  266. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  267. %% reconnect node 2
  268. syn_test_suite_helper:connect_node(SlaveNode2),
  269. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  270. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  271. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  272. %% check
  273. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  274. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  275. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  276. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  277. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  278. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  279. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_c, []),
  280. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  281. %% crash a scope process on 2
  282. rpc:call(SlaveNode2, syn_test_suite_helper, kill_process, [syn_registry_custom_scope_bc]),
  283. rpc:call(SlaveNode2, syn_test_suite_helper, wait_process_name_ready, [syn_registry_default]),
  284. %% check
  285. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  286. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  287. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  288. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  289. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  290. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  291. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_c, []),
  292. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  293. %% crash scopes supervisor on local
  294. syn_test_suite_helper:kill_process(syn_scopes_sup),
  295. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  296. %% check
  297. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  298. syn_test_suite_helper:assert_groups_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  299. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  300. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  301. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  302. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  303. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_c, []),
  304. syn_test_suite_helper:assert_groups_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]).
  305. three_nodes_join_leave_and_monitor_default_scope(Config) ->
  306. %% get slaves
  307. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  308. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  309. %% start syn on nodes
  310. ok = syn:start(),
  311. ok = rpc:call(SlaveNode1, syn, start, []),
  312. ok = rpc:call(SlaveNode2, syn, start, []),
  313. %% start processes
  314. Pid = syn_test_suite_helper:start_process(),
  315. PidWithMeta = syn_test_suite_helper:start_process(),
  316. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  317. %% check
  318. [] = syn:get_members({group, "one"}),
  319. [] = rpc:call(SlaveNode1, syn, get_members, [{group, "one"}]),
  320. [] = rpc:call(SlaveNode2, syn, get_members, [{group, "one"}]),
  321. [] = syn:get_members({group, "two"}),
  322. [] = rpc:call(SlaveNode1, syn, get_members, [{group, "two"}]),
  323. [] = rpc:call(SlaveNode2, syn, get_members, [{group, "two"}]),
  324. [] = syn:get_local_members({group, "one"}),
  325. [] = rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}]),
  326. [] = rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}]),
  327. [] = syn:get_local_members({group, "two"}),
  328. [] = rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}]),
  329. [] = rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}]),
  330. 0 = syn:groups_count(default),
  331. 0 = syn:groups_count(default, node()),
  332. 0 = syn:groups_count(default, SlaveNode1),
  333. 0 = syn:groups_count(default, SlaveNode2),
  334. %% join
  335. ok = syn:join({group, "one"}, Pid),
  336. ok = syn:join({group, "one"}, PidWithMeta, <<"with meta">>),
  337. ok = syn:join({group, "one"}, PidRemoteOn1),
  338. ok = syn:join({group, "two"}, Pid),
  339. ok = syn:join({group, "two"}, PidWithMeta, "with-meta-2"),
  340. %% errors
  341. {error, not_alive} = syn:join({"pid not alive"}, list_to_pid("<0.9999.0>")),
  342. {error, not_in_group} = syn:leave({group, "three"}, Pid),
  343. %% retrieve
  344. syn_test_suite_helper:assert_wait(
  345. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}, {PidRemoteOn1, undefined}]),
  346. fun() -> lists:sort(syn:get_members({group, "one"})) end
  347. ),
  348. syn_test_suite_helper:assert_wait(
  349. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}, {PidRemoteOn1, undefined}]),
  350. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "one"}])) end
  351. ),
  352. syn_test_suite_helper:assert_wait(
  353. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}, {PidRemoteOn1, undefined}]),
  354. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
  355. ),
  356. syn_test_suite_helper:assert_wait(
  357. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
  358. fun() -> lists:sort(syn:get_local_members({group, "one"})) end
  359. ),
  360. syn_test_suite_helper:assert_wait(
  361. [{PidRemoteOn1, undefined}],
  362. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
  363. ),
  364. syn_test_suite_helper:assert_wait(
  365. [],
  366. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
  367. ),
  368. syn_test_suite_helper:assert_wait(
  369. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  370. fun() -> lists:sort(syn:get_members({group, "two"})) end
  371. ),
  372. syn_test_suite_helper:assert_wait(
  373. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  374. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "two"}])) end
  375. ),
  376. syn_test_suite_helper:assert_wait(
  377. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  378. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
  379. ),
  380. syn_test_suite_helper:assert_wait(
  381. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  382. fun() -> lists:sort(syn:get_local_members({group, "two"})) end
  383. ),
  384. syn_test_suite_helper:assert_wait(
  385. [],
  386. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
  387. ),
  388. syn_test_suite_helper:assert_wait(
  389. [],
  390. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
  391. ),
  392. 2 = syn:groups_count(default),
  393. 2 = syn:groups_count(default, node()),
  394. 1 = syn:groups_count(default, SlaveNode1),
  395. 0 = syn:groups_count(default, SlaveNode2),
  396. %% re-join to edit meta
  397. ok = syn:join({group, "one"}, PidWithMeta, <<"with updated meta">>),
  398. ok = rpc:call(SlaveNode2, syn, join, [{group, "one"}, PidRemoteOn1, added_meta]), %% updated on slave 2
  399. %% retrieve
  400. syn_test_suite_helper:assert_wait(
  401. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}, {PidRemoteOn1, added_meta}]),
  402. fun() -> lists:sort(syn:get_members({group, "one"})) end
  403. ),
  404. syn_test_suite_helper:assert_wait(
  405. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}, {PidRemoteOn1, added_meta}]),
  406. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "one"}])) end
  407. ),
  408. syn_test_suite_helper:assert_wait(
  409. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}, {PidRemoteOn1, added_meta}]),
  410. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
  411. ),
  412. syn_test_suite_helper:assert_wait(
  413. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
  414. fun() -> lists:sort(syn:get_local_members({group, "one"})) end
  415. ),
  416. syn_test_suite_helper:assert_wait(
  417. [{PidRemoteOn1, added_meta}],
  418. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
  419. ),
  420. syn_test_suite_helper:assert_wait(
  421. [],
  422. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
  423. ),
  424. syn_test_suite_helper:assert_wait(
  425. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  426. fun() -> lists:sort(syn:get_members({group, "two"})) end
  427. ),
  428. syn_test_suite_helper:assert_wait(
  429. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  430. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "two"}])) end
  431. ),
  432. syn_test_suite_helper:assert_wait(
  433. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  434. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
  435. ),
  436. syn_test_suite_helper:assert_wait(
  437. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  438. fun() -> lists:sort(syn:get_local_members({group, "two"})) end
  439. ),
  440. syn_test_suite_helper:assert_wait(
  441. [],
  442. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
  443. ),
  444. syn_test_suite_helper:assert_wait(
  445. [],
  446. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
  447. ),
  448. 2 = syn:groups_count(default),
  449. 2 = syn:groups_count(default, node()),
  450. 1 = syn:groups_count(default, SlaveNode1),
  451. 0 = syn:groups_count(default, SlaveNode2),
  452. %% crash scope process to ensure that monitors get recreated
  453. exit(whereis(syn_groups_default), kill),
  454. syn_test_suite_helper:wait_process_name_ready(syn_groups_default),
  455. %% kill process
  456. syn_test_suite_helper:kill_process(Pid),
  457. syn_test_suite_helper:kill_process(PidRemoteOn1),
  458. %% leave
  459. ok = syn:leave({group, "one"}, PidWithMeta),
  460. %% retrieve
  461. syn_test_suite_helper:assert_wait(
  462. [],
  463. fun() -> lists:sort(syn:get_members({group, "one"})) end
  464. ),
  465. syn_test_suite_helper:assert_wait(
  466. [],
  467. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "one"}])) end
  468. ),
  469. syn_test_suite_helper:assert_wait(
  470. [],
  471. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "one"}])) end
  472. ),
  473. syn_test_suite_helper:assert_wait(
  474. [],
  475. fun() -> lists:sort(syn:get_local_members({group, "one"})) end
  476. ),
  477. syn_test_suite_helper:assert_wait(
  478. [],
  479. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "one"}])) end
  480. ),
  481. syn_test_suite_helper:assert_wait(
  482. [],
  483. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "one"}])) end
  484. ),
  485. syn_test_suite_helper:assert_wait(
  486. [{PidWithMeta, "with-meta-2"}],
  487. fun() -> lists:sort(syn:get_members({group, "two"})) end
  488. ),
  489. syn_test_suite_helper:assert_wait(
  490. [{PidWithMeta, "with-meta-2"}],
  491. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [{group, "two"}])) end
  492. ),
  493. syn_test_suite_helper:assert_wait(
  494. [{PidWithMeta, "with-meta-2"}],
  495. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [{group, "two"}])) end
  496. ),
  497. syn_test_suite_helper:assert_wait(
  498. [{PidWithMeta, "with-meta-2"}],
  499. fun() -> lists:sort(syn:get_local_members({group, "two"})) end
  500. ),
  501. syn_test_suite_helper:assert_wait(
  502. [],
  503. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [{group, "two"}])) end
  504. ),
  505. syn_test_suite_helper:assert_wait(
  506. [],
  507. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [{group, "two"}])) end
  508. ),
  509. 1 = syn:groups_count(default),
  510. 1 = syn:groups_count(default, node()),
  511. 0 = syn:groups_count(default, SlaveNode1),
  512. 0 = syn:groups_count(default, SlaveNode2),
  513. %% errors
  514. {error, not_in_group} = syn:leave({group, "one"}, PidWithMeta).
  515. three_nodes_join_leave_and_monitor_custom_scope(Config) ->
  516. %% get slaves
  517. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  518. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  519. %% start syn on nodes
  520. ok = syn:start(),
  521. ok = rpc:call(SlaveNode1, syn, start, []),
  522. ok = rpc:call(SlaveNode2, syn, start, []),
  523. %% add custom scopes
  524. ok = syn:add_node_to_scope(custom_scope_ab),
  525. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_ab, custom_scope_bc]]),
  526. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  527. %% start processes
  528. Pid = syn_test_suite_helper:start_process(),
  529. PidWithMeta = syn_test_suite_helper:start_process(),
  530. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  531. PidRemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  532. %% check
  533. [] = syn:get_members(custom_scope_ab, {group, "one"}),
  534. [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}]),
  535. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
  536. [] = syn:get_local_members(custom_scope_ab, {group, "one"}),
  537. [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
  538. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
  539. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "one"}),
  540. [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "one"}]),
  541. [] = rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "one"}]),
  542. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "one"}),
  543. [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "one"}]),
  544. [] = rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "one"}]),
  545. [] = syn:get_members(custom_scope_ab, {group, "two"}),
  546. [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}]),
  547. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
  548. [] = syn:get_local_members(custom_scope_ab, {group, "two"}),
  549. [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
  550. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
  551. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
  552. [] = rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "two"}]),
  553. [] = rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}]),
  554. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
  555. [] = rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}]),
  556. [] = rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}]),
  557. %% join
  558. ok = syn:join(custom_scope_ab, {group, "one"}, Pid),
  559. ok = syn:join(custom_scope_ab, {group, "one"}, PidWithMeta, <<"with meta">>),
  560. ok = rpc:call(SlaveNode1, syn, join, [custom_scope_bc, {group, "two"}, PidRemoteOn1]),
  561. ok = syn:join(custom_scope_ab, {group, "two"}, Pid),
  562. ok = syn:join(custom_scope_ab, {group, "two"}, PidWithMeta, "with-meta-2"),
  563. %% errors
  564. {error, not_alive} = syn:join({"pid not alive"}, list_to_pid("<0.9999.0>")),
  565. {error, not_in_group} = syn:leave({group, "three"}, Pid),
  566. {'EXIT', {{invalid_scope, custom_scope_ab}, _}} = catch syn:join(custom_scope_ab, {group, "one"}, PidRemoteOn2),
  567. %% retrieve
  568. syn_test_suite_helper:assert_wait(
  569. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
  570. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "one"})) end
  571. ),
  572. syn_test_suite_helper:assert_wait(
  573. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
  574. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
  575. ),
  576. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
  577. syn_test_suite_helper:assert_wait(
  578. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with meta">>}]),
  579. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
  580. ),
  581. syn_test_suite_helper:assert_wait(
  582. [],
  583. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
  584. ),
  585. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
  586. syn_test_suite_helper:assert_wait(
  587. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  588. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
  589. ),
  590. syn_test_suite_helper:assert_wait(
  591. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  592. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
  593. ),
  594. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
  595. syn_test_suite_helper:assert_wait(
  596. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  597. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
  598. ),
  599. syn_test_suite_helper:assert_wait(
  600. [],
  601. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
  602. ),
  603. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
  604. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
  605. syn_test_suite_helper:assert_wait(
  606. [{PidRemoteOn1, undefined}],
  607. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  608. ),
  609. syn_test_suite_helper:assert_wait(
  610. [{PidRemoteOn1, undefined}],
  611. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  612. ),
  613. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
  614. syn_test_suite_helper:assert_wait(
  615. [{PidRemoteOn1, undefined}],
  616. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  617. ),
  618. syn_test_suite_helper:assert_wait(
  619. [],
  620. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  621. ),
  622. 2 = syn:groups_count(custom_scope_ab),
  623. 2 = syn:groups_count(custom_scope_ab, node()),
  624. 0 = syn:groups_count(custom_scope_ab, SlaveNode1),
  625. 0 = syn:groups_count(custom_scope_ab, SlaveNode2),
  626. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  627. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  628. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  629. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  630. 2 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab]),
  631. 2 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, node()]),
  632. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  633. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  634. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  635. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  636. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  637. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  638. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab]),
  639. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, node()]),
  640. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  641. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  642. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  643. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  644. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  645. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  646. %% re-join to edit meta
  647. ok = syn:join(custom_scope_ab, {group, "one"}, PidWithMeta, <<"with updated meta">>),
  648. ok = rpc:call(SlaveNode2, syn, join, [custom_scope_bc, {group, "two"}, PidRemoteOn1, added_meta]), %% updated on slave 2
  649. %% retrieve
  650. syn_test_suite_helper:assert_wait(
  651. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
  652. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "one"})) end
  653. ),
  654. syn_test_suite_helper:assert_wait(
  655. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
  656. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
  657. ),
  658. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
  659. syn_test_suite_helper:assert_wait(
  660. lists:sort([{Pid, undefined}, {PidWithMeta, <<"with updated meta">>}]),
  661. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
  662. ),
  663. syn_test_suite_helper:assert_wait(
  664. [],
  665. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
  666. ),
  667. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
  668. syn_test_suite_helper:assert_wait(
  669. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  670. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
  671. ),
  672. syn_test_suite_helper:assert_wait(
  673. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  674. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
  675. ),
  676. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
  677. syn_test_suite_helper:assert_wait(
  678. lists:sort([{Pid, undefined}, {PidWithMeta, "with-meta-2"}]),
  679. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
  680. ),
  681. syn_test_suite_helper:assert_wait(
  682. [],
  683. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
  684. ),
  685. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
  686. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
  687. syn_test_suite_helper:assert_wait(
  688. [{PidRemoteOn1, added_meta}],
  689. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  690. ),
  691. syn_test_suite_helper:assert_wait(
  692. [{PidRemoteOn1, added_meta}],
  693. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  694. ),
  695. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
  696. syn_test_suite_helper:assert_wait(
  697. [{PidRemoteOn1, added_meta}],
  698. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  699. ),
  700. syn_test_suite_helper:assert_wait(
  701. [],
  702. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  703. ),
  704. 2 = syn:groups_count(custom_scope_ab),
  705. 2 = syn:groups_count(custom_scope_ab, node()),
  706. 0 = syn:groups_count(custom_scope_ab, SlaveNode1),
  707. 0 = syn:groups_count(custom_scope_ab, SlaveNode2),
  708. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  709. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  710. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  711. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  712. 2 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab]),
  713. 2 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, node()]),
  714. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  715. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  716. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  717. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  718. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  719. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  720. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab]),
  721. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, node()]),
  722. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  723. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  724. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  725. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  726. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  727. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  728. %% crash scope process to ensure that monitors get recreated
  729. exit(whereis(syn_groups_custom_scope_ab), kill),
  730. syn_test_suite_helper:wait_process_name_ready(syn_groups_custom_scope_ab),
  731. %% kill process
  732. syn_test_suite_helper:kill_process(Pid),
  733. syn_test_suite_helper:kill_process(PidRemoteOn1),
  734. %% leave
  735. ok = syn:leave(custom_scope_ab, {group, "one"}, PidWithMeta),
  736. %% retrieve
  737. syn_test_suite_helper:assert_wait(
  738. [],
  739. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "one"})) end
  740. ),
  741. syn_test_suite_helper:assert_wait(
  742. [],
  743. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "one"}])) end
  744. ),
  745. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "one"}]),
  746. syn_test_suite_helper:assert_wait(
  747. [],
  748. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "one"})) end
  749. ),
  750. syn_test_suite_helper:assert_wait(
  751. [],
  752. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "one"}])) end
  753. ),
  754. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "one"}]),
  755. syn_test_suite_helper:assert_wait(
  756. [{PidWithMeta, "with-meta-2"}],
  757. fun() -> lists:sort(syn:get_members(custom_scope_ab, {group, "two"})) end
  758. ),
  759. syn_test_suite_helper:assert_wait(
  760. [{PidWithMeta, "with-meta-2"}],
  761. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_ab, {group, "two"}])) end
  762. ),
  763. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_members, [custom_scope_ab, {group, "two"}]),
  764. syn_test_suite_helper:assert_wait(
  765. [{PidWithMeta, "with-meta-2"}],
  766. fun() -> lists:sort(syn:get_local_members(custom_scope_ab, {group, "two"})) end
  767. ),
  768. syn_test_suite_helper:assert_wait(
  769. [],
  770. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_ab, {group, "two"}])) end
  771. ),
  772. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_ab, {group, "two"}]),
  773. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, {group, "two"}),
  774. syn_test_suite_helper:assert_wait(
  775. [],
  776. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  777. ),
  778. syn_test_suite_helper:assert_wait(
  779. [], fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, {group, "two"}])) end
  780. ),
  781. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, {group, "two"}),
  782. syn_test_suite_helper:assert_wait(
  783. [],
  784. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  785. ),
  786. syn_test_suite_helper:assert_wait(
  787. [], fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, {group, "two"}])) end
  788. ),
  789. 1 = syn:groups_count(custom_scope_ab),
  790. 1 = syn:groups_count(custom_scope_ab, node()),
  791. 0 = syn:groups_count(custom_scope_ab, SlaveNode1),
  792. 0 = syn:groups_count(custom_scope_ab, SlaveNode2),
  793. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  794. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  795. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  796. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  797. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab]),
  798. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, node()]),
  799. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  800. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  801. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  802. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  803. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  804. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  805. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab]),
  806. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, node()]),
  807. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode1]),
  808. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, groups_count, [custom_scope_ab, SlaveNode2]),
  809. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  810. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  811. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  812. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  813. %% errors
  814. {error, not_in_group} = syn:leave(custom_scope_ab, {group, "one"}, PidWithMeta).
  815. three_nodes_cluster_changes(Config) ->
  816. %% get slaves
  817. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  818. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  819. %% disconnect 1 from 2
  820. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  821. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  822. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  823. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  824. %% start syn on 1 and 2, nodes don't know of each other
  825. ok = rpc:call(SlaveNode1, syn, start, []),
  826. ok = rpc:call(SlaveNode2, syn, start, []),
  827. %% add custom scopes
  828. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_bc]]),
  829. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  830. %% start processes
  831. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  832. PidRemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  833. %% join
  834. ok = rpc:call(SlaveNode1, syn, join, [<<"common-group">>, PidRemoteOn1, "meta-1"]),
  835. ok = rpc:call(SlaveNode2, syn, join, [<<"common-group">>, PidRemoteOn2, "meta-2"]),
  836. ok = rpc:call(SlaveNode2, syn, join, [<<"group-2">>, PidRemoteOn2, "other-meta"]),
  837. ok = rpc:call(SlaveNode1, syn, join, [custom_scope_bc, <<"scoped-on-bc">>, PidRemoteOn1, "scoped-meta-1"]),
  838. ok = rpc:call(SlaveNode2, syn, join, [custom_scope_bc, <<"scoped-on-bc">>, PidRemoteOn2, "scoped-meta-2"]),
  839. %% form full cluster
  840. ok = syn:start(),
  841. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  842. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  843. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  844. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  845. syn_test_suite_helper:wait_process_name_ready(syn_groups_default),
  846. %% retrieve
  847. syn_test_suite_helper:assert_wait(
  848. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  849. fun() -> lists:sort(syn:get_members(<<"common-group">>)) end
  850. ),
  851. syn_test_suite_helper:assert_wait(
  852. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  853. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"common-group">>])) end
  854. ),
  855. syn_test_suite_helper:assert_wait(
  856. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  857. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
  858. ),
  859. syn_test_suite_helper:assert_wait(
  860. [],
  861. fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
  862. ),
  863. syn_test_suite_helper:assert_wait(
  864. [{PidRemoteOn1, "meta-1"}],
  865. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
  866. ),
  867. syn_test_suite_helper:assert_wait(
  868. [{PidRemoteOn2, "meta-2"}],
  869. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
  870. ),
  871. syn_test_suite_helper:assert_wait(
  872. [{PidRemoteOn2, "other-meta"}],
  873. fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
  874. ),
  875. syn_test_suite_helper:assert_wait(
  876. [{PidRemoteOn2, "other-meta"}],
  877. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"group-2">>])) end
  878. ),
  879. syn_test_suite_helper:assert_wait(
  880. [{PidRemoteOn2, "other-meta"}],
  881. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
  882. ),
  883. syn_test_suite_helper:assert_wait(
  884. [],
  885. fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
  886. ),
  887. syn_test_suite_helper:assert_wait(
  888. [],
  889. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
  890. ),
  891. syn_test_suite_helper:assert_wait(
  892. [{PidRemoteOn2, "other-meta"}],
  893. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
  894. ),
  895. 2 = syn:groups_count(default),
  896. 0 = syn:groups_count(default, node()),
  897. 1 = syn:groups_count(default, SlaveNode1),
  898. 2 = syn:groups_count(default, SlaveNode2),
  899. 2 = rpc:call(SlaveNode1, syn, groups_count, [default]),
  900. 0 = rpc:call(SlaveNode1, syn, groups_count, [default, node()]),
  901. 1 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode1]),
  902. 2 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode2]),
  903. 2 = rpc:call(SlaveNode2, syn, groups_count, [default]),
  904. 0 = rpc:call(SlaveNode2, syn, groups_count, [default, node()]),
  905. 1 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
  906. 2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
  907. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
  908. syn_test_suite_helper:assert_wait(
  909. lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
  910. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  911. ),
  912. syn_test_suite_helper:assert_wait(
  913. lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
  914. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  915. ),
  916. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
  917. syn_test_suite_helper:assert_wait(
  918. [{PidRemoteOn1, "scoped-meta-1"}],
  919. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  920. ),
  921. syn_test_suite_helper:assert_wait(
  922. [{PidRemoteOn2, "scoped-meta-2"}],
  923. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  924. ),
  925. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  926. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  927. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  928. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  929. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  930. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  931. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  932. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  933. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  934. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  935. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  936. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  937. %% partial netsplit (1 cannot see 2)
  938. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  939. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  940. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  941. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  942. %% retrieve
  943. syn_test_suite_helper:assert_wait(
  944. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  945. fun() -> lists:sort(syn:get_members(<<"common-group">>)) end
  946. ),
  947. syn_test_suite_helper:assert_wait(
  948. [{PidRemoteOn1, "meta-1"}],
  949. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"common-group">>])) end
  950. ),
  951. syn_test_suite_helper:assert_wait(
  952. [{PidRemoteOn2, "meta-2"}],
  953. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
  954. ),
  955. syn_test_suite_helper:assert_wait(
  956. [],
  957. fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
  958. ),
  959. syn_test_suite_helper:assert_wait(
  960. [{PidRemoteOn1, "meta-1"}],
  961. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
  962. ),
  963. syn_test_suite_helper:assert_wait(
  964. [{PidRemoteOn2, "meta-2"}],
  965. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
  966. ),
  967. syn_test_suite_helper:assert_wait(
  968. [{PidRemoteOn2, "other-meta"}],
  969. fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
  970. ),
  971. syn_test_suite_helper:assert_wait(
  972. [],
  973. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"group-2">>])) end
  974. ),
  975. syn_test_suite_helper:assert_wait(
  976. [{PidRemoteOn2, "other-meta"}],
  977. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
  978. ),
  979. syn_test_suite_helper:assert_wait(
  980. [],
  981. fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
  982. ),
  983. syn_test_suite_helper:assert_wait(
  984. [],
  985. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
  986. ),
  987. syn_test_suite_helper:assert_wait(
  988. [{PidRemoteOn2, "other-meta"}],
  989. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
  990. ),
  991. 2 = syn:groups_count(default),
  992. 0 = syn:groups_count(default, node()),
  993. 1 = syn:groups_count(default, SlaveNode1),
  994. 2 = syn:groups_count(default, SlaveNode2),
  995. 1 = rpc:call(SlaveNode1, syn, groups_count, [default]),
  996. 0 = rpc:call(SlaveNode1, syn, groups_count, [default, node()]),
  997. 1 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode1]),
  998. 0 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode2]),
  999. 2 = rpc:call(SlaveNode2, syn, groups_count, [default]),
  1000. 0 = rpc:call(SlaveNode2, syn, groups_count, [default, node()]),
  1001. 0 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
  1002. 2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
  1003. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
  1004. syn_test_suite_helper:assert_wait(
  1005. [{PidRemoteOn1, "scoped-meta-1"}],
  1006. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1007. ),
  1008. syn_test_suite_helper:assert_wait(
  1009. [{PidRemoteOn2, "scoped-meta-2"}],
  1010. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1011. ),
  1012. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
  1013. syn_test_suite_helper:assert_wait(
  1014. [{PidRemoteOn1, "scoped-meta-1"}],
  1015. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1016. ),
  1017. syn_test_suite_helper:assert_wait(
  1018. [{PidRemoteOn2, "scoped-meta-2"}],
  1019. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1020. ),
  1021. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  1022. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  1023. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  1024. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  1025. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  1026. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  1027. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  1028. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  1029. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  1030. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  1031. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  1032. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  1033. %% re-join
  1034. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1035. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1036. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1037. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1038. %% retrieve
  1039. syn_test_suite_helper:assert_wait(
  1040. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  1041. fun() -> lists:sort(syn:get_members(<<"common-group">>)) end
  1042. ),
  1043. syn_test_suite_helper:assert_wait(
  1044. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  1045. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"common-group">>])) end
  1046. ),
  1047. syn_test_suite_helper:assert_wait(
  1048. lists:sort([{PidRemoteOn1, "meta-1"}, {PidRemoteOn2, "meta-2"}]),
  1049. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"common-group">>])) end
  1050. ),
  1051. syn_test_suite_helper:assert_wait(
  1052. [],
  1053. fun() -> lists:sort(syn:get_local_members(<<"common-group">>)) end
  1054. ),
  1055. syn_test_suite_helper:assert_wait(
  1056. [{PidRemoteOn1, "meta-1"}],
  1057. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"common-group">>])) end
  1058. ),
  1059. syn_test_suite_helper:assert_wait(
  1060. [{PidRemoteOn2, "meta-2"}],
  1061. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"common-group">>])) end
  1062. ),
  1063. syn_test_suite_helper:assert_wait(
  1064. [{PidRemoteOn2, "other-meta"}],
  1065. fun() -> lists:sort(syn:get_members(<<"group-2">>)) end
  1066. ),
  1067. syn_test_suite_helper:assert_wait(
  1068. [{PidRemoteOn2, "other-meta"}],
  1069. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [<<"group-2">>])) end
  1070. ),
  1071. syn_test_suite_helper:assert_wait(
  1072. [{PidRemoteOn2, "other-meta"}],
  1073. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [<<"group-2">>])) end
  1074. ),
  1075. syn_test_suite_helper:assert_wait(
  1076. [],
  1077. fun() -> lists:sort(syn:get_local_members(<<"group-2">>)) end
  1078. ),
  1079. syn_test_suite_helper:assert_wait(
  1080. [],
  1081. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [<<"group-2">>])) end
  1082. ),
  1083. syn_test_suite_helper:assert_wait(
  1084. [{PidRemoteOn2, "other-meta"}],
  1085. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [<<"group-2">>])) end
  1086. ),
  1087. 2 = syn:groups_count(default),
  1088. 0 = syn:groups_count(default, node()),
  1089. 1 = syn:groups_count(default, SlaveNode1),
  1090. 2 = syn:groups_count(default, SlaveNode2),
  1091. 2 = rpc:call(SlaveNode1, syn, groups_count, [default]),
  1092. 0 = rpc:call(SlaveNode1, syn, groups_count, [default, node()]),
  1093. 1 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode1]),
  1094. 2 = rpc:call(SlaveNode1, syn, groups_count, [default, SlaveNode2]),
  1095. 2 = rpc:call(SlaveNode2, syn, groups_count, [default]),
  1096. 0 = rpc:call(SlaveNode2, syn, groups_count, [default, node()]),
  1097. 1 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode1]),
  1098. 2 = rpc:call(SlaveNode2, syn, groups_count, [default, SlaveNode2]),
  1099. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_members(custom_scope_bc, <<"scoped-on-bc">>),
  1100. syn_test_suite_helper:assert_wait(
  1101. lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
  1102. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1103. ),
  1104. syn_test_suite_helper:assert_wait(
  1105. lists:sort([{PidRemoteOn1, "scoped-meta-1"}, {PidRemoteOn2, "scoped-meta-2"}]),
  1106. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1107. ),
  1108. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:get_local_members(custom_scope_bc, <<"scoped-on-bc">>),
  1109. syn_test_suite_helper:assert_wait(
  1110. [{PidRemoteOn1, "scoped-meta-1"}],
  1111. fun() -> lists:sort(rpc:call(SlaveNode1, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1112. ),
  1113. syn_test_suite_helper:assert_wait(
  1114. [{PidRemoteOn2, "scoped-meta-2"}],
  1115. fun() -> lists:sort(rpc:call(SlaveNode2, syn, get_local_members, [custom_scope_bc, <<"scoped-on-bc">>])) end
  1116. ),
  1117. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc),
  1118. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, node()),
  1119. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode1),
  1120. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:groups_count(custom_scope_bc, SlaveNode2),
  1121. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc]),
  1122. 0 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, node()]),
  1123. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  1124. 1 = rpc:call(SlaveNode1, syn, groups_count, [custom_scope_bc, SlaveNode2]),
  1125. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc]),
  1126. 0 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, node()]),
  1127. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode1]),
  1128. 1 = rpc:call(SlaveNode2, syn, groups_count, [custom_scope_bc, SlaveNode2]).
  1129. three_nodes_custom_event_handler_joined_left(Config) ->
  1130. %% get slaves
  1131. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  1132. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  1133. %% add custom handler for callbacks
  1134. syn:set_event_handler(syn_test_event_handler_callbacks),
  1135. rpc:call(SlaveNode1, syn, set_event_handler, [syn_test_event_handler_callbacks]),
  1136. rpc:call(SlaveNode2, syn, set_event_handler, [syn_test_event_handler_callbacks]),
  1137. %% start syn on nodes
  1138. ok = syn:start(),
  1139. ok = rpc:call(SlaveNode1, syn, start, []),
  1140. ok = rpc:call(SlaveNode2, syn, start, []),
  1141. %% init
  1142. CurrentNode = node(),
  1143. %% start process
  1144. Pid = syn_test_suite_helper:start_process(),
  1145. %% ---> on join
  1146. ok = syn:join("my-group", Pid, {recipient, self(), <<"meta">>}),
  1147. %% check callbacks called
  1148. syn_test_suite_helper:assert_received_messages([
  1149. {on_process_joined, CurrentNode, default, "my-group", Pid, <<"meta">>},
  1150. {on_process_joined, SlaveNode1, default, "my-group", Pid, <<"meta">>},
  1151. {on_process_joined, SlaveNode2, default, "my-group", Pid, <<"meta">>}
  1152. ]),
  1153. syn_test_suite_helper:assert_empty_queue(self()),
  1154. %% ---> on meta update
  1155. ok = syn:join("my-group", Pid, {recipient, self(), <<"new-meta-0">>}),
  1156. %% check callbacks called
  1157. syn_test_suite_helper:assert_received_messages([
  1158. {on_group_process_updated, CurrentNode, default, "my-group", Pid, <<"new-meta-0">>},
  1159. {on_group_process_updated, SlaveNode1, default, "my-group", Pid, <<"new-meta-0">>},
  1160. {on_group_process_updated, SlaveNode2, default, "my-group", Pid, <<"new-meta-0">>}
  1161. ]),
  1162. syn_test_suite_helper:assert_empty_queue(self()),
  1163. %% update meta from another node
  1164. ok = rpc:call(SlaveNode1, syn, join, ["my-group", Pid, {recipient, self(), <<"new-meta">>}]),
  1165. %% check callbacks called
  1166. syn_test_suite_helper:assert_received_messages([
  1167. {on_group_process_updated, CurrentNode, default, "my-group", Pid, <<"new-meta">>},
  1168. {on_group_process_updated, SlaveNode1, default, "my-group", Pid, <<"new-meta">>},
  1169. {on_group_process_updated, SlaveNode2, default, "my-group", Pid, <<"new-meta">>}
  1170. ]),
  1171. syn_test_suite_helper:assert_empty_queue(self()),
  1172. %% ---> on left
  1173. ok = syn:leave("my-group", Pid),
  1174. %% check callbacks called
  1175. syn_test_suite_helper:assert_received_messages([
  1176. {on_process_left, CurrentNode, default, "my-group", Pid, <<"new-meta">>},
  1177. {on_process_left, SlaveNode1, default, "my-group", Pid, <<"new-meta">>},
  1178. {on_process_left, SlaveNode2, default, "my-group", Pid, <<"new-meta">>}
  1179. ]),
  1180. syn_test_suite_helper:assert_empty_queue(self()),
  1181. %% clean & check
  1182. syn_test_suite_helper:kill_process(Pid),
  1183. syn_test_suite_helper:assert_empty_queue(self()),
  1184. %% ---> after a netsplit
  1185. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1186. syn:join(remote_on_1, PidRemoteOn1, {recipient, self(), <<"netsplit">>}),
  1187. %% check callbacks called
  1188. syn_test_suite_helper:assert_received_messages([
  1189. {on_process_joined, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
  1190. {on_process_joined, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
  1191. {on_process_joined, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
  1192. ]),
  1193. syn_test_suite_helper:assert_empty_queue(self()),
  1194. %% partial netsplit (1 cannot see 2)
  1195. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1196. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1197. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1198. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1199. %% check callbacks called
  1200. syn_test_suite_helper:assert_received_messages([
  1201. {on_process_left, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
  1202. ]),
  1203. syn_test_suite_helper:assert_empty_queue(self()),
  1204. %% ---> after a re-join
  1205. %% re-join
  1206. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1207. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1208. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1209. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1210. %% check callbacks called
  1211. syn_test_suite_helper:assert_received_messages([
  1212. {on_process_joined, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
  1213. ]),
  1214. syn_test_suite_helper:assert_empty_queue(self()),
  1215. %% clean
  1216. syn_test_suite_helper:kill_process(PidRemoteOn1),
  1217. %% check callbacks called
  1218. syn_test_suite_helper:assert_received_messages([
  1219. {on_process_left, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
  1220. {on_process_left, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>},
  1221. {on_process_left, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>}
  1222. ]),
  1223. syn_test_suite_helper:assert_empty_queue(self()),
  1224. %% ---> don't call on monitor rebuild
  1225. %% crash the scope process on local
  1226. syn_test_suite_helper:kill_process(syn_groups_default),
  1227. %% no messages
  1228. syn_test_suite_helper:assert_wait(
  1229. ok,
  1230. fun() -> syn_test_suite_helper:assert_empty_queue(self()) end
  1231. ).