Просмотр исходного кода

Add tests for custom handler crash & wrong pid.

Roberto Ostinelli 3 лет назад
Родитель
Сommit
1807d2afcc
3 измененных файлов с 131 добавлено и 3 удалено
  1. 4 2
      src/syn_registry.erl
  2. 122 0
      test/syn_registry_SUITE.erl
  3. 5 1
      test/syn_test_event_handler_resolution.erl

+ 4 - 2
src/syn_registry.erl

@@ -603,7 +603,7 @@ resolve_conflict(Scope, Name, {Pid, Meta, Time}, {TablePid, TableMeta, TableTime
             %% overwrite with updated time
             ResolveTime = erlang:system_time(),
             add_to_local_table(Name, TablePid, TableMeta, ResolveTime, TableMRef, TableByName, TableByPid),
-            %% broadcast to all but remote node
+            %% broadcast to all (including remote node to update the time)
             syn_gen_scope:broadcast({'3.0', sync_register, Name, TablePid, TableMeta, ResolveTime}, State);
 
         Invalid ->
@@ -619,5 +619,7 @@ resolve_conflict(Scope, Name, {Pid, Meta, Time}, {TablePid, TableMeta, TableTime
                 false -> ok
             end,
             %% callback
-            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta])
+            syn_event_handler:call_event_handler(on_process_unregistered, [Scope, Name, TablePid, TableMeta]),
+            %% broadcast to all but remote node, which will remove it during conflict resolution
+            syn_gen_scope:broadcast({'3.0', sync_unregister, Name, TablePid, TableMeta}, [node(Pid)], State)
     end.

+ 122 - 0
test/syn_registry_SUITE.erl

@@ -1500,6 +1500,128 @@ three_nodes_custom_event_handler_conflict_resolution(Config) ->
     syn_test_suite_helper:assert_wait(
         true,
         fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
+    ),
+
+    %% clean up default scope
+    syn:unregister("proc-confict-by-netsplit-custom"),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> syn:lookup("proc-confict-by-netsplit-custom") end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom"]) end
+    ),
+
+    %% --> conflict by netsplit, which returns invalid pid
+    %% partial netsplit (1 cannot see 2)
+    rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
+
+    %% update meta to not select any process
+    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn1, "meta-1"]),
+    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-other-pid", PidOn2, "meta-2"]),
+
+    %% re-join
+    rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
+
+    %% retrieve (names get freed)
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> syn:lookup("proc-confict-by-netsplit-custom-other-pid") end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom-other-pid"]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom-other-pid"]) end
+    ),
+    0 = syn:registry_count(),
+    0 = syn:registry_count(default, node()),
+    0 = syn:registry_count(default, SlaveNode1),
+    0 = syn:registry_count(default, SlaveNode2),
+    0 = rpc:call(SlaveNode1, syn, registry_count, []),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, []),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
+
+    %% process alive (discarded process does not get killed with a custom handler)
+    syn_test_suite_helper:assert_wait(
+        true,
+        fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [PidOn1]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        true,
+        fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
+    ),
+
+    %% --> conflict by netsplit, which crashes
+
+    %% partial netsplit (1 cannot see 2)
+    rpc:call(SlaveNode1, syn_test_suite_helper, disconnect_node, [SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node()]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node()]),
+
+    %% update meta to not select any process
+    ok = rpc:call(SlaveNode1, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn1, crash]),
+    ok = rpc:call(SlaveNode2, syn, register, ["proc-confict-by-netsplit-custom-crash", PidOn2, crash]),
+
+    %% re-join
+    rpc:call(SlaveNode1, syn_test_suite_helper, connect_node, [SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(node(), [SlaveNode1, SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode1, [node(), SlaveNode2]),
+    syn_test_suite_helper:assert_cluster(SlaveNode2, [node(), SlaveNode1]),
+
+    %% retrieve (names get freed)
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> syn:lookup("proc-confict-by-netsplit-custom-crash") end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode1, syn, lookup, ["proc-confict-by-netsplit-custom-crash"]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        undefined,
+        fun() -> rpc:call(SlaveNode2, syn, lookup, ["proc-confict-by-netsplit-custom-crash"]) end
+    ),
+    0 = syn:registry_count(),
+    0 = syn:registry_count(default, node()),
+    0 = syn:registry_count(default, SlaveNode1),
+    0 = syn:registry_count(default, SlaveNode2),
+    0 = rpc:call(SlaveNode1, syn, registry_count, []),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, node()]),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode1]),
+    0 = rpc:call(SlaveNode1, syn, registry_count, [default, SlaveNode2]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, []),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, node()]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode1]),
+    0 = rpc:call(SlaveNode2, syn, registry_count, [default, SlaveNode2]),
+
+    %% process alive (discarded process does not get killed with a custom handler)
+    syn_test_suite_helper:assert_wait(
+        true,
+        fun() -> rpc:call(SlaveNode1, erlang, is_process_alive, [PidOn1]) end
+    ),
+    syn_test_suite_helper:assert_wait(
+        true,
+        fun() -> rpc:call(SlaveNode2, erlang, is_process_alive, [PidOn2]) end
     ).
 
 %% ===================================================================

+ 5 - 1
test/syn_test_event_handler_resolution.erl

@@ -41,4 +41,8 @@ resolve_registry_conflict(custom_scope_bc, _Name, {Pid1, keepthis, _Time1}, {_Pi
 resolve_registry_conflict(default, _Name, {_Pid1, _Meta1, _Time1}, {Pid2, keepthis, _Time2}) ->
     Pid2;
 resolve_registry_conflict(custom_scope_bc, _Name, {_Pid1, _Meta1, _Time1}, {Pid2, keepthis, _Time2}) ->
-    Pid2.
+    Pid2;
+resolve_registry_conflict(default, _Name, {Pid1, _Meta1, _Time1}, {_Pid2, _Meta2, _Time2}) ->
+    syn_test_suite_helper:start_process(node(Pid1));
+resolve_registry_conflict(default, _Name, {_Pid1, crash, _Time1}, {_Pid2, crash, _Time2}) ->
+    exit(self(), syn_test_crash).