Initial pass at unit tests for ZoomManager.

This CL also includes some minor changes to the ZoomManager that
make the manager easier to test as well as fix some uncovered issues.

Change-Id: I66a84d70ee75e765ccf9cccb2d123757a9470f93
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 842f13a..5f76e56 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4188,7 +4188,7 @@
         // adjust the max viewport width depending on the view dimensions. This
         // is to ensure the scaling is not going insane. So do not shrink it if
         // the view size is temporarily smaller, e.g. when soft keyboard is up.
-        int newMaxViewportWidth = (int) (Math.max(w, h) / ZoomManager.getDefaultMinZoomScale());
+        int newMaxViewportWidth = (int) (Math.max(w, h) / mZoomManager.getDefaultMinZoomScale());
         if (newMaxViewportWidth > sMaxViewportWidth) {
             sMaxViewportWidth = newMaxViewportWidth;
         }
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index f385360..cf9688a 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -55,10 +55,16 @@
     private ZoomControlEmbedded mEmbeddedZoomControl;
     private ZoomControlExternal mExternalZoomControl;
 
-    // The default scale limits, which are dependent on the display density.
-    private static float DEFAULT_MAX_ZOOM_SCALE;
+    /*
+     * The scale factors that determine the upper and lower bounds for the
+     * default zoom scale.
+     */
+    protected static final float DEFAULT_MAX_ZOOM_SCALE_FACTOR = 4.00f;
+    protected static final float DEFAULT_MIN_ZOOM_SCALE_FACTOR = 0.25f;
 
-    private static float DEFAULT_MIN_ZOOM_SCALE;
+    // The default scale limits, which are dependent on the display density.
+    private float mDefaultMaxZoomScale;
+    private float mDefaultMinZoomScale;
 
     // The actual scale limits, which can be set through a webpage's viewport
     // meta-tag.
@@ -170,32 +176,49 @@
         setZoomOverviewWidth(WebView.DEFAULT_VIEWPORT_WIDTH);
     }
 
+    /**
+     * Initialize both the default and actual zoom scale to the given density.
+     *
+     * @param density The logical density of the display. This is a scaling factor
+     * for the Density Independent Pixel unit, where one DIP is one pixel on an
+     * approximately 160 dpi screen (see android.util.DisplayMetrics.density).
+     */
     public void init(float density) {
+        assert density > 0;
+
         setDefaultZoomScale(density);
-        mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
-        mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
         mActualScale = density;
         mInvActualScale = 1 / density;
         mTextWrapScale = density;
     }
 
+    /**
+     * Update the default zoom scale using the given density. It will also reset
+     * the current min and max zoom scales to the default boundaries as well as
+     * ensure that the actual scale falls within those boundaries.
+     *
+     * @param density The logical density of the display. This is a scaling factor
+     * for the Density Independent Pixel unit, where one DIP is one pixel on an
+     * approximately 160 dpi screen (see android.util.DisplayMetrics.density).
+     */
     public void updateDefaultZoomDensity(float density) {
+        assert density > 0;
+
         if (Math.abs(density - mDefaultScale) > MINIMUM_SCALE_INCREMENT) {
-            float scaleFactor = density * mInvDefaultScale;
             // set the new default density
             setDefaultZoomScale(density);
-            // adjust the limits
-            mMaxZoomScale *= scaleFactor;
-            mMinZoomScale *= scaleFactor;
-            setZoomScale(mActualScale * scaleFactor, true);
+            // adjust the scale if it falls outside the new zoom bounds
+            setZoomScale(mActualScale, true);
         }
     }
 
     private void setDefaultZoomScale(float defaultScale) {
         mDefaultScale = defaultScale;
         mInvDefaultScale = 1 / defaultScale;
-        DEFAULT_MAX_ZOOM_SCALE = 4.0f * defaultScale;
-        DEFAULT_MIN_ZOOM_SCALE = 0.25f * defaultScale;
+        mDefaultMaxZoomScale = defaultScale * DEFAULT_MAX_ZOOM_SCALE_FACTOR;
+        mDefaultMinZoomScale = defaultScale * DEFAULT_MIN_ZOOM_SCALE_FACTOR;
+        mMaxZoomScale = mDefaultMaxZoomScale;
+        mMinZoomScale = mDefaultMinZoomScale;
     }
 
     public final float getScale() {
@@ -210,10 +233,30 @@
         return mTextWrapScale;
     }
 
