diff options
author | Shaun Verch <shaun.verch@10gen.com> | 2013-02-15 12:42:08 -0800 |
---|---|---|
committer | Dan Pasette <dan@10gen.com> | 2013-03-29 11:37:59 -0400 |
commit | ffe9de8df384792315c40c65209c1932778b52a8 (patch) | |
tree | dcbb9df04997b9ea9f66b803f74b2bd3d2c8e04e | |
parent | 2e87ed15f0875087136404e78fecdbbb4a75e584 (diff) | |
download | mongo-ffe9de8df384792315c40c65209c1932778b52a8.tar.gz |
SERVER-8819 Framework for testing round trip and test roundtrip of DBRef and DBPointer
-rw-r--r-- | src/mongo/dbtests/jstests.cpp | 211 |
1 files changed, 156 insertions, 55 deletions
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp index 36f432438b0..c3c9bff6f3b 100644 --- a/src/mongo/dbtests/jstests.cpp +++ b/src/mongo/dbtests/jstests.cpp @@ -955,70 +955,168 @@ namespace JSTests { } }; - class DBRefTest { - public: - DBRefTest() { - _a = "unittest.dbref.a"; - _b = "unittest.dbref.b"; - reset(); - } - ~DBRefTest() { - //reset(); - } + namespace RoundTripTests { - void run() { + // Inherit from this class to test round tripping of JSON objects + class TestRoundTrip { + public: + virtual ~TestRoundTrip() {} + void run() { - client.insert( _a , BSON( "a" << "17" ) ); + // Insert in Javascript -> Find using DBDirectClient - { - BSONObj fromA = client.findOne( _a , BSONObj() ); - verify( fromA.valid() ); - //cout << "Froma : " << fromA << endl; + // Drop the collection + client.dropCollection( "unittest.testroundtrip" ); + + // Insert in Javascript + stringstream jsInsert; + jsInsert << "db.testroundtrip.insert(" << jsonIn() << ")"; + ASSERT_TRUE( client.eval( "unittest" , jsInsert.str() ) ); + + // Find using DBDirectClient + BSONObj excludeIdProjection = BSON( "_id" << 0 ); + BSONObj directFind = client.findOne( "unittest.testroundtrip", + "", + &excludeIdProjection); + bsonEquals( bson(), directFind ); + + + // Insert using DBDirectClient -> Find in Javascript + + // Drop the collection + client.dropCollection( "unittest.testroundtrip" ); + + // Insert using DBDirectClient + client.insert( "unittest.testroundtrip" , bson() ); + + // Find in Javascript + stringstream jsFind; + jsFind << "dbref = db.testroundtrip.findOne( { } , { _id : 0 } )\n" + << "assert.eq(dbref, " << jsonOut() << ")"; + ASSERT_TRUE( client.eval( "unittest" , jsFind.str() ) ); + } + protected: + + // Methods that must be defined by child classes + virtual BSONObj bson() const = 0; + virtual string json() const = 0; + + // This can be overriden if a different meaning of equality besides woCompare is needed + virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) { + if ( expected.woCompare( actual ) ) { + out() << "want:" << expected.jsonString() << " size: " << expected.objsize() << endl; + out() << "got :" << actual.jsonString() << " size: " << actual.objsize() << endl; + out() << expected.hexDump() << endl; + out() << actual.hexDump() << endl; + } + ASSERT( !expected.woCompare( actual ) ); + } + + // This can be overriden if the JSON representation is altered on the round trip + virtual string jsonIn() const { + return json(); + } + virtual string jsonOut() const { + return json(); + } + }; + + class DBRefTest : public TestRoundTrip { + virtual BSONObj bson() const { BSONObjBuilder b; - b.append( "b" , 18 ); - b.appendDBRef( "c" , "dbref.a" , fromA["_id"].__oid() ); - client.insert( _b , b.obj() ); + OID o; + memset( &o, 0, 12 ); + BSONObjBuilder subBuilder(b.subobjStart("a")); + subBuilder.append("$ref", "ns"); + subBuilder.append("$id", o); + subBuilder.done(); + return b.obj(); + } + virtual string json() const { + return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }"; } - ASSERT( client.eval( "unittest" , "x = db.dbref.b.findOne(); assert.eq( 17 , x.c.fetch().a , 'ref working' );" ) ); + // A "fetch" function is added to the DBRef object when it is inserted using the + // constructor, so we need to compare the fields individually + virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) { + ASSERT_EQUALS( expected["a"].type() , actual["a"].type() ); + ASSERT_EQUALS( expected["a"]["$id"].OID() , actual["a"]["$id"].OID() ); + ASSERT_EQUALS( expected["a"]["$ref"].String() , actual["a"]["$ref"].String() ); + } + }; - // BSON DBRef <=> JS DBPointer - ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBPointer( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) ); - ASSERT_EQUALS( DBRef, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() ); + class DBPointerTest : public TestRoundTrip { + virtual BSONObj bson() const { + BSONObjBuilder b; + OID o; + memset( &o, 0, 12 ); + b.appendDBRef( "a" , "ns" , o ); + return b.obj(); + } + virtual string json() const { + return "{ \"a\" : DBPointer( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }"; + } + }; - // BSON Object <=> JS DBRef - ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBRef( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) ); - ASSERT_EQUALS( Object, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() ); - ASSERT_EQUALS( string( "dbref.a" ), client.findOne( "unittest.dbref.b", "" )[ "c" ].embeddedObject().getStringField( "$ref" ) ); - } + class InformalDBRefTest : public TestRoundTrip { + virtual BSONObj bson() const { + BSONObjBuilder b; + OID o; + memset( &o, 0, 12 ); + BSONObjBuilder subBuilder(b.subobjStart("a")); + subBuilder.append("$ref", "ns"); + subBuilder.append("$id", o); + subBuilder.done(); + return b.obj(); + } - void reset() { - client.dropCollection( _a ); - client.dropCollection( _b ); - } + // Don't need to return anything because we are overriding both jsonOut and jsonIn + virtual string json() const { return ""; } - const char * _a; - const char * _b; - }; + // Need to override these because the JSON doesn't actually round trip. + // An object with "$ref" and "$id" fields is handled specially and different on the way out. + virtual string jsonOut() const { + return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }"; + } + virtual string jsonIn() const { + stringstream ss; + ss << "{ \"a\" : { \"$ref\" : \"ns\" , " << + "\"$id\" : ObjectId( \"000000000000000000000000\" ) } }"; + return ss.str(); + } + }; - class InformalDBRef { - public: - void run() { - client.insert( ns(), BSON( "i" << 1 ) ); - BSONObj obj = client.findOne( ns(), BSONObj() ); - client.remove( ns(), BSONObj() ); - client.insert( ns(), BSON( "r" << BSON( "$ref" << "jstests.informaldbref" << "$id" << obj["_id"].__oid() << "foo" << "bar" ) ) ); - obj = client.findOne( ns(), BSONObj() ); - ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() ); - - ASSERT( client.eval( "unittest", "x = db.jstests.informaldbref.findOne(); y = { r:x.r }; db.jstests.informaldbref.drop(); y.r[ \"a\" ] = \"b\"; db.jstests.informaldbref.save( y );" ) ); - obj = client.findOne( ns(), BSONObj() ); - ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() ); - ASSERT_EQUALS( "b", obj[ "r" ].embeddedObject()[ "a" ].str() ); - } - private: - static const char *ns() { return "unittest.jstests.informaldbref"; } - }; + class InformalDBRefExtraFieldTest : public TestRoundTrip { + virtual BSONObj bson() const { + BSONObjBuilder b; + OID o; + memset( &o, 0, 12 ); + BSONObjBuilder subBuilder(b.subobjStart("a")); + subBuilder.append("$ref", "ns"); + subBuilder.append("$id", o); + subBuilder.append("otherfield", "value"); + subBuilder.done(); + return b.obj(); + } + + // Don't need to return anything because we are overriding both jsonOut and jsonIn + virtual string json() const { return ""; } + + // Need to override these because the JSON doesn't actually round trip. + // An object with "$ref" and "$id" fields is handled specially and different on the way out. + virtual string jsonOut() const { + return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }"; + } + virtual string jsonIn() const { + stringstream ss; + ss << "{ \"a\" : { \"$ref\" : \"ns\" , " << + "\"$id\" : ObjectId( \"000000000000000000000000\" ) , " << + "\"otherfield\" : \"value\" } }"; + return ss.str(); + } + }; + + } // namespace RoundTripTests class BinDataType { public: @@ -1219,8 +1317,6 @@ namespace JSTests { add< WeirdObjects >(); add< CodeTests >(); - add< DBRefTest >(); - add< InformalDBRef >(); add< BinDataType >(); add< VarTests >(); @@ -1233,6 +1329,11 @@ namespace JSTests { add< ScopeOut >(); add< InvalidStoredJS >(); + + add< RoundTripTests::DBRefTest >(); + add< RoundTripTests::DBPointerTest >(); + add< RoundTripTests::InformalDBRefTest >(); + add< RoundTripTests::InformalDBRefExtraFieldTest >(); } } myall; |