package com.rapidftr.utils; import android.content.Context; import android.graphics.Bitmap; import android.media.ExifInterface; import android.os.Environment; import com.google.common.io.Files; import com.rapidftr.CustomTestRunner; import com.rapidftr.RapidFtrApplication; import com.rapidftr.model.User; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Matchers; import org.robolectric.Robolectric; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Calendar; import static com.rapidftr.RapidFtrApplication.*; import static com.rapidftr.utils.PhotoCaptureHelper.QUALITY; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringEndsWith.endsWith; import static org.hamcrest.core.StringStartsWith.startsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; @RunWith(CustomTestRunner.class) public class PhotoCaptureHelperTest { RapidFtrApplication application; PhotoCaptureHelper photoCaptureHelper; @Before public void setUp() { application = mock(RapidFtrApplication.class); when(application.getSharedPreferences()).thenReturn(Robolectric.application.getSharedPreferences(APP_IDENTIFIER, MODE_PRIVATE)); photoCaptureHelper = spy(new PhotoCaptureHelper(application)); } @Test public void testCaptureUnderNoMedia() { String path = photoCaptureHelper.getDir().getAbsolutePath(); assertThat(path, endsWith("/.nomedia")); } @Test public void testCaptureUnderSDCard() { File file = Environment.getExternalStorageDirectory(); doReturn(file).when(photoCaptureHelper).getExternalStorageDir(); File result = photoCaptureHelper.getDir(); assertThat(result.getParentFile(), equalTo(file)); } @Test public void testCaptureUnderInternalStorage() { File file = mock(File.class); doReturn(false).when(file).canWrite(); doReturn(file).when(photoCaptureHelper).getExternalStorageDir(); File file2 = new File(Environment.getExternalStorageDirectory(), "internal"); doReturn(file2).when(application).getDir("capture", Context.MODE_PRIVATE); File result = photoCaptureHelper.getDir(); assertThat(result.getParentFile(), equalTo(file2)); } @Test public void testCaptureDirUnderSDCard() { Environment.getExternalStorageState(); } @Test public void testCatureFileUnderCaptureDir() { String path = photoCaptureHelper.getDir().getAbsolutePath(); String file = photoCaptureHelper.getTempCaptureFile().getAbsolutePath(); assertThat(file, startsWith(path)); } @Test public void testSaveCaptureTimeInSharedPreferences() { long time1 = System.currentTimeMillis(); photoCaptureHelper.setCaptureTime(); long time2 = System.currentTimeMillis(); long time = application.getSharedPreferences().getLong("capture_start_time", 0); assertTrue(time >= time1 && time <= time2); } @Test public void testGetCaptureTimeFromSharedPreferences() { Calendar expected = Calendar.getInstance(); expected.setTimeInMillis(500); application.getSharedPreferences().edit().putLong("capture_start_time", 500).commit(); Calendar actual = photoCaptureHelper.getCaptureTime(); assertThat(actual, equalTo(expected)); } @Test @Ignore // TODO: Failing in Robolectric 2.0 public void testReturnDefaultThumbnail() throws Exception { doThrow(RuntimeException.class).when(photoCaptureHelper).loadThumbnail("random_file"); Bitmap bitmap = photoCaptureHelper.getThumbnailOrDefault("random_file"); assertTrue(sameBitmap(bitmap, photoCaptureHelper.getDefaultThumbnail())); } @Test public void testReturnOriginalThumbnail() throws Exception { Bitmap expected = mock(Bitmap.class); doReturn(expected).when(photoCaptureHelper).loadThumbnail("random_file"); doReturn(new File("random_file.jpg")).when(photoCaptureHelper).getFile("random_file", ".jpg"); Bitmap actual = photoCaptureHelper.getThumbnailOrDefault("random_file"); assertThat(actual, equalTo(expected)); } @Test public void testSaveThumbnailShouldResizeAndSave() throws Exception { Bitmap original = mock(Bitmap.class), scaled = mock(Bitmap.class), rotated = mock(Bitmap.class); doReturn(scaled).when(photoCaptureHelper).resizeImageTo(original, 96, 96); doReturn(rotated).when(photoCaptureHelper).rotateBitmap(scaled, 90); User user = mock(User.class); doReturn(user).when(application).getCurrentUser(); doReturn("key").when(user).getDbKey(); doNothing().when(photoCaptureHelper).save(rotated, "random_file_thumb", QUALITY, "key"); photoCaptureHelper.saveThumbnail(original, 90, "random_file"); verify(photoCaptureHelper).save(rotated, "random_file_thumb", QUALITY, "key"); } @Test public void testSaveActualImageShouldResizeAndSave() throws Exception { Bitmap original = mock(Bitmap.class), scaled = mock(Bitmap.class), rotated = mock(Bitmap.class); doReturn(scaled).when(photoCaptureHelper).scaleImageTo(original, 475, 635); doReturn(rotated).when(photoCaptureHelper).rotateBitmap(scaled, 180); User user = mock(User.class); doReturn(user).when(application).getCurrentUser(); doReturn("key").when(user).getDbKey(); doNothing().when(photoCaptureHelper).save(rotated, "random_file", QUALITY, "key"); photoCaptureHelper.savePhoto(original, 180, "random_file"); verify(photoCaptureHelper).save(rotated, "random_file", QUALITY, "key"); verify(scaled).recycle(); verify(rotated).recycle(); } @Test public void testSavePhotoAndCompress() throws Exception { Bitmap bitmap = mock(Bitmap.class); File file = new File(photoCaptureHelper.getDir(), "random_file.jpg"); OutputStream out = mock(OutputStream.class); doReturn(out).when(photoCaptureHelper).getCipherOutputStream(eq(file), anyString()); doReturn(mock(User.class)).when(application).getCurrentUser(); photoCaptureHelper.save(bitmap, "random_file", QUALITY, "key"); verify(bitmap).compress(Bitmap.CompressFormat.JPEG, 85, out); verify(out).close(); } @Test public void testShouldReturnRotationInfoOfPicture() throws IOException { ExifInterface mockExifInterface = mock(ExifInterface.class); doReturn(mockExifInterface).when(photoCaptureHelper).getExifInterface(); doReturn(ExifInterface.ORIENTATION_ROTATE_90).when(mockExifInterface).getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); int rotation = photoCaptureHelper.getPictureRotation(); assertEquals(90, rotation); } @Test public void testScaleImagePreserveAspectRatioHorizontally() throws Exception { Bitmap bitmap = mock(Bitmap.class); int maxWidth = 100, maxHeight = 100; int givenWidth = 300, givenHeight = 200; int expectedWidth = 100, expectedHeight = 66; given(bitmap.getWidth()).willReturn(givenWidth); given(bitmap.getHeight()).willReturn(givenHeight); doReturn(bitmap).when(photoCaptureHelper).resizeImageTo(bitmap, expectedWidth, expectedHeight); // If you get exception here - then it means resizeImageTo was not called with proper passing arguments assertThat(bitmap, equalTo(photoCaptureHelper.scaleImageTo(bitmap, maxWidth, maxHeight))); } @Test public void testScaleImagePreserveAspectRatioVertically() throws Exception { Bitmap bitmap = mock(Bitmap.class); int maxWidth = 100, maxHeight = 100; int givenWidth = 200, givenHeight = 300; int expectedWidth = 66, expectedHeight = 100; given(bitmap.getWidth()).willReturn(givenWidth); given(bitmap.getHeight()).willReturn(givenHeight); doReturn(bitmap).when(photoCaptureHelper).resizeImageTo(bitmap, expectedWidth, expectedHeight); // If you get exception here - then it means resizeImageTo was not called with proper passing arguments assertThat(bitmap, equalTo(photoCaptureHelper.scaleImageTo(bitmap, maxWidth, maxHeight))); } @Test public void testScaleImagePreserveAspectRatioHorizontally2() throws Exception { Bitmap bitmap = mock(Bitmap.class); int maxWidth = 100, maxHeight = 100; int givenWidth = 200, givenHeight = 50; int expectedWidth = 100, expectedHeight = 25; given(bitmap.getWidth()).willReturn(givenWidth); given(bitmap.getHeight()).willReturn(givenHeight); doReturn(bitmap).when(photoCaptureHelper).resizeImageTo(bitmap, expectedWidth, expectedHeight); // If you get exception here - then it means resizeImageTo was not called with proper passing arguments assertThat(bitmap, equalTo(photoCaptureHelper.scaleImageTo(bitmap, maxWidth, maxHeight))); } @Test public void testScaleImagePreserveAspectRatioVertically2() throws Exception { Bitmap bitmap = mock(Bitmap.class); int maxWidth = 100, maxHeight = 100; int givenWidth = 50, givenHeight = 200; int expectedWidth = 25, expectedHeight = 100; given(bitmap.getWidth()).willReturn(givenWidth); given(bitmap.getHeight()).willReturn(givenHeight); doReturn(bitmap).when(photoCaptureHelper).resizeImageTo(bitmap, expectedWidth, expectedHeight); // If you get exception here - then it means resizeImageTo was not called with proper passing arguments assertThat(bitmap, equalTo(photoCaptureHelper.scaleImageTo(bitmap, maxWidth, maxHeight))); } @Test public void shouldEncryptTheGivenEncryptedPhotoUsingNewKey() throws IOException, GeneralSecurityException { File mockFile = mock(File.class); File mockThumbnailFile = mock(File.class); doReturn(mockFile).when(photoCaptureHelper).getFile("photo_name", ".jpg"); doReturn(mockThumbnailFile).when(photoCaptureHelper).getFile("photo_name_thumb", ".jpg"); InputStream mockInputStream = mock(InputStream.class); InputStream mockThumbnailInputStream = mock(InputStream.class); Bitmap mockBitmap = mock(Bitmap.class); Bitmap mockThumbnailBitmap = mock(Bitmap.class); doReturn(mockInputStream).when(photoCaptureHelper).getCipherInputStream(mockFile, "oldKey"); doReturn(mockThumbnailInputStream).when(photoCaptureHelper).getCipherInputStream(mockThumbnailFile, "oldKey"); doReturn(mockBitmap).when(photoCaptureHelper).decodeStreamToBitMap(mockInputStream); doReturn(mockThumbnailBitmap).when(photoCaptureHelper).decodeStreamToBitMap(mockThumbnailInputStream); doNothing().when(photoCaptureHelper).save(Matchers.<Bitmap>any(), anyString(), anyInt(), anyString()); photoCaptureHelper.convertPhoto("photo_name", "oldKey", "newKey"); verify(photoCaptureHelper).save(mockBitmap, "photo_name", PhotoCaptureHelper.QUALITY, "newKey"); verify(photoCaptureHelper).save(mockThumbnailBitmap, "photo_name_thumb", PhotoCaptureHelper.QUALITY, "newKey"); } @After public void resetSharedDirectory() { try { Files.deleteRecursively(Environment.getExternalStorageDirectory()); Environment.getExternalStorageDirectory().mkdir(); } catch (IOException e) { // Do nothing } } protected boolean sameBitmap(Bitmap bitmap1, Bitmap bitmap2) { ByteBuffer buffer1 = ByteBuffer.allocate(bitmap1.getHeight() * bitmap1.getRowBytes()); bitmap1.copyPixelsToBuffer(buffer1); ByteBuffer buffer2 = ByteBuffer.allocate(bitmap2.getHeight() * bitmap2.getRowBytes()); bitmap2.copyPixelsToBuffer(buffer2); return Arrays.equals(buffer1.array(), buffer2.array()); } }