/*
 * Copyright (c) 2006, 2007, 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 6360946 6360948
 * @summary Test various operations on concurrently mutating collections
 * @author Martin Buchholz
 */

import static java.util.Collections.*;
import java.util.*;
import java.util.concurrent.*;

public class RacingCollections {
    /**
     * How long to run each "race" (in milliseconds).
     * Turn this up to some higher value like 1000 for stress testing:
     * java -Dmillis=1000 RacingCollections
     */
    final static long defaultWorkTimeMillis = Long.getLong("millis", 10L);

    /**
     * Whether to print debug information.
     */
    final static boolean debug = Boolean.getBoolean("debug");

    final static Integer one = 1;
    final static Integer two = 2;

    /**
     * A thread that mutates an object forever, alternating between
     * being empty and containing singleton "two"
     */
    static class Frobber extends CheckedThread {
        volatile boolean done = false;
        boolean keepGoing(int i) { return (i % 128 != 0) || ! done; }

        final Object elLoco;
        Frobber(Object elLoco) {
            this.elLoco = elLoco;
            this.start();
        }

        @SuppressWarnings("unchecked") void clear(Object o) {
            if (o instanceof Collection)
                ((Collection<?>)o).clear();
            else
                ((Map<?,?>)o).clear();
        }

        @SuppressWarnings("unchecked") void realRun() {
            // Mutate elLoco wildly forever, checking occasionally for "done"
            clear(elLoco);
            if (elLoco instanceof List) {
                List<Integer> l = (List<Integer>) elLoco;
                for (int i = 0; keepGoing(i); i++) {
                    switch (i%2) {
                    case 0: l.add(two);    break;
                    case 1: l.add(0, two); break;
                    }
                    switch (i%2) {
                    case 0: l.remove(two); break;
                    case 1: l.remove(0);   break;
                    }}}
            else if (elLoco instanceof Deque) {
                Deque<Integer> q = (Deque<Integer>) elLoco;
                for (int i = 0; keepGoing(i); i++) {
                    switch (i%6) {
                    case 0: q.add(two);        break;
                    case 1: q.addFirst(two);   break;
                    case 2: q.addLast(two);    break;
                    case 3: q.offer(two);      break;
                    case 4: q.offerFirst(two); break;
                    case 5: q.offerLast(two);  break;
                    }
                    switch (i%6) {
                    case 0: q.remove(two);     break;
                    case 1: q.removeFirst();   break;
                    case 2: q.removeLast();    break;
                    case 3: q.poll();          break;
                    case 4: q.pollFirst();     break;
                    case 5: q.pollLast();      break;
                    }}}
            else if (elLoco instanceof Queue) {
                Queue<Integer> q = (Queue<Integer>) elLoco;
                for (int i = 0; keepGoing(i); i++) {
                    switch (i%2) {
                    case 0: q.add(two);    break;
                    case 1: q.offer(two);  break;
                    }
                    switch (i%2) {
                    case 0: q.remove(two); break;
                    case 1: q.poll();      break;
                    }}}
            else if (elLoco instanceof Map) {
                Map<Integer, Boolean> m = (Map<Integer, Boolean>) elLoco;
                for (int i = 0; keepGoing(i); i++) {
                    m.put(two, true);
                    m.remove(two);
                }}
            else if (elLoco instanceof Collection) {
                Collection<Integer> c = (Collection<Integer>) elLoco;
                for (int i = 0; keepGoing(i); i++) {
                    c.add(two);
                    c.remove(two);
                }}
            else { throw new Error("Huh? " + elLoco); }
        }

        void enoughAlready() {
            done = true;
            try { join(); } catch (Throwable t) { unexpected(t); }
        }
    }

    private static void checkEqualSanity(Object theRock, Object elLoco) {
        //equal(theRock, theRock);
        equal(elLoco, elLoco);

        // It would be nice someday to have theRock and elLoco never "equal",
        // although the meaning of "equal" for mutating collections
        // is a bit fuzzy.  Uncomment when/if we fix:
        // 6374942: Improve thread safety of collection .equals() methods
        //notEqual(theRock, elLoco);
        //notEqual(elLoco, theRock);

        notEqual(theRock.toString(), elLoco.toString());
    }

    static class Looper {
        final long quittingTime;
        int i = 0;
        Looper() { this(defaultWorkTimeMillis); }
        Looper(long workTimeMillis) {
            quittingTime = System.nanoTime() + workTimeMillis * 1024 * 1024;
        }
        boolean keepGoing() {
            return (i++ % 128 != 0) || (System.nanoTime() < quittingTime);
        }
    }

    private static void frob(Object theRock, Object elLoco) {
        Frobber frobber = new Frobber(elLoco);
        try {
            if (theRock instanceof Collection) {
                @SuppressWarnings("unchecked")
                Collection<Integer> c = (Collection<Integer>) theRock;
                if (! c.contains(one))
                    c.add(one);
            } else {
                @SuppressWarnings("unchecked")
                Map<Integer, Boolean> m = (Map<Integer, Boolean>) theRock;
                if (! m.containsKey(one))
                    m.put(one, true);
            }
            for (Looper looper = new Looper(); looper.keepGoing(); )
                checkEqualSanity(theRock, elLoco);
        }
        catch (Throwable t) { unexpected(t); }
        finally { frobber.enoughAlready(); }
    }

