LCOV - code coverage report
Current view: top level - gcc - splay-tree-utils.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.2 % 113 111
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Splay tree utilities                                             -*- C++ -*-
       2              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       3              : //
       4              : // This file is part of GCC.
       5              : //
       6              : // GCC is free software; you can redistribute it and/or modify it under
       7              : // the terms of the GNU General Public License as published by the Free
       8              : // Software Foundation; either version 3, or (at your option) any later
       9              : // version.
      10              : //
      11              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : // for more details.
      15              : //
      16              : // You should have received a copy of the GNU General Public License
      17              : // along with GCC; see the file COPYING3.  If not see
      18              : // <http://www.gnu.org/licenses/>.
      19              : 
      20              : #define INCLUDE_ALGORITHM
      21              : #define INCLUDE_ARRAY
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "pretty-print.h"
      26              : #include "splay-tree-utils.h"
      27              : #include "selftest.h"
      28              : 
      29              : #if CHECKING_P
      30              : namespace {
      31              : // A simple test node for rootless_splay_tree.
      32              : struct rootless_test_node
      33              : {
      34              :   int data;
      35              :   rootless_test_node *m_parent;
      36              :   rootless_test_node *m_children[2];
      37              : };
      38              : }
      39              : 
      40              : namespace selftest {
      41              : 
      42              : // Random input data.
      43              : static const size_t MAX_DATA = 32768;
      44              : static const int data[] = {
      45              :   1379, 14643, 30579, 28160, 31750, 22280, 5502, 4720, 30075, 27595,
      46              :   8395, 19410, 518, 19709, 29694, 19865, 25372, 11752, 15485, 21547,
      47              :   25153, 25072, 10146, 3341, 15625, 3038, 10189, 19943, 1322, 11762,
      48              :   807, 430, 11284, 11841, 23965, 32008, 4547, 8087, 13225, 23054,
      49              :   22284, 13756, 2182, 26450, 30482, 32502, 23348, 20265, 29509, 3290,
      50              :   10807, 1242, 3212, 32178, 25354, 22032, 30509, 16157, 22432, 1295,
      51              :   8348, 23342, 24678, 193, 31016, 10316, 3872, 13521, 19211, 30594,
      52              :   12229, 4794, 25083, 16098, 28144, 27896, 4801, 20689, 31450, 15614,
      53              :   19597, 13731, 30309, 24846, 11042, 31929, 18306, 28520, 16907, 12488,
      54              :   15001, 18487, 3438, 1706, 4829, 20892, 6226, 18204, 15776, 30717,
      55              :   19398, 2480, 19434, 2838, 2605, 3994, 22538, 12269, 6486, 1314,
      56              :   30301, 9919, 31405, 30847, 25000, 24013, 22196, 30220, 31415, 14630,
      57              :   26319, 4880, 21292, 20217, 20078, 14679, 25686, 28675, 13883, 14853,
      58              :   2872, 2428, 3636, 14131, 2952, 2133, 4470, 25808, 12576, 31395,
      59              :   5938, 28393, 14553, 4494, 14928, 24310, 17394, 17436, 23385, 22792,
      60              :   9785, 13118, 22338, 23320, 27059, 17663, 16434, 14954, 16962, 31088,
      61              :   22247, 22600, 7980, 1344, 15635, 13611, 32739, 3283, 12924, 17904,
      62              :   28216, 7542, 9212, 28308, 18873, 3912, 5473, 4666, 11900, 21420,
      63              :   20072, 27662, 16445, 29848, 24444, 31668, 30664, 14287, 13754, 29276,
      64              :   21462, 25517, 17632, 8105, 32510, 16677, 11162, 20734, 26873, 5097
      65              : };
      66              : 
      67              : // Look up VALUE in TREE using the single-comparator lookup function.
      68              : static int
      69         3208 : lookup1 (splay_tree<int> &tree, int value)
      70              : {
      71        34540 :   auto compare = [&](splay_tree_node<int> *node)
      72              :     {
      73        31332 :       return value - node->value ();
      74         3208 :     };
      75         2400 :   return tree.lookup (compare);
      76              : }
      77              : 
      78              : // Look up VALUE in TREE using the double-comparator lookup function.
      79              : static int
      80         2400 : lookup2 (splay_tree<int> &tree, int value)
      81              : {
      82        28868 :   auto want_something_smaller = [&](splay_tree_node<int> *node)
      83              :     {
      84        26468 :       return value < node->value ();
      85         2400 :     };
      86        19224 :   auto want_something_bigger = [&](splay_tree_node<int> *node)
      87              :     {
      88        16824 :       return value > node->value ();
      89         2400 :     };
      90         2400 :   return tree.lookup (want_something_smaller, want_something_bigger);
      91              : }
      92              : 
      93              : // Test printing TREE to a pretty printer.  Don't check the output against
      94              : // anything; just make sure that it doesn't crash.
      95              : static void
      96            4 : test_print (splay_tree<int> &tree)
      97              : {
      98          804 :   auto print_node = [](pretty_printer *pp, splay_tree_node<int> *node)
      99              :     {
     100          800 :       pp_decimal_int (pp, node->value ());
     101          800 :     };
     102            4 :   pretty_printer pp;
     103            4 :   tree.print (&pp, print_node);
     104            4 : }
     105              : 
     106              : // Test various lookups on TREE using LOOKUP, where lookup returns the
     107              : // same kind of value as the rooted_splay_tree lookup functions.
     108              : static void
     109            8 : test_lookup (splay_tree<int> &tree, int (*lookup) (splay_tree<int> &, int))
     110              : {
     111              :   // Look up values that are known to exist.
     112         1608 :   for (int value : data)
     113         1600 :     ASSERT_EQ (lookup (tree, value), 0);
     114              : 
     115              :   // Look up values that are 1 less than values that are known to exist.
     116         1608 :   for (int value : data)
     117              :     {
     118         1600 :       int result = lookup (tree, value - 1);
     119         1600 :       if (result == 0)
     120            0 :         ASSERT_EQ (tree->value (), value - 1);
     121         1600 :       else if (result < 0)
     122              :         // VALUE - 1 is less than the root.
     123         1372 :         ASSERT_EQ (tree->value (), value);
     124          228 :       else if (result > 0)
     125              :         {
     126              :           // VALUE - 1 is greater than the root.
     127          228 :           ASSERT_TRUE (tree->value () < value - 1);
     128          228 :           if (tree.splay_next_node ())
     129          228 :             ASSERT_EQ (tree->value (), value);
     130              :         }
     131              :     }
     132              : 
     133              :   // Look up values that are 1 greater than values that are known to exist.
     134         1608 :   for (int value : data)
     135              :     {
     136         1600 :       int result = lookup (tree, value + 1);
     137         1600 :       if (result == 0)
     138            0 :         ASSERT_EQ (tree->value (), value + 1);
     139         1600 :       else if (result < 0)
     140              :         {
     141              :           // VALUE + 1 is less than the root.
     142          448 :           ASSERT_TRUE (tree->value () > value + 1);
     143          448 :           if (tree.splay_prev_node ())
     144          448 :             ASSERT_EQ (tree->value (), value);
     145              :         }
     146         1152 :       else if (result > 0)
     147              :         // VALUE + 1 is greater than the root.
     148         1152 :         ASSERT_EQ (tree->value (), value);
     149              :     }
     150            8 : }
     151              : 
     152              : // Run all tests for this module.
     153              : void
     154            4 : splay_tree_cc_tests ()
     155              : {
     156            4 :   obstack ob;
     157            4 :   gcc_obstack_init (&ob);
     158              : 
     159              :   // Build up the splay tree.
     160            4 :   splay_tree<int> tree;
     161          804 :   for (int value : data)
     162              :     {
     163          800 :       auto *node = XOBNEW (&ob, splay_tree_node<int>);
     164          800 :       new (node) splay_tree_node<int> (value);
     165         8072 :       auto compare = [&](splay_tree_node<int> *other_node)
     166              :         {
     167         7272 :           return value - other_node->value ();
     168          800 :         };
     169          800 :       bool inserted = tree.insert (node, compare);
     170          800 :       ASSERT_TRUE (inserted);
     171              :     }
     172              : 
     173              :   // Test the single-comparator lookup function.
     174            4 :   test_lookup (tree, lookup1);
     175              : 
     176              :   // Sort the input data.
     177            4 :   std::array<int, ARRAY_SIZE (data)> sorted;
     178            4 :   std::copy (data, data + ARRAY_SIZE (data), sorted.begin ());
     179            4 :   std::sort (sorted.begin (), sorted.end ());
     180              : 
     181              :   // Iterate over the tree in ascending order.
     182            4 :   tree.splay_min_node ();
     183            4 :   bool result = true;
     184          804 :   for (int value : sorted)
     185              :     {
     186          800 :       ASSERT_TRUE (result);
     187          800 :       ASSERT_EQ (tree->value (), value);
     188          800 :       result = tree.splay_next_node ();
     189              :     }
     190            4 :   ASSERT_FALSE (result);
     191            4 :   ASSERT_EQ (tree.min_node ()->value (), sorted.front ());
     192              : 
     193              :   // Test the double-comparator lookup function.
     194            4 :   test_lookup (tree, lookup2);
     195              : 
     196              :   // Test printing the tree now, while it's still bushy.
     197            4 :   test_print (tree);
     198              : 
     199              :   // Iterate over the tree in descending order.
     200            4 :   tree.splay_max_node ();
     201            4 :   result = true;
     202          808 :   for (auto it = sorted.rbegin (); it != sorted.rend (); ++it)
     203              :     {
     204          800 :       ASSERT_TRUE (result);
     205          800 :       ASSERT_EQ (tree->value (), *it);
     206          800 :       result = tree.splay_prev_node ();
     207              :     }
     208            4 :   ASSERT_FALSE (result);
     209            4 :   ASSERT_EQ (tree.max_node ()->value (), sorted.back ());
     210              : 
     211              :   // Try splitting the tree into three.
     212            4 :   int mid_min = sorted[sorted.size () / 3];
     213            4 :   int mid_max = sorted[sorted.size () * 2 / 3];
     214            4 :   ASSERT_EQ (lookup1 (tree, mid_min), 0);
     215            4 :   splay_tree<int> left = tree.split_before_root ();
     216            4 :   ASSERT_EQ (lookup1 (tree, mid_max), 0);
     217            4 :   splay_tree<int> right = tree.split_after_root ();
     218              : 
     219              :   // Test removing all the nodes from their respective trees.
     220          804 :   for (int value : data)
     221              :     {
     222          800 :       splay_tree<int> &t = (value < mid_min ? left
     223              :                             : value > mid_max ? right : tree);
     224          800 :       ASSERT_EQ (lookup1 (t, value), 0);
     225          800 :       t.remove_root ();
     226              :     }
     227            4 :   ASSERT_EQ (left.root (), nullptr);
     228            4 :   ASSERT_EQ (tree.root (), nullptr);
     229            4 :   ASSERT_EQ (right.root (), nullptr);
     230              : 
     231            4 :   using rootless = default_rootless_splay_tree<rootless_test_node *>;
     232              : 
     233              :   // Build a tree in ascending order with the lowest element as the root.
     234            4 :   auto *nodes = XOBNEWVEC (&ob, rootless_test_node *, MAX_DATA);
     235            4 :   rootless_test_node *parent = nullptr;
     236          804 :   for (int data : sorted)
     237              :     {
     238          800 :       auto *node = XOBNEW (&ob, rootless_test_node);
     239          800 :       new (node) rootless_test_node ();
     240          800 :       node->data = data;
     241          800 :       nodes[data] = node;
     242          800 :       if (parent)
     243          796 :         rootless::insert_child (parent, 1, node);
     244          800 :       parent = node;
     245              :     }
     246              : 
     247              :   // Try comparing nodes to make sure that their order matches the data.
     248          800 :   for (size_t i = 1; i < ARRAY_SIZE (data); ++i)
     249              :     {
     250          796 :       int data1 = data[i - 1];
     251          796 :       int data2 = data[i];
     252          796 :       int comparison = rootless::compare_nodes (nodes[data1], nodes[data2]);
     253          796 :       if (data1 < data2)
     254          396 :         ASSERT_TRUE (comparison < 0);
     255          400 :       else if (data1 > data2)
     256          400 :         ASSERT_TRUE (comparison > 0);
     257              :       else
     258          796 :         ASSERT_EQ (comparison, 0);
     259              :     }
     260              : 
     261            4 :   obstack_free (&ob, nullptr);
     262            4 : }
     263              : }
     264              : #endif // CHECKING_P
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.