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

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * Written by Martin Buchholz with assistance from members of JCP
 * JSR-166 Expert Group and released to the public domain, as
 * explained at http://creativecommons.org/publicdomain/zero/1.0/
 */

/*
 * @test
 * @modules java.base/java.util.concurrent:open
 * @run testng WhiteBox
 * @summary White box tests of implementation details
 */

import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadLocalRandom;
import static java.util.stream.Collectors.toList;
import java.util.function.Consumer;

@Test
public class WhiteBox {
    final ThreadLocalRandom rnd = ThreadLocalRandom.current();
    final VarHandle HEAD, TAIL, ITEM, NEXT;

    WhiteBox() throws ReflectiveOperationException {
        Class<?> qClass = ConcurrentLinkedQueue.class;
        Class<?> nodeClass = Class.forName(qClass.getName() + "$Node");
        MethodHandles.Lookup lookup
            = MethodHandles.privateLookupIn(qClass, MethodHandles.lookup());
        HEAD = lookup.findVarHandle(qClass, "head", nodeClass);
        TAIL = lookup.findVarHandle(qClass, "tail", nodeClass);
        NEXT = lookup.findVarHandle(nodeClass, "next", nodeClass);
        ITEM = lookup.findVarHandle(nodeClass, "item", Object.class);
    }

    Object head(ConcurrentLinkedQueue q) { return HEAD.getVolatile(q); }
    Object tail(ConcurrentLinkedQueue q) { return TAIL.getVolatile(q); }
    Object item(Object node)             { return ITEM.getVolatile(node); }
    Object next(Object node)             { return NEXT.getVolatile(node); }

    int nodeCount(ConcurrentLinkedQueue q) {
        int i = 0;
        for (Object p = head(q); p != null; ) {
            i++;
            if (p == (p = next(p))) p = head(q);
        }
        return i;
    }

    void assertIsSelfLinked(Object node) {
        assertSame(next(node), node);
        assertNull(item(node));
    }

    void assertIsNotSelfLinked(Object node) {
        assertNotSame(node, next(node));
    }

    @Test
    public void addRemove() {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        assertInvariants(q);
        assertNull(item(head(q)));
        assertEquals(nodeCount(q), 1);
        q.add(1);
        assertEquals(nodeCount(q), 2);
        assertInvariants(q);
        q.remove(1);
        assertEquals(nodeCount(q), 1);
        assertInvariants(q);
    }

    /**
     * Traversal actions that visit every node and do nothing, but
     * have side effect of squeezing out dead nodes.
     */
    @DataProvider
    public Object[][] traversalActions() {
        return List.<Consumer<ConcurrentLinkedQueue>>of(
            q -> q.forEach(e -> {}),
            q -> assertFalse(q.contains(new Object())),
            q -> assertFalse(q.remove(new Object())),
            q -> q.spliterator().forEachRemaining(e -> {}),
            q -> q.stream().collect(toList()),
            q -> assertFalse(q.removeIf(e -> false)),
            q -> assertFalse(q.removeAll(List.of())))
            .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
    }

    @Test(dataProvider = "traversalActions")
    public void traversalOperationsCollapseNodes(
        Consumer<ConcurrentLinkedQueue> traversalAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        Object oldHead;
        int n = 1 + rnd.nextInt(5);
        for (int i = 0; i < n; i++) q.add(i);
        assertInvariants(q);
        assertEquals(nodeCount(q), n + 1);
        oldHead = head(q);
        traversalAction.accept(q); // collapses head node
        assertIsSelfLinked(oldHead);
        assertInvariants(q);
        assertEquals(nodeCount(q), n);
        // Iterator.remove does not currently try to collapse dead nodes
        for (Iterator it = q.iterator(); it.hasNext(); ) {
            it.next();
            it.remove();
        }
        assertEquals(nodeCount(q), n);
        assertInvariants(q);
        oldHead = head(q);
        traversalAction.accept(q); // collapses all nodes
        if (n > 1) assertIsSelfLinked(oldHead);
        assertEquals(nodeCount(q), 1);
        assertInvariants(q);

        for (int i = 0; i < n + 1; i++) q.add(i);
        assertEquals(nodeCount(q), n + 2);
        oldHead = head(q);
        assertEquals(0, q.poll()); // 2 leading nodes collapsed
        assertIsSelfLinked(oldHead);
        assertEquals(nodeCount(q), n);
        assertTrue(q.remove(n));
        assertEquals(nodeCount(q), n);
        traversalAction.accept(q); // trailing node is never collapsed
    }

    @Test(dataProvider = "traversalActions")
    public void traversalOperationsCollapseLeadingNodes(
        Consumer<ConcurrentLinkedQueue> traversalAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        Object oldHead;
        int n = 1 + rnd.nextInt(5);
        for (int i = 0; i < n; i++) q.add(i);
        assertEquals(nodeCount(q), n + 1);
        oldHead = head(q);
        traversalAction.accept(q);
        assertInvariants(q);
        assertEquals(nodeCount(q), n);
        assertIsSelfLinked(oldHead);
    }

