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