mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
Adding some pairing tests
This commit is contained in:
parent
932e7a3295
commit
243a3e6b2f
@ -119,6 +119,7 @@ public:
|
||||
BSONObj contains more details e.g.:
|
||||
{ "ismaster" : 1.0 , "msg" : "not paired" , "ok" : 1.0 }
|
||||
*/
|
||||
virtual
|
||||
BSONObj cmdIsMaster(bool& isMaster);
|
||||
};
|
||||
|
||||
@ -151,7 +152,8 @@ public:
|
||||
If autoReconnect is true, you can try to use the DBClientConnection even when
|
||||
false was returned -- it will try to connect again.
|
||||
*/
|
||||
bool connect(const char *serverHostname, string& errmsg);
|
||||
virtual
|
||||
bool connect(const char *serverHostname, string& errmsg);
|
||||
|
||||
/* send a query to the database.
|
||||
ns: namespace to query, format is <dbname>.<collectname>[.<collectname>]*
|
||||
@ -173,7 +175,8 @@ public:
|
||||
BSONObj *fieldsToReturn = 0, int queryOptions = 0);
|
||||
|
||||
/*throws AssertionException*/
|
||||
BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
|
||||
virtual
|
||||
BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
|
||||
};
|
||||
|
||||
/* Use this class to connect to a replica pair of servers. The class will manage
|
||||
|
@ -41,3 +41,5 @@ public:
|
||||
|
||||
Command(const char *_name);
|
||||
};
|
||||
|
||||
bool runCommandAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder);
|
||||
|
2
db/db.h
2
db/db.h
@ -14,6 +14,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../grid/message.h"
|
||||
|
||||
|
@ -16,7 +16,7 @@ OBJS=../stdafx.o ../util/sock.o ../grid/message.o ../util/mmap.o pdfile.o query.
|
||||
|
||||
DBGRID_OBJS=../stdafx.o json.o ../util/sock.o ../grid/message.o ../util/util.o jsobj.o ../client/dbclient.o ../dbgrid/dbgrid.o ../dbgrid/request.o ../client/connpool.o ../dbgrid/gridconfig.o commands.o ../dbgrid/dbgrid_commands.o ../dbgrid/griddatabase.o ../client/model.o ../util/background.o ../dbgrid/shard.o
|
||||
|
||||
DBTEST_OBJS= $(OBJS) ../dbtests/dbtests.o ../dbtests/btreetests.o
|
||||
DBTEST_OBJS= $(OBJS) ../dbtests/dbtests.o ../dbtests/btreetests.o ../dbtests/pairingtests.o
|
||||
|
||||
GPP = g++
|
||||
|
||||
|
@ -72,7 +72,7 @@ void ReplPair::arbitrate() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto_ptr<DBClientConnection> conn( new DBClientConnection() );
|
||||
auto_ptr<DBClientConnection> conn( newClientConnection() );
|
||||
string errmsg;
|
||||
if( !conn->connect(arbHost.c_str(), errmsg) ) {
|
||||
setMaster(State_CantArb, "can't connect to arb");
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "db.h"
|
||||
#include "../client/dbclient.h"
|
||||
|
||||
extern int port;
|
||||
extern const char *allDead;
|
||||
|
||||
@ -84,6 +87,11 @@ public:
|
||||
|
||||
/* peer unreachable, try our arbitrator */
|
||||
void arbitrate();
|
||||
|
||||
virtual
|
||||
DBClientConnection *newClientConnection() {
|
||||
return new DBClientConnection();
|
||||
}
|
||||
};
|
||||
|
||||
extern ReplPair *replPair;
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "../grid/message.h"
|
||||
#include "../db/commands.h"
|
||||
#include "../db/dbmessage.h"
|
||||
#include "../client/connpool.h"
|
||||
|
||||
@ -59,8 +60,6 @@ void getMore(Message& m, MessagingPort& p) {
|
||||
dbcon.done();
|
||||
}
|
||||
|
||||
bool runCommandAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder);
|
||||
|
||||
/* got query operation from a database */
|
||||
void queryOp(Message& m, MessagingPort& p) {
|
||||
DbMessage d(m);
|
||||
|
@ -67,6 +67,7 @@ int main( int argc, char** argv ) {
|
||||
UnitTest::Registry tests;
|
||||
|
||||
tests.add( btreeTests(), "btree" );
|
||||
tests.add( pairingTests(), "pairing" );
|
||||
|
||||
return tests.run( argc, argv );
|
||||
}
|
||||
|
@ -1,3 +1,23 @@
|
||||
// dbtests.h : Test suite generator headers.
|
||||
//
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unittest/UnitTest.hpp>
|
||||
|
||||
UnitTest::TestPtr btreeTests();
|
||||
UnitTest::TestPtr pairingTests();
|
||||
|
72
dbtests/mockdbclient.h
Normal file
72
dbtests/mockdbclient.h
Normal file
@ -0,0 +1,72 @@
|
||||
// mockdbclient.h - mocked out client for testing.
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../client/dbclient.h"
|
||||
#include "../db/commands.h"
|
||||
|
||||
class MockDBClientConnection : public DBClientConnection {
|
||||
public:
|
||||
MockDBClientConnection() : connect_() {}
|
||||
virtual
|
||||
BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) {
|
||||
return one_;
|
||||
}
|
||||
virtual
|
||||
bool connect(const char *serverHostname, string& errmsg) {
|
||||
return connect_;
|
||||
}
|
||||
virtual
|
||||
BSONObj cmdIsMaster(bool& isMaster) {
|
||||
return res_;
|
||||
}
|
||||
void one( const BSONObj &one ) { one_ = one; }
|
||||
void connect( bool val ) { connect_ = val; }
|
||||
void res( const BSONObj &val ) { res_ = val; }
|
||||
private:
|
||||
BSONObj one_;
|
||||
bool connect_;
|
||||
BSONObj res_;
|
||||
};
|
||||
|
||||
class DirectDBClientConnection : public DBClientConnection {
|
||||
public:
|
||||
DirectDBClientConnection( ReplPair *rp ) : rp_( rp ) {
|
||||
}
|
||||
virtual BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) {
|
||||
SetGlobalReplPair s( rp_ );
|
||||
BSONObjBuilder result;
|
||||
result.append( "ok", runCommandAgainstRegistered( "admin.$cmd", query, result ) ? 1.0 : 0.0 );
|
||||
return result.doneAndDecouple();
|
||||
}
|
||||
private:
|
||||
ReplPair *rp_;
|
||||
class SetGlobalReplPair {
|
||||
public:
|
||||
SetGlobalReplPair( ReplPair *rp ) {
|
||||
backup_ = replPair;
|
||||
replPair = rp;
|
||||
}
|
||||
~SetGlobalReplPair() {
|
||||
replPair = backup_;
|
||||
}
|
||||
private:
|
||||
ReplPair *backup_;
|
||||
};
|
||||
};
|
221
dbtests/pairingtests.cpp
Normal file
221
dbtests/pairingtests.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
// pairingtests.cpp : Pairing unit tests.
|
||||
//
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "../db/replset.h"
|
||||
#include "dbtests.h"
|
||||
#include "mockdbclient.h"
|
||||
|
||||
namespace PairingTests {
|
||||
namespace ReplPairTests {
|
||||
class Create {
|
||||
public:
|
||||
void run() {
|
||||
ReplPair rp1( "foo", "bar" );
|
||||
checkFields( rp1, "foo", "foo", DBPort, "bar" );
|
||||
|
||||
ReplPair rp2( "foo:1", "bar" );
|
||||
checkFields( rp2, "foo:1", "foo", 1, "bar" );
|
||||
|
||||
// FIXME Should we accept this input?
|
||||
ReplPair rp3( "", "bar" );
|
||||
checkFields( rp3, "", "", DBPort, "bar" );
|
||||
|
||||
ASSERT_EXCEPTION( ReplPair( "foo:", "bar" ),
|
||||
UserAssertionException );
|
||||
|
||||
ASSERT_EXCEPTION( ReplPair( "foo:0", "bar" ),
|
||||
UserAssertionException );
|
||||
|
||||
ASSERT_EXCEPTION( ReplPair( "foo:10000000", "bar" ),
|
||||
UserAssertionException );
|
||||
|
||||
ASSERT_EXCEPTION( ReplPair( "foo", "" ),
|
||||
UserAssertionException );
|
||||
}
|
||||
private:
|
||||
void checkFields( const ReplPair &rp,
|
||||
const string &remote,
|
||||
const string &remoteHost,
|
||||
int remotePort,
|
||||
const string &arbHost ) {
|
||||
ASSERT( rp.state == ReplPair::State_Negotiating );
|
||||
ASSERT_EQUALS( rp.remote, remote );
|
||||
ASSERT_EQUALS( rp.remoteHost, remoteHost );
|
||||
ASSERT_EQUALS( rp.remotePort, remotePort );
|
||||
ASSERT_EQUALS( rp.arbHost, arbHost );
|
||||
}
|
||||
};
|
||||
|
||||
class Dominant {
|
||||
public:
|
||||
Dominant() : oldPort_( port ) {
|
||||
port = 10;
|
||||
}
|
||||
~Dominant() {
|
||||
port = oldPort_;
|
||||
}
|
||||
void run() {
|
||||
ASSERT( ReplPair( "b:9", "-" ).dominant( "b" ) );
|
||||
ASSERT( !ReplPair( "b:10", "-" ).dominant( "b" ) );
|
||||
ASSERT( ReplPair( "b", "-" ).dominant( "c" ) );
|
||||
ASSERT( !ReplPair( "b", "-" ).dominant( "a" ) );
|
||||
}
|
||||
private:
|
||||
int oldPort_;
|
||||
};
|
||||
|
||||
class SetMaster {
|
||||
public:
|
||||
void run() {
|
||||
ReplPair rp( "a", "b" );
|
||||
rp.setMaster( ReplPair::State_CantArb, "foo" );
|
||||
ASSERT( rp.state == ReplPair::State_CantArb );
|
||||
ASSERT_EQUALS( rp.info, "foo" );
|
||||
rp.setMaster( ReplPair::State_Confused, "foo" );
|
||||
ASSERT( rp.state == ReplPair::State_Confused );
|
||||
}
|
||||
};
|
||||
|
||||
class Negotiate {
|
||||
public:
|
||||
void run() {
|
||||
ReplPair rp( "a", "b" );
|
||||
MockDBClientConnection cc;
|
||||
|
||||
cc.one( res( 0, 0 ) );
|
||||
rp.negotiate( &cc );
|
||||
ASSERT( rp.state == ReplPair::State_Confused );
|
||||
|
||||
rp.state = ReplPair::State_Negotiating;
|
||||
cc.one( res( 1, 2 ) );
|
||||
rp.negotiate( &cc );
|
||||
ASSERT( rp.state == ReplPair::State_Negotiating );
|
||||
|
||||
cc.one( res( 1, ReplPair::State_Slave ) );
|
||||
rp.negotiate( &cc );
|
||||
ASSERT( rp.state == ReplPair::State_Slave );
|
||||
|
||||
cc.one( res( 1, ReplPair::State_Master ) );
|
||||
rp.negotiate( &cc );
|
||||
ASSERT( rp.state == ReplPair::State_Master );
|
||||
}
|
||||
private:
|
||||
BSONObj res( int ok, int youAre ) {
|
||||
BSONObjBuilder b;
|
||||
b.appendInt( "ok", ok );
|
||||
b.appendInt( "you_are", youAre );
|
||||
return b.doneAndDecouple();
|
||||
}
|
||||
};
|
||||
|
||||
class Arbitrate {
|
||||
public:
|
||||
void run() {
|
||||
ReplPair rp1( "a", "-" );
|
||||
rp1.arbitrate();
|
||||
ASSERT( rp1.state == ReplPair::State_Master );
|
||||
|
||||
TestableReplPair rp2( false, BSONObj() );
|
||||
rp2.arbitrate();
|
||||
ASSERT( rp2.state == ReplPair::State_CantArb );
|
||||
|
||||
BSONObjBuilder b;
|
||||
b.append( "foo", 1 );
|
||||
TestableReplPair rp3( true, b.doneAndDecouple() );
|
||||
rp3.arbitrate();
|
||||
ASSERT( rp3.state == ReplPair::State_Master );
|
||||
}
|
||||
private:
|
||||
class TestableReplPair : public ReplPair {
|
||||
public:
|
||||
TestableReplPair( bool connect, const BSONObj &res ) :
|
||||
ReplPair( "a", "z" ),
|
||||
connect_( connect ),
|
||||
res_( res ) {
|
||||
}
|
||||
virtual
|
||||
DBClientConnection *newClientConnection() {
|
||||
MockDBClientConnection * c = new MockDBClientConnection();
|
||||
c->connect( connect_ );
|
||||
c->res( res_ );
|
||||
return c;
|
||||
}
|
||||
private:
|
||||
bool connect_;
|
||||
BSONObj res_;
|
||||
};
|
||||
};
|
||||
} // namespace ReplPairTests
|
||||
|
||||
class DirectConnectBase {
|
||||
protected:
|
||||
static void negotiate( ReplPair &a, ReplPair &b ) {
|
||||
a.negotiate( auto_ptr< DBClientConnection >( new DirectDBClientConnection( &b ) ).get() );
|
||||
}
|
||||
};
|
||||
|
||||
class Negotiate : public DirectConnectBase {
|
||||
public:
|
||||
void run() {
|
||||
checkNegotiation( "a", "-", ReplPair::State_Negotiating, ReplPair::State_Master,
|
||||
"b", "-", ReplPair::State_Negotiating, ReplPair::State_Slave );
|
||||
checkNegotiation( "b", "-", ReplPair::State_Negotiating, ReplPair::State_Slave,
|
||||
"a", "-", ReplPair::State_Negotiating, ReplPair::State_Master );
|
||||
|
||||
checkNegotiation( "a", "-", ReplPair::State_Negotiating, ReplPair::State_Slave,
|
||||
"b", "-", ReplPair::State_Master, ReplPair::State_Master );
|
||||
checkNegotiation( "b", "-", ReplPair::State_Master, ReplPair::State_Master,
|
||||
"a", "-", ReplPair::State_Negotiating, ReplPair::State_Slave );
|
||||
|
||||
checkNegotiation( "a", "-", ReplPair::State_Negotiating, ReplPair::State_Slave,
|
||||
"b", "-", ReplPair::State_Slave, ReplPair::State_Master );
|
||||
// FIXME Move from negotiating to master?
|
||||
checkNegotiation( "a", "-", ReplPair::State_Slave, ReplPair::State_Slave,
|
||||
"b", "-", ReplPair::State_Negotiating, ReplPair::State_Master );
|
||||
}
|
||||
private:
|
||||
void checkNegotiation( const char *host1, const char *arb1, int state1, int newState1,
|
||||
const char *host2, const char *arb2, int state2, int newState2 ) {
|
||||
ReplPair one( host1, arb1 );
|
||||
one.state = state1;
|
||||
ReplPair two( host2, arb2 );
|
||||
two.state = state2;
|
||||
negotiate( one, two );
|
||||
ASSERT( one.state == newState1 );
|
||||
ASSERT( two.state == newState2 );
|
||||
}
|
||||
};
|
||||
|
||||
class All : public UnitTest::Suite {
|
||||
public:
|
||||
All() {
|
||||
add< ReplPairTests::Create >();
|
||||
add< ReplPairTests::Dominant >();
|
||||
add< ReplPairTests::SetMaster >();
|
||||
add< ReplPairTests::Negotiate >();
|
||||
add< ReplPairTests::Arbitrate >();
|
||||
add< Negotiate >();
|
||||
}
|
||||
};
|
||||
} // namespace PairingTests
|
||||
|
||||
UnitTest::TestPtr pairingTests() {
|
||||
return UnitTest::createSuite< PairingTests::All >();
|
||||
}
|
Loading…
Reference in New Issue
Block a user