// Copyright (c) 2013, 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.
// VMOptions=--optimization_counter_threshold=100

// Test field type tracking and field list-length tracking in the presence of
// multiple isolates.

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

class A {
  A(this.a);
  var a;
}

class B extends A {
  B(a, this.b) : super(a) { }

  var b;
}

f1(SendPort send_port) {
  send_port.send(new B("foo", "bar"));
}

test_b(B obj) => obj.a + obj.b;

test_field_type() {
  var receive_port = new ReceivePort();
  asyncStart();
  Future<Isolate> isolate = Isolate.spawn(f1, receive_port.sendPort);
  B b = new B(1, 2);
  for (var i = 0; i < 200; i++) { test_b(b); }
  Expect.equals(3, test_b(b));
  Future<B> item = receive_port.first;
  item.then((B value) {
      Expect.equals("foobar", test_b(value));
      receive_port.close();
      asyncEnd();
  });
}

class C {
  C(this.list);
  final List list;
}

f2(SendPort send_port) {
  send_port.send(new C(new List(1)));
}

test_c(C obj) => obj.list[9999];

test_list_length() {
  var receive_port = new ReceivePort();
  asyncStart();
  Future<Isolate> isolate = Isolate.spawn(f2, receive_port.sendPort);
  C c = new C(new List(10000));
  for (var i = 0; i < 200; i++) { test_c(c); }
  Expect.equals(null, test_c(c));
  Future<C> item = receive_port.first;
  item.then((C value) {
      Expect.throws(() => test_c(value), (e) => e is RangeError);
      receive_port.close();
      asyncEnd();
  });
}

main() {
  test_field_type();
  test_list_length();
}
