syn_registry_SUITE.erl 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. %% ==========================================================================================================
  2. %% Syn - A global Process Registry and Process Group manager.
  3. %%
  4. %% The MIT License (MIT)
  5. %%
  6. %% Copyright (c) 2015-2019 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. single_node_register_and_monitor/1,
  35. single_node_register_and_unregister/1,
  36. single_node_registration_errors/1,
  37. single_node_registry_count/1
  38. ]).
  39. -export([
  40. two_nodes_register_monitor_and_unregister/1,
  41. two_nodes_registry_count/1
  42. ]).
  43. -export([
  44. three_nodes_consistency_partial_net_split/1,
  45. three_nodes_consistency_full_net_split/1
  46. ]).
  47. %% include
  48. -include_lib("common_test/include/ct.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 = term()
  58. %% -------------------------------------------------------------------
  59. all() ->
  60. [
  61. {group, single_node_process_registration},
  62. {group, two_nodes_process_registration},
  63. {group, three_nodes_process_registration}
  64. ].
  65. %% -------------------------------------------------------------------
  66. %% Function: groups() -> [Group]
  67. %% Group = {GroupName,Properties,GroupsAndTestCases}
  68. %% GroupName = atom()
  69. %% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
  70. %% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
  71. %% TestCase = atom()
  72. %% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
  73. %% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
  74. %% repeat_until_any_ok | repeat_until_any_fail
  75. %% N = integer() | forever
  76. %% -------------------------------------------------------------------
  77. groups() ->
  78. [
  79. {single_node_process_registration, [shuffle], [
  80. single_node_register_and_monitor,
  81. single_node_register_and_unregister,
  82. single_node_registration_errors,
  83. single_node_registry_count
  84. ]},
  85. {two_nodes_process_registration, [shuffle], [
  86. two_nodes_register_monitor_and_unregister,
  87. two_nodes_registry_count
  88. ]},
  89. {three_nodes_process_registration, [shuffle], [
  90. three_nodes_consistency_partial_net_split,
  91. three_nodes_consistency_full_net_split
  92. ]}
  93. ].
  94. %% -------------------------------------------------------------------
  95. %% Function: init_per_suite(Config0) ->
  96. %% Config1 | {skip,Reason} |
  97. %% {skip_and_save,Reason,Config1}
  98. %% Config0 = Config1 = [tuple()]
  99. %% Reason = term()
  100. %% -------------------------------------------------------------------
  101. init_per_suite(Config) ->
  102. Config.
  103. %% -------------------------------------------------------------------
  104. %% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
  105. %% Config0 = Config1 = [tuple()]
  106. %% -------------------------------------------------------------------
  107. end_per_suite(_Config) ->
  108. ok.
  109. %% -------------------------------------------------------------------
  110. %% Function: init_per_group(GroupName, Config0) ->
  111. %% Config1 | {skip,Reason} |
  112. %% {skip_and_save,Reason,Config1}
  113. %% GroupName = atom()
  114. %% Config0 = Config1 = [tuple()]
  115. %% Reason = term()
  116. %% -------------------------------------------------------------------
  117. init_per_group(two_nodes_process_registration, Config) ->
  118. %% start slave
  119. {ok, SlaveNode} = syn_test_suite_helper:start_slave(syn_slave),
  120. %% config
  121. [{slave_node, SlaveNode} | Config];
  122. init_per_group(three_nodes_process_registration, Config) ->
  123. %% start slave
  124. {ok, SlaveNode1} = syn_test_suite_helper:start_slave(syn_slave_1),
  125. {ok, SlaveNode2} = syn_test_suite_helper:start_slave(syn_slave_2),
  126. %% config
  127. [{slave_node_1, SlaveNode1}, {slave_node_2, SlaveNode2} | Config];
  128. init_per_group(_GroupName, Config) ->
  129. Config.
  130. %% -------------------------------------------------------------------
  131. %% Function: end_per_group(GroupName, Config0) ->
  132. %% void() | {save_config,Config1}
  133. %% GroupName = atom()
  134. %% Config0 = Config1 = [tuple()]
  135. %% -------------------------------------------------------------------
  136. end_per_group(two_nodes_process_registration, Config) ->
  137. SlaveNode = proplists:get_value(slave_node, Config),
  138. syn_test_suite_helper:connect_node(SlaveNode),
  139. syn_test_suite_helper:stop_slave(syn_slave);
  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:stop_slave(syn_slave_1),
  146. syn_test_suite_helper:stop_slave(syn_slave_2);
  147. end_per_group(_GroupName, _Config) ->
  148. ok.
  149. % ----------------------------------------------------------------------------------------------------------
  150. % Function: init_per_testcase(TestCase, Config0) ->
  151. % Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
  152. % TestCase = atom()
  153. % Config0 = Config1 = [tuple()]
  154. % Reason = term()
  155. % ----------------------------------------------------------------------------------------------------------
  156. init_per_testcase(_TestCase, Config) ->
  157. Config.
  158. % ----------------------------------------------------------------------------------------------------------
  159. % Function: end_per_testcase(TestCase, Config0) ->
  160. % void() | {save_config,Config1} | {fail,Reason}
  161. % TestCase = atom()
  162. % Config0 = Config1 = [tuple()]
  163. % Reason = term()
  164. % ----------------------------------------------------------------------------------------------------------
  165. end_per_testcase(_, _Config) ->
  166. syn_test_suite_helper:clean_after_test().
  167. %% ===================================================================
  168. %% Tests
  169. %% ===================================================================
  170. single_node_register_and_monitor(_Config) ->
  171. %% start
  172. ok = syn:start(),
  173. %% start processes
  174. Pid = syn_test_suite_helper:start_process(),
  175. PidWithMeta = syn_test_suite_helper:start_process(),
  176. %% retrieve
  177. undefined = syn:whereis(<<"my proc">>),
  178. %% register
  179. ok = syn:register(<<"my proc">>, Pid),
  180. ok = syn:register(<<"my proc 2">>, Pid),
  181. ok = syn:register(<<"my proc with meta">>, PidWithMeta, {meta, <<"meta">>}),
  182. %% retrieve
  183. Pid = syn:whereis(<<"my proc">>),
  184. Pid = syn:whereis(<<"my proc 2">>),
  185. {PidWithMeta, {meta, <<"meta">>}} = syn:whereis(<<"my proc with meta">>, with_meta),
  186. %% kill process
  187. syn_test_suite_helper:kill_process(Pid),
  188. syn_test_suite_helper:kill_process(PidWithMeta),
  189. timer:sleep(100),
  190. %% retrieve
  191. undefined = syn:whereis(<<"my proc">>),
  192. undefined = syn:whereis(<<"my proc 2">>),
  193. undefined = syn:whereis(<<"my proc with meta">>).
  194. single_node_register_and_unregister(_Config) ->
  195. %% start
  196. ok = syn:start(),
  197. %% start process
  198. Pid = syn_test_suite_helper:start_process(),
  199. %% retrieve
  200. undefined = syn:whereis(<<"my proc">>),
  201. %% register
  202. ok = syn:register(<<"my proc">>, Pid),
  203. ok = syn:register(<<"my proc 2">>, Pid),
  204. %% retrieve
  205. Pid = syn:whereis(<<"my proc">>),
  206. Pid = syn:whereis(<<"my proc 2">>),
  207. %% unregister 1
  208. ok = syn:unregister(<<"my proc">>),
  209. %% retrieve
  210. undefined = syn:whereis(<<"my proc">>),
  211. Pid = syn:whereis(<<"my proc 2">>),
  212. %% unregister 2
  213. ok = syn:unregister(<<"my proc 2">>),
  214. {error, undefined} = syn:unregister(<<"my proc 2">>),
  215. %% retrieve
  216. undefined = syn:whereis(<<"my proc">>),
  217. undefined = syn:whereis(<<"my proc 2">>),
  218. %% kill process
  219. syn_test_suite_helper:kill_process(Pid).
  220. single_node_registration_errors(_Config) ->
  221. %% start
  222. ok = syn:start(),
  223. %% start process
  224. Pid = syn_test_suite_helper:start_process(),
  225. Pid2 = syn_test_suite_helper:start_process(),
  226. %% register
  227. ok = syn:register(<<"my proc">>, Pid),
  228. {error, taken} = syn:register(<<"my proc">>, Pid2),
  229. %% kill processes
  230. syn_test_suite_helper:kill_process(Pid),
  231. syn_test_suite_helper:kill_process(Pid2),
  232. timer:sleep(100),
  233. %% retrieve
  234. undefined = syn:whereis(<<"my proc">>),
  235. %% try registering a dead pid
  236. {error, not_alive} = syn:register(<<"my proc">>, Pid).
  237. single_node_registry_count(_Config) ->
  238. %% start
  239. ok = syn:start(),
  240. %% start process
  241. Pid = syn_test_suite_helper:start_process(),
  242. Pid2 = syn_test_suite_helper:start_process(),
  243. PidUnregistered = syn_test_suite_helper:start_process(),
  244. %% register
  245. ok = syn:register(<<"my proc">>, Pid),
  246. ok = syn:register(<<"my proc 2">>, Pid2),
  247. %% count
  248. 2 = syn:registry_count(),
  249. 2 = syn:registry_count(node()),
  250. %% kill & unregister
  251. syn_test_suite_helper:kill_process(Pid),
  252. ok = syn:unregister(<<"my proc 2">>),
  253. syn_test_suite_helper:kill_process(PidUnregistered),
  254. timer:sleep(100),
  255. %% count
  256. 0 = syn:registry_count(),
  257. 0 = syn:registry_count(node()).
  258. two_nodes_register_monitor_and_unregister(Config) ->
  259. %% get slave
  260. SlaveNode = proplists:get_value(slave_node, Config),
  261. %% start
  262. ok = syn:start(),
  263. ok = rpc:call(SlaveNode, syn, start, []),
  264. timer:sleep(100),
  265. %% start processes
  266. LocalPid = syn_test_suite_helper:start_process(),
  267. RemotePid = syn_test_suite_helper:start_process(SlaveNode),
  268. RemotePidRegRemote = syn_test_suite_helper:start_process(SlaveNode),
  269. %% retrieve
  270. undefined = syn:whereis(<<"local proc">>),
  271. undefined = syn:whereis(<<"remote proc">>),
  272. undefined = syn:whereis(<<"remote proc reg_remote">>),
  273. undefined = rpc:call(SlaveNode, syn, whereis, [<<"local proc">>]),
  274. undefined = rpc:call(SlaveNode, syn, whereis, [<<"remote proc">>]),
  275. undefined = rpc:call(SlaveNode, syn, whereis, [<<"remote proc reg_remote">>]),
  276. %% register
  277. ok = syn:register(<<"local proc">>, LocalPid),
  278. ok = syn:register(<<"remote proc">>, RemotePid),
  279. ok = rpc:call(SlaveNode, syn, register, [<<"remote proc reg_remote">>, RemotePidRegRemote]),
  280. timer:sleep(500),
  281. %% retrieve
  282. LocalPid = syn:whereis(<<"local proc">>),
  283. RemotePid = syn:whereis(<<"remote proc">>),
  284. RemotePidRegRemote = syn:whereis(<<"remote proc reg_remote">>),
  285. LocalPid = rpc:call(SlaveNode, syn, whereis, [<<"local proc">>]),
  286. RemotePid = rpc:call(SlaveNode, syn, whereis, [<<"remote proc">>]),
  287. RemotePidRegRemote = rpc:call(SlaveNode, syn, whereis, [<<"remote proc reg_remote">>]),
  288. %% kill & unregister processes
  289. syn_test_suite_helper:kill_process(LocalPid),
  290. ok = syn:unregister(<<"remote proc">>),
  291. syn_test_suite_helper:kill_process(RemotePidRegRemote),
  292. timer:sleep(100),
  293. %% retrieve
  294. undefined = syn:whereis(<<"local proc">>),
  295. undefined = syn:whereis(<<"remote proc">>),
  296. undefined = syn:whereis(<<"remote proc reg_remote">>),
  297. undefined = rpc:call(SlaveNode, syn, whereis, [<<"local proc">>]),
  298. undefined = rpc:call(SlaveNode, syn, whereis, [<<"remote proc">>]),
  299. undefined = rpc:call(SlaveNode, syn, whereis, [<<"remote proc reg_remote">>]),
  300. %% kill proc
  301. syn_test_suite_helper:kill_process(RemotePid).
  302. two_nodes_registry_count(Config) ->
  303. %% get slave
  304. SlaveNode = proplists:get_value(slave_node, Config),
  305. %% start
  306. ok = syn:start(),
  307. ok = rpc:call(SlaveNode, syn, start, []),
  308. timer:sleep(100),
  309. %% start processes
  310. LocalPid = syn_test_suite_helper:start_process(),
  311. RemotePid = syn_test_suite_helper:start_process(SlaveNode),
  312. RemotePidRegRemote = syn_test_suite_helper:start_process(SlaveNode),
  313. PidUnregistered = syn_test_suite_helper:start_process(),
  314. %% register
  315. ok = syn:register(<<"local proc">>, LocalPid),
  316. ok = syn:register(<<"remote proc">>, RemotePid),
  317. ok = rpc:call(SlaveNode, syn, register, [<<"remote proc reg_remote">>, RemotePidRegRemote]),
  318. timer:sleep(500),
  319. %% count
  320. 3 = syn:registry_count(),
  321. 1 = syn:registry_count(node()),
  322. 2 = syn:registry_count(SlaveNode),
  323. %% kill & unregister processes
  324. syn_test_suite_helper:kill_process(LocalPid),
  325. ok = syn:unregister(<<"remote proc">>),
  326. syn_test_suite_helper:kill_process(RemotePidRegRemote),
  327. timer:sleep(100),
  328. %% count
  329. 0 = syn:registry_count(),
  330. 0 = syn:registry_count(node()),
  331. 0 = syn:registry_count(SlaveNode),
  332. %% kill proc
  333. syn_test_suite_helper:kill_process(RemotePid).
  334. three_nodes_consistency_partial_net_split(Config) ->
  335. %% get slaves
  336. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  337. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  338. %% start syn on nodes
  339. ok = syn:start(),
  340. ok = rpc:call(SlaveNode1, syn, start, []),
  341. ok = rpc:call(SlaveNode2, syn, start, []),
  342. timer:sleep(100),
  343. %% start processes
  344. Pid0 = syn_test_suite_helper:start_process(),
  345. Pid0b = syn_test_suite_helper:start_process(),
  346. Pid1 = syn_test_suite_helper:start_process(SlaveNode1),
  347. Pid2 = syn_test_suite_helper:start_process(SlaveNode2),
  348. timer:sleep(100),
  349. %% retrieve
  350. undefined = syn:whereis(<<"proc0">>),
  351. undefined = syn:whereis(<<"proc0b">>),
  352. undefined = syn:whereis(<<"proc1">>),
  353. undefined = syn:whereis(<<"proc2">>),
  354. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  355. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  356. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  357. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  358. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  359. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  360. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  361. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  362. %% register (mix nodes)
  363. ok = rpc:call(SlaveNode2, syn, register, [<<"proc0">>, Pid0]),
  364. ok = syn:register(<<"proc1">>, Pid1),
  365. ok = rpc:call(SlaveNode1, syn, register, [<<"proc2">>, Pid2]),
  366. ok = rpc:call(SlaveNode1, syn, register, [<<"proc0b">>, Pid0b]),
  367. timer:sleep(200),
  368. %% retrieve
  369. Pid0 = syn:whereis(<<"proc0">>),
  370. Pid0b = syn:whereis(<<"proc0b">>),
  371. Pid1 = syn:whereis(<<"proc1">>),
  372. Pid2 = syn:whereis(<<"proc2">>),
  373. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  374. Pid0b = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  375. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  376. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  377. Pid0 = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  378. Pid0b = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  379. Pid1 = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  380. Pid2 = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  381. %% disconnect slave 2 from main (slave 1 can still see slave 2)
  382. syn_test_suite_helper:disconnect_node(SlaveNode2),
  383. timer:sleep(500),
  384. %% retrieve
  385. Pid0 = syn:whereis(<<"proc0">>),
  386. Pid0b = syn:whereis(<<"proc0b">>),
  387. Pid1 = syn:whereis(<<"proc1">>),
  388. undefined = syn:whereis(<<"proc2">>), %% main has lost slave 2 so 'proc2' is removed
  389. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  390. Pid0b = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  391. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  392. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]), %% slave 1 still has slave 2 so 'proc2' is still there
  393. %% disconnect slave 1
  394. syn_test_suite_helper:disconnect_node(SlaveNode1),
  395. timer:sleep(500),
  396. %% unregister 0b
  397. ok = syn:unregister(<<"proc0b">>),
  398. %% retrieve
  399. Pid0 = syn:whereis(<<"proc0">>),
  400. undefined = syn:whereis(<<"proc0b">>),
  401. undefined = syn:whereis(<<"proc1">>),
  402. undefined = syn:whereis(<<"proc2">>),
  403. %% reconnect all
  404. syn_test_suite_helper:connect_node(SlaveNode1),
  405. syn_test_suite_helper:connect_node(SlaveNode2),
  406. timer:sleep(5000),
  407. %% retrieve
  408. Pid0 = syn:whereis(<<"proc0">>),
  409. undefined = syn:whereis(<<"proc0b">>),
  410. Pid1 = syn:whereis(<<"proc1">>),
  411. Pid2 = syn:whereis(<<"proc2">>),
  412. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  413. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  414. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  415. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  416. Pid0 = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  417. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  418. Pid1 = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  419. Pid2 = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  420. %% kill processes
  421. syn_test_suite_helper:kill_process(Pid0),
  422. syn_test_suite_helper:kill_process(Pid1),
  423. syn_test_suite_helper:kill_process(Pid2).
  424. three_nodes_consistency_full_net_split(Config) ->
  425. %% get slaves
  426. SlaveNode1 = proplists:get_value(slave_node_1, Config),
  427. SlaveNode2 = proplists:get_value(slave_node_2, Config),
  428. %% start syn on nodes
  429. ok = syn:start(),
  430. ok = rpc:call(SlaveNode1, syn, start, []),
  431. ok = rpc:call(SlaveNode2, syn, start, []),
  432. timer:sleep(100),
  433. %% start processes
  434. Pid0 = syn_test_suite_helper:start_process(),
  435. Pid0b = syn_test_suite_helper:start_process(),
  436. Pid1 = syn_test_suite_helper:start_process(SlaveNode1),
  437. Pid2 = syn_test_suite_helper:start_process(SlaveNode2),
  438. timer:sleep(100),
  439. %% retrieve
  440. undefined = syn:whereis(<<"proc0">>),
  441. undefined = syn:whereis(<<"proc0b">>),
  442. undefined = syn:whereis(<<"proc1">>),
  443. undefined = syn:whereis(<<"proc2">>),
  444. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  445. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  446. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  447. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  448. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  449. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  450. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  451. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  452. %% register (mix nodes)
  453. ok = rpc:call(SlaveNode2, syn, register, [<<"proc0">>, Pid0]),
  454. ok = rpc:call(SlaveNode2, syn, register, [<<"proc0b">>, Pid0b]),
  455. ok = syn:register(<<"proc1">>, Pid1),
  456. ok = rpc:call(SlaveNode1, syn, register, [<<"proc2">>, Pid2]),
  457. timer:sleep(200),
  458. %% retrieve
  459. Pid0 = syn:whereis(<<"proc0">>),
  460. Pid0b = syn:whereis(<<"proc0b">>),
  461. Pid1 = syn:whereis(<<"proc1">>),
  462. Pid2 = syn:whereis(<<"proc2">>),
  463. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  464. Pid0b = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  465. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  466. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  467. Pid0 = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  468. Pid0b = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  469. Pid1 = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  470. Pid2 = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  471. %% disconnect slave 2 from main (slave 1 can still see slave 2)
  472. syn_test_suite_helper:disconnect_node(SlaveNode2),
  473. timer:sleep(500),
  474. %% retrieve
  475. Pid0 = syn:whereis(<<"proc0">>),
  476. Pid0b = syn:whereis(<<"proc0b">>),
  477. Pid1 = syn:whereis(<<"proc1">>),
  478. undefined = syn:whereis(<<"proc2">>), %% main has lost slave 2 so 'proc2' is removed
  479. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  480. Pid0b = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  481. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  482. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]), %% slave 1 still has slave 2 so 'proc2' is still there
  483. %% disconnect slave 2 from slave 1
  484. rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
  485. timer:sleep(500),
  486. %% retrieve
  487. Pid0 = syn:whereis(<<"proc0">>),
  488. Pid0b = syn:whereis(<<"proc0b">>),
  489. Pid1 = syn:whereis(<<"proc1">>),
  490. undefined = syn:whereis(<<"proc2">>), %% main has lost slave 2 so 'proc2' is removed
  491. undefined = syn:whereis(<<"proc2">>, with_meta),
  492. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  493. Pid0b = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  494. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  495. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  496. %% disconnect slave 1
  497. syn_test_suite_helper:disconnect_node(SlaveNode1),
  498. timer:sleep(500),
  499. %% unregister
  500. ok = syn:unregister(<<"proc0b">>),
  501. %% retrieve
  502. Pid0 = syn:whereis(<<"proc0">>),
  503. undefined = syn:whereis(<<"proc0b">>),
  504. undefined = syn:whereis(<<"proc1">>),
  505. undefined = syn:whereis(<<"proc2">>),
  506. %% reconnect all
  507. syn_test_suite_helper:connect_node(SlaveNode1),
  508. syn_test_suite_helper:connect_node(SlaveNode2),
  509. rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
  510. timer:sleep(1500),
  511. %% retrieve
  512. Pid0 = syn:whereis(<<"proc0">>),
  513. undefined = syn:whereis(<<"proc0b">>),
  514. Pid1 = syn:whereis(<<"proc1">>),
  515. Pid2 = syn:whereis(<<"proc2">>),
  516. Pid0 = rpc:call(SlaveNode1, syn, whereis, [<<"proc0">>]),
  517. undefined = rpc:call(SlaveNode1, syn, whereis, [<<"proc0b">>]),
  518. Pid1 = rpc:call(SlaveNode1, syn, whereis, [<<"proc1">>]),
  519. Pid2 = rpc:call(SlaveNode1, syn, whereis, [<<"proc2">>]),
  520. Pid0 = rpc:call(SlaveNode2, syn, whereis, [<<"proc0">>]),
  521. undefined = rpc:call(SlaveNode2, syn, whereis, [<<"proc0b">>]),
  522. Pid1 = rpc:call(SlaveNode2, syn, whereis, [<<"proc1">>]),
  523. Pid2 = rpc:call(SlaveNode2, syn, whereis, [<<"proc2">>]),
  524. %% kill processes
  525. syn_test_suite_helper:kill_process(Pid0),
  526. syn_test_suite_helper:kill_process(Pid0b),
  527. syn_test_suite_helper:kill_process(Pid1),
  528. syn_test_suite_helper:kill_process(Pid2).