summaryrefslogtreecommitdiff
path: root/dbtests/btreetests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dbtests/btreetests.cpp')
-rw-r--r--dbtests/btreetests.cpp178
1 files changed, 148 insertions, 30 deletions
diff --git a/dbtests/btreetests.cpp b/dbtests/btreetests.cpp
index 390071f..a90a097 100644
--- a/dbtests/btreetests.cpp
+++ b/dbtests/btreetests.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "stdafx.h"
+#include "pch.h"
#include "../db/db.h"
#include "../db/btree.h"
@@ -26,47 +26,47 @@
namespace BtreeTests {
- class Base {
+ const char* ns() {
+ return "unittests.btreetests";
+ }
+
+ class Ensure {
+ public:
+ Ensure() {
+ _c.ensureIndex( ns(), BSON( "a" << 1 ), false, "testIndex" );
+ }
+ ~Ensure() {
+ _c.dropIndexes( ns() );
+ }
+ private:
+ DBDirectClient _c;
+ };
+
+ class Base : public Ensure {
public:
Base() :
- _context( ns() ) {
-
+ _context( ns() ) {
{
bool f = false;
assert( f = true );
massert( 10402 , "assert is misdefined", f);
}
- BSONObjBuilder builder;
- builder.append( "ns", ns() );
- builder.append( "name", "testIndex" );
- BSONObj bobj = builder.done();
- idx_.info =
- theDataFileMgr.insert( ns(), bobj.objdata(), bobj.objsize() );
- idx_.head = BtreeBucket::addBucket( idx_ );
- }
- ~Base() {
- // FIXME cleanup all btree buckets.
- theDataFileMgr.deleteRecord( ns(), idx_.info.rec(), idx_.info );
- ASSERT( theDataFileMgr.findAll( ns() )->eof() );
}
protected:
- BtreeBucket* bt() const {
- return idx_.head.btree();
+ BtreeBucket* bt() {
+ return id().head.btree();
}
- DiskLoc dl() const {
- return idx_.head;
+ DiskLoc dl() {
+ return id().head;
}
IndexDetails& id() {
- return idx_;
- }
- static const char* ns() {
- return "unittests.btreetests";
+ return nsdetails( ns() )->idx( 1 );
}
// dummy, valid record loc
static DiskLoc recordLoc() {
return DiskLoc( 0, 2 );
}
- void checkValid( int nKeys ) const {
+ void checkValid( int nKeys ) {
ASSERT( bt() );
ASSERT( bt()->isHead() );
bt()->assertValid( order(), true );
@@ -76,7 +76,7 @@ namespace BtreeTests {
bt()->dumpTree( dl(), order() );
}
void insert( BSONObj &key ) {
- bt()->bt_insert( dl(), recordLoc(), key, order(), true, id(), true );
+ bt()->bt_insert( dl(), recordLoc(), key, Ordering::make(order()), true, id(), true );
}
void unindex( BSONObj &key ) {
bt()->unindex( dl(), id(), key, recordLoc() );
@@ -93,18 +93,17 @@ namespace BtreeTests {
int pos;
bool found;
DiskLoc location =
- bt()->locate( id(), dl(), key, order(), pos, found, recordLoc(), direction );
+ bt()->locate( id(), dl(), key, Ordering::make(order()), pos, found, recordLoc(), direction );
ASSERT_EQUALS( expectedFound, found );
ASSERT( location == expectedLocation );
ASSERT_EQUALS( expectedPos, pos );
}
- BSONObj order() const {
- return idx_.keyPattern();
+ BSONObj order() {
+ return id().keyPattern();
}
private:
dblock lk_;
Client::Context _context;
- IndexDetails idx_;
};
class Create : public Base {
@@ -251,6 +250,122 @@ namespace BtreeTests {
Base::insert( k );
}
};
+
+ class ReuseUnused : public Base {
+ public:
+ void run() {
+ for ( int i = 0; i < 10; ++i ) {
+ insert( i );
+ }
+ BSONObj root = key( 'p' );
+ unindex( root );
+ Base::insert( root );
+ locate( root, 0, true, dl(), 1 );
+ }
+ private:
+ BSONObj key( char c ) {
+ return simpleKey( c, 800 );
+ }
+ void insert( int i ) {
+ BSONObj k = key( 'b' + 2 * i );
+ Base::insert( k );
+ }
+ };
+
+ class PackUnused : public Base {
+ public:
+ void run() {
+ for ( long long i = 0; i < 1000000; i += 1000 ) {
+ insert( i );
+ }
+ string orig, after;
+ {
+ stringstream ss;
+ bt()->shape( ss );
+ orig = ss.str();
+ }
+ vector< string > toDel;
+ vector< string > other;
+ BSONObjBuilder start;
+ start.appendMinKey( "a" );
+ BSONObjBuilder end;
+ end.appendMaxKey( "a" );
+ auto_ptr< BtreeCursor > c( new BtreeCursor( nsdetails( ns() ), 1, id(), start.done(), end.done(), false, 1 ) );
+ while( c->ok() ) {
+ if ( !c->currKeyNode().prevChildBucket.isNull() ) {
+ toDel.push_back( c->currKey().firstElement().valuestr() );
+ } else {
+ other.push_back( c->currKey().firstElement().valuestr() );
+ }
+ c->advance();
+ }
+ ASSERT( toDel.size() > 0 );
+ for( vector< string >::const_iterator i = toDel.begin(); i != toDel.end(); ++i ) {
+ BSONObj o = BSON( "a" << *i );
+ unindex( o );
+ }
+ ASSERT( other.size() > 0 );
+ for( vector< string >::const_iterator i = other.begin(); i != other.end(); ++i ) {
+ BSONObj o = BSON( "a" << *i );
+ unindex( o );
+ }
+
+ int unused = 0;
+ ASSERT_EQUALS( 0, bt()->fullValidate( dl(), order(), &unused ) );
+
+ for ( long long i = 50000; i < 50100; ++i ) {
+ insert( i );
+ }
+
+ int unused2 = 0;
+ ASSERT_EQUALS( 100, bt()->fullValidate( dl(), order(), &unused2 ) );
+
+ ASSERT( unused2 < unused );
+ }
+ protected:
+ void insert( long long n ) {
+ string val( 800, ' ' );
+ for( int i = 0; i < 800; i += 8 ) {
+ for( int j = 0; j < 8; ++j ) {
+ // probably we won't get > 56 bits
+ unsigned char v = 0x80 | ( n >> ( ( 8 - j - 1 ) * 7 ) & 0x000000000000007f );
+ val[ i + j ] = v;
+ }
+ }
+ BSONObj k = BSON( "a" << val );
+ Base::insert( k );
+ }
+ };
+
+ class DontDropReferenceKey : public PackUnused {
+ public:
+ void run() {
+ // with 80 root node is full
+ for ( long long i = 0; i < 80; i += 1 ) {
+ insert( i );
+ }
+
+ BSONObjBuilder start;
+ start.appendMinKey( "a" );
+ BSONObjBuilder end;
+ end.appendMaxKey( "a" );
+ BSONObj l = bt()->keyNode( 0 ).key;
+ string toInsert;
+ auto_ptr< BtreeCursor > c( new BtreeCursor( nsdetails( ns() ), 1, id(), start.done(), end.done(), false, 1 ) );
+ while( c->ok() ) {
+ if ( c->currKey().woCompare( l ) > 0 ) {
+ toInsert = c->currKey().firstElement().valuestr();
+ break;
+ }
+ c->advance();
+ }
+ // too much work to try to make this happen through inserts and deletes
+ const_cast< DiskLoc& >( bt()->keyNode( 1 ).prevChildBucket ) = DiskLoc();
+ const_cast< DiskLoc& >( bt()->keyNode( 1 ).recordLoc ).GETOFS() |= 1; // make unused
+ BSONObj k = BSON( "a" << toInsert );
+ Base::insert( k );
+ }
+ };
class All : public Suite {
public:
@@ -265,6 +380,9 @@ namespace BtreeTests {
add< MissingLocate >();
add< MissingLocateMultiBucket >();
add< SERVER983 >();
+ add< ReuseUnused >();
+ add< PackUnused >();
+ add< DontDropReferenceKey >();
}
} myall;
}