LCOV - code coverage report
Current view: top level - gcc - digraph.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 131 131
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Template classes for directed graphs.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it
       8              : under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but
      13              : WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              : General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #define INCLUDE_STRING
      22              : #define INCLUDE_VECTOR
      23              : #include "config.h"
      24              : #include "system.h"
      25              : #include "coretypes.h"
      26              : #include "diagnostic.h"
      27              : #include "graphviz.h"
      28              : #include "digraph.h"
      29              : #include "shortest-paths.h"
      30              : #include "selftest.h"
      31              : 
      32              : #if CHECKING_P
      33              : 
      34              : namespace selftest {
      35              : 
      36              : /* A family of digraph classes for writing selftests.  */
      37              : 
      38              : struct test_node;
      39              : struct test_edge;
      40              : struct test_graph;
      41              : struct test_dump_args_t {};
      42              : struct test_cluster;
      43              : 
      44              : struct test_graph_traits
      45              : {
      46              :   typedef test_node node_t;
      47              :   typedef test_edge edge_t;
      48              :   typedef test_graph graph_t;
      49              :   typedef test_dump_args_t dump_args_t;
      50              :   typedef test_cluster cluster_t;
      51              : };
      52              : 
      53              : struct test_node : public dnode<test_graph_traits>
      54              : {
      55           32 :   test_node (const char *name, int index) : m_name (name), m_index (index) {}
      56            8 :   void dump_dot (graphviz_out *, const dump_args_t &) const override
      57              :   {
      58            8 :   }
      59              : 
      60              :   const char *m_name;
      61              :   int m_index;
      62              : };
      63              : 
      64              : struct test_edge : public dedge<test_graph_traits>
      65              : {
      66           28 :   test_edge (node_t *src, node_t *dest)
      67           28 :   : dedge<test_graph_traits> (src, dest)
      68              :   {}
      69              : 
      70            4 :   void dump_dot (graphviz_out *gv, const dump_args_t &) const override
      71              :   {
      72            4 :     gv->println ("%s %s %s%c", m_src->m_name, "->", m_dest->m_name, ';');
      73            4 :   }
      74              : };
      75              : 
      76           24 : struct test_graph : public digraph<test_graph_traits>
      77              : {
      78           32 :   test_node *add_test_node (const char *name)
      79              :   {
      80           56 :     test_node *result = new test_node (name, m_nodes.length ());
      81           32 :     add_node (result);
      82           32 :     return result;
      83              :   }
      84              : 
      85           28 :   test_edge *add_test_edge (test_node *src, test_node *dst)
      86              :   {
      87           28 :     test_edge *result = new test_edge (src, dst);
      88           28 :     add_edge (result);
      89           28 :     return result;
      90              :   }
      91              : };
      92              : 
      93              : struct test_cluster : public cluster<test_graph_traits>
      94              : {
      95              : };
      96              : 
      97           96 : struct test_path
      98              : {
      99              :   auto_vec<const test_edge *> m_edges;
     100              : };
     101              : 
     102              : /* Smoketest of digraph dumping.  */
     103              : 
     104              : static void
     105            4 : test_dump_to_dot ()
     106              : {
     107            4 :   test_graph g;
     108            4 :   test_node *a = g.add_test_node ("a");
     109            4 :   test_node *b = g.add_test_node ("b");
     110            4 :   g.add_test_edge (a, b);
     111              : 
     112            4 :   pretty_printer pp;
     113            4 :   pp.set_output_stream (nullptr);
     114            4 :   test_dump_args_t dump_args;
     115            4 :   g.dump_dot_to_pp (&pp, NULL, dump_args);
     116              : 
     117            4 :   ASSERT_STR_CONTAINS (pp_formatted_text (&pp),
     118              :                        "a -> b;\n");
     119            4 : }
     120              : 
     121              : /* Test shortest paths from A in this digraph,
     122              :    where edges run top-to-bottom if not otherwise labeled:
     123              : 
     124              :       A
     125              :      / \
     126              :     B   C-->D
     127              :     |   |
     128              :     E   |
     129              :      \ /
     130              :       F.  */
     131              : 
     132              : static void
     133            4 : test_shortest_paths ()
     134              : {
     135            4 :   test_graph g;
     136            4 :   test_node *a = g.add_test_node ("a");
     137            4 :   test_node *b = g.add_test_node ("b");
     138            4 :   test_node *c = g.add_test_node ("d");
     139            4 :   test_node *d = g.add_test_node ("d");
     140            4 :   test_node *e = g.add_test_node ("e");
     141            4 :   test_node *f = g.add_test_node ("f");
     142              : 
     143            4 :   test_edge *ab = g.add_test_edge (a, b);
     144            4 :   test_edge *ac = g.add_test_edge (a, c);
     145            4 :   test_edge *cd = g.add_test_edge (c, d);
     146            4 :   test_edge *be = g.add_test_edge (b, e);
     147            4 :   test_edge *ef = g.add_test_edge (e, f);
     148            4 :   test_edge *cf = g.add_test_edge (c, f);
     149              : 
     150              :   /* Use "A" as the origin; all nodes should be reachable.  */
     151            4 :   {
     152            4 :     shortest_paths<test_graph_traits, test_path> sp (g, a,
     153            4 :                                                      SPS_FROM_GIVEN_ORIGIN);
     154              : 
     155            4 :     test_path path_to_a = sp.get_shortest_path (a);
     156            4 :     ASSERT_EQ (path_to_a.m_edges.length (), 0); /* Trivial path.  */
     157              : 
     158            4 :     test_path path_to_b = sp.get_shortest_path (b);
     159            4 :     ASSERT_EQ (path_to_b.m_edges.length (), 1);
     160            4 :     ASSERT_EQ (path_to_b.m_edges[0], ab);
     161              : 
     162            4 :     test_path path_to_c = sp.get_shortest_path (c);
     163            4 :     ASSERT_EQ (path_to_c.m_edges.length (), 1);
     164            4 :     ASSERT_EQ (path_to_c.m_edges[0], ac);
     165              : 
     166            4 :     test_path path_to_d = sp.get_shortest_path (d);
     167            4 :     ASSERT_EQ (path_to_d.m_edges.length (), 2);
     168            4 :     ASSERT_EQ (path_to_d.m_edges[0], ac);
     169            4 :     ASSERT_EQ (path_to_d.m_edges[1], cd);
     170              : 
     171            4 :     test_path path_to_e = sp.get_shortest_path (e);
     172            4 :     ASSERT_EQ (path_to_e.m_edges.length (), 2);
     173            4 :     ASSERT_EQ (path_to_e.m_edges[0], ab);
     174            4 :     ASSERT_EQ (path_to_e.m_edges[1], be);
     175              : 
     176            4 :     test_path path_to_f = sp.get_shortest_path (f);
     177            4 :     ASSERT_EQ (path_to_f.m_edges.length (), 2);
     178            4 :     ASSERT_EQ (path_to_f.m_edges[0], ac);
     179            4 :     ASSERT_EQ (path_to_f.m_edges[1], cf);
     180            4 :   }
     181              : 
     182              :   /* Verify that we gracefully handle an origin from which some nodes
     183              :      aren't reachable.  */
     184              : 
     185              :   /* Use "B" as the origin, so only E and F are reachable.  */
     186            4 :   {
     187            4 :     shortest_paths<test_graph_traits, test_path> sp (g, b,
     188            4 :                                                      SPS_FROM_GIVEN_ORIGIN);
     189              : 
     190            4 :     test_path path_to_a = sp.get_shortest_path (a);
     191            4 :     ASSERT_EQ (path_to_a.m_edges.length (), 0); /* No path.  */
     192              : 
     193            4 :     test_path path_to_b = sp.get_shortest_path (b);
     194            4 :     ASSERT_EQ (path_to_b.m_edges.length (), 0); /* Trivial path.  */
     195              : 
     196            4 :     test_path path_to_c = sp.get_shortest_path (c);
     197            4 :     ASSERT_EQ (path_to_c.m_edges.length (), 0); /* No path.  */
     198              : 
     199            4 :     test_path path_to_d = sp.get_shortest_path (d);
     200            4 :     ASSERT_EQ (path_to_d.m_edges.length (), 0); /* No path.  */
     201              : 
     202            4 :     test_path path_to_e = sp.get_shortest_path (e);
     203            4 :     ASSERT_EQ (path_to_e.m_edges.length (), 1);
     204            4 :     ASSERT_EQ (path_to_e.m_edges[0], be);
     205              : 
     206            4 :     test_path path_to_f = sp.get_shortest_path (f);
     207            4 :     ASSERT_EQ (path_to_f.m_edges.length (), 2);
     208            4 :     ASSERT_EQ (path_to_f.m_edges[0], be);
     209            4 :     ASSERT_EQ (path_to_f.m_edges[1], ef);
     210            4 :   }
     211              : 
     212              :   /* Use "C" as the origin, so only D and F are reachable.  */
     213            4 :   {
     214            4 :     shortest_paths<test_graph_traits, test_path> sp (g, c,
     215            4 :                                                      SPS_FROM_GIVEN_ORIGIN);
     216              : 
     217            4 :     test_path path_to_a = sp.get_shortest_path (a);
     218            4 :     ASSERT_EQ (path_to_a.m_edges.length (), 0); /* No path.  */
     219              : 
     220            4 :     test_path path_to_b = sp.get_shortest_path (b);
     221            4 :     ASSERT_EQ (path_to_b.m_edges.length (), 0); /* No path.  */
     222              : 
     223            4 :     test_path path_to_c = sp.get_shortest_path (c);
     224            4 :     ASSERT_EQ (path_to_c.m_edges.length (), 0); /* Trivial path.  */
     225              : 
     226            4 :     test_path path_to_d = sp.get_shortest_path (d);
     227            4 :     ASSERT_EQ (path_to_d.m_edges.length (), 1);
     228            4 :     ASSERT_EQ (path_to_d.m_edges[0], cd);
     229              : 
     230            4 :     test_path path_to_e = sp.get_shortest_path (e);
     231            4 :     ASSERT_EQ (path_to_e.m_edges.length (), 0); /* No path.  */
     232              : 
     233            4 :     test_path path_to_f = sp.get_shortest_path (f);
     234            4 :     ASSERT_EQ (path_to_f.m_edges.length (), 1);
     235            4 :     ASSERT_EQ (path_to_f.m_edges[0], cf);
     236            4 :   }
     237              : 
     238              :   /* Test of SPS_TO_GIVEN_TARGET.  Use "F" as the target.  */
     239            4 :   {
     240            4 :     shortest_paths<test_graph_traits, test_path> sp (g, f,
     241            4 :                                                      SPS_TO_GIVEN_TARGET);
     242              : 
     243            4 :     test_path path_to_a = sp.get_shortest_path (a);
     244            4 :     ASSERT_EQ (path_to_a.m_edges.length (), 2);
     245            4 :     ASSERT_EQ (path_to_a.m_edges[0], ac);
     246            4 :     ASSERT_EQ (path_to_a.m_edges[1], cf);
     247              : 
     248            4 :     test_path path_to_b = sp.get_shortest_path (b);
     249            4 :     ASSERT_EQ (path_to_b.m_edges.length (), 2);
     250            4 :     ASSERT_EQ (path_to_b.m_edges[0], be);
     251            4 :     ASSERT_EQ (path_to_b.m_edges[1], ef);
     252              : 
     253            4 :     test_path path_to_c = sp.get_shortest_path (c);
     254            4 :     ASSERT_EQ (path_to_c.m_edges.length (), 1);
     255            4 :     ASSERT_EQ (path_to_c.m_edges[0], cf);
     256              : 
     257            4 :     test_path path_to_d = sp.get_shortest_path (d);
     258            4 :     ASSERT_EQ (path_to_d.m_edges.length (), 0); /* No path.  */
     259              : 
     260            4 :     test_path path_to_e = sp.get_shortest_path (e);
     261            4 :     ASSERT_EQ (path_to_e.m_edges.length (), 1);
     262            4 :     ASSERT_EQ (path_to_e.m_edges[0], ef);
     263              : 
     264            4 :     test_path path_to_f = sp.get_shortest_path (f);
     265            4 :     ASSERT_EQ (path_to_f.m_edges.length (), 0);
     266            8 :   }
     267            4 : }
     268              : 
     269              : /* Run all of the selftests within this file.  */
     270              : 
     271              : void
     272            4 : digraph_cc_tests ()
     273              : {
     274            4 :   test_dump_to_dot ();
     275            4 :   test_shortest_paths ();
     276            4 : }
     277              : 
     278              : } // namespace selftest
     279              : 
     280              : #endif /* #if 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.