package com.palantir.docker.compose.execution;

import com.palantir.docker.compose.utils.MockitoMultiAnswer;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;

import java.io.IOException;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

public class RetryingDockerComposeShould {
    private static final Object SUCCESS = null;

    private final DockerCompose dockerCompose = mock(DockerCompose.class);
    private final RetryingDockerCompose retryingDockerCompose = new RetryingDockerCompose(2, dockerCompose);

    @Test
    public void not_retry_if_the_up_command_was_successful() throws IOException, InterruptedException {
        retryingDockerCompose.up();
        verify(dockerCompose).up();
        verifyNoMoreInteractions(dockerCompose);
    }

    @Test
    public void retry_up_if_the_command_failed_once() throws IOException, InterruptedException {
        doAnswer(new MockitoMultiAnswer() {
            @Override
            protected Object firstCall(InvocationOnMock invocation) throws Exception {
                throw new DockerComposeExecutionException();
            }

            @Override
            protected Object secondCall(InvocationOnMock invocation) throws Exception {
                return SUCCESS;
            }
        }).when(dockerCompose).up();

        retryingDockerCompose.up();
        verify(dockerCompose, times(2)).up();
        verifyNoMoreInteractions(dockerCompose);
    }

    @Test
    public void throw_the_last_exception_when_failing_more_times_than_the_specified_attempts() throws IOException, InterruptedException {
        DockerComposeExecutionException finalException = new DockerComposeExecutionException();
        doAnswer(new MockitoMultiAnswer() {
            @Override
            protected Object firstCall(InvocationOnMock invocation) throws Exception {
                throw new DockerComposeExecutionException();
            }

            @Override
            protected Object secondCall(InvocationOnMock invocation) throws Exception {
                throw finalException;
            }
        }).when(dockerCompose).up();

        try {
            retryingDockerCompose.up();
            fail("Should have caught exception");
        } catch (DockerComposeExecutionException actualException) {
            assertThat(actualException, is(finalException));
        }

        verify(dockerCompose, times(2)).up();
        verifyNoMoreInteractions(dockerCompose);
    }
}

@@ -37,24 +37,86 @@
 execution;%0A%0A
+import com.palantir.docker.compose.connection.ContainerNames;%0A
 import com.p
@@ -160,24 +160,24 @@
 ultiAnswer;%0A
-
 import org.j
@@ -610,16 +610,56 @@
 actions;
+%0Aimport static org.mockito.Mockito.when;
 %0A%0Apublic
@@ -927,16 +927,97 @@
 ompose);
+%0A    private final ContainerNames someContainerNames = new ContainerNames(%22hey%22);
 %0A%0A    @T
@@ -1980,15 +1980,16 @@
 hen_
+up_
 fail
-ing
+s
 _mor
@@ -2830,32 +2830,32 @@
 n));%0A        %7D%0A%0A
-
         verify(d
@@ -2938,11 +2938,2169 @@
 );%0A    %7D
+%0A%0A    @Test%0A    public void not_retry_if_the_ps_command_was_successful_and_return_the_correct_container_names() throws IOException, InterruptedException %7B%0A        when(dockerCompose.ps()).thenReturn(someContainerNames);%0A%0A        assertThat(retryingDockerCompose.ps(), is(someContainerNames));%0A        verify(dockerCompose).ps();%0A        verifyNoMoreInteractions(dockerCompose);%0A    %7D%0A%0A    @Test%0A    public void retry_ps_if_the_command_failed_once_and_return_the_last_container_names() throws IOException, InterruptedException %7B%0A        when(dockerCompose.ps()).thenAnswer(new MockitoMultiAnswer() %7B%0A            @Override%0A            protected Object firstCall(InvocationOnMock invocation) throws Exception %7B%0A                throw new DockerComposeExecutionException();%0A            %7D%0A%0A            @Override%0A            protected Object secondCall(InvocationOnMock invocation) throws Exception %7B%0A                return someContainerNames;%0A            %7D%0A        %7D);%0A%0A        assertThat(retryingDockerCompose.ps(), is(someContainerNames));%0A        verify(dockerCompose, times(2)).ps();%0A        verifyNoMoreInteractions(dockerCompose);%0A    %7D%0A%0A    @Test%0A    public void throw_the_last_exception_when_ps_fails_more_times_than_the_specified_attempts() throws IOException, InterruptedException %7B%0A        DockerComposeExecutionException finalException = new DockerComposeExecutionException();%0A        when(dockerCompose.ps()).thenAnswer(new MockitoMultiAnswer() %7B%0A            @Override%0A            protected Object firstCall(InvocationOnMock invocation) throws Exception %7B%0A                throw new DockerComposeExecutionException();%0A            %7D%0A%0A            @Override%0A            protected Object secondCall(InvocationOnMock invocation) throws Exception %7B%0A                throw finalException;%0A            %7D%0A        %7D);%0A%0A        try %7B%0A            retryingDockerCompose.ps();%0A            fail(%22Should have caught exception%22);%0A        %7D catch (DockerComposeExecutionException actualException) %7B%0A            assertThat(actualException, is(finalException));%0A        %7D%0A%0A        verify(dockerCompose, times(2)).ps();%0A        verifyNoMoreInteractions(dockerCompose);%0A    %7D
 %0A%7D%0A

Add tests for ps