go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/graph/testdata/descendants.star (about)

     1  def test_descendants():
     2      g = new_graph()
     3  
     4      def node(name):
     5          k = g.key("node", name)
     6          g.add_node(k, idempotent = True)
     7          return k
     8  
     9      def edge(parent, child):
    10          g.add_edge(node(parent), node(child))
    11  
    12      root = node("root")
    13  
    14      edge("root", "3")
    15      edge("root", "2")
    16      edge("root", "1")
    17      edge("1", "1_1")
    18      edge("1_1", "leaf")
    19      edge("2", "leaf")
    20  
    21      g.finalize()
    22  
    23      # Redefine 'node' to return graph.node now, to make assertions below look
    24      # less cluttered.
    25      def node(name):
    26          return g.node(g.key("node", name))
    27  
    28      # Works without visitor callback: just returns all descendants.
    29  
    30      # In 'key' order, breadth first (default).
    31      assert.eq(g.descendants(root), [
    32          node("root"),
    33          node("1"),
    34          node("2"),
    35          node("3"),
    36          node("1_1"),
    37          node("leaf"),
    38      ])
    39  
    40      # In reverse 'key' order, breadth first.
    41      assert.eq(g.descendants(root, order_by = "~key"), [
    42          node("root"),
    43          node("3"),
    44          node("2"),
    45          node("1"),
    46          node("leaf"),
    47          node("1_1"),
    48      ])
    49  
    50      # In 'def' order, breadth first.
    51      assert.eq(g.descendants(root, order_by = "def"), [
    52          node("root"),
    53          node("3"),
    54          node("2"),
    55          node("1"),
    56          node("leaf"),
    57          node("1_1"),
    58      ])
    59  
    60      # In reverse 'def' order, breadth first.
    61      assert.eq(g.descendants(root, order_by = "~def"), [
    62          node("root"),
    63          node("1"),
    64          node("2"),
    65          node("3"),
    66          node("1_1"),
    67          node("leaf"),
    68      ])
    69  
    70      # In 'key' order, depth first.
    71      assert.eq(g.descendants(root, topology = "depth"), [
    72          node("leaf"),
    73          node("1_1"),
    74          node("1"),
    75          node("2"),
    76          node("3"),
    77          node("root"),
    78      ])
    79  
    80      # In reverse 'key' order, depth first.
    81      assert.eq(g.descendants(root, order_by = "~key", topology = "depth"), [
    82          node("3"),
    83          node("leaf"),
    84          node("2"),
    85          node("1_1"),
    86          node("1"),
    87          node("root"),
    88      ])
    89  
    90      # In 'def' order, depth first.
    91      assert.eq(g.descendants(root, order_by = "def", topology = "depth"), [
    92          node("3"),
    93          node("leaf"),
    94          node("2"),
    95          node("1_1"),
    96          node("1"),
    97          node("root"),
    98      ])
    99  
   100      # In reverse 'def' order, depth first.
   101      assert.eq(g.descendants(root, order_by = "~def", topology = "depth"), [
   102          node("leaf"),
   103          node("1_1"),
   104          node("1"),
   105          node("2"),
   106          node("3"),
   107          node("root"),
   108      ])
   109  
   110      # Just visit everything and see what we get in each individual call.
   111  
   112      # In 'key' order (default).
   113      visited = []
   114  
   115      def visitor(node, children):
   116          visited.append((node, children))
   117          return children
   118  
   119      g.descendants(root, visitor)
   120      assert.eq(visited, [
   121          (node("root"), [node("1"), node("2"), node("3")]),
   122          (node("1"), [node("1_1")]),
   123          (node("2"), [node("leaf")]),
   124          (node("3"), []),
   125          (node("1_1"), [node("leaf")]),
   126          (node("leaf"), []),  # visited only once
   127      ])
   128  
   129      # In 'def' order.
   130      visited = []
   131  
   132      def visitor(node, children):
   133          visited.append((node, children))
   134          return children
   135  
   136      g.descendants(root, visitor, "def")
   137      assert.eq(visited, [
   138          (node("root"), [node("3"), node("2"), node("1")]),
   139          (node("3"), []),
   140          (node("2"), [node("leaf")]),
   141          (node("1"), [node("1_1")]),
   142          (node("leaf"), []),  # visited only once
   143          (node("1_1"), [node("leaf")]),
   144      ])
   145  
   146      # Verify we can select what to visit.
   147  
   148      visited = []
   149  
   150      def visitor(node, children):
   151          visited.append((node, children))
   152          return [children[0]] if children else []
   153  
   154      assert.eq(g.descendants(root, visitor), [
   155          node("root"),
   156          node("1"),
   157          node("1_1"),
   158          node("leaf"),
   159      ])
   160      assert.eq(visited, [
   161          (node("root"), [node("1"), node("2"), node("3")]),
   162          (node("1"), [node("1_1")]),
   163          (node("1_1"), [node("leaf")]),
   164          (node("leaf"), []),
   165      ])
   166  
   167      # Checks the type of the return value, allows only subset of 'children'.
   168  
   169      def visitor(node, children):
   170          return "huh"
   171  
   172      assert.fails(
   173          lambda: g.descendants(root, visitor),
   174          "unexpectedly returned string instead of a list",
   175      )
   176  
   177      def visitor(node, children):
   178          return children + ["huh"]
   179  
   180      assert.fails(
   181          lambda: g.descendants(root, visitor),
   182          "unexpectedly returned string as element #3 instead of a graph.node",
   183      )
   184  
   185      def visitor(node, children):
   186          return [node]
   187  
   188      assert.fails(
   189          lambda: g.descendants(root, visitor),
   190          r'unexpectedly returned node\("root"\) which is not a child of node\("root"\)',
   191      )
   192  
   193  test_descendants()