// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.mojo.system.impl;

import android.support.test.filters.SmallTest;

import org.chromium.mojo.MojoTestCase;
import org.chromium.mojo.system.Core;
import org.chromium.mojo.system.Core.HandleSignals;
import org.chromium.mojo.system.DataPipe;
import org.chromium.mojo.system.Handle;
import org.chromium.mojo.system.InvalidHandle;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojo.system.MojoResult;
import org.chromium.mojo.system.Pair;
import org.chromium.mojo.system.ResultAnd;
import org.chromium.mojo.system.SharedBufferHandle;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * Testing the core API.
 */
public class CoreImplTest extends MojoTestCase {
    private static final long RUN_LOOP_TIMEOUT_MS = 5;

    private static final ScheduledExecutorService WORKER =
            Executors.newSingleThreadScheduledExecutor();

    private static final HandleSignals ALL_SIGNALS =
            HandleSignals.none().setPeerClosed(true).setReadable(true).setWritable(true);

    private List<Handle> mHandlesToClose = new ArrayList<Handle>();

    /**
     * @see MojoTestCase#tearDown()
     */
    @Override
    protected void tearDown() throws Exception {
        MojoException toThrow = null;
        for (Handle handle : mHandlesToClose) {
            try {
                handle.close();
            } catch (MojoException e) {
                if (toThrow == null) {
                    toThrow = e;
                }
            }
        }
        if (toThrow != null) {
            throw toThrow;
        }
        super.tearDown();
    }

    private void addHandleToClose(Handle handle) {
        mHandlesToClose.add(handle);
    }

    private void addHandlePairToClose(Pair<? extends Handle, ? extends Handle> handles) {
        mHandlesToClose.add(handles.first);
        mHandlesToClose.add(handles.second);
    }

