/*
 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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(18675309);

    static void compareCollections(Collection c1, Collection c2) {
        Object[] c1Array = c1.toArray();
        Object[] c2Array = c2.toArray();

        check(c1Array.length == c2Array.length);
        for(Object aC1 : c1Array) {
            boolean found = false;
            for(Object aC2 : c2Array) {
                if(Objects.equals(aC1, aC2)) {
                    found = true;
                    break;
                }
            }

            if(!found)
                fail(aC1 + " not found in " + Arrays.toString(c2Array));
        }
    }

    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 ConcurrentLinkedDeque(),
            new ConcurrentLinkedDeque() {
                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);}}}
}
