package com.atlassian.stash.internal.bootstrap;

import com.atlassian.bitbucket.user.DummySecurityService;
import com.atlassian.bitbucket.user.SecurityService;
import com.atlassian.bitbucket.util.Operation;
import com.atlassian.bitbucket.util.UncheckedOperation;
import com.atlassian.license.SIDManager;
import com.atlassian.stash.internal.concurrent.BootstrapLock;
import com.atlassian.stash.internal.concurrent.InternalLockService;
import com.atlassian.stash.internal.server.InternalApplicationPropertiesService;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class BootstrapperTest {

    @Rule
    public final ExpectedException expectedException = ExpectedException.none();
    @Mock
    private InternalApplicationPropertiesService propertiesService;
    @Mock
    private InternalLockService internalLockService;
    @Mock
    private BootstrapLock bootstrapLock;
    @Mock
    private UncheckedOperation bootstrapOperation;
    @Mock
    private SIDManager sidManager;

    private Bootstrapper bootstrapper;
    private SecurityService securityService;

    @Before
    public void setUp() throws Throwable {
        when(internalLockService.getBootstrapLock()).thenReturn(bootstrapLock);
        when(bootstrapLock.withLock(any())).thenAnswer(invocation -> invocation.getArgumentAt(0, Operation.class).perform());

        securityService = new DummySecurityService();

        bootstrapper = new Bootstrapper(propertiesService, securityService, sidManager, bootstrapOperation, internalLockService);
    }

    @Test
    public void testNoBootstrapWhenInitialised() {
        when(propertiesService.isBootstrapped()).thenReturn(true);

        bootstrapper.start();

        verify(bootstrapOperation, never()).perform();
    }

    @Test(expected = NumberFormatException.class)
    public void testBootstrapOperationThrowsException() {
        UncheckedOperation bootstrapOperation = () -> {
            throw new NumberFormatException();
        };

        bootstrapper = new Bootstrapper(propertiesService, securityService, sidManager, bootstrapOperation, internalLockService);
        bootstrapper.start();
    }
}