summaryrefslogtreecommitdiffstats
path: root/tests/DumpRenderTree/src/com/android/dumprendertree
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
commit9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch)
treed88beb88001f2482911e3d28e43833b50e4b4e97 /tests/DumpRenderTree/src/com/android/dumprendertree
parentd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff)
downloadframeworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'tests/DumpRenderTree/src/com/android/dumprendertree')
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java328
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java29
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java256
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java165
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java726
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostApp.java33
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java21
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java62
-rwxr-xr-xtests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java68
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java172
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java56
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java194
12 files changed, 2110 insertions, 0 deletions
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
new file mode 100644
index 0000000..a389461
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import android.os.Handler;
+import android.os.Message;
+
+import java.util.HashMap;
+
+public class CallbackProxy extends Handler implements EventSender, LayoutTestController {
+
+ private EventSender mEventSender;
+ private LayoutTestController mLayoutTestController;
+
+ private static final int EVENT_DOM_LOG = 1;
+ private static final int EVENT_FIRE_KBD = 2;
+ private static final int EVENT_KEY_DOWN_1 = 3;
+ private static final int EVENT_KEY_DOWN_2 = 4;
+ private static final int EVENT_LEAP = 5;
+ private static final int EVENT_MOUSE_CLICK = 6;
+ private static final int EVENT_MOUSE_DOWN = 7;
+ private static final int EVENT_MOUSE_MOVE = 8;
+ private static final int EVENT_MOUSE_UP = 9;
+
+ private static final int LAYOUT_CLEAR_LIST = 20;
+ private static final int LAYOUT_DISPLAY = 21;
+ private static final int LAYOUT_DUMP_TEXT = 22;
+ private static final int LAYOUT_DUMP_HISTORY = 23;
+ private static final int LAYOUT_DUMP_CHILD_SCROLL = 24;
+ private static final int LAYOUT_DUMP_EDIT_CB = 25;
+ private static final int LAYOUT_DUMP_SEL_RECT = 26;
+ private static final int LAYOUT_DUMP_TITLE_CHANGES = 27;
+ private static final int LAYOUT_KEEP_WEB_HISTORY = 28;
+ private static final int LAYOUT_NOTIFY_DONE = 29;
+ private static final int LAYOUT_QUEUE_BACK_NAV = 30;
+ private static final int LAYOUT_QUEUE_FWD_NAV = 31;
+ private static final int LAYOUT_QUEUE_LOAD = 32;
+ private static final int LAYOUT_QUEUE_RELOAD = 33;
+ private static final int LAYOUT_QUEUE_SCRIPT = 34;
+ private static final int LAYOUT_REPAINT_HORZ = 35;
+ private static final int LAYOUT_SET_ACCEPT_EDIT = 36;
+ private static final int LAYOUT_MAIN_FIRST_RESP = 37;
+ private static final int LAYOUT_SET_WINDOW_KEY = 38;
+ private static final int LAYOUT_TEST_REPAINT = 39;
+ private static final int LAYOUT_WAIT_UNTIL_DONE = 40;
+
+ CallbackProxy(EventSender eventSender,
+ LayoutTestController layoutTestController) {
+ mEventSender = eventSender;
+ mLayoutTestController = layoutTestController;
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_DOM_LOG:
+ mEventSender.enableDOMUIEventLogging(msg.arg1);
+ break;
+ case EVENT_FIRE_KBD:
+ mEventSender.fireKeyboardEventsToElement(msg.arg1);
+ break;
+ case EVENT_KEY_DOWN_1:
+ HashMap map = (HashMap) msg.obj;
+ mEventSender.keyDown((String) map.get("character"),
+ (String[]) map.get("withModifiers"));
+ break;
+
+ case EVENT_KEY_DOWN_2:
+ mEventSender.keyDown((String)msg.obj);
+ break;
+
+ case EVENT_LEAP:
+ mEventSender.leapForward(msg.arg1);
+ break;
+
+ case EVENT_MOUSE_CLICK:
+ mEventSender.mouseClick();
+ break;
+
+ case EVENT_MOUSE_DOWN:
+ mEventSender.mouseDown();
+ break;
+
+ case EVENT_MOUSE_MOVE:
+ mEventSender.mouseMoveTo(msg.arg1, msg.arg2);
+ break;
+
+ case EVENT_MOUSE_UP:
+ mEventSender.mouseUp();
+ break;
+
+ case LAYOUT_CLEAR_LIST:
+ mLayoutTestController.clearBackForwardList();
+ break;
+
+ case LAYOUT_DISPLAY:
+ mLayoutTestController.display();
+ break;
+
+ case LAYOUT_DUMP_TEXT:
+ mLayoutTestController.dumpAsText();
+ break;
+
+ case LAYOUT_DUMP_HISTORY:
+ mLayoutTestController.dumpBackForwardList();
+ break;
+
+ case LAYOUT_DUMP_CHILD_SCROLL:
+ mLayoutTestController.dumpChildFrameScrollPositions();
+ break;
+
+ case LAYOUT_DUMP_EDIT_CB:
+ mLayoutTestController.dumpEditingCallbacks();
+ break;
+
+ case LAYOUT_DUMP_SEL_RECT:
+ mLayoutTestController.dumpSelectionRect();
+ break;
+
+ case LAYOUT_DUMP_TITLE_CHANGES:
+ mLayoutTestController.dumpTitleChanges();
+ break;
+
+ case LAYOUT_KEEP_WEB_HISTORY:
+ mLayoutTestController.keepWebHistory();
+ break;
+
+ case LAYOUT_NOTIFY_DONE:
+ mLayoutTestController.notifyDone();
+ break;
+
+ case LAYOUT_QUEUE_BACK_NAV:
+ mLayoutTestController.queueBackNavigation(msg.arg1);
+ break;
+
+ case LAYOUT_QUEUE_FWD_NAV:
+ mLayoutTestController.queueForwardNavigation(msg.arg1);
+ break;
+
+ case LAYOUT_QUEUE_LOAD:
+ HashMap<String, String> loadMap =
+ (HashMap<String, String>) msg.obj;
+ mLayoutTestController.queueLoad(loadMap.get("Url"),
+ loadMap.get("frameTarget"));
+ break;
+
+ case LAYOUT_QUEUE_RELOAD:
+ mLayoutTestController.queueReload();
+ break;
+
+ case LAYOUT_QUEUE_SCRIPT:
+ mLayoutTestController.queueScript((String)msg.obj);
+ break;
+
+ case LAYOUT_REPAINT_HORZ:
+ mLayoutTestController.repaintSweepHorizontally();
+ break;
+
+ case LAYOUT_SET_ACCEPT_EDIT:
+ mLayoutTestController.setAcceptsEditing(
+ msg.arg1 == 1 ? true : false);
+ break;
+ case LAYOUT_MAIN_FIRST_RESP:
+ mLayoutTestController.setMainFrameIsFirstResponder(
+ msg.arg1 == 1 ? true : false);
+ break;
+
+ case LAYOUT_SET_WINDOW_KEY:
+ mLayoutTestController.setWindowIsKey(
+ msg.arg1 == 1 ? true : false);
+ break;
+
+ case LAYOUT_TEST_REPAINT:
+ mLayoutTestController.testRepaint();
+ break;
+
+ case LAYOUT_WAIT_UNTIL_DONE:
+ mLayoutTestController.waitUntilDone();
+ break;
+ }
+ }
+
+ // EventSender Methods
+
+ public void enableDOMUIEventLogging(int DOMNode) {
+ obtainMessage(EVENT_DOM_LOG, DOMNode, 0).sendToTarget();
+ }
+
+ public void fireKeyboardEventsToElement(int DOMNode) {
+ obtainMessage(EVENT_FIRE_KBD, DOMNode, 0).sendToTarget();
+ }
+
+ public void keyDown(String character, String[] withModifiers) {
+ // TODO Auto-generated method stub
+ HashMap map = new HashMap();
+ map.put("character", character);
+ map.put("withModifiers", withModifiers);
+ obtainMessage(EVENT_KEY_DOWN_1, map).sendToTarget();
+ }
+
+ public void keyDown(String character) {
+ obtainMessage(EVENT_KEY_DOWN_2, character).sendToTarget();
+ }
+
+ public void leapForward(int milliseconds) {
+ obtainMessage(EVENT_LEAP, milliseconds, 0).sendToTarget();
+ }
+
+ public void mouseClick() {
+ obtainMessage(EVENT_MOUSE_CLICK).sendToTarget();
+ }
+
+ public void mouseDown() {
+ obtainMessage(EVENT_MOUSE_DOWN).sendToTarget();
+ }
+
+ public void mouseMoveTo(int X, int Y) {
+ obtainMessage(EVENT_MOUSE_MOVE, X, Y).sendToTarget();
+ }
+
+ public void mouseUp() {
+ obtainMessage(EVENT_MOUSE_UP).sendToTarget();
+ }
+
+ // LayoutTestController Methods
+
+ public void clearBackForwardList() {
+ obtainMessage(LAYOUT_CLEAR_LIST).sendToTarget();
+ }
+
+ public void display() {
+ obtainMessage(LAYOUT_DISPLAY).sendToTarget();
+ }
+
+ public void dumpAsText() {
+ obtainMessage(LAYOUT_DUMP_TEXT).sendToTarget();
+ }
+
+ public void dumpBackForwardList() {
+ obtainMessage(LAYOUT_DUMP_HISTORY).sendToTarget();
+ }
+
+ public void dumpChildFrameScrollPositions() {
+ obtainMessage(LAYOUT_DUMP_CHILD_SCROLL).sendToTarget();
+ }
+
+ public void dumpEditingCallbacks() {
+ obtainMessage(LAYOUT_DUMP_EDIT_CB).sendToTarget();
+ }
+
+ public void dumpSelectionRect() {
+ obtainMessage(LAYOUT_DUMP_SEL_RECT).sendToTarget();
+ }
+
+ public void dumpTitleChanges() {
+ obtainMessage(LAYOUT_DUMP_TITLE_CHANGES).sendToTarget();
+ }
+
+ public void keepWebHistory() {
+ obtainMessage(LAYOUT_KEEP_WEB_HISTORY).sendToTarget();
+ }
+
+ public void notifyDone() {
+ obtainMessage(LAYOUT_NOTIFY_DONE).sendToTarget();
+ }
+
+ public void queueBackNavigation(int howfar) {
+ obtainMessage(LAYOUT_QUEUE_BACK_NAV, howfar, 0).sendToTarget();
+ }
+
+ public void queueForwardNavigation(int howfar) {
+ obtainMessage(LAYOUT_QUEUE_FWD_NAV, howfar, 0).sendToTarget();
+ }
+
+ public void queueLoad(String Url, String frameTarget) {
+ HashMap <String, String>map = new HashMap<String, String>();
+ map.put("Url", Url);
+ map.put("frameTarget", frameTarget);
+ obtainMessage(LAYOUT_QUEUE_LOAD, map).sendToTarget();
+ }
+
+ public void queueReload() {
+ obtainMessage(LAYOUT_QUEUE_RELOAD).sendToTarget();
+ }
+
+ public void queueScript(String scriptToRunInCurrentContext) {
+ obtainMessage(LAYOUT_QUEUE_SCRIPT,
+ scriptToRunInCurrentContext).sendToTarget();
+ }
+
+ public void repaintSweepHorizontally() {
+ obtainMessage(LAYOUT_REPAINT_HORZ).sendToTarget();
+ }
+
+ public void setAcceptsEditing(boolean b) {
+ obtainMessage(LAYOUT_SET_ACCEPT_EDIT, b ? 1 : 0, 0).sendToTarget();
+ }
+
+ public void setMainFrameIsFirstResponder(boolean b) {
+ obtainMessage(LAYOUT_MAIN_FIRST_RESP, b ? 1 : 0, 0).sendToTarget();
+ }
+
+ public void setWindowIsKey(boolean b) {
+ obtainMessage(LAYOUT_SET_WINDOW_KEY,b ? 1 : 0, 0).sendToTarget();
+ }
+
+ public void testRepaint() {
+ obtainMessage(LAYOUT_TEST_REPAINT).sendToTarget();
+ }
+
+ public void waitUntilDone() {
+ obtainMessage(LAYOUT_WAIT_UNTIL_DONE).sendToTarget();
+ }
+
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java
new file mode 100644
index 0000000..82fd8d8
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+public interface EventSender {
+ public void mouseDown();
+ public void mouseUp();
+ public void mouseClick();
+ public void mouseMoveTo(int X, int Y);
+ public void leapForward(int milliseconds);
+ public void keyDown (String character, String[] withModifiers);
+ public void keyDown (String character);
+ public void enableDOMUIEventLogging(int DOMNode);
+ public void fireKeyboardEventsToElement(int DOMNode);
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
new file mode 100644
index 0000000..9be33db
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import android.util.*;
+
+public class FileFilter {
+
+ public static boolean ignoreTest(String file) {
+ // treat files like directories for the time being.
+ for (int i = 0; i < ignoreTestList.length; i ++) {
+ if (file.endsWith(ignoreTestList[i])) {
+ Log.e("FileFilter", "File path in IgnoreTest: " + file);
+ return true;
+ }
+ }
+ for (int i = 0; i < ignoreTestDirs.length; i++) {
+ if (file.endsWith(ignoreTestDirs[i])) {
+ Log.e("FileFilter", "File path in ignore list: " + file);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean ignoreResults(String file) {
+ int index = file.indexOf("fast");
+ if (index != -1) {
+ String sub = file.substring(index);
+ if (ignoreResultList.contains(sub))
+ return true;
+ }
+ return false;
+
+ }
+
+ public static String isKnownBug(String file) {
+ int index = file.indexOf("fast");
+ if (index != -1) {
+ String sub = file.substring(index);
+ // Log.e("FileFilter", "Looking for:"+sub);
+ if (bugList.containsKey(sub))
+ return bugList.get(sub);
+ }
+ return null;
+ }
+
+ final static HashSet<String> ignoreResultList = new HashSet<String>();
+ final static Hashtable<String, String> bugList =
+ new Hashtable<String, String>();
+
+ static {
+ fillIgnoreResultSet();
+ fillBugTable();
+ }
+
+ static final String[] ignoreTestDirs = {
+ ".", // ignore hidden directories and files
+ "resources", // ignore resource directories
+ "AppleScript", // AppleScript not supported
+ "xpath", // xpath requires libxml2, not supported
+ "xsl", //xsl requires libxml2 & libxslt, not sup.
+ "kde", // don't run kde tests.
+ ".svn", // don't run anything under .svn folder
+ "gradients", // known crash
+ "profiler" // profiler is not supported
+ };
+
+ static final String [] ignoreTestList = {
+ "toString-stack-overflow.html", // Crashes #606688
+ "frame-limit.html", // generates too many GREFs
+ "css-insert-import-rule.html", // Crashes, #717414
+ "input-text-enter.html", // Crashes. #735088
+ "text-shadow-extreme-value.html", // Crashes #571671
+ "reflection-masks.html",
+ "frame-creation-removal.html",
+ "large-expressions.html",
+ "null-page-show-modal-dialog-crash.html",
+ "font-face-implicit-local-font.html",
+ "font-face-locally-installed.html",
+ "beforeSelectorOnCodeElement.html",
+ "cssTarget-crash.html",
+ "searchfield-heights.html", // Bug 1570692
+ "tabindex-focus-blur-all.html",
+ "search-rtl.html" // fast/forms/search-rtl.html
+ };
+
+ static void fillIgnoreResultSet() {
+ // need test plugin
+ ignoreResultList.add("fast/dom/Window/Plug-ins.html");
+ // pixel depth
+ ignoreResultList.add("fast/dom/Window/window-screen-properties.html");
+ // missing space in textrun, ok as text is wrapped. ignore. #714933
+ ignoreResultList.add("fast/events/onload-webkit-before-webcore.html");
+ // missing support for textInputController.makeAttributedString()
+ ignoreResultList.add("fast/forms/attributed-strings.html");
+ // charset convert. #516936 ignore, won't fix
+ ignoreResultList.add("fast/forms/form-data-encoding-2.html");
+ // charset convert. #516936 ignore, won't fix
+ ignoreResultList.add("fast/forms/form-data-encoding.html");
+ // execCommand "insertText" not supported
+ ignoreResultList.add("fast/forms/input-appearance-maxlength.html");
+ // Copy&Paste commands not supported
+ ignoreResultList.add("fast/forms/input-truncate-newline.html");
+ ignoreResultList.add("fast/forms/textarea-paste-newline.html");
+ // requires eventSender.mouseMoveTo, mouseDown & mouseUp and
+ // abs. position of mouse to select a word. ignore, won't fix #716583
+ ignoreResultList.add("fast/forms/onselect-textarea.html");
+ // requires eventSender.mouseMoveTo, mouseDown & mouseUp and
+ // abs. position of mouse to select a word. ignore, won't fix #716583
+ ignoreResultList.add("fast/forms/onselect-textfield.html");
+ // not implemented queryCommandEnabled:BackColor, Undo & Redo
+ ignoreResultList.add("fast/forms/plaintext-mode-1.html");
+ // Our text areas are a little thinner than Apples. Also RTL test failes
+ ignoreResultList.add("fast/forms/textarea-appearance-wrap.html");
+ // Our text areas are a little thinner than Apples
+ ignoreResultList.add("fast/forms/textarea-hard-linewrap.html");
+ // screen width&height are different
+ ignoreResultList.add("fast/frames/frameElement-widthheight.html");
+ ignoreResultList.add("fast/frames/frame-js-url-clientWidth.html");
+ // requires JS test API, textInputController
+ ignoreResultList.add("fast/text/attributed-substring-from-range.html");
+ ignoreResultList.add("fast/text/attributed-substring-from-range-001.html");
+ // will not fix #619707
+ ignoreResultList.add("fast/css/case-transform.html");
+ // different platform defaults for font and different screen size
+ ignoreResultList.add("fast/css/computed-style.html");
+ // different screen size result in extra spaces in Apple compared to us
+ ignoreResultList.add("fast/dom/Element/offsetLeft-offsetTop-body-quirk.html");
+ // xslt and xpath elements missing from property list
+ ignoreResultList.add("fast/dom/Window/window-properties.html");
+ // requires textInputController.characterIndexForPoint
+ ignoreResultList.add("fast/dom/character-index-for-point.html");
+ // requires xpath support
+ ignoreResultList.add("fast/dom/gc-9.html");
+ // requires xslt and xpath support
+ ignoreResultList.add("fast/dom/global-constructors.html");
+ // dynamic plugins not supported
+ ignoreResultList.add("fast/dom/object-embed-plugin-scripting.html");
+ ignoreResultList.add("fast/js/navigator-mimeTypes-length.html");
+ // there is extra spacing in the file due to multiple input boxes
+ // fitting on one line on Apple, ours are wrapped. Space at line ends
+ // are stripped.
+ ignoreResultList.add("fast/dom/tabindex-clamp.html");
+
+ // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/dom/Window/window-xy-properties.html");
+ ignoreResultList.add("fast/events/window-events-bubble.html");
+ ignoreResultList.add("fast/events/window-events-bubble2.html");
+ ignoreResultList.add("fast/events/window-events-capture.html");
+ ignoreResultList.add("fast/forms/select-empty-list.html");
+ ignoreResultList.add("fast/replaced/image-map.html");
+ ignoreResultList.add("fast/events/capture-on-target.html");
+ ignoreResultList.add("fast/events/dblclick-addEventListener.html");
+ ignoreResultList.add("fast/events/drag-in-frames.html");
+ ignoreResultList.add("fast/events/drag-outside-window.html");
+ ignoreResultList.add("fast/events/event-sender-mouse-click.html");
+ ignoreResultList.add("fast/events/event-view-toString.html");
+ ignoreResultList.add("fast/events/frame-click-focus.html");
+ ignoreResultList.add("fast/events/input-image-scrolled-x-y.html");
+ ignoreResultList.add("fast/events/anchor-image-scrolled-x-y.html");
+ ignoreResultList.add("fast/events/mouseclick-target-and-positioning.html");
+ ignoreResultList.add("fast/events/mouseover-mouseout.html");
+ ignoreResultList.add("fast/events/mouseover-mouseout2.html");
+ ignoreResultList.add("fast/events/mouseup-outside-button.html");
+ ignoreResultList.add("fast/events/mouseup-outside-document.html");
+ ignoreResultList.add("fast/events/onclick-list-marker.html");
+ ignoreResultList.add("fast/events/ondragenter.html");
+ ignoreResultList.add("fast/forms/drag-into-textarea.html");
+ ignoreResultList.add("fast/forms/input-select-on-click.html");
+ ignoreResultList.add("fast/forms/listbox-onchange.html");
+ ignoreResultList.add("fast/forms/search-cancel-button-mouseup.html");
+ ignoreResultList.add("fast/forms/textarea-scrolled-endline-caret.html");
+
+ // there is extra spacing in the file due to multiple frame boxes
+ // fitting on one line on Apple, ours are wrapped. Space at line ends
+ // are stripped.
+ ignoreResultList.add("fast/events/iframe-object-onload.html");
+ // eventSender.mouseDown(), mouseUp() and objc API missing
+ ignoreResultList.add("fast/events/mouseup-outside-document.html");
+ ignoreResultList.add("fast/events/objc-keyboard-event-creation.html");
+ ignoreResultList.add("fast/events/objc-event-api.html");
+ // not capturing the console messages
+ ignoreResultList.add("fast/forms/selected-index-assert.html");
+ ignoreResultList.add("fast/parser/script-tag-with-trailing-slash.html");
+ // there is extra spacing as the text areas and input boxes fit next
+ // to each other on Apple, but are wrapped on our screen.
+ ignoreResultList.add("fast/forms/selection-functions.html");
+ // Text selection done differently on our platform. When a inputbox
+ // gets focus, the entire block is selected.
+ ignoreResultList.add("fast/forms/textarea-initial-caret-position.html");
+ ignoreResultList.add("fast/forms/textarea-no-scroll-on-blur.html");
+ // Requires LayoutTests to exist at /tmp/LayoutTests
+ ignoreResultList.add("fast/loader/local-JavaScript-from-local.html");
+ ignoreResultList.add("fast/loader/local-iFrame-source-from-local.html");
+ // extra spacing because iFrames rendered next to each other on Apple
+ ignoreResultList.add("fast/loader/opaque-base-url.html");
+ // RegExp is too large, causing OOM
+ ignoreResultList.add("fast/js/regexp-charclass-crash.html");
+ ignoreResultList.add("fast/text/plain-text-line-breaks.html");
+
+
+ }
+
+ static void fillBugTable() {
+ bugList.put("fast/forms/check-box-enter-key.html", "716715");
+ bugList.put("fast/forms/focus-control-to-page.html", "716638");
+ bugList.put("fast/html/tab-order.html", "719289");
+ bugList.put("fast/dom/attribute-namespaces-get-set.html", "733229");
+ bugList.put("fast/dom/location-hash.html", "733822");
+ bugList.put("fast/dom/set-innerHTML.html", "733823");
+ bugList.put("fast/dom/xmlhttprequest-get.html", "733846");
+ bugList.put("fast/encoding/css-charset-default.html", "733856");
+ bugList.put("fast/encoding/default-xhtml-encoding.html", "733882");
+ bugList.put("fast/encoding/meta-in-xhtml.html", "733882");
+ bugList.put("fast/events/frame-tab-focus.html", "734308");
+ bugList.put("fast/events/keydown-keypress-focus-change.html", "653224");
+ bugList.put("fast/events/keypress-focus-change.html", "653224");
+ bugList.put("fast/events/option-tab.html", "734308");
+ bugList.put("fast/forms/focus2.html", "735111");
+ bugList.put("fast/forms/listbox-selection.html", "735116");
+ bugList.put("fast/forms/search-event-delay.html", "735120");
+ bugList.put("fast/frames/iframe-window-focus.html", "735140");
+ bugList.put("fast/innerHTML/004.html", "733882");
+ bugList.put("fast/js/date-DST-time-cusps.html", "735144");
+ bugList.put("fast/js/string-capitalization.html", "516936");
+ bugList.put("fast/js/string-concatenate-outofmemory.html","735152");
+ bugList.put("fast/parser/external-entities.html", "735176");
+ bugList.put("fast/events/div-focus.html", "735185");
+ bugList.put("fast/overflow/scroll-vertical-not-horizontal.html", "735196");
+ bugList.put("fast/events/arrow-navigation.html", "735233");
+ bugList.put("fast/forms/select-type-ahead-non-latin.html", "735244");
+ bugList.put("fast/events/js-keyboard-event-creation.html", "735255");
+
+ }
+
+
+
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
new file mode 100644
index 0000000..d685f5d
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.io.File;
+
+import android.app.ListActivity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.os.Bundle;
+
+
+public abstract class FileList extends ListActivity
+{
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode)
+ {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (mPath.length() > mBaseLength) {
+ File f = new File(mPath);
+ mFocusFile = f.getName();
+ mFocusIndex = 0;
+ f = f.getParentFile();
+ mPath = f.getPath();
+ updateList();
+ return true;
+ }
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ {
+ Map map = (Map) getListView().getItemAtPosition(getListView().getSelectedItemPosition());
+ String path = (String)map.get("path");
+ if ((new File(path)).isDirectory()) {
+ mPath = path;
+ mFocusFile = null;
+ updateList();
+ } else {
+ processFile(path, false);
+ }
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ public void onCreate(Bundle icicle)
+ {
+ super.onCreate(icicle);
+ setupPath();
+ updateList();
+ }
+
+ protected List getData()
+ {
+ List myData = new ArrayList<HashMap>();
+
+ File f = new File(mPath);
+ if (!f.exists()) {
+ addItem(myData, "!LayoutTests path missing!", "");
+ return myData;
+ }
+ String[] files = f.list();
+
+ for (int i = 0; i < files.length; i++) {
+ StringBuilder sb = new StringBuilder(mPath);
+ sb.append(File.separatorChar);
+ sb.append(files[i]);
+ String path = sb.toString();
+ File c = new File(path);
+ if (fileFilter(c)) {
+ if (c.isDirectory()) {
+ addItem(myData, "<"+files[i]+">", path);
+ if (mFocusFile != null && mFocusFile.equals(files[i]))
+ mFocusIndex = myData.size()-1;
+ }
+ else
+ addItem(myData, files[i], path);
+ }
+ }
+
+ return myData;
+ }
+
+ protected void addItem(List<Map> data, String name, String path)
+ {
+ HashMap temp = new HashMap();
+ temp.put("title", name);
+ temp.put("path", path);
+ data.add(temp);
+ }
+
+ protected void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Map map = (Map) l.getItemAtPosition(position);
+ String path = (String)map.get("path");
+
+ if ((new File(path)).isDirectory()) {
+ mPath = path;
+ mFocusFile = null;
+ updateList();
+ } else {
+ processFile(path, false);
+ }
+ }
+
+ /*
+ * This function is called when the user has selected a file in the
+ * file list. The selected file could be a file or a directory.
+ * The flag indicates if this was from a selection or not.
+ */
+ abstract void processFile(String filename, boolean selection);
+
+ /*
+ * This function is called when the file list is being built. Return
+ * true if the file is to be added to the file list.
+ */
+ abstract boolean fileFilter(File f);
+
+ protected void updateList() {
+ setListAdapter(new SimpleAdapter(this,
+ getData(),
+ android.R.layout.simple_list_item_1,
+ new String[] {"title"},
+ new int[] {android.R.id.text1}));
+ String title = mPath; //.substring(mBaseLength-11); // show the word LayoutTests
+ setTitle(title);
+ getListView().setSelection(mFocusIndex);
+ }
+
+ protected void setupPath()
+ {
+ mPath = "/sdcard/android/layout_tests";
+ mBaseLength = mPath.length();
+ }
+
+ protected String mPath;
+ protected int mBaseLength;
+ protected String mFocusFile;
+ protected int mFocusIndex;
+
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
new file mode 100644
index 0000000..86bfad7
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
@@ -0,0 +1,726 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.ViewGroup;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.widget.LinearLayout;
+import android.os.*;
+
+// TestRecorder creates two files, one for passing tests
+// and another for failing tests and writes the paths to
+// layout tests one line at a time. TestRecorder does not
+// have ability to clear the results.
+class TestRecorder {
+ public void passed(String layout_file) {
+ try {
+ mBufferedOutputPassedStream.write(layout_file.getBytes());
+ mBufferedOutputPassedStream.write('\n');
+ mBufferedOutputPassedStream.flush();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void failed(String layout_file, String reason) {
+ try {
+ mBufferedOutputFailedStream.write(layout_file.getBytes());
+ mBufferedOutputFailedStream.write(" : ".getBytes());
+ mBufferedOutputFailedStream.write(reason.getBytes());
+ mBufferedOutputFailedStream.write('\n');
+ mBufferedOutputFailedStream.flush();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void nontext(String layout_file, boolean has_results) {
+ try {
+ mBufferedOutputNontextStream.write(layout_file.getBytes());
+ if (has_results) {
+ mBufferedOutputNontextStream.write(" : has expected results".getBytes());
+ }
+ mBufferedOutputNontextStream.write('\n');
+ mBufferedOutputNontextStream.flush();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public TestRecorder(boolean resume) {
+ try {
+ File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt");
+ File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt");
+ File resultsNontextFile = new File("/sdcard/layout_tests_nontext.txt");
+
+ mBufferedOutputPassedStream =
+ new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume));
+ mBufferedOutputFailedStream =
+ new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume));
+ mBufferedOutputNontextStream =
+ new BufferedOutputStream(new FileOutputStream(resultsNontextFile, resume));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+ try {
+ mBufferedOutputPassedStream.close();
+ mBufferedOutputFailedStream.close();
+ mBufferedOutputNontextStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ private BufferedOutputStream mBufferedOutputPassedStream;
+ private BufferedOutputStream mBufferedOutputFailedStream;
+ private BufferedOutputStream mBufferedOutputNontextStream;
+}
+
+public class HTMLHostActivity extends Activity
+ implements LayoutTestController {
+
+ public class AsyncHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_TIMEOUT) {
+ mTimedOut = true;
+ requestWebKitData();
+ return;
+ } else if (msg.what == MSG_WEBKIT_DATA) {
+ HTMLHostActivity.this.dump(mTimedOut, (String)msg.obj);
+ return;
+ }
+
+ super.handleMessage(msg);
+ }
+ }
+
+ public void requestWebKitData() {
+ Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA);
+
+ if (mRequestedWebKitData)
+ throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl());
+
+ mRequestedWebKitData = true;
+ if (mDumpAsText) {
+ mWebView.documentAsText(callback);
+ } else {
+ mWebView.externalRepresentation(callback);
+ }
+ }
+ // Activity methods
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ LinearLayout contentView = new LinearLayout(this);
+ contentView.setOrientation(LinearLayout.VERTICAL);
+ setContentView(contentView);
+
+ mWebView = new WebView(this);
+ mWebView.getSettings().setJavaScriptEnabled(true);
+ mWebView.setWebChromeClient(mChromeClient);
+ mEventSender = new WebViewEventSender(mWebView);
+ mCallbackProxy = new CallbackProxy(mEventSender, this);
+ mFinishedRunning = false;
+
+ mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController");
+ mWebView.addJavascriptInterface(mCallbackProxy, "eventSender");
+ contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
+
+ mHandler = new AsyncHandler();
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ }
+
+ private void getTestList() {
+ // Read test list.
+ try {
+ BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE));
+ String line = inReader.readLine();
+ while (line != null) {
+ if (line.startsWith(mTestPathPrefix))
+ mTestList.add(line);
+ line = inReader.readLine();
+ }
+ inReader.close();
+ Log.v(LOGTAG, "Test list has " + mTestList.size() + " test(s).");
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Error while reading test list : " + e.getMessage());
+ }
+ }
+
+ private void resumeTestList() {
+ // read out the test name it stoped last time.
+ try {
+ BufferedReader inReader = new BufferedReader(new FileReader(TEST_STATUS_FILE));
+ String line = inReader.readLine();
+ for (int i = 0; i < mTestList.size(); i++) {
+ if (mTestList.elementAt(i).equals(line)) {
+ mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size()));
+ break;
+ }
+ }
+ inReader.close();
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE);
+ }
+ }
+
+ private void clearTestStatus() {
+ // Delete TEST_STATUS_FILE
+ try {
+ File f = new File(TEST_STATUS_FILE);
+ if (f.delete())
+ Log.v(LOGTAG, "Deleted " + TEST_STATUS_FILE);
+ else
+ Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE);
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE + " : " + e.getMessage());
+ }
+ }
+
+ private void updateTestStatus(String s) {
+ // Write TEST_STATUS_FILE
+ try {
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(TEST_STATUS_FILE));
+ bos.write(s.getBytes());
+ bos.close();
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Cannot update file " + TEST_STATUS_FILE);
+ }
+ }
+
+ protected void onResume() {
+ super.onResume();
+ if (mTestList == null)
+ mTestList = new Vector<String>();
+
+ if (mTestList.isEmpty()) {
+ // Read settings
+ Intent intent = getIntent();
+ mTestPathPrefix = intent.getStringExtra(TEST_PATH_PREFIX);
+ mSingleTestMode = intent.getBooleanExtra(SINGLE_TEST_MODE, false);
+ boolean resume = intent.getBooleanExtra(RESUME_FROM_CRASH, false);
+ mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 8000);
+
+ mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
+
+ if (mTestPathPrefix == null)
+ throw new AssertionError("mTestPathPrefix cannot be null");
+
+ Log.v(LOGTAG, "Run tests with prefix: " + mTestPathPrefix);
+
+ mResultRecorder = new TestRecorder(resume);
+
+ if (!resume)
+ clearTestStatus();
+
+ if (!mSingleTestMode) {
+ getTestList();
+ if (resume)
+ resumeTestList();
+ } else {
+ mTestList.add(mTestPathPrefix);
+ }
+
+ if (!mTestList.isEmpty())
+ runTestAtIndex(0);
+ else
+ mWebView.loadUrl("about:");
+ }
+ }
+
+ protected void onStop() {
+ super.onStop();
+ mWebView.stopLoading();
+ }
+
+ protected void onDestroy() {
+ super.onDestroy();
+ mResultRecorder.close();
+ mWebView.destroy();
+ mWebView = null;
+ }
+
+ public void onLowMemory() {
+ super.onLowMemory();
+ // Simulate a crash
+ Log.e(LOGTAG, "Low memory, killing self");
+ System.exit(1);
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Log key strokes as they don't seem to be matched
+ //Log.e(LOGTAG, "Event: "+event);
+ return super.dispatchKeyEvent(event);
+ }
+
+ // Run a test at specified index in the test list.
+ // Stops activity if run out of tests.
+ protected void runTestAtIndex(int testIndex) {
+ mTestIndex = testIndex;
+
+ resetTestStatus();
+
+ if (testIndex == mTestList.size()) {
+ if (!mSingleTestMode) {
+ updateTestStatus("#DONE");
+ }
+ finished();
+ return;
+ }
+ String s = mTestList.elementAt(testIndex);
+ if (!mSingleTestMode)
+ updateTestStatus(s);
+
+ Log.v(LOGTAG, " Running test: "+s);
+ mWebView.loadUrl("file://"+s);
+
+ if (!mSingleTestMode) {
+ // Create a timeout timer
+ Message m = mHandler.obtainMessage(MSG_TIMEOUT);
+ mHandler.sendMessageDelayed(m, mTimeoutInMillis);
+ }
+ }
+
+ // Dump the page
+ public void dump(boolean timeout, String webkitData) {
+ String currentTest = mTestList.elementAt(mTestIndex);
+ String resultFile = currentTest.substring(0, currentTest.lastIndexOf('.'));
+
+ // dumpAsText version can be directly compared to expected results
+ if (mDumpAsText) {
+ resultFile += "-results.txt";
+ } else {
+ resultFile += "-android-results.txt";
+ }
+
+ try {
+ FileOutputStream os = new FileOutputStream(resultFile);
+ if (timeout) {
+ Log.w("Layout test: Timeout", resultFile);
+ os.write(TIMEOUT_STR.getBytes());
+ os.write('\n');
+ }
+ if (mDumpTitleChanges)
+ os.write(mTitleChanges.toString().getBytes());
+ if (mDialogStrings != null)
+ os.write(mDialogStrings.toString().getBytes());
+ mDialogStrings = null;
+ os.write(webkitData.getBytes());
+ os.flush();
+ os.close();
+ } catch (FileNotFoundException ex) {
+ ex.printStackTrace();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+
+ processResult(timeout, currentTest);
+ runTestAtIndex(mTestIndex + 1);
+ }
+
+ // Wrap up
+ public void failedCase(String file, String reason) {
+ Log.w("Layout test: ", file + " failed " + reason);
+ mResultRecorder.failed(file, reason);
+
+ String bugNumber = FileFilter.isKnownBug(file);
+ if (bugNumber != null) {
+ System.out.println("FAIL known:"+bugNumber+ " "+file+reason);
+ return;
+ }
+ if (FileFilter.ignoreResults(file)) {
+ return;
+ }
+ System.out.println("FAIL: "+file+reason);
+ }
+
+ public void passedCase(String file) {
+ Log.v("Layout test:", file + " passed");
+ mResultRecorder.passed(file);
+
+ String bugNumber = FileFilter.isKnownBug(file);
+ if (bugNumber != null) {
+ System.out.println("Bug Fixed: "+bugNumber+ " "+file);
+ return;
+ }
+
+ if (FileFilter.ignoreResults(file)) {
+ System.out.println("Ignored test passed: "+file);
+ return;
+ }
+ }
+
+ public void nontextCase(String file, boolean has_expected_results) {
+ Log.v("Layout test:", file + " nontext");
+ mResultRecorder.nontext(file, has_expected_results);
+ }
+
+ public void setCallback(HTMLHostCallbackInterface callback) {
+ mCallback = callback;
+ }
+
+ public void processResult(boolean timeout, String test_path) {
+ Log.v(LOGTAG, " Processing result: " + test_path);
+ // remove the extension
+ String short_file = test_path.substring(0, test_path.lastIndexOf('.'));
+ if (timeout) {
+ failedCase(test_path, "TIMEDOUT");
+ return;
+ }
+ // Only check results that we can check, ie dumpAsText results
+ String dumpFile = short_file + "-results.txt";
+ File f = new File(dumpFile);
+ if (f.exists()) {
+ try {
+ FileInputStream fr = new FileInputStream(short_file+"-results.txt");
+ FileInputStream fe = new FileInputStream(short_file+"-expected.txt");
+
+ // If the length is different then they are different
+ int diff = fe.available() - fr.available();
+ if (diff > 1 || diff < 0) {
+ failedCase(test_path, " different length");
+ fr.close();
+ fe.close();
+ return;
+ }
+ byte[] br = new byte[fr.available()];
+ byte[] be = new byte[fe.available()];
+ fr.read(br);
+ fe.read(be);
+ boolean fail = false;
+ for (int i = 0; i < br.length; i++) {
+ if (br[i] != be[i]) {
+ failedCase(test_path, " @offset: "+i);
+ fr.close();
+ fe.close();
+ return;
+ }
+ }
+ if (br.length != be.length && be[be.length-1] == '\n') {
+ Log.d(LOGTAG, "Extra new line being ignore:" + test_path);
+ }
+ fr.close();
+ fe.close();
+ passedCase(test_path);
+ } catch (FileNotFoundException ex) {
+ // TODO do something here
+ } catch (IOException ex) {
+ // Failed on available() or read()
+ }
+
+ return;
+ }
+
+ File nontext_result = new File(short_file + "-android-results.txt");
+ if (nontext_result.exists()) {
+ // Check if the test has expected results.
+ File expected = new File(short_file + "-expected.txt");
+ nontextCase(test_path, expected.exists());
+ }
+ }
+
+ public void finished() {
+ if (mCallback != null) {
+ mCallback.waitForFinish();
+ }
+
+ mFinishedRunning = true;
+ finish();
+ }
+
+ // LayoutTestController Functions
+ public void dumpAsText() {
+ mDumpAsText = true;
+ if (mWebView != null) {
+ String url = mWebView.getUrl();
+ Log.v(LOGTAG, "dumpAsText called: "+url);
+ }
+ }
+
+ public void waitUntilDone() {
+ mWaitUntilDone = true;
+ String url = mWebView.getUrl();
+ Log.v(LOGTAG, "waitUntilDone called: " + url);
+ }
+ public void notifyDone() {
+ String url = mWebView.getUrl();
+ Log.v(LOGTAG, "notifyDone called: " + url);
+ if (mWaitUntilDone) {
+ mWaitUntilDone = false;
+ mChromeClient.onProgressChanged(mWebView, 100);
+ }
+ }
+
+ public void display() {
+ mWebView.invalidate();
+ }
+
+ public void clearBackForwardList() {
+ mWebView.clearHistory();
+
+ }
+
+ public void dumpBackForwardList() {
+ //printf("\n============== Back Forward List ==============\n");
+ // mWebHistory
+ //printf("===============================================\n");
+
+ }
+
+ public void dumpChildFrameScrollPositions() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void dumpEditingCallbacks() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void dumpSelectionRect() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void dumpTitleChanges() {
+ if (!mDumpTitleChanges) {
+ mTitleChanges = new StringBuffer();
+ }
+ mDumpTitleChanges = true;
+ }
+
+ public void keepWebHistory() {
+ if (!mKeepWebHistory) {
+ mWebHistory = new Vector();
+ }
+ mKeepWebHistory = true;
+ }
+
+ public void queueBackNavigation(int howfar) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void queueForwardNavigation(int howfar) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void queueLoad(String Url, String frameTarget) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void queueReload() {
+ mWebView.reload();
+ }
+
+ public void queueScript(String scriptToRunInCurrentContext) {
+ mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext);
+ }
+
+ public void repaintSweepHorizontally() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAcceptsEditing(boolean b) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setMainFrameIsFirstResponder(boolean b) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setWindowIsKey(boolean b) {
+ // This is meant to show/hide the window. The best I can find
+ // is setEnabled()
+ mWebView.setEnabled(b);
+ }
+
+ public void testRepaint() {
+ mWebView.invalidate();
+ }
+
+ // Instrumentation calls this to find
+ // if the activity has finished running the layout tests
+ // TODO(fqian): need to sync on mFinisheRunning
+ public boolean hasFinishedRunning() {
+ return mFinishedRunning;
+ }
+
+ private final WebChromeClient mChromeClient = new WebChromeClient() {
+ @Override
+ public void onProgressChanged(WebView view, int newProgress) {
+ if (newProgress == 100) {
+ if (!mSingleTestMode && !mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) {
+ String url = mWebView.getUrl();
+ Log.v(LOGTAG, "Finished: "+ url);
+ mHandler.removeMessages(MSG_TIMEOUT);
+ requestWebKitData();
+ } else {
+ String url = mWebView.getUrl();
+ if (mSingleTestMode) {
+ Log.v(LOGTAG, "Single test mode: " + url);
+ } else if (mTimedOut) {
+ Log.v(LOGTAG, "Timed out before finishing: " + url);
+ } else if (mWaitUntilDone) {
+ Log.v(LOGTAG, "Waiting for notifyDone: " + url);
+ } else if (mRequestedWebKitData) {
+ Log.v(LOGTAG, "Requested webkit data ready: " + url);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onReceivedTitle(WebView view, String title) {
+ if (title.length() > 30)
+ title = "..."+title.substring(title.length()-30);
+ setTitle(title);
+ if (mDumpTitleChanges) {
+ mTitleChanges.append("TITLE CHANGED: ");
+ mTitleChanges.append(title);
+ mTitleChanges.append("\n");
+ }
+ }
+
+ @Override
+ public boolean onJsAlert(WebView view, String url, String message,
+ JsResult result) {
+ if (mDialogStrings == null) {
+ mDialogStrings = new StringBuffer();
+ }
+ mDialogStrings.append("ALERT: ");
+ mDialogStrings.append(message);
+ mDialogStrings.append('\n');
+ result.confirm();
+ return true;
+ }
+
+ @Override
+ public boolean onJsConfirm(WebView view, String url, String message,
+ JsResult result) {
+ if (mDialogStrings == null) {
+ mDialogStrings = new StringBuffer();
+ }
+ mDialogStrings.append("CONFIRM: ");
+ mDialogStrings.append(message);
+ mDialogStrings.append('\n');
+ result.confirm();
+ return true;
+ }
+
+ @Override
+ public boolean onJsPrompt(WebView view, String url, String message,
+ String defaultValue, JsPromptResult result) {
+ if (mDialogStrings == null) {
+ mDialogStrings = new StringBuffer();
+ }
+ mDialogStrings.append("PROMPT: ");
+ mDialogStrings.append(message);
+ mDialogStrings.append(", default text: ");
+ mDialogStrings.append(defaultValue);
+ mDialogStrings.append('\n');
+ result.confirm();
+ return true;
+ }
+ };
+
+ private void resetTestStatus() {
+ mWaitUntilDone = false;
+ mDumpAsText = false;
+ mTimedOut = false;
+ mDumpTitleChanges = false;
+ mRequestedWebKitData = false;
+ mEventSender.resetMouse();
+ }
+
+ private TestRecorder mResultRecorder;
+ private HTMLHostCallbackInterface mCallback = null;
+ private CallbackProxy mCallbackProxy;
+
+ private WebView mWebView;
+ private WebViewEventSender mEventSender;
+
+ private Vector<String> mTestList;
+ private int mTestIndex;
+
+ private int mTimeoutInMillis;
+ private String mTestPathPrefix;
+ private boolean mSingleTestMode;
+
+ private AsyncHandler mHandler;
+ private boolean mFinishedRunning;
+
+ private boolean mTimedOut;
+ private boolean mRequestedWebKitData;
+ private boolean mDumpAsText;
+ private boolean mWaitUntilDone;
+ private boolean mDumpTitleChanges;
+
+ private StringBuffer mTitleChanges;
+ private StringBuffer mDialogStrings;
+
+ private boolean mKeepWebHistory;
+ private Vector mWebHistory;
+
+ static final String TIMEOUT_STR = "**Test timeout";
+
+ static final int MSG_TIMEOUT = 0;
+ static final int MSG_WEBKIT_DATA = 1;
+
+ static final String LOGTAG="DumpRenderTree";
+
+ static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/";
+ static final String LAYOUT_TESTS_LIST_FILE = "/sdcard/layout_tests_list.txt";
+ static final String TEST_STATUS_FILE = "/sdcard/running_test.txt";
+
+ static final String RESUME_FROM_CRASH = "ResumeFromCrash";
+ static final String TEST_PATH_PREFIX = "TestPathPrefix";
+ static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
+ static final String SINGLE_TEST_MODE = "SingleTestMode";
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostApp.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostApp.java
new file mode 100644
index 0000000..f610f5a
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostApp.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import android.app.Application;
+
+public class HTMLHostApp extends Application {
+
+ public HTMLHostApp() {
+ }
+
+ public void onCreate() {
+ }
+
+ public void onTerminate() {
+ }
+
+}
+
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java
new file mode 100644
index 0000000..60a2915
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+public interface HTMLHostCallbackInterface {
+ public void waitForFinish();
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
new file mode 100644
index 0000000..6166dd0
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+public interface LayoutTestController {
+
+ public void dumpAsText();
+ public void waitUntilDone();
+ public void notifyDone();
+
+ // Force a redraw of the page
+ public void display();
+ // Used with pixel dumps of content
+ public void testRepaint();
+
+ // If the page title changes, add the information to the output.
+ public void dumpTitleChanges();
+ public void dumpBackForwardList();
+ public void dumpChildFrameScrollPositions();
+ public void dumpEditingCallbacks();
+
+ // Show/Hide window for window.onBlur() testing
+ public void setWindowIsKey(boolean b);
+ // Mac function, used to disable events going to the window
+ public void setMainFrameIsFirstResponder(boolean b);
+
+ public void dumpSelectionRect();
+
+ // invalidate and draw one line at a time of the web view.
+ public void repaintSweepHorizontally();
+
+ // History testing functions
+ public void keepWebHistory();
+ public void clearBackForwardList();
+ // navigate after page load has finished
+ public void queueBackNavigation(int howfar);
+ public void queueForwardNavigation(int howfar);
+
+ // Reload when the page load has finished
+ public void queueReload();
+ // Execute the provided script in current context when page load has finished.
+ public void queueScript(String scriptToRunInCurrentContext);
+ // Load the provided URL into the provided frame
+ public void queueLoad(String Url, String frameTarget);
+
+ public void setAcceptsEditing(boolean b);
+
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
new file mode 100755
index 0000000..1f37405
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.dumprendertree;
+
+import junit.framework.TestSuite;
+import com.android.dumprendertree.LayoutTestsAutoTest;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import android.util.Log;
+import android.content.Intent;
+import android.os.Bundle;
+
+
+/**
+ * Instrumentation Test Runner for all MediaPlayer tests.
+ *
+ * Running all tests:
+ *
+ * adb shell am instrument \
+ * -w com.android.dumprendertree.LayoutTestsAutoRunner
+ */
+
+public class LayoutTestsAutoRunner extends InstrumentationTestRunner {
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(LayoutTestsAutoTest.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return LayoutTestsAutoRunner.class.getClassLoader();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ String path = (String) icicle.get("path");
+ LayoutTestsAutoTest.setLayoutTestDir(path);
+ String timeout_str = (String) icicle.get("timeout");
+ int timeout = 0; // default value
+ if (timeout_str != null) {
+ try {
+ timeout = Integer.parseInt(timeout_str);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ LayoutTestsAutoTest.setTimeoutInMillis(timeout);
+ }
+}
+
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
new file mode 100644
index 0000000..3e65f03
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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 com.android.dumprendertree;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Intent;
+
+import android.util.Log;
+import android.view.KeyEvent;
+
+import android.os.Bundle;
+import android.os.Message;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.dumprendertree.HTMLHostActivity;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase<Menu> {
+
+ private final static String LOGTAG = "LayoutTests";
+ private final static int DEFAULT_TIMEOUT_IN_MILLIS = 6000;
+ private static String layoutTestDir = null;
+ private static int mTimeoutInMillis = 0;
+
+ public LayoutTestsAutoTest() {
+ super("com.android.dumprendertree", Menu.class);
+ }
+
+ // This function writes the result of the layout test to
+ // Am status so that it can be picked up from a script.
+ public void passOrFailCallback(String file, boolean result) {
+ Instrumentation inst = getInstrumentation();
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(file, result);
+ inst.sendStatus(0, bundle);
+ }
+
+ public static void setTimeoutInMillis(int millis) {
+ mTimeoutInMillis = (millis > 0) ? millis : DEFAULT_TIMEOUT_IN_MILLIS;
+ }
+
+ public static void setLayoutTestDir(String name) {
+ if (name == null)
+ throw new AssertionError("Layout test directory cannot be null.");
+ layoutTestDir = HTMLHostActivity.LAYOUT_TESTS_ROOT + name;
+ Log.v("LayoutTestsAutoTest", " Only running the layout tests : " + layoutTestDir);
+ }
+
+ // Invokes running of layout tests
+ // and waits till it has finished running.
+ public void executeLayoutTests(boolean resume) {
+ Instrumentation inst = getInstrumentation();
+
+ {
+ Activity activity = getActivity();
+ Intent intent = new Intent();
+ intent.setClass(activity, HTMLHostActivity.class);
+ intent.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, resume);
+ intent.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, false);
+ intent.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, layoutTestDir);
+ intent.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, mTimeoutInMillis);
+ activity.startActivity(intent);
+ }
+
+ ActivityMonitor htmlHostActivityMonitor =
+ inst.addMonitor("com.android.dumprendertree.HTMLHostActivity", null, false);
+
+ HTMLHostActivity activity =
+ (HTMLHostActivity) htmlHostActivityMonitor.waitForActivity();
+
+ while (!activity.hasFinishedRunning()) {
+ // Poll every 5 seconds to determine if the layout
+ // tests have finished running
+ try {Thread.sleep(5000); } catch(Exception e){}
+ }
+
+ // Wait few more seconds so that results are
+ // flushed to the /sdcard
+ try {Thread.sleep(5000); } catch(Exception e){}
+
+ // Clean up the HTMLHostActivity activity
+ activity.finish();
+ }
+
+ public void generateTestList() {
+ try {
+ File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE);
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tests_list, false));
+ findTestsRecursively(bos, layoutTestDir);
+ bos.flush();
+ bos.close();
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Error when creating test list: " + e.getMessage());
+ }
+ }
+
+ private void findTestsRecursively(BufferedOutputStream bos, String dir) throws IOException {
+ Log.v(LOGTAG, "Searching tests under " + dir);
+
+ File d = new File(dir);
+ if (!d.isDirectory()) {
+ throw new AssertionError("A directory expected, but got " + dir);
+ }
+
+ String[] files = d.list();
+ for (int i = 0; i < files.length; i++) {
+ String s = dir + "/" + files[i];
+ if (FileFilter.ignoreTest(s)) {
+ Log.v(LOGTAG, " Ignoring: " + s);
+ continue;
+ }
+ if (s.toLowerCase().endsWith(".html")
+ || s.toLowerCase().endsWith(".xml")) {
+ bos.write(s.getBytes());
+ bos.write('\n');
+ continue;
+ }
+
+ File f = new File(s);
+ if (f.isDirectory()) {
+ findTestsRecursively(bos, s);
+ continue;
+ }
+
+ Log.v(LOGTAG, "Skipping " + s);
+ }
+ }
+
+ // Running all the layout tests at once sometimes
+ // causes the dumprendertree to run out of memory.
+ // So, additional tests are added to run the tests
+ // in chunks.
+ public void startLayoutTests() {
+ try {
+ File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE);
+ if (!tests_list.exists())
+ generateTestList();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ executeLayoutTests(false);
+ }
+
+ public void resumeLayoutTests() {
+ executeLayoutTests(true);
+ }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
new file mode 100644
index 0000000..de0da61
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import java.io.File;
+
+public class Menu extends FileList {
+
+ public void onCreate(Bundle icicle)
+ {
+ super.onCreate(icicle);
+ }
+
+ boolean fileFilter(File f) {
+ if (f.getName().startsWith("."))
+ return false;
+ if (f.getName().equalsIgnoreCase("resources"))
+ return false;
+ if (f.isDirectory())
+ return true;
+ if (f.getPath().toLowerCase().endsWith("ml"))
+ return true;
+ return false;
+ }
+
+ void processFile(String filename, boolean selection)
+ {
+ Intent result = new Intent();
+ result.setClass(this, HTMLHostActivity.class);
+ result.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, false);
+ result.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, true);
+ result.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, filename);
+ result.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, 8000);
+ startActivity(result);
+ }
+
+}
+
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
new file mode 100644
index 0000000..eea6346
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2007 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.dumprendertree;
+
+import android.webkit.WebView;
+import android.view.KeyEvent;
+import android.util.*;
+
+import java.util.Arrays;
+
+public class WebViewEventSender implements EventSender {
+
+ WebViewEventSender(WebView webView) {
+ mWebView = webView;
+ }
+
+ public void resetMouse() {
+ mouseX = mouseY = 0;
+ }
+
+ public void enableDOMUIEventLogging(int DOMNode) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void fireKeyboardEventsToElement(int DOMNode) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void keyDown(String character, String[] withModifiers) {
+ Log.e("EventSender", "KeyDown: " + character + "("
+ + character.getBytes()[0] + ") Modifiers: "
+ + Arrays.toString(withModifiers));
+ KeyEvent modifier = null;
+ if (withModifiers != null && withModifiers.length > 0) {
+ for (int i = 0; i < withModifiers.length; i++) {
+ int keyCode = modifierMapper(withModifiers[i]);
+ modifier = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+ mWebView.onKeyDown(modifier.getKeyCode(), modifier);
+ }
+ }
+ int keyCode = keyMapper(character.toLowerCase().toCharArray()[0]);
+ KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+ mWebView.onKeyDown(event.getKeyCode(), event);
+
+ }
+
+ public void keyDown(String character) {
+ keyDown(character, null);
+ }
+
+ public void leapForward(int milliseconds) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void mouseClick() {
+ mouseDown();
+ mouseUp();
+ }
+
+ public void mouseDown() {
+ /* KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
+ mWebView.onKeyDown(event.getKeyCode(), event); */
+ }
+
+ public void mouseMoveTo(int X, int Y) {
+ if (X > mouseX) {
+ KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
+ mWebView.onKeyDown(event.getKeyCode(), event);
+ mWebView.onKeyUp(event.getKeyCode(), event);
+ } else if ( X < mouseX ) {
+ KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
+ mWebView.onKeyDown(event.getKeyCode(), event);
+ mWebView.onKeyUp(event.getKeyCode(), event);
+ }
+ if (Y > mouseY) {
+ KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
+ mWebView.onKeyDown(event.getKeyCode(), event);
+ mWebView.onKeyUp(event.getKeyCode(), event);
+ } else if (Y < mouseY ) {
+ KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
+ mWebView.onKeyDown(event.getKeyCode(), event);
+ mWebView.onKeyUp(event.getKeyCode(), event);
+ }
+ mouseX= X;
+ mouseY= Y;
+
+ }
+
+ public void mouseUp() {
+ /* KeyEvent event = new KeyEvent(
+ KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
+ mWebView.onKeyDown(event.getKeyCode(), event);*/
+
+ }
+
+ // Assumes lowercase chars, case needs to be
+ // handled by calling function.
+ static int keyMapper(char c) {
+ // handle numbers
+ if (c >= '0' && c<= '9') {
+ int offset = c - '0';
+ return KeyEvent.KEYCODE_0 + offset;
+ }
+
+ // handle characters
+ if (c >= 'a' && c <= 'z') {
+ int offset = c - 'a';
+ return KeyEvent.KEYCODE_A + offset;
+ }
+
+ // handle all others
+ switch (c) {
+ case '*':
+ return KeyEvent.KEYCODE_STAR;
+ case '#':
+ return KeyEvent.KEYCODE_POUND;
+ case ',':
+ return KeyEvent.KEYCODE_COMMA;
+ case '.':
+ return KeyEvent.KEYCODE_PERIOD;
+ case '\t':
+ return KeyEvent.KEYCODE_TAB;
+ case ' ':
+ return KeyEvent.KEYCODE_SPACE;
+ case '\n':
+ return KeyEvent.KEYCODE_ENTER;
+ case '\b':
+ case 0x7F:
+ return KeyEvent.KEYCODE_DEL;
+ case '~':
+ return KeyEvent.KEYCODE_GRAVE;
+ case '-':
+ return KeyEvent.KEYCODE_MINUS;
+ case '=':
+ return KeyEvent.KEYCODE_EQUALS;
+ case '(':
+ return KeyEvent.KEYCODE_LEFT_BRACKET;
+ case ')':
+ return KeyEvent.KEYCODE_RIGHT_BRACKET;
+ case '\\':
+ return KeyEvent.KEYCODE_BACKSLASH;
+ case ';':
+ return KeyEvent.KEYCODE_SEMICOLON;
+ case '\'':
+ return KeyEvent.KEYCODE_APOSTROPHE;
+ case '/':
+ return KeyEvent.KEYCODE_SLASH;
+ default:
+ break;
+ }
+
+ return c;
+ }
+
+ static int modifierMapper(String modifier) {
+ if (modifier.equals("ctrlKey")) {
+ return KeyEvent.KEYCODE_ALT_LEFT;
+ } else if (modifier.equals("shiftKey")) {
+ return KeyEvent.KEYCODE_SHIFT_LEFT;
+ } else if (modifier.equals("altKey")) {
+ return KeyEvent.KEYCODE_SYM;
+ } else if (modifier.equals("metaKey")) {
+ return KeyEvent.KEYCODE_UNKNOWN;
+ }
+ return KeyEvent.KEYCODE_UNKNOWN;
+ }
+
+ private WebView mWebView = null;
+ private int mouseX;
+ private int mouseY;
+
+}