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

// @dart = 2.9

import "package:expect/expect.dart";

class FixedHashCode {
  final int _hashCode;
  const FixedHashCode(this._hashCode);
  int get hashCode {
    return _hashCode;
  }
}

class SetIteratorTest {
  static testMain() {
    testSmallSet();
    testLargeSet();
    testEmptySet();
    testSetWithDeletedEntries();
    testBug5116829();
    testDifferentSizes();
    testDifferentHashCodes();
  }

  static int sum(int expected, Iterator<int> it) {
    int count = 0;
    while (it.moveNext()) {
      count += it.current;
    }
    Expect.equals(expected, count);
  }

  static void testSmallSet() {
    Set<int> set = new Set<int>();
    set.add(1);
    set.add(2);
    set.add(3);

    Iterator<int> it = set.iterator;
    sum(6, it);
    Expect.isFalse(it.moveNext());
    Expect.isNull(it.current);
  }

  static void testLargeSet() {
    Set<int> set = new Set<int>();
    int count = 0;
    for (int i = 0; i < 100; i++) {
      count += i;
      set.add(i);
    }
    Iterator<int> it = set.iterator;
    sum(count, it);
    Expect.isFalse(it.moveNext());
    Expect.isNull(it.current);
  }

  static void testEmptySet() {
    Set<int> set = new Set<int>();
    Iterator<int> it = set.iterator;
    sum(0, it);
    Expect.isFalse(it.moveNext());
    Expect.isNull(it.current);
  }

  static void testSetWithDeletedEntries() {
    Set<int> set = new Set<int>();
    for (int i = 0; i < 100; i++) {
      set.add(i);
    }
    for (int i = 0; i < 100; i++) {
      set.remove(i);
    }
    Iterator<int> it = set.iterator;
    Expect.isFalse(it.moveNext());
    it = set.iterator;
    sum(0, it);
    Expect.isFalse(it.moveNext());
    Expect.isNull(it.current);

    int count = 0;
    for (int i = 0; i < 100; i++) {
      set.add(i);
      if (i % 2 == 0)
        set.remove(i);
      else
        count += i;
    }
    it = set.iterator;
    sum(count, it);
    Expect.isFalse(it.moveNext());
    Expect.isNull(it.current);
  }

  static void testBug5116829() {
    // During iteration we skipped slot 0 of the hashset's key list. "A" was
    // hashed to slot 0 and therefore triggered the bug.
    Set<String> mystrs = new Set<String>();
    mystrs.add("A");
    int seen = 0;
    for (String elt in mystrs) {
      seen++;
      Expect.equals("A", elt);
    }
    Expect.equals(1, seen);
  }

  static void testDifferentSizes() {
    for (int i = 1; i < 20; i++) {
      Set set = new Set();
      int sum = 0;
      for (int j = 0; j < i; j++) {
        set.add(j);
        sum += j;
      }
      int count = 0;
      int controlSum = 0;
      for (int x in set) {
        controlSum += x;
        count++;
      }
      Expect.equals(i, count);
      Expect.equals(sum, controlSum);
    }
  }

  static void testDifferentHashCodes() {
    for (int i = -20; i < 20; i++) {
      Set set = new Set();
      var element = new FixedHashCode(i);
      set.add(element);
      Expect.equals(1, set.length);
      bool foundIt = false;
      for (var x in set) {
        foundIt = true;
        Expect.equals(true, identical(x, element));
      }
      Expect.equals(true, foundIt);
    }
  }
}

main() {
  SetIteratorTest.testMain();
}
