diff options
author | Sam Judd <judds@google.com> | 2014-11-02 13:35:43 -0800 |
---|---|---|
committer | Sam Judd <judds@google.com> | 2014-11-02 17:48:13 -0800 |
commit | f4d511ebf70c55d9224b57e6ff390373c0e2b12e (patch) | |
tree | 0f6043ca791cfb306ab166079c9733310d399732 /library | |
parent | dfd29c7799559aa6215d36189e7ba1870256849b (diff) | |
download | glide-f4d511ebf70c55d9224b57e6ff390373c0e2b12e.tar.gz |
Fix some holes exposed by coverage report.
Diffstat (limited to 'library')
23 files changed, 972 insertions, 130 deletions
diff --git a/library/build.gradle b/library/build.gradle index 03213f28..35205660 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -22,6 +22,7 @@ dependencies { compile project(':third_party:disklrucache') compile "com.android.support:support-v4:${SUPPORT_V4_VERSION}" + androidTestCompile 'com.google.guava:guava-testlib:18.0' androidTestCompile "com.android.support:support-v4:${SUPPORT_V4_VERSION}" androidTestCompile "org.hamcrest:hamcrest-core:${HAMCREST_VERSION}" androidTestCompile "org.hamcrest:hamcrest-library:${HAMCREST_VERSION}" @@ -104,16 +105,17 @@ afterEvaluate { task jacocoTestReport(type:JacocoReport, dependsOn: testDebug) { def coverageSourceDirs = ['src/main/java'] group = "Reporting" - description = "Generate Jacoco coverage reports" classDirectories = fileTree( dir: 'build/intermediates/classes/debug', excludes: ['**/R.class', '**/R$*.class', - '**/*$ViewInjector*.*', '**/BuildConfig.*', - '**/Manifest*.*'] + '**/Manifest*.*', + '**/BitmapRequestBuilder.class', + '**/DrawableRequestBuilder.class', + '**/GifRequestBuilder.class', ] ) additionalSourceDirs = files(coverageSourceDirs) diff --git a/library/src/androidTest/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcherTest.java b/library/src/androidTest/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcherTest.java new file mode 100644 index 00000000..db8290b6 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcherTest.java @@ -0,0 +1,70 @@ +package com.bumptech.glide.load.data; + +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.os.ParcelFileDescriptor; +import com.bumptech.glide.Priority; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class FileDescriptorAssetPathFetcherTest { + private FileDescriptorAssetPathFetcher fetcher; + private ParcelFileDescriptor expected; + private String assetPath; + + @Before + public void setUp() throws IOException { + AssetManager assetManager = mock(AssetManager.class); + assetPath = "/some/asset/path"; + fetcher = new FileDescriptorAssetPathFetcher(assetManager, assetPath); + expected = mock(ParcelFileDescriptor.class); + AssetFileDescriptor assetFileDescriptor = mock(AssetFileDescriptor.class); + when(assetFileDescriptor.getParcelFileDescriptor()).thenReturn(expected); + when(assetManager.openFd(eq(assetPath))).thenReturn(assetFileDescriptor); + } + + @Test + public void testOpensInputStreamForPathWithAssetManager() throws Exception { + assertEquals(expected, fetcher.loadData(Priority.NORMAL)); + } + + @Test + public void testClosesOpenedInputStreamOnCleanup() throws Exception { + fetcher.loadData(Priority.NORMAL); + fetcher.cleanup(); + + verify(expected).close(); + } + + @Test + public void testReturnsAssetPathAsId() { + assertEquals(assetPath, fetcher.getId()); + } + + @Test + public void testDoesNothingOnCleanupIfNoDataLoaded() throws IOException { + fetcher.cleanup(); + verify(expected, never()).close(); + } + + @Test + public void testDoesNothingOnCancel() throws Exception { + fetcher.loadData(Priority.NORMAL); + fetcher.cancel(); + verify(expected, never()).close(); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/data/StreamAssetPathFetcherTest.java b/library/src/androidTest/java/com/bumptech/glide/load/data/StreamAssetPathFetcherTest.java new file mode 100644 index 00000000..a6cb153c --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/data/StreamAssetPathFetcherTest.java @@ -0,0 +1,67 @@ +package com.bumptech.glide.load.data; + +import android.content.res.AssetManager; +import com.bumptech.glide.Priority; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class StreamAssetPathFetcherTest { + private StreamAssetPathFetcher fetcher; + private InputStream expected; + private String assetPath; + + @Before + public void setUp() throws IOException { + AssetManager assetManager = mock(AssetManager.class); + assetPath = "/some/asset/path"; + fetcher = new StreamAssetPathFetcher(assetManager, assetPath); + expected = mock(InputStream.class); + when(assetManager.open(eq(assetPath))).thenReturn(expected); + } + + @Test + public void testOpensInputStreamForPathWithAssetManager() throws Exception { + assertEquals(expected, fetcher.loadData(Priority.NORMAL)); + } + + @Test + public void testClosesOpenedInputStreamOnCleanup() throws Exception { + fetcher.loadData(Priority.NORMAL); + fetcher.cleanup(); + + verify(expected).close(); + } + + @Test + public void testReturnsAssetPathAsId() { + assertEquals(assetPath, fetcher.getId()); + } + + @Test + public void testDoesNothingOnCleanupIfNoDataLoaded() throws IOException { + fetcher.cleanup(); + verify(expected, never()).close(); + } + + @Test + public void testDoesNothingOnCancel() throws Exception { + fetcher.loadData(Priority.NORMAL); + fetcher.cancel(); + verify(expected, never()).close(); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/EngineTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/EngineTest.java index 4d297c1f..1bef918a 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/engine/EngineTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/EngineTest.java @@ -397,6 +397,18 @@ public class EngineTest { verify(harness.engineJobFactory).build(eq(harness.cacheKey), eq(harness.isMemoryCacheable)); } + @Test + public void testReleaseReleasesEngineResource() { + EngineResource<Object> engineResource = mock(EngineResource.class); + harness.engine.release(engineResource); + verify(engineResource).release(); + } + + @Test(expected = IllegalArgumentException.class) + public void testThrowsIfAskedToReleaseNonEngineResource() { + harness.engine.release(mock(Resource.class)); + } + @Test(expected = RuntimeException.class) public void testThrowsIfLoadCalledOnBackgroundThread() throws InterruptedException { BackgroundUtil.testInBackground(new BackgroundUtil.BackgroundTester() { diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategyKeyTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategyKeyTest.java new file mode 100644 index 00000000..7d0c3af3 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategyKeyTest.java @@ -0,0 +1,75 @@ +package com.bumptech.glide.load.engine.bitmap_recycle; + +import android.graphics.Bitmap; +import com.bumptech.glide.load.engine.bitmap_recycle.AttributeStrategy.Key; +import com.google.common.testing.EqualsTester; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class AttributeStrategyKeyTest { + + private AttributeStrategy.KeyPool keyPool; + + @Before + public void setUp() { + keyPool = mock(AttributeStrategy.KeyPool.class); + } + + @Test + public void testEquality() { + Key first = new Key(keyPool); + first.init(100, 100, Bitmap.Config.ARGB_4444); + Key second = new Key(keyPool); + second.init(100, 100, Bitmap.Config.ARGB_4444); + + Key third = new Key(keyPool); + third.init(200, 100, Bitmap.Config.ARGB_4444); + + Key fourth = new Key(keyPool); + fourth.init(100, 200, Bitmap.Config.ARGB_4444); + + Key fifth = new Key(keyPool); + fifth.init(100, 100, Bitmap.Config.RGB_565); + + new EqualsTester() + .addEqualityGroup(first, second) + .addEqualityGroup(third) + .addEqualityGroup(fourth) + .addEqualityGroup(fifth) + .testEquals(); + } + + @Test + public void testReturnsSelfToPoolOnOffer() { + Key key = new Key(keyPool); + key.offer(); + + verify(keyPool).offer(eq(key)); + } + + @Test + public void testInitSetsAttributes() { + Key key = new Key(keyPool); + key.init(100, 100, Bitmap.Config.ARGB_4444); + + Key other = new Key(keyPool); + other.init(200, 200, Bitmap.Config.RGB_565); + + assertNotEquals(key, other); + + key.init(200, 200, Bitmap.Config.RGB_565); + + assertEquals(key, other); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategyKeyTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategyKeyTest.java new file mode 100644 index 00000000..c035bfbe --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategyKeyTest.java @@ -0,0 +1,63 @@ +package com.bumptech.glide.load.engine.bitmap_recycle; + +import com.bumptech.glide.load.engine.bitmap_recycle.SizeStrategy.Key; +import com.google.common.testing.EqualsTester; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@RunWith(JUnit4.class) +public class SizeStrategyKeyTest { + + private SizeStrategy.KeyPool keyPool; + + @Before + public void setUp() { + keyPool = mock(SizeStrategy.KeyPool.class); + } + + @Test + public void testEquality() { + Key first = new Key(keyPool); + first.init(100); + Key second = new Key(keyPool); + second.init(100); + Key third = new Key(keyPool); + third.init(50); + + new EqualsTester() + .addEqualityGroup(first, second) + .addEqualityGroup(third) + .testEquals(); + } + + @Test + public void testReturnsSelfToPoolOnOffer() { + Key key = new Key(keyPool); + key.offer(); + + verify(keyPool).offer(eq(key)); + } + + @Test + public void testInitSetsSize() { + Key key = new Key(keyPool); + key.init(100); + + Key other = new Key(keyPool); + other.init(200); + + assertNotEquals(key, other); + + key.init(200); + + assertEquals(key, other); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutorTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutorTest.java index 4a03a6d9..0dbd5108 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutorTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutorTest.java @@ -1,5 +1,7 @@ package com.bumptech.glide.load.engine.executor; +import com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.LoadTask; +import com.google.common.testing.EqualsTester; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -14,6 +16,8 @@ import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE, emulateSdk = 18) @@ -69,6 +73,48 @@ public class FifoPriorityThreadPoolExecutorTest { assertThat(executedOrder, contains(executionOrder)); } + @Test + public void testLoadTaskEquality() { + new EqualsTester() + .addEqualityGroup( + new LoadTask<Object>(new MockRunnable(10), new Object(), 1), + new LoadTask<Object>(new MockRunnable(10), new Object(), 1)) + .addEqualityGroup( + new LoadTask<Object>(new MockRunnable(5), new Object(), 1) + ) + .addEqualityGroup( + new LoadTask<Object>(new MockRunnable(10), new Object(), 3) + ) + .testEquals(); + } + + @Test + public void testLoadTaskCompareToPrefersHigherPriority() { + LoadTask<Object> first = new LoadTask<Object>(new MockRunnable(10), new Object(), 10); + LoadTask<Object> second = new LoadTask<Object>(new MockRunnable(0), new Object(), 10); + + assertTrue(first.compareTo(second) > 0); + assertTrue(second.compareTo(first) < 0); + } + + @Test + public void testLoadTaskCompareToFallsBackToOrderIfPriorityIsEqual() { + LoadTask<Object> first = new LoadTask<Object>(new MockRunnable(0), new Object(), 2); + LoadTask<Object> second = new LoadTask<Object>(new MockRunnable(0), new Object(), 1); + + assertTrue(first.compareTo(second) > 0); + assertTrue(second.compareTo(first) < 0); + } + + @Test + public void testLoadTaskCompareToReturnsZeroIfPriorityAndOrderAreEqual() { + LoadTask<Object> first = new LoadTask<Object>(new MockRunnable(0), new Object(), 1); + LoadTask<Object> second = new LoadTask<Object>(new MockRunnable(0), new Object(), 1); + + assertEquals(0, first.compareTo(second)); + assertEquals(0, second.compareTo(first)); + } + private static class MockRunnable implements Runnable, Prioritized { private final int priority; private final OnRun onRun; @@ -77,6 +123,10 @@ public class FifoPriorityThreadPoolExecutorTest { public void onRun(int priority); } + public MockRunnable(int priority) { + this(priority, mock(OnRun.class)); + } + public MockRunnable(int priority, OnRun onRun) { this.priority = priority; this.onRun = onRun; diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillerAllocationTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillerTest.java index 80bd8a61..8cbc0ab2 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillerAllocationTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/BitmapPreFillerTest.java @@ -9,6 +9,7 @@ import org.hamcrest.core.CombinableMatcher; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @@ -21,12 +22,16 @@ import static org.hamcrest.Matchers.either; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE, emulateSdk = 18) -public class BitmapPreFillerAllocationTest { +public class BitmapPreFillerTest { private static final int DEFAULT_BITMAP_WIDTH = 100; private static final int DEFAULT_BITMAP_HEIGHT = 50; private static final Bitmap.Config DEFAULT_BITMAP_CONFIG = PreFillType.DEFAULT_CONFIG; @@ -279,4 +284,27 @@ public class BitmapPreFillerAllocationTest { either(contains(smallWidth, smallHeight, smallWidth, smallHeight)); assertThat(attributes, either.or(contains(smallHeight, smallWidth, smallHeight, smallWidth))); } + + @Test + public void testSetsConfigOnBuildersToDefaultIfNotSet() { + PreFillType.Builder builder = mock(PreFillType.Builder.class); + when(builder.build()).thenReturn(new PreFillType.Builder(100).setConfig(Bitmap.Config.RGB_565).build()); + + bitmapPreFiller.preFill(builder); + + InOrder order = inOrder(builder); + order.verify(builder).setConfig(Bitmap.Config.RGB_565); + order.verify(builder).build(); + } + + @Test + public void testDoesNotSetConfigOnBuildersIfConfigIsAlreadySet() { + PreFillType.Builder builder = mock(PreFillType.Builder.class); + + when(builder.getConfig()).thenReturn(Bitmap.Config.ARGB_4444); + when(builder.build()).thenReturn(new PreFillType.Builder(100).setConfig(Bitmap.Config.ARGB_4444).build()); + bitmapPreFiller.preFill(builder); + + verify(builder, never()).setConfig(any(Bitmap.Config.class)); + } }
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillTypeTest.java b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillTypeTest.java new file mode 100644 index 00000000..1505a9d4 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/engine/prefill/PreFillTypeTest.java @@ -0,0 +1,85 @@ +package com.bumptech.glide.load.engine.prefill; + +import android.graphics.Bitmap; +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertEquals; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class PreFillTypeTest { + + @Test(expected = IllegalArgumentException.class) + public void testThrowsIfSizeIsZero() { + new PreFillType.Builder(0); + } + + @Test(expected = IllegalArgumentException.class) + public void testThrowsIfWidthIsZero() { + new PreFillType.Builder(0, 100); + } + + @Test(expected = IllegalArgumentException.class) + public void testThrowsIfHeightIsZero() { + new PreFillType.Builder(100, 0); + } + + @Test(expected = IllegalArgumentException.class) + public void testThrowsIfWeightIsZero() { + new PreFillType.Builder(100).setWeight(0); + } + + @Test(expected = NullPointerException.class) + public void testConstructorThrowsIfConfigIsNull() { + new PreFillType(100, 100, null, 1); + } + + @Test + public void testGetWidthReturnsGivenWidth() { + int width = 500; + assertEquals(width, new PreFillType(width, 100, Bitmap.Config.ARGB_4444, 1).getWidth()); + } + + @Test + public void testGetHeightReturnsGivenHeight() { + int height = 123; + assertEquals(height, new PreFillType(100, height, Bitmap.Config.ARGB_4444, 1).getHeight()); + } + + @Test + public void testGetConfigReturnsGivenConfig() { + Bitmap.Config config = Bitmap.Config.ARGB_8888; + assertEquals(config, new PreFillType(100, 100, config, 1).getConfig()); + } + + @Test + public void testGetWeightReturnsGivenWeight() { + int weight = 400; + assertEquals(weight, new PreFillType(100, 100, Bitmap.Config.ARGB_4444, weight).getWeight()); + } + + @Test + public void testEquality() { + new EqualsTester() + .addEqualityGroup( + new PreFillType(100, 100, Bitmap.Config.ARGB_4444, 1), + new PreFillType(100, 100, Bitmap.Config.ARGB_4444, 1)) + .addEqualityGroup( + new PreFillType(200, 100, Bitmap.Config.ARGB_4444, 1) + ) + .addEqualityGroup( + new PreFillType(100, 200, Bitmap.Config.ARGB_4444, 1) + ) + .addEqualityGroup( + new PreFillType(100, 100, Bitmap.Config.ARGB_8888, 1) + ) + .addEqualityGroup( + new PreFillType(100, 100, Bitmap.Config.ARGB_4444, 2) + ) + .testEquals(); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/model/ModelCacheTest.java b/library/src/androidTest/java/com/bumptech/glide/load/model/ModelCacheTest.java new file mode 100644 index 00000000..c62fe920 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/model/ModelCacheTest.java @@ -0,0 +1,55 @@ +package com.bumptech.glide.load.model; + +import com.google.common.testing.EqualsTester; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.junit.Assert.assertEquals; + +@RunWith(JUnit4.class) +public class ModelCacheTest { + + private ModelCache<Object, Object> cache; + + @Before + public void setUp() { + cache = new ModelCache<Object, Object>(10); + } + + @Test + public void testModelKeyEquivalence() { + new EqualsTester() + .addEqualityGroup(ModelCache.ModelKey.get(14f, 100, 200), ModelCache.ModelKey.get(14f, 100, 200)) + .addEqualityGroup(ModelCache.ModelKey.get(13f, 100, 200)) + .addEqualityGroup(ModelCache.ModelKey.get(14f, 200, 200)) + .addEqualityGroup(ModelCache.ModelKey.get(14f, 100, 300)) + .testEquals(); + } + + @Test + public void testCanSetAndGetModel() { + Object model = new Object(); + int width = 10; + int height = 20; + Object result = new Object(); + cache.put(model, width, height, result); + assertEquals(result, cache.get(model, width, height)); + } + + @Test + public void testCanSetAndGetMultipleResultsWithDifferentDimensionsForSameObject() { + Object model = new Object(); + int firstWidth = 10, firstHeight = 20; + Object firstResult = new Object(); + int secondWidth = 30, secondHeight = 40; + Object secondResult = new Object(); + + cache.put(model, firstWidth, firstHeight, firstResult); + cache.put(model, secondWidth, secondHeight, secondResult); + + assertEquals(firstResult, cache.get(model, firstWidth, firstHeight)); + assertEquals(secondResult, cache.get(model, secondWidth, secondHeight)); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/model/stream/BaseGlideUrlLoaderTest.java b/library/src/androidTest/java/com/bumptech/glide/load/model/stream/BaseGlideUrlLoaderTest.java new file mode 100644 index 00000000..e92ac8f5 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/model/stream/BaseGlideUrlLoaderTest.java @@ -0,0 +1,135 @@ +package com.bumptech.glide.load.model.stream; + +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.ModelCache; +import com.bumptech.glide.load.model.ModelLoader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.io.InputStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class BaseGlideUrlLoaderTest { + + private ModelCache<Object, GlideUrl> modelCache; + private ModelLoader<GlideUrl, InputStream> wrapped; + private TestLoader urlLoader; + + @SuppressWarnings("unchecked") + @Before + public void setUp() { + modelCache = mock(ModelCache.class); + wrapped = mock(ModelLoader.class); + urlLoader = new TestLoader(wrapped, modelCache); + } + + @Test + public void testReturnsNullIfUrlIsNull() { + urlLoader.resultUrl = null; + assertNull(urlLoader.getResourceFetcher(new Object(), 100, 100)); + } + + @Test + public void testReturnsNullIfUrlIsEmpty() { + urlLoader.resultUrl = " "; + assertNull(urlLoader.getResourceFetcher(new Object(), 100, 100)); + } + + @Test + public void testReturnsUrlFromCacheIfPresent() { + Object model = new Object(); + int width = 100; + int height = 200; + GlideUrl expectedUrl = mock(GlideUrl.class); + when(modelCache.get(eq(model), eq(width), eq(height))).thenReturn(expectedUrl); + DataFetcher<InputStream> expectedFetcher = mock(DataFetcher.class); + + when(wrapped.getResourceFetcher(eq(expectedUrl), eq(width), eq(height))).thenReturn(expectedFetcher); + + assertEquals(expectedFetcher, urlLoader.getResourceFetcher(model, width, height)); + } + + @Test + public void testBuildsNewUrlIfNotPresentInCache() { + int width = 10; + int height = 11; + + urlLoader.resultUrl = "fakeUrl"; + final DataFetcher<InputStream> expected = mock(DataFetcher.class); + when(wrapped.getResourceFetcher(any(GlideUrl.class), eq(width), eq(height))).thenAnswer( + new Answer<DataFetcher<InputStream>>() { + @Override + public DataFetcher<InputStream> answer(InvocationOnMock invocationOnMock) throws Throwable { + GlideUrl glideUrl = (GlideUrl) invocationOnMock.getArguments()[0]; + assertEquals(urlLoader.resultUrl, glideUrl.toString()); + return expected; + + } + }); + assertEquals(expected, urlLoader.getResourceFetcher(new Object(), width, height)); + } + + @Test + public void testAddsNewUrlToCacheIfNotPresentInCache() { + urlLoader.resultUrl = "fakeUrl"; + Object model = new Object(); + int width = 400; + int height = 500; + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocationOnMock) throws Throwable { + GlideUrl glideUrl = (GlideUrl) invocationOnMock.getArguments()[3]; + assertEquals(urlLoader.resultUrl, glideUrl.toString()); + return null; + } + }).when(modelCache).put(eq(model), eq(width), eq(height), any(GlideUrl.class)); + + urlLoader.getResourceFetcher(model, width, height); + + verify(modelCache).put(eq(model), eq(width), eq(height), any(GlideUrl.class)); + } + + @Test + public void testDoesNotInteractWithModelCacheIfNull() { + TestLoader urlLoader = new TestLoader(wrapped, null); + urlLoader.resultUrl = "fakeUrl"; + + int width = 456; + int height = 789; + + DataFetcher<InputStream> expected = mock(DataFetcher.class); + when(wrapped.getResourceFetcher(any(GlideUrl.class), eq(width), eq(height))).thenReturn(expected); + + assertEquals(expected, urlLoader.getResourceFetcher(new Object(), width, height)); + } + + private class TestLoader extends BaseGlideUrlLoader<Object> { + public String resultUrl; + + public TestLoader(ModelLoader<GlideUrl, InputStream> concreteLoader, ModelCache<Object, GlideUrl> modelCache) { + super(concreteLoader, modelCache); + } + + @Override + protected String getUrl(Object model, int width, int height) { + return resultUrl; + } + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/FileDescriptorBitmapDecoderTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/FileDescriptorBitmapDecoderTest.java new file mode 100644 index 00000000..c4668cb7 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/FileDescriptorBitmapDecoderTest.java @@ -0,0 +1,56 @@ +package com.bumptech.glide.load.resource.bitmap; + +import android.graphics.Bitmap; +import android.os.ParcelFileDescriptor; +import com.bumptech.glide.load.DecodeFormat; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class FileDescriptorBitmapDecoderTest { + + private FileDescriptorBitmapDecoder decoder; + private BitmapPool bitmapPool; + private VideoBitmapDecoder videoDecoder; + private DecodeFormat decodeFormat; + + @Before + public void setUp() { + bitmapPool = mock(BitmapPool.class); + videoDecoder = mock(VideoBitmapDecoder.class); + decodeFormat = DecodeFormat.DEFAULT; + decoder = new FileDescriptorBitmapDecoder(videoDecoder, bitmapPool, decodeFormat); + } + + @Test + public void testHasValidId() { + assertEquals("FileDescriptorBitmapDecoder.com.bumptech.glide.load.data.bitmap", decoder.getId()); + } + + @Test + public void testReturnsBitmapFromWrappedDecoderAsResource() throws IOException { + ParcelFileDescriptor source = mock(ParcelFileDescriptor.class); + int width = 100; + int height = 200; + Bitmap expected = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + when(videoDecoder.decode(eq(source), eq(bitmapPool), eq(width), eq(height), eq(decodeFormat))) + .thenReturn(expected); + + Resource<Bitmap> bitmapResource = decoder.decode(source, width, height); + + assertEquals(expected, bitmapResource.get()); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/util/TransformationUtilsTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java index b95c2870..57ec110f 100644 --- a/library/src/androidTest/java/com/bumptech/glide/util/TransformationUtilsTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java @@ -1,11 +1,13 @@ -package com.bumptech.glide.util; +package com.bumptech.glide.load.resource.bitmap; import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.media.ExifInterface; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; -import com.bumptech.glide.load.resource.bitmap.TransformationUtils; import org.hamcrest.core.CombinableMatcher; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; @@ -18,10 +20,12 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(RobolectricTestRunner.class) @@ -102,7 +106,7 @@ public class TransformationUtilsTest { // Test for Issue #195. @Test - public void testFitCenterUsesFloorInsteadofRoundingForOutputBitmapSize() { + public void testFitCenterUsesFloorInsteadOfRoundingForOutputBitmapSize() { Bitmap toTransform = Bitmap.createBitmap(1230, 1640, Bitmap.Config.RGB_565); Bitmap transformed = TransformationUtils.fitCenter(toTransform, mock(BitmapPool.class), 1075, 1366); @@ -112,6 +116,27 @@ public class TransformationUtilsTest { } @Test + public void testFitCenterReturnsGivenBitmapIfGivenBitmapMatchesExactly() { + Bitmap toFit = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444); + Bitmap transformed = TransformationUtils.fitCenter(toFit, null, toFit.getWidth(), toFit.getHeight()); + assertTrue(toFit == transformed); + } + + @Test + public void testFitCenterReturnsGivenBitmapIfGivenBitmapWidthMatchesExactly() { + Bitmap toFit = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444); + Bitmap transformed = TransformationUtils.fitCenter(toFit, null, toFit.getWidth(), toFit.getHeight() * 2); + assertTrue(toFit == transformed); + } + + @Test + public void testFitCenterReturnsGivenBitmapIfGivenBitmapHeightMatchesExactly() { + Bitmap toFit = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444); + Bitmap transformed = TransformationUtils.fitCenter(toFit, null, toFit.getWidth() * 2, toFit.getHeight()); + assertTrue(toFit == transformed); + } + + @Test public void testCenterCropSetsOutBitmapToHaveAlphaIfInBitmapHasAlphaAndOutBitmapIsReused() { Bitmap toTransform = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); @@ -247,6 +272,94 @@ public class TransformationUtilsTest { assertThat("one side must match maxSide", maxSide, eitherMatcher.or(equalTo(height))); } + @Test + public void testGetExifOrientationDegrees() { + assertEquals(0, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_NORMAL)); + assertEquals(90, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_TRANSPOSE)); + assertEquals(90, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_ROTATE_90)); + assertEquals(180, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_ROTATE_180)); + assertEquals(180, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_FLIP_VERTICAL)); + assertEquals(270, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_TRANSVERSE)); + assertEquals(270, TransformationUtils.getExifOrientationDegrees(ExifInterface.ORIENTATION_ROTATE_270)); + } + + @Test + public void testRotateImage() { + Bitmap toRotate = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888); + + Bitmap zero = TransformationUtils.rotateImage(toRotate, 0); + assertTrue(toRotate == zero); + + Bitmap ninety = TransformationUtils.rotateImage(toRotate, 90); + assertTrue(Robolectric.shadowOf(ninety).getDescription().contains("rotate=90.0")); + assertEquals(toRotate.getWidth(), toRotate.getHeight()); + } + + @Test + public void testRotateImageExifReturnsGivenBitmapIfRotationIsNormal() { + BitmapPool bitmapPool = mock(BitmapPool.class); + Bitmap toRotate = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444); + assertEquals(toRotate, + TransformationUtils.rotateImageExif(toRotate, bitmapPool, ExifInterface.ORIENTATION_NORMAL)); + } + + @Test + public void testRotateImageExifReturnsGivenBitmapIfRotationIsUndefined() { + BitmapPool bitmapPool = mock(BitmapPool.class); + Bitmap toRotate = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565); + assertEquals(toRotate, + TransformationUtils.rotateImageExif(toRotate, bitmapPool, ExifInterface.ORIENTATION_UNDEFINED)); + } + + @Test + public void testRotateImageExifHandlesEmptyBitmapPool() { + Bitmap toRotate = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_4444); + BitmapPool bitmapPool = mock(BitmapPool.class); + assertNotNull(TransformationUtils.rotateImageExif(toRotate, bitmapPool, ExifInterface.ORIENTATION_ROTATE_90)); + } + + @Test + public void testInitializeMatrixSetsScaleIfFlipHorizontal() { + Matrix matrix = mock(Matrix.class); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_FLIP_HORIZONTAL, matrix); + verify(matrix).setScale(-1, 1); + } + + @Test + public void testInitializeMatrixSetsScaleAndRotateIfFlipVertical() { + Matrix matrix = mock(Matrix.class); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_FLIP_VERTICAL, matrix); + verify(matrix).setRotate(180); + verify(matrix).postScale(-1, 1); + } + + @Test + public void testInitializeMatrixSetsScaleAndRotateIfTranspose() { + Matrix matrix = mock(Matrix.class); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_TRANSPOSE, matrix); + verify(matrix).setRotate(90); + verify(matrix).postScale(-1, 1); + } + + @Test + public void testInitializeMatrixSetsScaleAndRotateIfTransverse() { + Matrix matrix = mock(Matrix.class); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_TRANSVERSE, matrix); + verify(matrix).setRotate(-90); + verify(matrix).postScale(-1, 1); + } + + @Test + public void testInitializeMatrixSetsRotateOnRotation() { + Matrix matrix = mock(Matrix.class); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_ROTATE_90, matrix); + verify(matrix).setRotate(90); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_ROTATE_180, matrix); + verify(matrix).setRotate(180); + TransformationUtils.initializeMatrixForRotation(ExifInterface.ORIENTATION_ROTATE_270, matrix); + verify(matrix).setRotate(-90); + } + @Implements(Bitmap.class) public static class AlphaShadowBitmap extends ShadowBitmap { diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java index dbfccd2b..1a4c4c61 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java @@ -63,6 +63,7 @@ public class GifResourceEncoderTest { gifDrawable = mock(GifDrawable.class); when(gifDrawable.getFrameTransformation()).thenReturn(frameTransformation); + when(gifDrawable.getData()).thenReturn(new byte[0]); when(resource.get()).thenReturn(gifDrawable); diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/transcode/BitmapToGlideDrawableTranscoderTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/transcode/BitmapToGlideDrawableTranscoderTest.java new file mode 100644 index 00000000..afd60341 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/transcode/BitmapToGlideDrawableTranscoderTest.java @@ -0,0 +1,46 @@ +package com.bumptech.glide.load.resource.transcode; + +import android.graphics.Bitmap; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = Config.NONE, emulateSdk = 18) +public class BitmapToGlideDrawableTranscoderTest { + + private GlideBitmapDrawableTranscoder wrapped; + private BitmapToGlideDrawableTranscoder transcoder; + + @Before + public void setUp() { + wrapped = mock(GlideBitmapDrawableTranscoder.class); + transcoder = new BitmapToGlideDrawableTranscoder(wrapped); + } + + @Test + public void testReturnsWrappedId() { + final String expectedId = "fakeId"; + when(wrapped.getId()).thenReturn(expectedId); + assertEquals(expectedId, transcoder.getId()); + } + + @Test + public void testReturnsResourceFromWrapped() { + Resource<Bitmap> toTranscode = mock(Resource.class); + Resource<GlideBitmapDrawable> expected = mock(Resource.class); + + when(wrapped.transcode(eq(toTranscode))).thenReturn(expected); + + assertEquals(expected, transcoder.transcode(toTranscode)); + } +}
\ No newline at end of file diff --git a/library/src/androidTest/java/com/bumptech/glide/tests/GlideShadowLog.java b/library/src/androidTest/java/com/bumptech/glide/tests/GlideShadowLog.java new file mode 100644 index 00000000..50a3a3a0 --- /dev/null +++ b/library/src/androidTest/java/com/bumptech/glide/tests/GlideShadowLog.java @@ -0,0 +1,20 @@ +package com.bumptech.glide.tests; + +import android.util.Log; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowLog; + +/** + * Exists only to "enable" logging for test coverage. + * + * TODO: when we can ignore Log.* via configuration, remove this class. + */ +@Implements(Log.class) +public class GlideShadowLog extends ShadowLog { + + @Implementation + public static boolean isLoggable(String tag, int level) { + return true; + } +} diff --git a/library/src/androidTest/resources/org.robolectric.Config.properties b/library/src/androidTest/resources/org.robolectric.Config.properties new file mode 100644 index 00000000..3219ec4f --- /dev/null +++ b/library/src/androidTest/resources/org.robolectric.Config.properties @@ -0,0 +1,3 @@ +# Exists only to "enable" logging for test coverage. +# TODO: when we can ignore Log.* via configuration, remove this line. +shadows=com.bumptech.glide.tests.GlideShadowLog diff --git a/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategy.java b/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategy.java index ef57437e..f3035e50 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategy.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategy.java @@ -56,7 +56,8 @@ class AttributeStrategy implements LruPoolStrategy { return "[" + width + "x" + height + "], " + config; } - private static class KeyPool extends BaseKeyPool<Key> { + // Visible for testing. + static class KeyPool extends BaseKeyPool<Key> { public Key get(int width, int height, Bitmap.Config config) { Key result = get(); result.init(width, height, config); @@ -69,7 +70,8 @@ class AttributeStrategy implements LruPoolStrategy { } } - private static class Key implements Poolable { + // Visible for testing. + static class Key implements Poolable { private final KeyPool pool; private int width; private int height; @@ -88,26 +90,13 @@ class AttributeStrategy implements LruPoolStrategy { @Override public boolean equals(Object o) { - if (this == o) { - return true; + if (o instanceof Key) { + Key other = (Key) o; + return width == other.width + && height == other.height + && config == other.config; } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Key key = (Key) o; - - if (height != key.height) { - return false; - } - if (width != key.width) { - return false; - } - if (config != key.config) { - return false; - } - - return true; + return false; } @Override diff --git a/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategy.java b/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategy.java index b33d13ac..1ce61aaf 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategy.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/bitmap_recycle/SizeStrategy.java @@ -119,7 +119,8 @@ class SizeStrategy implements LruPoolStrategy { return "[" + size + "]"; } - private static class KeyPool extends BaseKeyPool<Key> { + // Visible for testing. + static class KeyPool extends BaseKeyPool<Key> { public Key get(int size) { Key result = get(); @@ -133,7 +134,8 @@ class SizeStrategy implements LruPoolStrategy { } } - private static final class Key implements Poolable { + // Visible for testing. + static final class Key implements Poolable { private final KeyPool pool; private int size; @@ -147,16 +149,11 @@ class SizeStrategy implements LruPoolStrategy { @Override public boolean equals(Object o) { - if (this == o) { - return true; + if (o instanceof Key) { + Key other = (Key) o; + return size == other.size; } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Key key = (Key) o; - - return size == key.size; + return false; } @Override diff --git a/library/src/main/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutor.java b/library/src/main/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutor.java index 9972fc6d..db0a128a 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutor.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/executor/FifoPriorityThreadPoolExecutor.java @@ -34,7 +34,7 @@ public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor { @Override protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { - return new FifoPriorityLoadTask<T>(runnable, value, ordering.getAndIncrement()); + return new LoadTask<T>(runnable, value, ordering.getAndIncrement()); } /** @@ -57,11 +57,12 @@ public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor { } } - private static class FifoPriorityLoadTask<T> extends FutureTask<T> implements Comparable<FifoPriorityLoadTask<?>> { + // Visible for testing. + static class LoadTask<T> extends FutureTask<T> implements Comparable<LoadTask<?>> { private final int priority; private final int order; - public FifoPriorityLoadTask(Runnable runnable, T result, int order) { + public LoadTask(Runnable runnable, T result, int order) { super(runnable, result); if (!(runnable instanceof Prioritized)) { throw new IllegalArgumentException("FifoPriorityThreadPoolExecutor must be given Runnables that " @@ -71,25 +72,14 @@ public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor { this.order = order; } + @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { - if (this == o) { - return true; + if (o instanceof LoadTask) { + LoadTask<Object> other = (LoadTask<Object>) o; + return order == other.order && priority == other.priority; } - if (o == null || getClass() != o.getClass()) { - return false; - } - - FifoPriorityLoadTask that = (FifoPriorityLoadTask) o; - - if (order != that.order) { - return false; - } - if (priority != that.priority) { - return false; - } - - return true; + return false; } @Override @@ -100,7 +90,7 @@ public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor { } @Override - public int compareTo(FifoPriorityLoadTask<?> loadTask) { + public int compareTo(LoadTask<?> loadTask) { int result = priority - loadTask.priority; if (result == 0) { result = order - loadTask.order; diff --git a/library/src/main/java/com/bumptech/glide/load/engine/prefill/PreFillType.java b/library/src/main/java/com/bumptech/glide/load/engine/prefill/PreFillType.java index 33d0387e..5037b352 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/prefill/PreFillType.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/prefill/PreFillType.java @@ -30,15 +30,6 @@ public final class PreFillType { if (config == null) { throw new NullPointerException("Config must not be null"); } - if (width <= 0) { - throw new IllegalArgumentException("Width must be > 0"); - } - if (height <= 0) { - throw new IllegalArgumentException("Height must be > 0"); - } - if (weight <= 0) { - throw new IllegalArgumentException("Weight must be > 0"); - } this.width = width; this.height = height; @@ -76,18 +67,14 @@ public final class PreFillType { @Override public boolean equals(Object o) { - if (this == o) { - return true; - } else if (o == null || getClass() != o.getClass()) { - return false; + if (o instanceof PreFillType) { + PreFillType other = (PreFillType) o; + return height == other.height + && width == other.width + && weight == other.weight + && config == other.config; } - - PreFillType size = (PreFillType) o; - - return height == size.height - && weight == size.weight - && width == size.width - && config == size.config; + return false; } @Override @@ -112,7 +99,7 @@ public final class PreFillType { /** * Builder for {@link PreFillType}. */ - public static final class Builder { + public static class Builder { private final int width; private final int height; @@ -133,6 +120,12 @@ public final class PreFillType { * @param height The height in pixels of the Bitmaps to prefill. */ public Builder(int width, int height) { + if (width <= 0) { + throw new IllegalArgumentException("Width must be > 0"); + } + if (height <= 0) { + throw new IllegalArgumentException("Height must be > 0"); + } this.width = width; this.height = height; } diff --git a/library/src/main/java/com/bumptech/glide/load/model/ModelCache.java b/library/src/main/java/com/bumptech/glide/load/model/ModelCache.java index a0dede14..55c0de0c 100644 --- a/library/src/main/java/com/bumptech/glide/load/model/ModelCache.java +++ b/library/src/main/java/com/bumptech/glide/load/model/ModelCache.java @@ -60,14 +60,15 @@ public class ModelCache<A, B> { cache.put(key, value); } - private static final class ModelKey<A> { + // Visible for testing. + static final class ModelKey<A> { private static final Queue<ModelKey<?>> KEY_QUEUE = Util.createQueue(0); private int height; private int width; private A model; - public static <A> ModelKey<A> get(A model, int width, int height) { + static <A> ModelKey<A> get(A model, int width, int height) { @SuppressWarnings("unchecked") ModelKey<A> modelKey = (ModelKey<A>) KEY_QUEUE.poll(); if (modelKey == null) { @@ -92,26 +93,11 @@ public class ModelCache<A, B> { @Override public boolean equals(Object o) { - if (this == o) { - return true; + if (o instanceof ModelKey) { + ModelKey other = (ModelKey) o; + return width == other.width && height == other.height && model.equals(other.model); } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ModelKey<?> modelKey = (ModelKey<?>) o; - - if (height != modelKey.height) { - return false; - } - if (width != modelKey.width) { - return false; - } - if (!model.equals(modelKey.model)) { - return false; - } - - return true; + return false; } @Override diff --git a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/TransformationUtils.java b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/TransformationUtils.java index 80ab07cc..0f9c6693 100644 --- a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/TransformationUtils.java +++ b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/TransformationUtils.java @@ -149,22 +149,18 @@ public final class TransformationUtils { * Returns a matrix with rotation set based on Exif orientation tag. * If the orientation is undefined or 0 null is returned. * + * @deprecated No longer used by Glide, scheduled to be removed in Glide 4.0 * @param pathToOriginal Path to original image file that may have exif data. * @return A rotation in degrees based on exif orientation */ @TargetApi(Build.VERSION_CODES.ECLAIR) + @Deprecated public static int getOrientation(String pathToOriginal) { int degreesToRotate = 0; try { ExifInterface exif = new ExifInterface(pathToOriginal); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); - if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { - degreesToRotate = 90; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { - degreesToRotate = 180; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { - degreesToRotate = 270; - } + return getExifOrientationDegrees(orientation); } catch (Exception e) { if (Log.isLoggable(TAG, Log.ERROR)) { Log.e(TAG, "Unable to get orientation for image with path=" + pathToOriginal, e); @@ -177,10 +173,12 @@ public final class TransformationUtils { * This is an expensive operation that copies the image in place with the pixels rotated. * If possible rather use getOrientationMatrix, and set that as the imageMatrix on an ImageView. * + * @deprecated No longer used by Glide, scheduled to be removed in Glide 4.0 * @param pathToOriginal Path to original image file that may have exif data. * @param imageToOrient Image Bitmap to orient. * @return The oriented bitmap. May be the imageToOrient without modification, or a new Bitmap. */ + @Deprecated public static Bitmap orientImage(String pathToOriginal, Bitmap imageToOrient) { int degreesToRotate = getOrientation(pathToOriginal); return rotateImage(imageToOrient, degreesToRotate); @@ -255,7 +253,36 @@ public final class TransformationUtils { * @return The rotated and/or flipped image or toOrient if no rotation or flip was necessary. */ public static Bitmap rotateImageExif(Bitmap toOrient, BitmapPool pool, int exifOrientation) { + if (exifOrientation == ExifInterface.ORIENTATION_NORMAL + || exifOrientation == ExifInterface.ORIENTATION_UNDEFINED) { + return toOrient; + } final Matrix matrix = new Matrix(); + initializeMatrixForRotation(exifOrientation, matrix); + + // From Bitmap.createBitmap. + final RectF newRect = new RectF(0, 0, toOrient.getWidth(), toOrient.getHeight()); + matrix.mapRect(newRect); + + final int newWidth = Math.round(newRect.width()); + final int newHeight = Math.round(newRect.height()); + + Bitmap result = pool.get(newWidth, newHeight, toOrient.getConfig()); + if (result == null) { + result = Bitmap.createBitmap(newWidth, newHeight, toOrient.getConfig()); + } + + matrix.postTranslate(-newRect.left, -newRect.top); + + final Canvas canvas = new Canvas(result); + final Paint paint = new Paint(PAINT_FLAGS); + canvas.drawBitmap(toOrient, matrix, paint); + + return result; + } + + // Visible for testing. + static void initializeMatrixForRotation(int exifOrientation, Matrix matrix) { switch (exifOrientation) { case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: matrix.setScale(-1, 1); @@ -281,29 +308,8 @@ public final class TransformationUtils { case ExifInterface.ORIENTATION_ROTATE_270: matrix.setRotate(-90); break; - // case ExifInterface.ORIENTATION_NORMAL default: - return toOrient; + // Do nothing. } - - // From Bitmap.createBitmap. - final RectF newRect = new RectF(0, 0, toOrient.getWidth(), toOrient.getHeight()); - matrix.mapRect(newRect); - - final int newWidth = Math.round(newRect.width()); - final int newHeight = Math.round(newRect.height()); - - Bitmap result = pool.get(newWidth, newHeight, toOrient.getConfig()); - if (result == null) { - result = Bitmap.createBitmap(newWidth, newHeight, toOrient.getConfig()); - } - - matrix.postTranslate(-newRect.left, -newRect.top); - - final Canvas canvas = new Canvas(result); - final Paint paint = new Paint(PAINT_FLAGS); - canvas.drawBitmap(toOrient, matrix, paint); - - return result; } } |