| OLD | NEW |
| (Empty) | |
| 1 import 'package:front_end/src/dependency_walker.dart'; |
| 2 import 'package:test/test.dart'; |
| 3 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 4 |
| 5 main() { |
| 6 defineReflectiveSuite(() { |
| 7 defineReflectiveTests(DependencyWalkerTest); |
| 8 }); |
| 9 } |
| 10 |
| 11 @reflectiveTest |
| 12 class DependencyWalkerTest { |
| 13 final nodes = <String, TestNode>{}; |
| 14 |
| 15 void checkGraph(Map<String, List<String>> graph, String startingNodeName, |
| 16 List<List<String>> expectedEvaluations, List<bool> expectedSccFlags) { |
| 17 makeGraph(graph); |
| 18 var walker = walk(startingNodeName); |
| 19 expect(walker._evaluations, expectedEvaluations.map((x) => x.toSet())); |
| 20 expect(walker._sccFlags, expectedSccFlags); |
| 21 } |
| 22 |
| 23 TestNode getNode(String name) => |
| 24 nodes.putIfAbsent(name, () => new TestNode(name)); |
| 25 |
| 26 void makeGraph(Map<String, List<String>> graph) { |
| 27 graph.forEach((name, deps) { |
| 28 var node = getNode(name); |
| 29 for (var dep in deps) { |
| 30 node._dependencies.add(getNode(dep)); |
| 31 } |
| 32 }); |
| 33 } |
| 34 |
| 35 void test_complex_graph() { |
| 36 checkGraph( |
| 37 { |
| 38 'a': ['b', 'c'], |
| 39 'b': ['c', 'd'], |
| 40 'c': [], |
| 41 'd': ['c', 'e'], |
| 42 'e': ['b', 'f'], |
| 43 'f': ['c', 'd'] |
| 44 }, |
| 45 'a', |
| 46 [ |
| 47 ['c'], |
| 48 ['b', 'd', 'e', 'f'], |
| 49 ['a'] |
| 50 ], |
| 51 [false, true, false]); |
| 52 } |
| 53 |
| 54 void test_diamond() { |
| 55 checkGraph( |
| 56 { |
| 57 'a': ['b', 'c'], |
| 58 'b': ['d'], |
| 59 'c': ['d'], |
| 60 'd': [] |
| 61 }, |
| 62 'a', |
| 63 [ |
| 64 ['d'], |
| 65 ['b'], |
| 66 ['c'], |
| 67 ['a'] |
| 68 ], |
| 69 [false, false, false, false]); |
| 70 } |
| 71 |
| 72 void test_singleNode() { |
| 73 checkGraph( |
| 74 {'a': []}, |
| 75 'a', |
| 76 [ |
| 77 ['a'] |
| 78 ], |
| 79 [false]); |
| 80 } |
| 81 |
| 82 void test_singleNodeWithTrivialCycle() { |
| 83 checkGraph( |
| 84 { |
| 85 'a': ['a'] |
| 86 }, |
| 87 'a', |
| 88 [ |
| 89 ['a'] |
| 90 ], |
| 91 [true]); |
| 92 } |
| 93 |
| 94 void test_threeNodesWithCircularDependency() { |
| 95 checkGraph( |
| 96 { |
| 97 'a': ['b'], |
| 98 'b': ['c'], |
| 99 'c': ['a'], |
| 100 }, |
| 101 'a', |
| 102 [ |
| 103 ['a', 'b', 'c'] |
| 104 ], |
| 105 [true]); |
| 106 } |
| 107 |
| 108 test_twoBacklinksEarlierFirst() { |
| 109 // Test a graph A->B->C->D, where D points back to B and then C. |
| 110 checkGraph( |
| 111 { |
| 112 'a': ['b'], |
| 113 'b': ['c'], |
| 114 'c': ['d'], |
| 115 'd': ['b', 'c'] |
| 116 }, |
| 117 'a', |
| 118 [ |
| 119 ['b', 'c', 'd'], |
| 120 ['a'] |
| 121 ], |
| 122 [true, false]); |
| 123 } |
| 124 |
| 125 test_twoBacklinksLaterFirst() { |
| 126 // Test a graph A->B->C->D, where D points back to C and then B. |
| 127 checkGraph( |
| 128 { |
| 129 'a': ['b'], |
| 130 'b': ['c'], |
| 131 'c': ['d'], |
| 132 'd': ['c', 'b'] |
| 133 }, |
| 134 'a', |
| 135 [ |
| 136 ['b', 'c', 'd'], |
| 137 ['a'] |
| 138 ], |
| 139 [true, false]); |
| 140 } |
| 141 |
| 142 void test_twoNodesWithCircularDependency() { |
| 143 checkGraph( |
| 144 { |
| 145 'a': ['b'], |
| 146 'b': ['a'] |
| 147 }, |
| 148 'a', |
| 149 [ |
| 150 ['a', 'b'] |
| 151 ], |
| 152 [true]); |
| 153 } |
| 154 |
| 155 void test_twoNodesWithSimpleDependency() { |
| 156 checkGraph( |
| 157 { |
| 158 'a': ['b'], |
| 159 'b': [] |
| 160 }, |
| 161 'a', |
| 162 [ |
| 163 ['b'], |
| 164 ['a'] |
| 165 ], |
| 166 [false, false]); |
| 167 } |
| 168 |
| 169 TestWalker walk(String startingNodeName) => |
| 170 new TestWalker()..walk(getNode(startingNodeName)); |
| 171 } |
| 172 |
| 173 class TestNode extends Node<TestNode> { |
| 174 final String _name; |
| 175 |
| 176 @override |
| 177 bool isEvaluated = false; |
| 178 |
| 179 bool _computeDependenciesCalled = false; |
| 180 |
| 181 final _dependencies = <TestNode>[]; |
| 182 |
| 183 TestNode(this._name); |
| 184 |
| 185 @override |
| 186 List<TestNode> computeDependencies() { |
| 187 expect(_computeDependenciesCalled, false); |
| 188 _computeDependenciesCalled = true; |
| 189 return _dependencies; |
| 190 } |
| 191 } |
| 192 |
| 193 class TestWalker extends DependencyWalker<TestNode> { |
| 194 final _evaluations = <Set<String>>[]; |
| 195 final _sccFlags = <bool>[]; |
| 196 |
| 197 @override |
| 198 void evaluate(TestNode v) { |
| 199 v.isEvaluated = true; |
| 200 _evaluations.add([v._name].toSet()); |
| 201 _sccFlags.add(false); |
| 202 } |
| 203 |
| 204 @override |
| 205 void evaluateScc(List<TestNode> scc) { |
| 206 for (var v in scc) { |
| 207 v.isEvaluated = true; |
| 208 } |
| 209 var sccNames = scc.map((node) => node._name).toSet(); |
| 210 // Make sure there were no duplicates |
| 211 expect(sccNames.length, scc.length); |
| 212 _evaluations.add(sccNames); |
| 213 _sccFlags.add(true); |
| 214 } |
| 215 } |
| OLD | NEW |