/**
 * Copyright 2009-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.javacrumbs.completionstage;

import org.junit.Test;

import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.function.Function;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

public abstract class AbstractUnfinishedCompletionStageTest extends AbstractCompletionStageTest {

    protected boolean finished() {
        return false;
    }

    @Test
    public void acceptEitherTakesOtherValueIfTheFirstIsNotReady() {
        CompletionStage<String> completionStage = createCompletionStage(VALUE);
        CompletionStage<String> completionStage2 = createCompletionStage(VALUE2);
        finish(completionStage2);

        @SuppressWarnings("unchecked")
        Consumer<String> consumer = mock(Consumer.class);
        completionStage.acceptEither(completionStage2, consumer);

        verify(consumer, times(1)).accept(VALUE2);
        finish(completionStage);

        verify(consumer, times(1)).accept(any(String.class));
    }

    @Test
    public void acceptEitherPropagatesExceptionFromSecondCompletable() {
        CompletionStage<String> completionStage = createCompletionStage(VALUE);
        CompletionStage<String> completionStage2 = createCompletionStage(EXCEPTION);
        finish(completionStage2);

        @SuppressWarnings("unchecked")
        Consumer<String> consumer = mock(Consumer.class);
        @SuppressWarnings("unchecked")
        Function<Throwable, Void> errorHandler = mock(Function.class);
        completionStage.acceptEither(completionStage2, consumer).exceptionally(errorHandler);

        verify(errorHandler, times(1)).apply(any(CompletionException.class));
        finish(completionStage);

        verifyZeroInteractions(consumer);
    }

    @Test
    public void acceptEitherPropagatesExceptionFromFirstCompletable() {
        CompletionStage<String> completionStage = createCompletionStage(EXCEPTION);
        CompletionStage<String> completionStage2 = createCompletionStage(VALUE2);
        finish(completionStage);

        @SuppressWarnings("unchecked")
        Consumer<String> consumer = mock(Consumer.class);
        @SuppressWarnings("unchecked")
        Function<Throwable, Void> errorHandler = mock(Function.class);
        completionStage.acceptEither(completionStage2, consumer).exceptionally(errorHandler);

        verify(errorHandler, times(1)).apply(any(CompletionException.class));
        finish(completionStage2);

        verifyZeroInteractions(consumer);
    }

    @Test
    public void acceptEitherPropagatesExceptionThrownByConsumerWhenProcessingFirsStage() {
        CompletionStage<String> completionStage = createCompletionStage(VALUE);
        CompletionStage<String> completionStage2 = createCompletionStage(VALUE2);
        finish(completionStage);

        Consumer<String> consumer = s -> {
            throw EXCEPTION;
        };

        @SuppressWarnings("unchecked")
        Function<Throwable, Void> errorHandler = mock(Function.class);
        completionStage.acceptEither(completionStage2, consumer).exceptionally(errorHandler);

        verify(errorHandler, times(1)).apply(any(CompletionException.class));
        finish(completionStage2);
    }

    @Test
    public void acceptEitherPropagatesExceptionThrownByConsumerWhenProcessingSecondStage() {
        CompletionStage<String> completionStage = createCompletionStage(VALUE);
        CompletionStage<String> completionStage2 = createCompletionStage(VALUE2);
        finish(completionStage2);

        Consumer<String> consumer = s -> {
            throw EXCEPTION;
        };

        @SuppressWarnings("unchecked")
        Function<Throwable, Void> errorHandler = mock(Function.class);
        completionStage.acceptEither(completionStage2, consumer).exceptionally(errorHandler);

        verify(errorHandler, times(1)).apply(any(CompletionException.class));
        finish(completionStage);
    }
}

@@ -1511,47 +1511,8 @@
 );%0A%0A
-        @SuppressWarnings(%22unchecked%22)%0A
     
@@ -1543,33 +1543,32 @@
 sumer = mock
-(
 Consumer
 .class);%0A   
@@ -1547,38 +1547,33 @@
 r = mockConsumer
-.class
+(
 );%0A        compl
@@ -2067,47 +2067,8 @@
 );%0A%0A
-        @SuppressWarnings(%22unchecked%22)%0A
     
@@ -2099,33 +2099,32 @@
 sumer = mock
-(
 Consumer
 .class);%0A   
@@ -2115,55 +2115,12 @@
 umer
-.class);%0A        @SuppressWarnings(%22unchecked%22)
+();%0A
 %0A   
@@ -2165,33 +2165,32 @@
 ndler = mock
-(
 Function
 .class);%0A   
@@ -2169,38 +2169,33 @@
 r = mockFunction
-.class
+(
 );%0A        compl
@@ -2429,32 +2429,157 @@
 nsumer);%0A    %7D%0A%0A
+    @SuppressWarnings(%22unchecked%22)%0A    private Consumer%3CString%3E mockConsumer() %7B%0A        return mock(Consumer.class);%0A    %7D%0A%0A
     @Test%0A    pu
@@ -2848,47 +2848,8 @@
 );%0A%0A
-        @SuppressWarnings(%22unchecked%22)%0A
     
@@ -2880,33 +2880,32 @@
 sumer = mock
-(
 Consumer
 .class);%0A   
@@ -2896,55 +2896,12 @@
 umer
-.class);%0A        @SuppressWarnings(%22unchecked%22)
+();%0A
 %0A   
@@ -2946,33 +2946,32 @@
 ndler = mock
-(
 Function
 .class);%0A   
@@ -2950,38 +2950,33 @@
 r = mockFunction
-.class
+(
 );%0A        compl
@@ -3211,32 +3211,166 @@
 nsumer);%0A    %7D%0A%0A
+    @SuppressWarnings(%22unchecked%22)%0A    private Function%3CThrowable, Void%3E mockFunction() %7B%0A        return mock(Function.class);%0A    %7D%0A%0A
     @Test%0A    pu
@@ -3444,16 +3444,17 @@
 singFirs
+t
 Stage() 
@@ -3739,46 +3739,8 @@
 %7D;%0A%0A
-        @SuppressWarnings(%22unchecked%22)
 %0A   
@@ -3785,33 +3785,32 @@
 ndler = mock
-(
 Function
 .class);%0A   
@@ -3789,38 +3789,33 @@
 r = mockFunction
-.class
+(
 );%0A        compl
@@ -4403,46 +4403,8 @@
 %7D;%0A%0A
-        @SuppressWarnings(%22unchecked%22)
 %0A   
@@ -4449,33 +4449,32 @@
 ndler = mock
-(
 Function
 .class);%0A   
@@ -4457,30 +4457,25 @@
 mockFunction
-.class
+(
 );%0A        c

Test cleanup