New tests, add CameraController.STATE (#37)
* Add set/get parameters tests * CameraCallbacks tests * Nits * Nits 2 * Nits 3 * Nits 4 * CameraController integration tests * Fix some bugs * Add CameraController.STATE, fix CameraView.isStarted() * Fix old tests * Video and focus tests * Remove video test, fails on Travis * Add picture tests * Remove other video test * Add audio tests * new travis.yml * WorkerHandler changes * Better GridLinesLayoutTest * Try add logcat to travis build * Debug failing test * Add logs * Grant permissions, bump tests to N * Add wake locks * Add wake lock permission * Remove integration tests * Change view matcher * Refinementspull/43/head
parent
0a8e2f3de7
commit
cf3bfc1ed0
@ -0,0 +1,304 @@ |
||||
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, Audio audio) { |
||||
return true; |
||||
} |
||||
}; |
||||
camera.addCameraListener(listener); |
||||
callbacks = camera.mCameraCallbacks; |
||||
task = new Task<>(); |
||||
task.listen(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() { |
||||
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); |
||||
LOG.i("testProcessJpeg", output); |
||||
assertEquals(output[0], 1000); |
||||
assertEquals(output[1], 1000); |
||||
|
||||
// Without crop flag: expect original ratio.
|
||||
output = testProcessImage(true, false, viewDim, imageDim); |
||||
LOG.i("testProcessJpeg", output); |
||||
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); |
||||
LOG.i("testProcessYuv", output); |
||||
assertEquals(output[0], 1000); |
||||
assertEquals(output[1], 1000); |
||||
|
||||
// Without crop flag: expect original ratio.
|
||||
output = testProcessImage(false, false, viewDim, imageDim); |
||||
LOG.i("testProcessYuv", output); |
||||
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(3000); |
||||
assertNotNull("Image was processed", result); |
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); |
||||
return new int[]{ bitmap.getWidth(), bitmap.getHeight() }; |
||||
} |
||||
} |
@ -0,0 +1,507 @@ |
||||
package com.otaliastudios.cameraview; |
||||
|
||||
|
||||
import android.content.Context; |
||||
import android.graphics.Bitmap; |
||||
import android.graphics.PointF; |
||||
import android.support.test.filters.MediumTest; |
||||
import android.support.test.rule.ActivityTestRule; |
||||
import android.support.test.runner.AndroidJUnit4; |
||||
import android.view.ViewGroup; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.BeforeClass; |
||||
import org.junit.Ignore; |
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
|
||||
import java.io.File; |
||||
import java.util.concurrent.CountDownLatch; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import static org.mockito.Mockito.*; |
||||
import static org.junit.Assert.*; |
||||
|
||||
|
||||
/** |
||||
* These tests work great on real devices, and are the only way to test actual CameraController |
||||
* implementation - we really need to open the camera device. |
||||
* Unfortunately they fail unreliably on emulated devices, due to some bug with the |
||||
* emulated camera controller. Waiting for it to be fixed. |
||||
*/ |
||||
@RunWith(AndroidJUnit4.class) |
||||
@MediumTest |
||||
@Ignore |
||||
public class IntegrationTest extends BaseTest { |
||||
|
||||
@Rule |
||||
public ActivityTestRule<TestActivity> rule = new ActivityTestRule<>(TestActivity.class); |
||||
|
||||
private CameraView camera; |
||||
private Camera1 controller; |
||||
private CameraListener listener; |
||||
|
||||
@BeforeClass |
||||
public static void grant() { |
||||
grantPermissions(); |
||||
} |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
WorkerHandler.destroy(); |
||||
ui(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
camera = new CameraView(rule.getActivity()) { |
||||
@Override |
||||
protected CameraController instantiateCameraController(CameraCallbacks callbacks, Preview preview) { |
||||
controller = new Camera1(callbacks, preview); |
||||
return controller; |
||||
} |
||||
}; |
||||
|
||||
listener = mock(CameraListener.class); |
||||
camera.addCameraListener(listener); |
||||
rule.getActivity().inflate(camera); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() throws Exception { |
||||
camera.stopCapturingVideo(); |
||||
camera.destroy(); |
||||
WorkerHandler.destroy(); |
||||
} |
||||
|
||||
private CameraOptions waitForOpen(boolean expectSuccess) { |
||||
final Task<CameraOptions> open = new Task<>(); |
||||
open.listen(); |
||||
doEndTask(open, 0).when(listener).onCameraOpened(any(CameraOptions.class)); |
||||
CameraOptions result = open.await(4000); |
||||
if (expectSuccess) { |
||||
assertNotNull("Can open", result); |
||||
} else { |
||||
assertNull("Should not open", result); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private Boolean waitForClose(boolean expectSuccess) { |
||||
final Task<Boolean> close = new Task<>(); |
||||
close.listen(); |
||||
doEndTask(close, true).when(listener).onCameraClosed(); |
||||
Boolean result = close.await(4000); |
||||
if (expectSuccess) { |
||||
assertNotNull("Can close", result); |
||||
} else { |
||||
assertNull("Should not close", result); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private Boolean waitForVideo(boolean expectSuccess) { |
||||
final Task<Boolean> video = new Task<>(); |
||||
video.listen(); |
||||
doEndTask(video, true).when(listener).onVideoTaken(any(File.class)); |
||||
Boolean result = video.await(2000); |
||||
if (expectSuccess) { |
||||
assertNotNull("Can take video", result); |
||||
} else { |
||||
assertNull("Should not take video", result); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private byte[] waitForPicture(boolean expectSuccess) { |
||||
final Task<byte[]> pic = new Task<>(); |
||||
pic.listen(); |
||||
doEndTask(pic, 0).when(listener).onPictureTaken(any(byte[].class)); |
||||
byte[] result = pic.await(5000); |
||||
if (expectSuccess) { |
||||
assertNotNull("Can take picture", result); |
||||
} else { |
||||
assertNull("Should not take picture", result); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
//region test open/close
|
||||
|
||||
//-@Test
|
||||
public void testOpenClose() throws Exception { |
||||
// Starting and stopping are hard to get since they happen on another thread.
|
||||
assertEquals(controller.getState(), CameraController.STATE_STOPPED); |
||||
|
||||
camera.start(); |
||||
waitForOpen(true); |
||||
assertEquals(controller.getState(), CameraController.STATE_STARTED); |
||||
|
||||
camera.stop(); |
||||
waitForClose(true); |
||||
assertEquals(controller.getState(), CameraController.STATE_STOPPED); |
||||
} |
||||
|
||||
//-@Test
|
||||
public void testOpenTwice() { |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.start(); |
||||
waitForOpen(false); |
||||
} |
||||
|
||||
//-@Test
|
||||
public void testCloseTwice() { |
||||
camera.stop(); |
||||
waitForClose(false); |
||||
} |
||||
|
||||
@Test |
||||
// This works great on the device but crashes often on the emulator.
|
||||
// There must be something wrong with the emulated camera...
|
||||
// Like stopPreview() and release() are not really sync calls?
|
||||
public void testConcurrentCalls() throws Exception { |
||||
final CountDownLatch latch = new CountDownLatch(4); |
||||
doCountDown(latch).when(listener).onCameraOpened(any(CameraOptions.class)); |
||||
doCountDown(latch).when(listener).onCameraClosed(); |
||||
|
||||
camera.start(); |
||||
camera.stop(); |
||||
camera.start(); |
||||
camera.stop(); |
||||
|
||||
boolean did = latch.await(10, TimeUnit.SECONDS); |
||||
assertTrue("Handles concurrent calls to start & stop, " + latch.getCount(), did); |
||||
} |
||||
|
||||
@Test |
||||
public void testStartInitializesOptions() { |
||||
assertNull(camera.getCameraOptions()); |
||||
assertNull(camera.getExtraProperties()); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
assertNotNull(camera.getCameraOptions()); |
||||
assertNotNull(camera.getExtraProperties()); |
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region test Facing/SessionType
|
||||
// Test things that should reset the camera.
|
||||
|
||||
@Test |
||||
public void testSetFacing() throws Exception { |
||||
camera.start(); |
||||
CameraOptions o = waitForOpen(true); |
||||
int size = o.getSupportedFacing().size(); |
||||
if (size > 1) { |
||||
// set facing should call stop and start again.
|
||||
final CountDownLatch latch = new CountDownLatch(2); |
||||
doCountDown(latch).when(listener).onCameraOpened(any(CameraOptions.class)); |
||||
doCountDown(latch).when(listener).onCameraClosed(); |
||||
|
||||
camera.toggleFacing(); |
||||
|
||||
boolean did = latch.await(2, TimeUnit.SECONDS); |
||||
assertTrue("Handles setFacing while active", did); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testSetSessionType() throws Exception { |
||||
camera.setSessionType(SessionType.PICTURE); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
|
||||
// set session type should call stop and start again.
|
||||
final CountDownLatch latch = new CountDownLatch(2); |
||||
doCountDown(latch).when(listener).onCameraOpened(any(CameraOptions.class)); |
||||
doCountDown(latch).when(listener).onCameraClosed(); |
||||
|
||||
camera.setSessionType(SessionType.VIDEO); |
||||
|
||||
boolean did = latch.await(2, TimeUnit.SECONDS); |
||||
assertTrue("Handles setSessionType while active", did); |
||||
assertEquals(camera.getSessionType(), SessionType.VIDEO); |
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region test Set Parameters
|
||||
// When camera is open, parameters will be set only if supported.
|
||||
|
||||
@Test |
||||
public void testSetZoom() { |
||||
camera.start(); |
||||
CameraOptions options = waitForOpen(true); |
||||
boolean can = options.isZoomSupported(); |
||||
float oldValue = camera.getZoom(); |
||||
float newValue = 0.65f; |
||||
camera.setZoom(newValue); |
||||
assertEquals(can ? newValue : oldValue, camera.getZoom(), 0f); |
||||
} |
||||
|
||||
@Test |
||||
public void testSetExposureCorrection() { |
||||
camera.start(); |
||||
CameraOptions options = waitForOpen(true); |
||||
boolean can = options.isExposureCorrectionSupported(); |
||||
float oldValue = camera.getExposureCorrection(); |
||||
float newValue = options.getExposureCorrectionMaxValue(); |
||||
camera.setExposureCorrection(newValue); |
||||
assertEquals(can ? newValue : oldValue, camera.getExposureCorrection(), 0f); |
||||
} |
||||
|
||||
@Test |
||||
public void testSetFlash() { |
||||
camera.start(); |
||||
CameraOptions options = waitForOpen(true); |
||||
Flash[] values = Flash.values(); |
||||
Flash oldValue = camera.getFlash(); |
||||
for (Flash value : values) { |
||||
camera.setFlash(value); |
||||
if (options.supports(value)) { |
||||
assertEquals(camera.getFlash(), value); |
||||
oldValue = value; |
||||
} else { |
||||
assertEquals(camera.getFlash(), oldValue); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testSetWhiteBalance() { |
||||
camera.start(); |
||||
CameraOptions options = waitForOpen(true); |
||||
WhiteBalance[] values = WhiteBalance.values(); |
||||
WhiteBalance oldValue = camera.getWhiteBalance(); |
||||
for (WhiteBalance value : values) { |
||||
camera.setWhiteBalance(value); |
||||
if (options.supports(value)) { |
||||
assertEquals(camera.getWhiteBalance(), value); |
||||
oldValue = value; |
||||
} else { |
||||
assertEquals(camera.getWhiteBalance(), oldValue); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testSetHdr() { |
||||
camera.start(); |
||||
CameraOptions options = waitForOpen(true); |
||||
Hdr[] values = Hdr.values(); |
||||
Hdr oldValue = camera.getHdr(); |
||||
for (Hdr value : values) { |
||||
camera.setHdr(value); |
||||
if (options.supports(value)) { |
||||
assertEquals(camera.getHdr(), value); |
||||
oldValue = value; |
||||
} else { |
||||
assertEquals(camera.getHdr(), oldValue); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testSetAudio() { |
||||
// TODO: when permissions are managed, check that Audio.ON triggers the audio permission
|
||||
camera.start(); |
||||
waitForOpen(true); |
||||
Audio[] values = Audio.values(); |
||||
for (Audio value : values) { |
||||
camera.setAudio(value); |
||||
assertEquals(camera.getAudio(), value); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testSetLocation() { |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.setLocation(10d, 2d); |
||||
assertNotNull(camera.getLocation()); |
||||
assertEquals(camera.getLocation().getLatitude(), 10d, 0d); |
||||
assertEquals(camera.getLocation().getLongitude(), 2d, 0d); |
||||
// This also ensures there are no crashes when attaching it to camera parameters.
|
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region testSetVideoQuality
|
||||
// This can be tricky because can trigger layout changes.
|
||||
|
||||
// TODO: @Test(expected = IllegalStateException.class)
|
||||
// Can't run on Travis, MediaRecorder not supported.
|
||||
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
|
||||
public void testSetVideoQuality_whileRecording() { |
||||
camera.setSessionType(SessionType.VIDEO); |
||||
camera.setVideoQuality(VideoQuality.HIGHEST); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.startCapturingVideo(null); |
||||
camera.setVideoQuality(VideoQuality.LOWEST); |
||||
} |
||||
|
||||
@Test |
||||
public void testSetVideoQuality_whileInPictureSessionType() { |
||||
camera.setSessionType(SessionType.PICTURE); |
||||
camera.setVideoQuality(VideoQuality.HIGHEST); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.setVideoQuality(VideoQuality.LOWEST); |
||||
assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST); |
||||
} |
||||
|
||||
@Test |
||||
public void testSetVideoQuality_whileNotStarted() { |
||||
camera.setVideoQuality(VideoQuality.HIGHEST); |
||||
assertEquals(camera.getVideoQuality(), VideoQuality.HIGHEST); |
||||
camera.setVideoQuality(VideoQuality.LOWEST); |
||||
assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST); |
||||
} |
||||
|
||||
@Test |
||||
public void testSetVideoQuality_shouldRecompute() { |
||||
// If video quality changes bring to a new capture size,
|
||||
// this might bring to a new aspect ratio,
|
||||
// which might bring to a new preview size. No idea how to test.
|
||||
assertTrue(true); |
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region test startVideo
|
||||
|
||||
// TODO: @Test(expected = IllegalStateException.class)
|
||||
// Fails on Travis. Some emulators can't deal with MediaRecorder
|
||||
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
|
||||
// as documented. This works locally though.
|
||||
public void testStartVideo_whileInPictureMode() { |
||||
camera.setSessionType(SessionType.PICTURE); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.startCapturingVideo(null); |
||||
} |
||||
|
||||
// TODO: @Test
|
||||
// Fails on Travis. Some emulators can't deal with MediaRecorder,
|
||||
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
|
||||
// as documented. This works locally though.
|
||||
public void testStartEndVideo() { |
||||
camera.setSessionType(SessionType.VIDEO); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.startCapturingVideo(null, 1000); |
||||
waitForVideo(true); // waits 2000
|
||||
} |
||||
|
||||
@Test |
||||
public void testEndVideo_withoutStarting() { |
||||
camera.setSessionType(SessionType.VIDEO); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
camera.stopCapturingVideo(); |
||||
waitForVideo(false); |
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region startAutoFocus
|
||||
// TODO: won't test onStopAutoFocus because that is not guaranteed to be called
|
||||
|
||||
@Test |
||||
public void testStartAutoFocus() { |
||||
camera.start(); |
||||
CameraOptions o = waitForOpen(true); |
||||
camera.startAutoFocus(1, 1); |
||||
if (o.isAutoFocusSupported()) { |
||||
verify(listener, times(1)).onFocusStart(new PointF(1, 1)); |
||||
} else { |
||||
verify(listener, never()).onFocusStart(any(PointF.class)); |
||||
} |
||||
} |
||||
|
||||
//endregion
|
||||
|
||||
//region capture
|
||||
|
||||
@Test |
||||
public void testCapturePicture_beforeStarted() { |
||||
camera.capturePicture(); |
||||
waitForPicture(false); |
||||
} |
||||
|
||||
@Test |
||||
public void testCapturePicture_concurrentCalls() throws Exception { |
||||
// Second take should fail.
|
||||
camera.start(); |
||||
waitForOpen(true); |
||||
|
||||
CountDownLatch latch = new CountDownLatch(2); |
||||
doCountDown(latch).when(listener).onPictureTaken(any(byte[].class)); |
||||
|
||||
camera.capturePicture(); |
||||
camera.capturePicture(); |
||||
boolean did = latch.await(4, TimeUnit.SECONDS); |
||||
assertFalse(did); |
||||
assertEquals(latch.getCount(), 1); |
||||
} |
||||
|
||||
@Test |
||||
public void testCapturePicture_size() throws Exception { |
||||
camera.setCropOutput(false); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
|
||||
Size size = camera.getCaptureSize(); |
||||
camera.capturePicture(); |
||||
byte[] jpeg = waitForPicture(true); |
||||
Bitmap b = CameraUtils.decodeBitmap(jpeg); |
||||
// Result can actually have swapped dimensions
|
||||
// Which one, depends on factors including device physical orientation
|
||||
assertTrue(b.getWidth() == size.getHeight() || b.getWidth() == size.getWidth()); |
||||
assertTrue(b.getHeight() == size.getHeight() || b.getHeight() == size.getWidth()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCaptureSnapshot_beforeStarted() { |
||||
camera.captureSnapshot(); |
||||
waitForPicture(false); |
||||
} |
||||
|
||||
@Test |
||||
public void testCaptureSnapshot_concurrentCalls() throws Exception { |
||||
// Second take should fail.
|
||||
camera.start(); |
||||
waitForOpen(true); |
||||
|
||||
CountDownLatch latch = new CountDownLatch(2); |
||||
doCountDown(latch).when(listener).onPictureTaken(any(byte[].class)); |
||||
|
||||
camera.captureSnapshot(); |
||||
camera.captureSnapshot(); |
||||
boolean did = latch.await(4, TimeUnit.SECONDS); |
||||
assertFalse(did); |
||||
assertEquals(latch.getCount(), 1); |
||||
} |
||||
|
||||
@Test |
||||
public void testCaptureSnapshot_size() throws Exception { |
||||
camera.setCropOutput(false); |
||||
camera.start(); |
||||
waitForOpen(true); |
||||
|
||||
Size size = camera.getPreviewSize(); |
||||
camera.captureSnapshot(); |
||||
byte[] jpeg = waitForPicture(true); |
||||
Bitmap b = CameraUtils.decodeBitmap(jpeg); |
||||
// Result can actually have swapped dimensions
|
||||
// Which one, depends on factors including device physical orientation
|
||||
assertTrue(b.getWidth() == size.getHeight() || b.getWidth() == size.getWidth()); |
||||
assertTrue(b.getHeight() == size.getHeight() || b.getHeight() == size.getWidth()); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue