package com.bumptech.glide.manager;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.bumptech.glide.request.Request;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@RunWith(JUnit4.class)
public class RequestTrackerTest {
private RequestTracker tracker;
@Before
public void setUp() {
tracker = new RequestTracker();
}
@Test
public void testClearsAddedRequestsOnDestroy() {
Request request = mock(Request.class);
tracker.addRequest(request);
tracker.clearRequests();
verify(request).clear();
verify(request).recycle();
}
@Test
public void testClearRemoveAndRecycle_withNullRequest_doesNothingAndReturnsFalse() {
assertThat(tracker.clearRemoveAndRecycle(null)).isFalse();
}
@Test
public void testClearRemoveAndRecycle_withUnTrackedRequest_doesNothingAndReturnsFalse() {
Request request = mock(Request.class);
assertThat(tracker.clearRemoveAndRecycle(request)).isFalse();
verify(request, never()).clear();
verify(request, never()).recycle();
}
@Test
public void testClearRemoveAndRecycle_withTrackedRequest_clearsRecyclesAndReturnsTrue() {
Request request = mock(Request.class);
tracker.addRequest(request);
assertThat(tracker.clearRemoveAndRecycle(request)).isTrue();
verify(request).clear();
verify(request).recycle();
}
@Test
public void testClearRemoveAndRecycle_withAlreadyRemovedRequest_doesNothingAndReturnsFalse() {
Request request = mock(Request.class);
tracker.addRequest(request);
tracker.clearRemoveAndRecycle(request);
assertThat(tracker.clearRemoveAndRecycle(request)).isFalse();
verify(request, times(1)).clear();
verify(request, times(1)).recycle();
}
@Test
public void testCanAddAndRemoveRequest() {
Request request = mock(Request.class);
tracker.addRequest(request);
tracker.clearRemoveAndRecycle(request);
tracker.clearRequests();
verify(request, times(1)).clear();
}
@Test
public void testCanAddMultipleRequests() {
Request first = mock(Request.class);
Request second = mock(Request.class);
tracker.addRequest(first);
tracker.addRequest(second);
tracker.clearRequests();
verify(first).clear();
verify(second).clear();
}
@Test
public void testPausesInProgressRequestsWhenPaused() {
Request request = mock(Request.class);
when(request.isRunning()).thenReturn(true);
tracker.addRequest(request);
tracker.pauseRequests();
verify(request).pause();
}
@Test
public void testDoesNotClearCompleteRequestsWhenPaused() {
Request request = mock(Request.class);
tracker.addRequest(request);
when(request.isComplete()).thenReturn(true);
tracker.pauseRequests();
verify(request, never()).clear();
}
@Test
public void testStartsRequestOnRun() {
Request request = mock(Request.class);
tracker.runRequest(request);
verify(request).begin();
}
@Test
public void testDoesNotStartRequestOnRunIfPaused() {
Request request = mock(Request.class);
tracker.pauseRequests();
tracker.runRequest(request);
verify(request, never()).begin();
}
@Test
public void testStartsRequestAddedWhenPausedWhenResumed() {
Request request = mock(Request.class);
tracker.pauseRequests();
tracker.runRequest(request);
tracker.resumeRequests();
verify(request).begin();
}
@Test
public void testDoesNotClearFailedRequestsWhenPaused() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(true);
tracker.addRequest(request);
tracker.pauseRequests();
verify(request, never()).clear();
}
@Test
public void testRestartsStoppedRequestWhenResumed() {
Request request = mock(Request.class);
tracker.addRequest(request);
tracker.resumeRequests();
verify(request).begin();
}
@Test
public void testDoesNotRestartCompletedRequestsWhenResumed() {
Request request = mock(Request.class);
when(request.isComplete()).thenReturn(true);
tracker.addRequest(request);
tracker.resumeRequests();
verify(request, never()).begin();
}
@Test
public void testDoesRestartFailedRequestsWhenResumed() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(true);
tracker.addRequest(request);
tracker.resumeRequests();
verify(request).begin();
}
@Test
public void testDoesNotStartStartedRequestsWhenResumed() {
Request request = mock(Request.class);
when(request.isRunning()).thenReturn(true);
tracker.addRequest(request);
tracker.resumeRequests();
verify(request, never()).begin();
}
@Test
public void testAvoidsConcurrentModificationWhenResuming() {
Request first = mock(Request.class);
Request second = mock(Request.class);
doAnswer(new ClearAndRemoveRequest(second)).when(first).begin();
tracker.addRequest(mock(Request.class));
tracker.addRequest(first);
tracker.addRequest(second);
tracker.resumeRequests();
}
@Test
public void testAvoidsConcurrentModificationWhenPausing() {
Request first = mock(Request.class);
Request second = mock(Request.class);
when(first.isRunning()).thenReturn(true);
doAnswer(new ClearAndRemoveRequest(second)).when(first).pause();
tracker.addRequest(mock(Request.class));
tracker.addRequest(first);
tracker.addRequest(second);
tracker.pauseRequests();
}
@Test
public void testAvoidsConcurrentModificationWhenClearing() {
Request first = mock(Request.class);
Request second = mock(Request.class);
doAnswer(new ClearAndRemoveRequest(second)).when(first).clear();
tracker.addRequest(mock(Request.class));
tracker.addRequest(first);
tracker.addRequest(second);
tracker.clearRequests();
}
@Test
public void testAvoidsConcurrentModificationWhenRestarting() {
Request first = mock(Request.class);
Request second = mock(Request.class);
doAnswer(new ClearAndRemoveRequest(second)).when(first).pause();
tracker.addRequest(mock(Request.class));
tracker.addRequest(first);
tracker.addRequest(second);
tracker.restartRequests();
}
@Test
public void testRestartsFailedRequestRestart() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(true);
tracker.addRequest(request);
tracker.restartRequests();
verify(request).begin();
}
@Test
public void testPausesAndRestartsNotYetFinishedRequestsOnRestart() {
Request request = mock(Request.class);
when(request.isComplete()).thenReturn(false);
tracker.addRequest(request);
tracker.restartRequests();
verify(request).pause();
verify(request).begin();
}
@Test
public void testDoesNotBeginFailedRequestOnRestartIfPaused() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(true);
tracker.pauseRequests();
tracker.addRequest(request);
tracker.restartRequests();
verify(request, never()).begin();
}
@Test
public void testPausesFailedRequestOnRestartIfPaused() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(true);
tracker.pauseRequests();
tracker.addRequest(request);
tracker.restartRequests();
verify(request).pause();
}
@Test
public void testDoesNotBeginIncompleteRequestsOnRestartIfPaused() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(false);
when(request.isComplete()).thenReturn(false);
tracker.pauseRequests();
tracker.addRequest(request);
tracker.restartRequests();
verify(request, never()).begin();
}
@Test
public void testPausesIncompleteRequestsOnRestartIfPaused() {
Request request = mock(Request.class);
when(request.isFailed()).thenReturn(false);
when(request.isComplete()).thenReturn(false);
tracker.pauseRequests();
tracker.addRequest(request);
tracker.restartRequests();
verify(request).pause();
}
@Test
public void testReturnsTrueFromIsPausedWhenPaused() {
tracker.pauseRequests();
assertTrue(tracker.isPaused());
}
@Test
public void testReturnsFalseFromIsPausedWhenResumed() {
tracker.resumeRequests();
assertFalse(tracker.isPaused());
}
private class ClearAndRemoveRequest implements Answer<Void> {
private Request toRemove;
public ClearAndRemoveRequest(Request toRemove) {
this.toRemove = toRemove;
}
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
tracker.clearRemoveAndRecycle(toRemove);
return null;
}
}
}