OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, 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 // Tests basic functionality of tasks in zones. |
| 6 |
| 7 import 'package:expect/expect.dart'; |
| 8 import 'package:async_helper/async_helper.dart'; |
| 9 import 'dart:async'; |
| 10 |
| 11 List log = []; |
| 12 |
| 13 class MySpecification extends TaskSpecification { |
| 14 final Function callback; |
| 15 final bool isOneShot; |
| 16 final int value; |
| 17 |
| 18 MySpecification(void this.callback(), this.isOneShot, this.value); |
| 19 |
| 20 String get name => "test.specification-name"; |
| 21 } |
| 22 |
| 23 class MyTask { |
| 24 final Zone zone; |
| 25 final Function callback; |
| 26 final int id; |
| 27 int invocationCount = 0; |
| 28 bool shouldStop = false; |
| 29 |
| 30 MyTask(this.zone, void this.callback(), this.id); |
| 31 } |
| 32 |
| 33 void runMyTask(MyTask task, int value) { |
| 34 log.add("running " |
| 35 "zone: ${Zone.current['name']} " |
| 36 "task-id: ${task.id} " |
| 37 "invocation-count: ${task.invocationCount} " |
| 38 "value: $value"); |
| 39 task.callback(); |
| 40 task.invocationCount++; |
| 41 } |
| 42 |
| 43 MyTask createMyTask(MySpecification spec, Zone zone) { |
| 44 var task = new MyTask(zone, spec.callback, spec.value); |
| 45 log.add("creating task: ${spec.value} oneshot?: ${spec.isOneShot}"); |
| 46 if (spec.isOneShot) { |
| 47 Timer.run(() { |
| 48 zone.runTask(runMyTask, task, task.id); |
| 49 }); |
| 50 } else { |
| 51 new Timer.periodic(const Duration(milliseconds: 10), (Timer timer) { |
| 52 zone.runTask(runMyTask, task, task.id); |
| 53 if (task.shouldStop) { |
| 54 timer.cancel(); |
| 55 } |
| 56 }); |
| 57 } |
| 58 return task; |
| 59 } |
| 60 |
| 61 MyTask startTask(f, bool oneShot, int value) { |
| 62 var spec = new MySpecification(f, oneShot, value); |
| 63 return Zone.current.createTask(createMyTask, spec); |
| 64 } |
| 65 |
| 66 /// Makes sure things are working in a simple setting. |
| 67 /// No interceptions, changes, ... |
| 68 Future testCustomTask() { |
| 69 var testCompleter = new Completer(); |
| 70 asyncStart(); |
| 71 |
| 72 Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
| 73 TaskCreate create, TaskSpecification specification) { |
| 74 if (specification is MySpecification) { |
| 75 log.add("create enter " |
| 76 "zone: ${self['name']} " |
| 77 "spec-value: ${specification.value} " |
| 78 "spec-oneshot?: ${specification.isOneShot}"); |
| 79 MyTask result = parent.createTask(zone, create, specification); |
| 80 log.add("create leave"); |
| 81 return result; |
| 82 } |
| 83 return parent.createTask(zone, create, specification); |
| 84 } |
| 85 |
| 86 void runTaskHandler(Zone self, ZoneDelegate parent, Zone zone, TaskRun run, |
| 87 Object task, Object arg) { |
| 88 if (task is MyTask) { |
| 89 log.add("run enter " |
| 90 "zone: ${self['name']} " |
| 91 "task-id: ${task.id} " |
| 92 "invocation-count: ${task.invocationCount} " |
| 93 "arg: $arg"); |
| 94 parent.runTask(zone, run, task, arg); |
| 95 log.add("run leave invocation-count: ${task.invocationCount}"); |
| 96 return; |
| 97 } |
| 98 parent.runTask(zone, run, task, arg); |
| 99 } |
| 100 |
| 101 runZoned(() async { |
| 102 var completer0 = new Completer(); |
| 103 startTask(() { |
| 104 completer0.complete("done"); |
| 105 }, true, 0); |
| 106 await completer0.future; |
| 107 |
| 108 Expect.listEquals([ |
| 109 'create enter zone: custom zone spec-value: 0 spec-oneshot?: true', |
| 110 'creating task: 0 oneshot?: true', |
| 111 'create leave', |
| 112 'run enter zone: custom zone task-id: 0 invocation-count: 0 arg: 0', |
| 113 'running zone: custom zone task-id: 0 invocation-count: 0 value: 0', |
| 114 'run leave invocation-count: 1' |
| 115 ], log); |
| 116 log.clear(); |
| 117 |
| 118 var completer1 = new Completer(); |
| 119 MyTask task1; |
| 120 task1 = startTask(() { |
| 121 if (task1.invocationCount == 1) { |
| 122 task1.shouldStop = true; |
| 123 completer1.complete("done"); |
| 124 } |
| 125 }, false, 1); |
| 126 await completer1.future; |
| 127 |
| 128 Expect.listEquals([ |
| 129 'create enter zone: custom zone spec-value: 1 spec-oneshot?: false', |
| 130 'creating task: 1 oneshot?: false', |
| 131 'create leave', |
| 132 'run enter zone: custom zone task-id: 1 invocation-count: 0 arg: 1', |
| 133 'running zone: custom zone task-id: 1 invocation-count: 0 value: 1', |
| 134 'run leave invocation-count: 1', |
| 135 'run enter zone: custom zone task-id: 1 invocation-count: 1 arg: 1', |
| 136 'running zone: custom zone task-id: 1 invocation-count: 1 value: 1', |
| 137 'run leave invocation-count: 2', |
| 138 ], log); |
| 139 log.clear(); |
| 140 |
| 141 testCompleter.complete("done"); |
| 142 asyncEnd(); |
| 143 }, |
| 144 zoneValues: {'name': 'custom zone'}, |
| 145 zoneSpecification: new ZoneSpecification( |
| 146 createTask: createTaskHandler, |
| 147 runTask: runTaskHandler)); |
| 148 |
| 149 return testCompleter.future; |
| 150 } |
| 151 |
| 152 /// More complicated zone, that intercepts... |
| 153 Future testCustomTask2() { |
| 154 var testCompleter = new Completer(); |
| 155 asyncStart(); |
| 156 |
| 157 Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, |
| 158 TaskCreate create, TaskSpecification specification) { |
| 159 if (specification is MySpecification) { |
| 160 log.add("create enter " |
| 161 "zone: ${self['name']} " |
| 162 "spec-value: ${specification.value} " |
| 163 "spec-oneshot?: ${specification.isOneShot}"); |
| 164 var replacement = new MySpecification(specification.callback, |
| 165 specification.isOneShot, specification.value + 1); |
| 166 MyTask result = parent.createTask(zone, create, replacement); |
| 167 log.add("create leave"); |
| 168 return result; |
| 169 } |
| 170 return parent.createTask(zone, create, specification); |
| 171 } |
| 172 |
| 173 void runTaskHandler(Zone self, ZoneDelegate parent, Zone zone, TaskRun run, |
| 174 Object task, Object arg) { |
| 175 if (task is MyTask) { |
| 176 log.add("run enter " |
| 177 "zone: ${self['name']} " |
| 178 "task-id: ${task.id} " |
| 179 "invocation-count: ${task.invocationCount} " |
| 180 "arg: $arg"); |
| 181 int value = arg; |
| 182 parent.runTask(zone, run, task, value + 101); |
| 183 log.add("run leave invocation-count: ${task.invocationCount}"); |
| 184 return; |
| 185 } |
| 186 parent.runTask(zone, run, task, arg); |
| 187 } |
| 188 |
| 189 runZoned(() async { |
| 190 var completer0 = new Completer(); |
| 191 startTask(() { |
| 192 completer0.complete("done"); |
| 193 }, true, 0); |
| 194 await completer0.future; |
| 195 |
| 196 Expect.listEquals([ |
| 197 'create enter zone: outer-zone spec-value: 0 spec-oneshot?: true', |
| 198 'creating task: 1 oneshot?: true', |
| 199 'create leave', |
| 200 'run enter zone: outer-zone task-id: 1 invocation-count: 0 arg: 1', |
| 201 'running zone: outer-zone task-id: 1 invocation-count: 0 value: 102', |
| 202 'run leave invocation-count: 1' |
| 203 ], log); |
| 204 log.clear(); |
| 205 |
| 206 var completer1 = new Completer(); |
| 207 MyTask task1; |
| 208 task1 = startTask(() { |
| 209 if (task1.invocationCount == 1) { |
| 210 task1.shouldStop = true; |
| 211 completer1.complete("done"); |
| 212 } |
| 213 }, false, 1); |
| 214 await completer1.future; |
| 215 |
| 216 Expect.listEquals([ |
| 217 'create enter zone: outer-zone spec-value: 1 spec-oneshot?: false', |
| 218 'creating task: 2 oneshot?: false', |
| 219 'create leave', |
| 220 'run enter zone: outer-zone task-id: 2 invocation-count: 0 arg: 2', |
| 221 'running zone: outer-zone task-id: 2 invocation-count: 0 value: 103', |
| 222 'run leave invocation-count: 1', |
| 223 'run enter zone: outer-zone task-id: 2 invocation-count: 1 arg: 2', |
| 224 'running zone: outer-zone task-id: 2 invocation-count: 1 value: 103', |
| 225 'run leave invocation-count: 2', |
| 226 ], log); |
| 227 log.clear(); |
| 228 |
| 229 var nestedCompleter = new Completer(); |
| 230 |
| 231 runZoned(() async { |
| 232 var completer0 = new Completer(); |
| 233 startTask(() { |
| 234 completer0.complete("done"); |
| 235 }, true, 0); |
| 236 await completer0.future; |
| 237 |
| 238 Expect.listEquals([ |
| 239 'create enter zone: inner-zone spec-value: 0 spec-oneshot?: true', |
| 240 'create enter zone: outer-zone spec-value: 1 spec-oneshot?: true', |
| 241 'creating task: 2 oneshot?: true', |
| 242 'create leave', |
| 243 'create leave', |
| 244 'run enter zone: inner-zone task-id: 2 invocation-count: 0 arg: 2', |
| 245 'run enter zone: outer-zone task-id: 2 invocation-count: 0 arg: 103', |
| 246 'running zone: inner-zone task-id: 2 invocation-count: 0 value: 204', |
| 247 'run leave invocation-count: 1', |
| 248 'run leave invocation-count: 1' |
| 249 ], log); |
| 250 log.clear(); |
| 251 |
| 252 var completer1 = new Completer(); |
| 253 MyTask task1; |
| 254 task1 = startTask(() { |
| 255 if (task1.invocationCount == 1) { |
| 256 task1.shouldStop = true; |
| 257 completer1.complete("done"); |
| 258 } |
| 259 }, false, 1); |
| 260 await completer1.future; |
| 261 |
| 262 Expect.listEquals([ |
| 263 'create enter zone: inner-zone spec-value: 1 spec-oneshot?: false', |
| 264 'create enter zone: outer-zone spec-value: 2 spec-oneshot?: false', |
| 265 'creating task: 3 oneshot?: false', |
| 266 'create leave', |
| 267 'create leave', |
| 268 'run enter zone: inner-zone task-id: 3 invocation-count: 0 arg: 3', |
| 269 'run enter zone: outer-zone task-id: 3 invocation-count: 0 arg: 104', |
| 270 'running zone: inner-zone task-id: 3 invocation-count: 0 value: 205', |
| 271 'run leave invocation-count: 1', |
| 272 'run leave invocation-count: 1', |
| 273 'run enter zone: inner-zone task-id: 3 invocation-count: 1 arg: 3', |
| 274 'run enter zone: outer-zone task-id: 3 invocation-count: 1 arg: 104', |
| 275 'running zone: inner-zone task-id: 3 invocation-count: 1 value: 205', |
| 276 'run leave invocation-count: 2', |
| 277 'run leave invocation-count: 2', |
| 278 ], log); |
| 279 log.clear(); |
| 280 |
| 281 nestedCompleter.complete("done"); |
| 282 }, |
| 283 zoneValues: {'name': 'inner-zone'}, |
| 284 zoneSpecification: new ZoneSpecification( |
| 285 createTask: createTaskHandler, |
| 286 runTask: runTaskHandler)); |
| 287 |
| 288 await nestedCompleter.future; |
| 289 testCompleter.complete("done"); |
| 290 asyncEnd(); |
| 291 }, |
| 292 zoneValues: {'name': 'outer-zone'}, |
| 293 zoneSpecification: new ZoneSpecification( |
| 294 createTask: createTaskHandler, |
| 295 runTask: runTaskHandler)); |
| 296 |
| 297 return testCompleter.future; |
| 298 } |
| 299 |
| 300 runTests() async { |
| 301 await testCustomTask(); |
| 302 await testCustomTask2(); |
| 303 } |
| 304 |
| 305 main() { |
| 306 asyncStart(); |
| 307 runTests().then((_) { |
| 308 asyncEnd(); |
| 309 }); |
| 310 } |
OLD | NEW |