diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-07-10 12:42:27 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2015-07-11 05:49:49 -0400 |
commit | 48432412d79d0712367837a12637d3682c04fddb (patch) | |
tree | c78e1725fe7bfd1564ba89849aeaa8ac07bf4ffa /src/mongo/s/collection_metadata_test.cpp | |
parent | ac42068ddeaae27d2cd5cfc4808915491e5097c7 (diff) | |
download | mongo-48432412d79d0712367837a12637d3682c04fddb.tar.gz |
SERVER-18084 Move mongod metadata management to be under mongo/db
Moves the metadata management code specific to mongod under the mongo/db
directory along with its tests.
Diffstat (limited to 'src/mongo/s/collection_metadata_test.cpp')
-rw-r--r-- | src/mongo/s/collection_metadata_test.cpp | 1321 |
1 files changed, 0 insertions, 1321 deletions
diff --git a/src/mongo/s/collection_metadata_test.cpp b/src/mongo/s/collection_metadata_test.cpp deleted file mode 100644 index 8fe16a8d5f5..00000000000 --- a/src/mongo/s/collection_metadata_test.cpp +++ /dev/null @@ -1,1321 +0,0 @@ -/** - * Copyright (C) 2012 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/>. - * - * 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/platform/basic.h" - -#include <string> -#include <vector> - -#include "mongo/db/jsobj.h" -#include "mongo/dbtests/mock/mock_conn_registry.h" -#include "mongo/dbtests/mock/mock_remote_db_server.h" -#include "mongo/s/catalog/legacy/catalog_manager_legacy.h" -#include "mongo/s/catalog/type_chunk.h" -#include "mongo/s/catalog/type_collection.h" -#include "mongo/s/chunk_version.h" -#include "mongo/s/collection_metadata.h" -#include "mongo/s/metadata_loader.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/net/hostandport.h" - -namespace { - -using namespace mongo; - -using std::make_pair; -using std::string; -using std::unique_ptr; -using std::vector; - -const std::string CONFIG_HOST_PORT = "$dummy_config:27017"; - -class NoChunkFixture : public mongo::unittest::Test { -protected: - void setUp() { - _dummyConfig.reset(new MockRemoteDBServer(CONFIG_HOST_PORT)); - mongo::ConnectionString::setConnectionHook(MockConnRegistry::get()->getConnStrHook()); - MockConnRegistry::get()->addServer(_dummyConfig.get()); - - OID epoch = OID::gen(); - - CollectionType collType; - collType.setNs(NamespaceString{"test.foo"}); - collType.setKeyPattern(BSON("a" << 1)); - collType.setUnique(false); - collType.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); - collType.setEpoch(epoch); - ASSERT_OK(collType.validate()); - - _dummyConfig->insert(CollectionType::ConfigNS, collType.toBSON()); - - // Need a chunk on another shard, otherwise the chunks are invalid in general and we - // can't load metadata - ChunkType chunkType; - chunkType.setNS(NamespaceString{"test.foo"}.ns()); - chunkType.setShard("shard0001"); - chunkType.setMin(BSON("a" << MINKEY)); - chunkType.setMax(BSON("a" << MAXKEY)); - chunkType.setVersion(ChunkVersion(1, 0, epoch)); - chunkType.setName(OID::gen().toString()); - ASSERT_OK(collType.validate()); - - _dummyConfig->insert(ChunkType::ConfigNS, chunkType.toBSON()); - - ConnectionString configLoc = ConnectionString(HostAndPort(CONFIG_HOST_PORT)); - ASSERT(configLoc.isValid()); - CatalogManagerLegacy catalogManager; - catalogManager.init(configLoc); - - MetadataLoader loader; - Status status = loader.makeCollectionMetadata( - &catalogManager, "test.foo", "shard0000", NULL, &_metadata); - ASSERT_OK(status); - ASSERT_EQUALS(0u, _metadata.getNumChunks()); - } - - void tearDown() { - MockConnRegistry::get()->clear(); - } - - const CollectionMetadata& getCollMetadata() const { - return _metadata; - } - -private: - unique_ptr<MockRemoteDBServer> _dummyConfig; - CollectionMetadata _metadata; -}; - -TEST_F(NoChunkFixture, BasicBelongsToMe) { - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << MINKEY))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 10))); -} - -TEST_F(NoChunkFixture, CompoundKeyBelongsToMe) { - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 1 << "b" << 2))); -} - -TEST_F(NoChunkFixture, IsKeyValid) { - ASSERT_TRUE(getCollMetadata().isValidKey(BSON("a" - << "abcde"))); - ASSERT_TRUE(getCollMetadata().isValidKey(BSON("a" << 3))); - ASSERT_FALSE(getCollMetadata().isValidKey(BSON("a" - << "abcde" - << "b" << 1))); - ASSERT_FALSE(getCollMetadata().isValidKey(BSON("c" - << "abcde"))); -} - -TEST_F(NoChunkFixture, getNextFromEmpty) { - ChunkType nextChunk; - ASSERT(!getCollMetadata().getNextChunk(getCollMetadata().getMinKey(), &nextChunk)); -} - -TEST_F(NoChunkFixture, FirstChunkClonePlus) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - string errMsg; - const ChunkVersion version(99, 0, OID()); - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().clonePlusChunk(chunk, version, &errMsg)); - - ASSERT(errMsg.empty()); - ASSERT_EQUALS(1u, cloned->getNumChunks()); - ASSERT_EQUALS(cloned->getShardVersion().toLong(), version.toLong()); - ASSERT_EQUALS(cloned->getCollVersion().toLong(), version.toLong()); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 15))); -} - -TEST_F(NoChunkFixture, MustHaveVersionForFirstChunk) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata() // br - .clonePlusChunk(chunk, ChunkVersion(0, 0, OID()), &errMsg)); - - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); -} - -TEST_F(NoChunkFixture, NoPendingChunks) { - ASSERT(!getCollMetadata().keyIsPending(BSON("a" << 15))); - ASSERT(!getCollMetadata().keyIsPending(BSON("a" << 25))); -} - -TEST_F(NoChunkFixture, FirstPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 15))); - ASSERT(!cloned->keyIsPending(BSON("a" << 25))); - ASSERT(cloned->keyIsPending(BSON("a" << 10))); - ASSERT(!cloned->keyIsPending(BSON("a" << 20))); -} - -TEST_F(NoChunkFixture, EmptyMultiPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - chunk.setMin(BSON("a" << 40)); - chunk.setMax(BSON("a" << 50)); - - cloned.reset(cloned->clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 15))); - ASSERT(!cloned->keyIsPending(BSON("a" << 25))); - ASSERT(cloned->keyIsPending(BSON("a" << 45))); - ASSERT(!cloned->keyIsPending(BSON("a" << 55))); -} - -TEST_F(NoChunkFixture, MinusPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - cloned.reset(cloned->cloneMinusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(!cloned->keyIsPending(BSON("a" << 15))); - ASSERT(!cloned->keyIsPending(BSON("a" << 25))); -} - -TEST_F(NoChunkFixture, OverlappingPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 40)); - - cloned.reset(cloned->clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(!cloned->keyIsPending(BSON("a" << 15))); - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(cloned->keyIsPending(BSON("a" << 35))); - ASSERT(!cloned->keyIsPending(BSON("a" << 45))); -} - -TEST_F(NoChunkFixture, OverlappingPendingChunks) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - chunk.setMin(BSON("a" << 30)); - chunk.setMax(BSON("a" << 50)); - - cloned.reset(cloned->clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 40)); - - cloned.reset(cloned->clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(!cloned->keyIsPending(BSON("a" << 15))); - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(cloned->keyIsPending(BSON("a" << 35))); - ASSERT(!cloned->keyIsPending(BSON("a" << 45))); -} - -TEST_F(NoChunkFixture, MinusInvalidPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().cloneMinusPending(chunk, &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(NoChunkFixture, MinusOverlappingPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - chunk.setMin(BSON("a" << 15)); - chunk.setMax(BSON("a" << 35)); - - cloned.reset(cloned->cloneMinusPending(chunk, &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(NoChunkFixture, PlusChunkWithPending) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 15))); - ASSERT(!cloned->keyIsPending(BSON("a" << 25))); - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(cloned->clonePlusChunk( - chunk, ChunkVersion(1, 0, cloned->getCollVersion().epoch()), &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 15))); - ASSERT(!cloned->keyIsPending(BSON("a" << 25))); -} - -TEST_F(NoChunkFixture, MergeChunkEmpty) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - - cloned.reset(getCollMetadata().cloneMerge( - BSON("a" << 15), BSON("a" << 25), ChunkVersion(1, 0, OID::gen()), &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(NoChunkFixture, OrphanedDataRangeBegin) { - const CollectionMetadata& metadata = getCollMetadata(); - - KeyRange keyRange; - BSONObj lookupKey = metadata.getMinKey(); - ASSERT(metadata.getNextOrphanRange(lookupKey, &keyRange)); - - ASSERT(keyRange.minKey.woCompare(metadata.getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(metadata.getMaxKey()) == 0); - - // Make sure we don't have any more ranges - ASSERT(!metadata.getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -TEST_F(NoChunkFixture, OrphanedDataRangeMiddle) { - const CollectionMetadata& metadata = getCollMetadata(); - - KeyRange keyRange; - BSONObj lookupKey = BSON("a" << 20); - ASSERT(metadata.getNextOrphanRange(lookupKey, &keyRange)); - - ASSERT(keyRange.minKey.woCompare(metadata.getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(metadata.getMaxKey()) == 0); - ASSERT(keyRange.keyPattern.woCompare(metadata.getKeyPattern()) == 0); - - // Make sure we don't have any more ranges - ASSERT(!metadata.getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -TEST_F(NoChunkFixture, OrphanedDataRangeEnd) { - const CollectionMetadata& metadata = getCollMetadata(); - - KeyRange keyRange; - ASSERT(!metadata.getNextOrphanRange(metadata.getMaxKey(), &keyRange)); -} - -TEST_F(NoChunkFixture, PendingOrphanedDataRanges) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - ASSERT_EQUALS(errMsg, string("")); - ASSERT(cloned != NULL); - - KeyRange keyRange; - ASSERT(cloned->getNextOrphanRange(cloned->getMinKey(), &keyRange)); - ASSERT(keyRange.minKey.woCompare(cloned->getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(BSON("a" << 10)) == 0); - ASSERT(keyRange.keyPattern.woCompare(cloned->getKeyPattern()) == 0); - - ASSERT(cloned->getNextOrphanRange(keyRange.maxKey, &keyRange)); - ASSERT(keyRange.minKey.woCompare(BSON("a" << 20)) == 0); - ASSERT(keyRange.maxKey.woCompare(cloned->getMaxKey()) == 0); - ASSERT(keyRange.keyPattern.woCompare(cloned->getKeyPattern()) == 0); - - ASSERT(!cloned->getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -/** - * Fixture with single chunk containing: - * [10->20) - */ -class SingleChunkFixture : public mongo::unittest::Test { -protected: - void setUp() { - _dummyConfig.reset(new MockRemoteDBServer(CONFIG_HOST_PORT)); - mongo::ConnectionString::setConnectionHook(MockConnRegistry::get()->getConnStrHook()); - MockConnRegistry::get()->addServer(_dummyConfig.get()); - - OID epoch = OID::gen(); - ChunkVersion chunkVersion = ChunkVersion(1, 0, epoch); - - CollectionType collType; - collType.setNs(NamespaceString{"test.foo"}); - collType.setKeyPattern(BSON("a" << 1)); - collType.setUnique(false); - collType.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); - collType.setEpoch(epoch); - _dummyConfig->insert(CollectionType::ConfigNS, collType.toBSON()); - - BSONObj fooSingle = BSON( - ChunkType::name("test.foo-a_10") - << ChunkType::ns("test.foo") << ChunkType::min(BSON("a" << 10)) - << ChunkType::max(BSON("a" << 20)) - << ChunkType::DEPRECATED_lastmod(Date_t::fromMillisSinceEpoch(chunkVersion.toLong())) - << ChunkType::DEPRECATED_epoch(epoch) << ChunkType::shard("shard0000")); - _dummyConfig->insert(ChunkType::ConfigNS, fooSingle); - - ConnectionString configLoc = ConnectionString(HostAndPort(CONFIG_HOST_PORT)); - ASSERT(configLoc.isValid()); - CatalogManagerLegacy catalogManager; - catalogManager.init(configLoc); - - MetadataLoader loader; - Status status = loader.makeCollectionMetadata( - &catalogManager, "test.foo", "shard0000", NULL, &_metadata); - ASSERT_OK(status); - } - - void tearDown() { - MockConnRegistry::get()->clear(); - } - - const CollectionMetadata& getCollMetadata() const { - return _metadata; - } - -private: - unique_ptr<MockRemoteDBServer> _dummyConfig; - CollectionMetadata _metadata; -}; - -TEST_F(SingleChunkFixture, BasicBelongsToMe) { - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 10))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 15))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 19))); -} - -TEST_F(SingleChunkFixture, DoesntBelongsToMe) { - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 0))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 9))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 20))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 1234))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << MINKEY))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << MAXKEY))); -} - -TEST_F(SingleChunkFixture, CompoudKeyBelongsToMe) { - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 15 << "a" << 14))); -} - -TEST_F(SingleChunkFixture, getNextFromEmpty) { - ChunkType nextChunk; - ASSERT(getCollMetadata().getNextChunk(getCollMetadata().getMinKey(), &nextChunk)); - ASSERT_EQUALS(0, nextChunk.getMin().woCompare(BSON("a" << 10))); - ASSERT_EQUALS(0, nextChunk.getMax().woCompare(BSON("a" << 20))); -} - -TEST_F(SingleChunkFixture, GetLastChunkIsFalse) { - ChunkType nextChunk; - ASSERT(!getCollMetadata().getNextChunk(getCollMetadata().getMaxKey(), &nextChunk)); -} - -TEST_F(SingleChunkFixture, LastChunkCloneMinus) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - string errMsg; - const ChunkVersion zeroVersion(0, 0, getCollMetadata().getShardVersion().epoch()); - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneMigrate(chunk, zeroVersion, &errMsg)); - - ASSERT(errMsg.empty()); - ASSERT_EQUALS(0u, cloned->getNumChunks()); - ASSERT_EQUALS(cloned->getShardVersion().toLong(), zeroVersion.toLong()); - ASSERT_EQUALS(cloned->getCollVersion().toLong(), getCollMetadata().getCollVersion().toLong()); - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 15))); -} - -TEST_F(SingleChunkFixture, LastChunkMinusCantHaveNonZeroVersion) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - string errMsg; - ChunkVersion version(99, 0, OID()); - unique_ptr<CollectionMetadata> cloned(getCollMetadata().cloneMigrate(chunk, version, &errMsg)); - - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); -} - -TEST_F(SingleChunkFixture, PlusPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyBelongsToMe(BSON("a" << 15))); - ASSERT(!cloned->keyBelongsToMe(BSON("a" << 25))); - ASSERT(!cloned->keyIsPending(BSON("a" << 15))); - ASSERT(cloned->keyIsPending(BSON("a" << 25))); -} - -TEST_F(SingleChunkFixture, PlusOverlapPendingChunk) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(SingleChunkFixture, MinusChunkWithPending) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(!cloned->keyIsPending(BSON("a" << 35))); - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - cloned.reset( - cloned->cloneMigrate(chunk, ChunkVersion(0, 0, cloned->getCollVersion().epoch()), &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(!cloned->keyIsPending(BSON("a" << 35))); -} - -TEST_F(SingleChunkFixture, SingleSplit) { - ChunkVersion version; - getCollMetadata().getCollVersion().cloneTo(&version); - version.incMinor(); - - ChunkType chunk; - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - vector<BSONObj> splitPoints; - splitPoints.push_back(BSON("a" << 14)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneSplit(chunk, splitPoints, version, &errMsg)); - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ChunkVersion newVersion(cloned->getCollVersion()); - ASSERT_EQUALS(version.epoch(), newVersion.epoch()); - ASSERT_EQUALS(version.majorVersion(), newVersion.majorVersion()); - ASSERT_EQUALS(version.minorVersion() + 1, newVersion.minorVersion()); - - ASSERT(cloned->getNextChunk(BSON("a" << MINKEY), &chunk)); - ASSERT(chunk.getMin().woCompare(BSON("a" << 10)) == 0); - ASSERT(chunk.getMax().woCompare(BSON("a" << 14)) == 0); - - ASSERT(cloned->getNextChunk(BSON("a" << 14), &chunk)); - ASSERT(chunk.getMin().woCompare(BSON("a" << 14)) == 0); - ASSERT(chunk.getMax().woCompare(BSON("a" << 20)) == 0); - - ASSERT_FALSE(cloned->getNextChunk(BSON("a" << 20), &chunk)); -} - -TEST_F(SingleChunkFixture, MultiSplit) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - vector<BSONObj> splitPoints; - splitPoints.push_back(BSON("a" << 14)); - splitPoints.push_back(BSON("a" << 16)); - - ChunkVersion version; - getCollMetadata().getCollVersion().cloneTo(&version); - version.incMinor(); - - cloned.reset(getCollMetadata().cloneSplit(chunk, splitPoints, version, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ChunkVersion newVersion(cloned->getCollVersion()); - ASSERT_EQUALS(version.epoch(), newVersion.epoch()); - ASSERT_EQUALS(version.majorVersion(), newVersion.majorVersion()); - ASSERT_EQUALS(version.minorVersion() + 2, newVersion.minorVersion()); - - ASSERT(cloned->getNextChunk(BSON("a" << MINKEY), &chunk)); - ASSERT(chunk.getMin().woCompare(BSON("a" << 10)) == 0); - ASSERT(chunk.getMax().woCompare(BSON("a" << 14)) == 0); - - ASSERT(cloned->getNextChunk(BSON("a" << 14), &chunk)); - ASSERT(chunk.getMin().woCompare(BSON("a" << 14)) == 0); - ASSERT(chunk.getMax().woCompare(BSON("a" << 16)) == 0); - - ASSERT(cloned->getNextChunk(BSON("a" << 16), &chunk)); - ASSERT(chunk.getMin().woCompare(BSON("a" << 16)) == 0); - ASSERT(chunk.getMax().woCompare(BSON("a" << 20)) == 0); - - ASSERT_FALSE(cloned->getNextChunk(BSON("a" << 20), &chunk)); -} - -TEST_F(SingleChunkFixture, SplitChunkWithPending) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(!cloned->keyIsPending(BSON("a" << 35))); - - chunk.setMin(BSON("a" << 10)); - chunk.setMax(BSON("a" << 20)); - - vector<BSONObj> splitPoints; - splitPoints.push_back(BSON("a" << 14)); - splitPoints.push_back(BSON("a" << 16)); - - cloned.reset(cloned->cloneSplit(chunk, - splitPoints, - ChunkVersion(cloned->getCollVersion().majorVersion() + 1, - 0, - cloned->getCollVersion().epoch()), - &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - - ASSERT(cloned->keyIsPending(BSON("a" << 25))); - ASSERT(!cloned->keyIsPending(BSON("a" << 35))); -} - - -TEST_F(SingleChunkFixture, MergeChunkSingle) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - - cloned.reset(getCollMetadata().cloneMerge( - BSON("a" << 10), BSON("a" << 20), ChunkVersion(2, 0, OID::gen()), &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(SingleChunkFixture, ChunkOrphanedDataRanges) { - KeyRange keyRange; - ASSERT(getCollMetadata().getNextOrphanRange(getCollMetadata().getMinKey(), &keyRange)); - ASSERT(keyRange.minKey.woCompare(getCollMetadata().getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(BSON("a" << 10)) == 0); - ASSERT(keyRange.keyPattern.woCompare(getCollMetadata().getKeyPattern()) == 0); - - ASSERT(getCollMetadata().getNextOrphanRange(keyRange.maxKey, &keyRange)); - ASSERT(keyRange.minKey.woCompare(BSON("a" << 20)) == 0); - ASSERT(keyRange.maxKey.woCompare(getCollMetadata().getMaxKey()) == 0); - ASSERT(keyRange.keyPattern.woCompare(getCollMetadata().getKeyPattern()) == 0); - - ASSERT(!getCollMetadata().getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -/** - * Fixture with single chunk containing: - * [(min, min)->(max, max)) - */ -class SingleChunkMinMaxCompoundKeyFixture : public mongo::unittest::Test { -protected: - void setUp() { - _dummyConfig.reset(new MockRemoteDBServer(CONFIG_HOST_PORT)); - mongo::ConnectionString::setConnectionHook(MockConnRegistry::get()->getConnStrHook()); - MockConnRegistry::get()->addServer(_dummyConfig.get()); - - OID epoch = OID::gen(); - ChunkVersion chunkVersion = ChunkVersion(1, 0, epoch); - - CollectionType collType; - collType.setNs(NamespaceString{"test.foo"}); - collType.setKeyPattern(BSON("a" << 1)); - collType.setUnique(false); - collType.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); - collType.setEpoch(epoch); - _dummyConfig->insert(CollectionType::ConfigNS, collType.toBSON()); - - BSONObj fooSingle = BSON( - ChunkType::name("test.foo-a_MinKey") - << ChunkType::ns("test.foo") << ChunkType::min(BSON("a" << MINKEY << "b" << MINKEY)) - << ChunkType::max(BSON("a" << MAXKEY << "b" << MAXKEY)) - << ChunkType::DEPRECATED_lastmod(Date_t::fromMillisSinceEpoch(chunkVersion.toLong())) - << ChunkType::DEPRECATED_epoch(epoch) << ChunkType::shard("shard0000")); - _dummyConfig->insert(ChunkType::ConfigNS, fooSingle); - - ConnectionString configLoc = ConnectionString(HostAndPort(CONFIG_HOST_PORT)); - ASSERT(configLoc.isValid()); - CatalogManagerLegacy catalogManager; - catalogManager.init(configLoc); - - MetadataLoader loader; - Status status = loader.makeCollectionMetadata( - &catalogManager, "test.foo", "shard0000", NULL, &_metadata); - ASSERT_OK(status); - } - - void tearDown() { - MockConnRegistry::get()->clear(); - } - - const CollectionMetadata& getCollMetadata() const { - return _metadata; - } - -private: - unique_ptr<MockRemoteDBServer> _dummyConfig; - CollectionMetadata _metadata; -}; - -// Note: no tests for single key belongsToMe because they are not allowed -// if shard key is compound. - -TEST_F(SingleChunkMinMaxCompoundKeyFixture, CompoudKeyBelongsToMe) { - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << MINKEY << "b" << MINKEY))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << MAXKEY << "b" << MAXKEY))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << MINKEY << "b" << 10))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 10 << "b" << 20))); -} - -/** - * Fixture with chunks: - * [(10, 0)->(20, 0)), [(30, 0)->(40, 0)) - */ -class TwoChunksWithGapCompoundKeyFixture : public mongo::unittest::Test { -protected: - void setUp() { - _dummyConfig.reset(new MockRemoteDBServer(CONFIG_HOST_PORT)); - mongo::ConnectionString::setConnectionHook(MockConnRegistry::get()->getConnStrHook()); - MockConnRegistry::get()->addServer(_dummyConfig.get()); - - OID epoch = OID::gen(); - ChunkVersion chunkVersion = ChunkVersion(1, 0, epoch); - - CollectionType collType; - collType.setNs(NamespaceString{"test.foo"}); - collType.setKeyPattern(BSON("a" << 1)); - collType.setUnique(false); - collType.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); - collType.setEpoch(epoch); - _dummyConfig->insert(CollectionType::ConfigNS, collType.toBSON()); - - _dummyConfig->insert( - ChunkType::ConfigNS, - BSON(ChunkType::name("test.foo-a_10") - << ChunkType::ns("test.foo") << ChunkType::min(BSON("a" << 10 << "b" << 0)) - << ChunkType::max(BSON("a" << 20 << "b" << 0)) - << ChunkType::DEPRECATED_lastmod( - Date_t::fromMillisSinceEpoch(chunkVersion.toLong())) - << ChunkType::DEPRECATED_epoch(epoch) << ChunkType::shard("shard0000"))); - - _dummyConfig->insert( - ChunkType::ConfigNS, - BSON(ChunkType::name("test.foo-a_10") - << ChunkType::ns("test.foo") << ChunkType::min(BSON("a" << 30 << "b" << 0)) - << ChunkType::max(BSON("a" << 40 << "b" << 0)) - << ChunkType::DEPRECATED_lastmod( - Date_t::fromMillisSinceEpoch(chunkVersion.toLong())) - << ChunkType::DEPRECATED_epoch(epoch) << ChunkType::shard("shard0000"))); - - ConnectionString configLoc = ConnectionString(HostAndPort(CONFIG_HOST_PORT)); - ASSERT(configLoc.isValid()); - CatalogManagerLegacy catalogManager; - catalogManager.init(configLoc); - - MetadataLoader loader; - Status status = loader.makeCollectionMetadata( - &catalogManager, "test.foo", "shard0000", NULL, &_metadata); - ASSERT_OK(status); - } - - void tearDown() { - MockConnRegistry::get()->clear(); - } - - const CollectionMetadata& getCollMetadata() const { - return _metadata; - } - -private: - unique_ptr<MockRemoteDBServer> _dummyConfig; - CollectionMetadata _metadata; -}; - -TEST_F(TwoChunksWithGapCompoundKeyFixture, ClonePlusBasic) { - ChunkType chunk; - chunk.setMin(BSON("a" << 40 << "b" << 0)); - chunk.setMax(BSON("a" << 50 << "b" << 0)); - - string errMsg; - ChunkVersion version(1, 0, getCollMetadata().getShardVersion().epoch()); - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().clonePlusChunk(chunk, version, &errMsg)); - - ASSERT(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); - ASSERT_EQUALS(3u, cloned->getNumChunks()); - - // TODO: test maxShardVersion, maxCollVersion - - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 25 << "b" << 0))); - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 29 << "b" << 0))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 30 << "b" << 0))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 45 << "b" << 0))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 49 << "b" << 0))); - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 50 << "b" << 0))); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, ClonePlusOverlappingRange) { - ChunkType chunk; - chunk.setMin(BSON("a" << 15 << "b" << 0)); - chunk.setMax(BSON("a" << 25 << "b" << 0)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().clonePlusChunk(chunk, ChunkVersion(1, 0, OID()), &errMsg)); - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, CloneMinusBasic) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10 << "b" << 0)); - chunk.setMax(BSON("a" << 20 << "b" << 0)); - - string errMsg; - ChunkVersion version(2, 0, OID()); - unique_ptr<CollectionMetadata> cloned(getCollMetadata().cloneMigrate(chunk, version, &errMsg)); - - ASSERT(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); - ASSERT_EQUALS(1u, cloned->getNumChunks()); - - // TODO: test maxShardVersion, maxCollVersion - - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 5 << "b" << 0))); - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 15 << "b" << 0))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 30 << "b" << 0))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 35 << "b" << 0))); - ASSERT_FALSE(cloned->keyBelongsToMe(BSON("a" << 40 << "b" << 0))); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, CloneMinusNonExisting) { - ChunkType chunk; - chunk.setMin(BSON("a" << 25 << "b" << 0)); - chunk.setMax(BSON("a" << 28 << "b" << 0)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneMigrate(chunk, ChunkVersion(1, 0, OID()), &errMsg)); - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, CloneSplitBasic) { - const BSONObj min(BSON("a" << 10 << "b" << 0)); - const BSONObj max(BSON("a" << 20 << "b" << 0)); - - ChunkType chunk; - chunk.setMin(min); - chunk.setMax(max); - - const BSONObj split1(BSON("a" << 15 << "b" << 0)); - const BSONObj split2(BSON("a" << 18 << "b" << 0)); - vector<BSONObj> splitKeys; - splitKeys.push_back(split1); - splitKeys.push_back(split2); - ChunkVersion version(1, 99, OID()); // first chunk 1|99 , second 1|100 - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneSplit(chunk, splitKeys, version, &errMsg)); - - version.incMinor(); /* second chunk 1|100, first split point */ - version.incMinor(); /* third chunk 1|101, second split point */ - ASSERT_EQUALS(cloned->getShardVersion().toLong(), version.toLong() /* 1|101 */); - ASSERT_EQUALS(cloned->getCollVersion().toLong(), version.toLong()); - ASSERT_EQUALS(getCollMetadata().getNumChunks(), 2u); - ASSERT_EQUALS(cloned->getNumChunks(), 4u); - ASSERT(cloned->keyBelongsToMe(min)); - ASSERT(cloned->keyBelongsToMe(split1)); - ASSERT(cloned->keyBelongsToMe(split2)); - ASSERT(!cloned->keyBelongsToMe(max)); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, CloneSplitOutOfRangeSplitPoint) { - ChunkType chunk; - chunk.setMin(BSON("a" << 10 << "b" << 0)); - chunk.setMax(BSON("a" << 20 << "b" << 0)); - - vector<BSONObj> splitKeys; - splitKeys.push_back(BSON("a" << 5 << "b" << 0)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneSplit(chunk, splitKeys, ChunkVersion(1, 0, OID()), &errMsg)); - - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, CloneSplitBadChunkRange) { - const BSONObj min(BSON("a" << 10 << "b" << 0)); - const BSONObj max(BSON("a" << 25 << "b" << 0)); - - ChunkType chunk; - chunk.setMin(BSON("a" << 10 << "b" << 0)); - chunk.setMax(BSON("a" << 25 << "b" << 0)); - - vector<BSONObj> splitKeys; - splitKeys.push_back(BSON("a" << 15 << "b" << 0)); - - string errMsg; - unique_ptr<CollectionMetadata> cloned( - getCollMetadata().cloneSplit(chunk, splitKeys, ChunkVersion(1, 0, OID()), &errMsg)); - - ASSERT(cloned == NULL); - ASSERT_FALSE(errMsg.empty()); - ASSERT_EQUALS(2u, getCollMetadata().getNumChunks()); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, ChunkGapOrphanedDataRanges) { - KeyRange keyRange; - ASSERT(getCollMetadata().getNextOrphanRange(getCollMetadata().getMinKey(), &keyRange)); - ASSERT(keyRange.minKey.woCompare(getCollMetadata().getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(BSON("a" << 10 << "b" << 0)) == 0); - ASSERT(keyRange.keyPattern.woCompare(getCollMetadata().getKeyPattern()) == 0); - - ASSERT(getCollMetadata().getNextOrphanRange(keyRange.maxKey, &keyRange)); - ASSERT(keyRange.minKey.woCompare(BSON("a" << 20 << "b" << 0)) == 0); - ASSERT(keyRange.maxKey.woCompare(BSON("a" << 30 << "b" << 0)) == 0); - ASSERT(keyRange.keyPattern.woCompare(getCollMetadata().getKeyPattern()) == 0); - - ASSERT(getCollMetadata().getNextOrphanRange(keyRange.maxKey, &keyRange)); - ASSERT(keyRange.minKey.woCompare(BSON("a" << 40 << "b" << 0)) == 0); - ASSERT(keyRange.maxKey.woCompare(getCollMetadata().getMaxKey()) == 0); - ASSERT(keyRange.keyPattern.woCompare(getCollMetadata().getKeyPattern()) == 0); - - ASSERT(!getCollMetadata().getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -TEST_F(TwoChunksWithGapCompoundKeyFixture, ChunkGapAndPendingOrphanedDataRanges) { - string errMsg; - ChunkType chunk; - unique_ptr<CollectionMetadata> cloned; - - chunk.setMin(BSON("a" << 20 << "b" << 0)); - chunk.setMax(BSON("a" << 30 << "b" << 0)); - - cloned.reset(getCollMetadata().clonePlusPending(chunk, &errMsg)); - ASSERT_EQUALS(errMsg, string("")); - ASSERT(cloned != NULL); - - KeyRange keyRange; - ASSERT(cloned->getNextOrphanRange(cloned->getMinKey(), &keyRange)); - ASSERT(keyRange.minKey.woCompare(cloned->getMinKey()) == 0); - ASSERT(keyRange.maxKey.woCompare(BSON("a" << 10 << "b" << 0)) == 0); - ASSERT(keyRange.keyPattern.woCompare(cloned->getKeyPattern()) == 0); - - ASSERT(cloned->getNextOrphanRange(keyRange.maxKey, &keyRange)); - ASSERT(keyRange.minKey.woCompare(BSON("a" << 40 << "b" << 0)) == 0); - ASSERT(keyRange.maxKey.woCompare(cloned->getMaxKey()) == 0); - ASSERT(keyRange.keyPattern.woCompare(cloned->getKeyPattern()) == 0); - - ASSERT(!cloned->getNextOrphanRange(keyRange.maxKey, &keyRange)); -} - -/** - * Fixture with chunk containing: - * [min->10) , [10->20) , <gap> , [30->max) - */ -class ThreeChunkWithRangeGapFixture : public mongo::unittest::Test { -protected: - void setUp() { - _dummyConfig.reset(new MockRemoteDBServer(CONFIG_HOST_PORT)); - mongo::ConnectionString::setConnectionHook(MockConnRegistry::get()->getConnStrHook()); - MockConnRegistry::get()->addServer(_dummyConfig.get()); - - OID epoch(OID::gen()); - - { - CollectionType collType; - collType.setNs(NamespaceString{"x.y"}); - collType.setKeyPattern(BSON("a" << 1)); - collType.setUnique(false); - collType.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); - collType.setEpoch(epoch); - _dummyConfig->insert(CollectionType::ConfigNS, collType.toBSON()); - } - - { - ChunkVersion version(1, 1, epoch); - _dummyConfig->insert(ChunkType::ConfigNS, - BSON(ChunkType::name("x.y-a_MinKey") - << ChunkType::ns("x.y") << ChunkType::min(BSON("a" << MINKEY)) - << ChunkType::max(BSON("a" << 10)) - << ChunkType::DEPRECATED_lastmod( - Date_t::fromMillisSinceEpoch(version.toLong())) - << ChunkType::DEPRECATED_epoch(version.epoch()) - << ChunkType::shard("shard0000"))); - } - - { - ChunkVersion version(1, 3, epoch); - _dummyConfig->insert(ChunkType::ConfigNS, - BSON(ChunkType::name("x.y-a_10") - << ChunkType::ns("x.y") << ChunkType::min(BSON("a" << 10)) - << ChunkType::max(BSON("a" << 20)) - << ChunkType::DEPRECATED_lastmod( - Date_t::fromMillisSinceEpoch(version.toLong())) - << ChunkType::DEPRECATED_epoch(version.epoch()) - << ChunkType::shard("shard0000"))); - } - - { - ChunkVersion version(1, 2, epoch); - _dummyConfig->insert(ChunkType::ConfigNS, - BSON(ChunkType::name("x.y-a_30") - << ChunkType::ns("x.y") << ChunkType::min(BSON("a" << 30)) - << ChunkType::max(BSON("a" << MAXKEY)) - << ChunkType::DEPRECATED_lastmod( - Date_t::fromMillisSinceEpoch(version.toLong())) - << ChunkType::DEPRECATED_epoch(version.epoch()) - << ChunkType::shard("shard0000"))); - } - - ConnectionString configLoc = ConnectionString(HostAndPort(CONFIG_HOST_PORT)); - ASSERT(configLoc.isValid()); - CatalogManagerLegacy catalogManager; - catalogManager.init(configLoc); - - MetadataLoader loader; - Status status = loader.makeCollectionMetadata( - &catalogManager, "test.foo", "shard0000", NULL, &_metadata); - ASSERT_OK(status); - } - - void tearDown() { - MockConnRegistry::get()->clear(); - } - - const CollectionMetadata& getCollMetadata() const { - return _metadata; - } - -private: - unique_ptr<MockRemoteDBServer> _dummyConfig; - CollectionMetadata _metadata; -}; - -TEST_F(ThreeChunkWithRangeGapFixture, ShardOwnsDoc) { - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 5))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 10))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 30))); - ASSERT(getCollMetadata().keyBelongsToMe(BSON("a" << 40))); -} - -TEST_F(ThreeChunkWithRangeGapFixture, ShardDoesntOwnDoc) { - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << 25))); - ASSERT_FALSE(getCollMetadata().keyBelongsToMe(BSON("a" << MAXKEY))); -} - -TEST_F(ThreeChunkWithRangeGapFixture, GetNextFromEmpty) { - ChunkType nextChunk; - ASSERT(getCollMetadata().getNextChunk(getCollMetadata().getMinKey(), &nextChunk)); - ASSERT_EQUALS(0, nextChunk.getMin().woCompare(BSON("a" << MINKEY))); - ASSERT_EQUALS(0, nextChunk.getMax().woCompare(BSON("a" << 10))); -} - -TEST_F(ThreeChunkWithRangeGapFixture, GetNextFromMiddle) { - ChunkType nextChunk; - ASSERT(getCollMetadata().getNextChunk(BSON("a" << 20), &nextChunk)); - ASSERT_EQUALS(0, nextChunk.getMin().woCompare(BSON("a" << 30))); - ASSERT_EQUALS(0, nextChunk.getMax().woCompare(BSON("a" << MAXKEY))); -} - -TEST_F(ThreeChunkWithRangeGapFixture, GetNextFromLast) { - ChunkType nextChunk; - ASSERT(getCollMetadata().getNextChunk(BSON("a" << 30), &nextChunk)); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkHoleInRange) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - - // Try to merge with hole in range - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - cloned.reset(getCollMetadata().cloneMerge( - BSON("a" << 10), BSON("a" << MAXKEY), newShardVersion, &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkDiffEndKey) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - - // Try to merge with different end key - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - cloned.reset(getCollMetadata().cloneMerge( - BSON("a" << MINKEY), BSON("a" << 19), newShardVersion, &errMsg)); - - ASSERT_NOT_EQUALS(errMsg, ""); - ASSERT(cloned == NULL); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkMinKey) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - - ASSERT_EQUALS(getCollMetadata().getNumChunks(), 3u); - - // Try to merge lowest chunks together - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - cloned.reset(getCollMetadata().cloneMerge( - BSON("a" << MINKEY), BSON("a" << 20), newShardVersion, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 10))); - ASSERT_EQUALS(cloned->getNumChunks(), 2u); - ASSERT_EQUALS(cloned->getShardVersion().majorVersion(), 5); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkMaxKey) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - - // Add one chunk to complete the range - ChunkType chunk; - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - cloned.reset(getCollMetadata().clonePlusChunk(chunk, newShardVersion, &errMsg)); - ASSERT_EQUALS(errMsg, ""); - ASSERT_EQUALS(cloned->getNumChunks(), 4u); - ASSERT(cloned != NULL); - - // Try to merge highest chunks together - newShardVersion.incMajor(); - cloned.reset( - cloned->cloneMerge(BSON("a" << 20), BSON("a" << MAXKEY), newShardVersion, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 30))); - ASSERT_EQUALS(cloned->getNumChunks(), 3u); - ASSERT_EQUALS(cloned->getShardVersion().majorVersion(), 6); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkFullRange) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - - // Add one chunk to complete the range - ChunkType chunk; - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - cloned.reset(getCollMetadata().clonePlusChunk(chunk, newShardVersion, &errMsg)); - ASSERT_EQUALS(errMsg, ""); - ASSERT_EQUALS(cloned->getNumChunks(), 4u); - ASSERT(cloned != NULL); - - // Try to merge all chunks together - newShardVersion.incMajor(); - cloned.reset( - cloned->cloneMerge(BSON("a" << MINKEY), BSON("a" << MAXKEY), newShardVersion, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 10))); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 30))); - ASSERT_EQUALS(cloned->getNumChunks(), 1u); - ASSERT_EQUALS(cloned->getShardVersion().majorVersion(), 6); -} - -TEST_F(ThreeChunkWithRangeGapFixture, MergeChunkMiddleRange) { - string errMsg; - unique_ptr<CollectionMetadata> cloned; - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - - // Add one chunk to complete the range - ChunkType chunk; - chunk.setMin(BSON("a" << 20)); - chunk.setMax(BSON("a" << 30)); - cloned.reset(getCollMetadata().clonePlusChunk(chunk, newShardVersion, &errMsg)); - ASSERT_EQUALS(errMsg, ""); - ASSERT_EQUALS(cloned->getNumChunks(), 4u); - ASSERT(cloned != NULL); - - // Try to merge middle two chunks - newShardVersion.incMajor(); - cloned.reset(cloned->cloneMerge(BSON("a" << 10), BSON("a" << 30), newShardVersion, &errMsg)); - - ASSERT_EQUALS(errMsg, ""); - ASSERT(cloned != NULL); - ASSERT(cloned->keyBelongsToMe(BSON("a" << 20))); - ASSERT_EQUALS(cloned->getNumChunks(), 3u); - ASSERT_EQUALS(cloned->getShardVersion().majorVersion(), 6); -} - -TEST_F(ThreeChunkWithRangeGapFixture, CannotMergeWithHole) { - string errMsg; - ChunkVersion newShardVersion(5, 0, getCollMetadata().getShardVersion().epoch()); - - // Try to merge middle two chunks with a hole in the middle. - newShardVersion.incMajor(); - CollectionMetadata* result = - getCollMetadata().cloneMerge(BSON("a" << 10), BSON("a" << 30), newShardVersion, &errMsg); - ASSERT(result == NULL); - ASSERT(!errMsg.empty()); -} - -} // unnamed namespace |