inital commit
[c11concurrency-benchmarks.git] / mabain / src / unittest / dict_test.cpp
1 /**
2  * Copyright (C) 2018 Cisco Inc.
3  *
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.
7  *
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.
12  *
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/>.
15  */
16
17 // @author Changxue Deng <chadeng@cisco.com>
18
19 #include <string>
20
21 #include <gtest/gtest.h>
22
23 #include "../dict.h"
24 #include "../drm_base.h"
25 #include "../integer_4b_5b.h"
26 #include "../resource_pool.h"
27
28 using namespace mabain;
29
30 namespace {
31
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"
36
37 class DictTest : public ::testing::Test
38 {
39 public:
40     DictTest() {
41         dict = NULL;
42         header = NULL;
43     }
44     virtual ~DictTest() {
45         DestroyDict();
46     }
47
48     virtual void SetUp() {
49         std::string cmd = std::string("mkdir -p ") + DICT_TEST_DIR;
50         if(system(cmd.c_str()) != 0) {
51         }
52     }
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) {
57         }
58     }
59
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);
64         if(init_header) {
65             EXPECT_EQ(dict->Init(0), MBError::SUCCESS);
66         }
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);
71     }
72
73     int AddKV(int key_len, int data_len, bool overwrite) {
74         MBData mbd;
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);
78         mbd.buff = NULL;
79         return rval;
80     }
81
82     int GetNodeOffset(const uint8_t *node_key, int key_len, size_t &node_offset) {
83         if(dict == NULL)
84             return MBError::INVALID_ARG;
85         MBData mbd;
86         node_offset = 0;
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);
91         } 
92         return rval;
93     }
94
95     void DestroyDict() {
96         if(dict != NULL) {
97             dict->Destroy();
98             delete dict;
99             dict = NULL;
100         }
101     }
102
103 protected:
104     Dict *dict;
105     IndexHeader *header;
106 };
107
108 TEST_F(DictTest, Constructor_test)
109 {
110     int opts = CONSTS::ACCESS_MODE_WRITER | CONSTS::USE_SLIDING_WINDOW;
111     InitDict(true, opts, 32*ONE_MEGA, 100);
112     DestroyDict();
113
114     int rval = MBError::SUCCESS;
115     try {
116         InitDict(false, CONSTS::ACCESS_MODE_READER, 16*ONE_MEGA, 100);
117     } catch (int err) {
118         rval = err;
119     }
120
121     EXPECT_EQ(rval, MBError::INVALID_SIZE);
122
123     rval = MBError::SUCCESS;
124     try {
125         InitDict(false, CONSTS::ACCESS_MODE_WRITER, 32*ONE_MEGA, 111);
126     } catch (int err) {
127         rval = err;
128     }
129
130     EXPECT_EQ(rval, MBError::INVALID_SIZE);
131
132     InitDict(false, CONSTS::ACCESS_MODE_READER, 32*ONE_MEGA, 100);
133 }
134
135 TEST_F(DictTest, PrintHeader_test)
136 {
137     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 32*ONE_MEGA, 128);
138     dict->PrintHeader(std::cout);
139 }
140
141 TEST_F(DictTest, Add_test)
142 {
143     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
144
145     uint8_t key[256];
146     int key_len;
147     MBData mbd;
148     int rval;
149     uint8_t *shm_ptr;
150
151     key_len = 10;
152     memcpy(key, "test-key-1", key_len);
153     mbd.data_len = 100;
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);
164
165     key_len = 10;
166     memcpy(key, "test-key-2", key_len);
167     mbd.data_len = 101;
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);
176
177     key_len = 10;
178     memcpy(key, "test-key-3", key_len);
179     mbd.data_len = 105;
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);
188
189     key_len = 10;
190     memcpy(key, "test-key-2", key_len);
191     mbd.data_len = 108;
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);
200 }
201
202 TEST_F(DictTest, Find_test)
203 {
204     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
205     int key_len;
206     int data_len;
207     MBData mbd;
208     int rval;
209
210     key_len = 10;
211     rval = dict->Find((const uint8_t *)FAKE_KEY, key_len, mbd);
212     EXPECT_EQ(rval, MBError::NOT_EXIST);
213
214     data_len = 32;
215     rval = AddKV(key_len, data_len, false);
216     EXPECT_EQ(rval, MBError::SUCCESS);
217     dict->Flush();
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);
222 }
223
224 TEST_F(DictTest, FindPrefix_test)
225 {
226     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
227     int key_len;
228     int data_len;
229     MBData mbd;
230     int rval;
231
232     key_len = 10;
233     data_len = 32;
234     rval = AddKV(key_len, data_len, false);
235     EXPECT_EQ(rval, MBError::SUCCESS);
236     key_len = 15;
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);
241 }
242
243 TEST_F(DictTest, Remove_test)
244 {
245     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 10);
246     int key_len;
247     int data_len;
248     int rval;
249
250     key_len = 10;
251     rval = dict->Remove((const uint8_t *)FAKE_KEY, key_len);
252     EXPECT_EQ(rval, MBError::NOT_EXIST);
253
254     key_len = 13;
255     data_len = 28;
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);
261 }
262
263 TEST_F(DictTest, RemoveAll_test)
264 {
265     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
266     int rval;
267
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);
277
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);
285 }
286
287 TEST_F(DictTest, ReserveData_test)
288 {
289     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
290     int data_size;
291     size_t offset;
292     uint8_t *shm_ptr;
293     
294     data_size = 1;
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);
299
300     data_size = 19;
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);
305 }
306
307 TEST_F(DictTest, WriteData_test)
308 {
309     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
310     int data_size;
311     size_t offset;
312     uint8_t *shm_ptr;
313
314     data_size = 14;
315     offset = 111;
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);
321
322     data_size = 33;
323     offset = 1234;
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);
328 }
329
330 TEST_F(DictTest, PrintStats_test)
331 {
332     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
333     dict->PrintStats(std::cout);
334 }
335
336 TEST_F(DictTest, ReadRootNode_test)
337 {
338     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
339     AddKV(10, 15, true);
340     AddKV(12, 50, true);
341     AddKV(15, 34, true);
342     AddKV(8, 22, true);
343
344     EdgePtrs edge_ptrs;
345     uint8_t buff[256];
346     MBData mbd;
347     int match;
348     int rval;
349
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);
355 }
356
357 TEST_F(DictTest, ReadNode_test)
358 {
359     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
360     AddKV(8, 22, true);
361     AddKV(10, 15, true);
362     AddKV(12, 50, true);
363     AddKV(15, 34, true);
364
365     int rval;
366     size_t offset = 0;
367     EdgePtrs edge_ptrs;
368     uint8_t buff[256];
369     MBData mbd;
370     int match;
371
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);
378     EXPECT_EQ(match, 2);
379 }
380
381 TEST_F(DictTest, ReadNextEdge_test)
382 {
383     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 8*ONE_MEGA, 12);
384     AddKV(10, 15, true);
385     AddKV(12, 50, true);
386     AddKV(15, 34, true);
387     AddKV(8, 22, true);
388
389     EdgePtrs edge_ptrs;
390     uint8_t buff[256];
391     MBData mbd;
392     std::string match_str;
393     size_t offset;
394     int match;
395     int rval;
396
397     memset(&edge_ptrs, 0, sizeof(edge_ptrs));
398     memset(buff, 0, 256);
399
400     edge_ptrs.curr_nt = 15;
401     buff[0] = 14;
402     rval = dict->ReadNextEdge(buff, edge_ptrs, match, mbd, match_str, offset, true);
403     EXPECT_EQ(rval, MBError::OUT_OF_BOUND);
404
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);
409     EXPECT_EQ(match, 0);
410     EXPECT_EQ(offset, 0u);
411 }
412
413 TEST_F(DictTest, ReadNodeHeader_test)
414 {
415     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 28);
416     AddKV(10, 15, true);
417     AddKV(12, 50, true);
418     AddKV(15, 34, true);
419     AddKV(8, 22, true);
420
421     int rval;
422     size_t offset=0, data_offset, data_link_offset;
423     int node_size;
424     int match;
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);
429     EXPECT_EQ(match, 2);
430     EXPECT_EQ(data_offset, 143u);
431     EXPECT_EQ(data_link_offset, 3647u);
432 }
433
434 /***
435 TEST_F(DictTest, CloseDBFiles_test)
436 {
437     InitDict(true, CONSTS::ACCESS_MODE_WRITER, 4*ONE_MEGA, 28);
438     AddKV(10, 15, true);
439     AddKV(11, 50, true);
440     AddKV(12, 34, true);
441     AddKV(8, 22, true);
442     EXPECT_EQ(dict->Status(), MBError::DB_CLOSED);
443     EXPECT_TRUE(dict->GetHeaderPtr() == NULL);
444     EXPECT_TRUE(dict->GetMM()->GetHeaderPtr() == NULL);
445
446     int rval;
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());
452
453     MBData mbd;
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);
462 }***/
463
464 }