summaryrefslogtreecommitdiffstats
path: root/WebKitTools
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:23:55 +0100
committerSteve Block <steveblock@google.com>2010-04-27 17:07:03 +0100
commit692e5dbf12901edacf14812a6fae25462920af42 (patch)
treed62802373a429e0a9dc093b6046c166b2c514285 /WebKitTools
parente24bea4efef1c414137d36a9778aa4e142e10c7d (diff)
downloadexternal_webkit-692e5dbf12901edacf14812a6fae25462920af42.zip
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.gz
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.bz2
Merge webkit.org at r55033 : Initial merge by git
Change-Id: I98a4af828067cc243ec3dc5e5826154dd88074b5
Diffstat (limited to 'WebKitTools')
-rw-r--r--WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json10
-rw-r--r--WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg38
-rw-r--r--WebKitTools/ChangeLog590
-rw-r--r--WebKitTools/DumpRenderTree/LayoutTestController.cpp39
-rw-r--r--WebKitTools/DumpRenderTree/LayoutTestController.h8
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp52
-rw-r--r--WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp8
-rw-r--r--WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp14
-rw-r--r--WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm8
-rw-r--r--WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm69
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp15
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h1
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp20
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.h2
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp33
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h6
-rw-r--r--WebKitTools/DumpRenderTree/qt/main.cpp4
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp10
-rw-r--r--WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp49
-rw-r--r--WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp12
-rw-r--r--WebKitTools/QtLauncher/main.cpp30
-rw-r--r--WebKitTools/QtLauncher/webview.cpp47
-rw-r--r--WebKitTools/QtLauncher/webview.h23
-rwxr-xr-xWebKitTools/Scripts/check-webkit-style15
-rwxr-xr-xWebKitTools/Scripts/rebaseline-chromium-webkit-tests1
-rwxr-xr-xWebKitTools/Scripts/resolve-ChangeLogs32
-rw-r--r--WebKitTools/Scripts/run-gtk-tests35
-rwxr-xr-xWebKitTools/Scripts/test-webkitpy1
-rwxr-xr-xWebKitTools/Scripts/webkit-build-directory20
-rw-r--r--WebKitTools/Scripts/webkitdirs.pm17
-rw-r--r--WebKitTools/Scripts/webkitpy/committers.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/__init__.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py52
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base.py22
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py119
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py66
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/test.py3
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py84
-rw-r--r--WebKitTools/Scripts/webkitpy/style/checker.py631
-rwxr-xr-xWebKitTools/Scripts/webkitpy/style/checker_unittest.py443
-rw-r--r--WebKitTools/Scripts/webkitpy/style/error_handlers.py57
-rw-r--r--WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py155
-rw-r--r--WebKitTools/Scripts/webkitpy/style/filter.py34
-rw-r--r--WebKitTools/Scripts/webkitpy/style/filter_unittest.py14
-rw-r--r--WebKitTools/Scripts/webkitpy/style/optparser.py424
-rw-r--r--WebKitTools/Scripts/webkitpy/style/optparser_unittest.py258
-rw-r--r--WebKitTools/Scripts/webkitpy/style/processors/cpp.py12
-rw-r--r--WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py25
-rw-r--r--WebKitTools/Scripts/webkitpy/style/unittests.py1
54 files changed, 2523 insertions, 1106 deletions
diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json
index 69ff238..3477c97 100644
--- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json
+++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json
@@ -24,6 +24,7 @@
{ "name": "gtk-linux-slave-1", "platform": "gtk"},
{ "name": "gtk-linux-slave-2", "platform": "gtk"},
{ "name": "gtk-linux-slave-3", "platform": "gtk"},
+ { "name": "gtk-linux-slave-4", "platform": "gtk"},
{ "name": "szeged-linux-1", "platform": "qt"},
@@ -92,7 +93,7 @@
"slavenames": ["apple-windows-4", "apple-windows-3", "test-slave"]
},
{
- "name": "GTK Linux Release", "type": "BuildAndTest", "builddir": "gtk-linux-release",
+ "name": "GTK Linux 32-bit Release", "type": "BuildAndTest", "builddir": "gtk-linux-32-release",
"platform": "gtk", "configuration": "release", "architectures": ["i386"],
"slavenames": ["gtk-linux-slave-1"]
},
@@ -107,6 +108,11 @@
"slavenames": ["gtk-linux-slave-3"]
},
{
+ "name": "GTK Linux 64-bit Release", "type": "BuildAndTest", "builddir": "gtk-linux-64-release",
+ "platform": "gtk", "configuration": "release", "architectures": ["x86_64"],
+ "slavenames": ["gtk-linux-slave-4"]
+ },
+ {
"name": "Qt Linux Release", "type": "BuildAndTest", "builddir": "qt-linux-release",
"platform": "qt", "configuration": "release", "architectures": ["i386"],
"slavenames": ["szeged-linux-1"]
@@ -132,7 +138,7 @@
"builderNames": ["Tiger Intel Release", "Leopard Intel Release (Build)", "Leopard Intel Debug (Build)",
"SnowLeopard Intel Release (Build)", "SnowLeopard Intel Leaks",
"Windows Release (Build)", "Windows Debug (Build)",
- "GTK Linux Release", "GTK Linux 32-bit Debug", "GTK Linux 64-bit Debug",
+ "GTK Linux 32-bit Release", "GTK Linux 32-bit Debug", "GTK Linux 64-bit Debug", "GTK Linux 64-bit Release",
"Qt Linux Release",
"Chromium Win Release", "Chromium Mac Release", "Chromium Linux Release"]
},
diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg
index cd81108..1823277 100644
--- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg
+++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg
@@ -230,6 +230,42 @@ class RunWebKitTests(shell.Test):
return [self.name]
+class RunGtkAPITests(shell.Test):
+ name = "API tests"
+ description = ["API tests running"]
+ descriptionDone = ["API tests"]
+ command = ["perl", "./WebKitTools/Scripts/run-gtk-tests", WithProperties("--%(configuration)s")]
+
+ def commandComplete(self, cmd):
+ shell.Test.commandComplete(self, cmd)
+
+ logText = cmd.logs['stdio'].getText()
+ incorrectLines = []
+ for line in logText.splitlines():
+ if line.startswith('ERROR'):
+ incorrectLines.append(line)
+
+ self.incorrectLines = incorrectLines
+
+ def evaluateCommand(self, cmd):
+ if self.incorrectLines:
+ return FAILURE
+
+ if cmd.rc != 0:
+ return FAILURE
+
+ return SUCCESS
+
+ def getText(self, cmd, results):
+ return self.getText2(cmd, results)
+
+ def getText2(self, cmd, results):
+ if results != SUCCESS and self.incorrectLines:
+ return ["%d API tests failed" % self.incorrectLines]
+
+ return [self.name]
+
+
class RunWebKitLeakTests(RunWebKitTests):
def start(self):
self.setCommand(self.command + ["--leaks"])
@@ -312,6 +348,8 @@ class BuildAndTestFactory(Factory):
self.addStep(ArchiveTestResults)
self.addStep(UploadTestResults)
self.addStep(ExtractTestResults)
+ if platform == "gtk":
+ self.addStep(RunGtkAPITests)
class BuildAndTestLeaksFactory(BuildAndTestFactory):
TestClass = RunWebKitLeakTests
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index ab4b32d..6a4b7b3 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,593 @@
+2010-02-19 Jesus Sanchez-Palencia <jesus.palencia@openbossa.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Need a final integration between QtLauncher and QGVLauncher
+ https://bugs.webkit.org/show_bug.cgi?id=35161
+
+ Add animated flip support to QtLauncher when running on QGraphicsView mode.
+
+ * QtLauncher/main.cpp:
+ (LauncherWindow::initializeView):
+ (LauncherWindow::setupUI):
+ * QtLauncher/webview.cpp:
+ (WebViewGraphicsBased::WebViewGraphicsBased):
+ (WebViewGraphicsBased::animatedFlip):
+ (WebViewGraphicsBased::animatedYFlip):
+ * QtLauncher/webview.h:
+ (WebViewGraphicsBased::setYRotation):
+ (WebViewGraphicsBased::yRotation):
+
+2010-02-19 Andras Becsi <abecsi@webkit.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Implement textZoomIn() and textZoomOut() in DRT's EventSender, add results
+ for passing new tests and unskip the passing ones from the Skipped list.
+ https://bugs.webkit.org/show_bug.cgi?id=35159
+
+ * DumpRenderTree/qt/EventSenderQt.cpp:
+ (EventSender::textZoomIn):
+ (EventSender::textZoomOut):
+ * DumpRenderTree/qt/EventSenderQt.h:
+
+2010-02-19 Laszlo Gombos <laszlo.1.gombos@nokia.com>
+
+ Reviewed by Eric Seidel.
+
+ [Qt] Clean-up the handling of HTML5 persistent data for LayoutTests
+ https://bugs.webkit.org/show_bug.cgi?id=35004
+
+ DumpRenderTreeQt.cpp calls QWebSettings::enablePersistentStorage which sets up
+ and enables all HTML5 persistent data. All the other calls for setting the
+ persistent path or enabling the persistent feature are redundant.
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::WebPage::WebPage): No need to enable AppCache again.
+ * DumpRenderTree/qt/main.cpp:
+ (main): No need to setup and enable HTML5 LocalStorage again.
+
+2010-02-19 Diego Gonzalez <diego.gonzalez@openbossa.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Send the context menu event from contextClick() of EventSender
+ and do not show context menu in DRT.
+
+ LayoutTests:
+ fast/events/contextmenu-scrolled-page-with-frame.html
+
+ [Qt] DRT: Send context menu event from EventSender
+ https://bugs.webkit.org/show_bug.cgi?id=35131
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::DumpRenderTree::DumpRenderTree):
+ * DumpRenderTree/qt/EventSenderQt.cpp:
+ (EventSender::contextClick):
+
+2010-02-18 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Shinichiro Hamaji.
+
+ Moved parsing-related code to a separate file. Also increased
+ the unit test coverage in some affected areas.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34675
+
+ This revision contains no new functionality.
+
+ * Scripts/check-webkit-style:
+ - Adjusted to call check_webkit_style_parser().
+
+ * Scripts/webkitpy/style/checker.py:
+ - Added check_webkit_style_parser() to pass checker.py
+ configuration settings to optparser.py.
+ - Moved _create_usage() and the CommandOptionValues,
+ DefaultCommandOptionValues, ArgumentPrinter, and
+ ArgumentParser classes to optparser.py.
+
+ * Scripts/webkitpy/style/checker_unittest.py:
+ - Moved the ProcessorOptionsTest, ArgumentPrinterTest, and
+ ArgumentParserTest classes to optparser.py.
+ - Added the CheckWebKitStyleFunctionTest class to check
+ the check_webkit_style_configuration() and
+ check_webkit_style_parser() code paths.
+
+ * Scripts/webkitpy/style/optparser.py: Added.
+ - From checker.py, added _create_usage() and the
+ CommandOptionValues, DefaultCommandOptionValues,
+ ArgumentPrinter, and ArgumentParser classes.
+ - In the ArgumentParser constructor--
+ - Added all_categories as a required parameter.
+ - Removed the default value from the default_options parameter.
+
+ * Scripts/webkitpy/style/optparser_unittest.py: Added.
+ - From checker_unittest.py, added the ProcessorOptionsTest,
+ ArgumentPrinterTest, and ArgumentParserTest classes.
+ - Added the CreateUsageTest class to test _create_usage().
+
+ * Scripts/webkitpy/style/unittests.py:
+ - Added optparser_unittest import.
+
+2010-02-18 Alexey Proskuryakov <ap@apple.com>
+
+ Reviewed by Dan Bernstein.
+
+ https://bugs.webkit.org/show_bug.cgi?id=35134
+ <rdar://problem/7246280> Crash when a plugin calls NPN_SetStatus(0)
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp:
+ (testSetStatus):
+ (pluginInvoke):
+ Added a setStatus() method.
+
+2010-02-18 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Particularly constructed WebFrames can try to access a null HistoryItem
+ <rdar://problem/7638892> and https://bugs.webkit.org/show_bug.cgi?id=35063
+
+ Add the specific ability to test this API pattern.
+
+ For now only on Mac, perhaps on the main Windows port later, probably not relevant for other ports.
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (apiTestNewWindowDataLoadBaseURLCallback):
+ (LayoutTestController::staticFunctions):
+ * DumpRenderTree/LayoutTestController.h:
+
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (-[APITestDelegate initWithCompletionCondition:]):
+ (-[APITestDelegate webView:didFailLoadWithError:forFrame:]):
+ (-[APITestDelegate webView:didFailProvisionalLoadWithError:forFrame:]):
+ (-[APITestDelegate webView:didFinishLoadForFrame:]):
+ (LayoutTestController::apiTestNewWindowDataLoadBaseURL): Create a WebView, do a loadData: in its
+ mainFrame, and synchronously wait for main load completion.
+
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::apiTestNewWindowDataLoadBaseURL):
+ * DumpRenderTree/wx/LayoutTestControllerWx.cpp:
+ (LayoutTestController::apiTestNewWindowDataLoadBaseURL):
+ * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+ (LayoutTestController::apiTestNewWindowDataLoadBaseURL):
+
+2010-02-18 Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
+
+ Reviewed by Eric Seidel.
+
+ Teach resolve-ChangeLogs to act as a merge-driver for Git
+
+ https://bugs.webkit.org/show_bug.cgi?id=28721
+
+ To enable automatic merging of ChangeLog files, use the following command:
+
+ git config merge.changelog.driver "resolve-ChangeLogs --merge-driver %O %A %B"
+
+ The driver always works in "downstream" merge mode, meaning
+ it will always put the user's changelog entries on top.
+
+ * Scripts/resolve-ChangeLogs:
+
+2009-12-05 Gustavo Noronha Silva <gns@gnome.org>
+
+ Reviewed by Eric Seidel.
+
+ Enable running of GTK+ API tests.
+
+ * BuildSlaveSupport/build.webkit.org-config/master.cfg:
+ * Scripts/run-gtk-tests: Added.
+
+2010-02-18 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ debug-safari doesn't pass --debug option to gdb-safari on MacOSX
+ https://bugs.webkit.org/show_bug.cgi?id=34411
+
+ * Scripts/webkitdirs.pm:
+
+2010-02-18 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ run-chromium-webkit-tests --platform=mac-leopard needs to run build-dumprendertree
+ https://bugs.webkit.org/show_bug.cgi?id=35053
+
+ * Scripts/webkitpy/layout_tests/port/base.py: Add script_path() function for finding scripts.
+ * Scripts/webkitpy/layout_tests/port/chromium.py: Remove unused argument.
+ * Scripts/webkitpy/layout_tests/port/mac.py:
+ - Make sure that calling webkit-build-directory works even if Scripts/ is not in the user's path.
+ - Call build-dumprendertree (and make sure it succeeds) before running the tests.
+
+2010-02-16 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Shinichiro Hamaji.
+
+ Refactored check-webkit-style's ProcessorOptions class into two
+ classes. This revision contains no new functionality.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34674
+
+ Divided the ProcessorOptions class into a CommandOptionValues
+ class (the result of parsing the command-line options) and
+ a StyleCheckerConfiguration class (which configures the main
+ StyleChecker).
+
+ * Scripts/check-webkit-style:
+ - Updated main() to convert the parsed command option values
+ to a StyleCheckConfiguration instance prior to constructing
+ a StyleChecker.
+
+ * Scripts/webkitpy/style/checker.py:
+ - Added check_webkit_style_configuration() to convert a
+ CommandOptionValues instance into a StyleCheckerConfiguration
+ instance.
+ - Renamed the ProcessorOptions class to CommandOptionValues.
+ - In the CommandOptionValues class--
+ - Replaced the filter_configuration attribute with the
+ simpler filter_rules attribute.
+ - Removed the max_reports_per_error attribute.
+ - Moved the is_reportable() method to the new
+ StyleCheckerConfiguration class.
+ - Removed the base_filter_rules attribute from the
+ DefaultCommandOptionValues class.
+ - In the ArgumentParser class--
+ - Added base_filter_rules to the constructor.
+ - Changed the parse() method to return a CommandOptionValues
+ instance instead of a ProcessorOptions instance.
+ - Created a StyleCheckerConfiguration class.
+ - Added the data attributes max_reports_per_category,
+ stderr_write, and verbosity.
+ - Added is_reportable() (moved from the ProcessorOptions
+ class) and write_style_error() (moved from the
+ DefaultStyleErrorHandler class).
+ - In the StyleChecker class--
+ - Replaced the ProcessorOptions options attribute with the
+ StyleCheckerConfiguration _configuration attribute.
+ - Removed the _stderr_write attribute.
+
+ * Scripts/webkitpy/style/checker_unittest.py:
+ - Updated the existing unit test classes as necessary.
+ - Added a StyleCheckerConfigurationTest class.
+
+ * Scripts/webkitpy/style/error_handlers.py:
+ - Updated the DefaultStyleErrorHandler class to accept a
+ StyleCheckerConfiguration instance instead of a ProcessorOptions
+ instance and an stderr_write method.
+
+ * Scripts/webkitpy/style/error_handlers_unittest.py:
+ - Updated the unit test classes as necessary.
+
+ * Scripts/webkitpy/style/filter.py:
+ - Addressed the FIXME in the FilterConfiguration class to change
+ the user_rules attribute to _user_rules (since it is now
+ accessed only internally).
+
+ * Scripts/webkitpy/style/filter_unittest.py:
+ - Updated to reflect the change from user_rules to _user_rules.
+
+2010-02-17 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ Share the DRT values maxViewWidth/Height among ports
+ https://bugs.webkit.org/show_bug.cgi?id=34474
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (pageNumberForElementByIdCallback):
+ * DumpRenderTree/LayoutTestController.h:
+ (LayoutTestController::maxViewWidth):
+ (LayoutTestController::maxViewHeight):
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (runTest):
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (createWebViewAndOffscreenWindow):
+ (sizeWebViewForCurrentTest):
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (dump):
+ (createWebViewAndOffscreenWindow):
+
+2010-02-17 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ [Win] Implement test functions for printing
+ https://bugs.webkit.org/show_bug.cgi?id=34570
+
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::pageNumberForElementById):
+ (LayoutTestController::numberOfPages):
+
+2010-02-17 Fumitoshi Ukai <ukai@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ websocket/tests/cookies/httponly-cookie.pl fails every time under run-chromium-webkit-tests
+ https://bugs.webkit.org/show_bug.cgi?id=35001
+
+ * Scripts/webkitpy/layout_tests/port/websocket_server.py: add -x flag to run pywebsocket.
+
+2010-02-17 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ check-webkit-style: Misses variables that contain underscores.
+ https://bugs.webkit.org/show_bug.cgi?id=33724
+
+ - Check identifiers whose types are unsigned.
+ - Check bitfields properly.
+
+ * Scripts/webkitpy/style/processors/cpp.py:
+ * Scripts/webkitpy/style/processors/cpp_unittest.py:
+
+2010-02-17 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ check-webkit-style should report the number of files checked
+ https://bugs.webkit.org/show_bug.cgi?id=34971
+
+ * Scripts/check-webkit-style:
+ * Scripts/webkitpy/style/checker.py:
+ * Scripts/webkitpy/style/checker_unittest.py:
+
+2010-02-17 Diego Gonzalez <diego.gonzalez@openbossa.org>
+
+ Reviewed by Ariya Hidayat.
+
+ Make possible Qt DRT to get total number of pages to be printed
+
+ LayoutTests:
+ printing/numberOfPages.html
+
+ [Qt] DRT: Get total number of pages to be printed
+ https://bugs.webkit.org/show_bug.cgi?id=34955
+
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::numberOfPages):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2010-02-17 Xan Lopez <xlopez@igalia.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Update to use new property name.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2010-02-17 Julien Chaffraix <jchaffraix@webkit.org>
+
+ Reviewed by Ariya Hidayat.
+
+ Remove some warnings seen when building Qt
+ https://bugs.webkit.org/show_bug.cgi?id=35017
+
+ Using a machine without the needed tools to build WebKit leads to
+ several errors and warnings.
+
+ * Scripts/webkitdirs.pm: Refactored the code testing the command's
+ presence into a commandExists routine. While doing so removed, stderr
+ output as it usually does not give anything more than our message. Also
+ added a Qt check for qmake that was missing.
+
+2010-02-17 Xan Lopez <xlopez@igalia.com>
+
+ Rubber-stamped by Gustavo Noronha.
+
+ Disable Java by default in DRT.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2010-02-15 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Shinichiro Hamaji.
+
+ Some minor check-webkit-style code clean-ups. This revision
+ contains no new functionality.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34932
+
+ * Scripts/check-webkit-style:
+ - Replaced the call to webkit_argument_defaults() with a
+ default parameter in the ArgumentParser constructor.
+
+ * Scripts/webkitpy/style/checker.py:
+ - Removed the WEBKIT prefix from the default global variables.
+ - Prefixed several of the global variables with an underscore
+ to reflect that they are used internally.
+ - Renamed _DEFAULT_FILTER_RULES to _BASE_FILTER_RULES.
+ - Addressed a FIXME by changing the _PATH_RULES_SPECIFIER
+ configuration from list-tuple pairs to list-list pairs.
+ - Renamed style_categories() to _all_categories().
+ - Renamed webkit_argument_defaults() to _check_webkit_style_defaults().
+ - Renamed the ArgumentDefaults class to DefaultCommandOptionValues.
+ - In the ArgumentParser class--
+ - Renamed the doc_print attribute to stderr_write.
+ - Other minor updates.
+
+ * Scripts/webkitpy/style/checker_unittest.py:
+ - Updated the import statements and unit test classes as necessary.
+ - Added assertions to test _PATH_RULES_SPECIFIER more fully.
+
+ * Scripts/webkitpy/style/error_handlers_unittest.py:
+ - Updated the unit test classes as necessary.
+ - Changed StyleErrorHandlerTestBase to store a list of error
+ messages rather than just the last one.
+
+ * Scripts/webkitpy/style/filter.py:
+ - Altered FilterConfiguration._path_rules_from_path()
+ to convert the path_rules list to a tuple.
+
+ * Scripts/webkitpy/style/filter_unittest.py:
+ - Updated the unit tests to reflect the change from tuples to
+ lists in the _PATH_RULES_SPECIFIER configuration variable.
+
+2010-02-16 Mark Rowe <mrowe@apple.com>
+
+ Let's not check garbage in to common build scripts and hose the world now eh guys?
+
+ * Scripts/webkitdirs.pm:
+
+2010-02-16 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ re-factor Skipped list parsing code into multiple functions and unit test it
+ https://bugs.webkit.org/show_bug.cgi?id=34986
+
+ * Scripts/test-webkitpy: Add new unit test.
+ * Scripts/webkitpy/layout_tests/__init__.py: Copied from WebKitTools/QueueStatusServer/filters/__init__.py.
+ * Scripts/webkitpy/layout_tests/port/mac.py: Split parsing function into multiple functions for testing.
+ * Scripts/webkitpy/layout_tests/port/mac_unittest.py: Added.
+
+2010-02-16 Xan Lopez <xlopez@igalia.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Enable 'auto-resize-window' in our DRT.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2010-02-15 Martin Robinson <mrobinson@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ check-webkit-style should not complain about NULL sentinel in calls to g_strconcat and g_strjoin
+ https://bugs.webkit.org/show_bug.cgi?id=34834
+
+ * Scripts/webkitpy/style/processors/cpp.py:
+ * Scripts/webkitpy/style/processors/cpp_unittest.py:
+
+2010-02-12 Alexey Proskuryakov <ap@apple.com>
+
+ Reviewed by Kevin Decker.
+
+ <rdar://problem/7130641> Browser objects identity is not preserved by Safari
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp:
+ (pluginInvoke): Added methods for checking object identity (via refcount).
+
+2010-02-15 Robert Hogan <robert@roberthogan.net>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] DRT: Support evaluateInWebInspector(), setTimelineProfilingEnabled().
+
+ Support LayoutTestController.evaluateInWebInspector(), setTimelineProfilingEnabled() in Qt DRT.
+
+ https://bugs.webkit.org/show_bug.cgi?id=33096
+
+ This allows the following tests to pass:
+
+ inspector/console-format-collections.html
+ inspector/styles-iframe.html
+ inspector/syntax-highlight-css.html
+ inspector/syntax-highlight-javascript.html
+ inspector/timeline-enum-stability.html
+ inspector/timeline-layout.html
+ inspector/timeline-mark-timeline.html
+ inspector/timeline-paint.html
+ inspector/timeline-parse-html.html
+ inspector/timeline-recalculate-styles.html
+ inspector/timeline-script-tag-1.html
+ inspector/timeline-script-tag-2.html
+ inspector/timeline-trivial.html
+ inspector/cookie-resource-match.html
+ inspector/elements-img-tooltip.html
+ inspector/elements-panel-selection-on-refresh.html
+ inspector/inspected-objects-not-overriden.html
+ inspector/timeline-event-dispatch.html
+ inspector/timeline-network-resource.html
+ inspector/elements-panel-rewrite-href.html
+ inspector/console-dir.html
+ inspector/console-dirxml.html
+ inspector/console-format.html
+ inspector/console-tests.html
+ inspector/elements-panel-structure.html
+ inspector/evaluate-in-frontend.html
+ inspector/console-clear.html
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::DumpRenderTree::resetToConsistentStateBeforeTesting):
+ (WebCore::isWebInspectorTest):
+ (WebCore::DumpRenderTree::open):
+ * DumpRenderTree/qt/DumpRenderTreeQt.h:
+ (WebCore::DumpRenderTree::display):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::closeWebInspector):
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::evaluateInWebInspector):
+ (LayoutTestController::setTimelineProfilingEnabled):
+ (LayoutTestController::display):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2010-02-14 Dirk Pranke <dpranke@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ Update rebaseline-chromium-webkit-tests to work with the new code
+ structure (port objects instead of path_utils and platform_utils).
+
+ Added a path_to_test_expectations_file() to the Port interface.
+
+ Fixed a bug in the chromium_* platform implementations where the
+ 'target' option was assumed to be set.
+
+ * Scripts/rebaseline-chromium-webkit-tests:
+ * Scripts/webkitpy/layout_tests/layout_package/test_expectations.py:
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ * Scripts/webkitpy/layout_tests/port/chromium.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/test.py:
+ * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py:
+
+2010-02-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ webkit-build-directory misuses terms
+ https://bugs.webkit.org/show_bug.cgi?id=34822
+
+ * Scripts/webkit-build-directory:
+ - Add --top-level and --configuration options and make using one of them required.
+ * Scripts/webkitpy/layout_tests/port/mac.py:
+ - Use --top-level instead of --base.
+
+2010-02-14 Chang Shu <Chang.Shu@nokia.com>
+
+ Reviewed by Laszlo Gombos.
+
+ [Qt] Enable appcache feature.
+ https://bugs.webkit.org/show_bug.cgi?id=34713
+
+ Re-land r54543 without the change in DumpRenderTree/qt/main.cpp.
+ Persistent storage for AppCache is already initialized in
+ DumpRenderTreeQt.cpp.
+
+ * DumpRenderTree/qt/DumpRenderTreeQt.cpp:
+ (WebCore::WebPage::WebPage):
+
+2010-02-12 Chang Shu <Chang.Shu@nokia.com>
+
+ Not Reviewed.
+
+ Change case of my email address as a work-around for the following bug.
+ https://bugs.webkit.org/show_bug.cgi?id=34717
+
+ * Scripts/webkitpy/committers.py:
+
+2010-02-12 Darin Adler <darin@apple.com>
+
+ Ignore compiled Python in more of webkitpy.
+
+ * Scripts/webkitpy/style/processors: Added property svn:ignore.
+
2010-02-12 Diego Gonzalez <diego.gonzalez@openbossa.org>
Reviewed by Kenneth Rohde Christiansen.
diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp
index c2393c3..f528b31 100644
--- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp
+++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp
@@ -467,10 +467,8 @@ static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function,
static bool parsePageParameters(JSContextRef context, int argumentCount, const JSValueRef* arguments, JSValueRef* exception, float& pageWidthInPixels, float& pageHeightInPixels)
{
- // FIXME: These values should sync with maxViewWidth/Height in
- // DumpRenderTree.mm. Factor these values out to somewhere.
- pageWidthInPixels = 800;
- pageHeightInPixels = 600;
+ pageWidthInPixels = LayoutTestController::maxViewWidth;
+ pageHeightInPixels = LayoutTestController::maxViewHeight;
switch (argumentCount) {
case 2:
pageWidthInPixels = static_cast<float>(JSValueToNumber(context, arguments[0], exception));
@@ -940,6 +938,18 @@ static JSValueRef setAllowUniversalAccessFromFileURLsCallback(JSContextRef conte
return JSValueMakeUndefined(context);
}
+static JSValueRef setAllowFileAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ // Has mac & windows implementation
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ controller->setAllowFileAccessFromFileURLs(JSValueToBoolean(context, arguments[0]));
+
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has mac & windows implementation
@@ -1252,6 +1262,22 @@ static JSValueRef addUserStyleSheetCallback(JSContextRef context, JSObjectRef, J
return JSValueMakeUndefined(context);
}
+static JSValueRef apiTestNewWindowDataLoadBaseURLCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount != 2)
+ return JSValueMakeUndefined(context);
+
+ JSRetainPtr<JSStringRef> utf8Data(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+ ASSERT(!*exception);
+
+ JSRetainPtr<JSStringRef> baseURL(Adopt, JSValueToStringCopy(context, arguments[1], exception));
+ ASSERT(!*exception);
+
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ controller->apiTestNewWindowDataLoadBaseURL(utf8Data.get(), baseURL.get());
+ return JSValueMakeUndefined(context);
+}
+
// Static Values
static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
@@ -1328,6 +1354,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
{ "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "addUserScript", addUserScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "addUserStyleSheet", addUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "apiTestNewWindowDataLoadBaseURL", apiTestNewWindowDataLoadBaseURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1380,6 +1407,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
{ "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAllowUniversalAccessFromFileURLs", setAllowUniversalAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setAllowFileAccessFromFileURLs", setAllowFileAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAuthenticationPassword", setAuthenticationPasswordCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1492,3 +1520,6 @@ void LayoutTestController::setPOSIXLocale(JSStringRef locale)
JSStringGetUTF8CString(locale, localeBuf, sizeof(localeBuf));
setlocale(LC_ALL, localeBuf);
}
+
+const unsigned LayoutTestController::maxViewWidth = 800;
+const unsigned LayoutTestController::maxViewHeight = 600;
diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h
index 5f9df50..3add32a 100644
--- a/WebKitTools/DumpRenderTree/LayoutTestController.h
+++ b/WebKitTools/DumpRenderTree/LayoutTestController.h
@@ -69,6 +69,7 @@ public:
void removeAllVisitedLinks();
void setAcceptsEditing(bool acceptsEditing);
void setAllowUniversalAccessFromFileURLs(bool);
+ void setAllowFileAccessFromFileURLs(bool);
void setAppCacheMaximumSize(unsigned long long quota);
void setAuthorAndUserStylesEnabled(bool);
void setCacheModel(int);
@@ -232,6 +233,13 @@ public:
void evaluateScriptInIsolatedWorld(unsigned worldId, JSObjectRef globalObject, JSStringRef script);
void setPOSIXLocale(JSStringRef locale);
+
+ // The following API test functions should probably be moved to platform-specific
+ // unit tests outside of DRT once they exist.
+ void apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL);
+
+ static const unsigned maxViewWidth;
+ static const unsigned maxViewHeight;
private:
bool m_dumpAsPDF;
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
index e69da73..8e278f5 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
@@ -176,6 +176,11 @@ enum {
ID_TEST_RELOAD_PLUGINS_AND_PAGES,
ID_TEST_GET_BROWSER_PROPERTY,
ID_TEST_SET_BROWSER_PROPERTY,
+ ID_REMEMBER,
+ ID_GET_REMEMBERED_OBJECT,
+ ID_GET_AND_FORGET_REMEMBERED_OBJECT,
+ ID_REF_COUNT,
+ ID_SET_STATUS,
NUM_METHOD_IDENTIFIERS
};
@@ -205,7 +210,12 @@ static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
"reloadPluginsNoPages",
"reloadPluginsAndPages",
"testGetBrowserProperty",
- "testSetBrowserProperty"
+ "testSetBrowserProperty",
+ "remember",
+ "getRememberedObject",
+ "getAndForgetRememberedObject",
+ "refCount",
+ "setStatus"
};
static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
@@ -747,6 +757,22 @@ bool testWindowOpen(NPP npp)
return false;
}
+static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ char* message = 0;
+ if (argCount && NPVARIANT_IS_STRING(args[0])) {
+ NPString statusString = NPVARIANT_TO_STRING(args[0]);
+ message = toCString(statusString);
+ }
+
+ browser->status(obj->npp, message);
+
+ free(message);
+ return true;
+}
+
+static NPObject* rememberedObject;
+
static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
@@ -807,7 +833,29 @@ static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* a
} else if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) {
browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]);
return true;
- }
+ } else if (name == pluginMethodIdentifiers[ID_REMEMBER]) {
+ if (rememberedObject)
+ browser->releaseobject(rememberedObject);
+ rememberedObject = NPVARIANT_TO_OBJECT(args[0]);
+ browser->retainobject(rememberedObject);
+ VOID_TO_NPVARIANT(*result);
+ return true;
+ } else if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) {
+ assert(rememberedObject);
+ browser->retainobject(rememberedObject);
+ OBJECT_TO_NPVARIANT(rememberedObject, *result);
+ return true;
+ } else if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) {
+ assert(rememberedObject);
+ OBJECT_TO_NPVARIANT(rememberedObject, *result);
+ rememberedObject = 0;
+ return true;
+ } else if (name == pluginMethodIdentifiers[ID_REF_COUNT]) {
+ uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount;
+ INT32_TO_NPVARIANT(refCount, *result);
+ return true;
+ } else if (name == pluginMethodIdentifiers[ID_SET_STATUS])
+ return testSetStatus(plugin, args, argCount, result);
return false;
}
diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
index 39430cf..a2fc79b 100644
--- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
@@ -94,8 +94,6 @@ GSList* webViewList = 0;
// current b/f item at the end of the previous test
static WebKitWebHistoryItem* prevTestBFItem = NULL;
-const unsigned maxViewHeight = 600;
-const unsigned maxViewWidth = 800;
const unsigned historyItemIndent = 8;
static gchar* autocorrectURL(const gchar* url)
@@ -335,6 +333,8 @@ static void resetDefaultsToConsistentValues()
"minimum-font-size", 1,
"enable-caret-browsing", FALSE,
"enable-page-cache", FALSE,
+ "auto-resize-window", TRUE,
+ "enable-java-applet", FALSE,
NULL);
webkit_web_frame_clear_main_frame_name(mainFrame);
@@ -477,8 +477,8 @@ static void runTest(const string& testPathOrURL)
bool isSVGW3CTest = (gLayoutTestController->testPathOrURL().find("svg/W3C-SVG-1.1") != string::npos);
GtkAllocation size;
size.x = size.y = 0;
- size.width = isSVGW3CTest ? 480 : maxViewWidth;
- size.height = isSVGW3CTest ? 360 : maxViewHeight;
+ size.width = isSVGW3CTest ? 480 : LayoutTestController::maxViewWidth;
+ size.height = isSVGW3CTest ? 360 : LayoutTestController::maxViewHeight;
gtk_window_resize(GTK_WINDOW(window), size.width, size.height);
gtk_widget_size_allocate(container, &size);
diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
index 422e2c2..668b852 100644
--- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
@@ -348,6 +348,15 @@ void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool flag)
g_object_set(G_OBJECT(settings), "enable-universal-access-from-file-uris", flag, NULL);
}
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool flag)
+{
+ WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
+ ASSERT(view);
+
+ WebKitWebSettings* settings = webkit_web_view_get_settings(view);
+ g_object_set(G_OBJECT(settings), "enable-file-access-from-file-uris", flag, NULL);
+}
+
void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
{
// FIXME: implement
@@ -586,3 +595,8 @@ void LayoutTestController::removeAllVisitedLinks()
{
// FIXME: Implement this.
}
+
+void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
+{
+
+}
diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
index 7a4429b..c7ddf21 100644
--- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
+++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
@@ -134,9 +134,6 @@ static RetainPtr<CFStringRef> persistentUserStyleSheetLocation;
static WebHistoryItem *prevTestBFItem = nil; // current b/f item at the end of the previous test
-const unsigned maxViewHeight = 600;
-const unsigned maxViewWidth = 800;
-
#if __OBJC2__
static void swizzleAllMethods(Class imposter, Class original)
{
@@ -279,7 +276,7 @@ static void activateFonts()
WebView *createWebViewAndOffscreenWindow()
{
- NSRect rect = NSMakeRect(0, 0, maxViewWidth, maxViewHeight);
+ NSRect rect = NSMakeRect(0, 0, LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight);
WebView *webView = [[WebView alloc] initWithFrame:rect frameName:nil groupName:@"org.webkit.DumpRenderTree"];
[webView setUIDelegate:uiDelegate];
@@ -396,6 +393,7 @@ static void resetDefaultsToConsistentValues()
WebPreferences *preferences = [WebPreferences standardPreferences];
[preferences setAllowUniversalAccessFromFileURLs:YES];
+ [preferences setAllowFileAccessFromFileURLs:YES];
[preferences setStandardFontFamily:@"Times"];
[preferences setFixedFontFamily:@"Courier"];
[preferences setSerifFontFamily:@"Times"];
@@ -1020,7 +1018,7 @@ static void sizeWebViewForCurrentTest()
if (isSVGW3CTest)
[[mainFrame webView] setFrameSize:NSMakeSize(480, 360)];
else
- [[mainFrame webView] setFrameSize:NSMakeSize(maxViewWidth, maxViewHeight)];
+ [[mainFrame webView] setFrameSize:NSMakeSize(LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight)];
}
static const char *methodNameStringForFailedTest()
diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
index b726e72..66ba5f0 100644
--- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
@@ -334,6 +334,11 @@ void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
[[[mainFrame webView] preferences] setAllowUniversalAccessFromFileURLs:enabled];
}
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
+{
+ [[[mainFrame webView] preferences] setAllowFileAccessFromFileURLs:enabled];
+}
+
void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled)
{
[[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled];
@@ -617,3 +622,67 @@ void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObj
[mainFrame _stringByEvaluatingJavaScriptFromString:scriptNS withGlobalObject:globalObject inScriptWorld:world];
}
+
+@interface APITestDelegate : NSObject
+{
+ bool* m_condition;
+}
+@end
+
+@implementation APITestDelegate
+
+- (id)initWithCompletionCondition:(bool*)condition
+{
+ [super init];
+ ASSERT(condition);
+ m_condition = condition;
+ *m_condition = false;
+ return self;
+}
+
+- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
+{
+ printf("API Test load failed\n");
+ *m_condition = true;
+}
+
+- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
+{
+ printf("API Test load failed provisional\n");
+ *m_condition = true;
+}
+
+- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
+{
+ printf("API Test load succeeded\n");
+ *m_condition = true;
+}
+
+@end
+
+void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ RetainPtr<CFStringRef> utf8DataCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, utf8Data));
+ RetainPtr<CFStringRef> baseURLCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, baseURL));
+
+ WebView *webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:@"" groupName:@""];
+
+ bool done = false;
+ APITestDelegate *delegate = [[APITestDelegate alloc] initWithCompletionCondition:&done];
+ [webView setFrameLoadDelegate:delegate];
+
+ [[webView mainFrame] loadData:[(NSString *)utf8DataCF.get() dataUsingEncoding:NSUTF8StringEncoding] MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:[NSURL URLWithString:(NSString *)baseURLCF.get()]];
+
+ while (!done) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
+ [pool release];
+ }
+
+ [webView close];
+ [webView release];
+ [delegate release];
+ [pool release];
+}
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
index c16a786..43f1318 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp
@@ -135,7 +135,6 @@ WebPage::WebPage(QObject* parent, DumpRenderTree* drt)
globalSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
globalSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
globalSettings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false);
- globalSettings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, false);
connect(this, SIGNAL(geometryChangeRequested(const QRect &)),
this, SLOT(setViewGeometry(const QRect & )));
@@ -324,6 +323,7 @@ DumpRenderTree::DumpRenderTree()
m_mainView->resize(QSize(maxViewWidth, maxViewHeight));
m_page = new WebPage(m_mainView, this);
m_mainView->setPage(m_page);
+ m_mainView->setContextMenuPolicy(Qt::NoContextMenu);
// create our controllers. This has to be done before connectFrame,
// as it exports there to the JavaScript DOM window.
@@ -412,10 +412,23 @@ void DumpRenderTree::resetToConsistentStateBeforeTesting()
setlocale(LC_ALL, "");
}
+static bool isWebInspectorTest(const QUrl& url)
+{
+ if (url.path().contains("inspector/"))
+ return true;
+ return false;
+}
+
void DumpRenderTree::open(const QUrl& url)
{
resetToConsistentStateBeforeTesting();
+ if (isWebInspectorTest(m_page->mainFrame()->url()))
+ layoutTestController()->closeWebInspector();
+
+ if (isWebInspectorTest(url))
+ layoutTestController()->showWebInspector();
+
// W3C SVG tests expect to be 480x360
bool isW3CTest = url.toString().contains("svg/W3C-SVG-1.1");
int width = isW3CTest ? 480 : maxViewWidth;
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
index 00d7ae4..8d80f87 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h
@@ -158,6 +158,7 @@ public:
WebPage(QObject* parent, DumpRenderTree*);
virtual ~WebPage();
QWebInspector* webInspector();
+ void closeWebInspector();
QWebPage *createWindow(QWebPage::WebWindowType);
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
index 73a9934..1ef2d3f 100644
--- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
@@ -274,6 +274,8 @@ void EventSender::contextClick()
QApplication::sendEvent(m_page, &event);
QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
QApplication::sendEvent(m_page, &event2);
+ QContextMenuEvent event3(QContextMenuEvent::Mouse, m_mousePos);
+ QApplication::sendEvent(m_page->view(), &event3);
}
void EventSender::scheduleAsynchronousClick()
@@ -397,18 +399,28 @@ void EventSender::sendTouchEvent(QEvent::Type type)
void EventSender::zoomPageIn()
{
- QWebFrame* frame = m_page->mainFrame();
- if (frame)
+ if (QWebFrame* frame = m_page->mainFrame())
frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP);
}
void EventSender::zoomPageOut()
{
- QWebFrame* frame = m_page->mainFrame();
- if (frame)
+ if (QWebFrame* frame = m_page->mainFrame())
frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP);
}
+void EventSender::textZoomIn()
+{
+ if (QWebFrame* frame = m_page->mainFrame())
+ frame->setTextSizeMultiplier(frame->textSizeMultiplier() * ZOOM_STEP);
+}
+
+void EventSender::textZoomOut()
+{
+ if (QWebFrame* frame = m_page->mainFrame())
+ frame->setTextSizeMultiplier(frame->textSizeMultiplier() / ZOOM_STEP);
+}
+
QWebFrame* EventSender::frameUnderMouse() const
{
QWebFrame* frame = m_page->mainFrame();
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
index f6cfc7c..38bca89 100644
--- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
@@ -68,6 +68,8 @@ public slots:
void touchEnd();
void zoomPageIn();
void zoomPageOut();
+ void textZoomIn();
+ void textZoomOut();
void clearTouchPoints();
void releaseTouchPoint(int index);
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
index 51c1181..a26bc3d 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
@@ -41,6 +41,7 @@ extern void qt_dump_frame_loader(bool b);
extern void qt_dump_resource_load_callbacks(bool b);
extern void qt_drt_setFrameSetFlatteningEnabled(QWebPage*, bool);
extern void qt_drt_setJavaScriptProfilingEnabled(QWebFrame*, bool enabled);
+extern void qt_drt_setTimelineProfilingEnabled(QWebPage*, bool enabled);
extern bool qt_drt_pauseAnimation(QWebFrame*, const QString& name, double time, const QString& elementId);
extern bool qt_drt_pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId);
extern bool qt_drt_pauseSVGAnimation(QWebFrame*, const QString& animationId, double time, const QString& elementId);
@@ -51,6 +52,10 @@ extern void qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const
extern QString qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id);
extern int qt_drt_workerThreadCount();
extern int qt_drt_pageNumberForElementById(QWebFrame* qFrame, const QString& id, float width, float height);
+extern int qt_drt_numberOfPages(QWebFrame* qFrame, float width, float height);
+extern void qt_drt_webinspector_executeScript(QWebPage* page, long callId, const QString& script);
+extern void qt_drt_webinspector_show(QWebPage *page);
+extern void qt_drt_webinspector_close(QWebPage *page);
LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt)
: QObject()
@@ -285,15 +290,22 @@ QString LayoutTestController::decodeHostName(const QString& host)
return decoded;
}
+
+void LayoutTestController::closeWebInspector()
+{
+ qt_drt_webinspector_close(m_drt->webPage());
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, false);
+}
+
void LayoutTestController::showWebInspector()
{
m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
- m_drt->webPage()->webInspector()->show();
+ qt_drt_webinspector_show(m_drt->webPage());
}
-void LayoutTestController::hideWebInspector()
+void LayoutTestController::evaluateInWebInspector(long callId, const QString& script)
{
- m_drt->webPage()->webInspector()->hide();
+ qt_drt_webinspector_executeScript(m_drt->webPage(), callId, script);
}
void LayoutTestController::setFrameSetFlatteningEnabled(bool enabled)
@@ -306,12 +318,22 @@ void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
m_drt->webPage()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, enabled);
}
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
+{
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, enabled);
+}
+
void LayoutTestController::setJavaScriptProfilingEnabled(bool enable)
{
m_topLoadingFrame->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
qt_drt_setJavaScriptProfilingEnabled(m_topLoadingFrame, enable);
}
+void LayoutTestController::setTimelineProfilingEnabled(bool enable)
+{
+ qt_drt_setTimelineProfilingEnabled(m_drt->webPage(), enable);
+}
+
void LayoutTestController::setFixedContentsSize(int width, int height)
{
m_topLoadingFrame->page()->setPreferredContentsSize(QSize(width, height));
@@ -473,3 +495,8 @@ int LayoutTestController::pageNumberForElementById(const QString& id, float widt
return qt_drt_pageNumberForElementById(m_drt->webPage()->mainFrame(), id, width, height);
}
+
+int LayoutTestController::numberOfPages(float width, float height)
+{
+ return qt_drt_numberOfPages(m_drt->webPage()->mainFrame(), width, height);
+}
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
index 64cbcc9..d73794e 100644
--- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
@@ -115,11 +115,14 @@ public slots:
QString decodeHostName(const QString& host);
void dumpSelectionRect() const {}
void showWebInspector();
- void hideWebInspector();
+ void closeWebInspector();
+ void evaluateInWebInspector(long callId, const QString& script);
void setFrameSetFlatteningEnabled(bool enable);
void setAllowUniversalAccessFromFileURLs(bool enable);
+ void setAllowFileAccessFromFileURLs(bool enable);
void setJavaScriptProfilingEnabled(bool enable);
+ void setTimelineProfilingEnabled(bool enable);
void setFixedContentsSize(int width, int height);
void setPrivateBrowsingEnabled(bool enable);
void setPopupBlockingEnabled(bool enable);
@@ -150,6 +153,7 @@ public slots:
void setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme);
int workerThreadCount();
int pageNumberForElementById(const QString& id, float width = 0, float height = 0);
+ int numberOfPages(float width, float height);
private slots:
void processWork();
diff --git a/WebKitTools/DumpRenderTree/qt/main.cpp b/WebKitTools/DumpRenderTree/qt/main.cpp
index efcda57..7d72982 100644
--- a/WebKitTools/DumpRenderTree/qt/main.cpp
+++ b/WebKitTools/DumpRenderTree/qt/main.cpp
@@ -37,9 +37,7 @@
#include <qdir.h>
#include <qdebug.h>
#include <qfont.h>
-#include <qwebsettings.h>
#include <qwebdatabase.h>
-#include <qdesktopservices.h>
#include <qtimer.h>
#include <qwindowsstyle.h>
@@ -161,8 +159,6 @@ int main(int argc, char* argv[])
if (args.contains(QLatin1String("--pixel-tests")))
dumper.setDumpPixels(true);
- QString dbDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "qtwebkitdrt";
- QWebSettings::setOfflineStoragePath(dbDir);
QWebDatabase::removeAllDatabases();
if (args.contains(QLatin1String("-"))) {
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
index 261b9e6..ddfca95 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
@@ -107,9 +107,6 @@ LayoutTestController* gLayoutTestController = 0;
UINT_PTR waitToDumpWatchdog = 0;
-const unsigned maxViewWidth = 800;
-const unsigned maxViewHeight = 600;
-
void setPersistentUserStyleSheetLocation(CFStringRef url)
{
persistentUserStyleSheetLocation = url;
@@ -667,8 +664,8 @@ void dump()
width = 480;
height = 360;
} else {
- width = maxViewWidth;
- height = maxViewHeight;
+ width = LayoutTestController::maxViewWidth;
+ height = LayoutTestController::maxViewHeight;
}
::SetWindowPos(webViewWindow, 0, 0, 0, width, height, SWP_NOMOVE);
@@ -787,6 +784,7 @@ static void resetDefaultsToConsistentValues(IWebPreferences* preferences)
COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
if (prefsPrivate) {
prefsPrivate->setAllowUniversalAccessFromFileURLs(TRUE);
+ prefsPrivate->setAllowFileAccessFromFileURLs(TRUE);
prefsPrivate->setAuthorAndUserStylesEnabled(TRUE);
prefsPrivate->setDeveloperExtrasEnabled(FALSE);
prefsPrivate->setExperimentalNotificationsEnabled(TRUE);
@@ -1097,6 +1095,8 @@ WindowToWebViewMap& windowToWebViewMap()
IWebView* createWebViewAndOffscreenWindow(HWND* webViewWindow)
{
+ unsigned maxViewWidth = LayoutTestController::maxViewWidth;
+ unsigned maxViewHeight = LayoutTestController::maxViewHeight;
HWND hostWindow = CreateWindowEx(WS_EX_TOOLWINDOW, kDumpRenderTreeClassName, TEXT("DumpRenderTree"), WS_POPUP,
-maxViewWidth, -maxViewHeight, maxViewWidth, maxViewHeight, 0, 0, GetModuleHandle(0), 0);
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
index 34fd2e6..9f84488 100644
--- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
+++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
@@ -406,6 +406,23 @@ void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
prefsPrivate->setAllowUniversalAccessFromFileURLs(enabled);
}
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
+{
+ COMPtr<IWebView> webView;
+ if (FAILED(frame->webView(&webView)))
+ return;
+
+ COMPtr<IWebPreferences> preferences;
+ if (FAILED(webView->preferences(&preferences)))
+ return;
+
+ COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
+ if (!prefsPrivate)
+ return;
+
+ prefsPrivate->setAllowFileAccessFromFileURLs(enabled);
+}
+
void LayoutTestController::setPopupBlockingEnabled(bool enabled)
{
COMPtr<IWebView> webView;
@@ -1121,14 +1138,34 @@ JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStri
return counterValueJS;
}
-int LayoutTestController::pageNumberForElementById(JSStringRef, float, float)
+int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels)
{
- // FIXME: implement
- return -1;
+ COMPtr<IWebFramePrivate> framePrivate(Query, frame);
+ if (!framePrivate)
+ return 0;
+
+ wstring idWstring = jsStringRefToWString(id);
+ BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
+ int pageNumber = -1;
+ if (FAILED(framePrivate->pageNumberForElementById(idBSTR, pageWidthInPixels, pageHeightInPixels, &pageNumber)))
+ pageNumber = -1;
+ SysFreeString(idBSTR);
+ return pageNumber;
}
-int LayoutTestController::numberOfPages(float, float)
+int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
{
- // FIXME: implement
- return -1;
+ COMPtr<IWebFramePrivate> framePrivate(Query, frame);
+ if (!framePrivate)
+ return 0;
+
+ int pageNumber = -1;
+ if (FAILED(framePrivate->numberOfPages(pageWidthInPixels, pageHeightInPixels, &pageNumber)))
+ pageNumber = -1;
+ return pageNumber;
+}
+
+void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
+{
+
}
diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
index 3bc84cd..ce1bda5 100644
--- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
+++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
@@ -180,6 +180,11 @@ void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
// FIXME: implement
}
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
+{
+ // FIXME: implement
+}
+
void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag)
{
// FIXME: implement
@@ -375,4 +380,9 @@ int LayoutTestController::numberOfPages(float, float)
{
// FIXME: implement
return -1;
-} \ No newline at end of file
+}
+
+void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
+{
+
+}
diff --git a/WebKitTools/QtLauncher/main.cpp b/WebKitTools/QtLauncher/main.cpp
index c725c2f..1203ce7 100644
--- a/WebKitTools/QtLauncher/main.cpp
+++ b/WebKitTools/QtLauncher/main.cpp
@@ -133,6 +133,8 @@ private:
WebInspector* inspector;
QAction* formatMenuAction;
+ QAction* flipAnimated;
+ QAction* flipYAnimated;
#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
QList<QTouchEvent::TouchPoint> touchPoints;
@@ -461,6 +463,13 @@ void LauncherWindow::initializeView(bool useGraphicsView)
if (gShowFrameRate)
view->enableFrameRateMeasurement();
page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, gUseCompositing);
+
+ if (flipAnimated)
+ connect(flipAnimated, SIGNAL(triggered()), view, SLOT(animatedFlip()));
+
+ if (flipYAnimated)
+ connect(flipYAnimated, SIGNAL(triggered()), view, SLOT(animatedYFlip()));
+
m_view = view;
}
@@ -540,13 +549,26 @@ void LauncherWindow::setupUI()
touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T));
#endif
- QAction* toggleAcceleratedCompositing = toolsMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool)));
+ QMenu* graphicsViewMenu = toolsMenu->addMenu("QGraphicsView");
+ QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(initializeView(bool)));
+ toggleGraphicsView->setCheckable(true);
+ toggleGraphicsView->setChecked(false);
+
+ QAction* toggleAcceleratedCompositing = graphicsViewMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool)));
toggleAcceleratedCompositing->setCheckable(true);
toggleAcceleratedCompositing->setChecked(false);
+ toggleAcceleratedCompositing->setEnabled(false);
+ toggleAcceleratedCompositing->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
- QAction* toggleGraphicsView = toolsMenu->addAction("Toggle use of QGraphicsView", this, SLOT(initializeView(bool)));
- toggleGraphicsView->setCheckable(true);
- toggleGraphicsView->setChecked(false);
+ graphicsViewMenu->addSeparator();
+
+ flipAnimated = graphicsViewMenu->addAction("Animated Flip");
+ flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ flipAnimated->setEnabled(false);
+
+ flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip");
+ flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
+ flipYAnimated->setEnabled(false);
}
QWebPage* WebPage::createWindow(QWebPage::WebWindowType type)
diff --git a/WebKitTools/QtLauncher/webview.cpp b/WebKitTools/QtLauncher/webview.cpp
index 443fc3e..311d79b 100644
--- a/WebKitTools/QtLauncher/webview.cpp
+++ b/WebKitTools/QtLauncher/webview.cpp
@@ -48,6 +48,29 @@ WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent)
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
+ QStateMachine* machine = new QStateMachine(this);
+ QState* s0 = new QState(machine);
+ s0->assignProperty(this, "yRotation", 0);
+
+ QState* s1 = new QState(machine);
+ s1->assignProperty(this, "yRotation", 90);
+
+ QAbstractTransition* t1 = s0->addTransition(this, SIGNAL(yFlipRequest()), s1);
+ QPropertyAnimation* yRotationAnim = new QPropertyAnimation(this, "yRotation", this);
+ yRotationAnim->setDuration(1000);
+ t1->addAnimation(yRotationAnim);
+
+ QState* s2 = new QState(machine);
+ s2->assignProperty(this, "yRotation", -90);
+ s1->addTransition(s1, SIGNAL(propertiesAssigned()), s2);
+
+ QAbstractTransition* t2 = s2->addTransition(s0);
+ t2->addAnimation(yRotationAnim);
+
+ machine->setInitialState(s0);
+ machine->start();
+#endif
}
void WebViewGraphicsBased::resizeEvent(QResizeEvent* event)
@@ -83,6 +106,30 @@ void WebViewGraphicsBased::updateFrameRate()
m_numPaintsSinceLastMeasure = 0;
}
+void WebViewGraphicsBased::animatedFlip()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
+ QSizeF center = m_item->boundingRect().size() / 2;
+ QPointF centerPoint = QPointF(center.width(), center.height());
+ m_item->setTransformOriginPoint(centerPoint);
+
+ QPropertyAnimation* animation = new QPropertyAnimation(m_item, "rotation", this);
+ animation->setDuration(1000);
+
+ int rotation = int(m_item->rotation());
+
+ animation->setStartValue(rotation);
+ animation->setEndValue(rotation + 180 - (rotation % 180));
+
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+#endif
+}
+
+void WebViewGraphicsBased::animatedYFlip()
+{
+ emit yFlipRequest();
+}
+
void WebViewGraphicsBased::paintEvent(QPaintEvent* event)
{
QGraphicsView::paintEvent(event);
diff --git a/WebKitTools/QtLauncher/webview.h b/WebKitTools/QtLauncher/webview.h
index 83bd801..297d975 100644
--- a/WebKitTools/QtLauncher/webview.h
+++ b/WebKitTools/QtLauncher/webview.h
@@ -66,6 +66,7 @@ protected:
class WebViewGraphicsBased : public QGraphicsView {
Q_OBJECT
+ Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation)
public:
WebViewGraphicsBased(QWidget* parent);
@@ -76,8 +77,29 @@ public:
void enableFrameRateMeasurement();
virtual void paintEvent(QPaintEvent* event);
+ void setYRotation(qreal angle)
+ {
+#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
+ QRectF r = m_item->boundingRect();
+ m_item->setTransform(QTransform()
+ .translate(r.width() / 2, r.height() / 2)
+ .rotate(angle, Qt::YAxis)
+ .translate(-r.width() / 2, -r.height() / 2));
+#endif
+ m_yRotation = angle;
+ }
+ qreal yRotation() const
+ {
+ return m_yRotation;
+ }
+
public slots:
void updateFrameRate();
+ void animatedFlip();
+ void animatedYFlip();
+
+signals:
+ void yFlipRequest();
private:
GraphicsWebView* m_item;
@@ -86,6 +108,7 @@ private:
QTime m_startTime;
QTime m_lastConsultTime;
bool m_measureFps;
+ qreal m_yRotation;
};
#endif
diff --git a/WebKitTools/Scripts/check-webkit-style b/WebKitTools/Scripts/check-webkit-style
index 501264b..ea2e943 100755
--- a/WebKitTools/Scripts/check-webkit-style
+++ b/WebKitTools/Scripts/check-webkit-style
@@ -57,13 +57,11 @@ def main():
codecs.getreader('utf8'),
codecs.getwriter('utf8'),
'replace')
-
- defaults = checker.webkit_argument_defaults()
-
- parser = checker.ArgumentParser(defaults)
+ parser = checker.check_webkit_style_parser()
(files, options) = parser.parse(sys.argv[1:])
- style_checker = checker.StyleChecker(options)
+ configuration = checker.check_webkit_style_configuration(options)
+ style_checker = checker.StyleChecker(configuration)
if files:
for filename in files:
@@ -87,8 +85,11 @@ def main():
style_checker.check_patch(patch)
error_count = style_checker.error_count
- sys.stderr.write('Total errors found: %d\n' % error_count)
- sys.exit(error_count > 0)
+ file_count = style_checker.file_count
+ sys.stderr.write('Total errors found: %d in %d files\n'
+ % (error_count, file_count))
+ # We fail when style errors are found or there are no checked files.
+ sys.exit(error_count > 0 or file_count == 0)
if __name__ == "__main__":
diff --git a/WebKitTools/Scripts/rebaseline-chromium-webkit-tests b/WebKitTools/Scripts/rebaseline-chromium-webkit-tests
index aea0edc..302995c 100755
--- a/WebKitTools/Scripts/rebaseline-chromium-webkit-tests
+++ b/WebKitTools/Scripts/rebaseline-chromium-webkit-tests
@@ -33,6 +33,7 @@ import sys
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),
"webkitpy", "layout_tests"))
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))))
import rebaseline_chromium_webkit_tests
diff --git a/WebKitTools/Scripts/resolve-ChangeLogs b/WebKitTools/Scripts/resolve-ChangeLogs
index 1a2d2af..3238350 100755
--- a/WebKitTools/Scripts/resolve-ChangeLogs
+++ b/WebKitTools/Scripts/resolve-ChangeLogs
@@ -34,6 +34,7 @@ use FindBin;
use lib $FindBin::Bin;
use File::Basename;
+use File::Copy;
use File::Path;
use File::Spec;
use Getopt::Long;
@@ -64,28 +65,30 @@ my $GIT = "git";
my $fixMerged;
my $gitRebaseContinue = 0;
+my $mergeDriver = 0;
my $printWarnings = 1;
my $showHelp;
my $getOptionsResult = GetOptions(
- 'c|continue!' => \$gitRebaseContinue,
- 'f|fix-merged:s' => \&parseFixMerged,
- 'h|help' => \$showHelp,
- 'w|warnings!' => \$printWarnings,
+ 'c|continue!' => \$gitRebaseContinue,
+ 'f|fix-merged:s' => \&parseFixMerged,
+ 'm|merge-driver!' => \$mergeDriver,
+ 'h|help' => \$showHelp,
+ 'w|warnings!' => \$printWarnings,
);
my $relativePath = isInGitFilterBranch() ? '.' : chdirReturningRelativePath(determineVCSRoot());
my @changeLogFiles = removeChangeLogArguments($relativePath);
-if (!defined $fixMerged && scalar(@changeLogFiles) == 0) {
+if (!defined $fixMerged && !$mergeDriver && scalar(@changeLogFiles) == 0) {
@changeLogFiles = findUnmergedChangeLogs();
}
-if (scalar(@ARGV) > 0) {
+if (!$mergeDriver && scalar(@ARGV) > 0) {
print STDERR "ERROR: Files listed on command-line that are not ChangeLogs.\n";
undef $getOptionsResult;
-} elsif (!defined $fixMerged && scalar(@changeLogFiles) == 0) {
+} elsif (!defined $fixMerged && !$mergeDriver && scalar(@changeLogFiles) == 0) {
print STDERR "ERROR: No ChangeLog files listed on command-line or found unmerged.\n";
undef $getOptionsResult;
} elsif ($gitRebaseContinue && !$isGit) {
@@ -94,6 +97,12 @@ if (scalar(@ARGV) > 0) {
} elsif (defined $fixMerged && !$isGit) {
print STDERR "ERROR: --fix-merged may only be used with a git repository\n";
undef $getOptionsResult;
+} elsif ($mergeDriver && !$isGit) {
+ print STDERR "ERROR: --merge-driver may only be used with a git repository\n";
+ undef $getOptionsResult;
+} elsif ($mergeDriver && scalar(@ARGV) < 3) {
+ print STDERR "ERROR: --merge-driver expects %O %A %B as arguments\n";
+ undef $getOptionsResult;
}
sub usageAndExit()
@@ -104,6 +113,7 @@ Usage: @{[ basename($0) ]} [options] [path/to/ChangeLog] [path/to/another/Change
entries (default: --no-continue)
-f|--fix-merged [revision-range] fix git-merged ChangeLog entries; if a revision-range
is specified, run git filter-branch on the range
+ -m|--merge-driver %O %A %B act as a git merge-driver on files %O %A %B
-h|--help show this help message
-w|--[no-]warnings show or suppress warnings (default: show warnings)
__END__
@@ -118,6 +128,14 @@ if (defined $fixMerged && length($fixMerged) > 0) {
my $commitRange = $fixMerged;
$commitRange = $commitRange . "..HEAD" if index($commitRange, "..") < 0;
fixMergedChangeLogs($commitRange, @changeLogFiles);
+} elsif ($mergeDriver) {
+ my ($base, $theirs, $ours) = @ARGV;
+ if (mergeChanges($ours, $base, $theirs)) {
+ unlink($ours);
+ copy($theirs, $ours) or die $!;
+ } else {
+ exit 1;
+ }
} elsif (@changeLogFiles) {
for my $file (@changeLogFiles) {
if (defined $fixMerged) {
diff --git a/WebKitTools/Scripts/run-gtk-tests b/WebKitTools/Scripts/run-gtk-tests
new file mode 100644
index 0000000..9a57319
--- /dev/null
+++ b/WebKitTools/Scripts/run-gtk-tests
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib $FindBin::Bin;
+use webkitdirs;
+
+# This initializes the correct configuration (Release/Debug)
+setConfiguration();
+
+my $productDir = productDir();
+my @unitTests = glob $productDir . "/Programs/unittests/*";
+if ($#unitTests < 1) {
+ die "ERROR: tests not found in $productDir.\n";
+}
+system "gtester -k @unitTests"
diff --git a/WebKitTools/Scripts/test-webkitpy b/WebKitTools/Scripts/test-webkitpy
index cfd3434..8617330 100755
--- a/WebKitTools/Scripts/test-webkitpy
+++ b/WebKitTools/Scripts/test-webkitpy
@@ -44,6 +44,7 @@ from webkitpy.credentials_unittest import *
from webkitpy.diff_parser_unittest import *
from webkitpy.executive_unittest import *
from webkitpy.grammar_unittest import *
+from webkitpy.layout_tests.port.mac_unittest import *
from webkitpy.multicommandtool_unittest import *
from webkitpy.networktransaction_unittest import *
from webkitpy.patchcollection_unittest import *
diff --git a/WebKitTools/Scripts/webkit-build-directory b/WebKitTools/Scripts/webkit-build-directory
index a85c587..bf7d66d 100755
--- a/WebKitTools/Scripts/webkit-build-directory
+++ b/WebKitTools/Scripts/webkit-build-directory
@@ -34,31 +34,35 @@ use Getopt::Long;
use lib $FindBin::Bin;
use webkitdirs;
-my $showBaseProductDirectory = 0;
+my $showConfigurationDirectory = 0;
my $showHelp = 0;
+my $showTopLevelDirectory = 0;
+
my $programName = basename($0);
my $usage = <<EOF;
Usage: $programName [options]
- --base Show the root build directory instead of one corresponding to the current target (e.g. Debug, Release)
- --debug Show build directory for the Debug target
- -h|--help Show this help message
- --release Show build directory for the Release target
+ --configuration Show the build directory for a specific configuration (e.g. Debug, Release. Defaults to the active configuration set by set-webkit-configuration)
+ -h|--help Show this help message
+ --top-level Show the top-level build directory
+
+Either --configuration or --top-level is required.
EOF
setConfiguration(); # Figure out from the command line if we're --debug or --release or the default.
my $getOptionsResult = GetOptions(
- 'base' => \$showBaseProductDirectory,
+ 'configuration' => \$showConfigurationDirectory,
+ 'top-level' => \$showTopLevelDirectory,
'help|h' => \$showHelp,
);
-if (!$getOptionsResult || $showHelp) {
+if (!$getOptionsResult || $showHelp || (!$showConfigurationDirectory && !$showTopLevelDirectory)) {
print STDERR $usage;
exit 1;
}
-if ($showBaseProductDirectory) {
+if ($showTopLevelDirectory) {
print baseProductDir() . "\n";
} else {
print productDir() . "\n";
diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm
index a788b3d..7985790 100644
--- a/WebKitTools/Scripts/webkitdirs.pm
+++ b/WebKitTools/Scripts/webkitdirs.pm
@@ -614,9 +614,17 @@ sub qtFeatureDefaults()
return %qtFeatureDefaults;
}
+sub commandExists($)
+{
+ my $command = shift;
+ my $devnull = File::Spec->devnull();
+ return `$command --version 2> $devnull`;
+}
+
sub determineQtFeatureDefaults()
{
return if %qtFeatureDefaults;
+ die "ERROR: qmake missing but required to build WebKit.\n" if not commandExists("qmake");
my $originalCwd = getcwd();
chdir File::Spec->catfile(sourceDir(), "WebCore");
my $defaults = `qmake CONFIG+=compute_defaults 2>&1`;
@@ -891,10 +899,9 @@ sub checkRequiredSystemConfig
my @cmds = qw(flex bison gperf);
my @missing = ();
foreach my $cmd (@cmds) {
- if (not `$cmd --version`) {
- push @missing, $cmd;
- }
+ push @missing, $cmd if not commandExists($cmd);
}
+
if (@missing) {
my $list = join ", ", @missing;
die "ERROR: $list missing but required to build WebKit.\n";
@@ -1162,7 +1169,7 @@ sub qtMakeCommand($)
#print "default spec: " . $mkspec . "\n";
#print "compiler found: " . $compiler . "\n";
- if ($compiler eq "cl") {
+ if ($compiler && $compiler eq "cl") {
return "nmake";
}
@@ -1454,7 +1461,7 @@ sub runSafari
my ($debugger) = @_;
if (isAppleMacWebKit()) {
- return system "$FindBin::Bin/gdb-safari", @ARGV if $debugger;
+ return system "$FindBin::Bin/gdb-safari", argumentsForConfiguration() if $debugger;
my $productDir = productDir();
print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
diff --git a/WebKitTools/Scripts/webkitpy/committers.py b/WebKitTools/Scripts/webkitpy/committers.py
index 7af0987..6413243 100644
--- a/WebKitTools/Scripts/webkitpy/committers.py
+++ b/WebKitTools/Scripts/webkitpy/committers.py
@@ -82,7 +82,7 @@ committers_unable_to_review = [
Committer("Brian Weinstein", "bweinstein@apple.com"),
Committer("Cameron McCormack", "cam@webkit.org"),
Committer("Carol Szabo", "carol.szabo@nokia.com"),
- Committer("Chang Shu", "chang.shu@nokia.com"),
+ Committer("Chang Shu", "Chang.Shu@nokia.com"),
Committer("Chris Fleizach", "cfleizach@apple.com"),
Committer("Chris Jerdonek", "cjerdonek@webkit.org"),
Committer("Chris Marrin", "cmarrin@apple.com"),
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/__init__.py b/WebKitTools/Scripts/webkitpy/layout_tests/__init__.py
new file mode 100644
index 0000000..ef65bee
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/__init__.py
@@ -0,0 +1 @@
+# Required for Python to search this directory for module files
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py
index a3650ed..01add62 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py
@@ -35,7 +35,6 @@ import logging
import os
import re
import sys
-import time
import simplejson
@@ -133,10 +132,9 @@ class TestExpectations:
def has_modifier(self, test, modifier):
return self._expected_failures.has_modifier(test, modifier)
- def remove_platform_from_file(self, tests, platform, backup=False):
- return self._expected_failures.remove_platform_from_file(tests,
- platform,
- backup)
+ def remove_platform_from_expectations(self, tests, platform):
+ return self._expected_failures.remove_platform_from_expectations(
+ tests, platform)
def strip_comments(line):
@@ -373,8 +371,9 @@ class TestExpectationsFile:
def contains(self, test):
return test in self._test_to_expectations
- def remove_platform_from_file(self, tests, platform, backup=False):
- """Remove the platform option from test expectations file.
+ def remove_platform_from_expectations(self, tests, platform):
+ """Returns a copy of the expectations with the tests matching the
+ platform remove.
If a test is in the test list and has an option that matches the given
platform, remove the matching platform and save the updated test back
@@ -384,24 +383,13 @@ class TestExpectationsFile:
Args:
tests: list of tests that need to update..
platform: which platform option to remove.
- backup: if true, the original test expectations file is saved as
- [self.TEST_LIST].orig.YYYYMMDDHHMMSS
Returns:
- no
+ the updated string.
"""
- # FIXME - remove_platform_from file worked by writing a new
- # test_expectations.txt file over the old one. Now that we're just
- # parsing strings, we need to change this to return the new
- # expectations string.
- raise NotImplementedException('remove_platform_from_file')
-
- new_file = self._path + '.new'
- logging.debug('Original file: "%s"', self._path)
- logging.debug('New file: "%s"', new_file)
f_orig = self._get_iterable_expectations()
- f_new = open(new_file, 'w')
+ f_new = []
tests_removed = 0
tests_updated = 0
@@ -413,7 +401,7 @@ class TestExpectationsFile:
if action == NO_CHANGE:
# Save the original line back to the file
logging.debug('No change to test: %s', line)
- f_new.write(line)
+ f_new.append(line)
elif action == REMOVE_TEST:
tests_removed += 1
logging.info('Test removed: %s', line)
@@ -421,7 +409,7 @@ class TestExpectationsFile:
parts = line.split(':')
new_options = parts[0].replace(platform.upper() + ' ', '', 1)
new_line = ('%s:%s' % (new_options, parts[1]))
- f_new.write(new_line)
+ f_new.append(new_line)
tests_updated += 1
logging.info('Test updated: ')
logging.info(' old: %s', line)
@@ -440,7 +428,7 @@ class TestExpectationsFile:
if not p in (platform.upper(), 'WIN-VISTA', 'WIN-7'):
new_options += p + ' '
new_line = ('%s:%s' % (new_options, parts[1]))
- f_new.write(new_line)
+ f_new.append(new_line)
tests_updated += 1
logging.info('Test updated: ')
logging.info(' old: %s', line)
@@ -452,23 +440,7 @@ class TestExpectationsFile:
logging.info('Total tests removed: %d', tests_removed)
logging.info('Total tests updated: %d', tests_updated)
- f_orig.close()
- f_new.close()
-
- if backup:
- date_suffix = time.strftime('%Y%m%d%H%M%S',
- time.localtime(time.time()))
- backup_file = ('%s.orig.%s' % (self._path, date_suffix))
- if os.path.exists(backup_file):
- os.remove(backup_file)
- logging.info('Saving original file to "%s"', backup_file)
- os.rename(self._path, backup_file)
- else:
- os.remove(self._path)
-
- logging.debug('Saving new file to "%s"', self._path)
- os.rename(new_file, self._path)
- return True
+ return "".join(f_new)
def parse_expectations_line(self, line, lineno):
"""Parses a line from test_expectations.txt and returns a tuple
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
index ce06b44..2b25e29 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
@@ -83,18 +83,20 @@ class Port(object):
interface so that it can be overriden for testing purposes."""
return actual_text != expected_text
- def diff_image(self, actual_filename, expected_filename, diff_filename):
+ def diff_image(self, actual_filename, expected_filename,
+ diff_filename=None):
"""Compare two image files and produce a delta image file.
Return 1 if the two files are different, 0 if they are the same.
Also produce a delta image of the two images and write that into
- |diff_filename|.
+ |diff_filename| if it is not None.
While this is a generic routine, we include it in the Port
interface so that it can be overriden for testing purposes."""
executable = self._path_to_image_diff()
- cmd = [executable, '--diff', actual_filename, expected_filename,
- diff_filename]
+ cmd = [executable, '--diff', actual_filename, expected_filename]
+ if diff_filename:
+ cmd.append(diff_filename)
result = 1
try:
result = subprocess.call(cmd)
@@ -267,6 +269,7 @@ class Port(object):
used by run-chromium-webkit-tests."""
raise NotImplementedError('Port.num_cores')
+ # FIXME: This could be replaced by functions in webkitpy.scm.
def path_from_webkit_base(self, *comps):
"""Returns the full path to path made by joining the top of the
WebKit source tree and the list of path components in |*comps|."""
@@ -275,6 +278,17 @@ class Port(object):
self._webkit_base_dir = abspath[0:abspath.find('WebKitTools')]
return os.path.join(self._webkit_base_dir, *comps)
+ # FIXME: Callers should eventually move to scm.script_path.
+ def script_path(self, script_name):
+ return self.path_from_webkit_base("WebKitTools", "Scripts", script_name)
+
+ def path_to_test_expectations_file(self):
+ """Update the test expectations to the passed-in string.
+
+ This is used by the rebaselining tool. Raises NotImplementedError
+ if the port does not use expectations files."""
+ raise NotImplementedError('Port.path_to_test_expectations_file')
+
def remove_directory(self, *path):
"""Recursively removes a directory, even if it's marked read-only.
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
index 70a8dea..1123376 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -88,6 +88,10 @@ class ChromiumPort(base.Port):
self._chromium_base_dir = abspath[0:abspath.find('third_party')]
return os.path.join(self._chromium_base_dir, *comps)
+ def path_to_test_expectations_file(self):
+ return self.path_from_chromium_base('webkit', 'tools', 'layout_tests',
+ 'test_expectations.txt')
+
def results_directory(self):
return self.path_from_chromium_base('webkit', self._options.target,
self._options.results_directory)
@@ -128,13 +132,12 @@ class ChromiumPort(base.Port):
def test_base_platform_names(self):
return ('linux', 'mac', 'win')
- def test_expectations(self, options=None):
+ def test_expectations(self):
"""Returns the test expectations for this port.
Basically this string should contain the equivalent of a
test_expectations file. See test_expectations.py for more details."""
- expectations_file = self.path_from_chromium_base('webkit', 'tools',
- 'layout_tests', 'test_expectations.txt')
+ expectations_file = self.path_to_test_expectations_file()
return file(expectations_file, "r").read()
def test_platform_names(self):
@@ -154,7 +157,6 @@ class ChromiumPort(base.Port):
return self.path_from_chromium_base('webkit', 'data', 'layout_tests',
'platform', platform, 'LayoutTests')
-
class ChromiumDriver(base.Driver):
"""Abstract interface for the DumpRenderTree interface."""
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
index 8fd5343..b817251 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
@@ -43,6 +43,8 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
def __init__(self, port_name=None, options=None):
if port_name is None:
port_name = 'chromium-linux'
+ if options and not hasattr(options, 'target'):
+ options.target = 'Release'
chromium.ChromiumPort.__init__(self, port_name, options)
def baseline_search_path(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
index 7e7b4ca..bcffcf8 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
@@ -43,6 +43,8 @@ class ChromiumMacPort(chromium.ChromiumPort):
def __init__(self, port_name=None, options=None):
if port_name is None:
port_name = 'chromium-mac'
+ if options and not hasattr(options, 'target'):
+ options.target = 'Release'
chromium.ChromiumPort.__init__(self, port_name, options)
def baseline_search_path(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
index 352916c..5eb0ba1 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
@@ -44,6 +44,8 @@ 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, 'target'):
+ options.target = 'Release'
chromium.ChromiumPort.__init__(self, port_name, options)
def baseline_search_path(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
index 4b73cec..d355f62 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py
@@ -67,8 +67,16 @@ class MacPort(base.Port):
return dirs
def check_sys_deps(self):
- # FIXME: This should run build-dumprendertree.
- # This should also validate that all of the tool paths are valid.
+ if executive.run_command([self.script_path("build-dumprendertree")], return_exit_code=True) != 0:
+ return False
+
+ driver_path = self._path_to_driver()
+ if not os.path.exists(driver_path):
+ logging.error("DumpRenderTree was not found at %s" % driver_path)
+ return False
+
+ # This should also validate that the ImageDiff path is valid (once this script knows how to use ImageDiff).
+ # https://bugs.webkit.org/show_bug.cgi?id=34826
return True
def num_cores(self):
@@ -103,8 +111,67 @@ class MacPort(base.Port):
# to return something.
return ('mac',)
+ def _skipped_file_paths(self):
+ # FIXME: This method will need to be made work for non-mac platforms and moved into base.Port.
+ skipped_files = []
+ if self._name in ('mac-tiger', 'mac-leopard', 'mac-snowleopard'):
+ skipped_files.append(os.path.join(
+ self._webkit_baseline_path(self._name), 'Skipped'))
+ skipped_files.append(os.path.join(self._webkit_baseline_path('mac'),
+ 'Skipped'))
+ return skipped_files
+
+ def _tests_for_other_platforms(self):
+ # The original run-webkit-tests builds up a "whitelist" of tests to run, and passes that to DumpRenderTree.
+ # run-chromium-webkit-tests assumes we run *all* tests and test_expectations.txt functions as a blacklist.
+ # FIXME: This list could be dynamic based on platform name and pushed into base.Port.
+ return [
+ "platform/chromium",
+ "platform/gtk",
+ "platform/qt",
+ "platform/win",
+ ]
+
+ def _tests_for_disabled_features(self):
+ # FIXME: This should use the feature detection from webkitperl/features.pm to match run-webkit-tests.
+ # For now we hard-code a list of features known to be disabled on the Mac platform.
+ disabled_feature_tests = [
+ "fast/xhtmlmp",
+ "http/tests/wml",
+ "mathml",
+ "wml",
+ ]
+ # FIXME: webarchive tests expect to read-write from -expected.webarchive files instead of .txt files.
+ # This script doesn't know how to do that yet, so pretend they're just "disabled".
+ webarchive_tests = [
+ "webarchive",
+ "svg/webarchive",
+ "http/tests/webarchive",
+ "svg/custom/image-with-prefix-in-webarchive.svg",
+ ]
+ return disabled_feature_tests + webarchive_tests
+
+ def _tests_from_skipped_file(self, skipped_file):
+ tests_to_skip = []
+ for line in skipped_file.readlines():
+ line = line.strip()
+ if line.startswith('#') or not len(line):
+ continue
+ tests_to_skip.append(line)
+ return tests_to_skip
+
+ def _expectations_from_skipped_files(self):
+ tests_to_skip = []
+ for filename in self._skipped_file_paths():
+ if not os.path.exists(filename):
+ logging.warn("Failed to open Skipped file: %s" % filename)
+ continue
+ skipped_file = file(filename)
+ tests_to_skip.extend(self._tests_from_skipped_file(skipped_file))
+ skipped_file.close()
+ return tests_to_skip
+
def test_expectations(self):
- #
# The WebKit mac port uses 'Skipped' files at the moment. Each
# file contains a list of files or directories to be skipped during
# the test run. The total list of tests to skipped is given by the
@@ -112,44 +179,11 @@ class MacPort(base.Port):
# a version-specific file found in platform/X-version. Duplicate
# entries are allowed. This routine reads those files and turns
# contents into the format expected by test_expectations.
- expectations = []
- skipped_files = []
- if self._name in ('mac-tiger', 'mac-leopard', 'mac-snowleopard'):
- skipped_files.append(os.path.join(
- self._webkit_baseline_path(self._name), 'Skipped'))
- skipped_files.append(os.path.join(self._webkit_baseline_path('mac'),
- 'Skipped'))
- for filename in skipped_files:
- if os.path.exists(filename):
- f = file(filename)
- for l in f.readlines():
- l = l.strip()
- if not l.startswith('#') and len(l):
- l = 'BUG_SKIPPED SKIP : ' + l + ' = FAIL'
- if l not in expectations:
- expectations.append(l)
- f.close()
-
- # TODO - figure out how to check for these dynamically
- expectations.append('BUG_SKIPPED SKIP : fast/wcss = FAIL')
- expectations.append('BUG_SKIPPED SKIP : fast/xhtmlmp = FAIL')
- expectations.append('BUG_SKIPPED SKIP : http/tests/wml = FAIL')
- expectations.append('BUG_SKIPPED SKIP : mathml = FAIL')
- expectations.append('BUG_SKIPPED SKIP : platform/chromium = FAIL')
- expectations.append('BUG_SKIPPED SKIP : platform/gtk = FAIL')
- expectations.append('BUG_SKIPPED SKIP : platform/qt = FAIL')
- expectations.append('BUG_SKIPPED SKIP : platform/win = FAIL')
- expectations.append('BUG_SKIPPED SKIP : wml = FAIL')
-
- # TODO - figure out how to handle webarchive tests
- expectations.append('BUG_SKIPPED SKIP : webarchive = PASS')
- expectations.append('BUG_SKIPPED SKIP : svg/webarchive = PASS')
- expectations.append('BUG_SKIPPED SKIP : http/tests/webarchive = PASS')
- expectations.append('BUG_SKIPPED SKIP : svg/custom/'
- 'image-with-prefix-in-webarchive.svg = PASS')
-
- expectations_str = '\n'.join(expectations)
- return expectations_str
+ tests_to_skip = set(self._expectations_from_skipped_files()) # Use a set to allow duplicates
+ tests_to_skip.update(self._tests_for_other_platforms())
+ tests_to_skip.update(self._tests_for_disabled_features())
+ expectations = map(lambda test_path: "BUG_SKIPPED SKIP : %s = FAIL" % test_path, tests_to_skip)
+ return "\n".join(expectations)
def test_platform_name(self):
# At the moment we don't use test platform names, but we have
@@ -180,7 +214,7 @@ class MacPort(base.Port):
def _build_path(self, *comps):
if not self._cached_build_root:
- self._cached_build_root = executive.run_command(["webkit-build-directory", "--base"]).rstrip()
+ self._cached_build_root = executive.run_command([self.script_path("webkit-build-directory"), "--top-level"]).rstrip()
return os.path.join(self._cached_build_root, self._options.target, *comps)
def _kill_process(self, pid):
@@ -390,7 +424,6 @@ class MacDriver(base.Driver):
return (crash, timeout, actual_image_hash,
''.join(output), ''.join(error))
- pass
def stop(self):
if self._proc:
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
new file mode 100644
index 0000000..e47a4a4
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
@@ -0,0 +1,66 @@
+# 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 unittest
+import mac
+import StringIO
+
+class MacTest(unittest.TestCase):
+
+ def test_skipped_file_paths(self):
+ port = mac.MacPort()
+ skipped_paths = port._skipped_file_paths()
+ # FIXME: _skipped_file_paths should return WebKit-relative paths.
+ # So to make it unit testable, we strip the WebKit directory from the path.
+ relative_paths = [path[len(port.path_from_webkit_base()):] for path in skipped_paths]
+ self.assertEqual(relative_paths, ['LayoutTests/platform/mac-leopard/Skipped', 'LayoutTests/platform/mac/Skipped'])
+
+ example_skipped_file = """
+# <rdar://problem/5647952> fast/events/mouseout-on-window.html needs mac DRT to issue mouse out events
+fast/events/mouseout-on-window.html
+
+# <rdar://problem/5643675> window.scrollTo scrolls a window with no scrollbars
+fast/events/attempt-scroll-with-no-scrollbars.html
+
+# see bug <rdar://problem/5646437> REGRESSION (r28015): svg/batik/text/smallFonts fails
+svg/batik/text/smallFonts.svg
+"""
+ example_skipped_tests = [
+ "fast/events/mouseout-on-window.html",
+ "fast/events/attempt-scroll-with-no-scrollbars.html",
+ "svg/batik/text/smallFonts.svg",
+ ]
+
+ def test_skipped_file_paths(self):
+ port = mac.MacPort()
+ skipped_file = StringIO.StringIO(self.example_skipped_file)
+ self.assertEqual(port._tests_from_skipped_file(skipped_file), self.example_skipped_tests)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
index 0bc6e7c..c3e97be 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
@@ -55,7 +55,8 @@ class TestPort(base.Port):
def check_sys_deps(self):
return True
- def diff_image(self, actual_filename, expected_filename, diff_filename):
+ def diff_image(self, actual_filename, expected_filename,
+ diff_filename=None):
return False
def compare_text(self, actual_text, expected_text):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
index ba8a5e9..54c2f6f 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
@@ -159,6 +159,7 @@ class PyWebSocket(http_server.Lighttpd):
'-p', str(self._port),
'-d', self._layout_tests,
'-s', self._web_socket_tests,
+ '-x', '/websocket/tests/cookies',
'-l', error_log,
]
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 83cf99de..4604a1a 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
@@ -54,7 +54,7 @@ import urllib
import webbrowser
import zipfile
-from layout_package import path_utils
+import port
from layout_package import test_expectations
from test_types import image_diff
from test_types import text_diff
@@ -200,9 +200,10 @@ class Rebaseliner(object):
REVISION_REGEX = r'<a href=\"(\d+)/\">'
- def __init__(self, platform, options):
- self._file_dir = path_utils.path_from_base('webkit', 'tools',
+ def __init__(self, port, platform, options):
+ self._file_dir = port.path_from_chromium_base('webkit', 'tools',
'layout_tests')
+ self._port = port
self._platform = platform
self._options = options
self._rebaselining_tests = []
@@ -212,10 +213,12 @@ class Rebaseliner(object):
# -. compile list of tests that need rebaselining.
# -. update the tests in test_expectations file after rebaseline
# is done.
+ expectations_str = self._port.test_expectations()
self._test_expectations = \
- test_expectations.TestExpectations(None,
- self._file_dir,
- platform,
+ test_expectations.TestExpectations(self._port,
+ None,
+ expectations_str,
+ self._platform,
False,
False)
@@ -359,7 +362,6 @@ class Rebaseliner(object):
latest_revision = self._get_latest_revision(url_base)
if latest_revision is None or latest_revision <= 0:
return None
-
archive_url = ('%s%s/layout-test-results.zip' % (url_base,
latest_revision))
logging.info('Archive url: "%s"', archive_url)
@@ -399,7 +401,7 @@ class Rebaseliner(object):
for name in zip_namelist:
logging.debug(' ' + name)
- platform = path_utils.platform_name(self._platform)
+ platform = self._port.name()
logging.debug('Platform dir: "%s"', platform)
test_no = 1
@@ -412,7 +414,7 @@ class Rebaseliner(object):
test_basename = os.path.splitext(test)[0]
for suffix in BASELINE_SUFFIXES:
archive_test_name = ('layout-test-results/%s-actual%s' %
- (test_basename, suffix))
+ (test_basename, suffix))
logging.debug(' Archive test file name: "%s"',
archive_test_name)
if not archive_test_name in zip_namelist:
@@ -431,7 +433,7 @@ class Rebaseliner(object):
expected_filename = '%s-expected%s' % (test_basename, suffix)
expected_fullpath = os.path.join(
- path_utils.chromium_baseline_path(platform),
+ self._port._chromium_baseline_path(platform),
expected_filename)
expected_fullpath = os.path.normpath(expected_fullpath)
logging.debug(' Expected file full path: "%s"',
@@ -443,17 +445,17 @@ class Rebaseliner(object):
# and lower
# levels and remove all duplicated baselines.
if self._is_dup_baseline(temp_name,
- expected_fullpath,
- test,
- suffix,
- self._platform):
+ expected_fullpath,
+ test,
+ suffix,
+ self._platform):
os.remove(temp_name)
self._delete_baseline(expected_fullpath)
continue
# Create the new baseline directory if it doesn't already
# exist.
- path_utils.maybe_make_directory(
+ self._port.maybe_make_directory(
os.path.dirname(expected_fullpath))
shutil.move(temp_name, expected_fullpath)
@@ -497,9 +499,9 @@ class Rebaseliner(object):
True if the baseline is unnecessary.
False otherwise.
"""
- test_filepath = os.path.join(path_utils.layout_tests_dir(), test)
- all_baselines = path_utils.expected_baselines(test_filepath,
- suffix, platform, True)
+ test_filepath = os.path.join(self._port.layout_tests_dir(), test)
+ all_baselines = self._port.expected_baselines(test_filepath,
+ suffix, True)
for (fallback_dir, fallback_file) in all_baselines:
if fallback_dir and fallback_file:
fallback_fullpath = os.path.normpath(
@@ -534,11 +536,11 @@ class Rebaseliner(object):
return True
if ext1 == '.PNG':
- return image_diff.ImageDiff(self._platform, '').diff_files(file1,
- file2)
+ return image_diff.ImageDiff(self._port, self._platform,
+ '').diff_files(self._port, file1, file2)
else:
- return text_diff.TestTextDiff(self._platform, '').diff_files(file1,
- file2)
+ return text_diff.TestTextDiff(self._port, self._platform,
+ '').diff_files(self._port, file1, file2)
def _delete_baseline(self, filename):
"""Remove the file from repository and delete it from disk.
@@ -570,8 +572,21 @@ class Rebaseliner(object):
"""
if self._rebaselined_tests:
- self._test_expectations.remove_platform_from_file(
- self._rebaselined_tests, self._platform, backup)
+ new_expectations = (
+ self._test_expectations.remove_platform_from_expectations(
+ self._rebaselined_tests, self._platform))
+ path = self._port.path_to_test_expectations_file()
+ if backup:
+ date_suffix = time.strftime('%Y%m%d%H%M%S',
+ time.localtime(time.time()))
+ backup_file = ('%s.orig.%s' % (path, date_suffix))
+ if os.path.exists(backup_file):
+ os.remove(backup_file)
+ logging.info('Saving original file to "%s"', backup_file)
+ os.rename(path, backup_file)
+ f = open(path, "w")
+ f.write(new_expectations)
+ f.close()
else:
logging.info('No test was rebaselined so nothing to remove.')
@@ -777,8 +792,9 @@ class HtmlGenerator(object):
'<img style="width: 200" src="%(uri)s" /></a></td>')
HTML_TR = '<tr>%s</tr>'
- def __init__(self, options, platforms, rebaselining_tests):
+ def __init__(self, port, options, platforms, rebaselining_tests):
self._html_directory = options.html_directory
+ self._port = port
self._platforms = platforms
self._rebaselining_tests = rebaselining_tests
self._html_file = os.path.join(options.html_directory,
@@ -817,7 +833,7 @@ class HtmlGenerator(object):
logging.info('Launching html: "%s"', self._html_file)
- html_uri = path_utils.filename_to_uri(self._html_file)
+ html_uri = self._port.filename_to_uri(self._html_file)
webbrowser.open(html_uri, 1)
logging.info('Html launched.')
@@ -855,13 +871,13 @@ class HtmlGenerator(object):
links = ''
if os.path.exists(old_file):
links += html_td_link % {
- 'uri': path_utils.filename_to_uri(old_file),
+ 'uri': self._port.filename_to_uri(old_file),
'name': baseline_filename}
else:
logging.info(' No old baseline file: "%s"', old_file)
links += self.HTML_TD_NOLINK % ''
- links += html_td_link % {'uri': path_utils.filename_to_uri(new_file),
+ links += html_td_link % {'uri': self._port.filename_to_uri(new_file),
'name': baseline_filename}
diff_file = get_result_file_fullpath(self._html_directory,
@@ -869,7 +885,7 @@ class HtmlGenerator(object):
'diff')
logging.info(' Baseline diff file: "%s"', diff_file)
if os.path.exists(diff_file):
- links += html_td_link % {'uri': path_utils.filename_to_uri(
+ links += html_td_link % {'uri': self._port.filename_to_uri(
diff_file), 'name': 'Diff'}
else:
logging.info(' No baseline diff file: "%s"', diff_file)
@@ -908,8 +924,8 @@ class HtmlGenerator(object):
rows.append(self.HTML_TR % row)
if rows:
- test_path = os.path.join(path_utils.layout_tests_dir(), test)
- html = self.HTML_TR_TEST % (path_utils.filename_to_uri(test_path),
+ test_path = os.path.join(self._port.layout_tests_dir(), test)
+ html = self.HTML_TR_TEST % (self._port.filename_to_uri(test_path),
test)
html += self.HTML_TEST_DETAIL % ' '.join(rows)
@@ -967,6 +983,7 @@ def main():
' rebaselining comparison.'))
options = option_parser.parse_args()[0]
+ port_obj = port.get(None, options)
# Set up our logging format.
log_level = logging.INFO
@@ -1002,7 +1019,7 @@ def main():
rebaselining_tests = set()
backup = options.backup
for platform in rebaseline_platforms:
- rebaseliner = Rebaseliner(platform, options)
+ rebaseliner = Rebaseliner(port_obj, platform, options)
logging.info('')
log_dashed_string('Rebaseline started', platform)
@@ -1017,7 +1034,8 @@ def main():
logging.info('')
log_dashed_string('Rebaselining result comparison started', None)
- html_generator = HtmlGenerator(options,
+ html_generator = HtmlGenerator(port_obj,
+ options,
rebaseline_platforms,
rebaselining_tests)
html_generator.generate_html()
diff --git a/WebKitTools/Scripts/webkitpy/style/checker.py b/WebKitTools/Scripts/webkitpy/style/checker.py
index fbda8cb..9beda9e 100644
--- a/WebKitTools/Scripts/webkitpy/style/checker.py
+++ b/WebKitTools/Scripts/webkitpy/style/checker.py
@@ -30,24 +30,24 @@
"""Front end of some style-checker modules."""
import codecs
-import getopt
import os.path
import sys
from .. style_references import parse_patch
from error_handlers import DefaultStyleErrorHandler
from error_handlers import PatchStyleErrorHandler
-from filter import validate_filter_rules
from filter import FilterConfiguration
+from optparser import ArgumentParser
+from optparser import DefaultCommandOptionValues
from processors.common import check_no_carriage_return
from processors.common import categories as CommonCategories
from processors.cpp import CppProcessor
from processors.text import TextProcessor
-# These defaults are used by check-webkit-style.
-WEBKIT_DEFAULT_VERBOSITY = 1
-WEBKIT_DEFAULT_OUTPUT_FORMAT = 'emacs'
+# These are default option values for the command-line option parser.
+_DEFAULT_VERBOSITY = 1
+_DEFAULT_OUTPUT_FORMAT = 'emacs'
# FIXME: For style categories we will never want to have, remove them.
@@ -55,14 +55,16 @@ WEBKIT_DEFAULT_OUTPUT_FORMAT = 'emacs'
# modify the implementation and enable them.
#
# Throughout this module, we use "filter rule" rather than "filter"
-# for an individual boolean filter flag like "+foo". This allows us to
+# for an individual boolean filter flag like "+foo". This allows us to
# reserve "filter" for what one gets by collectively applying all of
# the filter rules.
#
-# The _WEBKIT_FILTER_RULES are prepended to any user-specified filter
-# rules. Since by default all errors are on, only include rules that
-# begin with a - sign.
-WEBKIT_DEFAULT_FILTER_RULES = [
+# The base filter rules are the filter rules that begin the list of
+# filter rules used to check style. For example, these rules precede
+# any user-specified filter rules. Since by default all categories are
+# checked, this list should normally include only rules that begin
+# with a "-" sign.
+_BASE_FILTER_RULES = [
'-build/endif_comment',
'-build/include_what_you_use', # <string> for std::string
'-build/storage_class', # const static
@@ -86,26 +88,24 @@ WEBKIT_DEFAULT_FILTER_RULES = [
]
-# FIXME: Change the second value of each tuple from a tuple to a list,
-# and alter the filter code so it accepts lists instead. (The
-# filter code will need to convert incoming values from a list
-# to a tuple prior to caching). This will make this
-# configuration setting a bit simpler since tuples have an
-# unusual syntax case.
-#
# The path-specific filter rules.
#
# This list is order sensitive. Only the first path substring match
# is used. See the FilterConfiguration documentation in filter.py
# for more information on this list.
+#
+# Each string appearing in this nested list should have at least
+# one associated unit test assertion. These assertions are located,
+# for example, in the test_path_rules_specifier() unit test method of
+# checker_unittest.py.
_PATH_RULES_SPECIFIER = [
# Files in these directories are consumers of the WebKit
# API and therefore do not follow the same header including
# discipline as WebCore.
(["WebKitTools/WebKitAPITest/",
"WebKit/qt/QGVLauncher/"],
- ("-build/include",
- "-readability/streams")),
+ ["-build/include",
+ "-readability/streams"]),
([# The GTK+ APIs use GTK+ naming style, which includes
# lower-cased, underscore-separated values.
"WebKit/gtk/webkit/",
@@ -116,13 +116,7 @@ _PATH_RULES_SPECIFIER = [
# QtTest module.
"WebKit/qt/tests/",
"JavaScriptCore/qt/tests"],
- ("-readability/naming",)),
- # These are test file patterns.
- (["_test.cpp",
- "_unittest.cpp",
- "_regtest.cpp"],
- ("-readability/streams", # Many unit tests use cout.
- "-runtime/rtti")),
+ ["-readability/naming"]),
]
@@ -131,7 +125,7 @@ _PATH_RULES_SPECIFIER = [
# future merges.
#
# Include a warning for skipped files that are less obvious.
-SKIPPED_FILES_WITH_WARNING = [
+_SKIPPED_FILES_WITH_WARNING = [
# The Qt API and tests do not follow WebKit style.
# They follow Qt style. :)
"gtk2drawing.c", # WebCore/platform/gtk/gtk2drawing.c
@@ -145,439 +139,56 @@ SKIPPED_FILES_WITH_WARNING = [
# Don't include a warning for skipped files that are more common
# and more obvious.
-SKIPPED_FILES_WITHOUT_WARNING = [
+_SKIPPED_FILES_WITHOUT_WARNING = [
"LayoutTests/"
]
# The maximum number of errors to report per file, per category.
# If a category is not a key, then it has no maximum.
-MAX_REPORTS_PER_CATEGORY = {
+_MAX_REPORTS_PER_CATEGORY = {
"whitespace/carriage_return": 1
}
-def style_categories():
+def _all_categories():
"""Return the set of all categories used by check-webkit-style."""
# Take the union across all processors.
return CommonCategories.union(CppProcessor.categories)
-def webkit_argument_defaults():
- """Return the DefaultArguments instance for use by check-webkit-style."""
- return ArgumentDefaults(WEBKIT_DEFAULT_OUTPUT_FORMAT,
- WEBKIT_DEFAULT_VERBOSITY,
- WEBKIT_DEFAULT_FILTER_RULES)
-
-
-def _create_usage(defaults):
- """Return the usage string to display for command help.
-
- Args:
- defaults: An ArgumentDefaults instance.
-
- """
- usage = """
-Syntax: %(program_name)s [--verbose=#] [--git-commit=<SingleCommit>] [--output=vs7]
- [--filter=-x,+y,...] [file] ...
-
- The style guidelines this tries to follow are here:
- http://webkit.org/coding/coding-style.html
-
- Every style error is given a confidence score from 1-5, with 5 meaning
- we are certain of the problem, and 1 meaning it could be a legitimate
- construct. This can miss some errors and does not substitute for
- code review.
-
- To prevent specific lines from being linted, add a '// NOLINT' comment to the
- end of the line.
-
- Linted extensions are .cpp, .c and .h. Other file types are ignored.
-
- The file parameter is optional and accepts multiple files. Leaving
- out the file parameter applies the check to all files considered changed
- by your source control management system.
-
- Flags:
-
- verbose=#
- A number 1-5 that restricts output to errors with a confidence
- score at or above this value. In particular, the value 1 displays
- all errors. The default is %(default_verbosity)s.
-
- git-commit=<SingleCommit>
- Checks the style of everything from the given commit to the local tree.
-
- output=vs7
- The output format, which may be one of
- emacs : to ease emacs parsing
- vs7 : compatible with Visual Studio
- Defaults to "%(default_output_format)s". Other formats are unsupported.
-
- filter=-x,+y,...
- A comma-separated list of boolean filter rules used to filter
- which categories of style guidelines to check. The script checks
- a category if the category passes the filter rules, as follows.
-
- Any webkit category starts out passing. All filter rules are then
- evaluated left to right, with later rules taking precedence. For
- example, the rule "+foo" passes any category that starts with "foo",
- and "-foo" fails any such category. The filter input "-whitespace,
- +whitespace/braces" fails the category "whitespace/tab" and passes
- "whitespace/braces".
-
- Examples: --filter=-whitespace,+whitespace/braces
- --filter=-whitespace,-runtime/printf,+runtime/printf_format
- --filter=-,+build/include_what_you_use
-
- Category names appear in error messages in brackets, for example
- [whitespace/indent]. To see a list of all categories available to
- %(program_name)s, along with which are enabled by default, pass
- the empty filter as follows:
- --filter=
-""" % {'program_name': os.path.basename(sys.argv[0]),
- 'default_verbosity': defaults.verbosity,
- 'default_output_format': defaults.output_format}
-
- return usage
-
-
-# FIXME: Eliminate support for "extra_flag_values".
-#
-# FIXME: Remove everything from ProcessorOptions except for the
-# information that can be passed via the command line, and
-# rename to something like CheckWebKitStyleOptions. This
-# includes, but is not limited to, removing the
-# max_reports_per_error attribute and the is_reportable()
-# method. See also the FIXME below to create a new class
-# called something like CheckerConfiguration.
-#
-# This class should not have knowledge of the flag key names.
-class ProcessorOptions(object):
-
- """A container to store options passed via the command line.
-
- Attributes:
- extra_flag_values: A string-string dictionary of all flag key-value
- pairs that are not otherwise represented by this
- class. The default is the empty dictionary.
-
- filter_configuration: A FilterConfiguration instance. The default
- is the "empty" filter configuration, which
- means that all errors should be checked.
-
- git_commit: A string representing the git commit to check.
- The default is None.
-
- max_reports_per_error: The maximum number of errors to report
- per file, per category.
-
- output_format: A string that is the output format. The supported
- output formats are "emacs" which emacs can parse
- and "vs7" which Microsoft Visual Studio 7 can parse.
-
- verbosity: An integer between 1-5 inclusive that restricts output
- to errors with a confidence score at or above this value.
- The default is 1, which reports all errors.
-
- """
- def __init__(self,
- extra_flag_values=None,
- filter_configuration = None,
- git_commit=None,
- max_reports_per_category=None,
- output_format="emacs",
- verbosity=1):
- if extra_flag_values is None:
- extra_flag_values = {}
- if filter_configuration is None:
- filter_configuration = FilterConfiguration()
- if max_reports_per_category is None:
- max_reports_per_category = {}
-
- if output_format not in ("emacs", "vs7"):
- raise ValueError('Invalid "output_format" parameter: '
- 'value must be "emacs" or "vs7". '
- 'Value given: "%s".' % output_format)
-
- if (verbosity < 1) or (verbosity > 5):
- raise ValueError('Invalid "verbosity" parameter: '
- "value must be an integer between 1-5 inclusive. "
- 'Value given: "%s".' % verbosity)
-
- self.extra_flag_values = extra_flag_values
- self.filter_configuration = filter_configuration
- self.git_commit = git_commit
- self.max_reports_per_category = max_reports_per_category
- self.output_format = output_format
- self.verbosity = verbosity
-
- # Useful for unit testing.
- def __eq__(self, other):
- """Return whether this ProcessorOptions instance is equal to another."""
- if self.extra_flag_values != other.extra_flag_values:
- return False
- if self.filter_configuration != other.filter_configuration:
- return False
- if self.git_commit != other.git_commit:
- return False
- if self.max_reports_per_category != other.max_reports_per_category:
- return False
- if self.output_format != other.output_format:
- return False
- if self.verbosity != other.verbosity:
- return False
-
- return True
-
- # Useful for unit testing.
- def __ne__(self, other):
- # Python does not automatically deduce this from __eq__().
- return not self.__eq__(other)
-
- def is_reportable(self, category, confidence_in_error, path):
- """Return whether an error is reportable.
-
- An error is reportable if the confidence in the error
- is at least the current verbosity level, and if the current
- filter says that the category should be checked for the
- given path.
-
- Args:
- category: A string that is a style category.
- confidence_in_error: An integer between 1 and 5, inclusive, that
- represents the application's confidence in
- the error. A higher number signifies greater
- confidence.
- path: The path of the file being checked
-
- """
- if confidence_in_error < self.verbosity:
- return False
-
- return self.filter_configuration.should_check(category, path)
-
-
-# This class should not have knowledge of the flag key names.
-class ArgumentDefaults(object):
-
- """A container to store default argument values.
-
- Attributes:
- output_format: A string that is the default output format.
- verbosity: An integer that is the default verbosity level.
- base_filter_rules: A list of strings that are boolean filter rules
- to prepend to any user-specified rules.
-
- """
-
- def __init__(self, default_output_format, default_verbosity,
- default_base_filter_rules):
- self.output_format = default_output_format
- self.verbosity = default_verbosity
- self.base_filter_rules = default_base_filter_rules
-
-
-class ArgumentPrinter(object):
-
- """Supports the printing of check-webkit-style command arguments."""
-
- def _flag_pair_to_string(self, flag_key, flag_value):
- return '--%(key)s=%(val)s' % {'key': flag_key, 'val': flag_value }
-
- def to_flag_string(self, options):
- """Return a flag string yielding the given ProcessorOptions instance.
-
- This method orders the flag values alphabetically by the flag key.
-
- Args:
- options: A ProcessorOptions instance.
-
- """
- flags = options.extra_flag_values.copy()
+def _check_webkit_style_defaults():
+ """Return the default command-line options for check-webkit-style."""
+ return DefaultCommandOptionValues(output_format=_DEFAULT_OUTPUT_FORMAT,
+ verbosity=_DEFAULT_VERBOSITY)
- flags['output'] = options.output_format
- flags['verbose'] = options.verbosity
- # Only include the filter flag if user-provided rules are present.
- user_rules = options.filter_configuration.user_rules
- if user_rules:
- flags['filter'] = ",".join(user_rules)
- if options.git_commit:
- flags['git-commit'] = options.git_commit
- flag_string = ''
- # Alphabetizing lets us unit test this method.
- for key in sorted(flags.keys()):
- flag_string += self._flag_pair_to_string(key, flags[key]) + ' '
+# This function assists in optparser not having to import from checker.
+def check_webkit_style_parser():
+ all_categories = _all_categories()
+ default_options = _check_webkit_style_defaults()
+ return ArgumentParser(all_categories=all_categories,
+ base_filter_rules=_BASE_FILTER_RULES,
+ default_options=default_options)
- return flag_string.strip()
+def check_webkit_style_configuration(options):
+ """Return a StyleCheckerConfiguration instance for check-webkit-style.
-class ArgumentParser(object):
-
- """Supports the parsing of check-webkit-style command arguments.
-
- Attributes:
- defaults: An ArgumentDefaults instance.
- create_usage: A function that accepts an ArgumentDefaults instance
- and returns a string of usage instructions.
- This defaults to the function used to generate the
- usage string for check-webkit-style.
- doc_print: A function that accepts a string parameter and that is
- called to display help messages. This defaults to
- sys.stderr.write().
+ Args:
+ options: A CommandOptionValues instance.
"""
+ filter_configuration = FilterConfiguration(
+ base_rules=_BASE_FILTER_RULES,
+ path_specific=_PATH_RULES_SPECIFIER,
+ user_rules=options.filter_rules)
- def __init__(self, argument_defaults, create_usage=None, doc_print=None):
- if create_usage is None:
- create_usage = _create_usage
- if doc_print is None:
- doc_print = sys.stderr.write
-
- self.defaults = argument_defaults
- self.create_usage = create_usage
- self.doc_print = doc_print
-
- def _exit_with_usage(self, error_message=''):
- """Exit and print a usage string with an optional error message.
-
- Args:
- error_message: A string that is an error message to print.
-
- """
- usage = self.create_usage(self.defaults)
- self.doc_print(usage)
- if error_message:
- sys.exit('\nFATAL ERROR: ' + error_message)
- else:
- sys.exit(1)
-
- def _exit_with_categories(self):
- """Exit and print the style categories and default filter rules."""
- self.doc_print('\nAll categories:\n')
- categories = style_categories()
- for category in sorted(categories):
- self.doc_print(' ' + category + '\n')
-
- self.doc_print('\nDefault filter rules**:\n')
- for filter_rule in sorted(self.defaults.base_filter_rules):
- self.doc_print(' ' + filter_rule + '\n')
- self.doc_print('\n**The command always evaluates the above rules, '
- 'and before any --filter flag.\n\n')
-
- sys.exit(0)
-
- def _parse_filter_flag(self, flag_value):
- """Parse the --filter flag, and return a list of filter rules.
-
- Args:
- flag_value: A string of comma-separated filter rules, for
- example "-whitespace,+whitespace/indent".
-
- """
- filters = []
- for uncleaned_filter in flag_value.split(','):
- filter = uncleaned_filter.strip()
- if not filter:
- continue
- filters.append(filter)
- return filters
-
- def parse(self, args, extra_flags=None):
- """Parse the command line arguments to check-webkit-style.
-
- Args:
- args: A list of command-line arguments as returned by sys.argv[1:].
- extra_flags: A list of flags whose values we want to extract, but
- are not supported by the ProcessorOptions class.
- An example flag "new_flag=". This defaults to the
- empty list.
-
- Returns:
- A tuple of (filenames, options)
-
- filenames: The list of filenames to check.
- options: A ProcessorOptions instance.
-
- """
- if extra_flags is None:
- extra_flags = []
-
- output_format = self.defaults.output_format
- verbosity = self.defaults.verbosity
- base_rules = self.defaults.base_filter_rules
-
- # The flags already supported by the ProcessorOptions class.
- flags = ['help', 'output=', 'verbose=', 'filter=', 'git-commit=']
-
- for extra_flag in extra_flags:
- if extra_flag in flags:
- raise ValueError('Flag \'%(extra_flag)s is duplicated '
- 'or already supported.' %
- {'extra_flag': extra_flag})
- flags.append(extra_flag)
-
- try:
- (opts, filenames) = getopt.getopt(args, '', flags)
- except getopt.GetoptError:
- # FIXME: Settle on an error handling approach: come up
- # with a consistent guideline as to when and whether
- # a ValueError should be raised versus calling
- # sys.exit when needing to interrupt execution.
- self._exit_with_usage('Invalid arguments.')
-
- extra_flag_values = {}
- git_commit = None
- user_rules = []
-
- for (opt, val) in opts:
- if opt == '--help':
- self._exit_with_usage()
- elif opt == '--output':
- output_format = val
- elif opt == '--verbose':
- verbosity = val
- elif opt == '--git-commit':
- git_commit = val
- elif opt == '--filter':
- if not val:
- self._exit_with_categories()
- # Prepend the defaults.
- user_rules = self._parse_filter_flag(val)
- else:
- extra_flag_values[opt] = val
-
- # Check validity of resulting values.
- if filenames and (git_commit != None):
- self._exit_with_usage('It is not possible to check files and a '
- 'specific commit at the same time.')
-
- if output_format not in ('emacs', 'vs7'):
- raise ValueError('Invalid --output value "%s": The only '
- 'allowed output formats are emacs and vs7.' %
- output_format)
-
- all_categories = style_categories()
- validate_filter_rules(user_rules, all_categories)
-
- verbosity = int(verbosity)
- if (verbosity < 1) or (verbosity > 5):
- raise ValueError('Invalid --verbose value %s: value must '
- 'be between 1-5.' % verbosity)
-
- filter_configuration = FilterConfiguration(base_rules=base_rules,
- path_specific=_PATH_RULES_SPECIFIER,
- user_rules=user_rules)
-
- options = ProcessorOptions(extra_flag_values=extra_flag_values,
- filter_configuration=filter_configuration,
- git_commit=git_commit,
- max_reports_per_category=MAX_REPORTS_PER_CATEGORY,
- output_format=output_format,
- verbosity=verbosity)
-
- return (filenames, options)
+ return StyleCheckerConfiguration(filter_configuration=filter_configuration,
+ max_reports_per_category=_MAX_REPORTS_PER_CATEGORY,
+ output_format=options.output_format,
+ stderr_write=sys.stderr.write,
+ verbosity=options.verbosity)
# Enum-like idiom
@@ -617,14 +228,14 @@ class ProcessorDispatcher(object):
def should_skip_with_warning(self, file_path):
"""Return whether the given file should be skipped with a warning."""
- for skipped_file in SKIPPED_FILES_WITH_WARNING:
+ for skipped_file in _SKIPPED_FILES_WITH_WARNING:
if file_path.find(skipped_file) >= 0:
return True
return False
def should_skip_without_warning(self, file_path):
"""Return whether the given file should be skipped without a warning."""
- for skipped_file in SKIPPED_FILES_WITHOUT_WARNING:
+ for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING:
if file_path.find(skipped_file) >= 0:
return True
return False
@@ -678,16 +289,95 @@ class ProcessorDispatcher(object):
return processor
-# FIXME: When creating the new CheckWebKitStyleOptions class as
-# described in a FIXME above, add a new class here called
-# something like CheckerConfiguration. The class should contain
-# attributes for options needed to process a file. This includes
-# a subset of the CheckWebKitStyleOptions attributes, a
-# FilterConfiguration attribute, an stderr_write attribute, a
-# max_reports_per_category attribute, etc. It can also include
-# the is_reportable() method. The StyleChecker should accept
-# an instance of this class rather than a ProcessorOptions
-# instance.
+class StyleCheckerConfiguration(object):
+
+ """Stores configuration values for the StyleChecker class.
+
+ Attributes:
+ max_reports_per_category: The maximum number of errors to report
+ per category, per file.
+
+ stderr_write: A function that takes a string as a parameter and
+ serves as stderr.write.
+
+ verbosity: An integer between 1-5 inclusive that restricts output
+ to errors with a confidence score at or above this value.
+
+ """
+
+ def __init__(self,
+ filter_configuration,
+ max_reports_per_category,
+ output_format,
+ stderr_write,
+ verbosity):
+ """Create a StyleCheckerConfiguration instance.
+
+ Args:
+ filter_configuration: A FilterConfiguration instance. The default
+ is the "empty" filter configuration, which
+ means that all errors should be checked.
+
+ max_reports_per_category: The maximum number of errors to report
+ per category, per file.
+
+ output_format: A string that is the output format. The supported
+ output formats are "emacs" which emacs can parse
+ and "vs7" which Microsoft Visual Studio 7 can parse.
+
+ stderr_write: A function that takes a string as a parameter and
+ serves as stderr.write.
+
+ verbosity: An integer between 1-5 inclusive that restricts output
+ to errors with a confidence score at or above this value.
+ The default is 1, which reports all errors.
+
+ """
+ self._filter_configuration = filter_configuration
+ self._output_format = output_format
+
+ self.max_reports_per_category = max_reports_per_category
+ self.stderr_write = stderr_write
+ self.verbosity = verbosity
+
+ def is_reportable(self, category, confidence_in_error, file_path):
+ """Return whether an error is reportable.
+
+ An error is reportable if both the confidence in the error is
+ at least the current verbosity level and the current filter
+ says the category should be checked for the given path.
+
+ Args:
+ category: A string that is a style category.
+ confidence_in_error: An integer between 1 and 5, inclusive, that
+ represents the application's confidence in
+ the error. A higher number signifies greater
+ confidence.
+ file_path: The path of the file being checked
+
+ """
+ if confidence_in_error < self.verbosity:
+ return False
+
+ return self._filter_configuration.should_check(category, file_path)
+
+ def write_style_error(self,
+ category,
+ confidence,
+ file_path,
+ line_number,
+ message):
+ """Write a style error to the configured stderr."""
+ if self._output_format == 'vs7':
+ format_string = "%s(%s): %s [%s] [%d]\n"
+ else:
+ format_string = "%s:%s: %s [%s] [%d]\n"
+
+ self.stderr_write(format_string % (file_path,
+ line_number,
+ message,
+ category,
+ confidence))
class StyleChecker(object):
@@ -698,28 +388,26 @@ class StyleChecker(object):
error_count: An integer that is the total number of reported
errors for the lifetime of this StyleChecker
instance.
- options: A ProcessorOptions instance that controls the behavior
- of style checking.
+ file_count: An integer that is the total number of processed
+ files. Note that the number of skipped files is
+ included in this value.
"""
- def __init__(self, options, stderr_write=None):
+ def __init__(self, configuration):
"""Create a StyleChecker instance.
Args:
- options: See options attribute.
- stderr_write: A function that takes a string as a parameter
- and that is called when a style error occurs.
- Defaults to sys.stderr.write. This should be
- used only for unit tests.
+ configuration: A StyleCheckerConfiguration instance that controls
+ the behavior of style checking.
"""
- if stderr_write is None:
- stderr_write = sys.stderr.write
-
- self._stderr_write = stderr_write
+ self._configuration = configuration
self.error_count = 0
- self.options = options
+ self.file_count = 0
+
+ def _stderr_write(self, message):
+ self._configuration.stderr_write(message)
def _increment_error_count(self):
"""Increment the total count of reported errors."""
@@ -784,13 +472,16 @@ class StyleChecker(object):
"""
if handle_style_error is None:
- handle_style_error = DefaultStyleErrorHandler(file_path,
- self.options,
- self._increment_error_count,
- self._stderr_write)
+ handle_style_error = DefaultStyleErrorHandler(
+ configuration=self._configuration,
+ file_path=file_path,
+ increment_error_count=
+ self._increment_error_count)
if process_file is None:
process_file = self._process_file
+ self.file_count += 1
+
dispatcher = ProcessorDispatcher()
if dispatcher.should_skip_without_warning(file_path):
@@ -800,7 +491,7 @@ class StyleChecker(object):
"style guide.\n" % file_path)
return
- verbosity = self.options.verbosity
+ verbosity = self._configuration.verbosity
processor = dispatcher.dispatch_processor(file_path,
handle_style_error,
verbosity)
@@ -820,9 +511,7 @@ class StyleChecker(object):
for file_path, diff in patch_files.iteritems():
style_error_handler = PatchStyleErrorHandler(diff,
file_path,
- self.options,
- self._increment_error_count,
- self._stderr_write)
+ self._configuration,
+ self._increment_error_count)
self.check_file(file_path, style_error_handler)
-
diff --git a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
index e1c9baf..fe12512 100755
--- a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py
@@ -37,119 +37,40 @@
import unittest
import checker as style
+from checker import _BASE_FILTER_RULES
+from checker import _MAX_REPORTS_PER_CATEGORY
from checker import _PATH_RULES_SPECIFIER as PATH_RULES_SPECIFIER
-from checker import style_categories
+from checker import _all_categories
+from checker import check_webkit_style_configuration
+from checker import check_webkit_style_parser
from checker import ProcessorDispatcher
-from checker import ProcessorOptions
from checker import StyleChecker
+from checker import StyleCheckerConfiguration
from filter import validate_filter_rules
from filter import FilterConfiguration
+from optparser import ArgumentParser
+from optparser import CommandOptionValues
from processors.cpp import CppProcessor
from processors.text import TextProcessor
-class ProcessorOptionsTest(unittest.TestCase):
-
- """Tests ProcessorOptions class."""
-
- def test_init(self):
- """Test __init__ constructor."""
- # Check default parameters.
- options = ProcessorOptions()
- self.assertEquals(options.extra_flag_values, {})
- self.assertEquals(options.filter_configuration, FilterConfiguration())
- self.assertEquals(options.git_commit, None)
- self.assertEquals(options.max_reports_per_category, {})
- self.assertEquals(options.output_format, "emacs")
- self.assertEquals(options.verbosity, 1)
-
- # Check argument validation.
- self.assertRaises(ValueError, ProcessorOptions, output_format="bad")
- ProcessorOptions(output_format="emacs") # No ValueError: works
- ProcessorOptions(output_format="vs7") # works
- self.assertRaises(ValueError, ProcessorOptions, verbosity=0)
- self.assertRaises(ValueError, ProcessorOptions, verbosity=6)
- ProcessorOptions(verbosity=1) # works
- ProcessorOptions(verbosity=5) # works
-
- # Check attributes.
- filter_configuration = FilterConfiguration(base_rules=["+"])
- options = ProcessorOptions(extra_flag_values={"extra_value" : 2},
- filter_configuration=filter_configuration,
- git_commit="commit",
- max_reports_per_category={"category": 3},
- output_format="vs7",
- verbosity=3)
- self.assertEquals(options.extra_flag_values, {"extra_value" : 2})
- self.assertEquals(options.filter_configuration, filter_configuration)
- self.assertEquals(options.git_commit, "commit")
- self.assertEquals(options.max_reports_per_category, {"category": 3})
- self.assertEquals(options.output_format, "vs7")
- self.assertEquals(options.verbosity, 3)
-
- def test_eq(self):
- """Test __eq__ equality function."""
- # == calls __eq__.
- self.assertTrue(ProcessorOptions() == ProcessorOptions())
-
- # Verify that a difference in any argument causes equality to fail.
- filter_configuration = FilterConfiguration(base_rules=["+"])
- options = ProcessorOptions(extra_flag_values={"extra_value" : 1},
- filter_configuration=filter_configuration,
- git_commit="commit",
- max_reports_per_category={"category": 3},
- output_format="vs7",
- verbosity=1)
- self.assertFalse(options == ProcessorOptions(extra_flag_values={"extra_value" : 2}))
- new_config = FilterConfiguration(base_rules=["-"])
- self.assertFalse(options ==
- ProcessorOptions(filter_configuration=new_config))
- self.assertFalse(options == ProcessorOptions(git_commit="commit2"))
- self.assertFalse(options == ProcessorOptions(max_reports_per_category=
- {"category": 2}))
- self.assertFalse(options == ProcessorOptions(output_format="emacs"))
- self.assertFalse(options == ProcessorOptions(verbosity=2))
-
- def test_ne(self):
- """Test __ne__ inequality function."""
- # != calls __ne__.
- # By default, __ne__ always returns true on different objects.
- # Thus, just check the distinguishing case to verify that the
- # code defines __ne__.
- self.assertFalse(ProcessorOptions() != ProcessorOptions())
-
- def test_is_reportable(self):
- """Test is_reportable()."""
- filter_configuration = FilterConfiguration(base_rules=["-xyz"])
- options = ProcessorOptions(filter_configuration=filter_configuration,
- verbosity=3)
-
- # Test verbosity
- self.assertTrue(options.is_reportable("abc", 3, "foo.h"))
- self.assertFalse(options.is_reportable("abc", 2, "foo.h"))
-
- # Test filter
- self.assertTrue(options.is_reportable("xy", 3, "foo.h"))
- self.assertFalse(options.is_reportable("xyz", 3, "foo.h"))
-
-
class GlobalVariablesTest(unittest.TestCase):
"""Tests validity of the global variables."""
def _all_categories(self):
- return style.style_categories()
+ return _all_categories()
def defaults(self):
- return style.webkit_argument_defaults()
+ return style._check_webkit_style_defaults()
- def test_filter_rules(self):
+ def test_webkit_base_filter_rules(self):
+ base_filter_rules = _BASE_FILTER_RULES
defaults = self.defaults()
already_seen = []
- validate_filter_rules(defaults.base_filter_rules,
- self._all_categories())
+ validate_filter_rules(base_filter_rules, self._all_categories())
# Also do some additional checks.
- for rule in defaults.base_filter_rules:
+ for rule in base_filter_rules:
# Check no leading or trailing white space.
self.assertEquals(rule, rule.strip())
# All categories are on by default, so defaults should
@@ -161,203 +82,77 @@ class GlobalVariablesTest(unittest.TestCase):
def test_defaults(self):
"""Check that default arguments are valid."""
- defaults = self.defaults()
+ default_options = self.defaults()
# FIXME: We should not need to call parse() to determine
# whether the default arguments are valid.
- parser = style.ArgumentParser(defaults)
+ parser = ArgumentParser(all_categories=self._all_categories(),
+ base_filter_rules=[],
+ default_options=default_options)
# No need to test the return value here since we test parse()
# on valid arguments elsewhere.
parser.parse([]) # arguments valid: no error or SystemExit
def test_path_rules_specifier(self):
- all_categories = style_categories()
+ all_categories = self._all_categories()
for (sub_paths, path_rules) in PATH_RULES_SPECIFIER:
- self.assertTrue(isinstance(path_rules, tuple),
- "Checking: " + str(path_rules))
validate_filter_rules(path_rules, self._all_categories())
- # Try using the path specifier (as an "end-to-end" check).
config = FilterConfiguration(path_specific=PATH_RULES_SPECIFIER)
- self.assertTrue(config.should_check("xxx_any_category",
- "xxx_non_matching_path"))
- self.assertTrue(config.should_check("xxx_any_category",
- "WebKitTools/WebKitAPITest/"))
- self.assertFalse(config.should_check("build/include",
- "WebKitTools/WebKitAPITest/"))
- self.assertFalse(config.should_check("readability/naming",
- "WebKit/qt/tests/qwebelement/tst_qwebelement.cpp"))
+
+ def assertCheck(path, category):
+ """Assert that the given category should be checked."""
+ message = ('Should check category "%s" for path "%s".'
+ % (category, path))
+ self.assertTrue(config.should_check(category, path))
+
+ def assertNoCheck(path, category):
+ """Assert that the given category should not be checked."""
+ message = ('Should not check category "%s" for path "%s".'
+ % (category, path))
+ self.assertFalse(config.should_check(category, path), message)
+
+ assertCheck("random_path.cpp",
+ "build/include")
+ assertNoCheck("WebKitTools/WebKitAPITest/main.cpp",
+ "build/include")
+ assertNoCheck("WebKit/qt/QGVLauncher/main.cpp",
+ "build/include")
+ assertNoCheck("WebKit/qt/QGVLauncher/main.cpp",
+ "readability/streams")
+
+ assertCheck("random_path.cpp",
+ "readability/naming")
+ assertNoCheck("WebKit/gtk/webkit/webkit.h",
+ "readability/naming")
+ assertNoCheck("WebCore/css/CSSParser.cpp",
+ "readability/naming")
+ assertNoCheck("WebKit/qt/tests/qwebelement/tst_qwebelement.cpp",
+ "readability/naming")
+ assertNoCheck(
+ "JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp",
+ "readability/naming")
def test_max_reports_per_category(self):
- """Check that MAX_REPORTS_PER_CATEGORY is valid."""
+ """Check that _MAX_REPORTS_PER_CATEGORY is valid."""
all_categories = self._all_categories()
- for category in style.MAX_REPORTS_PER_CATEGORY.iterkeys():
+ for category in _MAX_REPORTS_PER_CATEGORY.iterkeys():
self.assertTrue(category in all_categories,
'Key "%s" is not a category' % category)
-class ArgumentPrinterTest(unittest.TestCase):
-
- """Tests the ArgumentPrinter class."""
-
- _printer = style.ArgumentPrinter()
-
- def _create_options(self,
- output_format='emacs',
- verbosity=3,
- user_rules=[],
- git_commit=None,
- extra_flag_values={}):
- filter_configuration = FilterConfiguration(user_rules=user_rules)
- return style.ProcessorOptions(extra_flag_values=extra_flag_values,
- filter_configuration=filter_configuration,
- git_commit=git_commit,
- output_format=output_format,
- verbosity=verbosity)
+class CheckWebKitStyleFunctionTest(unittest.TestCase):
+
+ """Tests the functions with names of the form check_webkit_style_*."""
+
+ def test_check_webkit_style_configuration(self):
+ # Exercise the code path to make sure the function does not error out.
+ option_values = CommandOptionValues()
+ configuration = check_webkit_style_configuration(option_values)
- def test_to_flag_string(self):
- options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git',
- {'a': 0, 'z': 1})
- self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git '
- '--output=vs7 --verbose=5 --z=1',
- self._printer.to_flag_string(options))
-
- # This is to check that --filter and --git-commit do not
- # show up when not user-specified.
- options = self._create_options()
- self.assertEquals('--output=emacs --verbose=3',
- self._printer.to_flag_string(options))
-
-
-class ArgumentParserTest(unittest.TestCase):
-
- """Test the ArgumentParser class."""
-
- def _parse(self):
- """Return a default parse() function for testing."""
- return self._create_parser().parse
-
- def _create_defaults(self, default_output_format='vs7',
- default_verbosity=3,
- default_filter_rules=['-', '+whitespace']):
- """Return a default ArgumentDefaults instance for testing."""
- return style.ArgumentDefaults(default_output_format,
- default_verbosity,
- default_filter_rules)
-
- def _create_parser(self, defaults=None):
- """Return an ArgumentParser instance for testing."""
- def create_usage(_defaults):
- """Return a usage string for testing."""
- return "usage"
-
- def doc_print(message):
- # We do not want the usage string or style categories
- # to print during unit tests, so print nothing.
- return
-
- if defaults is None:
- defaults = self._create_defaults()
-
- return style.ArgumentParser(defaults, create_usage, doc_print)
-
- def test_parse_documentation(self):
- parse = self._parse()
-
- # FIXME: Test both the printing of the usage string and the
- # filter categories help.
-
- # Request the usage string.
- self.assertRaises(SystemExit, parse, ['--help'])
- # Request default filter rules and available style categories.
- self.assertRaises(SystemExit, parse, ['--filter='])
-
- def test_parse_bad_values(self):
- parse = self._parse()
-
- # Pass an unsupported argument.
- self.assertRaises(SystemExit, parse, ['--bad'])
-
- self.assertRaises(ValueError, parse, ['--verbose=bad'])
- self.assertRaises(ValueError, parse, ['--verbose=0'])
- self.assertRaises(ValueError, parse, ['--verbose=6'])
- parse(['--verbose=1']) # works
- parse(['--verbose=5']) # works
-
- self.assertRaises(ValueError, parse, ['--output=bad'])
- parse(['--output=vs7']) # works
-
- # Pass a filter rule not beginning with + or -.
- self.assertRaises(ValueError, parse, ['--filter=build'])
- parse(['--filter=+build']) # works
- # Pass files and git-commit at the same time.
- self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt'])
- # Pass an extra flag already supported.
- self.assertRaises(ValueError, parse, [], ['filter='])
- parse([], ['extra=']) # works
- # Pass an extra flag with typo.
- self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra='])
- parse(['--extra='], ['extra=']) # works
- self.assertRaises(ValueError, parse, [], ['extra=', 'extra='])
-
-
- def test_parse_default_arguments(self):
- parse = self._parse()
-
- (files, options) = parse([])
-
- self.assertEquals(files, [])
-
- self.assertEquals(options.output_format, 'vs7')
- self.assertEquals(options.verbosity, 3)
- self.assertEquals(options.filter_configuration,
- FilterConfiguration(base_rules=["-", "+whitespace"],
- path_specific=PATH_RULES_SPECIFIER))
- self.assertEquals(options.git_commit, None)
-
- def test_parse_explicit_arguments(self):
- parse = self._parse()
-
- # Pass non-default explicit values.
- (files, options) = parse(['--output=emacs'])
- self.assertEquals(options.output_format, 'emacs')
- (files, options) = parse(['--verbose=4'])
- self.assertEquals(options.verbosity, 4)
- (files, options) = parse(['--git-commit=commit'])
- self.assertEquals(options.git_commit, 'commit')
-
- # Pass user_rules.
- (files, options) = parse(['--filter=+build,-whitespace'])
- config = options.filter_configuration
- self.assertEquals(options.filter_configuration,
- FilterConfiguration(base_rules=["-", "+whitespace"],
- path_specific=PATH_RULES_SPECIFIER,
- user_rules=["+build", "-whitespace"]))
-
- # Pass spurious white space in user rules.
- (files, options) = parse(['--filter=+build, -whitespace'])
- self.assertEquals(options.filter_configuration,
- FilterConfiguration(base_rules=["-", "+whitespace"],
- path_specific=PATH_RULES_SPECIFIER,
- user_rules=["+build", "-whitespace"]))
-
- # Pass extra flag values.
- (files, options) = parse(['--extra'], ['extra'])
- self.assertEquals(options.extra_flag_values, {'--extra': ''})
- (files, options) = parse(['--extra='], ['extra='])
- self.assertEquals(options.extra_flag_values, {'--extra': ''})
- (files, options) = parse(['--extra=x'], ['extra='])
- self.assertEquals(options.extra_flag_values, {'--extra': 'x'})
-
- def test_parse_files(self):
- parse = self._parse()
-
- (files, options) = parse(['foo.cpp'])
- self.assertEquals(files, ['foo.cpp'])
-
- # Pass multiple files.
- (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
- self.assertEquals(files, ['foo.cpp', 'bar.cpp'])
+ def test_check_webkit_style_parser(self):
+ # Exercise the code path to make sure the function does not error out.
+ parser = check_webkit_style_parser()
class ProcessorDispatcherSkipTest(unittest.TestCase):
@@ -519,30 +314,96 @@ class ProcessorDispatcherDispatchTest(unittest.TestCase):
self.assert_processor_none(path)
-class StyleCheckerTest(unittest.TestCase):
+class StyleCheckerConfigurationTest(unittest.TestCase):
- """Test the StyleChecker class.
+ """Tests the StyleCheckerConfiguration class."""
- Attributes:
- error_messages: A string containing all of the warning messages
- written to the mock_stderr_write method of
- this class.
+ def setUp(self):
+ self._error_messages = []
+ """The messages written to _mock_stderr_write() of this class."""
- """
+ def _mock_stderr_write(self, message):
+ self._error_messages.append(message)
+
+ def _style_checker_configuration(self, output_format="vs7"):
+ """Return a StyleCheckerConfiguration instance for testing."""
+ base_rules = ["-whitespace", "+whitespace/tab"]
+ filter_configuration = FilterConfiguration(base_rules=base_rules)
+
+ return StyleCheckerConfiguration(
+ filter_configuration=filter_configuration,
+ max_reports_per_category={"whitespace/newline": 1},
+ output_format=output_format,
+ stderr_write=self._mock_stderr_write,
+ verbosity=3)
+
+ def test_init(self):
+ """Test the __init__() method."""
+ configuration = self._style_checker_configuration()
+
+ # Check that __init__ sets the "public" data attributes correctly.
+ self.assertEquals(configuration.max_reports_per_category,
+ {"whitespace/newline": 1})
+ self.assertEquals(configuration.stderr_write, self._mock_stderr_write)
+ self.assertEquals(configuration.verbosity, 3)
+
+ def test_is_reportable(self):
+ """Test the is_reportable() method."""
+ config = self._style_checker_configuration()
+
+ self.assertTrue(config.is_reportable("whitespace/tab", 3, "foo.txt"))
+
+ # Test the confidence check code path by varying the confidence.
+ self.assertFalse(config.is_reportable("whitespace/tab", 2, "foo.txt"))
+
+ # Test the category check code path by varying the category.
+ self.assertFalse(config.is_reportable("whitespace/line", 4, "foo.txt"))
+
+ def _call_write_style_error(self, output_format):
+ config = self._style_checker_configuration(output_format=output_format)
+ config.write_style_error(category="whitespace/tab",
+ confidence=5,
+ file_path="foo.h",
+ line_number=100,
+ message="message")
+
+ def test_write_style_error_emacs(self):
+ """Test the write_style_error() method."""
+ self._call_write_style_error("emacs")
+ self.assertEquals(self._error_messages,
+ ["foo.h:100: message [whitespace/tab] [5]\n"])
+
+ def test_write_style_error_vs7(self):
+ """Test the write_style_error() method."""
+ self._call_write_style_error("vs7")
+ self.assertEquals(self._error_messages,
+ ["foo.h(100): message [whitespace/tab] [5]\n"])
+
+
+class StyleCheckerTest(unittest.TestCase):
+
+ """Test the StyleChecker class."""
def _mock_stderr_write(self, message):
pass
- def _style_checker(self, options):
- return StyleChecker(options, self._mock_stderr_write)
+ def _style_checker(self, configuration):
+ return StyleChecker(configuration)
def test_init(self):
"""Test __init__ constructor."""
- options = ProcessorOptions()
- style_checker = self._style_checker(options)
+ configuration = StyleCheckerConfiguration(
+ filter_configuration=FilterConfiguration(),
+ max_reports_per_category={},
+ output_format="vs7",
+ stderr_write=self._mock_stderr_write,
+ verbosity=3)
+
+ style_checker = self._style_checker(configuration)
+ self.assertEquals(style_checker._configuration, configuration)
self.assertEquals(style_checker.error_count, 0)
- self.assertEquals(style_checker.options, options)
+ self.assertEquals(style_checker.file_count, 0)
class StyleCheckerCheckFileTest(unittest.TestCase):
@@ -609,20 +470,21 @@ class StyleCheckerCheckFileTest(unittest.TestCase):
# Confirm that the attributes are reset.
self.assert_attributes(None, None, None, "")
- # Create a test StyleChecker instance.
- #
- # The verbosity attribute is the only ProcessorOptions
- # attribute that needs to be checked in this test.
- # This is because it is the only option is directly
- # passed to the constructor of a style processor.
- options = ProcessorOptions(verbosity=3)
+ configuration = StyleCheckerConfiguration(
+ filter_configuration=FilterConfiguration(),
+ max_reports_per_category={"whitespace/newline": 1},
+ output_format="vs7",
+ stderr_write=self.mock_stderr_write,
+ verbosity=3)
- style_checker = StyleChecker(options, self.mock_stderr_write)
+ style_checker = StyleChecker(configuration)
style_checker.check_file(file_path,
self.mock_handle_style_error,
self.mock_process_file)
+ self.assertEquals(1, style_checker.file_count)
+
def test_check_file_on_skip_without_warning(self):
"""Test check_file() for a skipped-without-warning file."""
@@ -678,4 +540,3 @@ if __name__ == '__main__':
import sys
unittest.main()
-
diff --git a/WebKitTools/Scripts/webkitpy/style/error_handlers.py b/WebKitTools/Scripts/webkitpy/style/error_handlers.py
index 1940e03..6bc3f15 100644
--- a/WebKitTools/Scripts/webkitpy/style/error_handlers.py
+++ b/WebKitTools/Scripts/webkitpy/style/error_handlers.py
@@ -56,30 +56,21 @@ class DefaultStyleErrorHandler(object):
"""The default style error handler."""
- def __init__(self, file_path, options, increment_error_count,
- stderr_write=None):
+ def __init__(self, file_path, configuration, increment_error_count):
"""Create a default style error handler.
Args:
file_path: The path to the file containing the error. This
is used for reporting to the user.
- options: A ProcessorOptions instance.
+ configuration: A StyleCheckerConfiguration instance.
increment_error_count: A function that takes no arguments and
increments the total count of reportable
errors.
- stderr_write: A function that takes a string as a parameter
- and that is called when a style error occurs.
- Defaults to sys.stderr.write. This should be
- used only for unit tests.
"""
- if stderr_write is None:
- stderr_write = sys.stderr.write
-
self._file_path = file_path
+ self._configuration = configuration
self._increment_error_count = increment_error_count
- self._options = options
- self._stderr_write = stderr_write
# A string to integer dictionary cache of the number of reportable
# errors per category passed to this instance.
@@ -99,9 +90,9 @@ class DefaultStyleErrorHandler(object):
def _max_reports(self, category):
"""Return the maximum number of errors to report."""
- if not category in self._options.max_reports_per_category:
+ if not category in self._configuration.max_reports_per_category:
return None
- return self._options.max_reports_per_category[category]
+ return self._configuration.max_reports_per_category[category]
def __call__(self, line_number, category, confidence, message):
"""Handle the occurrence of a style error.
@@ -109,9 +100,9 @@ class DefaultStyleErrorHandler(object):
See the docstring of this module for more information.
"""
- if not self._options.is_reportable(category,
- confidence,
- self._file_path):
+ if not self._configuration.is_reportable(category=category,
+ confidence_in_error=confidence,
+ file_path=self._file_path):
return
category_total = self._add_reportable_error(category)
@@ -122,28 +113,22 @@ class DefaultStyleErrorHandler(object):
# Then suppress displaying the error.
return
- if self._options.output_format == 'vs7':
- format_string = "%s(%s): %s [%s] [%d]\n"
- else:
- format_string = "%s:%s: %s [%s] [%d]\n"
+ self._configuration.write_style_error(category=category,
+ confidence=confidence,
+ file_path=self._file_path,
+ line_number=line_number,
+ message=message)
if category_total == max_reports:
- format_string += ("Suppressing further [%s] reports for this "
- "file.\n" % category)
-
- self._stderr_write(format_string % (self._file_path,
- line_number,
- message,
- category,
- confidence))
+ self._configuration.stderr_write("Suppressing further [%s] reports "
+ "for this file.\n" % category)
class PatchStyleErrorHandler(object):
"""The style error function for patch files."""
- def __init__(self, diff, file_path, options, increment_error_count,
- stderr_write):
+ def __init__(self, diff, file_path, configuration, increment_error_count):
"""Create a patch style error handler for the given path.
Args:
@@ -153,10 +138,12 @@ class PatchStyleErrorHandler(object):
"""
self._diff = diff
- self._default_error_handler = DefaultStyleErrorHandler(file_path,
- options,
- increment_error_count,
- stderr_write)
+
+ self._default_error_handler = DefaultStyleErrorHandler(
+ configuration=configuration,
+ file_path=file_path,
+ increment_error_count=
+ increment_error_count)
# The line numbers of the modified lines. This is set lazily.
self._line_numbers = set()
diff --git a/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py b/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py
index 1d7e998..a39ba2a 100644
--- a/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py
@@ -26,124 +26,111 @@
import unittest
from .. style_references import parse_patch
-from checker import ProcessorOptions
+from checker import StyleCheckerConfiguration
from error_handlers import DefaultStyleErrorHandler
from error_handlers import PatchStyleErrorHandler
-
+from filter import FilterConfiguration
class StyleErrorHandlerTestBase(unittest.TestCase):
def setUp(self):
- self._error_messages = ""
+ self._error_messages = []
self._error_count = 0
def _mock_increment_error_count(self):
self._error_count += 1
def _mock_stderr_write(self, message):
- self._error_messages += message
+ self._error_messages.append(message)
+
+ def _style_checker_configuration(self):
+ """Return a StyleCheckerConfiguration instance for testing."""
+ base_rules = ["-whitespace", "+whitespace/tab"]
+ filter_configuration = FilterConfiguration(base_rules=base_rules)
+
+ return StyleCheckerConfiguration(
+ filter_configuration=filter_configuration,
+ max_reports_per_category={"whitespace/tab": 2},
+ output_format="vs7",
+ stderr_write=self._mock_stderr_write,
+ verbosity=3)
class DefaultStyleErrorHandlerTest(StyleErrorHandlerTestBase):
"""Tests DefaultStyleErrorHandler class."""
- _file_path = "foo.h"
-
_category = "whitespace/tab"
+ """The category name for the tests in this class."""
- def _error_handler(self, options):
- return DefaultStyleErrorHandler(self._file_path,
- options,
- self._mock_increment_error_count,
- self._mock_stderr_write)
+ _file_path = "foo.h"
+ """The file path for the tests in this class."""
def _check_initialized(self):
"""Check that count and error messages are initialized."""
self.assertEquals(0, self._error_count)
- self.assertEquals("", self._error_messages)
-
- def _call(self, handle_error, options, confidence):
- """Handle an error with the given error handler."""
- line_number = 100
- message = "message"
-
- handle_error(line_number, self._category, confidence, message)
-
- def _call_error_handler(self, options, confidence):
- """Handle an error using a new error handler."""
- handle_error = self._error_handler(options)
- self._call(handle_error, options, confidence)
-
- def test_call_non_reportable(self):
- """Test __call__() method with a non-reportable error."""
- confidence = 1
- options = ProcessorOptions(verbosity=3)
+ self.assertEquals(0, len(self._error_messages))
+
+ def _error_handler(self, configuration):
+ return DefaultStyleErrorHandler(configuration=configuration,
+ file_path=self._file_path,
+ increment_error_count=self._mock_increment_error_count)
+
+ def _call_error_handler(self, handle_error, confidence):
+ """Call the given error handler with a test error."""
+ handle_error(line_number=100,
+ category=self._category,
+ confidence=confidence,
+ message="message")
+
+ def test_non_reportable_error(self):
+ """Test __call__() with a non-reportable error."""
self._check_initialized()
+ configuration = self._style_checker_configuration()
+ confidence = 1
# Confirm the error is not reportable.
- self.assertFalse(options.is_reportable(self._category,
- confidence,
- self._file_path))
-
- self._call_error_handler(options, confidence)
+ self.assertFalse(configuration.is_reportable(self._category,
+ confidence,
+ self._file_path))
+ error_handler = self._error_handler(configuration)
+ self._call_error_handler(error_handler, confidence)
self.assertEquals(0, self._error_count)
- self.assertEquals("", self._error_messages)
-
- def test_call_reportable_emacs(self):
- """Test __call__() method with a reportable error and emacs format."""
- confidence = 5
- options = ProcessorOptions(verbosity=3, output_format="emacs")
- self._check_initialized()
+ self.assertEquals([], self._error_messages)
- self._call_error_handler(options, confidence)
-
- self.assertEquals(1, self._error_count)
- self.assertEquals(self._error_messages,
- "foo.h:100: message [whitespace/tab] [5]\n")
-
- def test_call_reportable_vs7(self):
- """Test __call__() method with a reportable error and vs7 format."""
- confidence = 5
- options = ProcessorOptions(verbosity=3, output_format="vs7")
+ # Also serves as a reportable error test.
+ def test_max_reports_per_category(self):
+ """Test error report suppression in __call__() method."""
self._check_initialized()
+ configuration = self._style_checker_configuration()
+ error_handler = self._error_handler(configuration)
- self._call_error_handler(options, confidence)
-
- self.assertEquals(1, self._error_count)
- self.assertEquals(self._error_messages,
- "foo.h(100): message [whitespace/tab] [5]\n")
-
- def test_call_max_reports_per_category(self):
- """Test error report suppression in __call__() method."""
confidence = 5
- options = ProcessorOptions(verbosity=3,
- max_reports_per_category={self._category: 2})
- error_handler = self._error_handler(options)
-
- self._check_initialized()
# First call: usual reporting.
- self._call(error_handler, options, confidence)
+ self._call_error_handler(error_handler, confidence)
self.assertEquals(1, self._error_count)
+ self.assertEquals(1, len(self._error_messages))
self.assertEquals(self._error_messages,
- "foo.h:100: message [whitespace/tab] [5]\n")
+ ["foo.h(100): message [whitespace/tab] [5]\n"])
# Second call: suppression message reported.
- self._error_messages = ""
- self._call(error_handler, options, confidence)
+ self._call_error_handler(error_handler, confidence)
+ # The "Suppressing further..." message counts as an additional
+ # message (but not as an addition to the error count).
self.assertEquals(2, self._error_count)
- self.assertEquals(self._error_messages,
- "foo.h:100: message [whitespace/tab] [5]\n"
- "Suppressing further [%s] reports for this file.\n"
- % self._category)
+ self.assertEquals(3, len(self._error_messages))
+ self.assertEquals(self._error_messages[-2],
+ "foo.h(100): message [whitespace/tab] [5]\n")
+ self.assertEquals(self._error_messages[-1],
+ "Suppressing further [whitespace/tab] reports "
+ "for this file.\n")
# Third call: no report.
- self._error_messages = ""
- self._call(error_handler, options, confidence)
+ self._call_error_handler(error_handler, confidence)
self.assertEquals(3, self._error_count)
- self.assertEquals(self._error_messages, "")
+ self.assertEquals(3, len(self._error_messages))
class PatchStyleErrorHandlerTest(StyleErrorHandlerTestBase):
@@ -166,22 +153,22 @@ index ef65bee..e3db70e 100644
patch_files = parse_patch(self._patch_string)
diff = patch_files[self._file_path]
- options = ProcessorOptions(verbosity=3)
+ configuration = self._style_checker_configuration()
- handle_error = PatchStyleErrorHandler(diff,
- self._file_path,
- options,
- self._mock_increment_error_count,
- self._mock_stderr_write)
+ handle_error = PatchStyleErrorHandler(diff=diff,
+ file_path=self._file_path,
+ configuration=configuration,
+ increment_error_count=
+ self._mock_increment_error_count)
category = "whitespace/tab"
confidence = 5
message = "message"
# Confirm error is reportable.
- self.assertTrue(options.is_reportable(category,
- confidence,
- self._file_path))
+ self.assertTrue(configuration.is_reportable(category,
+ confidence,
+ self._file_path))
# Confirm error count initialized to zero.
self.assertEquals(0, self._error_count)
diff --git a/WebKitTools/Scripts/webkitpy/style/filter.py b/WebKitTools/Scripts/webkitpy/style/filter.py
index 19c2f4d..608a9e6 100644
--- a/WebKitTools/Scripts/webkitpy/style/filter.py
+++ b/WebKitTools/Scripts/webkitpy/style/filter.py
@@ -139,12 +139,8 @@ class FilterConfiguration(object):
are appended. The first substring match takes
precedence, i.e. only the first match triggers
an append.
- The "path_rules" value is the tuple of filter
+ The "path_rules" value is a list of filter
rules that can be appended to the base rules.
- The value is a tuple rather than a list so it
- can be used as a dictionary key. The dictionary
- is for caching purposes in the implementation of
- this class.
user_rules: A list of filter rules that is always appended
to the base rules and any path rules. In other
@@ -165,11 +161,7 @@ class FilterConfiguration(object):
self._path_specific_lower = None
"""The backing store for self._get_path_specific_lower()."""
- # FIXME: Make user rules internal after the FilterConfiguration
- # attribute is removed from ProcessorOptions (since at
- # that point ArgumentPrinter will no longer need to
- # access FilterConfiguration.user_rules).
- self.user_rules = user_rules
+ self._user_rules = user_rules
self._path_rules_to_filter = {}
"""Cached dictionary of path rules to CategoryFilter instance."""
@@ -188,7 +180,7 @@ class FilterConfiguration(object):
return False
if self._path_specific != other._path_specific:
return False
- if self.user_rules != other.user_rules:
+ if self._user_rules != other._user_rules:
return False
return True
@@ -210,22 +202,34 @@ class FilterConfiguration(object):
return self._path_specific_lower
def _path_rules_from_path(self, path):
- """Determine the path-specific rules to use, and return as a tuple."""
+ """Determine the path-specific rules to use, and return as a tuple.
+
+ This method returns a tuple rather than a list so the return
+ value can be passed to _filter_from_path_rules() without change.
+
+ """
path = path.lower()
for (sub_paths, path_rules) in self._get_path_specific_lower():
for sub_path in sub_paths:
if path.find(sub_path) > -1:
- return path_rules
+ return tuple(path_rules)
return () # Default to the empty tuple.
def _filter_from_path_rules(self, path_rules):
- """Return the CategoryFilter associated to a path rules tuple."""
+ """Return the CategoryFilter associated to the given path rules.
+
+ Args:
+ path_rules: A tuple of path rules. We require a tuple rather
+ than a list so the value can be used as a dictionary
+ key in self._path_rules_to_filter.
+
+ """
# We reuse the same CategoryFilter where possible to take
# advantage of the caching they do.
if path_rules not in self._path_rules_to_filter:
rules = list(self._base_rules) # Make a copy
rules.extend(path_rules)
- rules.extend(self.user_rules)
+ rules.extend(self._user_rules)
self._path_rules_to_filter[path_rules] = _CategoryFilter(rules)
return self._path_rules_to_filter[path_rules]
diff --git a/WebKitTools/Scripts/webkitpy/style/filter_unittest.py b/WebKitTools/Scripts/webkitpy/style/filter_unittest.py
index 84760a5..7b8a5402 100644
--- a/WebKitTools/Scripts/webkitpy/style/filter_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/style/filter_unittest.py
@@ -157,14 +157,14 @@ class FilterConfigurationTest(unittest.TestCase):
# Test that the attributes are getting set correctly.
# We use parameter values that are different from the defaults.
base_rules = ["-"]
- path_specific = [(["path"], ("+a",))]
+ path_specific = [(["path"], ["+a"])]
user_rules = ["+"]
config = self._config(base_rules, path_specific, user_rules)
self.assertEquals(base_rules, config._base_rules)
self.assertEquals(path_specific, config._path_specific)
- self.assertEquals(user_rules, config.user_rules)
+ self.assertEquals(user_rules, config._user_rules)
def test_default_arguments(self):
# Test that the attributes are getting set correctly to the defaults.
@@ -172,7 +172,7 @@ class FilterConfigurationTest(unittest.TestCase):
self.assertEquals([], config._base_rules)
self.assertEquals([], config._path_specific)
- self.assertEquals([], config.user_rules)
+ self.assertEquals([], config._user_rules)
def test_eq(self):
"""Test __eq__ method."""
@@ -185,7 +185,7 @@ class FilterConfigurationTest(unittest.TestCase):
# These parameter values are different from the defaults.
base_rules = ["-"]
- path_specific = [(["path"], ("+a",))]
+ path_specific = [(["path"], ["+a"])]
user_rules = ["+"]
self.assertFalse(config.__eq__(FilterConfiguration(
@@ -219,8 +219,8 @@ class FilterConfigurationTest(unittest.TestCase):
def test_path_specific(self):
"""Test effect of path_rules_specifier on should_check()."""
base_rules = ["-"]
- path_specific = [(["path1"], ("+b",)),
- (["path2"], ("+c",))]
+ path_specific = [(["path1"], ["+b"]),
+ (["path2"], ["+c"])]
user_rules = []
config = self._config(base_rules, path_specific, user_rules)
@@ -233,7 +233,7 @@ class FilterConfigurationTest(unittest.TestCase):
def test_path_with_different_case(self):
"""Test a path that differs only in case."""
base_rules = ["-"]
- path_specific = [(["Foo/"], ("+whitespace",))]
+ path_specific = [(["Foo/"], ["+whitespace"])]
user_rules = []
config = self._config(base_rules, path_specific, user_rules)
diff --git a/WebKitTools/Scripts/webkitpy/style/optparser.py b/WebKitTools/Scripts/webkitpy/style/optparser.py
new file mode 100644
index 0000000..4137c8b
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/style/optparser.py
@@ -0,0 +1,424 @@
+# 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.
+
+"""Supports the parsing of command-line options for check-webkit-style."""
+
+import getopt
+import os.path
+import sys
+
+from filter import validate_filter_rules
+# This module should not import anything from checker.py.
+
+
+def _create_usage(default_options):
+ """Return the usage string to display for command help.
+
+ Args:
+ default_options: A DefaultCommandOptionValues instance.
+
+ """
+ usage = """
+Syntax: %(program_name)s [--verbose=#] [--git-commit=<SingleCommit>] [--output=vs7]
+ [--filter=-x,+y,...] [file] ...
+
+ The style guidelines this tries to follow are here:
+ http://webkit.org/coding/coding-style.html
+
+ Every style error is given a confidence score from 1-5, with 5 meaning
+ we are certain of the problem, and 1 meaning it could be a legitimate
+ construct. This can miss some errors and does not substitute for
+ code review.
+
+ To prevent specific lines from being linted, add a '// NOLINT' comment to the
+ end of the line.
+
+ Linted extensions are .cpp, .c and .h. Other file types are ignored.
+
+ The file parameter is optional and accepts multiple files. Leaving
+ out the file parameter applies the check to all files considered changed
+ by your source control management system.
+
+ Flags:
+
+ verbose=#
+ A number 1-5 that restricts output to errors with a confidence
+ score at or above this value. In particular, the value 1 displays
+ all errors. The default is %(default_verbosity)s.
+
+ git-commit=<SingleCommit>
+ Checks the style of everything from the given commit to the local tree.
+
+ output=vs7
+ The output format, which may be one of
+ emacs : to ease emacs parsing
+ vs7 : compatible with Visual Studio
+ Defaults to "%(default_output_format)s". Other formats are unsupported.
+
+ filter=-x,+y,...
+ A comma-separated list of boolean filter rules used to filter
+ which categories of style guidelines to check. The script checks
+ a category if the category passes the filter rules, as follows.
+
+ Any webkit category starts out passing. All filter rules are then
+ evaluated left to right, with later rules taking precedence. For
+ example, the rule "+foo" passes any category that starts with "foo",
+ and "-foo" fails any such category. The filter input "-whitespace,
+ +whitespace/braces" fails the category "whitespace/tab" and passes
+ "whitespace/braces".
+
+ Examples: --filter=-whitespace,+whitespace/braces
+ --filter=-whitespace,-runtime/printf,+runtime/printf_format
+ --filter=-,+build/include_what_you_use
+
+ Category names appear in error messages in brackets, for example
+ [whitespace/indent]. To see a list of all categories available to
+ %(program_name)s, along with which are enabled by default, pass
+ the empty filter as follows:
+ --filter=
+""" % {'program_name': os.path.basename(sys.argv[0]),
+ 'default_verbosity': default_options.verbosity,
+ 'default_output_format': default_options.output_format}
+
+ return usage
+
+
+# This class should not have knowledge of the flag key names.
+class DefaultCommandOptionValues(object):
+
+ """Stores the default check-webkit-style command-line options.
+
+ Attributes:
+ output_format: A string that is the default output format.
+ verbosity: An integer that is the default verbosity level.
+
+ """
+
+ def __init__(self, output_format, verbosity):
+ self.output_format = output_format
+ self.verbosity = verbosity
+
+
+# FIXME: Eliminate support for "extra_flag_values".
+#
+# This class should not have knowledge of the flag key names.
+class CommandOptionValues(object):
+
+ """Stores the option values passed by the user via the command line.
+
+ Attributes:
+ extra_flag_values: A string-string dictionary of all flag key-value
+ pairs that are not otherwise represented by this
+ class. The default is the empty dictionary.
+
+ filter_rules: The list of filter rules provided by the user.
+ These rules are appended to the base rules and
+ path-specific rules and so take precedence over
+ the base filter rules, etc.
+
+ git_commit: A string representing the git commit to check.
+ The default is None.
+
+ output_format: A string that is the output format. The supported
+ output formats are "emacs" which emacs can parse
+ and "vs7" which Microsoft Visual Studio 7 can parse.
+
+ verbosity: An integer between 1-5 inclusive that restricts output
+ to errors with a confidence score at or above this value.
+ The default is 1, which reports all errors.
+
+ """
+ def __init__(self,
+ extra_flag_values=None,
+ filter_rules=None,
+ git_commit=None,
+ output_format="emacs",
+ verbosity=1):
+ if extra_flag_values is None:
+ extra_flag_values = {}
+ if filter_rules is None:
+ filter_rules = []
+
+ if output_format not in ("emacs", "vs7"):
+ raise ValueError('Invalid "output_format" parameter: '
+ 'value must be "emacs" or "vs7". '
+ 'Value given: "%s".' % output_format)
+
+ if (verbosity < 1) or (verbosity > 5):
+ raise ValueError('Invalid "verbosity" parameter: '
+ "value must be an integer between 1-5 inclusive. "
+ 'Value given: "%s".' % verbosity)
+
+ self.extra_flag_values = extra_flag_values
+ self.filter_rules = filter_rules
+ self.git_commit = git_commit
+ self.output_format = output_format
+ self.verbosity = verbosity
+
+ # Useful for unit testing.
+ def __eq__(self, other):
+ """Return whether this instance is equal to another."""
+ if self.extra_flag_values != other.extra_flag_values:
+ return False
+ if self.filter_rules != other.filter_rules:
+ return False
+ if self.git_commit != other.git_commit:
+ return False
+ if self.output_format != other.output_format:
+ return False
+ if self.verbosity != other.verbosity:
+ return False
+
+ return True
+
+ # Useful for unit testing.
+ def __ne__(self, other):
+ # Python does not automatically deduce this from __eq__().
+ return not self.__eq__(other)
+
+
+class ArgumentPrinter(object):
+
+ """Supports the printing of check-webkit-style command arguments."""
+
+ def _flag_pair_to_string(self, flag_key, flag_value):
+ return '--%(key)s=%(val)s' % {'key': flag_key, 'val': flag_value }
+
+ def to_flag_string(self, options):
+ """Return a flag string of the given CommandOptionValues instance.
+
+ This method orders the flag values alphabetically by the flag key.
+
+ Args:
+ options: A CommandOptionValues instance.
+
+ """
+ flags = options.extra_flag_values.copy()
+
+ flags['output'] = options.output_format
+ flags['verbose'] = options.verbosity
+ # Only include the filter flag if user-provided rules are present.
+ filter_rules = options.filter_rules
+ if filter_rules:
+ flags['filter'] = ",".join(filter_rules)
+ if options.git_commit:
+ flags['git-commit'] = options.git_commit
+
+ flag_string = ''
+ # Alphabetizing lets us unit test this method.
+ for key in sorted(flags.keys()):
+ flag_string += self._flag_pair_to_string(key, flags[key]) + ' '
+
+ return flag_string.strip()
+
+
+# FIXME: Replace the use of getopt.getopt() with optparse.OptionParser.
+class ArgumentParser(object):
+
+ # FIXME: Move the documentation of the attributes to the __init__
+ # docstring after making the attributes internal.
+ """Supports the parsing of check-webkit-style command arguments.
+
+ Attributes:
+ create_usage: A function that accepts a DefaultCommandOptionValues
+ instance and returns a string of usage instructions.
+ Defaults to the function that generates the usage
+ string for check-webkit-style.
+ default_options: A DefaultCommandOptionValues instance that provides
+ the default values for options not explicitly
+ provided by the user.
+ stderr_write: A function that takes a string as a parameter and
+ serves as stderr.write. Defaults to sys.stderr.write.
+ This parameter should be specified only for unit tests.
+
+ """
+
+ def __init__(self,
+ all_categories,
+ default_options,
+ base_filter_rules=None,
+ create_usage=None,
+ stderr_write=None):
+ """Create an ArgumentParser instance.
+
+ Args:
+ all_categories: The set of all available style categories.
+ default_options: See the corresponding attribute in the class
+ docstring.
+ Keyword Args:
+ base_filter_rules: The list of filter rules at the beginning of
+ the list of rules used to check style. This
+ list has the least precedence when checking
+ style and precedes any user-provided rules.
+ The class uses this parameter only for display
+ purposes to the user. Defaults to the empty list.
+ create_usage: See the documentation of the corresponding
+ attribute in the class docstring.
+ stderr_write: See the documentation of the corresponding
+ attribute in the class docstring.
+
+ """
+ if base_filter_rules is None:
+ base_filter_rules = []
+ if create_usage is None:
+ create_usage = _create_usage
+ if stderr_write is None:
+ stderr_write = sys.stderr.write
+
+ self._all_categories = all_categories
+ self._base_filter_rules = base_filter_rules
+ # FIXME: Rename these to reflect that they are internal.
+ self.create_usage = create_usage
+ self.default_options = default_options
+ self.stderr_write = stderr_write
+
+ def _exit_with_usage(self, error_message=''):
+ """Exit and print a usage string with an optional error message.
+
+ Args:
+ error_message: A string that is an error message to print.
+
+ """
+ usage = self.create_usage(self.default_options)
+ self.stderr_write(usage)
+ if error_message:
+ sys.exit('\nFATAL ERROR: ' + error_message)
+ else:
+ sys.exit(1)
+
+ def _exit_with_categories(self):
+ """Exit and print the style categories and default filter rules."""
+ self.stderr_write('\nAll categories:\n')
+ for category in sorted(self._all_categories):
+ self.stderr_write(' ' + category + '\n')
+
+ self.stderr_write('\nDefault filter rules**:\n')
+ for filter_rule in sorted(self._base_filter_rules):
+ self.stderr_write(' ' + filter_rule + '\n')
+ self.stderr_write('\n**The command always evaluates the above rules, '
+ 'and before any --filter flag.\n\n')
+
+ sys.exit(0)
+
+ def _parse_filter_flag(self, flag_value):
+ """Parse the --filter flag, and return a list of filter rules.
+
+ Args:
+ flag_value: A string of comma-separated filter rules, for
+ example "-whitespace,+whitespace/indent".
+
+ """
+ filters = []
+ for uncleaned_filter in flag_value.split(','):
+ filter = uncleaned_filter.strip()
+ if not filter:
+ continue
+ filters.append(filter)
+ return filters
+
+ def parse(self, args, extra_flags=None):
+ """Parse the command line arguments to check-webkit-style.
+
+ Args:
+ args: A list of command-line arguments as returned by sys.argv[1:].
+ extra_flags: A list of flags whose values we want to extract, but
+ are not supported by the CommandOptionValues class.
+ An example flag "new_flag=". This defaults to the
+ empty list.
+
+ Returns:
+ A tuple of (filenames, options)
+
+ filenames: The list of filenames to check.
+ options: A CommandOptionValues instance.
+
+ """
+ if extra_flags is None:
+ extra_flags = []
+
+ output_format = self.default_options.output_format
+ verbosity = self.default_options.verbosity
+
+ # The flags already supported by the CommandOptionValues class.
+ flags = ['help', 'output=', 'verbose=', 'filter=', 'git-commit=']
+
+ for extra_flag in extra_flags:
+ if extra_flag in flags:
+ raise ValueError('Flag \'%(extra_flag)s is duplicated '
+ 'or already supported.' %
+ {'extra_flag': extra_flag})
+ flags.append(extra_flag)
+
+ try:
+ (opts, filenames) = getopt.getopt(args, '', flags)
+ except getopt.GetoptError:
+ # FIXME: Settle on an error handling approach: come up
+ # with a consistent guideline as to when and whether
+ # a ValueError should be raised versus calling
+ # sys.exit when needing to interrupt execution.
+ self._exit_with_usage('Invalid arguments.')
+
+ extra_flag_values = {}
+ git_commit = None
+ filter_rules = []
+
+ for (opt, val) in opts:
+ if opt == '--help':
+ self._exit_with_usage()
+ elif opt == '--output':
+ output_format = val
+ elif opt == '--verbose':
+ verbosity = val
+ elif opt == '--git-commit':
+ git_commit = val
+ elif opt == '--filter':
+ if not val:
+ self._exit_with_categories()
+ filter_rules = self._parse_filter_flag(val)
+ else:
+ extra_flag_values[opt] = val
+
+ # Check validity of resulting values.
+ if filenames and (git_commit != None):
+ self._exit_with_usage('It is not possible to check files and a '
+ 'specific commit at the same time.')
+
+ if output_format not in ('emacs', 'vs7'):
+ raise ValueError('Invalid --output value "%s": The only '
+ 'allowed output formats are emacs and vs7.' %
+ output_format)
+
+ validate_filter_rules(filter_rules, self._all_categories)
+
+ verbosity = int(verbosity)
+ if (verbosity < 1) or (verbosity > 5):
+ raise ValueError('Invalid --verbose value %s: value must '
+ 'be between 1-5.' % verbosity)
+
+ options = CommandOptionValues(extra_flag_values=extra_flag_values,
+ filter_rules=filter_rules,
+ git_commit=git_commit,
+ output_format=output_format,
+ verbosity=verbosity)
+
+ return (filenames, options)
+
diff --git a/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py b/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py
new file mode 100644
index 0000000..f23c5d1
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py
@@ -0,0 +1,258 @@
+# 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 for parser.py."""
+
+import unittest
+
+from optparser import _create_usage
+from optparser import ArgumentParser
+from optparser import ArgumentPrinter
+from optparser import CommandOptionValues as ProcessorOptions
+from optparser import DefaultCommandOptionValues
+
+
+class CreateUsageTest(unittest.TestCase):
+
+ """Tests the _create_usage() function."""
+
+ def test_create_usage(self):
+ default_options = DefaultCommandOptionValues(output_format="vs7",
+ verbosity=3)
+ # Exercise the code path to make sure the function does not error out.
+ _create_usage(default_options)
+
+
+class ArgumentPrinterTest(unittest.TestCase):
+
+ """Tests the ArgumentPrinter class."""
+
+ _printer = ArgumentPrinter()
+
+ def _create_options(self,
+ output_format='emacs',
+ verbosity=3,
+ filter_rules=[],
+ git_commit=None,
+ extra_flag_values={}):
+ return ProcessorOptions(extra_flag_values=extra_flag_values,
+ filter_rules=filter_rules,
+ git_commit=git_commit,
+ output_format=output_format,
+ verbosity=verbosity)
+
+ def test_to_flag_string(self):
+ options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git',
+ {'a': 0, 'z': 1})
+ self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git '
+ '--output=vs7 --verbose=5 --z=1',
+ self._printer.to_flag_string(options))
+
+ # This is to check that --filter and --git-commit do not
+ # show up when not user-specified.
+ options = self._create_options()
+ self.assertEquals('--output=emacs --verbose=3',
+ self._printer.to_flag_string(options))
+
+
+class ArgumentParserTest(unittest.TestCase):
+
+ """Test the ArgumentParser class."""
+
+ def _parse(self):
+ """Return a default parse() function for testing."""
+ return self._create_parser().parse
+
+ def _create_defaults(self):
+ """Return a DefaultCommandOptionValues instance for testing."""
+ base_filter_rules = ["-", "+whitespace"]
+ return DefaultCommandOptionValues(output_format="vs7",
+ verbosity=3)
+
+ def _create_parser(self):
+ """Return an ArgumentParser instance for testing."""
+ def stderr_write(message):
+ # We do not want the usage string or style categories
+ # to print during unit tests, so print nothing.
+ return
+
+ default_options = self._create_defaults()
+
+ all_categories = ["build" ,"whitespace"]
+ return ArgumentParser(all_categories=all_categories,
+ base_filter_rules=[],
+ default_options=default_options,
+ stderr_write=stderr_write)
+
+ def test_parse_documentation(self):
+ parse = self._parse()
+
+ # FIXME: Test both the printing of the usage string and the
+ # filter categories help.
+
+ # Request the usage string.
+ self.assertRaises(SystemExit, parse, ['--help'])
+ # Request default filter rules and available style categories.
+ self.assertRaises(SystemExit, parse, ['--filter='])
+
+ def test_parse_bad_values(self):
+ parse = self._parse()
+
+ # Pass an unsupported argument.
+ self.assertRaises(SystemExit, parse, ['--bad'])
+
+ self.assertRaises(ValueError, parse, ['--verbose=bad'])
+ self.assertRaises(ValueError, parse, ['--verbose=0'])
+ self.assertRaises(ValueError, parse, ['--verbose=6'])
+ parse(['--verbose=1']) # works
+ parse(['--verbose=5']) # works
+
+ self.assertRaises(ValueError, parse, ['--output=bad'])
+ parse(['--output=vs7']) # works
+
+ # Pass a filter rule not beginning with + or -.
+ self.assertRaises(ValueError, parse, ['--filter=build'])
+ parse(['--filter=+build']) # works
+ # Pass files and git-commit at the same time.
+ self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt'])
+ # Pass an extra flag already supported.
+ self.assertRaises(ValueError, parse, [], ['filter='])
+ parse([], ['extra=']) # works
+ # Pass an extra flag with typo.
+ self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra='])
+ parse(['--extra='], ['extra=']) # works
+ self.assertRaises(ValueError, parse, [], ['extra=', 'extra='])
+
+
+ def test_parse_default_arguments(self):
+ parse = self._parse()
+
+ (files, options) = parse([])
+
+ self.assertEquals(files, [])
+
+ self.assertEquals(options.output_format, 'vs7')
+ self.assertEquals(options.verbosity, 3)
+ self.assertEquals(options.filter_rules, [])
+ self.assertEquals(options.git_commit, None)
+
+ def test_parse_explicit_arguments(self):
+ parse = self._parse()
+
+ # Pass non-default explicit values.
+ (files, options) = parse(['--output=emacs'])
+ self.assertEquals(options.output_format, 'emacs')
+ (files, options) = parse(['--verbose=4'])
+ self.assertEquals(options.verbosity, 4)
+ (files, options) = parse(['--git-commit=commit'])
+ self.assertEquals(options.git_commit, 'commit')
+
+ # Pass user_rules.
+ (files, options) = parse(['--filter=+build,-whitespace'])
+ self.assertEquals(options.filter_rules,
+ ["+build", "-whitespace"])
+
+ # Pass spurious white space in user rules.
+ (files, options) = parse(['--filter=+build, -whitespace'])
+ self.assertEquals(options.filter_rules,
+ ["+build", "-whitespace"])
+
+ # Pass extra flag values.
+ (files, options) = parse(['--extra'], ['extra'])
+ self.assertEquals(options.extra_flag_values, {'--extra': ''})
+ (files, options) = parse(['--extra='], ['extra='])
+ self.assertEquals(options.extra_flag_values, {'--extra': ''})
+ (files, options) = parse(['--extra=x'], ['extra='])
+ self.assertEquals(options.extra_flag_values, {'--extra': 'x'})
+
+ def test_parse_files(self):
+ parse = self._parse()
+
+ (files, options) = parse(['foo.cpp'])
+ self.assertEquals(files, ['foo.cpp'])
+
+ # Pass multiple files.
+ (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
+ self.assertEquals(files, ['foo.cpp', 'bar.cpp'])
+
+
+class CommandOptionValuesTest(unittest.TestCase):
+
+ """Tests CommandOptionValues class."""
+
+ def test_init(self):
+ """Test __init__ constructor."""
+ # Check default parameters.
+ options = ProcessorOptions()
+ self.assertEquals(options.extra_flag_values, {})
+ self.assertEquals(options.filter_rules, [])
+ self.assertEquals(options.git_commit, None)
+ self.assertEquals(options.output_format, "emacs")
+ self.assertEquals(options.verbosity, 1)
+
+ # Check argument validation.
+ self.assertRaises(ValueError, ProcessorOptions, output_format="bad")
+ ProcessorOptions(output_format="emacs") # No ValueError: works
+ ProcessorOptions(output_format="vs7") # works
+ self.assertRaises(ValueError, ProcessorOptions, verbosity=0)
+ self.assertRaises(ValueError, ProcessorOptions, verbosity=6)
+ ProcessorOptions(verbosity=1) # works
+ ProcessorOptions(verbosity=5) # works
+
+ # Check attributes.
+ options = ProcessorOptions(extra_flag_values={"extra_value" : 2},
+ filter_rules=["+"],
+ git_commit="commit",
+ output_format="vs7",
+ verbosity=3)
+ self.assertEquals(options.extra_flag_values, {"extra_value" : 2})
+ self.assertEquals(options.filter_rules, ["+"])
+ self.assertEquals(options.git_commit, "commit")
+ self.assertEquals(options.output_format, "vs7")
+ self.assertEquals(options.verbosity, 3)
+
+ def test_eq(self):
+ """Test __eq__ equality function."""
+ # == calls __eq__.
+ self.assertTrue(ProcessorOptions() == ProcessorOptions())
+
+ # Verify that a difference in any argument causes equality to fail.
+ options = ProcessorOptions(extra_flag_values={"extra_value" : 1},
+ filter_rules=["+"],
+ git_commit="commit",
+ output_format="vs7",
+ verbosity=1)
+ self.assertFalse(options == ProcessorOptions(extra_flag_values=
+ {"extra_value" : 2}))
+ self.assertFalse(options == ProcessorOptions(filter_rules=["-"]))
+ self.assertFalse(options == ProcessorOptions(git_commit="commit2"))
+ self.assertFalse(options == ProcessorOptions(output_format="emacs"))
+ self.assertFalse(options == ProcessorOptions(verbosity=2))
+
+ def test_ne(self):
+ """Test __ne__ inequality function."""
+ # != calls __ne__.
+ # By default, __ne__ always returns true on different objects.
+ # Thus, just check the distinguishing case to verify that the
+ # code defines __ne__.
+ self.assertFalse(ProcessorOptions() != ProcessorOptions())
+
diff --git a/WebKitTools/Scripts/webkitpy/style/processors/cpp.py b/WebKitTools/Scripts/webkitpy/style/processors/cpp.py
index 182c967..f83ae6a 100644
--- a/WebKitTools/Scripts/webkitpy/style/processors/cpp.py
+++ b/WebKitTools/Scripts/webkitpy/style/processors/cpp.py
@@ -1868,6 +1868,10 @@ def check_for_null(file_extension, clean_lines, line_number, error):
if search(r'\bg_object_[sg]et\b', line):
return
+ # Don't warn about NULL usage in g_str{join,concat}(). See Bug 34834
+ if search(r'\bg_str(join|concat)\b', line):
+ return
+
if search(r'\bNULL\b', line):
error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.')
return
@@ -2421,7 +2425,9 @@ def check_identifier_name_in_declaration(filename, line_number, line, error):
# Convert "long long", "long double", and "long long int" to
# simple types, but don't remove simple "long".
line = sub(r'long (long )?(?=long|double|int)', '', line)
- line = sub(r'\b(unsigned|signed|inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line)
+ # Convert unsigned/signed types to simple types, too.
+ line = sub(r'(unsigned|signed) (?=char|short|int|long)', '', line)
+ line = sub(r'\b(inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line)
# Remove all template parameters by removing matching < and >.
# Loop until no templates are removed to remove nested templates.
@@ -2449,8 +2455,9 @@ def check_identifier_name_in_declaration(filename, line_number, line, error):
# Detect variable and functions.
type_regexp = r'\w([\w]|\s*[*&]\s*|::)+'
identifier_regexp = r'(?P<identifier>[\w:]+)'
+ maybe_bitfield_regexp = r'(:\s*\d+\s*)?'
character_after_identifier_regexp = r'(?P<character_after_identifier>[[;()=,])(?!=)'
- declaration_without_type_regexp = r'\s*' + identifier_regexp + r'\s*' + character_after_identifier_regexp
+ declaration_without_type_regexp = r'\s*' + identifier_regexp + r'\s*' + maybe_bitfield_regexp + character_after_identifier_regexp
declaration_with_type_regexp = r'\s*' + type_regexp + r'\s' + declaration_without_type_regexp
is_function_arguments = False
number_of_identifiers = 0
@@ -2982,4 +2989,3 @@ class CppProcessor(object):
def process_file_data(filename, file_extension, lines, error, verbosity):
processor = CppProcessor(filename, file_extension, error, verbosity)
processor.process(lines)
-
diff --git a/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py b/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py
index fb5a487..c786b8e 100644
--- a/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py
@@ -3392,13 +3392,26 @@ class WebKitStyleTest(CppStyleTestBase):
'',
'foo.m')
- # Make sure that the NULL check does not apply to g_object_{set,get}
+ # Make sure that the NULL check does not apply to g_object_{set,get} and
+ # g_str{join,concat}
self.assert_lint(
'g_object_get(foo, "prop", &bar, NULL);',
'')
self.assert_lint(
'g_object_set(foo, "prop", bar, NULL);',
'')
+ self.assert_lint(
+ 'gchar* result = g_strconcat("part1", "part2", "part3", NULL);',
+ '')
+ self.assert_lint(
+ 'gchar* result = g_strconcat("part1", NULL);',
+ '')
+ self.assert_lint(
+ 'gchar* result = g_strjoin(",", "part1", "part2", "part3", NULL);',
+ '')
+ self.assert_lint(
+ 'gchar* result = g_strjoin(",", "part1", NULL);',
+ '')
# 2. C++ and C bool values should be written as true and
# false. Objective-C BOOL values should be written as YES and NO.
@@ -3503,6 +3516,12 @@ class WebKitStyleTest(CppStyleTestBase):
'_length' + name_error_message)
self.assert_lint('short length_;',
'length_' + name_error_message)
+ self.assert_lint('unsigned _length;',
+ '_length' + name_error_message)
+ self.assert_lint('unsigned int _length;',
+ '_length' + name_error_message)
+ self.assert_lint('unsigned long long _length;',
+ '_length' + name_error_message)
# Pointers, references, functions, templates, and adjectives.
self.assert_lint('char* under_score;',
@@ -3599,6 +3618,10 @@ class WebKitStyleTest(CppStyleTestBase):
# const_iterator is allowed as well.
self.assert_lint('typedef VectorType::const_iterator const_iterator;', '')
+ # Bitfields.
+ self.assert_lint('unsigned _fillRule : 1;',
+ '_fillRule' + name_error_message)
+
def test_comments(self):
# A comment at the beginning of a line is ok.
diff --git a/WebKitTools/Scripts/webkitpy/style/unittests.py b/WebKitTools/Scripts/webkitpy/style/unittests.py
index f8e3f71..62615ab 100644
--- a/WebKitTools/Scripts/webkitpy/style/unittests.py
+++ b/WebKitTools/Scripts/webkitpy/style/unittests.py
@@ -38,6 +38,7 @@ import unittest
from checker_unittest import *
from error_handlers_unittest import *
from filter_unittest import *
+from optparser_unittest import *
from processors.common_unittest import *
from processors.cpp_unittest import *
from processors.text_unittest import *