summaryrefslogtreecommitdiff
path: root/dbtests
diff options
context:
space:
mode:
Diffstat (limited to 'dbtests')
-rw-r--r--dbtests/basictests.cpp89
-rw-r--r--dbtests/btreetests.cpp7
-rw-r--r--dbtests/clienttests.cpp74
-rw-r--r--dbtests/cursortests.cpp8
-rw-r--r--dbtests/dbtests.cpp1
-rw-r--r--dbtests/framework.cpp2
-rw-r--r--dbtests/jsobjtests.cpp239
-rw-r--r--dbtests/jsontests.cpp4
-rw-r--r--dbtests/jstests.cpp130
-rw-r--r--dbtests/namespacetests.cpp11
-rw-r--r--dbtests/pairingtests.cpp2
-rw-r--r--dbtests/pdfiletests.cpp8
-rw-r--r--dbtests/perf/perftest.cpp6
-rw-r--r--dbtests/queryoptimizertests.cpp40
-rw-r--r--dbtests/querytests.cpp196
-rw-r--r--dbtests/repltests.cpp112
-rw-r--r--dbtests/test.vcproj78
-rw-r--r--dbtests/threadedtests.cpp24
-rw-r--r--dbtests/updatetests.cpp25
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="&quot;c:\program files\boost\boost_1_35_0\lib&quot;"
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 >();