// Copyright (c) 2015, 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.

// Test that async functions don't zone-register their callbacks for each
// await. Async functions should register their callback once in the beginning
// and then reuse it for all awaits in their body.
// This has two advantages: it is faster, when there are several awaits (on
// the Future class from dart:async), and it avoids zone-nesting when tracing
// stacktraces.
// See http://dartbug.com/23394 for more information.

import 'dart:async';
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';

gee(i) async {
  return await i;
}

bar() async* {
  var i = 0;
  while (true) yield await gee(i++);
}

awaitForTest() async {
  var sum = 0;
  await for (var x in bar().take(100)) {
    sum += x;
  }
  Expect.equals(4950, sum);
}

awaitTest() async {
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  await null;
  return await 499;
}

runTests() async {
  await awaitTest();
  await awaitForTest();
}

var depth = 0;

var depthIncreases = 0;

increaseDepth() {
  depthIncreases++;
  depth++;
  // The async/await code should not register callbacks recursively in the
  // then-calls. As such the depth should never grow too much. We don't want
  // to commit to a specific value, since implementations still have some
  // room in how async/await is implemented, but 20 should be safe.
  Expect.isTrue(depth < 20);
}

registerCallback(Zone self, ZoneDelegate parent, Zone zone, f) {
  var oldDepth = depth;
  increaseDepth();
  return parent.registerCallback(zone, () {
    depth = oldDepth;
    return f();
  });
}

registerUnaryCallback(Zone self, ZoneDelegate parent, Zone zone, f) {
  var oldDepth = depth;
  increaseDepth();
  return parent.registerUnaryCallback(zone, (x) {
    depth = oldDepth;
    return f(x);
  });
}

registerBinaryCallback(Zone self, ZoneDelegate parent, Zone zone, f) {
  var oldDepth = depth;
  increaseDepth();
  return parent.registerBinaryCallback(zone, (x, y) {
    depth = oldDepth;
    return f(x, y);
  });
}

sm(Zone self, ZoneDelegate parent, Zone zone, f) {
  var oldDepth = depth;
  increaseDepth();
  return parent.scheduleMicrotask(zone, () {
    depth = oldDepth;
    return f();
  });
}

main() {
  asyncStart();
  var desc = new ZoneSpecification(
      registerCallback: registerCallback,
      registerUnaryCallback: registerUnaryCallback,
      registerBinaryCallback: registerBinaryCallback,
      scheduleMicrotask: sm);
  var future = runZoned(runTests, zoneSpecification: desc);
  future.then((_) => asyncEnd());
}
