// uses Int as values by default
asclass TestUnorderedSet {
  new HashSet a;
  Set b;
  settable Int randomSeed;
  
  abstract Set makeSet();

  int n = 1000, valueRange = 100;
  bool remove = true;
  
  O makeEntry() { ret random(valueRange); }
  O randomNonContainedEntry() { ret random(valueRange+1, valueRange*2); }
  
  S moreInfo(Set b) { ret ""; }
  
  void printStats {
    print(joinNemptiesWithSlash(n2(b), moreInfo(b)) + " - " + takeFirst(10, b.iterator());
    print(/*"Size HashSet: " + n2(deepObjectSize(a))*/
      "Size " + shortClassName(b) + ": " + n2(deepObjectSize(b)));
  }
  
  run {
    temp tempSetRandomSeedUnlessNull(randomSeed);

    b = makeSet();
    printStats();
    repeat n {
      var o = makeEntry();
      bool change = addToTwoCollections(a, b, o);
      print((change ? "Added " : "Already contained ") + o);
      if (remove) {
        o = makeEntry();
        change = removeFromTwoCollections(a, b, o);
        print((change ? "Removed " : "Didn't contain ") + o);
      }
      assertSetsEqual(a, b);
      repeat 5 { assertFalse(b.contains(randomNonContainedEntry())); }
      printStats();
    }
  }
}