OSDN Git Service

Implement test to iterate over list of URLs and store load times.
authorAndrei Popescu <andreip@google.com>
Tue, 9 Feb 2010 16:59:58 +0000 (16:59 +0000)
committerJohn Spong <spong@google.com>
Tue, 23 Feb 2010 00:02:50 +0000 (16:02 -0800)
Also patch makefiles to correctly build tests and allow for hidden API calls in test.

Android.mk
tests/Android.mk
tests/src/com/android/browser/PopularUrlsTest.java [new file with mode: 0644]
tests/src/com/android/browser/TestWebChromeClient.java [new file with mode: 0644]
tests/src/com/android/browser/TestWebViewClient.java [new file with mode: 0644]

index 537ad60..d67a338 100644 (file)
@@ -8,7 +8,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
         gsf-client
 
 LOCAL_SRC_FILES := \
-        $(call all-subdir-java-files) \
+        $(call all-java-files-under, src) \
         src/com/android/browser/EventLogTags.logtags
 
 LOCAL_PACKAGE_NAME := Browser
index f86942d..ce9acbd 100644 (file)
@@ -31,7 +31,4 @@ LOCAL_PACKAGE_NAME := BrowserTests
 
 LOCAL_INSTRUMENTATION_FOR := Browser
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_PACKAGE)
-
diff --git a/tests/src/com/android/browser/PopularUrlsTest.java b/tests/src/com/android/browser/PopularUrlsTest.java
new file mode 100644 (file)
index 0000000..4ae69c7
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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 com.android.browser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.concurrent.CountDownLatch;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+
+/**
+ *
+ * Iterates over a list of URLs from a file and outputs the time to load each.
+ */
+public class PopularUrlsTest extends ActivityInstrumentationTestCase2<BrowserActivity> {
+
+    private final static String TAG = "PopularUrlsTest";
+    private final static String newLine = System.getProperty("line.separator");
+    private final static String sInputFile = "popular_urls.txt";
+    private final static String sOutputFile = "test_output.txt";
+    private final static File sExternalStorage = Environment.getExternalStorageDirectory();
+    private BrowserActivity mActivity = null;
+    private Instrumentation mInst = null;
+    private CountDownLatch mLatch = new CountDownLatch(1);
+
+    public PopularUrlsTest() {
+        super("com.android.browser", BrowserActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mInst = getInstrumentation();
+        mInst.waitForIdleSync();
+    }
+
+    static BufferedReader getInputStream() throws FileNotFoundException {
+        String path = sExternalStorage + File.separator + sInputFile;
+        FileReader fileReader = new FileReader(path);
+        BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+        return bufferedReader;
+    }
+
+    static OutputStreamWriter getOutputStream() throws IOException {
+        String path = sExternalStorage + File.separator + sOutputFile;
+
+        File file = new File(path);
+        if (file.exists()) {
+            file.delete();
+        }
+
+        return new FileWriter(file);
+    }
+
+    /**
+     * Gets the browser ready for testing by starting the application
+     * and wrapping the WebView's helper clients.
+     */
+    void setUpBrowser() {
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+
+        webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) {
+
+            /**
+             * Reset the latch whenever page progress reaches 100%.
+             */
+            @Override
+            public void onProgressChanged(WebView view, int newProgress) {
+                super.onProgressChanged(view, newProgress);
+                if (newProgress >= 100) {
+                    resetLatch();
+                }
+            }
+
+            /**
+             * Dismisses and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsAlert(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Alert '%s' received from %s", message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsConfirm(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Confirmation '%s' received from %s",
+                        message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts, providing the default value.
+             */
+            @Override
+            public boolean onJsPrompt(WebView view, String url, String message,
+                    String defaultValue, JsPromptResult result) {
+                String logMsg = String.format("JS Prompt '%s' received from %s; " +
+                        "Giving default value '%s'", message, url, defaultValue);
+                Log.w(TAG, logMsg);
+                result.confirm(defaultValue);
+
+                return true;
+            }
+        });
+
+        webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) {
+
+            /**
+             * Bypasses and logs errors.
+             */
+            @Override
+            public void onReceivedError(WebView view, int errorCode,
+                    String description, String failingUrl) {
+                String message = String.format("Error '%s' (%d) loading url: %s",
+                        description, errorCode, failingUrl);
+                Log.w(TAG, message);
+            }
+
+            /**
+             * Ignores and logs SSL errors.
+             */
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                    SslError error) {
+                Log.w(TAG, "SSL error: " + error);
+                handler.proceed();
+            }
+
+        });
+    }
+
+    void resetLatch() {
+        CountDownLatch temp = mLatch;
+        mLatch = new CountDownLatch(1);
+        if (temp != null) {
+            // Notify existing latch that it's done.
+            while (temp.getCount() > 0) {
+                temp.countDown();
+            }
+        }
+    }
+
+    void waitForLoad() throws InterruptedException {
+        mLatch.await();
+    }
+
+    /**
+     * Loops over a list of URLs, points the browser to each one, and records the time elapsed.
+     *
+     * @param input the reader from which to get the URLs.
+     * @param writer the writer to which to output the results.
+     * @throws IOException unable to read from input or write to writer.
+     * @throws InterruptedException the thread was interrupted waiting for the page to load.
+     */
+    void loopUrls(BufferedReader input, OutputStreamWriter writer)
+            throws IOException, InterruptedException {
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+        String page;
+
+        while (null != (page = input.readLine())) {
+            Uri uri = Uri.parse(page);
+            webView.clearCache(true);
+            final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+            writer.write(uri.toString());
+
+            long startTime = System.nanoTime();
+            mInst.runOnMainSync(new Runnable() {
+
+                public void run() {
+                    mActivity.onNewIntent(intent);
+                }
+
+            });
+            waitForLoad();
+            long stopTime = System.nanoTime();
+
+            String url = webView.getUrl();
+            Log.i(TAG, "Loaded url: " + url);
+            writer.write("|" + (stopTime - startTime) + newLine);
+        }
+    }
+
+    public void testLoadPerformance() throws IOException, InterruptedException {
+        setUpBrowser();
+
+        OutputStreamWriter writer = getOutputStream();
+        try {
+            BufferedReader bufferedReader = getInputStream();
+            try {
+                loopUrls(bufferedReader, writer);
+            } finally {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+            }
+        } finally {
+            if (writer != null) {
+                writer.close();
+            }
+        }
+    }
+}
+
diff --git a/tests/src/com/android/browser/TestWebChromeClient.java b/tests/src/com/android/browser/TestWebChromeClient.java
new file mode 100644 (file)
index 0000000..d78eaed
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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 com.android.browser;
+
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Message;
+import android.view.View;
+import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+
+/**
+ *
+ * WebChromeClient for browser tests.
+ * Wraps around existing client so that specific methods can be overridden if needed.
+ *
+ */
+abstract class TestWebChromeClient extends WebChromeClient {
+
+    private WebChromeClient mWrappedClient;
+
+    protected TestWebChromeClient(WebChromeClient wrappedClient) {
+        mWrappedClient = wrappedClient;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onProgressChanged(WebView view, int newProgress) {
+        mWrappedClient.onProgressChanged(view, newProgress);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedTitle(WebView view, String title) {
+        mWrappedClient.onReceivedTitle(view, title);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedIcon(WebView view, Bitmap icon) {
+        mWrappedClient.onReceivedIcon(view, icon);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedTouchIconUrl(WebView view, String url,
+            boolean precomposed) {
+        mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onShowCustomView(View view, CustomViewCallback callback) {
+        mWrappedClient.onShowCustomView(view, callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onHideCustomView() {
+        mWrappedClient.onHideCustomView();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onCreateWindow(WebView view, boolean dialog,
+            boolean userGesture, Message resultMsg) {
+        return mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onRequestFocus(WebView view) {
+        mWrappedClient.onRequestFocus(view);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onCloseWindow(WebView window) {
+        mWrappedClient.onCloseWindow(window);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsAlert(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsAlert(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsConfirm(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsConfirm(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message,
+            String defaultValue, JsPromptResult result) {
+        return mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsBeforeUnload(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsBeforeUnload(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier,
+            long currentQuota, long estimatedSize, long totalUsedQuota,
+            WebStorage.QuotaUpdater quotaUpdater) {
+        mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
+                estimatedSize, totalUsedQuota, quotaUpdater);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,
+            WebStorage.QuotaUpdater quotaUpdater) {
+        mWrappedClient.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onGeolocationPermissionsShowPrompt(String origin,
+            GeolocationPermissions.Callback callback) {
+        mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onGeolocationPermissionsHidePrompt() {
+        mWrappedClient.onGeolocationPermissionsHidePrompt();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsTimeout() {
+        return mWrappedClient.onJsTimeout();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Deprecated
+    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
+        mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+        return mWrappedClient.onConsoleMessage(consoleMessage);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Bitmap getDefaultVideoPoster() {
+        return mWrappedClient.getDefaultVideoPoster();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public View getVideoLoadingProgressView() {
+        return mWrappedClient.getVideoLoadingProgressView();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void getVisitedHistory(ValueCallback<String[]> callback) {
+        mWrappedClient.getVisitedHistory(callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void openFileChooser(ValueCallback<Uri> uploadFile) {
+        mWrappedClient.openFileChooser(uploadFile);
+    }
+}
diff --git a/tests/src/com/android/browser/TestWebViewClient.java b/tests/src/com/android/browser/TestWebViewClient.java
new file mode 100644 (file)
index 0000000..7159a7e
--- /dev/null
@@ -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 com.android.browser;
+
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+/**
+ *
+ *
+ * WebViewClient for browser tests.
+ * Wraps around existing client so that specific methods can be overridden if needed.
+ *
+ */
+abstract class TestWebViewClient extends WebViewClient {
+
+  private WebViewClient mWrappedClient;
+
+  protected TestWebViewClient(WebViewClient wrappedClient) {
+    mWrappedClient = wrappedClient;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public boolean shouldOverrideUrlLoading(WebView view, String url) {
+      return mWrappedClient.shouldOverrideUrlLoading(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onPageStarted(WebView view, String url, Bitmap favicon) {
+    mWrappedClient.onPageStarted(view, url, favicon);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onPageFinished(WebView view, String url) {
+    mWrappedClient.onPageFinished(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onLoadResource(WebView view, String url) {
+    mWrappedClient.onLoadResource(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Deprecated
+  @Override
+  public void onTooManyRedirects(WebView view, Message cancelMsg,
+          Message continueMsg) {
+      mWrappedClient.onTooManyRedirects(view, cancelMsg, continueMsg);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedError(WebView view, int errorCode,
+          String description, String failingUrl) {
+    mWrappedClient.onReceivedError(view, errorCode, description, failingUrl);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onFormResubmission(WebView view, Message dontResend,
+          Message resend) {
+    mWrappedClient.onFormResubmission(view, dontResend, resend);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void doUpdateVisitedHistory(WebView view, String url,
+          boolean isReload) {
+    mWrappedClient.doUpdateVisitedHistory(view, url, isReload);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedSslError(WebView view, SslErrorHandler handler,
+          SslError error) {
+      mWrappedClient.onReceivedSslError(view, handler, error);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedHttpAuthRequest(WebView view,
+          HttpAuthHandler handler, String host, String realm) {
+      mWrappedClient.onReceivedHttpAuthRequest(view, handler, host, realm);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+      return mWrappedClient.shouldOverrideKeyEvent(view, event);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+    mWrappedClient.onUnhandledKeyEvent(view, event);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onScaleChanged(WebView view, float oldScale, float newScale) {
+    mWrappedClient.onScaleChanged(view, oldScale, newScale);
+  }
+}