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 #pragma once 32 33 #include "mongo/db/logical_session_id.h" 34 #include "mongo/db/sessions_collection.h" 35 #include "mongo/stdx/functional.h" 36 #include "mongo/stdx/mutex.h" 37 #include "mongo/stdx/unordered_map.h" 38 39 namespace mongo { 40 41 /** 42 * To allow us to move a MockSessionCollection into the session cache while 43 * maintaining a hold on it from within our unit tests, the MockSessionCollection 44 * will have an internal pointer to a MockSessionsCollectionImpl object that the 45 * test creates and controls. 46 * 47 * This class can operate in two modes: 48 * 49 * - if no custom hooks are set, then the test caller may add() and remove() items 50 * from the _sessions map, and this class will simply perform the required 51 * operations against that set. 52 * 53 * - if custom hooks are set, then the hooks will be run instead of the provided 54 * defaults, and the internal _sessions map will NOT be updated. 55 */ 56 class MockSessionsCollectionImpl { 57 public: 58 using SessionMap = 59 stdx::unordered_map<LogicalSessionId, LogicalSessionRecord, LogicalSessionIdHash>; 60 61 MockSessionsCollectionImpl(); 62 63 using RefreshHook = stdx::function<Status(const LogicalSessionRecordSet&)>; 64 using RemoveHook = stdx::function<Status(const LogicalSessionIdSet&)>; 65 66 // Set custom hooks to override default behavior 67 void setRefreshHook(RefreshHook hook); 68 void setRemoveHook(RemoveHook hook); 69 70 // Reset all hooks to their defaults 71 void clearHooks(); 72 73 // Forwarding methods from the MockSessionsCollection 74 Status refreshSessions(const LogicalSessionRecordSet& sessions); 75 Status removeRecords(const LogicalSessionIdSet& sessions); 76 77 // Test-side methods that operate on the _sessions map 78 void add(LogicalSessionRecord record); 79 void remove(LogicalSessionId lsid); 80 bool has(LogicalSessionId lsid); 81 void clearSessions(); 82 const SessionMap& sessions() const; 83 84 StatusWith<LogicalSessionIdSet> findRemovedSessions(OperationContext* opCtx, 85 const LogicalSessionIdSet& sessions); 86 87 private: 88 // Default implementations, may be overridden with custom hooks. 89 Status _refreshSessions(const LogicalSessionRecordSet& sessions); 90 Status _removeRecords(const LogicalSessionIdSet& sessions); 91 92 stdx::mutex _mutex; 93 SessionMap _sessions; 94 95 RefreshHook _refresh; 96 RemoveHook _remove; 97 }; 98 99 /** 100 * To allow us to move this into the session cache while maintaining a hold 101 * on it from the test side, the MockSessionCollection will have an internal pointer 102 * to an impl that we maintain access to. 103 */ 104 class MockSessionsCollection : public SessionsCollection { 105 public: MockSessionsCollection(std::shared_ptr<MockSessionsCollectionImpl> impl)106 explicit MockSessionsCollection(std::shared_ptr<MockSessionsCollectionImpl> impl) 107 : _impl(std::move(impl)) {} 108 setupSessionsCollection(OperationContext * opCtx)109 Status setupSessionsCollection(OperationContext* opCtx) override { 110 return Status::OK(); 111 } 112 checkSessionsCollectionExists(OperationContext * opCtx)113 Status checkSessionsCollectionExists(OperationContext* opCtx) override { 114 return Status::OK(); 115 } 116 refreshSessions(OperationContext * opCtx,const LogicalSessionRecordSet & sessions)117 Status refreshSessions(OperationContext* opCtx, 118 const LogicalSessionRecordSet& sessions) override { 119 return _impl->refreshSessions(sessions); 120 } 121 removeRecords(OperationContext * opCtx,const LogicalSessionIdSet & sessions)122 Status removeRecords(OperationContext* opCtx, const LogicalSessionIdSet& sessions) override { 123 return _impl->removeRecords(sessions); 124 } 125 findRemovedSessions(OperationContext * opCtx,const LogicalSessionIdSet & sessions)126 StatusWith<LogicalSessionIdSet> findRemovedSessions( 127 OperationContext* opCtx, const LogicalSessionIdSet& sessions) override { 128 return _impl->findRemovedSessions(opCtx, sessions); 129 } 130 removeTransactionRecords(OperationContext * opCtx,const LogicalSessionIdSet & sessions)131 Status removeTransactionRecords(OperationContext* opCtx, 132 const LogicalSessionIdSet& sessions) override { 133 return Status::OK(); 134 } 135 136 private: 137 std::shared_ptr<MockSessionsCollectionImpl> _impl; 138 }; 139 140 } // namespace mongo 141