LCOV - differential code coverage report
Current view: top level - src/test/modules/test_rbtree - test_rbtree.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 84.5 % 200 169 9 2 6 14 6 28 38 97 11 70
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 16 16 4 1 11 5
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 84.5 % 200 169 9 2 6 14 6 28 38 97 5 28
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 84.2 % 19 16 4 1 11 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*--------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * test_rbtree.c
                                  4                 :  *      Test correctness of red-black tree operations.
                                  5                 :  *
                                  6                 :  * Copyright (c) 2009-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  * IDENTIFICATION
                                  9                 :  *      src/test/modules/test_rbtree/test_rbtree.c
                                 10                 :  *
                                 11                 :  * -------------------------------------------------------------------------
                                 12                 :  */
                                 13                 : 
                                 14                 : #include "postgres.h"
                                 15                 : 
                                 16                 : #include "common/pg_prng.h"
                                 17                 : #include "fmgr.h"
                                 18                 : #include "lib/rbtree.h"
                                 19                 : #include "utils/memutils.h"
                                 20                 : 
 2037 tgl                        21 CBC           1 : PG_MODULE_MAGIC;
                                 22                 : 
                                 23                 : 
                                 24                 : /*
                                 25                 :  * Our test trees store an integer key, and nothing else.
                                 26                 :  */
                                 27                 : typedef struct IntRBTreeNode
                                 28                 : {
                                 29                 :     RBTNode     rbtnode;
                                 30                 :     int         key;
                                 31                 : } IntRBTreeNode;
                                 32                 : 
                                 33                 : 
                                 34                 : /*
                                 35                 :  * Node comparator.  We don't worry about overflow in the subtraction,
                                 36                 :  * since none of our test keys are negative.
                                 37                 :  */
                                 38                 : static int
 1615                            39         1337692 : irbt_cmp(const RBTNode *a, const RBTNode *b, void *arg)
                                 40                 : {
 2037                            41         1337692 :     const IntRBTreeNode *ea = (const IntRBTreeNode *) a;
                                 42         1337692 :     const IntRBTreeNode *eb = (const IntRBTreeNode *) b;
                                 43                 : 
                                 44         1337692 :     return ea->key - eb->key;
                                 45                 : }
                                 46                 : 
                                 47                 : /*
                                 48                 :  * Node combiner.  For testing purposes, just check that library doesn't
                                 49                 :  * try to combine unequal keys.
                                 50                 :  */
                                 51                 : static void
 1615                            52               6 : irbt_combine(RBTNode *existing, const RBTNode *newdata, void *arg)
                                 53                 : {
 2037                            54               6 :     const IntRBTreeNode *eexist = (const IntRBTreeNode *) existing;
                                 55               6 :     const IntRBTreeNode *enew = (const IntRBTreeNode *) newdata;
                                 56                 : 
                                 57               6 :     if (eexist->key != enew->key)
 2037 tgl                        58 UBC           0 :         elog(ERROR, "red-black tree combines %d into %d",
                                 59                 :              enew->key, eexist->key);
 2037 tgl                        60 CBC           6 : }
                                 61                 : 
                                 62                 : /* Node allocator */
                                 63                 : static RBTNode *
 1615                            64           60000 : irbt_alloc(void *arg)
                                 65                 : {
                                 66           60000 :     return (RBTNode *) palloc(sizeof(IntRBTreeNode));
                                 67                 : }
                                 68                 : 
                                 69                 : /* Node freer */
                                 70                 : static void
                                 71           14989 : irbt_free(RBTNode *node, void *arg)
                                 72                 : {
 2037                            73           14989 :     pfree(node);
                                 74           14989 : }
                                 75                 : 
                                 76                 : /*
                                 77                 :  * Create a red-black tree using our support functions
                                 78                 :  */
                                 79                 : static RBTree *
                                 80               6 : create_int_rbtree(void)
                                 81                 : {
 1615                            82               6 :     return rbt_create(sizeof(IntRBTreeNode),
                                 83                 :                       irbt_cmp,
                                 84                 :                       irbt_combine,
                                 85                 :                       irbt_alloc,
                                 86                 :                       irbt_free,
                                 87                 :                       NULL);
                                 88                 : }
                                 89                 : 
                                 90                 : /*
                                 91                 :  * Generate a random permutation of the integers 0..size-1
                                 92                 :  */
                                 93                 : static int *
 2037                            94               6 : GetPermutation(int size)
                                 95                 : {
                                 96                 :     int        *permutation;
                                 97                 :     int         i;
                                 98                 : 
                                 99               6 :     permutation = (int *) palloc(size * sizeof(int));
                                100                 : 
                                101               6 :     permutation[0] = 0;
                                102                 : 
                                103                 :     /*
                                104                 :      * This is the "inside-out" variant of the Fisher-Yates shuffle algorithm.
                                105                 :      * Notionally, we append each new value to the array and then swap it with
                                106                 :      * a randomly-chosen array element (possibly including itself, else we
                                107                 :      * fail to generate permutations with the last integer last).  The swap
                                108                 :      * step can be optimized by combining it with the insertion.
                                109                 :      */
                                110           60000 :     for (i = 1; i < size; i++)
                                111                 :     {
  497                           112           59994 :         int         j = pg_prng_uint64_range(&pg_global_prng_state, 0, i);
                                113                 : 
 2037                           114           59994 :         if (j < i)               /* avoid fetching undefined data if j=i */
                                115           59939 :             permutation[i] = permutation[j];
                                116           59994 :         permutation[j] = i;
                                117                 :     }
                                118                 : 
                                119               6 :     return permutation;
                                120                 : }
                                121                 : 
                                122                 : /*
                                123                 :  * Populate an empty RBTree with "size" integers having the values
                                124                 :  * 0, step, 2*step, 3*step, ..., inserting them in random order
                                125                 :  */
                                126                 : static void
 1615                           127               6 : rbt_populate(RBTree *tree, int size, int step)
                                128                 : {
 2037                           129               6 :     int        *permutation = GetPermutation(size);
                                130                 :     IntRBTreeNode node;
                                131                 :     bool        isNew;
                                132                 :     int         i;
                                133                 : 
                                134                 :     /* Insert values.  We don't expect any collisions. */
                                135           60006 :     for (i = 0; i < size; i++)
                                136                 :     {
                                137           60000 :         node.key = step * permutation[i];
 1615                           138           60000 :         rbt_insert(tree, (RBTNode *) &node, &isNew);
 2037                           139           60000 :         if (!isNew)
 1615 tgl                       140 UBC           0 :             elog(ERROR, "unexpected !isNew result from rbt_insert");
                                141                 :     }
                                142                 : 
                                143                 :     /*
                                144                 :      * Re-insert the first value to make sure collisions work right.  It's
                                145                 :      * probably not useful to test that case over again for all the values.
                                146                 :      */
 2037 tgl                       147 CBC           6 :     if (size > 0)
                                148                 :     {
                                149               6 :         node.key = step * permutation[0];
 1615                           150               6 :         rbt_insert(tree, (RBTNode *) &node, &isNew);
 2037                           151               6 :         if (isNew)
 1615 tgl                       152 UBC           0 :             elog(ERROR, "unexpected isNew result from rbt_insert");
                                153                 :     }
                                154                 : 
 2037 tgl                       155 CBC           6 :     pfree(permutation);
                                156               6 : }
                                157                 : 
                                158                 : /*
                                159                 :  * Check the correctness of left-right traversal.
                                160                 :  * Left-right traversal is correct if all elements are
                                161                 :  * visited in increasing order.
                                162                 :  */
                                163                 : static void
                                164               1 : testleftright(int size)
                                165                 : {
                                166               1 :     RBTree     *tree = create_int_rbtree();
                                167                 :     IntRBTreeNode *node;
                                168                 :     RBTreeIterator iter;
                                169               1 :     int         lastKey = -1;
                                170               1 :     int         count = 0;
                                171                 : 
                                172                 :     /* check iteration over empty tree */
 1615                           173               1 :     rbt_begin_iterate(tree, LeftRightWalk, &iter);
                                174               1 :     if (rbt_iterate(&iter) != NULL)
 2037 tgl                       175 UBC           0 :         elog(ERROR, "left-right walk over empty tree produced an element");
                                176                 : 
                                177                 :     /* fill tree with consecutive natural numbers */
 1615 tgl                       178 CBC           1 :     rbt_populate(tree, size, 1);
                                179                 : 
                                180                 :     /* iterate over the tree */
                                181               1 :     rbt_begin_iterate(tree, LeftRightWalk, &iter);
                                182                 : 
                                183           10001 :     while ((node = (IntRBTreeNode *) rbt_iterate(&iter)) != NULL)
                                184                 :     {
                                185                 :         /* check that order is increasing */
 2037                           186           10000 :         if (node->key <= lastKey)
 2037 tgl                       187 UBC           0 :             elog(ERROR, "left-right walk gives elements not in sorted order");
 2037 tgl                       188 CBC       10000 :         lastKey = node->key;
                                189           10000 :         count++;
                                190                 :     }
                                191                 : 
                                192               1 :     if (lastKey != size - 1)
 2037 tgl                       193 UBC           0 :         elog(ERROR, "left-right walk did not reach end");
 2037 tgl                       194 CBC           1 :     if (count != size)
 2037 tgl                       195 UBC           0 :         elog(ERROR, "left-right walk missed some elements");
 2037 tgl                       196 CBC           1 : }
                                197                 : 
                                198                 : /*
                                199                 :  * Check the correctness of right-left traversal.
                                200                 :  * Right-left traversal is correct if all elements are
                                201                 :  * visited in decreasing order.
                                202                 :  */
                                203                 : static void
                                204               1 : testrightleft(int size)
                                205                 : {
                                206               1 :     RBTree     *tree = create_int_rbtree();
                                207                 :     IntRBTreeNode *node;
                                208                 :     RBTreeIterator iter;
                                209               1 :     int         lastKey = size;
                                210               1 :     int         count = 0;
                                211                 : 
                                212                 :     /* check iteration over empty tree */
 1615                           213               1 :     rbt_begin_iterate(tree, RightLeftWalk, &iter);
                                214               1 :     if (rbt_iterate(&iter) != NULL)
 2037 tgl                       215 UBC           0 :         elog(ERROR, "right-left walk over empty tree produced an element");
                                216                 : 
                                217                 :     /* fill tree with consecutive natural numbers */
 1615 tgl                       218 CBC           1 :     rbt_populate(tree, size, 1);
                                219                 : 
                                220                 :     /* iterate over the tree */
                                221               1 :     rbt_begin_iterate(tree, RightLeftWalk, &iter);
                                222                 : 
                                223           10001 :     while ((node = (IntRBTreeNode *) rbt_iterate(&iter)) != NULL)
                                224                 :     {
                                225                 :         /* check that order is decreasing */
 2037                           226           10000 :         if (node->key >= lastKey)
 2037 tgl                       227 UBC           0 :             elog(ERROR, "right-left walk gives elements not in sorted order");
 2037 tgl                       228 CBC       10000 :         lastKey = node->key;
                                229           10000 :         count++;
                                230                 :     }
                                231                 : 
                                232               1 :     if (lastKey != 0)
 2037 tgl                       233 UBC           0 :         elog(ERROR, "right-left walk did not reach end");
 2037 tgl                       234 CBC           1 :     if (count != size)
 2037 tgl                       235 UBC           0 :         elog(ERROR, "right-left walk missed some elements");
 2037 tgl                       236 CBC           1 : }
                                237                 : 
                                238                 : /*
                                239                 :  * Check the correctness of the rbt_find operation by searching for
                                240                 :  * both elements we inserted and elements we didn't.
                                241                 :  */
                                242                 : static void
                                243               1 : testfind(int size)
                                244                 : {
                                245               1 :     RBTree     *tree = create_int_rbtree();
                                246                 :     int         i;
                                247                 : 
                                248                 :     /* Insert even integers from 0 to 2 * (size-1) */
 1615                           249               1 :     rbt_populate(tree, size, 2);
                                250                 : 
                                251                 :     /* Check that all inserted elements can be found */
 2037                           252           10001 :     for (i = 0; i < size; i++)
                                253                 :     {
                                254                 :         IntRBTreeNode node;
                                255                 :         IntRBTreeNode *resultNode;
                                256                 : 
                                257           10000 :         node.key = 2 * i;
 1615                           258           10000 :         resultNode = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &node);
 2037                           259           10000 :         if (resultNode == NULL)
 2037 tgl                       260 UBC           0 :             elog(ERROR, "inserted element was not found");
 2037 tgl                       261 CBC       10000 :         if (node.key != resultNode->key)
 2037 tgl                       262 UBC           0 :             elog(ERROR, "find operation in rbtree gave wrong result");
                                263                 :     }
                                264                 : 
                                265                 :     /*
                                266                 :      * Check that not-inserted elements can not be found, being sure to try
                                267                 :      * values before the first and after the last element.
                                268                 :      */
 2037 tgl                       269 CBC       10002 :     for (i = -1; i <= 2 * size; i += 2)
                                270                 :     {
                                271                 :         IntRBTreeNode node;
                                272                 :         IntRBTreeNode *resultNode;
                                273                 : 
                                274           10001 :         node.key = i;
 1615                           275           10001 :         resultNode = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &node);
 2037                           276           10001 :         if (resultNode != NULL)
 2037 tgl                       277 UBC           0 :             elog(ERROR, "not-inserted element was found");
                                278                 :     }
 2037 tgl                       279 CBC           1 : }
                                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
  275 akorotkov                 287 GNC           1 : testfindltgt(int size)
                                288                 : {
                                289               1 :     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               1 :     int         randomKey = pg_prng_uint64_range(&pg_global_prng_state, 0, size - 1);
                                296                 :     bool        keyDeleted;
                                297               1 :     IntRBTreeNode searchNode = {.key = randomKey};
                                298                 :     IntRBTreeNode *lteNode;
                                299                 :     IntRBTreeNode *gteNode;
                                300                 :     IntRBTreeNode *node;
                                301                 : 
                                302                 :     /* Insert natural numbers */
                                303               1 :     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               1 :     lteNode = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode, true);
                                310               1 :     gteNode = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode, true);
                                311                 : 
                                312               1 :     if (lteNode == NULL || lteNode->key != searchNode.key)
  275 akorotkov                 313 UNC           0 :         elog(ERROR, "rbt_find_less() didn't find the equal key");
                                314                 : 
  275 akorotkov                 315 GNC           1 :     if (gteNode == NULL || gteNode->key != searchNode.key)
  275 akorotkov                 316 UNC           0 :         elog(ERROR, "rbt_find_great() didn't find the equal key");
                                317                 : 
  275 akorotkov                 318 GNC           1 :     if (lteNode != gteNode)
  275 akorotkov                 319 UNC           0 :         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 */
  275 akorotkov                 322 GNC           1 :     keyDeleted = false;
                                323            6465 :     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            6464 :         node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode,
                                330                 :                                                keyDeleted);
                                331                 : 
                                332                 :         /* ensure we find a lesser match */
                                333            6464 :         if (!node || !(node->key < searchNode.key))
  275 akorotkov                 334 UNC           0 :             elog(ERROR, "rbt_find_less() didn't find a lesser key");
                                335                 : 
                                336                 :         /* randomly delete the found key or leave it */
  275 akorotkov                 337 GNC        6464 :         keyDeleted = (pg_prng_uint64_range(&pg_global_prng_state, 0, 1) == 1);
                                338            6464 :         if (keyDeleted)
                                339            3247 :             rbt_delete(tree, (RBTNode *) node);
                                340                 :     }
                                341                 : 
                                342                 :     /* Find the rest of the naturals greater than the search key */
                                343               1 :     keyDeleted = false;
                                344            3536 :     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            3535 :         node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode,
                                351                 :                                                 keyDeleted);
                                352                 : 
                                353                 :         /* ensure we find a greater match */
                                354            3535 :         if (!node || !(node->key > searchNode.key))
  275 akorotkov                 355 UNC           0 :             elog(ERROR, "rbt_find_great() didn't find a greater key");
                                356                 : 
                                357                 :         /* randomly delete the found key or leave it */
  275 akorotkov                 358 GNC        3535 :         keyDeleted = (pg_prng_uint64_range(&pg_global_prng_state, 0, 1) == 1);
                                359            3535 :         if (keyDeleted)
                                360            1742 :             rbt_delete(tree, (RBTNode *) node);
                                361                 :     }
                                362                 : 
                                363                 :     /* Check out of bounds searches find nothing */
                                364               1 :     searchNode.key = -1;
                                365               1 :     node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode, true);
                                366               1 :     if (node != NULL)
  275 akorotkov                 367 UNC           0 :         elog(ERROR, "rbt_find_less() found non-inserted element");
  275 akorotkov                 368 GNC           1 :     searchNode.key = 0;
                                369               1 :     node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode, false);
                                370               1 :     if (node != NULL)
  275 akorotkov                 371 UNC           0 :         elog(ERROR, "rbt_find_less() found non-inserted element");
  275 akorotkov                 372 GNC           1 :     searchNode.key = size;
                                373               1 :     node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode, true);
                                374               1 :     if (node != NULL)
  275 akorotkov                 375 UNC           0 :         elog(ERROR, "rbt_find_great() found non-inserted element");
  275 akorotkov                 376 GNC           1 :     searchNode.key = size - 1;
                                377               1 :     node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode, false);
                                378               1 :     if (node != NULL)
  275 akorotkov                 379 UNC           0 :         elog(ERROR, "rbt_find_great() found non-inserted element");
  275 akorotkov                 380 GNC           1 : }
                                381                 : 
                                382                 : /*
                                383                 :  * Check the correctness of the rbt_leftmost operation.
                                384                 :  * This operation should always return the smallest element of the tree.
                                385                 :  */
                                386                 : static void
 2037 tgl                       387 GIC           1 : testleftmost(int size)
 2037 tgl                       388 ECB             : {
 2037 tgl                       389 GIC           1 :     RBTree     *tree = create_int_rbtree();
 2037 tgl                       390 ECB             :     IntRBTreeNode *result;
                                391                 : 
                                392                 :     /* Check that empty tree has no leftmost element */
 1615 tgl                       393 GIC           1 :     if (rbt_leftmost(tree) != NULL)
 2037 tgl                       394 UIC           0 :         elog(ERROR, "leftmost node of empty tree is not NULL");
                                395                 : 
 2037 tgl                       396 ECB             :     /* fill tree with consecutive natural numbers */
 1615 tgl                       397 GIC           1 :     rbt_populate(tree, size, 1);
 2037 tgl                       398 ECB             : 
                                399                 :     /* Check that leftmost element is the smallest one */
 1615 tgl                       400 GIC           1 :     result = (IntRBTreeNode *) rbt_leftmost(tree);
 2037                           401               1 :     if (result == NULL || result->key != 0)
 1615 tgl                       402 UIC           0 :         elog(ERROR, "rbt_leftmost gave wrong result");
 2037 tgl                       403 GIC           1 : }
 2037 tgl                       404 ECB             : 
                                405                 : /*
                                406                 :  * Check the correctness of the rbt_delete operation.
                                407                 :  */
                                408                 : static void
 2037 tgl                       409 GIC           1 : testdelete(int size, int delsize)
 2037 tgl                       410 ECB             : {
 2037 tgl                       411 CBC           1 :     RBTree     *tree = create_int_rbtree();
                                412                 :     int        *deleteIds;
 2037 tgl                       413 ECB             :     bool       *chosen;
 2037 tgl                       414 EUB             :     int         i;
                                415                 : 
 2037 tgl                       416 ECB             :     /* fill tree with consecutive natural numbers */
 1615 tgl                       417 GBC           1 :     rbt_populate(tree, size, 1);
                                418                 : 
 2037 tgl                       419 ECB             :     /* Choose unique ids to delete */
 2037 tgl                       420 GBC           1 :     deleteIds = (int *) palloc(delsize * sizeof(int));
 2037 tgl                       421 GIC           1 :     chosen = (bool *) palloc0(size * sizeof(bool));
                                422                 : 
 2037 tgl                       423 CBC        1001 :     for (i = 0; i < delsize; i++)
 2037 tgl                       424 ECB             :     {
  497 tgl                       425 GIC        1000 :         int         k = pg_prng_uint64_range(&pg_global_prng_state, 0, size - 1);
                                426                 : 
 2037                           427            1042 :         while (chosen[k])
                                428              42 :             k = (k + 1) % size;
                                429            1000 :         deleteIds[i] = k;
 2037 tgl                       430 CBC        1000 :         chosen[k] = true;
                                431                 :     }
                                432                 : 
                                433                 :     /* Delete elements */
                                434            1001 :     for (i = 0; i < delsize; i++)
 2037 tgl                       435 EUB             :     {
                                436                 :         IntRBTreeNode find;
                                437                 :         IntRBTreeNode *node;
 2037 tgl                       438 ECB             : 
 2037 tgl                       439 CBC        1000 :         find.key = deleteIds[i];
 2037 tgl                       440 ECB             :         /* Locate the node to be deleted */
 1615 tgl                       441 GIC        1000 :         node = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &find);
 2037                           442            1000 :         if (node == NULL || node->key != deleteIds[i])
 2037 tgl                       443 UIC           0 :             elog(ERROR, "expected element was not found during deleting");
 2037 tgl                       444 ECB             :         /* Delete it */
 1615 tgl                       445 CBC        1000 :         rbt_delete(tree, (RBTNode *) node);
                                446                 :     }
                                447                 : 
                                448                 :     /* Check that deleted elements are deleted */
 2037 tgl                       449 GIC       10001 :     for (i = 0; i < size; i++)
                                450                 :     {
 2037 tgl                       451 ECB             :         IntRBTreeNode node;
                                452                 :         IntRBTreeNode *result;
                                453                 : 
 2037 tgl                       454 GIC       10000 :         node.key = i;
 1615 tgl                       455 CBC       10000 :         result = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &node);
 2037 tgl                       456 GBC       10000 :         if (chosen[i])
                                457                 :         {
                                458                 :             /* Deleted element should be absent */
 2037 tgl                       459 CBC        1000 :             if (result != NULL)
 2037 tgl                       460 LBC           0 :                 elog(ERROR, "deleted element still present in the rbtree");
 2037 tgl                       461 ECB             :         }
                                462                 :         else
                                463                 :         {
                                464                 :             /* Else it should be present */
 2037 tgl                       465 CBC        9000 :             if (result == NULL || result->key != i)
 2037 tgl                       466 LBC           0 :                 elog(ERROR, "delete operation removed wrong rbtree value");
 2037 tgl                       467 ECB             :         }
 2037 tgl                       468 EUB             :     }
 2037 tgl                       469 ECB             : 
                                470                 :     /* Delete remaining elements, so as to exercise reducing tree to empty */
 2037 tgl                       471 CBC       10001 :     for (i = 0; i < size; i++)
 2037 tgl                       472 EUB             :     {
 2037 tgl                       473 ECB             :         IntRBTreeNode find;
                                474                 :         IntRBTreeNode *node;
                                475                 : 
 2037 tgl                       476 GBC       10000 :         if (chosen[i])
 2037 tgl                       477 CBC        1000 :             continue;
                                478            9000 :         find.key = i;
 2037 tgl                       479 ECB             :         /* Locate the node to be deleted */
 1615 tgl                       480 GBC        9000 :         node = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &find);
 2037 tgl                       481 CBC        9000 :         if (node == NULL || node->key != i)
 2037 tgl                       482 UIC           0 :             elog(ERROR, "expected element was not found during deleting");
                                483                 :         /* Delete it */
 1615 tgl                       484 GIC        9000 :         rbt_delete(tree, (RBTNode *) node);
                                485                 :     }
                                486                 : 
                                487                 :     /* Tree should now be empty */
 1615 tgl                       488 CBC           1 :     if (rbt_leftmost(tree) != NULL)
 2037 tgl                       489 UIC           0 :         elog(ERROR, "deleting all elements failed");
 2037 tgl                       490 ECB             : 
 2037 tgl                       491 GIC           1 :     pfree(deleteIds);
                                492               1 :     pfree(chosen);
                                493               1 : }
 2037 tgl                       494 ECB             : 
 2037 tgl                       495 EUB             : /*
                                496                 :  * SQL-callable entry point to perform all tests
                                497                 :  *
 2037 tgl                       498 ECB             :  * Argument is the number of entries to put in the trees
                                499                 :  */
 2037 tgl                       500 GIC           2 : PG_FUNCTION_INFO_V1(test_rb_tree);
 2037 tgl                       501 ECB             : 
                                502                 : Datum
 2037 tgl                       503 GBC           1 : test_rb_tree(PG_FUNCTION_ARGS)
 2037 tgl                       504 ECB             : {
 2037 tgl                       505 GIC           1 :     int         size = PG_GETARG_INT32(0);
                                506                 : 
                                507               1 :     if (size <= 0 || size > MaxAllocSize / sizeof(int))
 2037 tgl                       508 UIC           0 :         elog(ERROR, "invalid size for test_rb_tree: %d", size);
 2037 tgl                       509 GIC           1 :     testleftright(size);
 2037 tgl                       510 CBC           1 :     testrightleft(size);
 2037 tgl                       511 GIC           1 :     testfind(size);
  275 akorotkov                 512 GNC           1 :     testfindltgt(size);
 2037 tgl                       513 CBC           1 :     testleftmost(size);
 2037 tgl                       514 GIC           1 :     testdelete(size, Max(size / 10, 1));
                                515               1 :     PG_RETURN_VOID();
                                516                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a