syn_registry_SUITE.erl 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755
  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_registry_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. one_node_via_register_unregister/1
  35. ]).
  36. -export([
  37. three_nodes_discover_default_scope/1,
  38. three_nodes_discover_custom_scope/1,
  39. three_nodes_register_unregister_and_monitor_default_scope/1,
  40. three_nodes_register_unregister_and_monitor_custom_scope/1,
  41. three_nodes_cluster_changes/1,
  42. three_nodes_cluster_conflicts/1,
  43. three_nodes_custom_event_handler_reg_unreg/1,
  44. three_nodes_custom_event_handler_conflict_resolution/1
  45. ]).
  46. %% include
  47. -include_lib("common_test/include/ct.hrl").
  48. -include_lib("syn/src/syn.hrl").
  49. %% ===================================================================
  50. %% Callbacks
  51. %% ===================================================================
  52. %% -------------------------------------------------------------------
  53. %% Function: all() -> GroupsAndTestCases | {skip,Reason}
  54. %% GroupsAndTestCases = [{group,GroupName} | TestCase]
  55. %% GroupName = atom()
  56. %% TestCase = atom()
  57. %% Reason = any()
  58. %% -------------------------------------------------------------------
  59. all() ->
  60. [
  61. {group, one_node_process_registration},
  62. {group, three_nodes_process_registration}
  63. ].
  64. %% -------------------------------------------------------------------
  65. %% Function: groups() -> [Group]
  66. %% Group = {GroupName,Properties,GroupsAndTestCases}
  67. %% GroupName = atom()
  68. %% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
  69. %% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
  70. %% TestCase = atom()
  71. %% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
  72. %% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
  73. %% repeat_until_any_ok | repeat_until_any_fail
  74. %% N = integer() | forever
  75. %% -------------------------------------------------------------------
  76. groups() ->
  77. [
  78. {one_node_process_registration, [shuffle], [
  79. one_node_via_register_unregister
  80. ]},
  81. {three_nodes_process_registration, [shuffle], [
  82. three_nodes_discover_default_scope,
  83. three_nodes_discover_custom_scope,
  84. three_nodes_register_unregister_and_monitor_default_scope,
  85. three_nodes_register_unregister_and_monitor_custom_scope,
  86. three_nodes_cluster_changes,
  87. three_nodes_cluster_conflicts,
  88. three_nodes_custom_event_handler_reg_unreg,
  89. three_nodes_custom_event_handler_conflict_resolution
  90. ]}
  91. ].
  92. %% -------------------------------------------------------------------
  93. %% Function: init_per_suite(Config0) ->
  94. %% Config1 | {skip,Reason} |
  95. %% {skip_and_save,Reason,Config1}
  96. %% Config0 = Config1 = [tuple()]
  97. %% Reason = any()
  98. %% -------------------------------------------------------------------
  99. init_per_suite(Config) ->
  100. Config.
  101. %% -------------------------------------------------------------------
  102. %% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
  103. %% Config0 = Config1 = [tuple()]
  104. %% -------------------------------------------------------------------
  105. end_per_suite(_Config) ->
  106. ok.
  107. %% -------------------------------------------------------------------
  108. %% Function: init_per_group(GroupName, Config0) ->
  109. %% Config1 | {skip,Reason} |
  110. %% {skip_and_save,Reason,Config1}
  111. %% GroupName = atom()
  112. %% Config0 = Config1 = [tuple()]
  113. %% Reason = any()
  114. %% -------------------------------------------------------------------
  115. init_per_group(three_nodes_process_registration, Config) ->
  116. %% start slave
  117. {ok, SlaveNode1} = syn_test_suite_helper:start_slave(syn_slave_1),
  118. {ok, SlaveNode2} = syn_test_suite_helper:start_slave(syn_slave_2),
  119. syn_test_suite_helper:connect_node(SlaveNode1),
  120. syn_test_suite_helper:connect_node(SlaveNode2),
  121. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  122. %% wait full cluster
  123. case syn_test_suite_helper:wait_cluster_mesh_connected([node(), SlaveNode1, SlaveNode2]) of
  124. ok ->
  125. %% config
  126. [{slave_node_1, SlaveNode1}, {slave_node_2, SlaveNode2} | Config];
  127. Other ->
  128. ct:pal("*********** Could not get full cluster, skipping"),
  129. end_per_group(three_nodes_process_registration, Config),
  130. {skip, Other}
  131. end;
  132. init_per_group(_GroupName, Config) ->
  133. Config.
  134. %% -------------------------------------------------------------------
  135. %% Function: end_per_group(GroupName, Config0) ->
  136. %% void() | {save_config,Config1}
  137. %% GroupName = atom()
  138. %% Config0 = Config1 = [tuple()]
  139. %% -------------------------------------------------------------------
  140. end_per_group(three_nodes_process_registration, Config) ->
  141. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  142. syn_test_suite_helper:connect_node(SlaveNode1),
  143. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  144. syn_test_suite_helper:connect_node(SlaveNode2),
  145. syn_test_suite_helper:clean_after_test(),
  146. syn_test_suite_helper:stop_slave(syn_slave_1),
  147. syn_test_suite_helper:stop_slave(syn_slave_2),
  148. timer:sleep(1000);
  149. end_per_group(_GroupName, _Config) ->
  150. syn_test_suite_helper:clean_after_test().
  151. %% -------------------------------------------------------------------
  152. %% Function: init_per_testcase(TestCase, Config0) ->
  153. %% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
  154. %% TestCase = atom()
  155. %% Config0 = Config1 = [tuple()]
  156. %% Reason = any()
  157. %% -------------------------------------------------------------------
  158. init_per_testcase(TestCase, Config) ->
  159. ct:pal("Starting test: ~p", [TestCase]),
  160. Config.
  161. %% -------------------------------------------------------------------
  162. %% Function: end_per_testcase(TestCase, Config0) ->
  163. %% void() | {save_config,Config1} | {fail,Reason}
  164. %% TestCase = atom()
  165. %% Config0 = Config1 = [tuple()]
  166. %% Reason = any()
  167. %% -------------------------------------------------------------------
  168. end_per_testcase(_, _Config) ->
  169. syn_test_suite_helper:clean_after_test().
  170. %% ===================================================================
  171. %% Tests
  172. %% ===================================================================
  173. one_node_via_register_unregister(_Config) ->
  174. %% start syn
  175. ok = syn:start(),
  176. %% ---> default scope
  177. %% start gen server via syn
  178. GenServerName = {default, <<"my proc">>},
  179. Tuple = {via, syn, GenServerName},
  180. {ok, Pid} = syn_test_gen_server:start_link(Tuple),
  181. %% retrieve
  182. {Pid, undefined} = syn:lookup(<<"my proc">>),
  183. %% call
  184. pong = syn_test_gen_server:ping(Tuple),
  185. %% send via syn
  186. syn:send(GenServerName, {self(), send_ping}),
  187. syn_test_suite_helper:assert_received_messages([
  188. reply_pong
  189. ]),
  190. %% stop server
  191. syn_test_gen_server:stop(Tuple),
  192. %% retrieve
  193. syn_test_suite_helper:assert_wait(
  194. undefined,
  195. fun() -> syn:lookup(<<"my proc">>) end
  196. ),
  197. %% send via syn
  198. {badarg, {GenServerName, anything}} = catch syn:send(GenServerName, anything),
  199. %% ---> custom scope
  200. syn:add_node_to_scope(custom_scope),
  201. %% start gen server via syn
  202. GenServerNameCustom = {custom_scope, <<"my proc">>},
  203. TupleCustom = {via, syn, GenServerNameCustom},
  204. {ok, PidCustom} = syn_test_gen_server:start_link(TupleCustom),
  205. %% retrieve
  206. {PidCustom, undefined} = syn:lookup(custom_scope, <<"my proc">>),
  207. %% call
  208. pong = syn_test_gen_server:ping(TupleCustom),
  209. %% send via syn
  210. syn:send(GenServerNameCustom, {self(), send_ping}),
  211. syn_test_suite_helper:assert_received_messages([
  212. reply_pong
  213. ]),
  214. %% stop server
  215. syn_test_gen_server:stop(TupleCustom),
  216. %% retrieve
  217. syn_test_suite_helper:assert_wait(
  218. undefined,
  219. fun() -> syn:lookup(custom_scope, <<"my proc">>) end
  220. ),
  221. %% send via syn
  222. {badarg, {GenServerNameCustom, anything}} = catch syn:send(GenServerNameCustom, anything).
  223. three_nodes_discover_default_scope(Config) ->
  224. %% get slaves
  225. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  226. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  227. %% start syn on nodes
  228. ok = syn:start(),
  229. ok = rpc:call(SlaveNode1, syn, start, []),
  230. ok = rpc:call(SlaveNode2, syn, start, []),
  231. %% check
  232. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  233. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  234. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  235. %% simulate full netsplit
  236. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  237. syn_test_suite_helper:disconnect_node(SlaveNode1),
  238. syn_test_suite_helper:disconnect_node(SlaveNode2),
  239. syn_test_suite_helper:assert_cluster(node(), []),
  240. %% check
  241. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, []),
  242. %% reconnect slave 1
  243. syn_test_suite_helper:connect_node(SlaveNode1),
  244. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1]),
  245. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  246. %% check
  247. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1]),
  248. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node()]),
  249. %% reconnect all
  250. syn_test_suite_helper:connect_node(SlaveNode2),
  251. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  252. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  253. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  254. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  255. %% check
  256. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  257. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  258. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  259. %% simulate full netsplit, again
  260. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  261. syn_test_suite_helper:disconnect_node(SlaveNode1),
  262. syn_test_suite_helper:disconnect_node(SlaveNode2),
  263. syn_test_suite_helper:assert_cluster(node(), []),
  264. %% check
  265. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, []),
  266. %% reconnect all, again
  267. syn_test_suite_helper:connect_node(SlaveNode2),
  268. rpc:call(SlaveNode1, 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_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  274. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  275. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  276. %% crash the scope process on local
  277. syn_test_suite_helper:kill_process(syn_registry_default),
  278. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  279. %% check, it should have rebuilt after supervisor restarts it
  280. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  281. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  282. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  283. %% crash scopes supervisor on local
  284. syn_test_suite_helper:kill_process(syn_scopes_sup),
  285. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  286. %% check
  287. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  288. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  289. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]).
  290. three_nodes_discover_custom_scope(Config) ->
  291. %% get slaves
  292. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  293. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  294. %% start syn on nodes
  295. ok = syn:start(),
  296. ok = rpc:call(SlaveNode1, syn, start, []),
  297. ok = rpc:call(SlaveNode2, syn, start, []),
  298. %% add custom scopes
  299. ok = syn:add_node_to_scope(custom_scope_ab),
  300. ok = syn:add_node_to_scope(custom_scope_all),
  301. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_ab, custom_scope_bc, custom_scope_all]]),
  302. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc, custom_scope_c, custom_scope_all]]),
  303. %% get_subcluster_nodes should return invalid errors
  304. {'EXIT', {{invalid_scope, custom_abcdef}, _}} = catch syn_registry:get_subcluster_nodes(custom_abcdef),
  305. %% check
  306. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  307. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  308. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  309. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  310. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  311. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  312. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_c, []),
  313. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  314. %% check default
  315. syn_test_suite_helper:assert_registry_scope_subcluster(node(), default, [SlaveNode1, SlaveNode2]),
  316. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, default, [node(), SlaveNode2]),
  317. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, default, [node(), SlaveNode1]),
  318. %% disconnect node 2 (node 1 can still see node 2)
  319. syn_test_suite_helper:disconnect_node(SlaveNode2),
  320. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1]),
  321. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  322. %% check
  323. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  324. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_all, [SlaveNode1]),
  325. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  326. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  327. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  328. %% reconnect node 2
  329. syn_test_suite_helper:connect_node(SlaveNode2),
  330. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  331. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  332. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  333. %% check
  334. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  335. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  336. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  337. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  338. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  339. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  340. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_c, []),
  341. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  342. %% crash a scope process on 2
  343. rpc:call(SlaveNode2, syn_test_suite_helper, kill_process, [syn_registry_custom_scope_bc]),
  344. rpc:call(SlaveNode2, syn_test_suite_helper, wait_process_name_ready, [syn_registry_default]),
  345. %% check
  346. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  347. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  348. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  349. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  350. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  351. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  352. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_c, []),
  353. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]),
  354. %% crash scopes supervisor on local
  355. syn_test_suite_helper:kill_process(syn_scopes_sup),
  356. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  357. %% check
  358. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_ab, [SlaveNode1]),
  359. syn_test_suite_helper:assert_registry_scope_subcluster(node(), custom_scope_all, [SlaveNode1, SlaveNode2]),
  360. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_ab, [node()]),
  361. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_bc, [SlaveNode2]),
  362. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode1, custom_scope_all, [node(), SlaveNode2]),
  363. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_bc, [SlaveNode1]),
  364. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_c, []),
  365. syn_test_suite_helper:assert_registry_scope_subcluster(SlaveNode2, custom_scope_all, [node(), SlaveNode1]).
  366. three_nodes_register_unregister_and_monitor_default_scope(Config) ->
  367. %% get slaves
  368. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  369. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  370. %% start syn on nodes
  371. ok = syn:start(),
  372. ok = rpc:call(SlaveNode1, syn, start, []),
  373. ok = rpc:call(SlaveNode2, syn, start, []),
  374. %% start processes
  375. Pid = syn_test_suite_helper:start_process(),
  376. PidWithMeta = syn_test_suite_helper:start_process(),
  377. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  378. %% retrieve
  379. undefined = syn:lookup(<<"my proc">>),
  380. undefined = rpc:call(SlaveNode1, syn, lookup, [<<"my proc">>]),
  381. undefined = rpc:call(SlaveNode2, syn, lookup, [<<"my proc">>]),
  382. undefined = syn:lookup({"my proc alias"}),
  383. undefined = rpc:call(SlaveNode1, syn, lookup, [{"my proc alias"}]),
  384. undefined = rpc:call(SlaveNode2, syn, lookup, [{"my proc alias"}]),
  385. undefined = syn:lookup(<<"my proc with meta">>),
  386. undefined = rpc:call(SlaveNode1, syn, lookup, [<<"my proc with meta">>]),
  387. undefined = rpc:call(SlaveNode2, syn, lookup, [<<"my proc with meta">>]),
  388. undefined = syn:lookup({remote_pid_on, slave_1}),
  389. undefined = rpc:call(SlaveNode1, syn, lookup, [{remote_pid_on, slave_1}]),
  390. undefined = rpc:call(SlaveNode2, syn, lookup, [{remote_pid_on, slave_1}]),
  391. 0 = syn:registry_count(),
  392. 0 = syn:registry_count(default, node()),
  393. 0 = syn:registry_count(default, SlaveNode1),
  394. 0 = syn:registry_count(default, SlaveNode2),
  395. %% register
  396. ok = syn:register(<<"my proc">>, Pid),
  397. ok = syn:register({"my proc alias"}, Pid), %% same pid, different name
  398. ok = syn:register(<<"my proc with meta">>, PidWithMeta, {meta, <<"meta">>}), %% pid with meta
  399. ok = syn:register({remote_pid_on, slave_1}, PidRemoteOn1), %% remote on slave 1
  400. %% errors
  401. {error, taken} = syn:register(<<"my proc">>, PidRemoteOn1),
  402. {error, not_alive} = syn:register({"pid not alive"}, list_to_pid("<0.9999.0>")),
  403. %% retrieve
  404. syn_test_suite_helper:assert_wait(
  405. {Pid, undefined},
  406. fun() -> syn:lookup(<<"my proc">>) end
  407. ),
  408. syn_test_suite_helper:assert_wait(
  409. {Pid, undefined},
  410. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc">>]) end
  411. ),
  412. syn_test_suite_helper:assert_wait(
  413. {Pid, undefined},
  414. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc">>]) end
  415. ),
  416. syn_test_suite_helper:assert_wait(
  417. {Pid, undefined},
  418. fun() -> syn:lookup({"my proc alias"}) end
  419. ),
  420. syn_test_suite_helper:assert_wait(
  421. {Pid, undefined},
  422. fun() -> rpc:call(SlaveNode1, syn, lookup, [{"my proc alias"}]) end
  423. ),
  424. syn_test_suite_helper:assert_wait(
  425. {Pid, undefined},
  426. fun() -> rpc:call(SlaveNode2, syn, lookup, [{"my proc alias"}]) end
  427. ),
  428. syn_test_suite_helper:assert_wait(
  429. {PidWithMeta, {meta, <<"meta">>}},
  430. fun() -> syn:lookup(<<"my proc with meta">>) end
  431. ),
  432. syn_test_suite_helper:assert_wait(
  433. {PidWithMeta, {meta, <<"meta">>}},
  434. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc with meta">>]) end
  435. ),
  436. syn_test_suite_helper:assert_wait(
  437. {PidWithMeta, {meta, <<"meta">>}},
  438. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc with meta">>]) end
  439. ),
  440. syn_test_suite_helper:assert_wait(
  441. {PidRemoteOn1, undefined},
  442. fun() -> syn:lookup({remote_pid_on, slave_1}) end
  443. ),
  444. syn_test_suite_helper:assert_wait(
  445. {PidRemoteOn1, undefined},
  446. fun() -> rpc:call(SlaveNode1, syn, lookup, [{remote_pid_on, slave_1}]) end
  447. ),
  448. syn_test_suite_helper:assert_wait(
  449. {PidRemoteOn1, undefined},
  450. fun() -> rpc:call(SlaveNode2, syn, lookup, [{remote_pid_on, slave_1}]) end
  451. ),
  452. 4 = syn:registry_count(),
  453. 3 = syn:registry_count(default, node()),
  454. 1 = syn:registry_count(default, SlaveNode1),
  455. 0 = syn:registry_count(default, SlaveNode2),
  456. %% re-register to edit meta
  457. ok = syn:register(<<"my proc with meta">>, PidWithMeta, {meta2, <<"meta2">>}),
  458. ok = rpc:call(SlaveNode2, syn, register, [{remote_pid_on, slave_1}, PidRemoteOn1, added_meta]), %% updated on slave 2
  459. %% retrieve
  460. syn_test_suite_helper:assert_wait(
  461. {PidWithMeta, {meta2, <<"meta2">>}},
  462. fun() -> syn:lookup(<<"my proc with meta">>) end
  463. ),
  464. syn_test_suite_helper:assert_wait(
  465. {PidWithMeta, {meta2, <<"meta2">>}},
  466. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc with meta">>]) end
  467. ),
  468. syn_test_suite_helper:assert_wait(
  469. {PidWithMeta, {meta2, <<"meta2">>}},
  470. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc with meta">>]) end
  471. ),
  472. syn_test_suite_helper:assert_wait(
  473. {PidRemoteOn1, added_meta},
  474. fun() -> syn:lookup({remote_pid_on, slave_1}) end
  475. ),
  476. syn_test_suite_helper:assert_wait(
  477. {PidRemoteOn1, added_meta},
  478. fun() -> rpc:call(SlaveNode1, syn, lookup, [{remote_pid_on, slave_1}]) end
  479. ),
  480. syn_test_suite_helper:assert_wait(
  481. {PidRemoteOn1, added_meta},
  482. fun() -> rpc:call(SlaveNode2, syn, lookup, [{remote_pid_on, slave_1}]) end
  483. ),
  484. 4 = syn:registry_count(),
  485. 3 = syn:registry_count(default, node()),
  486. 1 = syn:registry_count(default, SlaveNode1),
  487. 0 = syn:registry_count(default, SlaveNode2),
  488. %% crash scope process to ensure that monitors get recreated
  489. exit(whereis(syn_registry_default), kill),
  490. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  491. %% kill process
  492. syn_test_suite_helper:kill_process(Pid),
  493. syn_test_suite_helper:kill_process(PidRemoteOn1),
  494. %% unregister process
  495. ok = syn:unregister(<<"my proc with meta">>),
  496. %% retrieve
  497. syn_test_suite_helper:assert_wait(
  498. undefined,
  499. fun() -> syn:lookup(<<"my proc">>) end
  500. ),
  501. syn_test_suite_helper:assert_wait(
  502. undefined,
  503. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc">>]) end
  504. ),
  505. syn_test_suite_helper:assert_wait(
  506. undefined,
  507. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc">>]) end
  508. ),
  509. syn_test_suite_helper:assert_wait(
  510. undefined,
  511. fun() -> syn:lookup({"my proc alias"}) end
  512. ),
  513. syn_test_suite_helper:assert_wait(
  514. undefined,
  515. fun() -> rpc:call(SlaveNode1, syn, lookup, [{"my proc alias"}]) end
  516. ),
  517. syn_test_suite_helper:assert_wait(
  518. undefined,
  519. fun() -> rpc:call(SlaveNode2, syn, lookup, [{"my proc alias"}]) end
  520. ),
  521. syn_test_suite_helper:assert_wait(
  522. undefined,
  523. fun() -> syn:lookup(<<"my proc with meta">>) end
  524. ),
  525. syn_test_suite_helper:assert_wait(
  526. undefined,
  527. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc with meta">>]) end
  528. ),
  529. syn_test_suite_helper:assert_wait(
  530. undefined,
  531. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc with meta">>]) end
  532. ),
  533. syn_test_suite_helper:assert_wait(
  534. undefined,
  535. fun() -> syn:lookup({remote_pid_on, slave_1}) end
  536. ),
  537. syn_test_suite_helper:assert_wait(
  538. undefined,
  539. fun() -> rpc:call(SlaveNode1, syn, lookup, [{remote_pid_on, slave_1}]) end
  540. ),
  541. syn_test_suite_helper:assert_wait(
  542. undefined,
  543. fun() -> rpc:call(SlaveNode2, syn, lookup, [{remote_pid_on, slave_1}]) end
  544. ),
  545. 0 = syn:registry_count(),
  546. 0 = syn:registry_count(default, node()),
  547. 0 = syn:registry_count(default, SlaveNode1),
  548. 0 = syn:registry_count(default, SlaveNode2),
  549. %% errors
  550. {error, undefined} = syn:unregister({invalid_name}),
  551. %% (simulate race condition)
  552. Pid1 = syn_test_suite_helper:start_process(),
  553. Pid2 = syn_test_suite_helper:start_process(),
  554. ok = syn:register(<<"my proc">>, Pid1),
  555. syn_test_suite_helper:assert_wait(
  556. {Pid1, undefined},
  557. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc">>]) end
  558. ),
  559. remove_from_local_table(default, <<"my proc">>, Pid1),
  560. add_to_local_table(default, <<"my proc">>, Pid2, undefined, 0, undefined),
  561. {error, race_condition} = rpc:call(SlaveNode1, syn, unregister, [<<"my proc">>]).
  562. three_nodes_register_unregister_and_monitor_custom_scope(Config) ->
  563. %% get slaves
  564. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  565. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  566. %% start syn on nodes
  567. ok = syn:start(),
  568. ok = rpc:call(SlaveNode1, syn, start, []),
  569. ok = rpc:call(SlaveNode2, syn, start, []),
  570. %% add custom scopes
  571. ok = syn:add_node_to_scope(custom_scope_ab),
  572. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_ab, custom_scope_bc]]),
  573. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  574. %% start processes
  575. Pid = syn_test_suite_helper:start_process(),
  576. PidWithMeta = syn_test_suite_helper:start_process(),
  577. PidRemoteWithMetaOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  578. %% retrieve
  579. undefined = syn:lookup("scope_a"),
  580. undefined = rpc:call(SlaveNode1, syn, lookup, ["scope_a"]),
  581. undefined = rpc:call(SlaveNode2, syn, lookup, ["scope_a"]),
  582. undefined = syn:lookup(custom_scope_ab, "scope_a"),
  583. undefined = rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a"]),
  584. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a"]),
  585. undefined = syn:lookup(custom_scope_ab, "scope_a_alias"),
  586. undefined = rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a_alias"]),
  587. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a_alias"]),
  588. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, {remote_scoped_bc}),
  589. undefined = rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]),
  590. undefined = rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]),
  591. 0 = syn:registry_count(custom_scope_ab),
  592. 0 = syn:registry_count(custom_scope_ab, node()),
  593. 0 = syn:registry_count(custom_scope_ab, SlaveNode1),
  594. 0 = syn:registry_count(custom_scope_ab, SlaveNode2),
  595. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  596. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, node()),
  597. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode1),
  598. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode2),
  599. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab]),
  600. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, node()]),
  601. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  602. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  603. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  604. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  605. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  606. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  607. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab]),
  608. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, node()]),
  609. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  610. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  611. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  612. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  613. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  614. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  615. %% register
  616. ok = syn:register(custom_scope_ab, "scope_a", Pid),
  617. ok = syn:register(custom_scope_ab, "scope_a_alias", PidWithMeta, <<"with_meta">>),
  618. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:register(custom_scope_bc, "scope_a", Pid),
  619. {'EXIT', {{invalid_scope, non_existent_scope}, _}} = catch syn:register(non_existent_scope, "scope_a", Pid),
  620. ok = rpc:call(SlaveNode2, syn, register, [custom_scope_bc, {remote_scoped_bc}, PidRemoteWithMetaOn1, <<"with_meta 1">>]),
  621. %% errors
  622. {error, taken} = syn:register(custom_scope_ab, "scope_a", PidWithMeta),
  623. {error, not_alive} = syn:register(custom_scope_ab, {"pid not alive"}, list_to_pid("<0.9999.0>")),
  624. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:register(custom_scope_bc, "scope_a_noscope", Pid),
  625. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:unregister(custom_scope_bc, "scope_a_noscope"),
  626. {badrpc, {'EXIT', {{invalid_scope, custom_scope_bc}, _}}} = catch rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "pid-outside", Pid]),
  627. %% retrieve
  628. syn_test_suite_helper:assert_wait(
  629. undefined,
  630. fun() -> syn:lookup("scope_a") end
  631. ),
  632. syn_test_suite_helper:assert_wait(
  633. undefined,
  634. fun() -> rpc:call(SlaveNode1, syn, lookup, ["scope_a"]) end
  635. ),
  636. syn_test_suite_helper:assert_wait(
  637. undefined,
  638. fun() -> rpc:call(SlaveNode2, syn, lookup, ["scope_a"]) end
  639. ),
  640. syn_test_suite_helper:assert_wait(
  641. {Pid, undefined},
  642. fun() -> syn:lookup(custom_scope_ab, "scope_a") end
  643. ),
  644. syn_test_suite_helper:assert_wait(
  645. {Pid, undefined},
  646. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a"]) end
  647. ),
  648. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a"]),
  649. syn_test_suite_helper:assert_wait(
  650. {PidWithMeta, <<"with_meta">>},
  651. fun() -> syn:lookup(custom_scope_ab, "scope_a_alias") end
  652. ),
  653. syn_test_suite_helper:assert_wait(
  654. {PidWithMeta, <<"with_meta">>},
  655. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a_alias"]) end
  656. ),
  657. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a_alias"]),
  658. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, {remote_scoped_bc}),
  659. syn_test_suite_helper:assert_wait(
  660. {PidRemoteWithMetaOn1, <<"with_meta 1">>},
  661. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]) end
  662. ),
  663. syn_test_suite_helper:assert_wait(
  664. {PidRemoteWithMetaOn1, <<"with_meta 1">>},
  665. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]) end
  666. ),
  667. 2 = syn:registry_count(custom_scope_ab),
  668. 2 = syn:registry_count(custom_scope_ab, node()),
  669. 0 = syn:registry_count(custom_scope_ab, SlaveNode1),
  670. 0 = syn:registry_count(custom_scope_ab, SlaveNode2),
  671. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  672. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, node()),
  673. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode1),
  674. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode2),
  675. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab]),
  676. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, node()]),
  677. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  678. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  679. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  680. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  681. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  682. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  683. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab]),
  684. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, node()]),
  685. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  686. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  687. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  688. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  689. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  690. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  691. %% re-register to edit meta
  692. ok = syn:register(custom_scope_ab, "scope_a_alias", PidWithMeta, <<"with_meta_updated">>),
  693. syn_test_suite_helper:assert_wait(
  694. {PidWithMeta, <<"with_meta_updated">>},
  695. fun() -> syn:lookup(custom_scope_ab, "scope_a_alias") end
  696. ),
  697. syn_test_suite_helper:assert_wait(
  698. {PidWithMeta, <<"with_meta_updated">>},
  699. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a_alias"]) end
  700. ),
  701. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a_alias"]),
  702. %% crash scope process to ensure that monitors get recreated
  703. syn_test_suite_helper:kill_process(syn_registry_custom_scope_ab),
  704. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  705. %% kill process
  706. syn_test_suite_helper:kill_process(Pid),
  707. syn_test_suite_helper:kill_process(PidWithMeta),
  708. %% unregister processes
  709. {error, undefined} = catch syn:unregister(<<"my proc with meta">>),
  710. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:unregister(custom_scope_bc, <<"my proc with meta">>),
  711. ok = rpc:call(SlaveNode1, syn, unregister, [custom_scope_bc, {remote_scoped_bc}]),
  712. %% retrieve
  713. syn_test_suite_helper:assert_wait(
  714. undefined,
  715. fun() -> syn:lookup("scope_a") end
  716. ),
  717. syn_test_suite_helper:assert_wait(
  718. undefined,
  719. fun() -> rpc:call(SlaveNode1, syn, lookup, ["scope_a"]) end
  720. ),
  721. syn_test_suite_helper:assert_wait(
  722. undefined,
  723. fun() -> rpc:call(SlaveNode2, syn, lookup, ["scope_a"]) end
  724. ),
  725. syn_test_suite_helper:assert_wait(
  726. undefined,
  727. fun() -> syn:lookup(custom_scope_ab, "scope_a") end
  728. ),
  729. syn_test_suite_helper:assert_wait(
  730. undefined,
  731. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a"]) end
  732. ),
  733. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a"]),
  734. syn_test_suite_helper:assert_wait(
  735. undefined,
  736. fun() -> syn:lookup(custom_scope_ab, "scope_a_alias") end
  737. ),
  738. syn_test_suite_helper:assert_wait(
  739. undefined,
  740. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, "scope_a_alias"]) end
  741. ),
  742. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, lookup, [custom_scope_ab, "scope_a_alias"]),
  743. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, {remote_scoped_bc}),
  744. syn_test_suite_helper:assert_wait(
  745. undefined,
  746. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]) end
  747. ),
  748. syn_test_suite_helper:assert_wait(
  749. undefined,
  750. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, {remote_scoped_bc}]) end
  751. ),
  752. 0 = syn:registry_count(custom_scope_ab),
  753. 0 = syn:registry_count(custom_scope_ab, node()),
  754. 0 = syn:registry_count(custom_scope_ab, SlaveNode1),
  755. 0 = syn:registry_count(custom_scope_ab, SlaveNode2),
  756. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  757. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, node()),
  758. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode1),
  759. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode2),
  760. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab]),
  761. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, node()]),
  762. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  763. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  764. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  765. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  766. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  767. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  768. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab]),
  769. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, node()]),
  770. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode1]),
  771. {badrpc, {'EXIT', {{invalid_scope, custom_scope_ab}, _}}} = catch rpc:call(SlaveNode2, syn, registry_count, [custom_scope_ab, SlaveNode2]),
  772. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  773. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  774. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  775. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  776. %% errors
  777. {error, undefined} = syn:unregister(custom_scope_ab, {invalid_name}),
  778. %% (simulate race condition)
  779. Pid1 = syn_test_suite_helper:start_process(),
  780. Pid2 = syn_test_suite_helper:start_process(),
  781. ok = syn:register(custom_scope_ab, <<"my proc">>, Pid1),
  782. syn_test_suite_helper:assert_wait(
  783. {Pid1, undefined},
  784. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_ab, <<"my proc">>]) end
  785. ),
  786. remove_from_local_table(custom_scope_ab, <<"my proc">>, Pid1),
  787. add_to_local_table(custom_scope_ab, <<"my proc">>, Pid2, undefined, 0, undefined),
  788. {error, race_condition} = rpc:call(SlaveNode1, syn, unregister, [custom_scope_ab, <<"my proc">>]).
  789. three_nodes_cluster_changes(Config) ->
  790. %% get slaves
  791. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  792. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  793. %% disconnect 1 from 2
  794. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  795. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  796. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  797. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  798. %% start syn on 1 and 2, nodes don't know of each other
  799. ok = rpc:call(SlaveNode1, syn, start, []),
  800. ok = rpc:call(SlaveNode2, syn, start, []),
  801. %% add custom scopes
  802. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_bc]]),
  803. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  804. %% start processes
  805. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  806. PidRemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  807. %% register
  808. ok = rpc:call(SlaveNode1, syn, register, ["proc-1", PidRemoteOn1, "meta-1"]),
  809. ok = rpc:call(SlaveNode1, syn, register, ["proc-2", PidRemoteOn2, "meta-2"]),
  810. ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "BC-proc-1", PidRemoteOn1, "meta-1"]),
  811. ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "BC-proc-1 alias", PidRemoteOn1, "meta-1 alias"]),
  812. %% form full cluster
  813. ok = syn:start(),
  814. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  815. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  816. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  817. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  818. syn_test_suite_helper:wait_process_name_ready(syn_registry_default),
  819. syn_test_suite_helper:assert_wait(
  820. {PidRemoteOn1, "meta-1"},
  821. fun() -> syn:lookup("proc-1") end
  822. ),
  823. syn_test_suite_helper:assert_wait(
  824. {PidRemoteOn1, "meta-1"},
  825. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-1"]) end
  826. ),
  827. syn_test_suite_helper:assert_wait(
  828. {PidRemoteOn1, "meta-1"},
  829. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-1"]) end
  830. ),
  831. syn_test_suite_helper:assert_wait(
  832. {PidRemoteOn2, "meta-2"},
  833. fun() -> syn:lookup("proc-2") end
  834. ),
  835. syn_test_suite_helper:assert_wait(
  836. {PidRemoteOn2, "meta-2"},
  837. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-2"]) end
  838. ),
  839. syn_test_suite_helper:assert_wait(
  840. {PidRemoteOn2, "meta-2"},
  841. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-2"]) end
  842. ),
  843. 2 = syn:registry_count(),
  844. 0 = syn:registry_count(default, node()),
  845. 1 = syn:registry_count(default, SlaveNode1),
  846. 1 = syn:registry_count(default, SlaveNode2),
  847. 2 = rpc:call(SlaveNode1, syn, registry_count, []),
  848. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  849. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  850. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  851. 2 = rpc:call(SlaveNode2, syn, registry_count, []),
  852. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  853. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  854. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  855. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1"),
  856. syn_test_suite_helper:assert_wait(
  857. {PidRemoteOn1, "meta-1"},
  858. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  859. ),
  860. syn_test_suite_helper:assert_wait(
  861. {PidRemoteOn1, "meta-1"},
  862. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  863. ),
  864. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1 alias"),
  865. syn_test_suite_helper:assert_wait(
  866. {PidRemoteOn1, "meta-1 alias"},
  867. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  868. ),
  869. syn_test_suite_helper:assert_wait(
  870. {PidRemoteOn1, "meta-1 alias"},
  871. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  872. ),
  873. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  874. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, node()),
  875. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode1),
  876. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc, SlaveNode2),
  877. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  878. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  879. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  880. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  881. 2 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  882. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  883. 2 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  884. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  885. %% partial netsplit (1 cannot see 2)
  886. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  887. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  888. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  889. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  890. %% retrieve
  891. syn_test_suite_helper:assert_wait(
  892. {PidRemoteOn1, "meta-1"},
  893. fun() -> syn:lookup("proc-1") end
  894. ),
  895. syn_test_suite_helper:assert_wait(
  896. {PidRemoteOn1, "meta-1"},
  897. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-1"]) end
  898. ),
  899. syn_test_suite_helper:assert_wait(
  900. undefined,
  901. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-1"]) end
  902. ),
  903. syn_test_suite_helper:assert_wait(
  904. {PidRemoteOn2, "meta-2"},
  905. fun() -> syn:lookup("proc-2") end
  906. ),
  907. syn_test_suite_helper:assert_wait(
  908. undefined,
  909. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-2"]) end
  910. ),
  911. syn_test_suite_helper:assert_wait(
  912. {PidRemoteOn2, "meta-2"},
  913. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-2"]) end
  914. ),
  915. 2 = syn:registry_count(),
  916. 0 = syn:registry_count(default, node()),
  917. 1 = syn:registry_count(default, SlaveNode1),
  918. 1 = syn:registry_count(default, SlaveNode2),
  919. 1 = rpc:call(SlaveNode1, syn, registry_count, []),
  920. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  921. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  922. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  923. 1 = rpc:call(SlaveNode2, syn, registry_count, []),
  924. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  925. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  926. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  927. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1"),
  928. syn_test_suite_helper:assert_wait(
  929. {PidRemoteOn1, "meta-1"},
  930. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  931. ),
  932. syn_test_suite_helper:assert_wait(
  933. undefined,
  934. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  935. ),
  936. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1 alias"),
  937. syn_test_suite_helper:assert_wait(
  938. {PidRemoteOn1, "meta-1 alias"},
  939. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  940. ),
  941. syn_test_suite_helper:assert_wait(
  942. undefined,
  943. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  944. ),
  945. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  946. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  947. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  948. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  949. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  950. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  951. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  952. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  953. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  954. %% re-join
  955. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  956. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  957. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  958. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  959. %% retrieve
  960. syn_test_suite_helper:assert_wait(
  961. {PidRemoteOn1, "meta-1"},
  962. fun() -> syn:lookup("proc-1") end
  963. ),
  964. syn_test_suite_helper:assert_wait(
  965. {PidRemoteOn1, "meta-1"},
  966. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-1"]) end
  967. ),
  968. syn_test_suite_helper:assert_wait(
  969. {PidRemoteOn1, "meta-1"},
  970. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-1"]) end
  971. ),
  972. syn_test_suite_helper:assert_wait(
  973. {PidRemoteOn2, "meta-2"},
  974. fun() -> syn:lookup("proc-2") end
  975. ),
  976. syn_test_suite_helper:assert_wait(
  977. {PidRemoteOn2, "meta-2"},
  978. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-2"]) end
  979. ),
  980. syn_test_suite_helper:assert_wait(
  981. {PidRemoteOn2, "meta-2"},
  982. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-2"]) end
  983. ),
  984. 2 = syn:registry_count(),
  985. 0 = syn:registry_count(default, node()),
  986. 1 = syn:registry_count(default, SlaveNode1),
  987. 1 = syn:registry_count(default, SlaveNode2),
  988. 2 = rpc:call(SlaveNode1, syn, registry_count, []),
  989. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  990. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  991. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  992. 2 = rpc:call(SlaveNode2, syn, registry_count, []),
  993. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  994. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  995. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  996. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1"),
  997. syn_test_suite_helper:assert_wait(
  998. {PidRemoteOn1, "meta-1"},
  999. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  1000. ),
  1001. syn_test_suite_helper:assert_wait(
  1002. {PidRemoteOn1, "meta-1"},
  1003. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1"]) end
  1004. ),
  1005. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:lookup(custom_scope_bc, "BC-proc-1 alias"),
  1006. syn_test_suite_helper:assert_wait(
  1007. {PidRemoteOn1, "meta-1 alias"},
  1008. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  1009. ),
  1010. syn_test_suite_helper:assert_wait(
  1011. {PidRemoteOn1, "meta-1 alias"},
  1012. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "BC-proc-1 alias"]) end
  1013. ),
  1014. {'EXIT', {{invalid_scope, custom_scope_bc}, _}} = catch syn:registry_count(custom_scope_bc),
  1015. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  1016. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  1017. 2 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1018. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  1019. 2 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  1020. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  1021. 2 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1022. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]).
  1023. three_nodes_cluster_conflicts(Config) ->
  1024. %% get slaves
  1025. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  1026. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  1027. %% start syn on nodes
  1028. ok = syn:start(),
  1029. ok = rpc:call(SlaveNode1, syn, start, []),
  1030. ok = rpc:call(SlaveNode2, syn, start, []),
  1031. %% add custom scopes
  1032. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_bc]]),
  1033. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  1034. %% partial netsplit (1 cannot see 2)
  1035. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1036. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1037. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1038. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1039. %% start conflict processes
  1040. Pid2RemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1041. Pid2RemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  1042. %% --> conflict by netsplit
  1043. ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit", Pid2RemoteOn1, "meta-1"]),
  1044. ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit", Pid2RemoteOn2, "meta-2"]),
  1045. ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped", Pid2RemoteOn1, "meta-1"]),
  1046. ok = rpc:call(SlaveNode2, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped", Pid2RemoteOn2, "meta-2"]),
  1047. %% re-join
  1048. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1049. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1050. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1051. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1052. %% retrieve
  1053. syn_test_suite_helper:assert_wait(
  1054. {Pid2RemoteOn2, "meta-2"},
  1055. fun() -> syn:lookup("proc-confict-by-netsplit") end
  1056. ),
  1057. syn_test_suite_helper:assert_wait(
  1058. {Pid2RemoteOn2, "meta-2"},
  1059. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit"]) end
  1060. ),
  1061. syn_test_suite_helper:assert_wait(
  1062. {Pid2RemoteOn2, "meta-2"},
  1063. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit"]) end
  1064. ),
  1065. 1 = syn:registry_count(),
  1066. 0 = syn:registry_count(default, node()),
  1067. 0 = syn:registry_count(default, SlaveNode1),
  1068. 1 = syn:registry_count(default, SlaveNode2),
  1069. 1 = rpc:call(SlaveNode1, syn, registry_count, []),
  1070. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  1071. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  1072. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  1073. 1 = rpc:call(SlaveNode2, syn, registry_count, []),
  1074. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  1075. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  1076. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  1077. syn_test_suite_helper:assert_wait(
  1078. {Pid2RemoteOn2, "meta-2"},
  1079. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped"]) end
  1080. ),
  1081. syn_test_suite_helper:assert_wait(
  1082. {Pid2RemoteOn2, "meta-2"},
  1083. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped"]) end
  1084. ),
  1085. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  1086. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  1087. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1088. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  1089. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  1090. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  1091. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1092. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  1093. %% process alive
  1094. syn_test_suite_helper:assert_wait(
  1095. false,
  1096. fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [Pid2RemoteOn1]) end
  1097. ),
  1098. syn_test_suite_helper:assert_wait(
  1099. true,
  1100. fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [Pid2RemoteOn2]) end
  1101. ),
  1102. %% --> conflict by race condition
  1103. PidOnMaster = syn_test_suite_helper:start_process(),
  1104. PidOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1105. rpc:call(SlaveNode1, syn_registry, add_to_local_table,
  1106. [default, <<"my proc">>, PidOn1, "meta-2", erlang:system_time(), undefined]
  1107. ),
  1108. ok = syn:register(<<"my proc">>, PidOnMaster, "meta-1"),
  1109. %% retrieve
  1110. syn_test_suite_helper:assert_wait(
  1111. {PidOnMaster, "meta-1"},
  1112. fun() -> syn:lookup(<<"my proc">>) end
  1113. ),
  1114. syn_test_suite_helper:assert_wait(
  1115. {PidOnMaster, "meta-1"},
  1116. fun() -> rpc:call(SlaveNode1, syn, lookup, [<<"my proc">>]) end
  1117. ),
  1118. syn_test_suite_helper:assert_wait(
  1119. {PidOnMaster, "meta-1"},
  1120. fun() -> rpc:call(SlaveNode2, syn, lookup, [<<"my proc">>]) end
  1121. ),
  1122. %% NB: we can't check for process alive here because we injected the conflictinf process in the DB
  1123. %% -> it's not actually monitored
  1124. %% same, but custom scope
  1125. PidCustom1 = syn_test_suite_helper:start_process(SlaveNode1),
  1126. PidCustom2 = syn_test_suite_helper:start_process(SlaveNode2),
  1127. rpc:call(SlaveNode2, syn_registry, add_to_local_table,
  1128. [custom_scope_bc, <<"my proc">>, PidCustom2, "meta-2", erlang:system_time(), undefined]
  1129. ),
  1130. ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, <<"my proc">>, PidCustom1, "meta-1"]),
  1131. syn_test_suite_helper:assert_wait(
  1132. {PidCustom1, "meta-1"},
  1133. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, <<"my proc">>]) end
  1134. ),
  1135. syn_test_suite_helper:assert_wait(
  1136. {PidCustom1, "meta-1"},
  1137. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, <<"my proc">>]) end
  1138. ).
  1139. three_nodes_custom_event_handler_reg_unreg(Config) ->
  1140. %% get slaves
  1141. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  1142. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  1143. %% add custom handler for callbacks
  1144. syn:set_event_handler(syn_test_event_handler_callbacks),
  1145. rpc:call(SlaveNode1, syn, set_event_handler, [syn_test_event_handler_callbacks]),
  1146. rpc:call(SlaveNode2, syn, set_event_handler, [syn_test_event_handler_callbacks]),
  1147. %% start syn on nodes
  1148. ok = syn:start(),
  1149. ok = rpc:call(SlaveNode1, syn, start, []),
  1150. ok = rpc:call(SlaveNode2, syn, start, []),
  1151. %% init
  1152. CurrentNode = node(),
  1153. %% start process
  1154. Pid = syn_test_suite_helper:start_process(),
  1155. Pid2 = syn_test_suite_helper:start_process(),
  1156. %% ---> on registration
  1157. ok = syn:register("proc-handler", Pid, {recipient, self(), <<"meta">>}),
  1158. %% check callbacks called
  1159. syn_test_suite_helper:assert_received_messages([
  1160. {on_process_registered, CurrentNode, default, "proc-handler", Pid, <<"meta">>, normal},
  1161. {on_process_registered, SlaveNode1, default, "proc-handler", Pid, <<"meta">>, normal},
  1162. {on_process_registered, SlaveNode2, default, "proc-handler", Pid, <<"meta">>, normal}
  1163. ]),
  1164. syn_test_suite_helper:assert_empty_queue(self()),
  1165. %% registration from another node
  1166. ok = rpc:call(SlaveNode1, syn, register, ["proc-handler-2", Pid2, {recipient, self(), <<"meta-for-2">>}]),
  1167. %% check callbacks called
  1168. syn_test_suite_helper:assert_received_messages([
  1169. {on_process_registered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
  1170. {on_process_registered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal},
  1171. {on_process_registered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2">>, normal}
  1172. ]),
  1173. syn_test_suite_helper:assert_empty_queue(self()),
  1174. %% ---> on meta update
  1175. ok = syn:register("proc-handler", Pid, {recipient, self(), <<"new-meta">>}),
  1176. %% check callbacks called
  1177. syn_test_suite_helper:assert_received_messages([
  1178. {on_registry_process_updated, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>, normal},
  1179. {on_registry_process_updated, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>, normal},
  1180. {on_registry_process_updated, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>, normal}
  1181. ]),
  1182. syn_test_suite_helper:assert_empty_queue(self()),
  1183. %% meta update from another node
  1184. ok = rpc:call(SlaveNode1, syn, register, ["proc-handler-2", Pid2, {recipient, self(), <<"meta-for-2-update">>}]),
  1185. %% check callbacks called
  1186. syn_test_suite_helper:assert_received_messages([
  1187. {on_registry_process_updated, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
  1188. {on_registry_process_updated, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
  1189. {on_registry_process_updated, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
  1190. ]),
  1191. syn_test_suite_helper:assert_empty_queue(self()),
  1192. %% ---> on unregister
  1193. ok = syn:unregister("proc-handler"),
  1194. %% check callbacks called
  1195. syn_test_suite_helper:assert_received_messages([
  1196. {on_process_unregistered, CurrentNode, default, "proc-handler", Pid, <<"new-meta">>, normal},
  1197. {on_process_unregistered, SlaveNode1, default, "proc-handler", Pid, <<"new-meta">>, normal},
  1198. {on_process_unregistered, SlaveNode2, default, "proc-handler", Pid, <<"new-meta">>, normal}
  1199. ]),
  1200. syn_test_suite_helper:assert_empty_queue(self()),
  1201. %% unregister from another node
  1202. ok = rpc:call(SlaveNode1, syn, unregister, ["proc-handler-2"]),
  1203. %% check callbacks called
  1204. syn_test_suite_helper:assert_received_messages([
  1205. {on_process_unregistered, CurrentNode, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
  1206. {on_process_unregistered, SlaveNode1, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal},
  1207. {on_process_unregistered, SlaveNode2, default, "proc-handler-2", Pid2, <<"meta-for-2-update">>, normal}
  1208. ]),
  1209. syn_test_suite_helper:assert_empty_queue(self()),
  1210. %% clean & check
  1211. syn_test_suite_helper:kill_process(Pid),
  1212. syn_test_suite_helper:assert_empty_queue(self()),
  1213. %% ---> after a netsplit
  1214. PidRemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1215. syn:register(remote_on_1, PidRemoteOn1, {recipient, self(), <<"netsplit">>}),
  1216. %% check callbacks called
  1217. syn_test_suite_helper:assert_received_messages([
  1218. {on_process_registered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
  1219. {on_process_registered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal},
  1220. {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, normal}
  1221. ]),
  1222. syn_test_suite_helper:assert_empty_queue(self()),
  1223. %% partial netsplit (1 cannot see 2)
  1224. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1225. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1226. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1227. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1228. %% check callbacks called
  1229. syn_test_suite_helper:assert_received_messages([
  1230. {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, {syn_remote_scope_node_down, default, SlaveNode1}}
  1231. ]),
  1232. syn_test_suite_helper:assert_empty_queue(self()),
  1233. %% ---> after a re-join
  1234. %% re-join
  1235. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1236. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1237. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1238. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1239. %% check callbacks called
  1240. syn_test_suite_helper:assert_received_messages([
  1241. {on_process_registered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, {syn_remote_scope_node_up, default, SlaveNode1}}
  1242. ]),
  1243. syn_test_suite_helper:assert_empty_queue(self()),
  1244. %% clean
  1245. syn_test_suite_helper:kill_process(PidRemoteOn1),
  1246. %% check callbacks called
  1247. syn_test_suite_helper:assert_received_messages([
  1248. {on_process_unregistered, CurrentNode, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
  1249. {on_process_unregistered, SlaveNode1, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed},
  1250. {on_process_unregistered, SlaveNode2, default, remote_on_1, PidRemoteOn1, <<"netsplit">>, killed}
  1251. ]),
  1252. syn_test_suite_helper:assert_empty_queue(self()),
  1253. %% ---> after a conflict resolution
  1254. %% partial netsplit (1 cannot see 2)
  1255. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1256. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1257. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1258. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1259. %% start conflict processes
  1260. Pid2RemoteOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1261. Pid2RemoteOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  1262. ok = rpc:call(SlaveNode1, syn, register, ["proc-confict", Pid2RemoteOn1, {recipient, self(), <<"meta-1">>}]),
  1263. ok = rpc:call(SlaveNode2, syn, register, ["proc-confict", Pid2RemoteOn2, {recipient, self(), <<"meta-2">>}]),
  1264. %% check callbacks called
  1265. syn_test_suite_helper:assert_received_messages([
  1266. {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
  1267. {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
  1268. {on_process_registered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal},
  1269. {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, normal},
  1270. {on_process_registered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, normal}
  1271. ]),
  1272. syn_test_suite_helper:assert_empty_queue(self()),
  1273. %% re-join
  1274. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1275. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1276. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1277. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1278. %% check callbacks called
  1279. syn_test_suite_helper:assert_received_messages([
  1280. {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn1, <<"meta-1">>, syn_conflict_resolution},
  1281. {on_process_registered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, syn_conflict_resolution}
  1282. ]),
  1283. syn_test_suite_helper:assert_empty_queue(self()),
  1284. %% kill
  1285. syn_test_suite_helper:kill_process(Pid2RemoteOn1),
  1286. syn_test_suite_helper:kill_process(Pid2RemoteOn2),
  1287. %% check callbacks called
  1288. syn_test_suite_helper:assert_received_messages([
  1289. {on_process_unregistered, CurrentNode, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
  1290. {on_process_unregistered, SlaveNode1, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed},
  1291. {on_process_unregistered, SlaveNode2, default, "proc-confict", Pid2RemoteOn2, <<"meta-2">>, killed}
  1292. ]),
  1293. syn_test_suite_helper:assert_empty_queue(self()),
  1294. %% ---> don't call on monitor rebuild
  1295. %% crash the scope process on local
  1296. syn_test_suite_helper:kill_process(syn_registry_default),
  1297. %% no messages
  1298. syn_test_suite_helper:assert_wait(
  1299. ok,
  1300. fun() -> syn_test_suite_helper:assert_empty_queue(self()) end
  1301. ).
  1302. three_nodes_custom_event_handler_conflict_resolution(Config) ->
  1303. %% get slaves
  1304. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  1305. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  1306. %% add custom handler for resolution
  1307. syn:set_event_handler(syn_test_event_handler_resolution),
  1308. rpc:call(SlaveNode1, syn, set_event_handler, [syn_test_event_handler_resolution]),
  1309. rpc:call(SlaveNode2, syn, set_event_handler, [syn_test_event_handler_resolution]),
  1310. %% start syn on nodes
  1311. ok = syn:start(),
  1312. ok = rpc:call(SlaveNode1, syn, start, []),
  1313. ok = rpc:call(SlaveNode2, syn, start, []),
  1314. %% add custom scopes
  1315. ok = rpc:call(SlaveNode1, syn, add_node_to_scopes, [[custom_scope_bc]]),
  1316. ok = rpc:call(SlaveNode2, syn, add_node_to_scopes, [[custom_scope_bc]]),
  1317. %% current node
  1318. TestPid = self(),
  1319. CurrentNode = node(),
  1320. %% partial netsplit (1 cannot see 2)
  1321. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1322. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1323. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1324. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1325. %% start conflict processes
  1326. PidOn1 = syn_test_suite_helper:start_process(SlaveNode1),
  1327. PidOn2 = syn_test_suite_helper:start_process(SlaveNode2),
  1328. %% --> conflict by netsplit
  1329. ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom", PidOn1, {recipient, TestPid, keepthis}]),
  1330. ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom", PidOn2, {recipient, TestPid, "meta-2"}]),
  1331. ok = rpc:call(SlaveNode1, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, {recipient, TestPid, keepthis}]),
  1332. ok = rpc:call(SlaveNode2, syn, register, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, {recipient, TestPid, "meta-2"}]),
  1333. %% check callbacks
  1334. syn_test_suite_helper:assert_received_messages([
  1335. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1336. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1337. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
  1338. {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1339. {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", normal},
  1340. {on_process_registered, SlaveNode1, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal},
  1341. {on_process_registered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, "meta-2", normal}
  1342. ]),
  1343. syn_test_suite_helper:assert_empty_queue(self()),
  1344. %% re-join
  1345. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1346. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1347. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1348. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1349. %% retrieve
  1350. syn_test_suite_helper:assert_wait(
  1351. {PidOn1, {recipient, TestPid, keepthis}},
  1352. fun() -> syn:lookup("proc-confict-by-netsplit-custom") end
  1353. ),
  1354. syn_test_suite_helper:assert_wait(
  1355. {PidOn1, {recipient, TestPid, keepthis}},
  1356. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
  1357. ),
  1358. syn_test_suite_helper:assert_wait(
  1359. {PidOn1, {recipient, TestPid, keepthis}},
  1360. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
  1361. ),
  1362. 1 = syn:registry_count(),
  1363. 0 = syn:registry_count(default, node()),
  1364. 1 = syn:registry_count(default, SlaveNode1),
  1365. 0 = syn:registry_count(default, SlaveNode2),
  1366. 1 = rpc:call(SlaveNode1, syn, registry_count, []),
  1367. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  1368. 1 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  1369. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  1370. 1 = rpc:call(SlaveNode2, syn, registry_count, []),
  1371. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  1372. 1 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  1373. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  1374. syn_test_suite_helper:assert_wait(
  1375. {PidOn1, {recipient, TestPid, keepthis}},
  1376. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
  1377. ),
  1378. syn_test_suite_helper:assert_wait(
  1379. {PidOn1, {recipient, TestPid, keepthis}},
  1380. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
  1381. ),
  1382. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc]),
  1383. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, node()]),
  1384. 1 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1385. 0 = rpc:call(SlaveNode1, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  1386. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc]),
  1387. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, node()]),
  1388. 1 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode1]),
  1389. 0 = rpc:call(SlaveNode2, syn, registry_count, [custom_scope_bc, SlaveNode2]),
  1390. syn_test_suite_helper:assert_received_messages([
  1391. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
  1392. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
  1393. {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn2, "meta-2", syn_conflict_resolution},
  1394. {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, syn_conflict_resolution},
  1395. {on_process_unregistered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn2, "meta-2", syn_conflict_resolution},
  1396. {on_process_registered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, syn_conflict_resolution}
  1397. ]),
  1398. syn_test_suite_helper:assert_empty_queue(self()),
  1399. %% process alive (discarded process does not get killed with a custom handler)
  1400. syn_test_suite_helper:assert_wait(
  1401. true,
  1402. fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [PidOn1]) end
  1403. ),
  1404. syn_test_suite_helper:assert_wait(
  1405. true,
  1406. fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
  1407. ),
  1408. %% clean up default scope
  1409. syn:unregister("proc-confict-by-netsplit-custom"),
  1410. ok = rpc:call(SlaveNode1, syn, unregister, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]),
  1411. %% retrieve
  1412. syn_test_suite_helper:assert_wait(
  1413. undefined,
  1414. fun() -> syn:lookup("proc-confict-by-netsplit-custom") end
  1415. ),
  1416. syn_test_suite_helper:assert_wait(
  1417. undefined,
  1418. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
  1419. ),
  1420. syn_test_suite_helper:assert_wait(
  1421. undefined,
  1422. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
  1423. ),
  1424. syn_test_suite_helper:assert_wait(
  1425. undefined,
  1426. fun() -> rpc:call(SlaveNode1, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
  1427. ),
  1428. syn_test_suite_helper:assert_wait(
  1429. undefined,
  1430. fun() -> rpc:call(SlaveNode2, syn, lookup, [custom_scope_bc, "proc-confict-by-netsplit-scoped-custom"]) end
  1431. ),
  1432. %% check callbacks
  1433. syn_test_suite_helper:assert_received_messages([
  1434. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1435. {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1436. {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom", PidOn1, keepthis, normal},
  1437. {on_process_unregistered, SlaveNode1, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal},
  1438. {on_process_unregistered, SlaveNode2, custom_scope_bc, "proc-confict-by-netsplit-scoped-custom", PidOn1, keepthis, normal}
  1439. ]),
  1440. syn_test_suite_helper:assert_empty_queue(self()),
  1441. %% --> conflict by netsplit, which returns invalid pid
  1442. %% partial netsplit (1 cannot see 2)
  1443. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1444. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1445. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1446. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1447. %% register with meta with no 'keepthis' element
  1448. ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn1, {recipient, TestPid, "meta-1"}]),
  1449. ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn2, {recipient, TestPid, "meta-2"}]),
  1450. %% check callbacks
  1451. syn_test_suite_helper:assert_received_messages([
  1452. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
  1453. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
  1454. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal},
  1455. {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", normal},
  1456. {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", normal}
  1457. ]),
  1458. syn_test_suite_helper:assert_empty_queue(self()),
  1459. %% re-join
  1460. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1461. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1462. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1463. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1464. %% retrieve (names get freed)
  1465. syn_test_suite_helper:assert_wait(
  1466. undefined,
  1467. fun() -> syn:lookup("proc-confict-by-netsplit-custom-other-pid") end
  1468. ),
  1469. syn_test_suite_helper:assert_wait(
  1470. undefined,
  1471. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom-other-pid"]) end
  1472. ),
  1473. syn_test_suite_helper:assert_wait(
  1474. undefined,
  1475. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom-other-pid"]) end
  1476. ),
  1477. 0 = syn:registry_count(),
  1478. 0 = syn:registry_count(default, node()),
  1479. 0 = syn:registry_count(default, SlaveNode1),
  1480. 0 = syn:registry_count(default, SlaveNode2),
  1481. 0 = rpc:call(SlaveNode1, syn, registry_count, []),
  1482. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  1483. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  1484. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  1485. 0 = rpc:call(SlaveNode2, syn, registry_count, []),
  1486. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  1487. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  1488. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  1489. %% check callbacks
  1490. syn_test_suite_helper:assert_received_messages([
  1491. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution},
  1492. {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1", syn_conflict_resolution},
  1493. {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2", syn_conflict_resolution}
  1494. ]),
  1495. syn_test_suite_helper:assert_empty_queue(self()),
  1496. %% process alive (discarded process does not get killed with a custom handler)
  1497. syn_test_suite_helper:assert_wait(
  1498. true,
  1499. fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [PidOn1]) end
  1500. ),
  1501. syn_test_suite_helper:assert_wait(
  1502. true,
  1503. fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
  1504. ),
  1505. %% --> conflict by netsplit, which crashes
  1506. %% partial netsplit (1 cannot see 2)
  1507. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  1508. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1509. syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
  1510. syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
  1511. %% register with meta with no 'crash' element
  1512. ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn1, {recipient, TestPid, crash}]),
  1513. ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn2, {recipient, TestPid, crash}]),
  1514. %% check callbacks
  1515. syn_test_suite_helper:assert_received_messages([
  1516. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
  1517. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
  1518. {on_process_registered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal},
  1519. {on_process_registered, SlaveNode1, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, normal},
  1520. {on_process_registered, SlaveNode2, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, normal}
  1521. ]),
  1522. syn_test_suite_helper:assert_empty_queue(self()),
  1523. %% re-join
  1524. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  1525. syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
  1526. syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
  1527. syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
  1528. %% retrieve (names get freed)
  1529. syn_test_suite_helper:assert_wait(
  1530. undefined,
  1531. fun() -> syn:lookup("proc-confict-by-netsplit-custom-crash") end
  1532. ),
  1533. syn_test_suite_helper:assert_wait(
  1534. undefined,
  1535. fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom-crash"]) end
  1536. ),
  1537. syn_test_suite_helper:assert_wait(
  1538. undefined,
  1539. fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom-crash"]) end
  1540. ),
  1541. 0 = syn:registry_count(),
  1542. 0 = syn:registry_count(default, node()),
  1543. 0 = syn:registry_count(default, SlaveNode1),
  1544. 0 = syn:registry_count(default, SlaveNode2),
  1545. 0 = rpc:call(SlaveNode1, syn, registry_count, []),
  1546. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
  1547. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
  1548. 0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
  1549. 0 = rpc:call(SlaveNode2, syn, registry_count, []),
  1550. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
  1551. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
  1552. 0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
  1553. %% check callbacks
  1554. syn_test_suite_helper:assert_received_messages([
  1555. {on_process_unregistered, CurrentNode, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution},
  1556. {on_process_unregistered, SlaveNode1, default, "proc-confict-by-netsplit-custom-crash", PidOn1, crash, syn_conflict_resolution},
  1557. {on_process_unregistered, SlaveNode2, default, "proc-confict-by-netsplit-custom-crash", PidOn2, crash, syn_conflict_resolution}
  1558. ]),
  1559. syn_test_suite_helper:assert_empty_queue(self()),
  1560. %% process alive (discarded process does not get killed with a custom handler)
  1561. syn_test_suite_helper:assert_wait(
  1562. true,
  1563. fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [PidOn1]) end
  1564. ),
  1565. syn_test_suite_helper:assert_wait(
  1566. true,
  1567. fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
  1568. ).
  1569. %% ===================================================================
  1570. %% Internal
  1571. %% ===================================================================
  1572. add_to_local_table(Scope, Name, Pid, Meta, Time, MRef) ->
  1573. TableByName = syn_backbone:get_table_name(syn_registry_by_name, Scope),
  1574. TableByPid = syn_backbone:get_table_name(syn_registry_by_pid, Scope),
  1575. syn_registry:add_to_local_table(Name, Pid, Meta, Time, MRef, TableByName, TableByPid).
  1576. remove_from_local_table(Scope, Name, Pid) ->
  1577. TableByName = syn_backbone:get_table_name(syn_registry_by_name, Scope),
  1578. TableByPid = syn_backbone:get_table_name(syn_registry_by_pid, Scope),
  1579. syn_registry:remove_from_local_table(Name, Pid, TableByName, TableByPid).