@@ -278,6 +278,107 @@ testfind(int size)
278
278
}
279
279
}
280
280
281
+ /*
282
+ * Check the correctness of the rbt_find_less() and rbt_find_great() functions
283
+ * by searching for an equal key and iterating the lesser keys then the greater
284
+ * keys.
285
+ */
286
+ static void
287
+ testfindltgt (int size )
288
+ {
289
+ RBTree * tree = create_int_rbtree ();
290
+
291
+ /*
292
+ * Using the size as the random key to search wouldn't allow us to get at
293
+ * least one greater match, so we do size - 1
294
+ */
295
+ int randomKey = pg_prng_uint64_range (& pg_global_prng_state , 0 , size - 1 );
296
+ bool keyDeleted ;
297
+ IntRBTreeNode searchNode = {.key = randomKey };
298
+ IntRBTreeNode * lteNode ;
299
+ IntRBTreeNode * gteNode ;
300
+ IntRBTreeNode * node ;
301
+
302
+ /* Insert natural numbers */
303
+ rbt_populate (tree , size , 1 );
304
+
305
+ /*
306
+ * Since the search key is included in the naturals of the tree, we're
307
+ * sure to find an equal match
308
+ */
309
+ lteNode = (IntRBTreeNode * ) rbt_find_less (tree , (RBTNode * ) & searchNode , true);
310
+ gteNode = (IntRBTreeNode * ) rbt_find_great (tree , (RBTNode * ) & searchNode , true);
311
+
312
+ if (lteNode == NULL || lteNode -> key != searchNode .key )
313
+ elog (ERROR , "rbt_find_less() didn't find the equal key" );
314
+
315
+ if (gteNode == NULL || gteNode -> key != searchNode .key )
316
+ elog (ERROR , "rbt_find_great() didn't find the equal key" );
317
+
318
+ if (lteNode != gteNode )
319
+ elog (ERROR , "rbt_find_less() and rbt_find_great() found different equal keys" );
320
+
321
+ /* Find the rest of the naturals lesser than the search key */
322
+ keyDeleted = false;
323
+ for (; searchNode .key > 0 ; searchNode .key -- )
324
+ {
325
+ /*
326
+ * Find the next key. If the current key is deleted, we can pass
327
+ * equal_match == true and still find the next one.
328
+ */
329
+ node = (IntRBTreeNode * ) rbt_find_less (tree , (RBTNode * ) & searchNode ,
330
+ keyDeleted );
331
+
332
+ /* ensure we find a lesser match */
333
+ if (!node || !(node -> key < searchNode .key ))
334
+ elog (ERROR , "rbt_find_less() didn't find a lesser key" );
335
+
336
+ /* randomly delete the found key or leave it */
337
+ keyDeleted = (pg_prng_uint64_range (& pg_global_prng_state , 0 , 1 ) == 1 );
338
+ if (keyDeleted )
339
+ rbt_delete (tree , (RBTNode * ) node );
340
+ }
341
+
342
+ /* Find the rest of the naturals greater than the search key */
343
+ keyDeleted = false;
344
+ for (searchNode .key = randomKey ; searchNode .key < size - 1 ; searchNode .key ++ )
345
+ {
346
+ /*
347
+ * Find the next key. If the current key is deleted, we can pass
348
+ * equal_match == true and still find the next one.
349
+ */
350
+ node = (IntRBTreeNode * ) rbt_find_great (tree , (RBTNode * ) & searchNode ,
351
+ keyDeleted );
352
+
353
+ /* ensure we find a greater match */
354
+ if (!node || !(node -> key > searchNode .key ))
355
+ elog (ERROR , "rbt_find_great() didn't find a greater key" );
356
+
357
+ /* randomly delete the found key or leave it */
358
+ keyDeleted = (pg_prng_uint64_range (& pg_global_prng_state , 0 , 1 ) == 1 );
359
+ if (keyDeleted )
360
+ rbt_delete (tree , (RBTNode * ) node );
361
+ }
362
+
363
+ /* Check out of bounds searches find nothing */
364
+ searchNode .key = -1 ;
365
+ node = (IntRBTreeNode * ) rbt_find_less (tree , (RBTNode * ) & searchNode , true);
366
+ if (node != NULL )
367
+ elog (ERROR , "rbt_find_less() found non-inserted element" );
368
+ searchNode .key = 0 ;
369
+ node = (IntRBTreeNode * ) rbt_find_less (tree , (RBTNode * ) & searchNode , false);
370
+ if (node != NULL )
371
+ elog (ERROR , "rbt_find_less() found non-inserted element" );
372
+ searchNode .key = size ;
373
+ node = (IntRBTreeNode * ) rbt_find_great (tree , (RBTNode * ) & searchNode , true);
374
+ if (node != NULL )
375
+ elog (ERROR , "rbt_find_great() found non-inserted element" );
376
+ searchNode .key = size - 1 ;
377
+ node = (IntRBTreeNode * ) rbt_find_great (tree , (RBTNode * ) & searchNode , false);
378
+ if (node != NULL )
379
+ elog (ERROR , "rbt_find_great() found non-inserted element" );
380
+ }
381
+
281
382
/*
282
383
* Check the correctness of the rbt_leftmost operation.
283
384
* This operation should always return the smallest element of the tree.
@@ -408,6 +509,7 @@ test_rb_tree(PG_FUNCTION_ARGS)
408
509
testleftright (size );
409
510
testrightleft (size );
410
511
testfind (size );
512
+ testfindltgt (size );
411
513
testleftmost (size );
412
514
testdelete (size , Max (size / 10 , 1 ));
413
515
PG_RETURN_VOID ();
0 commit comments