| OLD | NEW |
| (Empty) |
| 1 #library('TestUtils'); | |
| 2 | |
| 3 /** | |
| 4 * Verifies that [actual] has the same graph structure as [expected]. | |
| 5 * Detects cycles and DAG structure in Maps and Lists. | |
| 6 */ | |
| 7 verifyGraph(expected, actual) { | |
| 8 var eItems = []; | |
| 9 var aItems = []; | |
| 10 | |
| 11 message(path, reason) => path == '' | |
| 12 ? reason | |
| 13 : reason == null ? "path: $path" : "path: $path, $reason"; | |
| 14 | |
| 15 walk(path, expected, actual) { | |
| 16 if (expected is String || expected is num || expected == null) { | |
| 17 Expect.equals(expected, actual, message(path, 'not equal')); | |
| 18 return; | |
| 19 } | |
| 20 | |
| 21 // Cycle or DAG? | |
| 22 for (int i = 0; i < eItems.length; i++) { | |
| 23 if (expected === eItems[i]) { | |
| 24 Expect.identical(aItems[i], actual, message(path, 'back or side edge')); | |
| 25 return; | |
| 26 } | |
| 27 } | |
| 28 eItems.add(expected); | |
| 29 aItems.add(actual); | |
| 30 | |
| 31 if (expected is List) { | |
| 32 Expect.isTrue(actual is List, message(path, '$actual is List')); | |
| 33 Expect.equals(expected.length, actual.length, | |
| 34 message(path, 'different list lengths')); | |
| 35 for (var i = 0; i < expected.length; i++) { | |
| 36 walk('$path[$i]', expected[i], actual[i]); | |
| 37 } | |
| 38 return; | |
| 39 } | |
| 40 | |
| 41 if (expected is Map) { | |
| 42 Expect.isTrue(actual is Map, message(path, '$actual is Map')); | |
| 43 for (var key in expected.getKeys()) { | |
| 44 if (!actual.containsKey(key)) { | |
| 45 Expect.fail(message(path, 'missing key "$key"')); | |
| 46 } | |
| 47 walk('$path["$key"]', expected[key], actual[key]); | |
| 48 } | |
| 49 for (var key in actual.getKeys()) { | |
| 50 if (!expected.containsKey(key)) { | |
| 51 Expect.fail(message(path, 'extra key "$key"')); | |
| 52 } | |
| 53 } | |
| 54 return; | |
| 55 } | |
| 56 | |
| 57 Expect.fail('Unhandled type: $expected'); | |
| 58 } | |
| 59 | |
| 60 walk('', expected, actual); | |
| 61 } | |
| OLD | NEW |