diff options
author | David Storch <david.storch@10gen.com> | 2015-12-07 14:38:23 -0500 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2015-12-10 13:45:48 -0500 |
commit | 5c7573d23aff8529e1afdb1f6390f5664606b0ef (patch) | |
tree | 9b5aecba4214ea435cdb71ed8c53b95415ea9f45 /src | |
parent | 71f40809eee599eef7719dd2664081a4165b5a34 (diff) | |
download | mongo-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/SConscript | 13 | ||||
-rw-r--r-- | src/mongo/s/query/cluster_cursor_manager_test.cpp | 39 | ||||
-rw-r--r-- | src/mongo/s/query/store_possible_cursor_test.cpp | 104 |
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 |