diff options
author | Spencer T Brody <spencer@mongodb.com> | 2014-08-14 19:26:40 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@mongodb.com> | 2014-08-18 11:46:57 -0400 |
commit | 945a11a2a07c2b5c6c1479880a415fb48a99836f (patch) | |
tree | 9892a12cba0b4071175fc7ab605c4cc99ad85733 /src | |
parent | e970e918c5300a13360edb57a88871b02dbe5982 (diff) | |
download | mongo-945a11a2a07c2b5c6c1479880a415fb48a99836f.tar.gz |
SERVER-14938 Move replSetGetStatus unit test from a repl coordinator to a topology coordinator test
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/bson/optime.cpp | 3 | ||||
-rw-r--r-- | src/mongo/bson/optime.h | 2 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/member_heartbeat_data.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_coordinator_impl_test.cpp | 122 | ||||
-rw-r--r-- | src/mongo/db/repl/topology_coordinator_impl_test.cpp | 119 | ||||
-rw-r--r-- | src/mongo/util/time_support.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/time_support.h | 2 |
8 files changed, 141 insertions, 134 deletions
diff --git a/src/mongo/bson/optime.cpp b/src/mongo/bson/optime.cpp index b79750b5544..e81483acb88 100644 --- a/src/mongo/bson/optime.cpp +++ b/src/mongo/bson/optime.cpp @@ -42,4 +42,7 @@ namespace mongo { return OpTime(t, i); } + std::ostream& operator<<(std::ostream &s, const OpTime &ot) { + return s << ot.toString(); + } } diff --git a/src/mongo/bson/optime.h b/src/mongo/bson/optime.h index 099520b6c41..015fedcc6a7 100644 --- a/src/mongo/bson/optime.h +++ b/src/mongo/bson/optime.h @@ -144,4 +144,6 @@ namespace mongo { }; #pragma pack() + std::ostream& operator<<(std::ostream &s, const OpTime &ot); + } // namespace mongo diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index a801bb63f69..e4df641b393 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -237,7 +237,7 @@ namespace mongo { static void logStartup() { BSONObjBuilder toLog; stringstream id; - id << getHostNameCached() << "-" << jsTime(); + id << getHostNameCached() << "-" << jsTime().asInt64(); toLog.append( "_id", id.str() ); toLog.append( "hostname", getHostNameCached() ); diff --git a/src/mongo/db/repl/member_heartbeat_data.cpp b/src/mongo/db/repl/member_heartbeat_data.cpp index 2214a96f6fd..52d1100ef91 100644 --- a/src/mongo/db/repl/member_heartbeat_data.cpp +++ b/src/mongo/db/repl/member_heartbeat_data.cpp @@ -65,26 +65,27 @@ namespace repl { OpTime optime, const std::string& syncingTo, const std::string& heartbeatMessage) { - _authIssue = false; + _state = state; _health = 1; - + if (_upSince == 0) { + _upSince = now; + } _lastHeartbeat = now; - _upSince = now; - _state = state; - _electionTime = electionTime; - _opTime = optime; - _syncSource = syncingTo; _lastHeartbeatMsg = heartbeatMessage; + _syncSource = syncingTo; + _opTime = optime; + _authIssue = false; + _electionTime = electionTime; } void MemberHeartbeatData::setDownValues(Date_t now, const std::string& heartbeatMessage) { - _authIssue = false; - _health = 0; _state = MemberState::RS_DOWN; - + _health = 0; + _upSince = 0; _lastHeartbeat = now; _lastHeartbeatMsg = heartbeatMessage; + _authIssue = false; } } // namespace repl diff --git a/src/mongo/db/repl/repl_coordinator_impl_test.cpp b/src/mongo/db/repl/repl_coordinator_impl_test.cpp index 37524ff6902..c0aa6d03490 100644 --- a/src/mongo/db/repl/repl_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/repl_coordinator_impl_test.cpp @@ -50,18 +50,6 @@ #include "mongo/util/log.h" namespace mongo { - - // So that you can ASSERT_EQUALS two OpTimes - std::ostream& operator<<( std::ostream &s, const OpTime &ot ) { - s << ot.toString(); - return s; - } - // So that you can ASSERT_EQUALS two Date_ts - std::ostream& operator<<( std::ostream &s, const Date_t &t ) { - s << t.toString(); - return s; - } - namespace repl { namespace { @@ -692,116 +680,6 @@ namespace { ASSERT_EQUALS(3U, rids.size()); // Make sure we saw all 3 nodes } - TEST_F(ReplCoordTest, TestReplSetGetStatus) { - // This test starts by configuring a ReplicationCoordinator as a member of a 4 node replica - // set, with each node in a different state. - // The first node is DOWN, as if we tried heartbeating them and it failed in some way. - // The second node is in state SECONDARY, as if we've received a valid heartbeat from them. - // The third node is in state UNKNOWN, as if we've not yet had any heartbeating activity - // with them yet. The fourth node is PRIMARY and corresponds to ourself, which gets its - // information for replSetGetStatus from a different source than the nodes that aren't - // ourself. After this setup, we call replSetGetStatus and make sure that the fields - // returned for each member match our expectations. - init("mySet/test1:1234,test2:1234,test3:1234"); - assertStartSuccess( - BSON("_id" << "mySet" << - "version" << 1 << - "members" << BSON_ARRAY(BSON("_id" << 0 << "host" << "test0:1234") << - BSON("_id" << 1 << "host" << "test1:1234") << - BSON("_id" << 2 << "host" << "test2:1234") << - BSON("_id" << 3 << "host" << "test3:1234"))), - HostAndPort("test3", 1234)); - Date_t startupTime(curTimeMillis64()); - OpTime electionTime(1, 2); - OpTime oplogProgress(3, 4); - ReplicationExecutor::CallbackData cbd(NULL, - ReplicationExecutor::CallbackHandle(), - Status::OK()); - - // Now that the replica set is setup, put the members into the states we want them in. - MemberHeartbeatData member1hb(0); - member1hb.setDownValues(startupTime, ""); - getTopoCoord().updateHeartbeatData(startupTime, member1hb, 0, oplogProgress); - MemberHeartbeatData member2hb(1); - member2hb.setUpValues( - startupTime, MemberState::RS_SECONDARY, electionTime, oplogProgress, "", "READY"); - getTopoCoord().updateHeartbeatData(startupTime, member2hb, 1, oplogProgress); - sleepsecs(1); // so uptime will be non-zero - - getTopoCoord()._changeMemberState(MemberState::RS_PRIMARY); - OperationContextNoop txn; - getReplCoord()->setLastOptime(&txn, getReplCoord()->getMyRID(&txn), oplogProgress); - - // Now node 0 is down, node 1 is up, and for node 2 we have no heartbeat data yet. - BSONObjBuilder statusBuilder; - ASSERT_OK(getReplCoord()->processReplSetGetStatus(&statusBuilder)); - BSONObj rsStatus = statusBuilder.obj(); - - // Test results for all non-self members - ASSERT_EQUALS("mySet", rsStatus["set"].String()); - ASSERT_LESS_THAN(startupTime.asInt64(), rsStatus["date"].Date().asInt64()); - std::vector<BSONElement> memberArray = rsStatus["members"].Array(); - ASSERT_EQUALS(4U, memberArray.size()); - BSONObj member0Status = memberArray[0].Obj(); - BSONObj member1Status = memberArray[1].Obj(); - BSONObj member2Status = memberArray[2].Obj(); - - // Test member 0, the node that's DOWN - ASSERT_EQUALS(0, member0Status["_id"].Int()); - ASSERT_EQUALS("test0:1234", member0Status["name"].String()); - ASSERT_EQUALS(0, member0Status["health"].Double()); - ASSERT_EQUALS(MemberState::RS_DOWN, member0Status["state"].Int()); - ASSERT_EQUALS("(not reachable/healthy)", member0Status["stateStr"].String()); - ASSERT_EQUALS(0, member0Status["uptime"].Int()); - ASSERT_EQUALS(OpTime(), OpTime(member0Status["optime"].timestampValue())); - ASSERT_EQUALS(OpTime().asDate(), member0Status["optimeDate"].Date().millis); - ASSERT_EQUALS(startupTime, member0Status["lastHeartbeat"].Date()); - ASSERT_EQUALS(Date_t(), member0Status["lastHeartbeatRecv"].Date()); - - // Test member 1, the node that's SECONDARY - ASSERT_EQUALS(1, member1Status["_id"].Int()); - ASSERT_EQUALS("test1:1234", member1Status["name"].String()); - ASSERT_EQUALS(1, member1Status["health"].Double()); - ASSERT_EQUALS(MemberState::RS_SECONDARY, member1Status["state"].Int()); - ASSERT_EQUALS(MemberState(MemberState::RS_SECONDARY).toString(), - member1Status["stateStr"].String()); - ASSERT_LESS_THAN_OR_EQUALS(1, member1Status["uptime"].Int()); - ASSERT_EQUALS(oplogProgress, OpTime(member1Status["optime"].timestampValue())); - ASSERT_EQUALS(oplogProgress.asDate(), member1Status["optimeDate"].Date().millis); - ASSERT_EQUALS(startupTime, member1Status["lastHeartbeat"].Date()); - ASSERT_EQUALS(Date_t(), member1Status["lastHeartbeatRecv"].Date()); - ASSERT_EQUALS("READY", member1Status["lastHeartbeatMessage"].String()); - - // Test member 2, the node that's UNKNOWN - ASSERT_EQUALS(2, member2Status["_id"].Int()); - ASSERT_EQUALS("test2:1234", member2Status["name"].String()); - ASSERT_EQUALS(-1, member2Status["health"].Double()); - ASSERT_EQUALS(MemberState::RS_UNKNOWN, member2Status["state"].Int()); - ASSERT_EQUALS(MemberState(MemberState::RS_UNKNOWN).toString(), - member2Status["stateStr"].String()); - ASSERT_FALSE(member2Status.hasField("uptime")); - ASSERT_FALSE(member2Status.hasField("optime")); - ASSERT_FALSE(member2Status.hasField("optimeDate")); - ASSERT_FALSE(member2Status.hasField("lastHearbeat")); - ASSERT_FALSE(member2Status.hasField("lastHearbeatRecv")); - - // Now test results for ourself, the PRIMARY - ASSERT_EQUALS(MemberState::RS_PRIMARY, rsStatus["myState"].Int()); - BSONObj selfStatus = memberArray[3].Obj(); - ASSERT_TRUE(selfStatus["self"].Bool()); - ASSERT_EQUALS(3, selfStatus["_id"].Int()); - ASSERT_EQUALS("test3:1234", selfStatus["name"].String()); - ASSERT_EQUALS(1, selfStatus["health"].Double()); - ASSERT_EQUALS(MemberState::RS_PRIMARY, selfStatus["state"].Int()); - ASSERT_EQUALS(MemberState(MemberState::RS_PRIMARY).toString(), - selfStatus["stateStr"].String()); - ASSERT_LESS_THAN_OR_EQUALS(1, selfStatus["uptime"].Int()); - ASSERT_EQUALS(oplogProgress, OpTime(selfStatus["optime"].timestampValue())); - ASSERT_EQUALS(oplogProgress.asDate(), selfStatus["optimeDate"].Date().millis); - - // TODO(spencer): Test electionTime and pingMs are set properly - } - TEST_F(ReplCoordTest, TestGetElectionId) { init("mySet/test1:1234,test2:1234,test3:1234"); assertStartSuccess( diff --git a/src/mongo/db/repl/topology_coordinator_impl_test.cpp b/src/mongo/db/repl/topology_coordinator_impl_test.cpp index 49ab02d9b1b..e0967412bcb 100644 --- a/src/mongo/db/repl/topology_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_impl_test.cpp @@ -37,7 +37,6 @@ namespace mongo { namespace repl { - namespace { TEST(TopologyCoordinator, ChooseSyncSourceBasic) { @@ -387,6 +386,124 @@ namespace { ASSERT_EQUALS(topocoord.getSyncSourceAddress(),HostAndPort("h3")); } + TEST(TopologyCoordinator, ReplSetGetStatus) { + // This test starts by configuring a TopologyCoordinator as a member of a 4 node replica + // set, with each node in a different state. + // The first node is DOWN, as if we tried heartbeating them and it failed in some way. + // The second node is in state SECONDARY, as if we've received a valid heartbeat from them. + // The third node is in state UNKNOWN, as if we've not yet had any heartbeating activity + // with them yet. The fourth node is PRIMARY and corresponds to ourself, which gets its + // information for replSetGetStatus from a different source than the nodes that aren't + // ourself. After this setup, we call prepareStatusResponse and make sure that the fields + // returned for each member match our expectations. + Date_t startupTime(100); + Date_t heartbeatTime = 5000; + Seconds uptimeSecs(10); + Date_t curTime = heartbeatTime + uptimeSecs.total_milliseconds(); + OpTime electionTime(1, 2); + OpTime oplogProgress(3, 4); + ReplicationExecutor::CallbackHandle cbh; + ReplicationExecutor::CallbackData cbData(NULL, + cbh, + Status::OK()); + TopologyCoordinatorImpl topocoord((Seconds(999))); + + ReplicaSetConfig config; + ASSERT_OK(config.initialize( + BSON("_id" << "mySet" << + "version" << 1 << + "members" << BSON_ARRAY(BSON("_id" << 0 << "host" << "test0:1234") << + BSON("_id" << 1 << "host" << "test1:1234") << + BSON("_id" << 2 << "host" << "test2:1234") << + BSON("_id" << 3 << "host" << "test3:1234"))))); + topocoord.updateConfig(cbData, config, 3, startupTime + 1, OpTime(0,0)); + + // Now that the replica set is setup, put the members into the states we want them in. + MemberHeartbeatData member0hb(0); + member0hb.setDownValues(heartbeatTime, ""); + topocoord.updateHeartbeatData(heartbeatTime, member0hb, 0, oplogProgress); + MemberHeartbeatData member1hb(1); + member1hb.setUpValues( + heartbeatTime, MemberState::RS_SECONDARY, electionTime, oplogProgress, "", "READY"); + topocoord.updateHeartbeatData(startupTime, member1hb, 1, oplogProgress); + topocoord._changeMemberState(MemberState::RS_PRIMARY); + + // Now node 0 is down, node 1 is up, and for node 2 we have no heartbeat data yet. + BSONObjBuilder statusBuilder; + Status resultStatus(ErrorCodes::InternalError, "prepareStatusResponse didn't set result"); + topocoord.prepareStatusResponse(cbData, + curTime, + uptimeSecs.total_seconds(), + oplogProgress, + &statusBuilder, + &resultStatus); + ASSERT_OK(resultStatus); + BSONObj rsStatus = statusBuilder.obj(); + + // Test results for all non-self members + ASSERT_EQUALS("mySet", rsStatus["set"].String()); + ASSERT_EQUALS(curTime.asInt64(), rsStatus["date"].Date().asInt64()); + std::vector<BSONElement> memberArray = rsStatus["members"].Array(); + ASSERT_EQUALS(4U, memberArray.size()); + BSONObj member0Status = memberArray[0].Obj(); + BSONObj member1Status = memberArray[1].Obj(); + BSONObj member2Status = memberArray[2].Obj(); + + // Test member 0, the node that's DOWN + ASSERT_EQUALS(0, member0Status["_id"].Int()); + ASSERT_EQUALS("test0:1234", member0Status["name"].String()); + ASSERT_EQUALS(0, member0Status["health"].Double()); + ASSERT_EQUALS(MemberState::RS_DOWN, member0Status["state"].Int()); + ASSERT_EQUALS("(not reachable/healthy)", member0Status["stateStr"].String()); + ASSERT_EQUALS(0, member0Status["uptime"].Int()); + ASSERT_EQUALS(OpTime(), OpTime(member0Status["optime"].timestampValue())); + ASSERT_EQUALS(OpTime().asDate(), member0Status["optimeDate"].Date().millis); + ASSERT_EQUALS(heartbeatTime, member0Status["lastHeartbeat"].Date()); + ASSERT_EQUALS(Date_t(), member0Status["lastHeartbeatRecv"].Date()); + + // Test member 1, the node that's SECONDARY + ASSERT_EQUALS(1, member1Status["_id"].Int()); + ASSERT_EQUALS("test1:1234", member1Status["name"].String()); + ASSERT_EQUALS(1, member1Status["health"].Double()); + ASSERT_EQUALS(MemberState::RS_SECONDARY, member1Status["state"].Int()); + ASSERT_EQUALS(MemberState(MemberState::RS_SECONDARY).toString(), + member1Status["stateStr"].String()); + ASSERT_EQUALS(uptimeSecs.total_seconds(), member1Status["uptime"].Int()); + ASSERT_EQUALS(oplogProgress, OpTime(member1Status["optime"].timestampValue())); + ASSERT_EQUALS(oplogProgress.asDate(), member1Status["optimeDate"].Date().millis); + ASSERT_EQUALS(heartbeatTime, member1Status["lastHeartbeat"].Date()); + ASSERT_EQUALS(Date_t(), member1Status["lastHeartbeatRecv"].Date()); + ASSERT_EQUALS("READY", member1Status["lastHeartbeatMessage"].String()); + + // Test member 2, the node that's UNKNOWN + ASSERT_EQUALS(2, member2Status["_id"].Int()); + ASSERT_EQUALS("test2:1234", member2Status["name"].String()); + ASSERT_EQUALS(-1, member2Status["health"].Double()); + ASSERT_EQUALS(MemberState::RS_UNKNOWN, member2Status["state"].Int()); + ASSERT_EQUALS(MemberState(MemberState::RS_UNKNOWN).toString(), + member2Status["stateStr"].String()); + ASSERT_FALSE(member2Status.hasField("uptime")); + ASSERT_FALSE(member2Status.hasField("optime")); + ASSERT_FALSE(member2Status.hasField("optimeDate")); + ASSERT_FALSE(member2Status.hasField("lastHearbeat")); + ASSERT_FALSE(member2Status.hasField("lastHearbeatRecv")); + + // Now test results for ourself, the PRIMARY + ASSERT_EQUALS(MemberState::RS_PRIMARY, rsStatus["myState"].Int()); + BSONObj selfStatus = memberArray[3].Obj(); + ASSERT_TRUE(selfStatus["self"].Bool()); + ASSERT_EQUALS(3, selfStatus["_id"].Int()); + ASSERT_EQUALS("test3:1234", selfStatus["name"].String()); + ASSERT_EQUALS(1, selfStatus["health"].Double()); + ASSERT_EQUALS(MemberState::RS_PRIMARY, selfStatus["state"].Int()); + ASSERT_EQUALS(MemberState(MemberState::RS_PRIMARY).toString(), + selfStatus["stateStr"].String()); + ASSERT_EQUALS(uptimeSecs.total_seconds(), selfStatus["uptime"].Int()); + ASSERT_EQUALS(oplogProgress, OpTime(selfStatus["optime"].timestampValue())); + ASSERT_EQUALS(oplogProgress.asDate(), selfStatus["optimeDate"].Date().millis); + + // TODO(spencer): Test electionTime and pingMs are set properly + } } // namespace } // namespace repl diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index 24686de267c..5f817414e0a 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -70,6 +70,10 @@ namespace mongo { } } + std::ostream& operator<<(std::ostream &s, const Date_t &t) { + return s << t.toString(); + } + // jsTime_virtual_skew is just for testing. a test command manipulates it. long long jsTime_virtual_skew = 0; boost::thread_specific_ptr<long long> jsTime_virtual_thread_skew; diff --git a/src/mongo/util/time_support.h b/src/mongo/util/time_support.h index f7e62476eb8..c96a9793ac5 100644 --- a/src/mongo/util/time_support.h +++ b/src/mongo/util/time_support.h @@ -64,6 +64,8 @@ namespace mongo { bool isFormatable() const; }; + std::ostream& operator<<(std::ostream &s, const Date_t &t); + // uses ISO 8601 dates without trailing Z // colonsOk should be false when creating filenames std::string terseCurrentTime(bool colonsOk=true); |