@@ -193,5 +193,96 @@ TEST_F(BasicKVTest, BasicKVInsertDuplicatedKey) {
193
193
}
194
194
});
195
195
}
196
+ TEST_F (BasicKVTest, BasicKVScanAscAndScanDesc) {
197
+ storage::btree::BasicKV* btree;
198
+ // prepare key-value pairs to insert
199
+ size_t numKVs (10 );
200
+ std::vector<std::tuple<std::string, std::string>> kvToTest;
201
+ const auto keySize = sizeof (size_t );
202
+ uint8_t keyBuffer[keySize];
203
+ for (size_t i = 0 ; i < numKVs; ++i) {
204
+ utils::Fold (keyBuffer, i);
205
+ std::string key (" key_btree_LL_xxxxxxxxxxxx_" +
206
+ std::string (reinterpret_cast <char *>(keyBuffer), keySize));
207
+ std::string val (" VAL_BTREE_LL_YYYYYYYYYYYY_" +
208
+ std::string (reinterpret_cast <char *>(keyBuffer), keySize));
209
+ kvToTest.push_back (std::make_tuple (key, val));
210
+ }
211
+
212
+ // create leanstore btree for table records
213
+ auto * curTest = ::testing::UnitTest::GetInstance ()->current_test_info ();
214
+ auto btreeName = std::string (curTest->test_case_name ()) + " _" + std::string (curTest->name ());
215
+
216
+ mStore ->ExecSync (0 , [&]() {
217
+ auto res = mStore ->CreateBasicKV (btreeName);
218
+ EXPECT_TRUE (res);
219
+ EXPECT_NE (res.value (), nullptr );
220
+
221
+ btree = res.value ();
222
+ for (size_t i = 0 ; i < numKVs; ++i) {
223
+ const auto & [key, val] = kvToTest[i];
224
+ EXPECT_EQ (btree->Insert (Slice (key), Slice (val)), OpCode::kOK );
225
+ }
226
+
227
+ std::vector<std::tuple<std::string, std::string>> copiedKeyValue;
228
+ auto copyKeyAndValueOut = [&](Slice key, Slice val) {
229
+ copiedKeyValue.emplace_back (key.ToString (), val.ToString ());
230
+ return true ;
231
+ };
232
+
233
+ size_t startIndex = 5 ;
234
+ auto startKey = Slice (std::get<0 >(kvToTest[startIndex]));
235
+ auto callbackReturnFalse = [&]([[maybe_unused]] Slice key, [[maybe_unused]] Slice val) {
236
+ return false ;
237
+ };
238
+
239
+ // ScanAsc
240
+ {
241
+ // no bigger than largestLexicographicalOrderKey in ScanAsc should return OpCode::kNotFound
242
+ Slice largestLexicographicalOrderKey (" zzzzzzz" );
243
+ EXPECT_EQ (btree->ScanAsc (largestLexicographicalOrderKey, copyKeyAndValueOut),
244
+ OpCode::kNotFound );
245
+ EXPECT_EQ (btree->ScanAsc (largestLexicographicalOrderKey, callbackReturnFalse),
246
+ OpCode::kNotFound );
196
247
248
+ // callback return false should terminate scan
249
+ EXPECT_EQ (btree->ScanAsc (startKey, callbackReturnFalse), OpCode::kOK );
250
+
251
+ // query on ScanAsc
252
+ EXPECT_EQ (btree->ScanAsc (startKey, copyKeyAndValueOut), OpCode::kOK );
253
+ EXPECT_EQ (copiedKeyValue.size (), 5 );
254
+ for (size_t i = startIndex, j = 0 ; i < numKVs && j < copiedKeyValue.size (); i++, j++) {
255
+ const auto & [key, expectedVal] = kvToTest[i];
256
+ const auto & [copiedKey, copiedValue] = copiedKeyValue[j];
257
+ EXPECT_EQ (copiedKey, key);
258
+ EXPECT_EQ (copiedValue, expectedVal);
259
+ }
260
+ }
261
+
262
+ // ScanDesc
263
+ {
264
+ // no smaller than key in ScanDesc should return OpCode::kNotFound
265
+ Slice smallestLexicographicalOrderKey (" aaaaaaaa" );
266
+ EXPECT_EQ (btree->ScanDesc (smallestLexicographicalOrderKey, copyKeyAndValueOut),
267
+ OpCode::kNotFound );
268
+ EXPECT_EQ (btree->ScanDesc (smallestLexicographicalOrderKey, callbackReturnFalse),
269
+ OpCode::kNotFound );
270
+
271
+ // callback return false should terminate scan
272
+ EXPECT_EQ (btree->ScanDesc (startKey, callbackReturnFalse), OpCode::kOK );
273
+
274
+ // query on ScanDesc
275
+ copiedKeyValue.clear ();
276
+ EXPECT_EQ (btree->ScanDesc (startKey, copyKeyAndValueOut), OpCode::kOK );
277
+ EXPECT_EQ (copiedKeyValue.size (), 6 );
278
+ for (int i = startIndex, j = 0 ; i >= 0 && j < static_cast <int >(copiedKeyValue.size ());
279
+ i--, j++) {
280
+ const auto & [key, expectedVal] = kvToTest[i];
281
+ const auto & [copiedKey, copiedValue] = copiedKeyValue[j];
282
+ EXPECT_EQ (copiedKey, key);
283
+ EXPECT_EQ (copiedValue, expectedVal);
284
+ }
285
+ }
286
+ });
287
+ }
197
288
} // namespace leanstore::test
0 commit comments