diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java index ef30d897..3c3354a4 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java @@ -33,6 +33,7 @@ import com.otaliastudios.cameraview.tools.Op; import com.otaliastudios.cameraview.internal.utils.WorkerHandler; import com.otaliastudios.cameraview.overlay.Overlay; import com.otaliastudios.cameraview.size.Size; +import com.otaliastudios.cameraview.tools.RecoverCameraRule; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -71,7 +72,22 @@ public abstract class CameraIntegrationTest extends Base private final static long DELAY = 8000; @Rule - public ActivityTestRule rule = new ActivityTestRule<>(TestActivity.class); + public ActivityTestRule activityRule = new ActivityTestRule<>(TestActivity.class); + + @Rule + public RecoverCameraRule recoverRule = new RecoverCameraRule(new RecoverCameraRule.Callback() { + @NonNull + @Override + public CameraView getCamera() { + return camera; + } + + @NonNull + @Override + public CameraLogger getLogger() { + return LOG; + } + }); protected CameraView camera; protected E controller; @@ -94,7 +110,7 @@ public abstract class CameraIntegrationTest extends Base uiSync(new Runnable() { @Override public void run() { - camera = new CameraView(rule.getActivity()) { + camera = new CameraView(activityRule.getActivity()) { @NonNull @Override @@ -108,7 +124,7 @@ public abstract class CameraIntegrationTest extends Base camera.setExperimental(true); camera.setEngine(getEngine()); camera.addCameraListener(listener); - rule.getActivity().inflate(camera); + activityRule.getActivity().inflate(camera); // Ensure that controller exceptions are thrown on this thread (not on the UI thread). // TODO this makes debugging for wrong tests very hard, as we don't get the exception diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/tools/RecoverCameraRule.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/tools/RecoverCameraRule.java new file mode 100644 index 00000000..ee0ae224 --- /dev/null +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/tools/RecoverCameraRule.java @@ -0,0 +1,63 @@ +package com.otaliastudios.cameraview.tools; + +import androidx.annotation.NonNull; + +import com.otaliastudios.cameraview.CameraException; +import com.otaliastudios.cameraview.CameraListener; +import com.otaliastudios.cameraview.CameraLogger; +import com.otaliastudios.cameraview.CameraView; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +public class RecoverCameraRule implements TestRule { + + public interface Callback { + @NonNull + CameraView getCamera(); + @NonNull + CameraLogger getLogger(); + } + + private final Callback mCallback; + private final CameraListener mListener = new CameraListener() { + @Override + public void onCameraError(@NonNull CameraException exception) { + super.onCameraError(exception); + if (exception.isUnrecoverable()) { + mException = exception; + } + } + }; + private CameraException mException; + + public RecoverCameraRule(@NonNull Callback callback) { + mCallback = callback; + } + + @Override + public Statement apply(final Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + mException = null; + mCallback.getCamera().addCameraListener(mListener); + try { + base.evaluate(); + } catch (Throwable throwable) { + if (mException != null) { + mCallback.getLogger().e("**************************************"); + mCallback.getLogger().e("!!! TEST FAILED, TRYING TO RECOVER !!!"); + mCallback.getLogger().e("**************************************"); + mException = null; + mCallback.getCamera().destroy(); + base.evaluate(); + } + } finally { + mCallback.getCamera().removeCameraListener(mListener); + } + } + }; + } +}