// Copyright (c) 2011, 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 test of simple runtime behavior on numbers, strings and lists with
 * a focus on both correct behavior and runtime errors.
 *
 * This file is written to use minimal type declarations to match a
 * typical dynamic language coding style.
 */
class CoreRuntimeTypesTest {
  static testMain() {
    testBooleanOperators();
    testRationalOperators();
    testIntegerOperators();
    testOperatorErrors();
    testRationalMethods();
    testIntegerMethods();
    testStringOperators();
    testStringMethods();
    testListOperators();
    testListMethods();
    testMapOperators();
    testMapMethods();
    testLiterals();
    testDateMethods();
  }

  static assertEquals(a, b) {
    Expect.equals(b, a);
  }

  static assertListEquals(List a, List b) {
    Expect.equals(b.length, a.length);
    for (int i = 0; i < a.length; i++) {
      Expect.equals(b[i], a[i]);
    }
  }

  static assertListContains(List<Comparable> a, List<Comparable> b) {
    a.sort((x, y) => x.compareTo(y));
    b.sort((x, y) => x.compareTo(y));
    assertListEquals(a, b);
  }

  static assertTypeError(void f()) {
    Expect.throws(f, (exception) => (exception is TypeError) ||
                                    (exception is NoSuchMethodError) ||
                                    (exception is ArgumentError));
  }

  static testBooleanOperators() {
    var x = true, y = false;
    assertEquals(x, true);
    assertEquals(y, false);
    assertEquals(x, !y);
    assertEquals(!x, y);
  }


  static testRationalOperators() {
    var x = 10, y = 20;
    assertEquals(x + y, 30);
    assertEquals(x - y, -10);
    assertEquals(x * y, 200);
    assertEquals(x / y, 0.5);
    assertEquals(x ~/ y, 0);
    assertEquals(x % y, 10);
  }

  static testIntegerOperators() {
    var x = 18, y = 17;
    assertEquals(x | y, 19);
    assertEquals(x & y, 16);
    assertEquals(x ^ y, 3);
    assertEquals(2 >> 1, 1);
    assertEquals(1 << 1, 2);
  }

  static testOperatorErrors() {
    var objs = [1, '2', [3], null, true, new Map()];
    for (var i=0; i < objs.length; i++) {
      for (var j=i+1; j < objs.length; j++) {
        testBinaryOperatorErrors(objs[i], objs[j]);
        testBinaryOperatorErrors(objs[j], objs[i]);
      }
      if (objs[i] != 1) {
        testUnaryOperatorErrors(objs[i]);
      }
    }
  }

  static testBinaryOperatorErrors(x, y) {
    assertTypeError(() { x - y;});
    assertTypeError(() { x * y;});
    assertTypeError(() { x / y;});
    assertTypeError(() { x | y;});
    assertTypeError(() { x ^ y;});
    assertTypeError(() { x & y;});
    assertTypeError(() { x << y;});
    assertTypeError(() { x >> y;});
    assertTypeError(() { x ~/ y;});
    assertTypeError(() { x % y;});

    testComparisonOperatorErrors(x, y);
  }

  static testComparisonOperatorErrors(x, y) {
    assertEquals(x == y, false);
    assertEquals(x != y, true);
    assertTypeError(() { x < y; });
    assertTypeError(() { x <= y; });
    assertTypeError(() { x > y; });
    assertTypeError(() { x >= y; });
  }

  static testUnaryOperatorErrors(x) {
    // TODO(jimhug): Add guard for 'is num' when 'is' is working
    assertTypeError(() { ~x;});
    assertTypeError(() { -x;});
    // TODO(jimhug): Add check for !x as an error when x is not a bool
  }

  static testRationalMethods() {
    var x = 10.6;
    assertEquals(x.abs(), 10.6);
    assertEquals((-x).abs(), 10.6);
    assertEquals(x.round(), 11);
    assertEquals(x.floor(), 10);
    assertEquals(x.ceil(), 11);
  }

  // TODO(jimhug): Determine correct behavior for mixing ints and floats.
  static testIntegerMethods() {
    var y = 9;
    assertEquals(y.isEven, false);
    assertEquals(y.isOdd, true);
    assertEquals(y.toRadixString(2), '1001');
    assertEquals(y.toRadixString(3), '100');
    assertEquals(y.toRadixString(16), '9');
    assertEquals((0).toRadixString(16), '0');
    try {
      y.toRadixString(0);
      Expect.fail("Illegal radix 0 accepted.");
    } catch (e) { }
    try {
      y.toRadixString(-1);
      Expect.fail("Illegal radix -1 accepted.");
    } catch (e) { }
  }

