Index: tests/lib/async/zone_task_test.dart |
diff --git a/tests/lib/async/zone_task_test.dart b/tests/lib/async/zone_task_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa9b008bad62e3d6ac89a2c3472a39b851a4a717 |
--- /dev/null |
+++ b/tests/lib/async/zone_task_test.dart |
@@ -0,0 +1,310 @@ |
+// 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 basic functionality of tasks in zones. |
+ |
+import 'package:expect/expect.dart'; |
+import 'package:async_helper/async_helper.dart'; |
+import 'dart:async'; |
+ |
+List log = []; |
+ |
+class MySpecification extends TaskSpecification { |
+ final Function callback; |
+ final bool isOneShot; |
+ final int value; |
+ |
+ MySpecification(void this.callback(), this.isOneShot, this.value); |
+ |
+ String get name => "test.specification-name"; |
+} |
+ |
+class MyTask { |
+ final Zone zone; |
+ final Function callback; |
+ final int id; |
+ int invocationCount = 0; |
+ bool shouldStop = false; |
+ |
+ MyTask(this.zone, void this.callback(), this.id); |
+} |
+ |
+void runMyTask(MyTask task, int value) { |
+ log.add("running " |
+ "zone: ${Zone.current['name']} " |
+ "task-id: ${task.id} " |
+ "invocation-count: ${task.invocationCount} " |
+ "value: $value"); |
+ task.callback(); |
+ task.invocationCount++; |
+} |
+ |
+MyTask createMyTask(MySpecification spec, Zone zone) { |
+ var task = new MyTask(zone, spec.callback, spec.value); |
+ log.add("creating task: ${spec.value} oneshot?: ${spec.isOneShot}"); |
+ if (spec.isOneShot) { |
+ Timer.run(() { |
+ zone.runTask(runMyTask, task, task.id); |
+ }); |
+ } else { |
+ new Timer.periodic(const Duration(milliseconds: 10), (Timer timer) { |
+ zone.runTask(runMyTask, task, task.id); |
+ if (task.shouldStop) { |
+ timer.cancel(); |
+ } |
+ }); |
+ } |
+ return task; |
+} |
+ |
+MyTask startTask(f, bool oneShot, int value) { |
+ var spec = new MySpecification(f, oneShot, value); |
+ return Zone.current.createTask(createMyTask, spec); |
+} |
+ |
+/// Makes sure things are working in a simple setting. |
+/// No interceptions, changes, ... |
+Future testCustomTask() { |
+ var testCompleter = new Completer(); |
+ asyncStart(); |
+ |
+ Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
+ TaskCreate create, TaskSpecification specification) { |
+ if (specification is MySpecification) { |
+ log.add("create enter " |
+ "zone: ${self['name']} " |
+ "spec-value: ${specification.value} " |
+ "spec-oneshot?: ${specification.isOneShot}"); |
+ MyTask result = parent.createTask(zone, create, specification); |
+ 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) { |
+ if (task is MyTask) { |
+ log.add("run enter " |
+ "zone: ${self['name']} " |
+ "task-id: ${task.id} " |
+ "invocation-count: ${task.invocationCount} " |
+ "arg: $arg"); |
+ parent.runTask(zone, run, task, arg); |
+ log.add("run leave invocation-count: ${task.invocationCount}"); |
+ return; |
+ } |
+ parent.runTask(zone, run, task, arg); |
+ } |
+ |
+ runZoned(() async { |
+ var completer0 = new Completer(); |
+ startTask(() { |
+ completer0.complete("done"); |
+ }, true, 0); |
+ await completer0.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: custom zone spec-value: 0 spec-oneshot?: true', |
+ 'creating task: 0 oneshot?: true', |
+ 'create leave', |
+ 'run enter zone: custom zone task-id: 0 invocation-count: 0 arg: 0', |
+ 'running zone: custom zone task-id: 0 invocation-count: 0 value: 0', |
+ 'run leave invocation-count: 1' |
+ ], log); |
+ log.clear(); |
+ |
+ var completer1 = new Completer(); |
+ MyTask task1; |
+ task1 = startTask(() { |
+ if (task1.invocationCount == 1) { |
+ task1.shouldStop = true; |
+ completer1.complete("done"); |
+ } |
+ }, false, 1); |
+ await completer1.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: custom zone spec-value: 1 spec-oneshot?: false', |
+ 'creating task: 1 oneshot?: false', |
+ 'create leave', |
+ 'run enter zone: custom zone task-id: 1 invocation-count: 0 arg: 1', |
+ 'running zone: custom zone task-id: 1 invocation-count: 0 value: 1', |
+ 'run leave invocation-count: 1', |
+ 'run enter zone: custom zone task-id: 1 invocation-count: 1 arg: 1', |
+ 'running zone: custom zone task-id: 1 invocation-count: 1 value: 1', |
+ 'run leave invocation-count: 2', |
+ ], log); |
+ log.clear(); |
+ |
+ testCompleter.complete("done"); |
+ asyncEnd(); |
+ }, |
+ zoneValues: {'name': 'custom zone'}, |
+ zoneSpecification: new ZoneSpecification( |
+ createTask: createTaskHandler, |
+ runTask: runTaskHandler)); |
+ |
+ return testCompleter.future; |
+} |
+ |
+/// More complicated zone, that intercepts... |
+Future testCustomTask2() { |
+ var testCompleter = new Completer(); |
+ asyncStart(); |
+ |
+ Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
+ TaskCreate create, TaskSpecification specification) { |
+ if (specification is MySpecification) { |
+ log.add("create enter " |
+ "zone: ${self['name']} " |
+ "spec-value: ${specification.value} " |
+ "spec-oneshot?: ${specification.isOneShot}"); |
+ var replacement = new MySpecification(specification.callback, |
+ specification.isOneShot, specification.value + 1); |
+ MyTask result = parent.createTask(zone, create, replacement); |
+ 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) { |
+ if (task is MyTask) { |
+ log.add("run enter " |
+ "zone: ${self['name']} " |
+ "task-id: ${task.id} " |
+ "invocation-count: ${task.invocationCount} " |
+ "arg: $arg"); |
+ int value = arg; |
+ parent.runTask(zone, run, task, value + 101); |
+ log.add("run leave invocation-count: ${task.invocationCount}"); |
+ return; |
+ } |
+ parent.runTask(zone, run, task, arg); |
+ } |
+ |
+ runZoned(() async { |
+ var completer0 = new Completer(); |
+ startTask(() { |
+ completer0.complete("done"); |
+ }, true, 0); |
+ await completer0.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: outer-zone spec-value: 0 spec-oneshot?: true', |
+ 'creating task: 1 oneshot?: true', |
+ 'create leave', |
+ 'run enter zone: outer-zone task-id: 1 invocation-count: 0 arg: 1', |
+ 'running zone: outer-zone task-id: 1 invocation-count: 0 value: 102', |
+ 'run leave invocation-count: 1' |
+ ], log); |
+ log.clear(); |
+ |
+ var completer1 = new Completer(); |
+ MyTask task1; |
+ task1 = startTask(() { |
+ if (task1.invocationCount == 1) { |
+ task1.shouldStop = true; |
+ completer1.complete("done"); |
+ } |
+ }, false, 1); |
+ await completer1.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: outer-zone spec-value: 1 spec-oneshot?: false', |
+ 'creating task: 2 oneshot?: false', |
+ 'create leave', |
+ 'run enter zone: outer-zone task-id: 2 invocation-count: 0 arg: 2', |
+ 'running zone: outer-zone task-id: 2 invocation-count: 0 value: 103', |
+ 'run leave invocation-count: 1', |
+ 'run enter zone: outer-zone task-id: 2 invocation-count: 1 arg: 2', |
+ 'running zone: outer-zone task-id: 2 invocation-count: 1 value: 103', |
+ 'run leave invocation-count: 2', |
+ ], log); |
+ log.clear(); |
+ |
+ var nestedCompleter = new Completer(); |
+ |
+ runZoned(() async { |
+ var completer0 = new Completer(); |
+ startTask(() { |
+ completer0.complete("done"); |
+ }, true, 0); |
+ await completer0.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: inner-zone spec-value: 0 spec-oneshot?: true', |
+ 'create enter zone: outer-zone spec-value: 1 spec-oneshot?: true', |
+ 'creating task: 2 oneshot?: true', |
+ 'create leave', |
+ 'create leave', |
+ 'run enter zone: inner-zone task-id: 2 invocation-count: 0 arg: 2', |
+ 'run enter zone: outer-zone task-id: 2 invocation-count: 0 arg: 103', |
+ 'running zone: inner-zone task-id: 2 invocation-count: 0 value: 204', |
+ 'run leave invocation-count: 1', |
+ 'run leave invocation-count: 1' |
+ ], log); |
+ log.clear(); |
+ |
+ var completer1 = new Completer(); |
+ MyTask task1; |
+ task1 = startTask(() { |
+ if (task1.invocationCount == 1) { |
+ task1.shouldStop = true; |
+ completer1.complete("done"); |
+ } |
+ }, false, 1); |
+ await completer1.future; |
+ |
+ Expect.listEquals([ |
+ 'create enter zone: inner-zone spec-value: 1 spec-oneshot?: false', |
+ 'create enter zone: outer-zone spec-value: 2 spec-oneshot?: false', |
+ 'creating task: 3 oneshot?: false', |
+ 'create leave', |
+ 'create leave', |
+ 'run enter zone: inner-zone task-id: 3 invocation-count: 0 arg: 3', |
+ 'run enter zone: outer-zone task-id: 3 invocation-count: 0 arg: 104', |
+ 'running zone: inner-zone task-id: 3 invocation-count: 0 value: 205', |
+ 'run leave invocation-count: 1', |
+ 'run leave invocation-count: 1', |
+ 'run enter zone: inner-zone task-id: 3 invocation-count: 1 arg: 3', |
+ 'run enter zone: outer-zone task-id: 3 invocation-count: 1 arg: 104', |
+ 'running zone: inner-zone task-id: 3 invocation-count: 1 value: 205', |
+ 'run leave invocation-count: 2', |
+ 'run leave invocation-count: 2', |
+ ], log); |
+ log.clear(); |
+ |
+ nestedCompleter.complete("done"); |
+ }, |
+ zoneValues: {'name': 'inner-zone'}, |
+ zoneSpecification: new ZoneSpecification( |
+ createTask: createTaskHandler, |
+ runTask: runTaskHandler)); |
+ |
+ await nestedCompleter.future; |
+ testCompleter.complete("done"); |
+ asyncEnd(); |
+ }, |
+ zoneValues: {'name': 'outer-zone'}, |
+ zoneSpecification: new ZoneSpecification( |
+ createTask: createTaskHandler, |
+ runTask: runTaskHandler)); |
+ |
+ return testCompleter.future; |
+} |
+ |
+runTests() async { |
+ await testCustomTask(); |
+ await testCustomTask2(); |
+} |
+ |
+main() { |
+ asyncStart(); |
+ runTests().then((_) { |
+ asyncEnd(); |
+ }); |
+} |