package com.atlassian.bitbucket.scm.throttle;

import com.atlassian.bitbucket.i18n.KeyedMessage;
import com.atlassian.bitbucket.scm.http.HttpScmRequest;
import com.atlassian.bitbucket.scm.ssh.SshScmRequest;
import com.atlassian.bitbucket.throttle.ResourceBusyException;
import com.atlassian.bitbucket.throttle.ThrottleService;
import com.atlassian.bitbucket.throttle.Ticket;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ThrottledScmRequestFactoryTest {

    @Mock
    HttpScmRequest httpScmRequest;
    @Mock
    SshScmRequest sshScmRequest;
    @Mock
    ThrottleService throttleService;
    @InjectMocks
    ThrottledScmRequestFactory throttledFactory;
    @Mock
    Ticket ticket;

    @Before
    public void setUp() {
    }

    @Test
    public void testHttpThrottled() throws Exception {
        when(throttleService.acquireTicket(eq(ThrottledScmRequestFactory.RESOURCE_NAME))).thenThrow(
                new ResourceBusyException(new KeyedMessage("this", "is", "not"), "good"));

        try {
            throttledFactory.throttled(httpScmRequest).handleRequest();
            fail("Expected a ResourceBusyException");
        } catch (ResourceBusyException e) {
            // expected
        }

        verify(httpScmRequest, never()).handleRequest();
    }

    @Test
    public void testHttpNotThrottled() throws Exception {
        when(throttleService.acquireTicket(eq(ThrottledScmRequestFactory.RESOURCE_NAME))).thenReturn(ticket);

        throttledFactory.throttled(httpScmRequest).handleRequest();

        verify(httpScmRequest).handleRequest();
    }

    @Test(expected = NullPointerException.class)
    public void testNullHttpRequestIsChecked() throws Exception {
        assertNull(throttledFactory.throttled((HttpScmRequest) null));
    }

    @Test(expected = NullPointerException.class)
    public void testNullSshRequestIsChecked() throws Exception {
        assertNull(throttledFactory.throttled((SshScmRequest) null));
    }

    @Test
    public void testSshThrottled() throws Exception {
        when(throttleService.acquireTicket(eq(ThrottledScmRequestFactory.RESOURCE_NAME))).thenThrow(
                new ResourceBusyException(new KeyedMessage("this", "is", "not"), "good"));

        try {
            throttledFactory.throttled(sshScmRequest).handleRequest();
            fail("Expected a ResourceBusyException");
        } catch (ResourceBusyException e) {
            // expected
        }

        verify(sshScmRequest, never()).handleRequest();
    }

    @Test
    public void testSshNotThrottled() throws Exception {
        when(throttleService.acquireTicket(eq(ThrottledScmRequestFactory.RESOURCE_NAME))).thenReturn(ticket);

        throttledFactory.throttled(sshScmRequest).handleRequest();

        verify(sshScmRequest).handleRequest();
    }


}
