1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/platform/basic.h"
32
33 #include "mongo/db/catalog/capped_utils.h"
34 #include "mongo/db/catalog/collection_catalog_entry.h"
35 #include "mongo/db/client.h"
36 #include "mongo/db/db_raii.h"
37 #include "mongo/db/repl/replication_coordinator.h"
38 #include "mongo/db/repl/replication_coordinator_mock.h"
39 #include "mongo/db/repl/storage_interface_impl.h"
40 #include "mongo/db/service_context_d_test_fixture.h"
41 #include "mongo/stdx/memory.h"
42 #include "mongo/unittest/unittest.h"
43
44 namespace {
45
46 using namespace mongo;
47
48 class CappedUtilsTest : public ServiceContextMongoDTest {
49 private:
50 void setUp() override;
51 void tearDown() override;
52
53 protected:
54 // Use StorageInterface to access storage features below catalog interface.
55 std::unique_ptr<repl::StorageInterface> _storage;
56 };
57
setUp()58 void CappedUtilsTest::setUp() {
59 // Set up mongod.
60 ServiceContextMongoDTest::setUp();
61
62 auto service = getServiceContext();
63
64 // Set up ReplicationCoordinator and ensure that we are primary.
65 auto replCoord = stdx::make_unique<repl::ReplicationCoordinatorMock>(service);
66 ASSERT_OK(replCoord->setFollowerMode(repl::MemberState::RS_PRIMARY));
67 repl::ReplicationCoordinator::set(service, std::move(replCoord));
68
69 _storage = stdx::make_unique<repl::StorageInterfaceImpl>();
70 }
71
tearDown()72 void CappedUtilsTest::tearDown() {
73 _storage = {};
74
75 // Tear down mongod.
76 ServiceContextMongoDTest::tearDown();
77 }
78
79 /**
80 * Creates an OperationContext.
81 */
makeOpCtx()82 ServiceContext::UniqueOperationContext makeOpCtx() {
83 return cc().makeOperationContext();
84 }
85
86 /**
87 * Returns true if collection exists.
88 */
collectionExists(OperationContext * opCtx,const NamespaceString & nss)89 bool collectionExists(OperationContext* opCtx, const NamespaceString& nss) {
90 return AutoGetCollectionForRead(opCtx, nss).getCollection() != nullptr;
91 }
92
93 /**
94 * Returns collection options.
95 */
getCollectionOptions(OperationContext * opCtx,const NamespaceString & nss)96 CollectionOptions getCollectionOptions(OperationContext* opCtx, const NamespaceString& nss) {
97 AutoGetCollectionForRead autoColl(opCtx, nss);
98 auto collection = autoColl.getCollection();
99 ASSERT_TRUE(collection) << "Unable to get collections options for " << nss
100 << " because collection does not exist.";
101 auto catalogEntry = collection->getCatalogEntry();
102 return catalogEntry->getCollectionOptions(opCtx);
103 }
104
105 // Size of capped collection to be passed to convertToCapped() which accepts a double.
106 // According to documentation, the size (in bytes) of capped collection must be a minimum of 4096
107 // and a multiple of 256.
108 const double cappedCollectionSize = 8192.0;
109
TEST_F(CappedUtilsTest,ConvertToCappedReturnsNamespaceNotFoundIfCollectionIsMissing)110 TEST_F(CappedUtilsTest, ConvertToCappedReturnsNamespaceNotFoundIfCollectionIsMissing) {
111 NamespaceString nss("test.t");
112 auto opCtx = makeOpCtx();
113 ASSERT_FALSE(collectionExists(opCtx.get(), nss));
114 ASSERT_EQUALS(ErrorCodes::NamespaceNotFound, convertToCapped(opCtx.get(), nss, 1000.0));
115 }
116
TEST_F(CappedUtilsTest,ConvertToCappedUpdatesCollectionOptionsOnSuccess)117 TEST_F(CappedUtilsTest, ConvertToCappedUpdatesCollectionOptionsOnSuccess) {
118 NamespaceString nss("test.t");
119
120 auto opCtx = makeOpCtx();
121 ASSERT_OK(_storage->createCollection(opCtx.get(), nss, {}));
122 auto options = getCollectionOptions(opCtx.get(), nss);
123 ASSERT_FALSE(options.capped);
124
125 ASSERT_OK(convertToCapped(opCtx.get(), nss, cappedCollectionSize));
126 options = getCollectionOptions(opCtx.get(), nss);
127 ASSERT_TRUE(options.capped);
128 ASSERT_APPROX_EQUAL(cappedCollectionSize, options.cappedSize, 0.001)
129 << "unexpected capped collection size: " << options.toBSON();
130 }
131
TEST_F(CappedUtilsTest,ConvertToCappedReturnsNamespaceNotFoundIfCollectionIsDropPending)132 TEST_F(CappedUtilsTest, ConvertToCappedReturnsNamespaceNotFoundIfCollectionIsDropPending) {
133 NamespaceString nss("test.t");
134 repl::OpTime dropOpTime(Timestamp(Seconds(100), 0), 1LL);
135 auto dropPendingNss = nss.makeDropPendingNamespace(dropOpTime);
136
137 auto opCtx = makeOpCtx();
138 ASSERT_OK(_storage->createCollection(opCtx.get(), dropPendingNss, {}));
139 auto options = getCollectionOptions(opCtx.get(), dropPendingNss);
140 ASSERT_FALSE(options.capped);
141
142 ASSERT_EQUALS(ErrorCodes::NamespaceNotFound,
143 convertToCapped(opCtx.get(), dropPendingNss, cappedCollectionSize));
144 options = getCollectionOptions(opCtx.get(), dropPendingNss);
145 ASSERT_FALSE(options.capped);
146 }
147
148 } // namespace
149