diff options
Diffstat (limited to 'dbtests')
-rw-r--r-- | dbtests/basictests.cpp | 89 | ||||
-rw-r--r-- | dbtests/btreetests.cpp | 7 | ||||
-rw-r--r-- | dbtests/clienttests.cpp | 74 | ||||
-rw-r--r-- | dbtests/cursortests.cpp | 8 | ||||
-rw-r--r-- | dbtests/dbtests.cpp | 1 | ||||
-rw-r--r-- | dbtests/framework.cpp | 2 | ||||
-rw-r--r-- | dbtests/jsobjtests.cpp | 239 | ||||
-rw-r--r-- | dbtests/jsontests.cpp | 4 | ||||
-rw-r--r-- | dbtests/jstests.cpp | 130 | ||||
-rw-r--r-- | dbtests/namespacetests.cpp | 11 | ||||
-rw-r--r-- | dbtests/pairingtests.cpp | 2 | ||||
-rw-r--r-- | dbtests/pdfiletests.cpp | 8 | ||||
-rw-r--r-- | dbtests/perf/perftest.cpp | 6 | ||||
-rw-r--r-- | dbtests/queryoptimizertests.cpp | 40 | ||||
-rw-r--r-- | dbtests/querytests.cpp | 196 | ||||
-rw-r--r-- | dbtests/repltests.cpp | 112 | ||||
-rw-r--r-- | dbtests/test.vcproj | 78 | ||||
-rw-r--r-- | dbtests/threadedtests.cpp | 24 | ||||
-rw-r--r-- | dbtests/updatetests.cpp | 25 |
19 files changed, 899 insertions, 157 deletions
diff --git a/dbtests/basictests.cpp b/dbtests/basictests.cpp index 20dc6d7..eaadf75 100644 --- a/dbtests/basictests.cpp +++ b/dbtests/basictests.cpp @@ -21,6 +21,7 @@ #include "dbtests.h" #include "../util/base64.h" +#include "../util/array.h" namespace BasicTests { @@ -227,6 +228,91 @@ namespace BasicTests { ASSERT_EQUALS( 1 , x ); } }; + + namespace ArrayTests { + class basic1 { + public: + void run(){ + FastArray<int> a(100); + a.push_back( 5 ); + a.push_back( 6 ); + + ASSERT_EQUALS( 2 , a.size() ); + + FastArray<int>::iterator i = a.begin(); + ASSERT( i != a.end() ); + ASSERT_EQUALS( 5 , *i ); + ++i; + ASSERT( i != a.end() ); + ASSERT_EQUALS( 6 , *i ); + ++i; + ASSERT( i == a.end() ); + } + }; + }; + + class ThreadSafeStringTest { + public: + void run(){ + ThreadSafeString s; + s = "eliot"; + ASSERT_EQUALS( s , "eliot" ); + ASSERT( s != "eliot2" ); + + ThreadSafeString s2 = s; + ASSERT_EQUALS( s2 , "eliot" ); + + + { + string foo; + { + ThreadSafeString bar; + bar = "eliot2"; + foo = bar; + } + ASSERT_EQUALS( "eliot2" , foo ); + } + } + }; + + class LexNumCmp { + public: + void run() { + ASSERT_EQUALS( 0, lexNumCmp( "a", "a" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "a", "aa" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "aa", "a" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "a", "b" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "100", "50" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "50", "100" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "b", "a" ) ); + ASSERT_EQUALS( 0, lexNumCmp( "aa", "aa" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "aa", "ab" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "ab", "aa" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "0", "a" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "a0", "aa" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "a", "0" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "aa", "a0" ) ); + ASSERT_EQUALS( 0, lexNumCmp( "0", "0" ) ); + ASSERT_EQUALS( 0, lexNumCmp( "10", "10" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "1", "10" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "10", "1" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "11", "10" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "10", "11" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "f11f", "f10f" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "f10f", "f11f" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "f11f", "f111" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "f111", "f11f" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "f12f", "f12g" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "f12g", "f12f" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "aa{", "aab" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "aa{", "aa1" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "a1{", "a11" ) ); + ASSERT_EQUALS( 1, lexNumCmp( "a1{a", "a1{" ) ); + ASSERT_EQUALS( -1, lexNumCmp( "a1{", "a1{a" ) ); + ASSERT_EQUALS( 1, lexNumCmp("21", "11") ); + ASSERT_EQUALS( -1, lexNumCmp("11", "21") ); + } + }; class All : public Suite { public: @@ -244,6 +330,9 @@ namespace BasicTests { add< sleeptest >(); add< AssertTests >(); + + add< ArrayTests::basic1 >(); + add< LexNumCmp >(); } } myall; diff --git a/dbtests/btreetests.cpp b/dbtests/btreetests.cpp index 5a0b15d..3c9dc8d 100644 --- a/dbtests/btreetests.cpp +++ b/dbtests/btreetests.cpp @@ -28,14 +28,14 @@ namespace BtreeTests { class Base { public: - Base() { + Base() : + _context( ns() ) { + { bool f = false; assert( f = true ); massert( 10402 , "assert is misdefined", f); } - - setClient( ns() ); BSONObjBuilder builder; builder.append( "ns", ns() ); builder.append( "name", "testIndex" ); @@ -100,6 +100,7 @@ namespace BtreeTests { } private: dblock lk_; + Client::Context _context; IndexDetails idx_; }; diff --git a/dbtests/clienttests.cpp b/dbtests/clienttests.cpp index 1dadd1a..6735a40 100644 --- a/dbtests/clienttests.cpp +++ b/dbtests/clienttests.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2010 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/>. + */ + // client.cpp #include "stdafx.h" @@ -82,7 +98,62 @@ namespace ClientTests { }; + class CS_10 : public Base { + public: + CS_10() : Base( "CS_10" ) {} + void run() { + string longs( 770, 'c' ); + for( int i = 0; i < 1111; ++i ) + db.insert( ns(), BSON( "a" << i << "b" << longs ) ); + db.ensureIndex( ns(), BSON( "a" << 1 << "b" << 1 ) ); + + auto_ptr< DBClientCursor > c = db.query( ns(), Query().sort( BSON( "a" << 1 << "b" << 1 ) ) ); + ASSERT_EQUALS( 1111, c->itcount() ); + } + }; + class PushBack : public Base { + public: + PushBack() : Base( "PushBack" ) {} + void run() { + for( int i = 0; i < 10; ++i ) + db.insert( ns(), BSON( "i" << i ) ); + auto_ptr< DBClientCursor > c = db.query( ns(), Query().sort( BSON( "i" << 1 ) ) ); + BSONObj o = c->next(); + ASSERT( c->more() ); + ASSERT( c->moreInCurrentBatch() ); + c->putBack( o ); + ASSERT( c->more() ); + ASSERT( c->moreInCurrentBatch() ); + o = c->next(); + BSONObj o2 = c->next(); + BSONObj o3 = c->next(); + c->putBack( o3 ); + c->putBack( o2 ); + c->putBack( o ); + for( int i = 0; i < 10; ++i ) { + o = c->next(); + ASSERT_EQUALS( i, o[ "i" ].number() ); + } + ASSERT( !c->more() ); + ASSERT( !c->moreInCurrentBatch() ); + c->putBack( o ); + ASSERT( c->more() ); + ASSERT( c->moreInCurrentBatch() ); + ASSERT_EQUALS( 1, c->itcount() ); + } + }; + + class Create : public Base { + public: + Create() : Base( "Create" ) {} + void run() { + db.createCollection( "unittests.clienttests.create", 0, true ); + BSONObj info; + ASSERT( db.runCommand( "unittests", BSON( "collstats" << "clienttests.create" ), info ) ); + } + }; + class All : public Suite { public: All() : Suite( "client" ){ @@ -92,6 +163,9 @@ namespace ClientTests { add<DropIndex>(); add<ReIndex>(); add<ReIndex2>(); + add<CS_10>(); + add<PushBack>(); + add<Create>(); } } all; diff --git a/dbtests/cursortests.cpp b/dbtests/cursortests.cpp index 28a4ba4..f14c5fa 100644 --- a/dbtests/cursortests.cpp +++ b/dbtests/cursortests.cpp @@ -42,7 +42,7 @@ namespace CursorTests { BoundList b; b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 1 ), BSON( "" << 2 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 4 ), BSON( "" << 6 ) ) ); - setClient( ns ); + Client::Context ctx( ns ); BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, 1 ); ASSERT_EQUALS( "BtreeCursor a_1 multi", c.toString() ); double expected[] = { 1, 2, 4, 5, 6 }; @@ -72,7 +72,7 @@ namespace CursorTests { b.push_back( pair< BSONObj, BSONObj >( BSON( "" << -50 ), BSON( "" << 2 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 40 ), BSON( "" << 60 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 109 ), BSON( "" << 200 ) ) ); - setClient( ns ); + Client::Context ctx( ns ); BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, 1 ); ASSERT_EQUALS( "BtreeCursor a_1 multi", c.toString() ); double expected[] = { 0, 1, 2, 109 }; @@ -99,7 +99,7 @@ namespace CursorTests { BoundList b; b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 6 ), BSON( "" << 4 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 2 ), BSON( "" << 1 ) ) ); - setClient( ns ); + Client::Context ctx( ns ); BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, -1 ); ASSERT_EQUALS( "BtreeCursor a_1 reverse multi", c.toString() ); double expected[] = { 6, 5, 4, 2, 1 }; @@ -112,7 +112,7 @@ namespace CursorTests { } }; - } // namespace MultiBtreeCursorTests + } // namespace BtreeCursorTests class All : public Suite { public: diff --git a/dbtests/dbtests.cpp b/dbtests/dbtests.cpp index 3821163..4b81ea9 100644 --- a/dbtests/dbtests.cpp +++ b/dbtests/dbtests.cpp @@ -22,6 +22,7 @@ #include "dbtests.h" int main( int argc, char** argv ) { + static StaticObserver StaticObserver; return Suite::run(argc, argv, "/tmp/unittest"); } diff --git a/dbtests/framework.cpp b/dbtests/framework.cpp index 6ed5e72..4553686 100644 --- a/dbtests/framework.cpp +++ b/dbtests/framework.cpp @@ -358,4 +358,6 @@ namespace mongo { } } + + void setupSignals(){} } diff --git a/dbtests/jsobjtests.cpp b/dbtests/jsobjtests.cpp index 0402426..e470e60 100644 --- a/dbtests/jsobjtests.cpp +++ b/dbtests/jsobjtests.cpp @@ -251,6 +251,133 @@ namespace JsobjTests { } }; + class AsTempObj{ + public: + void run(){ + { + BSONObjBuilder bb; + bb << "a" << 1; + BSONObj tmp = bb.asTempObj(); + ASSERT(tmp.objsize() == 4+(1+2+4)+1); + ASSERT(tmp.valid()); + ASSERT(tmp.hasField("a")); + ASSERT(!tmp.hasField("b")); + ASSERT(tmp == BSON("a" << 1)); + + bb << "b" << 2; + BSONObj obj = bb.obj(); + ASSERT(obj.objsize() == 4+(1+2+4)+(1+2+4)+1); + ASSERT(obj.valid()); + ASSERT(obj.hasField("a")); + ASSERT(obj.hasField("b")); + ASSERT(obj == BSON("a" << 1 << "b" << 2)); + } + { + BSONObjBuilder bb; + bb << "a" << GT << 1; + BSONObj tmp = bb.asTempObj(); + ASSERT(tmp.objsize() == 4+(1+2+(4+1+4+4+1))+1); + ASSERT(tmp.valid()); + ASSERT(tmp.hasField("a")); + ASSERT(!tmp.hasField("b")); + ASSERT(tmp == BSON("a" << BSON("$gt" << 1))); + + bb << "b" << LT << 2; + BSONObj obj = bb.obj(); + ASSERT(obj.objsize() == 4+(1+2+(4+1+4+4+1))+(1+2+(4+1+4+4+1))+1); + ASSERT(obj.valid()); + ASSERT(obj.hasField("a")); + ASSERT(obj.hasField("b")); + ASSERT(obj == BSON("a" << BSON("$gt" << 1) + << "b" << BSON("$lt" << 2))); + } + { + BSONObjBuilder bb(32); + bb << "a" << 1; + BSONObj tmp = bb.asTempObj(); + ASSERT(tmp.objsize() == 4+(1+2+4)+1); + ASSERT(tmp.valid()); + ASSERT(tmp.hasField("a")); + ASSERT(!tmp.hasField("b")); + ASSERT(tmp == BSON("a" << 1)); + + //force a realloc + BSONArrayBuilder arr; + for (int i=0; i < 10000; i++){ + arr << i; + } + bb << "b" << arr.arr(); + BSONObj obj = bb.obj(); + ASSERT(obj.valid()); + ASSERT(obj.hasField("a")); + ASSERT(obj.hasField("b")); + ASSERT(obj.objdata() != tmp.objdata()); + } + } + }; + + struct AppendIntOrLL{ + void run(){ + const long long billion = 1000*1000*1000; + BSONObjBuilder b; + b.appendIntOrLL("i1", 1); + b.appendIntOrLL("i2", -1); + b.appendIntOrLL("i3", 1*billion); + b.appendIntOrLL("i4", -1*billion); + + b.appendIntOrLL("L1", 2*billion); + b.appendIntOrLL("L2", -2*billion); + b.appendIntOrLL("L3", 4*billion); + b.appendIntOrLL("L4", -4*billion); + b.appendIntOrLL("L5", 16*billion); + b.appendIntOrLL("L6", -16*billion); + + BSONObj o = b.obj(); + + ASSERT(o["i1"].type() == NumberInt); + ASSERT(o["i1"].number() == 1); + ASSERT(o["i2"].type() == NumberInt); + ASSERT(o["i2"].number() == -1); + ASSERT(o["i3"].type() == NumberInt); + ASSERT(o["i3"].number() == 1*billion); + ASSERT(o["i4"].type() == NumberInt); + ASSERT(o["i4"].number() == -1*billion); + + ASSERT(o["L1"].type() == NumberLong); + ASSERT(o["L1"].number() == 2*billion); + ASSERT(o["L2"].type() == NumberLong); + ASSERT(o["L2"].number() == -2*billion); + ASSERT(o["L3"].type() == NumberLong); + ASSERT(o["L3"].number() == 4*billion); + ASSERT(o["L4"].type() == NumberLong); + ASSERT(o["L4"].number() == -4*billion); + ASSERT(o["L5"].type() == NumberLong); + ASSERT(o["L5"].number() == 16*billion); + ASSERT(o["L6"].type() == NumberLong); + ASSERT(o["L6"].number() == -16*billion); + } + }; + + struct AppendNumber { + void run(){ + BSONObjBuilder b; + b.appendNumber( "a" , 5 ); + b.appendNumber( "b" , 5.5 ); + b.appendNumber( "c" , (1024LL*1024*1024)-1 ); + b.appendNumber( "d" , (1024LL*1024*1024*1024)-1 ); + b.appendNumber( "e" , 1024LL*1024*1024*1024*1024*1024 ); + + BSONObj o = b.obj(); + + ASSERT( o["a"].type() == NumberInt ); + ASSERT( o["b"].type() == NumberDouble ); + ASSERT( o["c"].type() == NumberInt ); + ASSERT( o["d"].type() == NumberDouble ); + ASSERT( o["e"].type() == NumberLong ); + + } + }; + namespace Validation { class Base { @@ -339,8 +466,9 @@ namespace JsobjTests { } BSONObj invalid() const { BSONObj ret = valid(); - set( ret, 0, get( ret, 0 ) + 1 ); - set( ret, 7, get( ret, 7 ) + 1 ); + ASSERT_EQUALS( ret.firstElement().valuestr()[0] , 'b' ); + ASSERT_EQUALS( ret.firstElement().valuestr()[1] , 0 ); + ((char*)ret.firstElement().valuestr())[1] = 1; return ret.copy(); } }; @@ -391,32 +519,6 @@ namespace JsobjTests { }; }; - class WrongSymbolSize : public Base { - BSONObj valid() const { - return fromjson( "{\"a\":\"b\"}" ); - } - BSONObj invalid() const { - BSONObj ret = valid(); - set( ret, 4, Symbol ); - set( ret, 0, get( ret, 0 ) + 1 ); - set( ret, 7, get( ret, 7 ) + 1 ); - return ret.copy(); - } - }; - - class WrongCodeSize : public Base { - BSONObj valid() const { - return fromjson( "{\"a\":\"b\"}" ); - } - BSONObj invalid() const { - BSONObj ret = valid(); - set( ret, 4, Code ); - set( ret, 0, get( ret, 0 ) + 1 ); - set( ret, 7, get( ret, 7 ) + 1 ); - return ret.copy(); - } - }; - class NoFieldNameEnd : public Base { BSONObj valid() const { return fromjson( "{\"a\":1}" ); @@ -759,7 +861,9 @@ namespace JsobjTests { public: void run() { Date_t before = jsTime(); + sleepmillis(1); time_t now = time(NULL); + sleepmillis(1); Date_t after = jsTime(); BSONObjBuilder b; @@ -1245,6 +1349,77 @@ namespace JsobjTests { } }; + class InvalidIDFind { + public: + void run(){ + BSONObj x = BSON( "_id" << 5 << "t" << 2 ); + { + char * crap = (char*)malloc( x.objsize() ); + memcpy( crap , x.objdata() , x.objsize() ); + BSONObj y( crap , false ); + ASSERT_EQUALS( x , y ); + free( crap ); + } + + { + char * crap = (char*)malloc( x.objsize() ); + memcpy( crap , x.objdata() , x.objsize() ); + int * foo = (int*)crap; + foo[0] = 123123123; + int state = 0; + try { + BSONObj y( crap , false ); + state = 1; + } + catch ( std::exception& e ){ + state = 2; + ASSERT( strstr( e.what() , "_id: 5" ) > 0 ); + } + free( crap ); + ASSERT_EQUALS( 2 , state ); + } + + + } + }; + + class ElementSetTest { + public: + void run(){ + BSONObj x = BSON( "a" << 1 << "b" << 1 << "c" << 2 ); + BSONElement a = x["a"]; + BSONElement b = x["b"]; + BSONElement c = x["c"]; + cout << "c: " << c << endl; + ASSERT( a.woCompare( b ) != 0 ); + ASSERT( a.woCompare( b , false ) == 0 ); + + BSONElementSet s; + s.insert( a ); + ASSERT_EQUALS( 1U , s.size() ); + s.insert( b ); + ASSERT_EQUALS( 1U , s.size() ); + ASSERT( ! s.count( c ) ); + + ASSERT( s.find( a ) != s.end() ); + ASSERT( s.find( b ) != s.end() ); + ASSERT( s.find( c ) == s.end() ); + + + s.insert( c ); + ASSERT_EQUALS( 2U , s.size() ); + + + ASSERT( s.find( a ) != s.end() ); + ASSERT( s.find( b ) != s.end() ); + ASSERT( s.find( c ) != s.end() ); + + ASSERT( s.count( a ) ); + ASSERT( s.count( b ) ); + ASSERT( s.count( c ) ); + } + }; + class All : public Suite { public: All() : Suite( "jsobj" ){ @@ -1264,6 +1439,9 @@ namespace JsobjTests { add< BSONObjTests::MultiKeySortOrder > (); add< BSONObjTests::TimestampTest >(); add< BSONObjTests::Nan >(); + add< BSONObjTests::AsTempObj >(); + add< BSONObjTests::AppendIntOrLL >(); + add< BSONObjTests::AppendNumber >(); add< BSONObjTests::Validation::BadType >(); add< BSONObjTests::Validation::EooBeforeEnd >(); add< BSONObjTests::Validation::Undefined >(); @@ -1274,8 +1452,6 @@ namespace JsobjTests { add< BSONObjTests::Validation::NegativeStringSize >(); add< BSONObjTests::Validation::WrongSubobjectSize >(); add< BSONObjTests::Validation::WrongDbrefNsSize >(); - add< BSONObjTests::Validation::WrongSymbolSize >(); - add< BSONObjTests::Validation::WrongCodeSize >(); add< BSONObjTests::Validation::NoFieldNameEnd >(); add< BSONObjTests::Validation::BadRegex >(); add< BSONObjTests::Validation::BadRegexOptions >(); @@ -1332,7 +1508,8 @@ namespace JsobjTests { add< NumberParsing >(); add< bson2settest >(); add< checkForStorageTests >(); - + add< InvalidIDFind >(); + add< ElementSetTest >(); } } myall; diff --git a/dbtests/jsontests.cpp b/dbtests/jsontests.cpp index 68c6b5c..aa6b1a2 100644 --- a/dbtests/jsontests.cpp +++ b/dbtests/jsontests.cpp @@ -47,7 +47,7 @@ namespace JsonTests { void run() { BSONObjBuilder b; b.append( "a", "\" \\ / \b \f \n \r \t" ); - ASSERT_EQUALS( "{ \"a\" : \"\\\" \\\\ \\/ \\b \\f \\n \\r \\t\" }", b.done().jsonString( Strict ) ); + ASSERT_EQUALS( "{ \"a\" : \"\\\" \\\\ / \\b \\f \\n \\r \\t\" }", b.done().jsonString( Strict ) ); } }; @@ -304,7 +304,7 @@ namespace JsonTests { BSONObjBuilder b; b.appendRegex( "a", "/\"", "i" ); BSONObj built = b.done(); - ASSERT_EQUALS( "{ \"a\" : { \"$regex\" : \"\\/\\\"\", \"$options\" : \"i\" } }", + ASSERT_EQUALS( "{ \"a\" : { \"$regex\" : \"/\\\"\", \"$options\" : \"i\" } }", built.jsonString( Strict ) ); ASSERT_EQUALS( "{ \"a\" : /\\/\\\"/i }", built.jsonString( TenGen ) ); ASSERT_EQUALS( "{ \"a\" : /\\/\\\"/i }", built.jsonString( JS ) ); diff --git a/dbtests/jstests.cpp b/dbtests/jstests.cpp index 86b0218..454dcdc 100644 --- a/dbtests/jstests.cpp +++ b/dbtests/jstests.cpp @@ -515,6 +515,62 @@ namespace JSTests { }; + class NumberLong { + public: + void run() { + Scope * s = globalScriptEngine->newScope(); + s->localConnect( "blah" ); + BSONObjBuilder b; + long long val = (long long)( 0xbabadeadbeefbaddULL ); + b.append( "a", val ); + BSONObj in = b.obj(); + s->setObject( "a", in ); + BSONObj out = s->getObject( "a" ); + ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() ); + + ASSERT( s->exec( "printjson( a ); b = {b:a.a}", "foo", false, true, false ) ); + out = s->getObject( "b" ); + ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() ); + ASSERT_EQUALS( val, out.firstElement().numberLong() ); + + ASSERT( s->exec( "c = {c:a.a.toString()}", "foo", false, true, false ) ); + out = s->getObject( "c" ); + stringstream ss; + ss << val; + ASSERT_EQUALS( ss.str(), out.firstElement().valuestr() ); + + ASSERT( s->exec( "d = {d:a.a.toNumber()}", "foo", false, true, false ) ); + out = s->getObject( "d" ); + ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); + ASSERT_EQUALS( double( val ), out.firstElement().number() ); + + ASSERT( s->exec( "e = {e:a.a.floatApprox}", "foo", false, true, false ) ); + out = s->getObject( "e" ); + ASSERT_EQUALS( NumberDouble, out.firstElement().type() ); + ASSERT_EQUALS( double( val ), out.firstElement().number() ); + + ASSERT( s->exec( "f = {f:a.a.top}", "foo", false, true, false ) ); + out = s->getObject( "f" ); + ASSERT( NumberDouble == out.firstElement().type() || NumberInt == out.firstElement().type() ); + + s->setObject( "z", BSON( "z" << (long long)( 4 ) ) ); + ASSERT( s->exec( "y = {y:z.z.top}", "foo", false, true, false ) ); + out = s->getObject( "y" ); + ASSERT_EQUALS( Undefined, out.firstElement().type() ); + + ASSERT( s->exec( "x = {x:z.z.floatApprox}", "foo", false, true, false ) ); + out = s->getObject( "x" ); + ASSERT( NumberDouble == out.firstElement().type() || NumberInt == out.firstElement().type() ); + ASSERT_EQUALS( double( 4 ), out.firstElement().number() ); + + ASSERT( s->exec( "w = {w:z.z}", "foo", false, true, false ) ); + out = s->getObject( "w" ); + ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() ); + ASSERT_EQUALS( 4, out.firstElement().numberLong() ); + + } + }; + class WeirdObjects { public: @@ -673,6 +729,25 @@ namespace JSTests { const char * _b; }; + 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 BinDataType { public: @@ -690,7 +765,7 @@ namespace JSTests { Scope * s = globalScriptEngine->newScope(); s->localConnect( "asd" ); const char * foo = "asdas\0asdasd"; - + const char * base64 = "YXNkYXMAYXNkYXNk"; BSONObj in; { @@ -706,13 +781,30 @@ namespace JSTests { BSONObj out = s->getObject( "y" ); ASSERT_EQUALS( BinData , out["c"].type() ); - //blah( "in " , in["b"] ); - //blah( "out" , out["c"] ); +// pp( "in " , in["b"] ); +// pp( "out" , out["c"] ); ASSERT_EQUALS( 0 , in["b"].woCompare( out["c"] , false ) ); // check that BinData js class is utilized - s->invokeSafe( "q = tojson( x.b );", BSONObj() ); - ASSERT_EQUALS( "BinData", s->getString( "q" ).substr( 0, 7 ) ); + s->invokeSafe( "q = x.b.toString();", BSONObj() ); + stringstream expected; + expected << "BinData( type: " << ByteArray << ", base64: \"" << base64 << "\" )"; + ASSERT_EQUALS( expected.str(), s->getString( "q" ) ); + + stringstream scriptBuilder; + scriptBuilder << "z = { c : new BinData( " << ByteArray << ", \"" << base64 << "\" ) };"; + string script = scriptBuilder.str(); + s->invokeSafe( script.c_str(), BSONObj() ); + out = s->getObject( "z" ); +// pp( "out" , out["c"] ); + ASSERT_EQUALS( 0 , in["b"].woCompare( out["c"] , false ) ); + + s->invokeSafe( "a = { f: new BinData( 128, \"\" ) };", BSONObj() ); + out = s->getObject( "a" ); + int len = -1; + out[ "f" ].binData( len ); + ASSERT_EQUALS( 0, len ); + ASSERT_EQUALS( 128, out[ "f" ].binDataType() ); delete s; } @@ -732,6 +824,28 @@ namespace JSTests { } }; + class Speed1 { + public: + void run(){ + BSONObj start = BSON( "x" << 5 ); + BSONObj empty; + + auto_ptr<Scope> s; + s.reset( globalScriptEngine->newScope() ); + + ScriptingFunction f = s->createFunction( "return this.x + 6;" ); + s->setThis( &start ); + + Timer t; + double n = 0; + for ( ; n < 100000; n++ ){ + s->invoke( f , empty ); + ASSERT_EQUALS( 11 , s->getNumber( "return" ) ); + } + cout << "speed1: " << ( n / t.millis() ) << " ops/ms" << endl; + } + }; + class All : public Suite { public: All() : Suite( "js" ) { @@ -752,15 +866,19 @@ namespace JSTests { add< OtherJSTypes >(); add< SpecialDBTypes >(); add< TypeConservation >(); + add< NumberLong >(); add< WeirdObjects >(); add< Utf8Check >(); add< LongUtf8String >(); add< CodeTests >(); add< DBRefTest >(); + add< InformalDBRef >(); add< BinDataType >(); - + add< VarTests >(); + + add< Speed1 >(); } } myall; diff --git a/dbtests/namespacetests.cpp b/dbtests/namespacetests.cpp index c820ca6..205c5d2 100644 --- a/dbtests/namespacetests.cpp +++ b/dbtests/namespacetests.cpp @@ -30,9 +30,9 @@ namespace NamespaceTests { namespace IndexDetailsTests { class Base { dblock lk; + Client::Context _context; public: - Base() { - setClient( ns() ); + Base() : _context(ns()){ } virtual ~Base() { if ( id_.info.isNull() ) @@ -571,9 +571,11 @@ namespace NamespaceTests { namespace NamespaceDetailsTests { class Base { + const char *ns_; dblock lk; + Client::Context _context; public: - Base( const char *ns = "unittests.NamespaceDetailsTests" ) : ns_( ns ) {} + Base( const char *ns = "unittests.NamespaceDetailsTests" ) : ns_( ns ) , _context( ns ) {} virtual ~Base() { if ( !nsd() ) return; @@ -585,7 +587,6 @@ namespace NamespaceTests { protected: void create() { dblock lk; - setClient( ns() ); string err; ASSERT( userCreateNS( ns(), fromjson( spec() ), err, false ) ); } @@ -627,8 +628,6 @@ namespace NamespaceTests { b.append( "a", as ); return b.obj(); } - private: - const char *ns_; }; class Create : public Base { diff --git a/dbtests/pairingtests.cpp b/dbtests/pairingtests.cpp index b3e772b..e832310 100644 --- a/dbtests/pairingtests.cpp +++ b/dbtests/pairingtests.cpp @@ -144,7 +144,7 @@ namespace PairingTests { ReplPair rp( "a", "b" ); rp.setMaster( ReplPair::State_CantArb, "foo" ); ASSERT( rp.state == ReplPair::State_CantArb ); - ASSERT_EQUALS( "foo", rp.info ); + ASSERT_EQUALS( rp.info , "foo" ); rp.setMaster( ReplPair::State_Confused, "foo" ); ASSERT( rp.state == ReplPair::State_Confused ); } diff --git a/dbtests/pdfiletests.cpp b/dbtests/pdfiletests.cpp index 17659c0..fbacf8b 100644 --- a/dbtests/pdfiletests.cpp +++ b/dbtests/pdfiletests.cpp @@ -31,8 +31,7 @@ namespace PdfileTests { class Base { public: - Base() { - setClient( ns() ); + Base() : _context( ns() ){ } virtual ~Base() { if ( !nsd() ) @@ -99,6 +98,7 @@ namespace PdfileTests { } private: dblock lk_; + Client::Context _context; }; class Empty : public Base { @@ -269,8 +269,7 @@ namespace PdfileTests { namespace Insert { class Base { public: - Base() { - setClient( ns() ); + Base() : _context( ns() ){ } virtual ~Base() { if ( !nsd() ) @@ -287,6 +286,7 @@ namespace PdfileTests { } private: dblock lk_; + Client::Context _context; }; class UpdateDate : public Base { diff --git a/dbtests/perf/perftest.cpp b/dbtests/perf/perftest.cpp index 6fe9d6a..02b2fad 100644 --- a/dbtests/perf/perftest.cpp +++ b/dbtests/perf/perftest.cpp @@ -623,7 +623,7 @@ namespace Plan { client_->ensureIndex( ns_.c_str(), BSON( ( names + i ) << 1 ), false, names + i ); } lk_.reset( new dblock ); - setClient( ns_.c_str() ); + Client::Context ctx( ns_ ); hint_ = BSON( "hint" << BSON( "a" << 1 ) ); hintElt_ = hint_.firstElement(); } @@ -646,9 +646,9 @@ namespace Plan { client_->ensureIndex( ns_.c_str(), BSON( ( names + i ) << 1 ), false, names + i ); } lk_.reset( new dblock ); - setClient( ns_.c_str() ); } void run() { + Client::Context ctx( ns_ ); for( int i = 0; i < 10000; ++i ) QueryPlanSet s( ns_.c_str(), BSONObj(), BSON( "a" << 1 ) ); } @@ -665,9 +665,9 @@ namespace Plan { client_->ensureIndex( ns_.c_str(), BSON( ( names + i ) << 1 ), false, names + i ); } lk_.reset( new dblock ); - setClient( ns_.c_str() ); } void run() { + Client::Context ctx( ns_.c_str() ); for( int i = 0; i < 10000; ++i ) QueryPlanSet s( ns_.c_str(), BSON( "a" << 1 ), BSONObj() ); } diff --git a/dbtests/queryoptimizertests.cpp b/dbtests/queryoptimizertests.cpp index c9465f3..d757f1a 100644 --- a/dbtests/queryoptimizertests.cpp +++ b/dbtests/queryoptimizertests.cpp @@ -30,7 +30,8 @@ namespace mongo { extern BSONObj id_obj; auto_ptr< QueryResult > runQuery(Message& m, QueryMessage& q ){ - CurOp op; + CurOp op( &(cc()) ); + op.ensureStarted(); return runQuery( m , q , op ); } } // namespace mongo @@ -54,7 +55,6 @@ namespace QueryOptimizerTests { virtual bool lowerInclusive() { return true; } virtual BSONElement upper() { return maxKey.firstElement(); } virtual bool upperInclusive() { return true; } - private: static void checkElt( BSONElement expected, BSONElement actual ) { if ( expected.woCompare( actual, false ) ) { stringstream ss; @@ -143,7 +143,17 @@ namespace QueryOptimizerTests { } }; - class Regex : public Base { + struct RegexBase : Base { + void run() { //need to only look at first interval + FieldRangeSet s( "ns", query() ); + checkElt( lower(), s.range( "a" ).intervals()[0].lower_.bound_ ); + checkElt( upper(), s.range( "a" ).intervals()[0].upper_.bound_ ); + ASSERT_EQUALS( lowerInclusive(), s.range( "a" ).intervals()[0].lower_.inclusive_ ); + ASSERT_EQUALS( upperInclusive(), s.range( "a" ).intervals()[0].upper_.inclusive_ ); + } + }; + + class Regex : public RegexBase { public: Regex() : o1_( BSON( "" << "abc" ) ), o2_( BSON( "" << "abd" ) ) {} virtual BSONObj query() { @@ -157,7 +167,7 @@ namespace QueryOptimizerTests { BSONObj o1_, o2_; }; - class RegexObj : public Base { + class RegexObj : public RegexBase { public: RegexObj() : o1_( BSON( "" << "abc" ) ), o2_( BSON( "" << "abd" ) ) {} virtual BSONObj query() { return BSON("a" << BSON("$regex" << "^abc")); } @@ -167,12 +177,24 @@ namespace QueryOptimizerTests { BSONObj o1_, o2_; }; - class UnhelpfulRegex : public Base { + class UnhelpfulRegex : public RegexBase { + public: + UnhelpfulRegex() { + BSONObjBuilder b; + b.appendMinForType("lower", String); + b.appendMaxForType("upper", String); + limits = b.obj(); + } + virtual BSONObj query() { BSONObjBuilder b; b.appendRegex( "a", "abc" ); return b.obj(); } + virtual BSONElement lower() { return limits["lower"]; } + virtual BSONElement upper() { return limits["upper"]; } + virtual bool upperInclusive() { return false; } + BSONObj limits; }; class In : public Base { @@ -316,8 +338,7 @@ namespace QueryOptimizerTests { namespace QueryPlanTests { class Base { public: - Base() : indexNum_( 0 ) { - setClient( ns() ); + Base() : _ctx( ns() ) , indexNum_( 0 ) { string err; userCreateNS( ns(), BSONObj(), err, false ); } @@ -357,6 +378,7 @@ namespace QueryOptimizerTests { } private: dblock lk_; + Client::Context _ctx; int indexNum_; static DBDirectClient client_; }; @@ -595,8 +617,7 @@ namespace QueryOptimizerTests { namespace QueryPlanSetTests { class Base { public: - Base() { - setClient( ns() ); + Base() : _context( ns() ){ string err; userCreateNS( ns(), BSONObj(), err, false ); } @@ -625,6 +646,7 @@ namespace QueryOptimizerTests { static NamespaceDetails *nsd() { return nsdetails( ns() ); } private: dblock lk_; + Client::Context _context; }; class NoIndexes : public Base { diff --git a/dbtests/querytests.cpp b/dbtests/querytests.cpp index 4681bf0..f175543 100644 --- a/dbtests/querytests.cpp +++ b/dbtests/querytests.cpp @@ -27,14 +27,17 @@ #include "dbtests.h" +namespace mongo { + extern int __findingStartInitialTimeout; +} + namespace QueryTests { class Base { dblock lk; + Client::Context _context; public: - Base() { - dblock lk; - setClient( ns() ); + Base() : _context( ns() ){ addIndex( fromjson( "{\"a\":1}" ) ); } ~Base() { @@ -186,6 +189,31 @@ namespace QueryTests { } }; + class PositiveLimit : public ClientBase { + public: + const char* ns; + PositiveLimit() : ns("unittests.querytests.PositiveLimit") {} + ~PositiveLimit() { + client().dropCollection( ns ); + } + + void testLimit(int limit){ + ASSERT_EQUALS(client().query( ns, BSONObj(), limit )->itcount(), limit); + } + void run() { + for(int i=0; i<1000; i++) + insert( ns, BSON( GENOID << "i" << i ) ); + + ASSERT_EQUALS( client().query(ns, BSONObj(), 1 )->itcount(), 1); + ASSERT_EQUALS( client().query(ns, BSONObj(), 10 )->itcount(), 10); + ASSERT_EQUALS( client().query(ns, BSONObj(), 101 )->itcount(), 101); + ASSERT_EQUALS( client().query(ns, BSONObj(), 999 )->itcount(), 999); + ASSERT_EQUALS( client().query(ns, BSONObj(), 1000 )->itcount(), 1000); + ASSERT_EQUALS( client().query(ns, BSONObj(), 1001 )->itcount(), 1000); + ASSERT_EQUALS( client().query(ns, BSONObj(), 0 )->itcount(), 1000); + } + }; + class ReturnOneOfManyAndTail : public ClientBase { public: ~ReturnOneOfManyAndTail() { @@ -193,6 +221,7 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.ReturnOneOfManyAndTail"; + client().createCollection( ns, 0, true ); insert( ns, BSON( "a" << 0 ) ); insert( ns, BSON( "a" << 1 ) ); insert( ns, BSON( "a" << 2 ) ); @@ -211,6 +240,7 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.TailNotAtEnd"; + client().createCollection( ns, 0, true ); insert( ns, BSON( "a" << 0 ) ); insert( ns, BSON( "a" << 1 ) ); insert( ns, BSON( "a" << 2 ) ); @@ -235,9 +265,14 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.EmptyTail"; - ASSERT_EQUALS( 0, client().query( ns, Query().hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable )->getCursorId() ); + client().createCollection( ns, 0, true ); + auto_ptr< DBClientCursor > c = client().query( ns, Query().hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable ); + ASSERT_EQUALS( 0, c->getCursorId() ); + ASSERT( c->isDead() ); insert( ns, BSON( "a" << 0 ) ); - ASSERT( 0 != client().query( ns, QUERY( "a" << 1 ).hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable )->getCursorId() ); + c = client().query( ns, QUERY( "a" << 1 ).hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable ); + ASSERT( 0 != c->getCursorId() ); + ASSERT( !c->isDead() ); } }; @@ -248,14 +283,15 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.TailableDelete"; + client().createCollection( ns, 0, true, 2 ); insert( ns, BSON( "a" << 0 ) ); insert( ns, BSON( "a" << 1 ) ); auto_ptr< DBClientCursor > c = client().query( ns, Query().hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable ); c->next(); c->next(); ASSERT( !c->more() ); - client().remove( ns, QUERY( "a" << 1 ) ); insert( ns, BSON( "a" << 2 ) ); + insert( ns, BSON( "a" << 3 ) ); ASSERT( !c->more() ); ASSERT_EQUALS( 0, c->getCursorId() ); } @@ -268,6 +304,7 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.TailableInsertDelete"; + client().createCollection( ns, 0, true ); insert( ns, BSON( "a" << 0 ) ); insert( ns, BSON( "a" << 1 ) ); auto_ptr< DBClientCursor > c = client().query( ns, Query().hint( BSON( "$natural" << 1 ) ), 2, 0, 0, QueryOption_CursorTailable ); @@ -282,6 +319,52 @@ namespace QueryTests { } }; + class TailCappedOnly : public ClientBase { + public: + ~TailCappedOnly() { + client().dropCollection( "unittest.querytests.TailCappedOnly" ); + } + void run() { + const char *ns = "unittests.querytests.TailCappedOnly"; + client().insert( ns, BSONObj() ); + auto_ptr< DBClientCursor > c = client().query( ns, BSONObj(), 0, 0, 0, QueryOption_CursorTailable ); + ASSERT( c->isDead() ); + ASSERT( !client().getLastError().empty() ); + } + }; + + class TailableQueryOnId : public ClientBase { + public: + ~TailableQueryOnId() { + client().dropCollection( "unittests.querytests.TailableQueryOnId" ); + } + void run() { + const char *ns = "unittests.querytests.TailableQueryOnId"; + BSONObj info; + client().runCommand( "unittests", BSON( "create" << "querytests.TailableQueryOnId" << "capped" << true << "autoIndexId" << true ), info ); + insert( ns, BSON( "a" << 0 ) ); + insert( ns, BSON( "a" << 1 ) ); + auto_ptr< DBClientCursor > c1 = client().query( ns, QUERY( "a" << GT << -1 ), 0, 0, 0, QueryOption_CursorTailable ); + OID id; + id.init("000000000000000000000000"); + auto_ptr< DBClientCursor > c2 = client().query( ns, QUERY( "_id" << GT << id ), 0, 0, 0, QueryOption_CursorTailable ); + c1->next(); + c1->next(); + ASSERT( !c1->more() ); + c2->next(); + c2->next(); + ASSERT( !c2->more() ); + insert( ns, BSON( "a" << 2 ) ); + ASSERT( c1->more() ); + ASSERT_EQUALS( 2, c1->next().getIntField( "a" ) ); + ASSERT( !c1->more() ); + ASSERT( c2->more() ); + ASSERT_EQUALS( 2, c2->next().getIntField( "a" ) ); // SERVER-645 + ASSERT( !c2->more() ); + ASSERT( !c2->isDead() ); + } + }; + class OplogReplayMode : public ClientBase { public: ~OplogReplayMode() { @@ -289,13 +372,13 @@ namespace QueryTests { } void run() { const char *ns = "unittests.querytests.OplogReplayMode"; - insert( ns, BSON( "a" << 3 ) ); - insert( ns, BSON( "a" << 0 ) ); - insert( ns, BSON( "a" << 1 ) ); - insert( ns, BSON( "a" << 2 ) ); - auto_ptr< DBClientCursor > c = client().query( ns, QUERY( "a" << GT << 1 ).hint( BSON( "$natural" << 1 ) ), 0, 0, 0, QueryOption_OplogReplay ); + insert( ns, BSON( "ts" << 3 ) ); + insert( ns, BSON( "ts" << 0 ) ); + insert( ns, BSON( "ts" << 1 ) ); + insert( ns, BSON( "ts" << 2 ) ); + auto_ptr< DBClientCursor > c = client().query( ns, QUERY( "ts" << GT << 1 ).hint( BSON( "$natural" << 1 ) ), 0, 0, 0, QueryOption_OplogReplay ); ASSERT( c->more() ); - ASSERT_EQUALS( 2, c->next().getIntField( "a" ) ); + ASSERT_EQUALS( 2, c->next().getIntField( "ts" ) ); ASSERT( !c->more() ); } }; @@ -545,7 +628,7 @@ namespace QueryTests { void check( const string &hintField ) { const char *ns = "unittests.querytests.SubobjArr"; ASSERT( client().query( ns, Query( "{'a.b':1}" ).hint( BSON( hintField << 1 ) ) )->more() ); - ASSERT( !client().query( ns, Query( "{'a.b':[1]}" ).hint( BSON( hintField << 1 ) ) )->more() ); + ASSERT( client().query( ns, Query( "{'a.b':[1]}" ).hint( BSON( hintField << 1 ) ) )->more() ); } }; @@ -608,7 +691,7 @@ namespace QueryTests { public: void run() { dblock lk; - setClient( "unittests.DirectLocking" ); + Client::Context ctx( "unittests.DirectLocking" ); client().remove( "a.b", BSONObj() ); ASSERT_EQUALS( "unittests", cc().database()->name ); } @@ -678,6 +761,7 @@ namespace QueryTests { CollectionBase( string leaf ){ _ns = "unittests.querytests."; _ns += leaf; + client().dropCollection( ns() ); } virtual ~CollectionBase(){ @@ -725,7 +809,7 @@ namespace QueryTests { string err; writelock lk(""); - setClient( "unittests" ); + Client::Context ctx( "unittests" ); ASSERT( userCreateNS( ns() , fromjson( "{ capped : true , size : 2000 }" ) , err , false ) ); for ( int i=0; i<100; i++ ){ @@ -770,7 +854,7 @@ namespace QueryTests { void run(){ writelock lk(""); - setClient( "unittests" ); + Client::Context ctx( "unittests" ); for ( int i=0; i<50; i++ ){ insert( ns() , BSON( "_id" << i << "x" << i * 2 ) ); @@ -836,7 +920,7 @@ namespace QueryTests { void run(){ writelock lk(""); - setClient( "unittests" ); + Client::Context ctx( "unittests" ); for ( int i=0; i<1000; i++ ){ insert( ns() , BSON( "_id" << i << "x" << i * 2 ) ); @@ -860,7 +944,7 @@ namespace QueryTests { void run(){ writelock lk(""); - setClient( "unittests" ); + Client::Context ctx( "unittests" ); for ( int i=0; i<1000; i++ ){ insert( ns() , BSON( "_id" << i << "x" << i * 2 ) ); @@ -870,6 +954,75 @@ namespace QueryTests { } }; + class FindingStart : public CollectionBase { + public: + FindingStart() : CollectionBase( "findingstart" ), _old( __findingStartInitialTimeout ) { + __findingStartInitialTimeout = 0; + } + ~FindingStart() { + __findingStartInitialTimeout = _old; + } + + void run() { + BSONObj info; + ASSERT( client().runCommand( "unittests", BSON( "create" << "querytests.findingstart" << "capped" << true << "size" << 1000 << "$nExtents" << 5 << "autoIndexId" << false ), info ) ); + + int i = 0; + for( int oldCount = -1; + count() != oldCount; + oldCount = count(), client().insert( ns(), BSON( "ts" << i++ ) ) ); + + for( int k = 0; k < 5; ++k ) { + client().insert( ns(), BSON( "ts" << i++ ) ); + int min = client().query( ns(), Query().sort( BSON( "$natural" << 1 ) ) )->next()[ "ts" ].numberInt(); + for( int j = -1; j < i; ++j ) { + auto_ptr< DBClientCursor > c = client().query( ns(), QUERY( "ts" << GTE << j ), 0, 0, 0, QueryOption_OplogReplay ); + ASSERT( c->more() ); + ASSERT_EQUALS( ( j > min ? j : min ), c->next()[ "ts" ].numberInt() ); + } + } + } + + private: + int _old; + }; + + class WhatsMyUri : public CollectionBase { + public: + WhatsMyUri() : CollectionBase( "whatsmyuri" ) {} + void run() { + BSONObj result; + client().runCommand( "admin", BSON( "whatsmyuri" << 1 ), result ); + ASSERT_EQUALS( unknownAddress.toString(), result[ "you" ].str() ); + } + }; + + namespace parsedtests { + class basic1 { + public: + void _test( const BSONObj& in ){ + ParsedQuery q( "a.b" , 5 , 6 , 9 , in , BSONObj() ); + ASSERT_EQUALS( BSON( "x" << 5 ) , q.getFilter() ); + } + void run(){ + _test( BSON( "x" << 5 ) ); + _test( BSON( "query" << BSON( "x" << 5 ) ) ); + _test( BSON( "$query" << BSON( "x" << 5 ) ) ); + + { + ParsedQuery q( "a.b" , 5 , 6 , 9 , BSON( "x" << 5 ) , BSONObj() ); + ASSERT_EQUALS( 6 , q.getNumToReturn() ); + ASSERT( q.wantMore() ); + } + { + ParsedQuery q( "a.b" , 5 , -6 , 9 , BSON( "x" << 5 ) , BSONObj() ); + ASSERT_EQUALS( 6 , q.getNumToReturn() ); + ASSERT( ! q.wantMore() ); + } + } + }; + }; + class All : public Suite { public: All() : Suite( "query" ) { @@ -883,11 +1036,14 @@ namespace QueryTests { add< CountIndexedRegex >(); add< BoundedKey >(); add< GetMore >(); + add< PositiveLimit >(); add< ReturnOneOfManyAndTail >(); add< TailNotAtEnd >(); add< EmptyTail >(); add< TailableDelete >(); add< TailableInsertDelete >(); + add< TailCappedOnly >(); + add< TailableQueryOnId >(); add< OplogReplayMode >(); add< ArrayId >(); add< UnderscoreNs >(); @@ -912,6 +1068,10 @@ namespace QueryTests { add< TailableCappedRaceCondition >(); add< HelperTest >(); add< HelperByIdTest >(); + add< FindingStart >(); + add< WhatsMyUri >(); + + add< parsedtests::basic1 >(); } } myall; diff --git a/dbtests/repltests.cpp b/dbtests/repltests.cpp index d4d97c1..c6ef6c2 100644 --- a/dbtests/repltests.cpp +++ b/dbtests/repltests.cpp @@ -37,17 +37,17 @@ namespace ReplTests { } class Base { + dblock lk; + Client::Context _context; public: - Base() { - master = true; + Base() : _context( ns() ){ + replSettings.master = true; createOplog(); - dblock lk; - setClient( ns() ); ensureHaveIdIndex( ns() ); } ~Base() { try { - master = false; + replSettings.master = false; deleteAll( ns() ); deleteAll( cllNS() ); } catch ( ... ) { @@ -88,7 +88,7 @@ namespace ReplTests { int count() const { int count = 0; dblock lk; - setClient( ns() ); + Client::Context ctx( ns() ); auto_ptr< Cursor > c = theDataFileMgr.findAll( ns() ); for(; c->ok(); c->advance(), ++count ) { // cout << "obj: " << c->current().toString() << endl; @@ -97,7 +97,7 @@ namespace ReplTests { } static int opCount() { dblock lk; - setClient( cllNS() ); + Client::Context ctx( cllNS() ); int count = 0; for( auto_ptr< Cursor > c = theDataFileMgr.findAll( cllNS() ); c->ok(); c->advance() ) ++count; @@ -111,17 +111,21 @@ namespace ReplTests { } }; dblock lk; - setClient( cllNS() ); vector< BSONObj > ops; - for( auto_ptr< Cursor > c = theDataFileMgr.findAll( cllNS() ); c->ok(); c->advance() ) - ops.push_back( c->current() ); - setClient( ns() ); - for( vector< BSONObj >::iterator i = ops.begin(); i != ops.end(); ++i ) - Applier::apply( *i ); + { + Client::Context ctx( cllNS() ); + for( auto_ptr< Cursor > c = theDataFileMgr.findAll( cllNS() ); c->ok(); c->advance() ) + ops.push_back( c->current() ); + } + { + Client::Context ctx( ns() ); + for( vector< BSONObj >::iterator i = ops.begin(); i != ops.end(); ++i ) + Applier::apply( *i ); + } } static void printAll( const char *ns ) { dblock lk; - setClient( ns ); + Client::Context ctx( ns ); auto_ptr< Cursor > c = theDataFileMgr.findAll( ns ); vector< DiskLoc > toDelete; out() << "all for " << ns << endl; @@ -132,7 +136,7 @@ namespace ReplTests { // These deletes don't get logged. static void deleteAll( const char *ns ) { dblock lk; - setClient( ns ); + Client::Context ctx( ns ); auto_ptr< Cursor > c = theDataFileMgr.findAll( ns ); vector< DiskLoc > toDelete; for(; c->ok(); c->advance() ) { @@ -144,7 +148,7 @@ namespace ReplTests { } static void insert( const BSONObj &o, bool god = false ) { dblock lk; - setClient( ns() ); + Client::Context ctx( ns() ); theDataFileMgr.insert( ns(), o.objdata(), o.objsize(), god ); } static BSONObj wid( const char *json ) { @@ -460,6 +464,75 @@ namespace ReplTests { BSONObj o_, q_, u_, ou_; }; + class UpdateInc2 : public Base { + public: + UpdateInc2() : + o_( fromjson( "{'_id':1,a:5}" ) ), + q_( fromjson( "{a:5}" ) ), + u_( fromjson( "{$inc:{a:3},$set:{x:5}}" ) ), + ou_( fromjson( "{'_id':1,a:8,x:5}" ) ) {} + void doIt() const { + client()->update( ns(), q_, u_ ); + } + void check() const { + ASSERT_EQUALS( 1, count() ); + checkOne( ou_ ); + } + void reset() const { + deleteAll( ns() ); + insert( o_ ); + } + protected: + BSONObj o_, q_, u_, ou_; + }; + + class IncEmbedded : public Base { + public: + IncEmbedded() : + o_( fromjson( "{'_id':1,a:{b:3},b:{b:1}}" ) ), + q_( fromjson( "{'_id':1}" ) ), + u_( fromjson( "{$inc:{'a.b':1,'b.b':1}}" ) ), + ou_( fromjson( "{'_id':1,a:{b:4},b:{b:2}}" ) ) + {} + void doIt() const { + client()->update( ns(), q_, u_ ); + } + void check() const { + ASSERT_EQUALS( 1, count() ); + checkOne( ou_ ); + } + void reset() const { + deleteAll( ns() ); + insert( o_ ); + } + protected: + BSONObj o_, q_, u_, ou_; + }; + + class IncCreates : public Base { + public: + IncCreates() : + o_( fromjson( "{'_id':1}" ) ), + q_( fromjson( "{'_id':1}" ) ), + u_( fromjson( "{$inc:{'a':1}}" ) ), + ou_( fromjson( "{'_id':1,a:1}") ) + {} + void doIt() const { + client()->update( ns(), q_, u_ ); + } + void check() const { + ASSERT_EQUALS( 1, count() ); + checkOne( ou_ ); + } + void reset() const { + deleteAll( ns() ); + insert( o_ ); + } + protected: + BSONObj o_, q_, u_, ou_; + }; + + class UpsertInsertIdMod : public Base { public: UpsertInsertIdMod() : @@ -885,7 +958,7 @@ namespace ReplTests { class DbIdsTest { public: void run() { - setClient( "unittests.repltest.DbIdsTest" ); + Client::Context ctx( "unittests.repltest.DbIdsTest" ); s_.reset( new DbIds( "local.temp.DbIdsTest" ) ); s_->reset(); @@ -960,7 +1033,7 @@ namespace ReplTests { class IdTrackerTest { public: void run() { - setClient( "unittests.repltests.IdTrackerTest" ); + Client::Context ctx( "unittests.repltests.IdTrackerTest" ); ASSERT( s_.inMem() ); s_.reset( 4 * sizeof( BSONObj ) - 1 ); @@ -1016,6 +1089,9 @@ namespace ReplTests { add< Idempotence::UpsertInsertNoMods >(); add< Idempotence::UpdateSet >(); add< Idempotence::UpdateInc >(); + add< Idempotence::UpdateInc2 >(); + add< Idempotence::IncEmbedded >(); // SERVER-716 + add< Idempotence::IncCreates >(); // SERVER-717 add< Idempotence::UpsertInsertIdMod >(); add< Idempotence::UpsertInsertSet >(); add< Idempotence::UpsertInsertInc >(); diff --git a/dbtests/test.vcproj b/dbtests/test.vcproj index 4582ef2..002d464 100644 --- a/dbtests/test.vcproj +++ b/dbtests/test.vcproj @@ -144,7 +144,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="ws2_32.lib"
+ AdditionalDependencies="ws2_32.lib psapi.lib"
LinkIncremental="1"
AdditionalLibraryDirectories=""c:\program files\boost\boost_1_35_0\lib""
GenerateDebugInformation="true"
@@ -350,36 +350,8 @@ >
</File>
<File
- RelativePath="..\..\js\js\Debug\js.lib"
- >
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCustomBuildTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\..\js\js\Release\js.lib"
+ RelativePath="..\..\js\src\js.lib"
>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCustomBuildTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug Recstore|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCustomBuildTool"
- />
- </FileConfiguration>
</File>
<File
RelativePath="..\pcre-7.4\pcrecpp.cc"
@@ -1330,7 +1302,7 @@ >
</File>
<File
- RelativePath="..\client\quorum.cpp"
+ RelativePath="..\client\syncclusterconnection.cpp"
>
</File>
<Filter
@@ -1358,6 +1330,10 @@ >
</File>
<File
+ RelativePath="..\db\cmdline.cpp"
+ >
+ </File>
+ <File
RelativePath="..\db\cmdline.h"
>
</File>
@@ -1398,6 +1374,10 @@ >
</File>
<File
+ RelativePath="..\db\diskloc.h"
+ >
+ </File>
+ <File
RelativePath="..\db\extsort.h"
>
</File>
@@ -1495,6 +1475,10 @@ >
</File>
<File
+ RelativePath="..\db\common.cpp"
+ >
+ </File>
+ <File
RelativePath="..\db\cursor.cpp"
>
</File>
@@ -1515,10 +1499,6 @@ >
</File>
<File
- RelativePath="..\db\dbstats.cpp"
- >
- </File>
- <File
RelativePath="..\db\dbwebserver.cpp"
>
</File>
@@ -1531,6 +1511,10 @@ >
</File>
<File
+ RelativePath="..\db\index_geo2d.cpp"
+ >
+ </File>
+ <File
RelativePath="..\db\instance.cpp"
>
</File>
@@ -1631,10 +1615,6 @@ >
</File>
<File
- RelativePath="..\util\top.cpp"
- >
- </File>
- <File
RelativePath="..\db\update.cpp"
>
</File>
@@ -1836,6 +1816,10 @@ />
</FileConfiguration>
</File>
+ <File
+ RelativePath="..\scripting\utils.cpp"
+ >
+ </File>
</Filter>
<Filter
Name="dbtests"
@@ -1925,6 +1909,22 @@ >
</File>
</Filter>
+ <Filter
+ Name="stats"
+ >
+ <File
+ RelativePath="..\db\stats\counters.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\db\stats\snapshots.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\db\stats\top.cpp"
+ >
+ </File>
+ </Filter>
</Files>
<Globals>
</Globals>
diff --git a/dbtests/threadedtests.cpp b/dbtests/threadedtests.cpp index f3ebe39..2ffafba 100644 --- a/dbtests/threadedtests.cpp +++ b/dbtests/threadedtests.cpp @@ -18,6 +18,7 @@ */ #include "stdafx.h" +#include "../util/atomic_int.h" #include "../util/mvar.h" #include "../util/thread_pool.h" #include <boost/thread.hpp> @@ -59,18 +60,26 @@ namespace ThreadedTests { }; // Tested with up to 30k threads - class IsWrappingIntAtomic : public ThreadedTest<> { + class IsAtomicUIntAtomic : public ThreadedTest<> { static const int iterations = 1000000; - WrappingInt target; + AtomicUInt target; void subthread(){ for(int i=0; i < iterations; i++){ //target.x++; // verified to fail with this version - target.atomicIncrement(); + target++; } } void validate(){ ASSERT_EQUALS(target.x , unsigned(nthreads * iterations)); + + AtomicUInt u; + ASSERT_EQUALS(0u, u); + ASSERT_EQUALS(0u, u++); + ASSERT_EQUALS(2u, ++u); + ASSERT_EQUALS(2u, u--); + ASSERT_EQUALS(0u, --u); + ASSERT_EQUALS(0u, u); } }; @@ -99,10 +108,10 @@ namespace ThreadedTests { static const int iterations = 10000; static const int nThreads = 8; - WrappingInt counter; + AtomicUInt counter; void increment(int n){ for (int i=0; i<n; i++){ - counter.atomicIncrement(); + counter++; } } @@ -111,13 +120,12 @@ namespace ThreadedTests { ThreadPool tp(nThreads); for (int i=0; i < iterations; i++){ - tp.schedule(&WrappingInt::atomicIncrement, &counter); tp.schedule(&ThreadPoolTest::increment, this, 2); } tp.join(); - ASSERT(counter == (unsigned)(iterations * 3)); + ASSERT(counter == (unsigned)(iterations * 2)); } }; @@ -127,7 +135,7 @@ namespace ThreadedTests { } void setupTests(){ - add< IsWrappingIntAtomic >(); + add< IsAtomicUIntAtomic >(); add< MVarTest >(); add< ThreadPoolTest >(); } diff --git a/dbtests/updatetests.cpp b/dbtests/updatetests.cpp index a9c4b1e..09caae6 100644 --- a/dbtests/updatetests.cpp +++ b/dbtests/updatetests.cpp @@ -525,8 +525,7 @@ namespace UpdateTests { public: void run(){ BSONObj b = BSON( "$inc" << BSON( "x" << 1 << "a.b" << 1 ) ); - ModSet m; - m.getMods( b ); + ModSet m(b); ASSERT( m.haveModForField( "x" ) ); ASSERT( m.haveModForField( "a.b" ) ); @@ -551,10 +550,9 @@ namespace UpdateTests { void test( BSONObj morig , BSONObj in , BSONObj wanted ){ BSONObj m = morig.copy(); - ModSet set; - set.getMods( m ); + ModSet set(m); - BSONObj out = set.createNewFromMods( in ); + BSONObj out = set.prepare(in)->createNewFromMods(); ASSERT_EQUALS( wanted , out ); } }; @@ -663,6 +661,22 @@ namespace UpdateTests { } }; + + class inc2 : public SingleTest { + virtual BSONObj initial(){ + return BSON( "_id" << 1 << "x" << 1 ); + } + virtual BSONObj mod(){ + return BSON( "$inc" << BSON( "x" << 2.5 ) ); + } + virtual BSONObj after(){ + return BSON( "_id" << 1 << "x" << 3.5 ); + } + virtual const char * ns(){ + return "unittests.inc2"; + } + + }; class bit1 : public Base { const char * ns(){ @@ -760,6 +774,7 @@ namespace UpdateTests { add< ModSetTests::push1 >(); add< basic::inc1 >(); + add< basic::inc2 >(); add< basic::bit1 >(); add< basic::unset >(); add< basic::setswitchint >(); |