diff options
Diffstat (limited to 'src/mongo/client/dbclient_rs_test.cpp')
| -rw-r--r-- | src/mongo/client/dbclient_rs_test.cpp | 405 |
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(); |
