DO NOT MERGE. Cherrypick CacheManagerTest from mr2.

Integrate unsubmitted cupcake change 149423:
	CTS: add test cases for android.webkit.CacheManager
diff --git a/tests/src/android/webkit/cts/CtsTestServer.java b/tests/src/android/webkit/cts/CtsTestServer.java
index 45eb439..a45589d 100644
--- a/tests/src/android/webkit/cts/CtsTestServer.java
+++ b/tests/src/android/webkit/cts/CtsTestServer.java
@@ -31,6 +31,7 @@
 import org.apache.http.entity.InputStreamEntity;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.impl.cookie.DateUtils;
 import org.apache.http.message.BasicHttpResponse;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.CoreProtocolPNames;
@@ -49,6 +50,7 @@
 import java.net.Socket;
 import java.net.URI;
 import java.security.KeyStore;
+import java.util.Date;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -97,6 +99,8 @@
     private MimeTypeMap mMap;
     private String mLastQuery;
     private int mRequestCount;
+    private long mDocValidity;
+    private long mDocAge;
 
     /**
      * Create and start a local HTTP server instance.
@@ -243,6 +247,24 @@
     }
 
     /**
+     * Set the validity of any future responses in milliseconds. If this is set to a non-zero
+     * value, the server will include a "Expires" header.
+     * @param timeMillis The time, in milliseconds, for which any future response will be valid.
+     */
+    public void setDocumentValidity(long timeMillis) {
+        mDocValidity = timeMillis;
+    }
+
+    /**
+     * Set the age of documents served. If this is set to a non-zero value, the server will include
+     * a "Last-Modified" header calculated from the value.
+     * @param timeMillis The age, in milliseconds, of any document served in the future.
+     */
+    public void setDocumentAge(long timeMillis) {
+        mDocAge = timeMillis;
+    }
+
+    /**
      * Generate a response to the given request.
      */
     private HttpResponse getResponse(HttpRequest request) {
@@ -375,9 +397,25 @@
         }
         StatusLine sl = response.getStatusLine();
         Log.i(TAG, sl.getStatusCode() + "(" + sl.getReasonPhrase() + ")");
+        setDateHeaders(response);
         return response;
     }
 
+    private void setDateHeaders(HttpResponse response) {
+        long time = System.currentTimeMillis();
+        if (mDocValidity != 0) {
+            String expires =
+                    DateUtils.formatDate(new Date(time + mDocValidity), DateUtils.PATTERN_RFC1123);
+            response.addHeader("Expires", expires);
+        }
+        if (mDocAge != 0) {
+            String modified =
+                    DateUtils.formatDate(new Date(time - mDocAge), DateUtils.PATTERN_RFC1123);
+            response.addHeader("Last-Modified", modified);
+        }
+        response.addHeader("Date", DateUtils.formatDate(new Date(), DateUtils.PATTERN_RFC1123));
+    }
+
     /**
      * Create an empty response with the given status.
      */
