/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.imagepipeline.producers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import com.facebook.common.references.CloseableReference;
import com.facebook.imagepipeline.image.CloseableImage;
import org.junit.*;
import org.junit.runner.*;
import org.mockito.*;
import org.mockito.invocation.*;
import org.mockito.stubbing.*;
import org.robolectric.*;
import org.robolectric.annotation.*;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
/**
* Checks basic properties of swallow result producer, that is:
* - it swallows all results.
* - it notifies previous consumer of last result.
* - it notifies previous consumer of a failure.
*/
@RunWith(RobolectricTestRunner.class)
@Config(manifest= Config.NONE)
public class SwallowResultProducerTest {
@Mock public Producer<CloseableReference<CloseableImage>> mInputProducer;
@Mock public Consumer<Void> mConsumer;
@Mock public ProducerContext mProducerContext;
@Mock public Exception mException;
private CloseableReference<CloseableImage> mFinalImageReference;
private CloseableReference<CloseableImage> mIntermediateImageReference;
private SwallowResultProducer<CloseableReference<CloseableImage>>
mSwallowResultProducer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mSwallowResultProducer =
new SwallowResultProducer<CloseableReference<CloseableImage>>(mInputProducer);
mFinalImageReference = CloseableReference.of(mock(CloseableImage.class));
mIntermediateImageReference = CloseableReference.of(mock(CloseableImage.class));
}
@Test
public void testSwallowResults() {
setupInputProducerStreamingSuccess();
mSwallowResultProducer.produceResults(mConsumer, mProducerContext);
verify(mConsumer).onNewResult(null, Consumer.IS_LAST);
verifyNoMoreInteractions(mConsumer);
}
@Test
public void testPassOnNullResult() {
setupInputProducerNotFound();
mSwallowResultProducer.produceResults(mConsumer, mProducerContext);
verify(mConsumer).onNewResult(null, Consumer.IS_LAST);
verifyNoMoreInteractions(mConsumer);
}
@Test
public void testPassOnFailure() {
setupInputProducerFailure();
mSwallowResultProducer.produceResults(mConsumer, mProducerContext);
verify(mConsumer).onFailure(mException);
verifyNoMoreInteractions(mConsumer);
}
@Test
public void testPassOnCancellation() {
setupInputProducerCancellation();
mSwallowResultProducer.produceResults(mConsumer, mProducerContext);
verify(mConsumer).onCancellation();
verifyNoMoreInteractions(mConsumer);
}
private void setupInputProducerStreamingSuccess() {
doAnswer(new ProduceResultsNewResultAnswer(
Arrays.asList(mIntermediateImageReference, mFinalImageReference)))
.when(mInputProducer).produceResults(any(Consumer.class), eq(mProducerContext));
}
private void setupInputProducerNotFound() {
final List<CloseableReference<CloseableImage>> empty =
new ArrayList<CloseableReference<CloseableImage>>(1);
empty.add(null);
doAnswer(
new ProduceResultsNewResultAnswer(empty))
.when(mInputProducer).produceResults(any(Consumer.class), eq(mProducerContext));
}
private void setupInputProducerFailure() {
doAnswer(new ProduceResultsFailureAnswer()).
when(mInputProducer).produceResults(any(Consumer.class), eq(mProducerContext));
}
private void setupInputProducerCancellation() {
doAnswer(new ProduceResultsCancellationAnswer()).
when(mInputProducer).produceResults(any(Consumer.class), eq(mProducerContext));
}
private static class ProduceResultsNewResultAnswer implements Answer<Void> {
private final List<CloseableReference<CloseableImage>> mResults;
private ProduceResultsNewResultAnswer(List<CloseableReference<CloseableImage>> results) {
mResults = results;
}
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Consumer consumer = (Consumer) invocation.getArguments()[0];
Iterator<CloseableReference<CloseableImage>> iterator = mResults.iterator();
while (iterator.hasNext()) {
CloseableReference<CloseableImage> result = iterator.next();
consumer.onNewResult(result, BaseConsumer.simpleStatusForIsLast(!iterator.hasNext()));
}
return null;
}
}
private class ProduceResultsFailureAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Consumer consumer = (Consumer) invocation.getArguments()[0];
consumer.onFailure(mException);
return null;
}
}
private class ProduceResultsCancellationAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Consumer consumer = (Consumer) invocation.getArguments()[0];
consumer.onCancellation();
return null;
}
}
}