  static testStringOperators() {
    var s = "abcdef";
    assertEquals(s, "abcdef");
    assertEquals(s.codeUnitAt(0), 97);
    assertEquals(s[0], 'a');
    assertEquals(s.length, 6);
    assertTypeError(() { s[null]; });
    assertTypeError(() { s['hello']; });
    assertTypeError(() { s[0] = 'x'; });
  }

  // TODO(jimhug): Fill out full set of string methods.
  static testStringMethods() {
    var s = "abcdef";
    assertEquals(s.isEmpty, false);
    assertEquals(s.startsWith("abc"), true);
    assertEquals(s.endsWith("def"), true);
    assertEquals(s.startsWith("aa"), false);
    assertEquals(s.endsWith("ff"), false);
    assertEquals(s.contains('cd', 0), true);
    assertEquals(s.contains('cd', 2), true);
    assertEquals(s.contains('cd', 3), false);
    assertEquals(s.indexOf('cd', 2), 2);
    assertEquals(s.indexOf('cd', 3), -1);

    assertTypeError(() { s.startsWith(1); });
    assertTypeError(() { s.endsWith(1); });
  }

  static testListOperators() {
    var a = [1,2,3,4];
    assertEquals(a[0], 1);
    assertTypeError(() { a['0']; });
    a[0] = 42;
    assertEquals(a[0], 42);
    assertTypeError(() { a['0'] = 99; });
    assertEquals(a.length, 4);
  }

  // TODO(jimhug): Fill out full set of list methods.
  static testListMethods() {
    var a = [1,2,3,4];
    assertEquals(a.isEmpty, false);
    assertEquals(a.length, 4);
    var exception = null;
    a.clear();
    assertEquals(a.length, 0);
  }

  static testMapOperators() {
    var d = new Map();
    d['a'] = 1;
    d['b'] = 2;
    assertEquals(d['a'], 1);
    assertEquals(d['b'], 2);
    assertEquals(d['c'], null);
  }

  static testMapMethods() {
    var d = new Map();
    d['a'] = 1;
    d['b'] = 2;
    assertEquals(d.containsValue(2), true);
    assertEquals(d.containsValue(3), false);
    assertEquals(d.containsKey('a'), true);
    assertEquals(d.containsKey('c'), false);
    assertEquals(d.keys.length, 2);
    assertEquals(d.values.length, 2);

    assertEquals(d.remove('c'), null);
    assertEquals(d.remove('b'), 2);
    assertEquals(d.keys.single, 'a');
    assertEquals(d.values.single, 1);

    d['c'] = 3;
    d['f'] = 4;
    assertEquals(d.keys.length, 3);
    assertEquals(d.values.length, 3);
    assertListContains(d.keys.toList(), ['a', 'c', 'f']);
    assertListContains(d.values.toList(), [1, 3, 4]);

    var count = 0;
    d.forEach((key, value) {
      count++;
      assertEquals(value, d[key]);
    });
    assertEquals(count, 3);

    d = { 'a': 1, 'b': 2 };
    assertEquals(d.containsValue(2), true);
    assertEquals(d.containsValue(3), false);
    assertEquals(d.containsKey('a'), true);
    assertEquals(d.containsKey('c'), false);
    assertEquals(d.keys.length, 2);
    assertEquals(d.values.length, 2);

    d['g'] = null;
    assertEquals(d.containsKey('g'), true);
    assertEquals(d['g'], null);
  }

  static testDateMethods() {
    var msec = 115201000;
    var d = new DateTime.fromMillisecondsSinceEpoch(msec, isUtc: true);
    assertEquals(d.second, 1);
    assertEquals(d.year, 1970);

    d = new DateTime.now();
    assertEquals(d.year >= 2011, true);
  }

  static testLiterals() {
    true.toString();
    1.0.toString();
    .5.toString();
    1.toString();
    if (false) {
      // Depends on http://b/4198808.
      null.toString();
    }
    '${null}'.toString();
    '${true}'.toString();
    '${false}'.toString();
    ''.toString();
    ''.endsWith('');
  }
}

main() {
  CoreRuntimeTypesTest.testMain();
}