diff --git a/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java
new file mode 100644
index 0000000..bf66bad
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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 android.webkit.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.animation.cts.DelayedCheck;
+import android.webkit.CacheManager;
+import android.webkit.WebView;
+import android.webkit.CacheManager.CacheResult;
+
+import java.util.Map;
+
+@TestTargetClass(android.webkit.CacheManager.class)
+public class CacheManagerTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+    private static final long NETWORK_OPERATION_DELAY = 10000l;
+
+    private WebView mWebView;
+    private CtsTestServer mWebServer;
+
+    public CacheManagerTest() {
+        super("com.android.cts.stub", WebViewStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mWebView = getActivity().getWebView();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mWebServer != null) {
+            mWebServer.shutdown();
+        }
+        super.tearDown();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getCacheFileBaseDir",
+        args = {}
+    )
+    public void testGetCacheFileBaseDir() {
+        assertTrue(CacheManager.getCacheFileBaseDir().exists());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "startCacheTransaction",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "endCacheTransaction",
+            args = {}
+        )
+    })
+    @ToBeFixed(bug = "1695243", explanation = "the javadoc of these two methods doesn't exist.")
+    public void testCacheTransaction() {
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCacheFile",
+            args = {String.class, Map.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "saveCacheFile",
+            args = {String.class, CacheResult.class}
+        )
+    })
+    public void testCacheFile() throws Exception {
+        mWebServer = new CtsTestServer(getActivity());
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.EMBEDDED_IMG_URL);
+
+        mWebView.clearCache(true);
+        new DelayedCheck(NETWORK_OPERATION_DELAY) {
+            @Override
+            protected boolean check() {
+                CacheResult result =
+                    CacheManager.getCacheFile(url, null);
+                return result == null;
+            }
+        }.run();
+        loadUrl(url);
+        CacheResult result = CacheManager.getCacheFile(url, null);
+        assertNotNull(result);
+
+        // Can not test saveCacheFile(), because the output stream is null and
+        // saveCacheFile() will throw a NullPointerException.  There is no
+        // public API to set the output stream.
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        method = "cacheDisabled",
+        args = {}
+    )
+    public void testCacheDisabled() {
+        assertFalse(CacheManager.cacheDisabled());
+
+        // Because setCacheDisabled is package private, we can not call it.
+        // cacheDisabled() always return false. How to let it return true?
+    }
+
+    private void loadUrl(String url){
+        mWebView.loadUrl(url);
+        // check whether loadURL successfully
+        new DelayedCheck(NETWORK_OPERATION_DELAY) {
+            @Override
+            protected boolean check() {
+                return mWebView.getProgress() == 100;
+            }
+        }.run();
+        assertEquals(100, mWebView.getProgress());
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java b/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java
new file mode 100644
index 0000000..1a18a86
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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 android.webkit.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import org.apache.http.HttpStatus;
+import org.apache.http.impl.cookie.DateUtils;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.animation.cts.DelayedCheck;
+import android.webkit.CacheManager;
+import android.webkit.WebView;
+import android.webkit.CacheManager.CacheResult;
+
+import java.io.File;
+import java.io.InputStream;
+
+@TestTargetClass(android.webkit.CacheManager.CacheResult.class)
+public class CacheManager_CacheResultTest
+        extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+    private static final long NETWORK_OPERATION_DELAY = 10000l;
+
+    private WebView mWebView;
+    private CtsTestServer mWebServer;
+
+    public CacheManager_CacheResultTest() {
+        super("com.android.cts.stub", WebViewStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mWebView = getActivity().getWebView();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mWebServer != null) {
+            mWebServer.shutdown();
+        }
+        super.tearDown();
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getInputStream",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getContentLength",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getETag",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLastModified",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLocalPath",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLocation",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getMimeType",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getOutputStream",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getExpires",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getHttpStatusCode",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEncoding",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEncoding",
+            args = {String.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setInputStream",
+            args = {InputStream.class}
+        )
+    })
+    public void testCacheResult() throws Exception {
+        final long validity = 5 * 50 * 1000; // 5 min
+        final long age = 30 * 60 * 1000; // 30 min
+        final long tolerance = 5 * 1000; // 5s
+
+        mWebServer = new CtsTestServer(getActivity());
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mWebServer.setDocumentAge(age);
+        mWebServer.setDocumentValidity(validity);
+
+        mWebView.clearCache(true);
+        new DelayedCheck(NETWORK_OPERATION_DELAY) {
+            @Override
+            protected boolean check() {
+                CacheResult result =
+                    CacheManager.getCacheFile(url, null);
+                return result == null;
+            }
+        }.run();
+        final long time = System.currentTimeMillis();
+        loadUrl(url);
+        CacheResult result = CacheManager.getCacheFile(url, null);
+        assertNotNull(result);
+        assertNotNull(result.getInputStream());
+        assertTrue(result.getContentLength() > 0);
+        assertNull(result.getETag());
+        assertEquals(time - age,
+                DateUtils.parseDate(result.getLastModified()).getTime(), tolerance);
+        File file = new File(CacheManager.getCacheFileBaseDir().getPath(), result.getLocalPath());
+        assertTrue(file.exists());
+        assertNull(result.getLocation());
+        assertEquals("text/html", result.getMimeType());
+        assertNull(result.getOutputStream());
+        assertEquals(time + validity, result.getExpires(), tolerance);
+        assertEquals(HttpStatus.SC_OK, result.getHttpStatusCode());
+        assertNotNull(result.getEncoding());
+
+        result.setEncoding("iso-8859-1");
+        assertEquals("iso-8859-1", result.getEncoding());
+
+        result.setInputStream(null);
+        assertNull(result.getInputStream());
+    }
+
+    private void loadUrl(String url){
+        mWebView.loadUrl(url);
+        // check whether loadURL successfully
+        new DelayedCheck(NETWORK_OPERATION_DELAY) {
+            @Override
+            protected boolean check() {
+                return mWebView.getProgress() == 100;
+            }
+        }.run();
+        assertEquals(100, mWebView.getProgress());
+    }
+}