Improve coverage (#507)
	
		
	
				
					
				
			* Do not use ViewCompat * Remove TODOs, improve logging * SizeSelectorParser and CameraUtils tests * DefaultAutoFOcusMarkerTest * MarkerParserTest and improve MarkerLayoutTest * Add MediaEncoderEngine comments * Add ExifHelper test * ImageHelper test * More internal/utils testspull/513/head
							parent
							
								
									6962744d4f
								
							
						
					
					
						commit
						1318b7d10b
					
				| @ -0,0 +1,55 @@ | ||||
| package com.otaliastudios.cameraview.internal.utils; | ||||
| 
 | ||||
| 
 | ||||
| import android.media.CamcorderProfile; | ||||
| 
 | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| import com.otaliastudios.cameraview.CameraUtils; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class CamcorderProfilesTest extends BaseTest { | ||||
| 
 | ||||
|     private String getCameraId() { | ||||
|         if (CameraUtils.hasCameras(getContext())) { | ||||
|             return "0"; | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testInvalidCameraReturnsLowest() { | ||||
|         CamcorderProfile invalid = CamcorderProfiles.get("invalid", new Size(100, 100)); | ||||
|         CamcorderProfile lowest = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW); | ||||
|         assertEquals(lowest.videoFrameWidth, invalid.videoFrameWidth); | ||||
|         assertEquals(lowest.videoFrameHeight, invalid.videoFrameHeight); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testGet() { | ||||
|         String cameraId = getCameraId(); | ||||
|         if (cameraId == null) return; | ||||
|         int cameraIdInt = Integer.parseInt(cameraId); | ||||
| 
 | ||||
|         // Not much we can test. Let's just ask for lowest and highest.
 | ||||
|         CamcorderProfile low = CamcorderProfiles.get(cameraId, new Size(1, 1)); | ||||
|         CamcorderProfile high = CamcorderProfiles.get(cameraId, new Size(Integer.MAX_VALUE, Integer.MAX_VALUE)); | ||||
| 
 | ||||
|         // Compare with lowest
 | ||||
|         CamcorderProfile lowest = CamcorderProfile.get(cameraIdInt, CamcorderProfile.QUALITY_LOW); | ||||
|         CamcorderProfile highest = CamcorderProfile.get(cameraIdInt, CamcorderProfile.QUALITY_HIGH); | ||||
|         assertEquals(lowest.videoFrameWidth, low.videoFrameWidth); | ||||
|         assertEquals(lowest.videoFrameHeight, low.videoFrameHeight); | ||||
|         assertEquals(highest.videoFrameWidth, high.videoFrameWidth); | ||||
|         assertEquals(highest.videoFrameHeight, high.videoFrameHeight); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,102 @@ | ||||
| package com.otaliastudios.cameraview.internal.utils; | ||||
| 
 | ||||
| 
 | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.BitmapFactory; | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.ImageFormat; | ||||
| import android.graphics.Paint; | ||||
| import android.graphics.PorterDuff; | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.YuvImage; | ||||
| import android.media.Image; | ||||
| import android.media.ImageReader; | ||||
| import android.opengl.GLES20; | ||||
| import android.os.Handler; | ||||
| import android.os.Looper; | ||||
| import android.view.Surface; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| import com.otaliastudios.cameraview.internal.egl.EglCore; | ||||
| import com.otaliastudios.cameraview.internal.egl.EglViewport; | ||||
| import com.otaliastudios.cameraview.internal.egl.EglWindowSurface; | ||||
| import com.otaliastudios.cameraview.size.AspectRatio; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.nio.ByteBuffer; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class ImageHelperTest extends BaseTest { | ||||
| 
 | ||||
|     @NonNull | ||||
|     private Image getImage() { | ||||
|         ImageReader reader = ImageReader.newInstance(100, 100, ImageFormat.YUV_420_888, 1); | ||||
|         Surface readerSurface = reader.getSurface(); | ||||
|         final Op<Image> imageOp = new Op<>(true); | ||||
|         reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { | ||||
|             @Override | ||||
|             public void onImageAvailable(ImageReader reader) { | ||||
|                 Image image = reader.acquireLatestImage(); | ||||
|                 if (image != null) imageOp.end(image); | ||||
|             } | ||||
|         }, new Handler(Looper.getMainLooper())); | ||||
| 
 | ||||
|         // Write on reader surface.
 | ||||
|         Canvas readerCanvas = readerSurface.lockCanvas(null); | ||||
|         Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); | ||||
|         paint.setColor(Color.RED); | ||||
|         readerCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY); | ||||
|         readerCanvas.drawCircle(50, 50, 50, paint); | ||||
|         readerSurface.unlockCanvasAndPost(readerCanvas); | ||||
| 
 | ||||
|         // Wait
 | ||||
|         Image image = imageOp.await(5000); | ||||
|         assertNotNull(image); | ||||
|         return image; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testImage() { | ||||
|         Image image = getImage(); | ||||
|         int width = image.getWidth(); | ||||
|         int height = image.getHeight(); | ||||
|         int bitsPerPixel = ImageFormat.getBitsPerPixel(ImageFormat.NV21); | ||||
|         int sizeBits = width * height * bitsPerPixel; | ||||
|         int sizeBytes = (int) Math.ceil(sizeBits / 8.0d); | ||||
|         byte[] bytes = new byte[sizeBytes]; | ||||
|         ImageHelper.convertToNV21(image, bytes); | ||||
|         image.close(); | ||||
| 
 | ||||
|         // Read the image
 | ||||
|         YuvImage yuvImage = new YuvImage(bytes, ImageFormat.NV21, width, height, null); | ||||
|         ByteArrayOutputStream jpegStream = new ByteArrayOutputStream(); | ||||
|         yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, jpegStream); | ||||
|         byte[] jpegByteArray = jpegStream.toByteArray(); | ||||
|         Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length); | ||||
|         assertNotNull(bitmap); | ||||
| 
 | ||||
|         // Wanted to do assertions on the color here but it doesn't work. There must be an issue
 | ||||
|         // with how we are drawing the image in this test, since in real camera, the algorithm works well.
 | ||||
|         // So for now let's just test that nothing crashes during this process.
 | ||||
|         // int color = bitmap.getPixel(bitmap.getWidth() - 1, bitmap.getHeight() - 1);
 | ||||
|         // assertEquals(Color.red(color), 255, 5);
 | ||||
|         // assertEquals(Color.green(color), 0, 5);
 | ||||
|         // assertEquals(Color.blue(color), 0, 5);
 | ||||
|         // assertEquals(Color.alpha(color), 0, 5);
 | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package com.otaliastudios.cameraview.internal.utils; | ||||
| 
 | ||||
| 
 | ||||
| import android.graphics.ImageFormat; | ||||
| import android.graphics.YuvImage; | ||||
| 
 | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class RotationHelperTest extends BaseTest { | ||||
| 
 | ||||
|     @Test(expected = IllegalArgumentException.class) | ||||
|     public void testInvalidRotation1() { | ||||
|         RotationHelper.rotate(new byte[10], new Size(1, 1), -1); | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = IllegalArgumentException.class) | ||||
|     public void testInvalidRotation2() { | ||||
|         RotationHelper.rotate(new byte[10], new Size(1, 1), -90); | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = IllegalArgumentException.class) | ||||
|     public void testInvalidRotation3() { | ||||
|         RotationHelper.rotate(new byte[10], new Size(1, 1), 360); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRotate() { | ||||
|         // Just test that nothing happens.
 | ||||
|         Size inputSize = new Size(160, 90); | ||||
|         int inputSizeBits = inputSize.getWidth() * inputSize.getHeight() * ImageFormat.getBitsPerPixel(ImageFormat.NV21); | ||||
|         int inputSizeBytes = (int) Math.ceil(inputSizeBits / 8.0d); | ||||
|         byte[] input = new byte[inputSizeBytes]; | ||||
|         byte[] output = RotationHelper.rotate(input, inputSize, 90); | ||||
|         assertEquals(input.length, output.length); | ||||
| 
 | ||||
|         Size outputSize = inputSize.flip(); | ||||
|         YuvImage image = new YuvImage(output, ImageFormat.NV21, outputSize.getWidth(), outputSize.getHeight(), null); | ||||
|         assertNotNull(image); | ||||
|     } | ||||
| } | ||||
| @ -1,41 +1,229 @@ | ||||
| package com.otaliastudios.cameraview.internal.utils; | ||||
| 
 | ||||
| 
 | ||||
| import com.google.android.gms.tasks.Task; | ||||
| import com.google.android.gms.tasks.Tasks; | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import java.util.concurrent.Callable; | ||||
| import java.util.concurrent.ExecutionException; | ||||
| import java.util.concurrent.Executor; | ||||
| 
 | ||||
| import static org.junit.Assert.*; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class WorkerHandlerTest extends BaseTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void testCache() { | ||||
|         WorkerHandler w1 = WorkerHandler.get("handler1"); | ||||
|         WorkerHandler w1a = WorkerHandler.get("handler1"); | ||||
|         WorkerHandler w2 = WorkerHandler.get("handler2"); | ||||
|         assertSame(w1, w1a); | ||||
|         assertNotSame(w1, w2); | ||||
|     public void testGetFromCache() { | ||||
|         WorkerHandler first = WorkerHandler.get("first"); | ||||
|         WorkerHandler second = WorkerHandler.get("first"); | ||||
|         assertSame(first, second); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testStaticRun() { | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         Runnable action = new Runnable() { | ||||
|     public void testGetAnother() { | ||||
|         WorkerHandler first = WorkerHandler.get("first"); | ||||
|         WorkerHandler second = WorkerHandler.get("second"); | ||||
|         assertNotSame(first, second); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private Runnable getRunnableForOp(final @NonNull Op<Boolean> op) { | ||||
|         return new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 op.end(true); | ||||
|             } | ||||
|         }; | ||||
|         WorkerHandler.execute(action); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private Callable<Boolean> getCallableForOp(final @NonNull Op<Boolean> op) { | ||||
|         return new Callable<Boolean>() { | ||||
|             @Override | ||||
|             public Boolean call() { | ||||
|                 op.end(true); | ||||
|                 return true; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private Callable<Void> getThrowCallable() { | ||||
|         return new Callable<Void>() { | ||||
|             @Override | ||||
|             public Void call() { | ||||
|                 throw new RuntimeException("Fake error"); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     private void waitOp(@NonNull Op<Boolean> op) { | ||||
|         Boolean result = op.await(500); | ||||
|         assertNotNull(result); | ||||
|         assertTrue(result); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testFallbackExecute() { | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         WorkerHandler.execute(getRunnableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testPostRunnable() { | ||||
|         WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.post(getRunnableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testPostCallable() { | ||||
|         WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.post(getCallableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testPostCallable_throws() { | ||||
|         WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         Task<Void> task = handler.post(getThrowCallable()); | ||||
|         try { Tasks.await(task); } catch (ExecutionException | InterruptedException ignore) {} | ||||
|         assertTrue(task.isComplete()); | ||||
|         assertFalse(task.isSuccessful()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRunRunnable_background() { | ||||
|         WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.run(getRunnableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRunRunnable_sameThread() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op1 = new Op<>(true); | ||||
|         final Op<Boolean> op2 = new Op<>(true); | ||||
|         handler.post(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 handler.run(getRunnableForOp(op2)); | ||||
|                 assertTrue(op2.await(0)); // Do not wait.
 | ||||
|                 op1.end(true); | ||||
|             } | ||||
|         }); | ||||
|         waitOp(op1); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRunCallable_background() { | ||||
|         WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.run(getCallableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRunCallable_sameThread() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op1 = new Op<>(true); | ||||
|         final Op<Boolean> op2 = new Op<>(true); | ||||
|         handler.post(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 handler.run(getCallableForOp(op2)); | ||||
|                 assertTrue(op2.await(0)); // Do not wait.
 | ||||
|                 op1.end(true); | ||||
|             } | ||||
|         }); | ||||
|         waitOp(op1); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRunCallable_sameThread_throws() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.post(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 Task<Void> task = handler.run(getThrowCallable()); | ||||
|                 assertTrue(task.isComplete()); // Already complete
 | ||||
|                 assertFalse(task.isSuccessful()); | ||||
|                 op.end(true); | ||||
|             } | ||||
|         }); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testPostDelayed_tooEarly() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.post(1000, getRunnableForOp(op)); | ||||
|         assertNull(op.await(500)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testPostDelayed() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         handler.post(1000, getRunnableForOp(op)); | ||||
|         assertNotNull(op.await(2000)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testRemove() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         Runnable runnable = getRunnableForOp(op); | ||||
|         handler.post(1000, runnable); | ||||
|         handler.remove(runnable); | ||||
|         assertNull(op.await(2000)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testGetters() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         assertNotNull(handler.getExecutor()); | ||||
|         assertNotNull(handler.getHandler()); | ||||
|         assertNotNull(handler.getLooper()); | ||||
|         assertNotNull(handler.getThread()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testExecutor() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         Executor executor = handler.getExecutor(); | ||||
|         final Op<Boolean> op = new Op<>(true); | ||||
|         executor.execute(getRunnableForOp(op)); | ||||
|         waitOp(op); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testDestroy() { | ||||
|         final WorkerHandler handler = WorkerHandler.get("handler"); | ||||
|         assertTrue(handler.getThread().isAlive()); | ||||
|         WorkerHandler.destroy(); | ||||
|         // Wait for the thread to die.
 | ||||
|         try { handler.getThread().join(500); } catch (InterruptedException ignore) {} | ||||
|         assertFalse(handler.getThread().isAlive()); | ||||
|         WorkerHandler newHandler = WorkerHandler.get("handler"); | ||||
|         assertNotSame(handler, newHandler); | ||||
|         assertTrue(newHandler.getThread().isAlive()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,104 @@ | ||||
| package com.otaliastudios.cameraview.markers; | ||||
| 
 | ||||
| 
 | ||||
| import android.graphics.PointF; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.FrameLayout; | ||||
| 
 | ||||
| import androidx.test.annotation.UiThreadTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| 
 | ||||
| import org.junit.After; | ||||
| import org.junit.Assert; | ||||
| import org.junit.Before; | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| import org.mockito.Mockito; | ||||
| 
 | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.mockito.Mockito.atLeastOnce; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.never; | ||||
| import static org.mockito.Mockito.spy; | ||||
| import static org.mockito.Mockito.verify; | ||||
| 
 | ||||
| public class DefaultAutoFocusMarkerTest extends BaseTest { | ||||
| 
 | ||||
|     private DefaultAutoFocusMarker marker; | ||||
| 
 | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         marker = new DefaultAutoFocusMarker(); | ||||
|     } | ||||
| 
 | ||||
|     @After | ||||
|     public void tearDown() { | ||||
|         marker = null; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testOnAttach() { | ||||
|         assertNull(marker.mContainer); | ||||
|         assertNull(marker.mFill); | ||||
|         ViewGroup container = new FrameLayout(getContext()); | ||||
|         View result = marker.onAttach(getContext(), container); | ||||
|         assertNotNull(result); | ||||
|         assertNotNull(marker.mContainer); | ||||
|         assertNotNull(marker.mFill); | ||||
|     } | ||||
| 
 | ||||
|     @UiThreadTest | ||||
|     @Test | ||||
|     public void testOnAutoFocusStart() { | ||||
|         View mockContainer = spy(new View(getContext())); | ||||
|         View mockFill = spy(new View(getContext())); | ||||
|         marker.mContainer = mockContainer; | ||||
|         marker.mFill = mockFill; | ||||
|         marker.onAutoFocusStart(AutoFocusTrigger.GESTURE, new PointF()); | ||||
|         verify(mockContainer, atLeastOnce()).clearAnimation(); | ||||
|         verify(mockFill, atLeastOnce()).clearAnimation(); | ||||
|         verify(mockContainer, atLeastOnce()).animate(); | ||||
|         verify(mockFill, atLeastOnce()).animate(); | ||||
|     } | ||||
| 
 | ||||
|     @UiThreadTest | ||||
|     @Test | ||||
|     public void testOnAutoFocusStart_fromMethod() { | ||||
|         View mockContainer = spy(new View(getContext())); | ||||
|         View mockFill = spy(new View(getContext())); | ||||
|         marker.mContainer = mockContainer; | ||||
|         marker.mFill = mockFill; | ||||
|         marker.onAutoFocusStart(AutoFocusTrigger.METHOD, new PointF()); | ||||
|         verify(mockContainer, never()).clearAnimation(); | ||||
|         verify(mockFill, never()).clearAnimation(); | ||||
|         verify(mockContainer, never()).animate(); | ||||
|         verify(mockFill, never()).animate(); | ||||
|     } | ||||
| 
 | ||||
|     @UiThreadTest | ||||
|     @Test | ||||
|     public void testOnAutoFocusEnd() { | ||||
|         View mockContainer = spy(new View(getContext())); | ||||
|         View mockFill = spy(new View(getContext())); | ||||
|         marker.mContainer = mockContainer; | ||||
|         marker.mFill = mockFill; | ||||
|         marker.onAutoFocusEnd(AutoFocusTrigger.GESTURE, true, new PointF()); | ||||
|         verify(mockContainer, atLeastOnce()).animate(); | ||||
|         verify(mockFill, atLeastOnce()).animate(); | ||||
|     } | ||||
| 
 | ||||
|     @UiThreadTest | ||||
|     @Test | ||||
|     public void testOnAutoFocusEnd_fromMethod() { | ||||
|         View mockContainer = spy(new View(getContext())); | ||||
|         View mockFill = spy(new View(getContext())); | ||||
|         marker.mContainer = mockContainer; | ||||
|         marker.mFill = mockFill; | ||||
|         marker.onAutoFocusEnd(AutoFocusTrigger.METHOD, true, new PointF()); | ||||
|         verify(mockContainer, never()).animate(); | ||||
|         verify(mockFill, never()).animate(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,79 @@ | ||||
| package com.otaliastudios.cameraview.markers; | ||||
| 
 | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.PointF; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.annotation.StyleableRes; | ||||
| import androidx.arch.core.util.Function; | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| import com.otaliastudios.cameraview.R; | ||||
| import com.otaliastudios.cameraview.size.Size; | ||||
| import com.otaliastudios.cameraview.size.SizeSelectorParser; | ||||
| 
 | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static junit.framework.TestCase.assertNotNull; | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.ArgumentMatchers.anyBoolean; | ||||
| import static org.mockito.ArgumentMatchers.anyInt; | ||||
| import static org.mockito.ArgumentMatchers.eq; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.when; | ||||
| 
 | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class MarkerParserTest extends BaseTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void testNullConstructor() { | ||||
|         TypedArray array = mock(TypedArray.class); | ||||
|         when(array.hasValue(R.styleable.CameraView_cameraAutoFocusMarker)).thenReturn(false); | ||||
|         when(array.getString(R.styleable.CameraView_cameraAutoFocusMarker)).thenReturn(null); | ||||
|         MarkerParser parser = new MarkerParser(array); | ||||
|         assertNull(parser.getAutoFocusMarker()); | ||||
|     } | ||||
|     @Test | ||||
|     public void testConstructor() { | ||||
|         TypedArray array = mock(TypedArray.class); | ||||
|         when(array.hasValue(R.styleable.CameraView_cameraAutoFocusMarker)).thenReturn(true); | ||||
|         when(array.getString(R.styleable.CameraView_cameraAutoFocusMarker)).thenReturn(Marker.class.getName()); | ||||
|         MarkerParser parser = new MarkerParser(array); | ||||
|         assertNotNull(parser.getAutoFocusMarker()); | ||||
|         assertTrue(parser.getAutoFocusMarker() instanceof Marker); | ||||
|     } | ||||
| 
 | ||||
|     public static class Marker implements AutoFocusMarker { | ||||
| 
 | ||||
|         public Marker() { } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public View onAttach(@NonNull Context context, @NonNull ViewGroup container) { | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onAutoFocusStart(@NonNull AutoFocusTrigger trigger, @NonNull PointF point) { } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onAutoFocusEnd(@NonNull AutoFocusTrigger trigger, boolean successful, @NonNull PointF point) { } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,211 @@ | ||||
| package com.otaliastudios.cameraview.size; | ||||
| 
 | ||||
| 
 | ||||
| import android.content.res.TypedArray; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.StyleableRes; | ||||
| import androidx.arch.core.util.Function; | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||||
| import androidx.test.filters.SmallTest; | ||||
| 
 | ||||
| import com.otaliastudios.cameraview.BaseTest; | ||||
| import com.otaliastudios.cameraview.R; | ||||
| 
 | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.mockito.ArgumentMatchers.anyBoolean; | ||||
| import static org.mockito.ArgumentMatchers.anyInt; | ||||
| import static org.mockito.ArgumentMatchers.eq; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.when; | ||||
| 
 | ||||
| 
 | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| @SmallTest | ||||
| public class SizeSelectorParserTest extends BaseTest { | ||||
| 
 | ||||
|     private MockTypedArray input; | ||||
|     private List<Size> sizes = Arrays.asList( | ||||
|             new Size(100, 200), | ||||
|             new Size(150, 300), | ||||
|             new Size(600, 900), | ||||
|             new Size(600, 600), | ||||
|             new Size(1600, 900), | ||||
|             new Size(30, 40), | ||||
|             new Size(40, 30), | ||||
|             new Size(2000, 4000) | ||||
|     ); | ||||
| 
 | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         input = new MockTypedArray(); | ||||
|     } | ||||
| 
 | ||||
|     @After | ||||
|     public void tearDown() { | ||||
|         input = null; | ||||
|     } | ||||
| 
 | ||||
|     private void doAssert(@NonNull Function<List<Size>, Void> assertions) { | ||||
|         SizeSelectorParser parser = new SizeSelectorParser(input.array); | ||||
|         assertions.apply(parser.getPictureSizeSelector().select(sizes)); | ||||
|         assertions.apply(parser.getVideoSizeSelector().select(sizes)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testWidth() { | ||||
|         input.setMinWidth(1500); | ||||
|         input.setMaxWidth(1700); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(1, input.size()); | ||||
|                 assertEquals(new Size(1600, 900), input.get(0)); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testHeight() { | ||||
|         input.setMinHeight(25); | ||||
|         input.setMaxHeight(35); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(1, input.size()); | ||||
|                 assertEquals(new Size(40, 30), input.get(0)); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testArea() { | ||||
|         input.setMinArea(30 * 30); | ||||
|         input.setMaxArea(40 * 40); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(2, input.size()); | ||||
|                 assertTrue(input.contains(new Size(40, 30))); | ||||
|                 assertTrue(input.contains(new Size(30, 40))); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testSmallest() { | ||||
|         input.setSmallest(true); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(sizes.size(), input.size()); | ||||
|                 Size first = input.get(0); | ||||
|                 assertEquals(30 * 40, first.getWidth() * first.getHeight()); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testBiggest() { | ||||
|         input.setBiggest(true); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(sizes.size(), input.size()); | ||||
|                 assertEquals(new Size(2000, 4000), input.get(0)); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testAspectRatio() { | ||||
|         input.setAspectRatio("16:9"); | ||||
|         doAssert(new Function<List<Size>, Void>() { | ||||
|             @Override | ||||
|             public Void apply(List<Size> input) { | ||||
|                 assertEquals(1, input.size()); | ||||
|                 assertEquals(new Size(1600, 900), input.get(0)); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("SameParameterValue") | ||||
|     private class MockTypedArray { | ||||
|         private TypedArray array = mock(TypedArray.class); | ||||
| 
 | ||||
|         private void setIntValue(@StyleableRes int index, int value) { | ||||
|             when(array.hasValue(index)).thenReturn(true); | ||||
|             when(array.getInteger(eq(index), anyInt())).thenReturn(value); | ||||
|         } | ||||
| 
 | ||||
|         private void setBooleanValue(@StyleableRes int index, boolean value) { | ||||
|             when(array.hasValue(index)).thenReturn(true); | ||||
|             when(array.getBoolean(eq(index), anyBoolean())).thenReturn(value); | ||||
|         } | ||||
| 
 | ||||
|         private void setStringValue(@StyleableRes int index, @NonNull String value) { | ||||
|             when(array.hasValue(index)).thenReturn(true); | ||||
|             when(array.getString(index)).thenReturn(value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMinWidth(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMinWidth, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMinWidth, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMaxWidth(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMaxWidth, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMaxWidth, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMinHeight(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMinHeight, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMinHeight, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMaxHeight(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMaxHeight, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMaxHeight, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMinArea(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMinArea, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMinArea, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setMaxArea(int value) { | ||||
|             setIntValue(R.styleable.CameraView_cameraPictureSizeMaxArea, value); | ||||
|             setIntValue(R.styleable.CameraView_cameraVideoSizeMaxArea, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setSmallest(boolean value) { | ||||
|             setBooleanValue(R.styleable.CameraView_cameraPictureSizeSmallest, value); | ||||
|             setBooleanValue(R.styleable.CameraView_cameraVideoSizeSmallest, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setBiggest(boolean value) { | ||||
|             setBooleanValue(R.styleable.CameraView_cameraPictureSizeBiggest, value); | ||||
|             setBooleanValue(R.styleable.CameraView_cameraVideoSizeBiggest, value); | ||||
|         } | ||||
| 
 | ||||
|         private void setAspectRatio(@NonNull String value) { | ||||
|             setStringValue(R.styleable.CameraView_cameraPictureSizeAspectRatio, value); | ||||
|             setStringValue(R.styleable.CameraView_cameraVideoSizeAspectRatio, value); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,41 @@ | ||||
| package com.otaliastudios.cameraview.internal.utils; | ||||
| 
 | ||||
| 
 | ||||
| import androidx.exifinterface.media.ExifInterface; | ||||
| 
 | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static junit.framework.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertFalse; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| 
 | ||||
| public class ExifHelperTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void testValues() { | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_NORMAL)); | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_FLIP_HORIZONTAL)); | ||||
|         assertEquals(180, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_ROTATE_180)); | ||||
|         assertEquals(180, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_FLIP_VERTICAL)); | ||||
|         assertEquals(90, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_ROTATE_90)); | ||||
|         assertEquals(90, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_TRANSPOSE)); | ||||
|         assertEquals(270, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_ROTATE_270)); | ||||
|         assertEquals(270, ExifHelper.readExifOrientation(ExifInterface.ORIENTATION_TRANSVERSE)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testUnknownValues() { | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(-15)); | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(-1)); | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(195)); | ||||
|         assertEquals(0, ExifHelper.readExifOrientation(Integer.MAX_VALUE)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue