OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import "package:test/test.dart"; |
| 6 |
| 7 import "package:collection/collection.dart"; |
| 8 |
| 9 void main() { |
| 10 group("mapMap()", () { |
| 11 test("with an empty map returns an empty map", () { |
| 12 expect( |
| 13 mapMap({}, |
| 14 key: expectAsync2((_, __) {}, count: 0), |
| 15 value: expectAsync2((_, __) {}, count: 0)), |
| 16 isEmpty); |
| 17 }); |
| 18 |
| 19 test("with no callbacks, returns a copy of the map", () { |
| 20 var map = {"foo": 1, "bar": 2}; |
| 21 var result = mapMap(map); |
| 22 expect(result, equals({"foo": 1, "bar": 2})); |
| 23 |
| 24 // The resulting map should be a copy. |
| 25 result["foo"] = 3; |
| 26 expect(map, equals({"foo": 1, "bar": 2})); |
| 27 }); |
| 28 |
| 29 test("maps the map's keys", () { |
| 30 expect(mapMap({"foo": 1, "bar": 2}, key: (key, value) => key[value]), |
| 31 equals({"o": 1, "r": 2})); |
| 32 }); |
| 33 |
| 34 test("maps the map's values", () { |
| 35 expect(mapMap({"foo": 1, "bar": 2}, value: (key, value) => key[value]), |
| 36 equals({"foo": "o", "bar": "r"})); |
| 37 }); |
| 38 |
| 39 test("maps both the map's keys and values", () { |
| 40 expect( |
| 41 mapMap({"foo": 1, "bar": 2}, |
| 42 key: (key, value) => "$key$value", |
| 43 value: (key, value) => key[value]), |
| 44 equals({"foo1": "o", "bar2": "r"})); |
| 45 }); |
| 46 }); |
| 47 |
| 48 group("mergeMaps()", () { |
| 49 test("with empty maps returns an empty map", () { |
| 50 expect(mergeMaps({}, {}, value: expectAsync2((_, __) {}, count: 0)), |
| 51 isEmpty); |
| 52 }); |
| 53 |
| 54 test("returns a map with all values in both input maps", () { |
| 55 expect(mergeMaps({"foo": 1, "bar": 2}, {"baz": 3, "qux": 4}), |
| 56 equals({"foo": 1, "bar": 2, "baz": 3, "qux": 4})); |
| 57 }); |
| 58 |
| 59 test("the second map's values win by default", () { |
| 60 expect(mergeMaps({"foo": 1, "bar": 2}, {"bar": 3, "baz": 4}), |
| 61 equals({"foo": 1, "bar": 3, "baz": 4})); |
| 62 }); |
| 63 |
| 64 test("uses the callback to merge values", () { |
| 65 expect( |
| 66 mergeMaps({"foo": 1, "bar": 2}, {"bar": 3, "baz": 4}, |
| 67 value: (value1, value2) => value1 + value2), |
| 68 equals({"foo": 1, "bar": 5, "baz": 4})); |
| 69 }); |
| 70 }); |
| 71 |
| 72 group("groupBy()", () { |
| 73 test("returns an empty map for an empty iterable", () { |
| 74 expect(groupBy([], expectAsync1((_) {}, count: 0)), isEmpty); |
| 75 }); |
| 76 |
| 77 test("groups elements by the function's return value", () { |
| 78 expect( |
| 79 groupBy(["foo", "bar", "baz", "bop", "qux"], (string) => string[1]), |
| 80 equals({ |
| 81 "o": ["foo", "bop"], |
| 82 "a": ["bar", "baz"], |
| 83 "u": ["qux"] |
| 84 })); |
| 85 }); |
| 86 }); |
| 87 |
| 88 group("minBy()", () { |
| 89 test("returns null for an empty iterable", () { |
| 90 expect( |
| 91 minBy([], expectAsync1((_) {}, count: 0), |
| 92 compare: expectAsync2((_, __) {}, count: 0)), |
| 93 isNull); |
| 94 }); |
| 95 |
| 96 test( |
| 97 "returns the element for which the ordering function returns the " |
| 98 "smallest value", () { |
| 99 expect( |
| 100 minBy([ |
| 101 {"foo": 3}, |
| 102 {"foo": 5}, |
| 103 {"foo": 4}, |
| 104 {"foo": 1}, |
| 105 {"foo": 2} |
| 106 ], (map) => map["foo"]), |
| 107 equals({"foo": 1})); |
| 108 }); |
| 109 |
| 110 test("uses a custom comparator if provided", () { |
| 111 expect( |
| 112 minBy([ |
| 113 {"foo": 3}, |
| 114 {"foo": 5}, |
| 115 {"foo": 4}, |
| 116 {"foo": 1}, |
| 117 {"foo": 2} |
| 118 ], (map) => map, |
| 119 compare: (map1, map2) => map1["foo"].compareTo(map2["foo"])), |
| 120 equals({"foo": 1})); |
| 121 }); |
| 122 }); |
| 123 |
| 124 group("maxBy()", () { |
| 125 test("returns null for an empty iterable", () { |
| 126 expect( |
| 127 maxBy([], expectAsync1((_) {}, count: 0), |
| 128 compare: expectAsync2((_, __) {}, count: 0)), |
| 129 isNull); |
| 130 }); |
| 131 |
| 132 test( |
| 133 "returns the element for which the ordering function returns the " |
| 134 "largest value", () { |
| 135 expect( |
| 136 maxBy([ |
| 137 {"foo": 3}, |
| 138 {"foo": 5}, |
| 139 {"foo": 4}, |
| 140 {"foo": 1}, |
| 141 {"foo": 2} |
| 142 ], (map) => map["foo"]), |
| 143 equals({"foo": 5})); |
| 144 }); |
| 145 |
| 146 test("uses a custom comparator if provided", () { |
| 147 expect( |
| 148 maxBy([ |
| 149 {"foo": 3}, |
| 150 {"foo": 5}, |
| 151 {"foo": 4}, |
| 152 {"foo": 1}, |
| 153 {"foo": 2} |
| 154 ], (map) => map, |
| 155 compare: (map1, map2) => map1["foo"].compareTo(map2["foo"])), |
| 156 equals({"foo": 5})); |
| 157 }); |
| 158 }); |
| 159 |
| 160 group("transitiveClosure()", () { |
| 161 test("returns an empty map for an empty graph", () { |
| 162 expect(transitiveClosure({}), isEmpty); |
| 163 }); |
| 164 |
| 165 test("returns the input when there are no transitive connections", () { |
| 166 expect( |
| 167 transitiveClosure({ |
| 168 "foo": ["bar"], |
| 169 "bar": [], |
| 170 "bang": ["qux", "zap"], |
| 171 "qux": [], |
| 172 "zap": [] |
| 173 }), |
| 174 equals({ |
| 175 "foo": ["bar"], |
| 176 "bar": [], |
| 177 "bang": ["qux", "zap"], |
| 178 "qux": [], |
| 179 "zap": [] |
| 180 })); |
| 181 }); |
| 182 |
| 183 test("flattens transitive connections", () { |
| 184 expect( |
| 185 transitiveClosure({ |
| 186 "qux": [], |
| 187 "bar": ["baz"], |
| 188 "baz": ["qux"], |
| 189 "foo": ["bar"] |
| 190 }), |
| 191 equals({ |
| 192 "foo": ["bar", "baz", "qux"], |
| 193 "bar": ["baz", "qux"], |
| 194 "baz": ["qux"], |
| 195 "qux": [] |
| 196 })); |
| 197 }); |
| 198 |
| 199 test("handles loops", () { |
| 200 expect( |
| 201 transitiveClosure({ |
| 202 "foo": ["bar"], |
| 203 "bar": ["baz"], |
| 204 "baz": ["foo"] |
| 205 }), |
| 206 equals({ |
| 207 "foo": ["bar", "baz", "foo"], |
| 208 "bar": ["baz", "foo", "bar"], |
| 209 "baz": ["foo", "bar", "baz"] |
| 210 })); |
| 211 }); |
| 212 }); |
| 213 |
| 214 group("stronglyConnectedComponents()", () { |
| 215 test("returns an empty list for an empty graph", () { |
| 216 expect(stronglyConnectedComponents({}), isEmpty); |
| 217 }); |
| 218 |
| 219 test("returns one set for a singleton graph", () { |
| 220 expect( |
| 221 stronglyConnectedComponents({"a": []}), |
| 222 equals([ |
| 223 new Set.from(["a"]) |
| 224 ])); |
| 225 }); |
| 226 |
| 227 test("returns two sets for a two-element tree", () { |
| 228 expect( |
| 229 stronglyConnectedComponents({ |
| 230 "a": ["b"], |
| 231 "b": [] |
| 232 }), |
| 233 equals([ |
| 234 new Set.from(["a"]), |
| 235 new Set.from(["b"]) |
| 236 ])); |
| 237 }); |
| 238 |
| 239 test("returns one set for a two-element loop", () { |
| 240 expect( |
| 241 stronglyConnectedComponents({ |
| 242 "a": ["b"], |
| 243 "b": ["a"] |
| 244 }), |
| 245 equals([ |
| 246 new Set.from(["a", "b"]) |
| 247 ])); |
| 248 }); |
| 249 |
| 250 test("returns individual vertices for a tree", () { |
| 251 expect( |
| 252 stronglyConnectedComponents({ |
| 253 "foo": ["bar"], |
| 254 "bar": ["baz", "bang"], |
| 255 "baz": ["qux"], |
| 256 "bang": ["zap"], |
| 257 "qux": [], |
| 258 "zap": [] |
| 259 }), |
| 260 equals([ |
| 261 // This is expected to return *a* topological ordering, but this isn
't |
| 262 // the only valid one. If the function implementation changes in the |
| 263 // future, this test may need to be updated. |
| 264 new Set.from(["foo"]), |
| 265 new Set.from(["bar"]), |
| 266 new Set.from(["bang"]), |
| 267 new Set.from(["zap"]), |
| 268 new Set.from(["baz"]), |
| 269 new Set.from(["qux"]) |
| 270 ])); |
| 271 }); |
| 272 |
| 273 test("returns a single set for a fully cyclic graph", () { |
| 274 expect( |
| 275 stronglyConnectedComponents({ |
| 276 "foo": ["bar"], |
| 277 "bar": ["baz"], |
| 278 "baz": ["bang"], |
| 279 "bang": ["foo"] |
| 280 }), |
| 281 equals([ |
| 282 new Set.from(["foo", "bar", "baz", "bang"]) |
| 283 ])); |
| 284 }); |
| 285 |
| 286 test("returns separate sets for each strongly connected component", () { |
| 287 // https://en.wikipedia.org/wiki/Strongly_connected_component#/media/File:
Scc.png |
| 288 expect( |
| 289 stronglyConnectedComponents({ |
| 290 "a": ["b"], |
| 291 "b": ["c", "e", "f"], |
| 292 "c": ["d", "g"], |
| 293 "d": ["c", "h"], |
| 294 "e": ["a", "f"], |
| 295 "f": ["g"], |
| 296 "g": ["f"], |
| 297 "h": ["g", "d"] |
| 298 }), |
| 299 equals([ |
| 300 // This is expected to return *a* topological ordering, but this isn
't |
| 301 // the only valid one. If the function implementation changes in the |
| 302 // future, this test may need to be updated. |
| 303 new Set.from(["a", "b", "e"]), |
| 304 new Set.from(["c", "d", "h"]), |
| 305 new Set.from(["f", "g"]), |
| 306 ])); |
| 307 }); |
| 308 |
| 309 test("always returns components in topological order", () { |
| 310 expect( |
| 311 stronglyConnectedComponents({ |
| 312 "bar": ["baz", "bang"], |
| 313 "zap": [], |
| 314 "baz": ["qux"], |
| 315 "qux": [], |
| 316 "foo": ["bar"], |
| 317 "bang": ["zap"] |
| 318 }), |
| 319 equals([ |
| 320 // This is expected to return *a* topological ordering, but this isn
't |
| 321 // the only valid one. If the function implementation changes in the |
| 322 // future, this test may need to be updated. |
| 323 new Set.from(["foo"]), |
| 324 new Set.from(["bar"]), |
| 325 new Set.from(["bang"]), |
| 326 new Set.from(["zap"]), |
| 327 new Set.from(["baz"]), |
| 328 new Set.from(["qux"]) |
| 329 ])); |
| 330 }); |
| 331 }); |
| 332 } |
OLD | NEW |