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()