package com.atlassian.bitbucket.web.cgi;

import com.atlassian.utils.process.Watchdog;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;

import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class CgiOutputHandlerTest {
    
    private static final String EXPIRE_DATE = "Fri, 01 Jan 1980 00:00:00 GMT";
    private static final String CACHE_CONTROL = "no-cache, max-age=0, must-revalidate";
    private static final String PRAGMA = "no-cache";
    private static final String CONTENT_TYPE = "application/x-git-upload-pack-advertisement";
    
    private static final String BODY = "001e# service=git-upload-pack\n" +
            "000000a3135e3c0301db8ef1fc7df25640529d49a0f3f7d3 HEAD\u0000multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done\n" +
            "00635beffb578a2ce5308176543caff86c3b10047bb5 refs/heads/FECRU-2034-permission-check-create-project\n" +
            "004d6c10603ace124392c31c0da71d0ed9cdd3523fff refs/heads/commit-id-in-build-number\n" +
            "003f135e3c0301db8ef1fc7df25640529d49a0f3f7d3 refs/heads/master\n" +
            "004c1e7a3e24839d4e3841989278bd6c58527c1f50c8 refs/heads/maven-project-reorg\n" +
            "0000";
    
    private static final String GIT_UPLOAD_PACK = "Expires: " + EXPIRE_DATE + "\n" +
            "Pragma: " + PRAGMA + "\n" +
            "Cache-Control: " + CACHE_CONTROL + "\n" +
            "Content-Type: " + CONTENT_TYPE + "\n" +
            "\n" +
            BODY;
    
    @Mock
    private HttpServletRequest request;
    
    @Mock
    private ServletOutputStream outputStream;
    
    @Mock
    private HttpServletResponse response;

    @Mock
    private Watchdog watchdog;

    private CgiOutputHandler handler;
    
    private int index;
    private byte[] bytesReceived;

    @Before
    public void setup() throws Exception {
        handler = new CgiOutputHandler(response, 1024);
        when(response.getOutputStream()).thenReturn(outputStream);
        bytesReceived = new byte[BODY.getBytes("UTF-8").length];
        doAnswer(new Answer<Void>() {
            public Void answer(InvocationOnMock invocation) throws Throwable {
                final byte[] bytes = (byte[]) invocation.getArguments()[0];
                final int off = (Integer) invocation.getArguments()[1];
                final int n = (Integer) invocation.getArguments()[2];
                for (int i = off; i < bytes.length && off + n < bytes.length; i++) {
                    if (index >= bytesReceived.length) {
                        break;
                    }
                    bytesReceived[index] = bytes[i];
                    index++;
                }
                return null;
            }
        }).when(outputStream).write((byte[]) any(), anyInt(), anyInt());
        handler.setWatchdog(watchdog);
    }

    @Test
    public void testProcess() throws Exception {
        handler.process(new ByteArrayInputStream(GIT_UPLOAD_PACK.getBytes("UTF-8")));
        verify(response).addHeader("Expires", EXPIRE_DATE);
        verify(response).addHeader("Pragma", PRAGMA);
        verify(response).addHeader("Cache-Control", CACHE_CONTROL);
        verify(response).addHeader("Content-Type", CONTENT_TYPE);
        verify(response).getOutputStream();
        assertArrayEquals(BODY.getBytes("UTF-8"), bytesReceived);
    }
}
