summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2015-12-07 14:38:23 -0500
committerDavid Storch <david.storch@10gen.com>2015-12-10 13:45:48 -0500
commit5c7573d23aff8529e1afdb1f6390f5664606b0ef (patch)
tree9b5aecba4214ea435cdb71ed8c53b95415ea9f45 /src
parent71f40809eee599eef7719dd2664081a4165b5a34 (diff)
downloadmongo-5c7573d23aff8529e1afdb1f6390f5664606b0ef.tar.gz
SERVER-21786 increase test coverage of the s/query directory
Fills in gaps in coverage discovered with code coverage analysis. (cherry picked from commit 09126c5f0e81d569058ffcc8d23c0c036b147b55)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/s/query/SConscript13
-rw-r--r--src/mongo/s/query/cluster_cursor_manager_test.cpp39
-rw-r--r--src/mongo/s/query/store_possible_cursor_test.cpp104
3 files changed, 156 insertions, 0 deletions
diff --git a/src/mongo/s/query/SConscript b/src/mongo/s/query/SConscript
index 3ed716d3b89..18022507aa2 100644
--- a/src/mongo/s/query/SConscript
+++ b/src/mongo/s/query/SConscript
@@ -106,6 +106,19 @@ env.Library(
],
)
+env.CppUnitTest(
+ target="store_possible_cursor_test",
+ source=[
+ "store_possible_cursor_test.cpp",
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/db/auth/authorization_manager_mock_init',
+ "$BUILD_DIR/mongo/s/mongoscore",
+ "$BUILD_DIR/mongo/util/clock_source_mock",
+ "store_possible_cursor",
+ ],
+)
+
env.Library(
target="cluster_cursor_manager",
source=[
diff --git a/src/mongo/s/query/cluster_cursor_manager_test.cpp b/src/mongo/s/query/cluster_cursor_manager_test.cpp
index 8f5f4b54355..7fb84a5eafd 100644
--- a/src/mongo/s/query/cluster_cursor_manager_test.cpp
+++ b/src/mongo/s/query/cluster_cursor_manager_test.cpp
@@ -774,6 +774,45 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorDestructorKill) {
ASSERT(isMockCursorKilled(0));
}
+// Test that PinnedCursor::remotesExhausted() correctly forwards to the underlying mock cursor.
+TEST_F(ClusterCursorManagerTest, RemotesExhausted) {
+ auto mockCursor = allocateMockCursor();
+ mockCursor->markRemotesNotExhausted();
+ ASSERT_FALSE(mockCursor->remotesExhausted());
+
+ auto cursorId =
+ getManager()->registerCursor(std::move(mockCursor),
+ nss,
+ ClusterCursorManager::CursorType::NamespaceNotSharded,
+ ClusterCursorManager::CursorLifetime::Mortal);
+ auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId);
+ ASSERT_OK(pinnedCursor.getStatus());
+ ASSERT_FALSE(pinnedCursor.getValue().remotesExhausted());
+}
+
+// Test that killed cursors which are still pinned are not reaped.
+TEST_F(ClusterCursorManagerTest, DoNotReapKilledPinnedCursors) {
+ auto cursorId =
+ getManager()->registerCursor(allocateMockCursor(),
+ nss,
+ ClusterCursorManager::CursorType::NamespaceNotSharded,
+ ClusterCursorManager::CursorLifetime::Mortal);
+ auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId);
+ ASSERT_OK(pinnedCursor.getStatus());
+ ASSERT_OK(getManager()->killCursor(nss, cursorId));
+ ASSERT(!isMockCursorKilled(0));
+
+ // Pinned cursor should remain alive after reaping.
+ getManager()->reapZombieCursors();
+ ASSERT(!isMockCursorKilled(0));
+
+ // The cursor can be reaped once it is returned to the manager.
+ pinnedCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted);
+ ASSERT(!isMockCursorKilled(0));
+ getManager()->reapZombieCursors();
+ ASSERT(isMockCursorKilled(0));
+}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/s/query/store_possible_cursor_test.cpp b/src/mongo/s/query/store_possible_cursor_test.cpp
new file mode 100644
index 00000000000..23a56a3e5f8
--- /dev/null
+++ b/src/mongo/s/query/store_possible_cursor_test.cpp
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2015 MongoDB 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 "mongo/s/query/store_possible_cursor.h"
+
+#include "mongo/bson/json.h"
+#include "mongo/db/query/cursor_response.h"
+#include "mongo/s/query/cluster_cursor_manager.h"
+#include "mongo/unittest/unittest.h"
+#include "mongo/util/clock_source_mock.h"
+#include "mongo/util/net/hostandport.h"
+
+namespace mongo {
+namespace {
+
+const NamespaceString nss("test.collection");
+const HostAndPort hostAndPort("testhost", 27017);
+
+class StorePossibleCursorTest : public unittest::Test {
+protected:
+ StorePossibleCursorTest() : _manager(&_clockSourceMock) {}
+
+ ClusterCursorManager* getManager() {
+ return &_manager;
+ }
+
+private:
+ ClockSourceMock _clockSourceMock;
+
+ ClusterCursorManager _manager;
+};
+
+// Test that storePossibleCursor() returns a valid cursor response document.
+TEST_F(StorePossibleCursorTest, ReturnsValidCursorResponse) {
+ std::vector<BSONObj> batch = {fromjson("{_id: 1}"), fromjson("{_id: 2}")};
+ CursorResponse cursorResponse(nss, CursorId(0), batch);
+ auto outgoingCursorResponse =
+ storePossibleCursor(hostAndPort,
+ cursorResponse.toBSON(CursorResponse::ResponseType::InitialResponse),
+ nullptr, // TaskExecutor
+ getManager());
+ ASSERT_OK(outgoingCursorResponse.getStatus());
+
+ auto parsedOutgoingResponse = CursorResponse::parseFromBSON(outgoingCursorResponse.getValue());
+ ASSERT_OK(parsedOutgoingResponse.getStatus());
+ ASSERT_EQ(nss.toString(), parsedOutgoingResponse.getValue().getNSS().toString());
+ ASSERT_EQ(0U, parsedOutgoingResponse.getValue().getCursorId());
+ ASSERT_EQ(2U, parsedOutgoingResponse.getValue().getBatch().size());
+ ASSERT_EQ(fromjson("{_id: 1}"), parsedOutgoingResponse.getValue().getBatch()[0]);
+ ASSERT_EQ(fromjson("{_id: 2}"), parsedOutgoingResponse.getValue().getBatch()[1]);
+}
+
+// Test that storePossibleCursor() propagates an error if it cannot parse the cursor response.
+TEST_F(StorePossibleCursorTest, FailsGracefullyOnBadCursorResponseDocument) {
+ auto outgoingCursorResponse = storePossibleCursor(hostAndPort,
+ fromjson("{ok: 1, cursor: {}}"),
+ nullptr, // TaskExecutor
+ getManager());
+ ASSERT_NOT_OK(outgoingCursorResponse.getStatus());
+ ASSERT_EQ(ErrorCodes::TypeMismatch, outgoingCursorResponse.getStatus());
+}
+
+// Test that storePossibleCursor() passes up the command response if it is not recognized as a
+// cursor response.
+TEST_F(StorePossibleCursorTest, PassesUpCommandResultIfItDoesNotDescribeACursor) {
+ BSONObj notACursorObj = BSON("not"
+ << "cursor");
+ auto outgoingCursorResponse = storePossibleCursor(hostAndPort,
+ notACursorObj,
+ nullptr, // TaskExecutor
+ getManager());
+ ASSERT_OK(outgoingCursorResponse.getStatus());
+ ASSERT_EQ(notACursorObj, outgoingCursorResponse.getValue());
+}
+
+} // namespace
+} // namespace mongo