| OLD | NEW |
| 1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 | 165 |
| 166 test('should process microtasks surrounding each timer', () { | 166 test('should process microtasks surrounding each timer', () { |
| 167 new FakeAsync().run((async) { | 167 new FakeAsync().run((async) { |
| 168 var microtaskCalls = 0; | 168 var microtaskCalls = 0; |
| 169 var timerCalls = 0; | 169 var timerCalls = 0; |
| 170 scheduleMicrotasks() { | 170 scheduleMicrotasks() { |
| 171 for (int i = 0; i < 5; i++) { | 171 for (int i = 0; i < 5; i++) { |
| 172 scheduleMicrotask(() => microtaskCalls++); | 172 scheduleMicrotask(() => microtaskCalls++); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 |
| 175 scheduleMicrotasks(); | 176 scheduleMicrotasks(); |
| 176 new Timer.periodic(elapseBy ~/ 5, (_) { | 177 new Timer.periodic(elapseBy ~/ 5, (_) { |
| 177 timerCalls++; | 178 timerCalls++; |
| 178 expect(microtaskCalls, 5 * timerCalls); | 179 expect(microtaskCalls, 5 * timerCalls); |
| 179 scheduleMicrotasks(); | 180 scheduleMicrotasks(); |
| 180 }); | 181 }); |
| 181 async.elapse(elapseBy); | 182 async.elapse(elapseBy); |
| 182 expect(timerCalls, 5); | 183 expect(timerCalls, 5); |
| 183 expect(microtaskCalls, 5 * (timerCalls + 1)); | 184 expect(microtaskCalls, 5 * (timerCalls + 1)); |
| 184 }); | 185 }); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 201 scheduleMicrotask(() { | 202 scheduleMicrotask(() { |
| 202 calledAt = async.getClock(initialTime).now(); | 203 calledAt = async.getClock(initialTime).now(); |
| 203 }); | 204 }); |
| 204 async.elapse(const Duration(minutes: 1)); | 205 async.elapse(const Duration(minutes: 1)); |
| 205 expect(calledAt, initialTime); | 206 expect(calledAt, initialTime); |
| 206 }); | 207 }); |
| 207 }); | 208 }); |
| 208 | 209 |
| 209 test('should add event before advancing time', () { | 210 test('should add event before advancing time', () { |
| 210 return new Future(() => new FakeAsync().run((async) { | 211 return new Future(() => new FakeAsync().run((async) { |
| 211 var controller = new StreamController(); | 212 var controller = new StreamController(); |
| 212 var ret = controller.stream.first.then((_) { | 213 var ret = controller.stream.first.then((_) { |
| 213 expect(async.getClock(initialTime).now(), initialTime); | 214 expect(async.getClock(initialTime).now(), initialTime); |
| 214 }); | 215 }); |
| 215 controller.add(null); | 216 controller.add(null); |
| 216 async.elapse(const Duration(minutes: 1)); | 217 async.elapse(const Duration(minutes: 1)); |
| 217 return ret; | 218 return ret; |
| 218 })); | 219 })); |
| 219 }); | 220 }); |
| 220 | 221 |
| 221 test('should increase negative duration timers to zero duration', () { | 222 test('should increase negative duration timers to zero duration', () { |
| 222 new FakeAsync().run((async) { | 223 new FakeAsync().run((async) { |
| 223 var negativeDuration = const Duration(days: -1); | 224 var negativeDuration = const Duration(days: -1); |
| 224 DateTime calledAt; | 225 DateTime calledAt; |
| 225 new Timer(negativeDuration, () { | 226 new Timer(negativeDuration, () { |
| 226 calledAt = async.getClock(initialTime).now(); | 227 calledAt = async.getClock(initialTime).now(); |
| 227 }); | 228 }); |
| 228 async.elapse(const Duration(minutes: 1)); | 229 async.elapse(const Duration(minutes: 1)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 int result; | 280 int result; |
| 280 new Future.delayed(elapseBy, () => result = 5); | 281 new Future.delayed(elapseBy, () => result = 5); |
| 281 async.elapse(elapseBy); | 282 async.elapse(elapseBy); |
| 282 expect(result, 5); | 283 expect(result, 5); |
| 283 }); | 284 }); |
| 284 }); | 285 }); |
| 285 | 286 |
| 286 test('should work with Future.timeout', () { | 287 test('should work with Future.timeout', () { |
| 287 new FakeAsync().run((async) { | 288 new FakeAsync().run((async) { |
| 288 var completer = new Completer(); | 289 var completer = new Completer(); |
| 289 var timed = completer.future.timeout(elapseBy ~/ 2); | 290 TimeoutException timeout; |
| 290 expect(timed, throwsA(new isInstanceOf<TimeoutException>())); | 291 completer.future.timeout(elapseBy ~/ 2).catchError((err) { |
| 292 timeout = err; |
| 293 }); |
| 291 async.elapse(elapseBy); | 294 async.elapse(elapseBy); |
| 295 expect(timeout, new isInstanceOf<TimeoutException>()); |
| 292 completer.complete(); | 296 completer.complete(); |
| 293 }); | 297 }); |
| 294 }); | 298 }); |
| 295 | 299 |
| 296 // TODO: Pausing and resuming the timeout Stream doesn't work since | 300 // TODO: Pausing and resuming the timeout Stream doesn't work since |
| 297 // it uses `new Stopwatch()`. | 301 // it uses `new Stopwatch()`. |
| 298 // | 302 // |
| 299 // See https://code.google.com/p/dart/issues/detail?id=18149 | 303 // See https://code.google.com/p/dart/issues/detail?id=18149 |
| 300 test('should work with Stream.periodic', () { | 304 test('should work with Stream.periodic', () { |
| 301 new FakeAsync().run((async) { | 305 new FakeAsync().run((async) { |
| 302 var events = <int>[]; | 306 var events = <int>[]; |
| 303 StreamSubscription subscription; | 307 StreamSubscription subscription; |
| 304 var periodic = | 308 var periodic = |
| 305 new Stream.periodic(const Duration(minutes: 1), (i) => i); | 309 new Stream.periodic(const Duration(minutes: 1), (i) => i); |
| 306 subscription = periodic.listen(events.add, cancelOnError: true); | 310 subscription = periodic.listen(events.add); |
| 307 async.elapse(const Duration(minutes: 3)); | 311 async.elapse(const Duration(minutes: 3)); |
| 312 expect(events, [0, 1, 2]); |
| 308 subscription.cancel(); | 313 subscription.cancel(); |
| 309 expect(events, [0, 1, 2]); | |
| 310 }); | 314 }); |
| 311 }); | 315 }); |
| 312 | 316 |
| 313 test('should work with Stream.timeout', () { | 317 test('should work with Stream.timeout', () { |
| 314 new FakeAsync().run((async) { | 318 new FakeAsync().run((async) { |
| 315 var events = <int>[]; | 319 var events = <int>[]; |
| 316 var errors = []; | 320 var errors = []; |
| 317 var controller = new StreamController(); | 321 var controller = new StreamController(); |
| 318 var timed = controller.stream.timeout(const Duration(minutes: 2)); | 322 var timed = controller.stream.timeout(const Duration(minutes: 2)); |
| 319 var subscription = timed.listen(events.add, | 323 var subscription = timed.listen(events.add, onError: errors.add); |
| 320 onError: errors.add, cancelOnError: true); | |
| 321 controller.add(0); | 324 controller.add(0); |
| 322 async.elapse(const Duration(minutes: 1)); | 325 async.elapse(const Duration(minutes: 1)); |
| 323 expect(events, [0]); | 326 expect(events, [0]); |
| 324 async.elapse(const Duration(minutes: 1)); | 327 async.elapse(const Duration(minutes: 1)); |
| 325 subscription.cancel(); | |
| 326 expect(errors, hasLength(1)); | 328 expect(errors, hasLength(1)); |
| 327 expect(errors.first, new isInstanceOf<TimeoutException>()); | 329 expect(errors.first, new isInstanceOf<TimeoutException>()); |
| 328 return controller.close(); | 330 subscription.cancel(); |
| 331 controller.close(); |
| 329 }); | 332 }); |
| 330 }); | 333 }); |
| 331 }); | 334 }); |
| 332 }); | 335 }); |
| 333 | 336 |
| 334 group('flushMicrotasks', () { | 337 group('flushMicrotasks', () { |
| 335 test('should flush a microtask', () { | 338 test('should flush a microtask', () { |
| 336 new FakeAsync().run((async) { | 339 new FakeAsync().run((async) { |
| 337 bool microtaskRan = false; | 340 bool microtaskRan = false; |
| 338 new Future.microtask(() { | 341 new Future.microtask(() { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 363 }); | 366 }); |
| 364 test('should not run timers', () { | 367 test('should not run timers', () { |
| 365 new FakeAsync().run((async) { | 368 new FakeAsync().run((async) { |
| 366 final log = []; | 369 final log = []; |
| 367 new Future.microtask(() { | 370 new Future.microtask(() { |
| 368 log.add(1); | 371 log.add(1); |
| 369 }); | 372 }); |
| 370 new Future(() { | 373 new Future(() { |
| 371 log.add(2); | 374 log.add(2); |
| 372 }); | 375 }); |
| 373 new Timer.periodic(new Duration(seconds: 1), (_) { | 376 new Timer.periodic(const Duration(seconds: 1), (_) { |
| 374 log.add(2); | 377 log.add(2); |
| 375 }); | 378 }); |
| 376 async.flushMicrotasks(); | 379 async.flushMicrotasks(); |
| 377 expect(log, [1]); | 380 expect(log, [1]); |
| 378 }); | 381 }); |
| 379 }); | 382 }); |
| 380 }); | 383 }); |
| 381 | 384 |
| 382 group('flushTimers', () { | 385 group('flushTimers', () { |
| 383 test('should flush timers', () { | 386 test('should flush timers', () { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 395 expect(log, hasLength(0), reason: 'should not flush until asked to'); | 398 expect(log, hasLength(0), reason: 'should not flush until asked to'); |
| 396 async.flushTimers(timeout: elapseBy * 2, flushPeriodicTimers: false); | 399 async.flushTimers(timeout: elapseBy * 2, flushPeriodicTimers: false); |
| 397 expect(log, [1, 2, 3]); | 400 expect(log, [1, 2, 3]); |
| 398 expect(async.getClock(initialTime).now(), initialTime.add(elapseBy)); | 401 expect(async.getClock(initialTime).now(), initialTime.add(elapseBy)); |
| 399 }); | 402 }); |
| 400 }); | 403 }); |
| 401 | 404 |
| 402 test('should run collateral periodic timers', () { | 405 test('should run collateral periodic timers', () { |
| 403 new FakeAsync().run((async) { | 406 new FakeAsync().run((async) { |
| 404 final log = []; | 407 final log = []; |
| 405 new Future.delayed(new Duration(seconds: 2), () { | 408 new Future.delayed(const Duration(seconds: 2), () { |
| 406 log.add('delayed'); | 409 log.add('delayed'); |
| 407 }); | 410 }); |
| 408 new Timer.periodic(new Duration(seconds: 1), (_) { | 411 new Timer.periodic(const Duration(seconds: 1), (_) { |
| 409 log.add('periodic'); | 412 log.add('periodic'); |
| 410 }); | 413 }); |
| 411 expect(log, hasLength(0), reason: 'should not flush until asked to'); | 414 expect(log, hasLength(0), reason: 'should not flush until asked to'); |
| 412 async.flushTimers(flushPeriodicTimers: false); | 415 async.flushTimers(flushPeriodicTimers: false); |
| 413 expect(log, ['periodic', 'periodic', 'delayed']); | 416 expect(log, ['periodic', 'periodic', 'delayed']); |
| 414 }); | 417 }); |
| 415 }); | 418 }); |
| 416 | 419 |
| 417 test('should timeout', () { | 420 test('should timeout', () { |
| 418 new FakeAsync().run((async) { | 421 new FakeAsync().run((async) { |
| 419 int count = 0; | 422 int count = 0; |
| 420 // Schedule 3 timers. All but the last one should fire. | 423 // Schedule 3 timers. All but the last one should fire. |
| 421 for (int delay in [30, 60, 90]) { | 424 for (int delay in [30, 60, 90]) { |
| 422 new Future.delayed(new Duration(minutes: delay), () { | 425 new Future.delayed(new Duration(minutes: delay), () { |
| 423 count++; | 426 count++; |
| 424 }); | 427 }); |
| 425 } | 428 } |
| 426 expect(() => async.flushTimers(flushPeriodicTimers: false), | 429 expect(() => async.flushTimers(flushPeriodicTimers: false), |
| 427 throwsStateError); | 430 throwsStateError); |
| 428 expect(count, 2); | 431 expect(count, 2); |
| 429 }); | 432 }); |
| 430 }); | 433 }); |
| 431 | 434 |
| 432 test('should timeout a chain of timers', () { | 435 test('should timeout a chain of timers', () { |
| 433 new FakeAsync().run((async) { | 436 new FakeAsync().run((async) { |
| 434 int count = 0; | 437 int count = 0; |
| 435 createTimer() { | 438 createTimer() { |
| 436 new Future.delayed(new Duration(minutes: 30), () { | 439 new Future.delayed(const Duration(minutes: 30), () { |
| 437 count++; | 440 count++; |
| 438 createTimer(); | 441 createTimer(); |
| 439 }); | 442 }); |
| 440 } | 443 } |
| 444 |
| 441 createTimer(); | 445 createTimer(); |
| 442 expect(() => async.flushTimers( | 446 expect( |
| 443 timeout: new Duration(hours: 2), flushPeriodicTimers: false), | 447 () => async.flushTimers( |
| 448 timeout: const Duration(hours: 2), |
| 449 flushPeriodicTimers: false), |
| 444 throwsStateError); | 450 throwsStateError); |
| 445 expect(count, 4); | 451 expect(count, 4); |
| 446 }); | 452 }); |
| 447 }); | 453 }); |
| 448 | 454 |
| 449 test('should timeout periodic timers', () { | 455 test('should timeout periodic timers', () { |
| 450 new FakeAsync().run((async) { | 456 new FakeAsync().run((async) { |
| 451 int count = 0; | 457 int count = 0; |
| 452 new Timer.periodic(new Duration(minutes: 30), (Timer timer) { | 458 new Timer.periodic(const Duration(minutes: 30), (Timer timer) { |
| 453 count++; | 459 count++; |
| 454 }); | 460 }); |
| 455 expect(() => async.flushTimers(timeout: new Duration(hours: 1)), | 461 expect(() => async.flushTimers(timeout: const Duration(hours: 1)), |
| 456 throwsStateError); | 462 throwsStateError); |
| 457 expect(count, 2); | 463 expect(count, 2); |
| 458 }); | 464 }); |
| 459 }); | 465 }); |
| 460 | 466 |
| 461 test('should flush periodic timers', () { | 467 test('should flush periodic timers', () { |
| 462 new FakeAsync().run((async) { | 468 new FakeAsync().run((async) { |
| 463 int count = 0; | 469 int count = 0; |
| 464 new Timer.periodic(new Duration(minutes: 30), (Timer timer) { | 470 new Timer.periodic(const Duration(minutes: 30), (Timer timer) { |
| 465 if (count == 3) { | 471 if (count == 3) { |
| 466 timer.cancel(); | 472 timer.cancel(); |
| 467 } | 473 } |
| 468 count++; | 474 count++; |
| 469 }); | 475 }); |
| 470 async.flushTimers(timeout: new Duration(hours: 20)); | 476 async.flushTimers(timeout: const Duration(hours: 20)); |
| 471 expect(count, 4); | 477 expect(count, 4); |
| 472 }); | 478 }); |
| 473 }); | 479 }); |
| 474 | 480 |
| 475 test('should compute absolute timeout as elapsed + timeout', () { | 481 test('should compute absolute timeout as elapsed + timeout', () { |
| 476 new FakeAsync().run((async) { | 482 new FakeAsync().run((async) { |
| 477 final log = []; | 483 final log = []; |
| 478 int count = 0; | 484 int count = 0; |
| 479 createTimer() { | 485 createTimer() { |
| 480 new Future.delayed(new Duration(minutes: 30), () { | 486 new Future.delayed(const Duration(minutes: 30), () { |
| 481 log.add(count); | 487 log.add(count); |
| 482 count++; | 488 count++; |
| 483 if (count < 4) { | 489 if (count < 4) { |
| 484 createTimer(); | 490 createTimer(); |
| 485 } | 491 } |
| 486 }); | 492 }); |
| 487 } | 493 } |
| 494 |
| 488 createTimer(); | 495 createTimer(); |
| 489 async.elapse(new Duration(hours: 1)); | 496 async.elapse(const Duration(hours: 1)); |
| 490 async.flushTimers(timeout: new Duration(hours: 1)); | 497 async.flushTimers(timeout: const Duration(hours: 1)); |
| 491 expect(count, 4); | 498 expect(count, 4); |
| 492 }); | 499 }); |
| 493 }); | 500 }); |
| 494 }); | 501 }); |
| 495 | 502 |
| 496 group('stats', () { | 503 group('stats', () { |
| 497 test('should report the number of pending microtasks', () { | 504 test('should report the number of pending microtasks', () { |
| 498 new FakeAsync().run((async) { | 505 new FakeAsync().run((async) { |
| 499 expect(async.microtaskCount, 0); | 506 expect(async.microtaskCount, 0); |
| 500 scheduleMicrotask(() => null); | 507 scheduleMicrotask(() => null); |
| 501 expect(async.microtaskCount, 1); | 508 expect(async.microtaskCount, 1); |
| 502 scheduleMicrotask(() => null); | 509 scheduleMicrotask(() => null); |
| 503 expect(async.microtaskCount, 2); | 510 expect(async.microtaskCount, 2); |
| 504 async.flushMicrotasks(); | 511 async.flushMicrotasks(); |
| 505 expect(async.microtaskCount, 0); | 512 expect(async.microtaskCount, 0); |
| 506 }); | 513 }); |
| 507 }); | 514 }); |
| 508 | 515 |
| 509 test('it should report the number of pending periodic timers', () { | 516 test('it should report the number of pending periodic timers', () { |
| 510 new FakeAsync().run((async) { | 517 new FakeAsync().run((async) { |
| 511 expect(async.periodicTimerCount, 0); | 518 expect(async.periodicTimerCount, 0); |
| 512 Timer timer = new Timer.periodic(new Duration(minutes: 30), | 519 Timer timer = |
| 513 (Timer timer) { }); | 520 new Timer.periodic(const Duration(minutes: 30), (Timer timer) {}); |
| 514 expect(async.periodicTimerCount, 1); | 521 expect(async.periodicTimerCount, 1); |
| 515 new Timer.periodic(new Duration(minutes: 20), (Timer timer) { }); | 522 new Timer.periodic(const Duration(minutes: 20), (Timer timer) {}); |
| 516 expect(async.periodicTimerCount, 2); | 523 expect(async.periodicTimerCount, 2); |
| 517 async.elapse(new Duration(minutes: 20)); | 524 async.elapse(const Duration(minutes: 20)); |
| 518 expect(async.periodicTimerCount, 2); | 525 expect(async.periodicTimerCount, 2); |
| 519 timer.cancel(); | 526 timer.cancel(); |
| 520 expect(async.periodicTimerCount, 1); | 527 expect(async.periodicTimerCount, 1); |
| 521 }); | 528 }); |
| 522 }); | 529 }); |
| 523 | 530 |
| 524 test('it should report the number of pending non periodic timers', () { | 531 test('it should report the number of pending non periodic timers', () { |
| 525 new FakeAsync().run((async) { | 532 new FakeAsync().run((async) { |
| 526 expect(async.nonPeriodicTimerCount, 0); | 533 expect(async.nonPeriodicTimerCount, 0); |
| 527 Timer timer = new Timer(new Duration(minutes: 30), () { }); | 534 Timer timer = new Timer(const Duration(minutes: 30), () {}); |
| 528 expect(async.nonPeriodicTimerCount, 1); | 535 expect(async.nonPeriodicTimerCount, 1); |
| 529 new Timer(new Duration(minutes: 20), () { }); | 536 new Timer(const Duration(minutes: 20), () {}); |
| 530 expect(async.nonPeriodicTimerCount, 2); | 537 expect(async.nonPeriodicTimerCount, 2); |
| 531 async.elapse(new Duration(minutes: 25)); | 538 async.elapse(const Duration(minutes: 25)); |
| 532 expect(async.nonPeriodicTimerCount, 1); | 539 expect(async.nonPeriodicTimerCount, 1); |
| 533 timer.cancel(); | 540 timer.cancel(); |
| 534 expect(async.nonPeriodicTimerCount, 0); | 541 expect(async.nonPeriodicTimerCount, 0); |
| 535 }); | 542 }); |
| 536 }); | 543 }); |
| 537 }); | 544 }); |
| 545 |
| 546 group('timers', () { |
| 547 test('should behave like real timers', () { |
| 548 return new FakeAsync().run((async) { |
| 549 var timeout = const Duration(minutes: 1); |
| 550 int counter = 0; |
| 551 var timer; |
| 552 timer = new Timer(timeout, () { |
| 553 counter++; |
| 554 expect(timer.isActive, isFalse, |
| 555 reason: "is not active while executing callback"); |
| 556 }); |
| 557 expect(timer.isActive, isTrue, |
| 558 reason: "is active before executing callback"); |
| 559 async.elapse(timeout); |
| 560 expect(counter, equals(1), reason: "timer executed"); |
| 561 expect(timer.isActive, isFalse, |
| 562 reason: "is not active after executing callback"); |
| 563 }); |
| 564 }); |
| 565 }); |
| 538 }); | 566 }); |
| 539 } | 567 } |
| OLD | NEW |