package com.atlassian.bitbucket.mesh.git.hosting;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcStreamChunk;
import com.atlassian.bitbucket.mesh.util.SatiableConsumer;
import com.google.protobuf.ByteString;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import static com.atlassian.bitbucket.mesh.git.hosting.GitPackets.FLUSH_PACKET;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class ReceivePackRequestAnalyzerTest {

    private ReceivePackRequestAnalyzer analyzer;

    @Before
    public void setUp() {
        analyzer = new ReceivePackRequestAnalyzer();
    }

    @Test
    public void testDisconnectAfterRefAdvertisement() {
        analyze(FLUSH_PACKET);

        assertFalse(analyzer.wantsPacketLines());
        assertFalse(analyzer.isShallow());
        assertFalse(analyzer.isSigned());
        assertFalse(analyzer.isUpdate());
    }

    @Test
    public void testPush() {
        analyze(GitTestData.V1_PUSH_INPUT);

        assertFalse(analyzer.wantsPacketLines());
        assertFalse(analyzer.isShallow());
        assertFalse(analyzer.isSigned());
        assertTrue(analyzer.isUpdate());
    }

    private void analyze(String data) {
        SatiableConsumer<RpcStreamChunk> delegate = mock(SatiableConsumer.class);
        FilteringGitReceivePackStream stream = new FilteringGitReceivePackStream(delegate);
        stream.addFilter(analyzer);

        ByteString input = ByteString.copyFromUtf8(data);
        RpcStreamChunk chunk = RpcStreamChunk.newBuilder()
                .setClosed(true)
                .setData(input)
                .build();
        stream.write(chunk);

        ArgumentCaptor<RpcStreamChunk> chunkCaptor = ArgumentCaptor.forClass(RpcStreamChunk.class);
        verify(delegate, atLeastOnce()).accept(chunkCaptor.capture());

        ByteString output = ByteString.EMPTY;
        for (RpcStreamChunk outChunk : chunkCaptor.getAllValues()) {
            output = output.concat(outChunk.getData());
        }
        assertArrayEquals(input.toByteArray(), output.toByteArray());
    }
}