1 // sorted_data_interface_test_cursor_locate.cpp
2
3
4 /**
5 * Copyright (C) 2018-present MongoDB, Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the Server Side Public License, version 1,
9 * as published by MongoDB, Inc.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * Server Side Public License for more details.
15 *
16 * You should have received a copy of the Server Side Public License
17 * along with this program. If not, see
18 * <http://www.mongodb.com/licensing/server-side-public-license>.
19 *
20 * As a special exception, the copyright holders give permission to link the
21 * code of portions of this program with the OpenSSL library under certain
22 * conditions as described in each individual source file and distribute
23 * linked combinations including the program with the OpenSSL library. You
24 * must comply with the Server Side Public License in all respects for
25 * all of the code used other than as permitted herein. If you modify file(s)
26 * with this exception, you may extend this exception to your version of the
27 * file(s), but you are not obligated to do so. If you do not wish to do so,
28 * delete this exception statement from your version. If you delete this
29 * exception statement from all source files in the program, then also delete
30 * it in the license file.
31 */
32
33 #include "mongo/db/storage/sorted_data_interface_test_harness.h"
34
35 #include <memory>
36
37 #include "mongo/db/storage/sorted_data_interface.h"
38 #include "mongo/unittest/unittest.h"
39
40 namespace mongo {
41 namespace {
42
43 // Insert a key and try to locate it using a forward cursor
44 // by specifying its exact key and RecordId.
TEST(SortedDataInterface,Locate)45 TEST(SortedDataInterface, Locate) {
46 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
47 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
48
49 {
50 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
51 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
52 ASSERT(!cursor->seek(key1, true));
53 }
54
55 {
56 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
57 {
58 WriteUnitOfWork uow(opCtx.get());
59 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
60 uow.commit();
61 }
62 }
63
64 {
65 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
66 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
67
68 ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1));
69 ASSERT_EQ(cursor->next(), boost::none);
70 }
71 }
72
73 // Insert a key and try to locate it using a reverse cursor
74 // by specifying its exact key and RecordId.
TEST(SortedDataInterface,LocateReversed)75 TEST(SortedDataInterface, LocateReversed) {
76 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
77 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
78
79 {
80 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
81 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
82 sorted->newCursor(opCtx.get(), false));
83 ASSERT(!cursor->seek(key1, true));
84 }
85
86 {
87 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
88 {
89 WriteUnitOfWork uow(opCtx.get());
90 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
91 uow.commit();
92 }
93 }
94
95 {
96 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
97 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
98 sorted->newCursor(opCtx.get(), false));
99
100 ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1));
101 ASSERT_EQ(cursor->next(), boost::none);
102 }
103 }
104
105 // Insert a compound key and try to locate it using a forward cursor
106 // by specifying its exact key and RecordId.
TEST(SortedDataInterface,LocateCompoundKey)107 TEST(SortedDataInterface, LocateCompoundKey) {
108 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
109 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
110
111 {
112 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
113 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
114 ASSERT(!cursor->seek(compoundKey1a, true));
115 }
116
117 {
118 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
119 {
120 WriteUnitOfWork uow(opCtx.get());
121 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
122 uow.commit();
123 }
124 }
125
126 {
127 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
128 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
129
130 ASSERT_EQ(cursor->seek(compoundKey1a, true), IndexKeyEntry(compoundKey1a, loc1));
131 ASSERT_EQ(cursor->next(), boost::none);
132 }
133 }
134
135 // Insert a compound key and try to locate it using a reverse cursor
136 // by specifying its exact key and RecordId.
TEST(SortedDataInterface,LocateCompoundKeyReversed)137 TEST(SortedDataInterface, LocateCompoundKeyReversed) {
138 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
139 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
140
141 {
142 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
143 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
144 sorted->newCursor(opCtx.get(), false));
145 ASSERT(!cursor->seek(compoundKey1a, true));
146 }
147
148 {
149 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
150 {
151 WriteUnitOfWork uow(opCtx.get());
152 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
153 uow.commit();
154 }
155 }
156
157 {
158 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
159 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
160 sorted->newCursor(opCtx.get(), false));
161
162 ASSERT_EQ(cursor->seek(compoundKey1a, true), IndexKeyEntry(compoundKey1a, loc1));
163 ASSERT_EQ(cursor->next(), boost::none);
164 }
165 }
166
167 // Insert multiple keys and try to locate them using a forward cursor
168 // by specifying their exact key and RecordId.
TEST(SortedDataInterface,LocateMultiple)169 TEST(SortedDataInterface, LocateMultiple) {
170 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
171 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
172
173 {
174 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
175 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
176 ASSERT(!cursor->seek(key1, true));
177 }
178
179 {
180 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
181 {
182 WriteUnitOfWork uow(opCtx.get());
183 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
184 ASSERT_OK(sorted->insert(opCtx.get(), key2, loc2, true));
185 uow.commit();
186 }
187 }
188
189 {
190 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
191 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
192
193 ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1));
194 ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc2));
195 ASSERT_EQ(cursor->next(), boost::none);
196 }
197
198 {
199 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
200 {
201 WriteUnitOfWork uow(opCtx.get());
202 ASSERT_OK(sorted->insert(opCtx.get(), key3, loc3, true));
203 uow.commit();
204 }
205 }
206
207 {
208 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
209 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
210
211 ASSERT_EQ(cursor->seek(key2, true), IndexKeyEntry(key2, loc2));
212 ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc3));
213 ASSERT_EQ(cursor->next(), boost::none);
214
215 ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1));
216 ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc2));
217 ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc3));
218 ASSERT_EQ(cursor->next(), boost::none);
219 }
220 }
221
222 // Insert multiple keys and try to locate them using a reverse cursor
223 // by specifying their exact key and RecordId.
TEST(SortedDataInterface,LocateMultipleReversed)224 TEST(SortedDataInterface, LocateMultipleReversed) {
225 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
226 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
227
228 {
229 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
230 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
231 sorted->newCursor(opCtx.get(), false));
232 ASSERT(!cursor->seek(key3, true));
233 }
234
235 {
236 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
237 {
238 WriteUnitOfWork uow(opCtx.get());
239 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
240 ASSERT_OK(sorted->insert(opCtx.get(), key2, loc2, true));
241 uow.commit();
242 }
243 }
244
245 {
246 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
247 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
248 sorted->newCursor(opCtx.get(), false));
249
250 ASSERT_EQ(cursor->seek(key2, true), IndexKeyEntry(key2, loc2));
251 ASSERT_EQ(cursor->next(), IndexKeyEntry(key1, loc1));
252 ASSERT_EQ(cursor->next(), boost::none);
253 }
254
255 {
256 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
257 {
258 WriteUnitOfWork uow(opCtx.get());
259 ASSERT_OK(sorted->insert(opCtx.get(), key3, loc3, true));
260 uow.commit();
261 }
262 }
263
264 {
265 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
266 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
267 sorted->newCursor(opCtx.get(), false));
268
269 ASSERT_EQ(cursor->seek(key2, true), IndexKeyEntry(key2, loc2));
270 ASSERT_EQ(cursor->next(), IndexKeyEntry(key1, loc1));
271 ASSERT_EQ(cursor->next(), boost::none);
272
273 ASSERT_EQ(cursor->seek(key3, true), IndexKeyEntry(key3, loc3));
274 ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc2));
275 ASSERT_EQ(cursor->next(), IndexKeyEntry(key1, loc1));
276 ASSERT_EQ(cursor->next(), boost::none);
277 }
278 }
279
280 // Insert multiple compound keys and try to locate them using a forward cursor
281 // by specifying their exact key and RecordId.
TEST(SortedDataInterface,LocateMultipleCompoundKeys)282 TEST(SortedDataInterface, LocateMultipleCompoundKeys) {
283 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
284 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
285
286 {
287 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
288 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
289 ASSERT(!cursor->seek(compoundKey1a, true));
290 }
291
292 {
293 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
294 {
295 WriteUnitOfWork uow(opCtx.get());
296 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
297 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1b, loc2, true));
298 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey2b, loc3, true));
299 uow.commit();
300 }
301 }
302
303 {
304 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
305 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
306
307 ASSERT_EQ(cursor->seek(compoundKey1a, true), IndexKeyEntry(compoundKey1a, loc1));
308 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1b, loc2));
309 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey2b, loc3));
310 ASSERT_EQ(cursor->next(), boost::none);
311 }
312
313 {
314 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
315 {
316 WriteUnitOfWork uow(opCtx.get());
317 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1c, loc4, true));
318 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey3a, loc5, true));
319 uow.commit();
320 }
321 }
322
323 {
324 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
325 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
326
327 ASSERT_EQ(cursor->seek(compoundKey1a, true), IndexKeyEntry(compoundKey1a, loc1));
328 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1b, loc2));
329 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1c, loc4));
330 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey2b, loc3));
331 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey3a, loc5));
332 ASSERT_EQ(cursor->next(), boost::none);
333 }
334 }
335
336 // Insert multiple compound keys and try to locate them using a reverse cursor
337 // by specifying their exact key and RecordId.
TEST(SortedDataInterface,LocateMultipleCompoundKeysReversed)338 TEST(SortedDataInterface, LocateMultipleCompoundKeysReversed) {
339 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
340 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
341
342 {
343 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
344 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
345 sorted->newCursor(opCtx.get(), false));
346 ASSERT(!cursor->seek(compoundKey3a, true));
347 }
348
349 {
350 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
351 {
352 WriteUnitOfWork uow(opCtx.get());
353 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
354 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1b, loc2, true));
355 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey2b, loc3, true));
356 uow.commit();
357 }
358 }
359
360 {
361 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
362 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
363 sorted->newCursor(opCtx.get(), false));
364
365 ASSERT_EQ(cursor->seek(compoundKey2b, true), IndexKeyEntry(compoundKey2b, loc3));
366 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1b, loc2));
367 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1a, loc1));
368 ASSERT_EQ(cursor->next(), boost::none);
369 }
370
371 {
372 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
373 {
374 WriteUnitOfWork uow(opCtx.get());
375 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1c, loc4, true));
376 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey3a, loc5, true));
377 uow.commit();
378 }
379 }
380
381 {
382 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
383 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
384 sorted->newCursor(opCtx.get(), false));
385
386 ASSERT_EQ(cursor->seek(compoundKey3a, true), IndexKeyEntry(compoundKey3a, loc5));
387 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey2b, loc3));
388 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1c, loc4));
389 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1b, loc2));
390 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1a, loc1));
391 ASSERT_EQ(cursor->next(), boost::none);
392 }
393 }
394
395 // Insert multiple keys and try to locate them using a forward cursor
396 // by specifying either a smaller key or RecordId.
TEST(SortedDataInterface,LocateIndirect)397 TEST(SortedDataInterface, LocateIndirect) {
398 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
399 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
400
401 {
402 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
403 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
404 ASSERT(!cursor->seek(key1, true));
405 }
406
407 {
408 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
409 {
410 WriteUnitOfWork uow(opCtx.get());
411 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
412 ASSERT_OK(sorted->insert(opCtx.get(), key2, loc2, true));
413 uow.commit();
414 }
415 }
416
417 {
418 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
419 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
420
421 ASSERT_EQ(cursor->seek(key1, false), IndexKeyEntry(key2, loc2));
422 ASSERT_EQ(cursor->next(), boost::none);
423 }
424
425 {
426 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
427 {
428 WriteUnitOfWork uow(opCtx.get());
429 ASSERT_OK(sorted->insert(opCtx.get(), key3, loc3, true));
430 uow.commit();
431 }
432 }
433
434 {
435 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
436 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
437
438 ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1));
439 ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc2));
440 ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc3));
441 ASSERT_EQ(cursor->next(), boost::none);
442 }
443 }
444
445 // Insert multiple keys and try to locate them using a reverse cursor
446 // by specifying either a larger key or RecordId.
TEST(SortedDataInterface,LocateIndirectReversed)447 TEST(SortedDataInterface, LocateIndirectReversed) {
448 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
449 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
450
451 {
452 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
453 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
454 sorted->newCursor(opCtx.get(), false));
455 ASSERT(!cursor->seek(key3, true));
456 }
457
458 {
459 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
460 {
461 WriteUnitOfWork uow(opCtx.get());
462 ASSERT_OK(sorted->insert(opCtx.get(), key1, loc1, true));
463 ASSERT_OK(sorted->insert(opCtx.get(), key2, loc2, true));
464 uow.commit();
465 }
466 }
467
468 {
469 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
470 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
471 sorted->newCursor(opCtx.get(), false));
472
473 ASSERT_EQ(cursor->seek(key2, false), IndexKeyEntry(key1, loc1));
474 ASSERT_EQ(cursor->next(), boost::none);
475 }
476
477 {
478 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
479 {
480 WriteUnitOfWork uow(opCtx.get());
481 ASSERT_OK(sorted->insert(opCtx.get(), key3, loc3, true));
482 uow.commit();
483 }
484 }
485
486 {
487 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
488 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
489 sorted->newCursor(opCtx.get(), false));
490
491 ASSERT_EQ(cursor->seek(key3, true), IndexKeyEntry(key3, loc3));
492 ASSERT_EQ(cursor->next(), IndexKeyEntry(key2, loc2));
493 ASSERT_EQ(cursor->next(), IndexKeyEntry(key1, loc1));
494 ASSERT_EQ(cursor->next(), boost::none);
495 }
496 }
497
498 // Insert multiple compound keys and try to locate them using a forward cursor
499 // by specifying either a smaller key or RecordId.
TEST(SortedDataInterface,LocateIndirectCompoundKeys)500 TEST(SortedDataInterface, LocateIndirectCompoundKeys) {
501 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
502 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
503
504 {
505 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
506 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
507 ASSERT(!cursor->seek(compoundKey1a, true));
508 }
509
510 {
511 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
512 {
513 WriteUnitOfWork uow(opCtx.get());
514 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
515 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1b, loc2, true));
516 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey2b, loc3, true));
517 uow.commit();
518 }
519 }
520
521 {
522 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
523 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
524
525 ASSERT_EQ(cursor->seek(compoundKey1a, false), IndexKeyEntry(compoundKey1b, loc2));
526 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey2b, loc3));
527 ASSERT_EQ(cursor->next(), boost::none);
528 }
529
530 {
531 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
532 {
533 WriteUnitOfWork uow(opCtx.get());
534 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1c, loc4, true));
535 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey3a, loc5, true));
536 uow.commit();
537 }
538 }
539
540 {
541 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
542 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
543
544 ASSERT_EQ(cursor->seek(compoundKey2a, true), IndexKeyEntry(compoundKey2b, loc3));
545 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey3a, loc5));
546 ASSERT_EQ(cursor->next(), boost::none);
547 }
548 }
549
550 // Insert multiple compound keys and try to locate them using a reverse cursor
551 // by specifying either a larger key or RecordId.
TEST(SortedDataInterface,LocateIndirectCompoundKeysReversed)552 TEST(SortedDataInterface, LocateIndirectCompoundKeysReversed) {
553 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
554 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
555
556 {
557 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
558 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
559 sorted->newCursor(opCtx.get(), false));
560 ASSERT(!cursor->seek(compoundKey3a, true));
561 }
562
563 {
564 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
565 {
566 WriteUnitOfWork uow(opCtx.get());
567 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1a, loc1, true));
568 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1b, loc2, true));
569 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey2b, loc3, true));
570 uow.commit();
571 }
572 }
573
574 {
575 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
576 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
577 sorted->newCursor(opCtx.get(), false));
578
579 ASSERT_EQ(cursor->seek(compoundKey2b, false), IndexKeyEntry(compoundKey1b, loc2));
580 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1a, loc1));
581 ASSERT_EQ(cursor->next(), boost::none);
582 }
583
584 {
585 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
586 {
587 WriteUnitOfWork uow(opCtx.get());
588 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey1c, loc4, true));
589 ASSERT_OK(sorted->insert(opCtx.get(), compoundKey3a, loc5, true));
590 uow.commit();
591 }
592 }
593
594 {
595 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
596 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
597 sorted->newCursor(opCtx.get(), false));
598
599 ASSERT_EQ(cursor->seek(compoundKey1d, true), IndexKeyEntry(compoundKey1c, loc4));
600 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1b, loc2));
601 ASSERT_EQ(cursor->next(), IndexKeyEntry(compoundKey1a, loc1));
602 ASSERT_EQ(cursor->next(), boost::none);
603 }
604 }
605
606 // Call locate on a forward cursor of an empty index and verify that the cursor
607 // is positioned at EOF.
TEST(SortedDataInterface,LocateEmpty)608 TEST(SortedDataInterface, LocateEmpty) {
609 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
610 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
611
612 {
613 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
614 ASSERT(sorted->isEmpty(opCtx.get()));
615 }
616
617 {
618 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
619 const std::unique_ptr<SortedDataInterface::Cursor> cursor(sorted->newCursor(opCtx.get()));
620
621 ASSERT(!cursor->seek(BSONObj(), true));
622 ASSERT(!cursor->next());
623 }
624 }
625
626 // Call locate on a reverse cursor of an empty index and verify that the cursor
627 // is positioned at EOF.
TEST(SortedDataInterface,LocateEmptyReversed)628 TEST(SortedDataInterface, LocateEmptyReversed) {
629 const auto harnessHelper(newSortedDataInterfaceHarnessHelper());
630 const std::unique_ptr<SortedDataInterface> sorted(harnessHelper->newSortedDataInterface(false));
631
632 {
633 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
634 ASSERT(sorted->isEmpty(opCtx.get()));
635 }
636
637 {
638 const ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
639 const std::unique_ptr<SortedDataInterface::Cursor> cursor(
640 sorted->newCursor(opCtx.get(), false));
641
642 ASSERT(!cursor->seek(BSONObj(), true));
643 ASSERT(!cursor->next());
644 }
645 }
646
647 } // namespace
648 } // namespace mongo
649