summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2014-08-14 19:26:40 -0400
committerSpencer T Brody <spencer@mongodb.com>2014-08-18 11:46:57 -0400
commit945a11a2a07c2b5c6c1479880a415fb48a99836f (patch)
tree9892a12cba0b4071175fc7ab605c4cc99ad85733 /src
parente970e918c5300a13360edb57a88871b02dbe5982 (diff)
downloadmongo-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.cpp3
-rw-r--r--src/mongo/bson/optime.h2
-rw-r--r--src/mongo/db/db.cpp2
-rw-r--r--src/mongo/db/repl/member_heartbeat_data.cpp21
-rw-r--r--src/mongo/db/repl/repl_coordinator_impl_test.cpp122
-rw-r--r--src/mongo/db/repl/topology_coordinator_impl_test.cpp119
-rw-r--r--src/mongo/util/time_support.cpp4
-rw-r--r--src/mongo/util/time_support.h2
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);