| // Copyright (c) 2022, 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. | 
 |  | 
 | // This test verifies that 'await' implementation calls Zone callbacks from | 
 | // correct Zones. | 
 |  | 
 | import 'dart:async'; | 
 |  | 
 | import 'package:expect/expect.dart'; | 
 |  | 
 | List<String> log = []; | 
 |  | 
 | class TestZone { | 
 |   final String name; | 
 |   TestZone(this.name); | 
 |  | 
 |   static T run<T>(String name, T Function() callback) { | 
 |     final tz = TestZone(name); | 
 |     final zone = Zone.current.fork( | 
 |         specification: ZoneSpecification( | 
 |             runUnary: tz.runUnary, | 
 |             runBinary: tz.runBinary, | 
 |             registerUnaryCallback: tz.registerUnaryCallback, | 
 |             registerBinaryCallback: tz.registerBinaryCallback, | 
 |             scheduleMicrotask: tz.scheduleMicrotask)); | 
 |     return zone.run(callback); | 
 |   } | 
 |  | 
 |   R runUnary<R, T>( | 
 |       Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg) { | 
 |     log.add('$name.runUnary'); | 
 |     return parent.runUnary(zone, f, arg); | 
 |   } | 
 |  | 
 |   R runBinary<R, T1, T2>(Zone self, ZoneDelegate parent, Zone zone, | 
 |       R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2) { | 
 |     log.add('$name.runBinary'); | 
 |     return parent.runBinary(zone, f, arg1, arg2); | 
 |   } | 
 |  | 
 |   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>( | 
 |       Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f) { | 
 |     log.add('$name.registerUnaryCallback'); | 
 |     return parent.registerUnaryCallback(zone, (T arg) { | 
 |       log.add('$name.unaryCallback'); | 
 |       return f(arg); | 
 |     }); | 
 |   } | 
 |  | 
 |   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(Zone self, | 
 |       ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f) { | 
 |     log.add('$name.registerBinaryCallback'); | 
 |     return parent.registerBinaryCallback(zone, (T1 arg1, T2 arg2) { | 
 |       log.add('$name.binaryCallback'); | 
 |       return f(arg1, arg2); | 
 |     }); | 
 |   } | 
 |  | 
 |   void scheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, void f()) { | 
 |     log.add('$name.scheduleMicrotask'); | 
 |     parent.scheduleMicrotask(zone, f); | 
 |   } | 
 | } | 
 |  | 
 | Future<void> foo() async { | 
 |   log.add('--- step 3'); | 
 | } | 
 |  | 
 | Future<void> baz() async { | 
 |   log.add('--- step 8'); | 
 | } | 
 |  | 
 | Future<void> bar() async { | 
 |   log.add('--- step 6'); | 
 |  | 
 |   Future f = TestZone.run('Z3', () { | 
 |     log.add('--- step 7'); | 
 |     return baz(); | 
 |   }); | 
 |  | 
 |   log.add('--- step 9'); | 
 |   await TestZone.run('Z4', () async { | 
 |     log.add('--- step 10'); | 
 |     await f; | 
 |     log.add('--- step 13'); | 
 |   }); | 
 |   log.add('--- step 14'); | 
 | } | 
 |  | 
 | main() async { | 
 |   log.add('--- start'); | 
 |   await TestZone.run('Z1', () async { | 
 |     log.add('--- step 1'); | 
 |     await null; | 
 |     log.add('--- step 2'); | 
 |     await foo(); | 
 |  | 
 |     log.add('--- step 4'); | 
 |     await TestZone.run('Z2', () async { | 
 |       log.add('--- step 5'); | 
 |       Future f = bar(); | 
 |  | 
 |       log.add('--- step 11'); | 
 |       await TestZone.run('Z4', () async { | 
 |         log.add('--- step 12'); | 
 |         await f; | 
 |         log.add('--- step 15'); | 
 |       }); | 
 |       log.add('--- step 16'); | 
 |     }); | 
 |     log.add('--- step 17'); | 
 |   }); | 
 |   log.add('--- end'); | 
 |  | 
 |   print('Actual log = ['); | 
 |   for (int i = 0; i < log.length; ++i) { | 
 |     print("  /* $i */ '${log[i]}',"); | 
 |   } | 
 |   print('];'); | 
 |  | 
 |   List<String> expectedLog = [ | 
 |     /* 0 */ '--- start', | 
 |     /* 1 */ '--- step 1', | 
 |     /* 2 */ 'Z1.registerUnaryCallback', | 
 |     /* 3 */ 'Z1.registerBinaryCallback', | 
 |     /* 4 */ 'Z1.scheduleMicrotask', | 
 |     /* 5 */ 'Z1.runUnary', | 
 |     /* 6 */ 'Z1.unaryCallback', | 
 |     /* 7 */ '--- step 2', | 
 |     /* 8 */ '--- step 3', | 
 |     /* 9 */ 'Z1.scheduleMicrotask', | 
 |     /* 10 */ 'Z1.runUnary', | 
 |     /* 11 */ 'Z1.unaryCallback', | 
 |     /* 12 */ '--- step 4', | 
 |     /* 13 */ '--- step 5', | 
 |     /* 14 */ '--- step 6', | 
 |     /* 15 */ '--- step 7', | 
 |     /* 16 */ '--- step 8', | 
 |     /* 17 */ '--- step 9', | 
 |     /* 18 */ '--- step 10', | 
 |     /* 19 */ 'Z4.registerUnaryCallback', | 
 |     /* 20 */ 'Z2.registerUnaryCallback', | 
 |     /* 21 */ 'Z1.registerUnaryCallback', | 
 |     /* 22 */ 'Z4.registerBinaryCallback', | 
 |     /* 23 */ 'Z2.registerBinaryCallback', | 
 |     /* 24 */ 'Z1.registerBinaryCallback', | 
 |     /* 25 */ 'Z3.scheduleMicrotask', | 
 |     /* 26 */ 'Z2.scheduleMicrotask', | 
 |     /* 27 */ 'Z1.scheduleMicrotask', | 
 |     /* 28 */ 'Z2.registerUnaryCallback', | 
 |     /* 29 */ 'Z1.registerUnaryCallback', | 
 |     /* 30 */ 'Z2.registerBinaryCallback', | 
 |     /* 31 */ 'Z1.registerBinaryCallback', | 
 |     /* 32 */ '--- step 11', | 
 |     /* 33 */ '--- step 12', | 
 |     /* 34 */ 'Z4.registerUnaryCallback', | 
 |     /* 35 */ 'Z2.registerUnaryCallback', | 
 |     /* 36 */ 'Z1.registerUnaryCallback', | 
 |     /* 37 */ 'Z4.registerBinaryCallback', | 
 |     /* 38 */ 'Z2.registerBinaryCallback', | 
 |     /* 39 */ 'Z1.registerBinaryCallback', | 
 |     /* 40 */ 'Z2.registerUnaryCallback', | 
 |     /* 41 */ 'Z1.registerUnaryCallback', | 
 |     /* 42 */ 'Z2.registerBinaryCallback', | 
 |     /* 43 */ 'Z1.registerBinaryCallback', | 
 |     /* 44 */ 'Z4.runUnary', | 
 |     /* 45 */ 'Z2.runUnary', | 
 |     /* 46 */ 'Z1.runUnary', | 
 |     /* 47 */ 'Z1.unaryCallback', | 
 |     /* 48 */ 'Z2.unaryCallback', | 
 |     /* 49 */ 'Z4.unaryCallback', | 
 |     /* 50 */ '--- step 13', | 
 |     /* 51 */ 'Z2.runUnary', | 
 |     /* 52 */ 'Z1.runUnary', | 
 |     /* 53 */ 'Z1.unaryCallback', | 
 |     /* 54 */ 'Z2.unaryCallback', | 
 |     /* 55 */ '--- step 14', | 
 |     /* 56 */ 'Z4.runUnary', | 
 |     /* 57 */ 'Z2.runUnary', | 
 |     /* 58 */ 'Z1.runUnary', | 
 |     /* 59 */ 'Z1.unaryCallback', | 
 |     /* 60 */ 'Z2.unaryCallback', | 
 |     /* 61 */ 'Z4.unaryCallback', | 
 |     /* 62 */ '--- step 15', | 
 |     /* 63 */ 'Z2.runUnary', | 
 |     /* 64 */ 'Z1.runUnary', | 
 |     /* 65 */ 'Z1.unaryCallback', | 
 |     /* 66 */ 'Z2.unaryCallback', | 
 |     /* 67 */ '--- step 16', | 
 |     /* 68 */ 'Z1.runUnary', | 
 |     /* 69 */ 'Z1.unaryCallback', | 
 |     /* 70 */ '--- step 17', | 
 |     /* 71 */ '--- end', | 
 |   ]; | 
 |   Expect.listEquals(expectedLog, log); | 
 | } |