2009-01-13 16:36:06 +01:00
|
|
|
// pdfiletests.cpp : pdfile unit tests.
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copyright (C) 2008 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/>.
|
|
|
|
*/
|
|
|
|
|
2010-04-27 21:27:52 +02:00
|
|
|
#include "pch.h"
|
2009-01-13 16:36:06 +01:00
|
|
|
#include "../db/pdfile.h"
|
|
|
|
|
|
|
|
#include "../db/db.h"
|
|
|
|
#include "../db/json.h"
|
|
|
|
|
|
|
|
#include "dbtests.h"
|
|
|
|
|
|
|
|
namespace PdfileTests {
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
namespace ScanCapped {
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class Base {
|
|
|
|
public:
|
2010-01-29 23:22:34 +01:00
|
|
|
Base() : _context( ns() ){
|
2009-01-15 16:17:11 +01:00
|
|
|
}
|
2009-02-18 19:42:32 +01:00
|
|
|
virtual ~Base() {
|
2009-01-15 16:17:11 +01:00
|
|
|
if ( !nsd() )
|
|
|
|
return;
|
|
|
|
string n( ns() );
|
|
|
|
dropNS( n );
|
|
|
|
}
|
|
|
|
void run() {
|
|
|
|
stringstream spec;
|
|
|
|
spec << "{\"capped\":true,\"size\":2000,\"$nExtents\":" << nExtents() << "}";
|
|
|
|
string err;
|
|
|
|
ASSERT( userCreateNS( ns(), fromjson( spec.str() ), err, false ) );
|
|
|
|
prepare();
|
|
|
|
int j = 0;
|
2010-05-08 00:59:22 +02:00
|
|
|
for ( boost::shared_ptr<Cursor> i = theDataFileMgr.findAll( ns() );
|
2009-01-15 16:17:11 +01:00
|
|
|
i->ok(); i->advance(), ++j )
|
|
|
|
ASSERT_EQUALS( j, i->current().firstElement().number() );
|
|
|
|
ASSERT_EQUALS( count(), j );
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
j = count() - 1;
|
2010-05-08 00:59:22 +02:00
|
|
|
for ( boost::shared_ptr<Cursor> i =
|
2009-01-15 16:17:11 +01:00
|
|
|
findTableScan( ns(), fromjson( "{\"$natural\":-1}" ) );
|
|
|
|
i->ok(); i->advance(), --j )
|
|
|
|
ASSERT_EQUALS( j, i->current().firstElement().number() );
|
|
|
|
ASSERT_EQUALS( -1, j );
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual void prepare() = 0;
|
|
|
|
virtual int count() const = 0;
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// bypass standard alloc/insert routines to use the extent we want.
|
|
|
|
static DiskLoc insert( DiskLoc ext, int i ) {
|
|
|
|
BSONObjBuilder b;
|
|
|
|
b.append( "a", i );
|
|
|
|
BSONObj o = b.done();
|
|
|
|
int len = o.objsize();
|
|
|
|
Extent *e = ext.ext();
|
|
|
|
int ofs;
|
|
|
|
if ( e->lastRecord.isNull() )
|
2010-04-05 23:31:58 +02:00
|
|
|
ofs = ext.getOfs() + ( e->_extentData - (char *)e );
|
2009-01-15 16:17:11 +01:00
|
|
|
else
|
|
|
|
ofs = e->lastRecord.getOfs() + e->lastRecord.rec()->lengthWithHeaders;
|
|
|
|
DiskLoc dl( ext.a(), ofs );
|
|
|
|
Record *r = dl.rec();
|
|
|
|
r->lengthWithHeaders = Record::HeaderSize + len;
|
|
|
|
r->extentOfs = e->myLoc.getOfs();
|
|
|
|
r->nextOfs = DiskLoc::NullOfs;
|
2009-02-03 05:42:34 +01:00
|
|
|
r->prevOfs = e->lastRecord.isNull() ? DiskLoc::NullOfs : e->lastRecord.getOfs();
|
2009-01-15 16:17:11 +01:00
|
|
|
memcpy( r->data, o.objdata(), len );
|
|
|
|
if ( e->firstRecord.isNull() )
|
|
|
|
e->firstRecord = dl;
|
|
|
|
else
|
|
|
|
e->lastRecord.rec()->nextOfs = ofs;
|
|
|
|
e->lastRecord = dl;
|
|
|
|
return dl;
|
|
|
|
}
|
|
|
|
static const char *ns() {
|
2009-05-12 21:58:26 +02:00
|
|
|
return "unittests.ScanCapped";
|
2009-01-15 16:17:11 +01:00
|
|
|
}
|
|
|
|
static NamespaceDetails *nsd() {
|
|
|
|
return nsdetails( ns() );
|
|
|
|
}
|
2009-02-06 19:26:29 +01:00
|
|
|
private:
|
|
|
|
dblock lk_;
|
2010-01-29 23:22:34 +01:00
|
|
|
Client::Context _context;
|
2009-01-15 16:17:11 +01:00
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class Empty : public Base {
|
|
|
|
virtual void prepare() {}
|
|
|
|
virtual int count() const {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class EmptyLooped : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capFirstNewRecord = DiskLoc();
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class EmptyMultiExtentLooped : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capFirstNewRecord = DiskLoc();
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class Single : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 0 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class NewCapFirst : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 0 );
|
|
|
|
insert( nsd()->capExtent, 1 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class NewCapLast : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 1 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class NewCapMiddle : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 1 );
|
|
|
|
insert( nsd()->capExtent, 2 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class FirstExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
insert( nsd()->lastExtent, 1 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 2 );
|
|
|
|
insert( nsd()->capExtent, 3 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class LastExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capExtent = nsd()->lastExtent;
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
insert( nsd()->firstExtent, 1 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 2 );
|
|
|
|
insert( nsd()->capExtent, 3 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class MidExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capExtent = nsd()->firstExtent.ext()->xnext;
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
insert( nsd()->lastExtent, 1 );
|
|
|
|
insert( nsd()->firstExtent, 2 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 3 );
|
|
|
|
insert( nsd()->capExtent, 4 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class AloneInExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capExtent = nsd()->firstExtent.ext()->xnext;
|
|
|
|
insert( nsd()->lastExtent, 0 );
|
|
|
|
insert( nsd()->firstExtent, 1 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 2 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class FirstInExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capExtent = nsd()->firstExtent.ext()->xnext;
|
|
|
|
insert( nsd()->lastExtent, 0 );
|
|
|
|
insert( nsd()->firstExtent, 1 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 2 );
|
|
|
|
insert( nsd()->capExtent, 3 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class LastInExtent : public Base {
|
|
|
|
virtual void prepare() {
|
|
|
|
nsd()->capExtent = nsd()->firstExtent.ext()->xnext;
|
|
|
|
insert( nsd()->capExtent, 0 );
|
|
|
|
insert( nsd()->lastExtent, 1 );
|
|
|
|
insert( nsd()->firstExtent, 2 );
|
|
|
|
nsd()->capFirstNewRecord = insert( nsd()->capExtent, 3 );
|
|
|
|
}
|
|
|
|
virtual int count() const {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
virtual int nExtents() const {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
};
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
} // namespace ScanCapped
|
2009-02-27 23:18:56 +01:00
|
|
|
|
|
|
|
namespace Insert {
|
|
|
|
class Base {
|
|
|
|
public:
|
2010-01-29 23:22:34 +01:00
|
|
|
Base() : _context( ns() ){
|
2009-02-27 23:18:56 +01:00
|
|
|
}
|
|
|
|
virtual ~Base() {
|
|
|
|
if ( !nsd() )
|
|
|
|
return;
|
|
|
|
string n( ns() );
|
|
|
|
dropNS( n );
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
static const char *ns() {
|
2009-05-12 21:58:26 +02:00
|
|
|
return "unittests.pdfiletests.Insert";
|
2009-02-27 23:18:56 +01:00
|
|
|
}
|
|
|
|
static NamespaceDetails *nsd() {
|
|
|
|
return nsdetails( ns() );
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
dblock lk_;
|
2010-01-29 23:22:34 +01:00
|
|
|
Client::Context _context;
|
2009-02-27 23:18:56 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class UpdateDate : public Base {
|
|
|
|
public:
|
|
|
|
void run() {
|
|
|
|
BSONObjBuilder b;
|
2009-02-28 00:14:45 +01:00
|
|
|
b.appendTimestamp( "a" );
|
2009-02-27 23:18:56 +01:00
|
|
|
BSONObj o = b.done();
|
2009-02-28 00:14:45 +01:00
|
|
|
ASSERT( 0 == o.getField( "a" ).date() );
|
2010-04-28 14:25:56 +02:00
|
|
|
theDataFileMgr.insertWithObjMod( ns(), o );
|
2009-02-28 00:14:45 +01:00
|
|
|
ASSERT( 0 != o.getField( "a" ).date() );
|
2009-02-27 23:18:56 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace Insert
|
|
|
|
|
2009-05-12 22:37:23 +02:00
|
|
|
class All : public Suite {
|
2009-01-15 16:17:11 +01:00
|
|
|
public:
|
2009-09-17 23:23:38 +02:00
|
|
|
All() : Suite( "pdfile" ){}
|
|
|
|
|
|
|
|
void setupTests(){
|
2009-01-15 16:17:11 +01:00
|
|
|
add< ScanCapped::Empty >();
|
|
|
|
add< ScanCapped::EmptyLooped >();
|
|
|
|
add< ScanCapped::EmptyMultiExtentLooped >();
|
|
|
|
add< ScanCapped::Single >();
|
|
|
|
add< ScanCapped::NewCapFirst >();
|
|
|
|
add< ScanCapped::NewCapLast >();
|
|
|
|
add< ScanCapped::NewCapMiddle >();
|
|
|
|
add< ScanCapped::FirstExtent >();
|
|
|
|
add< ScanCapped::LastExtent >();
|
|
|
|
add< ScanCapped::MidExtent >();
|
|
|
|
add< ScanCapped::AloneInExtent >();
|
|
|
|
add< ScanCapped::FirstInExtent >();
|
|
|
|
add< ScanCapped::LastInExtent >();
|
2009-02-27 23:18:56 +01:00
|
|
|
add< Insert::UpdateDate >();
|
2009-01-15 16:17:11 +01:00
|
|
|
}
|
2009-09-17 23:23:38 +02:00
|
|
|
} myall;
|
2009-01-14 23:17:24 +01:00
|
|
|
|
2009-01-13 16:36:06 +01:00
|
|
|
} // namespace PdfileTests
|
|
|
|
|