// 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.

/// A minimal, dependency-free emulation layer for a subset of the
/// unittest/test API used by the language and core library (especially HTML)
/// tests.
///
/// 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:expect/expect.dart';

typedef dynamic _Action();
typedef void _ExpectationFunction(Object actual);

final List<_Group> _groups = [new _Group()];

final Object isFalse = new _Expectation(Expect.isFalse);
final Object isNotNull = new _Expectation(Expect.isNotNull);
final Object isNull = new _Expectation(Expect.isNull);
final Object isTrue = new _Expectation(Expect.isTrue);

final Object returnsNormally = new _Expectation((actual) {
  try {
    (actual as _Action)();
  } catch (error) {
    Expect.fail("Expected function to return normally, but threw:\n$error");
  }
});

final Object throws = new _Expectation((actual) {
  Expect.throws(actual as _Action);
});

final Object throwsArgumentError = new _Expectation((actual) {
  Expect.throws(actual as _Action, (error) => error is ArgumentError);
});

final Object throwsNoSuchMethodError = new _Expectation((actual) {
  Expect.throws(actual as _Action, (error) => error is NoSuchMethodError);
});

final Object throwsRangeError = new _Expectation((actual) {
  Expect.throws(actual as _Action, (error) => error is RangeError);
});

final Object throwsStateError = new _Expectation((actual) {
  Expect.throws(actual as _Action, (error) => error is StateError);
});

final Object throwsUnsupportedError = new _Expectation((actual) {
  Expect.throws(actual as _Action, (error) => error is UnsupportedError);
});

/// The test runner should call this once after running a test file.
void finishTests() {
  _groups.clear();
  _groups.add(new _Group());
}

void group(String description, body()) {
  // TODO(rnystrom): Do something useful with the description.
  _groups.add(new _Group());

  try {
    var result = body();
    if (result is Future) {
      Expect.testError("group() does not support asynchronous functions.");
    }
  } finally {
    _groups.removeLast();
  }
}

void test(String description, body()) {
  // TODO(rnystrom): Do something useful with the description.
  for (var group in _groups) {
    var result = group.setUpFunction();
    if (result is Future) {
      Expect.testError("setUp() does not support asynchronous functions.");
    }
  }

  try {
    var result = body();
    if (result is Future) {
      Expect.testError("test() does not support asynchronous functions.");
    }
  } finally {
    for (var i = _groups.length - 1; i >= 0; i--) {
      var group = _groups[i];
      var result = group.tearDownFunction();
      if (result is Future) {
        Expect.testError("tearDown() does not support asynchronous functions.");
      }
    }
  }
}

void setUp(body()) {
  // Can't define multiple setUps at the same level.
  assert(_groups.last.setUpFunction == _defaultAction);
  _groups.last.setUpFunction = body;
}

void tearDown(body()) {
  // Can't define multiple tearDowns at the same level.
  assert(_groups.last.tearDownFunction == _defaultAction);
  _groups.last.tearDownFunction = body;
}

void expect(Object actual, Object expected, {String reason = ""}) {
  // TODO(rnystrom): Do something useful with reason.
  if (expected is! _Expectation) {
    expected = equals(expected);
  }

  var expectation = expected as _Expectation;
  expectation.function(actual);
}

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

Object equals(Object value) => new _Expectation((actual) {
      Expect.deepEquals(value, actual);
    });

Object notEquals(Object value) => new _Expectation((actual) {
      Expect.notEquals(value, actual);
    });

Object unorderedEquals(Object value) => new _Expectation((actual) {
      Expect.setEquals(value as Iterable, actual as Iterable);
    });

Object predicate(bool fn(Object value), [String description = ""]) =>
    new _Expectation((actual) {
      Expect.isTrue(fn(actual), description);
    });

Object inInclusiveRange(num min, num max) => new _Expectation((actual) {
      var actualNum = actual as num;
      if (actualNum < min || actualNum > max) {
        fail("Expected $actualNum to be in the inclusive range [$min, $max].");
      }
    });

Object greaterThan(num value) => new _Expectation((actual) {
      var actualNum = actual as num;
      if (actualNum <= value) {
        fail("Expected $actualNum to be greater than $value.");
      }
    });

Object same(Object value) => new _Expectation((actual) {
      Expect.identical(value, actual);
    });

Object closeTo(num value, num tolerance) => new _Expectation((actual) {
      Expect.approxEquals(value, actual as num, tolerance);
    });

/// Succeeds if the actual value is any of the given strings. Unlike matcher's
/// [anyOf], this only works with strings and requires an explicit list.
Object anyOf(List<String> expected) => new _Expectation((actual) {
      for (var string in expected) {
        if (actual == string) return;
      }

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

_defaultAction() {}

/// One level of group() nesting to track an optional [setUp()] and [tearDown()]
/// function for the group.
///
/// There is also an implicit top level group.
class _Group {
  _Action setUpFunction = _defaultAction;
  _Action tearDownFunction = _defaultAction;
}

/// A wrapper around an expectation function.
///
/// This function is passed the actual value and should throw an
/// [ExpectException] if the value doesn't match the expectation.
class _Expectation {
  final _ExpectationFunction function;

  _Expectation(this.function);
}
