summaryrefslogtreecommitdiffstats
path: root/WebKitTools
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-05-21 16:53:46 +0100
committerKristian Monsen <kristianm@google.com>2010-05-25 10:24:15 +0100
commit6c2af9490927c3c5959b5cb07461b646f8b32f6c (patch)
treef7111b9b22befab472616c1d50ec94eb50f1ec8c /WebKitTools
parenta149172322a9067c14e8b474a53e63649aa17cad (diff)
downloadexternal_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.zip
external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.gz
external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.bz2
Merge WebKit at r59636: Initial merge by git
Change-Id: I59b289c4e6b18425f06ce41cc9d34c522515de91
Diffstat (limited to 'WebKitTools')
-rw-r--r--WebKitTools/ChangeLog1526
-rw-r--r--WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp207
-rw-r--r--WebKitTools/DumpRenderTree/DumpRenderTree.gypi36
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp1
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h1
-rw-r--r--WebKitTools/DumpRenderTree/chromium/EventSender.cpp153
-rw-r--r--WebKitTools/DumpRenderTree/chromium/EventSender.h28
-rw-r--r--WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp102
-rw-r--r--WebKitTools/DumpRenderTree/chromium/LayoutTestController.h21
-rw-r--r--WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp119
-rw-r--r--WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h70
-rw-r--r--WebKitTools/DumpRenderTree/chromium/TestShell.cpp4
-rw-r--r--WebKitTools/DumpRenderTree/chromium/TestShell.h6
-rw-r--r--WebKitTools/DumpRenderTree/chromium/TestWebWorker.h1
-rw-r--r--WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp36
-rw-r--r--WebKitTools/DumpRenderTree/chromium/WebViewHost.h22
-rw-r--r--WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp26
-rw-r--r--WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp17
-rw-r--r--WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm3
-rw-r--r--WebKitTools/DumpRenderTree/mac/EventSendingController.mm23
-rw-r--r--WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm11
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp20
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h2
-rw-r--r--WebKitTools/DumpRenderTree/qt/ImageDiff.cpp7
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp56
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h3
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp11
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h1
-rw-r--r--WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp15
-rw-r--r--WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp9
-rwxr-xr-xWebKitTools/DumpRenderTree/win/UIDelegate.cpp2
-rw-r--r--WebKitTools/QtTestBrowser/QtTestBrowser.pro (renamed from WebKitTools/QtLauncher/QtLauncher.pro)2
-rw-r--r--WebKitTools/QtTestBrowser/QtTestBrowser.qrc (renamed from WebKitTools/QtLauncher/QtLauncher.qrc)0
-rw-r--r--WebKitTools/QtTestBrowser/fpstimer.cpp (renamed from WebKitTools/QtLauncher/fpstimer.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/fpstimer.h (renamed from WebKitTools/QtLauncher/fpstimer.h)0
-rw-r--r--WebKitTools/QtTestBrowser/locationedit.cpp (renamed from WebKitTools/QtLauncher/locationedit.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/locationedit.h (renamed from WebKitTools/QtLauncher/locationedit.h)0
-rw-r--r--WebKitTools/QtTestBrowser/main.cpp (renamed from WebKitTools/QtLauncher/main.cpp)4
-rw-r--r--WebKitTools/QtTestBrowser/mainwindow.cpp (renamed from WebKitTools/QtLauncher/mainwindow.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/mainwindow.h (renamed from WebKitTools/QtLauncher/mainwindow.h)0
-rw-r--r--WebKitTools/QtTestBrowser/urlloader.cpp (renamed from WebKitTools/QtLauncher/urlloader.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/urlloader.h (renamed from WebKitTools/QtLauncher/urlloader.h)0
-rw-r--r--WebKitTools/QtTestBrowser/useragentlist.txt (renamed from WebKitTools/QtLauncher/useragentlist.txt)0
-rw-r--r--WebKitTools/QtTestBrowser/utils.cpp (renamed from WebKitTools/QtLauncher/utils.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/utils.h (renamed from WebKitTools/QtLauncher/utils.h)0
-rw-r--r--WebKitTools/QtTestBrowser/webinspector.h (renamed from WebKitTools/QtLauncher/webinspector.h)0
-rw-r--r--WebKitTools/QtTestBrowser/webpage.cpp (renamed from WebKitTools/QtLauncher/webpage.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/webpage.h (renamed from WebKitTools/QtLauncher/webpage.h)0
-rw-r--r--WebKitTools/QtTestBrowser/webview.cpp (renamed from WebKitTools/QtLauncher/webview.cpp)0
-rw-r--r--WebKitTools/QtTestBrowser/webview.h (renamed from WebKitTools/QtLauncher/webview.h)0
-rw-r--r--WebKitTools/QueueStatusServer/handlers/dashboard.py45
-rw-r--r--WebKitTools/QueueStatusServer/handlers/statusbubble.py37
-rw-r--r--WebKitTools/QueueStatusServer/handlers/updatestatus.py9
-rw-r--r--WebKitTools/QueueStatusServer/handlers/updateworkitems.py (renamed from WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_wsh.py)43
-rw-r--r--WebKitTools/QueueStatusServer/main.py3
-rw-r--r--WebKitTools/QueueStatusServer/model/attachment.py50
-rw-r--r--WebKitTools/QueueStatusServer/model/queues.py10
-rw-r--r--WebKitTools/QueueStatusServer/model/workitems.py (renamed from WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py)16
-rw-r--r--WebKitTools/QueueStatusServer/templates/dashboard.html56
-rw-r--r--WebKitTools/QueueStatusServer/templates/statusbubble.html52
-rw-r--r--WebKitTools/QueueStatusServer/templates/updateworkitems.html8
-rw-r--r--WebKitTools/Scripts/VCSUtils.pm376
-rwxr-xr-xWebKitTools/Scripts/build-dumprendertree15
-rwxr-xr-xWebKitTools/Scripts/build-webkit38
-rwxr-xr-xWebKitTools/Scripts/do-webcore-rename64
-rw-r--r--WebKitTools/Scripts/ensure-valid-python135
-rwxr-xr-xWebKitTools/Scripts/new-run-webkit-httpd1
-rw-r--r--WebKitTools/Scripts/new-run-webkit-websocketserver25
-rwxr-xr-xWebKitTools/Scripts/old-run-webkit-tests70
-rwxr-xr-xWebKitTools/Scripts/run-launcher2
-rwxr-xr-xWebKitTools/Scripts/run-webkit-websocketserver40
-rwxr-xr-xWebKitTools/Scripts/svn-apply86
-rwxr-xr-xWebKitTools/Scripts/svn-unapply6
-rw-r--r--WebKitTools/Scripts/webkitdirs.pm24
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl212
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl130
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl8
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl6
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl419
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl149
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl13
-rw-r--r--WebKitTools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl128
-rw-r--r--WebKitTools/Scripts/webkitpy/common/checkout/scm.py108
-rw-r--r--WebKitTools/Scripts/webkitpy/common/config/__init__.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/common/config/committers.py7
-rw-r--r--WebKitTools/Scripts/webkitpy/common/config/ports.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py6
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/bugzilla.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py33
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/rietveld.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/executive.py60
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py30
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/user.py16
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py28
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py20
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py56
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_results_uploader.py (renamed from WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_memorizingfile.py)67
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base.py11
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py7
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py7
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py39
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py8
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py138
-rwxr-xr-xWebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py18
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py12
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py32
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py25
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/win.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py41
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py88
-rwxr-xr-xWebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py42
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py27
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/__init__.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/COPYING28
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/MANIFEST.in6
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README6
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README.webkit14
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_client.py209
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/handler_map.txt11
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/__init__.py105
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/dispatch.py231
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/handshake.py220
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/headerparserhandler.py99
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/memorizingfile.py81
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/msgutil.py250
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py453
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/util.py121
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/setup.py63
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/config.py45
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/mock.py205
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_dispatch.py244
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_handshake.py513
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_mock.py126
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_msgutil.py156
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_util.py78
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/README1
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/blank_wsh.py31
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/origin_check_wsh.py42
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py44
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py45
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/plain_wsh.py40
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py45
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py45
-rw-r--r--WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/hello.pl2
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py12
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/download.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py23
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py46
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/queues.py19
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py20
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py41
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py32
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/upload.py11
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/mocktool.py26
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py19
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/checkstyle_unittest.py (renamed from WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/run_all.py)52
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py29
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/runtests.py5
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py26
164 files changed, 5087 insertions, 4658 deletions
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 70b10f0..3596d14 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,1529 @@
+2010-05-17 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r59631.
+ http://trac.webkit.org/changeset/59631
+ https://bugs.webkit.org/show_bug.cgi?id=39255
+
+ chromium canaries can no longer run webkit_tests, suspect this
+ change. (Requested by atwilson on #webkit).
+
+ * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-17 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ Attempt to make new-run-webkit-tests --help more sane
+ https://bugs.webkit.org/show_bug.cgi?id=37836
+
+ * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py:
+ - Add a FIXME about options.singly and options.batch_size being different.
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ - Add support for hidden options.
+ - Add option groupings to attempt to simplify --help.
+ - Fix a bunch of option helps to start with a capitalized verb.
+ - Hide a bunch of options which make no sense to users.
+ - Sort options in --help.
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+ - Add tests for option sorting.
+
+2010-05-17 Robert Hogan <robert@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Disable Icon Database by default in Qt DRT
+
+ Unskip:
+ http/tests/misc/favicon-loads-with-images-disabled.html
+ http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html
+ http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html
+ http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag.html
+
+ https://bugs.webkit.org/show_bug.cgi?id=37382
+
+ Add support for layoutTestController.setIconDatabaseEnabled and layoutTestController.disableImageLoading().
+ The XFrameOptions tests were failing because of an extra resource load callback for favicon.ico requests.
+ These extra callbacks are removed by supporting both of the above layoutTestContoller commands.
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::WebPage::resetSettings):
+ (WebCore::DumpRenderTree::DumpRenderTree):
+ * DumpRenderTree/qt/DumpRenderTreeQt.h:
+ (WebCore::DumpRenderTree::drtStoragePath):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::reset):
+ (LayoutTestController::disableImageLoading):
+ (LayoutTestController::setIconDatabaseEnabled):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2010-05-17 Fumitoshi Ukai <ukai@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ Chromium: Add --chromium option to new-run-webkit-websocketserver
+ https://bugs.webkit.org/show_bug.cgi?id=37664
+
+ os.environ setup and setup_mount for cygwin are moved in ChromiumWinPort.setup_environ_for_server.
+
+ * Scripts/new-run-webkit-httpd:
+ Remove passing register_cygwin.
+ * Scripts/new-run-webkit-websocketserver:
+ Add --chromium flag.
+ Remove passing register_cygwin.
+ Create port object using options.
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ Add setup_environ_for_server().
+ * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+ Ditto.
+ * Scripts/webkitpy/layout_tests/port/factory_unittest.py: Added.
+ * Scripts/webkitpy/layout_tests/port/http_server.py:
+ Remove register_cygwin_parameter.
+ Call setup_environ_for_server().
+ * Scripts/webkitpy/layout_tests/port/websocket_server.py:
+ Ditto.
+
+2010-05-16 Daniel Bates <dbates@rim.com>
+
+ Reviewed by Chris Jerdonek.
+
+ https://bugs.webkit.org/show_bug.cgi?id=39184
+
+ Adds function VCSUtils::parseSvnProperty to parse an SVN property with
+ either a single-line or multi-line value change.
+
+ * Scripts/VCSUtils.pm:
+ - Added function parseSvnProperty. We will use this function
+ towards resolving Bug #38885 <https://bugs.webkit.org/show_bug.cgi?id=38885>.
+ - Removed FIXME comment above function parseSvnPropertyValue, since
+ it is being used by parseSvnProperty.
+ - Modified function parseSvnPropertyValue to break out of "while (<$fileHandle>)"
+ loop when it encounters the start of the next property so that it can be
+ processed by its caller, parseSvnPropertyValue. We reference this bullet below
+ by (*).
+ * Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl: Added.
+ - Added unit tests.
+ * Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl:
+ - Changed the name of the unit test "simple multi-line '-' change" to
+ "single-line '-' change followed by empty line" since the former was an
+ incorrect description of this test.
+ - Added unit test "single-line '-' change followed by the next property", and
+ "multi-line '-' change followed by the next property" to test (*) above.
+
+2010-05-16 Tony Chang <tony@chromium.org>
+
+ Not reviewed, fixing layout test.
+
+ Don't output Inspect Element since this is not enabled on the bots,
+ but most developers probably have it installed.
+
+ * DumpRenderTree/mac/EventSendingController.mm:
+ (-[EventSendingController contextClick:]):
+
+2010-05-12 Tony Chang <tony@chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Spellcheck disabling does not disable context menu
+ https://bugs.webkit.org/show_bug.cgi?id=25639
+
+ * DumpRenderTree/mac/EventSendingController.mm:
+ (+[EventSendingController isSelectorExcludedFromWebScript:]):
+ (+[EventSendingController webScriptNameForSelector:]):
+ (-[EventSendingController contextClick:]): add a bool parameter that
+ when true, dumps the context menu items to stdout.
+
+2010-05-16 Robert Hogan <robert@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Unskip fast/loader/main-document-url-for-non-http-loads.html
+
+ Update Qt DRT to use frame loader, editor client and notification presenter
+ functions in DumpRenderTreeSupportQt.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38867
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::DumpRenderTree::open):
+ (WebCore::DumpRenderTree::dump):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::reset):
+ (LayoutTestController::dumpEditingCallbacks):
+ (LayoutTestController::dumpFrameLoadCallbacks):
+ (LayoutTestController::dumpResourceLoadCallbacks):
+ (LayoutTestController::setWillSendRequestReturnsNullOnRedirect):
+ (LayoutTestController::setWillSendRequestReturnsNull):
+ (LayoutTestController::setWillSendRequestClearHeader):
+
+2010-05-16 Eric Seidel <eric@webkit.org>
+
+ Unreviewed, rolling out r59571.
+ http://trac.webkit.org/changeset/59571
+ https://bugs.webkit.org/show_bug.cgi?id=39054
+
+ Broke Cr Win, but we didn't notice immediately due to
+ https://bugs.webkit.org/show_bug.cgi?id=38926. It's possible
+ that this didn't actually break Cr Win, but rather that bug
+ 38926 necessitates a clean compile after this and sucessive
+ checkins only produced a partial recompile and thus failed to
+ build.
+
+ * DumpRenderTree/chromium/WebViewHost.cpp:
+ (WebViewHost::canvas):
+
+2010-05-16 Robert Hogan <robert@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt]Unskip security/set-form-autocomplete-attribute.html
+
+ Add support for layoutTestController.elementDoesAutoCompleteForElementWithId().
+
+ https://bugs.webkit.org/show_bug.cgi?id=38859
+
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::elementDoesAutoCompleteForElementWithId):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2010-05-16 Kent Tamura <tkent@chromium.org>
+
+ Reviewed by Dimitri Glazkov.
+
+ [DRT/Chromium] Fix repaint, WebGL, textarea tests
+ https://bugs.webkit.org/show_bug.cgi?id=39054
+
+ * DumpRenderTree/chromium/WebViewHost.cpp:
+ (WebViewHost::canvas): Remove m_paintRect initialization in canvas().
+ This line updated m_paintRect unexpectedly during paintRect().
+ We don't need to initialize m_paintRect because show() does it.
+
+2010-05-16 Sergio Villar Senin <svillar@igalia.com>
+
+ Reviewed by Gustavo Noronha Silva.
+
+ [GTK] Improve reporting of frame loader callbacks in DRT
+ https://bugs.webkit.org/show_bug.cgi?id=36454
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (webViewLoadStatusNotified):
+ (createWebView): added connection to notify::load-status and
+ signal callback
+
+2010-05-15 Daniel Bates <dbates@rim.com>
+
+ Reviewed by Chris Jerdonek.
+
+ https://bugs.webkit.org/show_bug.cgi?id=39170
+
+ Add function parseSvnPropertyValue to parse single-line and multi-line
+ property values of an SVN property change.
+
+ * Scripts/VCSUtils.pm:
+ Added function parseSvnPropertyValue. We will use this as part of
+ Bug #38885 <https://bugs.webkit.org/show_bug.cgi?id=38885>.
+ * Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl: Added.
+
+2010-05-15 Jochen Eisinger <jochen@chromium.org>
+
+ Reviewed by Dmitry Titov.
+
+ Add allowDatabase method to TestWebWorker.
+ https://bugs.webkit.org/show_bug.cgi?id=38742
+
+ * DumpRenderTree/chromium/TestWebWorker.h:
+ (TestWebWorker::allowDatabase):
+
+2010-05-15 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Antti Koivisto.
+
+ [Qt] Rename QtLauncher to QtTestBrowser
+ https://bugs.webkit.org/show_bug.cgi?id=37665
+
+ Forgot to remove the original directory after the rename.
+
+ * QtLauncher: Removed.
+
+2010-05-15 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r59544.
+ http://trac.webkit.org/changeset/59544
+ https://bugs.webkit.org/show_bug.cgi?id=39165
+
+ Cased LayoutTest to start crashing (Requested by abarth on
+ #webkit).
+
+ * Scripts/old-run-webkit-tests:
+
+2010-05-15 Mario Sanchez Prada <msanchez@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ Ensure DRT loads GAIL (Gtk+ module), for a11y tests
+ https://bugs.webkit.org/show_bug.cgi?id=38648
+
+ Add the GTK_MODULES envvar (set to "gail") to the clean
+ environment when running DRT for the Gtk+ port
+
+ * Scripts/old-run-webkit-tests:
+
+2010-05-15 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej Stachowiak.
+
+ Add script to check for minimum python version and install if missing on Tiger
+ https://bugs.webkit.org/show_bug.cgi?id=38886
+
+ Per Maciej's request on webkit-dev:
+ https://lists.webkit.org/pipermail/webkit-dev/2010-May/012785.html
+ provide a script which can automatically install Python on Tiger where
+ the system provided version is too old to be of use.
+
+ Note this uses the official Mac Python installer from python.org.
+ This installs a copy of Python in /Library/Frameworks/Python.framework.
+ It also makes symlinks from /usr/local/bin to the Python.framework/bin.
+
+ I have tested this script on Leopard and it worked fine. I have not
+ tested it on Tiger as I do not have access to a Tiger machine. In
+ either case this should provide a great starting point for someone
+ wishing to upgrade their copy of Python on Tiger.
+
+ Future patches can make our scripts depend on a success return from this
+ script and then they can either skip tests/sections for which python is
+ insufficient, or they can fail themselves.
+
+ * Scripts/ensure-valid-python: Added.
+
+2010-05-15 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ Display queue position inside EWS bubbles
+ https://bugs.webkit.org/show_bug.cgi?id=38979
+
+ This ended up being a lot of clean-up to our status server code.
+
+ Added a new WorkItems model, a form with which to fill it,
+ and taught the Attachment class how to calculate the current queue
+ postion for an attachment using the data in WorkItems.
+
+ I also finally made statusbubble.* and dashboard.* not use copy-paste code.
+
+ The Attachment class has this summary() method which is very
+ controller/view-like and does not belong in a model class.
+ This patch got rid of all direct uses of summary().
+
+ * QueueStatusServer/handlers/dashboard.py:
+ - Build row objects to hand off to the view instead of handing off a
+ summary object and expecting the view to process it directly.
+ * QueueStatusServer/handlers/statusbubble.py:
+ - Build bubble object and hand them off to the view.
+ * QueueStatusServer/handlers/updatestatus.py:
+ - Code cleanup. Just move some code into _queue_status_from_request
+ to make the main put() handler easier to read.
+ * QueueStatusServer/handlers/updateworkitems.py: Added.
+ - Controller to handle storing WorkItems model objects.
+ * QueueStatusServer/main.py:
+ - Add route for /update-work-items
+ * QueueStatusServer/model/attachment.py:
+ - Add new methods to replace direct summary() access.
+ - Teach attachment how to calculate queue positions from WorkItems data.
+ * QueueStatusServer/model/queues.py:
+ - Move name_with_underscores here for easier re-use.
+ * QueueStatusServer/model/workitems.py: Added.
+ - New model for storing what items are currently queue for any bot.
+ * QueueStatusServer/templates/dashboard.html:
+ - Kill the copy/paste code!
+ * QueueStatusServer/templates/statusbubble.html:
+ - Kill the copy/paste code!
+ * QueueStatusServer/templates/updateworkitems.html: Added.
+ - Simple form for updating a queue's current work items.
+
+2010-05-15 Joanmarie Diggs <joanmarie.diggs@gmail.com>
+
+ Reviewed by Xan Lopez.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30500
+ [Gtk] Find a way for WebKit to "announce" itself so that ATs can readily distinguish it from true Gtk/Gail
+
+ The "announcement" is now made in the form of an object attribute
+ associated with the AtkObject.
+
+ * DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp:
+ (AccessibilityUIElement::allAttributes):
+ (attributeSetToString):
+
+2010-05-15 Mario Sanchez Prada <msanchez@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ Accessibility: Implement isSelected in DRT for GTK
+ https://bugs.webkit.org/show_bug.cgi?id=31018
+
+ Implement AccessibilityUIElement::isSelected() for Gtk
+
+ * DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp:
+ (AccessibilityUIElement::isSelected):
+
+2010-05-14 Adam Barth <abarth@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ scm.py should use self.run instead of run_command
+ https://bugs.webkit.org/show_bug.cgi?id=38957
+
+ We've wanted to do this for a while, but it's a prerequiste for running
+ SVN from the cwd instead of the checkout_root.
+
+ * Scripts/webkitpy/common/checkout/scm.py:
+
+2010-05-14 Anton Muhin <antonm@chromium.org>
+
+ Reviewed by Darin Fisher.
+
+ [Chromium] Consider implementing addOriginAccessWhitelistEntry method
+ https://bugs.webkit.org/show_bug.cgi?id=37578
+
+ Remove deprecated methods.
+
+ * DumpRenderTree/chromium/LayoutTestController.cpp
+ * DumpRenderTree/chromium/LayoutTestController.h
+
+2010-05-14 Kenneth Russell <kbr@google.com>
+
+ Reviewed by Darin Adler.
+
+ Rename WebGLArray types to TypedArray types
+ https://bugs.webkit.org/show_bug.cgi?id=39091
+
+ Extended functionality of do-webcore-rename script and used it to
+ rename the WebGLArray types to the TypedArray naming convention.
+ The only source files which were touched by hand, and which are
+ being manually reviewed, are:
+ WebCore/page/DOMWindow.idl
+ WebCore/bindings/generic/RuntimeEnabledFeatures.h (script's changes undone)
+ WebKit/WebCore/bindings/js/JSDOMWindowCustom.cpp
+ WebKit/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
+ These only needed to be touched to update the aliases between the
+ WebGLArray and TypedArray names introduced in bug 39036. (It was
+ not feasible to have do-webcore-rename handle this as it would
+ introduce circular renamings.) These aliases will be removed in
+ roughly a month once existing WebGL content has been updated.
+
+ No new tests; covered under existing WebGL tests. Updated
+ constructed-objects-prototypes and prototype-inheritance-2 tests.
+ Ran all layout tests in Safari and all WebGL tests in Chromium.
+
+ * Scripts/do-webcore-rename:
+ Handle the case where some renames are substrings of others.
+ Support renaming files containing custom JS bindings. If
+ isDOMTypeRename is non-zero, expand the regexp which rewrites
+ the file's contents in order to support custom JS bindings.
+
+2010-05-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ webkit-patch rollout throws exception if bug is already open
+ https://bugs.webkit.org/show_bug.cgi?id=38803
+
+ This was caused by someone incorrectly wrapping the code. :p
+ I'm going to have to start demanding unit tests for wrapping changes...
+
+ I also fixed the code to be able to reopen bugs which were never confirmed.
+ Before it regressed, the code would just log in that case. Now it actually
+ will reopen the bug, but there is a FIXME about how the logic is a bit backwards.
+
+ * Scripts/webkitpy/common/net/bugzilla.py:
+ * Scripts/webkitpy/common/net/bugzilla_unittest.py:
+ - Yay testing!
+
+2010-05-14 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Antti Koivisto.
+
+ [Qt] Rename QtLauncher to QtTestBrowser
+
+ * QtTestBrowser: Copied from WebKitTools/QtLauncher.
+ * QtTestBrowser/QtLauncher.pro: Removed.
+ * QtTestBrowser/QtLauncher.qrc: Removed.
+ * QtTestBrowser/QtTestBrowser.pro: Copied from WebKitTools/QtLauncher/QtLauncher.pro.
+ * QtTestBrowser/QtTestBrowser.qrc: Copied from WebKitTools/QtLauncher/QtLauncher.qrc.
+ * Scripts/run-launcher:
+ * Scripts/webkitdirs.pm:
+
+2010-05-14 Adam Barth <abarth@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ Stop CCing webkit-bot-watchers
+ https://bugs.webkit.org/show_bug.cgi?id=39020
+
+ webkit-bot-watchers is somewhat of a failed experiment. No one
+ subscribed to the list (not even me). Removing it from the code
+ because wms says it bounces email sometimes.
+
+ * Scripts/webkitpy/tool/commands/queues.py:
+ * Scripts/webkitpy/tool/commands/sheriffbot_unittest.py:
+
+2010-05-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ REGRESSION: webkit-patch commit-message throws exception
+ https://bugs.webkit.org/show_bug.cgi?id=38997
+
+ * Scripts/webkitpy/tool/commands/upload.py:
+ - Fix to respect and pass the --squash and --git-commit options.
+ * Scripts/webkitpy/tool/commands/upload_unittest.py:
+ - Fix the unit test to use the central MockCheckout instead of
+ its own custom Mock which didn't require enough parameters.
+
+2010-05-13 Diego Gonzalez <diegohcg@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Improve QtLauncher user agent dialog resize
+ https://bugs.webkit.org/show_bug.cgi?id=39062
+
+ * QtLauncher/main.cpp:
+ (LauncherWindow::showUserAgentDialog):
+
+2010-05-13 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Ojan Vafai.
+
+ Disable compositing/iframes tests on the commit-queue as a workaround for bug 38912
+ https://bugs.webkit.org/show_bug.cgi?id=39067
+
+ Fix yet another typo in my original hack.
+ I also added another unit test for this fix.
+
+ * Scripts/webkitpy/common/config/ports.py:
+ * Scripts/webkitpy/common/config/ports_unittest.py:
+
+2010-05-13 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Ojan Vafai.
+
+ Disable compositing/iframes tests on the commit-queue as a workaround for bug 38912
+ https://bugs.webkit.org/show_bug.cgi?id=39067
+
+ My previous (unreviewed) hack didn't actually work due to checking "mac" instead of "Mac".
+ This change fixes my hack, and unit tests it.
+
+ * Scripts/webkitpy/tool/mocktool.py:
+ - Make it possible to make run_command log too.
+ * Scripts/webkitpy/tool/steps/runtests.py:
+ - Fix my hack to actually work.
+ * Scripts/webkitpy/tool/steps/steps_unittest.py:
+ - Test my hack (and basic RunTests behavior as well).
+
+2010-05-13 Antonio Gomes <tonikitoo@webkit.org>, Yi Shen <yi.4.shen@nokia.com>
+
+ Reviewed by Kenneth Christiansen.
+
+ [Qt] Add LayoutTestController interface: computedStyleIncludingVisitedInfo
+ https://bugs.webkit.org/show_bug.cgi?id=37759
+
+ WebKitTools:
+
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::computedStyleIncludingVisitedInfo):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2010-05-10 Adam Roben <aroben@apple.com>
+
+ Convert status bar text to UTF-8 before logging it on Windows
+
+ We were previously logging the text using printf("%S", bstr). This
+ converts the UTF-16 BSTR to a multibyte string using wctomb, which
+ uses the codepage for the current locale to perform the conversion.
+ The conversion was failing, causing printf to bail and truncate the
+ string. By converting to UTF-8 manually before logging, we avoid this
+ issue (and also end up with UTF-8 output, which is what the expected
+ results contain). We may have to do this in other places in DRT,
+ eventually.
+
+ Fixes <http://webkit.org/b/38849> REGRESSION (r59016):
+ plugins/set-status.html fails on Windows
+
+ Reviewed by Alexey Proskuryakov.
+
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (toUTF8): Moved this here from FrameLoadDelegate. Renamed from
+ BSTRtoString.
+
+ * DumpRenderTree/win/DumpRenderTreeWin.h: Added declaration of toUTF8.
+
+ * DumpRenderTree/win/FrameLoadDelegate.cpp: Removed BSTRtoString.
+ (descriptionSuitableForTestResult): Updated for rename.
+
+ * DumpRenderTree/win/UIDelegate.cpp:
+ (UIDelegate::setStatusText): Convert the status bar text to UTF-8
+ before logging it so that Windows won't try (and fail) to convert it
+ to the current locale's codepage.
+
+2010-05-13 Eric Seidel <eric@webkit.org>
+
+ Unreviewed hack, attempting to get the commit-queue running again.
+
+ Disable compositing/iframes tests on the commit-queue as a workaround for bug 38912
+ https://bugs.webkit.org/show_bug.cgi?id=39067
+
+ I had this hack locally on the commit-queue, but it's fragile
+ and broke this morning. It will work much better if committed
+ to the repository. In either case it's temporary while we
+ work up a real fix for bug 38912.
+
+ * Scripts/webkitpy/common/config/ports.py:
+ - Expose an is_leopard() method.
+ * Scripts/webkitpy/tool/steps/runtests.py:
+ - Don't run compositing/iframes tests on the commit-queue under leopard.
+
+2010-05-13 Fumitoshi Ukai <ukai@chromium.org>
+
+ Unreviewed fix. Revert previous change.
+
+ Even if with-statments are changed in websocket_server.py, it also claims syntax error for with statement in http_server.py.
+ Until python 2.5 is installed on tiger bot, skips websocket/tests on tiger.
+
+ * Scripts/webkitpy/layout_tests/port/websocket_server.py: use with statement
+
+2010-05-13 Fumitoshi Ukai <ukai@chromium.org>
+
+ Unreviewed fix.
+
+ On tiger bot, it claims syntax error for with statement.
+
+ * Scripts/webkitpy/layout_tests/port/websocket_server.py: rewrite with statement with try-finally.
+
+2010-05-13 Fumitoshi Ukai <ukai@chromium.org>
+
+ Reviewed by David Levin.
+
+ WebSocket: pywebsocket 0.5
+ https://bugs.webkit.org/show_bug.cgi?id=38034
+
+ Remove pywebsocket from webkitpy/thirdparty.
+ Make pywebsocket autoinstalled.
+
+ * Scripts/new-run-webkit-websocketserver:
+ Add --output-dir option.
+ * Scripts/old-run-webkit-tests:
+ Use new-run-webkit-websocketserver, rather than directly run pywebsocket's standalone.py
+ * Scripts/run-webkit-websocketserver:
+ Ditto.
+ * Scripts/webkitpy/layout_tests/port/websocket_server.py:
+ Use autoinstalled pywebsocket.
+ * Scripts/webkitpy/thirdparty/__init__.py:
+ Autoinstall pywebsocket
+ * Scripts/webkitpy/thirdparty/pywebsocket: Removed.
+
+2010-05-12 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ Fixed a bug in svn-apply whereby the reviewer would not get set if
+ the portion of the patch for the ChangeLog contains "NOBODY (**PS!)"
+ in the leading junk.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38998
+
+ * Scripts/VCSUtils.pm:
+ - Added the $changeLogTimeZone variable from svn-apply.
+ - Added setChangeLogDateAndReviewer() from svn-apply.
+ - Added a localTimeInProjectTimeZone() subroutine.
+ - In setChangeLogDateAndReviewer():
+ - Added an $epochTime parameter to make the subroutine more testable.
+ - Made the "NOBODY (**PS!)" regular expression more specific so that
+ it will not apply to text in the leading junk.
+ - Updated to call localTimeInProjectTimeZone().
+ * Scripts/svn-apply:
+ - Removed the $changeLogTimeZone file variable.
+ - Added an $epochTime file variable to represent the current time.
+ - Removed the setChangeLogDateAndReviewer() subroutine.
+ - Updated patch() to use the new setChangeLogDateAndReviewer() syntax.
+ * Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl: Added.
+ - Added unit tests.
+
+2010-05-12 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ test-webkitpy fails on windows due to lack of readline module
+ https://bugs.webkit.org/show_bug.cgi?id=38884
+
+ Win32 Python does not have a readline module, so we should
+ not exit(1) if the import fails.
+
+ Also the failure message is mac-specific and doesn't need to be.
+ Only print the mac-specific install instructions on mac.
+
+ * Scripts/webkitpy/common/system/user.py:
+
+2010-05-12 Kent Tamura <tkent@chromium.org>
+
+ Reviewed by Nate Chapin.
+
+ [DRT/Chromium] Add a missing Sans-serif font setting
+ https://bugs.webkit.org/show_bug.cgi?id=38981
+
+ * DumpRenderTree/chromium/TestShell.cpp:
+ (TestShell::resetWebSettings):
+ Set "Helvetica" for Sans-serif. It is the same as the default setting of test_shell.
+
+2010-05-10 Ojan Vafai <ojan@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ webkit-patch upload --fancy-review now uses the bugzilla bug ID as the rietveld ID
+ https://bugs.webkit.org/show_bug.cgi?id=38866
+
+ wkrietveld.appspot.com has already been updated to allow you to
+ pass --issue for the issue creation as well as subsequent uploads.
+
+ Also, remove the extra code for trying to read out the issue ID
+ from the changelog description since we just use the bugzilla ID now.
+
+ * Scripts/webkitpy/common/config/__init__.py:
+ * Scripts/webkitpy/common/net/rietveld.py:
+ * Scripts/webkitpy/tool/steps/postcodereview.py:
+ * Scripts/webkitpy/tool/steps/postdiff.py:
+
+2010-05-12 Ojan Vafai <ojan@chromium.org>
+
+ No review needed.
+
+ Marking myself as a reviewer.
+
+ * Scripts/webkitpy/common/config/committers.py:
+
+2010-05-12 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ new-run-webkit-tests: add a --print default option so that you can
+ easily get the default output plus something (e.g., you can say
+ '--print default,config' instead of '--print misc,one-line-progress,
+ one-line-summary,unexpected,unexpected-results,updates,config'.
+
+ Also, add more unit tests for --verbose, --print everything, etc.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38877
+
+ * Scripts/webkitpy/layout_tests/layout_package/printing.py:
+ * Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py:
+
+2010-05-12 Csaba Osztrogonác <ossy@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ Qt build failures cause SheriffBot false positives
+ https://bugs.webkit.org/show_bug.cgi?id=38969
+
+ Add Qt bots back to the core builders, because bug fixed by r59261.
+
+ * Scripts/webkitpy/common/net/buildbot.py:
+ * Scripts/webkitpy/common/net/buildbot_unittest.py:
+
+2010-05-12 Csaba Osztrogonác <ossy@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Slave losts cause build break on bots
+ https://bugs.webkit.org/show_bug.cgi?id=38980
+
+ * Scripts/build-webkit: Remove 0 byte sized files from productDir before build.
+
+2010-05-12 Csaba Osztrogonác <ossy@webkit.org>
+
+ Unreviewed trivial fix after r59254.
+
+ * Scripts/old-run-webkit-tests:
+
+2010-05-12 Csaba Osztrogonác <ossy@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ run-webkit-tests --exit-after-N-failures should not count new tests as failures
+ https://bugs.webkit.org/show_bug.cgi?id=31829
+
+ * Scripts/old-run-webkit-tests:
+
+2010-05-12 James Robinson <jamesr@chromium.org>
+
+ Reviewed by Simon Fraser.
+
+ Disable smooth scrolling on OS X when running tests
+ https://bugs.webkit.org/show_bug.cgi?id=38964
+
+ Some tests (like fast/repaint/fixed-move-after-keyboard-scroll.html)
+ depend on smooth scrolling behavior. Since this is off by default
+ in Leopard and on by default in Snow Leopard, DRT should turn it
+ off always to ensure a consistent test environment.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues):
+
+2010-05-10 Rodrigo Belem <rodrigo.belem@openbossa.org>
+
+ Reviewed by Kenneth Christiansen , Simon Hausmann and Gustavo Noronha.
+
+ [Qt, Gtk] Allows build-webkit script to receive an install prefix as parameter
+ https://bugs.webkit.org/show_bug.cgi?id=26224
+
+ Added more parameters to build-webkit script, the --prefix for gkt
+ and --install-libs, --install-headers for qt. Now it is possible
+ to change the install prefix for gtk and install path for qt.
+
+ * Scripts/build-webkit:
+ * Scripts/webkitdirs.pm:
+
+2010-05-12 Philippe Normand <pnormand@igalia.com>
+
+ Unreviewed, added my IRC nickname.
+
+ * Scripts/webkitpy/common/config/committers.py:
+
+2010-05-11 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ Fixed two FIXME's in svn-apply: eliminated the unnecessary %copiedFiles
+ variable and changed gitKnowsOfFile() to use exitStatus().
+
+ https://bugs.webkit.org/show_bug.cgi?id=38862
+
+ * Scripts/svn-apply:
+
+2010-05-11 Eric Seidel <eric@webkit.org>
+
+ Unreviewed, just fixing python typo.
+
+ EWS bots should poll more often than every 5 minutes
+ https://bugs.webkit.org/show_bug.cgi?id=38968
+
+ Typo in _now(), add a unittest to prove I fixed it.
+
+ * Scripts/webkitpy/tool/bot/queueengine.py:
+ * Scripts/webkitpy/tool/bot/queueengine_unittest.py:
+
+2010-05-11 Adam Barth <abarth@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ Qt build failures cause SheriffBot false positives
+ https://bugs.webkit.org/show_bug.cgi?id=38969
+
+ The Qt buildbot randomly fails to compile occasionally because its
+ network connection causes SVn to leave zero-byte files around. These
+ compile failures confuse SheriffBot into thinking someone's patch
+ caused a build break.
+
+ In this patch, I've temporarily removed Qt from the list of core
+ builders. Ossy is working on a script to clean up the zero byte files.
+ Once that goes in, we can add Qt back to the core builders.
+
+ * Scripts/webkitpy/common/net/buildbot.py:
+ * Scripts/webkitpy/common/net/buildbot_unittest.py:
+
+2010-05-11 Adam Barth <abarth@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ sheriffbot is spammy.
+ https://bugs.webkit.org/show_bug.cgi?id=38936
+
+ Reduce sheriffbot spam by not warning about new blameworthy revisions
+ that can be explained by previously blamed revisions. This might cause
+ us to not warn about some real failures, but we're getting too much
+ spam from slow builders that have large blamelists (and we've already
+ poked the responsible folks using data from a fast builder).
+
+ * Scripts/webkitpy/tool/bot/sheriff_unittest.py:
+ - Removed unneeded import
+ * Scripts/webkitpy/tool/commands/sheriffbot.py:
+ - The logic change
+ * Scripts/webkitpy/tool/commands/sheriffbot_unittest.py:
+ - Tests of the change
+ * Scripts/webkitpy/tool/mocktool.py:
+ - Merged two declarations of MockBuilder
+
+2010-05-11 Tony Chang <tony@chromium.org>
+
+ Reviewed by David Levin.
+
+ [chromium] detect num processors to pass to make -j on Linux
+ https://bugs.webkit.org/show_bug.cgi?id=38833
+
+ * Scripts/webkitdirs.pm:
+
+2010-05-11 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ EWS bots should poll more often than every 5 minutes
+ https://bugs.webkit.org/show_bug.cgi?id=38968
+
+ We'll make them poll every 2 minutes to start with.
+ I'm going to re-write how polling works soon, so this is
+ a stop-gap to try and make the bots more responsive.
+
+ If Bill notices any additional load on bugzilla we'll drop
+ the polling frequency back to 5 minutes. He's historically said
+ that the EWS bots appear to be a drop in the bucket and thus
+ should be able to poll much more frequently w/o causing trouble.
+
+ * Scripts/webkitpy/tool/bot/queueengine.py:
+ * Scripts/webkitpy/tool/bot/queueengine_unittest.py:
+ - Add a test for sleep_message
+
+2010-05-11 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ commit-queue should commit rollouts without running tests
+ https://bugs.webkit.org/show_bug.cgi?id=38940
+
+ Most of this change is improving our test coverage for the commit-queue.
+ The only functional change is removing the --test flag when the commit-queue
+ is running in rollouts mode.
+
+ I added test coverage for status updates, and updated the commit-queue status
+ messages to distinguish rollout vs. normal landing mode in its empty queue
+ and land patch messages.
+
+ * Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py:
+ - Got rid of a bunch of copy/paste code using _default_expected_stderr
+ * Scripts/webkitpy/tool/commands/queues.py:
+ - Moved rollout patch filtering out of _validate_patches_in_commit_queue
+ so that we only have to check if the builders are green in one place.
+ - Make the "empty queue" message note which queue it is referring to.
+ - Don't pass --text to land-attachment when in rollout mode.
+ * Scripts/webkitpy/tool/commands/queues_unittest.py:
+ - Update results now that we're testing status updates.
+ - Test _can_build_and_test since I made a typo in that call while
+ writing this change and the unit tests failed to catch it!
+ * Scripts/webkitpy/tool/mocktool.py:
+ - Log status updates to make them testable in our unit tests.
+
+2010-05-11 Kent Tamura <tkent@chromium.org>
+
+ Reviewed by Dimitri Glazkov.
+
+ [DRT/Chromium] Apply recent changes of test_shell to DRT
+ https://bugs.webkit.org/show_bug.cgi?id=38895
+
+ Port the changes to test_shell during (r40492, r46810] of Chromium.
+ Highlights:
+ - Introduce NotificationPresenter
+ - Fix parameter mismatch of WebViewClient::startDragging()
+
+ This change fixes dozens of unexpected behaviors.
+
+ * DumpRenderTree/DumpRenderTree.gypi:
+ Add NotificationPresenter.{cpp,h}
+ * DumpRenderTree/chromium/EventSender.cpp:
+ (applyKeyModifier):
+ (EventSender::EventSender):
+ (EventSender::reset):
+ (EventSender::webview):
+ (EventSender::doDragDrop):
+ (EventSender::keyDown):
+ (EventSender::addTouchPoint):
+ (EventSender::clearTouchPoints):
+ (EventSender::releaseTouchPoint):
+ (EventSender::setTouchModifier):
+ (EventSender::updateTouchPoint):
+ (EventSender::cancelTouchPoint):
+ (EventSender::sendCurrentTouchEvent):
+ (EventSender::touchEnd):
+ (EventSender::touchMove):
+ (EventSender::touchStart):
+ (EventSender::touchCancel):
+ * DumpRenderTree/chromium/EventSender.h:
+ * DumpRenderTree/chromium/LayoutTestController.cpp:
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::reset):
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::setAuthorAndUserStylesEnabled):
+ (LayoutTestController::setScrollbarPolicy):
+ (LayoutTestController::setWillSendRequestClearHeader):
+ (LayoutTestController::callShouldCloseOnWebView):
+ (LayoutTestController::grantDesktopNotificationPermission):
+ (LayoutTestController::removeOriginAccessWhitelistEntry):
+ (LayoutTestController::addUserScript):
+ (LayoutTestController::addUserStyleSheet):
+ * DumpRenderTree/chromium/LayoutTestController.h:
+ * DumpRenderTree/chromium/NotificationPresenter.cpp: Added.
+ * DumpRenderTree/chromium/NotificationPresenter.h: Added.
+ * DumpRenderTree/chromium/TestShell.cpp:
+ (TestShell::TestShell):
+ (TestShell::runFileTest):
+ (TestShell::resetTestController):
+ * DumpRenderTree/chromium/TestShell.h:
+ (TestShell::eventSender):
+ (TestShell::notificationPresenter):
+ (TestShell::showDevTools):
+ * DumpRenderTree/chromium/WebViewHost.cpp:
+ (WebViewHost::createView):
+ (WebViewHost::createPopupMenu):
+ (WebViewHost::startDragging):
+ (WebViewHost::notificationPresenter):
+ (WebViewHost::createApplicationCacheHost):
+ (WebViewHost::willSendRequest):
+ (WebViewHost::updateAddressBar):
+ (WebViewHost::updateURL):
+ * DumpRenderTree/chromium/WebViewHost.h:
+ (WebViewHost::addClearHeader):
+ (WebViewHost::clearHeaders):
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ new-run-webkit-tests: fix a path-handling bug that was breaking the
+ dryrun ports on windows, and add a comment about why we don't run
+ the chromium dryrun tests by default on every port.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38796
+
+ * Scripts/webkitpy/layout_tests/port/dryrun.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-11 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Darin Adler.
+
+ <http://webkit.org/b/38941> build-webkit shouldn't always override ENABLE_FOO Xcode configuration settings
+
+ * Scripts/build-webkit: Don't pass the ENABLE setting to xcodebuild if the value matches the default.
+ This will lead to xcodebuild picking up the settings from FeatureDefines.xcconfig, and will aid in
+ revealing problems that are due to inconsistent values for settings across projects.
+
+2010-05-11 Mark Rowe <mrowe@apple.com>
+
+ Build fix.
+
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+
+2010-05-10 Ojan Vafai <ojan@chromium.org>
+
+ Reviewed by David Levin.
+
+ CheckStyle was eating script errors when there were local-commits and working copy changes
+ https://bugs.webkit.org/show_bug.cgi?id=38880
+
+ * Scripts/webkitpy/tool/steps/checkstyle.py:
+ * Scripts/webkitpy/tool/steps/checkstyle_unittest.py: Added.
+
+2010-05-11 Jian Li <jianli@chromium.org>
+
+ Reviewed by Dmitry Titov.
+
+ Expose FileReader interface.
+ https://bugs.webkit.org/show_bug.cgi?id=38609
+
+ * Scripts/build-webkit: turn on building FileReader for Apple's WebKit.
+
+2010-05-10 Tony Chang <tony@chromium.org>
+
+ Reviewed by Kent Tamura.
+
+ [chromium] Build DRT when running build-webkit --chromium
+ https://bugs.webkit.org/show_bug.cgi?id=38730
+
+ * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: Removed.
+ * Scripts/build-dumprendertree: This does nothing now.
+
+2010-05-10 Jon Honeycutt <jhoneycutt@apple.com>
+
+ REGRESSION(r59100): Added test is broken on many platforms.
+ https://bugs.webkit.org/show_bug.cgi?id=38881
+
+ Reviewed by Eric Seidel.
+
+ * DumpRenderTree/win/TestNetscapePlugin/main.cpp:
+ (NPP_Destroy):
+ Use pluginLog, rather than printf, to match other platforms.
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Unreviewed, build fix.
+
+ Fix a build failure caused by assuming the default platform in
+ a unit test for new-run-webkit-tests instead of specifying
+ --platform test.
+
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Unreviewed, build-fix
+
+ new-run-webkit-tests: fix test failure caused by me failing to update
+ the expected output. Also, run '--platform test' instead of
+ 'platform dryrun' since the former is guaranteed to work and the
+ latter isn't.
+
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by David Levin.
+
+ new-run-webkit-tests: looks like the unicode conversion broke
+ --print-last-failures and --retest-last-failures. Fixing.
+
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by David Levin.
+
+ Re-attempt to fix 38616 - newline handling in new-run-webkit-tests.
+ I didn't handle some cases correctly before and the solution was
+ confusing. The new patch assumes all calls to the printing module
+ don't have newlines, and will append newlines where necessary, just
+ like logging does.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38790
+
+ * Scripts/webkitpy/layout_tests/layout_package/metered_stream.py:
+ * Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py:
+ * Scripts/webkitpy/layout_tests/layout_package/printing.py:
+ * Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+2010-05-10 Kent Tamura <tkent@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Make tkent a reviewer
+ https://bugs.webkit.org/show_bug.cgi?id=38875
+
+ * Scripts/webkitpy/common/config/committers.py:
+
+2010-05-07 Jon Honeycutt <jhoneycutt@apple.com>
+
+ Crash closing window containing Flash plug-in
+ https://bugs.webkit.org/show_bug.cgi?id=38797
+ <rdar://problem/7935266>
+
+ Reviewed by Eric Seidel.
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp:
+ (pluginAllocate):
+ Initialize new member to false.
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h:
+ Added a new member.
+
+ * DumpRenderTree/win/TestNetscapePlugin/main.cpp:
+ (NPP_New):
+ Check whether the element has the "testGetURLOnDestroy" attribute, and
+ record that.
+ (NPP_Destroy):
+ If "testGetURLOnDestroy" is set, perform a load while destroying the
+ plug-in.
+
+2010-05-10 Eric Seidel <eric@webkit.org>
+
+ Reviewed by David Levin.
+
+ Executive.kill_* do not work with windows python
+ https://bugs.webkit.org/show_bug.cgi?id=38872
+
+ http://trac.webkit.org/changeset/57444 is where the original
+ breakage occurred.
+ http://trac.webkit.org/changeset/58314 is where the regression
+ started affecting chromium.
+
+ I have since learned that sys.platform has no "windows" value.
+ "win32" is always the value, under 32 or 64 bit windows
+
+ The tests for this code are not run anywhere because
+ test-webkitpy does not yet work on "win32". Mostly due to
+ depending on unixisms like "cat" and "yes".
+
+ * Scripts/webkitpy/common/system/executive.py:
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+
+2010-05-10 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ Fix a bug in rebaseline-chromium-webkit-tests where we would crash
+ instead of logging an error and exiting if it couldn't find either a
+ debug or a release build of the image diff binary.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38692
+
+ * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py:
+ * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py: Added.
+
+2010-05-10 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ new-run-webkit-tests fails when run under sys.platform == "windows" due to undefined signal.SIGKILL
+ https://bugs.webkit.org/show_bug.cgi?id=38861
+
+ * Scripts/webkitpy/common/system/executive.py:
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+
+2010-05-10 Jer Noble <jer.noble@apple.com>
+
+ Unreviewed.
+
+ Adding myself as a committer.
+
+ * Scripts/webkitpy/common/config/committers.py:
+
+2010-05-10 Hans Wennborg <hans@chromium.org>
+
+ Reviewed by Jeremy Orlow.
+
+ [Chromium] Add quota parameter to WebViewClient::createSessionStorageNamespace()
+ https://bugs.webkit.org/show_bug.cgi?id=38750
+
+ Put a per-origin quota on session storage since it is using memory in
+ the browser process, and should not be allowed to grow arbitrarily
+ large. See also http://trac.webkit.org/changeset/58828.
+
+ * DumpRenderTree/chromium/WebViewHost.cpp:
+ (WebViewHost::createSessionStorageNamespace):
+ * DumpRenderTree/chromium/WebViewHost.h:
+
+2010-05-10 Csaba Osztrogonác <ossy@webkit.org>
+
+ Rubber-stamped by Simon Hausmann.
+
+ [Qt] Roll-out r59020 and r59021, because the Qt part of these changes
+ haven't been landed in Qt trunk yet. Should be rolled-in again after the merge.
+
+ https://bugs.webkit.org/show_bug.cgi?id=32967
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::WebPage::WebPage):
+ (WebCore::DumpRenderTree::DumpRenderTree):
+ * DumpRenderTree/qt/DumpRenderTreeQt.h:
+
+2010-05-09 Daniel Bates <dbates@rim.com>
+
+ Reviewed by Chris Jerdonek.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38812
+
+ Make the regular expressions for parsing the start of an SVN
+ and Git header global variables since they are used throughout
+ VCSUtils.pm.
+
+ * Scripts/VCSUtils.pm:
+
+2010-05-09 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ Finished moving the header-parsing logic from svn-apply and -unapply
+ to VCSUtils.pm's parsing methods.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38802
+
+ * Scripts/VCSUtils.pm:
+ - Added to parseGitDiffHeader() the ability to parse and store
+ whether a file is new or deleted.
+ - Also reordered in parseGitDiffHeader() some of the else statements
+ to a more readable ordering.
+ - Added to parseSvnDiffHeader() the ability to parse and store
+ whether a file is new.
+ * Scripts/svn-apply:
+ - Changed handleGitBinaryChange() to use the new "isNew" and "isDeletion"
+ diffHash key-values.
+ - Changed patch() to use the new "isNew" diffHash key-value.
+ * Scripts/svn-unapply:
+ - Changed patch() to use the new "isNew" and "isDeletion" diffHash key-values.
+ * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl:
+ - Added unit tests for new and deleted files.
+ * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl:
+ - Updated the unit tests as necessary.
+ - Added a unit test for a deleted file.
+ * Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl:
+ - Updated the unit tests as necessary.
+
+2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ Added to svn-apply support for git renames and copies with similarity
+ index less than 100%.
+
+ https://bugs.webkit.org/show_bug.cgi?id=32834
+
+ * Scripts/VCSUtils.pm:
+ - Added to parseGitDiffHeader() support for renames and similarity
+ index less than 100%.
+ - Added to parseDiff() support for processing renames, renames with
+ changes, and copies with changes.
+ - Added to parsePatch() the ability to process multiple return
+ values from parseDiff().
+ * Scripts/svn-apply:
+ - Added to patch() the ability to process diff hashes with the
+ isDeletion key-value set.
+ * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl:
+ - Updated the unit tests as necessary.
+ - Added unit tests for rename with similarity index 100%,
+ rename with similarity index < 100%, and rename with a change
+ to the executable bit.
+ * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl:
+ - Added unit tests for rename with similarity index 100%,
+ rename with similarity index < 100%, and rename with a change
+ to the executable bit.
+ * Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl:
+ - Updated the unit tests as necessary.
+ * Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl:
+ - Simplified the carriage-return unit test to more narrowly test
+ only carriage returns.
+
+2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ This revision suppresses the misleading "error: pathspec..." messages
+ when using svn-apply to add a binary file from a Git diff.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38047
+
+ When adding a new binary file from a Git diff, svn-apply prints
+ a misleading error of the form -- "error: pathspec '<filename>' did
+ not match any file(s) known to git. Did you forget to 'git add'?"
+ This patch suppresses these messages since they are normal.
+
+ * Scripts/VCSUtils.pm:
+ Added the callSilently() subroutine from runPatchCommand.pl, which
+ executes a Perl function while suppressing STDERR.
+ * Scripts/svn-apply:
+ Refactored the Git portion of scmKnowsOfFile() into a
+ gitKnowsOfFile(), and called this new subroutine using callSilently().
+ * Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl:
+ Removed callSilently() since it was moved to VCSUtils.pm in this patch.
+
+2010-05-08 Victor Wang <victorw@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ [chromium]: Upload test results json files to app engine server
+ Add an option to run_webkit_tests.py to upload generated
+ JSON files to app engine server. These JSON files will be used
+ by chromium layout test falkiness dashboard.
+
+ https://bugs.webkit.org/show_bug.cgi?id=36063
+
+ * Scripts/webkitpy/layout_tests/layout_package/test_results_uploader.py: Added.
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+
+2010-05-08 Laszlo Gombos <laszlo.1.gombos@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Build the ImageDiff tool for all platforms including Windows and Symbian
+ https://bugs.webkit.org/show_bug.cgi?id=38706
+
+ Use qmath.h instead of math.h to make it portable.
+
+ * DumpRenderTree/qt/ImageDiff.cpp:
+ (main):
+
+2010-05-08 Robert Hogan <robert@roberthogan.net>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Fix http/tests/xmlhttprequest/cross-origin-no-authorization.html
+ and http/tests/xmlhttprequest/cross-origin-authorization.html
+
+ QHttpNetworkRequest adds Authorization and Cookie headers to XHRs
+ without knowing if this is valid behaviour or not. In order to allow
+ Qt to decide whether Cookie/Authorization headers should be added
+ to an XHR QtWebKit needs to use an attribute added to QNetworkRequest.
+ These new attributes are: QNetworkRequest::CookieLoadControlAttribute,
+ QNetworkRequest::CookieSaveControlAttribute,and
+ QNetworkRequest::AuthenticationReuseControlAttribute.
+
+ In order to properly support the tests, Qt's DRT needs to use one
+ NetworkAccessManager for all pages. This allows it to use cached
+ credentials where appropriate.
+
+ The tests now pass when run individually but there seems to be a problem with
+ leaking the results of requests across tests when run with the others in
+ http/tests. This will be addressed in a separate patch.
+
+ https://bugs.webkit.org/show_bug.cgi?id=32967
+
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::WebPage::WebPage):
+ (WebCore::DumpRenderTree::DumpRenderTree):
+ * DumpRenderTree/qt/DumpRenderTreeQt.h:
+
+
+2010-05-04 Robert Hogan <robert@webkit.org>
+
+ Reviewed by Eric Seidel.
+
+ [Qt] unskip http/tests/plugins/npapi-response-headers.html
+
+ Turns out this failed because run-webkit-tests was eating the first occurrence
+ of 'Content-Type: text/plain' in the test output as a header. Strange but true.
+ So do as Chromium does and preface all text dumps with the
+ 'Content-Type: text/plain' header.
+
+ https://bugs.webkit.org/show_bug.cgi?id=38541
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::DumpRenderTree::dump):
+
+2010-05-08 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ test-webkitpy fails under cygwin
+ https://bugs.webkit.org/show_bug.cgi?id=38718
+
+ * Scripts/webkitpy/common/system/executive.py:
+ - Add _KILL_PROCESS_KILLED_PROCESS_EXIT_CODE and
+ _KILL_ALL_KILLED_PROCESS_EXIT_CODE to store the expected
+ exit codes of processes killed by kill_process and kill_all.
+ These two constants are only used by the unit tests but are
+ stored in executive.py so they can be right next to the platform ifs.
+ - Remove unnecessary str() conversion, run_command does that for us.
+ - Make os.kill retry on cygwin on EAGAIN. It's unclear why CYGWIN
+ throws EAGAIN, but it only does so sometimes. 3 may not be enough
+ retries, but we'll try it to start with.
+ - Add _windows_image_name to automatically convert "yes" to "yes.exe"
+ for use with taskkill.exe /im. Various callers to kill_all could
+ be updated to remove the .exe, but that can be done in another patch.
+ - Use taskkill.exe for killall on cygwin.
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+ - Use the new *_KILLED_PROCESS_EXIT_CODE constants which are correctly
+ set to 0 on windows/cygwin systems where taskkill.exe is used.
+ - Test _windows_image_name
+ * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+ - Add FIXME about including mac-snowleopard in baseline_search_path.
+ * Scripts/webkitpy/layout_tests/port/webkit.py:
+ - Make default_configuration actually read from the Configuration file.
+ * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: Added.
+ - Test default_configuration
+ * Scripts/webkitpy/layout_tests/port/win.py:
+ - Need a basic baseline_search_path if --platform dryrun is to work.
+
+2010-05-08 Eric Seidel <eric@webkit.org>
+
+ Unreviewed, just reverting commit.
+
+ REGRESSION(59000): r59000 contained all sorts of changes it should not have, needs revert.
+ https://bugs.webkit.org/show_bug.cgi?id=38798
+
+ * Scripts/webkitpy/common/system/executive.py:
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+ * Scripts/webkitpy/layout_tests/port/chromium_linux.py:
+ * Scripts/webkitpy/layout_tests/port/chromium_mac.py:
+ * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+ * Scripts/webkitpy/layout_tests/port/mac.py:
+ * Scripts/webkitpy/layout_tests/port/webkit.py:
+ * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: Removed.
+ * Scripts/webkitpy/layout_tests/port/win.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+ * Scripts/webkitpy/tool/commands/download.py:
+ * Scripts/webkitpy/tool/commands/download_unittest.py:
+
+2010-05-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ test-webkitpy fails under cygwin
+ https://bugs.webkit.org/show_bug.cgi?id=38718
+
+ * Scripts/webkitpy/common/system/executive.py:
+ - Add _KILL_PROCESS_KILLED_PROCESS_EXIT_CODE and
+ _KILL_ALL_KILLED_PROCESS_EXIT_CODE to store the expected
+ exit codes of processes killed by kill_process and kill_all.
+ These two constants are only used by the unit tests but are
+ stored in executive.py so they can be right next to the platform ifs.
+ - Remove unnecessary str() conversion, run_command does that for us.
+ - Make os.kill retry on cygwin on EAGAIN. It's unclear why CYGWIN
+ throws EAGAIN, but it only does so sometimes. 3 may not be enough
+ retries, but we'll try it to start with.
+ - Add _windows_image_name to automatically convert "yes" to "yes.exe"
+ for use with taskkill.exe /im. Various callers to kill_all could
+ be updated to remove the .exe, but that can be done in another patch.
+ - Use taskkill.exe for killall on cygwin.
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+ - Use the new *_KILLED_PROCESS_EXIT_CODE constants which are correctly
+ set to 0 on windows/cygwin systems where taskkill.exe is used.
+ - Test _windows_image_name
+ * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+ - Add FIXME about including mac-snowleopard in baseline_search_path.
+ * Scripts/webkitpy/layout_tests/port/webkit.py:
+ - Make default_configuration actually read from the Configuration file.
+ * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: Added.
+ - Test default_configuration
+ * Scripts/webkitpy/layout_tests/port/win.py:
+ - Need a basic baseline_search_path if --platform dryrun is to work.
+
+ 2010-05-07 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Nikolas Zimmermann.
+
+ DryrunTest fails on every platform other than mac
+ https://bugs.webkit.org/show_bug.cgi?id=38796
+
+ The test uses the port detection logic to find a suitable
+ port to use results from. However that detection logic assumes
+ chromium on linux, which requires a chromium checkout which the
+ bots don't have. The test is broken and we'll need to fix it.
+ For now I'm just going to disable the test on all platforms besides mac.
+
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py:
+
+ 2010-05-07 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ Clean up baseline_search_path to use map to reduce copy/paste code
+ https://bugs.webkit.org/show_bug.cgi?id=38792
+
+ Reading which portnames a port falls back to is easier if
+ we convert port names to paths with map instead of using copy/paste code.
+
+ * Scripts/webkitpy/layout_tests/port/chromium_linux.py:
+ * Scripts/webkitpy/layout_tests/port/chromium_mac.py:
+ * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+ * Scripts/webkitpy/layout_tests/port/mac.py:
+
+ 2010-05-07 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Daniel Bates.
+
+ rollout commands fail when commit is missing bug number
+ https://bugs.webkit.org/show_bug.cgi?id=38791
+
+ * Scripts/webkitpy/tool/commands/download.py:
+ - _commit_info failed to actually return the CommitInfo in the no-bug-id case.
+ * Scripts/webkitpy/tool/commands/download_unittest.py:
+ - Test that the fix worked.
+
+2010-05-07 Darin Fisher <darin@chromium.org>
+
+ Fix build bustage: toElement<T> should be to<T>.
+
+ * DumpRenderTree/chromium/LayoutTestController.cpp:
+ (LayoutTestController::elementDoesAutoCompleteForElementWithId):
+
2010-05-07 Chris Jerdonek <cjerdonek@webkit.org>
Reviewed by Daniel Bates.
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp b/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp
deleted file mode 100644
index 7167bf2..0000000
--- a/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp
+++ /dev/null
@@ -1,207 +0,0 @@
-#
-# Copyright (C) 2010 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-{
- 'includes': [
- '../../../WebKit/chromium/features.gypi',
- ],
- 'variables': {
- 'webkit_top': '../../..',
- 'webkit_api_dir': '<(webkit_top)/WebKit/chromium',
- 'conditions': [
- # Location of the chromium src directory and target type is different
- # if webkit is built inside chromium or as standalone project.
- ['inside_chromium_build==0', {
- # DumpRenderTree is being built outside of the full chromium project.
- # e.g. via build-dumprendertree --chromium
- 'chromium_src_dir': '<(webkit_api_dir)',
- 'webkit_support_gyp': '<(webkit_api_dir)/webkit/support/webkit_support.gyp',
- },{
- # WebKit is checked out in src/chromium/third_party/WebKit
- 'chromium_src_dir': '<(webkit_top)/../..',
- 'webkit_support_gyp': '<(webkit_top)/../../webkit/webkit.gyp',
- }],
- ],
- },
- 'target_defaults': {
- 'target_conditions': [
- ['OS!="linux" and OS!="freebsd" and OS!="openbsd"', {
- 'sources/': [
- ['exclude', '(Gtk|Linux)\\.cpp$']
- ]
- }],
- ['OS!="win"', {
- 'sources/': [
- ['exclude', 'Win\\.cpp$'],
- ]
- }],
- ['OS!="mac"', {
- 'sources/': [
- # .mm is already excluded by common.gypi
- ['exclude', 'Mac\\.cpp$'],
- ]
- }],
- ],
- },
- 'targets': [
- {
- 'target_name': 'DumpRenderTree',
- 'type': 'executable',
- 'mac_bundle': 1,
- 'dependencies': [
- '<(webkit_api_dir)/WebKit.gyp:webkit',
- '<(webkit_top)/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:wtf_config',
- '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
- '<(chromium_src_dir)/third_party/npapi/npapi.gyp:npapi',
- '<(chromium_src_dir)/skia/skia.gyp:skia',
- '<(webkit_support_gyp):webkit_support',
- ],
- 'include_dirs': [
- '.',
- '<(webkit_api_dir)',
- '<(webkit_top)/JavaScriptCore',
- '<(chromium_src_dir)',
- ],
- 'defines': [
- # Technically not a unit test but require functions available only to
- # unit tests.
- 'UNIT_TEST',
- ],
- 'sources': [
- '../chromium/AccessibilityController.cpp',
- '../chromium/AccessibilityController.h',
- '../chromium/AccessibilityUIElement.cpp',
- '../chromium/AccessibilityUIElement.h',
- '../chromium/CppBoundClass.cpp',
- '../chromium/CppBoundClass.h',
- '../chromium/CppVariant.cpp',
- '../chromium/CppVariant.h',
- '../chromium/DumpRenderTree.cpp',
- '../chromium/EventSender.cpp',
- '../chromium/EventSender.h',
- '../chromium/LayoutTestController.cpp',
- '../chromium/LayoutTestController.h',
- '../chromium/MockSpellCheck.cpp',
- '../chromium/MockSpellCheck.h',
- '../chromium/PlainTextController.cpp',
- '../chromium/PlainTextController.h',
- '../chromium/TestNavigationController.cpp',
- '../chromium/TestNavigationController.h',
- '../chromium/TestShell.cpp',
- '../chromium/TestShell.h',
- '../chromium/TestShellGtk.cpp',
- '../chromium/TestShellMac.mm',
- '../chromium/TestShellWin.cpp',
- '../chromium/TextInputController.cpp',
- '../chromium/TextInputController.h',
- '../chromium/WebViewHost.cpp',
- '../chromium/WebViewHost.h',
- ],
- 'conditions': [
- ['OS=="mac"', {
- 'dependencies': ['LayoutTestHelper'],
- 'mac_bundle_resources': [
- '../qt/fonts/AHEM____.TTF',
- '../fonts/WebKitWeightWatcher100.ttf',
- '../fonts/WebKitWeightWatcher200.ttf',
- '../fonts/WebKitWeightWatcher300.ttf',
- '../fonts/WebKitWeightWatcher400.ttf',
- '../fonts/WebKitWeightWatcher500.ttf',
- '../fonts/WebKitWeightWatcher600.ttf',
- '../fonts/WebKitWeightWatcher700.ttf',
- '../fonts/WebKitWeightWatcher800.ttf',
- '../fonts/WebKitWeightWatcher900.ttf',
- ],
- 'actions': [
- {
- 'action_name': 'repack_locale',
- 'variables': {
- 'repack_path': '<(chromium_src_dir)/tools/data_pack/repack.py',
- 'pak_inputs': [
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.pak',
- ]},
- 'inputs': [
- '<(repack_path)',
- '<@(pak_inputs)',
- ],
- 'outputs': [
- '<(INTERMEDIATE_DIR)/repack/DumpRenderTree.pak',
- ],
- 'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
- 'process_outputs_as_mac_bundle_resources': 1,
- },
- ], # actions
- }], # mac
- ], # conditions
- },
-
- {
- 'target_name': 'ImageDiff',
- 'type': 'executable',
- 'dependencies': [
- '<(webkit_api_dir)/WebKit.gyp:webkit',
- '<(webkit_top)/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:wtf',
- '<(chromium_src_dir)/gfx/gfx.gyp:gfx',
- ],
- 'include_dirs': [
- '<(webkit_top)/JavaScriptCore',
- '<(chromium_src_dir)',
- ],
- 'sources': [
- '../chromium/ImageDiff.cpp',
- ],
- },
- ], # targets
-
- 'conditions': [
- ['OS=="mac"', {
- 'targets': [
- {
- 'target_name': 'LayoutTestHelper',
- 'type': 'executable',
- 'sources': ['../chromium/LayoutTestHelper.mm'],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
- ],
- },
- },
- ],
- }],
- ], # conditions
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.gypi b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi
new file mode 100644
index 0000000..693f02e
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi
@@ -0,0 +1,36 @@
+{
+ 'variables': {
+ 'drt_files': [
+ 'chromium/AccessibilityController.cpp',
+ 'chromium/AccessibilityController.h',
+ 'chromium/AccessibilityUIElement.cpp',
+ 'chromium/AccessibilityUIElement.h',
+ 'chromium/CppBoundClass.cpp',
+ 'chromium/CppBoundClass.h',
+ 'chromium/CppVariant.cpp',
+ 'chromium/CppVariant.h',
+ 'chromium/DumpRenderTree.cpp',
+ 'chromium/EventSender.cpp',
+ 'chromium/EventSender.h',
+ 'chromium/LayoutTestController.cpp',
+ 'chromium/LayoutTestController.h',
+ 'chromium/MockSpellCheck.cpp',
+ 'chromium/MockSpellCheck.h',
+ 'chromium/NotificationPresenter.h',
+ 'chromium/NotificationPresenter.cpp',
+ 'chromium/PlainTextController.cpp',
+ 'chromium/PlainTextController.h',
+ 'chromium/TestNavigationController.cpp',
+ 'chromium/TestNavigationController.h',
+ 'chromium/TestShell.cpp',
+ 'chromium/TestShell.h',
+ 'chromium/TestShellGtk.cpp',
+ 'chromium/TestShellMac.mm',
+ 'chromium/TestShellWin.cpp',
+ 'chromium/TextInputController.cpp',
+ 'chromium/TextInputController.h',
+ 'chromium/WebViewHost.cpp',
+ 'chromium/WebViewHost.h',
+ ],
+ }
+}
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
index 83f420f..60103a5 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
@@ -971,6 +971,7 @@ static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
newInstance->lastUrl = NULL;
newInstance->lastHeaders = NULL;
+ newInstance->testGetURLOnDestroy = FALSE;
newInstance->testDocumentOpenInDestroyStream = FALSE;
newInstance->testWindowOpen = FALSE;
newInstance->testKeyboardFocusForPlugins = FALSE;
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
index 2ae4dbf..0020e56 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
@@ -40,6 +40,7 @@ typedef struct {
NPObject* rememberedObject;
NPStream* stream;
NPBool testDocumentOpenInDestroyStream;
+ NPBool testGetURLOnDestroy;
NPBool testWindowOpen;
NPBool testKeyboardFocusForPlugins;
char* onStreamLoad;
diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
index c48aaf4..381112e 100644
--- a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp
@@ -50,6 +50,7 @@
#include "public/WebDragOperation.h"
#include "public/WebPoint.h"
#include "public/WebString.h"
+#include "public/WebTouchPoint.h"
#include "public/WebView.h"
#include "webkit/support/webkit_support.h"
#include <wtf/Deque.h>
@@ -65,7 +66,6 @@ using namespace base;
using namespace std;
using namespace WebKit;
-TestShell* EventSender::testShell = 0;
WebPoint EventSender::lastMousePos;
WebMouseEvent::Button EventSender::pressedButton = WebMouseEvent::ButtonNone;
WebMouseEvent::Button EventSender::lastButtonType = WebMouseEvent::ButtonNone;
@@ -94,6 +94,8 @@ static WebDragOperation currentDragEffect;
static WebDragOperationsMask currentDragEffectsAllowed;
static bool replayingSavedEvents = false;
static Deque<SavedEvent> mouseEventQueue;
+static int touchModifiers;
+static Vector<WebTouchPoint> touchPoints;
// Time and place of the last mouse up event.
static double lastClickTimeSec = 0;
@@ -161,7 +163,7 @@ static bool applyKeyModifier(const string& modifierName, WebInputEvent* event)
event->modifiers |= WebInputEvent::AltKey;
#if !OS(MAC_OS_X)
// On Windows all keys with Alt modifier will be marked as system key.
- // We keep the same behavior on Linux, see:
+ // We keep the same behavior on Linux and everywhere non-Mac, see:
// WebKit/chromium/src/gtk/WebInputEventFactory.cpp
// If we want to change this behavior on Linux, this piece of code must be
// kept in sync with the related code in above file.
@@ -246,13 +248,8 @@ enum KeyLocationCode {
EventSender::EventSender(TestShell* shell)
: m_methodFactory(this)
+ , m_shell(shell)
{
- // Set static testShell variable since we can't do it in an initializer list.
- // We also need to be careful not to assign testShell to new windows which are
- // temporary.
- if (!testShell)
- testShell = shell;
-
// Initialize the map that associates methods of this class with the names
// they will use when called by JavaScript. The actual binding of those
// names to their methods will be done by calling bindToJavaScript() (defined
@@ -274,6 +271,16 @@ EventSender::EventSender(TestShell* shell)
bindMethod("zoomPageOut", &EventSender::zoomPageOut);
bindMethod("scheduleAsynchronousClick", &EventSender::scheduleAsynchronousClick);
bindMethod("beginDragWithFiles", &EventSender::beginDragWithFiles);
+ bindMethod("addTouchPoint", &EventSender::addTouchPoint);
+ bindMethod("cancelTouchPoint", &EventSender::cancelTouchPoint);
+ bindMethod("clearTouchPoints", &EventSender::clearTouchPoints);
+ bindMethod("releaseTouchPoint", &EventSender::releaseTouchPoint);
+ bindMethod("updateTouchPoint", &EventSender::updateTouchPoint);
+ bindMethod("setTouchModifier", &EventSender::setTouchModifier);
+ bindMethod("touchCancel", &EventSender::touchCancel);
+ bindMethod("touchEnd", &EventSender::touchEnd);
+ bindMethod("touchMove", &EventSender::touchMove);
+ bindMethod("touchStart", &EventSender::touchStart);
// When set to true (the default value), we batch mouse move and mouse up
// events so we can simulate drag & drop.
@@ -315,16 +322,16 @@ void EventSender::reset()
clickCount = 0;
lastButtonType = WebMouseEvent::ButtonNone;
timeOffsetMs = 0;
+ touchModifiers = 0;
+ touchPoints.clear();
}
WebView* EventSender::webview()
{
- return testShell->webView();
+ return m_shell->webView();
}
-void EventSender::doDragDrop(const WebKit::WebPoint& eventPos,
- const WebDragData& dragData,
- WebDragOperationsMask mask)
+void EventSender::doDragDrop(const WebDragData& dragData, WebDragOperationsMask mask)
{
WebMouseEvent event;
initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event);
@@ -610,11 +617,11 @@ void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
// We just simulate the same behavior here.
string editCommand;
if (getEditCommand(eventDown, &editCommand))
- testShell->webViewHost()->setEditCommand(editCommand, "");
+ m_shell->webViewHost()->setEditCommand(editCommand, "");
webview()->handleInputEvent(eventDown);
- testShell->webViewHost()->clearEditCommand();
+ m_shell->webViewHost()->clearEditCommand();
if (generateChar) {
eventChar.type = WebInputEvent::Char;
@@ -787,6 +794,124 @@ void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVarian
result->setNull();
}
+void EventSender::addTouchPoint(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ WebTouchPoint touchPoint;
+ touchPoint.state = WebTouchPoint::StatePressed;
+ touchPoint.position = WebPoint(arguments[0].toInt32(), arguments[1].toInt32());
+ touchPoint.id = touchPoints.size();
+ touchPoints.append(touchPoint);
+}
+
+void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
+{
+ result->setNull();
+ touchPoints.clear();
+}
+
+void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ const unsigned index = arguments[0].toInt32();
+ ASSERT(index < touchPoints.size());
+
+ WebTouchPoint* touchPoint = &touchPoints[index];
+ touchPoint->state = WebTouchPoint::StateReleased;
+}
+
+void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ int mask = 0;
+ const string keyName = arguments[0].toString();
+ if (keyName == "shift")
+ mask = WebInputEvent::ShiftKey;
+ else if (keyName == "alt")
+ mask = WebInputEvent::AltKey;
+ else if (keyName == "ctrl")
+ mask = WebInputEvent::ControlKey;
+ else if (keyName == "meta")
+ mask = WebInputEvent::MetaKey;
+
+ if (arguments[1].toBoolean())
+ touchModifiers |= mask;
+ else
+ touchModifiers &= ~mask;
+}
+
+void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ const unsigned index = arguments[0].toInt32();
+ ASSERT(index < touchPoints.size());
+
+ WebPoint position(arguments[1].toInt32(), arguments[2].toInt32());
+ WebTouchPoint* touchPoint = &touchPoints[index];
+ touchPoint->state = WebTouchPoint::StateMoved;
+ touchPoint->position = position;
+}
+
+void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ const unsigned index = arguments[0].toInt32();
+ ASSERT(index < touchPoints.size());
+
+ WebTouchPoint* touchPoint = &touchPoints[index];
+ touchPoint->state = WebTouchPoint::StateCancelled;
+}
+
+void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
+{
+ ASSERT(static_cast<unsigned>(WebTouchEvent::touchPointsLengthCap) > touchPoints.size());
+ WebTouchEvent touchEvent;
+ touchEvent.type = type;
+ touchEvent.modifiers = touchModifiers;
+ touchEvent.touchPointsLength = touchPoints.size();
+ for (unsigned i = 0; i < touchPoints.size(); ++i)
+ touchEvent.touchPoints[i] = touchPoints[i];
+ webview()->handleInputEvent(touchEvent);
+
+ for (unsigned i = 0; i < touchPoints.size(); ++i) {
+ WebTouchPoint* touchPoint = &touchPoints[i];
+ if (touchPoint->state == WebTouchPoint::StateReleased) {
+ touchPoints.remove(i);
+ --i;
+ } else
+ touchPoint->state = WebTouchPoint::StateStationary;
+ }
+}
+
+void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
+{
+ result->setNull();
+ sendCurrentTouchEvent(WebInputEvent::TouchEnd);
+}
+
+void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
+{
+ result->setNull();
+ sendCurrentTouchEvent(WebInputEvent::TouchMove);
+}
+
+void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
+{
+ result->setNull();
+ sendCurrentTouchEvent(WebInputEvent::TouchStart);
+}
+
+void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
+{
+ result->setNull();
+ sendCurrentTouchEvent(WebInputEvent::TouchCancel);
+}
+
//
// Unimplemented stubs
//
diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.h b/WebKitTools/DumpRenderTree/chromium/EventSender.h
index 756b008..ac475a3 100644
--- a/WebKitTools/DumpRenderTree/chromium/EventSender.h
+++ b/WebKitTools/DumpRenderTree/chromium/EventSender.h
@@ -60,9 +60,7 @@ public:
void reset();
// Simulate drag&drop system call.
- static void doDragDrop(const WebKit::WebPoint&,
- const WebKit::WebDragData&,
- WebKit::WebDragOperationsMask);
+ void doDragDrop(const WebKit::WebDragData&, WebKit::WebDragOperationsMask);
// JS callback methods.
void mouseDown(const CppArgumentList&, CppVariant*);
@@ -80,6 +78,17 @@ public:
void beginDragWithFiles(const CppArgumentList&, CppVariant*);
CppVariant dragMode;
+ void addTouchPoint(const CppArgumentList&, CppVariant*);
+ void cancelTouchPoint(const CppArgumentList&, CppVariant*);
+ void clearTouchPoints(const CppArgumentList&, CppVariant*);
+ void releaseTouchPoint(const CppArgumentList&, CppVariant*);
+ void setTouchModifier(const CppArgumentList&, CppVariant*);
+ void touchCancel(const CppArgumentList&, CppVariant*);
+ void touchEnd(const CppArgumentList&, CppVariant*);
+ void touchMove(const CppArgumentList&, CppVariant*);
+ void touchStart(const CppArgumentList&, CppVariant*);
+ void updateTouchPoint(const CppArgumentList&, CppVariant*);
+
// Unimplemented stubs
void contextClick(const CppArgumentList&, CppVariant*);
void enableDOMUIEventLogging(const CppArgumentList&, CppVariant*);
@@ -100,17 +109,17 @@ public:
private:
// Returns the test shell's webview.
- static WebKit::WebView* webview();
+ WebKit::WebView* webview();
// Returns true if dragMode is true.
bool isDragMode() { return dragMode.isBool() && dragMode.toBoolean(); }
// Sometimes we queue up mouse move and mouse up events for drag drop
// handling purposes. These methods dispatch the event.
- static void doMouseMove(const WebKit::WebMouseEvent&);
- static void doMouseUp(const WebKit::WebMouseEvent&);
+ void doMouseMove(const WebKit::WebMouseEvent&);
+ void doMouseUp(const WebKit::WebMouseEvent&);
static void doLeapForward(int milliseconds);
- static void replaySavedEvents();
+ void replaySavedEvents();
// Helper to return the button type given a button code
static WebKit::WebMouseEvent::Button getButtonTypeFromButtonNumber(int);
@@ -125,10 +134,13 @@ private:
void updateClickCountForButton(WebKit::WebMouseEvent::Button);
+ // Compose a touch event from the current touch points and send it.
+ void sendCurrentTouchEvent(const WebKit::WebInputEvent::Type);
+
ScopedRunnableMethodFactory<EventSender> m_methodFactory;
// Non-owning pointer. The EventSender is owned by the TestShell.
- static TestShell* testShell;
+ TestShell* m_shell;
// Location of last mouseMoveTo event.
static WebKit::WebPoint lastMousePos;
diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
index 21b168c..4413ff2 100644
--- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
@@ -41,6 +41,7 @@
#include "public/WebFrame.h"
#include "public/WebInputElement.h"
#include "public/WebKit.h"
+#include "public/WebNotificationPresenter.h"
#include "public/WebScriptSource.h"
#include "public/WebSecurityPolicy.h"
#include "public/WebSettings.h"
@@ -48,11 +49,13 @@
#include "public/WebURL.h"
#include "public/WebView.h"
#include "webkit/support/webkit_support.h"
+#include <wtf/text/WTFString.h>
#if OS(WINDOWS)
#include <wtf/OwnArrayPtr.h>
#endif
+using namespace WebCore;
using namespace WebKit;
using namespace std;
@@ -90,10 +93,12 @@ LayoutTestController::LayoutTestController(TestShell* shell)
bindMethod("setCloseRemainingWindowsWhenComplete", &LayoutTestController::setCloseRemainingWindowsWhenComplete);
bindMethod("objCIdentityIsEqual", &LayoutTestController::objCIdentityIsEqual);
bindMethod("setAlwaysAcceptCookies", &LayoutTestController::setAlwaysAcceptCookies);
+ bindMethod("showWebInspector", &LayoutTestController::showWebInspector);
bindMethod("setWindowIsKey", &LayoutTestController::setWindowIsKey);
bindMethod("setTabKeyCyclesThroughElements", &LayoutTestController::setTabKeyCyclesThroughElements);
bindMethod("setUserStyleSheetLocation", &LayoutTestController::setUserStyleSheetLocation);
bindMethod("setUserStyleSheetEnabled", &LayoutTestController::setUserStyleSheetEnabled);
+ bindMethod("setAuthorAndUserStylesEnabled", &LayoutTestController::setAuthorAndUserStylesEnabled);
bindMethod("pathToLocalResource", &LayoutTestController::pathToLocalResource);
bindMethod("addFileToPasteboardOnDrag", &LayoutTestController::addFileToPasteboardOnDrag);
bindMethod("execCommand", &LayoutTestController::execCommand);
@@ -109,18 +114,23 @@ LayoutTestController::LayoutTestController(TestShell* shell)
bindMethod("disableImageLoading", &LayoutTestController::disableImageLoading);
bindMethod("setIconDatabaseEnabled", &LayoutTestController::setIconDatabaseEnabled);
bindMethod("setCustomPolicyDelegate", &LayoutTestController::setCustomPolicyDelegate);
+ bindMethod("setScrollbarPolicy", &LayoutTestController::setScrollbarPolicy);
bindMethod("waitForPolicyDelegate", &LayoutTestController::waitForPolicyDelegate);
+ bindMethod("setWillSendRequestClearHeader", &LayoutTestController::setWillSendRequestClearHeader);
bindMethod("setWillSendRequestReturnsNullOnRedirect", &LayoutTestController::setWillSendRequestReturnsNullOnRedirect);
bindMethod("setWillSendRequestReturnsNull", &LayoutTestController::setWillSendRequestReturnsNull);
bindMethod("addOriginAccessWhitelistEntry", &LayoutTestController::addOriginAccessWhitelistEntry);
+ bindMethod("removeOriginAccessWhitelistEntry", &LayoutTestController::removeOriginAccessWhitelistEntry);
bindMethod("clearAllDatabases", &LayoutTestController::clearAllDatabases);
bindMethod("setDatabaseQuota", &LayoutTestController::setDatabaseQuota);
bindMethod("setPOSIXLocale", &LayoutTestController::setPOSIXLocale);
bindMethod("counterValueForElementById", &LayoutTestController::counterValueForElementById);
bindMethod("addUserScript", &LayoutTestController::addUserScript);
+ bindMethod("addUserStyleSheet", &LayoutTestController::addUserStyleSheet);
bindMethod("pageNumberForElementById", &LayoutTestController::pageNumberForElementById);
bindMethod("numberOfPages", &LayoutTestController::numberOfPages);
bindMethod("dumpSelectionRect", &LayoutTestController::dumpSelectionRect);
+ bindMethod("grantDesktopNotificationPermission", &LayoutTestController::grantDesktopNotificationPermission);
// The following are stubs.
bindMethod("dumpAsWebArchive", &LayoutTestController::dumpAsWebArchive);
@@ -135,6 +145,7 @@ LayoutTestController::LayoutTestController(TestShell* shell)
bindMethod("accessStoredWebScriptObject", &LayoutTestController::accessStoredWebScriptObject);
bindMethod("objCClassNameOf", &LayoutTestController::objCClassNameOf);
bindMethod("addDisallowedURL", &LayoutTestController::addDisallowedURL);
+ bindMethod("callShouldCloseOnWebView", &LayoutTestController::callShouldCloseOnWebView);
bindMethod("setCallCloseOnWebViews", &LayoutTestController::setCallCloseOnWebViews);
bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled);
bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode);
@@ -440,11 +451,11 @@ void LayoutTestController::reset()
if (m_shell) {
m_shell->webView()->setZoomLevel(false, 0);
m_shell->webView()->setTabKeyCyclesThroughElements(true);
-#if defined(OS_LINUX)
+#if !OS(DARWIN) && !OS(WINDOWS) // Actually, TOOLKIT_GTK
// (Constants copied because we can't depend on the header that defined
// them from this file.)
m_shell->webView()->setSelectionColors(0xff1e90ff, 0xff000000, 0xffc8c8c8, 0xff323232);
-#endif // defined(OS_LINUX)
+#endif
m_shell->webView()->removeAllUserContent();
}
m_dumpAsText = false;
@@ -468,7 +479,7 @@ void LayoutTestController::reset()
m_webHistoryItemCount.set(0);
webkit_support::SetAcceptAllCookies(false);
- WebSecurityPolicy::resetOriginAccessWhiteLists();
+ WebSecurityPolicy::resetOriginAccessWhitelists();
// Reset the default quota for each origin to 5MB
webkit_support::SetDatabaseQuota(5 * 1024 * 1024);
@@ -532,6 +543,12 @@ void LayoutTestController::setAlwaysAcceptCookies(const CppArgumentList& argumen
result->setNull();
}
+void LayoutTestController::showWebInspector(const CppArgumentList&, CppVariant* result)
+{
+ m_shell->showDevTools();
+ result->setNull();
+}
+
void LayoutTestController::setWindowIsKey(const CppArgumentList& arguments, CppVariant* result)
{
if (arguments.size() > 0 && arguments[0].isBool())
@@ -555,6 +572,13 @@ void LayoutTestController::setUserStyleSheetLocation(const CppArgumentList& argu
result->setNull();
}
+void LayoutTestController::setAuthorAndUserStylesEnabled(const CppArgumentList& arguments, CppVariant* result)
+{
+ if (arguments.size() > 0 && arguments[0].isBool())
+ m_shell->webView()->settings()->setAuthorAndUserStylesEnabled(arguments[0].value.boolValue);
+ result->setNull();
+}
+
void LayoutTestController::execCommand(const CppArgumentList& arguments, CppVariant* result)
{
result->setNull();
@@ -599,6 +623,13 @@ void LayoutTestController::setUseDashboardCompatibilityMode(const CppArgumentLis
result->setNull();
}
+void LayoutTestController::setScrollbarPolicy(const CppArgumentList&, CppVariant* result)
+{
+ // FIXME: implement.
+ // Currently only has a non-null implementation on QT.
+ result->setNull();
+}
+
void LayoutTestController::setCustomPolicyDelegate(const CppArgumentList& arguments, CppVariant* result)
{
if (arguments.size() > 0 && arguments[0].isBool()) {
@@ -618,6 +649,16 @@ void LayoutTestController::waitForPolicyDelegate(const CppArgumentList&, CppVari
result->setNull();
}
+void LayoutTestController::setWillSendRequestClearHeader(const CppArgumentList& arguments, CppVariant* result)
+{
+ if (arguments.size() > 0 && arguments[0].isString()) {
+ string header = arguments[0].toString();
+ if (!header.empty())
+ m_shell->webViewHost()->addClearHeader(String::fromUTF8(header.c_str()));
+ }
+ result->setNull();
+}
+
void LayoutTestController::setWillSendRequestReturnsNullOnRedirect(const CppArgumentList& arguments, CppVariant* result)
{
if (arguments.size() > 0 && arguments[0].isBool())
@@ -734,7 +775,7 @@ bool LayoutTestController::elementDoesAutoCompleteForElementWithId(const WebStri
if (element.isNull() || !element.hasTagName("input"))
return false;
- WebInputElement inputElement = element.toElement<WebInputElement>();
+ WebInputElement inputElement = element.to<WebInputElement>();
return inputElement.autoComplete();
}
@@ -800,6 +841,21 @@ void LayoutTestController::setIconDatabaseEnabled(const CppArgumentList&, CppVar
result->setNull();
}
+void LayoutTestController::callShouldCloseOnWebView(const CppArgumentList&, CppVariant* result)
+{
+ result->set(m_shell->webView()->dispatchBeforeUnloadEvent());
+}
+
+void LayoutTestController::grantDesktopNotificationPermission(const CppArgumentList& arguments, CppVariant* result)
+{
+ if (arguments.size() != 1 || !arguments[0].isString()) {
+ result->set(false);
+ return;
+ }
+ m_shell->notificationPresenter()->grantPermission(WebString::fromUTF8(arguments[0].toString()));
+ result->set(true);
+}
+
//
// Unimplemented stubs
//
@@ -1052,10 +1108,30 @@ void LayoutTestController::addOriginAccessWhitelistEntry(const CppArgumentList&
if (!url.isValid())
return;
- WebSecurityPolicy::whiteListAccessFromOrigin(url,
- WebString::fromUTF8(arguments[1].toString()),
- WebString::fromUTF8(arguments[2].toString()),
- arguments[3].toBoolean());
+ WebSecurityPolicy::addOriginAccessWhitelistEntry(
+ url,
+ WebString::fromUTF8(arguments[1].toString()),
+ WebString::fromUTF8(arguments[2].toString()),
+ arguments[3].toBoolean());
+}
+
+void LayoutTestController::removeOriginAccessWhitelistEntry(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+
+ if (arguments.size() != 4 || !arguments[0].isString() || !arguments[1].isString()
+ || !arguments[2].isString() || !arguments[3].isBool())
+ return;
+
+ WebKit::WebURL url(GURL(arguments[0].toString()));
+ if (!url.isValid())
+ return;
+
+ WebSecurityPolicy::removeOriginAccessWhitelistEntry(
+ url,
+ WebString::fromUTF8(arguments[1].toString()),
+ WebString::fromUTF8(arguments[2].toString()),
+ arguments[3].toBoolean());
}
void LayoutTestController::clearAllDatabases(const CppArgumentList& arguments, CppVariant* result)
@@ -1183,7 +1259,15 @@ void LayoutTestController::forceRedSelectionColors(const CppArgumentList& argume
void LayoutTestController::addUserScript(const CppArgumentList& arguments, CppVariant* result)
{
result->setNull();
- if (arguments.size() < 1 || !arguments[0].isString() || !arguments[1].isBool())
+ if (arguments.size() < 2 || !arguments[0].isString() || !arguments[1].isBool())
return;
m_shell->webView()->addUserScript(WebString::fromUTF8(arguments[0].toString()), arguments[1].toBoolean());
}
+
+void LayoutTestController::addUserStyleSheet(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+ if (arguments.size() < 1 || !arguments[0].isString())
+ return;
+ m_shell->webView()->addUserStyleSheet(WebString::fromUTF8(arguments[0].toString()));
+}
diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h
index ca8b014..e7a48e2 100644
--- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h
+++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h
@@ -127,6 +127,9 @@ public:
// Changes the cookie policy from the default to allow all cookies.
void setAlwaysAcceptCookies(const CppArgumentList&, CppVariant*);
+ // Shows DevTools window.
+ void showWebInspector(const CppArgumentList&, CppVariant*);
+
// Gives focus to the window.
void setWindowIsKey(const CppArgumentList&, CppVariant*);
@@ -139,11 +142,16 @@ public:
void setUserStyleSheetEnabled(const CppArgumentList&, CppVariant*);
void setUserStyleSheetLocation(const CppArgumentList&, CppVariant*);
+ // Passes this preference through to WebSettings.
+ void setAuthorAndUserStylesEnabled(const CppArgumentList&, CppVariant*);
+
// Puts Webkit in "dashboard compatibility mode", which is used in obscure
// Mac-only circumstances. It's not really necessary, and will most likely
// never be used by Chrome, but some layout tests depend on its presence.
void setUseDashboardCompatibilityMode(const CppArgumentList&, CppVariant*);
+ void setScrollbarPolicy(const CppArgumentList&, CppVariant*);
+
// Causes navigation actions just printout the intended navigation instead
// of taking you to the page. This is used for cases like mailto, where you
// don't actually want to open the mail program.
@@ -152,6 +160,9 @@ public:
// Delays completion of the test until the policy delegate runs.
void waitForPolicyDelegate(const CppArgumentList&, CppVariant*);
+ // Causes WillSendRequest to clear certain headers.
+ void setWillSendRequestClearHeader(const CppArgumentList&, CppVariant*);
+
// Causes WillSendRequest to block redirects.
void setWillSendRequestReturnsNullOnRedirect(const CppArgumentList&, CppVariant*);
@@ -195,6 +206,9 @@ public:
void dumpSelectionRect(const CppArgumentList&, CppVariant*);
+ // Grants permission for desktop notifications to an origin
+ void grantDesktopNotificationPermission(const CppArgumentList&, CppVariant*);
+
// The following are only stubs. TODO(pamg): Implement any of these that
// are needed to pass the layout tests.
void dumpAsWebArchive(const CppArgumentList&, CppVariant*);
@@ -210,6 +224,7 @@ public:
void accessStoredWebScriptObject(const CppArgumentList&, CppVariant*);
void objCClassNameOf(const CppArgumentList&, CppVariant*);
void addDisallowedURL(const CppArgumentList&, CppVariant*);
+ void callShouldCloseOnWebView(const CppArgumentList&, CppVariant*);
void setCallCloseOnWebViews(const CppArgumentList&, CppVariant*);
void setPrivateBrowsingEnabled(const CppArgumentList&, CppVariant*);
@@ -228,8 +243,9 @@ public:
// that case (as the Mac does).
void fallbackMethod(const CppArgumentList&, CppVariant*);
- // Allows layout tests to call SecurityOrigin::addOriginAccessWhitelistEntry().
+ // Allows layout tests to manage origins' whitelisting.
void addOriginAccessWhitelistEntry(const CppArgumentList&, CppVariant*);
+ void removeOriginAccessWhitelistEntry(const CppArgumentList&, CppVariant*);
// Clears all databases.
void clearAllDatabases(const CppArgumentList&, CppVariant*);
@@ -259,8 +275,9 @@ public:
// Forces the selection colors for testing under Linux.
void forceRedSelectionColors(const CppArgumentList&, CppVariant*);
- // Adds a user script to be injected into new documents.
+ // Adds a user script or user style sheet to be injected into new documents.
void addUserScript(const CppArgumentList&, CppVariant*);
+ void addUserStyleSheet(const CppArgumentList&, CppVariant*);
public:
// The following methods are not exposed to JavaScript.
diff --git a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp
new file mode 100644
index 0000000..86903be
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NotificationPresenter.h"
+
+#include "googleurl/src/gurl.h"
+#include "public/WebNotification.h"
+#include "public/WebNotificationPermissionCallback.h"
+#include "public/WebSecurityOrigin.h"
+#include "public/WebString.h"
+#include "public/WebURL.h"
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+void NotificationPresenter::grantPermission(const WebString& origin)
+{
+ // Make sure it's in the form of an origin.
+ GURL url(origin);
+ m_allowedOrigins.add(String(url.GetOrigin().spec().c_str()));
+}
+
+// The output from all these methods matches what DumpRenderTree produces.
+bool NotificationPresenter::show(const WebNotification& notification)
+{
+ if (!notification.replaceId().isEmpty()) {
+ String replaceId(notification.replaceId().data(), notification.replaceId().length());
+ if (m_replacements.find(replaceId) != m_replacements.end())
+ printf("REPLACING NOTIFICATION %s\n",
+ m_replacements.find(replaceId)->second.utf8().data());
+
+ WebString identifier = notification.isHTML() ?
+ notification.url().spec().utf16() : notification.title();
+ m_replacements.set(replaceId, String(identifier.data(), identifier.length()));
+ }
+
+ if (notification.isHTML()) {
+ printf("DESKTOP NOTIFICATION: contents at %s\n",
+ notification.url().spec().data());
+ } else {
+ printf("DESKTOP NOTIFICATION:%s icon %s, title %s, text %s\n",
+ notification.dir() == "rtl" ? "(RTL)" : "",
+ notification.iconURL().isEmpty() ? "" :
+ notification.iconURL().spec().data(),
+ notification.title().isEmpty() ? "" :
+ notification.title().utf8().data(),
+ notification.body().isEmpty() ? "" :
+ notification.body().utf8().data());
+ }
+
+ WebNotification eventTarget(notification);
+ eventTarget.dispatchDisplayEvent();
+ return true;
+}
+
+void NotificationPresenter::cancel(const WebNotification& notification)
+{
+ WebString identifier;
+ if (notification.isHTML())
+ identifier = notification.url().spec().utf16();
+ else
+ identifier = notification.title();
+
+ printf("DESKTOP NOTIFICATION CLOSED: %s\n", identifier.utf8().data());
+ WebNotification eventTarget(notification);
+ eventTarget.dispatchCloseEvent(false);
+}
+
+void NotificationPresenter::objectDestroyed(const WebKit::WebNotification& notification)
+{
+ // Nothing to do. Not storing the objects.
+}
+
+WebNotificationPresenter::Permission NotificationPresenter::checkPermission(const WebURL& url)
+{
+ // Check with the layout test controller
+ String origin = String(static_cast<GURL>(url).GetOrigin().spec().c_str());
+ bool allowed = m_allowedOrigins.find(origin) != m_allowedOrigins.end();
+ return allowed ? WebNotificationPresenter::PermissionAllowed
+ : WebNotificationPresenter::PermissionDenied;
+}
+
+void NotificationPresenter::requestPermission(
+ const WebSecurityOrigin& origin,
+ WebNotificationPermissionCallback* callback)
+{
+ printf("DESKTOP NOTIFICATION PERMISSION REQUESTED: %s\n",
+ origin.toString().utf8().data());
+ callback->permissionRequestComplete();
+}
diff --git a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h
new file mode 100644
index 0000000..f30862f
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NotificationPresenter_h
+#define NotificationPresenter_h
+
+#include "public/WebNotificationPresenter.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+class TestShell;
+
+// A class that implements WebNotificationPresenter for DRT.
+class NotificationPresenter : public WebKit::WebNotificationPresenter {
+public:
+ explicit NotificationPresenter(TestShell* shell) : m_shell(shell) {}
+
+ // Called by the LayoutTestController to simulate a user granting permission.
+ void grantPermission(const WebKit::WebString& origin);
+
+ // WebKit::WebNotificationPresenter interface
+ virtual bool show(const WebKit::WebNotification&);
+ virtual void cancel(const WebKit::WebNotification&);
+ virtual void objectDestroyed(const WebKit::WebNotification&);
+ virtual Permission checkPermission(const WebKit::WebURL&);
+ virtual void requestPermission(const WebKit::WebSecurityOrigin&, WebKit::WebNotificationPermissionCallback*);
+
+ void reset() { m_allowedOrigins.clear(); }
+
+private:
+ // Non-owned pointer. The NotificationPresenter is owned by the test shell.
+ TestShell* m_shell;
+
+ // Set of allowed origins.
+ HashSet<WebCore::String> m_allowedOrigins;
+
+ // Map of active replacement IDs to the titles of those notifications
+ HashMap<WebCore::String, WebCore::String> m_replacements;
+};
+
+#endif // NotificationPresenter_h
diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp
index e4229fe..24a895a 100644
--- a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp
@@ -85,6 +85,7 @@ TestShell::TestShell()
m_eventSender.set(new EventSender(this));
m_plainTextController.set(new PlainTextController());
m_textInputController.set(new TextInputController(this));
+ m_notificationPresenter.set(new NotificationPresenter(this));
m_webViewHost = createWebView();
m_webView = m_webViewHost->webView();
@@ -131,6 +132,7 @@ void TestShell::resetWebSettings(WebView& webView)
settings->setSerifFontFamily(serif);
settings->setStandardFontFamily(serif);
settings->setFixedFontFamily(WebString::fromUTF8("Courier"));
+ settings->setSansSerifFontFamily(WebString::fromUTF8("Helvetica"));
settings->setDefaultTextEncodingName(WebString::fromUTF8("ISO-8859-1"));
settings->setDefaultFontSize(16);
@@ -175,6 +177,7 @@ void TestShell::resetWebSettings(WebView& webView)
void TestShell::runFileTest(const TestParams& params)
{
+ ASSERT(params.testUrl.isValid());
m_testIsPreparing = true;
m_params = params;
string testUrl = m_params.testUrl.spec();
@@ -212,6 +215,7 @@ void TestShell::resetTestController()
m_layoutTestController->reset();
m_eventSender->reset();
m_webViewHost->reset();
+ m_notificationPresenter->reset();
}
void TestShell::loadURL(const WebURL& url)
diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.h b/WebKitTools/DumpRenderTree/chromium/TestShell.h
index c6a5b2e..283cbd4 100644
--- a/WebKitTools/DumpRenderTree/chromium/TestShell.h
+++ b/WebKitTools/DumpRenderTree/chromium/TestShell.h
@@ -31,6 +31,7 @@
#include "AccessibilityController.h"
#include "EventSender.h"
#include "LayoutTestController.h"
+#include "NotificationPresenter.h"
#include "PlainTextController.h"
#include "TextInputController.h"
#include "WebViewHost.h"
@@ -43,6 +44,7 @@
namespace WebKit {
class WebFrame;
+class WebNotificationPresenter;
class WebPreferences;
class WebView;
class WebURL;
@@ -74,7 +76,9 @@ public:
// Returns the host for the main WebView.
WebViewHost* webViewHost() const { return m_webViewHost; }
LayoutTestController* layoutTestController() const { return m_layoutTestController.get(); }
+ EventSender* eventSender() const { return m_eventSender.get(); }
AccessibilityController* accessibilityController() const { return m_accessibilityController.get(); }
+ NotificationPresenter* notificationPresenter() const { return m_notificationPresenter.get(); }
void bindJSObjectsToWindow(WebKit::WebFrame*);
void runFileTest(const TestParams&);
@@ -115,6 +119,7 @@ public:
void closeRemainingWindows();
int windowCount();
static void resizeWindowForTest(WebViewHost*, const WebKit::WebURL&);
+ void showDevTools() {} // FIXME: imeplement this.
static const int virtualWindowBorder = 3;
@@ -135,6 +140,7 @@ private:
OwnPtr<LayoutTestController*> m_layoutTestController;
OwnPtr<PlainTextController*> m_plainTextController;
OwnPtr<TextInputController*> m_textInputController;
+ OwnPtr<NotificationPresenter*> m_notificationPresenter;
TestParams m_params;
// List of all windows in this process.
diff --git a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h
index f28cc20..9470804 100644
--- a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h
+++ b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h
@@ -80,6 +80,7 @@ public:
virtual WebKit::WebWorker* createWorker(WebKit::WebWorkerClient*) { return 0; }
virtual WebKit::WebNotificationPresenter* notificationPresenter() { return 0; }
virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(WebKit::WebApplicationCacheHostClient*) { return 0; }
+ virtual bool allowDatabase(WebKit::WebFrame*, const WebKit::WebString&, const WebKit::WebString&, unsigned long) { return true; }
private:
~TestWebWorker() {}
diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp
index 6ea1de1..4761b1a 100644
--- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp
+++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp
@@ -52,10 +52,12 @@
#include "public/WebURLRequest.h"
#include "public/WebURLResponse.h"
#include "public/WebView.h"
+#include "public/WebWindowFeatures.h"
#include "skia/ext/platform_canvas.h"
#include "webkit/support/webkit_support.h"
#include <wtf/Assertions.h>
+using namespace WebCore;
using namespace WebKit;
using namespace skia;
using namespace std;
@@ -250,14 +252,19 @@ static string textAffinityDescription(WebTextAffinity affinity)
// WebViewClient -------------------------------------------------------------
-WebView* WebViewHost::createView(WebFrame*)
+WebView* WebViewHost::createView(WebFrame* creator)
+{
+ return createView(creator, WebWindowFeatures());
+}
+
+WebView* WebViewHost::createView(WebFrame*, const WebWindowFeatures&)
{
if (!layoutTestController()->canOpenWindows())
return 0;
return m_shell->createWebView()->webView();
}
-WebWidget* WebViewHost::createPopupMenu(bool)
+WebWidget* WebViewHost::createPopupMenu(WebPopupType)
{
return 0;
}
@@ -267,9 +274,9 @@ WebWidget* WebViewHost::createPopupMenu(const WebPopupMenuInfo&)
return 0;
}
-WebStorageNamespace* WebViewHost::createSessionStorageNamespace()
+WebStorageNamespace* WebViewHost::createSessionStorageNamespace(unsigned quota)
{
- return WebKit::WebStorageNamespace::createSessionStorageNamespace();
+ return WebKit::WebStorageNamespace::createSessionStorageNamespace(quota);
}
void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
@@ -481,7 +488,7 @@ void WebViewHost::setStatusText(const WebString& text)
printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text.utf8().data());
}
-void WebViewHost::startDragging(const WebPoint& mouseCoords, const WebDragData& data, WebDragOperationsMask mask)
+void WebViewHost::startDragging(const WebDragData& data, WebDragOperationsMask mask, const WebImage&, const WebPoint&)
{
WebDragData mutableDragData = data;
if (layoutTestController()->shouldAddFileToPasteboard()) {
@@ -491,7 +498,7 @@ void WebViewHost::startDragging(const WebPoint& mouseCoords, const WebDragData&
// When running a test, we need to fake a drag drop operation otherwise
// Windows waits for real mouse events to know when the drag is over.
- EventSender::doDragDrop(mouseCoords, mutableDragData, mask);
+ m_shell->eventSender()->doDragDrop(mutableDragData, mask);
}
void WebViewHost::navigateBackForwardSoon(int offset)
@@ -515,6 +522,11 @@ void WebViewHost::focusAccessibilityObject(const WebAccessibilityObject& object)
m_shell->accessibilityController()->setFocusedElement(object);
}
+WebNotificationPresenter* WebViewHost::notificationPresenter()
+{
+ return m_shell->notificationPresenter();
+}
+
// WebWidgetClient -----------------------------------------------------------
void WebViewHost::didInvalidateRect(const WebRect& rect)
@@ -629,6 +641,11 @@ WebMediaPlayer* WebViewHost::createMediaPlayer(WebFrame* frame, WebMediaPlayerCl
return webkit_support::CreateMediaPlayer(frame, client);
}
+WebApplicationCacheHost* WebViewHost::createApplicationCacheHost(WebFrame* frame, WebApplicationCacheHostClient* client)
+{
+ return webkit_support::CreateApplicationCacheHost(frame, client);
+}
+
bool WebViewHost::allowPlugins(WebFrame* frame, bool enabledPerSettings)
{
return enabledPerSettings;
@@ -906,6 +923,10 @@ void WebViewHost::willSendRequest(WebFrame*, unsigned identifier, WebURLRequest&
return;
}
+ HashSet<String>::const_iterator end = m_clearHeaders.end();
+ for (HashSet<String>::const_iterator header = m_clearHeaders.begin(); header != end; ++header)
+ request.clearHTTPHeaderField(WebString(header->characters(), header->length()));
+
// Set the new substituted URL.
request.setURL(webkit_support::RewriteLayoutTestsURL(request.url().spec()));
}
@@ -1115,7 +1136,7 @@ void WebViewHost::updateAddressBar(WebView* webView)
if (!dataSource)
return;
- setAddressBarURL(dataSource->request().firstPartyForCookies());
+ setAddressBarURL(dataSource->request().url());
}
void WebViewHost::locationChangeDone(WebFrame* frame)
@@ -1168,6 +1189,7 @@ void WebViewHost::updateURL(WebFrame* frame)
entry->setContentState(historyItem);
navigationController()->didNavigateToEntry(entry.release());
+ updateAddressBar(frame->view());
m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId);
}
diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h
index c5bed7a..5227b28 100644
--- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h
+++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h
@@ -37,15 +37,18 @@
#include "public/WebFrameClient.h"
#include "public/WebViewClient.h"
#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
class LayoutTestController;
class TestShell;
namespace WebKit {
class WebFrame;
class WebURL;
-struct WebURLError;
struct WebRect;
+struct WebURLError;
+struct WebWindowFeatures;
}
namespace skia {
class PlatformCanvas;
@@ -79,14 +82,18 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient,
void loadURLForFrame(const WebKit::WebURL&, const WebKit::WebString& frameName);
TestNavigationController* navigationController() { return m_navigationController.get(); }
+ void addClearHeader(const WebCore::String& header) { m_clearHeaders.add(header); }
+ const HashSet<WebCore::String>& clearHeaders() const { return m_clearHeaders; }
+
// NavigationHost
virtual bool navigate(const TestNavigationEntry&, bool reload);
// WebKit::WebViewClient
virtual WebKit::WebView* createView(WebKit::WebFrame*);
- virtual WebKit::WebWidget* createPopupMenu(bool activatable);
+ virtual WebKit::WebView* createView(WebKit::WebFrame*, const WebKit::WebWindowFeatures&);
+ virtual WebKit::WebWidget* createPopupMenu(WebKit::WebPopupType);
virtual WebKit::WebWidget* createPopupMenu(const WebKit::WebPopupMenuInfo&);
- virtual WebKit::WebStorageNamespace* createSessionStorageNamespace();
+ virtual WebKit::WebStorageNamespace* createSessionStorageNamespace(unsigned quota);
virtual void didAddMessageToConsole(const WebKit::WebConsoleMessage&, const WebKit::WebString& sourceName, unsigned sourceLine);
virtual void didStartLoading();
virtual void didStopLoading();
@@ -112,11 +119,12 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient,
virtual bool runModalBeforeUnloadDialog(WebKit::WebFrame*, const WebKit::WebString&);
virtual void showContextMenu(WebKit::WebFrame*, const WebKit::WebContextMenuData&);
virtual void setStatusText(const WebKit::WebString&);
- virtual void startDragging(const WebKit::WebPoint&, const WebKit::WebDragData&, WebKit::WebDragOperationsMask);
+ virtual void startDragging(const WebKit::WebDragData&, WebKit::WebDragOperationsMask, const WebKit::WebImage&, const WebKit::WebPoint&);
virtual void navigateBackForwardSoon(int offset);
virtual int historyBackListCount();
virtual int historyForwardListCount();
virtual void focusAccessibilityObject(const WebKit::WebAccessibilityObject&);
+ virtual WebKit::WebNotificationPresenter* notificationPresenter();
// WebKit::WebWidgetClient
virtual void didInvalidateRect(const WebKit::WebRect&);
@@ -137,7 +145,8 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient,
virtual WebKit::WebPlugin* createPlugin(WebKit::WebFrame*, const WebKit::WebPluginParams&);
virtual WebKit::WebWorker* createWorker(WebKit::WebFrame*, WebKit::WebWorkerClient*);
virtual WebKit::WebMediaPlayer* createMediaPlayer(WebKit::WebFrame*, WebKit::WebMediaPlayerClient*);
- virtual bool allowPlugins(WebKit::WebFrame*, bool enabledPerSettings);
+ virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(WebKit::WebFrame*, WebKit::WebApplicationCacheHostClient*);
+ virtual bool allowPlugins(WebKit::WebFrame*, bool enabledPerSettings);
virtual bool allowImages(WebKit::WebFrame*, bool enabledPerSettings);
virtual void loadURLExternally(WebKit::WebFrame*, const WebKit::WebURLRequest&, WebKit::WebNavigationPolicy);
virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
@@ -248,6 +257,9 @@ private:
// true if we want to enable selection of trailing whitespaces
bool m_selectTrailingWhitespaceEnabled;
+ // Set of headers to clear in willSendRequest.
+ HashSet<WebCore::String> m_clearHeaders;
+
// true if we should block any redirects
bool m_blocksRedirects;
diff --git a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
index fabada3..3735d0a 100644
--- a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "AccessibilityUIElement.h"
+#include "GRefPtr.h"
#include <JavaScriptCore/JSStringRef.h>
#include <wtf/Assertions.h>
@@ -128,10 +129,22 @@ unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
return 0;
}
+gchar* attributeSetToString(AtkAttributeSet* attributeSet)
+{
+ GString* str = g_string_new(0);
+ for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) {
+ AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
+ g_string_append(str, g_strconcat(attribute->name, ":", attribute->value, NULL));
+ if (attributes->next)
+ g_string_append(str, ", ");
+ }
+
+ return g_string_free(str, FALSE);
+}
+
JSStringRef AccessibilityUIElement::allAttributes()
{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
+ return JSStringCreateWithUTF8CString(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
}
JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
@@ -364,8 +377,13 @@ bool AccessibilityUIElement::isRequired() const
bool AccessibilityUIElement::isSelected() const
{
- // FIXME: implement
- return false;
+ if (!ATK_IS_OBJECT(m_element))
+ return false;
+
+ GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
+ gboolean isSelected = atk_state_set_contains_state(stateSet.get(), ATK_STATE_SELECTED);
+
+ return isSelected;
}
int AccessibilityUIElement::hierarchicalLevel() const
diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
index 0f3ca38..273bcdf 100644
--- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
@@ -843,6 +843,19 @@ static WebKitWebView* webInspectorInspectWebView(WebKitWebInspector*, gpointer d
return WEBKIT_WEB_VIEW(webView);
}
+static void webViewLoadStatusNotified(WebKitWebView* view, gpointer user_data)
+{
+ WebKitLoadStatus loadStatus = webkit_web_view_get_load_status(view);
+
+ if (gLayoutTestController->dumpFrameLoadCallbacks()) {
+ if (loadStatus == WEBKIT_LOAD_PROVISIONAL) {
+ char* frameName = getFrameNameSuitableForTestResult(view, mainFrame);
+ printf("%s - didStartProvisionalLoadForFrame\n", frameName);
+ g_free(frameName);
+ }
+ }
+}
+
static WebKitWebView* createWebView()
{
WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
@@ -871,6 +884,10 @@ static WebKitWebView* createWebView()
"signal::onload-event", webViewOnloadEvent, 0,
NULL);
+ g_signal_connect(view,
+ "notify::load-status", G_CALLBACK(webViewLoadStatusNotified),
+ NULL);
+
WebKitWebInspector* inspector = webkit_web_view_get_inspector(view);
g_object_connect(G_OBJECT(inspector),
"signal::inspect-web-view", webInspectorInspectWebView, 0,
diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
index 25b9f4f..6572a8e 100644
--- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
+++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
@@ -397,6 +397,9 @@ static void resetDefaultsToConsistentValues()
ThemeScrollBarArrowStyle style;
GetThemeScrollBarArrowStyle(&style); // Force HIToolbox to read from CFPreferences
#endif
+
+ [defaults setBool:NO forKey:@"AppleScrollAnimationEnabled"];
+
if (initialValue)
CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), initialValue.get(), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
index 8c5cebf..b5b6f82 100644
--- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
+++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm
@@ -122,7 +122,7 @@ BOOL replayingSavedEvents;
{
if (aSelector == @selector(beginDragWithFiles:)
|| aSelector == @selector(clearKillRing)
- || aSelector == @selector(contextClick)
+ || aSelector == @selector(contextClick:)
|| aSelector == @selector(enableDOMUIEventLogging:)
|| aSelector == @selector(fireKeyboardEventsToElement:)
|| aSelector == @selector(keyDown:withModifiers:withLocation:)
@@ -152,6 +152,8 @@ BOOL replayingSavedEvents;
{
if (aSelector == @selector(beginDragWithFiles:))
return @"beginDragWithFiles";
+ if (aSelector == @selector(contextClick:))
+ return @"contextClick";
if (aSelector == @selector(enableDOMUIEventLogging:))
return @"enableDOMUIEventLogging";
if (aSelector == @selector(fireKeyboardEventsToElement:))
@@ -492,7 +494,7 @@ static int buildModifierFlags(const WebScriptObject* modifiers)
[self mouseScrollByX:x andY:y continuously:NO];
}
-- (void)contextClick
+- (void)contextClick:(BOOL)shouldPrintMenuItems
{
[[[mainFrame frameView] documentView] layout];
[self updateClickCountForButton:RightMouseButton];
@@ -508,8 +510,21 @@ static int buildModifierFlags(const WebScriptObject* modifiers)
pressure:0.0];
NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]];
- if (subView)
- [subView menuForEvent:event];
+ if (subView) {
+ NSMenu* menu = [subView menuForEvent:event];
+ if (shouldPrintMenuItems) {
+ printf("ContextMenuItems: ");
+ for (int i = 0; i < [menu numberOfItems]; ++i) {
+ NSMenuItem* menuItem = [menu itemAtIndex:i];
+ if (!strcmp("Inspect Element", [[menuItem title] UTF8String]))
+ continue;
+ if (i > 0)
+ printf(", ");
+ fputs([menuItem isSeparatorItem] ? "<separator>" : [[menuItem title] UTF8String], stdout);
+ }
+ printf("\n");
+ }
+ }
}
- (void)scheduleAsynchronousClick
diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
index 29a5812..44aea81 100644
--- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
@@ -66,6 +66,10 @@
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#include <Foundation/NSPrivateDecls.h>
+#endif
+
@interface CommandValidationTarget : NSObject <NSValidatedUserInterfaceItem>
{
SEL _action;
@@ -758,7 +762,12 @@ void LayoutTestController::setWebViewEditable(bool editable)
#ifndef BUILDING_ON_TIGER
static NSString *SynchronousLoaderRunLoopMode = @"DumpRenderTreeSynchronousLoaderRunLoopMode";
-@interface SynchronousLoader : NSObject
+#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || !defined(__COCOA_FORMAL_PROTOCOLS_2__)
+@protocol NSURLConnectionDelegate <NSObject>
+@end
+#endif
+
+@interface SynchronousLoader : NSObject <NSURLConnectionDelegate>
{
NSString *m_username;
NSString *m_password;
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
index 9d2a065..f9caca6 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
@@ -80,10 +80,6 @@
#include <qdebug.h>
-extern void qt_dump_set_accepts_editing(bool b);
-extern void qt_dump_frame_loader(bool b);
-extern void qt_dump_resource_load_callbacks(bool b);
-
namespace WebCore {
NetworkAccessManager::NetworkAccessManager(QObject* parent)
@@ -192,6 +188,7 @@ void WebPage::resetSettings()
settings()->resetAttribute(QWebSettings::LocalContentCanAccessRemoteUrls);
settings()->resetAttribute(QWebSettings::PluginsEnabled);
settings()->resetAttribute(QWebSettings::JavaScriptCanAccessClipboard);
+ settings()->resetAttribute(QWebSettings::AutoLoadImages);
m_drt->layoutTestController()->setCaretBrowsingEnabled(false);
m_drt->layoutTestController()->setFrameFlatteningEnabled(false);
@@ -343,14 +340,11 @@ DumpRenderTree::DumpRenderTree()
, m_stdin(0)
, m_enableTextOutput(false)
, m_singleFileMode(false)
+ , m_persistentStoragePath(QString(getenv("DUMPRENDERTREE_TEMP")))
{
DumpRenderTreeSupportQt::overwritePluginDirectories();
- char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP");
- if (dumpRenderTreeTemp)
- QWebSettings::enablePersistentStorage(QString(dumpRenderTreeTemp));
- else
- QWebSettings::enablePersistentStorage();
+ QWebSettings::enablePersistentStorage(m_persistentStoragePath);
// create our primary testing page/view.
m_mainView = new QWebView(0);
@@ -480,6 +474,7 @@ static bool shouldEnableDeveloperExtras(const QUrl& url)
void DumpRenderTree::open(const QUrl& url)
{
+ DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(QFileInfo(url.toString()).path());
resetToConsistentStateBeforeTesting();
if (shouldEnableDeveloperExtras(m_page->mainFrame()->url())) {
@@ -512,7 +507,7 @@ void DumpRenderTree::open(const QUrl& url)
initializeFonts();
#endif
- qt_dump_frame_loader(url.toString().contains("loading/"));
+ DumpRenderTreeSupportQt::dumpFrameLoader(url.toString().contains("loading/"));
setTextOutputEnabled(true);
m_page->mainFrame()->load(url);
}
@@ -733,8 +728,8 @@ static const char *methodNameStringForFailedTest(LayoutTestController *controlle
void DumpRenderTree::dump()
{
// Prevent any further frame load or resource load callbacks from appearing after we dump the result.
- qt_dump_frame_loader(false);
- qt_dump_resource_load_callbacks(false);
+ DumpRenderTreeSupportQt::dumpFrameLoader(false);
+ DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(false);
QWebFrame *mainFrame = m_page->mainFrame();
@@ -751,6 +746,7 @@ void DumpRenderTree::dump()
resultString = mainFrame->renderTreeDump();
if (!resultString.isEmpty()) {
+ fprintf(stdout, "Content-Type: text/plain\n");
fprintf(stdout, "%s", resultString.toUtf8().constData());
if (m_controller->shouldDumpBackForwardList())
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
index 8309492..e6449b7 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
@@ -86,6 +86,7 @@ public:
LayoutTestController *layoutTestController() const { return m_controller; }
EventSender *eventSender() const { return m_eventSender; }
TextInputController *textInputController() const { return m_textInputController; }
+ QString persistentStoragePath() const { return m_persistentStoragePath; }
QWebPage *createWindow();
int windowCount() const;
@@ -141,6 +142,7 @@ private:
QList<QObject*> windows;
bool m_enableTextOutput;
bool m_singleFileMode;
+ QString m_persistentStoragePath;
};
class NetworkAccessManager : public QNetworkAccessManager {
diff --git a/WebKitTools/DumpRenderTree/qt/ImageDiff.cpp b/WebKitTools/DumpRenderTree/qt/ImageDiff.cpp
index 704ca13..8ee68db 100644
--- a/WebKitTools/DumpRenderTree/qt/ImageDiff.cpp
+++ b/WebKitTools/DumpRenderTree/qt/ImageDiff.cpp
@@ -17,13 +17,14 @@
Boston, MA 02110-1301, USA.
*/
+#include <QtCore/qmath.h>
+
#include <QApplication>
#include <QBuffer>
#include <QByteArray>
#include <QImage>
#include <QStringList>
-#include <math.h>
#include <stdio.h>
int main(int argc, char* argv[])
@@ -102,7 +103,7 @@ int main(int argc, char* argv[])
qreal green = (qGreen(pixel) - qGreen(basePixel)) / static_cast<float>(qMax(255 - qGreen(basePixel), qGreen(basePixel)));
qreal blue = (qBlue(pixel) - qBlue(basePixel)) / static_cast<float>(qMax(255 - qBlue(basePixel), qBlue(basePixel)));
qreal alpha = (qAlpha(pixel) - qAlpha(basePixel)) / static_cast<float>(qMax(255 - qAlpha(basePixel), qAlpha(basePixel)));
- qreal distance = sqrt(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
+ qreal distance = qSqrt(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
int gray = distance * qreal(255);
diffImage.setPixel(x, y, qRgb(gray, gray, gray));
if (distance >= 1 / qreal(255)) {
@@ -118,7 +119,7 @@ int main(int argc, char* argv[])
if (difference <= tolerance) {
difference = 0;
} else {
- difference = round(difference * 100) / 100;
+ difference = qRound(difference * 100) / 100;
difference = qMax(difference, qreal(0.01));
}
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
index 3f92b8a..1fadd61 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
@@ -37,22 +37,13 @@
#include <QLocale>
#include <qwebsettings.h>
-extern void qt_dump_editing_callbacks(bool b);
-extern void qt_dump_frame_loader(bool b);
-extern void qt_dump_resource_load_callbacks(bool b);
-extern void qt_set_will_send_request_returns_null_on_redirect(bool b);
-extern void qt_set_will_send_request_returns_null(bool b);
-extern void qt_set_will_send_request_clear_headers(const QStringList& headers);
-
-extern void qt_dump_notification(bool b);
-
LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt)
: QObject()
, m_drt(drt)
{
qRegisterMetaType<QWebElement>("QWebElement");
reset();
- qt_dump_notification(true);
+ DumpRenderTreeSupportQt::dumpNotification(true);
}
void LayoutTestController::reset()
@@ -73,12 +64,13 @@ void LayoutTestController::reset()
m_handleErrorPages = false;
m_webHistory = 0;
m_globalFlag = false;
- qt_dump_editing_callbacks(false);
- qt_dump_frame_loader(false);
- qt_dump_resource_load_callbacks(false);
- qt_set_will_send_request_returns_null_on_redirect(false);
- qt_set_will_send_request_returns_null(false);
- qt_set_will_send_request_clear_headers(QStringList());
+ DumpRenderTreeSupportQt::dumpEditingCallbacks(false);
+ DumpRenderTreeSupportQt::dumpFrameLoader(false);
+ DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(false);
+ DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(false);
+ DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(false);
+ DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(QStringList());
+ setIconDatabaseEnabled(false);
emit hidePage();
}
@@ -217,32 +209,32 @@ QString LayoutTestController::pathToLocalResource(const QString& url)
void LayoutTestController::dumpEditingCallbacks()
{
qDebug() << ">>>dumpEditingCallbacks";
- qt_dump_editing_callbacks(true);
+ DumpRenderTreeSupportQt::dumpEditingCallbacks(true);
}
void LayoutTestController::dumpFrameLoadCallbacks()
{
- qt_dump_frame_loader(true);
+ DumpRenderTreeSupportQt::dumpFrameLoader(true);
}
void LayoutTestController::dumpResourceLoadCallbacks()
{
- qt_dump_resource_load_callbacks(true);
+ DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(true);
}
void LayoutTestController::setWillSendRequestReturnsNullOnRedirect(bool enabled)
{
- qt_set_will_send_request_returns_null_on_redirect(enabled);
+ DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(enabled);
}
void LayoutTestController::setWillSendRequestReturnsNull(bool enabled)
{
- qt_set_will_send_request_returns_null(enabled);
+ DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(enabled);
}
void LayoutTestController::setWillSendRequestClearHeader(const QStringList& headers)
{
- qt_set_will_send_request_clear_headers(headers);
+ DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(headers);
}
void LayoutTestController::queueBackNavigation(int howFarBackward)
@@ -465,8 +457,7 @@ unsigned LayoutTestController::numberOfActiveAnimations() const
void LayoutTestController::disableImageLoading()
{
- // FIXME: Implement for testing fix for https://bugs.webkit.org/show_bug.cgi?id=27896
- // Also need to make sure image loading is re-enabled for each new test.
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::AutoLoadImages, false);
}
void LayoutTestController::dispatchPendingLoadRequests()
@@ -624,11 +615,28 @@ QString LayoutTestController::markerTextForListItem(const QWebElement& listItem)
return DumpRenderTreeSupportQt::markerTextForListItem(listItem);
}
+QVariantMap LayoutTestController::computedStyleIncludingVisitedInfo(const QWebElement& element) const
+{
+ return DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(element);
+}
+
+bool LayoutTestController::elementDoesAutoCompleteForElementWithId(const QString& elementId)
+{
+ return DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(m_drt->webPage()->mainFrame(), elementId);
+}
+
void LayoutTestController::authenticateSession(const QString&, const QString&, const QString&)
{
// FIXME: If there is a concept per-session (per-process) credential storage, the credentials should be added to it for later use.
}
+void LayoutTestController::setIconDatabaseEnabled(bool enable)
+{
+ if (enable && !m_drt->persistentStoragePath().isEmpty())
+ QWebSettings::setIconDatabasePath(m_drt->persistentStoragePath());
+ else
+ QWebSettings::setIconDatabasePath(QString());
+}
const unsigned LayoutTestController::maxViewWidth = 800;
const unsigned LayoutTestController::maxViewHeight = 600;
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
index 44b80b7..1359a6f 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
@@ -157,6 +157,7 @@ public slots:
bool pauseAnimationAtTimeOnElementWithId(const QString& animationName, double time, const QString& elementId);
bool pauseTransitionAtTimeOnElementWithId(const QString& propertyName, double time, const QString& elementId);
bool sampleSVGAnimationForElementAtTime(const QString& animationId, double time, const QString& elementId);
+ bool elementDoesAutoCompleteForElementWithId(const QString& elementId);
unsigned numberOfActiveAnimations() const;
@@ -168,6 +169,7 @@ public slots:
void setDatabaseQuota(int size);
void clearAllDatabases();
+ void setIconDatabaseEnabled(bool enable);
void waitForPolicyDelegate();
void overridePreference(const QString& name, const QVariant& value);
@@ -186,6 +188,7 @@ public slots:
void setScrollbarPolicy(const QString& orientation, const QString& policy);
QString markerTextForListItem(const QWebElement& listItem);
+ QVariantMap computedStyleIncludingVisitedInfo(const QWebElement& element) const;
// Simulate a request an embedding application could make, populating per-session credential storage.
void authenticateSession(const QString& url, const QString& username, const QString& password);
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
index e96adae..dfa4de0 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
@@ -140,6 +140,17 @@ wstring urlSuitableForTestResult(const wstring& url)
return PathFindFileNameW(url.c_str());
}
+string toUTF8(BSTR bstr)
+{
+ int result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, 0, 0, 0, 0);
+ Vector<char> utf8Vector(result);
+ result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, utf8Vector.data(), result, 0, 0);
+ if (!result)
+ return string();
+
+ return string(utf8Vector.data(), utf8Vector.size() - 1);
+}
+
static LRESULT CALLBACK DumpRenderTreeWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h
index 499c57b..eb5d312 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h
@@ -49,6 +49,7 @@ extern HWND webViewWindow;
#include <wtf/Vector.h>
std::wstring urlSuitableForTestResult(const std::wstring& url);
+std::string toUTF8(BSTR);
IWebView* createWebViewAndOffscreenWindow(HWND* webViewWindow = 0);
Vector<HWND>& openWindows();
typedef HashMap<HWND, COMPtr<IWebView> > WindowToWebViewMap;
diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp
index cf4d221..9b9e3c1 100644
--- a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp
+++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp
@@ -48,17 +48,6 @@ using std::string;
static FrameLoadDelegate* g_delegateWaitingOnTimer;
-string BSTRtoString(BSTR bstr)
-{
- int result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, 0, 0, 0, 0);
- Vector<char> utf8Vector(result);
- result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, utf8Vector.data(), result, 0, 0);
- if (!result)
- return string();
-
- return string(utf8Vector.data(), utf8Vector.size() - 1);
-}
-
string descriptionSuitableForTestResult(IWebFrame* webFrame)
{
COMPtr<IWebView> webView;
@@ -70,11 +59,11 @@ string descriptionSuitableForTestResult(IWebFrame* webFrame)
return string();
BSTR frameNameBSTR;
- if (FAILED(webFrame->name(&frameNameBSTR)) || BSTRtoString(frameNameBSTR).empty() )
+ if (FAILED(webFrame->name(&frameNameBSTR)) || toUTF8(frameNameBSTR).empty())
return (webFrame == mainFrame) ? "main frame" : string();
string frameName = (webFrame == mainFrame) ? "main frame" : "frame";
- frameName += " \"" + BSTRtoString(frameNameBSTR) + "\"";
+ frameName += " \"" + toUTF8(frameNameBSTR) + "\"";
SysFreeString(frameNameBSTR);
return frameName;
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
index 89873b6..321d9cf 100644
--- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
+++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
@@ -106,7 +106,9 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc
pluginLog(instance, "src: %s", argv[i]);
} else if (_stricmp(argn[i], "testdocumentopenindestroystream") == 0)
obj->testDocumentOpenInDestroyStream = TRUE;
- else if (_stricmp(argn[i], "testwindowopen") == 0)
+ else if (_stricmp(argn[i], "testGetURLOnDestroy") == 0)
+ obj->testGetURLOnDestroy = TRUE;
+ else if (_stricmp(argn[i], "testwindowopen") == 0)
obj->testWindowOpen = TRUE;
else if (_stricmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow)
obj->onSetWindow = strdup(argv[i]);
@@ -122,6 +124,9 @@ NPError NPP_Destroy(NPP instance, NPSavedData **save)
{
PluginObject *obj = (PluginObject*)instance->pdata;
if (obj) {
+ if (obj->testGetURLOnDestroy)
+ browser->geturlnotify(obj->npp, "about:blank", "", "");
+
if (obj->onStreamLoad)
free(obj->onStreamLoad);
@@ -137,7 +142,7 @@ NPError NPP_Destroy(NPP instance, NPSavedData **save)
}
if (obj->logDestroy)
- printf("PLUGIN: NPP_Destroy\n");
+ pluginLog(instance, "NPP_Destroy\n");
if (obj->onSetWindow)
free(obj->onSetWindow);
diff --git a/WebKitTools/DumpRenderTree/win/UIDelegate.cpp b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
index 16724d7..6637068 100755
--- a/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
+++ b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
@@ -625,7 +625,7 @@ HRESULT STDMETHODCALLTYPE UIDelegate::webViewDidInvalidate(
HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text)
{
if (gLayoutTestController->dumpStatusCallbacks())
- printf("UI DELEGATE STATUS CALLBACK: setStatusText:%S\n", text ? text : L"");
+ printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text ? toUTF8(text).c_str() : "");
return S_OK;
}
diff --git a/WebKitTools/QtLauncher/QtLauncher.pro b/WebKitTools/QtTestBrowser/QtTestBrowser.pro
index a91cee9..4c4d83f 100644
--- a/WebKitTools/QtLauncher/QtLauncher.pro
+++ b/WebKitTools/QtTestBrowser/QtTestBrowser.pro
@@ -55,4 +55,4 @@ contains(QT_CONFIG, opengl) {
}
RESOURCES += \
- QtLauncher.qrc
+ QtTestBrowser.qrc
diff --git a/WebKitTools/QtLauncher/QtLauncher.qrc b/WebKitTools/QtTestBrowser/QtTestBrowser.qrc
index ffe77b0..ffe77b0 100644
--- a/WebKitTools/QtLauncher/QtLauncher.qrc
+++ b/WebKitTools/QtTestBrowser/QtTestBrowser.qrc
diff --git a/WebKitTools/QtLauncher/fpstimer.cpp b/WebKitTools/QtTestBrowser/fpstimer.cpp
index 3b72cef..3b72cef 100644
--- a/WebKitTools/QtLauncher/fpstimer.cpp
+++ b/WebKitTools/QtTestBrowser/fpstimer.cpp
diff --git a/WebKitTools/QtLauncher/fpstimer.h b/WebKitTools/QtTestBrowser/fpstimer.h
index 66d38eb..66d38eb 100644
--- a/WebKitTools/QtLauncher/fpstimer.h
+++ b/WebKitTools/QtTestBrowser/fpstimer.h
diff --git a/WebKitTools/QtLauncher/locationedit.cpp b/WebKitTools/QtTestBrowser/locationedit.cpp
index a97f148..a97f148 100644
--- a/WebKitTools/QtLauncher/locationedit.cpp
+++ b/WebKitTools/QtTestBrowser/locationedit.cpp
diff --git a/WebKitTools/QtLauncher/locationedit.h b/WebKitTools/QtTestBrowser/locationedit.h
index e82920c..e82920c 100644
--- a/WebKitTools/QtLauncher/locationedit.h
+++ b/WebKitTools/QtTestBrowser/locationedit.h
diff --git a/WebKitTools/QtLauncher/main.cpp b/WebKitTools/QtTestBrowser/main.cpp
index 748936b..49c08d9 100644
--- a/WebKitTools/QtLauncher/main.cpp
+++ b/WebKitTools/QtTestBrowser/main.cpp
@@ -734,13 +734,15 @@ void LauncherWindow::showUserAgentDialog()
items << customUserAgent;
QDialog* dialog = new QDialog(this);
+ dialog->resize(size().width() * 0.7, dialog->size().height());
+ dialog->setMaximumHeight(dialog->size().height());
dialog->setWindowTitle("Change User Agent");
QVBoxLayout* layout = new QVBoxLayout(dialog);
dialog->setLayout(layout);
QComboBox* combo = new QComboBox(dialog);
- combo->setMaximumWidth(size().width() * 0.7);
+ combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
combo->setEditable(true);
combo->insertItems(0, items);
layout->addWidget(combo);
diff --git a/WebKitTools/QtLauncher/mainwindow.cpp b/WebKitTools/QtTestBrowser/mainwindow.cpp
index aa6aa26..aa6aa26 100644
--- a/WebKitTools/QtLauncher/mainwindow.cpp
+++ b/WebKitTools/QtTestBrowser/mainwindow.cpp
diff --git a/WebKitTools/QtLauncher/mainwindow.h b/WebKitTools/QtTestBrowser/mainwindow.h
index d753a46..d753a46 100644
--- a/WebKitTools/QtLauncher/mainwindow.h
+++ b/WebKitTools/QtTestBrowser/mainwindow.h
diff --git a/WebKitTools/QtLauncher/urlloader.cpp b/WebKitTools/QtTestBrowser/urlloader.cpp
index 630ead6..630ead6 100644
--- a/WebKitTools/QtLauncher/urlloader.cpp
+++ b/WebKitTools/QtTestBrowser/urlloader.cpp
diff --git a/WebKitTools/QtLauncher/urlloader.h b/WebKitTools/QtTestBrowser/urlloader.h
index ed14adc..ed14adc 100644
--- a/WebKitTools/QtLauncher/urlloader.h
+++ b/WebKitTools/QtTestBrowser/urlloader.h
diff --git a/WebKitTools/QtLauncher/useragentlist.txt b/WebKitTools/QtTestBrowser/useragentlist.txt
index ca53693..ca53693 100644
--- a/WebKitTools/QtLauncher/useragentlist.txt
+++ b/WebKitTools/QtTestBrowser/useragentlist.txt
diff --git a/WebKitTools/QtLauncher/utils.cpp b/WebKitTools/QtTestBrowser/utils.cpp
index 2d45dd0..2d45dd0 100644
--- a/WebKitTools/QtLauncher/utils.cpp
+++ b/WebKitTools/QtTestBrowser/utils.cpp
diff --git a/WebKitTools/QtLauncher/utils.h b/WebKitTools/QtTestBrowser/utils.h
index b67351e..b67351e 100644
--- a/WebKitTools/QtLauncher/utils.h
+++ b/WebKitTools/QtTestBrowser/utils.h
diff --git a/WebKitTools/QtLauncher/webinspector.h b/WebKitTools/QtTestBrowser/webinspector.h
index d251c5c..d251c5c 100644
--- a/WebKitTools/QtLauncher/webinspector.h
+++ b/WebKitTools/QtTestBrowser/webinspector.h
diff --git a/WebKitTools/QtLauncher/webpage.cpp b/WebKitTools/QtTestBrowser/webpage.cpp
index 624a66f..624a66f 100644
--- a/WebKitTools/QtLauncher/webpage.cpp
+++ b/WebKitTools/QtTestBrowser/webpage.cpp
diff --git a/WebKitTools/QtLauncher/webpage.h b/WebKitTools/QtTestBrowser/webpage.h
index 061deb5..061deb5 100644
--- a/WebKitTools/QtLauncher/webpage.h
+++ b/WebKitTools/QtTestBrowser/webpage.h
diff --git a/WebKitTools/QtLauncher/webview.cpp b/WebKitTools/QtTestBrowser/webview.cpp
index 1467cf8..1467cf8 100644
--- a/WebKitTools/QtLauncher/webview.cpp
+++ b/WebKitTools/QtTestBrowser/webview.cpp
diff --git a/WebKitTools/QtLauncher/webview.h b/WebKitTools/QtTestBrowser/webview.h
index 30161bb..30161bb 100644
--- a/WebKitTools/QtLauncher/webview.h
+++ b/WebKitTools/QtTestBrowser/webview.h
diff --git a/WebKitTools/QueueStatusServer/handlers/dashboard.py b/WebKitTools/QueueStatusServer/handlers/dashboard.py
index 80f30ec..bbb65b8 100644
--- a/WebKitTools/QueueStatusServer/handlers/dashboard.py
+++ b/WebKitTools/QueueStatusServer/handlers/dashboard.py
@@ -26,16 +26,55 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import operator
+
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from model.attachment import Attachment
+from model.queues import queues
+
class Dashboard(webapp.RequestHandler):
- def get(self):
- attachments = Attachment.recent(limit=25)
+ # FIXME: This list probably belongs as part of a Queue object in queues.py
+ # Arrays are bubble_name, queue_name
+ # FIXME: Can this be unified with StatusBubble._queues_to_display?
+ _queues_to_display = [
+ ["Style", "style-queue"],
+ ["Cr-Linux", "chromium-ews"],
+ ["Cr-Win", "cr-win-ews"],
+ ["Qt", "qt-ews"],
+ ["Gtk", "gtk-ews"],
+ ["Mac", "mac-ews"],
+ ["Win", "win-ews"],
+ ["Commit", "commit-queue"],
+ ]
+ # Split the zipped list into component parts
+ _header_names, _ordered_queue_names = zip(*_queues_to_display)
+
+ # This asserts that all of the queues listed above are valid queue names.
+ assert(reduce(operator.and_, map(lambda name: name in queues, _ordered_queue_names)))
+
+ def _build_bubble(self, attachment, queue_name):
+ queue_status = attachment.status_for_queue(queue_name)
+ bubble = {
+ "status_class": attachment.state_from_queue_status(queue_status) if queue_status else "none",
+ "status_date": queue_status.date if queue_status else None,
+ }
+ return bubble
+
+ def _build_row(self, attachment):
+ row = {
+ "bug_id": attachment.bug_id(),
+ "attachment_id": attachment.id,
+ "bubbles": [self._build_bubble(attachment, queue_name) for queue_name in self._ordered_queue_names],
+ }
+ return row
+
+ def get(self):
template_values = {
- "summaries" : [attachment.summary() for attachment in attachments],
+ "headers": self._header_names,
+ "rows": [self._build_row(attachment) for attachment in Attachment.recent(limit=25)],
}
self.response.out.write(template.render("templates/dashboard.html", template_values))
diff --git a/WebKitTools/QueueStatusServer/handlers/statusbubble.py b/WebKitTools/QueueStatusServer/handlers/statusbubble.py
index d52509f..0e2b8de 100644
--- a/WebKitTools/QueueStatusServer/handlers/statusbubble.py
+++ b/WebKitTools/QueueStatusServer/handlers/statusbubble.py
@@ -26,17 +26,50 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import operator
+
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from model.attachment import Attachment
+from model.workitems import WorkItems
+from model.queues import queues, name_with_underscores
class StatusBubble(webapp.RequestHandler):
+ # FIXME: This list probably belongs as part of a Queue object in queues.py
+ # Arrays are bubble_name, queue_name
+ _queues_to_display = [
+ ["style", "style-queue"],
+ ["cr-linux", "chromium-ews"],
+ ["cr-win", "cr-win-ews"],
+ ["gtk", "gtk-ews"],
+ ["qt", "qt-ews"],
+ ["mac", "mac-ews"],
+ ["win", "win-ews"],
+ ]
+
+ # This asserts that all of the queues listed above are valid queue names.
+ assert(reduce(operator.and_, map(lambda name_pair: name_pair[1] in queues, _queues_to_display)))
+
+ def _build_bubble(self, queue_name_pair, attachment):
+ bubble_name = queue_name_pair[0]
+ queue_name = queue_name_pair[1]
+
+ queue_status = attachment.status_for_queue(queue_name)
+ bubble = {
+ "name": bubble_name,
+ "attachment_id": attachment.id,
+ "queue_position": attachment.position_in_queue(queue_name),
+ "state": attachment.state_from_queue_status(queue_status) if queue_status else "none",
+ "status": queue_status,
+ }
+ return bubble
+
def get(self, attachment_id):
attachment = Attachment(int(attachment_id))
-
+ bubbles = [self._build_bubble(name_pair, attachment) for name_pair in self._queues_to_display]
template_values = {
- "summary" : attachment.summary()
+ "bubbles": bubbles,
}
self.response.out.write(template.render("templates/statusbubble.html", template_values))
diff --git a/WebKitTools/QueueStatusServer/handlers/updatestatus.py b/WebKitTools/QueueStatusServer/handlers/updatestatus.py
index 50d4b6e..5a93dbd 100644
--- a/WebKitTools/QueueStatusServer/handlers/updatestatus.py
+++ b/WebKitTools/QueueStatusServer/handlers/updatestatus.py
@@ -38,9 +38,10 @@ class UpdateStatus(UpdateBase):
def get(self):
self.response.out.write(template.render("templates/updatestatus.html", None))
- def post(self):
+ def _queue_status_from_request(self):
queue_status = QueueStatus()
+ # FIXME: I think this can be removed, no one uses it.
if users.get_current_user():
queue_status.author = users.get_current_user()
@@ -53,6 +54,10 @@ class UpdateStatus(UpdateBase):
queue_status.message = self.request.get("status")
results_file = self.request.get("results_file")
queue_status.results_file = db.Blob(str(results_file))
+ return queue_status
+
+ def post(self):
+ queue_status = self._queue_status_from_request()
queue_status.put()
- Attachment.dirty(patch_id)
+ Attachment.dirty(queue_status.active_patch_id)
self.response.out.write(queue_status.key().id())
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_wsh.py b/WebKitTools/QueueStatusServer/handlers/updateworkitems.py
index 50cad31..b58e743 100644
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_wsh.py
+++ b/WebKitTools/QueueStatusServer/handlers/updateworkitems.py
@@ -1,5 +1,4 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
+# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -27,23 +26,39 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
-from mod_pywebsocket import msgutil
+from handlers.updatebase import UpdateBase
+from model.queues import queues
+from model.workitems import WorkItems
+from datetime import datetime
-_GOODBYE_MESSAGE = 'Goodbye'
+class UpdateWorkItems(UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/updateworkitems.html", None))
-def web_socket_do_extra_handshake(request):
- pass # Always accept.
-
-
-def web_socket_transfer_data(request):
- while True:
- line = msgutil.receive_message(request)
- msgutil.send_message(request, line)
- if line == _GOODBYE_MESSAGE:
+ def _work_items_for_queue(self, queue_name):
+ if queue_name not in queues:
+ self.response.set_status(500)
return
+ work_items = WorkItems.all().filter("queue_name =", queue_name).get()
+ if not work_items:
+ work_items = WorkItems()
+ work_items.queue_name = queue_name
+ return work_items
+ def _work_items_from_request(self):
+ queue_name = self.request.get("queue_name")
+ work_items = self._work_items_for_queue(queue_name)
+ items_string = self.request.get("work_items")
+ # Our parsing could be much more robust.
+ work_items.item_ids = map(int, items_string.split(" "))
+ work_items.date = datetime.now()
+ return work_items
-# vi:sts=4 sw=4 et
+ def post(self):
+ work_items = self._work_items_from_request()
+ work_items.put()
diff --git a/WebKitTools/QueueStatusServer/main.py b/WebKitTools/QueueStatusServer/main.py
index 8bfa7e9..fb6fc4b 100644
--- a/WebKitTools/QueueStatusServer/main.py
+++ b/WebKitTools/QueueStatusServer/main.py
@@ -43,6 +43,8 @@ from handlers.statusbubble import StatusBubble
from handlers.svnrevision import SVNRevision
from handlers.updatestatus import UpdateStatus
from handlers.updatesvnrevision import UpdateSVNRevision
+from handlers.updateworkitems import UpdateWorkItems
+
webapp.template.register_template_library('filters.webkit_extras')
@@ -57,6 +59,7 @@ routes = [
(r'/svn-revision/(.*)', SVNRevision),
(r'/queue-status/(.*)', RecentStatus),
('/update-status', UpdateStatus),
+ ('/update-work-items', UpdateWorkItems),
('/update-svn-revision', UpdateSVNRevision),
]
diff --git a/WebKitTools/QueueStatusServer/model/attachment.py b/WebKitTools/QueueStatusServer/model/attachment.py
index 751f78e..9ae59e8 100644
--- a/WebKitTools/QueueStatusServer/model/attachment.py
+++ b/WebKitTools/QueueStatusServer/model/attachment.py
@@ -30,8 +30,9 @@ import re
from google.appengine.api import memcache
-from model.queues import queues
+from model.queues import queues, name_with_underscores
from model.queuestatus import QueueStatus
+from model.workitems import WorkItems
class Attachment(object):
@@ -60,6 +61,7 @@ class Attachment(object):
def __init__(self, attachment_id):
self.id = attachment_id
self._summary = None
+ self._cached_queue_positions = None
def summary(self):
if self._summary:
@@ -71,11 +73,7 @@ class Attachment(object):
memcache.set(str(self.id), self._summary, namespace="attachment-summary")
return self._summary
- def _dash_to_underscore(self, dashed_name):
- regexp = re.compile("-")
- return regexp.sub("_", dashed_name)
-
- def _state_from_status(self, status):
+ def state_from_queue_status(self, status):
table = {
"Pass" : "pass",
"Fail" : "fail",
@@ -89,6 +87,40 @@ class Attachment(object):
return "pending"
return None
+ def position_in_queue(self, queue_name):
+ return self._queue_positions().get(queue_name)
+
+ def status_for_queue(self, queue_name):
+ underscore_queue_name = name_with_underscores(queue_name)
+ # summary() is a horrible API and should be killed.
+ queue_summary = self.summary().get(underscore_queue_name)
+ if not queue_summary:
+ return None
+ return queue_summary.get("status")
+
+ def bug_id(self):
+ return self.summary().get("bug_id")
+
+ def _queue_positions(self):
+ if self._cached_queue_positions:
+ return self._cached_queue_positions
+ # FIXME: Should we be mem-caching this?
+ self._cached_queue_positions = self._calculate_queue_positions()
+ return self._cached_queue_positions
+
+ def _calculate_queue_positions(self):
+ queue_positions = {}
+ for work_items in WorkItems.all().fetch(limit=len(queues)):
+ queue_name = str(work_items.queue_name)
+ try:
+ position = work_items.item_ids.index(self.id)
+ # Display 1-based indecies to the user.
+ queue_positions[queue_name] = position + 1
+ except ValueError, e:
+ queue_positions[queue_name] = None
+ return queue_positions
+
+ # FIXME: This is controller/view code and does not belong in a model.
def _fetch_summary(self):
summary = { "attachment_id" : self.id }
@@ -102,8 +134,8 @@ class Attachment(object):
summary[queue] = None
status = QueueStatus.all().filter('queue_name =', queue).filter('active_patch_id =', self.id).order('-date').get()
if status:
- summary[self._dash_to_underscore(queue)] = {
- "state" : self._state_from_status(status),
- "status" : status,
+ summary[name_with_underscores(queue)] = {
+ "state": self.state_from_queue_status(status),
+ "status": status,
}
return summary
diff --git a/WebKitTools/QueueStatusServer/model/queues.py b/WebKitTools/QueueStatusServer/model/queues.py
index 57463de..46f2f15 100644
--- a/WebKitTools/QueueStatusServer/model/queues.py
+++ b/WebKitTools/QueueStatusServer/model/queues.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2009 Google Inc. All rights reserved.
+# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -26,6 +26,9 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import re
+
+
queues = [
"commit-queue",
"style-queue",
@@ -36,3 +39,8 @@ queues = [
"mac-ews",
"win-ews",
]
+
+
+def name_with_underscores(dashed_name):
+ regexp = re.compile("-")
+ return regexp.sub("_", dashed_name)
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py b/WebKitTools/QueueStatusServer/model/workitems.py
index 26352eb..3ea59cb 100644
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py
+++ b/WebKitTools/QueueStatusServer/model/workitems.py
@@ -1,5 +1,4 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
+# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -27,13 +26,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from google.appengine.ext import db
-"""Non-callable handlers.
-"""
-
-web_socket_do_extra_handshake = True
-web_socket_transfer_data = 1
-
-
-# vi:sts=4 sw=4 et
+class WorkItems(db.Model):
+ queue_name = db.StringProperty()
+ item_ids = db.ListProperty(int)
+ date = db.DateTimeProperty(auto_now_add=True)
diff --git a/WebKitTools/QueueStatusServer/templates/dashboard.html b/WebKitTools/QueueStatusServer/templates/dashboard.html
index 14b7ede..c5c2359 100644
--- a/WebKitTools/QueueStatusServer/templates/dashboard.html
+++ b/WebKitTools/QueueStatusServer/templates/dashboard.html
@@ -17,57 +17,27 @@ function statusDetail(patch_id) {
<tr>
<th>Bug</th>
<th>Attachment</th>
- <th>Style</th>
- <th>Cr-Linux</th>
- <th>Cr-Win</th>
- <th>Qt</th>
- <th>Mac</th>
- <th>Win</th>
- <th>Gtk</th>
- <th>Commit</th>
+ {% for header in headers %}
+ <th>{{ header }}</th>
+ {% endfor %}
</tr>
</thead>
- <tbody>{% for summary in summaries %}
+ <tbody>{% for row in rows %}
<tr>
<td class="status">
- {{ summary.bug_id|force_escape|webkit_bug_id|safe }}
+ {{ row.bug_id|force_escape|webkit_bug_id|safe }}
</td>
<td class="status">
- {{ summary.attachment_id|force_escape|webkit_attachment_id|safe }}
+ {{ row.attachment_id|force_escape|webkit_attachment_id|safe }}
</td>
- <!-- FIXME: Find some way to remove this copy-and-paste code! -->
- <td class="status {{ summary.style_queue.state }}"{% if summary.style_queue.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.style_queue.status.date|timesince }}"{% endif %}>
- </td>
- <td class="status {{ summary.chromium_ews.state }}"{% if summary.chromium_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.chromium_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.cr_win_ews.state }}"{% if summary.cr_win_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.cr_win_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.qt_ews.state }}"{% if summary.qt_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.qt_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.mac_ews.state }}"{% if summary.mac_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.mac_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.win_ews.state }}"{% if summary.win_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.win_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.gtk_ews.state }}"{% if summary.gtk_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.gtk_ews.status.date|timesince }} ago"{% endif %}>
- </td>
- <td class="status {{ summary.commit_queue.state }}"{% if summary.commit_queue.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.commit_queue.status.date|timesince }} ago"{% endif %}>
+ {% for bubble in row.bubbles %}
+ <td class="status {{ bubble.status_class }}"
+ {% if bubble.status %}
+ onclick="statusDetail({{ row.attachment_id }})"
+ title="{{ bubble.status_date|timesince }}"
+ {% endif %}>
</td>
+ {% endfor %}
</tr>{% endfor %}
</tbody>
</table>
diff --git a/WebKitTools/QueueStatusServer/templates/statusbubble.html b/WebKitTools/QueueStatusServer/templates/statusbubble.html
index c6e2134..3102741 100644
--- a/WebKitTools/QueueStatusServer/templates/statusbubble.html
+++ b/WebKitTools/QueueStatusServer/templates/statusbubble.html
@@ -18,26 +18,26 @@ body {
border: 1px solid #AAA;
background-color: white;
font-size: 11px;
+ cursor: pointer;
+}
+.none {
+ cursor: auto;
}
.pass {
background-color: #8FDF5F;
border: 1px solid #4F8530;
- cursor: pointer;
}
.fail {
background-color: #E98080;
border: 1px solid #A77272;
- cursor: pointer;
}
.pending {
background-color: #FFFC6C;
border: 1px solid #C5C56D;
- cursor: pointer;
}
.error {
background-color: #E0B0FF;
border: 1px solid #ACA0B3;
- cursor: pointer;
}
</style>
<script>
@@ -47,41 +47,15 @@ function statusDetail(patch_id) {
</script>
</head>
<body>
-<!-- FIXME: Find some way to remove this copy-and-paste code! -->
-<div class="status {{ summary.style_queue.state }}"{% if summary.style_queue.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.style_queue.status.date|timesince }} ago"{% endif %}>
- style
-</div>
-<div class="status {{ summary.chromium_ews.state }}"{% if summary.chromium_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.chromium_ews.status.date|timesince }} ago"{% endif %}>
- cr-linux
-</div>
-<div class="status {{ summary.cr_win_ews.state }}"{% if summary.cr_win_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.cr_win_ews.status.date|timesince }} ago"{% endif %}>
- cr-win
-</div>
-<div class="status {{ summary.qt_ews.state }}"{% if summary.qt_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.qt_ews.status.date|timesince }} ago"{% endif %}>
- qt
-</div>
-<div class="status {{ summary.gtk_ews.state }}"{% if summary.gtk_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.gtk_ews.status.date|timesince }} ago"{% endif %}>
- gtk
-</div>
-<div class="status {{ summary.mac_ews.state }}"{% if summary.mac_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.mac_ews.status.date|timesince }} ago"{% endif %}>
- mac
-</div>
-<div class="status {{ summary.win_ews.state }}"{% if summary.win_ews.status %}
- onclick="statusDetail({{ summary.attachment_id }})"
- title="{{ summary.win_ews.status.date|timesince }} ago"{% endif %}>
- win
+{% for bubble in bubbles %}
+<div class="status {{ bubble.state }}"{% if bubble.status %}
+ onclick="statusDetail({{ bubble.attachment_id }})"
+ title="{{ bubble.status.date|timesince }} ago"{% endif %}>
+ {{ bubble.name }}
+ {% if bubble.queue_position %}
+ (#{{ bubble.queue_position }})
+ {% endif %}
</div>
+{% endfor %}
</body>
</html>
diff --git a/WebKitTools/QueueStatusServer/templates/updateworkitems.html b/WebKitTools/QueueStatusServer/templates/updateworkitems.html
new file mode 100644
index 0000000..b086fc3
--- /dev/null
+++ b/WebKitTools/QueueStatusServer/templates/updateworkitems.html
@@ -0,0 +1,8 @@
+<form name="update_work_items" enctype="multipart/form-data" method="post">
+Update work items for a queue: <input name="queue_name">
+ <div>
+ Work Items:
+ <input name="work_items">
+ </div>
+ <div><input type="submit" value="Update Work Items"></div>
+</form>
diff --git a/WebKitTools/Scripts/VCSUtils.pm b/WebKitTools/Scripts/VCSUtils.pm
index 777fe7f..41bbf40 100644
--- a/WebKitTools/Scripts/VCSUtils.pm
+++ b/WebKitTools/Scripts/VCSUtils.pm
@@ -43,6 +43,7 @@ BEGIN {
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
+ &callSilently
&canonicalizePath
&changeLogEmailAddress
&changeLogName
@@ -67,6 +68,7 @@ BEGIN {
&pathRelativeToSVNRepositoryRootForPath
&prepareParsedPatch
&runPatchCommand
+ &setChangeLogDateAndReviewer
&svnRevisionForDirectory
&svnStatus
);
@@ -83,6 +85,14 @@ my $isGitBranchBuild;
my $isSVN;
my $svnVersion;
+# Project time zone for Cupertino, CA, US
+my $changeLogTimeZone = "PST8PDT";
+
+my $gitDiffStartRegEx = qr#^diff --git (\w/)?(.+) (\w/)?([^\r\n]+)#;
+my $svnDiffStartRegEx = qr#^Index: ([^\r\n]+)#;
+my $svnPropertyStartRegEx = qr#^(Modified|Name|Added|Deleted): ([^\r\n]+)#; # $2 is the name of the property.
+my $svnPropertyValueStartRegEx = qr#^ (\+|-) ([^\r\n]+)#; # $2 is the start of the property's value (which may span multiple lines).
+
# This method is for portability. Return the system-appropriate exit
# status of a child process.
#
@@ -97,6 +107,25 @@ sub exitStatus($)
return WEXITSTATUS($returnvalue);
}
+# Call a function while suppressing STDERR, and return the return values
+# as an array.
+sub callSilently($@) {
+ my ($func, @args) = @_;
+
+ # The following pattern was taken from here:
+ # http://www.sdsc.edu/~moreland/courses/IntroPerl/docs/manual/pod/perlfunc/open.html
+ #
+ # Also see this Perl documentation (search for "open OLDERR"):
+ # http://perldoc.perl.org/functions/open.html
+ open(OLDERR, ">&STDERR");
+ close(STDERR);
+ my @returnValue = &$func(@args);
+ open(STDERR, ">&OLDERR");
+ close(OLDERR);
+
+ return @returnValue;
+}
+
# Note, this method will not error if the file corresponding to the path does not exist.
sub scmToggleExecutableBit
{
@@ -425,14 +454,23 @@ sub isExecutable($)
#
# Returns ($headerHashRef, $lastReadLine):
# $headerHashRef: a hash reference representing a diff header, as follows--
-# copiedFromPath: the path from which the file was copied if the diff
-# is a copy.
+# copiedFromPath: the path from which the file was copied or moved if
+# the diff is a copy or move.
# executableBitDelta: the value 1 or -1 if the executable bit was added or
# removed, respectively. New and deleted files have
# this value only if the file is executable, in which
# case the value is 1 and -1, respectively.
# indexPath: the path of the target file.
# isBinary: the value 1 if the diff is for a binary file.
+# isDeletion: the value 1 if the diff is a file deletion.
+# isCopyWithChanges: the value 1 if the file was copied or moved and
+# the target file was changed in some way after being
+# copied or moved (e.g. if its contents or executable
+# bit were changed).
+# isNew: the value 1 if the diff is for a new file.
+# shouldDeleteSource: the value 1 if the file was copied or moved and
+# the source file was deleted -- i.e. if the copy
+# was actually a move.
# svnConvertedText: the header text with some lines converted to SVN
# format. Git-specific lines are preserved.
# $lastReadLine: the line last read from $fileHandle.
@@ -442,9 +480,8 @@ sub parseGitDiffHeader($$)
$_ = $line;
- my $headerStartRegEx = qr#^diff --git (\w/)?(.+) (\w/)?([^\r\n]+)#;
my $indexPath;
- if (/$headerStartRegEx/) {
+ if (/$gitDiffStartRegEx/) {
# The first and second paths can differ in the case of copies
# and renames. We use the second file path because it is the
# destination path.
@@ -458,9 +495,12 @@ sub parseGitDiffHeader($$)
my $copiedFromPath;
my $foundHeaderEnding;
my $isBinary;
+ my $isDeletion;
+ my $isNew;
my $newExecutableBit = 0;
my $oldExecutableBit = 0;
- my $similarityIndex;
+ my $shouldDeleteSource = 0;
+ my $similarityIndex = 0;
my $svnConvertedText;
while (1) {
# Temporarily strip off any end-of-line characters to simplify
@@ -468,45 +508,60 @@ sub parseGitDiffHeader($$)
s/([\n\r]+)$//;
my $eol = $1;
- if (/^(deleted file|old) mode ([0-9]{6})/) {
+ if (/^(deleted file|old) mode (\d+)/) {
$oldExecutableBit = (isExecutable($2) ? 1 : 0);
- } elsif (/^new( file)? mode ([0-9]{6})/) {
+ $isDeletion = 1 if $1 eq "deleted file";
+ } elsif (/^new( file)? mode (\d+)/) {
$newExecutableBit = (isExecutable($2) ? 1 : 0);
+ $isNew = 1 if $1;
+ } elsif (/^similarity index (\d+)%/) {
+ $similarityIndex = $1;
+ } elsif (/^copy from (\S+)/) {
+ $copiedFromPath = $1;
+ } elsif (/^rename from (\S+)/) {
+ # FIXME: Record this as a move rather than as a copy-and-delete.
+ # This will simplify adding rename support to svn-unapply.
+ # Otherwise, the hash for a deletion would have to know
+ # everything about the file being deleted in order to
+ # support undoing itself. Recording as a move will also
+ # permit us to use "svn move" and "git move".
+ $copiedFromPath = $1;
+ $shouldDeleteSource = 1;
} elsif (/^--- \S+/) {
$_ = "--- $indexPath"; # Convert to SVN format.
} elsif (/^\+\+\+ \S+/) {
$_ = "+++ $indexPath"; # Convert to SVN format.
$foundHeaderEnding = 1;
- } elsif (/^similarity index (\d+)%/) {
- $similarityIndex = $1;
- } elsif (/^copy from (\S+)/) {
- $copiedFromPath = $1;
+ } elsif (/^GIT binary patch$/ ) {
+ $isBinary = 1;
+ $foundHeaderEnding = 1;
# The "git diff" command includes a line of the form "Binary files
# <path1> and <path2> differ" if the --binary flag is not used.
} elsif (/^Binary files / ) {
die("Error: the Git diff contains a binary file without the binary data in ".
"line: \"$_\". Be sure to use the --binary flag when invoking \"git diff\" ".
"with diffs containing binary files.");
- } elsif (/^GIT binary patch$/ ) {
- $isBinary = 1;
- $foundHeaderEnding = 1;
}
$svnConvertedText .= "$_$eol"; # Also restore end-of-line characters.
$_ = <$fileHandle>; # Not defined if end-of-file reached.
- last if (!defined($_) || /$headerStartRegEx/ || $foundHeaderEnding);
+ last if (!defined($_) || /$gitDiffStartRegEx/ || $foundHeaderEnding);
}
my $executableBitDelta = $newExecutableBit - $oldExecutableBit;
my %header;
- $header{copiedFromPath} = $copiedFromPath if ($copiedFromPath && $similarityIndex == 100);
+ $header{copiedFromPath} = $copiedFromPath if $copiedFromPath;
$header{executableBitDelta} = $executableBitDelta if $executableBitDelta;
$header{indexPath} = $indexPath;
$header{isBinary} = $isBinary if $isBinary;
+ $header{isCopyWithChanges} = 1 if ($copiedFromPath && ($similarityIndex != 100 || $executableBitDelta));
+ $header{isDeletion} = $isDeletion if $isDeletion;
+ $header{isNew} = $isNew if $isNew;
+ $header{shouldDeleteSource} = $shouldDeleteSource if $shouldDeleteSource;
$header{svnConvertedText} = $svnConvertedText;
return (\%header, $_);
@@ -531,6 +586,7 @@ sub parseGitDiffHeader($$)
# indexPath: the path of the target file, which is the path found in
# the "Index:" line.
# isBinary: the value 1 if the diff is for a binary file.
+# isNew: the value 1 if the diff is for a new file.
# sourceRevision: the revision number of the source, if it exists. This
# is the same as the revision number the file was copied
# from, in the case of a file copy.
@@ -543,16 +599,17 @@ sub parseSvnDiffHeader($$)
$_ = $line;
- my $headerStartRegEx = qr/^Index: /;
-
- if (!/$headerStartRegEx/) {
+ my $indexPath;
+ if (/$svnDiffStartRegEx/) {
+ $indexPath = $1;
+ } else {
die("First line of SVN diff does not begin with \"Index \": \"$_\"");
}
my $copiedFromPath;
my $foundHeaderEnding;
- my $indexPath;
my $isBinary;
+ my $isNew;
my $sourceRevision;
my $svnConvertedText;
while (1) {
@@ -563,12 +620,11 @@ sub parseSvnDiffHeader($$)
# Fix paths on ""---" and "+++" lines to match the leading
# index line.
- if (/^Index: ([^\r\n]+)/) {
- $indexPath = $1;
- } elsif (s/^--- \S+/--- $indexPath/) {
+ if (s/^--- \S+/--- $indexPath/) {
# ---
if (/^--- .+\(revision (\d+)\)/) {
$sourceRevision = $1;
+ $isNew = 1 if !$sourceRevision; # if revision 0.
if (/\(from (\S+):(\d+)\)$/) {
# The "from" clause is created by svn-create-patch, in
# which case there is always also a "revision" clause.
@@ -588,7 +644,7 @@ sub parseSvnDiffHeader($$)
$_ = <$fileHandle>; # Not defined if end-of-file reached.
- last if (!defined($_) || /$headerStartRegEx/ || $foundHeaderEnding);
+ last if (!defined($_) || /$svnDiffStartRegEx/ || $foundHeaderEnding);
}
if (!$foundHeaderEnding) {
@@ -600,6 +656,7 @@ sub parseSvnDiffHeader($$)
$header{copiedFromPath} = $copiedFromPath if $copiedFromPath;
$header{indexPath} = $indexPath;
$header{isBinary} = $isBinary if $isBinary;
+ $header{isNew} = $isNew if $isNew;
$header{sourceRevision} = $sourceRevision if $sourceRevision;
$header{svnConvertedText} = $svnConvertedText;
@@ -646,10 +703,10 @@ sub parseDiffHeader($$)
my $isSvn;
my $lastReadLine;
- if ($line =~ /^Index:/) {
+ if ($line =~ $svnDiffStartRegEx) {
$isSvn = 1;
($header, $lastReadLine) = parseSvnDiffHeader($fileHandle, $line);
- } elsif ($line =~ /^diff --git/) {
+ } elsif ($line =~ $gitDiffStartRegEx) {
$isGit = 1;
($header, $lastReadLine) = parseGitDiffHeader($fileHandle, $line);
} else {
@@ -681,7 +738,9 @@ sub parseDiffHeader($$)
# indexPath: the path of the target file. For SVN-formatted diffs,
# this is the same as the path in the "Index:" line.
# isBinary: the value 1 if the diff is for a binary file.
+# isDeletion: the value 1 if the diff is known from the header to be a deletion.
# isGit: the value 1 if the diff is Git-formatted.
+# isNew: the value 1 if the dif is known from the header to be a new file.
# isSvn: the value 1 if the diff is SVN-formatted.
# sourceRevision: the revision number of the source, if it exists. This
# is the same as the revision number the file was copied
@@ -700,25 +759,27 @@ sub parseDiffHeader($$)
# header block. Leading junk is okay.
# $line: the line last read from $fileHandle.
#
-# Returns ($diffHashRef, $lastReadLine):
-# $diffHashRef: A reference to a %diffHash.
-# See the %diffHash documentation above.
+# Returns ($diffHashRefs, $lastReadLine):
+# $diffHashRefs: A reference to an array of references to %diffHash hashes.
+# See the %diffHash documentation above.
# $lastReadLine: the line last read from $fileHandle
sub parseDiff($$)
{
+ # FIXME: Adjust this method so that it dies if the first line does not
+ # match the start of a diff. This will require a change to
+ # parsePatch() so that parsePatch() skips over leading junk.
my ($fileHandle, $line) = @_;
- my $headerStartRegEx = qr#^Index: #; # SVN-style header for the default
- my $gitHeaderStartRegEx = qr#^diff --git \w/#;
+ my $headerStartRegEx = $svnDiffStartRegEx; # SVN-style header for the default
my $headerHashRef; # Last header found, as returned by parseDiffHeader().
my $svnText;
while (defined($line)) {
- if (!$headerHashRef && ($line =~ $gitHeaderStartRegEx)) {
+ if (!$headerHashRef && ($line =~ $gitDiffStartRegEx)) {
# Then assume all diffs in the patch are Git-formatted. This
# block was made to be enterable at most once since we assume
# all diffs in the patch are formatted the same (SVN or Git).
- $headerStartRegEx = $gitHeaderStartRegEx;
+ $headerStartRegEx = $gitDiffStartRegEx;
}
if ($line !~ $headerStartRegEx) {
@@ -738,19 +799,191 @@ sub parseDiff($$)
$svnText .= $headerHashRef->{svnConvertedText};
}
- my %diffHashRef;
- $diffHashRef{copiedFromPath} = $headerHashRef->{copiedFromPath} if $headerHashRef->{copiedFromPath};
- # FIXME: Add executableBitDelta as a key.
- $diffHashRef{indexPath} = $headerHashRef->{indexPath};
- $diffHashRef{isBinary} = $headerHashRef->{isBinary} if $headerHashRef->{isBinary};
- $diffHashRef{isGit} = $headerHashRef->{isGit} if $headerHashRef->{isGit};
- $diffHashRef{isSvn} = $headerHashRef->{isSvn} if $headerHashRef->{isSvn};
- $diffHashRef{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision};
- # FIXME: Remove the need for svnConvertedText. See the %diffHash
- # code comments above for more information.
- $diffHashRef{svnConvertedText} = $svnText;
-
- return (\%diffHashRef, $line);
+ my @diffHashRefs;
+
+ if ($headerHashRef->{shouldDeleteSource}) {
+ my %deletionHash;
+ $deletionHash{indexPath} = $headerHashRef->{copiedFromPath};
+ $deletionHash{isDeletion} = 1;
+ push @diffHashRefs, \%deletionHash;
+ }
+ if ($headerHashRef->{copiedFromPath}) {
+ my %copyHash;
+ $copyHash{copiedFromPath} = $headerHashRef->{copiedFromPath};
+ $copyHash{indexPath} = $headerHashRef->{indexPath};
+ $copyHash{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision};
+ push @diffHashRefs, \%copyHash;
+ }
+ if (!$headerHashRef->{copiedFromPath} || $headerHashRef->{isCopyWithChanges}) {
+ # Then add the usual file modification.
+ my %diffHash;
+ # FIXME: Add executableBitDelta as a key.
+ $diffHash{indexPath} = $headerHashRef->{indexPath};
+ $diffHash{isBinary} = $headerHashRef->{isBinary} if $headerHashRef->{isBinary};
+ $diffHash{isDeletion} = $headerHashRef->{isDeletion} if $headerHashRef->{isDeletion};
+ $diffHash{isGit} = $headerHashRef->{isGit} if $headerHashRef->{isGit};
+ $diffHash{isNew} = $headerHashRef->{isNew} if $headerHashRef->{isNew};
+ $diffHash{isSvn} = $headerHashRef->{isSvn} if $headerHashRef->{isSvn};
+ if (!$headerHashRef->{copiedFromPath}) {
+ # If the file was copied, then we have already incorporated the
+ # sourceRevision information into the change.
+ $diffHash{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision};
+ }
+ # FIXME: Remove the need for svnConvertedText. See the %diffHash
+ # code comments above for more information.
+ $diffHash{svnConvertedText} = $svnText;
+ push @diffHashRefs, \%diffHash;
+ }
+
+ return (\@diffHashRefs, $line);
+}
+
+# Parse the next SVN property from the given file handle, and advance the handle so the last
+# line read is the first line after the property.
+#
+# This subroutine dies if the first line is not a valid start of an SVN property,
+# or the property is missing a value, or the property change type (e.g. "Added")
+# does not correspond to the property value type (e.g. "+").
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the property to parse. This should be a line
+# that matches $svnPropertyStartRegEx.
+# $line: the line last read from $fileHandle.
+#
+# Returns ($propertyHashRef, $lastReadLine):
+# $propertyHashRef: a hash reference representing a SVN property.
+# name: the name of the property.
+# value: the last property value. For instance, suppose the property is "Modified".
+# Then it has both a '-' and '+' property value in that order. Therefore,
+# the value of this key is the value of the '+' property by ordering (since
+# it is the last value).
+# propertyChangeDelta: the value 1 or -1 if the property was added or
+# removed, respectively.
+# $lastReadLine: the line last read from $fileHandle.
+#
+# FIXME: This method is unused as of (05/16/2010). We will call this function
+# as part of parsing a SVN footer. See <https://bugs.webkit.org/show_bug.cgi?id=38885>.
+sub parseSvnProperty($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $propertyName;
+ my $propertyChangeType;
+ if (/$svnPropertyStartRegEx/) {
+ $propertyChangeType = $1;
+ $propertyName = $2;
+ } else {
+ die("Failed to find SVN property: \"$_\".");
+ }
+
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+
+ # The "svn diff" command neither inserts newline characters between property values
+ # nor between successive properties.
+ #
+ # FIXME: We do not support property values that contain tailing newline characters
+ # as it is difficult to disambiguate these trailing newlines from the empty
+ # line that precedes the contents of a binary patch.
+ my $propertyValue;
+ my $propertyValueType;
+ while (defined($_) && /$svnPropertyValueStartRegEx/) {
+ # Note, a '-' property may be followed by a '+' property in the case of a "Modified"
+ # or "Name" property. We only care about the ending value (i.e. the '+' property)
+ # in such circumstances. So, we take the property value for the property to be its
+ # last parsed property value.
+ #
+ # FIXME: We may want to consider strictly enforcing a '-', '+' property ordering or
+ # add error checking to prevent '+', '+', ..., '+' and other invalid combinations.
+ $propertyValueType = $1;
+ ($propertyValue, $_) = parseSvnPropertyValue($fileHandle, $_);
+ }
+
+ if (!$propertyValue) {
+ die("Failed to find the property value for the SVN property \"$propertyName\": \"$_\".");
+ }
+
+ my $propertyChangeDelta;
+ if ($propertyValueType eq '+') {
+ $propertyChangeDelta = 1;
+ } elsif ($propertyValueType eq '-') {
+ $propertyChangeDelta = -1;
+ } else {
+ die("Not reached.");
+ }
+
+ # We perform a simple validation that an "Added" or "Deleted" property
+ # change type corresponds with a "+" and "-" value type, respectively.
+ my $expectedChangeDelta;
+ if ($propertyChangeType eq "Added") {
+ $expectedChangeDelta = 1;
+ } elsif ($propertyChangeType eq "Deleted") {
+ $expectedChangeDelta = -1;
+ }
+
+ if ($expectedChangeDelta && $propertyChangeDelta != $expectedChangeDelta) {
+ die("The final property value type found \"$propertyValueType\" does not " .
+ "correspond to the property change type found \"$propertyChangeType\".");
+ }
+
+ my %propertyHash;
+ $propertyHash{name} = $propertyName;
+ $propertyHash{propertyChangeDelta} = $propertyChangeDelta;
+ $propertyHash{value} = $propertyValue;
+ return (\%propertyHash, $_);
+}
+
+# Parse the value of an SVN property from the given file handle, and advance
+# the handle so the last line read is the first line after the property value.
+#
+# This subroutine dies if the first line is an invalid SVN property value line
+# (i.e. a line that does not begin with " +" or " -").
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the property value to parse. This should be a line
+# beginning with " +" or " -".
+# $line: the line last read from $fileHandle.
+#
+# Returns ($propertyValue, $lastReadLine):
+# $propertyValue: the value of the property.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseSvnPropertyValue($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $propertyValue;
+ my $eol;
+ if (/$svnPropertyValueStartRegEx/) {
+ $propertyValue = $2; # Does not include the end-of-line character(s).
+ $eol = $POSTMATCH;
+ } else {
+ die("Failed to find property value beginning with '+' or '-': \"$_\".");
+ }
+
+ while (<$fileHandle>) {
+ if (/^$/ || /$svnPropertyValueStartRegEx/ || /$svnPropertyStartRegEx/) {
+ # Note, we may encounter an empty line before the contents of a binary patch.
+ # Also, we check for $svnPropertyValueStartRegEx because a '-' property may be
+ # followed by a '+' property in the case of a "Modified" or "Name" property.
+ # We check for $svnPropertyStartRegEx because it indicates the start of the
+ # next property to parse.
+ last;
+ }
+
+ # Temporarily strip off any end-of-line characters. We add the end-of-line characters
+ # from the previously processed line to the start of this line so that the last line
+ # of the property value does not end in end-of-line characters.
+ s/([\n\r]+)$//;
+ $propertyValue .= "$eol$_";
+ $eol = $1;
+ }
+
+ return ($propertyValue, $_);
}
# Parse a patch file created by svn-create-patch.
@@ -766,16 +999,16 @@ sub parsePatch($)
{
my ($fileHandle) = @_;
+ my $newDiffHashRefs;
my @diffHashRefs; # return value
my $line = <$fileHandle>;
while (defined($line)) { # Otherwise, at EOF.
- my $diffHashRef;
- ($diffHashRef, $line) = parseDiff($fileHandle, $line);
+ ($newDiffHashRefs, $line) = parseDiff($fileHandle, $line);
- push @diffHashRefs, $diffHashRef;
+ push @diffHashRefs, @$newDiffHashRefs;
}
return @diffHashRefs;
@@ -853,6 +1086,51 @@ sub prepareParsedPatch($@)
return \%preparedPatchHash;
}
+# Return localtime() for the project's time zone, given an integer time as
+# returned by Perl's time() function.
+sub localTimeInProjectTimeZone($)
+{
+ my $epochTime = shift;
+
+ # Change the time zone temporarily for the localtime() call.
+ my $savedTimeZone = $ENV{'TZ'};
+ $ENV{'TZ'} = $changeLogTimeZone;
+ my @localTime = localtime($epochTime);
+ if (defined $savedTimeZone) {
+ $ENV{'TZ'} = $savedTimeZone;
+ } else {
+ delete $ENV{'TZ'};
+ }
+
+ return @localTime;
+}
+
+# Set the reviewer and date in a ChangeLog patch, and return the new patch.
+#
+# Args:
+# $patch: a ChangeLog patch as a string.
+# $reviewer: the name of the reviewer, or undef if the reviewer should not be set.
+# $epochTime: an integer time as returned by Perl's time() function.
+sub setChangeLogDateAndReviewer($$$)
+{
+ my ($patch, $reviewer, $epochTime) = @_;
+
+ my @localTime = localTimeInProjectTimeZone($epochTime);
+ my $newDate = strftime("%Y-%m-%d", @localTime);
+
+ my $firstChangeLogLineRegEx = qr#(\n\+)\d{4}-[^-]{2}-[^-]{2}( )#;
+ $patch =~ s/$firstChangeLogLineRegEx/$1$newDate$2/;
+
+ if (defined($reviewer)) {
+ # We include a leading plus ("+") in the regular expression to make
+ # the regular expression less likely to match text in the leading junk
+ # for the patch, if the patch has leading junk.
+ $patch =~ s/(\n\+.*)NOBODY \(OOPS!\)/$1$reviewer/;
+ }
+
+ return $patch;
+}
+
# If possible, returns a ChangeLog patch equivalent to the given one,
# but with the newest ChangeLog entry inserted at the top of the
# file -- i.e. no leading context and all lines starting with "+".
diff --git a/WebKitTools/Scripts/build-dumprendertree b/WebKitTools/Scripts/build-dumprendertree
index 6502916..87c720f 100755
--- a/WebKitTools/Scripts/build-dumprendertree
+++ b/WebKitTools/Scripts/build-dumprendertree
@@ -70,20 +70,9 @@ if (isAppleMacWebKit()) {
$result = buildXCodeProject("DumpRenderTree", $clean, XcodeOptions(), @ARGV);
} elsif (isAppleWinWebKit()) {
$result = buildVisualStudioProject("DumpRenderTree.sln", $clean);
-} elsif (isQt() || isGtk() || isWx()) {
- # Qt, Gtk and wxWindows build everything in one shot. No need to build anything here.
+} elsif (isQt() || isGtk() || isWx() || isChromium()) {
+ # Qt, Gtk wxWindows, and Chromium build everything in one shot. No need to build anything here.
$result = 0;
-} elsif (isChromium()) {
- if (isDarwin()) {
- $result = buildXCodeProject("DumpRenderTree.gyp/DumpRenderTree", $clean, "-configuration", configuration(), @ARGV);
- } elsif (isCygwin() || isWindows()) {
- # Windows build - builds the root visual studio solution.
- $result = buildChromiumVisualStudioProject("DumpRenderTree.gyp/DumpRenderTree.sln", $clean);
- } elsif (isLinux()) {
- $result = buildChromiumMakefile("../../WebKit/chromium/", "DumpRenderTree", $clean);
- } else {
- die "This platform is not supported by Chromium.\n";
- }
} else {
die "Building not defined for this platform!\n";
}
diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit
index 3a3edb9..e70117f 100755
--- a/WebKitTools/Scripts/build-webkit
+++ b/WebKitTools/Scripts/build-webkit
@@ -31,6 +31,7 @@
use strict;
use File::Basename;
+use File::Find;
use File::Spec;
use FindBin;
use Getopt::Long qw(:config pass_through);
@@ -48,6 +49,9 @@ chdirWebKit();
my $showHelp = 0;
my $clean = 0;
my $minimal = 0;
+my $installHeaders;
+my $installLibs;
+my $prefixPath;
my $makeArgs;
my $startTime = time();
@@ -178,7 +182,7 @@ my @features = (
define => "ENABLE_XSLT", default => 1, value => \$xsltSupport },
{ option => "file-reader", desc => "Toggle FileReader support",
- define => "ENABLE_FILE_READER", default => 0, value => \$fileReaderSupport },
+ define => "ENABLE_FILE_READER", default => isAppleWebKit(), value => \$fileReaderSupport },
{ option => "file-writer", desc => "Toggle FileWriter support",
define => "ENABLE_FILE_WRITER", default => 0, value => \$fileWriterSupport },
@@ -225,6 +229,10 @@ Usage: $programName [options] [options to pass to build system]
--qt Build the Qt port
--inspector-frontend Copy changes to the inspector front-end files to the build directory
+ --install-headers=<path> Set installation path for the headers (Qt only)
+ --install-libs=<path> Set installation path for the libraries (Qt only)
+
+ --prefix=<path> Set installation prefix to the given path (Gtk only)
--makeargs=<arguments> Optional Makefile flags
--minimal No optional features, unless explicitly enabled.
@@ -234,6 +242,9 @@ EOF
my %options = (
'help' => \$showHelp,
'clean' => \$clean,
+ 'install-headers=s' => \$installHeaders,
+ 'install-libs=s' => \$installLibs,
+ 'prefix=s' => \$prefixPath,
'makeargs=s' => \$makeArgs,
'minimal' => \$minimal,
);
@@ -257,6 +268,18 @@ setConfiguration();
my $productDir = productDir();
+# Remove 0 byte sized files from productDir after slave lost for Qt buildbots.
+File::Find::find(\&unlinkZeroFiles, $productDir) if isQt();
+
+sub unlinkZeroFiles ()
+{
+ my $file = $File::Find::name;
+ if (! -s $file) {
+ unlink $file;
+ print "0 byte sized file removed from build directory: $file\n";
+ }
+}
+
# Check that all the project directories are there.
my @projects = ("JavaScriptCore", "WebCore", "WebKit");
@@ -276,13 +299,15 @@ if (isGtk()) {
push @options, autotoolsFlag(${$_->{value}}, $_->{option});
}
+ push @options, "--prefix=" . $prefixPath if defined($prefixPath);
push @options, "--makeargs=" . $makeArgs if defined($makeArgs);
} elsif (isAppleMacWebKit()) {
push @options, XcodeOptions();
- sub option($$)
+ sub option($$$)
{
- my ($feature, $isEnabled) = @_;
+ my ($feature, $isEnabled, $defaultValue) = @_;
+ return "" if $defaultValue == $isEnabled;
return $feature . "=" . ($isEnabled ? $feature : " ");
}
@@ -290,7 +315,8 @@ if (isGtk()) {
if ($_->{option} eq "coverage") {
push @options, XcodeCoverageSupportOptions() if $coverageSupport;
} else {
- push @options, option($_->{define}, ${$_->{value}});
+ my $option = option($_->{define}, ${$_->{value}}, $_->{default});
+ push @options, $option unless $option eq "";
}
}
@@ -338,12 +364,14 @@ if (isGtk()) {
(system("perl WebKitTools/Scripts/update-webkit-support-libs") == 0) or die;
} elsif (isQt()) {
@options = @ARGV;
+ push @options, "--install-headers=" . $installHeaders if defined($installHeaders);
+ push @options, "--install-libs=" . $installLibs if defined($installLibs);
push @options, "--makeargs=" . $makeArgs if defined($makeArgs);
foreach (@features) {
push @options, "DEFINES+=$_->{define}=${$_->{value}}" if ${$_->{value}} != $_->{default};
}
-
+
if ($minimal) {
push @options, "CONFIG+=minimal";
}
diff --git a/WebKitTools/Scripts/do-webcore-rename b/WebKitTools/Scripts/do-webcore-rename
index 56d8bed..32dd05e 100755
--- a/WebKitTools/Scripts/do-webcore-rename
+++ b/WebKitTools/Scripts/do-webcore-rename
@@ -67,9 +67,31 @@ sub wanted
push @paths, $File::Find::name;
}
-my $isDOMTypeRename = 0;
+
+# Setting isDOMTypeRename to 1 rather than 0 expands the regexps used
+# below to handle custom JavaScript bindings.
+my $isDOMTypeRename = 1;
my %renames = (
- "m_sel" => "m_selection",
+ "WebGLArray" => "ArrayBufferView",
+ "WebGLArrayBuffer" => "ArrayBuffer",
+ "WebGLByteArray" => "Int8Array",
+ "WebGLFloatArray" => "FloatArray",
+ "WebGLIntArray" => "Int32Array",
+ "WebGLIntegralTypedArrayBase" => "IntegralTypedArrayBase",
+ "WebGLShortArray" => "Int16Array",
+ "WebGLUnsignedByteArray" => "Uint8Array",
+ "WebGLUnsignedIntArray" => "Uint32Array",
+ "WebGLUnsignedShortArray" => "Uint16Array",
+ "WebGLTypedArrayBase" => "TypedArrayBase",
+ # JSDOMWindow constructors.
+ "webGLArrayBuffer" => "arrayBuffer",
+ "webGLByteArray" => "int8Array",
+ "webGLFloatArray" => "floatArray",
+ "webGLIntArray" => "int32Array",
+ "webGLShortArray" => "int16Array",
+ "webGLUnsignedByteArray" => "uint8Array",
+ "webGLUnsignedIntArray" => "uint32Array",
+ "webGLUnsignedShortArray" => "uint16Array",
);
my %renamesContemplatedForTheFuture = (
@@ -142,12 +164,39 @@ my %renamesContemplatedForTheFuture = (
"NativeFunction" => "HostFunction",
);
+# Sort the keys of the renames hash in order of decreasing length. This
+# handles the case where some of the renames are substrings of others;
+# i.e., "Foo" => "Bar" and "FooBuffer" => "BarBuffer".
+my @sortedRenameKeys = sort { length($b) - length($a) } keys %renames;
+
# rename files
+sub renameFile
+{
+ my $file = shift;
+
+ if ($isDOMTypeRename) {
+ # Find the longest key in %renames which matches this more permissive regexp.
+ # (The old regexp would match ".../Foo.cpp" but not ".../JSFooCustom.cpp".)
+ # This handles renaming of custom JavaScript bindings even when some of the
+ # renames are substrings of others. The only reason we don't do this all the
+ # time is to avoid accidental file renamings for short, non-DOM renames.
+ for my $key (@sortedRenameKeys) {
+ my $newFile = "";
+ $newFile = "$1$renames{$2}$3" if $file =~ /^(.*\/\w*)($key)(\w*\.\w+)$/;
+ if ($newFile ne "") {
+ return $newFile;
+ }
+ }
+ } else {
+ $file = "$1$renames{$2}$3" if $file =~ /^(.*\/)(\w+)(\.\w+)$/ && $renames{$2};
+ }
+ return $file;
+}
+
my %newFile;
for my $file (sort @paths) {
- my $f = $file;
- $f = "$1$renames{$2}$3" if $f =~ /^(.*\/)(\w+)(\.\w+)$/ && $renames{$2};
+ my $f = renameFile($file);
if ($f ne $file) {
$newFile{$file} = $f;
}
@@ -182,11 +231,12 @@ for my $file (sort @paths) {
my $newContents = $contents;
if ($isDOMTypeRename) {
- for my $from (keys %renames) {
- $newContents =~ s/\b$from/$renames{$from}/g;
+ for my $from (@sortedRenameKeys) {
+ # Handle JavaScript custom bindings.
+ $newContents =~ s/\b(JS|V8|to|)$from/$1$renames{$from}/g;
}
} else {
- for my $from (keys %renames) {
+ for my $from (@sortedRenameKeys) {
$newContents =~ s/\b$from(?!["\w])/$renames{$from}/g; # this " unconfuses Xcode syntax highlighting
}
}
diff --git a/WebKitTools/Scripts/ensure-valid-python b/WebKitTools/Scripts/ensure-valid-python
new file mode 100644
index 0000000..c21ad4e
--- /dev/null
+++ b/WebKitTools/Scripts/ensure-valid-python
@@ -0,0 +1,135 @@
+#!/usr/bin/perl -w
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+
+use File::Basename;
+use File::Spec;
+use File::Temp qw(tempdir);
+use FindBin;
+
+use lib $FindBin::Bin;
+use webkitdirs;
+use VCSUtils;
+
+my $macPythonURL = "http://www.python.org/ftp/python/2.6.5/python-2.6.5-macosx10.3-2010-03-24.dmg";
+my $macPythonMD5 = "84489bba813fdbb6041b69d4310a86da";
+my $macPythonInstallerName = "Python.mpkg";
+
+# We could use a consistent download location, like the source or build directory.
+my $tempDirectory = File::Temp->newdir();
+my $downloadDirectory = $tempDirectory;
+my $mountPoint = File::Spec->join($tempDirectory, "mount");
+
+sub checkPythonVersion()
+{
+ # Will exit 0 if Python is 2.5 or greater, non-zero otherwise.
+ `python -c "import sys;sys.exit(sys.version_info[:2] < (2,5))"`;
+ return exitStatus($?) == 0;
+}
+
+sub downloadFileToPath($$)
+{
+ my ($remoteURL, $localPath) = @_;
+ print "Downloading $remoteURL to $localPath\n";
+ my $exitCode = system("curl", "-o", $localPath, $remoteURL);
+ return exitStatus($exitCode) == 0;
+}
+
+sub checkMD5($$)
+{
+ my ($path, $expectedMD5) = @_;
+ my $md5Output = `md5 -q "$path"`;
+ chomp($md5Output);
+ my $isValid = $md5Output eq $expectedMD5;
+ print "'$md5Output' does not match expected: '$expectedMD5'\n" unless $isValid;
+ return $isValid;
+}
+
+sub mountDMG($$)
+{
+ my ($dmgPath, $mountPoint) = @_;
+ print "Mounting $dmgPath at $mountPoint\n";
+ return system("hdiutil", "attach", "-mountpoint", $mountPoint, "-nobrowse", $dmgPath) == 0;
+}
+
+sub unmountDMG($)
+{
+ my ($mountPoint) = @_;
+ print "Unmounting disk image from $mountPoint\n";
+ my $exitCode = system("hdiutil", "detach", $mountPoint);
+ return exitStatus($exitCode) == 0;
+}
+
+sub runInstaller($)
+{
+ my ($installerPackage) = @_;
+ print "sudo will now ask for your password to run the Python installer.\n";
+ print "The installer will install Python in /Library/Frameworks/Python.framework\n";
+ print "and add symlinks from /usr/local/bin.\n";
+ return system("sudo", "installer", "-verbose", "-pkg", $installerPackage, "-target", "/") == 0;
+}
+
+sub downloadAndMountMacPythonDMG($$)
+{
+ my ($pythonURL, $pythonMD5) = @_;
+ my $localFilename = basename($pythonURL);
+ my $localPath = File::Spec->join($downloadDirectory, $localFilename);
+
+ downloadFileToPath($pythonURL, $localPath) or die "Failed to download $pythonURL";
+ checkMD5($localPath, $pythonMD5) or die "MD5 check failed on $localPath";
+ return mountDMG($localPath, $mountPoint);
+}
+
+sub installMacPython()
+{
+ downloadAndMountMacPythonDMG($macPythonURL, $macPythonMD5) or die "Failed to download and mount disk image.";
+ print "Mounted python install image at: $mountPoint\n";
+ my $installerPackage = File::Spec->join($mountPoint, $macPythonInstallerName);
+ my $installSuccess = runInstaller($installerPackage);
+ unmountDMG($mountPoint) or die "Failed to unmount disk image from $mountPoint";
+ return $installSuccess;
+}
+
+sub main()
+{
+ # Congrats, your Python is fine.
+ return 0 if checkPythonVersion();
+
+ if (!isTiger()) {
+ print "Your Python version is insuficient to run WebKit's Python code. Please update.\n";
+ print "See http://trac.webkit.org/wiki/PythonGuidelines for more info.\n";
+ return 1;
+ }
+
+ installMacPython() or die "Failed to install Python.";
+
+ checkPythonVersion() or die "Final version check failed, must have failed to update Python";
+ print "Successfully updated python.\n";
+}
+
+exit(main());
diff --git a/WebKitTools/Scripts/new-run-webkit-httpd b/WebKitTools/Scripts/new-run-webkit-httpd
index 88ae84e..f6ec164 100755
--- a/WebKitTools/Scripts/new-run-webkit-httpd
+++ b/WebKitTools/Scripts/new-run-webkit-httpd
@@ -65,7 +65,6 @@ def run(options):
tempfile.gettempdir(),
port=options.port,
root=options.root,
- register_cygwin=options.register_cygwin,
run_background=options.run_background)
if options.server == 'start':
httpd.start()
diff --git a/WebKitTools/Scripts/new-run-webkit-websocketserver b/WebKitTools/Scripts/new-run-webkit-websocketserver
index 8e4aeaa..4f6deaa 100644
--- a/WebKitTools/Scripts/new-run-webkit-websocketserver
+++ b/WebKitTools/Scripts/new-run-webkit-websocketserver
@@ -42,25 +42,32 @@ def main():
option_parser = optparse.OptionParser()
option_parser.add_option('--server', type='choice',
choices=['start', 'stop'], default='start',
- help='Server action (start|stop)')
+ help='Server action (start|stop).')
option_parser.add_option('-p', '--port', dest='port',
- default=None, help='Port to listen on')
+ default=None, help='Port to listen on.')
option_parser.add_option('-r', '--root',
help='Absolute path to DocumentRoot '
- '(overrides layout test roots)')
+ '(overrides layout test roots).')
option_parser.add_option('-t', '--tls', dest='use_tls',
action='store_true',
- default=False, help='use TLS (wss://)')
+ default=False, help='use TLS (wss://).')
option_parser.add_option('-k', '--private_key', dest='private_key',
default='', help='TLS private key file.')
option_parser.add_option('-c', '--certificate', dest='certificate',
default='', help='TLS certificate file.')
+ option_parser.add_option('--chromium', action='store_true',
+ dest='chromium',
+ default=False,
+ help='Use the Chromium port.')
option_parser.add_option('--register_cygwin', action="store_true",
dest="register_cygwin",
- help='Register Cygwin paths (on Win try bots)')
+ help='Register Cygwin paths (on Win try bots).')
option_parser.add_option('--pidfile', help='path to pid file.')
+ option_parser.add_option('--output-dir', dest='output_dir',
+ default=None, help='output directory.')
option_parser.add_option('-v', '--verbose', action='store_true',
- default=False, help='include debug-level logging')
+ default=False,
+ help='Include debug-level logging.')
options, args = option_parser.parse_args()
if not options.port:
@@ -71,6 +78,9 @@ def main():
# FIXME: We shouldn't grab at this private variable.
options.port = websocket_server._DEFAULT_WS_PORT
+ if not options.output_dir:
+ options.output_dir = tempfile.gettempdir()
+
kwds = {'port': options.port, 'use_tls': options.use_tls}
if options.root:
kwds['root'] = options.root
@@ -78,12 +88,11 @@ def main():
kwds['private_key'] = options.private_key
if options.certificate:
kwds['certificate'] = options.certificate
- kwds['register_cygwin'] = options.register_cygwin
if options.pidfile:
kwds['pidfile'] = options.pidfile
port_obj = factory.get()
- pywebsocket = websocket_server.PyWebSocket(port_obj, tempfile.gettempdir(), **kwds)
+ pywebsocket = websocket_server.PyWebSocket(port_obj, options.output_dir, **kwds)
log_level = logging.WARN
if options.verbose:
diff --git a/WebKitTools/Scripts/old-run-webkit-tests b/WebKitTools/Scripts/old-run-webkit-tests
index f6dbf5b..783606d 100755
--- a/WebKitTools/Scripts/old-run-webkit-tests
+++ b/WebKitTools/Scripts/old-run-webkit-tests
@@ -557,7 +557,7 @@ my $lastDirectory = "";
my $isHttpdOpen = 0;
my $isWebSocketServerOpen = 0;
-my $webSocketServerPID = 0;
+my $webSocketServerPidFile = 0;
my $failedToStartWebSocketServer = 0;
# wss is disabled until all platforms support pyOpenSSL.
# my $webSocketSecureServerPID = 0;
@@ -1426,54 +1426,19 @@ sub openWebSocketServerIfNeeded()
return 1 if $isWebSocketServerOpen;
return 0 if $failedToStartWebSocketServer;
- my $webSocketServerPath = "/usr/bin/python";
- my $webSocketPythonPath = "WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket";
my $webSocketHandlerDir = "$testDirectory";
- my $webSocketHandlerScanDir = "$testDirectory/websocket/tests";
- my $webSocketHandlerMapFile = "$webSocketHandlerScanDir/handler_map.txt";
- my $sslCertificate = "$testDirectory/http/conf/webkit-httpd.pem";
my $absTestResultsDirectory = resolveAndMakeTestResultsDirectory();
- my $logFile = "$absTestResultsDirectory/pywebsocket_log.txt";
+ $webSocketServerPidFile = "$absTestResultsDirectory/websocket.pid";
my @args = (
- "WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py",
- "--server-host", "127.0.0.1",
+ "WebKitTools/Scripts/new-run-webkit-websocketserver",
+ "--server", "start",
"--port", "$webSocketPort",
- "--document-root", "$webSocketHandlerDir",
- "--scan-dir", "$webSocketHandlerScanDir",
- "--websock-handlers-map-file", "$webSocketHandlerMapFile",
- "--cgi-paths", "/websocket/tests",
- "--log-file", "$logFile",
- "--strict",
+ "--root", "$webSocketHandlerDir",
+ "--output-dir", "$absTestResultsDirectory",
+ "--pidfile", "$webSocketServerPidFile"
);
- # wss is disabled until all platforms support pyOpenSSL.
- # my @argsSecure = (
- # "WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py",
- # "-p", "$webSocketSecurePort",
- # "-d", "$webSocketHandlerDir",
- # "-t",
- # "-k", "$sslCertificate",
- # "-c", "$sslCertificate",
- # );
-
- $ENV{"PYTHONPATH"} = $webSocketPythonPath;
- $webSocketServerPID = open3(\*WEBSOCKETSERVER_IN, \*WEBSOCKETSERVER_OUT, \*WEBSOCKETSERVER_ERR, $webSocketServerPath, @args);
- # wss is disabled until all platforms support pyOpenSSL.
- # $webSocketSecureServerPID = open3(\*WEBSOCKETSECURESERVER_IN, \*WEBSOCKETSECURESERVER_OUT, \*WEBSOCKETSECURESERVER_ERR, $webSocketServerPath, @argsSecure);
- # my @listen = ("http://127.0.0.1:$webSocketPort", "https://127.0.0.1:$webSocketSecurePort");
- my @listen = ("http://127.0.0.1:$webSocketPort");
- for (my $i = 0; $i < @listen; $i++) {
- my $retryCount = 10;
- while (system("/usr/bin/curl -k -q --silent --stderr - --output /dev/null $listen[$i]") && $retryCount) {
- sleep 1;
- --$retryCount;
- }
- unless ($retryCount) {
- print STDERR "Timed out waiting for WebSocketServer to start.\n";
- $failedToStartWebSocketServer = 1;
- return 0;
- }
- }
+ system "/usr/bin/python", @args;
$isWebSocketServerOpen = 1;
return 1;
@@ -1483,17 +1448,15 @@ sub closeWebSocketServer()
{
return if !$isWebSocketServerOpen;
- close WEBSOCKETSERVER_IN;
- close WEBSOCKETSERVER_OUT;
- close WEBSOCKETSERVER_ERR;
- kill 15, $webSocketServerPID;
+ my @args = (
+ "WebKitTools/Scripts/new-run-webkit-websocketserver",
+ "--server", "stop",
+ "--pidfile", "$webSocketServerPidFile"
+ );
+ system "/usr/bin/python", @args;
+ unlink "$webSocketServerPidFile";
# wss is disabled until all platforms support pyOpenSSL.
- # close WEBSOCKETSECURESERVER_IN;
- # close WEBSOCKETSECURESERVER_OUT;
- # close WEBSOCKETSECURESERVER_ERR;
- # kill 15, $webSocketSecureServerPID;
-
$isWebSocketServerOpen = 0;
}
@@ -2277,7 +2240,8 @@ sub stopRunningTestsEarlyIfNeeded()
return 0 if !$exitAfterNFailures || $resetResults;
my $passCount = $counts{match} || 0; # $counts{match} will be undefined if we've not yet passed a test (e.g. the first test fails).
- my $failureCount = $count - $passCount; # "Failure" here includes new tests, timeouts, crashes, etc.
+ my $newCount = $counts{new} || 0;
+ my $failureCount = $count - $passCount - $newCount; # "Failure" here includes timeouts, crashes, etc.
return 0 if $failureCount < $exitAfterNFailures;
print "\nExiting early after $failureCount failures. $count tests run.";
diff --git a/WebKitTools/Scripts/run-launcher b/WebKitTools/Scripts/run-launcher
index bc00aac..414d4af 100755
--- a/WebKitTools/Scripts/run-launcher
+++ b/WebKitTools/Scripts/run-launcher
@@ -47,7 +47,7 @@ checkFrameworks();
# Set paths according to the build system used
if (isQt()) {
my $libDir = catdir(productDir(), 'lib');
- $launcherPath = catdir($launcherPath, "bin", "QtLauncher");
+ $launcherPath = catdir($launcherPath, "bin", "QtTestBrowser");
$ENV{QTWEBKIT_PLUGIN_PATH} = catdir($libDir, 'plugins');
diff --git a/WebKitTools/Scripts/run-webkit-websocketserver b/WebKitTools/Scripts/run-webkit-websocketserver
index 06f9079..08d430b 100755
--- a/WebKitTools/Scripts/run-webkit-websocketserver
+++ b/WebKitTools/Scripts/run-webkit-websocketserver
@@ -47,7 +47,7 @@ my $webSocketPort = 8880;
my $srcDir = sourceDir();
my $layoutTestsName = "$srcDir/LayoutTests";
my $testDirectory = File::Spec->rel2abs($layoutTestsName);
-my $webSocketServerPID = 0;
+my $webSocketServerPidFile = "$testDirectory/websocket.pid";
print "Starting Web Socket server...\n";
@@ -60,41 +60,29 @@ closeWebSocketServer();
print "Stopped.\n";
exit 0;
-
sub openWebSocketServer()
{
- my $webSocketServerPath = "/usr/bin/python";
- my $webSocketPythonPath = "$srcDir/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket";
my $webSocketHandlerDir = "$testDirectory";
- my $webSocketHandlerScanDir = "$testDirectory/websocket/tests";
- my $webSocketHandlerMapFile = "$webSocketHandlerScanDir/handler_map.txt";
my @args = (
- "$srcDir/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py",
- "--server-host", "127.0.0.1",
+ "$srcDir/WebKitTools/Scripts/new-run-webkit-websocketserver",
+ "--server", "start",
"--port", "$webSocketPort",
- "--document-root", "$webSocketHandlerDir",
- "--scan-dir", "$webSocketHandlerScanDir",
- "--websock-handlers-map-file", "$webSocketHandlerMapFile",
- "--cgi-paths", "/websocket/tests",
+ "--root", "$webSocketHandlerDir",
+ "--pidfile", "$webSocketServerPidFile"
);
-
- $ENV{"PYTHONPATH"} = $webSocketPythonPath;
- $webSocketServerPID = open2(\*WEBSOCKETSERVER_IN, \*WEBSOCKETSERVER_OUT, $webSocketServerPath, @args);
-
- my $listen = "http://127.0.0.1:$webSocketPort";
- my $retryCount = 10;
- while (system("/usr/bin/curl -k -q --silent --stderr - --output /dev/null $listen") && $retryCount) {
- sleep 1;
- --$retryCount;
- }
- die "Timed out waiting for WebSocketServer to start" unless $retryCount;
+ system "/usr/bin/python", @args;
}
sub closeWebSocketServer()
{
- close WEBSOCKETSERVER_IN;
- close WEBSOCKETSERVER_OUT;
- kill 15, $webSocketServerPID;
+ my @args = (
+ "$srcDir/WebKitTools/Scripts/new-run-webkit-websocketserver",
+ "--server", "stop",
+ "--pidfile", "$webSocketServerPidFile"
+ );
+ system "/usr/bin/python", @args;
+ unlink "$webSocketServerPidFile";
}
+
diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply
index b49ccec..33b2279 100755
--- a/WebKitTools/Scripts/svn-apply
+++ b/WebKitTools/Scripts/svn-apply
@@ -42,8 +42,7 @@
# Paths from Index: lines are used rather than the paths on the patch lines, which
# makes patches generated by "cvs diff" work (increasingly unimportant since we
# use Subversion now).
-# ChangeLog patches use --fuzz=3 to prevent rejects, and the entry date is set in
-# the patch to today's date using $changeLogTimeZone.
+# ChangeLog patches use --fuzz=3 to prevent rejects.
# Handles binary files (requires patches made by svn-create-patch).
# Handles copied and moved files (requires patches made by svn-create-patch).
# Handles git-diff patches (without binary changes) created at the top-level directory
@@ -80,7 +79,6 @@ sub handleGitBinaryChange($$);
sub isDirectoryEmptyForRemoval($);
sub patch($);
sub removeDirectoriesIfNeeded();
-sub setChangeLogDateAndReviewer($$);
# These should be replaced by an scm class/module:
sub scmKnowsOfFile($);
@@ -88,10 +86,6 @@ sub scmCopy($$);
sub scmAdd($);
sub scmRemove($);
-
-# Project time zone for Cupertino, CA, US
-my $changeLogTimeZone = "PST8PDT";
-
my $merge = 0;
my $showHelp = 0;
my $reviewer;
@@ -117,12 +111,12 @@ my %removeDirectoryIgnoreList = (
'_svn' => 1,
);
+my $epochTime = time(); # This is used to set the date in ChangeLog files.
my $globalExitStatus = 0;
my $repositoryRootPath = determineVCSRoot();
my %checkedDirectories;
-my %copiedFiles;
# Need to use a typeglob to pass the file handle as a parameter,
# otherwise get a bareword error.
@@ -154,8 +148,6 @@ for my $copyDiffHashRef (@copyDiffHashRefs) {
addDirectoriesIfNeeded(dirname($indexPath));
scmCopy($copiedFromPath, $indexPath);
-
- $copiedFiles{$indexPath} = $copiedFromPath;
}
for my $diffHashRef (@nonCopyDiffHashRefs) {
@@ -247,14 +239,16 @@ sub handleBinaryChange($$)
sub handleGitBinaryChange($$)
{
- my ($fullPath, $contents) = @_;
+ my ($fullPath, $diffHashRef) = @_;
+
+ my $contents = $diffHashRef->{svnConvertedText};
my ($binaryChunkType, $binaryChunk, $reverseBinaryChunkType, $reverseBinaryChunk) = decodeGitBinaryPatch($contents, $fullPath);
# FIXME: support "delta" type.
die "only literal type is supported now" if ($binaryChunkType ne "literal" || $reverseBinaryChunkType ne "literal");
- my $isFileAddition = $contents =~ /\nnew file mode \d+\n/;
- my $isFileDeletion = $contents =~ /\ndeleted file mode \d+\n/;
+ my $isFileAddition = $diffHashRef->{isNew};
+ my $isFileDeletion = $diffHashRef->{isDeletion};
my $originalContents = "";
if (open FILE, $fullPath) {
@@ -303,7 +297,10 @@ sub patch($)
{
my ($diffHashRef) = @_;
- my $patch = $diffHashRef->{svnConvertedText};
+ # Make sure $patch is initialized to some value. A deletion can have no
+ # svnConvertedText property in the case of a deletion resulting from a
+ # Git rename.
+ my $patch = $diffHashRef->{svnConvertedText} || "";
my $fullPath = $diffHashRef->{indexPath};
my $isBinary = $diffHashRef->{isBinary};
@@ -312,19 +309,18 @@ sub patch($)
my $deletion = 0;
my $addition = 0;
- # FIXME: This information should be extracted from the diff file as
- # part of the parsing stage, i.e. the call to parsePatch().
- $addition = 1 if ($patch =~ /\n--- .+\(revision 0\)\r?\n/ || $patch =~ /\n@@ -0,0 .* @@/) && !exists($copiedFiles{$fullPath});
- $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/;
+ $addition = 1 if ($diffHashRef->{isNew} || $patch =~ /\n@@ -0,0 .* @@/);
+ $deletion = 1 if ($diffHashRef->{isDeletion} || $patch =~ /\n@@ .* \+0,0 @@/);
if (!$addition && !$deletion && !$isBinary) {
# Standard patch, patch tool can handle this.
if (basename($fullPath) eq "ChangeLog") {
my $changeLogDotOrigExisted = -f "${fullPath}.orig";
- applyPatch(setChangeLogDateAndReviewer(fixChangeLogPatch($patch), $reviewer), $fullPath, ["--fuzz=3"]);
+ my $newPatch = setChangeLogDateAndReviewer(fixChangeLogPatch($patch), $reviewer, $epochTime);
+ applyPatch($newPatch, $fullPath, ["--fuzz=3"]);
unlink("${fullPath}.orig") if (! $changeLogDotOrigExisted);
} else {
- applyPatch($patch, $fullPath);
+ applyPatch($patch, $fullPath) if $patch;
}
} else {
# Either a deletion, an addition or a binary change.
@@ -333,18 +329,17 @@ sub patch($)
if ($isBinary) {
if ($isGit) {
- handleGitBinaryChange($fullPath, $patch);
+ handleGitBinaryChange($fullPath, $diffHashRef);
} else {
- handleBinaryChange($fullPath, $patch);
+ handleBinaryChange($fullPath, $patch) if $patch;
}
} elsif ($deletion) {
- # Deletion
- applyPatch($patch, $fullPath, ["--force"]);
+ applyPatch($patch, $fullPath, ["--force"]) if $patch;
scmRemove($fullPath);
} else {
# Addition
rename($fullPath, "$fullPath.orig") if -e $fullPath;
- applyPatch($patch, $fullPath);
+ applyPatch($patch, $fullPath) if $patch;
unlink("$fullPath.orig") if -e "$fullPath.orig" && checksum($fullPath) eq checksum("$fullPath.orig");
scmAdd($fullPath);
# What is this for?
@@ -364,26 +359,6 @@ sub removeDirectoriesIfNeeded()
}
}
-sub setChangeLogDateAndReviewer($$)
-{
- my $patch = shift;
- my $reviewer = shift;
- my $savedTimeZone = $ENV{'TZ'};
- # Set TZ temporarily so that localtime() is in that time zone
- $ENV{'TZ'} = $changeLogTimeZone;
- my $newDate = strftime("%Y-%m-%d", localtime());
- if (defined $savedTimeZone) {
- $ENV{'TZ'} = $savedTimeZone;
- } else {
- delete $ENV{'TZ'};
- }
- $patch =~ s/(\n\+)\d{4}-[^-]{2}-[^-]{2}( )/$1$newDate$2/;
- if (defined($reviewer)) {
- $patch =~ s/NOBODY \(OOPS!\)/$reviewer/;
- }
- return $patch;
-}
-
# This could be made into a more general "status" call, except svn and git
# have different ideas about "moving" files which might get confusing.
sub scmWillDeleteFile($)
@@ -399,6 +374,22 @@ sub scmWillDeleteFile($)
return 0;
}
+# Return whether the file at the given path is known to Git.
+#
+# This method outputs a message like the following to STDERR when
+# returning false:
+#
+# "error: pathspec 'test.png' did not match any file(s) known to git.
+# Did you forget to 'git add'?"
+sub gitKnowsOfFile($)
+{
+ my $path = shift;
+
+ `git ls-files --error-unmatch -- $path`;
+ my $exitStatus = exitStatus($?);
+ return $exitStatus == 0;
+}
+
sub scmKnowsOfFile($)
{
my ($path) = @_;
@@ -411,9 +402,8 @@ sub scmKnowsOfFile($)
# This does not handle errors well.
return 1;
} elsif (isGit()) {
- `git ls-files --error-unmatch -- $path`;
- my $exitCode = $? >> 8;
- return $exitCode == 0;
+ my @result = callSilently(\&gitKnowsOfFile, $path);
+ return $result[0];
}
}
diff --git a/WebKitTools/Scripts/svn-unapply b/WebKitTools/Scripts/svn-unapply
index 2ef7249..e502560 100755
--- a/WebKitTools/Scripts/svn-unapply
+++ b/WebKitTools/Scripts/svn-unapply
@@ -149,10 +149,8 @@ sub patch($)
my $deletion = 0;
my $addition = 0;
- # FIXME: This information should be extracted from the diff file as
- # part of the parsing stage, i.e. the call to parsePatch().
- $addition = 1 if ($diffHashRef->{copiedFromPath} || $patch =~ /\n--- .+\(revision 0\)\n/ || $patch =~ /\n@@ -0,0 .* @@/);
- $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/;
+ $addition = 1 if ($diffHashRef->{isNew} || $diffHashRef->{copiedFromPath} || $patch =~ /\n@@ -0,0 .* @@/);
+ $deletion = 1 if ($diffHashRef->{isDeletion} || $patch =~ /\n@@ .* \+0,0 @@/);
if (!$addition && !$deletion && !$isSvnBinary) {
# Standard patch, patch tool can handle this.
diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm
index 4fecf6b..c512009 100644
--- a/WebKitTools/Scripts/webkitdirs.pm
+++ b/WebKitTools/Scripts/webkitdirs.pm
@@ -891,7 +891,7 @@ sub launcherName()
if (isGtk()) {
return "GtkLauncher";
} elsif (isQt()) {
- return "QtLauncher";
+ return "QtTestBrowser";
} elsif (isWx()) {
return "wxBrowser";
} elsif (isAppleWebKit()) {
@@ -1239,7 +1239,7 @@ sub buildAutotoolsProject($@)
my $make = 'make';
my $dir = productDir();
my $config = passedConfiguration() || configuration();
- my $prefix = $ENV{"WebKitInstallationPrefix"};
+ my $prefix;
my @buildArgs = ();
my $makeArgs = $ENV{"WebKitMakeArguments"} || "";
@@ -1247,11 +1247,14 @@ sub buildAutotoolsProject($@)
my $opt = $buildParams[$i];
if ($opt =~ /^--makeargs=(.*)/i ) {
$makeArgs = $makeArgs . " " . $1;
+ } elsif ($opt =~ /^--prefix=(.*)/i ) {
+ $prefix = $1;
} else {
push @buildArgs, $opt;
}
}
+ $prefix = $ENV{"WebKitInstallationPrefix"} if !defined($prefix);
push @buildArgs, "--prefix=" . $prefix if defined($prefix);
# check if configuration is Debug
@@ -1282,7 +1285,7 @@ sub buildAutotoolsProject($@)
}
print "Calling configure in " . $dir . "\n\n";
- print "Installation directory: $prefix\n" if(defined($prefix));
+ print "Installation prefix directory: $prefix\n" if(defined($prefix));
# Make the path relative since it will appear in all -I compiler flags.
# Long argument lists cause bizarre slowdowns in libtool.
@@ -1311,6 +1314,8 @@ sub buildQMakeProject($@)
my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH
my $makeargs = "";
+ my $installHeaders;
+ my $installLibs;
for my $i (0 .. $#buildParams) {
my $opt = $buildParams[$i];
if ($opt =~ /^--qmake=(.*)/i ) {
@@ -1319,6 +1324,10 @@ sub buildQMakeProject($@)
push @buildArgs, $1;
} elsif ($opt =~ /^--makeargs=(.*)/i ) {
$makeargs = $1;
+ } elsif ($opt =~ /^--install-headers=(.*)/i ) {
+ $installHeaders = $1;
+ } elsif ($opt =~ /^--install-libs=(.*)/i ) {
+ $installLibs = $1;
} else {
push @buildArgs, $opt;
}
@@ -1326,7 +1335,8 @@ sub buildQMakeProject($@)
my $make = qtMakeCommand($qmakebin);
my $config = configuration();
- my $prefix = $ENV{"WebKitInstallationPrefix"};
+ push @buildArgs, "INSTALL_HEADERS=" . $installHeaders if defined($installHeaders);
+ push @buildArgs, "INSTALL_LIBS=" . $installLibs if defined($installLibs);
my $dir = File::Spec->canonpath(baseProductDir());
$dir = File::Spec->catfile($dir, $config) unless isSymbian();
File::Path::mkpath($dir);
@@ -1378,7 +1388,8 @@ sub buildQMakeProject($@)
}
print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n";
- print "Installation directory: $prefix\n" if(defined($prefix));
+ print "Installation headers directory: $installHeaders\n" if(defined($installHeaders));
+ print "Installation libraries directory: $installLibs\n" if(defined($installLibs));
$result = system "$qmakebin @buildArgs";
if ($result ne 0) {
@@ -1427,7 +1438,8 @@ sub buildChromiumMakefile($$$)
return system qw(rm -rf out);
}
my $config = configuration();
- my @command = ("make", "-j4", "BUILDTYPE=$config", $target);
+ my $numCpus = (grep /processor/, `cat /proc/cpuinfo`) || 1;
+ my @command = ("make", "-j$numCpus", "BUILDTYPE=$config", $target);
print join(" ", @command) . "\n";
return system @command;
}
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl
index 9f112b2..6af7da4 100644
--- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl
@@ -47,7 +47,7 @@ Index: Makefile
all:
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END', # Same as input text
Index: Makefile
===================================================================
@@ -62,7 +62,7 @@ END
indexPath => "Makefile",
isSvn => 1,
sourceRevision => "53052",
-},
+}],
undef],
expectedNextLine => undef,
},
@@ -84,7 +84,7 @@ Name: svn:mime-type
Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END', # Same as input text
Index: test_file.swf
===================================================================
@@ -102,7 +102,7 @@ END
indexPath => "test_file.swf",
isBinary => 1,
isSvn => 1,
-},
+}],
undef],
expectedNextLine => undef,
},
@@ -124,7 +124,7 @@ Index: Makefile
all:
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END', # Same as input text
LEADING JUNK
@@ -142,7 +142,7 @@ END
indexPath => "Makefile",
isSvn => 1,
sourceRevision => "53052",
-},
+}],
undef],
expectedNextLine => undef,
},
@@ -158,20 +158,11 @@ Index: Makefile_new
+MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
END
expectedReturn => [
-{
- svnConvertedText => <<'END', # Same as input text
-Index: Makefile_new
-===================================================================
---- Makefile_new (revision 53131) (from Makefile:53131)
-+++ Makefile_new (working copy)
-@@ -0,0 +1,1 @@
-+MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
-END
+[{
copiedFromPath => "Makefile",
indexPath => "Makefile_new",
- isSvn => 1,
sourceRevision => "53131",
-},
+}],
undef],
expectedNextLine => undef,
},
@@ -190,7 +181,7 @@ Index: Makefile_new
--- Makefile_new (revision 53131) (from Makefile:53131)
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END',
Index: Makefile
===================================================================
@@ -202,7 +193,7 @@ END
indexPath => "Makefile",
isSvn => 1,
sourceRevision => "53131",
-},
+}],
"Index: Makefile_new\n"],
expectedNextLine => "===================================================================\n",
},
@@ -223,7 +214,7 @@ index f5d5e74..3b6aa92 100644
@@ -1,1 1,1 @@ public:
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END', # Same as input text
Index: Makefile
===================================================================
@@ -240,7 +231,7 @@ END
indexPath => "Makefile",
isSvn => 1,
sourceRevision => "53131",
-},
+}],
undef],
expectedNextLine => undef,
},
@@ -258,7 +249,7 @@ index f5d5e74..3b6aa92 100644
@@ -1,1 1,1 @@ public:
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END',
Index: Makefile
index f5d5e74..3b6aa92 100644
@@ -268,10 +259,72 @@ index f5d5e74..3b6aa92 100644
END
indexPath => "Makefile",
isGit => 1,
-},
+}],
undef],
expectedNextLine => undef,
},
+{ # New test
+ diffName => "Git: new file",
+ inputText => <<'END',
+diff --git a/foo.h b/foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- /dev/null
++++ b/foo.h
+@@ -0,0 +1,34 @@
++<html>
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- foo.h
++++ foo.h
+@@ -0,0 +1,34 @@
++<html>
+END
+ indexPath => "foo.h",
+ isGit => 1,
+ isNew => 1,
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "Git: file deletion",
+ inputText => <<'END',
+diff --git a/foo b/foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- a/foo
++++ /dev/null
+@@ -1,1 +0,0 @@
+-line1
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- foo
++++ foo
+@@ -1,1 +0,0 @@
+-line1
+END
+ indexPath => "foo",
+ isDeletion => 1,
+ isGit => 1,
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
{
# New test
diffName => "Git: Git diff followed by SVN diff", # Should not recognize SVN start
@@ -286,7 +339,7 @@ Index: Makefile_new
--- Makefile_new (revision 53131) (from Makefile:53131)
END
expectedReturn => [
-{
+[{
svnConvertedText => <<'END',
Index: Makefile
index f5d5e74..3b6aa92 100644
@@ -299,10 +352,119 @@ Index: Makefile_new
END
indexPath => "Makefile",
isGit => 1,
-},
+}],
undef],
expectedNextLine => undef,
},
+####
+# Git test cases: file moves (multiple return values)
+##
+{
+ diffName => "Git: rename (with similarity index 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{
+ diffName => "rename (with similarity index < 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- a/foo
++++ b/foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+},
+{
+ indexPath => "foo_new",
+ isGit => 1,
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- foo_new
++++ foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+END
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{
+ diffName => "rename (with executable bit change)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+},
+{
+ indexPath => "foo_new",
+ isGit => 1,
+ svnConvertedText => <<'END',
+Index: foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
);
my $testCasesCount = @testCaseHashRefs;
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl
index 9e2a88d..bc0d4d4 100644
--- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl
@@ -57,7 +57,7 @@ END
expectedNextLine => "-file contents\n",
},
{ # New test
- diffName => "New file",
+ diffName => "new file",
inputText => <<'END',
diff --git a/foo.h b/foo.h
new file mode 100644
@@ -77,11 +77,40 @@ index 0000000..3c9f114
+++ foo.h
END
indexPath => "foo.h",
+ isNew => 1,
},
"@@ -0,0 +1,34 @@\n"],
expectedNextLine => "+<html>\n",
},
{ # New test
+ diffName => "file deletion",
+ inputText => <<'END',
+diff --git a/foo b/foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- a/foo
++++ /dev/null
+@@ -1,1 +0,0 @@
+-line1
+diff --git a/configure.ac b/configure.ac
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- foo
++++ foo
+END
+ indexPath => "foo",
+ isDeletion => 1,
+},
+"@@ -1,1 +0,0 @@\n"],
+ expectedNextLine => "-line1\n",
+},
+{ # New test
diffName => "using --no-prefix",
inputText => <<'END',
diff --git foo.h foo.h
@@ -149,7 +178,102 @@ similarity index 99%
copy from foo
copy to foo_new
END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ isCopyWithChanges => 1,
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "rename (with similarity index 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ shouldDeleteSource => 1,
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "rename (with similarity index < 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- a/foo
++++ b/foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- foo_new
++++ foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ isCopyWithChanges => 1,
+ shouldDeleteSource => 1,
+},
+"@@ -15,3 +15,4 @@ release r deployment dep deploy:\n"],
+ expectedNextLine => " line1\n",
+},
+{ # New test
+ diffName => "rename (with executable bit change)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+ copiedFromPath => "foo",
+ executableBitDelta => 1,
indexPath => "foo_new",
+ isCopyWithChanges => 1,
+ shouldDeleteSource => 1,
},
"diff --git a/bar b/bar\n"],
expectedNextLine => "index d45dd40..3494526 100644\n",
@@ -182,6 +306,7 @@ GIT binary patch
END
indexPath => "foo.gif",
isBinary => 1,
+ isNew => 1,
},
"literal 7\n"],
expectedNextLine => "OcmYex&reDa;sO8*F9L)B\n",
@@ -211,6 +336,7 @@ GIT binary patch
END
indexPath => "foo.gif",
isBinary => 1,
+ isDeletion => 1,
},
"literal 0\n"],
expectedNextLine => "HcmV?d00001\n",
@@ -312,6 +438,7 @@ index 0000000..d03e242
END
executableBitDelta => 1,
indexPath => "foo",
+ isNew => 1,
},
"@@ -0,0 +1 @@\n"],
expectedNextLine => "+file contents\n",
@@ -340,6 +467,7 @@ index d03e242..0000000
END
executableBitDelta => -1,
indexPath => "foo",
+ isDeletion => 1,
},
"@@ -1 +0,0 @@\n"],
expectedNextLine => "-file contents\n",
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl
index e6f82ca..8aae3d4 100644
--- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl
@@ -69,14 +69,6 @@ END
sourceRevision => "53131",
},
{
- svnConvertedText => <<'END',
-Index: Makefile_new
-===================================================================
---- Makefile_new (revision 53131) (from Makefile:53131)
-+++ Makefile_new (working copy)
-@@ -0,0 +1,1 @@
-+MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
-END
copiedFromPath => "Makefile",
indexPath => "Makefile_new",
sourceRevision => "53131",
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl
index b732889..ed8550d 100644
--- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl
@@ -83,6 +83,7 @@ Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl
+++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0)
END
indexPath => "WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl",
+ isNew => 1,
},
"@@ -0,0 +1,262 @@\n"],
expectedNextLine => "+#!/usr/bin/perl -w\n",
@@ -119,7 +120,7 @@ END
inputText => <<END, # No single quotes to allow interpolation of "\r"
Index: index_path.py\r
===================================================================\r
---- index_path.py (revision 53048) (from copied_from_path.py:53048)\r
+--- index_path.py (revision 53048)\r
+++ index_path.py (working copy)\r
@@ -0,0 +1,7 @@\r
+# Python file...\r
@@ -129,10 +130,9 @@ END
svnConvertedText => <<END, # No single quotes to allow interpolation of "\r"
Index: index_path.py\r
===================================================================\r
---- index_path.py (revision 53048) (from copied_from_path.py:53048)\r
+--- index_path.py (revision 53048)\r
+++ index_path.py (working copy)\r
END
- copiedFromPath => "copied_from_path.py",
indexPath => "index_path.py",
sourceRevision => 53048,
},
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl
new file mode 100644
index 0000000..cff7c2e
--- /dev/null
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl
@@ -0,0 +1,419 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnProperty().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+####
+# Simple test cases
+##
+{
+ # New test
+ diffName => "simple: add svn:executable",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:executable",
+ inputText => <<'END',
+Deleted: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => -1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Using SVN 1.4 syntax
+##
+{
+ # New test
+ diffName => "simple: delete svn:executable using SVN 1.4 syntax",
+ inputText => <<'END',
+Name: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => -1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: add svn:executable using SVN 1.4 syntax",
+ inputText => <<'END',
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Property value followed by empty line and start of next diff
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next diff",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next property diff",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next diff",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next property diff",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+####
+# Property value followed by empty line and start of binary patch
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change, followed by multi-line '+' change, empty line, and start of binary patch",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "Another\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+####
+# Successive properties
+##
+{
+ # New test
+ diffName => "single-line '+' change followed by custom property with single-line '+' change",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+Added: documentation
+ + A sentence.
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"Added: documentation\n"],
+ expectedNextLine => " + A sentence.\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by svn:executable",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"Name: svn:executable\n"],
+ expectedNextLine => " + *\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change, followed by multi-line '+' change and add svn:executable",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "Another\nlong sentence that spans\nmultiple lines.",
+},
+"Added: svn:executable\n"],
+ expectedNextLine => " + *\n",
+},
+####
+# Property values with trailing new lines.
+##
+# FIXME: We do not support property values with trailing new lines, since it is difficult to
+# disambiguate them from the empty line that preceeds the contents of a binary patch as
+# in the test case (above): "multi-line '+' change, followed by empty line and start of binary patch".
+{
+ # New test
+ diffName => "single-line '+' with trailing new line",
+ inputText => <<'END',
+Added: documentation
+ + A sentence.
+
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '+' with trailing new line, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Added: documentation
+ + A sentence.
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\n"],
+ expectedNextLine => "\n",
+},
+{
+ # New test
+ diffName => "single-line '-' change with trailing new line, and single-line '+' change",
+ inputText => <<'END',
+Modified: documentation
+ - A long sentence.
+
+ + A sentence.
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A long sentence.",
+},
+"\n"],
+ expectedNextLine => " + A sentence.\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change with trailing new line, and multi-line '+' change",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+
+ + Another
+long sentence that spans
+multiple lines.
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => " + Another\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnProperty(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnProperty($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl
new file mode 100644
index 0000000..5c79862
--- /dev/null
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnPropertyValue().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+{
+ # New test
+ diffName => "singe-line '+' change",
+ inputText => <<'END',
+ + *
+END
+ expectedReturn => ["*", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change",
+ inputText => <<'END',
+ - *
+END
+ expectedReturn => ["*", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change followed by empty line",
+ inputText => <<'END',
+ - *
+
+END
+ expectedReturn => ["*", "\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change followed by the next property",
+ inputText => <<'END',
+ - *
+Deleted: svn:executable
+END
+ expectedReturn => ["*", "Deleted: svn:executable\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '+' change and start of binary patch",
+ inputText => <<'END',
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", "\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by '+' single-line change",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+ + A single-line.
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", " + A single-line.\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by the next property",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+Added: svn:executable
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", "Added: svn:executable\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by '+' multi-line change",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", " + Another\n"],
+ expectedNextLine => "long sentence that spans\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnPropertyValue(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnPropertyValue($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl
index 8111def..5acc517 100644
--- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl
@@ -33,19 +33,6 @@
use Test::Simple tests => 4;
use VCSUtils;
-# Call a function while suppressing STDERR.
-sub callSilently($@) {
- my ($func, @args) = @_;
-
- open(OLDERR, ">&STDERR");
- close(STDERR);
- my @returnValue = &$func(@args);
- open(STDERR, ">&OLDERR");
- close(OLDERR); # FIXME: Is this necessary?
-
- return @returnValue;
-}
-
# New test
$title = "runPatchCommand: Unsuccessful patch, forcing.";
diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl
new file mode 100644
index 0000000..076d88c
--- /dev/null
+++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl
@@ -0,0 +1,128 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of setChangeLogDateAndReviewer().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+{
+ testName => "reviewer defined and \"NOBODY (OOPS!)\" in leading junk",
+ reviewer => "John Doe",
+ epochTime => 1273414321,
+ patch => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+ expectedReturn => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-09 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by John Doe.
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+},
+{
+ testName => "reviewer not defined and \"NOBODY (OOPS!)\" in leading junk",
+ reviewer => undef,
+ epochTime => 1273414321,
+ patch => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+ expectedReturn => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-09 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 1 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "setChangeLogDateAndReviewer(): $testCase->{testName}: comparing";
+
+ my $patch = $testCase->{patch};
+ my $reviewer = $testCase->{reviewer};
+ my $epochTime = $testCase->{epochTime};
+
+ my $got = VCSUtils::setChangeLogDateAndReviewer($patch, $reviewer, $epochTime);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is($got, $expectedReturn, "$testNameStart return value.");
+}
diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
index 02e114a..ac9c42e 100644
--- a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
+++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
@@ -32,9 +32,6 @@
import os
import re
-# FIXME: Instead of using run_command directly, most places in this
-# class would rather use an SCM.run method which automatically set
-# cwd=self.checkout_root.
from webkitpy.common.system.executive import Executive, run_command, ScriptError
from webkitpy.common.system.user import User
from webkitpy.common.system.deprecated_logging import error, log
@@ -102,6 +99,18 @@ class SCM:
self.checkout_root = self.find_checkout_root(self.cwd)
self.dryrun = False
+ # A wrapper used by subclasses to create processes.
+ def run(self, args, cwd=None, input=None, error_handler=None, return_exit_code=False, return_stderr=True, decode_output=True):
+ # FIXME: We should set cwd appropriately.
+ # FIXME: We should use Executive.
+ return run_command(args,
+ cwd=cwd,
+ input=input,
+ error_handler=error_handler,
+ return_exit_code=return_exit_code,
+ return_stderr=return_stderr,
+ decode_output=decode_output)
+
# SCM always returns repository relative path, but sometimes we need
# absolute paths to pass to rm, etc.
def absolute_path(self, repository_relative_path):
@@ -118,7 +127,7 @@ class SCM:
def ensure_clean_working_directory(self, force_clean):
if not force_clean and not self.working_directory_is_clean():
# FIXME: Shouldn't this use cwd=self.checkout_root?
- print run_command(self.status_command(), error_handler=Executive.ignore_error)
+ print self.run(self.status_command(), error_handler=Executive.ignore_error)
raise ScriptError(message="Working directory has modifications, pass --force-clean or --no-clean to continue.")
log("Cleaning working directory")
@@ -137,7 +146,7 @@ class SCM:
def run_status_and_extract_filenames(self, status_command, status_regexp):
filenames = []
# We run with cwd=self.checkout_root so that returned-paths are root-relative.
- for line in run_command(status_command, cwd=self.checkout_root).splitlines():
+ for line in self.run(status_command, cwd=self.checkout_root).splitlines():
match = re.search(status_regexp, line)
if not match:
continue
@@ -297,17 +306,17 @@ class SVN(SCM):
if not os.path.isdir(os.path.join(home_directory, ".subversion")):
return False
find_args = ["find", ".subversion", "-type", "f", "-exec", "grep", "-q", realm, "{}", ";", "-print"];
- find_output = run_command(find_args, cwd=home_directory, error_handler=Executive.ignore_error).rstrip()
+ find_output = self.run(find_args, cwd=home_directory, error_handler=Executive.ignore_error).rstrip()
return find_output and os.path.isfile(os.path.join(home_directory, find_output))
def svn_version(self):
if not self.cached_version:
- self.cached_version = run_command(['svn', '--version', '--quiet'])
+ self.cached_version = self.run(['svn', '--version', '--quiet'])
return self.cached_version
def working_directory_is_clean(self):
- return run_command(["svn", "diff"], cwd=self.checkout_root, decode_output=False) == ""
+ return self.run(["svn", "diff"], cwd=self.checkout_root, decode_output=False) == ""
def clean_working_directory(self):
# svn revert -R is not as awesome as git reset --hard.
@@ -317,7 +326,7 @@ class SVN(SCM):
added_files = reversed(sorted(self.added_files()))
# added_files() returns directories for SVN, we walk the files in reverse path
# length order so that we remove files before we try to remove the directories.
- run_command(["svn", "revert", "-R", "."], cwd=self.checkout_root)
+ self.run(["svn", "revert", "-R", "."], cwd=self.checkout_root)
for path in added_files:
# This is robust against cwd != self.checkout_root
absolute_path = self.absolute_path(path)
@@ -336,14 +345,14 @@ class SVN(SCM):
def add(self, path):
# path is assumed to be cwd relative?
- run_command(["svn", "add", path])
+ self.run(["svn", "add", path])
def changed_files(self, git_commit=None, squash=None):
return self.run_status_and_extract_filenames(self.status_command(), self._status_regexp("ACDMR"))
def changed_files_for_revision(self, revision):
# As far as I can tell svn diff --summarize output looks just like svn status output.
- # No file contents printed, thus utf-8 auto-decoding in run_command is fine.
+ # No file contents printed, thus utf-8 auto-decoding in self.run is fine.
status_command = ["svn", "diff", "--summarize", "-c", revision]
return self.run_status_and_extract_filenames(status_command, self._status_regexp("ACDMR"))
@@ -360,26 +369,27 @@ class SVN(SCM):
def display_name(self):
return "svn"
+ # FIXME: This method should be on Checkout.
def create_patch(self, git_commit=None, squash=None):
"""Returns a byte array (str()) representing the patch file.
Patch files are effectively binary since they may contain
files of multiple different encodings."""
- return run_command([self.script_path("svn-create-patch")],
+ return self.run([self.script_path("svn-create-patch")],
cwd=self.checkout_root, return_stderr=False,
decode_output=False)
def committer_email_for_revision(self, revision):
- return run_command(["svn", "propget", "svn:author", "--revprop", "-r", revision]).rstrip()
+ return self.run(["svn", "propget", "svn:author", "--revprop", "-r", revision]).rstrip()
def contents_at_revision(self, path, revision):
"""Returns a byte array (str()) containing the contents
of path @ revision in the repository."""
remote_path = "%s/%s" % (self._repository_url(), path)
- return run_command(["svn", "cat", "-r", revision, remote_path], decode_output=False)
+ return self.run(["svn", "cat", "-r", revision, remote_path], decode_output=False)
def diff_for_revision(self, revision):
# FIXME: This should probably use cwd=self.checkout_root
- return run_command(['svn', 'diff', '-c', revision])
+ return self.run(['svn', 'diff', '-c', revision])
def _repository_url(self):
return self.value_from_svn_info(self.checkout_root, 'URL')
@@ -390,11 +400,11 @@ class SVN(SCM):
log("WARNING: svn merge has been known to take more than 10 minutes to complete. It is recommended you use git for rollouts.")
log("Running '%s'" % " ".join(svn_merge_args))
# FIXME: Should this use cwd=self.checkout_root?
- run_command(svn_merge_args)
+ self.run(svn_merge_args)
def revert_files(self, file_paths):
# FIXME: This should probably use cwd=self.checkout_root.
- run_command(['svn', 'revert'] + file_paths)
+ self.run(['svn', 'revert'] + file_paths)
def should_squash(self, squash):
# SVN doesn't support the concept of squashing.
@@ -414,11 +424,11 @@ class SVN(SCM):
svn_commit_args.extend(["--username", username])
svn_commit_args.extend(["-m", message])
# FIXME: Should this use cwd=self.checkout_root?
- return run_command(svn_commit_args, error_handler=commit_error_handler)
+ return self.run(svn_commit_args, error_handler=commit_error_handler)
def svn_commit_log(self, svn_revision):
svn_revision = self.strip_r_from_svn_revision(svn_revision)
- return run_command(['svn', 'log', '--non-interactive', '--revision', svn_revision]);
+ return self.run(['svn', 'log', '--non-interactive', '--revision', svn_revision])
def last_svn_commit_log(self):
# BASE is the checkout revision, HEAD is the remote repository revision
@@ -455,30 +465,30 @@ class Git(SCM):
def discard_local_commits(self):
# FIXME: This should probably use cwd=self.checkout_root
- run_command(['git', 'reset', '--hard', self.svn_branch_name()])
+ self.run(['git', 'reset', '--hard', self.svn_branch_name()])
def local_commits(self):
# FIXME: This should probably use cwd=self.checkout_root
- return run_command(['git', 'log', '--pretty=oneline', 'HEAD...' + self.svn_branch_name()]).splitlines()
+ return self.run(['git', 'log', '--pretty=oneline', 'HEAD...' + self.svn_branch_name()]).splitlines()
def rebase_in_progress(self):
return os.path.exists(os.path.join(self.checkout_root, '.git/rebase-apply'))
def working_directory_is_clean(self):
# FIXME: This should probably use cwd=self.checkout_root
- return run_command(['git', 'diff', 'HEAD', '--name-only']) == ""
+ return self.run(['git', 'diff', 'HEAD', '--name-only']) == ""
def clean_working_directory(self):
# FIXME: These should probably use cwd=self.checkout_root.
# Could run git clean here too, but that wouldn't match working_directory_is_clean
- run_command(['git', 'reset', '--hard', 'HEAD'])
+ self.run(['git', 'reset', '--hard', 'HEAD'])
# Aborting rebase even though this does not match working_directory_is_clean
if self.rebase_in_progress():
- run_command(['git', 'rebase', '--abort'])
+ self.run(['git', 'rebase', '--abort'])
def status_command(self):
# git status returns non-zero when there are changes, so we use git diff name --name-status HEAD instead.
- # No file contents printed, thus utf-8 autodecoding in run_command is fine.
+ # No file contents printed, thus utf-8 autodecoding in self.run is fine.
return ["git", "diff", "--name-status", "HEAD"]
def _status_regexp(self, expected_types):
@@ -486,7 +496,7 @@ class Git(SCM):
def add(self, path):
# path is assumed to be cwd relative?
- run_command(["git", "add", path])
+ self.run(["git", "add", path])
def _merge_base(self, git_commit, squash):
if git_commit:
@@ -510,7 +520,7 @@ class Git(SCM):
def _changes_files_for_commit(self, git_commit):
# --pretty="format:" makes git show not print the commit log header,
- changed_files = run_command(["git", "show", "--pretty=format:", "--name-only", git_commit]).splitlines()
+ changed_files = self.run(["git", "show", "--pretty=format:", "--name-only", git_commit]).splitlines()
# instead it just prints a blank line at the top, so we skip the blank line:
return changed_files[1:]
@@ -539,7 +549,7 @@ class Git(SCM):
Patch files are effectively binary since they may contain
files of multiple different encodings."""
# FIXME: This should probably use cwd=self.checkout_root
- return run_command(['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "-M", self._merge_base(git_commit, squash)], decode_output=False)
+ return self.run(['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "-M", self._merge_base(git_commit, squash)], decode_output=False)
@classmethod
def git_commit_from_svn_revision(cls, revision):
@@ -553,7 +563,7 @@ class Git(SCM):
def contents_at_revision(self, path, revision):
"""Returns a byte array (str()) containing the contents
of path @ revision in the repository."""
- return run_command(["git", "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)], decode_output=False)
+ return self.run(["git", "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)], decode_output=False)
def diff_for_revision(self, revision):
git_commit = self.git_commit_from_svn_revision(revision)
@@ -561,7 +571,7 @@ class Git(SCM):
def committer_email_for_revision(self, revision):
git_commit = self.git_commit_from_svn_revision(revision)
- committer_email = run_command(["git", "log", "-1", "--pretty=format:%ce", git_commit])
+ committer_email = self.run(["git", "log", "-1", "--pretty=format:%ce", git_commit])
# Git adds an extra @repository_hash to the end of every committer email, remove it:
return committer_email.rsplit("@", 1)[0]
@@ -569,10 +579,10 @@ class Git(SCM):
# Assume the revision is an svn revision.
git_commit = self.git_commit_from_svn_revision(revision)
# I think this will always fail due to ChangeLogs.
- run_command(['git', 'revert', '--no-commit', git_commit], error_handler=Executive.ignore_error)
+ self.run(['git', 'revert', '--no-commit', git_commit], error_handler=Executive.ignore_error)
def revert_files(self, file_paths):
- run_command(['git', 'checkout', 'HEAD'] + file_paths)
+ self.run(['git', 'checkout', 'HEAD'] + file_paths)
def should_squash(self, squash):
if squash is not None:
@@ -607,7 +617,7 @@ class Git(SCM):
squash = self.should_squash(squash)
if squash:
- run_command(['git', 'reset', '--soft', self.svn_branch_name()])
+ self.run(['git', 'reset', '--soft', self.svn_branch_name()])
self.commit_locally_with_message(message)
elif not self.working_directory_is_clean():
if not len(self.local_commits()):
@@ -627,7 +637,7 @@ class Git(SCM):
return self.push_local_commits_to_server()
def _commit_on_branch(self, message, git_commit):
- branch_ref = run_command(['git', 'symbolic-ref', 'HEAD']).strip()
+ branch_ref = self.run(['git', 'symbolic-ref', 'HEAD']).strip()
branch_name = branch_ref.replace('refs/heads/', '')
commit_ids = self.commit_ids_from_commitish_arguments([git_commit])
@@ -645,16 +655,16 @@ class Git(SCM):
# We wrap in a try...finally block so if anything goes wrong, we clean up the branches.
commit_succeeded = True
try:
- run_command(['git', 'checkout', '-q', '-b', MERGE_BRANCH, self.svn_branch_name()])
+ self.run(['git', 'checkout', '-q', '-b', MERGE_BRANCH, self.svn_branch_name()])
for commit in commit_ids:
# We're on a different branch now, so convert "head" to the branch name.
commit = re.sub(r'(?i)head', branch_name, commit)
# FIXME: Once changed_files and create_patch are modified to separately handle each
# commit in a commit range, commit each cherry pick so they'll get dcommitted separately.
- run_command(['git', 'cherry-pick', '--no-commit', commit])
+ self.run(['git', 'cherry-pick', '--no-commit', commit])
- run_command(['git', 'commit', '-m', message])
+ self.run(['git', 'commit', '-m', message])
output = self.push_local_commits_to_server()
except Exception, e:
log("COMMIT FAILED: " + str(e))
@@ -663,26 +673,26 @@ class Git(SCM):
finally:
# And then swap back to the original branch and clean up.
self.clean_working_directory()
- run_command(['git', 'checkout', '-q', branch_name])
+ self.run(['git', 'checkout', '-q', branch_name])
self.delete_branch(MERGE_BRANCH)
return output
def svn_commit_log(self, svn_revision):
svn_revision = self.strip_r_from_svn_revision(svn_revision)
- return run_command(['git', 'svn', 'log', '-r', svn_revision])
+ return self.run(['git', 'svn', 'log', '-r', svn_revision])
def last_svn_commit_log(self):
- return run_command(['git', 'svn', 'log', '--limit=1'])
+ return self.run(['git', 'svn', 'log', '--limit=1'])
# Git-specific methods:
def delete_branch(self, branch):
- if run_command(['git', 'show-ref', '--quiet', '--verify', 'refs/heads/' + branch], return_exit_code=True) == 0:
- run_command(['git', 'branch', '-D', branch])
+ if self.run(['git', 'show-ref', '--quiet', '--verify', 'refs/heads/' + branch], return_exit_code=True) == 0:
+ self.run(['git', 'branch', '-D', branch])
def svn_merge_base(self):
- return run_command(['git', 'merge-base', self.svn_branch_name(), 'HEAD']).strip()
+ return self.run(['git', 'merge-base', self.svn_branch_name(), 'HEAD']).strip()
def svn_branch_name(self):
# FIXME: This should so something like: Git.read_git_config('svn-remote.svn.fetch').split(':')[1]
@@ -690,13 +700,13 @@ class Git(SCM):
return 'trunk'
def commit_locally_with_message(self, message):
- run_command(['git', 'commit', '--all', '-F', '-'], input=message)
+ self.run(['git', 'commit', '--all', '-F', '-'], input=message)
def push_local_commits_to_server(self):
dcommit_command = ['git', 'svn', 'dcommit']
if self.dryrun:
dcommit_command.append('--dry-run')
- output = run_command(dcommit_command, error_handler=commit_error_handler)
+ output = self.run(dcommit_command, error_handler=commit_error_handler)
# Return a string which looks like a commit so that things which parse this output will succeed.
if self.dryrun:
output += "\nCommitted r0"
@@ -716,14 +726,14 @@ class Git(SCM):
if '...' in commitish:
raise ScriptError(message="'...' is not supported (found in '%s'). Did you mean '..'?" % commitish)
elif '..' in commitish:
- commit_ids += reversed(run_command(['git', 'rev-list', commitish]).splitlines())
+ commit_ids += reversed(self.run(['git', 'rev-list', commitish]).splitlines())
else:
# Turn single commits or branch or tag names into commit ids.
- commit_ids += run_command(['git', 'rev-parse', '--revs-only', commitish]).splitlines()
+ commit_ids += self.run(['git', 'rev-parse', '--revs-only', commitish]).splitlines()
return commit_ids
def commit_message_for_local_commit(self, commit_id):
- commit_lines = run_command(['git', 'cat-file', 'commit', commit_id]).splitlines()
+ commit_lines = self.run(['git', 'cat-file', 'commit', commit_id]).splitlines()
# Skip the git headers.
first_line_after_headers = 0
@@ -734,4 +744,4 @@ class Git(SCM):
return CommitMessage(commit_lines[first_line_after_headers:])
def files_changed_summary_for_commit(self, commit_id):
- return run_command(['git', 'diff-tree', '--shortstat', '--no-commit-id', commit_id])
+ return self.run(['git', 'diff-tree', '--shortstat', '--no-commit-id', commit_id])
diff --git a/WebKitTools/Scripts/webkitpy/common/config/__init__.py b/WebKitTools/Scripts/webkitpy/common/config/__init__.py
index 03f1bc7..62d129e 100644
--- a/WebKitTools/Scripts/webkitpy/common/config/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/common/config/__init__.py
@@ -3,5 +3,4 @@
import re
codereview_server_host = "wkrietveld.appspot.com"
-codereview_server_regex = "https?://%s/" % re.sub('\.', '\\.', codereview_server_host)
codereview_server_url = "https://%s/" % codereview_server_host
diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py
index 56887ab..c33d2a6 100644
--- a/WebKitTools/Scripts/webkitpy/common/config/committers.py
+++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py
@@ -116,6 +116,7 @@ committers_unable_to_review = [
Committer("James Hawkins", ["jhawkins@chromium.org", "jhawkins@google.com"], "jhawkins"),
Committer("James Robinson", ["jamesr@chromium.org", "jamesr@google.com"]),
Committer("Jens Alfke", ["snej@chromium.org", "jens@apple.com"]),
+ Committer("Jer Noble", "jer.noble@apple.com", "jernoble"),
Committer("Jeremy Moskovich", ["playmobil@google.com", "jeremy@chromium.org"], "jeremymos"),
Committer("Jessie Berlin", ["jberlin@webkit.org", "jberlin@apple.com"]),
Committer("Jesus Sanchez-Palencia", ["jesus@webkit.org", "jesus.palencia@openbossa.org"], "jeez_"),
@@ -128,7 +129,6 @@ committers_unable_to_review = [
Committer("Keishi Hattori", "keishi@webkit.org", "keishi"),
Committer("Kelly Norton", "knorton@google.com"),
Committer("Kenneth Russell", "kbr@google.com"),
- Committer("Kent Tamura", "tkent@chromium.org", "tkent"),
Committer("Kinuko Yasuda", "kinuko@chromium.org", "kinuko"),
Committer("Krzysztof Kowalczyk", "kkowalczyk@gmail.com"),
Committer("Levi Weintraub", "lweintraub@apple.com"),
@@ -144,10 +144,9 @@ committers_unable_to_review = [
Committer("Mike Thole", ["mthole@mikethole.com", "mthole@apple.com"]),
Committer("Mikhail Naganov", "mnaganov@chromium.org"),
Committer("MORITA Hajime", "morrita@google.com", "morrita"),
- Committer("Ojan Vafai", "ojan@chromium.org", "ojan"),
Committer("Pam Greene", "pam@chromium.org", "pamg"),
Committer("Peter Kasting", ["pkasting@google.com", "pkasting@chromium.org"], "pkasting"),
- Committer("Philippe Normand", ["pnormand@igalia.com", "philn@webkit.org"], "pnormand"),
+ Committer("Philippe Normand", ["pnormand@igalia.com", "philn@webkit.org"], "philn-tp"),
Committer("Pierre d'Herbemont", ["pdherbemont@free.fr", "pdherbemont@apple.com"], "pdherbemont"),
Committer("Pierre-Olivier Latour", "pol@apple.com", "pol"),
Committer("Robert Hogan", ["robert@webkit.org", "robert@roberthogan.net"], "mwenge"),
@@ -222,6 +221,7 @@ reviewers_list = [
Reviewer("Justin Garcia", "justin.garcia@apple.com", "justing"),
Reviewer("Ken Kocienda", "kocienda@apple.com"),
Reviewer("Kenneth Rohde Christiansen", ["kenneth@webkit.org", "kenneth.christiansen@openbossa.org"], "kenne"),
+ Reviewer("Kent Tamura", "tkent@chromium.org", "tkent"),
Reviewer("Kevin Decker", "kdecker@apple.com", "superkevin"),
Reviewer("Kevin McCullough", "kmccullough@apple.com", "maculloch"),
Reviewer("Kevin Ollivier", ["kevino@theolliviers.com", "kevino@webkit.org"], "kollivier"),
@@ -231,6 +231,7 @@ reviewers_list = [
Reviewer("Mark Rowe", "mrowe@apple.com", "bdash"),
Reviewer("Nate Chapin", "japhet@chromium.org", "japhet"),
Reviewer("Nikolas Zimmermann", ["zimmermann@kde.org", "zimmermann@physik.rwth-aachen.de", "zimmermann@webkit.org"], "wildfox"),
+ Reviewer("Ojan Vafai", "ojan@chromium.org", "ojan"),
Reviewer("Oliver Hunt", "oliver@apple.com", "olliej"),
Reviewer("Pavel Feldman", "pfeldman@chromium.org", "pfeldman"),
Reviewer("Richard Williamson", "rjw@apple.com", "rjw"),
diff --git a/WebKitTools/Scripts/webkitpy/common/config/ports.py b/WebKitTools/Scripts/webkitpy/common/config/ports.py
index a881a67..9d4ac3f 100644
--- a/WebKitTools/Scripts/webkitpy/common/config/ports.py
+++ b/WebKitTools/Scripts/webkitpy/common/config/ports.py
@@ -112,6 +112,16 @@ class MacPort(WebKitPort):
def flag(cls):
return "--port=mac"
+ @classmethod
+ def _system_version(cls):
+ version_string = platform.mac_ver()[0] # e.g. "10.5.6"
+ version_tuple = version_string.split('.')
+ return map(int, version_tuple)
+
+ @classmethod
+ def is_leopard(cls):
+ return tuple(cls._system_version()[:2]) == (10, 5)
+
class WinPort(WebKitPort):
diff --git a/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py b/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py
index c42d2d0..42c4f2d 100644
--- a/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py
@@ -41,6 +41,12 @@ class WebKitPortTest(unittest.TestCase):
self.assertEquals(MacPort.build_webkit_command(build_style="debug"), [WebKitPort.script_path("build-webkit"), "--debug"])
self.assertEquals(MacPort.build_webkit_command(build_style="release"), [WebKitPort.script_path("build-webkit"), "--release"])
+ class TestIsLeopard(MacPort):
+ @classmethod
+ def _system_version(cls):
+ return [10, 5]
+ self.assertTrue(TestIsLeopard.is_leopard())
+
def test_gtk_port(self):
self.assertEquals(GtkPort.name(), "Gtk")
self.assertEquals(GtkPort.flag(), "--port=gtk")
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
index 4311a00..074a021 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
@@ -856,9 +856,13 @@ class Bugzilla(object):
possible_bug_statuses = map(lambda item: item.name, bug_status.items)
if "REOPENED" in possible_bug_statuses:
bug_status.value = ["REOPENED"]
+ # If the bug was never confirmed it will not have a "REOPENED"
+ # state, but only an "UNCONFIRMED" state.
+ elif "UNCONFIRMED" in possible_bug_statuses:
+ bug_status.value = ["UNCONFIRMED"]
else:
- log("Did not reopen bug %s. " +
- "It appears to already be open with status %s." % (
- bug_id, bug_status.value))
+ # FIXME: This logic is slightly backwards. We won't print this
+ # message if the bug is already open with state "UNCONFIRMED".
+ log("Did not reopen bug %s, it appears to already be open with status %s." % (bug_id, bug_status.value))
self.browser['comment'] = comment_text
self.browser.submit()
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
index 4c44cdf..62a0746 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
@@ -259,6 +259,35 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg==
expected_stderr = "Adding ['adam@example.com'] to the CC list for bug 42\n"
OutputCapture().assert_outputs(self, bugzilla.add_cc_to_bug, [42, ["adam@example.com"]], expected_stderr=expected_stderr)
+ def _mock_control_item(self, name):
+ mock_item = Mock()
+ mock_item.name = name
+ return mock_item
+
+ def _mock_find_control(self, item_names=[], selected_index=0):
+ mock_control = Mock()
+ mock_control.items = [self._mock_control_item(name) for name in item_names]
+ mock_control.value = [item_names[selected_index]] if item_names else None
+ return lambda name, type: mock_control
+
+ def _assert_reopen(self, item_names=None, selected_index=None, extra_stderr=None):
+ bugzilla = Bugzilla()
+ bugzilla.browser = MockBrowser()
+ bugzilla.authenticate = lambda: None
+
+ mock_find_control = self._mock_find_control(item_names, selected_index)
+ bugzilla.browser.find_control = mock_find_control
+ expected_stderr = "Re-opening bug 42\n['comment']\n"
+ if extra_stderr:
+ expected_stderr += extra_stderr
+ OutputCapture().assert_outputs(self, bugzilla.reopen_bug, [42, ["comment"]], expected_stderr=expected_stderr)
+
+ def test_reopen_bug(self):
+ self._assert_reopen(item_names=["REOPENED", "RESOLVED", "CLOSED"], selected_index=1)
+ self._assert_reopen(item_names=["UNCONFIRMED", "RESOLVED", "CLOSED"], selected_index=1)
+ extra_stderr = "Did not reopen bug 42, it appears to already be open with status ['NEW'].\n"
+ self._assert_reopen(item_names=["NEW", "RESOLVED"], selected_index=0, extra_stderr=extra_stderr)
+
class BugzillaQueriesTest(unittest.TestCase):
_sample_request_page = """
@@ -341,7 +370,3 @@ class BugzillaQueriesTest(unittest.TestCase):
def test_load_query(self):
queries = BugzillaQueries(Mock())
queries._load_query("request.cgi?action=queue&type=review&group=type")
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/common/net/rietveld.py b/WebKitTools/Scripts/webkitpy/common/net/rietveld.py
index 9cc97f2..c0d6119 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/rietveld.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/rietveld.py
@@ -37,16 +37,6 @@ from webkitpy.common.system.executive import ScriptError
import webkitpy.thirdparty.autoinstalled.rietveld.upload as upload
-def parse_codereview_issue(message):
- if not message:
- return None
- match = re.search(config.codereview_server_regex +
- "(?P<codereview_issue>\d+)",
- message)
- if match:
- return int(match.group('codereview_issue'))
-
-
class Rietveld(object):
def __init__(self, executive, dryrun=False):
self.dryrun = dryrun
diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive.py b/WebKitTools/Scripts/webkitpy/common/system/executive.py
index 11eb051..c7a7aec 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/executive.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/executive.py
@@ -33,6 +33,8 @@ try:
except ImportError:
multiprocessing = None
+import errno
+import logging
import os
import platform
import StringIO
@@ -43,6 +45,9 @@ import sys
from webkitpy.common.system.deprecated_logging import tee
+_log = logging.getLogger("webkitpy.common.system")
+
+
class ScriptError(Exception):
def __init__(self,
@@ -165,28 +170,48 @@ class Executive(object):
def kill_process(self, pid):
"""Attempts to kill the given pid.
Will fail silently if pid does not exist or insufficient permisssions."""
- if platform.system() == "Windows":
- # According to http://docs.python.org/library/os.html
- # os.kill isn't available on Windows. However, when I tried it
- # using Cygwin, it worked fine. We should investigate whether
- # we need this platform specific code here.
- command = ["taskkill.exe", "/f", "/pid", str(pid)]
- # taskkill will exit 128 if the process is not found.
+ if sys.platform == "win32":
+ # We only use taskkill.exe on windows (not cygwin) because subprocess.pid
+ # is a CYGWIN pid and taskkill.exe expects a windows pid.
+ # Thankfully os.kill on CYGWIN handles either pid type.
+ command = ["taskkill.exe", "/f", "/pid", pid]
+ # taskkill will exit 128 if the process is not found. We should log.
self.run_command(command, error_handler=self.ignore_error)
return
- try:
- os.kill(pid, signal.SIGKILL)
- except OSError, e:
- # FIXME: We should make non-silent failure an option.
- pass
+
+ # According to http://docs.python.org/library/os.html
+ # os.kill isn't available on Windows. python 2.5.5 os.kill appears
+ # to work in cygwin, however it occasionally raises EAGAIN.
+ retries_left = 3 if sys.platform == "cygwin" else 1
+ while retries_left > 0:
+ try:
+ retries_left -= 1
+ os.kill(pid, signal.SIGKILL)
+ except OSError, e:
+ if e.errno == errno.EAGAIN:
+ if retries_left <= 0:
+ _log.warn("Failed to kill pid %s. Too many EAGAIN errors." % pid)
+ continue
+ if e.errno == errno.ESRCH: # The process does not exist.
+ _log.warn("Called kill_process with a non-existant pid %s" % pid)
+ return
+ raise
+
+ def _windows_image_name(self, process_name):
+ name, extension = os.path.splitext(process_name)
+ if not extension:
+ # taskkill expects processes to end in .exe
+ # If necessary we could add a flag to disable appending .exe.
+ process_name = "%s.exe" % name
+ return process_name
def kill_all(self, process_name):
"""Attempts to kill processes matching process_name.
Will fail silently if no process are found."""
- if platform.system() == "Windows":
- # We might want to automatically append .exe?
- command = ["taskkill.exe", "/f", "/im", process_name]
- # taskkill will exit 128 if the process is not found.
+ if sys.platform in ("win32", "cygwin"):
+ image_name = self._windows_image_name(process_name)
+ command = ["taskkill.exe", "/f", "/im", image_name]
+ # taskkill will exit 128 if the process is not found. We should log.
self.run_command(command, error_handler=self.ignore_error)
return
@@ -195,6 +220,9 @@ class Executive(object):
# We should pick one mode, or add support for switching between them.
# Note: Mac OS X 10.6 requires -SIGNALNAME before -u USER
command = ["killall", "-TERM", "-u", os.getenv("USER"), process_name]
+ # killall returns 1 if no process can be found and 2 on command error.
+ # FIXME: We should pass a custom error_handler to allow only exit_code 1.
+ # We should log in exit_code == 1
self.run_command(command, error_handler=self.ignore_error)
# Error handlers do not need to be static methods once all callers are
diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
index ce91269..30468ce 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
@@ -72,22 +72,44 @@ class ExecutiveTest(unittest.TestCase):
def test_kill_process(self):
executive = Executive()
- # FIXME: This may need edits to work right on windows.
# We use "yes" because it loops forever.
process = subprocess.Popen(["yes"], stdout=subprocess.PIPE)
self.assertEqual(process.poll(), None) # Process is running
executive.kill_process(process.pid)
- self.assertEqual(process.wait(), -signal.SIGKILL)
+ # Note: Can't use a ternary since signal.SIGKILL is undefined for sys.platform == "win32"
+ if sys.platform == "win32":
+ expected_exit_code = 0 # taskkill.exe results in exit(0)
+ else:
+ expected_exit_code = -signal.SIGKILL
+ self.assertEqual(process.wait(), expected_exit_code)
# Killing again should fail silently.
executive.kill_process(process.pid)
+ def _assert_windows_image_name(self, name, expected_windows_name):
+ executive = Executive()
+ windows_name = executive._windows_image_name(name)
+ self.assertEqual(windows_name, expected_windows_name)
+
+ def test_windows_image_name(self):
+ self._assert_windows_image_name("foo", "foo.exe")
+ self._assert_windows_image_name("foo.exe", "foo.exe")
+ self._assert_windows_image_name("foo.com", "foo.com")
+ # If the name looks like an extension, even if it isn't
+ # supposed to, we have no choice but to return the original name.
+ self._assert_windows_image_name("foo.baz", "foo.baz")
+ self._assert_windows_image_name("foo.baz.exe", "foo.baz.exe")
+
def test_kill_all(self):
executive = Executive()
- # FIXME: This may need edits to work right on windows.
# We use "yes" because it loops forever.
process = subprocess.Popen(["yes"], stdout=subprocess.PIPE)
self.assertEqual(process.poll(), None) # Process is running
executive.kill_all("yes")
- self.assertEqual(process.wait(), -signal.SIGTERM)
+ # Note: Can't use a ternary since signal.SIGTERM is undefined for sys.platform == "win32"
+ if sys.platform in ("win32", "cygwin"):
+ expected_exit_code = 0 # taskkill.exe results in exit(0)
+ else:
+ expected_exit_code = -signal.SIGTERM
+ self.assertEqual(process.wait(), expected_exit_code)
# Killing again should fail silently.
executive.kill_all("yes")
diff --git a/WebKitTools/Scripts/webkitpy/common/system/user.py b/WebKitTools/Scripts/webkitpy/common/system/user.py
index 64995bb..edce93d 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/user.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/user.py
@@ -26,17 +26,27 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import logging
import os
import shlex
import subprocess
import webbrowser
+
+_log = logging.getLogger("webkitpy.common.system.user")
+
+
try:
import readline
except ImportError:
- print "Unable to import readline. If you're using MacPorts, try running:"
- print " sudo port install py25-readline"
- exit(1)
+ if sys.platform != "win32":
+ # There is no readline module for win32, not much to do except cry.
+ _log.warn("Unable to import readline.")
+ # FIXME: We could give instructions for non-mac platforms.
+ # Lack of readline results in a very bad user experiance.
+ if sys.platform == "mac":
+ _log.warn("If you're using MacPorts, try running:")
+ _log.warn(" sudo port install py25-readline")
class User(object):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py
index 9c42d73..20646a1 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py
@@ -137,12 +137,10 @@ class MeteredStream:
# Print the necessary number of backspaces to erase the previous
# message.
if len(self._last_update):
- self._stream.write("\b" * len(self._last_update))
- if len(str):
- self._stream.write(str)
- num_remaining = len(self._last_update) - len(str)
- if num_remaining > 0:
- self._stream.write(" " * num_remaining + "\b" * num_remaining)
+ self._stream.write("\b" * len(self._last_update) +
+ " " * len(self._last_update) +
+ "\b" * len(self._last_update))
+ self._stream.write(str)
last_newline = str.rfind("\n")
self._last_update = str[(last_newline + 1):]
self._dirty = True
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py
index 926f9b3..a9c6d5b 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py
@@ -50,32 +50,36 @@ class TestMeteredStream(unittest.TestCase):
# for coverage.
m.write("foo")
m.flush()
- self.assertEquals(a.get(), ['foo'])
+ exp = ['foo']
+ self.assertEquals(a.get(), exp)
# now check that a second write() does not overwrite the first.
m.write("bar")
- self.assertEquals(a.get(), ['foo', 'bar'])
+ exp.append('bar')
+ self.assertEquals(a.get(), exp)
m.update("batter")
- self.assertEquals(a.get(), ['foo', 'bar', 'batter'])
+ exp.append('batter')
+ self.assertEquals(a.get(), exp)
# The next update() should overwrite the laste update() but not the
# other text. Note that the cursor is effectively positioned at the
# end of 'foo', even though we had to erase three more characters.
m.update("foo")
- self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b',
- 'foo', ' \b\b\b'])
+ exp.append('\b\b\b\b\b\b \b\b\b\b\b\b')
+ exp.append('foo')
+ self.assertEquals(a.get(), exp)
m.progress("progress")
- self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b',
- 'foo', ' \b\b\b', '\b\b\b', 'progress'])
+ exp.append('\b\b\b \b\b\b')
+ exp.append('progress')
+ self.assertEquals(a.get(), exp)
# now check that a write() does overwrite the progress bar
m.write("foo")
- self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b',
- 'foo', ' \b\b\b', '\b\b\b', 'progress',
- '\b\b\b\b\b\b\b\b',
- 'foo', ' \b\b\b\b\b'])
+ exp.append('\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b')
+ exp.append('foo')
+ self.assertEquals(a.get(), exp)
# Now test that we only back up to the most recent newline.
@@ -84,7 +88,7 @@ class TestMeteredStream(unittest.TestCase):
a.reset()
m.update("foo\nbar")
m.update("baz")
- self.assertEquals(a.get(), ['foo\nbar', '\b\b\b', 'baz'])
+ self.assertEquals(a.get(), ['foo\nbar', '\b\b\b \b\b\b', 'baz'])
def test_verbose(self):
a = ArrayStream()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py
index 91d49c6..77de2e0 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py
@@ -56,6 +56,8 @@ the output at the beginning of the run, during the run, or at the end:
Overall options:
nothing don't print anything. This overrides every other option
+ default include the default options. This is useful for logging
+ the default options plus additional settings.
everything print everything (except the trace-* options and the
detailed-progress option, see below for the full list )
misc print miscellaneous things like blank lines
@@ -101,15 +103,19 @@ Notes:
--print 'everything' is equivalent to --print '%(everything)s'.
-The default is to --print '%(default)s'.
+The default (--print default) is equivalent to --print '%(default)s'.
""" % {'slowest': NUM_SLOW_TESTS_TO_LOG, 'everything': PRINT_EVERYTHING,
'default': PRINT_DEFAULT}
def print_options():
return [
- # Note: we use print_options rather than just 'print' because print
+ # Note: We use print_options rather than just 'print' because print
# is a reserved word.
+ # Note: Also, we don't specify a default value so we can detect when
+ # no flag is specified on the command line and use different defaults
+ # based on whether or not --verbose is specified (since --print
+ # overrides --verbose).
optparse.make_option("--print", dest="print_options",
help=("controls print output of test run. "
"Use --help-printing for more.")),
@@ -171,6 +177,10 @@ def parse_print_options(print_options, verbose, child_processes,
switches.discard('everything')
switches.update(set(PRINT_EVERYTHING.split(',')))
+ if 'default' in switches:
+ switches.discard('default')
+ switches.update(set(PRINT_DEFAULT.split(',')))
+
if 'detailed-progress' in switches:
switches.discard('one-line-progress')
@@ -310,7 +320,7 @@ class Printer(object):
png_file = self._port.expected_filename(filename, '.png')
if os.path.exists(png_file):
self._write(' png: %s' %
- self._port.relative_test_filename(filename))
+ self._port.relative_test_filename(png_file))
else:
self._write(' png: <none>')
self._write(' exp: %s' % exp_str)
@@ -486,10 +496,8 @@ class Printer(object):
# from the logger :(.
if self._options.verbose:
_log.info(msg)
- elif msg == "":
- self._meter.write("\n")
else:
- self._meter.write(msg)
+ self._meter.write("%s\n" % msg)
#
# Utility routines used by the Controller class
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py
index 8e6aa8f..dba1194 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py
@@ -98,6 +98,44 @@ class TestUtilityFunctions(unittest.TestCase):
options, args = get_options([])
self.assertTrue(options is not None)
+ def test_parse_print_options(self):
+ def test_switches(args, verbose, child_processes, is_fully_parallel,
+ expected_switches_str):
+ options, args = get_options(args)
+ if expected_switches_str:
+ expected_switches = set(expected_switches_str.split(','))
+ else:
+ expected_switches = set()
+ switches = printing.parse_print_options(options.print_options,
+ verbose,
+ child_processes,
+ is_fully_parallel)
+ self.assertEqual(expected_switches, switches)
+
+ # test that we default to the default set of switches
+ test_switches([], False, 1, False,
+ printing.PRINT_DEFAULT)
+
+ # test that verbose defaults to everything
+ test_switches([], True, 1, False,
+ printing.PRINT_EVERYTHING)
+
+ # test that --print default does what it's supposed to
+ test_switches(['--print', 'default'], False, 1, False,
+ printing.PRINT_DEFAULT)
+
+ # test that --print nothing does what it's supposed to
+ test_switches(['--print', 'nothing'], False, 1, False,
+ None)
+
+ # test that --print everything does what it's supposed to
+ test_switches(['--print', 'everything'], False, 1, False,
+ printing.PRINT_EVERYTHING)
+
+ # this tests that '--print X' overrides '--verbose'
+ test_switches(['--print', 'actual'], True, 1, False,
+ 'actual')
+
class Testprinter(unittest.TestCase):
def get_printer(self, args=None, single_threaded=False,
@@ -144,7 +182,7 @@ class Testprinter(unittest.TestCase):
exp_bot = [message + "\n"]
else:
if exp_err is None:
- exp_err = [message]
+ exp_err = [message + "\n"]
if exp_bot is None:
exp_bot = []
do_helper(method_name, 'nothing', 'hello', [], [])
@@ -182,21 +220,21 @@ class Testprinter(unittest.TestCase):
printer, err, out = self.get_printer(['--print', 'one-line-summary'])
printer.print_one_line_summary(1, 1)
- self.assertEquals(err.get(), ["All 1 tests ran as expected.", "\n"])
+ self.assertEquals(err.get(), ["All 1 tests ran as expected.\n", "\n"])
printer, err, out = self.get_printer(['--print', 'everything'])
printer.print_one_line_summary(1, 1)
- self.assertEquals(err.get(), ["All 1 tests ran as expected.", "\n"])
+ self.assertEquals(err.get(), ["All 1 tests ran as expected.\n", "\n"])
err.reset()
printer.print_one_line_summary(2, 1)
self.assertEquals(err.get(),
- ["1 test ran as expected, 1 didn't:", "\n"])
+ ["1 test ran as expected, 1 didn't:\n", "\n"])
err.reset()
printer.print_one_line_summary(3, 2)
self.assertEquals(err.get(),
- ["2 tests ran as expected, 1 didn't:", "\n"])
+ ["2 tests ran as expected, 1 didn't:\n", "\n"])
def test_print_test_result(self):
result = get_result('foo.html')
@@ -212,7 +250,7 @@ class Testprinter(unittest.TestCase):
printer.print_test_result(result, expected=False, exp_str='',
got_str='')
self.assertEquals(err.get(),
- [' foo.html -> unexpected pass'])
+ [' foo.html -> unexpected pass\n'])
printer, err, out = self.get_printer(['--print', 'everything'])
printer.print_test_result(result, expected=True, exp_str='',
@@ -222,7 +260,7 @@ class Testprinter(unittest.TestCase):
printer.print_test_result(result, expected=False, exp_str='',
got_str='')
self.assertEquals(err.get(),
- [' foo.html -> unexpected pass'])
+ [' foo.html -> unexpected pass\n'])
printer, err, out = self.get_printer(['--print', 'nothing'])
printer.print_test_result(result, expected=False, exp_str='',
@@ -318,7 +356,7 @@ class Testprinter(unittest.TestCase):
err.reset()
out.reset()
printer.print_progress(rs, True, test_files)
- self.assertEqual(err.get(), [])
+ self.assertEqual(err.get(), [''])
self.assertTrue(out.empty())
printer, err, out = self.get_printer(
@@ -347,7 +385,7 @@ class Testprinter(unittest.TestCase):
err.reset()
out.reset()
printer.print_progress(rs, True, test_files)
- self.assertEqual(err.get(), [])
+ self.assertEqual(err.get(), [''])
self.assertTrue(out.empty())
def test_write(self):
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_memorizingfile.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_results_uploader.py
index 2de77ba..680b848 100644
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_memorizingfile.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_results_uploader.py
@@ -1,7 +1,5 @@
#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
+# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -29,44 +27,45 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import mimetypes
+import socket
-"""Tests for memorizingfile module."""
-
-
-import StringIO
-import unittest
-
-import config # This must be imported before mod_pywebsocket.
-from mod_pywebsocket import memorizingfile
+from webkitpy.common.net.networktransaction import NetworkTransaction
+from webkitpy.thirdparty.autoinstalled.mechanize import Browser
-class UtilTest(unittest.TestCase):
- def check(self, memorizing_file, num_read, expected_list):
- for unused in range(num_read):
- memorizing_file.readline()
- actual_list = memorizing_file.get_memorized_lines()
- self.assertEqual(len(expected_list), len(actual_list))
- for expected, actual in zip(expected_list, actual_list):
- self.assertEqual(expected, actual)
+def get_mime_type(filename):
+ return mimetypes.guess_type(filename)[0] or "text/plain"
- def test_get_memorized_lines(self):
- memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
- 'Hello\nWorld\nWelcome'))
- self.check(memorizing_file, 3, ['Hello\n', 'World\n', 'Welcome'])
- def test_get_memorized_lines_limit_memorized_lines(self):
- memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
- 'Hello\nWorld\nWelcome'), 2)
- self.check(memorizing_file, 3, ['Hello\n', 'World\n'])
+class TestResultsUploader:
+ def __init__(self, host):
+ self._host = host
+ self._browser = Browser()
- def test_get_memorized_lines_empty_file(self):
- memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
- ''))
- self.check(memorizing_file, 10, [])
+ def _upload_files(self, attrs, file_objs):
+ self._browser.open("http://%s/testfile/uploadform" % self._host)
+ self._browser.select_form("test_result_upload")
+ for (name, data) in attrs:
+ self._browser[name] = str(data)
+ for (filename, handle) in file_objs:
+ self._browser.add_file(handle, get_mime_type(filename), filename,
+ "file")
-if __name__ == '__main__':
- unittest.main()
+ self._browser.submit()
+ def upload(self, params, files, timeout_seconds):
+ orig_timeout = socket.getdefaulttimeout()
+ file_objs = []
+ try:
+ file_objs = [(filename, open(path, "rb")) for (filename, path)
+ in files]
-# vi:sts=4 sw=4 et
+ socket.setdefaulttimeout(timeout_seconds)
+ NetworkTransaction(timeout_seconds=timeout_seconds).run(
+ lambda: self._upload_files(params, file_objs))
+ finally:
+ socket.setdefaulttimeout(orig_timeout)
+ for (filename, handle) in file_objs:
+ handle.close()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
index 25946af..a4cbe42 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
@@ -414,10 +414,17 @@ class Port(object):
raise NotImplemented('Port.results_directory')
def setup_test_run(self):
- """This routine can be overridden to perform any port-specific
- work that shouuld be done at the beginning of a test run."""
+ """Perform port-specific work at the beginning of a test run."""
pass
+ def setup_environ_for_server(self):
+ """Perform port-specific work at the beginning of a server launch.
+
+ Returns:
+ Operating-system's environment.
+ """
+ return os.environ
+
def show_html_results_file(self, results_filename):
"""This routine should display the HTML file pointed at by
results_filename in a users' browser."""
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
index a01bd14..979e225 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
@@ -49,11 +49,8 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
chromium.ChromiumPort.__init__(self, port_name, options)
def baseline_search_path(self):
- return [self._webkit_baseline_path('chromium-linux'),
- self._webkit_baseline_path('chromium-win'),
- self._webkit_baseline_path('chromium'),
- self._webkit_baseline_path('win'),
- self._webkit_baseline_path('mac')]
+ port_names = ["chromium-linux", "chromium-win", "chromium", "win", "mac"]
+ return map(self._webkit_baseline_path, port_names)
def check_build(self, needs_http):
result = chromium.ChromiumPort.check_build(self, needs_http)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
index 4ead26f..ba67a3e 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
@@ -52,10 +52,8 @@ class ChromiumMacPort(chromium.ChromiumPort):
chromium.ChromiumPort.__init__(self, port_name, options)
def baseline_search_path(self):
- return [self._webkit_baseline_path('chromium-mac'),
- self._webkit_baseline_path('chromium'),
- self._webkit_baseline_path('mac' + self.version()),
- self._webkit_baseline_path('mac')]
+ port_names = ["chromium-mac", "chromium", "mac" + self.version(), "mac"]
+ return map(self._webkit_baseline_path, port_names)
def check_build(self, needs_http):
result = chromium.ChromiumPort.check_build(self, needs_http)
@@ -87,6 +85,7 @@ class ChromiumMacPort(chromium.ChromiumPort):
return 'mac'
def version(self):
+ # FIXME: It's strange that this string is -version, not just version.
os_version_string = platform.mac_ver()[0] # e.g. "10.5.6"
if not os_version_string:
return '-leopard'
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
index 302af86..ad78e61 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
@@ -43,22 +43,39 @@ class ChromiumWinPort(chromium.ChromiumPort):
def __init__(self, port_name=None, options=None):
if port_name is None:
- port_name = 'chromium-win' + self.version()
- if options and not hasattr(options, 'configuration'):
- options.configuration = 'Release'
+ port_name = "chromium-win" + self.version()
+ if options and not hasattr(options, "configuration"):
+ options.configuration = "Release"
chromium.ChromiumPort.__init__(self, port_name, options)
+ def setup_environ_for_server(self):
+ env = chromium.ChromiumPort.setup_environ_for_server(self)
+ # Put the cygwin directory first in the path to find cygwin1.dll.
+ env["PATH"] = "%s;%s" % (
+ self.path_from_chromium_base("third_party", "cygwin", "bin"),
+ env["PATH"])
+ # Configure the cygwin directory so that pywebsocket finds proper
+ # python executable to run cgi program.
+ env["CYGWIN_PATH"] = self.path_from_chromium_base(
+ "third_party", "cygwin", "bin")
+ if (sys.platform == "win32" and self._options and
+ hasattr(self._options, "register_cygwin") and
+ self._options.register_cygwin):
+ setup_mount = self.path_from_chromium_base("third_party",
+ "cygwin",
+ "setup_mount.bat")
+ self._executive.run_command(setup_mount)
+ return env
+
def baseline_search_path(self):
- dirs = []
+ port_names = []
if self._name == 'chromium-win-xp':
- dirs.append(self._webkit_baseline_path('chromium-win-xp'))
+ port_names.append("chromium-win-xp")
if self._name in ('chromium-win-xp', 'chromium-win-vista'):
- dirs.append(self._webkit_baseline_path('chromium-win-vista'))
- dirs.append(self._webkit_baseline_path('chromium-win'))
- dirs.append(self._webkit_baseline_path('chromium'))
- dirs.append(self._webkit_baseline_path('win'))
- dirs.append(self._webkit_baseline_path('mac'))
- return dirs
+ port_names.append("chromium-win-vista")
+ # FIXME: This may need to include mac-snowleopard like win.py.
+ port_names.extend(["chromium-win", "chromium", "win", "mac"])
+ return map(self._webkit_baseline_path, port_names)
def check_build(self, needs_http):
result = chromium.ChromiumPort.check_build(self, needs_http)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
index 2cbb1b9..2c92865 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
@@ -46,6 +46,8 @@
from __future__ import with_statement
+import sys
+
import base
import factory
@@ -172,7 +174,11 @@ class DryrunDriver(base.Driver):
test = uri
if uri.startswith("file:///"):
- test = test.replace('file://', '')
+ if sys.platform == 'win32':
+ test = test.replace('file:///', '')
+ test = test.replace('/', '\\')
+ else:
+ test = test.replace('file://', '')
return test
elif uri.startswith("http://127.0.0.1:8880/"):
# websocket tests
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
new file mode 100644
index 0000000..d8dffdf
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
@@ -0,0 +1,138 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import sys
+import unittest
+
+import chromium_linux
+import chromium_mac
+import chromium_win
+import dryrun
+import factory
+import gtk
+import mac
+import qt
+import test
+import win
+
+
+class FactoryTest(unittest.TestCase):
+ """Test factory creates proper port object for the target.
+
+ Target is specified by port_name, sys.platform and options.
+
+ """
+ # FIXME: The ports themselves should expose what options they require,
+ # instead of passing generic "options".
+
+ class WebKitOptions(object):
+ """Represents the minimum options for WebKit port."""
+ def __init__(self):
+ self.pixel_tests = False
+
+ class ChromiumOptions(WebKitOptions):
+ """Represents minimum options for Chromium port."""
+ def __init__(self):
+ FactoryTest.WebKitOptions.__init__(self)
+ self.chromium = True
+
+ def setUp(self):
+ self.real_sys_platform = sys.platform
+ self.webkit_options = FactoryTest.WebKitOptions()
+ self.chromium_options = FactoryTest.ChromiumOptions()
+
+ def tearDown(self):
+ sys.platform = self.real_sys_platform
+
+ def assert_port(self, port_name, expected_port):
+ """Helper assert for port_name.
+
+ Args:
+ port_name: port name to get port object.
+ expected_port: class of expected port object.
+
+ """
+ self.assertTrue(isinstance(factory.get(port_name=port_name),
+ expected_port))
+
+ def assert_platform_port(self, platform, options, expected_port):
+ """Helper assert for platform and options.
+
+ Args:
+ platform: sys.platform.
+ options: options to get port object.
+ expected_port: class of expected port object.
+
+ """
+ orig_platform = sys.platform
+ sys.platform = platform
+ self.assertTrue(isinstance(factory.get(options=options),
+ expected_port))
+ sys.platform = orig_platform
+
+ def test_test(self):
+ self.assert_port("test", test.TestPort)
+
+ def test_dryrun(self):
+ self.assert_port("dryrun-test", dryrun.DryRunPort)
+ self.assert_port("dryrun-mac", dryrun.DryRunPort)
+
+ def test_mac(self):
+ self.assert_port("mac", mac.MacPort)
+ self.assert_platform_port("darwin", None, mac.MacPort)
+ self.assert_platform_port("darwin", self.webkit_options, mac.MacPort)
+
+ def test_win(self):
+ self.assert_port("win", win.WinPort)
+ self.assert_platform_port("win32", None, win.WinPort)
+ self.assert_platform_port("win32", self.webkit_options, win.WinPort)
+ self.assert_platform_port("cygwin", None, win.WinPort)
+ self.assert_platform_port("cygwin", self.webkit_options, win.WinPort)
+
+ def test_gtk(self):
+ self.assert_port("gtk", gtk.GtkPort)
+
+ def test_qt(self):
+ self.assert_port("qt", qt.QtPort)
+
+ def test_chromium_mac(self):
+ self.assert_port("chromium-mac", chromium_mac.ChromiumMacPort)
+ self.assert_platform_port("darwin", self.chromium_options,
+ chromium_mac.ChromiumMacPort)
+
+ def test_chromium_linux(self):
+ self.assert_port("chromium-linux", chromium_linux.ChromiumLinuxPort)
+ self.assert_platform_port("linux2", self.chromium_options,
+ chromium_linux.ChromiumLinuxPort)
+
+ def test_chromium_win(self):
+ self.assert_port("chromium-win", chromium_win.ChromiumWinPort)
+ self.assert_platform_port("win32", self.chromium_options,
+ chromium_win.ChromiumWinPort)
+ self.assert_platform_port("cygwin", self.chromium_options,
+ chromium_win.ChromiumWinPort)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py
index fbe47e3..0f8a21e 100755
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py
@@ -55,7 +55,7 @@ class HttpdNotStarted(Exception):
class Lighttpd(http_server_base.HttpServerBase):
def __init__(self, port_obj, output_dir, background=False, port=None,
- root=None, register_cygwin=None, run_background=None):
+ root=None, run_background=None):
"""Args:
output_dir: the absolute path to the layout test result directory
"""
@@ -65,7 +65,6 @@ class Lighttpd(http_server_base.HttpServerBase):
self._process = None
self._port = port
self._root = root
- self._register_cygwin = register_cygwin
self._run_background = run_background
if self._port:
self._port = int(self._port)
@@ -199,20 +198,7 @@ class Lighttpd(http_server_base.HttpServerBase):
shutil.copyfile(os.path.join(module_path, lib_file),
os.path.join(tmp_module_path, lib_file))
- # Put the cygwin directory first in the path to find cygwin1.dll
- env = os.environ
- if sys.platform in ('cygwin', 'win32'):
- env['PATH'] = '%s;%s' % (
- self._port_obj.path_from_chromium_base('third_party',
- 'cygwin', 'bin'),
- env['PATH'])
-
- if sys.platform == 'win32' and self._register_cygwin:
- setup_mount = self._port_obj.path_from_chromium_base('third_party',
- 'cygwin', 'setup_mount.bat')
- # FIXME: Should use Executive.run_command
- subprocess.Popen(setup_mount).wait()
-
+ env = self._port_obj.setup_environ_for_server()
_log.debug('Starting http server')
# FIXME: Should use Executive.run_command
self._process = subprocess.Popen(start_cmd, env=env)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
index 350b088..413b5f2 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
@@ -58,15 +58,15 @@ class MacPort(WebKitPort):
return child_processes
def baseline_search_path(self):
- dirs = []
+ port_names = []
if self._name == 'mac-tiger':
- dirs.append(self._webkit_baseline_path(self._name))
+ port_names.append("mac-tiger")
if self._name in ('mac-tiger', 'mac-leopard'):
- dirs.append(self._webkit_baseline_path('mac-leopard'))
+ port_names.append("mac-leopard")
if self._name in ('mac-tiger', 'mac-leopard', 'mac-snowleopard'):
- dirs.append(self._webkit_baseline_path('mac-snowleopard'))
- dirs.append(self._webkit_baseline_path('mac'))
- return dirs
+ port_names.append("mac-snowleopard")
+ port_names.append("mac")
+ return map(self._webkit_baseline_path, port_names)
def path_to_test_expectations_file(self):
return self.path_from_webkit_base('LayoutTests', 'platform',
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
index ada83ce..2097ce7 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -294,13 +294,33 @@ class WebKitPort(base.Port):
return self.test_base_platform_names() + (
'mac-tiger', 'mac-leopard', 'mac-snowleopard')
+ def _configuration_file_path(self):
+ build_root = self._webkit_build_directory(["--top-level"])
+ return os.path.join(build_root, "Configuration")
+
+ # Easy override for unit tests
+ def _open_configuration_file(self):
+ configuration_path = self._configuration_file_path()
+ return codecs.open(configuration_path, "r", "utf-8")
+
+ def _read_configuration(self):
+ try:
+ with self._open_configuration_file() as file:
+ return file.readline().rstrip()
+ except IOError, e:
+ return None
+
+ # FIXME: This list may be incomplete as Apple has some sekret configs.
+ _RECOGNIZED_CONFIGURATIONS = ("Debug", "Release")
+
def default_configuration(self):
- # This is a bit of a hack. This state exists in a much nicer form in
- # perl-land.
- configuration = ospath.relpath(
- self._webkit_build_directory(["--configuration"]),
- self._webkit_build_directory(["--top-level"]))
- assert(configuration == "Debug" or configuration == "Release")
+ # FIXME: Unify this with webkitdir.pm configuration reading code.
+ configuration = self._read_configuration()
+ if not configuration:
+ configuration = "Release"
+ if configuration not in self._RECOGNIZED_CONFIGURATIONS:
+ _log.warn("Configuration \"%s\" found in %s is not a recognized value.\n" % (configuration, self._configuration_file_path()))
+ _log.warn("Scripts may fail. See 'set-webkit-configuration --help'.")
return configuration
def _webkit_build_directory(self, args):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
index ad557bd..22ae780 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
@@ -46,6 +46,8 @@ import factory
import http_server
from webkitpy.common.system.executive import Executive
+from webkitpy.thirdparty.autoinstalled.pywebsocket import mod_pywebsocket
+
_log = logging.getLogger("webkitpy.layout_tests.port.websocket_server")
@@ -95,15 +97,13 @@ class PyWebSocket(http_server.Lighttpd):
def __init__(self, port_obj, output_dir, port=_DEFAULT_WS_PORT,
root=None, use_tls=False,
- register_cygwin=True,
pidfile=None):
"""Args:
output_dir: the absolute path to the layout test result directory
"""
http_server.Lighttpd.__init__(self, port_obj, output_dir,
port=_DEFAULT_WS_PORT,
- root=root,
- register_cygwin=register_cygwin)
+ root=root)
self._output_dir = output_dir
self._process = None
self._port = port
@@ -159,7 +159,8 @@ class PyWebSocket(http_server.Lighttpd):
python_interp = sys.executable
pywebsocket_base = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))), 'thirdparty', 'pywebsocket')
+ os.path.abspath(__file__)))), 'thirdparty',
+ 'autoinstalled', 'pywebsocket')
pywebsocket_script = os.path.join(pywebsocket_base, 'mod_pywebsocket',
'standalone.py')
start_cmd = [
@@ -185,21 +186,7 @@ class PyWebSocket(http_server.Lighttpd):
start_cmd.extend(['-t', '-k', self._private_key,
'-c', self._certificate])
- # Put the cygwin directory first in the path to find cygwin1.dll
- env = os.environ
- if sys.platform in ('cygwin', 'win32'):
- env['PATH'] = '%s;%s' % (
- self._port_obj.path_from_chromium_base('third_party',
- 'cygwin', 'bin'),
- env['PATH'])
- env['CYGWIN_PATH'] = self._port_obj.path_from_chromium_base(
- 'third_party', 'cygwin', 'bin')
-
- if sys.platform == 'win32' and self._register_cygwin:
- setup_mount = self._port_obj.path_from_chromium_base(
- 'third_party', 'cygwin', 'setup_mount.bat')
- subprocess.Popen(setup_mount).wait()
-
+ env = self._port_obj.setup_environ_for_server()
env['PYTHONPATH'] = (pywebsocket_base + os.path.pathsep +
env.get('PYTHONPATH', ''))
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py
index 3b7a817..e05a69d 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py
@@ -44,6 +44,11 @@ class WinPort(WebKitPort):
port_name = 'win'
WebKitPort.__init__(self, port_name, options)
+ def baseline_search_path(self):
+ # Based on code from old-run-webkit-tests expectedDirectoryForTest()
+ port_names = ["win", "mac-snowleopard", "mac"]
+ return map(self._webkit_baseline_path, port_names)
+
def _tests_for_other_platforms(self):
# FIXME: This list could be dynamic based on platform name and
# pushed into base.Port.
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
index 211ce93..f11b8a9 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
@@ -970,6 +970,28 @@ class HtmlGenerator(object):
return 'Other'
+def get_host_port_object(options):
+ """Return a port object for the platform we're running on."""
+ # The only thing we really need on the host is a way to diff
+ # text files and image files, which means we need to check that some
+ # version of ImageDiff has been built. We will look for either Debug
+ # or Release versions of the default port on the platform.
+ options.configuration = "Release"
+ port_obj = port.get(None, options)
+ if not port_obj.check_image_diff(override_step=None, logging=False):
+ _log.debug('No release version of the image diff binary was found.')
+ options.configuration = "Debug"
+ port_obj = port.get(None, options)
+ if not port_obj.check_image_diff(override_step=None, logging=False):
+ _log.error('No version of image diff was found. Check your build.')
+ return None
+ else:
+ _log.debug('Found the debug version of the image diff binary.')
+ else:
+ _log.debug('Found the release version of the image diff binary.')
+ return port_obj
+
+
def main():
"""Main function to produce new baselines."""
@@ -1034,19 +1056,11 @@ def main():
'%(levelname)s %(message)s'),
datefmt='%y%m%d %H:%M:%S')
- # options.configuration is used by port to locate image_diff binary.
- # Check the imgage_diff release binary, if it does not exist,
- # fallback to debug.
- options.configuration = "Release"
- port_obj = port.get(None, options)
- if not port_obj.check_image_diff(override_step=None, logging=False):
- _log.debug('No release version image diff binary found.')
- options.configuration = "Debug"
- port_obj = port.get(None, options)
- else:
- _log.debug('Found release version image diff binary.')
+ host_port_obj = get_host_port_object(options)
+ if not host_port_obj:
+ sys.exit(1)
- # Verify 'platforms' option is valid
+ # Verify 'platforms' option is valid.
if not options.platforms:
_log.error('Invalid "platforms" option. --platforms must be '
'specified in order to rebaseline.')
@@ -1071,7 +1085,8 @@ def main():
rebaselining_tests = set()
backup = options.backup
for platform in rebaseline_platforms:
- rebaseliner = Rebaseliner(port_obj, target_port_obj, platform, options)
+ rebaseliner = Rebaseliner(host_port_obj, target_port_obj,
+ platform, options)
_log.info('')
log_dashed_string('Rebaseline started', platform)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py
new file mode 100644
index 0000000..fa03238
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit tests for rebaseline_chromium_webkit_tests.py."""
+
+import unittest
+
+from webkitpy.layout_tests import port
+from webkitpy.layout_tests import rebaseline_chromium_webkit_tests
+
+
+class MockPort(object):
+ def __init__(self, image_diff_exists):
+ self.image_diff_exists = image_diff_exists
+
+ def check_image_diff(self, override_step, logging):
+ return self.image_diff_exists
+
+
+class MockOptions(object):
+ def __init__(self):
+ self.configuration = None
+
+
+def get_mock_get(config_expectations):
+ def mock_get(port_name, options):
+ return MockPort(config_expectations[options.configuration])
+ return mock_get
+
+
+class TestGetHostPortObject(unittest.TestCase):
+ def assert_result(self, release_present, debug_present, valid_port_obj):
+ # Tests whether we get a valid port object returned when we claim
+ # that Image diff is (or isn't) present in the two configs.
+ port.get = get_mock_get({'Release': release_present,
+ 'Debug': debug_present})
+ options = MockOptions()
+ port_obj = rebaseline_chromium_webkit_tests.get_host_port_object(
+ options)
+ if valid_port_obj:
+ self.assertNotEqual(port_obj, None)
+ else:
+ self.assertEqual(port_obj, None)
+
+ def test_get_host_port_object(self):
+ # Save the normal port.get() function for future testing.
+ old_get = port.get
+
+ # Test whether we get a valid port object back for the four
+ # possible cases of having ImageDiffs built. It should work when
+ # there is at least one binary present.
+ self.assert_result(False, False, False)
+ self.assert_result(True, False, True)
+ self.assert_result(False, True, True)
+ self.assert_result(True, True, True)
+
+ # Restore the normal port.get() function.
+ port.get = old_get
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index 456c6f3..148174d 100755
--- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -62,16 +62,17 @@ import sys
import time
import traceback
-from layout_package import test_expectations
+from layout_package import dump_render_tree_thread
from layout_package import json_layout_results_generator
from layout_package import printing
+from layout_package import test_expectations
from layout_package import test_failures
-from layout_package import dump_render_tree_thread
from layout_package import test_files
+from layout_package import test_results_uploader
from test_types import fuzzy_image_diff
from test_types import image_diff
-from test_types import test_type_base
from test_types import text_diff
+from test_types import test_type_base
from webkitpy.common.system.executive import Executive
from webkitpy.thirdparty import simplejson
@@ -790,6 +791,9 @@ class TestRunner:
self._write_json_files(unexpected_results, result_summary,
individual_test_timings)
+ # Upload generated JSON files to appengine server.
+ self._upload_json_files()
+
# Write the summary to disk (results.html) and display it if requested.
wrote_results = self._write_results_html_file(result_summary)
if self._options.show_results and wrote_results:
@@ -878,6 +882,31 @@ class TestRunner:
_log.debug("Finished writing JSON files.")
+ def _upload_json_files(self):
+ if not self._options.test_results_server:
+ return
+
+ _log.info("Uploading JSON files for builder: %s",
+ self._options.builder_name)
+
+ attrs = [('builder', self._options.builder_name)]
+ json_files = ["expectations.json", "results.json"]
+
+ files = [(file, os.path.join(self._options.results_directory, file))
+ for file in json_files]
+
+ uploader = test_results_uploader.TestResultsUploader(
+ self._options.test_results_server)
+ try:
+ # Set uploading timeout in case appengine server is having problem.
+ # 120 seconds are more than enough to upload test results.
+ uploader.upload(attrs, files, 120)
+ except Exception, err:
+ _log.error("Upload failed: %s" % err)
+ return
+
+ _log.info("JSON files uploaded.")
+
def _print_expected_results_of_type(self, result_summary,
result_type, result_type_str):
"""Print the number of the tests in a given result class.
@@ -1289,11 +1318,11 @@ def run(port_obj, options, args, regular_output=sys.stderr,
if options.print_last_failures or options.retest_last_failures:
unexpected_results_filename = os.path.join(
options.results_directory, "unexpected_results.json")
- with open(unexpected_results_filename, "r", "utf-8") as file:
+ with codecs.open(unexpected_results_filename, "r", "utf-8") as file:
results = simplejson.load(file)
last_unexpected_results = results['tests'].keys()
if options.print_last_failures:
- print "\n".join(last_unexpected_results) + "\n"
+ printer.write("\n".join(last_unexpected_results) + "\n")
return 0
if options.clobber_old_results:
@@ -1608,6 +1637,9 @@ def parse_args(args=None):
"webkit-rel.")),
optparse.make_option("--build-number", default="DUMMY_BUILD_NUMBER",
help=("The build number of the builder running this script.")),
+ optparse.make_option("--test-results-server", default="",
+ help=("If specified, upload results json files to this appengine "
+ "server.")),
]
option_list = (configuration_options + print_options +
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
index cd72fa3..e050cba 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -78,15 +78,21 @@ class MainTest(unittest.TestCase):
(res, buildbot_output, regular_output) = logging_run(
['--platform', 'test', '--print', 'config', '--child-processes',
'1', 'fast/html'])
- self.assertTrue('Running one DumpRenderTree'
+ self.assertTrue('Running one DumpRenderTree\n'
in regular_output.get())
(res, buildbot_output, regular_output) = logging_run(
['--platform', 'test', '--print', 'config', '--child-processes',
'2', 'fast/html'])
- self.assertTrue('Running 2 DumpRenderTrees in parallel'
+ self.assertTrue('Running 2 DumpRenderTrees in parallel\n'
in regular_output.get())
+ def test_last_results(self):
+ passing_run(['--platform', 'test', 'fast/html'])
+ (res, buildbot_output, regular_output) = logging_run(
+ ['--platform', 'test', '--print-last-failures'])
+ self.assertEqual(regular_output.get(), ['\n\n'])
+ self.assertEqual(buildbot_output.get(), [])
class TestRunnerTest(unittest.TestCase):
@@ -112,16 +118,17 @@ class TestRunnerTest(unittest.TestCase):
class DryrunTest(unittest.TestCase):
def test_basics(self):
+ # FIXME: it's hard to know which platforms are safe to test; the
+ # chromium platforms require a chromium checkout, and the mac platform
+ # requires fcntl, so it can't be tested on win32, etc. There is
+ # probably a better way of handling this.
+ if sys.platform != "mac":
+ return
self.assertTrue(passing_run(['--platform', 'dryrun',
'fast/html']))
- #self.assertTrue(passing_run(['--platform', 'dryrun-mac',
- # 'fast/html']))
- #self.assertTrue(passing_run(['--platform', 'dryrun-chromium-mac',
- # 'fast/html']))
- #self.assertTrue(passing_run(['--platform', 'dryrun-chromium-win',
- # 'fast/html']))
- #self.assertTrue(passing_run(['--platform', 'dryrun-chromium-linux',
- # 'fast/html']))
+ self.assertTrue(passing_run(['--platform', 'dryrun-mac',
+ 'fast/html']))
+
if __name__ == '__main__':
unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py
index c052f00..3642286 100644
--- a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py
@@ -89,6 +89,11 @@ installer.install(url="http://iweb.dl.sourceforge.net/project/python-irclib/pyth
installer.install(url="http://iweb.dl.sourceforge.net/project/python-irclib/python-irclib/0.4.8/python-irclib-0.4.8.zip",
url_subpath="ircbot.py")
+pywebsocket_dir = os.path.join(autoinstalled_dir, "pywebsocket")
+installer = AutoInstaller(target_dir=pywebsocket_dir)
+installer.install(url="http://pywebsocket.googlecode.com/files/mod_pywebsocket-0.5.tar.gz",
+ url_subpath="pywebsocket-0.5/src/mod_pywebsocket")
+
readme_path = os.path.join(autoinstalled_dir, "README")
if not os.path.exists(readme_path):
with codecs.open(readme_path, "w", "ascii") as file:
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/COPYING b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/COPYING
deleted file mode 100644
index ab9d52d..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/COPYING
+++ /dev/null
@@ -1,28 +0,0 @@
-Copyright 2009, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/MANIFEST.in b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/MANIFEST.in
deleted file mode 100644
index 1925688..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/MANIFEST.in
+++ /dev/null
@@ -1,6 +0,0 @@
-include COPYING
-include MANIFEST.in
-include README
-recursive-include example *.py
-recursive-include mod_pywebsocket *.py
-recursive-include test *.py
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README
deleted file mode 100644
index 1f9f05f..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README
+++ /dev/null
@@ -1,6 +0,0 @@
-Install this package by:
-$ python setup.py build
-$ sudo python setup.py install
-
-Then read document by:
-$ pydoc mod_pywebsocket
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README.webkit b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README.webkit
deleted file mode 100644
index 83e3cee..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/README.webkit
+++ /dev/null
@@ -1,14 +0,0 @@
-This directory contains a copy of the pywebsocket Python module obtained
-from the following location:
-
-http://code.google.com/p/pywebsocket/
-
-This directory currently contains the following version:
-0.4.9.2
-
-The following modifications have been made to this local version:
-minor updates in WebSocketRequestHandler.is_cgi
-
-More information on these local modifications can be found here:
-
-http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_client.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_client.py
deleted file mode 100644
index 2b976e1..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/echo_client.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Web Socket Echo client.
-
-This is an example Web Socket client that talks with echo_wsh.py.
-This may be useful for checking mod_pywebsocket installation.
-
-Note:
-This code is far from robust, e.g., we cut corners in handshake.
-"""
-
-
-import codecs
-from optparse import OptionParser
-import socket
-import sys
-
-
-_TIMEOUT_SEC = 10
-
-_DEFAULT_PORT = 80
-_DEFAULT_SECURE_PORT = 443
-_UNDEFINED_PORT = -1
-
-_UPGRADE_HEADER = 'Upgrade: WebSocket\r\n'
-_CONNECTION_HEADER = 'Connection: Upgrade\r\n'
-_EXPECTED_RESPONSE = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
- _UPGRADE_HEADER +
- _CONNECTION_HEADER)
-
-_GOODBYE_MESSAGE = 'Goodbye'
-
-
-def _method_line(resource):
- return 'GET %s HTTP/1.1\r\n' % resource
-
-
-def _origin_header(origin):
- return 'Origin: %s\r\n' % origin
-
-
-class _TLSSocket(object):
- """Wrapper for a TLS connection."""
-
- def __init__(self, raw_socket):
- self._ssl = socket.ssl(raw_socket)
-
- def send(self, bytes):
- return self._ssl.write(bytes)
-
- def recv(self, size=-1):
- return self._ssl.read(size)
-
- def close(self):
- # Nothing to do.
- pass
-
-
-class EchoClient(object):
- """Web Socket echo client."""
-
- def __init__(self, options):
- self._options = options
- self._socket = None
-
- def run(self):
- """Run the client.
-
- Shake hands and then repeat sending message and receiving its echo.
- """
- self._socket = socket.socket()
- self._socket.settimeout(self._options.socket_timeout)
- try:
- self._socket.connect((self._options.server_host,
- self._options.server_port))
- if self._options.use_tls:
- self._socket = _TLSSocket(self._socket)
- self._handshake()
- for line in self._options.message.split(',') + [_GOODBYE_MESSAGE]:
- frame = '\x00' + line.encode('utf-8') + '\xff'
- self._socket.send(frame)
- if self._options.verbose:
- print 'Send: %s' % line
- received = self._socket.recv(len(frame))
- if received != frame:
- raise Exception('Incorrect echo: %r' % received)
- if self._options.verbose:
- print 'Recv: %s' % received[1:-1].decode('utf-8',
- 'replace')
- finally:
- self._socket.close()
-
- def _handshake(self):
- self._socket.send(_method_line(self._options.resource))
- self._socket.send(_UPGRADE_HEADER)
- self._socket.send(_CONNECTION_HEADER)
- self._socket.send(self._format_host_header())
- self._socket.send(_origin_header(self._options.origin))
- self._socket.send('\r\n')
-
- for expected_char in _EXPECTED_RESPONSE:
- received = self._socket.recv(1)[0]
- if expected_char != received:
- raise Exception('Handshake failure')
- # We cut corners and skip other headers.
- self._skip_headers()
-
- def _skip_headers(self):
- terminator = '\r\n\r\n'
- pos = 0
- while pos < len(terminator):
- received = self._socket.recv(1)[0]
- if received == terminator[pos]:
- pos += 1
- elif received == terminator[0]:
- pos = 1
- else:
- pos = 0
-
- def _format_host_header(self):
- host = 'Host: ' + self._options.server_host
- if ((not self._options.use_tls and
- self._options.server_port != _DEFAULT_PORT) or
- (self._options.use_tls and
- self._options.server_port != _DEFAULT_SECURE_PORT)):
- host += ':' + str(self._options.server_port)
- host += '\r\n'
- return host
-
-
-def main():
- sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
-
- parser = OptionParser()
- parser.add_option('-s', '--server-host', '--server_host',
- dest='server_host', type='string',
- default='localhost', help='server host')
- parser.add_option('-p', '--server-port', '--server_port',
- dest='server_port', type='int',
- default=_UNDEFINED_PORT, help='server port')
- parser.add_option('-o', '--origin', dest='origin', type='string',
- default='http://localhost/', help='origin')
- parser.add_option('-r', '--resource', dest='resource', type='string',
- default='/echo', help='resource path')
- parser.add_option('-m', '--message', dest='message', type='string',
- help=('comma-separated messages to send excluding "%s" '
- 'that is always sent at the end' %
- _GOODBYE_MESSAGE))
- parser.add_option('-q', '--quiet', dest='verbose', action='store_false',
- default=True, help='suppress messages')
- parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
- default=False, help='use TLS (wss://)')
- parser.add_option('-k', '--socket-timeout', '--socket_timeout',
- dest='socket_timeout', type='int', default=_TIMEOUT_SEC,
- help='Timeout(sec) for sockets')
-
- (options, unused_args) = parser.parse_args()
-
- # Default port number depends on whether TLS is used.
- if options.server_port == _UNDEFINED_PORT:
- if options.use_tls:
- options.server_port = _DEFAULT_SECURE_PORT
- else:
- options.server_port = _DEFAULT_PORT
-
- # optparse doesn't seem to handle non-ascii default values.
- # Set default message here.
- if not options.message:
- options.message = u'Hello,\u65e5\u672c' # "Japan" in Japanese
-
- EchoClient(options).run()
-
-
-if __name__ == '__main__':
- main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/handler_map.txt b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/handler_map.txt
deleted file mode 100644
index 21c4c09..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/example/handler_map.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-# websocket handler map file, used by standalone.py -m option.
-# A line starting with '#' is a comment line.
-# Each line consists of 'alias_resource_path' and 'existing_resource_path'
-# separated by spaces.
-# Aliasing is processed from the top to the bottom of the line, and
-# 'existing_resource_path' must exist before it is aliased.
-# For example,
-# / /echo
-# means that a request to '/' will be handled by handlers for '/echo'.
-/ /echo
-
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/__init__.py
deleted file mode 100644
index 05e80e8..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/__init__.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Web Socket extension for Apache HTTP Server.
-
-mod_pywebsocket is a Web Socket extension for Apache HTTP Server
-intended for testing or experimental purposes. mod_python is required.
-
-Installation:
-
-0. Prepare an Apache HTTP Server for which mod_python is enabled.
-
-1. Specify the following Apache HTTP Server directives to suit your
- configuration.
-
- If mod_pywebsocket is not in the Python path, specify the following.
- <websock_lib> is the directory where mod_pywebsocket is installed.
-
- PythonPath "sys.path+['<websock_lib>']"
-
- Always specify the following. <websock_handlers> is the directory where
- user-written Web Socket handlers are placed.
-
- PythonOption mod_pywebsocket.handler_root <websock_handlers>
- PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
-
- To limit the search for Web Socket handlers to a directory <scan_dir>
- under <websock_handlers>, configure as follows:
-
- PythonOption mod_pywebsocket.handler_scan <scan_dir>
-
- <scan_dir> is useful in saving scan time when <websock_handlers>
- contains many non-Web Socket handler files.
-
- Example snippet of httpd.conf:
- (mod_pywebsocket is in /websock_lib, Web Socket handlers are in
- /websock_handlers, port is 80 for ws, 443 for wss.)
-
- <IfModule python_module>
- PythonPath "sys.path+['/websock_lib']"
- PythonOption mod_pywebsocket.handler_root /websock_handlers
- PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
- </IfModule>
-
-Writing Web Socket handlers:
-
-When a Web Socket request comes in, the resource name
-specified in the handshake is considered as if it is a file path under
-<websock_handlers> and the handler defined in
-<websock_handlers>/<resource_name>_wsh.py is invoked.
-
-For example, if the resource name is /example/chat, the handler defined in
-<websock_handlers>/example/chat_wsh.py is invoked.
-
-A Web Socket handler is composed of the following two functions:
-
- web_socket_do_extra_handshake(request)
- web_socket_transfer_data(request)
-
-where:
- request: mod_python request.
-
-web_socket_do_extra_handshake is called during the handshake after the
-headers are successfully parsed and Web Socket properties (ws_location,
-ws_origin, ws_protocol, and ws_resource) are added to request. A handler
-can reject the request by raising an exception.
-
-web_socket_transfer_data is called after the handshake completed
-successfully. A handler can receive/send messages from/to the client
-using request. mod_pywebsocket.msgutil module provides utilities
-for data transfer.
-
-A Web Socket handler must be thread-safe if the server (Apache or
-standalone.py) is configured to use threads.
-"""
-
-
-# vi:sts=4 sw=4 et tw=72
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/dispatch.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/dispatch.py
deleted file mode 100644
index c52e9eb..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/dispatch.py
+++ /dev/null
@@ -1,231 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Dispatch Web Socket request.
-"""
-
-
-import os
-import re
-
-import util
-
-
-_SOURCE_PATH_PATTERN = re.compile(r'(?i)_wsh\.py$')
-_SOURCE_SUFFIX = '_wsh.py'
-_DO_EXTRA_HANDSHAKE_HANDLER_NAME = 'web_socket_do_extra_handshake'
-_TRANSFER_DATA_HANDLER_NAME = 'web_socket_transfer_data'
-
-
-class DispatchError(Exception):
- """Exception in dispatching Web Socket request."""
-
- pass
-
-
-def _normalize_path(path):
- """Normalize path.
-
- Args:
- path: the path to normalize.
-
- Path is converted to the absolute path.
- The input path can use either '\\' or '/' as the separator.
- The normalized path always uses '/' regardless of the platform.
- """
-
- path = path.replace('\\', os.path.sep)
- path = os.path.realpath(path)
- path = path.replace('\\', '/')
- return path
-
-
-def _path_to_resource_converter(base_dir):
- base_dir = _normalize_path(base_dir)
- base_len = len(base_dir)
- suffix_len = len(_SOURCE_SUFFIX)
- def converter(path):
- if not path.endswith(_SOURCE_SUFFIX):
- return None
- path = _normalize_path(path)
- if not path.startswith(base_dir):
- return None
- return path[base_len:-suffix_len]
- return converter
-
-
-def _source_file_paths(directory):
- """Yield Web Socket Handler source file names in the given directory."""
-
- for root, unused_dirs, files in os.walk(directory):
- for base in files:
- path = os.path.join(root, base)
- if _SOURCE_PATH_PATTERN.search(path):
- yield path
-
-
-def _source(source_str):
- """Source a handler definition string."""
-
- global_dic = {}
- try:
- exec source_str in global_dic
- except Exception:
- raise DispatchError('Error in sourcing handler:' +
- util.get_stack_trace())
- return (_extract_handler(global_dic, _DO_EXTRA_HANDSHAKE_HANDLER_NAME),
- _extract_handler(global_dic, _TRANSFER_DATA_HANDLER_NAME))
-
-
-def _extract_handler(dic, name):
- if name not in dic:
- raise DispatchError('%s is not defined.' % name)
- handler = dic[name]
- if not callable(handler):
- raise DispatchError('%s is not callable.' % name)
- return handler
-
-
-class Dispatcher(object):
- """Dispatches Web Socket requests.
-
- This class maintains a map from resource name to handlers.
- """
-
- def __init__(self, root_dir, scan_dir=None):
- """Construct an instance.
-
- Args:
- root_dir: The directory where handler definition files are
- placed.
- scan_dir: The directory where handler definition files are
- searched. scan_dir must be a directory under root_dir,
- including root_dir itself. If scan_dir is None, root_dir
- is used as scan_dir. scan_dir can be useful in saving
- scan time when root_dir contains many subdirectories.
- """
-
- self._handlers = {}
- self._source_warnings = []
- if scan_dir is None:
- scan_dir = root_dir
- if not os.path.realpath(scan_dir).startswith(
- os.path.realpath(root_dir)):
- raise DispatchError('scan_dir:%s must be a directory under '
- 'root_dir:%s.' % (scan_dir, root_dir))
- self._source_files_in_dir(root_dir, scan_dir)
-
- def add_resource_path_alias(self,
- alias_resource_path, existing_resource_path):
- """Add resource path alias.
-
- Once added, request to alias_resource_path would be handled by
- handler registered for existing_resource_path.
-
- Args:
- alias_resource_path: alias resource path
- existing_resource_path: existing resource path
- """
- try:
- handler = self._handlers[existing_resource_path]
- self._handlers[alias_resource_path] = handler
- except KeyError:
- raise DispatchError('No handler for: %r' % existing_resource_path)
-
- def source_warnings(self):
- """Return warnings in sourcing handlers."""
-
- return self._source_warnings
-
- def do_extra_handshake(self, request):
- """Do extra checking in Web Socket handshake.
-
- Select a handler based on request.uri and call its
- web_socket_do_extra_handshake function.
-
- Args:
- request: mod_python request.
- """
-
- do_extra_handshake_, unused_transfer_data = self._handler(request)
- try:
- do_extra_handshake_(request)
- except Exception, e:
- util.prepend_message_to_exception(
- '%s raised exception for %s: ' % (
- _DO_EXTRA_HANDSHAKE_HANDLER_NAME,
- request.ws_resource),
- e)
- raise
-
- def transfer_data(self, request):
- """Let a handler transfer_data with a Web Socket client.
-
- Select a handler based on request.ws_resource and call its
- web_socket_transfer_data function.
-
- Args:
- request: mod_python request.
- """
-
- unused_do_extra_handshake, transfer_data_ = self._handler(request)
- try:
- transfer_data_(request)
- except Exception, e:
- util.prepend_message_to_exception(
- '%s raised exception for %s: ' % (
- _TRANSFER_DATA_HANDLER_NAME, request.ws_resource),
- e)
- raise
-
- def _handler(self, request):
- try:
- ws_resource_path = request.ws_resource.split('?', 1)[0]
- return self._handlers[ws_resource_path]
- except KeyError:
- raise DispatchError('No handler for: %r' % request.ws_resource)
-
- def _source_files_in_dir(self, root_dir, scan_dir):
- """Source all the handler source files in the scan_dir directory.
-
- The resource path is determined relative to root_dir.
- """
-
- to_resource = _path_to_resource_converter(root_dir)
- for path in _source_file_paths(scan_dir):
- try:
- handlers = _source(open(path).read())
- except DispatchError, e:
- self._source_warnings.append('%s: %s' % (path, e))
- continue
- self._handlers[to_resource(path)] = handlers
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/handshake.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/handshake.py
deleted file mode 100644
index b86278e..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/handshake.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Web Socket handshaking.
-
-Note: request.connection.write/read are used in this module, even though
-mod_python document says that they should be used only in connection handlers.
-Unfortunately, we have no other options. For example, request.write/read are
-not suitable because they don't allow direct raw bytes writing/reading.
-"""
-
-
-import re
-
-import util
-
-
-_DEFAULT_WEB_SOCKET_PORT = 80
-_DEFAULT_WEB_SOCKET_SECURE_PORT = 443
-_WEB_SOCKET_SCHEME = 'ws'
-_WEB_SOCKET_SECURE_SCHEME = 'wss'
-
-_MANDATORY_HEADERS = [
- # key, expected value or None
- ['Upgrade', 'WebSocket'],
- ['Connection', 'Upgrade'],
- ['Host', None],
- ['Origin', None],
-]
-
-_FIRST_FIVE_LINES = map(re.compile, [
- r'^GET /[\S]* HTTP/1.1\r\n$',
- r'^Upgrade: WebSocket\r\n$',
- r'^Connection: Upgrade\r\n$',
- r'^Host: [\S]+\r\n$',
- r'^Origin: [\S]+\r\n$',
-])
-
-_SIXTH_AND_LATER = re.compile(
- r'^'
- r'(WebSocket-Protocol: [\x20-\x7e]+\r\n)?'
- r'(Cookie: [^\r]*\r\n)*'
- r'(Cookie2: [^\r]*\r\n)?'
- r'(Cookie: [^\r]*\r\n)*'
- r'\r\n')
-
-
-def _default_port(is_secure):
- if is_secure:
- return _DEFAULT_WEB_SOCKET_SECURE_PORT
- else:
- return _DEFAULT_WEB_SOCKET_PORT
-
-
-class HandshakeError(Exception):
- """Exception in Web Socket Handshake."""
-
- pass
-
-
-def _validate_protocol(protocol):
- """Validate WebSocket-Protocol string."""
-
- if not protocol:
- raise HandshakeError('Invalid WebSocket-Protocol: empty')
- for c in protocol:
- if not 0x20 <= ord(c) <= 0x7e:
- raise HandshakeError('Illegal character in protocol: %r' % c)
-
-
-class Handshaker(object):
- """This class performs Web Socket handshake."""
-
- def __init__(self, request, dispatcher, strict=False):
- """Construct an instance.
-
- Args:
- request: mod_python request.
- dispatcher: Dispatcher (dispatch.Dispatcher).
- strict: Strictly check handshake request. Default: False.
- If True, request.connection must provide get_memorized_lines
- method.
-
- Handshaker will add attributes such as ws_resource in performing
- handshake.
- """
-
- self._request = request
- self._dispatcher = dispatcher
- self._strict = strict
-
- def do_handshake(self):
- """Perform Web Socket Handshake."""
-
- self._check_header_lines()
- self._set_resource()
- self._set_origin()
- self._set_location()
- self._set_protocol()
- self._dispatcher.do_extra_handshake(self._request)
- self._send_handshake()
-
- def _set_resource(self):
- self._request.ws_resource = self._request.uri
-
- def _set_origin(self):
- self._request.ws_origin = self._request.headers_in['Origin']
-
- def _set_location(self):
- location_parts = []
- if self._request.is_https():
- location_parts.append(_WEB_SOCKET_SECURE_SCHEME)
- else:
- location_parts.append(_WEB_SOCKET_SCHEME)
- location_parts.append('://')
- host, port = self._parse_host_header()
- connection_port = self._request.connection.local_addr[1]
- if port != connection_port:
- raise HandshakeError('Header/connection port mismatch: %d/%d' %
- (port, connection_port))
- location_parts.append(host)
- if (port != _default_port(self._request.is_https())):
- location_parts.append(':')
- location_parts.append(str(port))
- location_parts.append(self._request.uri)
- self._request.ws_location = ''.join(location_parts)
-
- def _parse_host_header(self):
- fields = self._request.headers_in['Host'].split(':', 1)
- if len(fields) == 1:
- return fields[0], _default_port(self._request.is_https())
- try:
- return fields[0], int(fields[1])
- except ValueError, e:
- raise HandshakeError('Invalid port number format: %r' % e)
-
- def _set_protocol(self):
- protocol = self._request.headers_in.get('WebSocket-Protocol')
- if protocol is not None:
- _validate_protocol(protocol)
- self._request.ws_protocol = protocol
-
- def _send_handshake(self):
- self._request.connection.write(
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n')
- self._request.connection.write('Upgrade: WebSocket\r\n')
- self._request.connection.write('Connection: Upgrade\r\n')
- self._request.connection.write('WebSocket-Origin: ')
- self._request.connection.write(self._request.ws_origin)
- self._request.connection.write('\r\n')
- self._request.connection.write('WebSocket-Location: ')
- self._request.connection.write(self._request.ws_location)
- self._request.connection.write('\r\n')
- if self._request.ws_protocol:
- self._request.connection.write('WebSocket-Protocol: ')
- self._request.connection.write(self._request.ws_protocol)
- self._request.connection.write('\r\n')
- self._request.connection.write('\r\n')
-
- def _check_header_lines(self):
- for key, expected_value in _MANDATORY_HEADERS:
- actual_value = self._request.headers_in.get(key)
- if not actual_value:
- raise HandshakeError('Header %s is not defined' % key)
- if expected_value:
- if actual_value != expected_value:
- raise HandshakeError('Illegal value for header %s: %s' %
- (key, actual_value))
- if self._strict:
- try:
- lines = self._request.connection.get_memorized_lines()
- except AttributeError, e:
- util.prepend_message_to_exception(
- 'Strict handshake is specified but the connection '
- 'doesn\'t provide get_memorized_lines()', e)
- raise
- self._check_first_lines(lines)
-
- def _check_first_lines(self, lines):
- if len(lines) < len(_FIRST_FIVE_LINES):
- raise HandshakeError('Too few header lines: %d' % len(lines))
- for line, regexp in zip(lines, _FIRST_FIVE_LINES):
- if not regexp.search(line):
- raise HandshakeError('Unexpected header: %r doesn\'t match %r'
- % (line, regexp.pattern))
- sixth_and_later = ''.join(lines[5:])
- if not _SIXTH_AND_LATER.search(sixth_and_later):
- raise HandshakeError('Unexpected header: %r doesn\'t match %r'
- % (sixth_and_later,
- _SIXTH_AND_LATER.pattern))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/headerparserhandler.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/headerparserhandler.py
deleted file mode 100644
index 124b9f1..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/headerparserhandler.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""PythonHeaderParserHandler for mod_pywebsocket.
-
-Apache HTTP Server and mod_python must be configured such that this
-function is called to handle Web Socket request.
-"""
-
-
-from mod_python import apache
-
-import dispatch
-import handshake
-import util
-
-
-# PythonOption to specify the handler root directory.
-_PYOPT_HANDLER_ROOT = 'mod_pywebsocket.handler_root'
-
-# PythonOption to specify the handler scan directory.
-# This must be a directory under the root directory.
-# The default is the root directory.
-_PYOPT_HANDLER_SCAN = 'mod_pywebsocket.handler_scan'
-
-
-def _create_dispatcher():
- _HANDLER_ROOT = apache.main_server.get_options().get(
- _PYOPT_HANDLER_ROOT, None)
- if not _HANDLER_ROOT:
- raise Exception('PythonOption %s is not defined' % _PYOPT_HANDLER_ROOT,
- apache.APLOG_ERR)
- _HANDLER_SCAN = apache.main_server.get_options().get(
- _PYOPT_HANDLER_SCAN, _HANDLER_ROOT)
- dispatcher = dispatch.Dispatcher(_HANDLER_ROOT, _HANDLER_SCAN)
- for warning in dispatcher.source_warnings():
- apache.log_error('mod_pywebsocket: %s' % warning, apache.APLOG_WARNING)
- return dispatcher
-
-
-# Initialize
-_dispatcher = _create_dispatcher()
-
-
-def headerparserhandler(request):
- """Handle request.
-
- Args:
- request: mod_python request.
-
- This function is named headerparserhandler because it is the default name
- for a PythonHeaderParserHandler.
- """
-
- try:
- handshaker = handshake.Handshaker(request, _dispatcher)
- handshaker.do_handshake()
- request.log_error('mod_pywebsocket: resource: %r' % request.ws_resource,
- apache.APLOG_DEBUG)
- _dispatcher.transfer_data(request)
- except handshake.HandshakeError, e:
- # Handshake for ws/wss failed.
- # But the request can be valid http/https request.
- request.log_error('mod_pywebsocket: %s' % e, apache.APLOG_INFO)
- return apache.DECLINED
- except dispatch.DispatchError, e:
- request.log_error('mod_pywebsocket: %s' % e, apache.APLOG_WARNING)
- return apache.DECLINED
- return apache.DONE # Return DONE such that no other handlers are invoked.
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/memorizingfile.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/memorizingfile.py
deleted file mode 100644
index 2f8a54e..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/memorizingfile.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Memorizing file.
-
-A memorizing file wraps a file and memorizes lines read by readline.
-"""
-
-
-import sys
-
-
-class MemorizingFile(object):
- """MemorizingFile wraps a file and memorizes lines read by readline.
-
- Note that data read by other methods are not memorized. This behavior
- is good enough for memorizing lines SimpleHTTPServer reads before
- the control reaches WebSocketRequestHandler.
- """
- def __init__(self, file_, max_memorized_lines=sys.maxint):
- """Construct an instance.
-
- Args:
- file_: the file object to wrap.
- max_memorized_lines: the maximum number of lines to memorize.
- Only the first max_memorized_lines are memorized.
- Default: sys.maxint.
- """
- self._file = file_
- self._memorized_lines = []
- self._max_memorized_lines = max_memorized_lines
-
- def __getattribute__(self, name):
- if name in ('_file', '_memorized_lines', '_max_memorized_lines',
- 'readline', 'get_memorized_lines'):
- return object.__getattribute__(self, name)
- return self._file.__getattribute__(name)
-
- def readline(self):
- """Override file.readline and memorize the line read."""
-
- line = self._file.readline()
- if line and len(self._memorized_lines) < self._max_memorized_lines:
- self._memorized_lines.append(line)
- return line
-
- def get_memorized_lines(self):
- """Get lines memorized so far."""
- return self._memorized_lines
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/msgutil.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/msgutil.py
deleted file mode 100644
index 90ae715..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/msgutil.py
+++ /dev/null
@@ -1,250 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Message related utilities.
-
-Note: request.connection.write/read are used in this module, even though
-mod_python document says that they should be used only in connection handlers.
-Unfortunately, we have no other options. For example, request.write/read are
-not suitable because they don't allow direct raw bytes writing/reading.
-"""
-
-
-import Queue
-import threading
-import util
-
-
-class MsgUtilException(Exception):
- pass
-
-
-def _read(request, length):
- bytes = request.connection.read(length)
- if not bytes:
- raise MsgUtilException(
- 'Failed to receive message from %r' %
- (request.connection.remote_addr,))
- return bytes
-
-
-def _write(request, bytes):
- try:
- request.connection.write(bytes)
- except Exception, e:
- util.prepend_message_to_exception(
- 'Failed to send message to %r: ' %
- (request.connection.remote_addr,),
- e)
- raise
-
-
-def send_message(request, message):
- """Send message.
-
- Args:
- request: mod_python request.
- message: unicode string to send.
- """
-
- _write(request, '\x00' + message.encode('utf-8') + '\xff')
-
-
-def receive_message(request):
- """Receive a Web Socket frame and return its payload as unicode string.
-
- Args:
- request: mod_python request.
- """
-
- while True:
- # Read 1 byte.
- # mp_conn.read will block if no bytes are available.
- # Timeout is controlled by TimeOut directive of Apache.
- frame_type_str = _read(request, 1)
- frame_type = ord(frame_type_str[0])
- if (frame_type & 0x80) == 0x80:
- # The payload length is specified in the frame.
- # Read and discard.
- length = _payload_length(request)
- _receive_bytes(request, length)
- else:
- # The payload is delimited with \xff.
- bytes = _read_until(request, '\xff')
- # The Web Socket protocol section 4.4 specifies that invalid
- # characters must be replaced with U+fffd REPLACEMENT CHARACTER.
- message = bytes.decode('utf-8', 'replace')
- if frame_type == 0x00:
- return message
- # Discard data of other types.
-
-
-def _payload_length(request):
- length = 0
- while True:
- b_str = _read(request, 1)
- b = ord(b_str[0])
- length = length * 128 + (b & 0x7f)
- if (b & 0x80) == 0:
- break
- return length
-
-
-def _receive_bytes(request, length):
- bytes = []
- while length > 0:
- new_bytes = _read(request, length)
- bytes.append(new_bytes)
- length -= len(new_bytes)
- return ''.join(bytes)
-
-
-def _read_until(request, delim_char):
- bytes = []
- while True:
- ch = _read(request, 1)
- if ch == delim_char:
- break
- bytes.append(ch)
- return ''.join(bytes)
-
-
-class MessageReceiver(threading.Thread):
- """This class receives messages from the client.
-
- This class provides three ways to receive messages: blocking, non-blocking,
- and via callback. Callback has the highest precedence.
-
- Note: This class should not be used with the standalone server for wss
- because pyOpenSSL used by the server raises a fatal error if the socket
- is accessed from multiple threads.
- """
- def __init__(self, request, onmessage=None):
- """Construct an instance.
-
- Args:
- request: mod_python request.
- onmessage: a function to be called when a message is received.
- May be None. If not None, the function is called on
- another thread. In that case, MessageReceiver.receive
- and MessageReceiver.receive_nowait are useless because
- they will never return any messages.
- """
- threading.Thread.__init__(self)
- self._request = request
- self._queue = Queue.Queue()
- self._onmessage = onmessage
- self._stop_requested = False
- self.setDaemon(True)
- self.start()
-
- def run(self):
- while not self._stop_requested:
- message = receive_message(self._request)
- if self._onmessage:
- self._onmessage(message)
- else:
- self._queue.put(message)
-
- def receive(self):
- """ Receive a message from the channel, blocking.
-
- Returns:
- message as a unicode string.
- """
- return self._queue.get()
-
- def receive_nowait(self):
- """ Receive a message from the channel, non-blocking.
-
- Returns:
- message as a unicode string if available. None otherwise.
- """
- try:
- message = self._queue.get_nowait()
- except Queue.Empty:
- message = None
- return message
-
- def stop(self):
- """Request to stop this instance.
-
- The instance will be stopped after receiving the next message.
- This method may not be very useful, but there is no clean way
- in Python to forcefully stop a running thread.
- """
- self._stop_requested = True
-
-
-class MessageSender(threading.Thread):
- """This class sends messages to the client.
-
- This class provides both synchronous and asynchronous ways to send
- messages.
-
- Note: This class should not be used with the standalone server for wss
- because pyOpenSSL used by the server raises a fatal error if the socket
- is accessed from multiple threads.
- """
- def __init__(self, request):
- """Construct an instance.
-
- Args:
- request: mod_python request.
- """
- threading.Thread.__init__(self)
- self._request = request
- self._queue = Queue.Queue()
- self.setDaemon(True)
- self.start()
-
- def run(self):
- while True:
- message, condition = self._queue.get()
- condition.acquire()
- send_message(self._request, message)
- condition.notify()
- condition.release()
-
- def send(self, message):
- """Send a message, blocking."""
-
- condition = threading.Condition()
- condition.acquire()
- self._queue.put((message, condition))
- condition.wait()
-
- def send_nowait(self, message):
- """Send a message, non-blocking."""
-
- self._queue.put((message, threading.Condition()))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py
deleted file mode 100644
index f411910..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py
+++ /dev/null
@@ -1,453 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Standalone Web Socket server.
-
-Use this server to run mod_pywebsocket without Apache HTTP Server.
-
-Usage:
- python standalone.py [-p <ws_port>] [-w <websock_handlers>]
- [-s <scan_dir>]
- [-d <document_root>]
- [-m <websock_handlers_map_file>]
- ... for other options, see _main below ...
-
-<ws_port> is the port number to use for ws:// connection.
-
-<document_root> is the path to the root directory of HTML files.
-
-<websock_handlers> is the path to the root directory of Web Socket handlers.
-See __init__.py for details of <websock_handlers> and how to write Web Socket
-handlers. If this path is relative, <document_root> is used as the base.
-
-<scan_dir> is a path under the root directory. If specified, only the handlers
-under scan_dir are scanned. This is useful in saving scan time.
-
-Note:
-This server is derived from SocketServer.ThreadingMixIn. Hence a thread is
-used for each request.
-"""
-
-import BaseHTTPServer
-import CGIHTTPServer
-import SimpleHTTPServer
-import SocketServer
-import logging
-import logging.handlers
-import optparse
-import os
-import re
-import socket
-import sys
-
-_HAS_OPEN_SSL = False
-try:
- import OpenSSL.SSL
- _HAS_OPEN_SSL = True
-except ImportError:
- pass
-
-import dispatch
-import handshake
-import memorizingfile
-import util
-
-
-_LOG_LEVELS = {
- 'debug': logging.DEBUG,
- 'info': logging.INFO,
- 'warn': logging.WARN,
- 'error': logging.ERROR,
- 'critical': logging.CRITICAL};
-
-_DEFAULT_LOG_MAX_BYTES = 1024 * 256
-_DEFAULT_LOG_BACKUP_COUNT = 5
-
-_DEFAULT_REQUEST_QUEUE_SIZE = 128
-
-# 1024 is practically large enough to contain WebSocket handshake lines.
-_MAX_MEMORIZED_LINES = 1024
-
-def _print_warnings_if_any(dispatcher):
- warnings = dispatcher.source_warnings()
- if warnings:
- for warning in warnings:
- logging.warning('mod_pywebsocket: %s' % warning)
-
-
-class _StandaloneConnection(object):
- """Mimic mod_python mp_conn."""
-
- def __init__(self, request_handler):
- """Construct an instance.
-
- Args:
- request_handler: A WebSocketRequestHandler instance.
- """
- self._request_handler = request_handler
-
- def get_local_addr(self):
- """Getter to mimic mp_conn.local_addr."""
- return (self._request_handler.server.server_name,
- self._request_handler.server.server_port)
- local_addr = property(get_local_addr)
-
- def get_remote_addr(self):
- """Getter to mimic mp_conn.remote_addr.
-
- Setting the property in __init__ won't work because the request
- handler is not initialized yet there."""
- return self._request_handler.client_address
- remote_addr = property(get_remote_addr)
-
- def write(self, data):
- """Mimic mp_conn.write()."""
- return self._request_handler.wfile.write(data)
-
- def read(self, length):
- """Mimic mp_conn.read()."""
- return self._request_handler.rfile.read(length)
-
- def get_memorized_lines(self):
- """Get memorized lines."""
- return self._request_handler.rfile.get_memorized_lines()
-
-
-class _StandaloneRequest(object):
- """Mimic mod_python request."""
-
- def __init__(self, request_handler, use_tls):
- """Construct an instance.
-
- Args:
- request_handler: A WebSocketRequestHandler instance.
- """
- self._request_handler = request_handler
- self.connection = _StandaloneConnection(request_handler)
- self._use_tls = use_tls
-
- def get_uri(self):
- """Getter to mimic request.uri."""
- return self._request_handler.path
- uri = property(get_uri)
-
- def get_headers_in(self):
- """Getter to mimic request.headers_in."""
- return self._request_handler.headers
- headers_in = property(get_headers_in)
-
- def is_https(self):
- """Mimic request.is_https()."""
- return self._use_tls
-
-
-class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
- """HTTPServer specialized for Web Socket."""
-
- SocketServer.ThreadingMixIn.daemon_threads = True
-
- def __init__(self, server_address, RequestHandlerClass):
- """Override SocketServer.BaseServer.__init__."""
-
- SocketServer.BaseServer.__init__(
- self, server_address, RequestHandlerClass)
- self.socket = self._create_socket()
- self.server_bind()
- self.server_activate()
-
- def _create_socket(self):
- socket_ = socket.socket(self.address_family, self.socket_type)
- if WebSocketServer.options.use_tls:
- ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
- ctx.use_privatekey_file(WebSocketServer.options.private_key)
- ctx.use_certificate_file(WebSocketServer.options.certificate)
- socket_ = OpenSSL.SSL.Connection(ctx, socket_)
- return socket_
-
- def handle_error(self, rquest, client_address):
- """Override SocketServer.handle_error."""
-
- logging.error(
- ('Exception in processing request from: %r' % (client_address,)) +
- '\n' + util.get_stack_trace())
- # Note: client_address is a tuple. To match it against %r, we need the
- # trailing comma.
-
-
-class WebSocketRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
- """CGIHTTPRequestHandler specialized for Web Socket."""
-
- def setup(self):
- """Override SocketServer.StreamRequestHandler.setup."""
-
- self.connection = self.request
- self.rfile = memorizingfile.MemorizingFile(
- socket._fileobject(self.request, 'rb', self.rbufsize),
- max_memorized_lines=_MAX_MEMORIZED_LINES)
- self.wfile = socket._fileobject(self.request, 'wb', self.wbufsize)
-
- def __init__(self, *args, **keywords):
- self._request = _StandaloneRequest(
- self, WebSocketRequestHandler.options.use_tls)
- self._dispatcher = WebSocketRequestHandler.options.dispatcher
- self._print_warnings_if_any()
- self._handshaker = handshake.Handshaker(
- self._request, self._dispatcher,
- WebSocketRequestHandler.options.strict)
- CGIHTTPServer.CGIHTTPRequestHandler.__init__(
- self, *args, **keywords)
-
- def _print_warnings_if_any(self):
- warnings = self._dispatcher.source_warnings()
- if warnings:
- for warning in warnings:
- logging.warning('mod_pywebsocket: %s' % warning)
-
- def parse_request(self):
- """Override BaseHTTPServer.BaseHTTPRequestHandler.parse_request.
-
- Return True to continue processing for HTTP(S), False otherwise.
- """
- result = CGIHTTPServer.CGIHTTPRequestHandler.parse_request(self)
- if result:
- try:
- self._handshaker.do_handshake()
- self._dispatcher.transfer_data(self._request)
- return False
- except handshake.HandshakeError, e:
- # Handshake for ws(s) failed. Assume http(s).
- logging.info('mod_pywebsocket: %s' % e)
- return True
- except dispatch.DispatchError, e:
- logging.warning('mod_pywebsocket: %s' % e)
- return False
- except Exception, e:
- logging.warning('mod_pywebsocket: %s' % e)
- logging.info('mod_pywebsocket: %s' % util.get_stack_trace())
- return False
- return result
-
- def log_request(self, code='-', size='-'):
- """Override BaseHTTPServer.log_request."""
-
- logging.info('"%s" %s %s',
- self.requestline, str(code), str(size))
-
- def log_error(self, *args):
- """Override BaseHTTPServer.log_error."""
-
- # Despite the name, this method is for warnings than for errors.
- # For example, HTTP status code is logged by this method.
- logging.warn('%s - %s' % (self.address_string(), (args[0] % args[1:])))
-
- def is_cgi(self):
- """Test whether self.path corresponds to a CGI script.
-
- Add extra check that self.path doesn't contains ..
- Also check if the file is a executable file or not.
- If the file is not executable, it is handled as static file or dir
- rather than a CGI script.
- """
- if CGIHTTPServer.CGIHTTPRequestHandler.is_cgi(self):
- if '..' in self.path:
- return False
- # strip query parameter from request path
- resource_name = self.path.split('?', 2)[0]
- # convert resource_name into real path name in filesystem.
- scriptfile = self.translate_path(resource_name)
- if not os.path.isfile(scriptfile):
- return False
- if not self.is_executable(scriptfile):
- return False
- return True
- return False
-
-
-def _configure_logging(options):
- logger = logging.getLogger()
- logger.setLevel(_LOG_LEVELS[options.log_level])
- if options.log_file:
- handler = logging.handlers.RotatingFileHandler(
- options.log_file, 'a', options.log_max, options.log_count)
- else:
- handler = logging.StreamHandler()
- formatter = logging.Formatter(
- "[%(asctime)s] [%(levelname)s] %(name)s: %(message)s")
- handler.setFormatter(formatter)
- logger.addHandler(handler)
-
-def _alias_handlers(dispatcher, websock_handlers_map_file):
- """Set aliases specified in websock_handler_map_file in dispatcher.
-
- Args:
- dispatcher: dispatch.Dispatcher instance
- websock_handler_map_file: alias map file
- """
- fp = open(websock_handlers_map_file)
- try:
- for line in fp:
- if line[0] == '#' or line.isspace():
- continue
- m = re.match('(\S+)\s+(\S+)', line)
- if not m:
- logging.warning('Wrong format in map file:' + line)
- continue
- try:
- dispatcher.add_resource_path_alias(
- m.group(1), m.group(2))
- except dispatch.DispatchError, e:
- logging.error(str(e))
- finally:
- fp.close()
-
-
-
-def _main():
- parser = optparse.OptionParser()
- parser.add_option('-H', '--server-host', '--server_host',
- dest='server_host',
- default='',
- help='server hostname to listen to')
- parser.add_option('-p', '--port', dest='port', type='int',
- default=handshake._DEFAULT_WEB_SOCKET_PORT,
- help='port to listen to')
- parser.add_option('-w', '--websock-handlers', '--websock_handlers',
- dest='websock_handlers',
- default='.',
- help='Web Socket handlers root directory.')
- parser.add_option('-m', '--websock-handlers-map-file',
- '--websock_handlers_map_file',
- dest='websock_handlers_map_file',
- default=None,
- help=('Web Socket handlers map file. '
- 'Each line consists of alias_resource_path and '
- 'existing_resource_path, separated by spaces.'))
- parser.add_option('-s', '--scan-dir', '--scan_dir', dest='scan_dir',
- default=None,
- help=('Web Socket handlers scan directory. '
- 'Must be a directory under websock_handlers.'))
- parser.add_option('-d', '--document-root', '--document_root',
- dest='document_root', default='.',
- help='Document root directory.')
- parser.add_option('-x', '--cgi-paths', '--cgi_paths', dest='cgi_paths',
- default=None,
- help=('CGI paths relative to document_root.'
- 'Comma-separated. (e.g -x /cgi,/htbin) '
- 'Files under document_root/cgi_path are handled '
- 'as CGI programs. Must be executable.'))
- parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
- default=False, help='use TLS (wss://)')
- parser.add_option('-k', '--private-key', '--private_key',
- dest='private_key',
- default='', help='TLS private key file.')
- parser.add_option('-c', '--certificate', dest='certificate',
- default='', help='TLS certificate file.')
- parser.add_option('-l', '--log-file', '--log_file', dest='log_file',
- default='', help='Log file.')
- parser.add_option('--log-level', '--log_level', type='choice',
- dest='log_level', default='warn',
- choices=['debug', 'info', 'warn', 'error', 'critical'],
- help='Log level.')
- parser.add_option('--log-max', '--log_max', dest='log_max', type='int',
- default=_DEFAULT_LOG_MAX_BYTES,
- help='Log maximum bytes')
- parser.add_option('--log-count', '--log_count', dest='log_count',
- type='int', default=_DEFAULT_LOG_BACKUP_COUNT,
- help='Log backup count')
- parser.add_option('--strict', dest='strict', action='store_true',
- default=False, help='Strictly check handshake request')
- parser.add_option('-q', '--queue', dest='request_queue_size', type='int',
- default=_DEFAULT_REQUEST_QUEUE_SIZE,
- help='request queue size')
- options = parser.parse_args()[0]
-
- os.chdir(options.document_root)
-
- _configure_logging(options)
-
- SocketServer.TCPServer.request_queue_size = options.request_queue_size
- CGIHTTPServer.CGIHTTPRequestHandler.cgi_directories = []
-
- if options.cgi_paths:
- CGIHTTPServer.CGIHTTPRequestHandler.cgi_directories = \
- options.cgi_paths.split(',')
- if sys.platform in ('cygwin', 'win32'):
- cygwin_path = None
- # For Win32 Python, it is expected that CYGWIN_PATH
- # is set to a directory of cygwin binaries.
- # For example, websocket_server.py in Chromium sets CYGWIN_PATH to
- # full path of third_party/cygwin/bin.
- if 'CYGWIN_PATH' in os.environ:
- cygwin_path = os.environ['CYGWIN_PATH']
- util.wrap_popen3_for_win(cygwin_path)
- def __check_script(scriptpath):
- return util.get_script_interp(scriptpath, cygwin_path)
- CGIHTTPServer.executable = __check_script
-
- if options.use_tls:
- if not _HAS_OPEN_SSL:
- logging.critical('To use TLS, install pyOpenSSL.')
- sys.exit(1)
- if not options.private_key or not options.certificate:
- logging.critical(
- 'To use TLS, specify private_key and certificate.')
- sys.exit(1)
-
- if not options.scan_dir:
- options.scan_dir = options.websock_handlers
-
- try:
- # Share a Dispatcher among request handlers to save time for
- # instantiation. Dispatcher can be shared because it is thread-safe.
- options.dispatcher = dispatch.Dispatcher(options.websock_handlers,
- options.scan_dir)
- if options.websock_handlers_map_file:
- _alias_handlers(options.dispatcher,
- options.websock_handlers_map_file)
- _print_warnings_if_any(options.dispatcher)
-
- WebSocketRequestHandler.options = options
- WebSocketServer.options = options
-
- server = WebSocketServer((options.server_host, options.port),
- WebSocketRequestHandler)
- server.serve_forever()
- except Exception, e:
- logging.critical(str(e))
- sys.exit(1)
-
-
-if __name__ == '__main__':
- _main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/util.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/util.py
deleted file mode 100644
index 8ec9dca..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/util.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Web Sockets utilities.
-"""
-
-
-import StringIO
-import os
-import re
-import traceback
-
-
-def get_stack_trace():
- """Get the current stack trace as string.
-
- This is needed to support Python 2.3.
- TODO: Remove this when we only support Python 2.4 and above.
- Use traceback.format_exc instead.
- """
-
- out = StringIO.StringIO()
- traceback.print_exc(file=out)
- return out.getvalue()
-
-
-def prepend_message_to_exception(message, exc):
- """Prepend message to the exception."""
-
- exc.args = (message + str(exc),)
- return
-
-
-def __translate_interp(interp, cygwin_path):
- """Translate interp program path for Win32 python to run cygwin program
- (e.g. perl). Note that it doesn't support path that contains space,
- which is typically true for Unix, where #!-script is written.
- For Win32 python, cygwin_path is a directory of cygwin binaries.
-
- Args:
- interp: interp command line
- cygwin_path: directory name of cygwin binary, or None
- Returns:
- translated interp command line.
- """
- if not cygwin_path:
- return interp
- m = re.match("^[^ ]*/([^ ]+)( .*)?", interp)
- if m:
- cmd = os.path.join(cygwin_path, m.group(1))
- return cmd + m.group(2)
- return interp
-
-
-def get_script_interp(script_path, cygwin_path=None):
- """Gets #!-interpreter command line from the script.
-
- It also fixes command path. When Cygwin Python is used, e.g. in WebKit,
- it could run "/usr/bin/perl -wT hello.pl".
- When Win32 Python is used, e.g. in Chromium, it couldn't. So, fix
- "/usr/bin/perl" to "<cygwin_path>\perl.exe".
-
- Args:
- script_path: pathname of the script
- cygwin_path: directory name of cygwin binary, or None
- Returns:
- #!-interpreter command line, or None if it is not #!-script.
- """
- fp = open(script_path)
- line = fp.readline()
- fp.close()
- m = re.match("^#!(.*)", line)
- if m:
- return __translate_interp(m.group(1), cygwin_path)
- return None
-
-def wrap_popen3_for_win(cygwin_path):
- """Wrap popen3 to support #!-script on Windows.
-
- Args:
- cygwin_path: path for cygwin binary if command path is needed to be
- translated. None if no translation required.
- """
- __orig_popen3 = os.popen3
- def __wrap_popen3(cmd, mode='t', bufsize=-1):
- cmdline = cmd.split(' ')
- interp = get_script_interp(cmdline[0], cygwin_path)
- if interp:
- cmd = interp + " " + cmd
- return __orig_popen3(cmd, mode, bufsize)
- os.popen3 = __wrap_popen3
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/setup.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/setup.py
deleted file mode 100644
index a34a83b..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/setup.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Set up script for mod_pywebsocket.
-"""
-
-
-from distutils.core import setup
-import sys
-
-
-_PACKAGE_NAME = 'mod_pywebsocket'
-
-if sys.version < '2.3':
- print >>sys.stderr, '%s requires Python 2.3 or later.' % _PACKAGE_NAME
- sys.exit(1)
-
-setup(author='Yuzo Fujishima',
- author_email='yuzo@chromium.org',
- description='Web Socket extension for Apache HTTP Server.',
- long_description=(
- 'mod_pywebsocket is an Apache HTTP Server extension for '
- 'Web Socket (http://tools.ietf.org/html/'
- 'draft-hixie-thewebsocketprotocol). '
- 'See mod_pywebsocket/__init__.py for more detail.'),
- license='See COPYING',
- name=_PACKAGE_NAME,
- packages=[_PACKAGE_NAME],
- url='http://code.google.com/p/pywebsocket/',
- version='0.4.9.2',
- )
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/config.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/config.py
deleted file mode 100644
index 5aaab8c..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/config.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Configuration for testing.
-
-Test files should import this module before mod_pywebsocket.
-"""
-
-
-import os
-import sys
-
-
-# Add the parent directory to sys.path to enable importing mod_pywebsocket.
-sys.path += [os.path.join(os.path.split(__file__)[0], '..')]
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/mock.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/mock.py
deleted file mode 100644
index 3b85d64..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/mock.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Mocks for testing.
-"""
-
-
-import Queue
-import threading
-
-
-class _MockConnBase(object):
- """Base class of mocks for mod_python.apache.mp_conn.
-
- This enables tests to check what is written to a (mock) mp_conn.
- """
-
- def __init__(self):
- self._write_data = []
-
- def write(self, data):
- """Override mod_python.apache.mp_conn.write."""
-
- self._write_data.append(data)
-
- def written_data(self):
- """Get bytes written to this mock."""
-
- return ''.join(self._write_data)
-
-
-class MockConn(_MockConnBase):
- """Mock for mod_python.apache.mp_conn.
-
- This enables tests to specify what should be read from a (mock) mp_conn as
- well as to check what is written to it.
- """
-
- def __init__(self, read_data):
- """Constructs an instance.
-
- Args:
- read_data: bytes that should be returned when read* methods are
- called.
- """
-
- _MockConnBase.__init__(self)
- self._read_data = read_data
- self._read_pos = 0
-
- def readline(self):
- """Override mod_python.apache.mp_conn.readline."""
-
- if self._read_pos >= len(self._read_data):
- return ''
- end_index = self._read_data.find('\n', self._read_pos) + 1
- if not end_index:
- end_index = len(self._read_data)
- return self._read_up_to(end_index)
-
- def read(self, length):
- """Override mod_python.apache.mp_conn.read."""
-
- if self._read_pos >= len(self._read_data):
- return ''
- end_index = min(len(self._read_data), self._read_pos + length)
- return self._read_up_to(end_index)
-
- def _read_up_to(self, end_index):
- line = self._read_data[self._read_pos:end_index]
- self._read_pos = end_index
- return line
-
-
-class MockBlockingConn(_MockConnBase):
- """Blocking mock for mod_python.apache.mp_conn.
-
- This enables tests to specify what should be read from a (mock) mp_conn as
- well as to check what is written to it.
- Callers of read* methods will block if there is no bytes available.
- """
-
- def __init__(self):
- _MockConnBase.__init__(self)
- self._queue = Queue.Queue()
-
- def readline(self):
- """Override mod_python.apache.mp_conn.readline."""
- line = ''
- while True:
- c = self._queue.get()
- line += c
- if c == '\n':
- return line
-
- def read(self, length):
- """Override mod_python.apache.mp_conn.read."""
-
- data = ''
- for unused in range(length):
- data += self._queue.get()
- return data
-
- def put_bytes(self, bytes):
- """Put bytes to be read from this mock.
-
- Args:
- bytes: bytes to be read.
- """
-
- for byte in bytes:
- self._queue.put(byte)
-
-
-class MockTable(dict):
- """Mock table.
-
- This mimics mod_python mp_table. Note that only the methods used by
- tests are overridden.
- """
-
- def __init__(self, copy_from={}):
- if isinstance(copy_from, dict):
- copy_from = copy_from.items()
- for key, value in copy_from:
- self.__setitem__(key, value)
-
- def __getitem__(self, key):
- return super(MockTable, self).__getitem__(key.lower())
-
- def __setitem__(self, key, value):
- super(MockTable, self).__setitem__(key.lower(), value)
-
- def get(self, key, def_value=None):
- return super(MockTable, self).get(key.lower(), def_value)
-
-
-class MockRequest(object):
- """Mock request.
-
- This mimics mod_python request.
- """
-
- def __init__(self, uri=None, headers_in={}, connection=None,
- is_https=False):
- """Construct an instance.
-
- Arguments:
- uri: URI of the request.
- headers_in: Request headers.
- connection: Connection used for the request.
- is_https: Whether this request is over SSL.
-
- See the document of mod_python Request for details.
- """
- self.uri = uri
- self.connection = connection
- self.headers_in = MockTable(headers_in)
- # self.is_https_ needs to be accessible from tests. To avoid name
- # conflict with self.is_https(), it is named as such.
- self.is_https_ = is_https
-
- def is_https(self):
- """Return whether this request is over SSL."""
- return self.is_https_
-
-
-class MockDispatcher(object):
- """Mock for dispatch.Dispatcher."""
-
- def do_extra_handshake(self, conn_context):
- pass
-
- def transfer_data(self, conn_context):
- pass
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_dispatch.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_dispatch.py
deleted file mode 100644
index 5403228..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_dispatch.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Tests for dispatch module."""
-
-
-
-import os
-import unittest
-
-import config # This must be imported before mod_pywebsocket.
-from mod_pywebsocket import dispatch
-
-import mock
-
-
-_TEST_HANDLERS_DIR = os.path.join(
- os.path.split(__file__)[0], 'testdata', 'handlers')
-
-_TEST_HANDLERS_SUB_DIR = os.path.join(_TEST_HANDLERS_DIR, 'sub')
-
-class DispatcherTest(unittest.TestCase):
- def test_normalize_path(self):
- self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
- dispatch._normalize_path('/a/b'))
- self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
- dispatch._normalize_path('\\a\\b'))
- self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
- dispatch._normalize_path('/a/c/../b'))
- self.assertEqual(os.path.abspath('abc').replace('\\', '/'),
- dispatch._normalize_path('abc'))
-
- def test_converter(self):
- converter = dispatch._path_to_resource_converter('/a/b')
- self.assertEqual('/h', converter('/a/b/h_wsh.py'))
- self.assertEqual('/c/h', converter('/a/b/c/h_wsh.py'))
- self.assertEqual(None, converter('/a/b/h.py'))
- self.assertEqual(None, converter('a/b/h_wsh.py'))
-
- converter = dispatch._path_to_resource_converter('a/b')
- self.assertEqual('/h', converter('a/b/h_wsh.py'))
-
- converter = dispatch._path_to_resource_converter('/a/b///')
- self.assertEqual('/h', converter('/a/b/h_wsh.py'))
- self.assertEqual('/h', converter('/a/b/../b/h_wsh.py'))
-
- converter = dispatch._path_to_resource_converter('/a/../a/b/../b/')
- self.assertEqual('/h', converter('/a/b/h_wsh.py'))
-
- converter = dispatch._path_to_resource_converter(r'\a\b')
- self.assertEqual('/h', converter(r'\a\b\h_wsh.py'))
- self.assertEqual('/h', converter(r'/a/b/h_wsh.py'))
-
- def test_source_file_paths(self):
- paths = list(dispatch._source_file_paths(_TEST_HANDLERS_DIR))
- paths.sort()
- self.assertEqual(7, len(paths))
- expected_paths = [
- os.path.join(_TEST_HANDLERS_DIR, 'blank_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'origin_check_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'exception_in_transfer_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'sub', 'non_callable_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'sub', 'plain_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'wrong_handshake_sig_wsh.py'),
- os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'wrong_transfer_sig_wsh.py'),
- ]
- for expected, actual in zip(expected_paths, paths):
- self.assertEqual(expected, actual)
-
- def test_source(self):
- self.assertRaises(dispatch.DispatchError, dispatch._source, '')
- self.assertRaises(dispatch.DispatchError, dispatch._source, 'def')
- self.assertRaises(dispatch.DispatchError, dispatch._source, '1/0')
- self.failUnless(dispatch._source(
- 'def web_socket_do_extra_handshake(request):pass\n'
- 'def web_socket_transfer_data(request):pass\n'))
-
- def test_source_warnings(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- warnings = dispatcher.source_warnings()
- warnings.sort()
- expected_warnings = [
- (os.path.join(_TEST_HANDLERS_DIR, 'blank_wsh.py') +
- ': web_socket_do_extra_handshake is not defined.'),
- (os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'non_callable_wsh.py') +
- ': web_socket_do_extra_handshake is not callable.'),
- (os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'wrong_handshake_sig_wsh.py') +
- ': web_socket_do_extra_handshake is not defined.'),
- (os.path.join(_TEST_HANDLERS_DIR, 'sub',
- 'wrong_transfer_sig_wsh.py') +
- ': web_socket_transfer_data is not defined.'),
- ]
- self.assertEquals(4, len(warnings))
- for expected, actual in zip(expected_warnings, warnings):
- self.assertEquals(expected, actual)
-
- def test_do_extra_handshake(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- request = mock.MockRequest()
- request.ws_resource = '/origin_check'
- request.ws_origin = 'http://example.com'
- dispatcher.do_extra_handshake(request) # Must not raise exception.
-
- request.ws_origin = 'http://bad.example.com'
- self.assertRaises(Exception, dispatcher.do_extra_handshake, request)
-
- def test_transfer_data(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = '/origin_check'
- request.ws_protocol = 'p1'
-
- dispatcher.transfer_data(request)
- self.assertEqual('origin_check_wsh.py is called for /origin_check, p1',
- request.connection.written_data())
-
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = '/sub/plain'
- request.ws_protocol = None
- dispatcher.transfer_data(request)
- self.assertEqual('sub/plain_wsh.py is called for /sub/plain, None',
- request.connection.written_data())
-
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = '/sub/plain?'
- request.ws_protocol = None
- dispatcher.transfer_data(request)
- self.assertEqual('sub/plain_wsh.py is called for /sub/plain?, None',
- request.connection.written_data())
-
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = '/sub/plain?q=v'
- request.ws_protocol = None
- dispatcher.transfer_data(request)
- self.assertEqual('sub/plain_wsh.py is called for /sub/plain?q=v, None',
- request.connection.written_data())
-
- def test_transfer_data_no_handler(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- for resource in ['/blank', '/sub/non_callable',
- '/sub/no_wsh_at_the_end', '/does/not/exist']:
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = resource
- request.ws_protocol = 'p2'
- try:
- dispatcher.transfer_data(request)
- self.fail()
- except dispatch.DispatchError, e:
- self.failUnless(str(e).find('No handler') != -1)
- except Exception:
- self.fail()
-
- def test_transfer_data_handler_exception(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- request = mock.MockRequest(connection=mock.MockConn(''))
- request.ws_resource = '/sub/exception_in_transfer'
- request.ws_protocol = 'p3'
- try:
- dispatcher.transfer_data(request)
- self.fail()
- except Exception, e:
- self.failUnless(str(e).find('Intentional') != -1)
-
- def test_scan_dir(self):
- disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- self.assertEqual(3, len(disp._handlers))
- self.failUnless(disp._handlers.has_key('/origin_check'))
- self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
- self.failUnless(disp._handlers.has_key('/sub/plain'))
-
- def test_scan_sub_dir(self):
- disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, _TEST_HANDLERS_SUB_DIR)
- self.assertEqual(2, len(disp._handlers))
- self.failIf(disp._handlers.has_key('/origin_check'))
- self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
- self.failUnless(disp._handlers.has_key('/sub/plain'))
-
- def test_scan_sub_dir_as_root(self):
- disp = dispatch.Dispatcher(_TEST_HANDLERS_SUB_DIR,
- _TEST_HANDLERS_SUB_DIR)
- self.assertEqual(2, len(disp._handlers))
- self.failIf(disp._handlers.has_key('/origin_check'))
- self.failIf(disp._handlers.has_key('/sub/exception_in_transfer'))
- self.failIf(disp._handlers.has_key('/sub/plain'))
- self.failUnless(disp._handlers.has_key('/exception_in_transfer'))
- self.failUnless(disp._handlers.has_key('/plain'))
-
- def test_scan_dir_must_under_root(self):
- dispatch.Dispatcher('a/b', 'a/b/c') # OK
- dispatch.Dispatcher('a/b///', 'a/b') # OK
- self.assertRaises(dispatch.DispatchError,
- dispatch.Dispatcher, 'a/b/c', 'a/b')
-
- def test_resource_path_alias(self):
- disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
- disp.add_resource_path_alias('/', '/origin_check')
- self.assertEqual(4, len(disp._handlers))
- self.failUnless(disp._handlers.has_key('/origin_check'))
- self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
- self.failUnless(disp._handlers.has_key('/sub/plain'))
- self.failUnless(disp._handlers.has_key('/'))
- self.assertRaises(dispatch.DispatchError,
- disp.add_resource_path_alias, '/alias', '/not-exist')
-
-
-if __name__ == '__main__':
- unittest.main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_handshake.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_handshake.py
deleted file mode 100644
index 8bf07be..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_handshake.py
+++ /dev/null
@@ -1,513 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Tests for handshake module."""
-
-
-import unittest
-
-import config # This must be imported before mod_pywebsocket.
-from mod_pywebsocket import handshake
-
-import mock
-
-
-_GOOD_REQUEST = (
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
-)
-
-_GOOD_RESPONSE_DEFAULT_PORT = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
- 'Upgrade: WebSocket\r\n'
- 'Connection: Upgrade\r\n'
- 'WebSocket-Origin: http://example.com\r\n'
- 'WebSocket-Location: ws://example.com/demo\r\n'
- 'WebSocket-Protocol: sample\r\n'
- '\r\n')
-
-_GOOD_RESPONSE_SECURE = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
- 'Upgrade: WebSocket\r\n'
- 'Connection: Upgrade\r\n'
- 'WebSocket-Origin: http://example.com\r\n'
- 'WebSocket-Location: wss://example.com/demo\r\n'
- 'WebSocket-Protocol: sample\r\n'
- '\r\n')
-
-_GOOD_REQUEST_NONDEFAULT_PORT = (
- 8081,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com:8081',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
-)
-
-_GOOD_RESPONSE_NONDEFAULT_PORT = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
- 'Upgrade: WebSocket\r\n'
- 'Connection: Upgrade\r\n'
- 'WebSocket-Origin: http://example.com\r\n'
- 'WebSocket-Location: ws://example.com:8081/demo\r\n'
- 'WebSocket-Protocol: sample\r\n'
- '\r\n')
-
-_GOOD_RESPONSE_SECURE_NONDEF = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
- 'Upgrade: WebSocket\r\n'
- 'Connection: Upgrade\r\n'
- 'WebSocket-Origin: http://example.com\r\n'
- 'WebSocket-Location: wss://example.com:8081/demo\r\n'
- 'WebSocket-Protocol: sample\r\n'
- '\r\n')
-
-_GOOD_REQUEST_NO_PROTOCOL = (
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- }
-)
-
-_GOOD_RESPONSE_NO_PROTOCOL = (
- 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
- 'Upgrade: WebSocket\r\n'
- 'Connection: Upgrade\r\n'
- 'WebSocket-Origin: http://example.com\r\n'
- 'WebSocket-Location: ws://example.com/demo\r\n'
- '\r\n')
-
-_GOOD_REQUEST_WITH_OPTIONAL_HEADERS = (
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- 'AKey':'AValue',
- 'EmptyValue':'',
- }
-)
-
-_BAD_REQUESTS = (
- ( # HTTP request
- 80,
- '/demo',
- {
- 'Host':'www.google.com',
- 'User-Agent':'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5;'
- ' en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'
- ' GTB6 GTBA',
- 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,'
- '*/*;q=0.8',
- 'Accept-Language':'en-us,en;q=0.5',
- 'Accept-Encoding':'gzip,deflate',
- 'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
- 'Keep-Alive':'300',
- 'Connection':'keep-alive',
- }
- ),
- ( # Missing Upgrade
- 80,
- '/demo',
- {
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
- ),
- ( # Wrong Upgrade
- 80,
- '/demo',
- {
- 'Upgrade':'NonWebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
- ),
- ( # Empty WebSocket-Protocol
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'',
- }
- ),
- ( # Wrong port number format
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com:0x50',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
- ),
- ( # Header/connection port mismatch
- 8080,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'sample',
- }
- ),
- ( # Illegal WebSocket-Protocol
- 80,
- '/demo',
- {
- 'Upgrade':'WebSocket',
- 'Connection':'Upgrade',
- 'Host':'example.com',
- 'Origin':'http://example.com',
- 'WebSocket-Protocol':'illegal\x09protocol',
- }
- ),
-)
-
-_STRICTLY_GOOD_REQUESTS = (
- (
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # WebSocket-Protocol
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'WebSocket-Protocol: sample\r\n',
- '\r\n',
- ),
- ( # WebSocket-Protocol and Cookie
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'WebSocket-Protocol: sample\r\n',
- 'Cookie: xyz\r\n'
- '\r\n',
- ),
- ( # Cookie
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'Cookie: abc/xyz\r\n'
- 'Cookie2: $Version=1\r\n'
- 'Cookie: abc\r\n'
- '\r\n',
- ),
- (
- 'GET / HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
-)
-
-_NOT_STRICTLY_GOOD_REQUESTS = (
- ( # Extra space after GET
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # Resource name doesn't stat with '/'
- 'GET demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # No space after :
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade:WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # Lower case Upgrade header
- 'GET /demo HTTP/1.1\r\n',
- 'upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # Connection comes before Upgrade
- 'GET /demo HTTP/1.1\r\n',
- 'Connection: Upgrade\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # Origin comes before Host
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Origin: http://example.com\r\n',
- 'Host: example.com\r\n',
- '\r\n',
- ),
- ( # Host continued to the next line
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example\r\n',
- ' .com\r\n',
- 'Origin: http://example.com\r\n',
- '\r\n',
- ),
- ( # Cookie comes before WebSocket-Protocol
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'Cookie: xyz\r\n'
- 'WebSocket-Protocol: sample\r\n',
- '\r\n',
- ),
- ( # Unknown header
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'Content-Type: text/html\r\n'
- '\r\n',
- ),
- ( # Cookie with continuation lines
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'Cookie: xyz\r\n',
- ' abc\r\n',
- ' defg\r\n',
- '\r\n',
- ),
- ( # Wrong-case cookie
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'cookie: abc/xyz\r\n'
- '\r\n',
- ),
- ( # Cookie, no space after colon
- 'GET /demo HTTP/1.1\r\n',
- 'Upgrade: WebSocket\r\n',
- 'Connection: Upgrade\r\n',
- 'Host: example.com\r\n',
- 'Origin: http://example.com\r\n',
- 'Cookie:abc/xyz\r\n'
- '\r\n',
- ),
-)
-
-
-def _create_request(request_def):
- conn = mock.MockConn('')
- conn.local_addr = ('0.0.0.0', request_def[0])
- return mock.MockRequest(
- uri=request_def[1],
- headers_in=request_def[2],
- connection=conn)
-
-
-def _create_get_memorized_lines(lines):
- def get_memorized_lines():
- return lines
- return get_memorized_lines
-
-
-def _create_requests_with_lines(request_lines_set):
- requests = []
- for lines in request_lines_set:
- request = _create_request(_GOOD_REQUEST)
- request.connection.get_memorized_lines = _create_get_memorized_lines(
- lines)
- requests.append(request)
- return requests
-
-
-class HandshakerTest(unittest.TestCase):
- def test_validate_protocol(self):
- handshake._validate_protocol('sample') # should succeed.
- handshake._validate_protocol('Sample') # should succeed.
- handshake._validate_protocol('sample\x20protocol') # should succeed.
- handshake._validate_protocol('sample\x7eprotocol') # should succeed.
- self.assertRaises(handshake.HandshakeError,
- handshake._validate_protocol,
- '')
- self.assertRaises(handshake.HandshakeError,
- handshake._validate_protocol,
- 'sample\x19protocol')
- self.assertRaises(handshake.HandshakeError,
- handshake._validate_protocol,
- 'sample\x7fprotocol')
- self.assertRaises(handshake.HandshakeError,
- handshake._validate_protocol,
- # "Japan" in Japanese
- u'\u65e5\u672c')
-
- def test_good_request_default_port(self):
- request = _create_request(_GOOD_REQUEST)
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual(_GOOD_RESPONSE_DEFAULT_PORT,
- request.connection.written_data())
- self.assertEqual('/demo', request.ws_resource)
- self.assertEqual('http://example.com', request.ws_origin)
- self.assertEqual('ws://example.com/demo', request.ws_location)
- self.assertEqual('sample', request.ws_protocol)
-
- def test_good_request_secure_default_port(self):
- request = _create_request(_GOOD_REQUEST)
- request.connection.local_addr = ('0.0.0.0', 443)
- request.is_https_ = True
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual(_GOOD_RESPONSE_SECURE,
- request.connection.written_data())
- self.assertEqual('sample', request.ws_protocol)
-
- def test_good_request_nondefault_port(self):
- request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual(_GOOD_RESPONSE_NONDEFAULT_PORT,
- request.connection.written_data())
- self.assertEqual('sample', request.ws_protocol)
-
- def test_good_request_secure_non_default_port(self):
- request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
- request.is_https_ = True
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual(_GOOD_RESPONSE_SECURE_NONDEF,
- request.connection.written_data())
- self.assertEqual('sample', request.ws_protocol)
-
- def test_good_request_default_no_protocol(self):
- request = _create_request(_GOOD_REQUEST_NO_PROTOCOL)
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual(_GOOD_RESPONSE_NO_PROTOCOL,
- request.connection.written_data())
- self.assertEqual(None, request.ws_protocol)
-
- def test_good_request_optional_headers(self):
- request = _create_request(_GOOD_REQUEST_WITH_OPTIONAL_HEADERS)
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- handshaker.do_handshake()
- self.assertEqual('AValue',
- request.headers_in['AKey'])
- self.assertEqual('',
- request.headers_in['EmptyValue'])
-
- def test_bad_requests(self):
- for request in map(_create_request, _BAD_REQUESTS):
- handshaker = handshake.Handshaker(request,
- mock.MockDispatcher())
- self.assertRaises(handshake.HandshakeError, handshaker.do_handshake)
-
- def test_strictly_good_requests(self):
- for request in _create_requests_with_lines(_STRICTLY_GOOD_REQUESTS):
- strict_handshaker = handshake.Handshaker(request,
- mock.MockDispatcher(),
- True)
- strict_handshaker.do_handshake()
-
- def test_not_strictly_good_requests(self):
- for request in _create_requests_with_lines(_NOT_STRICTLY_GOOD_REQUESTS):
- strict_handshaker = handshake.Handshaker(request,
- mock.MockDispatcher(),
- True)
- self.assertRaises(handshake.HandshakeError,
- strict_handshaker.do_handshake)
-
-
-
-if __name__ == '__main__':
- unittest.main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_mock.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_mock.py
deleted file mode 100644
index 8b137d1..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_mock.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Tests for mock module."""
-
-
-import Queue
-import threading
-import unittest
-
-import mock
-
-
-class MockConnTest(unittest.TestCase):
- def setUp(self):
- self._conn = mock.MockConn('ABC\r\nDEFG\r\n\r\nHIJK')
-
- def test_readline(self):
- self.assertEqual('ABC\r\n', self._conn.readline())
- self.assertEqual('DEFG\r\n', self._conn.readline())
- self.assertEqual('\r\n', self._conn.readline())
- self.assertEqual('HIJK', self._conn.readline())
- self.assertEqual('', self._conn.readline())
-
- def test_read(self):
- self.assertEqual('ABC\r\nD', self._conn.read(6))
- self.assertEqual('EFG\r\n\r\nHI', self._conn.read(9))
- self.assertEqual('JK', self._conn.read(10))
- self.assertEqual('', self._conn.read(10))
-
- def test_read_and_readline(self):
- self.assertEqual('ABC\r\nD', self._conn.read(6))
- self.assertEqual('EFG\r\n', self._conn.readline())
- self.assertEqual('\r\nHIJK', self._conn.read(9))
- self.assertEqual('', self._conn.readline())
-
- def test_write(self):
- self._conn.write('Hello\r\n')
- self._conn.write('World\r\n')
- self.assertEqual('Hello\r\nWorld\r\n', self._conn.written_data())
-
-
-class MockBlockingConnTest(unittest.TestCase):
- def test_read(self):
- class LineReader(threading.Thread):
- def __init__(self, conn, queue):
- threading.Thread.__init__(self)
- self._queue = queue
- self._conn = conn
- self.setDaemon(True)
- self.start()
- def run(self):
- while True:
- data = self._conn.readline()
- self._queue.put(data)
- conn = mock.MockBlockingConn()
- queue = Queue.Queue()
- reader = LineReader(conn, queue)
- self.failUnless(queue.empty())
- conn.put_bytes('Foo bar\r\n')
- read = queue.get()
- self.assertEqual('Foo bar\r\n', read)
-
-
-class MockTableTest(unittest.TestCase):
- def test_create_from_dict(self):
- table = mock.MockTable({'Key':'Value'})
- self.assertEqual('Value', table.get('KEY'))
- self.assertEqual('Value', table['key'])
-
- def test_create_from_list(self):
- table = mock.MockTable([('Key', 'Value')])
- self.assertEqual('Value', table.get('KEY'))
- self.assertEqual('Value', table['key'])
-
- def test_create_from_tuple(self):
- table = mock.MockTable((('Key', 'Value'),))
- self.assertEqual('Value', table.get('KEY'))
- self.assertEqual('Value', table['key'])
-
- def test_set_and_get(self):
- table = mock.MockTable()
- self.assertEqual(None, table.get('Key'))
- table['Key'] = 'Value'
- self.assertEqual('Value', table.get('Key'))
- self.assertEqual('Value', table.get('key'))
- self.assertEqual('Value', table.get('KEY'))
- self.assertEqual('Value', table['Key'])
- self.assertEqual('Value', table['key'])
- self.assertEqual('Value', table['KEY'])
-
-
-if __name__ == '__main__':
- unittest.main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_msgutil.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_msgutil.py
deleted file mode 100644
index 16b88e0..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_msgutil.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Tests for msgutil module."""
-
-
-import Queue
-import unittest
-
-import config # This must be imported before mod_pywebsocket.
-from mod_pywebsocket import msgutil
-
-import mock
-
-
-def _create_request(read_data):
- return mock.MockRequest(connection=mock.MockConn(read_data))
-
-def _create_blocking_request():
- return mock.MockRequest(connection=mock.MockBlockingConn())
-
-class MessageTest(unittest.TestCase):
- def test_send_message(self):
- request = _create_request('')
- msgutil.send_message(request, 'Hello')
- self.assertEqual('\x00Hello\xff', request.connection.written_data())
-
- def test_send_message_unicode(self):
- request = _create_request('')
- msgutil.send_message(request, u'\u65e5')
- # U+65e5 is encoded as e6,97,a5 in UTF-8
- self.assertEqual('\x00\xe6\x97\xa5\xff',
- request.connection.written_data())
-
- def test_receive_message(self):
- request = _create_request('\x00Hello\xff\x00World!\xff')
- self.assertEqual('Hello', msgutil.receive_message(request))
- self.assertEqual('World!', msgutil.receive_message(request))
-
- def test_receive_message_unicode(self):
- request = _create_request('\x00\xe6\x9c\xac\xff')
- # U+672c is encoded as e6,9c,ac in UTF-8
- self.assertEqual(u'\u672c', msgutil.receive_message(request))
-
- def test_receive_message_erroneous_unicode(self):
- # \x80 and \x81 are invalid as UTF-8.
- request = _create_request('\x00\x80\x81\xff')
- # Invalid characters should be replaced with
- # U+fffd REPLACEMENT CHARACTER
- self.assertEqual(u'\ufffd\ufffd', msgutil.receive_message(request))
-
- def test_receive_message_discard(self):
- request = _create_request('\x80\x06IGNORE\x00Hello\xff'
- '\x01DISREGARD\xff\x00World!\xff')
- self.assertEqual('Hello', msgutil.receive_message(request))
- self.assertEqual('World!', msgutil.receive_message(request))
-
- def test_payload_length(self):
- for length, bytes in ((0, '\x00'), (0x7f, '\x7f'), (0x80, '\x81\x00'),
- (0x1234, '\x80\xa4\x34')):
- self.assertEqual(length,
- msgutil._payload_length(_create_request(bytes)))
-
- def test_receive_bytes(self):
- request = _create_request('abcdefg')
- self.assertEqual('abc', msgutil._receive_bytes(request, 3))
- self.assertEqual('defg', msgutil._receive_bytes(request, 4))
-
- def test_read_until(self):
- request = _create_request('abcXdefgX')
- self.assertEqual('abc', msgutil._read_until(request, 'X'))
- self.assertEqual('defg', msgutil._read_until(request, 'X'))
-
-
-class MessageReceiverTest(unittest.TestCase):
- def test_queue(self):
- request = _create_blocking_request()
- receiver = msgutil.MessageReceiver(request)
-
- self.assertEqual(None, receiver.receive_nowait())
-
- request.connection.put_bytes('\x00Hello!\xff')
- self.assertEqual('Hello!', receiver.receive())
-
- def test_onmessage(self):
- onmessage_queue = Queue.Queue()
- def onmessage_handler(message):
- onmessage_queue.put(message)
-
- request = _create_blocking_request()
- receiver = msgutil.MessageReceiver(request, onmessage_handler)
-
- request.connection.put_bytes('\x00Hello!\xff')
- self.assertEqual('Hello!', onmessage_queue.get())
-
-
-class MessageSenderTest(unittest.TestCase):
- def test_send(self):
- request = _create_blocking_request()
- sender = msgutil.MessageSender(request)
-
- sender.send('World')
- self.assertEqual('\x00World\xff', request.connection.written_data())
-
- def test_send_nowait(self):
- # Use a queue to check the bytes written by MessageSender.
- # request.connection.written_data() cannot be used here because
- # MessageSender runs in a separate thread.
- send_queue = Queue.Queue()
- def write(bytes):
- send_queue.put(bytes)
- request = _create_blocking_request()
- request.connection.write = write
-
- sender = msgutil.MessageSender(request)
-
- sender.send_nowait('Hello')
- sender.send_nowait('World')
- self.assertEqual('\x00Hello\xff', send_queue.get())
- self.assertEqual('\x00World\xff', send_queue.get())
-
-
-if __name__ == '__main__':
- unittest.main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_util.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_util.py
deleted file mode 100644
index 61f0db5..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/test_util.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Tests for util module."""
-
-
-import os
-import sys
-import unittest
-
-import config # This must be imported before mod_pywebsocket.
-from mod_pywebsocket import util
-
-_TEST_DATA_DIR = os.path.join(os.path.split(__file__)[0], 'testdata')
-
-class UtilTest(unittest.TestCase):
- def test_get_stack_trace(self):
- self.assertEqual('None\n', util.get_stack_trace())
- try:
- a = 1 / 0 # Intentionally raise exception.
- except Exception:
- trace = util.get_stack_trace()
- self.failUnless(trace.startswith('Traceback'))
- self.failUnless(trace.find('ZeroDivisionError') != -1)
-
- def test_prepend_message_to_exception(self):
- exc = Exception('World')
- self.assertEqual('World', str(exc))
- util.prepend_message_to_exception('Hello ', exc)
- self.assertEqual('Hello World', str(exc))
-
- def test_get_script_interp(self):
- cygwin_path = 'c:\\cygwin\\bin'
- cygwin_perl = os.path.join(cygwin_path, 'perl')
- self.assertEqual(None, util.get_script_interp(
- os.path.join(_TEST_DATA_DIR, 'README')))
- self.assertEqual(None, util.get_script_interp(
- os.path.join(_TEST_DATA_DIR, 'README'), cygwin_path))
- self.assertEqual('/usr/bin/perl -wT', util.get_script_interp(
- os.path.join(_TEST_DATA_DIR, 'hello.pl')))
- self.assertEqual(cygwin_perl + ' -wT', util.get_script_interp(
- os.path.join(_TEST_DATA_DIR, 'hello.pl'), cygwin_path))
-
-
-if __name__ == '__main__':
- unittest.main()
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/README b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/README
deleted file mode 100644
index c001aa5..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/README
+++ /dev/null
@@ -1 +0,0 @@
-Test data directory
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/blank_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/blank_wsh.py
deleted file mode 100644
index 7f87c6a..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/blank_wsh.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-# intentionally left blank
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/origin_check_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/origin_check_wsh.py
deleted file mode 100644
index 2c139fa..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/origin_check_wsh.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-def web_socket_do_extra_handshake(request):
- if request.ws_origin == 'http://example.com':
- return
- raise ValueError('Unacceptable origin: %r' % request.ws_origin)
-
-
-def web_socket_transfer_data(request):
- request.connection.write('origin_check_wsh.py is called for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py
deleted file mode 100644
index b982d02..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Exception in web_socket_transfer_data().
-"""
-
-
-def web_socket_do_extra_handshake(request):
- pass
-
-
-def web_socket_transfer_data(request):
- raise Exception('Intentional Exception for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py
deleted file mode 100644
index 17e7be1..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Correct signatures, wrong file name.
-"""
-
-
-def web_socket_do_extra_handshake(request):
- pass
-
-
-def web_socket_transfer_data(request):
- request.connection.write(
- 'sub/no_wsh_at_the_end.py is called for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/plain_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/plain_wsh.py
deleted file mode 100644
index db3ff69..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/plain_wsh.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-def web_socket_do_extra_handshake(request):
- pass
-
-
-def web_socket_transfer_data(request):
- request.connection.write('sub/plain_wsh.py is called for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
deleted file mode 100644
index 6bf659b..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Wrong web_socket_do_extra_handshake signature.
-"""
-
-
-def no_web_socket_do_extra_handshake(request):
- pass
-
-
-def web_socket_transfer_data(request):
- request.connection.write(
- 'sub/wrong_handshake_sig_wsh.py is called for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
deleted file mode 100644
index e0e2e55..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-"""Wrong web_socket_transfer_data() signature.
-"""
-
-
-def web_socket_do_extra_handshake(request):
- pass
-
-
-def no_web_socket_transfer_data(request):
- request.connection.write(
- 'sub/wrong_transfer_sig_wsh.py is called for %s, %s' %
- (request.ws_resource, request.ws_protocol))
-
-
-# vi:sts=4 sw=4 et
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/hello.pl b/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/hello.pl
deleted file mode 100644
index 9dd01b4..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/hello.pl
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/perl -wT
-print "Hello\n";
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py
index 2c45ab6..ac7a760 100644
--- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py
+++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py
@@ -77,8 +77,8 @@ class QueueEngine:
self._output_tee = OutputTee()
log_date_format = "%Y-%m-%d %H:%M:%S"
- sleep_duration_text = "5 mins"
- seconds_to_sleep = 300
+ sleep_duration_text = "2 mins" # This could be generated from seconds_to_sleep
+ seconds_to_sleep = 120
handled_error_code = 2
# Child processes exit with a special code to the parent queue process can detect the error was handled.
@@ -142,8 +142,12 @@ class QueueEngine:
self._output_tee.remove_log(self._work_log)
self._work_log = None
+ def _now(self):
+ """Overriden by the unit tests to allow testing _sleep_message"""
+ return datetime.now()
+
def _sleep_message(self, message):
- wake_time = datetime.now() + timedelta(seconds=self.seconds_to_sleep)
+ wake_time = self._now() + timedelta(seconds=self.seconds_to_sleep)
return "%s Sleeping until %s (%s)." % (message, wake_time.strftime(self.log_date_format), self.sleep_duration_text)
def _sleep(self, message):
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py
index 626181d..ec91bdb 100644
--- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py
@@ -26,6 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import datetime
import os
import shutil
import tempfile
@@ -160,6 +161,17 @@ class QueueEngineTest(unittest.TestCase):
expected_callbacks.append('should_continue_work_queue')
self.assertEquals(delegate._callbacks, expected_callbacks)
+ def test_now(self):
+ """Make sure there are no typos in the QueueEngine.now() method."""
+ engine = QueueEngine("test", None, None)
+ self.assertTrue(isinstance(engine._now(), datetime.datetime))
+
+ def test_sleep_message(self):
+ engine = QueueEngine("test", None, None)
+ engine._now = lambda: datetime.datetime(2010, 1, 1)
+ expected_sleep_message = "MESSAGE Sleeping until 2010-01-01 00:02:00 (2 mins)."
+ self.assertEqual(engine._sleep_message("MESSAGE"), expected_sleep_message)
+
def setUp(self):
self.temp_dir = tempfile.mkdtemp(suffix="work_queue_test_logs")
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py
index dd048a1..c375ff9 100644
--- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py
@@ -33,7 +33,7 @@ from webkitpy.common.net.buildbot import Builder
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.bot.sheriff import Sheriff
-from webkitpy.tool.mocktool import MockTool, mock_builder
+from webkitpy.tool.mocktool import MockTool
class MockSheriffBot(object):
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download.py b/WebKitTools/Scripts/webkitpy/tool/commands/download.py
index c66b95c..a283da9 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/download.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/download.py
@@ -260,8 +260,9 @@ class AbstractRolloutPrepCommand(AbstractSequencedCommand):
# of create-rollout for bug URLs. It should do better
# parsing instead.
log("Preparing rollout for bug %s." % commit_info.bug_id())
- return commit_info
- log("Unable to parse bug number from diff.")
+ else:
+ log("Unable to parse bug number from diff.")
+ return commit_info
def _prepare_state(self, options, args, tool):
revision = args[0]
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py
index 926037c..4dd9d7f 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py
@@ -26,9 +26,32 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import unittest
+
+from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.commands.commandtest import CommandsTest
from webkitpy.tool.commands.download import *
+from webkitpy.tool.mocktool import MockTool
+
+
+class AbstractRolloutPrepCommandTest(unittest.TestCase):
+ def test_commit_info(self):
+ command = AbstractRolloutPrepCommand()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+ output = OutputCapture()
+
+ expected_stderr = "Preparing rollout for bug 42.\n"
+ commit_info = output.assert_outputs(self, command._commit_info, [1234], expected_stderr=expected_stderr)
+ self.assertTrue(commit_info)
+
+ mock_commit_info = Mock()
+ mock_commit_info.bug_id = lambda: None
+ tool._checkout.commit_info_for_revision = lambda revision: mock_commit_info
+ expected_stderr = "Unable to parse bug number from diff.\n"
+ commit_info = output.assert_outputs(self, command._commit_info, [1234], expected_stderr=expected_stderr)
+ self.assertEqual(commit_info, mock_commit_info)
class DownloadCommandsTest(CommandsTest):
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
index 4d23a4c..3d0ddd1 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
@@ -39,37 +39,37 @@ class EarlyWarningSytemTest(QueuesTest):
ews._can_build = lambda: True
ews.review_patch(Mock())
- def test_chromium_linux_ews(self):
+ def _default_expected_stderr(self, ews):
+ string_replacemnts = {
+ "name": ews.name,
+ "checkout_dir": os.getcwd(), # FIXME: Use of os.getcwd() is wrong, should be scm.checkout_root
+ }
expected_stderr = {
- "begin_work_queue": "CAUTION: chromium-ews will discard all local changes in \"%s\"\nRunning WebKit chromium-ews.\n" % os.getcwd(),
+ "begin_work_queue": "CAUTION: %(name)s will discard all local changes in \"%(checkout_dir)s\"\nRunning WebKit %(name)s.\n" % string_replacemnts,
"handle_unexpected_error": "Mock error message\n",
+ "process_work_item": "MOCK: update_status: %(name)s Pass\n" % string_replacemnts,
}
- self.assert_queue_outputs(ChromiumLinuxEWS(), expected_stderr=expected_stderr)
+ return expected_stderr
+
+ def _test_ews(self, ews):
+ self.assert_queue_outputs(ews, expected_stderr=self._default_expected_stderr(ews))
+
+ # FIXME: If all EWSes are going to output the same text, we
+ # could test them all in one method with a for loop over an array.
+ def test_chromium_linux_ews(self):
+ self._test_ews(ChromiumLinuxEWS())
def test_chromium_windows_ews(self):
- expected_stderr = {
- "begin_work_queue": "CAUTION: cr-win-ews will discard all local changes in \"%s\"\nRunning WebKit cr-win-ews.\n" % os.getcwd(),
- "handle_unexpected_error": "Mock error message\n",
- }
- self.assert_queue_outputs(ChromiumWindowsEWS(), expected_stderr=expected_stderr)
+ self._test_ews(ChromiumWindowsEWS())
def test_qt_ews(self):
- expected_stderr = {
- "begin_work_queue": "CAUTION: qt-ews will discard all local changes in \"%s\"\nRunning WebKit qt-ews.\n" % os.getcwd(),
- "handle_unexpected_error": "Mock error message\n",
- }
- self.assert_queue_outputs(QtEWS(), expected_stderr=expected_stderr)
+ self._test_ews(QtEWS())
def test_gtk_ews(self):
- expected_stderr = {
- "begin_work_queue": "CAUTION: gtk-ews will discard all local changes in \"%s\"\nRunning WebKit gtk-ews.\n" % os.getcwd(),
- "handle_unexpected_error": "Mock error message\n",
- }
- self.assert_queue_outputs(GtkEWS(), expected_stderr=expected_stderr)
+ self._test_ews(GtkEWS())
def test_mac_ews(self):
- expected_stderr = {
- "begin_work_queue": "CAUTION: mac-ews will discard all local changes in \"%s\"\nRunning WebKit mac-ews.\n" % os.getcwd(),
- "handle_unexpected_error": "Mock error message\n",
- }
- self.assert_queue_outputs(MacEWS(), expected_stderr=expected_stderr)
+ ews = MacEWS()
+ expected_stderr = self._default_expected_stderr(ews)
+ expected_stderr["process_work_item"] = "MOCK: update_status: mac-ews Error: mac-ews cannot process patches from non-committers :(\n"
+ self.assert_queue_outputs(ews, expected_stderr=expected_stderr)
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
index 775aa44..78ca729 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
@@ -46,7 +46,6 @@ from webkitpy.tool.multicommandtool import Command
class AbstractQueue(Command, QueueEngineDelegate):
watchers = [
- "webkit-bot-watchers@googlegroups.com",
]
_pass_status = "Pass"
@@ -168,16 +167,17 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler):
# Not using BugzillaQueries.fetch_patches_from_commit_queue() so we can reject patches with invalid committers/reviewers.
bug_ids = self.tool.bugs.queries.fetch_bug_ids_from_commit_queue()
all_patches = sum([self.tool.bugs.fetch_bug(bug_id).commit_queued_patches(include_invalid=True) for bug_id in bug_ids], [])
- valid_patches = self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches)
- if not self._builders_are_green():
- return filter(lambda patch: patch.is_rollout(), valid_patches)
- return valid_patches
+ return self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches)
def next_work_item(self):
patches = self._validate_patches_in_commit_queue()
+ builders_are_green = self._builders_are_green()
+ if not builders_are_green:
+ patches = filter(lambda patch: patch.is_rollout(), patches)
# FIXME: We could sort the patches in a specific order here, was suggested by https://bugs.webkit.org/show_bug.cgi?id=33395
if not patches:
- self._update_status("Empty queue")
+ queue_text = "queue" if builders_are_green else "rollout queue"
+ self._update_status("Empty %s" % queue_text)
return None
# Only bother logging if we have patches in the queue.
self.log_progress([patch.id() for patch in patches])
@@ -211,7 +211,8 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler):
if not patch.is_rollout():
if not self._builders_are_green():
return False
- self._update_status("Landing patch", patch)
+ patch_text = "rollout patch" if patch.is_rollout() else "patch"
+ self._update_status("Landing %s" % patch_text, patch)
return True
def _land(self, patch, first_run=False):
@@ -226,7 +227,6 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler):
"land-attachment",
"--force-clean",
"--build",
- "--test",
"--non-interactive",
# The master process is responsible for checking the status
# of the builders (see above call to _builders_are_green).
@@ -235,6 +235,9 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler):
"--quiet",
patch.id()
]
+ # We don't bother to run tests for rollouts as that makes them too slow.
+ if not patch.is_rollout():
+ args.append("--test")
if not first_run:
# The first time through, we don't reject the patch from the
# commit queue because we want to make sure we can build and
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py
index 16eb053..0bd42fb 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py
@@ -118,11 +118,13 @@ class CommitQueueTest(QueuesTest):
def test_commit_queue(self):
expected_stderr = {
"begin_work_queue" : "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root,
+ "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing patch\n",
# FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time.
"next_work_item" : """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
2 patches in commit-queue [197, 106]
""",
+ "process_work_item" : "MOCK: update_status: commit-queue Pass\n",
}
self.assert_queue_outputs(CommitQueue(), expected_stderr=expected_stderr)
@@ -131,11 +133,14 @@ Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.c
tool.buildbot.light_tree_on_fire()
expected_stderr = {
"begin_work_queue" : "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root,
+ "should_proceed_with_work_item": "MOCK: update_status: commit-queue Builders [\"Builder2\"] are red. See http://build.webkit.org\n",
# FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time.
"next_work_item" : """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
+MOCK: update_status: commit-queue Builders ["Builder2"] are red. See http://build.webkit.org
1 patch in commit-queue [106]
""",
+ "process_work_item" : "MOCK: update_status: commit-queue Builders [\"Builder2\"] are red. See http://build.webkit.org\n",
}
self.assert_queue_outputs(CommitQueue(), tool=tool, expected_stderr=expected_stderr)
@@ -145,20 +150,33 @@ Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.c
rollout_patch = MockPatch()
expected_stderr = {
"begin_work_queue": "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root,
+ "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing rollout patch\n",
# FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time.
"next_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
+MOCK: update_status: commit-queue Builders ["Builder2"] are red. See http://build.webkit.org
1 patch in commit-queue [106]
""",
- "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--test', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', 76543]\n",
+ "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', 76543]\nMOCK: update_status: commit-queue Pass\n",
}
self.assert_queue_outputs(CommitQueue(), tool=tool, work_item=rollout_patch, expected_stderr=expected_stderr)
+ def test_can_build_and_test(self):
+ queue = CommitQueue()
+ tool = MockTool()
+ tool.executive = Mock()
+ queue.bind_to_tool(tool)
+ self.assertTrue(queue._can_build_and_test())
+ expected_run_args = ["echo", "--status-host=example.com", "build-and-test", "--force-clean", "--build", "--test", "--non-interactive", "--no-update", "--build-style=both", "--quiet"]
+ tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args)
+
class StyleQueueTest(QueuesTest):
def test_style_queue(self):
expected_stderr = {
"begin_work_queue" : "CAUTION: style-queue will discard all local changes in \"%s\"\nRunning WebKit style-queue.\n" % MockSCM.fake_checkout_root,
+ "should_proceed_with_work_item": "MOCK: update_status: style-queue Checking style\n",
+ "process_work_item" : "MOCK: update_status: style-queue Pass\n",
"handle_unexpected_error" : "Mock error message\n",
}
self.assert_queue_outputs(StyleQueue(), expected_stderr=expected_stderr)
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py
index eb80d8f..24c8517 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py
@@ -57,17 +57,46 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler):
def work_item_log_path(self, new_failures):
return os.path.join("%s-logs" % self.name, "%s.log" % new_failures.keys()[0])
- def next_work_item(self):
- self._irc_bot.process_pending_messages()
- self._update()
+ def _new_failures(self, revisions_causing_failures, old_failing_svn_revisions):
+ # We ignore failures that might have been caused by svn_revisions that
+ # we've already complained about. This is conservative in the sense
+ # that we might be ignoring some new failures, but our experience has
+ # been that skipping this check causes a lot of spam for builders that
+ # take a long time to cycle.
+ old_failing_builder_names = []
+ for svn_revision in old_failing_svn_revisions:
+ old_failing_builder_names.extend(
+ [builder.name() for builder in revisions_causing_failures[svn_revision]])
+
new_failures = {}
- revisions_causing_failures = self.tool.buildbot.revisions_causing_failures()
for svn_revision, builders in revisions_causing_failures.items():
- if self.tool.status_server.svn_revision(svn_revision):
+ if svn_revision in old_failing_svn_revisions:
# FIXME: We should re-process the work item after some time delay.
# https://bugs.webkit.org/show_bug.cgi?id=36581
continue
- new_failures[svn_revision] = builders
+ new_builders = [builder for builder in builders
+ if builder.name() not in old_failing_builder_names]
+ if new_builders:
+ new_failures[svn_revision] = new_builders
+
+ return new_failures
+
+ def next_work_item(self):
+ self._irc_bot.process_pending_messages()
+ self._update()
+
+ # We do one read from buildbot to ensure a consistent view.
+ revisions_causing_failures = self.tool.buildbot.revisions_causing_failures()
+
+ # Similarly, we read once from our the status_server.
+ old_failing_svn_revisions = []
+ for svn_revision in revisions_causing_failures.keys():
+ if self.tool.status_server.svn_revision(svn_revision):
+ old_failing_svn_revisions.append(svn_revision)
+
+ new_failures = self._new_failures(revisions_causing_failures,
+ old_failing_svn_revisions)
+
self._sheriff.provoke_flaky_builders(revisions_causing_failures)
return new_failures
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py
index f121eda..4b4b8b6 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py
@@ -30,18 +30,44 @@ import os
from webkitpy.tool.commands.queuestest import QueuesTest
from webkitpy.tool.commands.sheriffbot import SheriffBot
-from webkitpy.tool.mocktool import mock_builder
+from webkitpy.tool.mocktool import MockBuilder
class SheriffBotTest(QueuesTest):
+ builder1 = MockBuilder("Builder1")
+ builder2 = MockBuilder("Builder2")
+
def test_sheriff_bot(self):
mock_work_item = {
- 29837: [mock_builder],
+ 29837: [self.builder1],
}
expected_stderr = {
"begin_work_queue": "CAUTION: sheriff-bot will discard all local changes in \"%s\"\nRunning WebKit sheriff-bot.\n" % os.getcwd(),
"next_work_item": "",
- "process_work_item": "MOCK: irc.post: abarth, darin, eseidel: http://trac.webkit.org/changeset/29837 might have broken Mock builder name (Tests)\nMOCK bug comment: bug_id=42, cc=['webkit-bot-watchers@googlegroups.com', 'abarth@webkit.org', 'eric@webkit.org']\n--- Begin comment ---\\http://trac.webkit.org/changeset/29837 might have broken Mock builder name (Tests)\n--- End comment ---\n\n",
+ "process_work_item": "MOCK: irc.post: abarth, darin, eseidel: http://trac.webkit.org/changeset/29837 might have broken Builder1\nMOCK bug comment: bug_id=42, cc=['abarth@webkit.org', 'eric@webkit.org']\n--- Begin comment ---\\http://trac.webkit.org/changeset/29837 might have broken Builder1\n--- End comment ---\n\n",
"handle_unexpected_error": "Mock error message\n"
}
self.assert_queue_outputs(SheriffBot(), work_item=mock_work_item, expected_stderr=expected_stderr)
+
+ revisions_causing_failures = {
+ 1234: [builder1],
+ 1235: [builder1, builder2],
+ }
+
+ def test_new_failures(self):
+ old_failing_svn_revisions = []
+ self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures,
+ old_failing_svn_revisions),
+ self.revisions_causing_failures)
+
+ def test_new_failures_with_old_revisions(self):
+ old_failing_svn_revisions = [1234]
+ self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures,
+ old_failing_svn_revisions),
+ {1235: [builder2]})
+
+ def test_new_failures_with_old_revisions(self):
+ old_failing_svn_revisions = [1235]
+ self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures,
+ old_failing_svn_revisions),
+ {})
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py
index 99d45a6..4797ef6 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py
@@ -46,14 +46,23 @@ from webkitpy.tool.comments import bug_comment_from_svn_revision
from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand
from webkitpy.common.system.deprecated_logging import error, log
+
class CommitMessageForCurrentDiff(AbstractDeclarativeCommand):
name = "commit-message"
help_text = "Print a commit message suitable for the uncommitted changes"
+ def __init__(self):
+ options = [
+ steps.Options.squash,
+ steps.Options.git_commit,
+ ]
+ AbstractDeclarativeCommand.__init__(self, options=options)
+
def execute(self, options, args, tool):
# This command is a useful test to make sure commit_message_for_this_commit
# always returns the right value regardless of the current working directory.
- print "%s" % tool.checkout().commit_message_for_this_commit().message()
+ print "%s" % tool.checkout().commit_message_for_this_commit(options.git_commit, options.squash).message()
+
class CleanPendingCommit(AbstractDeclarativeCommand):
name = "clean-pending-commit"
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py
index eec3751..8f6483a 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py
@@ -34,10 +34,7 @@ from webkitpy.tool.mocktool import MockTool
class UploadCommandsTest(CommandsTest):
def test_commit_message_for_current_diff(self):
tool = MockTool()
- mock_commit_message_for_this_commit = Mock()
- mock_commit_message_for_this_commit.message = lambda: "Mock message"
- tool._checkout.commit_message_for_this_commit = lambda: mock_commit_message_for_this_commit
- expected_stdout = "Mock message\n"
+ expected_stdout = "This is a fake commit message that is at least 50 characters.\n"
self.assert_execute_outputs(CommitMessageForCurrentDiff(), [], expected_stdout=expected_stdout, tool=tool)
def test_clean_pending_commit(self):
diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool.py b/WebKitTools/Scripts/webkitpy/tool/mocktool.py
index 128362a..47fff1b 100644
--- a/WebKitTools/Scripts/webkitpy/tool/mocktool.py
+++ b/WebKitTools/Scripts/webkitpy/tool/mocktool.py
@@ -184,15 +184,6 @@ _bug4 = {
}
-class MockBuilder(object):
-
- def name(self):
- return "Mock builder name (Tests)"
-
-
-mock_builder = MockBuilder()
-
-
class MockBugzillaQueries(Mock):
def __init__(self, bugzilla):
@@ -319,6 +310,9 @@ class MockBuilder(object):
def __init__(self, name):
self._name = name
+ def name(self):
+ return self._name
+
def force_build(self, username, comments):
log("MOCK: force_build: name=%s, username=%s, comments=%s" % (
self._name, username, comments))
@@ -369,7 +363,7 @@ class MockBuildBot(object):
def revisions_causing_failures(self):
return {
- "29837": [mock_builder]
+ "29837": [self.builder_with_name("Builder1")],
}
@@ -484,6 +478,7 @@ class MockStatusServer(object):
return None
def update_status(self, queue_name, status, patch=None, results_file=None):
+ log("MOCK: update_status: %s %s" % (queue_name, status))
return 187
def update_svn_revision(self, svn_revision, broken_bot):
@@ -491,7 +486,12 @@ class MockStatusServer(object):
class MockExecute(Mock):
+ def __init__(self, should_log):
+ self._should_log = should_log
+
def run_and_throw_if_fail(self, args, quiet=False):
+ if self._should_log:
+ log("MOCK run_and_throw_if_fail: %s" % args)
return "MOCK output of child process"
def run_command(self,
@@ -502,6 +502,8 @@ class MockExecute(Mock):
return_exit_code=False,
return_stderr=True,
decode_output=False):
+ if self._should_log:
+ log("MOCK run_command: %s" % args)
return "MOCK output of child process"
@@ -511,9 +513,7 @@ class MockTool():
self.wakeup_event = threading.Event()
self.bugs = MockBugzilla()
self.buildbot = MockBuildBot()
- self.executive = MockExecute()
- if log_executive:
- self.executive.run_and_throw_if_fail = lambda args: log("MOCK run_and_throw_if_fail: %s" % args)
+ self.executive = MockExecute(should_log=log_executive)
self._irc = None
self.user = MockUser()
self._scm = MockSCM()
diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py
index 7b2be99..93e6215 100644
--- a/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py
@@ -48,16 +48,17 @@ class CheckStyle(AbstractStep):
if not self._options.check_style:
return
os.chdir(self._tool.scm().checkout_root)
- try:
- args = []
- if self._options.git_commit:
- args.append("--git-commit")
- args.append(self._options.git_commit)
- if self._tool.scm().should_squash(self._options.squash):
- args.append("--squash")
- else:
- args.append("--no-squash")
+ args = []
+ if self._options.git_commit:
+ args.append("--git-commit")
+ args.append(self._options.git_commit)
+ if self._tool.scm().should_squash(self._options.squash):
+ args.append("--squash")
+ else:
+ args.append("--no-squash")
+
+ try:
self._run_script("check-webkit-style", args)
except ScriptError, e:
if self._options.non_interactive:
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/run_all.py b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle_unittest.py
index 3885618..a23ea1b 100644
--- a/WebKitTools/Scripts/webkitpy/thirdparty/pywebsocket/test/run_all.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle_unittest.py
@@ -1,19 +1,16 @@
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
+# Copyright (C) 2009 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
-# * Redistributions of source code must retain the above copyright
+# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
+# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
-# * Neither the name of Google Inc. nor the names of its
+# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
@@ -29,36 +26,21 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Run all tests in the same directory.
-"""
-
-
-import os
-import re
import unittest
+from webkitpy.common.system.executive import ScriptError
+from webkitpy.thirdparty.mock import Mock
+from webkitpy.tool.mocktool import MockTool
+from webkitpy.tool.steps.checkstyle import CheckStyle
-_TEST_MODULE_PATTERN = re.compile(r'^(test_.+)\.py$')
-
-
-def _list_test_modules(directory):
- module_names = []
- for filename in os.listdir(directory):
- match = _TEST_MODULE_PATTERN.search(filename)
- if match:
- module_names.append(match.group(1))
- return module_names
-
-
-def _suite():
- loader = unittest.TestLoader()
- return loader.loadTestsFromNames(
- _list_test_modules(os.path.join(os.path.split(__file__)[0], '.')))
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='_suite')
+class CheckStyleTest(unittest.TestCase):
+ def test_should_squash_error(self):
+ """should_squash can throw an error. That error should not be eaten by CheckStyle."""
+ def should_squash(squash):
+ raise ScriptError(message="Dummy error")
-# vi:sts=4 sw=4 et
+ tool = MockTool()
+ tool._scm.should_squash = should_squash
+ step = CheckStyle(tool, Mock())
+ self.assertRaises(ScriptError, step.run, [])
diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py b/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py
index 198cfce..8397519 100644
--- a/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py
@@ -42,33 +42,32 @@ class PostCodeReview(AbstractStep):
def run(self, state):
if not self._options.fancy_review:
return
- # FIXME: This will always be None because we don't retrieve the issue
- # number from the ChangeLog yet.
- codereview_issue = state.get("codereview_issue")
+
+ bug_id = state.get("bug_id")
+ if not bug_id:
+ raise ScriptError(message="Cannot upload a fancy review without a bug ID.")
+
message = self._options.description
if not message:
# If we have an issue number, then the message becomes the label
# of the new patch. Otherwise, it becomes the title of the whole
# issue.
- if codereview_issue:
- message = "Updated patch"
- elif state.get("bug_title"):
+ if state.get("bug_title"):
# This is the common case for the the first "upload" command.
message = state.get("bug_title")
- elif state.get("bug_id"):
+ elif bug_id:
# This is the common case for the "post" command and
- # subsequent runs of the "upload" command. In this case,
- # I'd rather add the new patch to the existing issue, but
- # that's not implemented yet.
- message = "Code review for %s" % self._tool.bugs.bug_url_for_bug_id(state["bug_id"])
+ # subsequent runs of the "upload" command.
+ message = "Code review for %s" % self._tool.bugs.bug_url_for_bug_id(bug_id)
else:
# Unreachable with our current commands, but we might hit
# this case if we support bug-less code reviews.
message = "Code review"
+
+ # Use the bug ID as the rietveld issue number. This means rietveld code reviews
+ # when there are multiple different patches on a bug will be a bit wonky, but
+ # webkit-patch assumes one-patch-per-bug.
created_issue = self._tool.codereview.post(diff=self.cached_lookup(state, "diff"),
message=message,
- codereview_issue=codereview_issue,
+ codereview_issue=bug_id,
cc=self._options.cc)
- if created_issue:
- # FIXME: Record the issue number in the ChangeLog.
- state["codereview_issue"] = created_issue
diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py b/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py
index a542dba..79739cd 100644
--- a/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py
@@ -44,11 +44,6 @@ class PostDiff(AbstractStep):
diff = self.cached_lookup(state, "diff")
description = self._options.description or "Patch"
comment_text = None
- codereview_issue = state.get("codereview_issue")
- # Include codereview issue number in patch name. This is a bit of a hack,
- # but it makes doing the rietveld integration a lot easier.
- if codereview_issue:
- description += "-%s" % state["codereview_issue"]
self._tool.bugs.add_patch_to_bug(state["bug_id"], diff, description, comment_text=comment_text, mark_for_review=self._options.review, mark_for_commit_queue=self._options.request_commit)
if self._options.open_bug:
self._tool.user.open_url(self._tool.bugs.bug_url_for_bug_id(state["bug_id"]))
diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py
index b1c2d3b..0734d8f 100644
--- a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py
@@ -57,6 +57,11 @@ class RunTests(AbstractStep):
if self._options.non_interactive:
args.append("--no-launch-safari")
args.append("--exit-after-n-failures=1")
+ # FIXME: Hack to work around https://bugs.webkit.org/show_bug.cgi?id=38912
+ # when running the commit-queue on a mac leopard machine.
+ if self.port().name() == "Mac" and self.port().is_leopard():
+ args.extend(["--ignore-tests", "compositing/iframes"])
+
if self._options.quiet:
args.append("--quiet")
self._tool.executive.run_and_throw_if_fail(args)
diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py
index 5abfc6d..eee183b 100644
--- a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py
@@ -29,9 +29,11 @@
import unittest
from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.config.ports import WebKitPort
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.mocktool import MockTool
from webkitpy.tool.steps.update import Update
+from webkitpy.tool.steps.runtests import RunTests
from webkitpy.tool.steps.promptforbugortitle import PromptForBugOrTitle
@@ -55,3 +57,27 @@ class StepsTest(unittest.TestCase):
tool = MockTool()
tool.user.prompt = lambda message: 42
self._run_step(PromptForBugOrTitle, tool=tool)
+
+ def test_runtests_leopard_commit_queue_hack(self):
+ expected_stderr = "Running Python unit tests\nRunning Perl unit tests\nRunning JavaScriptCore tests\nRunning run-webkit-tests\n"
+ OutputCapture().assert_outputs(self, self._run_step, [RunTests], expected_stderr=expected_stderr)
+
+ def test_runtests_leopard_commit_queue_hack(self):
+ mock_options = Mock()
+ mock_options.non_interactive = True
+ step = RunTests(MockTool(log_executive=True), mock_options)
+ # FIXME: We shouldn't use a real port-object here, but there is too much to mock at the moment.
+ mock_port = WebKitPort()
+ mock_port.name = lambda: "Mac"
+ mock_port.is_leopard = lambda: True
+ step.port = lambda: mock_port
+ expected_stderr = """Running Python unit tests
+MOCK run_and_throw_if_fail: ['WebKitTools/Scripts/test-webkitpy']
+Running Perl unit tests
+MOCK run_and_throw_if_fail: ['WebKitTools/Scripts/test-webkitperl']
+Running JavaScriptCore tests
+MOCK run_and_throw_if_fail: ['WebKitTools/Scripts/run-javascriptcore-tests']
+Running run-webkit-tests
+MOCK run_and_throw_if_fail: ['WebKitTools/Scripts/run-webkit-tests', '--no-launch-safari', '--exit-after-n-failures=1', '--ignore-tests', 'compositing/iframes', '--quiet']
+"""
+ OutputCapture().assert_outputs(self, step.run, [{}], expected_stderr=expected_stderr)