diff options
Diffstat (limited to 'jstests/repl')
-rw-r--r-- | jstests/repl/basic1.js | 59 | ||||
-rw-r--r-- | jstests/repl/pair1.js | 99 | ||||
-rw-r--r-- | jstests/repl/pair2.js | 71 | ||||
-rw-r--r-- | jstests/repl/pair3.js | 235 | ||||
-rw-r--r-- | jstests/repl/pair4.js | 159 | ||||
-rw-r--r-- | jstests/repl/pair5.js | 95 | ||||
-rw-r--r-- | jstests/repl/pair6.js | 115 | ||||
-rw-r--r-- | jstests/repl/repl1.js | 55 | ||||
-rw-r--r-- | jstests/repl/repl2.js | 45 | ||||
-rw-r--r-- | jstests/repl/repl3.js | 47 | ||||
-rw-r--r-- | jstests/repl/repl4.js | 30 | ||||
-rw-r--r-- | jstests/repl/repl5.js | 32 | ||||
-rw-r--r-- | jstests/repl/repl6.js | 73 | ||||
-rw-r--r-- | jstests/repl/repl7.js | 45 | ||||
-rw-r--r-- | jstests/repl/repl8.js | 30 | ||||
-rw-r--r-- | jstests/repl/repl9.js | 48 | ||||
-rw-r--r-- | jstests/repl/replacePeer1.js | 71 | ||||
-rw-r--r-- | jstests/repl/replacePeer2.js | 72 |
18 files changed, 1381 insertions, 0 deletions
diff --git a/jstests/repl/basic1.js b/jstests/repl/basic1.js new file mode 100644 index 0000000..9668a91 --- /dev/null +++ b/jstests/repl/basic1.js @@ -0,0 +1,59 @@ + +// test repl basics +// data on master/slave is the same + +var rt = new ReplTest( "basic1" ); + +m = rt.start( true ); +s = rt.start( false ); + +function hash( db ){ + var s = ""; + var a = db.getCollectionNames(); + a = a.sort(); + a.forEach( + function(cn){ + var c = db.getCollection( cn ); + s += cn + "\t" + c.find().count() + "\n"; + c.find().sort( { _id : 1 } ).forEach( + function(o){ + s += tojson( o , "" , true ) + "\n"; + } + ); + } + ); + return s; +} + +am = m.getDB( "foo" ); +as = s.getDB( "foo" ); + +function check( note ){ + var start = new Date(); + var x,y; + while ( (new Date()).getTime() - start.getTime() < 30000 ){ + x = hash( am ); + y = hash( as ); + if ( x == y ) + return; + sleep( 200 ); + } + assert.eq( x , y , note ); +} + +am.a.save( { x : 1 } ); +check( "A" ); + +am.a.save( { x : 5 } ); + +am.a.update( {} , { $inc : { x : 1 } } ); +check( "B" ); + +am.a.update( {} , { $inc : { x : 1 } } , false , true ); +check( "C" ); + +rt.stop(); + + + + diff --git a/jstests/repl/pair1.js b/jstests/repl/pair1.js new file mode 100644 index 0000000..7004048 --- /dev/null +++ b/jstests/repl/pair1.js @@ -0,0 +1,99 @@ +// Basic pairing test + +var baseName = "jstests_pair1test"; + +debug = function( p ) { +// print( p ); +} + +ismaster = function( n ) { + var im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); +// print( "ismaster: " + tojson( im ) ); + assert( im, "command ismaster failed" ); + return im.ismaster; +} + +var writeOneIdx = 0; + +writeOne = function( n ) { + n.getDB( baseName ).z.save( { _id: new ObjectId(), i: ++writeOneIdx } ); +} + +getCount = function( n ) { + return n.getDB( baseName ).z.find( { i: writeOneIdx } ).toArray().length; +} + +checkWrite = function( m, s ) { + writeOne( m ); + assert.eq( 1, getCount( m ) ); + check( s ); +} + +check = function( s ) { + s.setSlaveOk(); + assert.soon( function() { + return 1 == getCount( s ); + } ); +} + +// check that slave reads and writes are guarded +checkSlaveGuard = function( s ) { + var t = s.getDB( baseName + "-temp" ).temp; + assert.throws( t.find().count, {}, "not master" ); + assert.throws( t.find(), {}, "not master", "find did not assert" ); + + checkError = function() { + assert.eq( "not master", s.getDB( "admin" ).getLastError() ); + s.getDB( "admin" ).resetError(); + } + s.getDB( "admin" ).resetError(); + t.save( {x:1} ); + checkError(); + t.update( {}, {x:2}, true ); + checkError(); + t.remove( {x:0} ); + checkError(); +} + +doTest = function( signal ) { + + ports = allocatePorts( 3 ); + + a = new MongodRunner( ports[ 0 ], "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( ports[ 1 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 2 ], "127.0.0.1:" + ports[ 0 ] ); + r = new MongodRunner( ports[ 2 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 1 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( l, r, a ); + rp.start(); + rp.waitForSteadyState(); + + checkSlaveGuard( rp.slave() ); + + checkWrite( rp.master(), rp.slave() ); + + debug( "kill first" ); + rp.killNode( rp.master(), signal ); + rp.waitForSteadyState( [ 1, null ], rp.slave().host ); + writeOne( rp.master() ); + + debug( "restart first" ); + rp.start( true ); + rp.waitForSteadyState(); + check( rp.slave() ); + checkWrite( rp.master(), rp.slave() ); + + debug( "kill second" ); + rp.killNode( rp.master(), signal ); + rp.waitForSteadyState( [ 1, null ], rp.slave().host ); + + debug( "restart second" ); + rp.start( true ); + rp.waitForSteadyState( [ 1, 0 ], rp.master().host ); + checkWrite( rp.master(), rp.slave() ); + + ports.forEach( function( x ) { stopMongod( x ); } ); + +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/pair2.js b/jstests/repl/pair2.js new file mode 100644 index 0000000..2491fb2 --- /dev/null +++ b/jstests/repl/pair2.js @@ -0,0 +1,71 @@ +// Pairing resync + +var baseName = "jstests_pair2test"; + +ismaster = function( n ) { + im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); + assert( im ); + return im.ismaster; +} + +soonCount = function( m, count ) { + assert.soon( function() { +// print( "counting" ); +//// print( "counted: " + l.getDB( baseName ).z.find().count() ); + return m.getDB( baseName ).z.find().count() == count; + } ); +} + +doTest = function( signal ) { + + ports = allocatePorts( 3 ); + + a = new MongodRunner( ports[ 0 ], "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( ports[ 1 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 2 ], "127.0.0.1:" + ports[ 0 ] ); + r = new MongodRunner( ports[ 2 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 1 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( l, r, a ); + rp.start(); + rp.waitForSteadyState(); + + rp.slave().setSlaveOk(); + mz = rp.master().getDB( baseName ).z; + + mz.save( { _id: new ObjectId() } ); + soonCount( rp.slave(), 1 ); + assert.eq( 0, rp.slave().getDB( "admin" ).runCommand( { "resync" : 1 } ).ok ); + + sleep( 3000 ); // allow time to finish clone and save ReplSource + rp.killNode( rp.slave(), signal ); + rp.waitForSteadyState( [ 1, null ], rp.master().host ); + + big = new Array( 2000 ).toString(); + for( i = 0; i < 1000; ++i ) + mz.save( { _id: new ObjectId(), i: i, b: big } ); + + rp.start( true ); + rp.waitForSteadyState( [ 1, 0 ], rp.master().host ); + + sleep( 15000 ); + + rp.slave().setSlaveOk(); + assert.soon( function() { + ret = rp.slave().getDB( "admin" ).runCommand( { "resync" : 1 } ); +// printjson( ret ); + return 1 == ret.ok; + } ); + + sleep( 8000 ); + soonCount( rp.slave(), 1001 ); + sz = rp.slave().getDB( baseName ).z + assert.eq( 1, sz.find( { i: 0 } ).count() ); + assert.eq( 1, sz.find( { i: 999 } ).count() ); + + assert.eq( 0, rp.slave().getDB( "admin" ).runCommand( { "resync" : 1 } ).ok ); + + ports.forEach( function( x ) { stopMongod( x ); } ); + +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/pair3.js b/jstests/repl/pair3.js new file mode 100644 index 0000000..506e173 --- /dev/null +++ b/jstests/repl/pair3.js @@ -0,0 +1,235 @@ +// test arbitration + +var baseName = "jstests_pair3test"; + +ismaster = function( n ) { + var im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); + print( "ismaster: " + tojson( im ) ); + assert( im, "command ismaster failed" ); + return im.ismaster; +} + +// bring up node connections before arbiter connections so that arb can forward to node when expected +connect = function() { + if ( lp == null ) { + lp = startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + } + if ( rp == null ) { + rp = startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); + } + if ( al == null ) { + al = startMongoProgram( "mongobridge", "--port", alPort, "--dest", "localhost:" + aPort ); + } + if ( ar == null ) { + ar = startMongoProgram( "mongobridge", "--port", arPort, "--dest", "localhost:" + aPort ); + } +} + +disconnectNode = function( mongo ) { + if ( lp ) { + stopMongoProgram( lpPort ); + lp = null; + } + if ( rp ) { + stopMongoProgram( rpPort ); + rp = null; + } + if ( mongo.host.match( new RegExp( "^127.0.0.1:" + lPort + "$" ) ) ) { + stopMongoProgram( alPort ); + al = null; + } else if ( mongo.host.match( new RegExp( "^127.0.0.1:" + rPort + "$" ) ) ) { + stopMongoProgram( arPort ); + ar = null; + } else { + assert( false, "don't know how to disconnect node: " + mongo ); + } +} + +doTest1 = function() { + al = ar = lp = rp = null; + ports = allocatePorts( 7 ); + aPort = ports[ 0 ]; + alPort = ports[ 1 ]; + arPort = ports[ 2 ]; + lPort = ports[ 3 ]; + lpPort = ports[ 4 ]; + rPort = ports[ 5 ]; + rpPort = ports[ 6 ]; + + connect(); + + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + alPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + arPort ); + + pair = new ReplPair( l, r, a ); + + // normal startup + pair.start(); + pair.waitForSteadyState(); + + // disconnect slave + disconnectNode( pair.slave() ); + pair.waitForSteadyState( [ 1, -3 ], pair.master().host ); + + // disconnect master + disconnectNode( pair.master() ); + pair.waitForSteadyState( [ -3, -3 ] ); + + // reconnect + connect(); + pair.waitForSteadyState(); + + // disconnect master + disconnectNode( pair.master() ); + pair.waitForSteadyState( [ 1, -3 ], pair.slave().host, true ); + + // disconnect new master + disconnectNode( pair.master() ); + pair.waitForSteadyState( [ -3, -3 ] ); + + // reconnect + connect(); + pair.waitForSteadyState(); + + // disconnect slave + disconnectNode( pair.slave() ); + pair.waitForSteadyState( [ 1, -3 ], pair.master().host ); + + // reconnect slave + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.master().host ); + + // disconnect master + disconnectNode( pair.master() ); + pair.waitForSteadyState( [ 1, -3 ], pair.slave().host, true ); + + // reconnect old master + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.master().host ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); +} + +// this time don't start connected +doTest2 = function() { + al = ar = lp = rp = null; + ports = allocatePorts( 7 ); + aPort = ports[ 0 ]; + alPort = ports[ 1 ]; + arPort = ports[ 2 ]; + lPort = ports[ 3 ]; + lpPort = ports[ 4 ]; + rPort = ports[ 5 ]; + rpPort = ports[ 6 ]; + + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + alPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + arPort ); + + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState( [ -3, -3 ] ); + + startMongoProgram( "mongobridge", "--port", arPort, "--dest", "localhost:" + aPort ); + + // there hasn't been an initial sync, no no node will become master + + for( i = 0; i < 10; ++i ) { + assert( pair.isMaster( pair.right() ) == -3 && pair.isMaster( pair.left() ) == -3 ); + sleep( 500 ); + } + + stopMongoProgram( arPort ); + + startMongoProgram( "mongobridge", "--port", alPort, "--dest", "localhost:" + aPort ); + + for( i = 0; i < 10; ++i ) { + assert( pair.isMaster( pair.right() ) == -3 && pair.isMaster( pair.left() ) == -3 ); + sleep( 500 ); + } + + stopMongoProgram( alPort ); + + // connect l and r without a + + startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); + + pair.waitForSteadyState( [ 1, 0 ] ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); +} + +// recover from master - master setup +doTest3 = function() { + al = ar = lp = rp = null; + ports = allocatePorts( 7 ); + aPort = ports[ 0 ]; + alPort = ports[ 1 ]; + arPort = ports[ 2 ]; + lPort = ports[ 3 ]; + lpPort = ports[ 4 ]; + rPort = ports[ 5 ]; + rpPort = ports[ 6 ]; + + connect(); + + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + alPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + arPort ); + + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState(); + + // now can only talk to arbiter + stopMongoProgram( lpPort ); + stopMongoProgram( rpPort ); + pair.waitForSteadyState( [ 1, 1 ], null, true ); + + // recover + startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); + pair.waitForSteadyState( [ 1, 0 ], null, true ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); +} + +// check that initial sync is persistent +doTest4 = function( signal ) { + al = ar = lp = rp = null; + ports = allocatePorts( 7 ); + aPort = ports[ 0 ]; + alPort = ports[ 1 ]; + arPort = ports[ 2 ]; + lPort = ports[ 3 ]; + lpPort = ports[ 4 ]; + rPort = ports[ 5 ]; + rpPort = ports[ 6 ]; + + connect(); + + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + alPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + arPort ); + + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState(); + + pair.killNode( pair.left(), signal ); + pair.killNode( pair.right(), signal ); + stopMongoProgram( rpPort ); + stopMongoProgram( lpPort ); + + // now can only talk to arbiter + pair.start( true ); + pair.waitForSteadyState( [ 1, 1 ], null, true ); +} + +doTest1(); +doTest2(); +doTest3(); +doTest4( 15 ); +doTest4( 9 ); diff --git a/jstests/repl/pair4.js b/jstests/repl/pair4.js new file mode 100644 index 0000000..5a59c16 --- /dev/null +++ b/jstests/repl/pair4.js @@ -0,0 +1,159 @@ +// data consistency after master-master + +var baseName = "jstests_pair4test"; + +debug = function( o ) { + printjson( o ); +} + +ismaster = function( n ) { + var im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); + print( "ismaster: " + tojson( im ) ); + assert( im, "command ismaster failed" ); + return im.ismaster; +} + +connect = function() { + startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); +} + +disconnect = function() { + stopMongoProgram( lpPort ); + stopMongoProgram( rpPort ); +} + +write = function( m, n, id ) { + if ( id ) { + save = { _id:id, n:n }; + } else { + save = { n:n }; + } + m.getDB( baseName ).getCollection( baseName ).save( save ); +} + +check = function( m, n, id ) { + m.setSlaveOk(); + if ( id ) { + find = { _id:id, n:n }; + } else { + find = { n:n }; + } + assert.soon( function() { return m.getDB( baseName ).getCollection( baseName ).find( find ).count() > 0; }, + "failed waiting for " + m + " value of n to be " + n ); +} + +checkCount = function( m, c ) { + m.setSlaveOk(); + assert.soon( function() { + actual = m.getDB( baseName ).getCollection( baseName ).find().count(); + print( actual ); + return c == actual; }, + "count failed for " + m ); +} + +coll = function( m ) { + return m.getDB( baseName ).getCollection( baseName ); +} + +db2Coll = function( m ) { + return m.getDB( baseName + "_second" ).getCollection( baseName ); +} + +doTest = function( recover, newMaster, newSlave ) { + ports = allocatePorts( 5 ); + aPort = ports[ 0 ]; + lPort = ports[ 1 ]; + lpPort = ports[ 2 ]; + rPort = ports[ 3 ]; + rpPort = ports[ 4 ]; + + // start normally + connect(); + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + aPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + aPort ); + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState(); + + firstMaster = pair.master(); + firstSlave = pair.slave(); + + write( pair.master(), 0 ); + write( pair.master(), 1 ); + check( pair.slave(), 0 ); + check( pair.slave(), 1 ); + + // now each can only talk to arbiter + disconnect(); + pair.waitForSteadyState( [ 1, 1 ], null, true ); + + m = newMaster(); + write( m, 10 ); + write( m, 100, "a" ); + coll( m ).update( {n:1}, {$set:{n:2}} ); + db2Coll( m ).save( {n:500} ); + db2Coll( m ).findOne(); + + s = newSlave(); + write( s, 20 ); + write( s, 200, "a" ); + coll( s ).update( {n:1}, {n:1,m:3} ); + db2Coll( s ).save( {_id:"a",n:600} ); + db2Coll( s ).findOne(); + + // recover + recover(); + + nodes = [ pair.right(), pair.left() ]; + + nodes.forEach( function( x ) { checkCount( x, 5 ); } ); + nodes.forEach( function( x ) { [ 0, 10, 20, 100 ].forEach( function( y ) { check( x, y ); } ); } ); + + checkM = function( c ) { + assert.soon( function() { + obj = coll( c ).findOne( {n:2} ); + printjson( obj ); + return obj.m == undefined; + }, "n:2 test for " + c + " failed" ); + }; + nodes.forEach( function( x ) { checkM( x ); } ); + + // check separate database + nodes.forEach( function( x ) { assert.soon( function() { + r = db2Coll( x ).findOne( {_id:"a"} ); + debug( r ); + if ( r == null ) { + return false; + } + return 600 == r.n; + } ) } ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); + +} + +debug( "basic test" ); +doTest( function() { + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.right().host, true ); + }, function() { return pair.right(); }, function() { return pair.left(); } ); + +doRestartTest = function( signal ) { + doTest( function() { + if ( signal == 9 ) { + sleep( 3000 ); + } + pair.killNode( firstMaster, signal ); + connect(); + pair.start( true ); + pair.waitForSteadyState( [ 1, 0 ], firstSlave.host, true ); + }, function() { return firstSlave; }, function() { return firstMaster; } ); +} + +debug( "sigterm restart test" ); +doRestartTest( 15 ) // SIGTERM + +debug( "sigkill restart test" ); +doRestartTest( 9 ) // SIGKILL diff --git a/jstests/repl/pair5.js b/jstests/repl/pair5.js new file mode 100644 index 0000000..ed8c72d --- /dev/null +++ b/jstests/repl/pair5.js @@ -0,0 +1,95 @@ +// writes to new master while making master-master logs consistent + +var baseName = "jstests_pair5test"; + +debug = function( p ) { + print( p ); +} + +ismaster = function( n ) { + var im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); + print( "ismaster: " + tojson( im ) ); + assert( im, "command ismaster failed" ); + return im.ismaster; +} + +connect = function() { + startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); +} + +disconnect = function() { + stopMongoProgram( lpPort ); + stopMongoProgram( rpPort ); +} + +write = function( m, n, id ) { + if ( id ) { + save = { _id:id, n:n }; + } else { + save = { n:n }; + } + m.getDB( baseName ).getCollection( baseName ).save( save ); +} + +checkCount = function( m, c ) { + m.setSlaveOk(); + assert.soon( function() { + actual = m.getDB( baseName ).getCollection( baseName ).find().count(); + print( actual ); + return c == actual; }, + "count failed for " + m ); +} + +doTest = function( nSlave, opIdMem ) { + ports = allocatePorts( 5 ); + aPort = ports[ 0 ]; + lPort = ports[ 1 ]; + lpPort = ports[ 2 ]; + rPort = ports[ 3 ]; + rpPort = ports[ 4 ]; + + // start normally + connect(); + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + aPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + aPort ); + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState(); + + // now each can only talk to arbiter + disconnect(); + pair.waitForSteadyState( [ 1, 1 ], null, true ); + + // left will become slave + for( i = 0; i < nSlave; ++i ) { + write( pair.left(), i, i ); + } + pair.left().getDB( baseName ).getCollection( baseName ).findOne(); + + for( i = 10000; i < 15000; ++i ) { + write( pair.right(), i, i ); + } + pair.right().getDB( baseName ).getCollection( baseName ).findOne(); + + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.right().host, true ); + + pair.master().getDB( baseName ).getCollection( baseName ).update( {_id:nSlave - 1}, {_id:nSlave - 1,n:-1}, true ); + assert.eq( -1, pair.master().getDB( baseName ).getCollection( baseName ).findOne( {_id:nSlave - 1} ).n ); + checkCount( pair.master(), 5000 + nSlave ); + assert.eq( -1, pair.master().getDB( baseName ).getCollection( baseName ).findOne( {_id:nSlave - 1} ).n ); + pair.slave().setSlaveOk(); + assert.soon( function() { + n = pair.slave().getDB( baseName ).getCollection( baseName ).findOne( {_id:nSlave - 1} ).n; + print( n ); + return -1 == n; + } ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); + +} + +doTest( 5000, 100000000 ); +doTest( 5000, 100 ); // force op id converstion to collection based storage diff --git a/jstests/repl/pair6.js b/jstests/repl/pair6.js new file mode 100644 index 0000000..b249fc0 --- /dev/null +++ b/jstests/repl/pair6.js @@ -0,0 +1,115 @@ +// pairing cases where oplogs run out of space + +var baseName = "jstests_pair6test"; + +debug = function( p ) { + print( p ); +} + +ismaster = function( n ) { + var im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); + print( "ismaster: " + tojson( im ) ); + assert( im, "command ismaster failed" ); + return im.ismaster; +} + +connect = function() { + startMongoProgram( "mongobridge", "--port", lpPort, "--dest", "localhost:" + lPort ); + startMongoProgram( "mongobridge", "--port", rpPort, "--dest", "localhost:" + rPort ); +} + +disconnect = function() { + stopMongoProgram( lpPort ); + stopMongoProgram( rpPort ); +} + +checkCount = function( m, c ) { + m.setSlaveOk(); + assert.soon( function() { + actual = m.getDB( baseName ).getCollection( baseName ).find().count(); + print( actual ); + return c == actual; }, + "expected count " + c + " for " + m ); +} + +resetSlave = function( s ) { + s.setSlaveOk(); + assert.soon( function() { + ret = s.getDB( "admin" ).runCommand( { "resync" : 1 } ); + // printjson( ret ); + return 1 == ret.ok; + } ); +} + +big = new Array( 2000 ).toString(); + +doTest = function() { + ports = allocatePorts( 5 ); + aPort = ports[ 0 ]; + lPort = ports[ 1 ]; + lpPort = ports[ 2 ]; + rPort = ports[ 3 ]; + rpPort = ports[ 4 ]; + + // start normally + connect(); + a = new MongodRunner( aPort, "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( lPort, "/data/db/" + baseName + "-left", "127.0.0.1:" + rpPort, "127.0.0.1:" + aPort ); + r = new MongodRunner( rPort, "/data/db/" + baseName + "-right", "127.0.0.1:" + lpPort, "127.0.0.1:" + aPort ); + pair = new ReplPair( l, r, a ); + pair.start(); + pair.waitForSteadyState(); + + disconnect(); + pair.waitForSteadyState( [ 1, 1 ], null, true ); + + print( "test one" ); + + // fill new slave oplog + for( i = 0; i < 1000; ++i ) { + pair.left().getDB( baseName ).getCollection( baseName ).save( {b:big} ); + } + pair.left().getDB( baseName ).getCollection( baseName ).findOne(); + + // write single to new master + pair.right().getDB( baseName ).getCollection( baseName ).save( {} ); + + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.right().host, true ); + + resetSlave( pair.left() ); + + checkCount( pair.left(), 1 ); + checkCount( pair.right(), 1 ); + + pair.right().getDB( baseName ).getCollection( baseName ).remove( {} ); + checkCount( pair.left(), 0 ); + + disconnect(); + pair.waitForSteadyState( [ 1, 1 ], null, true ); + + print( "test two" ); + + // fill new master oplog + for( i = 0; i < 1000; ++i ) { + pair.right().getDB( baseName ).getCollection( baseName ).save( {b:big} ); + } + + pair.left().getDB( baseName ).getCollection( baseName ).save( {_id:"abcde"} ); + + connect(); + pair.waitForSteadyState( [ 1, 0 ], pair.right().host, true ); + + sleep( 15000 ); + + resetSlave( pair.left() ); + + checkCount( pair.left(), 1000 ); + checkCount( pair.right(), 1000 ); + assert.eq( 0, pair.left().getDB( baseName ).getCollection( baseName ).find( {_id:"abcde"} ).count() ); + + ports.forEach( function( x ) { stopMongoProgram( x ); } ); + +} + +doTest();
\ No newline at end of file diff --git a/jstests/repl/repl1.js b/jstests/repl/repl1.js new file mode 100644 index 0000000..60f3942 --- /dev/null +++ b/jstests/repl/repl1.js @@ -0,0 +1,55 @@ +// Test basic replication functionality + +var baseName = "jstests_repl1test"; + +soonCount = function( count ) { + assert.soon( function() { +// print( "check count" ); +// print( "count: " + s.getDB( baseName ).z.find().count() ); + return s.getDB( baseName ).a.find().count() == count; + } ); +} + +doTest = function( signal ) { + + rt = new ReplTest( "repl1tests" ); + + m = rt.start( true ); + s = rt.start( false ); + + am = m.getDB( baseName ).a + + for( i = 0; i < 1000; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + soonCount( 1000 ); + as = s.getDB( baseName ).a + assert.eq( 1, as.find( { i: 0 } ).count() ); + assert.eq( 1, as.find( { i: 999 } ).count() ); + + rt.stop( false, signal ); + + for( i = 1000; i < 1010; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + s = rt.start( false, null, true ); + soonCount( 1010 ); + as = s.getDB( baseName ).a + assert.eq( 1, as.find( { i: 1009 } ).count() ); + + rt.stop( true, signal ); + + m = rt.start( true, null, true ); + am = m.getDB( baseName ).a + + for( i = 1010; i < 1020; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + assert.soon( function() { return as.find().count() == 1020; } ); + assert.eq( 1, as.find( { i: 1019 } ).count() ); + + rt.stop(); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl2.js b/jstests/repl/repl2.js new file mode 100644 index 0000000..c9fe6b9 --- /dev/null +++ b/jstests/repl/repl2.js @@ -0,0 +1,45 @@ +// Test resync command + +soonCount = function( count ) { + assert.soon( function() { +// print( "check count" ); +// print( "count: " + s.getDB( baseName ).z.find().count() ); + return s.getDB("foo").a.find().count() == count; + } ); +} + +doTest = function( signal ) { + + var rt = new ReplTest( "repl2tests" ); + + // implicit small oplog makes slave get out of sync + m = rt.start( true ); + s = rt.start( false ); + + am = m.getDB("foo").a + + am.save( { _id: new ObjectId() } ); + soonCount( 1 ); + assert.eq( 0, s.getDB( "admin" ).runCommand( { "resync" : 1 } ).ok ); + rt.stop( false , signal ); + + big = new Array( 2000 ).toString(); + for( i = 0; i < 1000; ++i ) + am.save( { _id: new ObjectId(), i: i, b: big } ); + + s = rt.start( false , null , true ); + assert.soon( function() { return 1 == s.getDB( "admin" ).runCommand( { "resync" : 1 } ).ok; } ); + + soonCount( 1001 ); + as = s.getDB("foo").a + assert.eq( 1, as.find( { i: 0 } ).count() ); + assert.eq( 1, as.find( { i: 999 } ).count() ); + + assert.eq( 0, s.getDB( "admin" ).runCommand( { "resync" : 1 } ).ok ); + + rt.stop(); + +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl3.js b/jstests/repl/repl3.js new file mode 100644 index 0000000..d3c3848 --- /dev/null +++ b/jstests/repl/repl3.js @@ -0,0 +1,47 @@ +// Test autoresync + +var baseName = "jstests_repl3test"; + +soonCount = function( count ) { + assert.soon( function() { +// print( "check count" ); +// print( "count: " + s.getDB( baseName ).z.find().count() + ", expected: " + count ); + return s.getDB( baseName ).a.find().count() == count; + } ); +} + +doTest = function( signal ) { + + rt = new ReplTest( "repl3tests" ); + + m = rt.start( true ); + s = rt.start( false ); + + am = m.getDB( baseName ).a + + am.save( { _id: new ObjectId() } ); + soonCount( 1 ); + rt.stop( false, signal ); + + big = new Array( 2000 ).toString(); + for( i = 0; i < 1000; ++i ) + am.save( { _id: new ObjectId(), i: i, b: big } ); + + s = rt.start( false, { autoresync: null }, true ); + + // after SyncException, mongod waits 10 secs. + sleep( 15000 ); + + // Need the 2 additional seconds timeout, since commands don't work on an 'allDead' node. + soonCount( 1001 ); + as = s.getDB( baseName ).a + assert.eq( 1, as.find( { i: 0 } ).count() ); + assert.eq( 1, as.find( { i: 999 } ).count() ); + + assert.commandFailed( s.getDB( "admin" ).runCommand( { "resync" : 1 } ) ); + + rt.stop(); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl4.js b/jstests/repl/repl4.js new file mode 100644 index 0000000..de7ca43 --- /dev/null +++ b/jstests/repl/repl4.js @@ -0,0 +1,30 @@ +// Test replication 'only' mode + +soonCount = function( db, coll, count ) { + assert.soon( function() { + return s.getDB( db )[ coll ].find().count() == count; + } ); +} + +doTest = function() { + + rt = new ReplTest( "repl4tests" ); + + m = rt.start( true ); + s = rt.start( false, { only: "c" } ); + + cm = m.getDB( "c" ).c + bm = m.getDB( "b" ).b + + cm.save( { x:1 } ); + bm.save( { x:2 } ); + + soonCount( "c", "c", 1 ); + assert.eq( 1, s.getDB( "c" ).c.findOne().x ); + sleep( 10000 ); + printjson( s.getDBNames() ); + assert.eq( -1, s.getDBNames().indexOf( "b" ) ); + assert.eq( 0, s.getDB( "b" ).b.find().count() ); +} + +doTest(); diff --git a/jstests/repl/repl5.js b/jstests/repl/repl5.js new file mode 100644 index 0000000..b9bcef9 --- /dev/null +++ b/jstests/repl/repl5.js @@ -0,0 +1,32 @@ +// Test auto reclone after failed initial clone + +soonCountAtLeast = function( db, coll, count ) { + assert.soon( function() { +// print( "count: " + s.getDB( db )[ coll ].find().count() ); + return s.getDB( db )[ coll ].find().count() >= count; + } ); +} + +doTest = function( signal ) { + + rt = new ReplTest( "repl5tests" ); + + m = rt.start( true ); + + ma = m.getDB( "a" ).a; + for( i = 0; i < 10000; ++i ) + ma.save( { i:i } ); + + s = rt.start( false ); + soonCountAtLeast( "a", "a", 1 ); + rt.stop( false, signal ); + + s = rt.start( false, null, true ); + sleep( 1000 ); + soonCountAtLeast( "a", "a", 10000 ); + + rt.stop(); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl6.js b/jstests/repl/repl6.js new file mode 100644 index 0000000..f4fdc9b --- /dev/null +++ b/jstests/repl/repl6.js @@ -0,0 +1,73 @@ +// Test one master replicating to two slaves + +var baseName = "jstests_repl6test"; + +soonCount = function( m, count ) { + assert.soon( function() { + return m.getDB( baseName ).a.find().count() == count; + }, "expected count: " + count + " from : " + m ); +} + +doTest = function( signal ) { + + ports = allocatePorts( 3 ); + + ms1 = new ReplTest( "repl6tests-1", [ ports[ 0 ], ports[ 1 ] ] ); + ms2 = new ReplTest( "repl6tests-2", [ ports[ 0 ], ports[ 2 ] ] ); + + m = ms1.start( true ); + s1 = ms1.start( false ); + s2 = ms2.start( false ); + + am = m.getDB( baseName ).a + + for( i = 0; i < 1000; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + soonCount( s1, 1000 ); + soonCount( s2, 1000 ); + + check = function( as ) { + assert.eq( 1, as.find( { i: 0 } ).count() ); + assert.eq( 1, as.find( { i: 999 } ).count() ); + } + + as = s1.getDB( baseName ).a + check( as ); + as = s2.getDB( baseName ).a + check( as ); + + ms1.stop( false, signal ); + ms2.stop( false, signal ); + + for( i = 1000; i < 1010; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + s1 = ms1.start( false, null, true ); + soonCount( s1, 1010 ); + as = s1.getDB( baseName ).a + assert.eq( 1, as.find( { i: 1009 } ).count() ); + + ms1.stop( true, signal ); + + m = ms1.start( true, null, true ); + am = m.getDB( baseName ).a + + for( i = 1010; i < 1020; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + soonCount( s1, 1020 ); + assert.eq( 1, as.find( { i: 1019 } ).count() ); + + s2 = ms2.start( false, null, true ); + soonCount( s2, 1020 ); + as = s2.getDB( baseName ).a + assert.eq( 1, as.find( { i: 1009 } ).count() ); + assert.eq( 1, as.find( { i: 1019 } ).count() ); + + ms1.stop(); + ms2.stop( false ); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl7.js b/jstests/repl/repl7.js new file mode 100644 index 0000000..e3fdee9 --- /dev/null +++ b/jstests/repl/repl7.js @@ -0,0 +1,45 @@ +// Test persistence of list of dbs to add. + +doTest = function( signal ) { + + rt = new ReplTest( "repl7tests" ); + + m = rt.start( true ); + + for( n = "a"; n != "aaaaa"; n += "a" ) { + m.getDB( n ).a.save( {x:1} ); + } + + s = rt.start( false ); + + assert.soon( function() { + return -1 != s.getDBNames().indexOf( "aa" ); + }, "aa timeout", 60000, 1000 ); + + rt.stop( false, signal ); + + s = rt.start( false, null, signal ); + + assert.soon( function() { + for( n = "a"; n != "aaaaa"; n += "a" ) { + if ( -1 == s.getDBNames().indexOf( n ) ) + return false; + } + return true; + }, "a-aaaa timeout", 60000, 1000 ); + + assert.soon( function() { + for( n = "a"; n != "aaaaa"; n += "a" ) { + if ( 1 != m.getDB( n ).a.find().count() ) { + return false; + } + } + return true; }, "a-aaaa count timeout" ); + + sleep( 300 ); + + rt.stop(); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/repl8.js b/jstests/repl/repl8.js new file mode 100644 index 0000000..64e65cc --- /dev/null +++ b/jstests/repl/repl8.js @@ -0,0 +1,30 @@ +// Test cloning of capped collections + +baseName = "jstests_repl_repl8"; + +rt = new ReplTest( "repl8tests" ); + +m = rt.start( true ); + +m.getDB( baseName ).createCollection( "first", {capped:true,size:1000} ); +assert( m.getDB( baseName ).getCollection( "first" ).isCapped() ); + +s = rt.start( false ); + +assert.soon( function() { return s.getDB( baseName ).getCollection( "first" ).isCapped(); } ); + +m.getDB( baseName ).createCollection( "second", {capped:true,size:1000} ); +assert.soon( function() { return s.getDB( baseName ).getCollection( "second" ).isCapped(); } ); + +m.getDB( baseName ).getCollection( "third" ).save( { a: 1 } ); +assert.soon( function() { return s.getDB( baseName ).getCollection( "third" ).exists(); } ); +assert.commandWorked( m.getDB( "admin" ).runCommand( {renameCollection:"jstests_repl_repl8.third", to:"jstests_repl_repl8.third_rename"} ) ); +assert( m.getDB( baseName ).getCollection( "third_rename" ).exists() ); +assert( !m.getDB( baseName ).getCollection( "third" ).exists() ); +assert.soon( function() { return s.getDB( baseName ).getCollection( "third_rename" ).exists(); } ); +assert.soon( function() { return !s.getDB( baseName ).getCollection( "third" ).exists(); } ); + +m.getDB( baseName ).getCollection( "fourth" ).save( {a:1} ); +assert.commandWorked( m.getDB( baseName ).getCollection( "fourth" ).convertToCapped( 1000 ) ); +assert( m.getDB( baseName ).getCollection( "fourth" ).isCapped() ); +assert.soon( function() { return s.getDB( baseName ).getCollection( "fourth" ).isCapped(); } ); diff --git a/jstests/repl/repl9.js b/jstests/repl/repl9.js new file mode 100644 index 0000000..be06e08 --- /dev/null +++ b/jstests/repl/repl9.js @@ -0,0 +1,48 @@ +// Test replication of collection renaming + +baseName = "jstests_repl_repl9"; + +rt = new ReplTest( "repl9tests" ); + +m = rt.start( true ); +s = rt.start( false ); + +admin = m.getDB( "admin" ); + +debug = function( foo ) {} // print( foo ); } + +// rename within db + +m.getDB( baseName ).one.save( { a: 1 } ); +assert.soon( function() { v = s.getDB( baseName ).one.findOne(); return v && 1 == v.a } ); + +assert.commandWorked( admin.runCommand( {renameCollection:"jstests_repl_repl9.one", to:"jstests_repl_repl9.two"} ) ); +assert.soon( function() { + if ( -1 == s.getDB( baseName ).getCollectionNames().indexOf( "two" ) ) { + debug( "no two coll" ); + debug( tojson( s.getDB( baseName ).getCollectionNames() ) ); + return false; + } + if ( !s.getDB( baseName ).two.findOne() ) { + debug( "no two object" ); + return false; + } + return 1 == s.getDB( baseName ).two.findOne().a; }); +assert.eq( -1, s.getDB( baseName ).getCollectionNames().indexOf( "one" ) ); + +// rename to new db + +first = baseName + "_first"; +second = baseName + "_second"; + +m.getDB( first ).one.save( { a: 1 } ); +assert.soon( function() { return s.getDB( first ).one.findOne() && 1 == s.getDB( first ).one.findOne().a; } ); + +assert.commandWorked( admin.runCommand( {renameCollection:"jstests_repl_repl9_first.one", to:"jstests_repl_repl9_second.two"} ) ); +assert.soon( function() { + return -1 != s.getDBNames().indexOf( second ) && + -1 != s.getDB( second ).getCollectionNames().indexOf( "two" ) && + s.getDB( second ).two.findOne() && + 1 == s.getDB( second ).two.findOne().a; } ); +assert.eq( -1, s.getDB( first ).getCollectionNames().indexOf( "one" ) ); + diff --git a/jstests/repl/replacePeer1.js b/jstests/repl/replacePeer1.js new file mode 100644 index 0000000..45ee544 --- /dev/null +++ b/jstests/repl/replacePeer1.js @@ -0,0 +1,71 @@ +// test replace peer on master + +var baseName = "jstests_replacepeer1test"; + +ismaster = function( n ) { + im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); +// print( "ismaster: " + tojson( im ) ); + assert( im ); + return im.ismaster; +} + +var writeOneIdx = 0; + +writeOne = function( n ) { + n.getDB( baseName ).z.save( { _id: new ObjectId(), i: ++writeOneIdx } ); +} + +getCount = function( n ) { + return n.getDB( baseName ).z.find( { i: writeOneIdx } ).toArray().length; +} + +checkWrite = function( m, s ) { + writeOne( m ); + assert.eq( 1, getCount( m ) ); + s.setSlaveOk(); + assert.soon( function() { + return 1 == getCount( s ); + } ); +} + +doTest = function( signal ) { + + ports = allocatePorts( 4 ); + + a = new MongodRunner( ports[ 0 ], "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( ports[ 1 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 3 ], "127.0.0.1:" + ports[ 0 ] ); + r = new MongodRunner( ports[ 3 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 1 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( l, r, a ); + rp.start(); + rp.waitForSteadyState( [ 1, 0 ], rp.right().host ); + + checkWrite( rp.master(), rp.slave() ); + + rp.killNode( rp.slave(), signal ); + + writeOne( rp.master() ); + + assert.commandWorked( rp.master().getDB( "admin" ).runCommand( {replacepeer:1} ) ); + + rp.killNode( rp.master(), signal ); + rp.killNode( rp.arbiter(), signal ); + + o = new MongodRunner( ports[ 2 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 3 ], "127.0.0.1:" + ports[ 0 ] ); + r = new MongodRunner( ports[ 3 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 2 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( o, r, a ); + resetDbpath( "/data/db/" + baseName + "-left" ); + rp.start( true ); + rp.waitForSteadyState( [ 1, 0 ], rp.right().host ); + + checkWrite( rp.master(), rp.slave() ); + rp.slave().setSlaveOk(); + assert.eq( 3, rp.slave().getDB( baseName ).z.find().toArray().length ); + + ports.forEach( function( x ) { stopMongod( x ); } ); + +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/jstests/repl/replacePeer2.js b/jstests/repl/replacePeer2.js new file mode 100644 index 0000000..09c8177 --- /dev/null +++ b/jstests/repl/replacePeer2.js @@ -0,0 +1,72 @@ +// test replace peer on slave + +var baseName = "jstests_replacepeer2test"; + +ismaster = function( n ) { + im = n.getDB( "admin" ).runCommand( { "ismaster" : 1 } ); +// print( "ismaster: " + tojson( im ) ); + assert( im ); + return im.ismaster; +} + +var writeOneIdx = 0; + +writeOne = function( n ) { + n.getDB( baseName ).z.save( { _id: new ObjectId(), i: ++writeOneIdx } ); +} + +getCount = function( n ) { + return n.getDB( baseName ).z.find( { i: writeOneIdx } ).toArray().length; +} + +checkWrite = function( m, s ) { + writeOne( m ); + assert.eq( 1, getCount( m ) ); + s.setSlaveOk(); + assert.soon( function() { + return 1 == getCount( s ); + } ); +} + +doTest = function( signal ) { + + ports = allocatePorts( 4 ); + + a = new MongodRunner( ports[ 0 ], "/data/db/" + baseName + "-arbiter" ); + l = new MongodRunner( ports[ 1 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 3 ], "127.0.0.1:" + ports[ 0 ] ); + r = new MongodRunner( ports[ 3 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 1 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( l, r, a ); + rp.start(); + rp.waitForSteadyState( [ 1, 0 ], rp.right().host ); + + checkWrite( rp.master(), rp.slave() ); + + // allow slave to finish initial sync + assert.soon( function() { return 1 == rp.slave().getDB( "admin" ).runCommand( {replacepeer:1} ).ok; } ); + + // Should not be saved to slave. + writeOne( rp.master() ); + // Make sure there would be enough time to save to l if we hadn't called replacepeer. + sleep( 10000 ); + + ports.forEach( function( x ) { stopMongod( x, signal ); } ); + + l = new MongodRunner( ports[ 1 ], "/data/db/" + baseName + "-left", "127.0.0.1:" + ports[ 2 ], "127.0.0.1:" + ports[ 0 ] ); + o = new MongodRunner( ports[ 2 ], "/data/db/" + baseName + "-right", "127.0.0.1:" + ports[ 1 ], "127.0.0.1:" + ports[ 0 ] ); + + rp = new ReplPair( l, o, a ); + resetDbpath( "/data/db/" + baseName + "-right" ); + rp.start( true ); + rp.waitForSteadyState( [ 1, 0 ], rp.left().host ); + + checkWrite( rp.master(), rp.slave() ); + rp.slave().setSlaveOk(); + assert.eq( 2, rp.slave().getDB( baseName ).z.find().toArray().length ); + + ports.forEach( function( x ) { stopMongod( x ); } ); + +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL |