parent
64a02a9d33
commit
bd6d8cdaa5
@ -0,0 +1,301 @@ |
|||||||
|
package com.otaliastudios.cameraview; |
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.graphics.Bitmap; |
||||||
|
import android.graphics.BitmapFactory; |
||||||
|
import android.graphics.Color; |
||||||
|
import android.graphics.PointF; |
||||||
|
import android.graphics.Rect; |
||||||
|
import android.graphics.YuvImage; |
||||||
|
import android.support.test.filters.MediumTest; |
||||||
|
import android.support.test.runner.AndroidJUnit4; |
||||||
|
import android.view.ViewGroup; |
||||||
|
|
||||||
|
import org.junit.After; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.mockito.invocation.InvocationOnMock; |
||||||
|
import org.mockito.stubbing.Answer; |
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
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; |
||||||
|
import static org.mockito.Matchers.any; |
||||||
|
import static org.mockito.Matchers.anyFloat; |
||||||
|
import static org.mockito.Matchers.anyInt; |
||||||
|
import static org.mockito.Mockito.doAnswer; |
||||||
|
import static org.mockito.Mockito.mock; |
||||||
|
import static org.mockito.Mockito.never; |
||||||
|
import static org.mockito.Mockito.times; |
||||||
|
import static org.mockito.Mockito.verify; |
||||||
|
import static org.mockito.Mockito.when; |
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class) |
||||||
|
@MediumTest |
||||||
|
public class CameraCallbacksTest extends BaseTest { |
||||||
|
|
||||||
|
private CameraView camera; |
||||||
|
private CameraView.CameraCallbacks callbacks; |
||||||
|
private CameraListener listener; |
||||||
|
private MockCameraController mockController; |
||||||
|
private MockPreview mockPreview; |
||||||
|
private Task<Boolean> task; |
||||||
|
|
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
ui(new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
Context context = context(); |
||||||
|
listener = mock(CameraListener.class); |
||||||
|
camera = new CameraView(context) { |
||||||
|
@Override |
||||||
|
protected CameraController instantiateCameraController(CameraCallbacks callbacks, Preview preview) { |
||||||
|
mockController = new MockCameraController(callbacks, preview); |
||||||
|
return mockController; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Preview instantiatePreview(Context context, ViewGroup container) { |
||||||
|
mockPreview = new MockPreview(context, container); |
||||||
|
return mockPreview; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean checkPermissions(SessionType sessionType) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
camera.addCameraListener(listener); |
||||||
|
callbacks = camera.mCameraCallbacks; |
||||||
|
task = new Task<>(); |
||||||
|
task.listen(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@After |
||||||
|
public void tearDown() { |
||||||
|
camera.removeCameraListener(listener); |
||||||
|
camera = null; |
||||||
|
mockController = null; |
||||||
|
mockPreview = null; |
||||||
|
callbacks = null; |
||||||
|
listener = null; |
||||||
|
} |
||||||
|
|
||||||
|
// Completes our task.
|
||||||
|
private Answer completeTask() { |
||||||
|
return new Answer() { |
||||||
|
@Override |
||||||
|
public Object answer(InvocationOnMock invocation) throws Throwable { |
||||||
|
task.end(true); |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDontDispatchIfRemoved() { |
||||||
|
camera.removeCameraListener(listener); |
||||||
|
doAnswer(completeTask()).when(listener).onCameraOpened(null); |
||||||
|
callbacks.dispatchOnCameraOpened(null); |
||||||
|
|
||||||
|
assertNull(task.await(200)); |
||||||
|
verify(listener, never()).onCameraOpened(null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDontDispatchIfCleared() { |
||||||
|
camera.clearCameraListeners(); |
||||||
|
doAnswer(completeTask()).when(listener).onCameraOpened(null); |
||||||
|
callbacks.dispatchOnCameraOpened(null); |
||||||
|
|
||||||
|
assertNull(task.await(200)); |
||||||
|
verify(listener, never()).onCameraOpened(null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnCameraOpened() { |
||||||
|
doAnswer(completeTask()).when(listener).onCameraOpened(null); |
||||||
|
callbacks.dispatchOnCameraOpened(null); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onCameraOpened(null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnCameraClosed() { |
||||||
|
doAnswer(completeTask()).when(listener).onCameraClosed(); |
||||||
|
callbacks.dispatchOnCameraClosed(); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onCameraClosed(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnVideoTaken() { |
||||||
|
doAnswer(completeTask()).when(listener).onVideoTaken(null); |
||||||
|
callbacks.dispatchOnVideoTaken(null); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onVideoTaken(null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnZoomChanged() { |
||||||
|
doAnswer(completeTask()).when(listener).onZoomChanged(anyFloat(), any(float[].class), any(PointF[].class)); |
||||||
|
callbacks.dispatchOnZoomChanged(0f, null); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onZoomChanged(anyFloat(), any(float[].class), any(PointF[].class)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnExposureCorrectionChanged() { |
||||||
|
doAnswer(completeTask()).when(listener).onExposureCorrectionChanged(0f, null, null); |
||||||
|
callbacks.dispatchOnExposureCorrectionChanged(0f, null, null); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onExposureCorrectionChanged(0f, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnFocusStart() { |
||||||
|
// Enable tap gesture.
|
||||||
|
// Can't mock package protected. camera.mTapGestureLayout = mock(TapGestureLayout.class);
|
||||||
|
camera.mapGesture(Gesture.TAP, GestureAction.FOCUS_WITH_MARKER); |
||||||
|
|
||||||
|
PointF point = new PointF(); |
||||||
|
doAnswer(completeTask()).when(listener).onFocusStart(point); |
||||||
|
callbacks.dispatchOnFocusStart(Gesture.TAP, point); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onFocusStart(point); |
||||||
|
// Can't mock package protected. verify(camera.mTapGestureLayout, times(1)).onFocusStart(point);
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDispatchOnFocusEnd() { |
||||||
|
// Enable tap gesture.
|
||||||
|
// Can't mock package protected. camera.mTapGestureLayout = mock(TapGestureLayout.class);
|
||||||
|
camera.mapGesture(Gesture.TAP, GestureAction.FOCUS_WITH_MARKER); |
||||||
|
|
||||||
|
PointF point = new PointF(); |
||||||
|
boolean success = true; |
||||||
|
doAnswer(completeTask()).when(listener).onFocusEnd(success, point); |
||||||
|
callbacks.dispatchOnFocusEnd(Gesture.TAP, success, point); |
||||||
|
|
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onFocusEnd(success, point); |
||||||
|
// Can't mock package protected. verify(camera.mTapGestureLayout, times(1)).onFocusEnd(success);
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testOrientationCallbacks_deviceOnly() { |
||||||
|
doAnswer(completeTask()).when(listener).onOrientationChanged(anyInt()); |
||||||
|
|
||||||
|
// Assert not called. Both methods must be called.
|
||||||
|
callbacks.onDeviceOrientationChanged(0); |
||||||
|
assertNull(task.await(200)); |
||||||
|
verify(listener, never()).onOrientationChanged(anyInt()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testOrientationCallbacks_displayOnly() { |
||||||
|
doAnswer(completeTask()).when(listener).onOrientationChanged(anyInt()); |
||||||
|
|
||||||
|
// Assert not called. Both methods must be called.
|
||||||
|
callbacks.onDisplayOffsetChanged(0); |
||||||
|
assertNull(task.await(200)); |
||||||
|
verify(listener, never()).onOrientationChanged(anyInt()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testOrientationCallbacks_both() { |
||||||
|
doAnswer(completeTask()).when(listener).onOrientationChanged(anyInt()); |
||||||
|
|
||||||
|
// Assert called.
|
||||||
|
callbacks.onDisplayOffsetChanged(0); |
||||||
|
callbacks.onDeviceOrientationChanged(90); |
||||||
|
assertNotNull(task.await(200)); |
||||||
|
verify(listener, times(1)).onOrientationChanged(anyInt()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Test |
||||||
|
public void testProcessJpeg() { |
||||||
|
int[] viewDim = new int[]{ 200, 200 }; |
||||||
|
int[] imageDim = new int[]{ 1000, 1600 }; |
||||||
|
|
||||||
|
// With crop flag: expect a 1:1 ratio.
|
||||||
|
int[] output = testProcessImage(true, true, viewDim, imageDim); |
||||||
|
assertEquals(output[0], 1000); |
||||||
|
assertEquals(output[1], 1000); |
||||||
|
|
||||||
|
// Without crop flag: expect original ratio.
|
||||||
|
output = testProcessImage(true, false, viewDim, imageDim); |
||||||
|
assertEquals(output[0], imageDim[0]); |
||||||
|
assertEquals(output[1], imageDim[1]); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testProcessYuv() { |
||||||
|
int[] viewDim = new int[]{ 200, 200 }; |
||||||
|
int[] imageDim = new int[]{ 1000, 1600 }; |
||||||
|
|
||||||
|
// With crop flag: expect a 1:1 ratio.
|
||||||
|
int[] output = testProcessImage(false, true, viewDim, imageDim); |
||||||
|
assertEquals(output[0], 1000); |
||||||
|
assertEquals(output[1], 1000); |
||||||
|
|
||||||
|
// Without crop flag: expect original ratio.
|
||||||
|
output = testProcessImage(false, false, viewDim, imageDim); |
||||||
|
assertEquals(output[0], imageDim[0]); |
||||||
|
assertEquals(output[1], imageDim[1]); |
||||||
|
} |
||||||
|
|
||||||
|
private int[] testProcessImage(boolean jpeg, boolean crop, int[] viewDim, int[] imageDim) { |
||||||
|
// End our task when onPictureTaken is called. Take note of the result.
|
||||||
|
final Task<byte[]> jpegTask = new Task<>(); |
||||||
|
jpegTask.listen(); |
||||||
|
doAnswer(new Answer() { |
||||||
|
@Override |
||||||
|
public Object answer(InvocationOnMock invocation) throws Throwable { |
||||||
|
jpegTask.end((byte[]) invocation.getArguments()[0]); |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).when(listener).onPictureTaken(any(byte[].class)); |
||||||
|
|
||||||
|
// Fake our own dimensions.
|
||||||
|
camera.setTop(0); |
||||||
|
camera.setBottom(viewDim[1]); |
||||||
|
camera.setLeft(0); |
||||||
|
camera.setRight(viewDim[0]); |
||||||
|
|
||||||
|
// Ensure the image will (not) be cropped.
|
||||||
|
camera.setCropOutput(crop); |
||||||
|
mockPreview.setIsCropping(crop); |
||||||
|
|
||||||
|
// Create fake JPEG array and trigger the process.
|
||||||
|
if (jpeg) { |
||||||
|
callbacks.processImage(mockJpeg(imageDim[0], imageDim[1]), true, false); |
||||||
|
} else { |
||||||
|
callbacks.processSnapshot(mockYuv(imageDim[0], imageDim[1]), true, false); |
||||||
|
} |
||||||
|
|
||||||
|
// Wait for result and get out dimensions.
|
||||||
|
byte[] result = jpegTask.await(800); |
||||||
|
assertNotNull(result); |
||||||
|
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); |
||||||
|
return new int[]{ bitmap.getWidth(), bitmap.getHeight() }; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue