package com.bumptech.glide.manager;
import static com.bumptech.glide.tests.BackgroundUtil.testInBackground;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.tests.BackgroundUtil;
import com.bumptech.glide.tests.GlideShadowLooper;
import com.bumptech.glide.tests.Util;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 18, shadows = GlideShadowLooper.class)
public class RequestManagerRetrieverTest {
private static final String PARENT_TAG = "parent";
private RetrieverHarness[] harnesses;
private RequestManagerRetriever retriever;
private int initialSdkVersion;
@Before
public void setUp() {
retriever = new RequestManagerRetriever(null /*factory*/);
harnesses =
new RetrieverHarness[] { new DefaultRetrieverHarness(), new SupportRetrieverHarness() };
initialSdkVersion = Build.VERSION.SDK_INT;
Util.setSdkVersionInt(18);
}
@After
public void tearDown() {
Util.setSdkVersionInt(initialSdkVersion);
Shadows.shadowOf(Looper.getMainLooper()).runToEndOfTasks();
assertThat(retriever.pendingRequestManagerFragments).isEmpty();
assertThat(retriever.pendingSupportRequestManagerFragments).isEmpty();
}
@Test
public void testCreatesNewFragmentIfNoneExists() {
for (RetrieverHarness harness : harnesses) {
harness.doGet();
Shadows.shadowOf(Looper.getMainLooper()).runToEndOfTasks();
assertTrue(harness.hasFragmentWithTag(RequestManagerRetriever.FRAGMENT_TAG));
}
}
@Test
public void testReturnsNewManagerIfNoneExists() {
for (RetrieverHarness harness : harnesses) {
assertNotNull(harness.doGet());
}
}
@Test
public void testReturnsExistingRequestManagerIfExists() {
for (RetrieverHarness harness : harnesses) {
RequestManager requestManager = mock(RequestManager.class);
harness.addFragmentWithTag(RequestManagerRetriever.FRAGMENT_TAG, requestManager);
assertEquals(requestManager, harness.doGet());
}
}
@Test
public void testReturnsNewRequestManagerIfFragmentExistsButHasNoRequestManager() {
for (RetrieverHarness harness : harnesses) {
harness.addFragmentWithTag(RequestManagerRetriever.FRAGMENT_TAG, null);
assertNotNull(harness.doGet());
}
}
@Test
public void testSavesNewRequestManagerToFragmentIfCreatesRequestManagerForExistingFragment() {
for (RetrieverHarness harness : harnesses) {
harness.addFragmentWithTag(RequestManagerRetriever.FRAGMENT_TAG, null);
RequestManager first = harness.doGet();
RequestManager second = harness.doGet();
assertEquals(first, second);
}
}
@Test
public void testHasValidTag() {
assertEquals(RequestManagerRetriever.class.getPackage().getName(),
RequestManagerRetriever.FRAGMENT_TAG);
}
@Test
public void testCanGetRequestManagerFromActivity() {
Activity activity = Robolectric.buildActivity(Activity.class).create().start().get();
RequestManager manager = retriever.get(activity);
assertEquals(manager, retriever.get(activity));
}
@Test
public void testSupportCanGetRequestManagerFromActivity() {
FragmentActivity fragmentActivity =
Robolectric.buildActivity(FragmentActivity.class).create().start().get();
RequestManager manager = retriever.get(fragmentActivity);
assertEquals(manager, retriever.get(fragmentActivity));
}
@Test
public void testCanGetRequestManagerFromFragment() {
Activity activity = Robolectric.buildActivity(Activity.class).create().start().resume().get();
android.app.Fragment fragment = new android.app.Fragment();
activity.getFragmentManager().beginTransaction().add(fragment, PARENT_TAG).commit();
activity.getFragmentManager().executePendingTransactions();
RequestManager manager = retriever.get(fragment);
assertEquals(manager, retriever.get(fragment));
}
@Test
public void testSupportCanGetRequestManagerFromFragment() {
FragmentActivity activity =
Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get();
Fragment fragment = new Fragment();
activity.getSupportFragmentManager().beginTransaction().add(fragment, PARENT_TAG).commit();
activity.getSupportFragmentManager().executePendingTransactions();
RequestManager manager = retriever.get(fragment);
assertEquals(manager, retriever.get(fragment));
}
@Test
public void testCanGetRequestManagerFromDetachedFragment() {
helpTestCanGetRequestManagerFromDetachedFragment();
}
@Test
public void testCanGetRequestManagerFromDetachedFragment_PreJellyBeanMr1() {
Util.setSdkVersionInt(Build.VERSION_CODES.JELLY_BEAN);
helpTestCanGetRequestManagerFromDetachedFragment();
}
private void helpTestCanGetRequestManagerFromDetachedFragment() {
Activity activity = Robolectric.buildActivity(Activity.class).create().start().resume().get();
android.app.Fragment fragment = new android.app.Fragment();
activity.getFragmentManager().beginTransaction().add(fragment, PARENT_TAG).detach(fragment)
.commit();
activity.getFragmentManager().executePendingTransactions();
assertTrue(fragment.isDetached());
retriever.get(fragment);
}
@Test
public void testSupportCanGetRequestManagerFromDetachedFragment() {
helpTestSupportCanGetRequestManagerFromDetachedFragment();
}
@Test
public void testSupportCanGetRequestManagerFromDetachedFragment_PreJellyBeanMr1() {
Util.setSdkVersionInt(Build.VERSION_CODES.JELLY_BEAN);
helpTestSupportCanGetRequestManagerFromDetachedFragment();
}
private void helpTestSupportCanGetRequestManagerFromDetachedFragment() {
FragmentActivity activity =
Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get();
Fragment fragment = new Fragment();
activity.getSupportFragmentManager().beginTransaction().add(fragment, PARENT_TAG)
.detach(fragment).commit();
activity.getSupportFragmentManager().executePendingTransactions();
assertTrue(fragment.isDetached());
retriever.get(fragment);
}
@Test(expected = IllegalArgumentException.class)
public void testThrowsIfFragmentNotAttached() {
android.app.Fragment fragment = new android.app.Fragment();
retriever.get(fragment);
}
@Test(expected = NullPointerException.class)
public void testThrowsIfSupportFragmentNotAttached() {
Fragment fragment = new Fragment();
retriever.get(fragment);
}
@Test(expected = IllegalArgumentException.class)
public void testThrowsIfActivityDestroyed() {
RetrieverHarness harness = new DefaultRetrieverHarness();
harness.getController().pause().stop().destroy();
harness.doGet();
}
@Test(expected = IllegalArgumentException.class)
public void testThrowsIfFragmentActivityDestroyed() {
RetrieverHarness harness = new SupportRetrieverHarness();
harness.getController().pause().stop().destroy();
harness.doGet();
}
@Test(expected = IllegalArgumentException.class)
public void testThrowsIfGivenNullContext() {
retriever.get((Context) null);
}
@Test
public void testChecksIfContextIsFragmentActivity() {
RetrieverHarness harness = new SupportRetrieverHarness();
RequestManager requestManager = harness.doGet();
assertEquals(requestManager, retriever.get((Context) harness.getController().get()));
}
@Test
public void testChecksIfContextIsActivity() {
RetrieverHarness harness = new DefaultRetrieverHarness();
RequestManager requestManager = harness.doGet();
assertEquals(requestManager, retriever.get((Context) harness.getController().get()));
}
@Test
public void testHandlesContextWrappersForActivities() {
RetrieverHarness harness = new DefaultRetrieverHarness();
RequestManager requestManager = harness.doGet();
ContextWrapper contextWrapper = new ContextWrapper(harness.getController().get());
assertEquals(requestManager, retriever.get(contextWrapper));
}
@Test
public void testHandlesContextWrappersForApplication() {
ContextWrapper contextWrapper = new ContextWrapper(RuntimeEnvironment.application);
RequestManager requestManager = retriever.get(RuntimeEnvironment.application);
assertEquals(requestManager, retriever.get(contextWrapper));
}
@Test
public void testReturnsNonNullManagerIfGivenApplicationContext() {
assertNotNull(retriever.get(RuntimeEnvironment.application));
}
@Test
public void testApplicationRequestManagerIsNotPausedWhenRetrieved() {
RequestManager manager = retriever.get(RuntimeEnvironment.application);
assertFalse(manager.isPaused());
}
@Test
public void testApplicationRequestManagerIsNotReResumedAfterFirstRetrieval() {
RequestManager manager = retriever.get(RuntimeEnvironment.application);
manager.pauseRequests();
manager = retriever.get(RuntimeEnvironment.application);
assertTrue(manager.isPaused());
}
@Test
public void testDoesNotThrowWhenGetWithContextCalledFromBackgroundThread()
throws InterruptedException {
testInBackground(new BackgroundUtil.BackgroundTester() {
@Override
public void runTest() throws Exception {
retriever.get(RuntimeEnvironment.application);
}
});
}
// See Issue #117: https://github.com/bumptech/glide/issues/117.
@Test
public void testCanCallGetInOnAttachToWindowInFragmentInViewPager() {
// Robolectric by default runs messages posted to the main looper synchronously, the
// framework does not. We post
// to the main thread here to work around an issue caused by a recursive method call so we
// need (and reasonably
// expect) our message to not run immediately
Shadows.shadowOf(Looper.getMainLooper()).pause();
Robolectric.buildActivity(Issue117Activity.class).create().start().resume().visible();
}
@Test
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public void testDoesNotThrowIfAskedToGetManagerForActivityPreJellYBeanMr1() {
Util.setSdkVersionInt(Build.VERSION_CODES.JELLY_BEAN);
Activity activity = Robolectric.buildActivity(Activity.class).create().start().resume().get();
Activity spyActivity = Mockito.spy(activity);
when(spyActivity.isDestroyed()).thenThrow(new NoSuchMethodError());
assertNotNull(retriever.get(spyActivity));
}
@Test
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public void testDoesNotThrowIfAskedToGetManagerForFragmentPreJellyBeanMr1() {
Util.setSdkVersionInt(Build.VERSION_CODES.JELLY_BEAN);
Activity activity = Robolectric.buildActivity(Activity.class).create().start().resume().get();
android.app.Fragment fragment = new android.app.Fragment();
activity.getFragmentManager().beginTransaction().add(fragment, "test").commit();
android.app.Fragment spyFragment = Mockito.spy(fragment);
when(spyFragment.getChildFragmentManager()).thenThrow(new NoSuchMethodError());
assertNotNull(retriever.get(spyFragment));
}
private interface RetrieverHarness {
ActivityController<?> getController();
RequestManager doGet();
boolean hasFragmentWithTag(String tag);
void addFragmentWithTag(String tag, RequestManager manager);
}
public class DefaultRetrieverHarness implements RetrieverHarness {
private final ActivityController<Activity> controller =
Robolectric.buildActivity(Activity.class);
private final android.app.Fragment parent;
public DefaultRetrieverHarness() {
this.parent = new android.app.Fragment();
controller.create();
controller.get().getFragmentManager().beginTransaction().add(parent, PARENT_TAG)
.commitAllowingStateLoss();
controller.get().getFragmentManager().executePendingTransactions();
controller.start().resume();
}
@Override
public ActivityController<?> getController() {
return controller;
}
@Override
public RequestManager doGet() {
return retriever.get(controller.get());
}
@Override
public boolean hasFragmentWithTag(String tag) {
return null != controller
.get()
.getFragmentManager()
.findFragmentByTag(RequestManagerRetriever.FRAGMENT_TAG);
}
@Override
public void addFragmentWithTag(String tag, RequestManager requestManager) {
RequestManagerFragment fragment = new RequestManagerFragment();
fragment.setRequestManager(requestManager);
controller.get().getFragmentManager().beginTransaction()
.add(fragment, RequestManagerRetriever.FRAGMENT_TAG).commitAllowingStateLoss();
controller.get().getFragmentManager().executePendingTransactions();
}
}
public class SupportRetrieverHarness implements RetrieverHarness {
private final ActivityController<FragmentActivity> controller =
Robolectric.buildActivity(FragmentActivity.class);
private final Fragment parent;
public SupportRetrieverHarness() {
this.parent = new Fragment();
controller.create();
controller.get().getSupportFragmentManager().beginTransaction().add(parent, PARENT_TAG)
.commitAllowingStateLoss();
controller.get().getSupportFragmentManager().executePendingTransactions();
controller.start().resume();
}
@Override
public ActivityController<?> getController() {
return controller;
}
@Override
public RequestManager doGet() {
return retriever.get(controller.get());
}
@Override
public boolean hasFragmentWithTag(String tag) {
return controller.get().getSupportFragmentManager()
.findFragmentByTag(RequestManagerRetriever.FRAGMENT_TAG) != null;
}
@Override
public void addFragmentWithTag(String tag, RequestManager manager) {
SupportRequestManagerFragment fragment = new SupportRequestManagerFragment();
fragment.setRequestManager(manager);
controller.get().getSupportFragmentManager().beginTransaction()
.add(fragment, RequestManagerRetriever.FRAGMENT_TAG).commitAllowingStateLoss();
controller.get().getSupportFragmentManager().executePendingTransactions();
}
}
}