diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
commit | f013e1afd1e68af5e3b868c26a653bbfb39538f8 (patch) | |
tree | 7ad6c8fd9c7b55f4b4017171dec1cb760bbd26bf /tests/DumpRenderTree | |
parent | e70cfafe580c6f2994c4827cd8a534aabf3eb05c (diff) | |
download | frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.zip frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.gz frameworks_base-f013e1afd1e68af5e3b868c26a653bbfb39538f8.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'tests/DumpRenderTree')
14 files changed, 1980 insertions, 0 deletions
diff --git a/tests/DumpRenderTree/Android.mk b/tests/DumpRenderTree/Android.mk new file mode 100644 index 0000000..505a436 --- /dev/null +++ b/tests/DumpRenderTree/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_JAVA_LIBRARIES := android.test.runner + +LOCAL_PACKAGE_NAME := DumpRenderTree + +include $(BUILD_PACKAGE) diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml new file mode 100644 index 0000000..8e06cc8 --- /dev/null +++ b/tests/DumpRenderTree/AndroidManifest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.dumprendertree"> + <application android:name="HTMLHostApp"> + <uses-library android:name="android.test.runner" /> + <activity android:name="Menu" android:label="1 Dump Render Tree"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.TEST" /> + </intent-filter> + </activity> + <activity android:name="HTMLHostActivity"> + </activity> + </application> + + <instrumentation android:name=".LayoutTestsAutoRunner" + android:targetPackage="com.android.dumprendertree" + android:label="Layout test automation runner" + /> +</manifest> 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..5a73759 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -0,0 +1,242 @@ +/* + * 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. + int size = ignoreTestList.length; + for (int i = 0; i < size; i ++) { + if (file.startsWith(ignoreTestList[i])) { + Log.e("FileFilter", "File path in IgnoreTest: " + 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 [] ignoreTestList = { + ".", // 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 + "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 + "001.html", + "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" + }; + + 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"); + 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..8b33d16 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java @@ -0,0 +1,160 @@ +/* + * 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 (path.length() > 0) + processFile(path, true); + + } + + /* + * 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"; + 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..9521f80 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java @@ -0,0 +1,607 @@ +/* + * 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.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Vector; +import java.util.Stack; + +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.*; +import android.test.TestRecorder; + +// SQLite3 in android has a bunch of bugs which +// is causing TestRecorder to not record the results +// properly. This class is a wrapper around it and records +// results in a file as well. +class TestRecorderV2 extends TestRecorder { + @Override + public void passed(String layout_file) { + try { + mBufferedOutputPassedStream.write(layout_file.getBytes()); + mBufferedOutputPassedStream.write('\n'); + mBufferedOutputPassedStream.flush(); + } catch(Exception e) { + e.printStackTrace(); + } + super.passed(layout_file); + } + + @Override + public void failed(String layout_file, String reason) { + try { + mBufferedOutputFailedStream.write(layout_file.getBytes()); + mBufferedOutputFailedStream.write('\n'); + mBufferedOutputFailedStream.flush(); + } catch(Exception e) { + e.printStackTrace(); + } + super.failed(layout_file, reason); + } + + public TestRecorderV2() { + super(); + try { + File resultsPassedFile = new File("/sdcard/layout_test_presults.txt"); + File resultsFailedFile = new File("/sdcard/layout_test_fresults.txt"); + + mBufferedOutputPassedStream = + new BufferedOutputStream(new FileOutputStream(resultsPassedFile, true)); + mBufferedOutputFailedStream = + new BufferedOutputStream(new FileOutputStream(resultsFailedFile, true)); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + protected void finalize() throws Throwable { + mBufferedOutputPassedStream.flush(); + mBufferedOutputFailedStream.flush(); + mBufferedOutputPassedStream.close(); + mBufferedOutputFailedStream.close(); + } + + private static BufferedOutputStream mBufferedOutputPassedStream; + private static BufferedOutputStream mBufferedOutputFailedStream; +} + +public class HTMLHostActivity extends Activity + implements LayoutTestController { + + private TestRecorderV2 mResultRecorder = new TestRecorderV2(); + private HTMLHostCallbackInterface mCallback = null; + private CallbackProxy mCallbackProxy; + + public class FileEntry { + public FileEntry(String path, int index) { + mPath = path; mIndex=index; + } + String mPath; + int mIndex; + } + + public class AsyncHandler extends Handler { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_DUMP) { + this.removeMessages(MSG_TIMEOUT); + mTimedOut = false; + requestWebKitData(); + return; + } else 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); + } + + void requestWebKitData() { + Message callback = obtainMessage(MSG_WEBKIT_DATA); + if (dumpAsText) { + 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); + eventSender = new WebViewEventSender(mWebView); + mCallbackProxy = new CallbackProxy(eventSender, this); + + 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); + } + + protected void onResume() { + super.onResume(); + if (mProcessStack == null || mProcessStack.isEmpty() ) { + mOutstandingLoads = 0; + dumpAsText = false; + pageComplete = false; + + mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); + + mFinishedStack = new Stack(); + + Intent intent = getIntent(); + if (intent.getData() != null) { + File f = new File(intent.getData().toString()); + + if (f.isDirectory()) { + mProcessStack = new Vector(); + mProcessStack.add(new FileEntry(intent.getData().toString(), 0)); + Log.v(LOGTAG, "Initial dir: "+intent.getData().toString()); + loadNextPage(); + } else { + mCurrentFile = intent.getData().toString(); + mWebView.loadUrl("file://"+intent.getData().toString()); + } + + } + else + mWebView.loadUrl("about:"); + } + } + + protected void onStop() { + super.onStop(); + mWebView.stopLoading(); + } + + protected void onDestroy() { + super.onDestroy(); + mWebView.destroy(); + mWebView = null; + } + + 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); + } + + // Functions + + protected void loadNextPage() { + dumpAsText = false; + pageComplete = false; + dumpTitleChanges = false; + eventSender.resetMouse(); + while (!mProcessStack.isEmpty()) { + FileEntry fe = (FileEntry)mProcessStack.remove(0); + if (fe.mIndex == 0) { + System.out.println(); + System.out.print(fe.mPath); + } + Log.v(LOGTAG, "Processing dir: "+fe.mPath+" size: "+mProcessStack.size()); + File f = new File(fe.mPath); + String [] files = f.list(); + for (int i = fe.mIndex; i < files.length; i++) { + if (FileFilter.ignoreTest(files[i])) { + continue; + } + File c = new File(f.getPath(), files[i]); + if (c.isDirectory()) { + Log.v(LOGTAG, "Adding dir: "+fe.mPath+"/"+files[i]); + mProcessStack.add(new FileEntry(fe.mPath+"/"+files[i], 0)); + } else if (files[i].toLowerCase().endsWith("ml")) { + mProcessStack.add(0, new FileEntry(fe.mPath, i+1)); + mCurrentFile = fe.mPath+"/"+files[i]; + Log.e(LOGTAG, "Processing: "+mCurrentFile); + mWebView.loadUrl("file://"+mCurrentFile); + + // Create a timeout timer + Message m = mHandler.obtainMessage(MSG_TIMEOUT); + // Some tests can take up to 5secs to run. + mHandler.sendMessageDelayed(m, 6000); + return; + } + } + Log.v(LOGTAG, "Finished dir: "+fe.mPath+" size: "+mProcessStack.size()); + } + // If we got to here, then we must have finished completely + finished(); + } + + public void scheduleDump() { + // Only schedule if we really are ready + if (waitToDump || mOutstandingLoads > 0 || mDumpRequested) { + return; + } + mDumpRequested = true; + mHandler.obtainMessage(MSG_DUMP).sendToTarget(); + } + + // Dump the page + public void dump(boolean timeout, String webkitData) { + mDumpRequested = false; + System.out.print('.'); + + // remove the extension + String resultFile = mCurrentFile.substring(0, mCurrentFile.lastIndexOf('.')); + + // store the finished file on the stack so that we can do a diff at the end. + mFinishedStack.push(resultFile); + + // dumpAsText version can be directly compared to expected results + if (dumpAsText) { + resultFile += "-results.txt"; + } else { + resultFile += "-android-results.txt"; + } + try { + FileOutputStream os = new FileOutputStream(resultFile); + if (timeout) { + Log.i("Layout test: Timeout", resultFile); + os.write("**Test timeout\n".getBytes()); + } + if (dumpTitleChanges) + 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(); + } + + if (mProcessStack != null) + loadNextPage(); + else + finished(); + } + + // Wrap up + public void failedCase(String file, String reason) { + Log.i("Layout test:", file + " failed" + reason); + mResultRecorder.failed(file, reason); + + file = file + ".html"; + 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) { + // Add the result to the sqlite database + Log.i("Layout test:", file + " passed"); + mResultRecorder.passed(file); + + file = file + ".html"; + 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 setCallback(HTMLHostCallbackInterface callback) { + mCallback = callback; + } + + public void finished() { + int passed = 0; + while (!mFinishedStack.empty()) { + Log.v(LOGTAG, "Comparing dump and reference"); + String file = (String)mFinishedStack.pop(); + + // Only check results that we can check, ie dumpAsText results + String dumpFile = file + "-results.txt"; + File f = new File(dumpFile); + if (f.exists()) { + try { + FileInputStream fr = new FileInputStream(file+"-results.txt"); + FileInputStream fe = new FileInputStream(file+"-expected.txt"); + + mResultRecorder.started(file); + + // If the length is different then they are different + int diff = fe.available() - fr.available(); + if (diff > 1 || diff < 0) { + failedCase(file, " different length"); + fr.close(); + fe.close(); + + mResultRecorder.finished(file); + continue; + } + 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(file, " @offset: "+i); + fail = true; + break; + } + } + if (br.length != be.length && be[be.length-1] == '\n') { + Log.d(LOGTAG, "Extra new line being ignore:" + file); + } + fr.close(); + fe.close(); + if (!fail) { + passed++; + passedCase(file); + } + } catch (FileNotFoundException ex) { + // TODO do something here + } catch (IOException ex) { + // Failed on available() or read() + } + mResultRecorder.finished(file); + } + } + + if (mCallback != null) { + mCallback.waitForFinish(); + } + + finish(); + } + + // LayoutTestController Functions + public void dumpAsText() { + dumpAsText = true; + String url = mWebView.getUrl(); + Log.v(LOGTAG, "dumpAsText called:"+url); + if (url.length() > 60) + url = url.substring(60); + } + + public void waitUntilDone() { + waitToDump = true; + } + public void notifyDone() { + waitToDump = 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 (!dumpTitleChanges) { + mTitleChanges = new StringBuffer(); + } + dumpTitleChanges = true; + } + + public void keepWebHistory() { + if (!keepWebHistory) { + mWebHistory = new Vector(); + } + keepWebHistory = 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 + public boolean hasFinishedRunning() { + if( mProcessStack == null || mFinishedStack == null) + return false; + + if (mProcessStack.isEmpty() && mFinishedStack.empty()) { + return true; + } + + return false; + } + + private final WebChromeClient mChromeClient = new WebChromeClient() { + @Override + public void onProgressChanged(WebView view, int newProgress) { + if (newProgress == 100) { + pageComplete = true; + String url = mWebView.getUrl(); + if (url != null) { + Log.v(LOGTAG, "Finished: "+ url); + if (url.length() > 60) + url = url.substring(60); + scheduleDump(); + } + } + } + + @Override + public void onReceivedTitle(WebView view, String title) { + if (title.length() > 30) + title = "..."+title.substring(title.length()-30); + setTitle(title); + if (dumpTitleChanges) { + 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'); + return false; + } + }; + + private WebView mWebView; + private WebViewEventSender eventSender; + private Vector mProcessStack; + private Stack mFinishedStack; + static final String LOGTAG="DumpRenderTree"; + private String mCurrentFile; + private int mOutstandingLoads; + private AsyncHandler mHandler; + private boolean mDumpRequested; + + private boolean dumpAsText; + private boolean waitToDump; + private boolean pageComplete; + + private boolean dumpTitleChanges; + private StringBuffer mTitleChanges; + + private StringBuffer mDialogStrings; + + private boolean keepWebHistory; + private Vector mWebHistory; + + private boolean mTimedOut; + + static final int MSG_DUMP = 0; + static final int MSG_TIMEOUT = 1; + static final int MSG_WEBKIT_DATA = 2; + +} 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..e0e535e --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java @@ -0,0 +1,48 @@ +/* + * 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; + + +/** + * 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(); + } +} + 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..f46b263 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -0,0 +1,157 @@ +/* + * 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.Instrumentation; +import android.app.Instrumentation.ActivityMonitor; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.util.Log; +import android.view.KeyEvent; + +import android.test.ActivityInstrumentationTestCase; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import com.android.dumprendertree.HTMLHostActivity; + +public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase<Menu> { + + private final static String LOGTAG = "LayoutTests"; + private final static String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/"; + + public LayoutTestsAutoTest() { + super("com.android.dumprendertree", Menu.class); + } + + // Invokes running of layout tests + // and waits till it has finished running. + public void executeLayoutTests(String folder) { + Instrumentation inst = getInstrumentation(); + getActivity().processFile(folder, true); + + ActivityMonitor htmlHostActivityMonitor = + inst.addMonitor("com.android.dumprendertree.HTMLHostActivity", null, false); + HTMLHostActivity activity = + (HTMLHostActivity) htmlHostActivityMonitor.waitForActivityWithTimeout(6000); + + 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){} + + return ; + } + + // 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. + @LargeTest + public void testAllLayoutTests() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast"); + } + + @LargeTest + public void testLayoutSubset1() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/backgrounds"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/borders"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/box-shadow"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/box-sizing"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/canvas"); + } + + @LargeTest + public void testLayoutSubset2() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/clip"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/compact"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/cookies"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/css"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/css-generated-content"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/doctypes"); + } + + @LargeTest + public void testLayoutSubset3() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/dom"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/dynamic"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/encoding"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/events"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/flexbox"); + } + + @LargeTest + public void testLayoutSubset4() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/forms"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/frames"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/gradients"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/history"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/html"); + } + + @LargeTest + public void testLayoutSubset5() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/images"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/inline"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/inline-block"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/innerHTML"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/invalid"); + } + + @LargeTest + public void testLayoutSubset6() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/js"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/layers"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/leaks"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/lists"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/loader"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/media"); + } + + @LargeTest + public void testLayoutSubset7() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/multicol"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/overflow"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/parser"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/profiler"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/reflections"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/regex"); + } + + @LargeTest + public void testLayoutSubset8() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/repaint"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/replaced"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/runin"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/selectors"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/table"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/text"); + } + + @LargeTest + public void testLayoutSubset9() { + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/tokenizer"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/transforms"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/xpath"); + executeLayoutTests(LAYOUT_TESTS_ROOT + "fast/xsl"); + } +} 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..2def8f3 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java @@ -0,0 +1,53 @@ +/* + * 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(null, Uri.parse(filename)); + result.setClass(this, HTMLHostActivity.class); + result.putExtra("ReturnWhenFinished", selection); + 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; + +} |