    @Test(dataProvider = "traversalActions")
    public void traversalOperationsDoNotSelfLinkInteriorNodes(
        Consumer<ConcurrentLinkedQueue> traversalAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        int c;
        int n = 3 + rnd.nextInt(3);
        for (int i = 0; i < n; i++) q.add(i);
        Object oneNode;
        for (oneNode = head(q);
             ! (item(oneNode) != null && item(oneNode).equals(1));
             oneNode = next(oneNode))
            ;
        Object next = next(oneNode);
        c = nodeCount(q);
        for (Iterator it = q.iterator(); it.hasNext(); )
            if (it.next().equals(1)) it.remove();
        assertEquals(nodeCount(q), c - 1); // iterator detached head!
        assertNull(item(oneNode));
        assertSame(next, next(oneNode));
        assertInvariants(q);
        c = nodeCount(q);
        traversalAction.accept(q);
        assertEquals(nodeCount(q), c - 1);
        assertSame(next, next(oneNode)); // un-linked, but not self-linked
    }

    /**
     * Checks that traversal operations collapse a random pattern of
     * dead nodes as could normally only occur with a race.
     */
    @Test(dataProvider = "traversalActions")
    public void traversalOperationsCollapseRandomNodes(
        Consumer<ConcurrentLinkedQueue> traversalAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        int n = rnd.nextInt(6);
        for (int i = 0; i < n; i++) q.add(i);
        ArrayList nulledOut = new ArrayList();
        for (Object p = head(q); p != null; p = next(p))
            if (item(p) != null && rnd.nextBoolean()) {
                nulledOut.add(item(p));
                ITEM.setVolatile(p, null);
            }
        traversalAction.accept(q);
        int c = nodeCount(q);
        assertEquals(q.size(), c - (q.contains(n - 1) ? 0 : 1));
        for (int i = 0; i < n; i++)
            assertTrue(nulledOut.contains(i) ^ q.contains(i));
    }

    /**
     * Traversal actions that remove every element, and are also
     * expected to squeeze out dead nodes.
     */
    @DataProvider
    public Object[][] bulkRemovalActions() {
        return List.<Consumer<ConcurrentLinkedQueue>>of(
            q -> q.clear(),
            q -> assertTrue(q.removeIf(e -> true)),
            q -> assertTrue(q.retainAll(List.of())))
            .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
    }

    @Test(dataProvider = "bulkRemovalActions")
    public void bulkRemovalOperationsCollapseNodes(
        Consumer<ConcurrentLinkedQueue> bulkRemovalAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        int n = 1 + rnd.nextInt(5);
        for (int i = 0; i < n; i++) q.add(i);
        bulkRemovalAction.accept(q);
        assertEquals(nodeCount(q), 1);
        assertInvariants(q);
    }

    /**
     * Actions that remove the first element, and are expected to
     * leave at most one slack dead node at head.
     */
    @DataProvider
    public Object[][] pollActions() {
        return List.<Consumer<ConcurrentLinkedQueue>>of(
            q -> assertNotNull(q.poll()),
            q -> assertNotNull(q.remove()))
            .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
    }

    @Test(dataProvider = "pollActions")
    public void pollActionsOneNodeSlack(
        Consumer<ConcurrentLinkedQueue> pollAction) {
        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
        int n = 1 + rnd.nextInt(5);
        for (int i = 0; i < n; i++) q.add(i);
        assertEquals(nodeCount(q), n + 1);
        for (int i = 0; i < n; i++) {
            int c = nodeCount(q);
            boolean slack = item(head(q)) == null;
            if (slack) assertNotNull(item(next(head(q))));
            pollAction.accept(q);
            assertEquals(nodeCount(q), q.isEmpty() ? 1 : c - (slack ? 2 : 0));
        }
        assertInvariants(q);
    }

    byte[] serialBytes(Object o) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(o);
            oos.flush();
            oos.close();
            return bos.toByteArray();
        } catch (Exception fail) {
            throw new AssertionError(fail);
        }
    }

    @SuppressWarnings("unchecked")
    <T> T serialClone(T o) {
        try {
            ObjectInputStream ois = new ObjectInputStream
                (new ByteArrayInputStream(serialBytes(o)));
            T clone = (T) ois.readObject();
            assertNotSame(o, clone);
            assertSame(o.getClass(), clone.getClass());
            return clone;
        } catch (Exception fail) {
            throw new AssertionError(fail);
        }
    }

    @Test
    public void testSerialization() {
        ConcurrentLinkedQueue q = serialClone(new ConcurrentLinkedQueue());
        assertInvariants(q);
    }

    /** Checks conditions which should always be true. */
    void assertInvariants(ConcurrentLinkedQueue q) {
        assertNotNull(head(q));
        assertNotNull(tail(q));
        // head is never self-linked (but tail may!)
        for (Object h; next(h = head(q)) == h; )
            assertNotSame(h, head(q)); // must be update race
    }
}
