go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/testdata/misc/triggerer.star (about) 1 load("@stdlib//internal/graph.star", "graph") 2 load("@stdlib//internal/luci/common.star", "builder_ref", "keys", "triggerer") 3 4 ### Toy builder+poller model. 5 6 def builder(bucket, name, triggered_by = [], triggers = []): 7 k = keys.builder(bucket, name) 8 graph.add_node(k) 9 ref = builder_ref.add(k) 10 trg = triggerer.add(k) 11 for t in triggered_by: 12 graph.add_edge(keys.triggerer(t), ref) 13 for t in triggers: 14 graph.add_edge(trg, keys.builder_ref(t)) 15 return k 16 17 def poller(bucket, name, triggers = []): 18 k = keys.gitiles_poller(bucket, name) 19 graph.add_node(k) 20 trg = triggerer.add(k) 21 for t in triggers: 22 graph.add_edge(trg, keys.builder_ref(t)) 23 return k 24 25 def targets(poller_key): 26 return [n.key for n in triggerer.targets(graph.node(poller_key))] 27 28 ### Test cases. 29 30 def test_triggers(): 31 p1 = poller("buck", "p1", triggers = ["buck1/b1", "b2"]) 32 p2 = poller("buck", "p2", triggers = ["b2"]) 33 p3 = poller("buck", "p3") 34 b1 = builder("buck1", "b1") 35 b2 = builder("buck2", "b2") 36 __native__.graph().finalize() 37 assert.eq(targets(p1), [b1, b2]) 38 assert.eq(targets(p2), [b2]) 39 assert.eq(targets(p3), []) 40 41 def test_triggered_by(): 42 p1 = poller("buck", "p1") 43 p2 = poller("buck", "p2") 44 b1 = builder("buck1", "b1", triggered_by = ["buck/p1"]) 45 b2 = builder("buck2", "b2", triggered_by = ["p1", "p2"]) 46 __native__.graph().finalize() 47 assert.eq(targets(p1), [b1, b2]) 48 assert.eq(targets(p2), [b2]) 49 50 def test_both_directions_not_an_error(): 51 p1 = poller("buck", "p1", triggers = ["buck1/b1", "b2"]) 52 b1 = builder("buck1", "b1", triggered_by = ["p1"]) 53 b2 = builder("buck2", "b2", triggered_by = ["buck/p1"]) 54 __native__.graph().finalize() 55 assert.eq(targets(p1), [b1, b2]) 56 57 def test_ambiguous_builder_ref(): 58 p = poller("buck", "p", triggers = ["b"]) 59 b1 = builder("buck1", "b") 60 b2 = builder("buck2", "b") 61 __native__.graph().finalize() 62 assert.fails( 63 lambda: targets(p), 64 r'ambiguous reference "b" in luci.gitiles_poller\("buck/p"\), possible variants:\n' + 65 r' luci.builder\("buck1/b"\)\n' + 66 r' luci.builder\("buck2/b"\)', 67 ) 68 69 def test_ambiguous_triggerer(): 70 p1 = poller("buck1", "p") 71 p2 = poller("buck2", "p") 72 bp = builder("buck3", "p") 73 b = builder("buck", "b", triggered_by = ["p"]) 74 __native__.graph().finalize() 75 err_re = ( 76 r'ambiguous reference "p" in luci.builder\("buck/b"\), possible variants:\n' + 77 r' luci.gitiles_poller\("buck1/p"\)\n' + 78 r' luci.gitiles_poller\("buck2/p"\)\n' + 79 r' luci.builder\("buck3/p"\)' 80 ) 81 assert.fails(lambda: targets(p1), err_re) 82 assert.fails(lambda: targets(p2), err_re) 83 84 def test_triggering_cycle(): 85 builder("buck", "b1", triggers = ["b2"]) 86 assert.fails( 87 lambda: builder("buck", "b2", triggers = ["b1"]), 88 "introduces a cycle", 89 ) 90 91 ### Test runner. 92 93 def with_clean_state(cbs): 94 for cb in cbs: 95 __native__.clear_state() 96 __native__.fail_on_errors() 97 cb() 98 99 with_clean_state([ 100 test_triggers, 101 test_triggered_by, 102 test_both_directions_not_an_error, 103 test_ambiguous_builder_ref, 104 test_ambiguous_triggerer, 105 test_triggering_cycle, 106 ])