code: // from gee.cs.oswego.edu/home/jsr166/jsr166
  
  package jsr166tests.jtreg.util.Collection;
  
  /*
   * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  /*
   * @test
   * @bug 6415641 6377302
   * @summary Concurrent collections are permitted to lie about their size
   * @author Martin Buchholz
   */
  
  import java.io.*;
  import java.util.*;
  import java.util.concurrent.*;
  
  @SuppressWarnings("unchecked")
  public class BiggernYours {
      static final Random rnd = new Random();
  
      static void compareCollections(Collection c1, Collection c2) {
          arrayEqual(c1.toArray(),
                     c2.toArray());
          arrayEqual(c1.toArray(new Object[0]),
                     c2.toArray(new Object[0]));
          arrayEqual(c1.toArray(new Object[5]),
                     c2.toArray(new Object[5]));
      }
  
      static void compareMaps(Map m1, Map m2) {
          compareCollections(m1.keySet(),
                             m2.keySet());
          compareCollections(m1.values(),
                             m2.values());
          compareCollections(m1.entrySet(),
                             m2.entrySet());
      }
  
      static void compareNavigableMaps(NavigableMap m1, NavigableMap m2) {
          compareMaps(m1, m2);
          compareMaps(m1.descendingMap(),
                      m2.descendingMap());
          compareMaps(m1.tailMap(Integer.MIN_VALUE),
                      m2.tailMap(Integer.MIN_VALUE));
          compareMaps(m1.headMap(Integer.MAX_VALUE),
                      m2.headMap(Integer.MAX_VALUE));
      }
  
      static void compareNavigableSets(NavigableSet s1, NavigableSet s2) {
          compareCollections(s1, s2);
          compareCollections(s1.descendingSet(),
                             s2.descendingSet());
          compareCollections(s1.tailSet(Integer.MIN_VALUE),
                             s2.tailSet(Integer.MIN_VALUE));
      }
  
      static abstract class MapFrobber { abstract void frob(Map m); }
      static abstract class SetFrobber { abstract void frob(Set s); }
      static abstract class ColFrobber { abstract void frob(Collection c); }
  
      static ColFrobber adder(final int i) {
          return new ColFrobber() {void frob(Collection c) { c.add(i); }};
      }
  
      static final ColFrobber[] adders =
      { adder(1), adder(3), adder(2) };
  
      static MapFrobber putter(final int k, final int v) {
          return new MapFrobber() {void frob(Map m) { m.put(k,v); }};
      }
  
      static final MapFrobber[] putters =
      { putter(1, -2), putter(3, -6), putter(2, -4) };
  
      static void unexpected(Throwable t, Object suspect) {
          System.out.println(suspect.getClass());
          unexpected(t);
      }
  
      static void testCollections(Collection c1, Collection c2) {
          try {
              compareCollections(c1, c2);
              for (ColFrobber adder : adders) {
                  for (Collection c : new Collection[]{c1, c2})
                      adder.frob(c);
                  compareCollections(c1, c2);
              }
          } catch (Throwable t) { unexpected(t, c1); }
      }
  
      static void testNavigableSets(NavigableSet s1, NavigableSet s2) {
          try {
              compareNavigableSets(s1, s2);
              for (ColFrobber adder : adders) {
                  for (Set s : new Set[]{s1, s2})
                      adder.frob(s);
                  compareNavigableSets(s1, s2);
              }
          } catch (Throwable t) { unexpected(t, s1); }
      }
  
      static void testMaps(Map m1, Map m2) {
          try {
              compareMaps(m1, m2);
              for (MapFrobber putter : putters) {
                  for (Map m : new Map[]{m1, m2})
                      putter.frob(m);
                  compareMaps(m1, m2);
              }
          } catch (Throwable t) { unexpected(t, m1); }
      }
  
      static void testNavigableMaps(NavigableMap m1, NavigableMap m2) {
          try {
              compareNavigableMaps(m1, m2);
              for (MapFrobber putter : putters) {
                  for (Map m : new Map[]{m1, m2})
                      putter.frob(m);
                  compareNavigableMaps(m1, m2);
              }
          } catch (Throwable t) { unexpected(t, m1); }
      }
  
      static int randomize(int size) { return rnd.nextInt(size + 2); }
  
      @SuppressWarnings("serial")
      private static void realMain(String[] args) throws Throwable {
          testNavigableMaps(
              new ConcurrentSkipListMap(),
              new ConcurrentSkipListMap() {
                  public int size() {return randomize(super.size());}});
  
          testNavigableSets(
              new ConcurrentSkipListSet(),
              new ConcurrentSkipListSet() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new CopyOnWriteArraySet(),
              new CopyOnWriteArraySet() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new CopyOnWriteArrayList(),
              new CopyOnWriteArrayList() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new TreeSet(),
              new TreeSet() {
                  public int size() {return randomize(super.size());}});
  
          testMaps(
              new ConcurrentHashMap(),
              new ConcurrentHashMap() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new ConcurrentLinkedQueue(),
              new ConcurrentLinkedQueue() {
                  public int size() {return randomize(super.size());}});
  
  //        testCollections(
  //            new LinkedTransferQueue(),
  //            new LinkedTransferQueue() {
  //                public int size() {return randomize(super.size());}});
  
          testCollections(
              new LinkedBlockingQueue(),
              new LinkedBlockingQueue() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new LinkedBlockingDeque(),
              new LinkedBlockingDeque() {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new ArrayBlockingQueue(5),
              new ArrayBlockingQueue(5) {
                  public int size() {return randomize(super.size());}});
  
          testCollections(
              new PriorityBlockingQueue(5),
              new PriorityBlockingQueue(5) {
                  public int size() {return randomize(super.size());}});
      }
  
      //--------------------- Infrastructure ---------------------------
      static volatile int passed = 0, failed = 0;
      static void pass() {passed++;}
      static void fail() {failed++; Thread.dumpStack();}
      static void fail(String msg) {System.out.println(msg); fail();}
      static void unexpected(Throwable t) {failed++; t.printStackTrace();}
      static void check(boolean cond) {if (cond) pass(); else fail();}
      static void equal(Object x, Object y) {
          if (x == null ? y == null : x.equals(y)) pass();
          else fail(x + " not equal to " + y);}
      static void arrayEqual(Object[] x, Object[] y) {
          if (x == null ? y == null : Arrays.equals(x, y)) pass();
          else fail(Arrays.toString(x) + " not equal to " + Arrays.toString(y));}
      public static void main(String[] args) throws Throwable {
          try {realMain(args);} catch (Throwable t) {unexpected(t);}
          System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
          if (failed > 0) throw new AssertionError("Some tests failed");}
      private static abstract class Fun {abstract void f() throws Throwable;}
      static void THROWS(Class<? extends Throwable> k, Fun... fs) {
          for (Fun f : fs)
              try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
              catch (Throwable t) {
                  if (k.isAssignableFrom(t.getClass())) pass();
                  else unexpected(t);}}
      private static abstract class CheckedThread extends Thread {
          abstract void realRun() throws Throwable;
          public void run() {
              try {realRun();} catch (Throwable t) {unexpected(t);}}}
  }
  