/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.transport.nio;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.transport.nio.channel.NioSocketChannel;
import org.junit.Before;

import java.io.IOException;
import java.nio.ByteBuffer;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class WriteOperationTests extends ESTestCase {

    private NioSocketChannel channel;
    private ActionListener<Void> listener;

    @Before
    @SuppressWarnings("unchecked")
    public void setFields() {
        channel = mock(NioSocketChannel.class);
        listener = mock(ActionListener.class);

    }

    public void testFlush() throws IOException {
        WriteOperation writeOp = new WriteOperation(channel, new BytesArray(new byte[10]), listener);


        when(channel.write(any(ByteBuffer[].class))).thenReturn(10);

        writeOp.flush();

        assertTrue(writeOp.isFullyFlushed());
    }

    public void testPartialFlush() throws IOException {
        WriteOperation writeOp = new WriteOperation(channel, new BytesArray(new byte[10]), listener);

        when(channel.write(any(ByteBuffer[].class))).thenReturn(5);

        writeOp.flush();

        assertFalse(writeOp.isFullyFlushed());
    }
}

@@ -923,16 +923,79 @@
 sArray;%0A
+import org.elasticsearch.common.bytes.CompositeBytesReference;%0A
 import o
@@ -1028,16 +1028,16 @@
 stCase;%0A
-
 import o
@@ -1117,16 +1117,51 @@
 .Before;
+%0Aimport org.mockito.ArgumentCaptor;
 %0A%0Aimport
@@ -1209,16 +1209,39 @@
 eBuffer;
+%0Aimport java.util.List;
 %0A%0Aimport
@@ -2220,32 +2220,32 @@
 iteOp.flush();%0A%0A
-
         assertFa
@@ -2280,11 +2280,1912 @@
 );%0A    %7D
+%0A%0A    public void testMultipleFlushesWithCompositeBuffer() throws IOException %7B%0A        BytesArray bytesReference1 = new BytesArray(new byte%5B10%5D);%0A        BytesArray bytesReference2 = new BytesArray(new byte%5B15%5D);%0A        BytesArray bytesReference3 = new BytesArray(new byte%5B3%5D);%0A        CompositeBytesReference bytesReference = new CompositeBytesReference(bytesReference1, bytesReference2, bytesReference3);%0A        WriteOperation writeOp = new WriteOperation(channel, bytesReference, listener);%0A%0A        ArgumentCaptor%3CByteBuffer%5B%5D%3E buffersCaptor = ArgumentCaptor.forClass(ByteBuffer%5B%5D.class);%0A%0A        when(channel.write(buffersCaptor.capture())).thenReturn(5)%0A            .thenReturn(5)%0A            .thenReturn(2)%0A            .thenReturn(15)%0A            .thenReturn(1);%0A%0A        writeOp.flush();%0A        assertFalse(writeOp.isFullyFlushed());%0A        writeOp.flush();%0A        assertFalse(writeOp.isFullyFlushed());%0A        writeOp.flush();%0A        assertFalse(writeOp.isFullyFlushed());%0A        writeOp.flush();%0A        assertFalse(writeOp.isFullyFlushed());%0A        writeOp.flush();%0A        assertTrue(writeOp.isFullyFlushed());%0A%0A        List%3CByteBuffer%5B%5D%3E values = buffersCaptor.getAllValues();%0A        ByteBuffer%5B%5D byteBuffers = values.get(0);%0A        assertEquals(3, byteBuffers.length);%0A        assertEquals(10, byteBuffers%5B0%5D.remaining());%0A%0A        byteBuffers = values.get(1);%0A        assertEquals(3, byteBuffers.length);%0A        assertEquals(5, byteBuffers%5B0%5D.remaining());%0A%0A        byteBuffers = values.get(2);%0A        assertEquals(2, byteBuffers.length);%0A        assertEquals(15, byteBuffers%5B0%5D.remaining());%0A%0A        byteBuffers = values.get(3);%0A        assertEquals(2, byteBuffers.length);%0A        assertEquals(13, byteBuffers%5B0%5D.remaining());%0A%0A        byteBuffers = values.get(4);%0A        assertEquals(1, byteBuffers.length);%0A        assertEquals(1, byteBuffers%5B0%5D.remaining());%0A    %7D
 %0A%7D%0A

Add test for writer operation buffer accounting (#27707)