Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: content/public/android/junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java

Issue 2765443004: AndroidOverlay implementation using Dialog. (Closed)
Patch Set: fixed test Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java
diff --git a/content/public/android/junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java b/content/public/android/junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..24a98615af79430932401f6d566fe5e48fc3806e
--- /dev/null
+++ b/content/public/android/junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java
@@ -0,0 +1,280 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.androidoverlay;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+
+// TODO(liberato): prior to M, this was ...policy.impl.PhoneWindow
+import com.android.internal.policy.PhoneWindow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowDialog;
+import org.robolectric.shadows.ShadowPhoneWindow;
+import org.robolectric.shadows.ShadowSurfaceView;
+
+import org.chromium.gfx.mojom.Rect;
+import org.chromium.media.mojom.AndroidOverlayConfig;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * Tests for DialogOverlayCore.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class DialogOverlayCoreTest {
+ private Activity mActivity;
+
+ AndroidOverlayConfig mConfig = new AndroidOverlayConfig();
+
+ // DialogCore under test.
+ DialogOverlayCore mCore;
+
+ // The dialog that we've provided to |mCore|.
+ Dialog mDialog;
+
+ // Fake window token that we'll send to |mCore|.
+ IBinder mWindowToken = new Binder();
+
+ // Surface that will be provided by |mDialog|.
+ Surface mSurface = new Surface();
+
+ // SurfaceHolder that will be provided by |mDialog|.
+ SurfaceHolder mHolder = new MyFakeSurfaceHolder(mSurface);
+
+ /**
+ * Robolectric shadow for PhoneWindow. This one keeps track of takeSurface() calls.
+ * TODO(liberato): the @Impl specifies 'minSdk=M' in the robolectric source.
+ */
+ @Implements(value = PhoneWindow.class, isInAndroidSdk = false)
+ public static class MyPhoneWindowShadow extends ShadowPhoneWindow {
+ public MyPhoneWindowShadow() {}
+
+ private SurfaceHolder.Callback2 mCallback;
+
+ @Implementation
+ public void takeSurface(SurfaceHolder.Callback2 callback) {
+ mCallback = callback;
+ }
+ }
+
+ /**
+ * The default fake surface holder doesn't let us provide a surface.
+ */
+ public static class MyFakeSurfaceHolder extends ShadowSurfaceView.FakeSurfaceHolder {
+ private Surface mSurface;
+
+ // @param surface The Surface that we'll provide via getSurface.
+ public MyFakeSurfaceHolder(Surface surface) {
+ mSurface = surface;
+ }
+
+ @Override
+ public Surface getSurface() {
+ return mSurface;
+ }
+ }
+
+ @Before
+ public void setUp() {
+ mActivity = Robolectric.buildActivity(Activity.class).setup().get();
+
+ mConfig = new AndroidOverlayConfig();
+ mConfig.rect = new Rect();
+ mConfig.rect.x = 0;
+ mConfig.rect.y = 1;
+ mConfig.rect.width = 2;
+ mConfig.rect.height = 3;
+
+ mCore = new DialogOverlayCore();
+ mCore.initialize(mActivity, mConfig, mHost);
+ mDialog = mCore.getDialog();
+
+ // Nothing should be called yet.
+ checkOverlayDidntCall();
+
+ // The dialog should not be shown yet.
+ checkDialogIsNotShown();
+ }
+
+ // Make sure that the overlay didn't provide us with a surface, or notify us that it was
+ // destroyed, or wait for cleanup.
+ void checkOverlayDidntCall() {
+ assertEquals(null, mHost.surface());
+ assertEquals(0, mHost.destroyedCount());
+ assertEquals(0, mHost.cleanupCount());
+ }
+
+ // Return the SurfaceHolder callback that was provided to takeSurface(), if any.
+ SurfaceHolder.Callback2 holderCallback() {
+ return ((MyPhoneWindowShadow) Shadows.shadowOf(mDialog.getWindow())).mCallback;
+ }
+
+ /**
+ * Host impl that counts calls to it.
+ */
+ class HostMock implements DialogOverlayCore.Host {
+ private Surface mSurface;
+ private int mDestroyedCount;
+ private int mCleanupCount;
+
+ @Override
+ public void onSurfaceReady(Surface surface) {
+ mSurface = surface;
+ }
+
+ @Override
+ public void onOverlayDestroyed() {
+ mDestroyedCount++;
+ }
+
+ @Override
+ public void waitForCleanup() {
+ mCleanupCount++;
+ }
+
+ public Surface surface() {
+ return mSurface;
+ }
+
+ public int destroyedCount() {
+ return mDestroyedCount;
+ }
+
+ public int cleanupCount() {
+ return mCleanupCount;
+ }
+ };
+
+ HostMock mHost = new HostMock();
+
+ // Send a window token and provide the surface, so that the overlay is ready for use.
+ void sendTokenAndSurface() {
+ mCore.onWindowToken(mWindowToken);
+ // Make sure that somebody called takeSurface.
+ assertNotNull(holderCallback());
+
+ checkDialogIsShown();
+
+ // Provide the Android Surface.
+ holderCallback().surfaceCreated(mHolder);
+
+ // The host should have been told about the surface.
+ assertEquals(mSurface, mHost.surface());
+ }
+
+ // Verify that the dialog has been shown.
+ void checkDialogIsShown() {
+ assertEquals(mDialog, ShadowDialog.getShownDialogs().get(0));
+ }
+
+ // Verify that the dialog is not currently shown. Note that dismiss() doesn't remove it from
+ // the shown dialog list in Robolectric, so we check for "was never shown or was dismissed".
+ void checkDialogIsNotShown() {
+ assertTrue(ShadowDialog.getShownDialogs().size() == 0
+ || Shadows.shadowOf(mDialog).hasBeenDismissed());
+ }
+
+ // Verify that |mCore| signaled that the overlay was lost to|mHost|.
+ void checkOverlayWasDestroyed() {
+ // |mCore| should have notified the host that it has been destroyed, and also waited for
+ // the host to signal that the client released it.
+ assertEquals(1, mHost.destroyedCount());
+ checkDialogIsNotShown();
+ }
+
+ // Check that releasing an overlay before getting a window token works.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testReleaseImmediately() {
+ // Release the overlay. |mCore| shouldn't notify us, since we released it.
+ mCore.release();
+ checkOverlayDidntCall();
+ checkDialogIsNotShown();
+ }
+
+ // Create a dialog, then send it a token. Verify that it's shown.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testTokenThenRelease() {
+ mCore.onWindowToken(mWindowToken);
+ checkDialogIsShown();
+
+ // Release the surface. |mHost| shouldn't be notified, nor should it wait for cleanup.
+ // Note: it might be okay if it checks for cleanup, since cleanup would be complete after
+ // we call release(). However, it's not needed, so we enforce that it isn't.
+ mCore.release();
+ checkOverlayDidntCall();
+ checkDialogIsNotShown();
+ }
+
+ // Create a dialog, send a token, send a surface, then release it.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testSurfaceThenRelease() {
+ sendTokenAndSurface();
+
+ mCore.release();
+ assertEquals(0, mHost.destroyedCount());
+ assertEquals(0, mHost.cleanupCount());
+ checkDialogIsNotShown();
+ }
+
+ // Create a dialog, send a surface, then destroy the surface.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testSurfaceThenDestroy() {
+ sendTokenAndSurface();
+
+ // Destroy the surface.
+ holderCallback().surfaceDestroyed(mHolder);
+ // |mCore| should have waited for cleanup during surfaceDestroyed.
+ assertEquals(1, mHost.cleanupCount());
+ // Since we waited for cleanup, also pretend that the release was posted during the wait and
+ // will arrive after the wait completes.
+ mCore.release();
+
+ checkOverlayWasDestroyed();
+ }
+
+ // Test that we're notified when the window token changes.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testChangeWindowToken() {
+ sendTokenAndSurface();
+
+ // Change the window token.
+ mCore.onWindowToken(new Binder());
+
+ checkOverlayWasDestroyed();
+ }
+
+ // Test that we're notified when the window token is lost.
+ @Test
+ @Config(shadows = {MyPhoneWindowShadow.class})
+ public void testLoseWindowToken() {
+ sendTokenAndSurface();
+
+ // Remove the window token.
+ mCore.onWindowToken(null);
+
+ checkOverlayWasDestroyed();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698