diff options
Diffstat (limited to 'src/mongo/s/compute_at_cluster_time_test.cpp')
-rw-r--r-- | src/mongo/s/compute_at_cluster_time_test.cpp | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/src/mongo/s/compute_at_cluster_time_test.cpp b/src/mongo/s/compute_at_cluster_time_test.cpp deleted file mode 100644 index da30e27251f..00000000000 --- a/src/mongo/s/compute_at_cluster_time_test.cpp +++ /dev/null @@ -1,348 +0,0 @@ - -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * 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 Server Side 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 <boost/optional.hpp> - -#include "mongo/client/remote_command_targeter_mock.h" -#include "mongo/db/logical_clock.h" -#include "mongo/db/logical_time.h" -#include "mongo/s/catalog_cache_test_fixture.h" -#include "mongo/s/client/shard_remote.h" -#include "mongo/s/cluster_commands_helpers.h" -#include "mongo/s/session_catalog_router.h" -#include "mongo/s/shard_id.h" -#include "mongo/s/sharding_router_test_fixture.h" -#include "mongo/s/transaction_router.h" -#include "mongo/unittest/unittest.h" - -namespace mongo { -namespace { - -const HostAndPort kTestConfigShardHost = HostAndPort("FakeConfigHost", 12345); - -const ShardId shardOneId("shardOne"); -const HostAndPort shardOne("shardOne:1234"); - -const ShardId shardTwoId("shardTwo"); -const HostAndPort shardTwo("shardTwo:1234"); - -const NamespaceString kNss = NamespaceString("test", "coll"); -const BSONObj kEmptyQuery; -const BSONObj kEmptyCollation; -const LogicalTime kInMemoryLogicalTime(Timestamp(3, 1)); - -const TxnNumber kTxnNumber = 3; - -class AtClusterTimeTest : public ShardingTestFixture { -protected: - void setUp() { - ShardingTestFixture::setUp(); - configTargeter()->setFindHostReturnValue(kTestConfigShardHost); - std::vector<std::tuple<ShardId, HostAndPort>> shardInfos; - shardInfos.push_back(std::make_tuple(shardOneId, shardOne)); - shardInfos.push_back(std::make_tuple(shardTwoId, shardTwo)); - - ShardingTestFixture::addRemoteShards(shardInfos); - - // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); - logicalClock->setClusterTimeFromTrustedSource(kInMemoryLogicalTime); - LogicalClock::set(getServiceContext(), std::move(logicalClock)); - - operationContext()->setLogicalSessionId(makeLogicalSessionIdForTest()); - operationContext()->setTxnNumber(kTxnNumber); - repl::ReadConcernArgs::get(operationContext()) = - repl::ReadConcernArgs(repl::ReadConcernLevel::kSnapshotReadConcern); - - _scopedSession.emplace(operationContext()); - txnRouter()->beginOrContinueTxn( - operationContext(), kTxnNumber, TransactionRouter::TransactionActions::kStart); - } - - TransactionRouter* txnRouter() const { - return TransactionRouter::get(operationContext()); - } - - LogicalTime getSelectedTime() { - return txnRouter()->getAtClusterTime()->getTime(); - } - -private: - boost::optional<RouterOperationContextSession> _scopedSession; -}; - -TEST_F(AtClusterTimeTest, ComputeValidValid) { - auto shardOne = shardRegistry()->getShardNoReload(shardOneId); - LogicalTime timeOne(Timestamp(10, 2)); - shardOne->updateLastCommittedOpTime(timeOne); - ASSERT_EQ(timeOne, shardOne->getLastCommittedOpTime()); - - auto shardTwo = shardRegistry()->getShardNoReload(shardTwoId); - LogicalTime timeTwo(Timestamp(15, 1)); - shardTwo->updateLastCommittedOpTime(timeTwo); - ASSERT_EQ(timeTwo, shardTwo->getLastCommittedOpTime()); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {shardOneId, shardTwoId}, kNss, kEmptyQuery, kEmptyCollation); - // TODO SERVER-36312: - // ASSERT_EQ(getSelectedTime(), timeTwo); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -TEST_F(AtClusterTimeTest, ComputeValidInvalid) { - auto shardOne = shardRegistry()->getShardNoReload(shardOneId); - ASSERT_EQ(LogicalTime(), shardOne->getLastCommittedOpTime()); - - auto shardTwo = shardRegistry()->getShardNoReload(shardTwoId); - LogicalTime timeTwo(Timestamp(15, 1)); - shardTwo->updateLastCommittedOpTime(timeTwo); - ASSERT_EQ(timeTwo, shardTwo->getLastCommittedOpTime()); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {shardOneId, shardTwoId}, kNss, kEmptyQuery, kEmptyCollation); - // TODO SERVER-36312: - // ASSERT_EQ(getSelectedTime(), timeTwo); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -TEST_F(AtClusterTimeTest, ComputeInvalidInvalid) { - auto shardOne = shardRegistry()->getShardNoReload(shardOneId); - ASSERT_EQ(LogicalTime(), shardOne->getLastCommittedOpTime()); - - auto shardTwo = shardRegistry()->getShardNoReload(shardTwoId); - ASSERT_EQ(LogicalTime(), shardTwo->getLastCommittedOpTime()); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {shardOneId, shardTwoId}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -TEST_F(AtClusterTimeTest, ComputeForUnsharded) { - auto shardOne = shardRegistry()->getShardNoReload(shardOneId); - - LogicalTime timeOne(Timestamp(10, 2)); - shardOne->updateLastCommittedOpTime(timeOne); - ASSERT_EQ(timeOne, shardOne->getLastCommittedOpTime()); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), shardOneId); - // TODO SERVER-36312: - // ASSERT_EQ(getSelectedTime(), timeOne); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -TEST_F(AtClusterTimeTest, ComputeForUnshardedNoCachedOpTime) { - auto shardOne = shardRegistry()->getShardNoReload(shardOneId); - ASSERT_EQ(LogicalTime(), shardOne->getLastCommittedOpTime()); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), shardOneId); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -// TODO SERVER-36312: Verify computing atClusterTime for a single shard that does not exist returns -// an error. - -class AtClusterTimeTargetingTest : public CatalogCacheTestFixture { -protected: - void setUp() { - CatalogCacheTestFixture::setUp(); - CatalogCacheTestFixture::setupNShards(2); - - // Set up a logical clock with an initial time. - auto logicalClock = stdx::make_unique<LogicalClock>(getServiceContext()); - logicalClock->setClusterTimeFromTrustedSource(kInMemoryLogicalTime); - LogicalClock::set(getServiceContext(), std::move(logicalClock)); - - operationContext()->setLogicalSessionId(makeLogicalSessionIdForTest()); - operationContext()->setTxnNumber(kTxnNumber); - repl::ReadConcernArgs::get(operationContext()) = - repl::ReadConcernArgs(repl::ReadConcernLevel::kSnapshotReadConcern); - - _scopedSession.emplace(operationContext()); - txnRouter()->beginOrContinueTxn( - operationContext(), kTxnNumber, TransactionRouter::TransactionActions::kStart); - } - - TransactionRouter* txnRouter() const { - return TransactionRouter::get(operationContext()); - } - - LogicalTime getSelectedTime() { - return txnRouter()->getAtClusterTime()->getTime(); - } - -private: - boost::optional<RouterOperationContextSession> _scopedSession; -}; - -// Verifies that the latest in-memory logical time is returned when lastCommittedOpTime on one -// targeted shard is not initialized. -TEST_F(AtClusterTimeTargetingTest, ReturnsLatestInMemoryTime) { - auto routingInfo = loadRoutingTableWithTwoChunksAndTwoShards(kNss); - auto query = BSON("find" << kNss.coll()); - auto collation = BSONObj(); - auto shards = getTargetedShardsForQuery(operationContext(), routingInfo, query, collation); - - LogicalTime time(Timestamp(2, 1)); - shardRegistry()->getShardNoReload(ShardId("0"))->updateLastCommittedOpTime(time); - - ASSERT_LT(time, kInMemoryLogicalTime); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, shards, kNss, query, collation); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -// Verifies that the greatest logical time is returned when all shard's lastCommittedOpTime values -// are initialized. -TEST_F(AtClusterTimeTargetingTest, ReturnsLatestTimeFromShard) { - auto routingInfo = loadRoutingTableWithTwoChunksAndTwoShards(kNss); - auto query = BSON("find" << kNss.coll()); - auto collation = BSONObj(); - auto shards = getTargetedShardsForQuery(operationContext(), routingInfo, query, collation); - - LogicalTime time1(Timestamp(2, 1)); - shardRegistry()->getShardNoReload(ShardId("0"))->updateLastCommittedOpTime(time1); - - LogicalTime time2(Timestamp(4, 1)); - shardRegistry()->getShardNoReload(ShardId("1"))->updateLastCommittedOpTime(time2); - - ASSERT_LT(time1, kInMemoryLogicalTime); - ASSERT_GT(time2, kInMemoryLogicalTime); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, shards, kNss, query, collation); - // TODO SERVER-36312: - // ASSERT_EQ(getSelectedTime(), time2); - ASSERT_EQ(getSelectedTime(), kInMemoryLogicalTime); -} - -// Verifies that if atClusterTime is specified in the request, atClusterTime is always greater than -// or equal to it. -TEST_F(AtClusterTimeTargetingTest, AfterClusterTime) { - const auto afterClusterTime = LogicalTime(Timestamp(50, 2)); - repl::ReadConcernArgs::get(operationContext()) = - repl::ReadConcernArgs(afterClusterTime, repl::ReadConcernLevel::kSnapshotReadConcern); - - // This cannot be true in a real cluster, but is done to verify that the chosen atClusterTime - // cannot be less than afterClusterTime. - ASSERT_GT(afterClusterTime, kInMemoryLogicalTime); - - const auto s0 = ShardId("0"); - const auto s1 = ShardId("1"); - - // Neither shard has a last committed optime. - - // Target one shard. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), s0); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - // Target all shards. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0, s1}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - // One shard has a last committed optime. - - LogicalTime time1(Timestamp(1, 1)); - shardRegistry()->getShardNoReload(s0)->updateLastCommittedOpTime(time1); - ASSERT_LT(time1, afterClusterTime); - - // Target one shard. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), s0); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - // Target all shards. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0, s1}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - // Both shards have a last committed optime. - - LogicalTime time2(Timestamp(2, 1)); - shardRegistry()->getShardNoReload(s1)->updateLastCommittedOpTime(time2); - ASSERT_LT(time2, afterClusterTime); - - // Target one shard. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); - - // Target all shards. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0, s1}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_GTE(getSelectedTime(), afterClusterTime); -} - -// Verify that when afterClusterTime is given, the smallest computed atClusterTime is equal to -// afterClusterTime. -TEST_F(AtClusterTimeTargetingTest, AfterClusterTimeLowerBound) { - auto afterClusterTime = LogicalTime(kInMemoryLogicalTime); - repl::ReadConcernArgs::get(operationContext()) = - repl::ReadConcernArgs(afterClusterTime, repl::ReadConcernLevel::kSnapshotReadConcern); - - ASSERT_EQ(afterClusterTime, kInMemoryLogicalTime); - - const auto s0 = ShardId("0"); - - // Target one shard without a last committed optime. The computed value should equal - // afterClusterTime. - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_EQ(getSelectedTime(), afterClusterTime); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), s0); - ASSERT_EQ(getSelectedTime(), afterClusterTime); - - // Target one shard with a last committed optime less than afterClusterTime. The computed value - // should still equal afterClusterTime. - LogicalTime time1(Timestamp(1, 1)); - shardRegistry()->getShardNoReload(s0)->updateLastCommittedOpTime(time1); - ASSERT_LT(time1, afterClusterTime); - - txnRouter()->computeAndSetAtClusterTime( - operationContext(), true, {s0}, kNss, kEmptyQuery, kEmptyCollation); - ASSERT_EQ(getSelectedTime(), afterClusterTime); - - txnRouter()->computeAndSetAtClusterTimeForUnsharded(operationContext(), s0); - ASSERT_EQ(getSelectedTime(), afterClusterTime); -} - -} // namespace -} // namespace mongo |