LCOV - code coverage report
Current view: top level - gcc/diagnostics - digraphs.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 66.9 % 248 166
Test Date: 2025-11-22 14:42:49 Functions: 48.5 % 33 16
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Directed graphs associated with a diagnostic.
       2                 :             :    Copyright (C) 2025 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_ALGORITHM
      22                 :             : #define INCLUDE_MAP
      23                 :             : #define INCLUDE_SET
      24                 :             : #define INCLUDE_STRING
      25                 :             : #define INCLUDE_VECTOR
      26                 :             : #include "config.h"
      27                 :             : #include "system.h"
      28                 :             : #include "coretypes.h"
      29                 :             : 
      30                 :             : #include "graphviz.h"
      31                 :             : #include "diagnostics/digraphs.h"
      32                 :             : #include "diagnostics/sarif-sink.h"
      33                 :             : #include "custom-sarif-properties/digraphs.h"
      34                 :             : 
      35                 :             : using digraph_object = diagnostics::digraphs::object;
      36                 :             : using digraph = diagnostics::digraphs::digraph;
      37                 :             : using digraph_node = diagnostics::digraphs::node;
      38                 :             : using digraph_edge = diagnostics::digraphs::edge;
      39                 :             : 
      40                 :             : namespace properties = custom_sarif_properties::digraphs;
      41                 :             : 
      42                 :             : namespace {
      43                 :             : 
      44                 :          11 : class conversion_to_dot
      45                 :             : {
      46                 :             : public:
      47                 :             :   std::unique_ptr<dot::graph>
      48                 :             :   make_dot_graph_from_diagnostic_graph (const digraph &);
      49                 :             : 
      50                 :             :   std::unique_ptr<dot::stmt>
      51                 :             :   make_dot_node_from_digraph_node (const digraph_node &);
      52                 :             : 
      53                 :             :   std::unique_ptr<dot::edge_stmt>
      54                 :             :   make_dot_edge_from_digraph_edge (const digraph_edge &);
      55                 :             : 
      56                 :             :   dot::id
      57                 :             :   get_dot_id_for_node (const digraph_node &);
      58                 :             : 
      59                 :             :   bool
      60                 :             :   has_edges_p (const digraph_node &);
      61                 :             : 
      62                 :             : private:
      63                 :             :   std::set<const digraph_node *> m_nodes_with_edges;
      64                 :             :   std::map<const digraph_node *, dot::stmt *> m_node_map;
      65                 :             : };
      66                 :             : 
      67                 :             : } // anonymous namespace
      68                 :             : 
      69                 :             : // class conversion_to_dot
      70                 :             : 
      71                 :             : std::unique_ptr<dot::graph>
      72                 :          11 : conversion_to_dot::
      73                 :             : make_dot_graph_from_diagnostic_graph (const diagnostics::digraphs::digraph &input_graph)
      74                 :             : {
      75                 :          11 :   auto output_graph = std::make_unique<dot::graph> ();
      76                 :             : 
      77                 :          11 :   if (const char *description = input_graph.get_description ())
      78                 :          14 :     output_graph->m_stmt_list.add_attr (dot::id ("label"),
      79                 :          14 :                                         dot::id (description));
      80                 :             : 
      81                 :          11 :   const int num_nodes = input_graph.get_num_nodes ();
      82                 :          11 :   const int num_edges = input_graph.get_num_edges ();
      83                 :             : 
      84                 :             :   /* Determine which nodes have in-edges and out-edges.  */
      85                 :         405 :   for (int i = 0; i < num_edges; ++i)
      86                 :             :     {
      87                 :         394 :       const digraph_edge &input_edge = input_graph.get_edge (i);
      88                 :         394 :       m_nodes_with_edges.insert (&input_edge.get_src_node ());
      89                 :         394 :       m_nodes_with_edges.insert (&input_edge.get_dst_node ());
      90                 :             :     }
      91                 :             : 
      92                 :          28 :   for (int i = 0; i < num_nodes; ++i)
      93                 :             :     {
      94                 :          17 :       const digraph_node &input_node = input_graph.get_node (i);
      95                 :          17 :       auto dot_node_stmt = make_dot_node_from_digraph_node (input_node);
      96                 :          17 :       output_graph->m_stmt_list.add_stmt (std::move (dot_node_stmt));
      97                 :          17 :     }
      98                 :             : 
      99                 :         405 :   for (int i = 0; i < num_edges; ++i)
     100                 :             :     {
     101                 :         394 :       const digraph_edge &input_edge = input_graph.get_edge (i);
     102                 :         394 :       auto dot_edge_stmt = make_dot_edge_from_digraph_edge (input_edge);
     103                 :         394 :       output_graph->m_stmt_list.add_stmt (std::move (dot_edge_stmt));
     104                 :         394 :     }
     105                 :             : 
     106                 :          11 :   return output_graph;
     107                 :             : }
     108                 :             : 
     109                 :             : std::unique_ptr<dot::stmt>
     110                 :         416 : conversion_to_dot::
     111                 :             : make_dot_node_from_digraph_node (const diagnostics::digraphs::node &input_node)
     112                 :             : {
     113                 :         416 :   dot::id dot_id (get_dot_id_for_node (input_node));
     114                 :             : 
     115                 :             :   /* For now, we can only do either edges or children, not both
     116                 :             :      ...but see https://graphviz.org/docs/attrs/compound/  */
     117                 :             : 
     118                 :         416 :   if (has_edges_p (input_node))
     119                 :             :     {
     120                 :         405 :       auto output_node
     121                 :         405 :         = std::make_unique<dot::node_stmt> (std::move (dot_id));
     122                 :         405 :       m_node_map[&input_node] = output_node.get ();
     123                 :         405 :       if (const char *label = input_node.get_label ())
     124                 :         399 :         output_node->set_label (dot::id (label));
     125                 :         405 :       return output_node;
     126                 :         405 :     }
     127                 :             :   else
     128                 :             :     {
     129                 :          11 :       auto output_node = std::make_unique<dot::subgraph> (std::move (dot_id));
     130                 :          11 :       m_node_map[&input_node] = output_node.get ();
     131                 :          11 :       if (const char *label = input_node.get_label ())
     132                 :           5 :         output_node->add_attr (dot::id ("label"), dot::id (label));
     133                 :          11 :       const int num_children = input_node.get_num_children ();
     134                 :         410 :       for (int i = 0; i < num_children; ++i)
     135                 :             :         {
     136                 :         399 :           const digraph_node &input_child = input_node.get_child (i);
     137                 :         399 :           auto dot_child_stmt = make_dot_node_from_digraph_node (input_child);
     138                 :         399 :           output_node->m_stmt_list.add_stmt (std::move (dot_child_stmt));
     139                 :         399 :         }
     140                 :          11 :       return output_node;
     141                 :          11 :     }
     142                 :         416 : }
     143                 :             : 
     144                 :             : std::unique_ptr<dot::edge_stmt>
     145                 :         394 : conversion_to_dot::
     146                 :             : make_dot_edge_from_digraph_edge (const digraph_edge &input_edge)
     147                 :             : {
     148                 :         394 :   const digraph_node &src_dnode = input_edge.get_src_node ();
     149                 :         394 :   const digraph_node &dst_dnode = input_edge.get_dst_node ();
     150                 :         394 :   auto output_edge
     151                 :             :     = std::make_unique<dot::edge_stmt>
     152                 :         788 :     (get_dot_id_for_node (src_dnode),
     153                 :         788 :      get_dot_id_for_node (dst_dnode));
     154                 :         394 :   if (const char *label = input_edge.get_label ())
     155                 :         394 :     output_edge->set_label (dot::id (label));
     156                 :         394 :   return output_edge;
     157                 :             : }
     158                 :             : 
     159                 :             : dot::id
     160                 :        1204 : conversion_to_dot::get_dot_id_for_node (const digraph_node &input_node)
     161                 :             : {
     162                 :        1204 :   if (has_edges_p (input_node))
     163                 :        2386 :     return input_node.get_id ();
     164                 :             :   else
     165                 :          22 :     return std::string ("cluster_") + input_node.get_id ();
     166                 :             : }
     167                 :             : 
     168                 :             : bool
     169                 :        1620 : conversion_to_dot::has_edges_p (const digraph_node &input_node)
     170                 :             : {
     171                 :        1620 :   return m_nodes_with_edges.find (&input_node) != m_nodes_with_edges.end ();
     172                 :             : }
     173                 :             : 
     174                 :             : // class object
     175                 :             : 
     176                 :             : /* String properties.  */
     177                 :             : 
     178                 :             : const char *
     179                 :          32 : digraph_object::get_property (const json::string_property &property) const
     180                 :             : {
     181                 :          32 :   if (!m_property_bag)
     182                 :             :     return nullptr;
     183                 :          32 :   if (json::value *jv = m_property_bag->get (property.m_key.get ()))
     184                 :          21 :     if (json::string *jstr = jv->dyn_cast_string ())
     185                 :          21 :       return jstr->get_string ();
     186                 :             :   return nullptr;
     187                 :             : }
     188                 :             : 
     189                 :             : void
     190                 :        1167 : digraph_object::set_property (const json::string_property &property,
     191                 :             :                               const char *utf8_value)
     192                 :             : {
     193                 :        1167 :   auto &bag = ensure_property_bag ();
     194                 :        1167 :   bag.set_string (property.m_key.get (), utf8_value);
     195                 :        1167 : }
     196                 :             : 
     197                 :             : /* Integer properties.  */
     198                 :             : 
     199                 :             : bool
     200                 :           0 : digraph_object::maybe_get_property (const json::integer_property &property,
     201                 :             :                                     long &out_value) const
     202                 :             : {
     203                 :           0 :   if (!m_property_bag)
     204                 :             :     return false;
     205                 :           0 :   if (json::value *jv = m_property_bag->get (property.m_key.get ()))
     206                 :           0 :     if (json::integer_number *jnum = jv->dyn_cast_integer_number ())
     207                 :             :       {
     208                 :           0 :         out_value = jnum->get ();
     209                 :           0 :         return true;
     210                 :             :       }
     211                 :             :   return false;
     212                 :             : }
     213                 :             : 
     214                 :             : void
     215                 :           0 : digraph_object::set_property (const json::integer_property &property, long value)
     216                 :             : {
     217                 :           0 :   auto &bag = ensure_property_bag ();
     218                 :           0 :   bag.set_integer (property.m_key.get (), value);
     219                 :           0 : }
     220                 :             : 
     221                 :             : /* Bool properties.  */
     222                 :             : void
     223                 :           0 : digraph_object::set_property (const json::bool_property &property, bool value)
     224                 :             : {
     225                 :           0 :   auto &bag = ensure_property_bag ();
     226                 :           0 :   bag.set_bool (property.m_key.get (), value);  
     227                 :           0 : }
     228                 :             : 
     229                 :             : tristate
     230                 :           0 : digraph_object::
     231                 :             : get_property_as_tristate (const json::bool_property &property) const
     232                 :             : {
     233                 :           0 :   if (m_property_bag)
     234                 :             :     {
     235                 :           0 :       if (json::value *jv = m_property_bag->get (property.m_key.get ()))
     236                 :           0 :         switch (jv->get_kind ())
     237                 :             :           {
     238                 :             :           default:
     239                 :             :             break;
     240                 :           0 :           case json::JSON_TRUE:
     241                 :           0 :             return tristate (true);
     242                 :           0 :           case json::JSON_FALSE:
     243                 :           0 :             return tristate (false);
     244                 :             :           }
     245                 :             :     }
     246                 :           0 :   return tristate::unknown ();
     247                 :             : }
     248                 :             : 
     249                 :             : /* Array-of-string properties.  */
     250                 :             : json::array *
     251                 :           0 : digraph_object::get_property (const json::array_of_string_property &property) const
     252                 :             : {
     253                 :           0 :   if (m_property_bag)
     254                 :           0 :     if (json::value *jv = m_property_bag->get (property.m_key.get ()))
     255                 :           0 :       if (json::array *arr = jv->dyn_cast_array ())
     256                 :             :         return arr;
     257                 :             :   return nullptr;
     258                 :             : }
     259                 :             : 
     260                 :             : /* json::value properties.  */
     261                 :             : const json::value *
     262                 :           0 : digraph_object::get_property (const json::json_property &property) const
     263                 :             : {
     264                 :           0 :   if (m_property_bag)
     265                 :           0 :     return m_property_bag->get (property.m_key.get ());
     266                 :             :   return nullptr;
     267                 :             : }
     268                 :             : 
     269                 :             : void
     270                 :         250 : digraph_object::set_property (const json::json_property &property,
     271                 :             :                               std::unique_ptr<json::value> value)
     272                 :             : {
     273                 :         250 :   auto &bag = ensure_property_bag ();
     274                 :         250 :   bag.set (property.m_key.get (), std::move (value));
     275                 :         250 : }
     276                 :             : 
     277                 :             : json::object &
     278                 :        2011 : digraph_object::ensure_property_bag ()
     279                 :             : {
     280                 :        2011 :   if (!m_property_bag)
     281                 :         589 :     m_property_bag = std::make_unique<sarif_property_bag> ( );
     282                 :        2011 :   return *m_property_bag;
     283                 :             : }
     284                 :             : 
     285                 :             : // class digraph
     286                 :             : 
     287                 :             : DEBUG_FUNCTION void
     288                 :           0 : digraph::dump () const
     289                 :             : {
     290                 :           0 :   make_json_sarif_graph ()->dump ();
     291                 :           0 : }
     292                 :             : 
     293                 :             : std::unique_ptr<json::object>
     294                 :           8 : digraph::make_json_sarif_graph () const
     295                 :             : {
     296                 :           8 :   return make_sarif_graph (*this, nullptr, nullptr);
     297                 :             : }
     298                 :             : 
     299                 :             : std::unique_ptr<dot::graph>
     300                 :          11 : digraph::make_dot_graph () const
     301                 :             : {
     302                 :          11 :   conversion_to_dot converter;
     303                 :          11 :   return converter.make_dot_graph_from_diagnostic_graph (*this);
     304                 :          11 : }
     305                 :             : 
     306                 :             : std::unique_ptr<digraph>
     307                 :           0 : digraph::clone () const
     308                 :             : {
     309                 :           0 :   auto result = std::make_unique<diagnostics::digraphs::digraph> ();
     310                 :             : 
     311                 :           0 :   if (get_property_bag ())
     312                 :           0 :     result->set_property_bag (get_property_bag ()->clone_as_object ());
     313                 :             : 
     314                 :           0 :   std::map<digraph_node *, digraph_node *> node_mapping;
     315                 :             : 
     316                 :           0 :   for (auto &iter : m_nodes)
     317                 :           0 :     result->add_node (iter->clone (*result, node_mapping));
     318                 :           0 :   for (auto &iter : m_edges)
     319                 :           0 :     result->add_edge (iter->clone (*result, node_mapping));
     320                 :             : 
     321                 :           0 :   return result;
     322                 :           0 : }
     323                 :             : 
     324                 :             : void
     325                 :         823 : digraph::add_edge (const char *id,
     326                 :             :                    node &src_node,
     327                 :             :                    node &dst_node,
     328                 :             :                    const char *label)
     329                 :             : {
     330                 :         823 :   auto e = std::make_unique<digraph_edge> (*this,
     331                 :             :                                            id,
     332                 :             :                                            src_node,
     333                 :         823 :                                            dst_node);
     334                 :         823 :   if (label)
     335                 :         776 :     e->set_label (label);
     336                 :         823 :   add_edge (std::move (e));
     337                 :         823 : }
     338                 :             : 
     339                 :             : /* Utility function for edge ids: either use EDGE_ID, or
     340                 :             :    generate a unique one for when we don't care about the name.
     341                 :             : 
     342                 :             :    Edges in SARIF "SHALL" have an id that's unique within the graph
     343                 :             :    (SARIF 2.1.0 §3.41.2).  This is so that graph traversals can refer
     344                 :             :    to edges by id (SARIF 2.1.0's §3.43.2 edgeId property).  */
     345                 :             : 
     346                 :             : std::string
     347                 :         831 : digraph::make_edge_id (const char *edge_id)
     348                 :             : {
     349                 :             :   /* If we have an id, use it.  */
     350                 :         831 :   if (edge_id)
     351                 :           4 :     return edge_id;
     352                 :             : 
     353                 :             :   /* Otherwise, generate a unique one of the form "edgeN".  */
     354                 :         827 :   while (true)
     355                 :             :     {
     356                 :        1654 :       auto candidate (std::string ("edge")
     357                 :         827 :                       + std::to_string (m_next_edge_id_index++));
     358                 :         827 :       auto iter = m_id_to_edge_map.find (candidate);
     359                 :         827 :       if (iter != m_id_to_edge_map.end ())
     360                 :             :         {
     361                 :             :           // Try again with the next index...
     362                 :           0 :           continue;
     363                 :             :         }
     364                 :         827 :       return candidate;
     365                 :         827 :     }
     366                 :             : }
     367                 :             : 
     368                 :             : const char *
     369                 :           0 : digraph::get_graph_kind () const
     370                 :             : {
     371                 :           0 :   return get_property (properties::digraph::kind);
     372                 :             : }
     373                 :             : 
     374                 :             : void
     375                 :           0 : digraph::set_graph_kind (const char *kind)
     376                 :             : {
     377                 :           0 :   set_property (properties::digraph::kind, kind);
     378                 :           0 : }
     379                 :             : 
     380                 :             : // class node
     381                 :             : 
     382                 :             : DEBUG_FUNCTION void
     383                 :           0 : digraph_node::dump () const
     384                 :             : {
     385                 :           0 :   to_json_sarif_node ()->dump ();
     386                 :           0 : }
     387                 :             : 
     388                 :             : std::unique_ptr<json::object>
     389                 :           0 : digraph_node::to_json_sarif_node () const
     390                 :             : {
     391                 :           0 :   return make_sarif_node (*this, nullptr, nullptr);
     392                 :             : }
     393                 :             : 
     394                 :             : std::unique_ptr<digraph_node>
     395                 :           0 : digraph_node::clone (digraph &new_graph,
     396                 :             :                      std::map<node *, node *> &node_mapping) const
     397                 :             : {
     398                 :           0 :   auto result
     399                 :           0 :     = std::make_unique<digraph_node> (new_graph, get_id ());
     400                 :           0 :   node_mapping.insert ({const_cast <node *> (this), result.get ()});
     401                 :             : 
     402                 :           0 :   result->set_logical_loc (m_logical_loc);
     403                 :             : 
     404                 :           0 :   if (get_property_bag ())
     405                 :           0 :     result->set_property_bag (get_property_bag ()->clone_as_object ());
     406                 :             : 
     407                 :           0 :   for (auto &iter : m_children)
     408                 :           0 :     result->add_child (iter->clone (new_graph, node_mapping));
     409                 :             : 
     410                 :           0 :   return result;
     411                 :             : }
     412                 :             : 
     413                 :             : // class edge
     414                 :             : 
     415                 :             : std::unique_ptr<digraph_edge>
     416                 :           0 : digraph_edge::clone (digraph &new_graph,
     417                 :             :                      const std::map<node *, node *> &node_mapping) const
     418                 :             : {
     419                 :           0 :   auto iter_new_src = node_mapping.find (&m_src_node);
     420                 :           0 :   gcc_assert (iter_new_src != node_mapping.end ());
     421                 :           0 :   auto iter_new_dst = node_mapping.find (&m_dst_node);
     422                 :           0 :   gcc_assert (iter_new_dst != node_mapping.end ());
     423                 :           0 :   auto result
     424                 :             :     = std::make_unique<digraph_edge> (new_graph,
     425                 :           0 :                                       m_id.c_str (),
     426                 :           0 :                                       *iter_new_src->second,
     427                 :           0 :                                       *iter_new_dst->second);
     428                 :           0 :   if (get_property_bag ())
     429                 :           0 :     result->set_property_bag (get_property_bag ()->clone_as_object ());
     430                 :             : 
     431                 :           0 :   return result;
     432                 :             : }
     433                 :             : 
     434                 :             : DEBUG_FUNCTION void
     435                 :           0 : diagnostics::digraphs::edge::dump () const
     436                 :             : {
     437                 :           0 :   to_json_sarif_edge ()->dump ();
     438                 :           0 : }
     439                 :             : 
     440                 :             : std::unique_ptr<json::object>
     441                 :           0 : diagnostics::digraphs::edge::to_json_sarif_edge () const
     442                 :             : {
     443                 :           0 :   return make_sarif_edge (*this, nullptr);
     444                 :             : }
     445                 :             : 
     446                 :             : #if CHECKING_P
     447                 :             : 
     448                 :             : #include "selftest.h"
     449                 :             : #include "custom-sarif-properties/state-graphs.h"
     450                 :             : 
     451                 :             : namespace diagnostics {
     452                 :             : namespace selftest {
     453                 :             : 
     454                 :             : static void
     455                 :           4 : test_empty_graph ()
     456                 :             : {
     457                 :           4 :   digraph g;
     458                 :             : 
     459                 :           4 :   {
     460                 :           4 :     auto sarif = g.make_json_sarif_graph ();
     461                 :             : 
     462                 :           4 :     pretty_printer pp;
     463                 :           4 :     sarif->print (&pp, true);
     464                 :           4 :     ASSERT_STREQ
     465                 :             :       (pp_formatted_text (&pp),
     466                 :             :        ("{\"nodes\": [],\n"
     467                 :             :         " \"edges\": []}"));
     468                 :           4 :   }
     469                 :             : 
     470                 :           4 :   {
     471                 :           4 :     auto dg = g.make_dot_graph ();
     472                 :             : 
     473                 :           4 :     pretty_printer pp;
     474                 :           4 :     dot::writer w (pp);
     475                 :           4 :     dg->print (w);
     476                 :           4 :     ASSERT_STREQ
     477                 :             :       (pp_formatted_text (&pp),
     478                 :             :        ("digraph {\n"
     479                 :             :         "}\n"));
     480                 :           4 :   }
     481                 :           4 : }
     482                 :             : 
     483                 :             : static void
     484                 :           4 : test_simple_graph ()
     485                 :             : {
     486                 :             : #define KEY_PREFIX "/placeholder/"
     487                 :           4 :   auto g = std::make_unique<digraph> ();
     488                 :           4 :   g->set_description ("test graph");
     489                 :           4 :   g->set_property (json::string_property (KEY_PREFIX, "date"), "1066");
     490                 :             : 
     491                 :           4 :   auto a = std::make_unique<digraph_node> (*g, "a");
     492                 :           4 :   auto b = std::make_unique<digraph_node> (*g, "b");
     493                 :           4 :   b->set_property (json::string_property (KEY_PREFIX, "color"), "red");
     494                 :           4 :   auto c = std::make_unique<digraph_node> (*g, "c");
     495                 :           4 :   c->set_label ("I am a node label");
     496                 :             : 
     497                 :           4 :   auto e = std::make_unique<digraph_edge> (*g, nullptr, *a, *c);
     498                 :           4 :   e->set_property (json::string_property (KEY_PREFIX, "status"),
     499                 :             :                    "copacetic");
     500                 :           4 :   e->set_label ("I am an edge label");
     501                 :           4 :   g->add_edge (std::move (e));
     502                 :             : 
     503                 :           4 :   g->add_node (std::move (a));
     504                 :             : 
     505                 :           4 :   b->add_child (std::move (c));
     506                 :           4 :   g->add_node (std::move (b));
     507                 :             : #undef KEY_PREFIX
     508                 :             : 
     509                 :           4 :   {
     510                 :           4 :     auto sarif = g->make_json_sarif_graph ();
     511                 :             : 
     512                 :           4 :     pretty_printer pp;
     513                 :           4 :     sarif->print (&pp, true);
     514                 :           4 :     ASSERT_STREQ
     515                 :             :       (pp_formatted_text (&pp),
     516                 :             :        ("{\"properties\": {\"/placeholder/date\": \"1066\"},\n"
     517                 :             :         " \"nodes\": [{\"id\": \"a\"},\n"
     518                 :             :         "           {\"id\": \"b\",\n"
     519                 :             :         "            \"properties\": {\"/placeholder/color\": \"red\"},\n"
     520                 :             :         "            \"children\": [{\"id\": \"c\"}]}],\n"
     521                 :             :         " \"edges\": [{\"id\": \"edge0\",\n"
     522                 :             :         "            \"properties\": {\"/placeholder/status\": \"copacetic\"},\n"
     523                 :             :         "            \"sourceNodeId\": \"a\",\n"
     524                 :             :         "            \"targetNodeId\": \"c\"}]}"));
     525                 :           4 :   }
     526                 :             : 
     527                 :           4 :   {
     528                 :           4 :     auto dg = g->make_dot_graph ();
     529                 :             : 
     530                 :           4 :     pretty_printer pp;
     531                 :           4 :     dot::writer w (pp);
     532                 :           4 :     dg->print (w);
     533                 :           4 :     ASSERT_STREQ
     534                 :             :       (pp_formatted_text (&pp),
     535                 :             :        ("digraph {\n"
     536                 :             :         "    label=\"test graph\";\n"
     537                 :             :         "    a;\n"
     538                 :             :         "    \n"
     539                 :             :         "    subgraph cluster_b {\n"
     540                 :             :         "        c [label=\"I am a node label\"];\n"
     541                 :             :         "\n"
     542                 :             :         "    };\n"
     543                 :             :         "    a -> c [label=\"I am an edge label\"];\n"
     544                 :             :         "}\n"));
     545                 :           4 :   }
     546                 :           4 : }
     547                 :             : 
     548                 :             : static void
     549                 :           4 : test_property_objects ()
     550                 :             : {
     551                 :           4 :   namespace state_node_properties = custom_sarif_properties::state_graphs::node;
     552                 :             : 
     553                 :           4 :   digraph g;
     554                 :           4 :   digraph_node node (g, "a");
     555                 :             : 
     556                 :           4 :   ASSERT_EQ (node.get_property (state_node_properties::kind_prop),
     557                 :             :              state_node_properties::kind_t::other);
     558                 :           4 :   node.set_property (state_node_properties::kind_prop,
     559                 :             :                      state_node_properties::kind_t::stack);
     560                 :           4 :   ASSERT_EQ (node.get_property (state_node_properties::kind_prop),
     561                 :             :              state_node_properties::kind_t::stack);
     562                 :             : 
     563                 :           4 :   ASSERT_EQ (node.get_property (state_node_properties::dynalloc_state_prop),
     564                 :             :              state_node_properties::dynalloc_state_t::unknown);
     565                 :           4 :   node.set_property (state_node_properties::dynalloc_state_prop,
     566                 :             :                      state_node_properties::dynalloc_state_t::freed);
     567                 :           4 :   ASSERT_EQ (node.get_property (state_node_properties::dynalloc_state_prop),
     568                 :             :              state_node_properties::dynalloc_state_t::freed);
     569                 :             : 
     570                 :           4 :   ASSERT_EQ (node.get_property (state_node_properties::type), nullptr);
     571                 :           4 :   node.set_property (state_node_properties::type, "const char *");
     572                 :           4 :   ASSERT_STREQ (node.get_property (state_node_properties::type),
     573                 :             :                 "const char *");
     574                 :           4 : }
     575                 :             : 
     576                 :             : /* Run all of the selftests within this file.  */
     577                 :             : 
     578                 :             : void
     579                 :           4 : digraphs_cc_tests ()
     580                 :             : {
     581                 :           4 :   test_empty_graph ();
     582                 :           4 :   test_simple_graph ();
     583                 :           4 :   test_property_objects ();
     584                 :           4 : }
     585                 :             : 
     586                 :             : } // namespace diagnostics::selftest
     587                 :             : } // namespace diagnostics
     588                 :             : 
     589                 :             : #endif /* CHECKING_P */
        

Generated by: LCOV version 2.1-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.