@@ -769,3 +769,185 @@ TEST(ReplicaSetMonitorTests, OutOfBandFailedHost) {
769
769
}
770
770
}
771
771
}
772
+
773
+ // Newly elected primary with electionId >= maximum electionId seen by the Refresher
774
+ TEST (ReplicaSetMonitorTests, NewPrimaryWithMaxElectionId) {
775
+ SetStatePtr state = boost::make_shared<SetState>(" name" , basicSeedsSet);
776
+ Refresher refresher (state);
777
+
778
+ set<HostAndPort> seen;
779
+
780
+ // get all hosts to contact first
781
+ for (size_t i = 0 ; i != basicSeeds.size (); ++i) {
782
+ NextStep ns = refresher.getNextStep ();
783
+ ASSERT_EQUALS (ns.step , NextStep::CONTACT_HOST);
784
+ ASSERT (basicSeedsSet.count (ns.host ));
785
+ ASSERT (!seen.count (ns.host ));
786
+ seen.insert (ns.host );
787
+ }
788
+
789
+ const ReadPreferenceSetting primaryOnly (ReadPreference_PrimaryOnly, TagSet ());
790
+
791
+ // mock all replies
792
+ for (size_t i = 0 ; i != basicSeeds.size (); ++i) {
793
+ // All hosts to talk to are already dispatched, but no reply has been received
794
+ NextStep ns = refresher.getNextStep ();
795
+ ASSERT_EQUALS (ns.step , NextStep::WAIT);
796
+ ASSERT (ns.host .empty ());
797
+
798
+ refresher.receivedIsMaster (basicSeeds[i],
799
+ -1 ,
800
+ BSON (" setName" << " name"
801
+ << " ismaster" << true
802
+ << " secondary" << false
803
+ << " hosts" << BSON_ARRAY (" a" << " b" << " c" )
804
+ << " electionId" << OID::gen ()
805
+ << " ok" << true ));
806
+
807
+ // Ensure the set primary is the host we just got a reply from
808
+ HostAndPort currentPrimary = state->getMatchingHost (primaryOnly);
809
+ ASSERT_EQUALS (currentPrimary.host (), basicSeeds[i].host ());
810
+ ASSERT_EQUALS (state->nodes .size (), basicSeeds.size ());
811
+
812
+ // Check the state of each individual node
813
+ for (size_t j = 0 ; j != basicSeeds.size (); ++j) {
814
+ Node* node = state->findNode (basicSeeds[j]);
815
+ ASSERT (node);
816
+ ASSERT_EQUALS (node->host .toString (), basicSeeds[j].toString ());
817
+ ASSERT_EQUALS (node->isUp , j <= i);
818
+ ASSERT_EQUALS (node->isMaster , j == i);
819
+ ASSERT (node->tags .isEmpty ());
820
+ }
821
+ }
822
+
823
+ // Now all hosts have returned data
824
+ NextStep ns = refresher.getNextStep ();
825
+ ASSERT_EQUALS (ns.step , NextStep::DONE);
826
+ ASSERT (ns.host .empty ());
827
+ }
828
+
829
+ // Ignore electionId of secondaries
830
+ TEST (ReplicaSetMonitorTests, IgnoreElectionIdFromSecondaries) {
831
+ SetStatePtr state = boost::make_shared<SetState>(" name" , basicSeedsSet);
832
+ Refresher refresher (state);
833
+
834
+ set<HostAndPort> seen;
835
+
836
+ const OID primaryElectionId = OID::gen ();
837
+
838
+ // mock all replies
839
+ for (size_t i = 0 ; i != basicSeeds.size (); ++i) {
840
+ NextStep ns = refresher.getNextStep ();
841
+ ASSERT_EQUALS (ns.step , NextStep::CONTACT_HOST);
842
+ ASSERT (basicSeedsSet.count (ns.host ));
843
+ ASSERT (!seen.count (ns.host ));
844
+ seen.insert (ns.host );
845
+
846
+ // mock a reply
847
+ const bool primary = ns.host .host () == " a" ;
848
+ refresher.receivedIsMaster (ns.host ,
849
+ -1 ,
850
+ BSON (" setName" << " name"
851
+ << " ismaster" << primary
852
+ << " secondary" << !primary
853
+ << " electionId" << (primary ?
854
+ primaryElectionId : OID::gen ())
855
+ << " hosts" << BSON_ARRAY (" a" << " b" << " c" )
856
+ << " ok" << true ));
857
+ }
858
+
859
+ // check that the SetState's maxElectionId == primary's electionId
860
+ ASSERT_EQUALS (state->maxElectionId , primaryElectionId);
861
+
862
+ // Now all hosts have returned data
863
+ NextStep ns = refresher.getNextStep ();
864
+ ASSERT_EQUALS (ns.step , NextStep::DONE);
865
+ ASSERT (ns.host .empty ());
866
+ }
867
+
868
+ // Stale Primary with obsolete electionId
869
+ TEST (ReplicaSetMonitorTests, StalePrimaryWithObsoleteElectionId) {
870
+ SetStatePtr state = boost::make_shared<SetState>(" name" , basicSeedsSet);
871
+ Refresher refresher (state);
872
+
873
+ const OID firstElectionId = OID::gen ();
874
+ const OID secondElectionId = OID::gen ();
875
+
876
+ set<HostAndPort> seen;
877
+
878
+ // contact first host claiming to be primary with greater electionId
879
+ {
880
+ NextStep ns = refresher.getNextStep ();
881
+ ASSERT_EQUALS (ns.step , NextStep::CONTACT_HOST);
882
+ ASSERT (basicSeedsSet.count (ns.host ));
883
+ ASSERT (!seen.count (ns.host ));
884
+ seen.insert (ns.host );
885
+
886
+ refresher.receivedIsMaster (ns.host ,
887
+ -1 ,
888
+ BSON (" setName" << " name"
889
+ << " ismaster" << true
890
+ << " secondary" << false
891
+ << " electionId" << secondElectionId
892
+ << " hosts" << BSON_ARRAY (" a" << " b" << " c" )
893
+ << " ok" << true ));
894
+
895
+ Node* node = state->findNode (ns.host );
896
+ ASSERT (node);
897
+ ASSERT_TRUE (node->isMaster );
898
+ ASSERT_EQUALS (state->maxElectionId , secondElectionId);
899
+ }
900
+
901
+ // contact second host claiming to be primary with smaller electionId
902
+ {
903
+ NextStep ns = refresher.getNextStep ();
904
+ ASSERT_EQUALS (ns.step , NextStep::CONTACT_HOST);
905
+ ASSERT (basicSeedsSet.count (ns.host ));
906
+ ASSERT (!seen.count (ns.host ));
907
+ seen.insert (ns.host );
908
+
909
+ refresher.receivedIsMaster (ns.host ,
910
+ -1 ,
911
+ BSON (" setName" << " name"
912
+ << " ismaster" << true
913
+ << " secondary" << false
914
+ << " electionId" << firstElectionId
915
+ << " hosts" << BSON_ARRAY (" a" << " b" << " c" )
916
+ << " ok" << true ));
917
+
918
+ Node* node = state->findNode (ns.host );
919
+ ASSERT (node);
920
+ // The SetState shouldn't see this host as master
921
+ ASSERT_FALSE (node->isMaster );
922
+ // the max electionId should remain the same
923
+ ASSERT_EQUALS (state->maxElectionId , secondElectionId);
924
+ }
925
+
926
+ // third host is a secondary
927
+ {
928
+ NextStep ns = refresher.getNextStep ();
929
+ ASSERT_EQUALS (ns.step , NextStep::CONTACT_HOST);
930
+ ASSERT (basicSeedsSet.count (ns.host ));
931
+ ASSERT (!seen.count (ns.host ));
932
+ seen.insert (ns.host );
933
+
934
+ refresher.receivedIsMaster (ns.host ,
935
+ -1 ,
936
+ BSON (" setName" << " name"
937
+ << " ismaster" << false
938
+ << " secondary" << true
939
+ << " hosts" << BSON_ARRAY (" a" << " b" << " c" )
940
+ << " ok" << true ));
941
+
942
+ Node* node = state->findNode (ns.host );
943
+ ASSERT (node);
944
+ ASSERT_FALSE (node->isMaster );
945
+ // the max electionId should remain the same
946
+ ASSERT_EQUALS (state->maxElectionId , secondElectionId);
947
+ }
948
+
949
+ // Now all hosts have returned data
950
+ NextStep ns = refresher.getNextStep ();
951
+ ASSERT_EQUALS (ns.step , NextStep::DONE);
952
+ ASSERT (ns.host .empty ());
953
+ }
0 commit comments