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

import "dart:collection";
import "dart:typed_data";
import "package:expect/expect.dart";

void main() {
  // Growable lists. Initial length 0.
  testConcurrentModification(new List());
  testConcurrentModification(new List<int>().toList());
  testConcurrentModification(new List<int?>(0).toList());
  testConcurrentModification(new List.filled(0, null, growable: true));
  testConcurrentModification([]);
  testConcurrentModification(new List.from(const []));
  testConcurrentModification(new MyList([]));
  testConcurrentModification(new MyList<int>([]).toList());

  testConcurrentModification(new Uint8List(0).toList());
  testConcurrentModification(new Int8List(0).toList());
  testConcurrentModification(new Uint16List(0).toList());
  testConcurrentModification(new Int16List(0).toList());
  testConcurrentModification(new Uint32List(0).toList());
  testConcurrentModification(new Int32List(0).toList());

  testConcurrentAddSelf([]);
  testConcurrentAddSelf([1, 2, 3]);
}

void testConcurrentModification(List<int?> list) {
  // add, removeLast.
  list.clear();
  list.addAll([1, 2, 3, 2, 7, 9, 9, 7, 2, 3, 2, 1]);

  // Operations that change the length cause ConcurrentModificationError.
  void testModification(action()) {
    testIterator(int when) {
      list.length = 4;
      list.setAll(0, [0, 1, 2, 3]);
      Expect.throws(() {
        for (var element in list) {
          if (element == when) action();
        }
      }, (e) => e is ConcurrentModificationError);
    }

    testForEach(int when) {
      list.length = 4;
      list.setAll(0, [0, 1, 2, 3]);
      Expect.throws(() {
        list.forEach((var element) {
          if (element == when) action();
        });
      }, (e) => e is ConcurrentModificationError);
    }

    // Test the change at different points of the iteration.
    testIterator(0);
    testIterator(1);
    testIterator(3);
    testForEach(0);
    testForEach(1);
    testForEach(3);
  }

  testModification(() => list.add(5));
  testModification(() => list.addAll([5, 6]));
  testModification(() => list.removeLast());
  for (int i = 0; i < 4; i++) {
    testModification(() => list.remove(i));
    testModification(() => list.removeAt(i));
    testModification(() => list.removeWhere((x) => x == i));
    testModification(() => list.retainWhere((x) => x != i));
    testModification(() => list.insert(i, 5));
    testModification(() => list.insertAll(i, [5, 6]));
    testModification(() => list.removeRange(i, i + 1));
    testModification(() => list.replaceRange(i, i + 1, [5, 6]));
  }
}

testConcurrentAddSelf(List list) {
  Expect.throws(() {
    list.addAll(list);
  }, (e) => e is ConcurrentModificationError, "testConcurrentAddSelf($list)");
}

class MyList<E> extends ListBase<E> {
  List<E> _source;
  MyList(this._source);
  int get length => _source.length;
  void set length(int length) {
    _source.length = length;
  }

  E operator [](int index) => _source[index];
  void operator []=(int index, E value) {
    _source[index] = value;
  }
}