+    public final float getMaxZoomScale() {
+        return mMaxZoomScale;
+    }
+
+    public final float getMinZoomScale() {
+        return mMinZoomScale;
+    }
+
     public final float getDefaultScale() {
         return mDefaultScale;
     }
 
+    public final float getInvDefaultScale() {
+        return mInvDefaultScale;
+    }
+
+    public final float getDefaultMaxZoomScale() {
+        return mDefaultMaxZoomScale;
+    }
+
+    public final float getDefaultMinZoomScale() {
+        return mDefaultMinZoomScale;
+    }
+
     public final int getDocumentAnchorX() {
         return mAnchorX;
     }
@@ -235,10 +278,6 @@
         mInitialScale = scaleInPercent * 0.01f;
     }
 
-    public static final float getDefaultMinZoomScale() {
-        return DEFAULT_MIN_ZOOM_SCALE;
-    }
-
     public final float computeScaleWithLimits(float scale) {
         if (scale < mMinZoomScale) {
             scale = mMinZoomScale;
@@ -693,7 +732,7 @@
                     mMinZoomScaleFixed = true;
                 }
             } else {
-                mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+                mMinZoomScale = mDefaultMinZoomScale;
                 mMinZoomScaleFixed = false;
             }
         } else {
@@ -701,7 +740,7 @@
             mMinZoomScaleFixed = true;
         }
         if (restoreState.mMaxScale == 0) {
-            mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
+            mMaxZoomScale = mDefaultMaxZoomScale;
         } else {
             mMaxZoomScale = restoreState.mMaxScale;
         }
