/* * 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.decoder; import java.io.IOException; import java.util.Arrays; import com.facebook.common.internal.ByteStreams; import com.facebook.common.memory.ByteArrayPool; import com.facebook.common.memory.PooledByteBuffer; import com.facebook.common.references.CloseableReference; import com.facebook.common.references.ResourceReleaser; import com.facebook.imagepipeline.image.EncodedImage; import com.facebook.imagepipeline.testing.TrivialPooledByteBuffer; import org.junit.*; import org.junit.runner.*; import org.mockito.*; import org.robolectric.*; import static org.junit.Assert.*; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.*; @RunWith(RobolectricTestRunner.class) public class ProgressiveJpegParserTest { @Mock public ResourceReleaser mResourceReleaser; private ProgressiveJpegParser mProgressiveJpegParser; private byte[] mWebpBytes; private byte[] mPartialWebpBytes; private byte[] mJpegBytes; @Before public void setUp() throws IOException { MockitoAnnotations.initMocks(this); ByteArrayPool byteArrayPool = mock(ByteArrayPool.class); when(byteArrayPool.get(anyInt())).thenReturn(new byte[10]); mProgressiveJpegParser = new ProgressiveJpegParser(byteArrayPool); mJpegBytes = ByteStreams.toByteArray( ProgressiveJpegParserTest.class.getResourceAsStream("images/image.jpg")); mWebpBytes = ByteStreams.toByteArray( ProgressiveJpegParserTest.class.getResourceAsStream(("images/image.webp"))); mPartialWebpBytes = new byte[mWebpBytes.length / 2]; System.arraycopy(mWebpBytes, 0, mPartialWebpBytes, 0, mPartialWebpBytes.length); } @Test public void testOnPartialWebp() { final TrivialPooledByteBuffer byteBuffer = new TrivialPooledByteBuffer(mPartialWebpBytes); mProgressiveJpegParser.parseMoreData(buildEncodedImage(byteBuffer)); assertFalse(mProgressiveJpegParser.isJpeg()); } @Test public void testOnWebp() { final TrivialPooledByteBuffer byteBuffer = new TrivialPooledByteBuffer(mWebpBytes); mProgressiveJpegParser.parseMoreData(buildEncodedImage(byteBuffer)); assertFalse(mProgressiveJpegParser.isJpeg()); } @Test public void testOnTooShortImage() { final TrivialPooledByteBuffer shortByteBuffer = new TrivialPooledByteBuffer( new byte[] {(byte) 0xff}); assertFalse(mProgressiveJpegParser.isJpeg()); assertFalse(mProgressiveJpegParser.parseMoreData(buildEncodedImage(shortByteBuffer))); assertFalse(mProgressiveJpegParser.isJpeg()); assertEquals(0, mProgressiveJpegParser.getBestScanEndOffset()); assertEquals(0, mProgressiveJpegParser.getBestScanNumber()); } @Test public void testOnShortestJpeg() { final TrivialPooledByteBuffer shortByteBuffer = new TrivialPooledByteBuffer( new byte[] {(byte) 0xff, (byte) 0xd8}); assertFalse(mProgressiveJpegParser.parseMoreData(buildEncodedImage(shortByteBuffer))); assertTrue(mProgressiveJpegParser.isJpeg()); assertEquals(0, mProgressiveJpegParser.getBestScanEndOffset()); assertEquals(0, mProgressiveJpegParser.getBestScanNumber()); } @Test public void testBasic() { byte[] veryFakeJpeg = new byte[] { (byte) 0xff, (byte) 0xd8, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xda, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xda, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0xff, (byte) 0xda, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0xff, (byte) 0xda}; testFirstNBytes(veryFakeJpeg, 3, false, 0, 0); testFirstNBytes(veryFakeJpeg, 6, false, 0, 0); testFirstNBytes(veryFakeJpeg, 8, false, 0, 0); testFirstNBytes(veryFakeJpeg, 13, true, 1, 11); testFirstNBytes(veryFakeJpeg, 13, false, 1, 11); testFirstNBytes(veryFakeJpeg, 17, false, 1, 11); testFirstNBytes(veryFakeJpeg, 18, true, 2, 16); testFirstNBytes(veryFakeJpeg, 20, false, 2, 16); testFirstNBytes(veryFakeJpeg, veryFakeJpeg.length, true, 3, 21); } @Test public void testOnRealJpeg() { testFirstNBytes(mJpegBytes, 7000, true, 1, 4332); testFirstNBytes(mJpegBytes, mJpegBytes.length, true, 10, 32844); } /** * Feeds mProgressiveJpegParser with n initial bytes from byteArray and checks that * * @param byteArray * @param n * @param foundNewScan expected return value of ProgressiveJpegParser.parseMoreData * @param expectedBestScan expected number of scans found by the parser + 1 * @param bestScanEndOffset offset of expected best scan found so far */ private void testFirstNBytes( byte[] byteArray, int n, boolean foundNewScan, int expectedBestScan, int bestScanEndOffset) { assertEquals( foundNewScan, mProgressiveJpegParser.parseMoreData(buildEncodedImage( new TrivialPooledByteBuffer(Arrays.copyOf(byteArray, n))))); assertTrue(mProgressiveJpegParser.isJpeg()); assertEquals(expectedBestScan, mProgressiveJpegParser.getBestScanNumber()); assertEquals(bestScanEndOffset, mProgressiveJpegParser.getBestScanEndOffset()); } private EncodedImage buildEncodedImage(TrivialPooledByteBuffer byteBuffer) { return new EncodedImage(CloseableReference.<PooledByteBuffer>of(byteBuffer)); } }