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 |