diff --git a/core/tests/coretests/src/android/webkit/ZoomManagerTest.java b/core/tests/coretests/src/android/webkit/ZoomManagerTest.java
new file mode 100644
index 0000000..b8c547c
--- /dev/null
+++ b/core/tests/coretests/src/android/webkit/ZoomManagerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.webkit;
+
+import android.test.AndroidTestCase;
+
+public class ZoomManagerTest extends AndroidTestCase {
+
+    private ZoomManager zoomManager;
+
+    @Override
+    public void setUp() {
+        WebView webView = new WebView(this.getContext());
+        CallbackProxy callbackProxy = new CallbackProxy(this.getContext(), webView);
+        zoomManager = new ZoomManager(webView, callbackProxy);
+
+        zoomManager.init(1.00f);
+    }
+
+    public void testInit() {
+        testInit(0.01f);
+        testInit(1.00f);
+        testInit(1.25f);
+    }
+
+    private void testInit(float density) {
+        zoomManager.init(density);
+        actualScaleTest(density);
+        defaultScaleTest(density);
+        assertEquals(zoomManager.getDefaultMaxZoomScale(), zoomManager.getMaxZoomScale());
+        assertEquals(zoomManager.getDefaultMinZoomScale(), zoomManager.getMinZoomScale());
+        assertEquals(density, zoomManager.getTextWrapScale());
+    }
+
+    public void testUpdateDefaultZoomDensity() {
+        // test the basic case where the actual values are equal to the defaults
+        testUpdateDefaultZoomDensity(0.01f);
+        testUpdateDefaultZoomDensity(1.00f);
+        testUpdateDefaultZoomDensity(1.25f);
+    }
+
+    private void testUpdateDefaultZoomDensity(float density) {
+        zoomManager.updateDefaultZoomDensity(density);
+        defaultScaleTest(density);
+    }
+
+    public void testUpdateDefaultZoomDensityWithSmallMinZoom() {
+        // test the case where the minZoomScale has changed to be < the default
+        float newDefaultScale = 1.50f;
+        float minZoomScale = ZoomManager.DEFAULT_MIN_ZOOM_SCALE_FACTOR * newDefaultScale;
+        WebViewCore.RestoreState minRestoreState = new WebViewCore.RestoreState();
+        minRestoreState.mMinScale = minZoomScale - 0.1f;
+        zoomManager.updateZoomRange(minRestoreState, 0, 0);
+        zoomManager.updateDefaultZoomDensity(newDefaultScale);
+        defaultScaleTest(newDefaultScale);
+    }
+
+    public void testUpdateDefaultZoomDensityWithLargeMinZoom() {
+        // test the case where the minZoomScale has changed to be > the default
+        float newDefaultScale = 1.50f;
+        float minZoomScale = ZoomManager.DEFAULT_MIN_ZOOM_SCALE_FACTOR * newDefaultScale;
+        WebViewCore.RestoreState minRestoreState = new WebViewCore.RestoreState();
+        minRestoreState.mMinScale = minZoomScale + 0.1f;
+        zoomManager.updateZoomRange(minRestoreState, 0, 0);
+        zoomManager.updateDefaultZoomDensity(newDefaultScale);
+        defaultScaleTest(newDefaultScale);
+    }
+
+    public void testUpdateDefaultZoomDensityWithSmallMaxZoom() {
+        // test the case where the maxZoomScale has changed to be < the default
+        float newDefaultScale = 1.50f;
+        float maxZoomScale = ZoomManager.DEFAULT_MAX_ZOOM_SCALE_FACTOR * newDefaultScale;
+        WebViewCore.RestoreState maxRestoreState = new WebViewCore.RestoreState();
+        maxRestoreState.mMaxScale = maxZoomScale - 0.1f;
+        zoomManager.updateZoomRange(maxRestoreState, 0, 0);
+        zoomManager.updateDefaultZoomDensity(newDefaultScale);
+        defaultScaleTest(newDefaultScale);
+    }
+
+    public void testUpdateDefaultZoomDensityWithLargeMaxZoom() {
+        // test the case where the maxZoomScale has changed to be > the default
+        float newDefaultScale = 1.50f;
+        float maxZoomScale = ZoomManager.DEFAULT_MAX_ZOOM_SCALE_FACTOR * newDefaultScale;
+        WebViewCore.RestoreState maxRestoreState = new WebViewCore.RestoreState();
+        maxRestoreState.mMaxScale = maxZoomScale + 0.1f;
+        zoomManager.updateZoomRange(maxRestoreState, 0, 0);
+        zoomManager.updateDefaultZoomDensity(newDefaultScale);
+        defaultScaleTest(newDefaultScale);
+    }
+
+    public void testComputeScaleWithLimits() {
+        final float maxScale = zoomManager.getMaxZoomScale();
+        final float minScale = zoomManager.getMinZoomScale();
+        assertTrue(maxScale > minScale);
+        assertEquals(maxScale, zoomManager.computeScaleWithLimits(maxScale));
+        assertEquals(maxScale, zoomManager.computeScaleWithLimits(maxScale + .01f));
+        assertEquals(minScale, zoomManager.computeScaleWithLimits(minScale));
+        assertEquals(minScale, zoomManager.computeScaleWithLimits(minScale - .01f));
+    }
+
+    private void actualScaleTest(float actualScale) {
+        assertEquals(actualScale, zoomManager.getScale());
+        assertEquals(1 / actualScale, zoomManager.getInvScale());
+    }
+
+    private void defaultScaleTest(float defaultScale) {
+        final float maxDefault = ZoomManager.DEFAULT_MAX_ZOOM_SCALE_FACTOR * defaultScale;
+        final float minDefault = ZoomManager.DEFAULT_MIN_ZOOM_SCALE_FACTOR * defaultScale;
+        assertEquals(defaultScale, zoomManager.getDefaultScale());
+        assertEquals(1 / defaultScale, zoomManager.getInvDefaultScale());
+        assertEquals(maxDefault, zoomManager.getDefaultMaxZoomScale());
+        assertEquals(minDefault, zoomManager.getDefaultMinZoomScale());
+    }
+}