50e698ad4225b086d99207595172168ed2fe23c8
[ep-engine.git] / tests / module_tests / evp_store_test.cc
1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17
18 /*
19  * Unit tests for the EventuallyPersistentStore class.
20  *
21  * Note that these test do *not* have the normal Tasks running (BGFetcher,
22  * flusher etc) as we do not initialise EPEngine. This means that such tasks
23  * need to be manually run. This can be very helpful as it essentially gives us
24  * synchronous control of EPStore.
25  */
26
27 #include "evp_store_test.h"
28
29 #include "bgfetcher.h"
30 #include "checkpoint.h"
31 #include "checkpoint_remover.h"
32 #include "connmap.h"
33 #include "ep_engine.h"
34 #include "flusher.h"
35 #include "../mock/mock_dcp_producer.h"
36
37 #include "programs/engine_testapp/mock_server.h"
38 #include <platform/dirutils.h>
39
40 SynchronousEPEngine::SynchronousEPEngine(const std::string& extra_config)
41     : EventuallyPersistentEngine(get_mock_server_api) {
42     maxFailoverEntries = 1;
43
44     EventuallyPersistentEngine::loggerApi = get_mock_server_api()->log;
45
46     // Merge any extra config into the main configuration.
47     if (extra_config.size() > 0) {
48         if (!configuration.parseConfiguration(extra_config.c_str(),
49                                               serverApi)) {
50             throw std::invalid_argument("Unable to parse config string: " +
51                                         extra_config);
52         }
53     }
54
55     // workload is needed by EPStore's constructor (to construct the
56     // VBucketMap).
57     workload = new WorkLoadPolicy(/*workers*/1, /*shards*/1);
58
59     // dcpConnMap_ is needed by EPStore's constructor.
60     dcpConnMap_ = new DcpConnMap(*this);
61
62     // tapConnMap is needed by queueDirty.
63     tapConnMap = new TapConnMap(*this);
64
65     // checkpointConfig is needed by CheckpointManager (via EPStore).
66     checkpointConfig = new CheckpointConfig(*this);
67 }
68
69 void SynchronousEPEngine::setEPStore(EventuallyPersistentStore* store) {
70     cb_assert(epstore == NULL);
71     epstore = store;
72 }
73
74 MockEPStore::MockEPStore(EventuallyPersistentEngine &theEngine)
75     : EventuallyPersistentStore(theEngine) {
76     // Perform a limited set of setup (normally done by EPStore::initialize) -
77     // enough such that objects which are assumed to exist are present.
78
79     // Create the closed checkpoint removed task. Note we do _not_ schedule
80     // it, unlike EPStore::initialize
81     chkTask = new ClosedUnrefCheckpointRemoverTask
82             (&engine, stats, theEngine.getConfiguration().getChkRemoverStime());
83 }
84
85 VBucketMap& MockEPStore::getVbMap() {
86     return vbMap;
87 }
88
89 /* Mock Task class. Doesn't actually run() or snooze() - they both do nothing.
90  */
91 class MockGlobalTask : public GlobalTask {
92 public:
93     MockGlobalTask(EventuallyPersistentEngine* e, const Priority &p)
94         : GlobalTask(e, p) {}
95
96     bool run() { return false; }
97     std::string getDescription() { return "MockGlobalTask"; }
98
99     void snooze(const double secs) {}
100 };
101
102 void EventuallyPersistentStoreTest::SetUp() {
103     // Paranoia - kill any existing files in case they are left over
104     // from a previous run.
105     CouchbaseDirectoryUtilities::rmrf(test_dbname);
106
107     // Add dbname to config string.
108     std::string config = config_string;
109     if (config.size() > 0) {
110         config += ";";
111     }
112     config += "dbname=" + std::string(test_dbname);
113
114     vbid = 0;
115
116     engine = new SynchronousEPEngine(config);
117     ObjectRegistry::onSwitchThread(engine);
118
119     store = new MockEPStore(*engine);
120     engine->setEPStore(store);
121
122     // Ensure that EPEngine is hold about necessary server callbacks
123     // (client disconnect, bucket delete).
124     engine->public_initializeEngineCallbacks();
125
126     // Need to initialize ep_real_time and friends.
127     initialize_time_functions(get_mock_server_api()->core);
128
129     cookie = create_mock_cookie();
130 }
131
132 void EventuallyPersistentStoreTest::TearDown() {
133     destroy_mock_cookie(cookie);
134     destroy_mock_event_callbacks();
135     engine->getDcpConnMap().manageConnections();
136
137     // Need to have the current engine valid before deleting (this is what
138     // EvpDestroy does normally; however we have a smart ptr to the engine
139     // so must delete via that).
140     ObjectRegistry::onSwitchThread(engine);
141     delete engine;
142
143     // Shutdown the ExecutorPool singleton (initialized when we create
144     // an EventuallyPersistentStore object). Must happen after engine
145     // has been destroyed (to allow the tasks the engine has
146     // registered a chance to be unregistered).
147     ExecutorPool::shutdown();
148 }
149
150 void EventuallyPersistentStoreTest::store_item(uint16_t vbid,
151                                                const std::string& key,
152                                                const std::string& value) {
153     Item item(key.c_str(), key.size(), /*flags*/0, /*exp*/0, value.c_str(),
154               value.size());
155     item.setVBucketId(vbid);
156     EXPECT_EQ(ENGINE_SUCCESS, store->set(item, NULL));
157 }
158
159
160 //
161 // EPStoreEvictionTest disabled in 3.0.x backport - there's an unknown
162 // bug where onSwitchThread() ends up NULL, meaning that we eventually hit
163 // an assert and crash.
164 //
165
166
167 const char EventuallyPersistentStoreTest::test_dbname[] = "ep_engine_ep_unit_tests_db";