summaryrefslogtreecommitdiff
path: root/src/mongo/dbtests/repltests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/dbtests/repltests.cpp')
-rw-r--r--src/mongo/dbtests/repltests.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/mongo/dbtests/repltests.cpp b/src/mongo/dbtests/repltests.cpp
index 23ae7680092..754556ae540 100644
--- a/src/mongo/dbtests/repltests.cpp
+++ b/src/mongo/dbtests/repltests.cpp
@@ -815,6 +815,23 @@ namespace ReplTests {
}
};
+ class PushWithDollarSigns : public Base {
+ void doIt() const {
+ client()->update( ns(),
+ BSON( "_id" << 0),
+ BSON( "$push" << BSON( "a" << BSON( "$foo" << 1 ) ) ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{'_id':0, a:[0, {'$foo':1}]}"), one( fromjson( "{'_id':0}" ) ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( BSON( "_id" << 0 << "a" << BSON_ARRAY( 0 ) ) );
+ }
+ };
+
class PushAllUpsert : public Base {
public:
void doIt() const {
@@ -1009,6 +1026,138 @@ namespace ReplTests {
}
};
+ class NestedNoRename : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSON( "_id" << 0 ),
+ fromjson( "{$rename:{'a.b':'c.d'},$set:{z:1}}"
+ ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( BSON( "_id" << 0 << "z" << 1 ) , one( fromjson("{'_id':0}" ) ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( fromjson( "{'_id':0}" ) );
+ }
+ };
+
+ class SingletonNoRename : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSONObj(), fromjson("{$rename:{a:'b'}}" ) );
+
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{_id:0,z:1}" ), one(fromjson("{'_id':0}" ) ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( fromjson( "{'_id':0,z:1}" ) );
+ }
+ };
+
+ class IndexedSingletonNoRename : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSONObj(), fromjson("{$rename:{a:'b'}}" ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{_id:0,z:1}" ), one(fromjson("{'_id':0}" ) ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ // Add an index on 'a'. This prevents the update from running 'in place'.
+ client()->ensureIndex( ns(), BSON( "a" << 1 ) );
+ insert( fromjson( "{'_id':0,z:1}" ) );
+ }
+ };
+
+ class AddToSetEmptyMissing : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSON( "_id" << 0 ), fromjson(
+ "{$addToSet:{a:{$each:[]}}}" ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{_id:0,a:[]}" ), one( fromjson("{'_id':0}" ) )
+ );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( fromjson( "{'_id':0}" ) );
+ }
+ };
+
+ class AddToSetWithDollarSigns : public Base {
+ void doIt() const {
+ client()->update( ns(),
+ BSON( "_id" << 0),
+ BSON( "$addToSet" << BSON( "a" << BSON( "$foo" << 1 ) ) ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{'_id':0, a:[0, {'$foo':1}]}"), one( fromjson( "{'_id':0}" ) ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( BSON( "_id" << 0 << "a" << BSON_ARRAY( 0 ) ) );
+ }
+ };
+
+ //
+ // replay cases
+ //
+
+ class ReplaySetPreexistingNoOpPull : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSONObj(), fromjson( "{$unset:{z:1}}" ));
+
+ // This is logged as {$set:{'a.b':[]},$set:{z:1}}, which might not be
+ // replayable against future versions of a document (here {_id:0,a:1,z:1}) due
+ // to SERVER-4781. As a result the $set:{z:1} will not be replayed in such
+ // cases (and also an exception may abort replication). If this were instead
+ // logged as {$set:{z:1}}, SERVER-4781 would not be triggered.
+ client()->update( ns(), BSONObj(), fromjson( "{$pull:{'a.b':1}, $set:{z:1}}" ) );
+ client()->update( ns(), BSONObj(), fromjson( "{$set:{a:1}}" ) );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{_id:0,a:1,z:1}" ), one( fromjson("{'_id':0}") ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( fromjson( "{'_id':0,a:{b:[]},z:1}" ) );
+ }
+ };
+
+ class ReplayArrayFieldNotAppended : public Base {
+ public:
+ void doIt() const {
+ client()->update( ns(), BSONObj(), fromjson( "{$push:{'a.0.b':2}}" ) );
+ client()->update( ns(), BSONObj(), fromjson( "{$set:{'a.0':1}}") );
+ }
+ using ReplTests::Base::check;
+ void check() const {
+ ASSERT_EQUALS( 1, count() );
+ check( fromjson( "{_id:0,a:[1,{b:[1]}]}" ), one(fromjson("{'_id':0}") ) );
+ }
+ void reset() const {
+ deleteAll( ns() );
+ insert( fromjson( "{'_id':0,a:[{b:[0]},{b:[1]}]}" ) );
+ }
+ };
} // namespace Idempotence
@@ -1218,6 +1367,7 @@ namespace ReplTests {
add< Idempotence::EmptyPush >();
add< Idempotence::EmptyPushSparseIndex >();
add< Idempotence::PushAll >();
+ add< Idempotence::PushWithDollarSigns >();
add< Idempotence::PushAllUpsert >();
add< Idempotence::EmptyPushAll >();
add< Idempotence::Pull >();
@@ -1230,6 +1380,13 @@ namespace ReplTests {
add< Idempotence::RenameReplace >();
add< Idempotence::RenameOverwrite >();
add< Idempotence::NoRename >();
+ add< Idempotence::NestedNoRename >();
+ add< Idempotence::SingletonNoRename >();
+ add< Idempotence::IndexedSingletonNoRename >();
+ add< Idempotence::AddToSetEmptyMissing >();
+ add< Idempotence::AddToSetWithDollarSigns >();
+ add< Idempotence::ReplaySetPreexistingNoOpPull >();
+ add< Idempotence::ReplayArrayFieldNotAppended >();
add< DeleteOpIsIdBased >();
add< DatabaseIgnorerBasic >();
add< DatabaseIgnorerUpdate >();