]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2012 Inktank, Inc. | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | */ | |
13 | #include "include/memory.h" | |
14 | #include <map> | |
15 | #include <set> | |
16 | #include <deque> | |
17 | #include <boost/scoped_ptr.hpp> | |
18 | ||
19 | #include "test/ObjectMap/KeyValueDBMemory.h" | |
20 | #include "kv/KeyValueDB.h" | |
21 | #include <sys/types.h> | |
22 | #include "global/global_init.h" | |
23 | #include "common/ceph_argparse.h" | |
24 | #include "gtest/gtest.h" | |
25 | ||
26 | using namespace std; | |
27 | ||
28 | string store_path; | |
29 | ||
30 | class IteratorTest : public ::testing::Test | |
31 | { | |
32 | public: | |
33 | boost::scoped_ptr<KeyValueDB> db; | |
34 | boost::scoped_ptr<KeyValueDBMemory> mock; | |
35 | ||
36 | void SetUp() override { | |
37 | assert(!store_path.empty()); | |
38 | ||
39 | KeyValueDB *db_ptr = KeyValueDB::create(g_ceph_context, "leveldb", store_path); | |
40 | assert(!db_ptr->create_and_open(std::cerr)); | |
41 | db.reset(db_ptr); | |
42 | mock.reset(new KeyValueDBMemory()); | |
43 | } | |
44 | ||
45 | void TearDown() override { } | |
46 | ||
47 | ::testing::AssertionResult validate_db_clear(KeyValueDB *store) { | |
48 | KeyValueDB::WholeSpaceIterator it = store->get_iterator(); | |
49 | it->seek_to_first(); | |
50 | while (it->valid()) { | |
51 | pair<string,string> k = it->raw_key(); | |
52 | if (mock->db.count(k)) { | |
53 | return ::testing::AssertionFailure() | |
54 | << __func__ | |
55 | << " mock store count " << mock->db.count(k) | |
56 | << " key(" << k.first << "," << k.second << ")"; | |
57 | } | |
58 | it->next(); | |
59 | } | |
60 | return ::testing::AssertionSuccess(); | |
61 | } | |
62 | ||
63 | ::testing::AssertionResult validate_db_match() { | |
64 | KeyValueDB::WholeSpaceIterator it = db->get_iterator(); | |
65 | it->seek_to_first(); | |
66 | while (it->valid()) { | |
67 | pair<string, string> k = it->raw_key(); | |
68 | if (!mock->db.count(k)) { | |
69 | return ::testing::AssertionFailure() | |
70 | << __func__ | |
71 | << " mock db.count() " << mock->db.count(k) | |
72 | << " key(" << k.first << "," << k.second << ")"; | |
73 | } | |
74 | ||
75 | bufferlist it_bl = it->value(); | |
76 | bufferlist mock_bl = mock->db[k]; | |
77 | ||
78 | string it_val = _bl_to_str(it_bl); | |
79 | string mock_val = _bl_to_str(mock_bl); | |
80 | ||
81 | if (it_val != mock_val) { | |
82 | return ::testing::AssertionFailure() | |
83 | << __func__ | |
84 | << " key(" << k.first << "," << k.second << ")" | |
85 | << " mismatch db value(" << it_val << ")" | |
86 | << " mock value(" << mock_val << ")"; | |
87 | } | |
88 | it->next(); | |
89 | } | |
90 | return ::testing::AssertionSuccess(); | |
91 | } | |
92 | ||
93 | ::testing::AssertionResult validate_iterator( | |
94 | KeyValueDB::WholeSpaceIterator it, | |
95 | string expected_prefix, | |
96 | string expected_key, | |
97 | string expected_value) { | |
98 | if (!it->valid()) { | |
99 | return ::testing::AssertionFailure() | |
100 | << __func__ | |
101 | << " iterator not valid"; | |
102 | } | |
103 | ||
104 | if (!it->raw_key_is_prefixed(expected_prefix)) { | |
105 | return ::testing::AssertionFailure() | |
106 | << __func__ | |
107 | << " expected raw_key_is_prefixed() == TRUE" | |
108 | << " got FALSE"; | |
109 | } | |
110 | ||
111 | if (it->raw_key_is_prefixed("??__SomeUnexpectedValue__??")) { | |
112 | return ::testing::AssertionFailure() | |
113 | << __func__ | |
114 | << " expected raw_key_is_prefixed() == FALSE" | |
115 | << " got TRUE"; | |
116 | } | |
117 | ||
118 | pair<string,string> key = it->raw_key(); | |
119 | ||
120 | if (expected_prefix != key.first) { | |
121 | return ::testing::AssertionFailure() | |
122 | << __func__ | |
123 | << " expected prefix '" << expected_prefix << "'" | |
124 | << " got prefix '" << key.first << "'"; | |
125 | } | |
126 | ||
127 | if (expected_key != it->key()) { | |
128 | return ::testing::AssertionFailure() | |
129 | << __func__ | |
130 | << " expected key '" << expected_key << "'" | |
131 | << " got key '" << it->key() << "'"; | |
132 | } | |
133 | ||
134 | if (it->key() != key.second) { | |
135 | return ::testing::AssertionFailure() | |
136 | << __func__ | |
137 | << " key '" << it->key() << "'" | |
138 | << " does not match" | |
139 | << " pair key '" << key.second << "'"; | |
140 | } | |
141 | ||
142 | if (_bl_to_str(it->value()) != expected_value) { | |
143 | return ::testing::AssertionFailure() | |
144 | << __func__ | |
145 | << " key '(" << key.first << "," << key.second << ")''" | |
146 | << " expected value '" << expected_value << "'" | |
147 | << " got value '" << _bl_to_str(it->value()) << "'"; | |
148 | } | |
149 | ||
150 | return ::testing::AssertionSuccess(); | |
151 | } | |
152 | ||
153 | /** | |
154 | * Checks if each key in the queue can be forward sequentially read from | |
155 | * the iterator iter. All keys must be present and be prefixed with prefix, | |
156 | * otherwise the validation will fail. | |
157 | * | |
158 | * Assumes that each key value must be based on the key name and generated | |
159 | * by _gen_val(). | |
160 | */ | |
161 | void validate_prefix(KeyValueDB::WholeSpaceIterator iter, | |
162 | string &prefix, deque<string> &keys) { | |
163 | ||
164 | while (!keys.empty()) { | |
165 | ASSERT_TRUE(iter->valid()); | |
166 | string expected_key = keys.front(); | |
167 | keys.pop_front(); | |
168 | string expected_value = _gen_val_str(expected_key); | |
169 | ||
170 | ASSERT_TRUE(validate_iterator(iter, prefix, | |
171 | expected_key, expected_value)); | |
172 | ||
173 | iter->next(); | |
174 | } | |
175 | } | |
176 | /** | |
177 | * Checks if each key in the queue can be backward sequentially read from | |
178 | * the iterator iter. All keys must be present and be prefixed with prefix, | |
179 | * otherwise the validation will fail. | |
180 | * | |
181 | * Assumes that each key value must be based on the key name and generated | |
182 | * by _gen_val(). | |
183 | */ | |
184 | void validate_prefix_backwards(KeyValueDB::WholeSpaceIterator iter, | |
185 | string &prefix, deque<string> &keys) { | |
186 | ||
187 | while (!keys.empty()) { | |
188 | ASSERT_TRUE(iter->valid()); | |
189 | string expected_key = keys.front(); | |
190 | keys.pop_front(); | |
191 | string expected_value = _gen_val_str(expected_key); | |
192 | ||
193 | ASSERT_TRUE(validate_iterator(iter, prefix, | |
194 | expected_key, expected_value)); | |
195 | ||
196 | iter->prev(); | |
197 | } | |
198 | } | |
199 | ||
200 | void clear(KeyValueDB *store) { | |
201 | KeyValueDB::WholeSpaceIterator it = store->get_iterator(); | |
202 | it->seek_to_first(); | |
203 | KeyValueDB::Transaction t = store->get_transaction(); | |
204 | while (it->valid()) { | |
205 | pair<string,string> k = it->raw_key(); | |
206 | t->rmkey(k.first, k.second); | |
207 | it->next(); | |
208 | } | |
209 | store->submit_transaction_sync(t); | |
210 | } | |
211 | ||
212 | string _bl_to_str(bufferlist val) { | |
213 | string str(val.c_str(), val.length()); | |
214 | return str; | |
215 | } | |
216 | ||
217 | string _gen_val_str(string key) { | |
218 | ostringstream ss; | |
219 | ss << "##value##" << key << "##"; | |
220 | return ss.str(); | |
221 | } | |
222 | ||
223 | bufferlist _gen_val(string key) { | |
224 | bufferlist bl; | |
225 | bl.append(_gen_val_str(key)); | |
226 | return bl; | |
227 | } | |
228 | ||
229 | void print_iterator(KeyValueDB::WholeSpaceIterator iter) { | |
230 | if (!iter->valid()) { | |
231 | std::cerr << __func__ << " iterator is not valid; stop." << std::endl; | |
232 | return; | |
233 | } | |
234 | ||
235 | int i = 0; | |
236 | while (iter->valid()) { | |
237 | pair<string,string> k = iter->raw_key(); | |
238 | std::cerr << __func__ | |
239 | << " pos " << (++i) | |
240 | << " key (" << k.first << "," << k.second << ")" | |
241 | << " value(" << _bl_to_str(iter->value()) << ")" << std::endl; | |
242 | iter->next(); | |
243 | } | |
244 | } | |
245 | ||
246 | void print_db(KeyValueDB *store) { | |
247 | KeyValueDB::WholeSpaceIterator it = store->get_iterator(); | |
248 | it->seek_to_first(); | |
249 | print_iterator(it); | |
250 | } | |
251 | }; | |
252 | ||
253 | // ------- Remove Keys / Remove Keys By Prefix ------- | |
254 | class RmKeysTest : public IteratorTest | |
255 | { | |
256 | public: | |
257 | string prefix1; | |
258 | string prefix2; | |
259 | string prefix3; | |
260 | ||
261 | void init(KeyValueDB *db) { | |
262 | KeyValueDB::Transaction tx = db->get_transaction(); | |
263 | ||
264 | tx->set(prefix1, "11", _gen_val("11")); | |
265 | tx->set(prefix1, "12", _gen_val("12")); | |
266 | tx->set(prefix1, "13", _gen_val("13")); | |
267 | tx->set(prefix2, "21", _gen_val("21")); | |
268 | tx->set(prefix2, "22", _gen_val("22")); | |
269 | tx->set(prefix2, "23", _gen_val("23")); | |
270 | tx->set(prefix3, "31", _gen_val("31")); | |
271 | tx->set(prefix3, "32", _gen_val("32")); | |
272 | tx->set(prefix3, "33", _gen_val("33")); | |
273 | ||
274 | db->submit_transaction_sync(tx); | |
275 | } | |
276 | ||
277 | void SetUp() override { | |
278 | IteratorTest::SetUp(); | |
279 | ||
280 | prefix1 = "_PREFIX_1_"; | |
281 | prefix2 = "_PREFIX_2_"; | |
282 | prefix3 = "_PREFIX_3_"; | |
283 | ||
284 | clear(db.get()); | |
285 | ASSERT_TRUE(validate_db_clear(db.get())); | |
286 | clear(mock.get()); | |
287 | ASSERT_TRUE(validate_db_match()); | |
288 | ||
289 | init(db.get()); | |
290 | init(mock.get()); | |
291 | ||
292 | ASSERT_TRUE(validate_db_match()); | |
293 | } | |
294 | ||
295 | void TearDown() override { | |
296 | IteratorTest::TearDown(); | |
297 | } | |
298 | ||
299 | ||
300 | /** | |
301 | * Test the transaction's rmkeys behavior when we remove a given prefix | |
302 | * from the beginning of the key space, or from the end of the key space, | |
303 | * or even simply in the middle. | |
304 | */ | |
305 | void RmKeysByPrefix(KeyValueDB *store) { | |
306 | // remove prefix2 ; check if prefix1 remains, and then prefix3 | |
307 | KeyValueDB::Transaction tx = store->get_transaction(); | |
308 | // remove the prefix in the middle of the key space | |
309 | tx->rmkeys_by_prefix(prefix2); | |
310 | store->submit_transaction_sync(tx); | |
311 | ||
312 | deque<string> key_deque; | |
313 | KeyValueDB::WholeSpaceIterator iter = store->get_iterator(); | |
314 | iter->seek_to_first(); | |
315 | ||
316 | // check for prefix1 | |
317 | key_deque.push_back("11"); | |
318 | key_deque.push_back("12"); | |
319 | key_deque.push_back("13"); | |
320 | validate_prefix(iter, prefix1, key_deque); | |
321 | ASSERT_FALSE(HasFatalFailure()); | |
322 | ||
323 | // check for prefix3 | |
324 | ASSERT_TRUE(iter->valid()); | |
325 | key_deque.clear(); | |
326 | key_deque.push_back("31"); | |
327 | key_deque.push_back("32"); | |
328 | key_deque.push_back("33"); | |
329 | validate_prefix(iter, prefix3, key_deque); | |
330 | ASSERT_FALSE(HasFatalFailure()); | |
331 | ||
332 | ASSERT_FALSE(iter->valid()); | |
333 | ||
334 | clear(store); | |
335 | ASSERT_TRUE(validate_db_clear(store)); | |
336 | init(store); | |
337 | ||
338 | // remove prefix1 ; check if prefix2 and then prefix3 remain | |
339 | tx = store->get_transaction(); | |
340 | // remove the prefix at the beginning of the key space | |
341 | tx->rmkeys_by_prefix(prefix1); | |
342 | store->submit_transaction_sync(tx); | |
343 | ||
344 | iter = store->get_iterator(); | |
345 | iter->seek_to_first(); | |
346 | ||
347 | // check for prefix2 | |
348 | key_deque.clear(); | |
349 | key_deque.push_back("21"); | |
350 | key_deque.push_back("22"); | |
351 | key_deque.push_back("23"); | |
352 | validate_prefix(iter, prefix2, key_deque); | |
353 | ASSERT_FALSE(HasFatalFailure()); | |
354 | ||
355 | // check for prefix3 | |
356 | ASSERT_TRUE(iter->valid()); | |
357 | key_deque.clear(); | |
358 | key_deque.push_back("31"); | |
359 | key_deque.push_back("32"); | |
360 | key_deque.push_back("33"); | |
361 | validate_prefix(iter, prefix3, key_deque); | |
362 | ASSERT_FALSE(HasFatalFailure()); | |
363 | ||
364 | ASSERT_FALSE(iter->valid()); | |
365 | ||
366 | clear(store); | |
367 | ASSERT_TRUE(validate_db_clear(store)); | |
368 | init(store); | |
369 | ||
370 | // remove prefix3 ; check if prefix1 and then prefix2 remain | |
371 | tx = store->get_transaction(); | |
372 | // remove the prefix at the end of the key space | |
373 | tx->rmkeys_by_prefix(prefix3); | |
374 | store->submit_transaction_sync(tx); | |
375 | ||
376 | iter = store->get_iterator(); | |
377 | iter->seek_to_first(); | |
378 | ||
379 | // check for prefix1 | |
380 | key_deque.clear(); | |
381 | key_deque.push_back("11"); | |
382 | key_deque.push_back("12"); | |
383 | key_deque.push_back("13"); | |
384 | validate_prefix(iter, prefix1, key_deque); | |
385 | ASSERT_FALSE(HasFatalFailure()); | |
386 | ||
387 | // check for prefix2 | |
388 | ASSERT_TRUE(iter->valid()); | |
389 | key_deque.clear(); | |
390 | key_deque.push_back("21"); | |
391 | key_deque.push_back("22"); | |
392 | key_deque.push_back("23"); | |
393 | validate_prefix(iter, prefix2, key_deque); | |
394 | ASSERT_FALSE(HasFatalFailure()); | |
395 | ||
396 | ASSERT_FALSE(iter->valid()); | |
397 | } | |
398 | ||
399 | /** | |
400 | * Test how the leveldb's whole-space iterator behaves when we remove | |
401 | * keys from the store while iterating over them. | |
402 | */ | |
403 | void RmKeysWhileIteratingSnapshot(KeyValueDB *store, | |
404 | KeyValueDB::WholeSpaceIterator iter) { | |
405 | ||
406 | SCOPED_TRACE("RmKeysWhileIteratingSnapshot"); | |
407 | ||
408 | iter->seek_to_first(); | |
409 | ASSERT_TRUE(iter->valid()); | |
410 | ||
411 | KeyValueDB::Transaction t = store->get_transaction(); | |
412 | t->rmkey(prefix1, "11"); | |
413 | t->rmkey(prefix1, "12"); | |
414 | t->rmkey(prefix2, "23"); | |
415 | t->rmkey(prefix3, "33"); | |
416 | store->submit_transaction_sync(t); | |
417 | ||
418 | deque<string> key_deque; | |
419 | ||
420 | // check for prefix1 | |
421 | key_deque.push_back("11"); | |
422 | key_deque.push_back("12"); | |
423 | key_deque.push_back("13"); | |
424 | validate_prefix(iter, prefix1, key_deque); | |
425 | ASSERT_FALSE(HasFatalFailure()); | |
426 | ||
427 | // check for prefix2 | |
428 | key_deque.clear(); | |
429 | key_deque.push_back("21"); | |
430 | key_deque.push_back("22"); | |
431 | key_deque.push_back("23"); | |
432 | validate_prefix(iter, prefix2, key_deque); | |
433 | ASSERT_FALSE(HasFatalFailure()); | |
434 | ||
435 | // check for prefix3 | |
436 | key_deque.clear(); | |
437 | key_deque.push_back("31"); | |
438 | key_deque.push_back("32"); | |
439 | key_deque.push_back("33"); | |
440 | validate_prefix(iter, prefix3, key_deque); | |
441 | ASSERT_FALSE(HasFatalFailure()); | |
442 | ||
443 | iter->next(); | |
444 | ASSERT_FALSE(iter->valid()); | |
445 | ||
446 | // make sure those keys were removed from the store | |
447 | KeyValueDB::WholeSpaceIterator tmp_it = store->get_iterator(); | |
448 | tmp_it->seek_to_first(); | |
449 | ASSERT_TRUE(tmp_it->valid()); | |
450 | ||
451 | key_deque.clear(); | |
452 | key_deque.push_back("13"); | |
453 | validate_prefix(tmp_it, prefix1, key_deque); | |
454 | ASSERT_FALSE(HasFatalFailure()); | |
455 | ||
456 | ASSERT_TRUE(tmp_it->valid()); | |
457 | key_deque.clear(); | |
458 | key_deque.push_back("21"); | |
459 | key_deque.push_back("22"); | |
460 | validate_prefix(tmp_it, prefix2, key_deque); | |
461 | ASSERT_FALSE(HasFatalFailure()); | |
462 | ||
463 | ASSERT_TRUE(tmp_it->valid()); | |
464 | key_deque.clear(); | |
465 | key_deque.push_back("31"); | |
466 | key_deque.push_back("32"); | |
467 | validate_prefix(tmp_it, prefix3, key_deque); | |
468 | ASSERT_FALSE(HasFatalFailure()); | |
469 | ||
470 | ASSERT_FALSE(tmp_it->valid()); | |
471 | } | |
472 | }; | |
473 | ||
474 | TEST_F(RmKeysTest, RmKeysByPrefixLevelDB) | |
475 | { | |
476 | SCOPED_TRACE("LevelDB"); | |
477 | RmKeysByPrefix(db.get()); | |
478 | ASSERT_FALSE(HasFatalFailure()); | |
479 | } | |
480 | ||
481 | TEST_F(RmKeysTest, RmKeysByPrefixMockDB) | |
482 | { | |
483 | SCOPED_TRACE("Mock DB"); | |
484 | RmKeysByPrefix(mock.get()); | |
485 | ASSERT_FALSE(HasFatalFailure()); | |
486 | } | |
487 | ||
488 | /** | |
489 | * If you refer to function RmKeysTest::RmKeysWhileIteratingSnapshot(), | |
490 | * you will notice that we seek the iterator to the first key, and then | |
491 | * we go on to remove several keys from the underlying store, including | |
492 | * the first couple keys. | |
493 | * | |
494 | * We would expect that during this test, as soon as we removed the keys | |
495 | * from the store, the iterator would get invalid, or cause some sort of | |
496 | * unexpected mess. | |
497 | * | |
498 | * Instead, the current version of leveldb handles it perfectly, by making | |
499 | * the iterator to use a snapshot instead of the store's real state. This | |
500 | * way, LevelDBStore's whole-space iterator will behave much like its own | |
501 | * whole-space snapshot iterator. | |
502 | * | |
503 | * However, this particular behavior of the iterator hasn't been documented | |
504 | * on leveldb, and we should assume that it can be changed at any point in | |
505 | * time. | |
506 | * | |
507 | * Therefore, we keep this test, being exactly the same as the one for the | |
508 | * whole-space snapshot iterator, as we currently assume they should behave | |
509 | * identically. If this test fails, at some point, and the whole-space | |
510 | * snapshot iterator passes, then it probably means that leveldb changed | |
511 | * how its iterator behaves. | |
512 | */ | |
513 | TEST_F(RmKeysTest, RmKeysWhileIteratingLevelDB) | |
514 | { | |
515 | SCOPED_TRACE("LevelDB -- WholeSpaceIterator"); | |
516 | RmKeysWhileIteratingSnapshot(db.get(), db->get_iterator()); | |
517 | ASSERT_FALSE(HasFatalFailure()); | |
518 | } | |
519 | ||
520 | TEST_F(RmKeysTest, RmKeysWhileIteratingMockDB) | |
521 | { | |
522 | std::cout << "There is no safe way to test key removal while iterating\n" | |
523 | << "over the mock store without using snapshots" << std::endl; | |
524 | } | |
525 | ||
526 | // ------- Set Keys / Update Values ------- | |
527 | class SetKeysTest : public IteratorTest | |
528 | { | |
529 | public: | |
530 | string prefix1; | |
531 | string prefix2; | |
532 | ||
533 | void init(KeyValueDB *db) { | |
534 | KeyValueDB::Transaction tx = db->get_transaction(); | |
535 | ||
536 | tx->set(prefix1, "aaa", _gen_val("aaa")); | |
537 | tx->set(prefix1, "ccc", _gen_val("ccc")); | |
538 | tx->set(prefix1, "eee", _gen_val("eee")); | |
539 | tx->set(prefix2, "vvv", _gen_val("vvv")); | |
540 | tx->set(prefix2, "xxx", _gen_val("xxx")); | |
541 | tx->set(prefix2, "zzz", _gen_val("zzz")); | |
542 | ||
543 | db->submit_transaction_sync(tx); | |
544 | } | |
545 | ||
546 | void SetUp() override { | |
547 | IteratorTest::SetUp(); | |
548 | ||
549 | prefix1 = "_PREFIX_1_"; | |
550 | prefix2 = "_PREFIX_2_"; | |
551 | ||
552 | clear(db.get()); | |
553 | ASSERT_TRUE(validate_db_clear(db.get())); | |
554 | clear(mock.get()); | |
555 | ASSERT_TRUE(validate_db_match()); | |
556 | ||
557 | init(db.get()); | |
558 | init(mock.get()); | |
559 | ||
560 | ASSERT_TRUE(validate_db_match()); | |
561 | } | |
562 | ||
563 | void TearDown() override { | |
564 | IteratorTest::TearDown(); | |
565 | } | |
566 | ||
567 | /** | |
568 | * Make sure that the iterator picks on new keys added if it hasn't yet | |
569 | * iterated away from that position. | |
570 | * | |
571 | * This should only happen for the whole-space iterator when not using | |
572 | * the snapshot version. | |
573 | * | |
574 | * We don't need to test the validity of all elements, but we do test | |
575 | * inserting while moving from the first element to the last, using next() | |
576 | * to move forward, and then we test the same behavior while iterating | |
577 | * from the last element to the first, using prev() to move backwards. | |
578 | */ | |
579 | void SetKeysWhileIterating(KeyValueDB *store, | |
580 | KeyValueDB::WholeSpaceIterator iter) { | |
581 | iter->seek_to_first(); | |
582 | ASSERT_TRUE(iter->valid()); | |
583 | ASSERT_TRUE(validate_iterator(iter, prefix1, "aaa", | |
584 | _gen_val_str("aaa"))); | |
585 | iter->next(); | |
586 | ASSERT_TRUE(iter->valid()); | |
587 | ASSERT_TRUE(validate_iterator(iter, prefix1, "ccc", | |
588 | _bl_to_str(_gen_val("ccc")))); | |
589 | ||
590 | // insert new key 'ddd' after 'ccc' and before 'eee' | |
591 | KeyValueDB::Transaction tx = store->get_transaction(); | |
592 | tx->set(prefix1, "ddd", _gen_val("ddd")); | |
593 | store->submit_transaction_sync(tx); | |
594 | ||
595 | iter->next(); | |
596 | ASSERT_TRUE(iter->valid()); | |
597 | ASSERT_TRUE(validate_iterator(iter, prefix1, "ddd", | |
598 | _gen_val_str("ddd"))); | |
599 | ||
600 | iter->seek_to_last(); | |
601 | ASSERT_TRUE(iter->valid()); | |
602 | tx = store->get_transaction(); | |
603 | tx->set(prefix2, "yyy", _gen_val("yyy")); | |
604 | store->submit_transaction_sync(tx); | |
605 | ||
606 | iter->prev(); | |
607 | ASSERT_TRUE(iter->valid()); | |
608 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
609 | "yyy", _gen_val_str("yyy"))); | |
610 | } | |
611 | ||
612 | /** | |
613 | * Make sure that the whole-space snapshot iterator does not pick on new keys | |
614 | * added to the store since we created the iterator, thus guaranteeing | |
615 | * read-consistency. | |
616 | * | |
617 | * We don't need to test the validity of all elements, but we do test | |
618 | * inserting while moving from the first element to the last, using next() | |
619 | * to move forward, and then we test the same behavior while iterating | |
620 | * from the last element to the first, using prev() to move backwards. | |
621 | */ | |
622 | void SetKeysWhileIteratingSnapshot(KeyValueDB *store, | |
623 | KeyValueDB::WholeSpaceIterator iter) { | |
624 | iter->seek_to_first(); | |
625 | ASSERT_TRUE(iter->valid()); | |
626 | ASSERT_TRUE(validate_iterator(iter, prefix1, "aaa", | |
627 | _gen_val_str("aaa"))); | |
628 | iter->next(); | |
629 | ASSERT_TRUE(iter->valid()); | |
630 | ASSERT_TRUE(validate_iterator(iter, prefix1, "ccc", | |
631 | _bl_to_str(_gen_val("ccc")))); | |
632 | ||
633 | // insert new key 'ddd' after 'ccc' and before 'eee' | |
634 | KeyValueDB::Transaction tx = store->get_transaction(); | |
635 | tx->set(prefix1, "ddd", _gen_val("ddd")); | |
636 | store->submit_transaction_sync(tx); | |
637 | ||
638 | iter->next(); | |
639 | ASSERT_TRUE(iter->valid()); | |
640 | ASSERT_TRUE(validate_iterator(iter, prefix1, "eee", | |
641 | _gen_val_str("eee"))); | |
642 | ||
643 | iter->seek_to_last(); | |
644 | ASSERT_TRUE(iter->valid()); | |
645 | tx = store->get_transaction(); | |
646 | tx->set(prefix2, "yyy", _gen_val("yyy")); | |
647 | store->submit_transaction_sync(tx); | |
648 | ||
649 | iter->prev(); | |
650 | ASSERT_TRUE(iter->valid()); | |
651 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
652 | "xxx", _gen_val_str("xxx"))); | |
653 | } | |
654 | ||
655 | /** | |
656 | * Make sure that the whole-space iterator is able to read values changed on | |
657 | * the store, even after we moved to the updated position. | |
658 | * | |
659 | * This should only be possible when not using the whole-space snapshot | |
660 | * version of the iterator. | |
661 | */ | |
662 | void UpdateValuesWhileIterating(KeyValueDB *store, | |
663 | KeyValueDB::WholeSpaceIterator iter) { | |
664 | iter->seek_to_first(); | |
665 | ASSERT_TRUE(iter->valid()); | |
666 | ASSERT_TRUE(validate_iterator(iter, prefix1, | |
667 | "aaa", _gen_val_str("aaa"))); | |
668 | ||
669 | KeyValueDB::Transaction tx = store->get_transaction(); | |
670 | tx->set(prefix1, "aaa", _gen_val("aaa_1")); | |
671 | store->submit_transaction_sync(tx); | |
672 | ||
673 | ASSERT_TRUE(validate_iterator(iter, prefix1, | |
674 | "aaa", _gen_val_str("aaa_1"))); | |
675 | ||
676 | iter->seek_to_last(); | |
677 | ASSERT_TRUE(iter->valid()); | |
678 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
679 | "zzz", _gen_val_str("zzz"))); | |
680 | ||
681 | tx = store->get_transaction(); | |
682 | tx->set(prefix2, "zzz", _gen_val("zzz_1")); | |
683 | store->submit_transaction_sync(tx); | |
684 | ||
685 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
686 | "zzz", _gen_val_str("zzz_1"))); | |
687 | } | |
688 | ||
689 | /** | |
690 | * Make sure that the whole-space iterator is able to read values changed on | |
691 | * the store, even after we moved to the updated position. | |
692 | * | |
693 | * This should only be possible when not using the whole-space snapshot | |
694 | * version of the iterator. | |
695 | */ | |
696 | void UpdateValuesWhileIteratingSnapshot( | |
697 | KeyValueDB *store, | |
698 | KeyValueDB::WholeSpaceIterator iter) { | |
699 | iter->seek_to_first(); | |
700 | ASSERT_TRUE(iter->valid()); | |
701 | ASSERT_TRUE(validate_iterator(iter, prefix1, | |
702 | "aaa", _gen_val_str("aaa"))); | |
703 | ||
704 | KeyValueDB::Transaction tx = store->get_transaction(); | |
705 | tx->set(prefix1, "aaa", _gen_val("aaa_1")); | |
706 | store->submit_transaction_sync(tx); | |
707 | ||
708 | ASSERT_TRUE(validate_iterator(iter, prefix1, | |
709 | "aaa", _gen_val_str("aaa"))); | |
710 | ||
711 | iter->seek_to_last(); | |
712 | ASSERT_TRUE(iter->valid()); | |
713 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
714 | "zzz", _gen_val_str("zzz"))); | |
715 | ||
716 | tx = store->get_transaction(); | |
717 | tx->set(prefix2, "zzz", _gen_val("zzz_1")); | |
718 | store->submit_transaction_sync(tx); | |
719 | ||
720 | ASSERT_TRUE(validate_iterator(iter, prefix2, | |
721 | "zzz", _gen_val_str("zzz"))); | |
722 | ||
723 | // check those values were really changed in the store | |
724 | KeyValueDB::WholeSpaceIterator tmp_iter = store->get_iterator(); | |
725 | tmp_iter->seek_to_first(); | |
726 | ASSERT_TRUE(tmp_iter->valid()); | |
727 | ASSERT_TRUE(validate_iterator(tmp_iter, prefix1, | |
728 | "aaa", _gen_val_str("aaa_1"))); | |
729 | tmp_iter->seek_to_last(); | |
730 | ASSERT_TRUE(tmp_iter->valid()); | |
731 | ASSERT_TRUE(validate_iterator(tmp_iter, prefix2, | |
732 | "zzz", _gen_val_str("zzz_1"))); | |
733 | } | |
734 | ||
735 | ||
736 | }; | |
737 | ||
738 | TEST_F(SetKeysTest, DISABLED_SetKeysWhileIteratingLevelDB) | |
739 | { | |
740 | SCOPED_TRACE("LevelDB: SetKeysWhileIteratingLevelDB"); | |
741 | SetKeysWhileIterating(db.get(), db->get_iterator()); | |
742 | ASSERT_TRUE(HasFatalFailure()); | |
743 | } | |
744 | ||
745 | TEST_F(SetKeysTest, SetKeysWhileIteratingMockDB) | |
746 | { | |
747 | SCOPED_TRACE("Mock DB: SetKeysWhileIteratingMockDB"); | |
748 | SetKeysWhileIterating(mock.get(), mock->get_iterator()); | |
749 | ASSERT_FALSE(HasFatalFailure()); | |
750 | } | |
751 | ||
752 | TEST_F(SetKeysTest, DISABLED_UpdateValuesWhileIteratingLevelDB) | |
753 | { | |
754 | SCOPED_TRACE("LevelDB: UpdateValuesWhileIteratingLevelDB"); | |
755 | UpdateValuesWhileIterating(db.get(), db->get_iterator()); | |
756 | ASSERT_FALSE(HasFatalFailure()); | |
757 | } | |
758 | ||
759 | TEST_F(SetKeysTest, UpdateValuesWhileIteratingMockDB) | |
760 | { | |
761 | SCOPED_TRACE("MockDB: UpdateValuesWhileIteratingMockDB"); | |
762 | UpdateValuesWhileIterating(mock.get(), mock->get_iterator()); | |
763 | ASSERT_FALSE(HasFatalFailure()); | |
764 | } | |
765 | ||
766 | class BoundsTest : public IteratorTest | |
767 | { | |
768 | public: | |
769 | string prefix1; | |
770 | string prefix2; | |
771 | string prefix3; | |
772 | ||
773 | void init(KeyValueDB *store) { | |
774 | KeyValueDB::Transaction tx = store->get_transaction(); | |
775 | ||
776 | tx->set(prefix1, "aaa", _gen_val("aaa")); | |
777 | tx->set(prefix1, "ccc", _gen_val("ccc")); | |
778 | tx->set(prefix1, "eee", _gen_val("eee")); | |
779 | tx->set(prefix2, "vvv", _gen_val("vvv")); | |
780 | tx->set(prefix2, "xxx", _gen_val("xxx")); | |
781 | tx->set(prefix2, "zzz", _gen_val("zzz")); | |
782 | tx->set(prefix3, "aaa", _gen_val("aaa")); | |
783 | tx->set(prefix3, "mmm", _gen_val("mmm")); | |
784 | tx->set(prefix3, "yyy", _gen_val("yyy")); | |
785 | ||
786 | store->submit_transaction_sync(tx); | |
787 | } | |
788 | ||
789 | void SetUp() override { | |
790 | IteratorTest::SetUp(); | |
791 | ||
792 | prefix1 = "_PREFIX_1_"; | |
793 | prefix2 = "_PREFIX_2_"; | |
794 | prefix3 = "_PREFIX_4_"; | |
795 | ||
796 | clear(db.get()); | |
797 | ASSERT_TRUE(validate_db_clear(db.get())); | |
798 | clear(mock.get()); | |
799 | ASSERT_TRUE(validate_db_match()); | |
800 | ||
801 | init(db.get()); | |
802 | init(mock.get()); | |
803 | ||
804 | ASSERT_TRUE(validate_db_match()); | |
805 | } | |
806 | ||
807 | void TearDown() override { | |
808 | IteratorTest::TearDown(); | |
809 | } | |
810 | ||
811 | void LowerBoundWithEmptyKeyOnWholeSpaceIterator( | |
812 | KeyValueDB::WholeSpaceIterator iter) { | |
813 | deque<string> key_deque; | |
814 | // see what happens when we have an empty key and try to get to the | |
815 | // first available prefix | |
816 | iter->lower_bound(prefix1, ""); | |
817 | ASSERT_TRUE(iter->valid()); | |
818 | ||
819 | key_deque.push_back("aaa"); | |
820 | key_deque.push_back("ccc"); | |
821 | key_deque.push_back("eee"); | |
822 | validate_prefix(iter, prefix1, key_deque); | |
823 | ASSERT_FALSE(HasFatalFailure()); | |
824 | ASSERT_TRUE(iter->valid()); | |
825 | // if we got here without problems, then it is safe to assume the | |
826 | // remaining prefixes are intact. | |
827 | ||
828 | // see what happens when we have an empty key and try to get to the | |
829 | // middle of the key-space | |
830 | iter->lower_bound(prefix2, ""); | |
831 | ASSERT_TRUE(iter->valid()); | |
832 | key_deque.clear(); | |
833 | ||
834 | key_deque.push_back("vvv"); | |
835 | key_deque.push_back("xxx"); | |
836 | key_deque.push_back("zzz"); | |
837 | validate_prefix(iter, prefix2, key_deque); | |
838 | ASSERT_FALSE(HasFatalFailure()); | |
839 | ASSERT_TRUE(iter->valid()); | |
840 | // if we got here without problems, then it is safe to assume the | |
841 | // remaining prefixes are intact. | |
842 | ||
843 | // see what happens when we have an empty key and try to get to the | |
844 | // last prefix on the key-space | |
845 | iter->lower_bound(prefix3, ""); | |
846 | ASSERT_TRUE(iter->valid()); | |
847 | key_deque.clear(); | |
848 | ||
849 | key_deque.push_back("aaa"); | |
850 | key_deque.push_back("mmm"); | |
851 | key_deque.push_back("yyy"); | |
852 | validate_prefix(iter, prefix3, key_deque); | |
853 | ASSERT_FALSE(HasFatalFailure()); | |
854 | ASSERT_FALSE(iter->valid()); | |
855 | // we reached the end of the key_space, so the iterator should no longer | |
856 | // be valid | |
857 | ||
858 | // see what happens when we look for an inexistent prefix, that will | |
859 | // compare higher than the existing prefixes, with an empty key | |
860 | // expected: reach the store's end; iterator becomes invalid | |
861 | iter->lower_bound("_PREFIX_9_", ""); | |
862 | ASSERT_FALSE(iter->valid()); | |
863 | ||
864 | // see what happens when we look for an inexistent prefix, that will | |
865 | // compare lower than the existing prefixes, with an empty key | |
866 | // expected: find the first prefix; iterator is valid | |
867 | iter->lower_bound("_PREFIX_0_", ""); | |
868 | ASSERT_TRUE(iter->valid()); | |
869 | key_deque.clear(); | |
870 | key_deque.push_back("aaa"); | |
871 | key_deque.push_back("ccc"); | |
872 | key_deque.push_back("eee"); | |
873 | validate_prefix(iter, prefix1, key_deque); | |
874 | ASSERT_FALSE(HasFatalFailure()); | |
875 | ASSERT_TRUE(iter->valid()); | |
876 | ||
877 | // see what happens when we look for an empty prefix (that should compare | |
878 | // lower than any existing prefixes) | |
879 | // expected: find the first prefix; iterator is valid | |
880 | iter->lower_bound("", ""); | |
881 | ASSERT_TRUE(iter->valid()); | |
882 | key_deque.push_back("aaa"); | |
883 | key_deque.push_back("ccc"); | |
884 | key_deque.push_back("eee"); | |
885 | validate_prefix(iter, prefix1, key_deque); | |
886 | ASSERT_FALSE(HasFatalFailure()); | |
887 | ASSERT_TRUE(iter->valid()); | |
888 | } | |
889 | ||
890 | void LowerBoundWithEmptyPrefixOnWholeSpaceIterator( | |
891 | KeyValueDB::WholeSpaceIterator iter) { | |
892 | deque<string> key_deque; | |
893 | // check for an empty prefix, with key 'aaa'. Since this key is shared | |
894 | // among two different prefixes, it is relevant to check which will be | |
895 | // found first. | |
896 | // expected: find key (prefix1, aaa); iterator is valid | |
897 | iter->lower_bound("", "aaa"); | |
898 | ASSERT_TRUE(iter->valid()); | |
899 | ||
900 | key_deque.push_back("aaa"); | |
901 | key_deque.push_back("ccc"); | |
902 | key_deque.push_back("eee"); | |
903 | validate_prefix(iter, prefix1, key_deque); | |
904 | ASSERT_FALSE(HasFatalFailure()); | |
905 | ASSERT_TRUE(iter->valid()); | |
906 | // since we found prefix1, it is safe to assume that the remaining | |
907 | // prefixes (prefix2 and prefix3) will follow | |
908 | ||
909 | // any lower_bound operation with an empty prefix should always put the | |
910 | // iterator in the first key in the key-space, despite what key is | |
911 | // specified. This means that looking for ("","AAAAAAAAAA") should | |
912 | // also position the iterator on (prefix1, aaa). | |
913 | // expected: find key (prefix1, aaa); iterator is valid | |
914 | iter->lower_bound("", "AAAAAAAAAA"); | |
915 | ASSERT_TRUE(iter->valid()); | |
916 | key_deque.clear(); | |
917 | key_deque.push_back("aaa"); | |
918 | key_deque.push_back("ccc"); | |
919 | key_deque.push_back("eee"); | |
920 | validate_prefix(iter, prefix1, key_deque); | |
921 | ASSERT_FALSE(HasFatalFailure()); | |
922 | ASSERT_TRUE(iter->valid()); | |
923 | ||
924 | // note: this test is a duplicate of the one in the function above. Why? | |
925 | // Well, because it also fits here (being its prefix empty), and one could | |
926 | // very well run solely this test (instead of the whole battery) and would | |
927 | // certainly expect this case to be tested. | |
928 | ||
929 | // see what happens when we look for an empty prefix (that should compare | |
930 | // lower than any existing prefixes) | |
931 | // expected: find the first prefix; iterator is valid | |
932 | iter->lower_bound("", ""); | |
933 | ASSERT_TRUE(iter->valid()); | |
934 | key_deque.push_back("aaa"); | |
935 | key_deque.push_back("ccc"); | |
936 | key_deque.push_back("eee"); | |
937 | validate_prefix(iter, prefix1, key_deque); | |
938 | ASSERT_FALSE(HasFatalFailure()); | |
939 | ASSERT_TRUE(iter->valid()); | |
940 | } | |
941 | ||
942 | void LowerBoundOnWholeSpaceIterator( | |
943 | KeyValueDB::WholeSpaceIterator iter) { | |
944 | deque<string> key_deque; | |
945 | // check that we find the first key in the store | |
946 | // expected: find (prefix1, aaa); iterator is valid | |
947 | iter->lower_bound(prefix1, "aaa"); | |
948 | ASSERT_TRUE(iter->valid()); | |
949 | key_deque.push_back("aaa"); | |
950 | validate_prefix(iter, prefix1, key_deque); | |
951 | ASSERT_FALSE(HasFatalFailure()); | |
952 | ASSERT_TRUE(iter->valid()); | |
953 | ||
954 | // check that we find the last key in the store | |
955 | // expected: find (prefix3, yyy); iterator is valid | |
956 | iter->lower_bound(prefix3, "yyy"); | |
957 | ASSERT_TRUE(iter->valid()); | |
958 | key_deque.clear(); | |
959 | key_deque.push_back("yyy"); | |
960 | validate_prefix(iter, prefix3, key_deque); | |
961 | ASSERT_FALSE(HasFatalFailure()); | |
962 | ASSERT_FALSE(iter->valid()); | |
963 | ||
964 | // check that looking for non-existent prefix '_PREFIX_0_' will | |
965 | // always result in the first value of prefix1 (prefix1,"aaa") | |
966 | // expected: find (prefix1, aaa); iterator is valid | |
967 | iter->lower_bound("_PREFIX_0_", "AAAAA"); | |
968 | ASSERT_TRUE(iter->valid()); | |
969 | key_deque.clear(); | |
970 | key_deque.push_back("aaa"); | |
971 | validate_prefix(iter, prefix1, key_deque); | |
972 | ASSERT_FALSE(HasFatalFailure()); | |
973 | ASSERT_TRUE(iter->valid()); | |
974 | ||
975 | // check that looking for non-existent prefix '_PREFIX_3_' will | |
976 | // always result in the first value of prefix3 (prefix4,"aaa") | |
977 | // expected: find (prefix3, aaa); iterator is valid | |
978 | iter->lower_bound("_PREFIX_3_", "AAAAA"); | |
979 | ASSERT_TRUE(iter->valid()); | |
980 | key_deque.clear(); | |
981 | key_deque.push_back("aaa"); | |
982 | validate_prefix(iter, prefix3, key_deque); | |
983 | ASSERT_FALSE(HasFatalFailure()); | |
984 | ASSERT_TRUE(iter->valid()); | |
985 | ||
986 | // check that looking for non-existent prefix '_PREFIX_9_' will | |
987 | // always result in an invalid iterator. | |
988 | // expected: iterator is invalid | |
989 | iter->lower_bound("_PREFIX_9_", "AAAAA"); | |
990 | ASSERT_FALSE(iter->valid()); | |
991 | } | |
992 | ||
993 | void UpperBoundWithEmptyKeyOnWholeSpaceIterator( | |
994 | KeyValueDB::WholeSpaceIterator iter) { | |
995 | deque<string> key_deque; | |
996 | // check that looking for (prefix1, "") will result in finding | |
997 | // the first key in prefix1 (prefix1, "aaa") | |
998 | // expected: find (prefix1, aaa); iterator is valid | |
999 | iter->upper_bound(prefix1, ""); | |
1000 | key_deque.push_back("aaa"); | |
1001 | validate_prefix(iter, prefix1, key_deque); | |
1002 | ASSERT_FALSE(HasFatalFailure()); | |
1003 | ASSERT_TRUE(iter->valid()); | |
1004 | ||
1005 | // check that looking for (prefix2, "") will result in finding | |
1006 | // the first key in prefix2 (prefix2, vvv) | |
1007 | // expected: find (prefix2, aaa); iterator is valid | |
1008 | iter->upper_bound(prefix2, ""); | |
1009 | key_deque.push_back("vvv"); | |
1010 | validate_prefix(iter, prefix2, key_deque); | |
1011 | ASSERT_FALSE(HasFatalFailure()); | |
1012 | ASSERT_TRUE(iter->valid()); | |
1013 | ||
1014 | ||
1015 | // check that looking for (prefix3, "") will result in finding | |
1016 | // the first key in prefix3 (prefix3, aaa) | |
1017 | // expected: find (prefix3, aaa); iterator is valid | |
1018 | iter->upper_bound(prefix3, ""); | |
1019 | key_deque.push_back("aaa"); | |
1020 | validate_prefix(iter, prefix3, key_deque); | |
1021 | ASSERT_FALSE(HasFatalFailure()); | |
1022 | ASSERT_TRUE(iter->valid()); | |
1023 | ||
1024 | // see what happens when we look for an inexistent prefix, that will | |
1025 | // compare higher than the existing prefixes, with an empty key | |
1026 | // expected: reach the store's end; iterator becomes invalid | |
1027 | iter->upper_bound("_PREFIX_9_", ""); | |
1028 | ASSERT_FALSE(iter->valid()); | |
1029 | ||
1030 | // see what happens when we look for an inexistent prefix, that will | |
1031 | // compare lower than the existing prefixes, with an empty key | |
1032 | // expected: find the first prefix; iterator is valid | |
1033 | iter->upper_bound("_PREFIX_0_", ""); | |
1034 | ASSERT_TRUE(iter->valid()); | |
1035 | key_deque.clear(); | |
1036 | key_deque.push_back("aaa"); | |
1037 | validate_prefix(iter, prefix1, key_deque); | |
1038 | ASSERT_FALSE(HasFatalFailure()); | |
1039 | ASSERT_TRUE(iter->valid()); | |
1040 | ||
1041 | // see what happens when we look for an empty prefix (that should compare | |
1042 | // lower than any existing prefixes) | |
1043 | // expected: find the first prefix; iterator is valid | |
1044 | iter->upper_bound("", ""); | |
1045 | ASSERT_TRUE(iter->valid()); | |
1046 | key_deque.push_back("aaa"); | |
1047 | validate_prefix(iter, prefix1, key_deque); | |
1048 | ASSERT_FALSE(HasFatalFailure()); | |
1049 | ASSERT_TRUE(iter->valid()); | |
1050 | } | |
1051 | ||
1052 | void UpperBoundWithEmptyPrefixOnWholeSpaceIterator( | |
1053 | KeyValueDB::WholeSpaceIterator iter) { | |
1054 | deque<string> key_deque; | |
1055 | // check for an empty prefix, with key 'aaa'. Since this key is shared | |
1056 | // among two different prefixes, it is relevant to check which will be | |
1057 | // found first. | |
1058 | // expected: find key (prefix1, aaa); iterator is valid | |
1059 | iter->upper_bound("", "aaa"); | |
1060 | ASSERT_TRUE(iter->valid()); | |
1061 | key_deque.push_back("aaa"); | |
1062 | key_deque.push_back("ccc"); | |
1063 | key_deque.push_back("eee"); | |
1064 | validate_prefix(iter, prefix1, key_deque); | |
1065 | ASSERT_FALSE(HasFatalFailure()); | |
1066 | ASSERT_TRUE(iter->valid()); | |
1067 | ||
1068 | // any upper_bound operation with an empty prefix should always put the | |
1069 | // iterator in the first key whose prefix compares greater, despite the | |
1070 | // key that is specified. This means that looking for ("","AAAAAAAAAA") | |
1071 | // should position the iterator on (prefix1, aaa). | |
1072 | // expected: find key (prefix1, aaa); iterator is valid | |
1073 | iter->upper_bound("", "AAAAAAAAAA"); | |
1074 | ASSERT_TRUE(iter->valid()); | |
1075 | key_deque.clear(); | |
1076 | key_deque.push_back("aaa"); | |
1077 | validate_prefix(iter, prefix1, key_deque); | |
1078 | ASSERT_FALSE(HasFatalFailure()); | |
1079 | ASSERT_TRUE(iter->valid()); | |
1080 | ||
1081 | // note: this test is a duplicate of the one in the function above. Why? | |
1082 | // Well, because it also fits here (being its prefix empty), and one could | |
1083 | // very well run solely this test (instead of the whole battery) and would | |
1084 | // certainly expect this case to be tested. | |
1085 | ||
1086 | // see what happens when we look for an empty prefix (that should compare | |
1087 | // lower than any existing prefixes) | |
1088 | // expected: find the first prefix; iterator is valid | |
1089 | iter->upper_bound("", ""); | |
1090 | ASSERT_TRUE(iter->valid()); | |
1091 | key_deque.push_back("aaa"); | |
1092 | validate_prefix(iter, prefix1, key_deque); | |
1093 | ASSERT_FALSE(HasFatalFailure()); | |
1094 | ASSERT_TRUE(iter->valid()); | |
1095 | } | |
1096 | ||
1097 | void UpperBoundOnWholeSpaceIterator( | |
1098 | KeyValueDB::WholeSpaceIterator iter) { | |
1099 | deque<string> key_deque; | |
1100 | // check that we find the second key in the store | |
1101 | // expected: find (prefix1, ccc); iterator is valid | |
1102 | iter->upper_bound(prefix1, "bbb"); | |
1103 | ASSERT_TRUE(iter->valid()); | |
1104 | key_deque.push_back("ccc"); | |
1105 | validate_prefix(iter, prefix1, key_deque); | |
1106 | ASSERT_FALSE(HasFatalFailure()); | |
1107 | ASSERT_TRUE(iter->valid()); | |
1108 | ||
1109 | // check that we find the last key in the store | |
1110 | // expected: find (prefix3, yyy); iterator is valid | |
1111 | iter->upper_bound(prefix3, "xxx"); | |
1112 | ASSERT_TRUE(iter->valid()); | |
1113 | key_deque.clear(); | |
1114 | key_deque.push_back("yyy"); | |
1115 | validate_prefix(iter, prefix3, key_deque); | |
1116 | ASSERT_FALSE(HasFatalFailure()); | |
1117 | ASSERT_FALSE(iter->valid()); | |
1118 | ||
1119 | // check that looking for non-existent prefix '_PREFIX_0_' will | |
1120 | // always result in the first value of prefix1 (prefix1,"aaa") | |
1121 | // expected: find (prefix1, aaa); iterator is valid | |
1122 | iter->upper_bound("_PREFIX_0_", "AAAAA"); | |
1123 | ASSERT_TRUE(iter->valid()); | |
1124 | key_deque.clear(); | |
1125 | key_deque.push_back("aaa"); | |
1126 | validate_prefix(iter, prefix1, key_deque); | |
1127 | ASSERT_FALSE(HasFatalFailure()); | |
1128 | ASSERT_TRUE(iter->valid()); | |
1129 | ||
1130 | // check that looking for non-existent prefix '_PREFIX_3_' will | |
1131 | // always result in the first value of prefix3 (prefix3,"aaa") | |
1132 | // expected: find (prefix3, aaa); iterator is valid | |
1133 | iter->upper_bound("_PREFIX_3_", "AAAAA"); | |
1134 | ASSERT_TRUE(iter->valid()); | |
1135 | key_deque.clear(); | |
1136 | key_deque.push_back("aaa"); | |
1137 | validate_prefix(iter, prefix3, key_deque); | |
1138 | ASSERT_FALSE(HasFatalFailure()); | |
1139 | ASSERT_TRUE(iter->valid()); | |
1140 | ||
1141 | // check that looking for non-existent prefix '_PREFIX_9_' will | |
1142 | // always result in an invalid iterator. | |
1143 | // expected: iterator is invalid | |
1144 | iter->upper_bound("_PREFIX_9_", "AAAAA"); | |
1145 | ASSERT_FALSE(iter->valid()); | |
1146 | } | |
1147 | }; | |
1148 | ||
1149 | TEST_F(BoundsTest, LowerBoundWithEmptyKeyOnWholeSpaceIteratorLevelDB) | |
1150 | { | |
1151 | SCOPED_TRACE("LevelDB: Lower Bound, Empty Key, Whole-Space Iterator"); | |
1152 | LowerBoundWithEmptyKeyOnWholeSpaceIterator(db->get_iterator()); | |
1153 | ASSERT_FALSE(HasFatalFailure()); | |
1154 | } | |
1155 | ||
1156 | TEST_F(BoundsTest, LowerBoundWithEmptyKeyOnWholeSpaceIteratorMockDB) | |
1157 | { | |
1158 | SCOPED_TRACE("MockDB: Lower Bound, Empty Key, Whole-Space Iterator"); | |
1159 | LowerBoundWithEmptyKeyOnWholeSpaceIterator(mock->get_iterator()); | |
1160 | ASSERT_FALSE(HasFatalFailure()); | |
1161 | } | |
1162 | ||
1163 | TEST_F(BoundsTest, LowerBoundWithEmptyPrefixOnWholeSpaceIteratorLevelDB) | |
1164 | { | |
1165 | SCOPED_TRACE("LevelDB: Lower Bound, Empty Prefix, Whole-Space Iterator"); | |
1166 | LowerBoundWithEmptyPrefixOnWholeSpaceIterator(db->get_iterator()); | |
1167 | ASSERT_FALSE(HasFatalFailure()); | |
1168 | } | |
1169 | ||
1170 | TEST_F(BoundsTest, LowerBoundWithEmptyPrefixOnWholeSpaceIteratorMockDB) | |
1171 | { | |
1172 | SCOPED_TRACE("MockDB: Lower Bound, Empty Prefix, Whole-Space Iterator"); | |
1173 | LowerBoundWithEmptyPrefixOnWholeSpaceIterator(mock->get_iterator()); | |
1174 | ASSERT_FALSE(HasFatalFailure()); | |
1175 | } | |
1176 | ||
1177 | TEST_F(BoundsTest, LowerBoundOnWholeSpaceIteratorLevelDB) | |
1178 | { | |
1179 | SCOPED_TRACE("LevelDB: Lower Bound, Whole-Space Iterator"); | |
1180 | LowerBoundOnWholeSpaceIterator(db->get_iterator()); | |
1181 | ASSERT_FALSE(HasFatalFailure()); | |
1182 | } | |
1183 | ||
1184 | TEST_F(BoundsTest, LowerBoundOnWholeSpaceIteratorMockDB) | |
1185 | { | |
1186 | SCOPED_TRACE("MockDB: Lower Bound, Whole-Space Iterator"); | |
1187 | LowerBoundOnWholeSpaceIterator(mock->get_iterator()); | |
1188 | ASSERT_FALSE(HasFatalFailure()); | |
1189 | } | |
1190 | ||
1191 | TEST_F(BoundsTest, UpperBoundWithEmptyKeyOnWholeSpaceIteratorLevelDB) | |
1192 | { | |
1193 | SCOPED_TRACE("LevelDB: Upper Bound, Empty Key, Whole-Space Iterator"); | |
1194 | UpperBoundWithEmptyKeyOnWholeSpaceIterator(db->get_iterator()); | |
1195 | ASSERT_FALSE(HasFatalFailure()); | |
1196 | } | |
1197 | ||
1198 | TEST_F(BoundsTest, UpperBoundWithEmptyKeyOnWholeSpaceIteratorMockDB) | |
1199 | { | |
1200 | SCOPED_TRACE("MockDB: Upper Bound, Empty Key, Whole-Space Iterator"); | |
1201 | UpperBoundWithEmptyKeyOnWholeSpaceIterator(mock->get_iterator()); | |
1202 | ASSERT_FALSE(HasFatalFailure()); | |
1203 | } | |
1204 | ||
1205 | TEST_F(BoundsTest, UpperBoundWithEmptyPrefixOnWholeSpaceIteratorLevelDB) | |
1206 | { | |
1207 | SCOPED_TRACE("LevelDB: Upper Bound, Empty Prefix, Whole-Space Iterator"); | |
1208 | UpperBoundWithEmptyPrefixOnWholeSpaceIterator(db->get_iterator()); | |
1209 | ASSERT_FALSE(HasFatalFailure()); | |
1210 | } | |
1211 | ||
1212 | TEST_F(BoundsTest, UpperBoundWithEmptyPrefixOnWholeSpaceIteratorMockDB) | |
1213 | { | |
1214 | SCOPED_TRACE("MockDB: Upper Bound, Empty Prefix, Whole-Space Iterator"); | |
1215 | UpperBoundWithEmptyPrefixOnWholeSpaceIterator(mock->get_iterator()); | |
1216 | ASSERT_FALSE(HasFatalFailure()); | |
1217 | } | |
1218 | ||
1219 | TEST_F(BoundsTest, UpperBoundOnWholeSpaceIteratorLevelDB) | |
1220 | { | |
1221 | SCOPED_TRACE("LevelDB: Upper Bound, Whole-Space Iterator"); | |
1222 | UpperBoundOnWholeSpaceIterator(db->get_iterator()); | |
1223 | ASSERT_FALSE(HasFatalFailure()); | |
1224 | } | |
1225 | ||
1226 | TEST_F(BoundsTest, UpperBoundOnWholeSpaceIteratorMockDB) | |
1227 | { | |
1228 | SCOPED_TRACE("MockDB: Upper Bound, Whole-Space Iterator"); | |
1229 | UpperBoundOnWholeSpaceIterator(mock->get_iterator()); | |
1230 | ASSERT_FALSE(HasFatalFailure()); | |
1231 | } | |
1232 | ||
1233 | ||
1234 | class SeeksTest : public IteratorTest | |
1235 | { | |
1236 | public: | |
1237 | string prefix0; | |
1238 | string prefix1; | |
1239 | string prefix2; | |
1240 | string prefix3; | |
1241 | string prefix4; | |
1242 | string prefix5; | |
1243 | ||
1244 | void init(KeyValueDB *store) { | |
1245 | KeyValueDB::Transaction tx = store->get_transaction(); | |
1246 | ||
1247 | tx->set(prefix1, "aaa", _gen_val("aaa")); | |
1248 | tx->set(prefix1, "ccc", _gen_val("ccc")); | |
1249 | tx->set(prefix1, "eee", _gen_val("eee")); | |
1250 | tx->set(prefix2, "vvv", _gen_val("vvv")); | |
1251 | tx->set(prefix2, "xxx", _gen_val("xxx")); | |
1252 | tx->set(prefix2, "zzz", _gen_val("zzz")); | |
1253 | tx->set(prefix4, "aaa", _gen_val("aaa")); | |
1254 | tx->set(prefix4, "mmm", _gen_val("mmm")); | |
1255 | tx->set(prefix4, "yyy", _gen_val("yyy")); | |
1256 | ||
1257 | store->submit_transaction_sync(tx); | |
1258 | } | |
1259 | ||
1260 | void SetUp() override { | |
1261 | IteratorTest::SetUp(); | |
1262 | ||
1263 | prefix0 = "_PREFIX_0_"; | |
1264 | prefix1 = "_PREFIX_1_"; | |
1265 | prefix2 = "_PREFIX_2_"; | |
1266 | prefix3 = "_PREFIX_3_"; | |
1267 | prefix4 = "_PREFIX_4_"; | |
1268 | prefix5 = "_PREFIX_5_"; | |
1269 | ||
1270 | clear(db.get()); | |
1271 | ASSERT_TRUE(validate_db_clear(db.get())); | |
1272 | clear(mock.get()); | |
1273 | ASSERT_TRUE(validate_db_match()); | |
1274 | ||
1275 | init(db.get()); | |
1276 | init(mock.get()); | |
1277 | ||
1278 | ASSERT_TRUE(validate_db_match()); | |
1279 | } | |
1280 | ||
1281 | void TearDown() override { | |
1282 | IteratorTest::TearDown(); | |
1283 | } | |
1284 | ||
1285 | ||
1286 | void SeekToFirstOnWholeSpaceIterator( | |
1287 | KeyValueDB::WholeSpaceIterator iter) { | |
1288 | iter->seek_to_first(); | |
1289 | ASSERT_TRUE(iter->valid()); | |
1290 | deque<string> key_deque; | |
1291 | key_deque.push_back("aaa"); | |
1292 | key_deque.push_back("ccc"); | |
1293 | key_deque.push_back("eee"); | |
1294 | validate_prefix(iter, prefix1, key_deque); | |
1295 | ASSERT_FALSE(HasFatalFailure()); | |
1296 | ASSERT_TRUE(iter->valid()); | |
1297 | } | |
1298 | ||
1299 | void SeekToFirstWithPrefixOnWholeSpaceIterator( | |
1300 | KeyValueDB::WholeSpaceIterator iter) { | |
1301 | deque<string> key_deque; | |
1302 | ||
1303 | // if the prefix is empty, we must end up seeking to the first key. | |
1304 | // expected: seek to (prefix1, aaa); iterator is valid | |
1305 | iter->seek_to_first(""); | |
1306 | ASSERT_TRUE(iter->valid()); | |
1307 | key_deque.push_back("aaa"); | |
1308 | validate_prefix(iter, prefix1, key_deque); | |
1309 | ASSERT_FALSE(HasFatalFailure()); | |
1310 | ASSERT_TRUE(iter->valid()); | |
1311 | ||
1312 | // try seeking to non-existent prefix that compares lower than the | |
1313 | // first available prefix | |
1314 | // expected: seek to (prefix1, aaa); iterator is valid | |
1315 | iter->seek_to_first(prefix0); | |
1316 | ASSERT_TRUE(iter->valid()); | |
1317 | key_deque.clear(); | |
1318 | key_deque.push_back("aaa"); | |
1319 | validate_prefix(iter, prefix1, key_deque); | |
1320 | ASSERT_FALSE(HasFatalFailure()); | |
1321 | ASSERT_TRUE(iter->valid()); | |
1322 | ||
1323 | // try seeking to non-existent prefix | |
1324 | // expected: seek to (prefix4, aaa); iterator is valid | |
1325 | iter->seek_to_first(prefix3); | |
1326 | ASSERT_TRUE(iter->valid()); | |
1327 | key_deque.clear(); | |
1328 | key_deque.push_back("aaa"); | |
1329 | validate_prefix(iter, prefix4, key_deque); | |
1330 | ASSERT_FALSE(HasFatalFailure()); | |
1331 | ASSERT_TRUE(iter->valid()); | |
1332 | ||
1333 | // try seeking to non-existent prefix that compares greater than the | |
1334 | // last available prefix | |
1335 | // expected: iterator is invalid | |
1336 | iter->seek_to_first(prefix5); | |
1337 | ASSERT_FALSE(iter->valid()); | |
1338 | ||
1339 | // try seeking to the first prefix and make sure we end up in its first | |
1340 | // position | |
1341 | // expected: seek to (prefix1,aaa); iterator is valid | |
1342 | iter->seek_to_first(prefix1); | |
1343 | ASSERT_TRUE(iter->valid()); | |
1344 | key_deque.clear(); | |
1345 | key_deque.push_back("aaa"); | |
1346 | validate_prefix(iter, prefix1, key_deque); | |
1347 | ASSERT_FALSE(HasFatalFailure()); | |
1348 | ASSERT_TRUE(iter->valid()); | |
1349 | ||
1350 | // try seeking to the second prefix and make sure we end up in its | |
1351 | // first position | |
1352 | // expected: seek to (prefix2,vvv); iterator is valid | |
1353 | iter->seek_to_first(prefix2); | |
1354 | ASSERT_TRUE(iter->valid()); | |
1355 | key_deque.clear(); | |
1356 | key_deque.push_back("vvv"); | |
1357 | validate_prefix(iter, prefix2, key_deque); | |
1358 | ASSERT_FALSE(HasFatalFailure()); | |
1359 | ASSERT_TRUE(iter->valid()); | |
1360 | ||
1361 | // try seeking to the last prefix and make sure we end up in its | |
1362 | // first position | |
1363 | // expected: seek to (prefix4,aaa); iterator is valid | |
1364 | iter->seek_to_first(prefix4); | |
1365 | ASSERT_TRUE(iter->valid()); | |
1366 | key_deque.clear(); | |
1367 | key_deque.push_back("aaa"); | |
1368 | validate_prefix(iter, prefix4, key_deque); | |
1369 | ASSERT_FALSE(HasFatalFailure()); | |
1370 | ASSERT_TRUE(iter->valid()); | |
1371 | } | |
1372 | ||
1373 | void SeekToLastOnWholeSpaceIterator( | |
1374 | KeyValueDB::WholeSpaceIterator iter) { | |
1375 | deque<string> key_deque; | |
1376 | iter->seek_to_last(); | |
1377 | key_deque.push_back("yyy"); | |
1378 | validate_prefix(iter, prefix4, key_deque); | |
1379 | ASSERT_FALSE(HasFatalFailure()); | |
1380 | ASSERT_FALSE(iter->valid()); | |
1381 | } | |
1382 | ||
1383 | void SeekToLastWithPrefixOnWholeSpaceIterator( | |
1384 | KeyValueDB::WholeSpaceIterator iter) { | |
1385 | deque<string> key_deque; | |
1386 | ||
1387 | // if the prefix is empty, we must end up seeking to last position | |
1388 | // that has an empty prefix, or to the previous position to the first | |
1389 | // position whose prefix compares higher than empty. | |
1390 | // expected: iterator is invalid (because (prefix1,aaa) is the first | |
1391 | // position that compared higher than an empty prefix) | |
1392 | iter->seek_to_last(""); | |
1393 | ASSERT_FALSE(iter->valid()); | |
1394 | ||
1395 | // try seeking to non-existent prefix that compares lower than the | |
1396 | // first available prefix | |
1397 | // expected: iterator is invalid (because (prefix1,aaa) is the first | |
1398 | // position that compared higher than prefix0) | |
1399 | iter->seek_to_last(prefix0); | |
1400 | ASSERT_FALSE(iter->valid()); | |
1401 | ||
1402 | // try seeking to non-existent prefix | |
1403 | // expected: seek to (prefix2, zzz); iterator is valid | |
1404 | iter->seek_to_last(prefix3); | |
1405 | ASSERT_TRUE(iter->valid()); | |
1406 | key_deque.clear(); | |
1407 | key_deque.push_back("zzz"); | |
1408 | validate_prefix(iter, prefix2, key_deque); | |
1409 | ASSERT_FALSE(HasFatalFailure()); | |
1410 | ASSERT_TRUE(iter->valid()); | |
1411 | ||
1412 | // try seeking to non-existent prefix that compares greater than the | |
1413 | // last available prefix | |
1414 | // expected: iterator is in the last position of the store; | |
1415 | // i.e., (prefix4,yyy) | |
1416 | iter->seek_to_last(prefix5); | |
1417 | ASSERT_TRUE(iter->valid()); | |
1418 | key_deque.clear(); | |
1419 | key_deque.push_back("yyy"); | |
1420 | validate_prefix(iter, prefix4, key_deque); | |
1421 | ASSERT_FALSE(HasFatalFailure()); | |
1422 | ASSERT_FALSE(iter->valid()); | |
1423 | ||
1424 | // try seeking to the first prefix and make sure we end up in its last | |
1425 | // position | |
1426 | // expected: seek to (prefix1,eee); iterator is valid | |
1427 | iter->seek_to_last(prefix1); | |
1428 | ASSERT_TRUE(iter->valid()); | |
1429 | key_deque.clear(); | |
1430 | key_deque.push_back("eee"); | |
1431 | validate_prefix(iter, prefix1, key_deque); | |
1432 | ASSERT_FALSE(HasFatalFailure()); | |
1433 | ASSERT_TRUE(iter->valid()); | |
1434 | ||
1435 | // try seeking to the second prefix and make sure we end up in its | |
1436 | // last position | |
1437 | // expected: seek to (prefix2,vvv); iterator is valid | |
1438 | iter->seek_to_last(prefix2); | |
1439 | ASSERT_TRUE(iter->valid()); | |
1440 | key_deque.clear(); | |
1441 | key_deque.push_back("zzz"); | |
1442 | validate_prefix(iter, prefix2, key_deque); | |
1443 | ASSERT_FALSE(HasFatalFailure()); | |
1444 | ASSERT_TRUE(iter->valid()); | |
1445 | ||
1446 | // try seeking to the last prefix and make sure we end up in its | |
1447 | // last position | |
1448 | // expected: seek to (prefix4,aaa); iterator is valid | |
1449 | iter->seek_to_last(prefix4); | |
1450 | ASSERT_TRUE(iter->valid()); | |
1451 | key_deque.clear(); | |
1452 | key_deque.push_back("yyy"); | |
1453 | validate_prefix(iter, prefix4, key_deque); | |
1454 | ASSERT_FALSE(HasFatalFailure()); | |
1455 | ASSERT_FALSE(iter->valid()); | |
1456 | } | |
1457 | }; | |
1458 | ||
1459 | TEST_F(SeeksTest, SeekToFirstOnWholeSpaceIteratorLevelDB) { | |
1460 | SCOPED_TRACE("LevelDB: Seek To First, Whole Space Iterator"); | |
1461 | SeekToFirstOnWholeSpaceIterator(db->get_iterator()); | |
1462 | ASSERT_FALSE(HasFatalFailure()); | |
1463 | } | |
1464 | ||
1465 | TEST_F(SeeksTest, SeekToFirstOnWholeSpaceIteratorMockDB) { | |
1466 | SCOPED_TRACE("MockDB: Seek To First, Whole Space Iterator"); | |
1467 | SeekToFirstOnWholeSpaceIterator(mock->get_iterator()); | |
1468 | ASSERT_FALSE(HasFatalFailure()); | |
1469 | } | |
1470 | ||
1471 | TEST_F(SeeksTest, SeekToFirstWithPrefixOnWholeSpaceIteratorLevelDB) { | |
1472 | SCOPED_TRACE("LevelDB: Seek To First, With Prefix, Whole Space Iterator"); | |
1473 | SeekToFirstWithPrefixOnWholeSpaceIterator(db->get_iterator()); | |
1474 | ASSERT_FALSE(HasFatalFailure()); | |
1475 | } | |
1476 | ||
1477 | TEST_F(SeeksTest, SeekToFirstWithPrefixOnWholeSpaceIteratorMockDB) { | |
1478 | SCOPED_TRACE("MockDB: Seek To First, With Prefix, Whole Space Iterator"); | |
1479 | SeekToFirstWithPrefixOnWholeSpaceIterator(mock->get_iterator()); | |
1480 | ASSERT_FALSE(HasFatalFailure()); | |
1481 | } | |
1482 | ||
1483 | TEST_F(SeeksTest, SeekToLastOnWholeSpaceIteratorLevelDB) { | |
1484 | SCOPED_TRACE("LevelDB: Seek To Last, Whole Space Iterator"); | |
1485 | SeekToLastOnWholeSpaceIterator(db->get_iterator()); | |
1486 | ASSERT_FALSE(HasFatalFailure()); | |
1487 | } | |
1488 | ||
1489 | TEST_F(SeeksTest, SeekToLastOnWholeSpaceIteratorMockDB) { | |
1490 | SCOPED_TRACE("MockDB: Seek To Last, Whole Space Iterator"); | |
1491 | SeekToLastOnWholeSpaceIterator(mock->get_iterator()); | |
1492 | ASSERT_FALSE(HasFatalFailure()); | |
1493 | } | |
1494 | ||
1495 | TEST_F(SeeksTest, SeekToLastWithPrefixOnWholeSpaceIteratorLevelDB) { | |
1496 | SCOPED_TRACE("LevelDB: Seek To Last, With Prefix, Whole Space Iterator"); | |
1497 | SeekToLastWithPrefixOnWholeSpaceIterator(db->get_iterator()); | |
1498 | ASSERT_FALSE(HasFatalFailure()); | |
1499 | } | |
1500 | ||
1501 | TEST_F(SeeksTest, SeekToLastWithPrefixOnWholeSpaceIteratorMockDB) { | |
1502 | SCOPED_TRACE("MockDB: Seek To Last, With Prefix, Whole Space Iterator"); | |
1503 | SeekToLastWithPrefixOnWholeSpaceIterator(mock->get_iterator()); | |
1504 | ASSERT_FALSE(HasFatalFailure()); | |
1505 | } | |
1506 | ||
1507 | class KeySpaceIteration : public IteratorTest | |
1508 | { | |
1509 | public: | |
1510 | string prefix1; | |
1511 | ||
1512 | void init(KeyValueDB *store) { | |
1513 | KeyValueDB::Transaction tx = store->get_transaction(); | |
1514 | ||
1515 | tx->set(prefix1, "aaa", _gen_val("aaa")); | |
1516 | tx->set(prefix1, "vvv", _gen_val("vvv")); | |
1517 | tx->set(prefix1, "zzz", _gen_val("zzz")); | |
1518 | ||
1519 | store->submit_transaction_sync(tx); | |
1520 | } | |
1521 | ||
1522 | void SetUp() override { | |
1523 | IteratorTest::SetUp(); | |
1524 | ||
1525 | prefix1 = "_PREFIX_1_"; | |
1526 | ||
1527 | clear(db.get()); | |
1528 | ASSERT_TRUE(validate_db_clear(db.get())); | |
1529 | clear(mock.get()); | |
1530 | ASSERT_TRUE(validate_db_match()); | |
1531 | ||
1532 | init(db.get()); | |
1533 | init(mock.get()); | |
1534 | ||
1535 | ASSERT_TRUE(validate_db_match()); | |
1536 | } | |
1537 | ||
1538 | void TearDown() override { | |
1539 | IteratorTest::TearDown(); | |
1540 | } | |
1541 | ||
1542 | void ForwardIteration(KeyValueDB::WholeSpaceIterator iter) { | |
1543 | deque<string> key_deque; | |
1544 | iter->seek_to_first(); | |
1545 | key_deque.push_back("aaa"); | |
1546 | key_deque.push_back("vvv"); | |
1547 | key_deque.push_back("zzz"); | |
1548 | validate_prefix(iter, prefix1, key_deque); | |
1549 | ASSERT_FALSE(HasFatalFailure()); | |
1550 | ASSERT_FALSE(iter->valid()); | |
1551 | } | |
1552 | ||
1553 | void BackwardIteration(KeyValueDB::WholeSpaceIterator iter) { | |
1554 | deque<string> key_deque; | |
1555 | iter->seek_to_last(); | |
1556 | key_deque.push_back("zzz"); | |
1557 | key_deque.push_back("vvv"); | |
1558 | key_deque.push_back("aaa"); | |
1559 | validate_prefix_backwards(iter, prefix1, key_deque); | |
1560 | ASSERT_FALSE(HasFatalFailure()); | |
1561 | ASSERT_FALSE(iter->valid()); | |
1562 | } | |
1563 | }; | |
1564 | ||
1565 | TEST_F(KeySpaceIteration, ForwardIterationLevelDB) | |
1566 | { | |
1567 | SCOPED_TRACE("LevelDB: Forward Iteration, Whole Space Iterator"); | |
1568 | ForwardIteration(db->get_iterator()); | |
1569 | ASSERT_FALSE(HasFatalFailure()); | |
1570 | } | |
1571 | ||
1572 | TEST_F(KeySpaceIteration, ForwardIterationMockDB) { | |
1573 | SCOPED_TRACE("MockDB: Forward Iteration, Whole Space Iterator"); | |
1574 | ForwardIteration(mock->get_iterator()); | |
1575 | ASSERT_FALSE(HasFatalFailure()); | |
1576 | } | |
1577 | ||
1578 | TEST_F(KeySpaceIteration, BackwardIterationLevelDB) | |
1579 | { | |
1580 | SCOPED_TRACE("LevelDB: Backward Iteration, Whole Space Iterator"); | |
1581 | BackwardIteration(db->get_iterator()); | |
1582 | ASSERT_FALSE(HasFatalFailure()); | |
1583 | } | |
1584 | ||
1585 | TEST_F(KeySpaceIteration, BackwardIterationMockDB) { | |
1586 | SCOPED_TRACE("MockDB: Backward Iteration, Whole Space Iterator"); | |
1587 | BackwardIteration(mock->get_iterator()); | |
1588 | ASSERT_FALSE(HasFatalFailure()); | |
1589 | } | |
1590 | ||
1591 | class EmptyStore : public IteratorTest | |
1592 | { | |
1593 | public: | |
1594 | void SetUp() override { | |
1595 | IteratorTest::SetUp(); | |
1596 | ||
1597 | clear(db.get()); | |
1598 | ASSERT_TRUE(validate_db_clear(db.get())); | |
1599 | clear(mock.get()); | |
1600 | ASSERT_TRUE(validate_db_match()); | |
1601 | } | |
1602 | ||
1603 | void SeekToFirst(KeyValueDB::WholeSpaceIterator iter) { | |
1604 | // expected: iterator is invalid | |
1605 | iter->seek_to_first(); | |
1606 | ASSERT_FALSE(iter->valid()); | |
1607 | } | |
1608 | ||
1609 | void SeekToFirstWithPrefix(KeyValueDB::WholeSpaceIterator iter) { | |
1610 | // expected: iterator is invalid | |
1611 | iter->seek_to_first("prefix"); | |
1612 | ASSERT_FALSE(iter->valid()); | |
1613 | } | |
1614 | ||
1615 | void SeekToLast(KeyValueDB::WholeSpaceIterator iter) { | |
1616 | // expected: iterator is invalid | |
1617 | iter->seek_to_last(); | |
1618 | ASSERT_FALSE(iter->valid()); | |
1619 | } | |
1620 | ||
1621 | void SeekToLastWithPrefix(KeyValueDB::WholeSpaceIterator iter) { | |
1622 | // expected: iterator is invalid | |
1623 | iter->seek_to_last("prefix"); | |
1624 | ASSERT_FALSE(iter->valid()); | |
1625 | } | |
1626 | ||
1627 | void LowerBound(KeyValueDB::WholeSpaceIterator iter) { | |
1628 | // expected: iterator is invalid | |
1629 | iter->lower_bound("prefix", ""); | |
1630 | ASSERT_FALSE(iter->valid()); | |
1631 | ||
1632 | // expected: iterator is invalid | |
1633 | iter->lower_bound("", "key"); | |
1634 | ASSERT_FALSE(iter->valid()); | |
1635 | ||
1636 | // expected: iterator is invalid | |
1637 | iter->lower_bound("prefix", "key"); | |
1638 | ASSERT_FALSE(iter->valid()); | |
1639 | } | |
1640 | ||
1641 | void UpperBound(KeyValueDB::WholeSpaceIterator iter) { | |
1642 | // expected: iterator is invalid | |
1643 | iter->upper_bound("prefix", ""); | |
1644 | ASSERT_FALSE(iter->valid()); | |
1645 | ||
1646 | // expected: iterator is invalid | |
1647 | iter->upper_bound("", "key"); | |
1648 | ASSERT_FALSE(iter->valid()); | |
1649 | ||
1650 | // expected: iterator is invalid | |
1651 | iter->upper_bound("prefix", "key"); | |
1652 | ASSERT_FALSE(iter->valid()); | |
1653 | } | |
1654 | }; | |
1655 | ||
1656 | TEST_F(EmptyStore, SeekToFirstLevelDB) | |
1657 | { | |
1658 | SCOPED_TRACE("LevelDB: Empty Store, Seek To First"); | |
1659 | SeekToFirst(db->get_iterator()); | |
1660 | ASSERT_FALSE(HasFatalFailure()); | |
1661 | } | |
1662 | ||
1663 | TEST_F(EmptyStore, SeekToFirstMockDB) | |
1664 | { | |
1665 | SCOPED_TRACE("MockDB: Empty Store, Seek To First"); | |
1666 | SeekToFirst(mock->get_iterator()); | |
1667 | ASSERT_FALSE(HasFatalFailure()); | |
1668 | } | |
1669 | ||
1670 | TEST_F(EmptyStore, SeekToFirstWithPrefixLevelDB) | |
1671 | { | |
1672 | SCOPED_TRACE("LevelDB: Empty Store, Seek To First With Prefix"); | |
1673 | SeekToFirstWithPrefix(db->get_iterator()); | |
1674 | ASSERT_FALSE(HasFatalFailure()); | |
1675 | } | |
1676 | ||
1677 | TEST_F(EmptyStore, SeekToFirstWithPrefixMockDB) | |
1678 | { | |
1679 | SCOPED_TRACE("MockDB: Empty Store, Seek To First With Prefix"); | |
1680 | SeekToFirstWithPrefix(mock->get_iterator()); | |
1681 | ASSERT_FALSE(HasFatalFailure()); | |
1682 | } | |
1683 | ||
1684 | TEST_F(EmptyStore, SeekToLastLevelDB) | |
1685 | { | |
1686 | SCOPED_TRACE("LevelDB: Empty Store, Seek To Last"); | |
1687 | SeekToLast(db->get_iterator()); | |
1688 | ASSERT_FALSE(HasFatalFailure()); | |
1689 | } | |
1690 | ||
1691 | TEST_F(EmptyStore, SeekToLastMockDB) | |
1692 | { | |
1693 | SCOPED_TRACE("MockDB: Empty Store, Seek To Last"); | |
1694 | SeekToLast(mock->get_iterator()); | |
1695 | ASSERT_FALSE(HasFatalFailure()); | |
1696 | } | |
1697 | ||
1698 | TEST_F(EmptyStore, SeekToLastWithPrefixLevelDB) | |
1699 | { | |
1700 | SCOPED_TRACE("LevelDB: Empty Store, Seek To Last With Prefix"); | |
1701 | SeekToLastWithPrefix(db->get_iterator()); | |
1702 | ASSERT_FALSE(HasFatalFailure()); | |
1703 | } | |
1704 | ||
1705 | TEST_F(EmptyStore, SeekToLastWithPrefixMockDB) | |
1706 | { | |
1707 | SCOPED_TRACE("MockDB: Empty Store, Seek To Last With Prefix"); | |
1708 | SeekToLastWithPrefix(mock->get_iterator()); | |
1709 | ASSERT_FALSE(HasFatalFailure()); | |
1710 | } | |
1711 | ||
1712 | TEST_F(EmptyStore, LowerBoundLevelDB) | |
1713 | { | |
1714 | SCOPED_TRACE("LevelDB: Empty Store, Lower Bound"); | |
1715 | LowerBound(db->get_iterator()); | |
1716 | ASSERT_FALSE(HasFatalFailure()); | |
1717 | } | |
1718 | ||
1719 | TEST_F(EmptyStore, LowerBoundMockDB) | |
1720 | { | |
1721 | SCOPED_TRACE("MockDB: Empty Store, Lower Bound"); | |
1722 | LowerBound(mock->get_iterator()); | |
1723 | ASSERT_FALSE(HasFatalFailure()); | |
1724 | } | |
1725 | ||
1726 | TEST_F(EmptyStore, UpperBoundLevelDB) | |
1727 | { | |
1728 | SCOPED_TRACE("LevelDB: Empty Store, Upper Bound"); | |
1729 | UpperBound(db->get_iterator()); | |
1730 | ASSERT_FALSE(HasFatalFailure()); | |
1731 | } | |
1732 | ||
1733 | TEST_F(EmptyStore, UpperBoundMockDB) | |
1734 | { | |
1735 | SCOPED_TRACE("MockDB: Empty Store, Upper Bound"); | |
1736 | UpperBound(mock->get_iterator()); | |
1737 | ASSERT_FALSE(HasFatalFailure()); | |
1738 | } | |
1739 | ||
1740 | ||
1741 | int main(int argc, char *argv[]) | |
1742 | { | |
1743 | vector<const char*> args; | |
1744 | argv_to_vec(argc, (const char **) argv, args); | |
1745 | ||
1746 | auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); | |
1747 | common_init_finish(g_ceph_context); | |
1748 | ::testing::InitGoogleTest(&argc, argv); | |
1749 | ||
1750 | if (argc < 2) { | |
1751 | std::cerr << "Usage: " << argv[0] | |
1752 | << "[ceph_options] [gtest_options] <store_path>" << std::endl; | |
1753 | return 1; | |
1754 | } | |
1755 | store_path = string(argv[1]); | |
1756 | ||
1757 | return RUN_ALL_TESTS(); | |
1758 | } |