    private static List<Map<Integer, Boolean>> newConcurrentMaps() {
        List<Map<Integer, Boolean>> list =
            new ArrayList<Map<Integer, Boolean>>();
        list.add(new ConcurrentHashMap<Integer, Boolean>());
        list.add(new ConcurrentSkipListMap<Integer, Boolean>());
        return list;
    }

    private static List<Map<Integer, Boolean>> maps() {
        List<Map<Integer, Boolean>> list = newConcurrentMaps();
        list.add(new Hashtable<Integer, Boolean>());
        list.add(new HashMap<Integer, Boolean>());
        list.add(new TreeMap<Integer, Boolean>());
        Comparator<Integer> cmp = new Comparator<Integer>() {
            public int compare(Integer x, Integer y) {
                return x - y;
            }};
        list.add(new TreeMap<Integer, Boolean>(Collections.reverseOrder(cmp)));
        return list;
    }

    private static List<Set<Integer>> newConcurrentSets() {
        List<Set<Integer>> list = new ArrayList<Set<Integer>>();
        list.add(new ConcurrentSkipListSet<Integer>());
        list.add(new CopyOnWriteArraySet<Integer>());
        return list;
    }

    private static List<Set<Integer>> newSets() {
        List<Set<Integer>> list = newConcurrentSets();
        list.add(new HashSet<Integer>());
        list.add(new TreeSet<Integer>());
        list.add(new TreeSet<Integer>(Collections.reverseOrder()));
        return list;
    }

    private static List<List<Integer>> newConcurrentLists() {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        list.add(new CopyOnWriteArrayList<Integer>());
        return list;
    }

    private static List<List<Integer>> newLists() {
        List<List<Integer>> list = newConcurrentLists();
        list.add(new Vector<Integer>());
        list.add(new ArrayList<Integer>());
        return list;
    }

    private static List<Queue<Integer>> newConcurrentQueues() {
        List<Queue<Integer>> list =
            new ArrayList<Queue<Integer>>(newConcurrentDeques());
        list.add(new LinkedBlockingQueue<Integer>(10));
        list.add(new LinkedTransferQueue<Integer>());
        return list;
    }

    private static List<Queue<Integer>> newQueues() {
        List<Queue<Integer>> list =
            new ArrayList<Queue<Integer>>(newDeques());
        list.add(new LinkedBlockingQueue<Integer>(10));
        return list;
    }

    private static List<Deque<Integer>> newConcurrentDeques() {
        List<Deque<Integer>> list = new ArrayList<Deque<Integer>>();
        list.add(new LinkedBlockingDeque<Integer>(10));
        return list;
    }

    private static List<Deque<Integer>> newDeques() {
        List<Deque<Integer>> list = newConcurrentDeques();
        list.add(new ArrayDeque<Integer>());
        list.add(new LinkedList<Integer>());
        return list;
    }

    private static void describe(Class<?> k, Object x, Object y) {
        if (debug)
            System.out.printf("%s: %s, %s%n", k.getSimpleName(),
                              x.getClass().getSimpleName(),
                              y.getClass().getSimpleName());
    }

    private static void realMain(String[] args) {
        for (Map<Integer, Boolean> x : maps())
            for (Map<Integer, Boolean> y : newConcurrentMaps()) {
                describe(Map.class, x, y);
                x.put(one, true);
                frob(x, y);
                frob(unmodifiableMap(x), y);
                frob(synchronizedMap(x), y);
                frob(x, synchronizedMap(y));
                frob(checkedMap(x, Integer.class, Boolean.class), y);
                frob(x, checkedMap(y, Integer.class, Boolean.class));
                x.clear();
                frob(newSetFromMap(x), newSetFromMap(y));
                frob(x.keySet(), newSetFromMap(y));
            }

        for (Set<Integer> x : newSets())
            for (Set<Integer> y : newConcurrentSets()) {
                describe(Set.class, x, y);
                frob(x, y);
                frob(unmodifiableSet(x), y);
                frob(synchronizedSet(x), y);
                frob(x, synchronizedSet(y));
                frob(checkedSet(x, Integer.class), y);
                frob(x, checkedSet(y, Integer.class));
            }

        for (List<Integer> x : newLists())
            for (List<Integer> y : newConcurrentLists()) {
                describe(List.class, x, y);
                frob(x, y);
                frob(unmodifiableList(x), y);
                frob(synchronizedList(x), y);
                frob(x, synchronizedList(y));
                frob(checkedList(x, Integer.class), y);
                frob(x, checkedList(y, Integer.class));
            }

        for (Queue<Integer> x : newQueues())
            for (Queue<Integer> y : newConcurrentQueues()) {
                describe(Queue.class, x, y);
                frob(x, y);
            }

        for (Deque<Integer> x : newDeques())
            for (Deque<Integer> y : newConcurrentDeques()) {
                describe(Deque.class, x, y);
                frob(asLifoQueue(x), y);
                frob(x, asLifoQueue(y));
            }
    }

    //--------------------- 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 String toString(Object x) {
        return ((x instanceof Collection) || (x instanceof Map)) ?
            x.getClass().getName() : x.toString();}
    static void equal(Object x, Object y) {
        if (x == null ? y == null : x.equals(y)) pass();
        else fail(toString(x) + " not equal to " + toString(y));}
    static void notEqual(Object x, Object y) {
        if (x == null ? y == null : x.equals(y))
            fail(toString(x) + " equal to " + toString(y));
        else pass();}
    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 CheckedThread extends Thread {
        abstract void realRun() throws Throwable;
        public void run() {
            try { realRun(); } catch (Throwable t) { unexpected(t); }}}
}
