2 * Copyright (C) 2018 Cisco Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // @author Changxue Deng <chadeng@cisco.com>
21 #include <gtest/gtest.h>
24 #include "../drm_base.h"
25 #include "../integer_4b_5b.h"
26 #include "../resource_pool.h"
28 using namespace mabain;
32 #define DICT_TEST_DIR "/var/tmp/mabain_test/"
33 #define ONE_MEGA 1024*1024
34 #define FAKE_KEY "test-key-129ksjkjdjdkfjdkfjkdjfkdfjkdjkkdsalslsdlkflsdfsd"
35 #define FAKE_DATA "This is a test; fake data; sdkll vlksaflksafdlfsadflkdkvkvkv ldlsldklkdsk4930 90234924894388438348348348878&^&^YYYYYY"
37 class DictTest : public ::testing::Test
48 virtual void SetUp() {
49 std::string cmd = std::string("mkdir -p ") + DICT_TEST_DIR;
50 if(system(cmd.c_str()) != 0) {
53 virtual void TearDown() {
54 ResourcePool::getInstance().RemoveAll();
55 std::string cmd = std::string("rm -rf ") + DICT_TEST_DIR + "/_*";
56 if(system(cmd.c_str()) != 0) {
60 void InitDict(bool init_header, int opts, int blk_size, int bucket_sz) {
61 dict = new Dict(std::string(DICT_TEST_DIR), init_header, 0,
62 opts, 256LL*ONE_MEGA, 256LL*ONE_MEGA,
63 32*ONE_MEGA, blk_size, 100, 150, bucket_sz, 0);
65 EXPECT_EQ(dict->Init(0), MBError::SUCCESS);
67 if(init_header) EXPECT_EQ(dict->Status(), MBError::SUCCESS);
68 else EXPECT_EQ(MBError::NOT_INITIALIZED, dict->Status());
69 header = dict->GetHeaderPtr();
70 EXPECT_EQ(header != NULL, true);
73 int AddKV(int key_len, int data_len, bool overwrite) {
75 mbd.data_len = data_len;
76 mbd.buff = (uint8_t *) FAKE_DATA;
77 int rval = dict->Add((const uint8_t *)FAKE_KEY, key_len, mbd, overwrite);
82 int GetNodeOffset(const uint8_t *node_key, int key_len, size_t &node_offset) {
84 return MBError::INVALID_ARG;
87 mbd.options = CONSTS::OPTION_FIND_AND_STORE_PARENT;
88 int rval = dict->Find(node_key, key_len, mbd);
89 if(rval == MBError::IN_DICT) {
90 node_offset = Get6BInteger(mbd.edge_ptrs.offset_ptr);
108 TEST_F(DictTest, Constructor_test)
110 int opts = CONSTS::ACCESS_MODE_WRITER | CONSTS::USE_SLIDING_WINDOW;
111 InitDict(true, opts, 32*ONE_MEGA, 100);
114 int rval = MBError::SUCCESS;
116 InitDict(false, CONSTS::ACCESS_MODE_READER, 16*ONE_MEGA, 100);
121 EXPECT_EQ(rval, MBError::INVALID_SIZE);
123 rval = MBError::SUCCESS;
125 InitDict(false, CONSTS::ACCESS_MODE_WRITER, 32*ONE_MEGA, 111);
130 EXPECT_EQ(rval, MBError::INVALID_SIZE);
132 InitDict(false, CONSTS::ACCESS_MODE_READER, 32*ONE_MEGA, 100);
135 TEST_F(DictTest, PrintHeader_test)
137 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 32*ONE_MEGA, 128);
138 dict->PrintHeader(std::cout);
141 TEST_F(DictTest, Add_test)
143 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
152 memcpy(key, "test-key-1", key_len);
154 mbd.Resize(mbd.data_len);
155 memcpy(mbd.buff, FAKE_DATA, mbd.data_len);
156 rval = dict->Add(key, key_len, mbd, false);
157 EXPECT_EQ(rval, MBError::SUCCESS);
158 rval = dict->Add(key, key_len, mbd, false);
159 EXPECT_EQ(rval, MBError::IN_DICT);
160 EXPECT_EQ(dict->Count(), 1);
161 shm_ptr = dict->GetShmPtr(header->m_data_offset-mbd.data_len, mbd.data_len);
162 EXPECT_EQ(shm_ptr!=NULL, true);
163 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, mbd.data_len), 0);
166 memcpy(key, "test-key-2", key_len);
168 mbd.Resize(mbd.data_len);
169 memcpy(mbd.buff, FAKE_DATA, mbd.data_len);
170 rval = dict->Add(key, key_len, mbd, false);
171 EXPECT_EQ(rval, MBError::SUCCESS);
172 EXPECT_EQ(dict->Count(), 2);
173 shm_ptr = dict->GetShmPtr(header->m_data_offset-mbd.data_len, mbd.data_len);
174 EXPECT_EQ(shm_ptr!=NULL, true);
175 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, mbd.data_len), 0);
178 memcpy(key, "test-key-3", key_len);
180 mbd.Resize(mbd.data_len);
181 memcpy(mbd.buff, FAKE_DATA, mbd.data_len);
182 rval = dict->Add(key, key_len, mbd, false);
183 EXPECT_EQ(rval, MBError::SUCCESS);
184 EXPECT_EQ(dict->Count(), 3);
185 shm_ptr = dict->GetShmPtr(header->m_data_offset-mbd.data_len, mbd.data_len);
186 EXPECT_EQ(shm_ptr!=NULL, true);
187 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, mbd.data_len), 0);
190 memcpy(key, "test-key-2", key_len);
192 mbd.Resize(mbd.data_len);
193 memcpy(mbd.buff, FAKE_DATA, mbd.data_len);
194 rval = dict->Add(key, key_len, mbd, true);
195 EXPECT_EQ(rval, MBError::SUCCESS);
196 EXPECT_EQ(dict->Count(), 3);
197 shm_ptr = dict->GetShmPtr(header->m_data_offset-mbd.data_len, mbd.data_len);
198 EXPECT_EQ(shm_ptr!=NULL, true);
199 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, mbd.data_len), 0);
202 TEST_F(DictTest, Find_test)
204 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
211 rval = dict->Find((const uint8_t *)FAKE_KEY, key_len, mbd);
212 EXPECT_EQ(rval, MBError::NOT_EXIST);
215 rval = AddKV(key_len, data_len, false);
216 EXPECT_EQ(rval, MBError::SUCCESS);
218 rval = dict->Find((const uint8_t*)FAKE_KEY, key_len, mbd);
219 EXPECT_EQ(rval, MBError::SUCCESS);
220 EXPECT_EQ(mbd.data_len, 32);
221 EXPECT_EQ(memcmp(mbd.buff, FAKE_DATA, mbd.data_len), 0);
224 TEST_F(DictTest, FindPrefix_test)
226 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
234 rval = AddKV(key_len, data_len, false);
235 EXPECT_EQ(rval, MBError::SUCCESS);
237 rval = dict->FindPrefix((const uint8_t *)FAKE_KEY, key_len, mbd);
238 EXPECT_EQ(MBError::SUCCESS, rval);
239 EXPECT_EQ(mbd.data_len, 32);
240 EXPECT_EQ(memcmp(mbd.buff, FAKE_DATA, mbd.data_len), 0);
243 TEST_F(DictTest, Remove_test)
245 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
251 rval = dict->Remove((const uint8_t *)FAKE_KEY, key_len);
252 EXPECT_EQ(rval, MBError::NOT_EXIST);
256 rval = AddKV(key_len, data_len, true);
257 EXPECT_EQ(rval, MBError::SUCCESS);
258 rval = dict->Remove((const uint8_t *)FAKE_KEY, key_len);
259 EXPECT_EQ(rval, MBError::SUCCESS);
260 EXPECT_EQ(dict->Count(), 0);
263 TEST_F(DictTest, RemoveAll_test)
265 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
268 rval = AddKV(10, 50, true);
269 EXPECT_EQ(rval, MBError::SUCCESS);
270 rval = AddKV(11, 52, true);
271 EXPECT_EQ(rval, MBError::SUCCESS);
272 rval = AddKV(12, 54, true);
273 EXPECT_EQ(rval, MBError::SUCCESS);
274 rval = AddKV(19, 64, true);
275 EXPECT_EQ(rval, MBError::SUCCESS);
276 dict->PrintStats(std::cout);
278 rval = dict->RemoveAll();
279 EXPECT_EQ(rval, MBError::SUCCESS);
280 EXPECT_EQ(dict->Count(), 0);
281 EXPECT_EQ(header->m_data_offset, dict->GetStartDataOffset());
282 EXPECT_EQ(header->pending_data_buff_size, 0);
283 EXPECT_EQ(header->eviction_bucket_index, 0);
284 EXPECT_EQ(header->num_update, 0);
287 TEST_F(DictTest, ReserveData_test)
289 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
295 dict->ReserveData((const uint8_t *)FAKE_DATA, data_size, offset);
296 offset += DATA_HDR_BYTE;
297 shm_ptr = dict->GetShmPtr(offset, data_size);
298 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, data_size), 0);
301 dict->ReserveData((const uint8_t *)FAKE_DATA, data_size, offset);
302 offset += DATA_HDR_BYTE;
303 shm_ptr = dict->GetShmPtr(offset, data_size);
304 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, data_size), 0);
307 TEST_F(DictTest, WriteData_test)
309 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
316 header->m_data_offset = offset + data_size;
317 dict->Reserve(offset, data_size, shm_ptr);
318 dict->WriteData((const uint8_t *)FAKE_DATA, data_size, offset);
319 shm_ptr = dict->GetShmPtr(offset, data_size);
320 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, data_size), 0);
324 header->m_data_offset = offset + data_size;
325 dict->WriteData((const uint8_t *)FAKE_DATA, data_size, offset);
326 shm_ptr = dict->GetShmPtr(offset, data_size);
327 EXPECT_EQ(memcmp(shm_ptr, FAKE_DATA, data_size), 0);
330 TEST_F(DictTest, PrintStats_test)
332 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
333 dict->PrintStats(std::cout);
336 TEST_F(DictTest, ReadRootNode_test)
338 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
350 rval = dict->ReadRootNode(buff, edge_ptrs, match, mbd);
351 EXPECT_EQ(rval, MBError::SUCCESS);
352 EXPECT_EQ(edge_ptrs.offset, 264u);
353 EXPECT_EQ((int)buff[0], 0);
354 EXPECT_EQ((int)buff[1], 255);
357 TEST_F(DictTest, ReadNode_test)
359 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
372 rval = GetNodeOffset((const uint8_t *)FAKE_KEY, 8, offset);
373 EXPECT_EQ(rval, MBError::IN_DICT);
374 rval = dict->ReadNode(offset, buff, edge_ptrs, match, mbd, true);
375 EXPECT_EQ(rval, MBError::SUCCESS);
376 EXPECT_EQ((int)buff[0], 1);
377 EXPECT_EQ((int)buff[1], 0);
381 TEST_F(DictTest, ReadNextEdge_test)
383 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
392 std::string match_str;
397 memset(&edge_ptrs, 0, sizeof(edge_ptrs));
398 memset(buff, 0, 256);
400 edge_ptrs.curr_nt = 15;
402 rval = dict->ReadNextEdge(buff, edge_ptrs, match, mbd, match_str, offset, true);
403 EXPECT_EQ(rval, MBError::OUT_OF_BOUND);
405 rval = dict->ReadRootNode(buff, edge_ptrs, match, mbd);
406 EXPECT_EQ(rval, MBError::SUCCESS);
407 rval = dict->ReadNextEdge(buff, edge_ptrs, match, mbd, match_str, offset, true);
408 EXPECT_EQ(rval, MBError::SUCCESS);
410 EXPECT_EQ(offset, 0u);
413 TEST_F(DictTest, ReadNodeHeader_test)
415 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 28);
422 size_t offset=0, data_offset, data_link_offset;
425 rval = GetNodeOffset((const uint8_t *)FAKE_KEY, 8, offset);
426 EXPECT_EQ(rval, MBError::IN_DICT);
427 dict->ReadNodeHeader(offset, node_size, match, data_offset, data_link_offset);
428 EXPECT_EQ(node_size, 22);
430 EXPECT_EQ(data_offset, 143u);
431 EXPECT_EQ(data_link_offset, 3647u);
435 TEST_F(DictTest, CloseDBFiles_test)
437 InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 28);
442 EXPECT_EQ(dict->Status(), MBError::DB_CLOSED);
443 EXPECT_TRUE(dict->GetHeaderPtr() == NULL);
444 EXPECT_TRUE(dict->GetMM()->GetHeaderPtr() == NULL);
447 EXPECT_EQ(rval, MBError::SUCCESS);
448 EXPECT_EQ(dict->Status(), MBError::SUCCESS);
449 EXPECT_TRUE(dict->GetHeaderPtr() != NULL);
450 EXPECT_TRUE(dict->GetMM()->GetHeaderPtr() != NULL);
451 EXPECT_TRUE(dict->GetMM()->GetHeaderPtr() == dict->GetHeaderPtr());
454 rval = dict->Find((const uint8_t*)FAKE_KEY, 10, mbd);
455 EXPECT_EQ(rval, MBError::SUCCESS);
456 rval = dict->Find((const uint8_t*)FAKE_KEY, 11, mbd);
457 EXPECT_EQ(rval, MBError::SUCCESS);
458 rval = dict->Find((const uint8_t*)FAKE_KEY, 12, mbd);
459 EXPECT_EQ(rval, MBError::SUCCESS);
460 rval = dict->Find((const uint8_t*)FAKE_KEY, 8, mbd);
461 EXPECT_EQ(rval, MBError::SUCCESS);