0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 01:21:03 +01:00
mongodb/dbtests/updatetests.cpp

224 lines
7.1 KiB
C++

// updatetests.cpp : unit tests relating to update requests
//
/**
* 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/>.
*/
#include "../db/query.h"
#include "../db/db.h"
#include "../db/instance.h"
#include "../db/json.h"
#include "../db/lasterror.h"
#include "dbtests.h"
namespace UpdateTests {
class ClientBase {
public:
// NOTE: Not bothering to backup the old error record.
ClientBase() {
mongo::lastError.reset( new LastError() );
}
~ClientBase() {
mongo::lastError.release();
}
protected:
static void insert( const char *ns, BSONObj o ) {
client_.insert( ns, o );
}
static void update( const char *ns, BSONObj q, BSONObj o, bool upsert = 0 ) {
client_.update( ns, Query( q ), o, upsert );
}
static bool error() {
return !client_.getPrevError().getField( "err" ).isNull();
}
DBDirectClient &client() const { return client_; }
private:
static DBDirectClient client_;
};
DBDirectClient ClientBase::client_;
class Fail : public ClientBase {
public:
virtual ~Fail() {}
void run() {
prep();
ASSERT( !error() );
doIt();
ASSERT( error() );
}
protected:
const char *ns() { return "UpdateTests_Fail"; }
virtual void prep() {
insert( ns(), fromjson( "{a:1}" ) );
}
virtual void doIt() = 0;
};
class ModId : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{$set:{'_id':4}}" ) );
}
};
class ModNonmodMix : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{$set:{a:4},z:3}" ) );
}
};
class InvalidMod : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{$awk:{a:4}}" ) );
}
};
class ModNotFirst : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{z:3,$set:{a:4}}" ) );
}
};
class ModDuplicateFieldSpec : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{$set:{a:4},$inc:{a:1}}" ) );
}
};
class IncNonNumber : public Fail {
void doIt() {
update( ns(), BSONObj(), fromjson( "{$inc:{a:'d'}}" ) );
}
};
class IncTargetNonNumber : public Fail {
void doIt() {
insert( ns(), BSON( "a" << "a" ) );
update( ns(), BSON( "a" << "a" ), fromjson( "{$inc:{a:1}}" ) );
}
};
class SetBase : public ClientBase {
public:
~SetBase() {
client().dropCollection( ns() );
}
protected:
const char *ns() { return "updatetests.SetBase"; }
};
class SetNum : public SetBase {
public:
void run() {
client().insert( ns(), BSON( "a" << 1 ) );
client().update( ns(), BSON( "a" << 1 ), BSON( "$set" << BSON( "a" << 4 ) ) );
ASSERT( !client().findOne( ns(), BSON( "a" << 4 ) ).isEmpty() );
}
};
class SetString : public SetBase {
public:
void run() {
client().insert( ns(), BSON( "a" << "b" ) );
client().update( ns(), BSON( "a" << "b" ), BSON( "$set" << BSON( "a" << "c" ) ) );
ASSERT( !client().findOne( ns(), BSON( "a" << "c" ) ).isEmpty() );
}
};
class SetStringDifferentLength : public SetBase {
public:
void run() {
client().insert( ns(), BSON( "a" << "b" ) );
client().update( ns(), BSON( "a" << "b" ), BSON( "$set" << BSON( "a" << "cd" ) ) );
ASSERT( !client().findOne( ns(), BSON( "a" << "cd" ) ).isEmpty() );
}
};
class SetStringToNum : public SetBase {
public:
void run() {
client().insert( ns(), BSON( "a" << "b" ) );
client().update( ns(), BSONObj(), BSON( "$set" << BSON( "a" << 5 ) ) );
ASSERT( !client().findOne( ns(), BSON( "a" << 5 ) ).isEmpty() );
}
};
class SetStringToNumInPlace : public SetBase {
public:
void run() {
client().insert( ns(), BSON( "a" << "bcd" ) );
client().update( ns(), BSONObj(), BSON( "$set" << BSON( "a" << 5.0 ) ) );
ASSERT( !client().findOne( ns(), BSON( "a" << 5.0 ) ).isEmpty() );
}
};
class ModDotted : public SetBase {
public:
void run() {
client().insert( ns(), fromjson( "{a:{b:4}}" ) );
client().update( ns(), BSONObj(), BSON( "$inc" << BSON( "a.b" << 10 ) ) );
ASSERT( !client().findOne( ns(), BSON( "a.b" << 14 ) ).isEmpty() );
client().update( ns(), BSONObj(), BSON( "$set" << BSON( "a.b" << 55 ) ) );
ASSERT( !client().findOne( ns(), BSON( "a.b" << 55 ) ).isEmpty() );
}
};
class SetInPlaceDotted : public SetBase {
public:
void run() {
client().insert( ns(), fromjson( "{a:{b:'cdef'}}" ) );
client().update( ns(), BSONObj(), BSON( "$set" << BSON( "a.b" << "llll" ) ) );
ASSERT( !client().findOne( ns(), BSON( "a.b" << "llll" ) ).isEmpty() );
}
};
class SetRecreateDotted : public SetBase {
public:
void run() {
client().insert( ns(), fromjson( "{a:{b:'cdef'}}" ) );
client().update( ns(), BSONObj(), BSON( "$set" << BSON( "a.b" << "lllll" ) ) );
ASSERT( !client().findOne( ns(), BSON( "a.b" << "lllll" ) ).isEmpty() );
}
};
class All : public UnitTest::Suite {
public:
All() {
add< ModId >();
add< ModNonmodMix >();
add< InvalidMod >();
add< ModNotFirst >();
add< ModDuplicateFieldSpec >();
add< IncNonNumber >();
add< IncTargetNonNumber >();
add< SetNum >();
add< SetString >();
add< SetStringDifferentLength >();
add< SetStringToNum >();
add< SetStringToNumInPlace >();
add< ModDotted >();
add< SetInPlaceDotted >();
add< SetRecreateDotted >();
}
};
} // namespace UpdateTests
UnitTest::TestPtr updateTests() {
return UnitTest::createSuite< UpdateTests::All >();
}