    private static void checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out) {
        Random random = new Random();

        // Writing a random 8 bytes message.
        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
        buffer.put(bytes);
        in.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE);

        // Try to read into a small buffer.
        ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length / 2);
        ResultAnd<MessagePipeHandle.ReadMessageResult> result =
                out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
        assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult());
        assertEquals(bytes.length, result.getValue().getMessageSize());
        assertEquals(0, result.getValue().getHandlesCount());

        // Read into a correct buffer.
        receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
        result = out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
        assertEquals(MojoResult.OK, result.getMojoResult());
        assertEquals(bytes.length, result.getValue().getMessageSize());
        assertEquals(0, result.getValue().getHandlesCount());
        assertEquals(0, receiveBuffer.position());
        assertEquals(result.getValue().getMessageSize(), receiveBuffer.limit());
        byte[] receivedBytes = new byte[result.getValue().getMessageSize()];
        receiveBuffer.get(receivedBytes);
        assertTrue(Arrays.equals(bytes, receivedBytes));
    }

    private static void checkSendingData(DataPipe.ProducerHandle in, DataPipe.ConsumerHandle out) {
        Random random = new Random();

        // Writing a random 8 bytes message.
        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
        buffer.put(bytes);
        ResultAnd<Integer> result = in.writeData(buffer, DataPipe.WriteFlags.NONE);
        assertEquals(MojoResult.OK, result.getMojoResult());
        assertEquals(bytes.length, result.getValue().intValue());

        // Query number of bytes available.
        ResultAnd<Integer> readResult = out.readData(null, DataPipe.ReadFlags.none().query(true));
        assertEquals(MojoResult.OK, readResult.getMojoResult());
        assertEquals(bytes.length, readResult.getValue().intValue());

        // Peek data into a buffer.
        ByteBuffer peekBuffer = ByteBuffer.allocateDirect(bytes.length);
        readResult = out.readData(peekBuffer, DataPipe.ReadFlags.none().peek(true));
        assertEquals(MojoResult.OK, readResult.getMojoResult());
        assertEquals(bytes.length, readResult.getValue().intValue());
        assertEquals(bytes.length, peekBuffer.limit());
        byte[] peekBytes = new byte[bytes.length];
        peekBuffer.get(peekBytes);
        assertTrue(Arrays.equals(bytes, peekBytes));

        // Read into a buffer.
        ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
        readResult = out.readData(receiveBuffer, DataPipe.ReadFlags.NONE);
        assertEquals(MojoResult.OK, readResult.getMojoResult());
        assertEquals(bytes.length, readResult.getValue().intValue());
        assertEquals(0, receiveBuffer.position());
        assertEquals(bytes.length, receiveBuffer.limit());
        byte[] receivedBytes = new byte[bytes.length];
        receiveBuffer.get(receivedBytes);
        assertTrue(Arrays.equals(bytes, receivedBytes));
    }

    private static void checkSharing(SharedBufferHandle in, SharedBufferHandle out) {
        Random random = new Random();

        ByteBuffer buffer1 = in.map(0, 8, SharedBufferHandle.MapFlags.NONE);
        assertEquals(8, buffer1.capacity());
        ByteBuffer buffer2 = out.map(0, 8, SharedBufferHandle.MapFlags.NONE);
        assertEquals(8, buffer2.capacity());

        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        buffer1.put(bytes);

        byte[] receivedBytes = new byte[bytes.length];
        buffer2.get(receivedBytes);

        assertTrue(Arrays.equals(bytes, receivedBytes));

        in.unmap(buffer1);
        out.unmap(buffer2);
    }

    /**
     * Testing that Core can be retrieved from a handle.
     */
    @SmallTest
    public void testGetCore() {
        Core core = CoreImpl.getInstance();

        Pair<? extends Handle, ? extends Handle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);
        assertEquals(core, handles.first.getCore());
        assertEquals(core, handles.second.getCore());

        handles = core.createDataPipe(null);
        addHandlePairToClose(handles);
        assertEquals(core, handles.first.getCore());
        assertEquals(core, handles.second.getCore());

        SharedBufferHandle handle = core.createSharedBuffer(null, 100);
        SharedBufferHandle handle2 = handle.duplicate(null);
        addHandleToClose(handle);
        addHandleToClose(handle2);
        assertEquals(core, handle.getCore());
        assertEquals(core, handle2.getCore());
    }

    private static void createAndCloseMessagePipe(MessagePipeHandle.CreateOptions options) {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(options);
        handles.first.close();
        handles.second.close();
    }

    /**
     * Testing {@link MessagePipeHandle} creation.
     */
    @SmallTest
    public void testMessagePipeCreation() {
        // Test creation with null options.
        createAndCloseMessagePipe(null);
        // Test creation with default options.
        createAndCloseMessagePipe(new MessagePipeHandle.CreateOptions());
    }

    /**
     * Testing {@link MessagePipeHandle}.
     */
    @SmallTest
    public void testMessagePipeEmpty() {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);

        // Testing read on an empty pipe.
        ResultAnd<MessagePipeHandle.ReadMessageResult> readResult =
                handles.first.readMessage(null, 0, MessagePipeHandle.ReadFlags.NONE);
        assertEquals(MojoResult.SHOULD_WAIT, readResult.getMojoResult());

        handles.first.close();
        handles.second.close();
    }

    /**
     * Testing {@link MessagePipeHandle}.
     */
    @SmallTest
    public void testMessagePipeSend() {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);

        checkSendingMessage(handles.first, handles.second);
        checkSendingMessage(handles.second, handles.first);
    }

    /**
     * Testing {@link MessagePipeHandle}.
     */
    @SmallTest
    public void testMessagePipeReceiveOnSmallBuffer() {
        Random random = new Random();
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);

        // Writing a random 8 bytes message.
        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
        buffer.put(bytes);
        handles.first.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE);

        ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(1);
        ResultAnd<MessagePipeHandle.ReadMessageResult> result =
                handles.second.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE);
        assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult());
        assertEquals(bytes.length, result.getValue().getMessageSize());
        assertEquals(0, result.getValue().getHandlesCount());
    }

    /**
     * Testing {@link MessagePipeHandle}.
     */
    @SmallTest
    public void testMessagePipeSendHandles() {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        Pair<MessagePipeHandle, MessagePipeHandle> handlesToShare = core.createMessagePipe(null);
        addHandlePairToClose(handles);
        addHandlePairToClose(handlesToShare);

        handles.first.writeMessage(null, Collections.<Handle>singletonList(handlesToShare.second),
                MessagePipeHandle.WriteFlags.NONE);
        assertFalse(handlesToShare.second.isValid());
        ResultAnd<MessagePipeHandle.ReadMessageResult> readMessageResult =
                handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE);
        assertEquals(1, readMessageResult.getValue().getHandlesCount());
        MessagePipeHandle newHandle =
                readMessageResult.getValue().getHandles().get(0).toMessagePipeHandle();
        addHandleToClose(newHandle);
        assertTrue(newHandle.isValid());
        checkSendingMessage(handlesToShare.first, newHandle);
        checkSendingMessage(newHandle, handlesToShare.first);
    }

    private static void createAndCloseDataPipe(DataPipe.CreateOptions options) {
        Core core = CoreImpl.getInstance();
        Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles =
                core.createDataPipe(options);
        handles.first.close();
        handles.second.close();
    }

    /**
     * Testing {@link DataPipe}.
     */
    @SmallTest
    public void testDataPipeCreation() {
        // Create datapipe with null options.
        createAndCloseDataPipe(null);
        DataPipe.CreateOptions options = new DataPipe.CreateOptions();
        // Create datapipe with element size set.
        options.setElementNumBytes(24);
        createAndCloseDataPipe(options);
        // Create datapipe with capacity set.
        options.setCapacityNumBytes(1024 * options.getElementNumBytes());
        createAndCloseDataPipe(options);
    }

    /**
     * Testing {@link DataPipe}.
     */
    @SmallTest
    public void testDataPipeSend() {
        Core core = CoreImpl.getInstance();

        Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
        addHandlePairToClose(handles);

        checkSendingData(handles.first, handles.second);
    }

    /**
     * Testing {@link DataPipe}.
     */
    @SmallTest
    public void testDataPipeTwoPhaseSend() {
        Random random = new Random();
        Core core = CoreImpl.getInstance();
        Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
        addHandlePairToClose(handles);

        // Writing a random 8 bytes message.
        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        ByteBuffer buffer = handles.first.beginWriteData(bytes.length, DataPipe.WriteFlags.NONE);
        assertTrue(buffer.capacity() >= bytes.length);
        buffer.put(bytes);
        handles.first.endWriteData(bytes.length);

        // Read into a buffer.
        ByteBuffer receiveBuffer =
                handles.second.beginReadData(bytes.length, DataPipe.ReadFlags.NONE);
        assertEquals(0, receiveBuffer.position());
        assertEquals(bytes.length, receiveBuffer.limit());
        byte[] receivedBytes = new byte[bytes.length];
        receiveBuffer.get(receivedBytes);
        assertTrue(Arrays.equals(bytes, receivedBytes));
        handles.second.endReadData(bytes.length);
    }

    /**
     * Testing {@link DataPipe}.
     */
    @SmallTest
    public void testDataPipeDiscard() {
        Random random = new Random();
        Core core = CoreImpl.getInstance();
        Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
        addHandlePairToClose(handles);

        // Writing a random 8 bytes message.
        byte[] bytes = new byte[8];
        random.nextBytes(bytes);
        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
        buffer.put(bytes);
        ResultAnd<Integer> result = handles.first.writeData(buffer, DataPipe.WriteFlags.NONE);
        assertEquals(MojoResult.OK, result.getMojoResult());
        assertEquals(bytes.length, result.getValue().intValue());

        // Discard bytes.
        final int nbBytesToDiscard = 4;
        assertEquals(nbBytesToDiscard,
                handles.second.discardData(nbBytesToDiscard, DataPipe.ReadFlags.NONE));

        // Read into a buffer.
        ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length - nbBytesToDiscard);
        ResultAnd<Integer> readResult =
                handles.second.readData(receiveBuffer, DataPipe.ReadFlags.NONE);
        assertEquals(MojoResult.OK, readResult.getMojoResult());
        assertEquals(bytes.length - nbBytesToDiscard, readResult.getValue().intValue());
        assertEquals(0, receiveBuffer.position());
        assertEquals(bytes.length - nbBytesToDiscard, receiveBuffer.limit());
        byte[] receivedBytes = new byte[bytes.length - nbBytesToDiscard];
        receiveBuffer.get(receivedBytes);
        assertTrue(Arrays.equals(
                Arrays.copyOfRange(bytes, nbBytesToDiscard, bytes.length), receivedBytes));
    }

    /**
     * Testing {@link SharedBufferHandle}.
     */
    @SmallTest
    public void testSharedBufferCreation() {
        Core core = CoreImpl.getInstance();
        // Test creation with empty options.
        core.createSharedBuffer(null, 8).close();
        // Test creation with default options.
        core.createSharedBuffer(new SharedBufferHandle.CreateOptions(), 8).close();
    }

    /**
     * Testing {@link SharedBufferHandle}.
     */
    @SmallTest
    public void testSharedBufferDuplication() {
        Core core = CoreImpl.getInstance();
        SharedBufferHandle handle = core.createSharedBuffer(null, 8);
        addHandleToClose(handle);

        // Test duplication with empty options.
        handle.duplicate(null).close();
        // Test creation with default options.
        handle.duplicate(new SharedBufferHandle.DuplicateOptions()).close();
    }

    /**
     * Testing {@link SharedBufferHandle}.
     */
    @SmallTest
    public void testSharedBufferSending() {
        Core core = CoreImpl.getInstance();
        SharedBufferHandle handle = core.createSharedBuffer(null, 8);
        addHandleToClose(handle);
        SharedBufferHandle newHandle = handle.duplicate(null);
        addHandleToClose(newHandle);

        checkSharing(handle, newHandle);
        checkSharing(newHandle, handle);
    }

    /**
     * Testing that invalid handle can be used with this implementation.
     */
    @SmallTest
    public void testInvalidHandle() {
        Core core = CoreImpl.getInstance();
        Handle handle = InvalidHandle.INSTANCE;

        // Checking sending an invalid handle.
        // Until the behavior is changed on the C++ side, handle gracefully 2 different use case:
        // - Receive a INVALID_ARGUMENT exception
        // - Receive an invalid handle on the other side.
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);
        try {
            handles.first.writeMessage(null, Collections.<Handle>singletonList(handle),
                    MessagePipeHandle.WriteFlags.NONE);
            ResultAnd<MessagePipeHandle.ReadMessageResult> readMessageResult =
                    handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE);
            assertEquals(1, readMessageResult.getValue().getHandlesCount());
            assertFalse(readMessageResult.getValue().getHandles().get(0).isValid());
        } catch (MojoException e) {
            assertEquals(MojoResult.INVALID_ARGUMENT, e.getMojoResult());
        }
    }

    /**
     * Testing the pass method on message pipes.
     */
    @SmallTest
    public void testMessagePipeHandlePass() {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);

        assertTrue(handles.first.isValid());
        MessagePipeHandle handleClone = handles.first.pass();

        addHandleToClose(handleClone);

        assertFalse(handles.first.isValid());
        assertTrue(handleClone.isValid());
        checkSendingMessage(handleClone, handles.second);
        checkSendingMessage(handles.second, handleClone);
    }

    /**
     * Testing the pass method on data pipes.
     */
    @SmallTest
    public void testDataPipeHandlePass() {
        Core core = CoreImpl.getInstance();
        Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
        addHandlePairToClose(handles);

        DataPipe.ProducerHandle producerClone = handles.first.pass();
        DataPipe.ConsumerHandle consumerClone = handles.second.pass();

        addHandleToClose(producerClone);
        addHandleToClose(consumerClone);

        assertFalse(handles.first.isValid());
        assertFalse(handles.second.isValid());
        assertTrue(producerClone.isValid());
        assertTrue(consumerClone.isValid());
        checkSendingData(producerClone, consumerClone);
    }

    /**
     * Testing the pass method on shared buffers.
     */
    @SmallTest
    public void testSharedBufferPass() {
        Core core = CoreImpl.getInstance();
        SharedBufferHandle handle = core.createSharedBuffer(null, 8);
        addHandleToClose(handle);
        SharedBufferHandle newHandle = handle.duplicate(null);
        addHandleToClose(newHandle);

        SharedBufferHandle handleClone = handle.pass();
        SharedBufferHandle newHandleClone = newHandle.pass();

        addHandleToClose(handleClone);
        addHandleToClose(newHandleClone);

        assertFalse(handle.isValid());
        assertTrue(handleClone.isValid());
        checkSharing(handleClone, newHandleClone);
        checkSharing(newHandleClone, handleClone);
    }

    /**
     * esting handle conversion to native and back.
     */
    @SmallTest
    public void testHandleConversion() {
        Core core = CoreImpl.getInstance();
        Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
        addHandlePairToClose(handles);

        MessagePipeHandle converted =
                core.acquireNativeHandle(handles.first.releaseNativeHandle()).toMessagePipeHandle();
        addHandleToClose(converted);

        assertFalse(handles.first.isValid());

        checkSendingMessage(converted, handles.second);
        checkSendingMessage(handles.second, converted);
    }
}
