Browse Source

Add PG tests for common operations.

Roberto Ostinelli 9 years ago
parent
commit
1d891b0659
1 changed files with 324 additions and 0 deletions
  1. 324 0
      test/syn_process_groups_SUITE.erl

+ 324 - 0
test/syn_process_groups_SUITE.erl

@@ -0,0 +1,324 @@
+%% ==========================================================================================================
+%% Syn - A global process registry.
+%%
+%% The MIT License (MIT)
+%%
+%% Copyright (c) 2016 Roberto Ostinelli <roberto@ostinelli.net> and Neato Robotics, Inc.
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% ==========================================================================================================
+-module(syn_process_groups_SUITE).
+
+%% callbacks
+-export([all/0]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([groups/0, init_per_group/2, end_per_group/2]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+%% tests
+-export([
+    single_node_leave/1,
+    single_node_kill/1,
+    single_node_publish/1
+]).
+-export([
+    two_nodes_kill/1,
+    two_nodes_publish/1
+]).
+
+%% internal
+-export([recipient_loop/1]).
+
+%% include
+-include_lib("common_test/include/ct.hrl").
+
+
+%% ===================================================================
+%% Callbacks
+%% ===================================================================
+
+%% -------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% -------------------------------------------------------------------
+all() ->
+    [
+%%        {group, single_node_process_groups},
+        {group, two_nodes_process_groups}
+    ].
+
+%% -------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%%			   repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% -------------------------------------------------------------------
+groups() ->
+    [
+        {single_node_process_groups, [shuffle], [
+            single_node_leave,
+            single_node_kill,
+            single_node_publish
+        ]},
+        {two_nodes_process_groups, [shuffle], [
+            two_nodes_kill,
+            two_nodes_publish
+        ]}
+    ].
+%% -------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%%				Config1 | {skip,Reason} |
+%%              {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% -------------------------------------------------------------------
+init_per_suite(Config) ->
+    %% config
+    [
+        {slave_node_short_name, syn_slave}
+        | Config
+    ].
+
+%% -------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% -------------------------------------------------------------------
+end_per_suite(_Config) -> ok.
+
+%% -------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%%				Config1 | {skip,Reason} |
+%%              {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% -------------------------------------------------------------------
+init_per_group(two_nodes_process_groups, Config) ->
+    %% start slave
+    SlaveNodeShortName = proplists:get_value(slave_node_short_name, Config),
+    {ok, SlaveNode} = syn_test_suite_helper:start_slave(SlaveNodeShortName),
+    %% config
+    [
+        {slave_node, SlaveNode}
+        | Config
+    ];
+init_per_group(_GroupName, Config) -> Config.
+
+%% -------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%%				void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% -------------------------------------------------------------------
+end_per_group(two_nodes_process_groups, Config) ->
+    %% get slave node name
+    SlaveNodeShortName = proplists:get_value(slave_node_short_name, Config),
+    %% stop slave
+    syn_test_suite_helper:stop_slave(SlaveNodeShortName);
+end_per_group(_GroupName, _Config) ->
+    ok.
+
+% ----------------------------------------------------------------------------------------------------------
+% Function: init_per_testcase(TestCase, Config0) ->
+%				Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+% TestCase = atom()
+% Config0 = Config1 = [tuple()]
+% Reason = term()
+% ----------------------------------------------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+    Config.
+
+% ----------------------------------------------------------------------------------------------------------
+% Function: end_per_testcase(TestCase, Config0) ->
+%				void() | {save_config,Config1} | {fail,Reason}
+% TestCase = atom()
+% Config0 = Config1 = [tuple()]
+% Reason = term()
+% ----------------------------------------------------------------------------------------------------------
+end_per_testcase(_TestCase, Config) ->
+    %% get slave
+    SlaveNode = proplists:get_value(slave_node, Config),
+    syn_test_suite_helper:clean_after_test(SlaveNode).
+
+%% ===================================================================
+%% Tests
+%% ===================================================================
+single_node_leave(_Config) ->
+    %% start
+    ok = syn:start(),
+    ok = syn:init(),
+    %% start process
+    Pid = syn_test_suite_helper:start_process(),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(Pid, <<"my pg">>),
+    %% join
+    ok = syn:join(<<"my pg">>, Pid),
+    %% retrieve
+    [Pid] = syn:get_members(<<"my pg">>),
+    true = syn:member(Pid, <<"my pg">>),
+    %% leave
+    ok = syn:leave(<<"my pg">>, Pid),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(Pid, <<"my pg">>),
+    %% kill process
+    syn_test_suite_helper:kill_process(Pid).
+
+single_node_kill(_Config) ->
+    %% start
+    ok = syn:start(),
+    ok = syn:init(),
+    %% start process
+    Pid = syn_test_suite_helper:start_process(),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(Pid, <<"my pg">>),
+    %% join
+    ok = syn:join(<<"my pg">>, Pid),
+    %% retrieve
+    [Pid] = syn:get_members(<<"my pg">>),
+    true = syn:member(Pid, <<"my pg">>),
+    %% kill process
+    syn_test_suite_helper:kill_process(Pid),
+    timer:sleep(100),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(Pid, <<"my pg">>).
+
+single_node_publish(_Config) ->
+    %% start
+    ok = syn:start(),
+    ok = syn:init(),
+    %% start process
+    ResultPid = self(),
+    F = fun() -> recipient_loop(ResultPid) end,
+    Pid1 = syn_test_suite_helper:start_process(F),
+    Pid2 = syn_test_suite_helper:start_process(F),
+    %% join
+    ok = syn:join(<<"my pg">>, Pid1),
+    ok = syn:join(<<"my pg">>, Pid2),
+    %% publish
+    syn:publish(<<"my pg">>, {test, message}),
+    %% check publish was received
+    receive
+        {received, Pid1, {test, message}} -> ok
+    after 2000 ->
+        ok = published_message_was_not_received_by_pid1
+    end,
+    receive
+        {received, Pid2, {test, message}} -> ok
+    after 2000 ->
+        ok = published_message_was_not_received_by_pid2
+    end,
+    %% kill processes
+    syn_test_suite_helper:kill_process(Pid1),
+    syn_test_suite_helper:kill_process(Pid2).
+
+two_nodes_kill(Config) ->
+    %% get slave
+    SlaveNode = proplists:get_value(slave_node, Config),
+    %% start
+    ok = syn:start(),
+    ok = syn:init(),
+    ok = rpc:call(SlaveNode, syn, start, []),
+    ok = rpc:call(SlaveNode, syn, init, []),
+    timer:sleep(100),
+    %% start processes
+    PidLocal = syn_test_suite_helper:start_process(),
+    PidSlave = syn_test_suite_helper:start_process(SlaveNode),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(PidLocal, <<"my pg">>),
+    false = syn:member(PidSlave, <<"my pg">>),
+    [] = rpc:call(SlaveNode, syn, get_members, [<<"my pg">>]),
+    false = rpc:call(SlaveNode, syn, member, [PidLocal, <<"my pg">>]),
+    false = rpc:call(SlaveNode, syn, member, [PidSlave, <<"my pg">>]),
+    %% register
+    ok = syn:join(<<"my pg">>, PidSlave),
+    ok = rpc:call(SlaveNode, syn, join, [<<"my pg">>, PidLocal]),
+    %% retrieve
+    2 = length(syn:get_members(<<"my pg">>)),
+    true = syn:member(PidLocal, <<"my pg">>),
+    true = syn:member(PidSlave, <<"my pg">>),
+    2 = length(rpc:call(SlaveNode, syn, get_members, [<<"my pg">>])),
+    true = rpc:call(SlaveNode, syn, member, [PidLocal, <<"my pg">>]),
+    true = rpc:call(SlaveNode, syn, member, [PidSlave, <<"my pg">>]),
+    %% kill processes
+    syn_test_suite_helper:kill_process(PidLocal),
+    syn_test_suite_helper:kill_process(PidSlave),
+    timer:sleep(100),
+    %% retrieve
+    [] = syn:get_members(<<"my pg">>),
+    false = syn:member(PidLocal, <<"my pg">>),
+    false = syn:member(PidSlave, <<"my pg">>),
+    [] = rpc:call(SlaveNode, syn, get_members, [<<"my pg">>]),
+    false = rpc:call(SlaveNode, syn, member, [PidLocal, <<"my pg">>]),
+    false = rpc:call(SlaveNode, syn, member, [PidSlave, <<"my pg">>]).
+
+two_nodes_publish(Config) ->
+    %% get slave
+    SlaveNode = proplists:get_value(slave_node, Config),
+    %% start
+    ok = syn:start(),
+    ok = syn:init(),
+    ok = rpc:call(SlaveNode, syn, start, []),
+    ok = rpc:call(SlaveNode, syn, init, []),
+    timer:sleep(100),
+    %% start process
+    ResultPid = self(),
+    F = fun() -> recipient_loop(ResultPid) end,
+    PidLocal = syn_test_suite_helper:start_process(F),
+    PidSlave = syn_test_suite_helper:start_process(SlaveNode, F),
+    %% register
+    ok = syn:join(<<"my pg">>, PidSlave),
+    ok = rpc:call(SlaveNode, syn, join, [<<"my pg">>, PidLocal]),
+    %% publish
+    syn:publish(<<"my pg">>, {test, message}),
+    %% check publish was received
+    receive
+        {received, PidLocal, {test, message}} -> ok
+    after 2000 ->
+        ok = published_message_was_not_received_by_pidlocal
+    end,
+    receive
+        {received, PidSlave, {test, message}} -> ok
+    after 2000 ->
+        ok = published_message_was_not_received_by_pidslave
+    end,
+    %% kill processes
+    syn_test_suite_helper:kill_process(PidLocal),
+    syn_test_suite_helper:kill_process(PidSlave).
+
+%% ===================================================================
+%% Internal
+%% ===================================================================
+recipient_loop(Pid) ->
+    receive
+        Message -> Pid ! {received, self(), Message}
+    end.