OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011, 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 // Test the basic StreamController and StreamController.singleSubscription. |
| 6 library stream_controller_test; |
| 7 |
| 8 import "package:expect/expect.dart"; |
| 9 import "package:async_helper/async_helper.dart"; |
| 10 import 'dart:async'; |
| 11 import 'event_helper.dart'; |
| 12 |
| 13 const MS = const Duration(milliseconds: 1); |
| 14 |
| 15 fail(e) { Expect.fail("Unexepected error: $e"); } |
| 16 |
| 17 void testMultiController() { |
| 18 // Test normal flow. |
| 19 { |
| 20 var c = new StreamController(sync: true); |
| 21 Events expectedEvents = new Events() |
| 22 ..add(42) |
| 23 ..add("dibs") |
| 24 ..error("error!") |
| 25 ..error("error too!") |
| 26 ..close(); |
| 27 CaptureEvents actualEvents = |
| 28 new Events.capture(c.stream.asBroadcastStream()); |
| 29 expectedEvents.replay(c); |
| 30 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 31 } |
| 32 |
| 33 // Test automatic unsubscription on error. |
| 34 { |
| 35 var c = new StreamController(sync: true); |
| 36 var expectedEvents = new Events()..add(42)..error("error"); |
| 37 var actualEvents = new Events.capture(c.stream.asBroadcastStream(), |
| 38 cancelOnError: true); |
| 39 Events sentEvents = |
| 40 new Events()..add(42)..error("error")..add("Are you there?"); |
| 41 sentEvents.replay(c); |
| 42 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 43 } |
| 44 |
| 45 // Test manual unsubscription. |
| 46 { |
| 47 var c = new StreamController(sync: true); |
| 48 var expectedEvents = new Events()..add(42)..error("error")..add(37); |
| 49 var actualEvents = new Events.capture(c.stream.asBroadcastStream(), |
| 50 cancelOnError: false); |
| 51 expectedEvents.replay(c); |
| 52 actualEvents.subscription.cancel(); |
| 53 c.add("Are you there"); // Not sent to actualEvents. |
| 54 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 55 } |
| 56 |
| 57 // Test filter. |
| 58 { |
| 59 var c = new StreamController(sync: true); |
| 60 var expectedEvents = new Events() |
| 61 ..add("a string")..add("another string")..close(); |
| 62 var sentEvents = new Events() |
| 63 ..add("a string")..add(42)..add("another string")..close(); |
| 64 var actualEvents = new Events.capture(c.stream |
| 65 .asBroadcastStream() |
| 66 .where((v) => v is String)); |
| 67 sentEvents.replay(c); |
| 68 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 69 } |
| 70 |
| 71 // Test map. |
| 72 { |
| 73 var c = new StreamController(sync: true); |
| 74 var expectedEvents = new Events()..add("abab")..error("error")..close(); |
| 75 var sentEvents = new Events()..add("ab")..error("error")..close(); |
| 76 var actualEvents = new Events.capture(c.stream |
| 77 .asBroadcastStream() |
| 78 .map((v) => "$v$v")); |
| 79 sentEvents.replay(c); |
| 80 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 81 } |
| 82 |
| 83 // Test handleError. |
| 84 { |
| 85 var c = new StreamController(sync: true); |
| 86 var expectedEvents = new Events()..add("ab")..error("[foo]"); |
| 87 var sentEvents = new Events()..add("ab")..error("foo")..add("ab")..close(); |
| 88 var actualEvents = new Events.capture(c.stream |
| 89 .asBroadcastStream() |
| 90 .handleError((error) { |
| 91 if (error is String) { |
| 92 // TODO(floitsch): this test originally changed the stacktrace. |
| 93 throw "[${error}]"; |
| 94 } |
| 95 }), cancelOnError: true); |
| 96 sentEvents.replay(c); |
| 97 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 98 } |
| 99 |
| 100 // reduce is tested asynchronously and therefore not in this file. |
| 101 |
| 102 // Test expand |
| 103 { |
| 104 var c = new StreamController(sync: true); |
| 105 var sentEvents = new Events()..add(3)..add(2)..add(4)..close(); |
| 106 var expectedEvents = new Events()..add(1)..add(2)..add(3) |
| 107 ..add(1)..add(2) |
| 108 ..add(1)..add(2)..add(3)..add(4) |
| 109 ..close(); |
| 110 var actualEvents = |
| 111 new Events.capture(c.stream.asBroadcastStream().expand((v) { |
| 112 var l = []; |
| 113 for (int i = 0; i < v; i++) l.add(i + 1); |
| 114 return l; |
| 115 })); |
| 116 sentEvents.replay(c); |
| 117 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 118 } |
| 119 |
| 120 // Test transform. |
| 121 { |
| 122 var c = new StreamController(sync: true); |
| 123 var sentEvents = new Events()..add("a")..error(42)..add("b")..close(); |
| 124 var expectedEvents = |
| 125 new Events()..error("a")..add(42)..error("b")..add("foo")..close(); |
| 126 var actualEvents = |
| 127 new Events.capture(c.stream.asBroadcastStream().transform( |
| 128 new StreamTransformer.fromHandlers( |
| 129 handleData: (v, s) { s.addError(v); }, |
| 130 handleError: (e, st, s) { s.add(e); }, |
| 131 handleDone: (s) { |
| 132 s.add("foo"); |
| 133 s.close(); |
| 134 }))); |
| 135 sentEvents.replay(c); |
| 136 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 137 } |
| 138 |
| 139 // Test multiple filters. |
| 140 { |
| 141 var c = new StreamController(sync: true); |
| 142 var sentEvents = new Events()..add(42) |
| 143 ..add("snugglefluffy") |
| 144 ..add(7) |
| 145 ..add("42") |
| 146 ..error("not FormatException") // Unsubscribes. |
| 147 ..close(); |
| 148 var expectedEvents = new Events()..add(42)..error("not FormatException"); |
| 149 var actualEvents = new Events.capture( |
| 150 c.stream.asBroadcastStream().where((v) => v is String) |
| 151 .map((v) => int.parse(v)) |
| 152 .handleError((error) { |
| 153 if (error is! FormatException) throw error; |
| 154 }) |
| 155 .where((v) => v > 10), |
| 156 cancelOnError: true); |
| 157 sentEvents.replay(c); |
| 158 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 159 } |
| 160 |
| 161 // Test subscription changes while firing. |
| 162 { |
| 163 var c = new StreamController(sync: true); |
| 164 var sink = c.sink; |
| 165 var stream = c.stream.asBroadcastStream(); |
| 166 var counter = 0; |
| 167 var subscription = stream.listen(null); |
| 168 subscription.onData((data) { |
| 169 counter += data; |
| 170 subscription.cancel(); |
| 171 stream.listen((data) { |
| 172 counter += 10 * data; |
| 173 }); |
| 174 var subscription2 = stream.listen(null); |
| 175 subscription2.onData((data) { |
| 176 counter += 100 * data; |
| 177 if (data == 4) subscription2.cancel(); |
| 178 }); |
| 179 }); |
| 180 sink.add(1); // seen by stream 1 |
| 181 sink.add(2); // seen by stream 10 and 100 |
| 182 sink.add(3); // -"- |
| 183 sink.add(4); // -"- |
| 184 sink.add(5); // seen by stream 10 |
| 185 Expect.equals(1 + 20 + 200 + 30 + 300 + 40 + 400 + 50, counter); |
| 186 } |
| 187 } |
| 188 |
| 189 testSingleController() { |
| 190 // Test normal flow. |
| 191 { |
| 192 var c = new StreamController(sync: true); |
| 193 Events expectedEvents = new Events() |
| 194 ..add(42) |
| 195 ..add("dibs") |
| 196 ..error("error!") |
| 197 ..error("error too!") |
| 198 ..close(); |
| 199 CaptureEvents actualEvents = new Events.capture(c.stream); |
| 200 expectedEvents.replay(c); |
| 201 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 202 } |
| 203 |
| 204 // Test automatic unsubscription on error. |
| 205 { |
| 206 var c = new StreamController(sync: true); |
| 207 var expectedEvents = new Events()..add(42)..error("error"); |
| 208 var actualEvents = new Events.capture(c.stream, cancelOnError: true); |
| 209 Events sentEvents = |
| 210 new Events()..add(42)..error("error")..add("Are you there?"); |
| 211 sentEvents.replay(c); |
| 212 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 213 } |
| 214 |
| 215 // Test manual unsubscription. |
| 216 { |
| 217 var c = new StreamController(sync: true); |
| 218 var expectedEvents = new Events()..add(42)..error("error")..add(37); |
| 219 var actualEvents = new Events.capture(c.stream, cancelOnError: false); |
| 220 expectedEvents.replay(c); |
| 221 actualEvents.subscription.cancel(); |
| 222 c.add("Are you there"); // Not sent to actualEvents. |
| 223 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 224 } |
| 225 |
| 226 // Test filter. |
| 227 { |
| 228 var c = new StreamController(sync: true); |
| 229 var expectedEvents = new Events() |
| 230 ..add("a string")..add("another string")..close(); |
| 231 var sentEvents = new Events() |
| 232 ..add("a string")..add(42)..add("another string")..close(); |
| 233 var actualEvents = new Events.capture(c.stream.where((v) => v is String)); |
| 234 sentEvents.replay(c); |
| 235 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 236 } |
| 237 |
| 238 // Test map. |
| 239 { |
| 240 var c = new StreamController(sync: true); |
| 241 var expectedEvents = new Events()..add("abab")..error("error")..close(); |
| 242 var sentEvents = new Events()..add("ab")..error("error")..close(); |
| 243 var actualEvents = new Events.capture(c.stream.map((v) => "$v$v")); |
| 244 sentEvents.replay(c); |
| 245 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 246 } |
| 247 |
| 248 // Test handleError. |
| 249 { |
| 250 var c = new StreamController(sync: true); |
| 251 var expectedEvents = new Events()..add("ab")..error("[foo]"); |
| 252 var sentEvents = new Events()..add("ab")..error("foo")..add("ab")..close(); |
| 253 var actualEvents = new Events.capture(c.stream.handleError((error) { |
| 254 if (error is String) { |
| 255 // TODO(floitsch): this error originally changed the stack trace. |
| 256 throw "[${error}]"; |
| 257 } |
| 258 }), cancelOnError: true); |
| 259 sentEvents.replay(c); |
| 260 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 261 } |
| 262 |
| 263 // reduce is tested asynchronously and therefore not in this file. |
| 264 |
| 265 // Test expand |
| 266 { |
| 267 var c = new StreamController(sync: true); |
| 268 var sentEvents = new Events()..add(3)..add(2)..add(4)..close(); |
| 269 var expectedEvents = new Events()..add(1)..add(2)..add(3) |
| 270 ..add(1)..add(2) |
| 271 ..add(1)..add(2)..add(3)..add(4) |
| 272 ..close(); |
| 273 var actualEvents = new Events.capture(c.stream.expand((v) { |
| 274 var l = []; |
| 275 for (int i = 0; i < v; i++) l.add(i + 1); |
| 276 return l; |
| 277 })); |
| 278 sentEvents.replay(c); |
| 279 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 280 } |
| 281 |
| 282 // test contains. |
| 283 { |
| 284 var c = new StreamController(sync: true); |
| 285 // Error after match is not important. |
| 286 var sentEvents = new Events()..add("a")..add("x")..error("FAIL")..close(); |
| 287 Future<bool> contains = c.stream.contains("x"); |
| 288 contains.then((var c) { |
| 289 Expect.isTrue(c); |
| 290 }); |
| 291 sentEvents.replay(c); |
| 292 } |
| 293 |
| 294 { |
| 295 var c = new StreamController(sync: true); |
| 296 // Not matching is ok. |
| 297 var sentEvents = new Events()..add("a")..add("x")..add("b")..close(); |
| 298 Future<bool> contains = c.stream.contains("y"); |
| 299 contains.then((var c) { |
| 300 Expect.isFalse(c); |
| 301 }); |
| 302 sentEvents.replay(c); |
| 303 } |
| 304 |
| 305 { |
| 306 var c = new StreamController(sync: true); |
| 307 // Error before match makes future err. |
| 308 var sentEvents = new Events()..add("a")..error("FAIL")..add("b")..close(); |
| 309 Future<bool> contains = c.stream.contains("b"); |
| 310 contains.then((var c) { |
| 311 Expect.fail("no value expected"); |
| 312 }).catchError((error) { |
| 313 Expect.equals("FAIL", error); |
| 314 }); |
| 315 sentEvents.replay(c); |
| 316 } |
| 317 |
| 318 // Test transform. |
| 319 { |
| 320 var c = new StreamController(sync: true); |
| 321 var sentEvents = new Events()..add("a")..error(42)..add("b")..close(); |
| 322 var expectedEvents = |
| 323 new Events()..error("a")..add(42)..error("b")..add("foo")..close(); |
| 324 var actualEvents = new Events.capture(c.stream.transform( |
| 325 new StreamTransformer.fromHandlers( |
| 326 handleData: (v, s) { s.addError(v); }, |
| 327 handleError: (e, st, s) { s.add(e); }, |
| 328 handleDone: (s) { |
| 329 s.add("foo"); |
| 330 s.close(); |
| 331 }))); |
| 332 sentEvents.replay(c); |
| 333 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 334 } |
| 335 |
| 336 // Test multiple filters. |
| 337 { |
| 338 var c = new StreamController(sync: true); |
| 339 var sentEvents = new Events()..add(42) |
| 340 ..add("snugglefluffy") |
| 341 ..add(7) |
| 342 ..add("42") |
| 343 ..error("not FormatException") // Unsubscribes. |
| 344 ..close(); |
| 345 var expectedEvents = new Events()..add(42)..error("not FormatException"); |
| 346 var actualEvents = new Events.capture( |
| 347 c.stream.where((v) => v is String) |
| 348 .map((v) => int.parse(v)) |
| 349 .handleError((error) { |
| 350 if (error is! FormatException) throw error; |
| 351 }) |
| 352 .where((v) => v > 10), |
| 353 cancelOnError: true); |
| 354 sentEvents.replay(c); |
| 355 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 356 } |
| 357 |
| 358 // Test that only one subscription is allowed. |
| 359 { |
| 360 var c = new StreamController(sync: true); |
| 361 var sink = c.sink; |
| 362 var stream = c.stream; |
| 363 var counter = 0; |
| 364 var subscription = stream.listen((data) { counter += data; }); |
| 365 Expect.throws(() => stream.listen(null), (e) => e is StateError); |
| 366 sink.add(1); |
| 367 Expect.equals(1, counter); |
| 368 c.close(); |
| 369 } |
| 370 } |
| 371 |
| 372 testExtraMethods() { |
| 373 Events sentEvents = new Events()..add(1)..add(2)..add(3)..close(); |
| 374 |
| 375 var c = new StreamController(sync: true); |
| 376 Events expectedEvents = new Events()..add(3)..close(); |
| 377 Events actualEvents = new Events.capture(c.stream.skip(2)); |
| 378 sentEvents.replay(c); |
| 379 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 380 |
| 381 c = new StreamController(sync: true); |
| 382 expectedEvents = new Events()..close(); |
| 383 actualEvents = new Events.capture(c.stream.skip(3)); |
| 384 sentEvents.replay(c); |
| 385 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 386 |
| 387 c = new StreamController(sync: true); |
| 388 expectedEvents = new Events()..close(); |
| 389 actualEvents = new Events.capture(c.stream.skip(7)); |
| 390 sentEvents.replay(c); |
| 391 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 392 |
| 393 c = new StreamController(sync: true); |
| 394 expectedEvents = sentEvents; |
| 395 actualEvents = new Events.capture(c.stream.skip(0)); |
| 396 sentEvents.replay(c); |
| 397 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 398 |
| 399 |
| 400 c = new StreamController(sync: true); |
| 401 expectedEvents = new Events()..add(3)..close(); |
| 402 actualEvents = new Events.capture(c.stream.skipWhile((x) => x <= 2)); |
| 403 sentEvents.replay(c); |
| 404 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 405 |
| 406 |
| 407 c = new StreamController(sync: true); |
| 408 expectedEvents = new Events()..add(2)..add(3)..close(); |
| 409 actualEvents = new Events.capture(c.stream.skipWhile((x) => x <= 1)); |
| 410 sentEvents.replay(c); |
| 411 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 412 |
| 413 |
| 414 c = new StreamController(sync: true); |
| 415 expectedEvents = new Events()..add(1)..add(2)..add(3)..close(); |
| 416 actualEvents = new Events.capture(c.stream.skipWhile((x) => false)); |
| 417 sentEvents.replay(c); |
| 418 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 419 |
| 420 |
| 421 c = new StreamController(sync: true); |
| 422 expectedEvents = new Events()..add(1)..add(2)..close(); |
| 423 actualEvents = new Events.capture(c.stream.take(2)); |
| 424 sentEvents.replay(c); |
| 425 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 426 |
| 427 |
| 428 c = new StreamController(sync: true); |
| 429 expectedEvents = new Events()..add(1)..add(2)..close(); |
| 430 actualEvents = new Events.capture(c.stream.takeWhile((x) => x <= 2)); |
| 431 sentEvents.replay(c); |
| 432 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 433 |
| 434 |
| 435 c = new StreamController(sync: true); |
| 436 sentEvents = new Events() |
| 437 ..add(1)..add(1)..add(2)..add(1)..add(2)..add(2)..add(2)..close(); |
| 438 expectedEvents = new Events() |
| 439 ..add(1)..add(2)..add(1)..add(2)..close(); |
| 440 actualEvents = new Events.capture(c.stream.distinct()); |
| 441 sentEvents.replay(c); |
| 442 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 443 |
| 444 |
| 445 c = new StreamController(sync: true); |
| 446 sentEvents = new Events() |
| 447 ..add(5)..add(6)..add(4)..add(6)..add(8)..add(3)..add(4)..add(1)..close(); |
| 448 expectedEvents = new Events() |
| 449 ..add(5)..add(4)..add(3)..add(1)..close(); |
| 450 // Use 'distinct' as a filter with access to the previously emitted event. |
| 451 actualEvents = new Events.capture(c.stream.distinct((a, b) => a < b)); |
| 452 sentEvents.replay(c); |
| 453 Expect.listEquals(expectedEvents.events, actualEvents.events); |
| 454 } |
| 455 |
| 456 void testClosed() { |
| 457 StreamController c = new StreamController(sync: true); |
| 458 Expect.isFalse(c.isClosed); |
| 459 c.add(42); |
| 460 Expect.isFalse(c.isClosed); |
| 461 c.addError("bad"); |
| 462 Expect.isFalse(c.isClosed); |
| 463 c.close(); |
| 464 Expect.isTrue(c.isClosed); |
| 465 } |
| 466 |
| 467 void testCloseFuture() { |
| 468 asyncStart(); |
| 469 asyncStart(); |
| 470 var c = new StreamController(); |
| 471 var f = c.close(); |
| 472 Expect.isTrue(c.isClosed); |
| 473 bool doneSeen = false; |
| 474 f.then((_) { |
| 475 Expect.isTrue(doneSeen); |
| 476 asyncEnd(); |
| 477 }); |
| 478 // Only listen after a while. |
| 479 new Timer(MS * 250, () { |
| 480 c.stream.listen(null, onDone: () { |
| 481 asyncEnd(); |
| 482 doneSeen = true; |
| 483 }); |
| 484 }); |
| 485 } |
| 486 |
| 487 void testCloseFuture2() { |
| 488 asyncStart(); |
| 489 asyncStart(); |
| 490 var c = new StreamController.broadcast(); |
| 491 var f = c.close(); |
| 492 Expect.isTrue(c.isClosed); |
| 493 bool doneSeen = false; |
| 494 f.then((_) { |
| 495 // Done future on broadcast stream can happen |
| 496 // before a listener is added. |
| 497 Expect.isFalse(doneSeen); |
| 498 asyncEnd(); |
| 499 }); |
| 500 // Only listen after a while. |
| 501 new Timer(MS * 250, () { |
| 502 c.stream.listen(null, onDone: () { |
| 503 doneSeen = true; |
| 504 asyncEnd(); |
| 505 }); |
| 506 }); |
| 507 } |
| 508 |
| 509 void testCloseFuture3() { |
| 510 asyncStart(); |
| 511 var c = new StreamController.broadcast(); |
| 512 c..add(1)..add(2)..add(3)..add(4); |
| 513 c.stream.listen(null).cancel(); |
| 514 var f = c.close(); |
| 515 Expect.isTrue(c.isClosed); |
| 516 f.then((_) { |
| 517 asyncEnd(); |
| 518 }); |
| 519 } |
| 520 |
| 521 void testStreamEquals() { |
| 522 StreamController c; |
| 523 c = new StreamController(sync: false); |
| 524 Expect.equals(c.stream, c.stream); |
| 525 c = new StreamController(sync: true); |
| 526 Expect.equals(c.stream, c.stream); |
| 527 c = new StreamController(sync: false, onListen: () {}); |
| 528 Expect.equals(c.stream, c.stream); |
| 529 c = new StreamController(sync: true, onListen: () {}); |
| 530 Expect.equals(c.stream, c.stream); |
| 531 c = new StreamController.broadcast(sync: false); |
| 532 Expect.equals(c.stream, c.stream); |
| 533 c = new StreamController.broadcast(sync: true); |
| 534 Expect.equals(c.stream, c.stream); |
| 535 c = new StreamController.broadcast(sync: false, onListen: () {}); |
| 536 Expect.equals(c.stream, c.stream); |
| 537 c = new StreamController.broadcast(sync: true, onListen: () {}); |
| 538 Expect.equals(c.stream, c.stream); |
| 539 } |
| 540 |
| 541 void testCancelThrow() { |
| 542 asyncStart(); |
| 543 asyncStart(); |
| 544 asyncStart(); |
| 545 StreamController c = new StreamController(onCancel: () { |
| 546 asyncEnd(); |
| 547 throw "ERROR"; |
| 548 }); |
| 549 c.add(1); |
| 550 c.add(2); |
| 551 c.add(3); |
| 552 Future done = c.close(); |
| 553 StreamSubscription sub; |
| 554 sub = c.stream.listen((v) { |
| 555 Expect.equals(1, v); |
| 556 Future f = sub.cancel(); |
| 557 f.catchError((e) { |
| 558 // Must complete with error from onCancel. |
| 559 Expect.equals("ERROR", e); |
| 560 asyncEnd(); |
| 561 }); |
| 562 }); |
| 563 done.catchError(fail).whenComplete(asyncEnd); // Must complete without error. |
| 564 } |
| 565 |
| 566 void testCancelThrow2() { |
| 567 asyncStart(); |
| 568 asyncStart(); |
| 569 asyncStart(); |
| 570 asyncStart(); |
| 571 asyncStart(); |
| 572 StreamController c2 = new StreamController(onCancel: () { |
| 573 asyncEnd(); |
| 574 throw "ERROR"; |
| 575 }); |
| 576 c2.add(1); |
| 577 c2.add(2); |
| 578 Future done2 = c2.close(); |
| 579 done2.catchError(fail).whenComplete(asyncEnd); // Should not get error; |
| 580 |
| 581 StreamController c = new StreamController(); |
| 582 var sub; |
| 583 sub = c.stream.listen((v) { |
| 584 Expect.equals(1, v); |
| 585 Future f = sub.cancel(); |
| 586 f.catchError((e) { |
| 587 // Error from addStream stream's cancel must go only here. |
| 588 asyncEnd(); |
| 589 Expect.equals("ERROR", e); |
| 590 }); |
| 591 }); |
| 592 var addDone = c.addStream(c2.stream); |
| 593 addDone.catchError(fail).whenComplete(asyncEnd); // Should not get error. |
| 594 var done = c.done; |
| 595 done.catchError(fail).whenComplete(asyncEnd); // Should not get error. |
| 596 } |
| 597 |
| 598 void testCancelThrow3() { |
| 599 asyncStart(); |
| 600 asyncStart(); |
| 601 asyncStart(); |
| 602 asyncStart(); |
| 603 asyncStart(); |
| 604 asyncStart(); |
| 605 StreamController c2 = new StreamController(onCancel: () { |
| 606 asyncEnd(); |
| 607 throw "ERROR2"; |
| 608 }); |
| 609 c2.add(1); |
| 610 c2.add(2); |
| 611 var done2 = c2.close(); |
| 612 done2.catchError(fail).whenComplete(asyncEnd); // Should not get error; |
| 613 |
| 614 StreamController c = new StreamController(onCancel: () { |
| 615 asyncEnd(); |
| 616 throw "ERROR1"; |
| 617 }); |
| 618 var sub; |
| 619 sub = c.stream.listen((v) { |
| 620 Expect.equals(1, v); |
| 621 Future f = sub.cancel(); |
| 622 f.catchError((e) { |
| 623 // Only the last error ends up here. |
| 624 Expect.equals("ERROR1", e); |
| 625 asyncEnd(); |
| 626 }); |
| 627 }); |
| 628 var addDone = c.addStream(c2.stream); |
| 629 addDone.catchError(fail).whenComplete(asyncEnd); // Error must not go here. |
| 630 c.done.catchError(fail).whenComplete(asyncEnd); // Error must not go here. |
| 631 } |
| 632 |
| 633 void testBroadcastListenAfterClose() { |
| 634 asyncStart(); |
| 635 StreamController c = new StreamController.broadcast(); |
| 636 var f = c.close(); |
| 637 f.then((_) { |
| 638 // Listening after close is allowed. The listener gets a done event. |
| 639 c.stream.listen(null, onDone: asyncEnd); |
| 640 }); |
| 641 } |
| 642 |
| 643 void testBroadcastListenAfterClosePaused() { |
| 644 asyncStart(); |
| 645 StreamController c = new StreamController.broadcast(); |
| 646 var f = c.close(); |
| 647 f.then((_) { |
| 648 // Listening after close is allowed. The listener gets a done event. |
| 649 var sub = c.stream.listen(null, onDone: () { |
| 650 Expect.fail("wrong done"); |
| 651 }); |
| 652 sub.pause(); |
| 653 sub.pause(); |
| 654 new Timer(MS * 100, () { |
| 655 sub.asFuture().whenComplete(() { Expect.fail("Bad complete"); }); |
| 656 sub.resume(); |
| 657 new Timer(MS * 100, () { |
| 658 sub.onDone(asyncEnd); |
| 659 sub.resume(); |
| 660 }); |
| 661 }); |
| 662 }); |
| 663 } |
| 664 |
| 665 void testAsBroadcastListenAfterClose() { |
| 666 asyncStart(); |
| 667 asyncStart(); |
| 668 StreamController c = new StreamController(); |
| 669 Stream s = c.stream.asBroadcastStream(); |
| 670 s.listen(null, onDone: asyncEnd); |
| 671 var f = c.close(); |
| 672 f.then((_) { |
| 673 // Listening after close is allowed. The listener gets a done event. |
| 674 s.listen(null, onDone: asyncEnd); |
| 675 }); |
| 676 } |
| 677 |
| 678 void testAsBroadcastListenAfterClosePaused() { |
| 679 asyncStart(); |
| 680 asyncStart(); |
| 681 StreamController c = new StreamController(); |
| 682 Stream s = c.stream.asBroadcastStream(); |
| 683 s.listen(null, onDone: asyncEnd); |
| 684 var f = c.close(); |
| 685 f.then((_) { |
| 686 // Listening after close is allowed. The listener gets a done event. |
| 687 var sub = s.listen(null, onDone: () { |
| 688 Expect.fail("wrong done"); |
| 689 }); |
| 690 sub.pause(); |
| 691 sub.pause(); |
| 692 new Timer(MS * 100, () { |
| 693 sub.asFuture().whenComplete(() { Expect.fail("Bad complete"); }); |
| 694 sub.resume(); |
| 695 new Timer(MS * 100, () { |
| 696 sub.onDone(asyncEnd); |
| 697 sub.resume(); |
| 698 }); |
| 699 }); |
| 700 }); |
| 701 } |
| 702 |
| 703 void testEventInListen() { |
| 704 asyncStart(); |
| 705 // Regression test for http://dartbug.com/19722 |
| 706 var c; |
| 707 void send() { |
| 708 c.add(1); |
| 709 } |
| 710 int i = 1; |
| 711 c = new StreamController.broadcast(onListen: send, sync: true); |
| 712 c.stream.listen((v) { |
| 713 Expect.equals(i++, v); |
| 714 }, onDone: asyncEnd); |
| 715 c.add(2); |
| 716 c.close(); |
| 717 } |
| 718 |
| 719 void testSyncControllerNotReentrant() { |
| 720 Stream emptyStream = (new StreamController.broadcast()..close()).stream; |
| 721 asyncStart(); |
| 722 for (int listenerCount = 1; listenerCount <= 2; listenerCount++) { |
| 723 StreamController c = new StreamController.broadcast(sync: true); |
| 724 for (int i = 0; i < listenerCount; i++) { |
| 725 asyncStart(); |
| 726 asyncStart(); |
| 727 c.stream.listen((v) { |
| 728 Expect.equals(42, v); |
| 729 Expect.throws(() { |
| 730 c.add(37); |
| 731 }); |
| 732 Expect.throws(() { |
| 733 c.addError(37); |
| 734 }); |
| 735 Expect.throws(() { |
| 736 c.addStream(emptyStream); |
| 737 }); |
| 738 Expect.throws(() { |
| 739 c.close(); |
| 740 }); |
| 741 asyncEnd(); |
| 742 }, onError: (e, s) { |
| 743 Expect.equals(87, e); |
| 744 Expect.throws(() { |
| 745 c.add(37); |
| 746 }); |
| 747 Expect.throws(() { |
| 748 c.addError(37); |
| 749 }); |
| 750 Expect.throws(() { |
| 751 c.addStream(emptyStream); |
| 752 }); |
| 753 Expect.throws(() { |
| 754 c.close(); |
| 755 }); |
| 756 asyncEnd(); |
| 757 }); |
| 758 } |
| 759 c.add(42); |
| 760 c.addError(87); |
| 761 } |
| 762 asyncEnd(); |
| 763 } |
| 764 |
| 765 void testSettingCallbacks() { |
| 766 const int initial = 0; |
| 767 const int running = 1; |
| 768 const int paused = 2; |
| 769 const int canceled = 3; |
| 770 |
| 771 var controller = new StreamController(); |
| 772 var stream = controller.stream; |
| 773 var state = initial; |
| 774 |
| 775 var onListen = () { state = running; }; |
| 776 var onPause = () { state = paused; }; |
| 777 var onResume = () { state = running; }; |
| 778 var onCancel = () { state = canceled; }; |
| 779 |
| 780 Expect.isNull(controller.onListen); |
| 781 Expect.isNull(controller.onPause); |
| 782 Expect.isNull(controller.onResume); |
| 783 Expect.isNull(controller.onCancel); |
| 784 |
| 785 controller..onListen = onListen |
| 786 ..onPause = onPause |
| 787 ..onResume = onResume |
| 788 ..onCancel = onCancel; |
| 789 |
| 790 Expect.equals(onListen, controller.onListen); |
| 791 Expect.equals(onPause, controller.onPause); |
| 792 Expect.equals(onResume, controller.onResume); |
| 793 Expect.equals(onCancel, controller.onCancel); |
| 794 |
| 795 Expect.equals(initial, state); |
| 796 var sub = stream.listen(null); |
| 797 Expect.equals(running, state); |
| 798 sub.pause(); |
| 799 Expect.equals(paused, state); |
| 800 Expect.isTrue(controller.isPaused); |
| 801 sub.resume(); |
| 802 Expect.equals(running, state); |
| 803 Expect.isFalse(controller.isPaused); |
| 804 |
| 805 var onListen2 = () { state = -running; }; |
| 806 var onPause2 = () { state = -paused; }; |
| 807 var onResume2 = () { state = -running; }; |
| 808 var onCancel2 = () { state = -canceled; }; |
| 809 // Changing them later does make a difference. |
| 810 controller..onListen = onListen2 |
| 811 ..onPause = onPause2 |
| 812 ..onResume = onResume2 |
| 813 ..onCancel = onCancel2; |
| 814 |
| 815 Expect.equals(onListen2, controller.onListen); |
| 816 Expect.equals(onPause2, controller.onPause); |
| 817 Expect.equals(onResume2, controller.onResume); |
| 818 Expect.equals(onCancel2, controller.onCancel); |
| 819 |
| 820 Expect.equals(running, state); |
| 821 sub.pause(); |
| 822 Expect.equals(-paused, state); |
| 823 Expect.isTrue(controller.isPaused); |
| 824 sub.resume(); |
| 825 Expect.equals(-running, state); |
| 826 Expect.isFalse(controller.isPaused); |
| 827 sub.cancel(); |
| 828 Expect.equals(-canceled, state); |
| 829 } |
| 830 |
| 831 void testSettingNullCallbacks() { |
| 832 failCallback() => fail("Callback should not be called"); |
| 833 var controller = new StreamController(onListen: failCallback, |
| 834 onPause : failCallback, |
| 835 onResume: failCallback, |
| 836 onCancel: failCallback); |
| 837 |
| 838 var stream = controller.stream; |
| 839 |
| 840 Expect.isFalse(controller.hasListener); |
| 841 Expect.isTrue(controller.isPaused); |
| 842 |
| 843 Expect.isNotNull(controller.onListen); |
| 844 controller.onListen = null; |
| 845 Expect.isNull(controller.onListen); |
| 846 |
| 847 var sub = stream.listen(null); |
| 848 |
| 849 Expect.isTrue(controller.hasListener); |
| 850 Expect.isFalse(controller.isPaused); |
| 851 |
| 852 Expect.isNotNull(controller.onPause); |
| 853 controller.onPause = null; |
| 854 Expect.isNull(controller.onPause); |
| 855 |
| 856 sub.pause(); |
| 857 |
| 858 Expect.isTrue(controller.hasListener); |
| 859 Expect.isTrue(controller.isPaused); |
| 860 |
| 861 Expect.isNotNull(controller.onResume); |
| 862 controller.onResume = null; |
| 863 Expect.isNull(controller.onResume); |
| 864 |
| 865 sub.resume(); |
| 866 |
| 867 Expect.isTrue(controller.hasListener); |
| 868 Expect.isFalse(controller.isPaused); |
| 869 |
| 870 Expect.isNotNull(controller.onCancel); |
| 871 controller.onCancel = null; |
| 872 Expect.isNull(controller.onCancel); |
| 873 |
| 874 sub.cancel(); |
| 875 |
| 876 Expect.isFalse(controller.hasListener); |
| 877 Expect.isFalse(controller.isPaused); |
| 878 } |
| 879 |
| 880 void testBroadcastSettingCallbacks() { |
| 881 const int initial = 0; |
| 882 const int running = 1; |
| 883 const int canceled = 2; |
| 884 |
| 885 var controller = new StreamController.broadcast(); |
| 886 var stream = controller.stream; |
| 887 var state = initial; |
| 888 |
| 889 Expect.throws(() { controller.onPause = () {}; }, |
| 890 (e) => e is UnsupportedError); |
| 891 Expect.throws(() { controller.onResume = () {}; }, |
| 892 (e) => e is UnsupportedError); |
| 893 |
| 894 controller..onListen = () { state = running; } |
| 895 ..onCancel = () { state = canceled; }; |
| 896 |
| 897 Expect.equals(initial, state); |
| 898 var sub = stream.listen(null); |
| 899 Expect.equals(running, state); |
| 900 sub.cancel(); |
| 901 Expect.equals(canceled, state); |
| 902 |
| 903 // Changing them later does make a difference. |
| 904 controller..onListen = () { state = -running; } |
| 905 ..onCancel = () { state = -canceled; }; |
| 906 |
| 907 var sub2 = stream.listen(null); |
| 908 Expect.equals(-running, state); |
| 909 sub2.cancel(); |
| 910 Expect.equals(-canceled, state); |
| 911 } |
| 912 |
| 913 void testBroadcastSettingNullCallbacks() { |
| 914 failCallback() => fail("Callback should not be called"); |
| 915 var controller = new StreamController.broadcast(onListen: failCallback, |
| 916 onCancel: failCallback); |
| 917 |
| 918 var stream = controller.stream; |
| 919 |
| 920 Expect.isFalse(controller.hasListener); |
| 921 |
| 922 controller.onListen = null; |
| 923 |
| 924 var sub = stream.listen(null); |
| 925 |
| 926 Expect.isTrue(controller.hasListener); |
| 927 |
| 928 controller.onCancel = null; |
| 929 |
| 930 sub.cancel(); |
| 931 |
| 932 Expect.isFalse(controller.hasListener); |
| 933 } |
| 934 |
| 935 main() { |
| 936 asyncStart(); |
| 937 testMultiController(); |
| 938 testSingleController(); |
| 939 testExtraMethods(); |
| 940 testClosed(); |
| 941 testCloseFuture(); |
| 942 testCloseFuture2(); |
| 943 testCloseFuture3(); |
| 944 testStreamEquals(); |
| 945 testCancelThrow(); |
| 946 testCancelThrow2(); |
| 947 testCancelThrow3(); |
| 948 testBroadcastListenAfterClose(); |
| 949 testBroadcastListenAfterClosePaused(); |
| 950 testAsBroadcastListenAfterClose(); |
| 951 testAsBroadcastListenAfterClosePaused(); |
| 952 testEventInListen(); |
| 953 testSyncControllerNotReentrant(); |
| 954 testSettingCallbacks(); |
| 955 testSettingNullCallbacks(); |
| 956 testBroadcastSettingCallbacks(); |
| 957 testBroadcastSettingNullCallbacks(); |
| 958 asyncEnd(); |
| 959 } |
OLD | NEW |