/* * 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.image; import java.io.FileInputStream; import java.io.IOException; import java.lang.Override; import com.facebook.cache.common.SimpleCacheKey; import com.facebook.common.internal.ByteStreams; import com.facebook.common.internal.Supplier; import com.facebook.common.memory.PooledByteBuffer; import com.facebook.common.references.CloseableReference; import com.facebook.imageformat.DefaultImageFormats; import com.facebook.imageformat.ImageFormat; import com.facebook.imagepipeline.testing.TrivialPooledByteBuffer; import com.facebook.imageutils.JfifUtil; import org.junit.*; import org.junit.runner.*; import org.robolectric.RobolectricTestRunner; import static org.junit.Assert.*; import static org.mockito.Mockito.*; /** * Tests for {@link EncodedImage} */ @RunWith(RobolectricTestRunner.class) public class EncodedImageTest { private static final int ENCODED_BYTES_LENGTH = 100; private CloseableReference<PooledByteBuffer> mByteBufferRef; private FileInputStream mInputStream; private Supplier<FileInputStream> mInputStreamSupplier; @Before public void setup() { mByteBufferRef = CloseableReference.of(mock(PooledByteBuffer.class)); mInputStream = mock(FileInputStream.class); mInputStreamSupplier = new Supplier<FileInputStream>() { @Override public FileInputStream get() { return mInputStream; } }; } @Test public void testByteBufferRef() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); assertEquals(2, mByteBufferRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); assertSame( encodedImage.getByteBufferRef().getUnderlyingReferenceTestOnly(), mByteBufferRef.getUnderlyingReferenceTestOnly()); } @Test public void testInputStream() { EncodedImage encodedImage = new EncodedImage(mInputStreamSupplier); assertSame(encodedImage.getInputStream(), mInputStreamSupplier.get()); } @Test public void testCloneOrNull() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); encodedImage.setImageFormat(DefaultImageFormats.JPEG); encodedImage.setRotationAngle(0); encodedImage.setWidth(1); encodedImage.setHeight(2); encodedImage.setSampleSize(4); encodedImage.setEncodedCacheKey(new SimpleCacheKey("key")); EncodedImage encodedImage2 = EncodedImage.cloneOrNull(encodedImage); assertEquals(3, mByteBufferRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); assertSame( encodedImage.getByteBufferRef().getUnderlyingReferenceTestOnly(), encodedImage2.getByteBufferRef().getUnderlyingReferenceTestOnly()); assertEquals(encodedImage.getImageFormat(), encodedImage2.getImageFormat()); assertEquals(encodedImage.getRotationAngle(), encodedImage2.getRotationAngle()); assertEquals(encodedImage.getHeight(), encodedImage2.getHeight()); assertEquals(encodedImage.getWidth(), encodedImage2.getWidth()); assertEquals(encodedImage.getSampleSize(), encodedImage2.getSampleSize()); assertEquals(encodedImage.getEncodedCacheKey(), encodedImage2.getEncodedCacheKey()); encodedImage = new EncodedImage(mInputStreamSupplier, 100); encodedImage.setImageFormat(DefaultImageFormats.JPEG); encodedImage.setRotationAngle(0); encodedImage.setWidth(1); encodedImage.setHeight(2); encodedImage2 = EncodedImage.cloneOrNull(encodedImage); assertSame(encodedImage.getInputStream(), encodedImage2.getInputStream()); assertEquals(encodedImage2.getSize(), encodedImage.getSize()); } @Test public void testCloneOrNull_withInvalidOrNullReferences() { assertEquals(null, EncodedImage.cloneOrNull(null)); EncodedImage encodedImage = new EncodedImage(mByteBufferRef); encodedImage.close(); assertEquals(null, EncodedImage.cloneOrNull(encodedImage)); } @Test public void testClose() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); encodedImage.close(); assertEquals(1, mByteBufferRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); } @Test public void testIsValid() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); assertTrue(encodedImage.isValid()); encodedImage.close(); assertFalse(encodedImage.isValid()); encodedImage = new EncodedImage(mInputStreamSupplier); assertTrue(encodedImage.isValid()); // Test the static method assertFalse(EncodedImage.isValid(null)); } @Test public void testIsMetaDataAvailable() { EncodedImage encodedImage1 = new EncodedImage(mByteBufferRef); EncodedImage encodedImage2 = new EncodedImage(mByteBufferRef); encodedImage2.setRotationAngle(1); encodedImage2.setWidth(1); encodedImage2.setHeight(1); assertFalse(EncodedImage.isMetaDataAvailable(encodedImage1)); assertTrue(EncodedImage.isMetaDataAvailable(encodedImage2)); } @Test public void testCloseSafely() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); EncodedImage.closeSafely(encodedImage); assertEquals(1, mByteBufferRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); } @Test public void testGetInputStream() { EncodedImage encodedImage = new EncodedImage(mInputStreamSupplier); assertSame(mInputStream, encodedImage.getInputStream()); } @Test public void testParseMetaData_JPEG() throws IOException { PooledByteBuffer buf = new TrivialPooledByteBuffer( ByteStreams.toByteArray(EncodedImageTest.class.getResourceAsStream("images/image.jpg"))); EncodedImage encodedImage = new EncodedImage(CloseableReference.of(buf)); encodedImage.parseMetaData(); assertSame(DefaultImageFormats.JPEG, encodedImage.getImageFormat()); assertEquals(550, encodedImage.getWidth()); assertEquals(468, encodedImage.getHeight()); assertEquals(0, encodedImage.getRotationAngle()); } @Test public void testParseMetaData_PNG() throws IOException { PooledByteBuffer buf = new TrivialPooledByteBuffer( ByteStreams.toByteArray(EncodedImageTest.class.getResourceAsStream("images/image.png"))); EncodedImage encodedImage = new EncodedImage(CloseableReference.of(buf)); encodedImage.parseMetaData(); assertSame(DefaultImageFormats.PNG, encodedImage.getImageFormat()); assertEquals(800, encodedImage.getWidth()); assertEquals(600, encodedImage.getHeight()); assertEquals(0, encodedImage.getRotationAngle()); } private void checkWebpImage(final String imagePath, final ImageFormat imageFormat, final int expectedWidth, final int expectedHeight) throws IOException { PooledByteBuffer buf = new TrivialPooledByteBuffer( ByteStreams.toByteArray(EncodedImageTest.class.getResourceAsStream(imagePath))); EncodedImage encodedImage = new EncodedImage(CloseableReference.of(buf)); encodedImage.parseMetaData(); assertSame(imageFormat, encodedImage.getImageFormat()); assertEquals(expectedWidth, encodedImage.getWidth()); assertEquals(expectedHeight, encodedImage.getHeight()); assertEquals(0, encodedImage.getRotationAngle()); } @Test public void testParseMetaData_SimpleWEBP() throws IOException { checkWebpImage("images/1_webp_plain.webp", DefaultImageFormats.WEBP_SIMPLE, 320, 214); } @Test public void testParseMetaData_LosslessWEBP() throws IOException { checkWebpImage("images/1_webp_ll.webp", DefaultImageFormats.WEBP_LOSSLESS, 400, 301); } @Test public void testParseMetaData_ExtendedWithAlphaWEBP() throws IOException { checkWebpImage("images/1_webp_ea.webp", DefaultImageFormats.WEBP_EXTENDED_WITH_ALPHA, 400, 301); } @Test public void testParseMetaData_ExtendedWEBP() throws IOException { checkWebpImage("images/1_webp_e.webp", DefaultImageFormats.WEBP_EXTENDED, 480, 320); } @Test public void testParseMetaData_AnimatedWEBP() throws IOException { checkWebpImage("images/1_webp_anim.webp", DefaultImageFormats.WEBP_ANIMATED, 322, 477); } @Test public void testIsJpegCompleteAt_notComplete() { byte[] encodedBytes = new byte[ENCODED_BYTES_LENGTH]; encodedBytes[ENCODED_BYTES_LENGTH - 2] = 0; encodedBytes[ENCODED_BYTES_LENGTH - 1] = 0; PooledByteBuffer buf = new TrivialPooledByteBuffer(encodedBytes); EncodedImage encodedImage = new EncodedImage(CloseableReference.of(buf)); encodedImage.setImageFormat(DefaultImageFormats.JPEG); assertFalse(encodedImage.isCompleteAt(ENCODED_BYTES_LENGTH)); } @Test public void testIsJpegCompleteAt_Complete() { byte[] encodedBytes = new byte[ENCODED_BYTES_LENGTH]; encodedBytes[ENCODED_BYTES_LENGTH - 2] = (byte) JfifUtil.MARKER_FIRST_BYTE; encodedBytes[ENCODED_BYTES_LENGTH - 1] = (byte) JfifUtil.MARKER_EOI; PooledByteBuffer buf = new TrivialPooledByteBuffer(encodedBytes); EncodedImage encodedImage = new EncodedImage(CloseableReference.of(buf)); encodedImage.setImageFormat(DefaultImageFormats.JPEG); assertTrue(encodedImage.isCompleteAt(ENCODED_BYTES_LENGTH)); } @Test public void testCopyMetaData() { EncodedImage encodedImage = new EncodedImage(mByteBufferRef); encodedImage.setImageFormat(DefaultImageFormats.JPEG); encodedImage.setRotationAngle(0); encodedImage.setWidth(1); encodedImage.setHeight(2); encodedImage.setSampleSize(3); EncodedImage encodedImage2 = new EncodedImage(mByteBufferRef); encodedImage2.copyMetaDataFrom(encodedImage); assertEquals(encodedImage.getImageFormat(), encodedImage2.getImageFormat()); assertEquals(encodedImage.getWidth(), encodedImage2.getWidth()); assertEquals(encodedImage.getHeight(), encodedImage2.getHeight()); assertEquals(encodedImage.getSampleSize(), encodedImage2.getSampleSize()); assertEquals(encodedImage.getSize(), encodedImage2.getSize()); EncodedImage encodedImage3 = new EncodedImage(mInputStreamSupplier); encodedImage3.setImageFormat(DefaultImageFormats.JPEG); encodedImage3.setRotationAngle(0); encodedImage3.setWidth(1); encodedImage3.setHeight(2); encodedImage3.setSampleSize(3); encodedImage3.setStreamSize(4); EncodedImage encodedImage4 = new EncodedImage(mInputStreamSupplier); encodedImage4.copyMetaDataFrom(encodedImage3); assertEquals(encodedImage3.getImageFormat(), encodedImage4.getImageFormat()); assertEquals(encodedImage3.getWidth(), encodedImage4.getWidth()); assertEquals(encodedImage3.getHeight(), encodedImage4.getHeight()); assertEquals(encodedImage3.getSampleSize(), encodedImage4.getSampleSize()); assertEquals(encodedImage3.getSize(), encodedImage4.getSize()); } }