Index: tests/lib/async/zone_timer_task_test.dart |
diff --git a/tests/lib/async/zone_timer_task_test.dart b/tests/lib/async/zone_timer_task_test.dart |
deleted file mode 100644 |
index 310f7ca510a5b6fa5ecf0ac24247e712a11240aa..0000000000000000000000000000000000000000 |
--- a/tests/lib/async/zone_timer_task_test.dart |
+++ /dev/null |
@@ -1,515 +0,0 @@ |
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-// Tests timer tasks. |
- |
-import 'package:expect/expect.dart'; |
-import 'package:async_helper/async_helper.dart'; |
-import 'dart:async'; |
-import 'dart:collection'; |
- |
-class MyTimerSpecification implements SingleShotTimerTaskSpecification { |
- final Function callback; |
- final Duration duration; |
- |
- MyTimerSpecification(this.callback, this.duration); |
- |
- bool get isOneShot => true; |
- String get name => "test.timer-override"; |
-} |
- |
-class MyPeriodicTimerSpecification implements PeriodicTimerTaskSpecification { |
- final Function callback; |
- final Duration duration; |
- |
- MyPeriodicTimerSpecification(this.callback, this.duration); |
- |
- bool get isOneShot => true; |
- String get name => "test.periodic-timer-override"; |
-} |
- |
-/// Makes sure things are working in a simple setting. |
-/// No interceptions, changes, ... |
-Future testTimerTask() { |
- List log = []; |
- |
- var testCompleter = new Completer(); |
- asyncStart(); |
- |
- int taskIdCounter = 0; |
- |
- Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
- TaskCreate create, TaskSpecification specification) { |
- var taskMap = self['taskMap']; |
- var taskIdMap = self['taskIdMap']; |
- if (specification is SingleShotTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var result = parent.createTask(zone, create, specification); |
- taskMap[result] = specification; |
- taskIdMap[specification] = taskIdCounter++; |
- log.add("create leave"); |
- return result; |
- } else if (specification is PeriodicTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var result = parent.createTask(zone, create, specification); |
- taskMap[result] = specification; |
- taskIdMap[specification] = taskIdCounter++; |
- log.add("create leave"); |
- return result; |
- } |
- return parent.createTask(zone, create, specification); |
- } |
- |
- void runTaskHandler(Zone self, ZoneDelegate parent, Zone zone, TaskRun run, |
- Object task, Object arg) { |
- var taskMap = self['taskMap']; |
- var taskIdMap = self['taskIdMap']; |
- if (taskMap.containsKey(task)) { |
- var spec = taskMap[task]; |
- log.add("run enter " |
- "zone: ${self['name']} " |
- "task-id: ${taskIdMap[spec]} " |
- "arg: $arg"); |
- parent.runTask(zone, run, task, arg); |
- log.add("run leave"); |
- return; |
- } |
- parent.runTask(zone, run, task, arg); |
- } |
- |
- runZoned(() async { |
- var completer0 = new Completer(); |
- Timer.run(() { |
- completer0.complete("done"); |
- }); |
- await completer0.future; |
- |
- Expect.listEquals([ |
- 'create enter zone: custom zone spec-duration: 0:00:00.000000 ' |
- 'spec-oneshot?: true', |
- 'create leave', |
- 'run enter zone: custom zone task-id: 0 arg: null', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- var completer1 = new Completer(); |
- var counter1 = 0; |
- new Timer.periodic(const Duration(milliseconds: 5), (Timer timer) { |
- if (counter1++ > 1) { |
- timer.cancel(); |
- completer1.complete("done"); |
- } |
- }); |
- await completer1.future; |
- |
- Expect.listEquals([ |
- 'create enter zone: custom zone spec-duration: 0:00:00.005000 ' |
- 'spec-oneshot?: false', |
- 'create leave', |
- 'run enter zone: custom zone task-id: 1 arg: null', |
- 'run leave', |
- 'run enter zone: custom zone task-id: 1 arg: null', |
- 'run leave', |
- 'run enter zone: custom zone task-id: 1 arg: null', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- testCompleter.complete("done"); |
- asyncEnd(); |
- }, |
- zoneValues: {'name': 'custom zone', 'taskMap': {}, 'taskIdMap': {}}, |
- zoneSpecification: new ZoneSpecification( |
- createTask: createTaskHandler, |
- runTask: runTaskHandler)); |
- |
- return testCompleter.future; |
-} |
- |
-/// More complicated zone, that intercepts... |
-Future testTimerTask2() { |
- List log = []; |
- |
- var testCompleter = new Completer(); |
- asyncStart(); |
- |
- int taskIdCounter = 0; |
- |
- Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
- TaskCreate create, TaskSpecification specification) { |
- var taskMap = self['taskMap']; |
- var taskIdMap = self['taskIdMap']; |
- if (specification is SingleShotTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var mySpec = new MyTimerSpecification(specification.callback, |
- specification.duration + const Duration(milliseconds: 2)); |
- var result = parent.createTask(zone, create, mySpec); |
- taskMap[result] = specification; |
- taskIdMap[specification] = taskIdCounter++; |
- log.add("create leave"); |
- return result; |
- } else if (specification is PeriodicTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var mySpec = new MyPeriodicTimerSpecification(specification.callback, |
- specification.duration + const Duration(milliseconds: 2)); |
- var result = parent.createTask(zone, create, specification); |
- taskMap[result] = specification; |
- taskIdMap[specification] = taskIdCounter++; |
- log.add("create leave"); |
- return result; |
- } |
- return parent.createTask(zone, create, specification); |
- } |
- |
- void runTaskHandler(Zone self, ZoneDelegate parent, Zone zone, TaskRun run, |
- Object task, Object arg) { |
- var taskMap = self['taskMap']; |
- var taskIdMap = self['taskIdMap']; |
- if (taskMap.containsKey(task)) { |
- var spec = taskMap[task]; |
- log.add("run enter " |
- "zone: ${self['name']} " |
- "task-id: ${taskIdMap[spec]} " |
- "arg: $arg"); |
- parent.runTask(zone, run, task, arg); |
- log.add("run leave"); |
- return; |
- } |
- parent.runTask(zone, run, task, arg); |
- } |
- |
- runZoned(() async { |
- var completer0 = new Completer(); |
- Timer.run(() { |
- completer0.complete("done"); |
- }); |
- await completer0.future; |
- |
- // No visible change (except for the zone name) in the log, compared to the |
- // simple invocations. |
- Expect.listEquals([ |
- 'create enter zone: outer-zone spec-duration: 0:00:00.000000 ' |
- 'spec-oneshot?: true', |
- 'create leave', |
- 'run enter zone: outer-zone task-id: 0 arg: null', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- var completer1 = new Completer(); |
- var counter1 = 0; |
- new Timer.periodic(const Duration(milliseconds: 5), (Timer timer) { |
- if (counter1++ > 1) { |
- timer.cancel(); |
- completer1.complete("done"); |
- } |
- }); |
- await completer1.future; |
- |
- // No visible change (except for the zone nome) in the log, compared to the |
- // simple invocations. |
- Expect.listEquals([ |
- 'create enter zone: outer-zone spec-duration: 0:00:00.005000 ' |
- 'spec-oneshot?: false', |
- 'create leave', |
- 'run enter zone: outer-zone task-id: 1 arg: null', |
- 'run leave', |
- 'run enter zone: outer-zone task-id: 1 arg: null', |
- 'run leave', |
- 'run enter zone: outer-zone task-id: 1 arg: null', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- var nestedCompleter = new Completer(); |
- |
- runZoned(() async { |
- var completer0 = new Completer(); |
- Timer.run(() { |
- completer0.complete("done"); |
- }); |
- await completer0.future; |
- |
- // The outer zone sees the duration change of the inner zone. |
- Expect.listEquals([ |
- 'create enter zone: inner-zone spec-duration: 0:00:00.000000 ' |
- 'spec-oneshot?: true', |
- 'create enter zone: outer-zone spec-duration: 0:00:00.002000 ' |
- 'spec-oneshot?: true', |
- 'create leave', |
- 'create leave', |
- 'run enter zone: inner-zone task-id: 3 arg: null', |
- 'run enter zone: outer-zone task-id: 2 arg: null', |
- 'run leave', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- var completer1 = new Completer(); |
- var counter1 = 0; |
- new Timer.periodic(const Duration(milliseconds: 5), (Timer timer) { |
- if (counter1++ > 1) { |
- timer.cancel(); |
- completer1.complete("done"); |
- } |
- }); |
- await completer1.future; |
- |
- // The outer zone sees the duration change of the inner zone. |
- Expect.listEquals([ |
- 'create enter zone: inner-zone spec-duration: 0:00:00.005000 ' |
- 'spec-oneshot?: false', |
- 'create enter zone: outer-zone spec-duration: 0:00:00.005000 ' |
- 'spec-oneshot?: false', |
- 'create leave', |
- 'create leave', |
- 'run enter zone: inner-zone task-id: 5 arg: null', |
- 'run enter zone: outer-zone task-id: 4 arg: null', |
- 'run leave', |
- 'run leave', |
- 'run enter zone: inner-zone task-id: 5 arg: null', |
- 'run enter zone: outer-zone task-id: 4 arg: null', |
- 'run leave', |
- 'run leave', |
- 'run enter zone: inner-zone task-id: 5 arg: null', |
- 'run enter zone: outer-zone task-id: 4 arg: null', |
- 'run leave', |
- 'run leave' |
- ], log); |
- log.clear(); |
- |
- nestedCompleter.complete("done"); |
- }, |
- zoneValues: {'name': 'inner-zone', 'taskMap': {}, 'taskIdMap': {}}, |
- zoneSpecification: new ZoneSpecification( |
- createTask: createTaskHandler, |
- runTask: runTaskHandler)); |
- |
- await nestedCompleter.future; |
- testCompleter.complete("done"); |
- asyncEnd(); |
- }, |
- zoneValues: {'name': 'outer-zone', 'taskMap': {}, 'taskIdMap': {}}, |
- zoneSpecification: new ZoneSpecification( |
- createTask: createTaskHandler, |
- runTask: runTaskHandler)); |
- |
- return testCompleter.future; |
-} |
- |
-class TimerEntry { |
- final int time; |
- final SimulatedTimer timer; |
- |
- TimerEntry(this.time, this.timer); |
-} |
- |
-class SimulatedTimer implements Timer { |
- static int _idCounter = 0; |
- |
- Zone _zone; |
- final int _id = _idCounter++; |
- final Duration _duration; |
- final Function _callback; |
- final bool _isPeriodic; |
- bool _isActive = true; |
- |
- SimulatedTimer(this._zone, this._duration, this._callback, this._isPeriodic); |
- |
- bool get isActive => _isActive; |
- |
- void cancel() { |
- _isActive = false; |
- } |
- |
- void _run() { |
- if (!isActive) return; |
- _zone.runTask(_runTimer, this, null); |
- } |
- |
- static void _runTimer(SimulatedTimer timer, _) { |
- if (timer._isPeriodic) { |
- timer._callback(timer); |
- } else { |
- timer._callback(); |
- } |
- } |
-} |
- |
-testSimulatedTimer() { |
- List log = []; |
- |
- var currentTime = 0; |
- // Using a simple list as queue. Not very efficient, but the test has only |
- // very few timers running at the same time. |
- var queue = new DoubleLinkedQueue<TimerEntry>(); |
- |
- // Schedules the given callback at now + duration. |
- void schedule(int scheduledTime, SimulatedTimer timer) { |
- log.add("scheduling timer ${timer._id} for $scheduledTime"); |
- if (queue.isEmpty) { |
- queue.add(new TimerEntry(scheduledTime, timer)); |
- } else { |
- DoubleLinkedQueueEntry current = queue.firstEntry(); |
- while (current != null) { |
- if (current.element.time <= scheduledTime) { |
- current = current.nextEntry(); |
- } else { |
- current.prepend(new TimerEntry(scheduledTime, timer)); |
- break; |
- } |
- } |
- if (current == null) { |
- queue.add(new TimerEntry(scheduledTime, timer)); |
- } |
- } |
- } |
- |
- void runQueue() { |
- while (queue.isNotEmpty) { |
- var item = queue.removeFirst(); |
- // If multiple callbacks were scheduled at the same time, increment the |
- // current time instead of staying at the same time. |
- currentTime = item.time > currentTime ? item.time : currentTime + 1; |
- SimulatedTimer timer = item.timer; |
- log.add("running timer ${timer._id} at $currentTime " |
- "(active?: ${timer.isActive})"); |
- if (!timer.isActive) continue; |
- if (timer._isPeriodic) { |
- schedule(currentTime + timer._duration.inMilliseconds, timer); |
- } |
- item.timer._run(); |
- } |
- } |
- |
- SimulatedTimer createSimulatedOneShotTimer( |
- SingleShotTimerTaskSpecification spec, Zone zone) { |
- var timer = new SimulatedTimer(zone, spec.duration, spec.callback, false); |
- schedule(currentTime + spec.duration.inMilliseconds, timer); |
- return timer; |
- } |
- |
- SimulatedTimer createSimulatedPeriodicTimer( |
- PeriodicTimerTaskSpecification spec, Zone zone) { |
- var timer = new SimulatedTimer(zone, spec.duration, spec.callback, true); |
- schedule(currentTime + spec.duration.inMilliseconds, timer); |
- return timer; |
- } |
- |
- Object createSimulatedTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
- TaskCreate create, TaskSpecification specification) { |
- var taskMap = self['taskMap']; |
- var taskIdMap = self['taskIdMap']; |
- if (specification is SingleShotTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var result = |
- parent.createTask(zone, createSimulatedOneShotTimer, specification); |
- log.add("create leave"); |
- return result; |
- } |
- if (specification is PeriodicTimerTaskSpecification) { |
- log.add("create enter " |
- "zone: ${self['name']} " |
- "spec-duration: ${specification.duration} " |
- "spec-oneshot?: ${specification.isOneShot}"); |
- var result = |
- parent.createTask(zone, createSimulatedPeriodicTimer, specification); |
- log.add("create leave"); |
- return result; |
- } |
- return parent.createTask(zone, create, specification); |
- } |
- |
- runZoned(() { |
- Timer.run(() { |
- log.add("running Timer.run"); |
- }); |
- |
- var timer0; |
- |
- new Timer(const Duration(milliseconds: 10), () { |
- log.add("running Timer(10)"); |
- timer0.cancel(); |
- log.add("canceled timer0"); |
- }); |
- |
- timer0 = new Timer(const Duration(milliseconds: 15), () { |
- log.add("running Timer(15)"); |
- }); |
- |
- var counter1 = 0; |
- new Timer.periodic(const Duration(milliseconds: 5), (Timer timer) { |
- log.add("running periodic timer $counter1"); |
- if (counter1++ > 1) { |
- timer.cancel(); |
- } |
- }); |
- }, |
- zoneSpecification: |
- new ZoneSpecification(createTask: createSimulatedTaskHandler)); |
- |
- runQueue(); |
- |
- Expect.listEquals([ |
- 'create enter zone: null spec-duration: 0:00:00.000000 spec-oneshot?: true', |
- 'scheduling timer 0 for 0', |
- 'create leave', |
- 'create enter zone: null spec-duration: 0:00:00.010000 spec-oneshot?: true', |
- 'scheduling timer 1 for 10', |
- 'create leave', |
- 'create enter zone: null spec-duration: 0:00:00.015000 spec-oneshot?: true', |
- 'scheduling timer 2 for 15', |
- 'create leave', |
- 'create enter zone: null spec-duration: 0:00:00.005000 ' |
- 'spec-oneshot?: false', |
- 'scheduling timer 3 for 5', |
- 'create leave', |
- 'running timer 0 at 1 (active?: true)', |
- 'running Timer.run', |
- 'running timer 3 at 5 (active?: true)', |
- 'scheduling timer 3 for 10', |
- 'running periodic timer 0', |
- 'running timer 1 at 10 (active?: true)', |
- 'running Timer(10)', |
- 'canceled timer0', |
- 'running timer 3 at 11 (active?: true)', |
- 'scheduling timer 3 for 16', |
- 'running periodic timer 1', |
- 'running timer 2 at 15 (active?: false)', |
- 'running timer 3 at 16 (active?: true)', |
- 'scheduling timer 3 for 21', |
- 'running periodic timer 2', |
- 'running timer 3 at 21 (active?: false)' |
- ], log); |
- log.clear(); |
-} |
- |
-runTests() async { |
- await testTimerTask(); |
- await testTimerTask2(); |
- testSimulatedTimer(); |
-} |
- |
-main() { |
- asyncStart(); |
- runTests().then((_) { |
- asyncEnd(); |
- }); |
-} |