@@ -48,6 +48,7 @@ all_tests() ->
4848 add_member_without_quorum ,
4949 force_start_follower_as_single_member ,
5050 force_start_follower_as_single_member_nonvoter ,
51+ force_start_nonvoter_as_single_member ,
5152 initial_members_query
5253 ].
5354
@@ -784,30 +785,80 @@ force_start_follower_as_single_member_nonvoter(Config) ->
784785 ServerId4 = ? config (server_id4 , Config ),
785786 UId4 = ? config (uid4 , Config ),
786787 Conf4 = conf (ClusterName , UId4 , ServerId4 , PrivDir , [ServerId3 ]),
787- {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => promotable , uid => << " test4 " >> }),
788+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => promotable , uid => UId4 }),
788789 % % the membership has changed but member not running yet
789790 % % it is nonvoter and does not affect quorum size
790791 {ok , _ , _ } = ra :process_command (ServerId3 , {enq , banana }),
791792 % % start new member
792- ok = ra :start_server (? SYS , Conf4 #{membership => promotable , uid => << " test4 " >> }),
793+ ok = ra :start_server (? SYS , Conf4 #{membership => promotable , uid => UId4 }),
793794 {ok , _ , ServerId3 } = ra :members (ServerId4 ),
794795 ok = enqueue (ServerId3 , msg3 ),
795796
796797 % % add a non-voter member
797798 ServerId5 = ? config (server_id5 , Config ),
798799 UId5 = ? config (uid5 , Config ),
799800 Conf5 = conf (ClusterName , UId5 , ServerId5 , PrivDir , [ServerId3 ]),
800- {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId5 , membership => non_voter , uid => << " test5 " >> }),
801+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId5 , membership => non_voter , uid => UId5 }),
801802 % % the membership has changed but member not running yet
802803 % % it is nonvoter and does not affect quorum size
803804 {ok , _ , _ } = ra :process_command (ServerId3 , {enq , banana }),
804805 % % start new member
805- ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => << " test5 " >> }),
806+ ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => UId5 }),
806807 {ok , _ , ServerId3 } = ra :members (ServerId5 ),
807808 ok = enqueue (ServerId3 , msg4 ),
808809
809810 ok .
810811
812+ force_start_nonvoter_as_single_member (Config ) ->
813+ ok = logger :set_primary_config (level , all ),
814+ ClusterName = ? config (cluster_name , Config ),
815+ PrivDir = ? config (priv_dir , Config ),
816+ ServerId1 = ? config (server_id , Config ),
817+ ServerId2 = ? config (server_id2 , Config ),
818+ ServerId3 = ? config (server_id3 , Config ),
819+ InitialCluster = [ServerId1 , ServerId2 , ServerId3 ],
820+ ok = start_cluster (ClusterName , InitialCluster ),
821+ timer :sleep (100 ),
822+
823+ ServerId4 = ? config (server_id4 , Config ),
824+ UId4 = ? config (uid4 , Config ),
825+ Conf4 = conf (ClusterName , UId4 , ServerId4 , PrivDir , InitialCluster ),
826+ {ok , _ , _ } = ra :add_member (ServerId3 , #{id => ServerId4 , membership => non_voter , uid => UId4 }),
827+ ok = ra :start_server (? SYS , Conf4 #{membership => non_voter , uid => UId4 }),
828+
829+ % % stop voters to simulate permanent outage
830+ ok = ra :stop_server (? SYS , ServerId1 ),
831+ ok = ra :stop_server (? SYS , ServerId2 ),
832+ ok = ra :stop_server (? SYS , ServerId3 ),
833+ timer :sleep (100 ),
834+
835+ % % force the remaining node to change it's membership
836+ ok = ra_server_proc :force_shrink_members_to_current_member (ServerId4 ),
837+ {ok , [_ ], ServerId4 } = ra :members (ServerId4 ),
838+ ok = enqueue (ServerId4 , msg1 ),
839+
840+ % % test that it works after restart
841+ ok = ra :stop_server (? SYS , ServerId4 ),
842+ ok = ra :restart_server (? SYS , ServerId4 ),
843+ {ok , [_ ], ServerId4 } = ra :members (ServerId4 ),
844+ ok = enqueue (ServerId4 , msg2 ),
845+
846+
847+ % % add a non-voter member
848+ ServerId5 = ? config (server_id5 , Config ),
849+ UId5 = ? config (uid5 , Config ),
850+ Conf5 = conf (ClusterName , UId5 , ServerId5 , PrivDir , [ServerId4 ]),
851+ {ok , _ , _ } = ra :add_member (ServerId4 , #{id => ServerId5 , membership => non_voter , uid => UId5 }),
852+ % % the membership has changed but member not running yet
853+ % % it is nonvoter and does not affect quorum size
854+ ok = enqueue (ServerId4 , msg3 ),
855+ % % start new member
856+ ok = ra :start_server (? SYS , Conf5 #{membership => non_voter , uid => UId5 }),
857+ {ok , _ , ServerId4 } = ra :members (ServerId5 ),
858+ ok = enqueue (ServerId4 , msg4 ),
859+
860+ ok .
861+
811862initial_members_query (Config ) ->
812863 ok = logger :set_primary_config (level , all ),
813864 % % ra:start_server should fail if the node already exists
0 commit comments