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

/// A minimal, dependency-free emulation layer for a subset of the
/// unittest/test API used by the language and core library.
///
/// Compared with `minitest.dart`, this library supports and expects
/// asynchronous tests. It uses a `Zone` per test to associate a test name with
/// the failure.
///
/// It does not support `setUp` or `tearDown` methods,
/// and matchers are severely restricted.
///
/// A number of our language and core library tests were written against the
/// unittest package, which is now deprecated in favor of the new test package.
/// The latter is much better feature-wise, but is also quite complex and has
/// many dependencies. For low-level language and core library tests, we don't
/// want to have to pull in a large number of dependencies and be able to run
/// them correctly in order to run a test, so we want to test them against
/// something simpler.
///
/// When possible, we just use the tiny expect library. But to avoid rewriting
/// all of the existing tests that use unittest, they can instead use this,
/// which shims the unittest API with as little code as possible and calls into
/// expect.
///
/// Eventually, it would be good to refactor those tests to use the expect
/// package directly and remove this.
import 'dart:async';

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

void group(String name, body()) {
  var oldName = _pushName(name);
  try {
    body();
  } finally {
    _popName(oldName);
  }
}

void test(String name, body()) {
  var oldName = _pushName(name);

  asyncStart();
  var result = runZoned(body, zoneValues: {_testToken: _currentName});
  if (result is Future) {
    result.then((_) {
      asyncEnd();
    });
  } else {
    // Ensure all tests get to be set up first.
    scheduleMicrotask(asyncEnd);
  }

  _popName(oldName);
}

void expect(dynamic value, dynamic matcher, {String reason = ""}) {
  Matcher m;
  if (matcher is _Matcher) {
    m = matcher.call;
  } else if (matcher is! Matcher) {
    m = equals(matcher);
  } else {
    m = matcher;
  }
  m(value);
}

R Function() expectAsync0<R>(R Function() f, {int count = 1}) {
  asyncStart(count);
  return () {
    var result = f();
    asyncEnd();
    return result;
  };
}

R Function(A) expectAsync1<R, A>(R Function(A) f, {int count = 1}) {
  asyncStart(count);
  return (A a) {
    var result = f(a);
    asyncEnd();
    return result;
  };
}

R Function(A, B) expectAsync2<R, A, B>(R Function(A, B) f, {int count = 1}) {
  asyncStart(count);
  return (A a, B b) {
    var result = f(a, b);
    asyncEnd();
    return result;
  };
}

dynamic expectAsync(Function f, {int count = 1}) {
  var f2 = f; // Avoid type-promoting f, we want dynamic invocations.
  if (f2 is Function(Never, Never, Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c, d, e]) {
      var result = f(a, b, c, d, e);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c, d]) {
      var result = f(a, b, c, d);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c]) {
      var result = f(a, b, c);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never)) {
    asyncStart(count);
    return ([a, b]) {
      var result = f(a, b);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never)) {
    asyncStart(count);
    return ([a]) {
      var result = f(a);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function()) {
    asyncStart(count);
    return () {
      var result = f();
      asyncEnd();
      return result;
    };
  }
  throw new UnsupportedError(
      "expectAsync only accepts up to five argument functions");
}

// Matchers
typedef Matcher = void Function(dynamic);

Matcher same(dynamic o) => (v) {
      Expect.identical(o, v);
    };

Matcher equals(dynamic o) => (v) {
      Expect.deepEquals(o, v);
    };

Matcher greaterThan(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value > n) return;
      Expect.fail("$v is not greater than $n");
    };

Matcher greaterThanOrEqualTo(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value >= n) return;
      Expect.fail("$v is not greater than $n");
    };

Matcher lessThan(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value < n) return;
      Expect.fail("$v is not less than $n");
    };

Matcher lessThanOrEqualTo(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value <= n) return;
      Expect.fail("$v is not less than $n");
    };

Matcher predicate(bool fn(dynamic value), [String description = ""]) =>
    (dynamic v) {
      Expect.isTrue(fn(v), description);
    };

Matcher anyOf(List<String> expected) => (dynamic actual) {
      for (var string in expected) {
        if (actual == string) return;
      }

      Expect.fail("Expected $actual to be one of $expected.");
    };

void isTrue(dynamic v) {
  Expect.isTrue(v);
}

void isFalse(dynamic v) {
  Expect.isFalse(v);
}

void isNull(dynamic o) {
  Expect.isNull(o);
}

void _checkThrow<T extends Object>(dynamic v, void onError(error)) {
  if (v is Future) {
    asyncStart();
    v.then((_) {
      Expect.fail("Did not throw");
    }, onError: (e, s) {
      if (e is! T) throw e;
      onError(e);
      asyncEnd();
    });
    return;
  }
  Expect.throws<T>(v, (e) {
    onError(e);
    return true;
  });
}

void returnsNormally(dynamic o) {
  try {
    Expect.type<Function()>(o);
    o();
  } catch (error, trace) {
    Expect.fail(
        "Expected function to return normally, but threw:\n$error\n\n$trace");
  }
}

void throws(dynamic v) {
  _checkThrow<Object>(v, (_) {});
}

Matcher throwsA(matcher) => (dynamic o) {
      _checkThrow<Object>(o, (error) {
        expect(error, matcher);
      });
    };

Matcher completion(matcher) => (dynamic o) {
      Expect.type<Future>(o);
      Future future = o;
      asyncStart();
      future.then((value) {
        expect(value, matcher);
        asyncEnd();
      });
    };

void completes(dynamic o) {
  Expect.type<Future>(o);
  Future future = o;
  asyncStart();
  future.then(asyncSuccess);
}

void isMap(dynamic o) {
  Expect.type<Map>(o);
}

void isList(dynamic o) {
  Expect.type<List>(o);
}

void isNotNull(dynamic o) {
  Expect.isNotNull(o);
}

abstract class _Matcher {
  void call(dynamic o);
}

// ignore: camel_case_types
class isInstanceOf<T> implements _Matcher {
  void call(dynamic o) {
    Expect.type<T>(o);
  }
}

void throwsArgumentError(dynamic v) {
  _checkThrow<ArgumentError>(v, (_) {});
}

void throwsStateError(dynamic v) {
  _checkThrow<StateError>(v, (_) {});
}

void fail(String message) {
  Expect.fail("$message");
}

/// Key for zone value holding current test name.
final _testToken = Object();

bool _initializedTestNameCallback = false;

/// The current combined name of the nesting [group] or [test].
String _currentName = "";

String _pushName(String newName) {
  // Look up the current test name from the zone created for the test.
  if (!_initializedTestNameCallback) {
    ExpectException.setTestNameCallback(() => Zone.current[_testToken]);
    _initializedTestNameCallback = true;
  }

  var oldName = _currentName;
  if (oldName == "") {
    _currentName = newName;
  } else {
    _currentName = "$oldName $newName";
  }
  return oldName;
}

void _popName(String oldName) {
  _currentName = oldName;
}
