Introduce Task for async tests

pull/22/head
Mattia Iavarone 8 years ago
parent e01eb46bfc
commit 1db8d74111
  1. 61
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/PreviewTest.java
  2. 72
      cameraview/src/main/utils/com/otaliastudios/cameraview/Task.java
  3. 33
      cameraview/src/main/views/com/otaliastudios/cameraview/Preview.java

@ -12,8 +12,6 @@ import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.junit.Assert.*;
@ -26,7 +24,7 @@ public abstract class PreviewTest {
private Preview preview;
private ViewGroup parent;
private Preview.SurfaceCallback callback;
private Semaphore lock;
private Size surfaceSize = new Size(1000, 1000);
@Rule
public ActivityTestRule<TestActivity> rule = new ActivityTestRule<>(TestActivity.class);
@ -37,13 +35,19 @@ public abstract class PreviewTest {
@Override
public void run() {
Context context = rule.getActivity();
// Using a parent so we know its size.
parent = new FrameLayout(context);
parent.setLayoutParams(new ViewGroup.LayoutParams(
surfaceSize.getWidth(), surfaceSize.getHeight()));
preview = createPreview(context, parent);
callback = mock(Preview.SurfaceCallback.class);
preview.setSurfaceCallback(callback);
rule.getActivity().setContentView(parent);
lock = new Semaphore(1, true);
// Add all to a decor view and to the activity.
FrameLayout decor = new FrameLayout(context);
decor.addView(parent);
rule.getActivity().setContentView(decor);
}
});
}
@ -88,52 +92,39 @@ public abstract class PreviewTest {
@Test
public void testCropCenter() throws Exception {
preview.setCropListener(new Preview.CropListener() {
@Override
public void onPreCrop() {
try {
lock.acquire();
} catch (Exception e) {
e.printStackTrace();
};
}
@Override
public void onPostCrop() {
lock.release();
}
});
Task cropTask = preview.mCropTask;
// If aspect ratio is different, there should be a crop.
Size s = new Size(1000, 1000);
preview.onSurfaceAvailable(s.getWidth(), s.getHeight());
preview.onSurfaceAvailable(
surfaceSize.getWidth(),
surfaceSize.getHeight());
// Not cropping.
cropTask.listen();
preview.setDesiredSize(100, 100); // Wait...
lock.acquire();
assertEquals(AspectRatio.of(100, 100), getScaledAspectRatio());
cropTask.await();
assertEquals(100f / 100f, getScaledAspectRatio(), 0.01f);
assertFalse(preview.isCropping());
lock.release();
// Cropping.
cropTask.listen();
preview.setDesiredSize(160, 50); // Wait...
lock.acquire();
assertEquals(AspectRatio.of(160, 50), getScaledAspectRatio());
cropTask.await();
assertEquals(160f / 50f, getScaledAspectRatio(), 0.01f);
assertTrue(preview.isCropping());
lock.release();
// Not cropping.
cropTask.listen();
preview.onSurfaceSizeChanged(1600, 500); // Wait...
lock.acquire();
assertEquals(AspectRatio.of(160, 50), getScaledAspectRatio());
cropTask.await();
assertEquals(160f / 50f, getScaledAspectRatio(), 0.01f);
assertFalse(preview.isCropping());
lock.release();
}
private AspectRatio getScaledAspectRatio() {
private float getScaledAspectRatio() {
Size size = preview.getSurfaceSize();
int newWidth = (int) ((float) size.getWidth() * preview.getView().getScaleX());
int newHeight = (int) ((float) size.getHeight() * preview.getView().getScaleY());
return AspectRatio.of(newWidth, newHeight);
int newWidth = (int) (((float) size.getWidth()) * preview.getView().getScaleX());
int newHeight = (int) (((float) size.getHeight()) * preview.getView().getScaleY());
return AspectRatio.of(newWidth, newHeight).toFloat();
}
}

@ -0,0 +1,72 @@
package com.otaliastudios.cameraview;
import android.support.annotation.NonNull;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* A naive implementation of {@link java.util.concurrent.CountDownLatch}
* to help in testing.
*/
class Task<T> {
private CountDownLatch mLatch;
private T mResult;
private int mCount;
Task() {
}
private boolean listening() {
return mLatch != null;
}
void listen() {
if (listening()) throw new RuntimeException("Should not happen.");
mResult = null;
mLatch = new CountDownLatch(1);
}
void start() {
if (!listening()) mCount++;
}
void end(T result) {
if (mCount > 0) {
mCount--;
return;
}
if (listening()) { // Should be always true.
mResult = result;
mLatch.countDown();
}
}
T await() {
try {
mLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
T result = mResult;
mResult = null;
mLatch = null;
return result;
}
T await(long time, @NonNull TimeUnit unit) {
try {
mLatch.await(time, unit);
} catch (Exception e) {
e.printStackTrace();
}
T result = mResult;
mResult = null;
mLatch = null;
return result;
}
}

@ -10,6 +10,9 @@ abstract class Preview<T extends View, Output> {
protected final static CameraLogger LOG = CameraLogger.create(Preview.class.getSimpleName());
// Used for testing.
Task<Void> mCropTask = new Task<Void>();
// This is used to notify CameraImpl to recompute its camera Preview size.
// After that, CameraView will need a new layout pass to adapt to the Preview size.
interface SurfaceCallback {
@ -109,13 +112,13 @@ abstract class Preview<T extends View, Output> {
* However that should be already managed by the framework.
*/
private final void crop() {
onPreCrop();
mCropTask.start();
getView().post(new Runnable() {
@Override
public void run() {
if (mDesiredHeight == 0 || mDesiredWidth == 0 ||
mSurfaceHeight == 0 || mSurfaceWidth == 0) {
onPostCrop();
mCropTask.end(null);
return;
}
@ -133,7 +136,7 @@ abstract class Preview<T extends View, Output> {
getView().setScaleY(scaleY);
LOG.i("crop:", "applied scaleX=", scaleX);
LOG.i("crop:", "applied scaleY=", scaleY);
onPostCrop();
mCropTask.end(null);
}
});
}
@ -145,27 +148,7 @@ abstract class Preview<T extends View, Output> {
* @return true if cropping
*/
final boolean isCropping() {
return getView().getScaleX() > 1 || getView().getScaleY() > 1;
}
// Utils for testing.
interface CropListener {
void onPreCrop();
void onPostCrop();
}
private CropListener cropListener;
private void onPreCrop() {
if (cropListener != null) cropListener.onPreCrop();
}
private void onPostCrop() {
if (cropListener != null) cropListener.onPostCrop();
}
void setCropListener(CropListener listener) {
cropListener = listener;
// Account for some error
return getView().getScaleX() > 1.02f || getView().getScaleY() > 1.02f;
}
}

Loading…
Cancel
Save