summaryrefslogtreecommitdiff
path: root/src/mongo/client/dbclient_rs_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/client/dbclient_rs_test.cpp')
-rw-r--r--src/mongo/client/dbclient_rs_test.cpp405
1 files changed, 374 insertions, 31 deletions
diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp
index 19e94a0fc9f..ccb7b71063e 100644
--- a/src/mongo/client/dbclient_rs_test.cpp
+++ b/src/mongo/client/dbclient_rs_test.cpp
@@ -15,7 +15,8 @@
*/
/**
- * This file contains tests for DBClientReplicaSet.
+ * This file contains tests for DBClientReplicaSet. The tests mocks the servers
+ * the DBClientReplicaSet talks to, so the tests only covers the client side logic.
*/
#include "mongo/bson/bson_field.h"
@@ -25,35 +26,13 @@
#include "mongo/dbtests/mock/mock_conn_registry.h"
#include "mongo/dbtests/mock/mock_replica_set.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/assert_util.h"
#include <map>
#include <memory>
#include <string>
#include <vector>
-using std::auto_ptr;
-using std::map;
-using std::make_pair;
-using std::pair;
-using std::string;
-using std::vector;
-using boost::scoped_ptr;
-
-using mongo::BSONField;
-using mongo::BSONObj;
-using mongo::BSONArray;
-using mongo::BSONElement;
-using mongo::ConnectionString;
-using mongo::DBClientCursor;
-using mongo::DBClientReplicaSet;
-using mongo::HostAndPort;
-using mongo::MockReplicaSet;
-using mongo::Query;
-using mongo::ReadPreference;
-using mongo::ReplicaSetMonitor;
-using mongo::ScopedDbConnection;
-using mongo::TagSet;
-
namespace mongo {
// Symbols defined to build the binary correctly.
CmdLine cmdLine;
@@ -73,16 +52,373 @@ namespace mongo {
}
}
-namespace mongo_test {
+namespace {
+ using boost::scoped_ptr;
+ using std::auto_ptr;
+ using std::map;
+ using std::make_pair;
+ using std::pair;
+ using std::string;
+ using std::vector;
+
+ using mongo::AssertionException;
+ using mongo::BSONArray;
+ using mongo::BSONElement;
+ using mongo::BSONField;
+ using mongo::BSONObj;
+ using mongo::ConnectionString;
+ using mongo::DBClientCursor;
+ using mongo::DBClientReplicaSet;
+ using mongo::HostAndPort;
+ using mongo::HostField;
+ using mongo::IdentityNS;
+ using mongo::MockReplicaSet;
+ using mongo::Query;
+ using mongo::ReadPreference;
+ using mongo::ReplicaSetMonitor;
+ using mongo::ScopedDbConnection;
+ using mongo::TagSet;
+
+ /**
+ * Basic fixture with one primary and one secondary.
+ */
+ class BasicRS: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(BasicRS, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ /**
+ * Setup for 2 member replica set will all of the nodes down.
+ */
+ class AllNodesDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+
+ vector<HostAndPort> hostList(_replSet->getHosts());
+ for (vector<HostAndPort>::const_iterator iter = hostList.begin();
+ iter != hostList.end(); ++iter) {
+ _replSet->kill(iter->toString(true));
+ }
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(AllNodesDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ /**
+ * Setup for 2 member replica set with the primary down.
+ */
+ class PrimaryDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+ _replSet->kill(_replSet->getPrimary());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(PrimaryDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(PrimaryDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ /**
+ * Setup for 2 member replica set with the secondary down.
+ */
+ class SecondaryDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+
+ _replSet->kill(_replSet->getSecondaries().front());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(SecondaryDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(SecondaryDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
/**
* Warning: Tests running this fixture cannot be run in parallel with other tests
* that uses ConnectionString::setConnectionHook
*/
class TaggedFiveMemberRS: public mongo::unittest::Test {
protected:
- static const string IdentityNS;
- static const BSONField<string> HostField;
-
void setUp() {
_replSet.reset(new MockReplicaSet("test", 5));
_originalConnectionHook = ConnectionString::getConnectionHook();
@@ -153,6 +489,8 @@ namespace mongo_test {
ConnectionString::setConnectionHook(_originalConnectionHook);
ReplicaSetMonitor::remove(_replSet->getSetName(), true);
_replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
mongo::ScopedDbConnection::clearPool();
}
@@ -165,9 +503,6 @@ namespace mongo_test {
boost::scoped_ptr<MockReplicaSet> _replSet;
};
- const string TaggedFiveMemberRS::IdentityNS("local.me");
- const BSONField<string> TaggedFiveMemberRS::HostField("host", "bad");
-
TEST_F(TaggedFiveMemberRS, ConnShouldPinIfSameSettings) {
MockReplicaSet* replSet = getReplSet();
vector<HostAndPort> seedList;
@@ -179,6 +514,8 @@ namespace mongo_test {
{
Query query;
query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -205,6 +542,8 @@ namespace mongo_test {
{
Query query;
query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -233,6 +572,8 @@ namespace mongo_test {
Query query;
query.readPref(mongo::ReadPreference_SecondaryPreferred,
BSON_ARRAY(BSON("dc" << "sf")));
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -261,6 +602,8 @@ namespace mongo_test {
string dest;
mongo::DBClientConnection& secConn = replConn.slaveConn();
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = secConn.query(IdentityNS, Query());
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();