// client.cpp /* * 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 . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #include "mongo/client/dbclientcursor.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/operation_context_impl.h" #include "mongo/dbtests/dbtests.h" namespace ClientTests { using std::unique_ptr; using std::string; using std::vector; class Base { public: Base(string coll) : _ns("test." + coll) { OperationContextImpl txn; DBDirectClient db(&txn); db.dropDatabase("test"); } virtual ~Base() { OperationContextImpl txn; DBDirectClient db(&txn); db.dropCollection(_ns); } const char* ns() { return _ns.c_str(); } const string _ns; }; class DropIndex : public Base { public: DropIndex() : Base("dropindex") {} void run() { OperationContextImpl txn; DBDirectClient db(&txn); db.insert(ns(), BSON("x" << 2)); ASSERT_EQUALS(1u, db.getIndexSpecs(ns()).size()); ASSERT_OK(dbtests::createIndex(&txn, ns(), BSON("x" << 1))); ASSERT_EQUALS(2u, db.getIndexSpecs(ns()).size()); db.dropIndex(ns(), BSON("x" << 1)); ASSERT_EQUALS(1u, db.getIndexSpecs(ns()).size()); ASSERT_OK(dbtests::createIndex(&txn, ns(), BSON("x" << 1))); ASSERT_EQUALS(2u, db.getIndexSpecs(ns()).size()); db.dropIndexes(ns()); ASSERT_EQUALS(1u, db.getIndexSpecs(ns()).size()); } }; /** * Check that nIndexes is incremented correctly when an index builds (and that it is not * incremented when an index fails to build), system.indexes has an entry added (or not), and * system.namespaces has a doc added (or not). */ class BuildIndex : public Base { public: BuildIndex() : Base("buildIndex") {} void run() { OperationContextImpl txn; OldClientWriteContext ctx(&txn, ns()); DBDirectClient db(&txn); db.insert(ns(), BSON("x" << 1 << "y" << 2)); db.insert(ns(), BSON("x" << 2 << "y" << 2)); Collection* collection = ctx.getCollection(); ASSERT(collection); IndexCatalog* indexCatalog = collection->getIndexCatalog(); ASSERT_EQUALS(1, indexCatalog->numIndexesReady(&txn)); // _id index ASSERT_EQUALS(1U, db.getIndexSpecs(ns()).size()); ASSERT_EQUALS(ErrorCodes::DuplicateKey, dbtests::createIndex(&txn, ns(), BSON("y" << 1), true)); ASSERT_EQUALS(1, indexCatalog->numIndexesReady(&txn)); ASSERT_EQUALS(1U, db.getIndexSpecs(ns()).size()); ASSERT_OK(dbtests::createIndex(&txn, ns(), BSON("x" << 1), true)); ASSERT_EQUALS(2, indexCatalog->numIndexesReady(&txn)); ASSERT_EQUALS(2U, db.getIndexSpecs(ns()).size()); } }; class CS_10 : public Base { public: CS_10() : Base("CS_10") {} void run() { OperationContextImpl txn; DBDirectClient db(&txn); const string longs(770, 'c'); for (int i = 0; i < 1111; ++i) { db.insert(ns(), BSON("a" << i << "b" << longs)); } ASSERT_OK(dbtests::createIndex(&txn, ns(), BSON("a" << 1 << "b" << 1))); unique_ptr 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() { OperationContextImpl txn; DBDirectClient db(&txn); for (int i = 0; i < 10; ++i) { db.insert(ns(), BSON("i" << i)); } unique_ptr c = db.query(ns(), Query().sort(BSON("i" << 1))); BSONObj o = c->next(); ASSERT(c->more()); ASSERT_EQUALS(9, c->objsLeftInBatch()); ASSERT(c->moreInCurrentBatch()); c->putBack(o); ASSERT(c->more()); ASSERT_EQUALS(10, c->objsLeftInBatch()); 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_EQUALS(0, c->objsLeftInBatch()); ASSERT(!c->moreInCurrentBatch()); c->putBack(o); ASSERT(c->more()); ASSERT_EQUALS(1, c->objsLeftInBatch()); ASSERT(c->moreInCurrentBatch()); ASSERT_EQUALS(1, c->itcount()); } }; class Create : public Base { public: Create() : Base("Create") {} void run() { OperationContextImpl txn; DBDirectClient db(&txn); db.createCollection("unittests.clienttests.create", 4096, true); BSONObj info; ASSERT(db.runCommand("unittests", BSON("collstats" << "clienttests.create"), info)); } }; class ConnectionStringTests { public: void run() { { ConnectionString s("a/b,c,d", ConnectionString::SET); ASSERT_EQUALS(ConnectionString::SET, s.type()); ASSERT_EQUALS("a", s.getSetName()); vector v = s.getServers(); ASSERT_EQUALS(3U, v.size()); ASSERT_EQUALS("b", v[0].host()); ASSERT_EQUALS("c", v[1].host()); ASSERT_EQUALS("d", v[2].host()); } } }; class All : public Suite { public: All() : Suite("client") {} void setupTests() { add(); add(); add(); add(); add(); add(); } }; SuiteInstance all; }