Add integration tests

pull/502/head
Mattia Iavarone 6 years ago
parent 3e6bfbdea0
commit d8c674c4a9
  1. 70
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java
  2. 201
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/overlay/OverlayLayoutTest.java
  3. 15
      cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java

@ -2,6 +2,7 @@ package com.otaliastudios.cameraview.engine;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PointF; import android.graphics.PointF;
import android.hardware.Camera; import android.hardware.Camera;
import android.os.Build; import android.os.Build;
@ -25,6 +26,7 @@ import com.otaliastudios.cameraview.frame.Frame;
import com.otaliastudios.cameraview.frame.FrameProcessor; import com.otaliastudios.cameraview.frame.FrameProcessor;
import com.otaliastudios.cameraview.internal.utils.Op; import com.otaliastudios.cameraview.internal.utils.Op;
import com.otaliastudios.cameraview.internal.utils.WorkerHandler; import com.otaliastudios.cameraview.internal.utils.WorkerHandler;
import com.otaliastudios.cameraview.overlay.Overlay;
import com.otaliastudios.cameraview.size.Size; import com.otaliastudios.cameraview.size.Size;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -48,10 +50,15 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public abstract class CameraIntegrationTest extends BaseTest { public abstract class CameraIntegrationTest extends BaseTest {
@ -502,6 +509,14 @@ public abstract class CameraIntegrationTest extends BaseTest {
waitForVideoResult(true); waitForVideoResult(true);
} }
@Test
public void testStartEndVideoSnapshot() {
// TODO should check api
waitForOpen(true);
camera.takeVideoSnapshot(new File(context().getFilesDir(), "video.mp4"), 4000);
waitForVideoEnd(true);
}
@Test @Test
public void testEndVideo_withoutStarting() { public void testEndVideo_withoutStarting() {
camera.setMode(Mode.VIDEO); camera.setMode(Mode.VIDEO);
@ -510,6 +525,13 @@ public abstract class CameraIntegrationTest extends BaseTest {
waitForVideoResult(false); waitForVideoResult(false);
} }
@Test
public void testEndVideoSnapshot_withoutStarting() {
waitForOpen(true);
camera.stopVideo();
waitForVideoEnd(false);
}
@Test @Test
public void testEndVideo_withMaxSize() { public void testEndVideo_withMaxSize() {
camera.setMode(Mode.VIDEO); camera.setMode(Mode.VIDEO);
@ -519,6 +541,15 @@ public abstract class CameraIntegrationTest extends BaseTest {
waitForVideoResult(true); waitForVideoResult(true);
} }
@Test
public void testEndVideoSnapshot_withMaxSize() {
// TODO
// camera.setVideoMaxSize(3000*1000);
// waitForOpen(true);
// waitForVideoStart();
// waitForVideoEnd(true);
}
@Test @Test
public void testEndVideo_withMaxDuration() { public void testEndVideo_withMaxDuration() {
camera.setMode(Mode.VIDEO); camera.setMode(Mode.VIDEO);
@ -528,6 +559,15 @@ public abstract class CameraIntegrationTest extends BaseTest {
waitForVideoResult(true); waitForVideoResult(true);
} }
@Test
public void testEndVideoSnapshot_withMaxDuration() {
// TODO
// camera.setVideoMaxDuration(4000);
// waitForOpen(true);
// waitForVideoStart();
// waitForVideoEnd(true);
}
//endregion //endregion
//region startAutoFocus //region startAutoFocus
@ -601,6 +641,7 @@ public abstract class CameraIntegrationTest extends BaseTest {
camera.takePicture(); camera.takePicture();
PictureResult result = waitForPictureResult(true); PictureResult result = waitForPictureResult(true);
Bitmap bitmap = CameraUtils.decodeBitmap(result.getData(), Integer.MAX_VALUE, Integer.MAX_VALUE); Bitmap bitmap = CameraUtils.decodeBitmap(result.getData(), Integer.MAX_VALUE, Integer.MAX_VALUE);
assertNotNull(bitmap);
assertEquals(result.getSize(), size); assertEquals(result.getSize(), size);
assertEquals(bitmap.getWidth(), size.getWidth()); assertEquals(bitmap.getWidth(), size.getWidth());
assertEquals(bitmap.getHeight(), size.getHeight()); assertEquals(bitmap.getHeight(), size.getHeight());
@ -735,4 +776,33 @@ public abstract class CameraIntegrationTest extends BaseTest {
} }
//endregion //endregion
//region Overlays
@Test
public void testOverlay_forPictureSnapshot() {
Overlay overlay = mock(Overlay.class);
when(overlay.drawsOn(any(Overlay.Target.class))).thenReturn(true);
controller.setOverlay(overlay);
waitForOpen(true);
camera.takePictureSnapshot();
waitForPicture(true);
verify(overlay, atLeastOnce()).drawsOn(Overlay.Target.PICTURE_SNAPSHOT);
verify(overlay, times(1)).drawOn(eq(Overlay.Target.PICTURE_SNAPSHOT), any(Canvas.class));
}
@Test
public void testOverlay_forVideoSnapshot() {
Overlay overlay = mock(Overlay.class);
when(overlay.drawsOn(any(Overlay.Target.class))).thenReturn(true);
controller.setOverlay(overlay);
waitForOpen(true);
camera.takeVideoSnapshot(new File(context().getFilesDir(), "video.mp4"), 4000);
waitForVideoStart();
waitForVideoEnd(true);
verify(overlay, atLeastOnce()).drawsOn(Overlay.Target.VIDEO_SNAPSHOT);
verify(overlay, atLeastOnce()).drawOn(eq(Overlay.Target.VIDEO_SNAPSHOT), any(Canvas.class));
}
//endregion
} }

@ -0,0 +1,201 @@
package com.otaliastudios.cameraview.overlay;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.test.annotation.UiThreadTest;
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 org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.w3c.dom.Attr;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class OverlayLayoutTest extends BaseTest {
private OverlayLayout overlayLayout;
@Before
public void setUp() {
overlayLayout = spy(new OverlayLayout(context()));
}
@After
public void tearDown() {
overlayLayout = null;
}
@Test
public void testIsOverlay_LayoutParams() {
ViewGroup.LayoutParams params;
params = new ViewGroup.LayoutParams(10, 10);
assertFalse(overlayLayout.isOverlay(params));
params = new OverlayLayout.LayoutParams(10, 10, Gravity.CENTER);
assertTrue(overlayLayout.isOverlay(params));
// Remove the isOverlay flag.
((OverlayLayout.LayoutParams) params).isOverlay = false;
assertFalse(overlayLayout.isOverlay(params));
}
@Test
public void testIsOverlay_attributeSet() throws Exception {
int layout1 = com.otaliastudios.cameraview.test.R.layout.overlay;
int layout2 = com.otaliastudios.cameraview.test.R.layout.not_overlay;
AttributeSet set1 = getAttributeSet(layout1);
assertTrue(overlayLayout.isOverlay(set1));
AttributeSet set2 = getAttributeSet(layout2);
assertFalse(overlayLayout.isOverlay(set2));
}
@NonNull
private AttributeSet getAttributeSet(int layout) throws Exception {
// Get the attribute set in the correct state: use a parser and move to START_TAG
XmlResourceParser parser = context().getResources().getLayout(layout);
//noinspection StatementWithEmptyBody
while (parser.next() != XmlResourceParser.START_TAG) {}
return Xml.asAttributeSet(parser);
}
@Test
public void testLayoutParams_drawsOn() {
OverlayLayout.LayoutParams params = new OverlayLayout.LayoutParams(10, 10, Gravity.CENTER);
assertFalse(params.drawsOn(Overlay.Target.PREVIEW));
assertFalse(params.drawsOn(Overlay.Target.PICTURE_SNAPSHOT));
assertFalse(params.drawsOn(Overlay.Target.VIDEO_SNAPSHOT));
params.drawOnPreview = true;
assertTrue(params.drawsOn(Overlay.Target.PREVIEW));
params.drawOnPictureSnapshot = true;
assertTrue(params.drawsOn(Overlay.Target.PICTURE_SNAPSHOT));
params.drawOnVideoSnapshot = true;
assertTrue(params.drawsOn(Overlay.Target.VIDEO_SNAPSHOT));
}
@Test
public void testLayoutParams_toString() {
OverlayLayout.LayoutParams params = new OverlayLayout.LayoutParams(10, 10, Gravity.CENTER);
String string = params.toString();
assertTrue(string.contains("drawOnPreview"));
assertTrue(string.contains("drawOnPictureSnapshot"));
assertTrue(string.contains("drawOnVideoSnapshot"));
}
@Test
public void testDrawChild() {
Canvas canvas = new Canvas();
OverlayLayout.LayoutParams params = new OverlayLayout.LayoutParams(10, 10, Gravity.CENTER);
View child = new View(context());
child.setLayoutParams(params);
when(overlayLayout.doDrawChild(canvas, child, 0)).thenReturn(true);
overlayLayout.currentTarget = Overlay.Target.PREVIEW;
assertFalse(overlayLayout.drawChild(canvas, child, 0));
params.drawOnPreview = true;
assertTrue(overlayLayout.drawChild(canvas, child, 0));
overlayLayout.currentTarget = Overlay.Target.PICTURE_SNAPSHOT;
assertFalse(overlayLayout.drawChild(canvas, child, 0));
params.drawOnPictureSnapshot = true;
assertTrue(overlayLayout.drawChild(canvas, child, 0));
overlayLayout.currentTarget = Overlay.Target.VIDEO_SNAPSHOT;
assertFalse(overlayLayout.drawChild(canvas, child, 0));
params.drawOnVideoSnapshot = true;
assertTrue(overlayLayout.drawChild(canvas, child, 0));
}
@UiThreadTest
@Test
public void testDraw() {
Canvas canvas = new Canvas();
when(overlayLayout.drawsOn(Overlay.Target.PREVIEW)).thenReturn(false);
overlayLayout.draw(canvas);
verify(overlayLayout, never()).drawOn(Overlay.Target.PREVIEW, canvas);
when(overlayLayout.drawsOn(Overlay.Target.PREVIEW)).thenReturn(true);
overlayLayout.draw(canvas);
verify(overlayLayout, times(1)).drawOn(Overlay.Target.PREVIEW, canvas);
}
@UiThreadTest
@Test
public void testDrawOn() {
Canvas canvas = spy(new Canvas());
View child = new View(context());
OverlayLayout.LayoutParams params = new OverlayLayout.LayoutParams(10, 10, Gravity.CENTER);
params.drawOnPreview = true;
params.drawOnPictureSnapshot = true;
params.drawOnVideoSnapshot = true;
overlayLayout.addView(child, params);
overlayLayout.drawOn(Overlay.Target.PREVIEW, canvas);
verify(canvas, never()).scale(anyFloat(), anyFloat());
verify(overlayLayout, times(1)).doDrawChild(eq(canvas), eq(child), anyLong());
reset(canvas);
reset(overlayLayout);
overlayLayout.drawOn(Overlay.Target.PICTURE_SNAPSHOT, canvas);
verify(canvas, times(1)).scale(anyFloat(), anyFloat());
verify(overlayLayout, times(1)).doDrawChild(eq(canvas), eq(child), anyLong());
reset(canvas);
reset(overlayLayout);
overlayLayout.drawOn(Overlay.Target.VIDEO_SNAPSHOT, canvas);
verify(canvas, times(1)).scale(anyFloat(), anyFloat());
verify(overlayLayout, times(1)).doDrawChild(eq(canvas), eq(child), anyLong());
reset(canvas);
reset(overlayLayout);
}
}

@ -12,6 +12,7 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.R; import com.otaliastudios.cameraview.R;
@ -23,7 +24,7 @@ public class OverlayLayout extends FrameLayout implements Overlay {
private static final String TAG = OverlayLayout.class.getSimpleName(); private static final String TAG = OverlayLayout.class.getSimpleName();
private static final CameraLogger LOG = CameraLogger.create(TAG); private static final CameraLogger LOG = CameraLogger.create(TAG);
private Target currentTarget = Target.PREVIEW; @VisibleForTesting Target currentTarget = Target.PREVIEW;
/** /**
* We set {@link #setWillNotDraw(boolean)} to false even if we don't draw anything. * We set {@link #setWillNotDraw(boolean)} to false even if we don't draw anything.
@ -149,7 +150,7 @@ public class OverlayLayout extends FrameLayout implements Overlay {
LOG.v("Performing drawing for view:", child.getClass().getSimpleName(), LOG.v("Performing drawing for view:", child.getClass().getSimpleName(),
"target:", currentTarget, "target:", currentTarget,
"params:", params); "params:", params);
return super.drawChild(canvas, child, drawingTime); return doDrawChild(canvas, child, drawingTime);
} else { } else {
LOG.v("Skipping drawing for view:", child.getClass().getSimpleName(), LOG.v("Skipping drawing for view:", child.getClass().getSimpleName(),
"target:", currentTarget, "target:", currentTarget,
@ -158,11 +159,16 @@ public class OverlayLayout extends FrameLayout implements Overlay {
} }
} }
@VisibleForTesting
boolean doDrawChild(Canvas canvas, View child, long drawingTime) {
return super.drawChild(canvas, child, drawingTime);
}
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public static class LayoutParams extends FrameLayout.LayoutParams { public static class LayoutParams extends FrameLayout.LayoutParams {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private boolean isOverlay; @VisibleForTesting boolean isOverlay;
public boolean drawOnPreview = false; public boolean drawOnPreview = false;
public boolean drawOnPictureSnapshot = false; public boolean drawOnPictureSnapshot = false;
public boolean drawOnVideoSnapshot = false; public boolean drawOnVideoSnapshot = false;
@ -186,7 +192,8 @@ public class OverlayLayout extends FrameLayout implements Overlay {
} }
} }
private boolean drawsOn(@NonNull Target target) { @VisibleForTesting
boolean drawsOn(@NonNull Target target) {
return ((target == Target.PREVIEW && drawOnPreview) return ((target == Target.PREVIEW && drawOnPreview)
|| (target == Target.VIDEO_SNAPSHOT && drawOnVideoSnapshot) || (target == Target.VIDEO_SNAPSHOT && drawOnVideoSnapshot)
|| (target == Target.PICTURE_SNAPSHOT && drawOnPictureSnapshot)); || (target == Target.PICTURE_SNAPSHOT && drawOnPictureSnapshot));

Loading…
Cancel
Save