eclair snapshot
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 0000000..f86942d
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1,37 @@
+# Copyright 2008, 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Notice that we don't have to include the src files of Browser because, by
+# running the tests using an instrumentation targeting Browser, we
+# automatically get all of its classes loaded into our environment.
+
+LOCAL_PACKAGE_NAME := BrowserTests
+
+LOCAL_INSTRUMENTATION_FOR := Browser
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 0000000..51715a9
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.browser.tests">
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    This declares that this app uses the instrumentation test runner targeting
+    the package of com.android.email.  To run the tests use the command:
+    "adb shell am instrument -w com.android.browser.tests/android.test.InstrumentationTestRunner"
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.browser"
+                     android:label="Tests for Browser."/>
+
+</manifest>
diff --git a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
new file mode 100644
index 0000000..b7956d7
--- /dev/null
+++ b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2009 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 com.android.browser;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.webkit.WebStorage;
+
+/**
+ * This is a series of unit tests for the WebStorageSizeManager class.
+ *
+ */
+@MediumTest
+public class WebStorageSizeManagerUnitTests extends AndroidTestCase {
+    // Used for testing the out-of-space callbacks.
+    private long mNewQuota;
+    // Callback functor that sets a new quota in case of out-of-space scenarios.
+    private class MockQuotaUpdater implements WebStorage.QuotaUpdater {
+        public void updateQuota(long newQuota) {
+            mNewQuota = newQuota;
+        }
+    }
+
+    // Mock the DiskInfo.
+    private class MockDiskInfo implements WebStorageSizeManager.DiskInfo {
+        private long mFreeSize;
+        private long mTotalSize;
+
+        public long getFreeSpaceSizeBytes() {
+            return mFreeSize;
+        }
+
+        public long getTotalSizeBytes() {
+            return mTotalSize;
+        }
+
+        public void setFreeSpaceSizeBytes(long freeSize) {
+            mFreeSize = freeSize;
+        }
+
+        public void setTotalSizeBytes(long totalSize) {
+            mTotalSize = totalSize;
+        }
+    }
+
+    // Mock the AppCacheInfo
+    public class MockAppCacheInfo implements WebStorageSizeManager.AppCacheInfo {
+        private long mAppCacheSize;
+
+        public long getAppCacheSizeBytes() {
+            return mAppCacheSize;
+        }
+
+        public void setAppCacheSizeBytes(long appCacheSize) {
+            mAppCacheSize = appCacheSize;
+        }
+    }
+
+    private MockQuotaUpdater mQuotaUpdater = new MockQuotaUpdater();
+    private final MockDiskInfo mDiskInfo = new MockDiskInfo();
+    private final MockAppCacheInfo mAppCacheInfo = new MockAppCacheInfo();
+    // Utility for making size computations easier to read.
+    private long bytes(double megabytes) {
+        return (new Double(megabytes * 1024 * 1024)).longValue();
+    }
+    /**
+     * Test the onExceededDatabaseQuota and onReachedMaxAppCacheSize callbacks
+     */
+    public void testCallbacks() {
+        long totalUsedQuota = 0;
+        final long quotaIncrease = WebStorageSizeManager.QUOTA_INCREASE_STEP;  // 1MB
+
+        // We have 75 MB total, 24MB free so the global limit will be 12 MB.
+        mDiskInfo.setTotalSizeBytes(bytes(75));
+        mDiskInfo.setFreeSpaceSizeBytes(bytes(24));
+        // We have an appcache file size of 0 MB.
+        mAppCacheInfo.setAppCacheSizeBytes(0);
+        // Create the manager.
+        WebStorageSizeManager manager = new WebStorageSizeManager(null, mDiskInfo, mAppCacheInfo);
+        // We add origin 1.
+        long origin1Quota = 0;
+        long origin1EstimatedSize = bytes(3.5);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1EstimatedSize, mNewQuota);
+        origin1Quota = mNewQuota;
+        totalUsedQuota += origin1Quota;
+
+        // We add origin 2.
+        long origin2Quota = 0;
+        long origin2EstimatedSize = bytes(2.5);
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin2EstimatedSize, mNewQuota);
+        origin2Quota = mNewQuota;
+        totalUsedQuota += origin2Quota;
+
+        // Origin 1 runs out of space.
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1EstimatedSize + quotaIncrease, mNewQuota);
+        totalUsedQuota -= origin1Quota;
+        origin1Quota = mNewQuota;
+        totalUsedQuota += origin1Quota;
+
+        // Origin 2 runs out of space.
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin2EstimatedSize + quotaIncrease, mNewQuota);
+        totalUsedQuota -= origin2Quota;
+        origin2Quota = mNewQuota;
+        totalUsedQuota += origin2Quota;
+
+        // We add origin 3. TotalUsedQuota is 8 (3.5 + 2.5 + 1 + 1). AppCacheMaxSize is 3 (12 / 4).
+        // So we have 1 MB free.
+        long origin3Quota = 0;
+        long origin3EstimatedSize = bytes(5);
+        manager.onExceededDatabaseQuota("3", "3", origin3Quota, origin3EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(0, mNewQuota);  // We cannot satisfy the estimatedSize
+        origin3Quota = mNewQuota;
+        totalUsedQuota += origin3Quota;
+
+        // Origin 1 runs out of space again. It should increase it's quota to take the last 1MB.
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1Quota + quotaIncrease, mNewQuota);
+        totalUsedQuota -= origin1Quota;
+        origin1Quota = mNewQuota;
+        totalUsedQuota += origin1Quota;
+
+        // Origin 1 runs out of space again. It should inow fail to increase in size.
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1Quota, mNewQuota);
+
+        // We try adding a new origin. Which will fail.
+        manager.onExceededDatabaseQuota("4", "4", 0, bytes(1), totalUsedQuota, mQuotaUpdater);
+        assertEquals(0, mNewQuota);
+
+        // AppCache size increases to 2MB...
+        mAppCacheInfo.setAppCacheSizeBytes(bytes(2));
+        // ... and wants 2MB more. Fail.
+        manager.onReachedMaxAppCacheSize(bytes(2), totalUsedQuota, mQuotaUpdater);
+        assertEquals(0, mNewQuota);
+
+        // The user nukes origin 2
+        totalUsedQuota -= origin2Quota;
+        origin2Quota = 0;
+        // TotalUsedQuota is 5.5 (9 - 3.5). AppCacheMaxSize is 3. AppCacheSize is 2.
+        // AppCache wants 1.5MB more
+        manager.onReachedMaxAppCacheSize(bytes(1.5), totalUsedQuota, mQuotaUpdater);
+        mAppCacheInfo.setAppCacheSizeBytes(mAppCacheInfo.getAppCacheSizeBytes() + bytes(2.5));
+        assertEquals(mAppCacheInfo.getAppCacheSizeBytes(), mNewQuota - WebStorageSizeManager.APPCACHE_MAXSIZE_PADDING);
+
+        // We try adding a new origin. This time we succeed.
+        // TotalUsedQuota is 5.5. AppCacheMaxSize is 5.0. So we have 12 - 10.5 = 1.5 available.
+        long origin4Quota = 0;
+        long origin4EstimatedSize = bytes(1.5);
+        manager.onExceededDatabaseQuota("4", "4", origin4Quota, origin4EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(bytes(1.5), mNewQuota);
+        origin4Quota = mNewQuota;
+        totalUsedQuota += origin4Quota;
+    }
+    /**
+     * Test the application caches max size calculator.
+     */
+    public void testCalculateGlobalLimit() {
+        long fileSystemSize = 78643200;  // 75 MB
+        long freeSpaceSize = 25165824;  // 24 MB
+        long maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(12582912, maxSize);  // 12MB
+
+        fileSystemSize = 78643200;  // 75 MB
+        freeSpaceSize = 60 * 1024 * 1024;  // 60MB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(19922944, maxSize);  // 19MB
+
+        fileSystemSize = 8589934592L;  // 8 GB
+        freeSpaceSize = 4294967296L;  // 4 GB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(536870912L, maxSize);  // 512 MB
+
+        fileSystemSize = -14;
+        freeSpaceSize = 21;
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(0, maxSize);
+
+        fileSystemSize = 100;
+        freeSpaceSize = 101;
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(0, maxSize);
+
+        fileSystemSize = 3774873; // ~4.2 MB
+        freeSpaceSize = 2560000;  // ~2.4 MB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(2097152, maxSize);  // 2 MB
+
+        fileSystemSize = 4404019; // ~4.2 MB
+        freeSpaceSize = 3774873;  // ~3.6 MB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(2097152, maxSize);  // 2 MB
+
+        fileSystemSize = 4404019; // ~4.2 MB
+        freeSpaceSize = 4404019;  // ~4.2 MB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(3145728, maxSize);  // 3 MB
+
+        fileSystemSize = 1048576; // 1 MB
+        freeSpaceSize = 1048575;  // 1 MB - 1 byte
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(0, maxSize);
+
+        fileSystemSize = 3774873; // ~3.6 MB
+        freeSpaceSize = 2097151;  // 2 MB - 1 byte
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(0, maxSize);
+
+        fileSystemSize = 3774873; // ~3.6 MB
+        freeSpaceSize = 2097151;  // 2 MB
+        maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
+        assertEquals(0, maxSize);
+    }
+}