diff options
Diffstat (limited to 'Tools')
214 files changed, 8053 insertions, 2184 deletions
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/config.json b/Tools/BuildSlaveSupport/build.webkit.org-config/config.json index dc62cd8fc..b51c525eb 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/config.json +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/config.json @@ -22,8 +22,6 @@ { "name": "apple-windows-4", "platform": "win"}, { "name": "apple-windows-5", "platform": "win"}, { "name": "apple-windows-6", "platform": "win"}, - { "name": "apple-windows-7", "platform": "win"}, - { "name": "apple-windows-8", "platform": "win"}, { "name": "apple-windows-13", "platform": "win"}, { "name": "apple-windows-14", "platform": "win"}, { "name": "apple-windows-15", "platform": "win"}, @@ -68,74 +66,70 @@ { "name": "hfreyther-sh4-linux1", "platform": "qt"} ], - "builders": [ { "name": "SnowLeopard Intel Release (Build)", "type": "Build", "builddir": "snowleopard-intel-release", + "builders": [ { "name": "Apple SnowLeopard Release (Build)", "type": "Build", "builddir": "snowleopard-release", "platform": "mac-snowleopard", "configuration": "release", "architectures": ["x86_64"], - "slavenames": ["apple-xserve-4", "test-slave"] + "slavenames": ["apple-xserve-4"] }, - { "name": "SnowLeopard Intel Debug (Build)", "type": "Build", "builddir": "snowleopard-intel-debug", + { "name": "Apple SnowLeopard Debug (Build)", "type": "Build", "builddir": "snowleopard-debug", "platform": "mac-snowleopard", "configuration": "debug", "architectures": ["x86_64"], "slavenames": ["apple-xserve-9"] }, - { "name": "Lion Leaks", "type": "BuildAndTestLeaks", "builddir": "lion-intel-leaks", + { "name": "Apple Lion (Leaks)", "type": "BuildAndTestLeaks", "builddir": "lion-leaks", "platform": "mac-lion", "configuration": "debug", "architectures": ["x86_64"], "slavenames": ["apple-macpro-3"] }, - { "name": "Lion Debug (Build)", "type": "Build", "builddir": "lion-intel-debug", + { "name": "Apple Lion Debug (Build)", "type": "Build", "builddir": "lion-debug", "platform": "mac-lion", "configuration": "debug", "architectures": ["x86_64"], - "triggers": ["lion-intel-debug-tests", "lion-intel-debug-tests-wk2"], + "triggers": ["lion-debug-tests-wk1", "lion-debug-tests-wk2"], "slavenames": ["apple-xserve-2", "apple-xserve-10"] }, - { "name": "Lion Release (Build)", "type": "Build", "builddir": "lion-intel-release", + { "name": "Apple Lion Release (Build)", "type": "Build", "builddir": "lion-release", "platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"], - "triggers": ["lion-intel-release-tests", "lion-intel-release-tests-wk2", "lion-intel-release-perf"], + "triggers": ["lion-release-tests-wk1", "lion-release-tests-wk2", "lion-release-perf"], "slavenames": ["apple-xserve-3"] }, - { "name": "Lion Debug (Tests)", "type": "Test", "builddir": "lion-intel-debug-tests", + { "name": "Apple Lion Debug WK1 (Tests)", "type": "Test", "builddir": "lion-debug-tests-wk1", "platform": "mac-lion", "configuration": "debug", "architectures": ["x86_64"], "slavenames": ["apple-macpro-4"] }, - { "name": "Lion Debug (WebKit2 Tests)", "type": "TestWebKit2", "builddir": "lion-intel-debug-tests-wk2", + { "name": "Apple Lion Debug WK2 (Tests)", "type": "TestWebKit2", "builddir": "lion-debug-tests-wk2", "platform": "mac-lion", "configuration": "debug", "architectures": ["x86_64"], "slavenames": ["apple-macpro-8", "apple-xserve-1"] }, - { "name": "Lion Release (Tests)", "type": "Test", "builddir": "lion-intel-release-tests", + { "name": "Apple Lion Release WK1 (Tests)", "type": "Test", "builddir": "lion-release-tests-wk1", "platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"], "slavenames": ["apple-macpro-5"] }, - { "name": "Lion Release (WebKit2 Tests)", "type": "TestWebKit2", "builddir": "lion-intel-release-tests-wk2", + { "name": "Apple Lion Release WK2 (Tests)", "type": "TestWebKit2", "builddir": "lion-release-tests-wk2", "platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"], "slavenames": ["apple-macpro-6"] }, { - "name": "Lion Release (Perf)", "type": "DownloadAndPerfTest", "builddir": "lion-release-perf-tests", + "name": "Apple Lion Release (Perf)", "type": "DownloadAndPerfTest", "builddir": "lion-release-perf-tests", "platform": "mac-lion", "configuration": "release", "architectures": ["x86_64"], "slavenames": ["apple-xserve-11"] }, { - "name": "Windows Release (Build)", "type": "Build", "builddir": "win-release", + "name": "Apple Win Release (Build)", "type": "Build", "builddir": "win-release", "platform": "win", "configuration": "release", "architectures": ["i386"], - "triggers": ["win-release-tests", "win-release-tests-wk2"], - "slavenames": ["apple-windows-2", "test-slave"] + "triggers": ["win-release-tests"], + "slavenames": ["apple-windows-2"] }, { - "name": "Windows 7 Release (Tests)", "type": "Test", "builddir": "win-release-tests", + "name": "Apple Win 7 Release (Tests)", "type": "Test", "builddir": "win-release-tests", "platform": "win", "configuration": "release", "architectures": ["i386"], - "slavenames": ["apple-windows-5", "apple-windows-6", "test-slave"] + "slavenames": ["apple-windows-5", "apple-windows-6"] }, { - "name": "Windows Debug (Build)", "type": "Build", "builddir": "win-debug", + "name": "Apple Win Debug (Build)", "type": "Build", "builddir": "win-debug", "platform": "win", "configuration": "debug", "architectures": ["i386"], "triggers": ["win-debug-tests"], - "slavenames": ["apple-windows-1", "test-slave"] + "slavenames": ["apple-windows-1"] }, { - "name": "Windows XP Debug (Tests)", "type": "Test", "builddir": "win-debug-tests", + "name": "Apple Win XP Debug (Tests)", "type": "Test", "builddir": "win-debug-tests", "platform": "win", "configuration": "debug", "architectures": ["i386"], - "slavenames": ["apple-windows-3", "apple-windows-4", "apple-windows-13", "apple-windows-14", "apple-windows-15", "test-slave"] - }, - { "name": "Windows 7 Release (WebKit2 Tests)", "type": "TestWebKit2", "builddir": "win-release-tests-wk2", - "platform": "win", "configuration": "release", "architectures": ["i386"], - "slavenames": ["apple-windows-7", "apple-windows-8", "test-slave"] + "slavenames": ["apple-windows-3", "apple-windows-4", "apple-windows-13", "apple-windows-14", "apple-windows-15"] }, { "name": "GTK Linux 32-bit Release", "type": "BuildAndTest", "builddir": "gtk-linux-32-release", @@ -294,37 +288,34 @@ "WinCairo Release", "WinCE Release (Build)"] }, { "type": "PlatformSpecificScheduler", "platform": "mac-snowleopard", "branch": "trunk", "treeStableTimer": 45.0, - "builderNames": ["SnowLeopard Intel Release (Build)", "SnowLeopard Intel Debug (Build)"] + "builderNames": ["Apple SnowLeopard Release (Build)", "Apple SnowLeopard Debug (Build)"] }, { "type": "PlatformSpecificScheduler", "platform": "mac-lion", "branch": "trunk", "treeStableTimer": 45.0, - "builderNames": ["Lion Release (Build)", "Lion Debug (Build)", "Lion Leaks"] + "builderNames": ["Apple Lion Release (Build)", "Apple Lion Debug (Build)", "Apple Lion (Leaks)"] }, { "type": "PlatformSpecificScheduler", "platform": "win", "branch": "trunk", "treeStableTimer": 45.0, - "builderNames": ["Windows Release (Build)", "Windows Debug (Build)"] + "builderNames": ["Apple Win Release (Build)", "Apple Win Debug (Build)"] }, - { "type": "Triggerable", "name": "lion-intel-release-tests", - "builderNames": ["Lion Release (Tests)"] + { "type": "Triggerable", "name": "lion-release-tests-wk1", + "builderNames": ["Apple Lion Release WK1 (Tests)"] }, - { "type": "Triggerable", "name": "lion-intel-release-tests-wk2", - "builderNames": ["Lion Release (WebKit2 Tests)"] + { "type": "Triggerable", "name": "lion-release-tests-wk2", + "builderNames": ["Apple Lion Release WK2 (Tests)"] }, - { "type": "Triggerable", "name": "lion-intel-release-perf", - "builderNames": ["Lion Release (Perf)"] + { "type": "Triggerable", "name": "lion-release-perf", + "builderNames": ["Apple Lion Release (Perf)"] }, - { "type": "Triggerable", "name": "lion-intel-debug-tests", - "builderNames": ["Lion Debug (Tests)"] + { "type": "Triggerable", "name": "lion-debug-tests-wk1", + "builderNames": ["Apple Lion Debug WK1 (Tests)"] }, - { "type": "Triggerable", "name": "lion-intel-debug-tests-wk2", - "builderNames": ["Lion Debug (WebKit2 Tests)"] + { "type": "Triggerable", "name": "lion-debug-tests-wk2", + "builderNames": ["Apple Lion Debug WK2 (Tests)"] }, { "type": "Triggerable", "name": "win-release-tests", - "builderNames": ["Windows 7 Release (Tests)"] + "builderNames": ["Apple Win 7 Release (Tests)"] }, { "type": "Triggerable", "name": "win-debug-tests", - "builderNames": ["Windows XP Debug (Tests)"] - }, - { "type": "Triggerable", "name": "win-release-tests-wk2", - "builderNames": ["Windows 7 Release (WebKit2 Tests)"] + "builderNames": ["Apple Win XP Debug (Tests)"] }, { "type": "Triggerable", "name": "chromium-win-release-tests", "builderNames": ["Chromium Win Release (Tests)"] diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg index 7244f91d0..c00a18072 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg @@ -4,6 +4,7 @@ from buildbot.buildslave import BuildSlave from buildbot.changes.pb import PBChangeSource from buildbot.scheduler import AnyBranchScheduler, Triggerable +from buildbot.schedulers.forcesched import FixedParameter, ForceScheduler, StringParameter from buildbot.schedulers.filter import ChangeFilter from buildbot.status import html from buildbot.status.web.authz import Authz @@ -402,23 +403,6 @@ class RunWebKitTests(shell.Test): return [self.name] -class NewRunWebKitTests(RunWebKitTests): - command = ["python", "./Tools/Scripts/new-run-webkit-tests", - "--no-show-results", "--no-new-test-results", - "--verbose", "--results-directory", "layout-test-results", - "--builder-name", WithProperties("%(buildername)s"), - "--build-number", WithProperties("%(buildnumber)s"), - "--master-name", "webkit.org", - "--test-results-server", "test-results.appspot.com", - WithProperties("--%(configuration)s")] - - def commandComplete(self, cmd): - shell.Test.commandComplete(self, cmd) - - logText = cmd.logs['stdio'].getText() - self._parseNewRunWebKitTestsOutput(logText) - - class RunUnitTests(TestWithFailureCount): name = "run-api-tests" description = ["unit tests running"] @@ -776,10 +760,6 @@ class BuildAndTestLeaksFactory(BuildAndTestFactory): ExtractTestResultsClass = ExtractTestResultsAndLeaks -class NewBuildAndTestFactory(BuildAndTestFactory): - TestClass = NewRunWebKitTests - - class TestWebKit2Factory(TestFactory): TestClass = RunWebKit2Tests @@ -841,11 +821,24 @@ def loadBuilderConfig(c): # unicode strings from json.load, so we map all keys to str objects. scheduler = dict(map(lambda key_value_pair: (str(key_value_pair[0]), key_value_pair[1]), scheduler.items())) - # BaseScheduler asserts if given unicode objects instead of strs. - # http://trac.buildbot.net/ticket/2075 - scheduler['builderNames'] = map(str, scheduler['builderNames']) c['schedulers'].append(kls(**scheduler)) + forceScheduler = ForceScheduler( + name="force", + builderNames=[builder['name'] for builder in config['builders']], + reason=StringParameter(name="reason", default="", size=40), + + # Validate SVN revision: number or emtpy string + revision=StringParameter(name="revision", default="", regex=re.compile(r'^(\d*)$')), + + # Disable default enabled input fields: branch, repository, project, additional properties + branch=FixedParameter(name="branch"), + repository=FixedParameter(name="repository"), + project=FixedParameter(name="project"), + properties=[] + ) + c['schedulers'].append(forceScheduler) + c['builders'] = [] for builder in config['builders']: for slaveName in builder['slavenames']: @@ -860,7 +853,8 @@ def loadBuilderConfig(c): platform = builder['platform'] - factory = globals()["%sFactory" % builder.pop('type')] + builderType = builder.pop('type') + factory = globals()["%sFactory" % builderType] factoryArgs = [] for key in "platform", "configuration", "architectures", "triggers": value = builder.pop(key, None) @@ -884,7 +878,7 @@ def loadBuilderConfig(c): else: builder["category"] = 'misc' - if builder['category'] == 'AppleMac' or builder['category'] == 'AppleWin': + if (builder['category'] == 'AppleMac' or builder['category'] == 'AppleWin') and builderType != 'Build': builder['nextBuild'] = pickLatestBuild c['builders'].append(builder) diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/garden-o-matic.html b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/garden-o-matic.html index 83b6bb51d..e961d8b8a 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/garden-o-matic.html +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/garden-o-matic.html @@ -32,10 +32,10 @@ James, a web developer from Birmingham, UK. script-src 'self' file: https://ajax.googleapis.com; style-src 'self' 'unsafe-inline' file: https://ajax.googleapis.com http://fonts.googleapis.com; font-src http://themes.googleusercontent.com; - img-src https://ajax.googleapis.com http://build.chromium.org file:; - media-src http://build.chromium.org; - frame-src http://build.chromium.org http://test-results.appspot.com; - connect-src http://trac.webkit.org http://build.chromium.org http://127.0.0.1:8127"> + img-src https://ajax.googleapis.com http://build.chromium.org http://build.webkit.org file:; + media-src http://build.chromium.org http://build.webkit.org; + frame-src http://build.chromium.org http://build.webkit.org http://test-results.appspot.com; + connect-src http://trac.webkit.org http://build.chromium.org http://build.webkit.org http://127.0.0.1:8127"> <title>Garden-O-Matic</title> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:400,700"> <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css"> diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/Bugzilla.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/Bugzilla.js index a899fbc89..2c441fb59 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/Bugzilla.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/Bugzilla.js @@ -70,6 +70,11 @@ var g_searchCache = new base.AsynchronousCache(function(query, callback) { }); }); +bugzilla.bugURL = function(bugNumber) +{ + return config.kBugzillaURL + '/show_bug.cgi?id=' + bugNumber; +}; + bugzilla.quickSearch = function(query, callback) { g_searchCache.get(query, callback); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js index bb99cc7c6..bc8013c11 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js @@ -132,10 +132,7 @@ ViewController.prototype = { latestBuildInfos.sort(function(a, b) { return a.tester.name.localeCompare(b.tester.name) }); list.removeAllChildren(); latestBuildInfos.forEach(function(buildInfo) { - var link = document.createElement('a'); - link.href = '#/' + buildInfo.tester.name; - link.appendChild(document.createTextNode(buildInfo.tester.name)); - + var link = base.createLinkNode('#/' + buildInfo.tester.name, buildInfo.tester.name) var item = document.createElement('li'); item.appendChild(link); if (buildInfo.tooManyFailures) @@ -193,12 +190,9 @@ ViewController.prototype = { var suspectsContainer = document.createElement('div'); result.appendChild(suspectsContainer); - var link = document.createElement('a'); + var link = base.createLinkNode(trac.logURL('trunk', firstSuspectRevision, lastSuspectRevision, true), 'View regression range in Trac'); result.appendChild(link); - link.href = trac.logURL('trunk', firstSuspectRevision, lastSuspectRevision, true); - link.appendChild(document.createTextNode('View regression range in Trac')); - suspectsContainer.appendChild(document.createTextNode('Searching for suspect revisions\u2026')); // FIXME: Maybe some of this code should go in LayoutTestHistoryAnalyzer, or some other class? @@ -229,12 +223,7 @@ ViewController.prototype = { list.appendChildren(sorted(suspectCommits, compareCommits).map(function(commit) { var item = document.createElement('li'); - var link = document.createElement('a'); - item.appendChild(link); - - link.href = trac.changesetURL(commit.revision); - link.appendChild(document.createTextNode(commit.title)) - + item.appendChild(base.createLinkNode(trac.changesetURL(commit.revision), commit.title)); return item; })); }); @@ -245,10 +234,6 @@ ViewController.prototype = { _domForAuxiliaryUIElements: function() { var aside = document.createElement('aside'); aside.appendChild(document.createTextNode('Something not working? Have an idea to improve this page? ')); - var link = document.createElement('a'); - aside.appendChild(link); - - link.appendChild(document.createTextNode('File a bug!')); var queryParameters = { product: 'WebKit', component: 'Tools / Tests', @@ -257,26 +242,16 @@ ViewController.prototype = { cc: 'aroben@apple.com', short_desc: 'TestFailures page needs more unicorns!', }; - link.href = addQueryParametersToURL(config.kBugzillaURL + '/enter_bug.cgi', queryParameters); - link.target = '_blank'; - + aside.appendChild(base.createLinkNode(addQueryParametersToURL(config.kBugzillaURL + '/enter_bug.cgi', queryParameters), 'File a bug!', '_blank')); return aside; }, _domForBuildName: function(builder, buildName) { var parsed = this._buildbot.parseBuildName(buildName); - var sourceLink = document.createElement('a'); - sourceLink.href = 'http://trac.webkit.org/changeset/' + parsed.revision; - sourceLink.appendChild(document.createTextNode('r' + parsed.revision)); - - var buildLink = document.createElement('a'); - buildLink.href = builder.buildURL(parsed.buildNumber); - buildLink.appendChild(document.createTextNode(parsed.buildNumber)); - - var resultsLink = document.createElement('a'); - resultsLink.href = builder.resultsPageURL(buildName); - resultsLink.appendChild(document.createTextNode('results.html')); + var sourceLink = base.createLinkNode('http://trac.webkit.org/changeset/' + parsed.revision, 'r' + parsed.revision); + var buildLink = base.createLinkNode(builder.buildURL(parsed.buildNumber), parsed.buildNumber); + var resultsLink = base.createLinkNode(builder.resultsPageURL(buildName), 'results.html'); var result = document.createDocumentFragment(); result.appendChild(sourceLink); @@ -314,10 +289,7 @@ ViewController.prototype = { if (!('url' in diagnosticInfo)) return textAndCrashingSymbol; - var link = document.createElement('a'); - link.href = diagnosticInfo.url; - link.appendChild(textAndCrashingSymbol); - return link; + return base.createLinkNode(diagnosticInfo.url, textAndCrashingSymbol); }, _domForNewAndExistingBugs: function(tester, failingTests, bugForm) { @@ -350,10 +322,7 @@ ViewController.prototype = { list.className = 'existing-bugs-list'; function bugToListItem(bug) { - var link = document.createElement('a'); - link.href = bug.url; - link.appendChild(document.createTextNode(bug.title)); - + var link = base.createLinkNode(bug.url, bug.title); var item = document.createElement('li'); item.appendChild(link); @@ -382,13 +351,11 @@ ViewController.prototype = { var form = bugForm.domElement(); result.appendChild(form); - var link = document.createElement('a'); - container.appendChild(link); - + var linkText = 'File bug for ' + (failingTests.length > 1 ? 'these failures' : 'this failure'); + var link = base.createLinkNode('#', linkText); link.addEventListener('click', function(event) { form.submit(); event.preventDefault(); }); - link.href = '#'; - link.appendChild(document.createTextNode('File bug for ' + (failingTests.length > 1 ? 'these failures' : 'this failure'))); + container.appendChild(link); return result; }, diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js index 9b049cd4b..09616d303 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js @@ -301,6 +301,12 @@ base.AsynchronousCache.prototype.get = function(key, callback) }); }; +base.AsynchronousCache.prototype.clear = function() +{ + this._dataCache = {}; + this._callbackCache = {}; +} + /* Maintains a dictionary of items, tracking their updates and removing items that haven't been updated. An "update" is a call to the "update" method. @@ -430,4 +436,27 @@ base.relativizeTime = function(time) return result; } +base.getURLParameter = function(name) +{ + return decodeURI( + (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1] + ); +} + + +base.underscoredBuilderName = function(builderName) +{ + return builderName.replace(/[ .()]/g, '_'); +} + +base.createLinkNode = function(url, textContent, opt_target) +{ + var link = document.createElement('a'); + link.href = url; + if (opt_target) + link.target = opt_target; + link.appendChild(document.createTextNode(textContent)); + return link; +} + })(); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js index 72b8de32c..24bdb1630 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js @@ -27,8 +27,6 @@ var builders = builders || {}; (function() { -var kChromiumBuildBotURL = 'http://build.chromium.org/p/chromium.webkit'; - var kUpdateStepName = 'update'; var kUpdateScriptsStepName = 'update_scripts'; var kCompileStepName = 'compile'; @@ -36,9 +34,19 @@ var kWebKitTestsStepName = 'webkit_tests'; var kCrashedOrHungOutputMarker = 'crashed or hung'; -function urlForBuildInfo(builderName, buildNumber) +function buildBotURL(platform) +{ + return config.kPlatforms[platform].buildConsoleURL; +} + +function urlForBuilderInfo(platform, builderName) +{ + return buildBotURL(platform) + '/json/builders/' + encodeURIComponent(builderName) + '/'; +} + +function urlForBuildInfo(platform, builderName, buildNumber) { - return kChromiumBuildBotURL + '/json/builders/' + encodeURIComponent(builderName) + '/builds/' + encodeURIComponent(buildNumber); + return buildBotURL(platform) + '/json/builders/' + encodeURIComponent(builderName) + '/builds/' + encodeURIComponent(buildNumber); } function didFail(step) @@ -47,7 +55,7 @@ function didFail(step) // run-webkit-tests fails to generate test coverage when it crashes or hangs. return step.text.indexOf(kCrashedOrHungOutputMarker) != -1; } - return step.results[0] > 0; + return step.results[0] > 0 && step.text.indexOf('warning') == -1; } function failingSteps(buildInfo) @@ -71,12 +79,17 @@ function mostRecentCompletedBuildNumber(individualBuilderStatus) var g_buildInfoCache = new base.AsynchronousCache(function(key, callback) { var explodedKey = key.split('\n'); - net.get(urlForBuildInfo(explodedKey[0], explodedKey[1]), callback); + net.get(urlForBuildInfo(explodedKey[0], explodedKey[1], explodedKey[2]), callback); }); -function fetchMostRecentBuildInfoByBuilder(callback) +builders.clearBuildInfoCache = function() { - net.get(kChromiumBuildBotURL + '/json/builders', function(builderStatus) { + g_buildInfoCache.clear(); +} + +function fetchMostRecentBuildInfoByBuilder(platform, callback) +{ + net.get(buildBotURL(platform) + '/json/builders', function(builderStatus) { var buildInfoByBuilder = {}; var builderNames = Object.keys(builderStatus); var requestTracker = new base.RequestTracker(builderNames.length, callback, [buildInfoByBuilder]); @@ -84,7 +97,7 @@ function fetchMostRecentBuildInfoByBuilder(callback) // FIXME: Should garden-o-matic show these? I can imagine showing the deps bots being useful at least so // that the gardener only need to look at garden-o-matic and never at the waterfall. Not really sure who // watches the GPU bots. - if (builderName.indexOf('GPU') != -1 || builderName.indexOf('deps') != -1) { + if (builderName.indexOf('GPU') != -1 || builderName.indexOf('deps') != -1 || builderName.indexOf('ASAN') != -1) { requestTracker.requestComplete(); return; } @@ -96,7 +109,7 @@ function fetchMostRecentBuildInfoByBuilder(callback) return; } - g_buildInfoCache.get(builderName + '\n' + buildNumber, function(buildInfo) { + g_buildInfoCache.get(platform + '\n' + builderName + '\n' + buildNumber, function(buildInfo) { buildInfoByBuilder[builderName] = buildInfo; requestTracker.requestComplete(); }); @@ -104,9 +117,42 @@ function fetchMostRecentBuildInfoByBuilder(callback) }); } +builders.builderInfo = function(platform, builderName, callback) +{ + var builderInfoURL = urlForBuilderInfo(platform, builderName); + net.get(builderInfoURL, callback); +}; + +builders.cachedBuildInfos = function(platform, builderName, callback) +{ + var builderInfoURL = urlForBuilderInfo(platform, builderName); + net.get(builderInfoURL, function(builderInfo) { + var selectURL = urlForBuilderInfo(platform, builderName) + 'builds'; + // // FIXME: limit to some reasonable number? + var selectParams = { select : builderInfo.cachedBuilds }; + var traditionalEncoding = true; + selectURL += '?' + $.param(selectParams, traditionalEncoding); + net.get(selectURL, callback); + }); +} + +builders.recentBuildInfos = function(callback) +{ + fetchMostRecentBuildInfoByBuilder(config.currentPlatform, function(buildInfoByBuilder) { + var buildInfo = {}; + $.each(buildInfoByBuilder, function(builderName, thisBuildInfo) { + if (!buildInfo) + return; + + buildInfo[builderName] = thisBuildInfo; + }); + callback(buildInfo); + }); +}; + builders.buildersFailingNonLayoutTests = function(callback) { - fetchMostRecentBuildInfoByBuilder(function(buildInfoByBuilder) { + fetchMostRecentBuildInfoByBuilder(config.currentPlatform, function(buildInfoByBuilder) { var failureList = {}; $.each(buildInfoByBuilder, function(builderName, buildInfo) { if (!buildInfo) @@ -121,11 +167,12 @@ builders.buildersFailingNonLayoutTests = function(callback) builders.perfBuilders = function(callback) { - fetchMostRecentBuildInfoByBuilder(function(buildInfoByBuilder) { + fetchMostRecentBuildInfoByBuilder(config.currentPlatform, function(buildInfoByBuilder) { var perfTestMap = {}; $.each(buildInfoByBuilder, function(builderName, buildInfo) { if (!buildInfo || builderName.indexOf('Perf') == -1) return; + buildInfo.steps.forEach(function(step) { // FIXME: If the compile is broken, grab an older build. // If the compile/update is broken, no steps will have a results url. diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js index 7259e2819..7e0f38d8f 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js @@ -46,6 +46,15 @@ var kExampleBuilderStatusJSON = { "slaves": ["vm124-m1"], "state": "building" }, + "Webkit ASAN": { + "basedir": "Webkit_Linux", + "cachedBuilds": [11459, 11460, 11461, 11462], + "category": "6webkit linux latest", + "currentBuilds": [11461, 11462], + "pendingBuilds": 0, + "slaves": ["vm124-m1"], + "state": "building" + }, }; var kExampleBuildInfoJSON = { @@ -582,6 +591,77 @@ var kExampleBuildInfoWithWebKitTestCrashJSON = { "times": [1318364210.066524, 1318366408.0732119] }; +var kExampleBuildInfoWithTaskKillWarning = { + "blame": ["asvitkine@chromium.org", "derat@chromium.org", "nirnimesh@chromium.org"], + "builderName": "Webkit Win (deps)(dbg)(2)", + "currentStep": null, + "eta": null, + "logs": [ + ["stdio", "http://build.chromium.org/p/chromium.webkitbuilders/Webkit%20Win%20%28deps%29%28dbg%29%282%29/builds/7653/steps/svnkill/logs/stdio"], + ], + "number": 7653, + "properties": [ + ["blamelist", ["asvitkine@chromium.org", "derat@chromium.org", "nirnimesh@chromium.org"], "Build"], + ["branch", "src", "Build"], + ["buildername", "Webkit Win (deps)(dbg)(2)", "Builder"], + ["buildnumber", 7653, "Build"], + ["got_revision", "104939", "Source"], + ["gtest_filter", null, "Factory"], + ["mastername", "chromium.webkit", "master.cfg"], + ["project", "", "Build"], + ["repository", "svn://svn-mirror.golo.chromium.org/chrome/trunk", "Build"], + ["revision", "104939", "Build"], + ["scheduler", "s1_chromium_dbg_dep", "Scheduler"], + ["slavename", "vm114-m1", "BuildSlave"] + ], + "reason": "downstream", + "results": 2, + "slave": "vm114-m1", + "sourceStamp": { + "branch": "src", + "changes": [{ + "at": "Tue 11 Oct 2011 12:18:40", + "branch": "src", + "category": null, + "comments": "Disable prefs.PrefsTest.testGeolocationPref on win\n\nTBR=dennisjeffrey@chromium.org\nBUG=99865\nTEST=\n\nReview URL: http://codereview.chromium.org/8234007", + "files": [{ + "name": "chrome/test/functional/PYAUTO_TESTS", + "url": null + }], + "number": 1397, + "project": "", + "properties": [], + "repository": "svn://svn-mirror.golo.chromium.org/chrome/trunk", + "rev": "104936", + "revision": "104936", + "revlink": "http://src.chromium.org/viewvc/chrome?view=rev&revision=104936", + "when": 1318360720, + "who": "nirnimesh@chromium.org" + }], + "hasPatch": false, + "project": "", + "repository": "svn://svn-mirror.golo.chromium.org/chrome/trunk", + "revision": "104939" + }, + "steps": [{ + "eta": null, + "expectations": [["output",1776,1534.0625014267862]], + "isFinished": true, + "isStarted": true, + "logs": [["stdio","http://build.chromium.org/p/chromium.webkitbuilders/Vista%20Perf/builds/10268/steps/taskkill/logs/stdio"]], + "name": "taskkill", + "results": [1,[]], + "statistics": {}, + "step_number": 2, + "text": ["taskkill","warning"], + "times": [1339438214.177362,1339438222.555572], + "urls": {} + }], + "text": ["failed", "webkit_tests", "archive_webkit_tests_results", "webkit_gpu_tests", "archive_webkit_tests_gpu_results"], + "times": [1318364210.066524, 1318366408.0732119] +}; + + var kExamplePerfBuilderStatusJSON = { "Webkit Linux": { "basedir": "Webkit_Linux", @@ -866,6 +946,7 @@ var kExamplePerfBuildInfoJSON = { test("buildersFailing", 3, function() { var simulator = new NetworkSimulator(); + builders.clearBuildInfoCache(); var failingBuildInfoJSON = JSON.parse(JSON.stringify(kExampleBuildInfoJSON)); failingBuildInfoJSON.number = 11460; @@ -882,6 +963,8 @@ test("buildersFailing", 3, function() { callback(kExampleBuildInfoJSON); else if (/Webkit%20Mac10\.6/.exec(url)) callback(failingBuildInfoJSON); + else if (/Webkit%20ASAN/.exec(url)) + callback(failingBuildInfoJSON); else { ok(false, "Unexpected URL: " + url); callback(); @@ -912,6 +995,7 @@ test("buildersFailing", 3, function() { test("buildersFailing (run-webkit-tests crash)", 3, function() { var simulator = new NetworkSimulator(); + builders.clearBuildInfoCache(); var builderStatusJSON = JSON.parse(JSON.stringify(kExampleBuilderStatusJSON)); delete builderStatusJSON['Webkit Mac10.6']; @@ -941,7 +1025,6 @@ test("buildersFailing (run-webkit-tests crash)", 3, function() { builders.buildersFailingNonLayoutTests(function(builderNameList) { deepEqual(builderNameList, { "Webkit Linux": [ - "extract_build", "webkit_tests", "archive_webkit_tests_results", "webkit_gpu_tests", @@ -957,8 +1040,50 @@ test("buildersFailing (run-webkit-tests crash)", 3, function() { ]); }); +test("buildersFailing (taskkill warning)", 3, function() { + var simulator = new NetworkSimulator(); + builders.clearBuildInfoCache(); + + var builderStatusJSON = JSON.parse(JSON.stringify(kExampleBuilderStatusJSON)); + delete builderStatusJSON['Webkit Mac10.6']; + builderStatusJSON['Webkit Linux'].cachedBuilds = [21460]; + builderStatusJSON['Webkit Linux'].currentBuilds = []; + + var failingBuildInfoJSON = JSON.parse(JSON.stringify(kExampleBuildInfoWithTaskKillWarning)); + failingBuildInfoJSON.number = 21460; + + var requestedURLs = []; + simulator.get = function(url, callback) + { + requestedURLs.push(url); + simulator.scheduleCallback(function() { + if (/\/json\/builders$/.exec(url)) + callback(builderStatusJSON); + else if (/Webkit%20Linux/.exec(url)) + callback(failingBuildInfoJSON); + else { + ok(false, "Unexpected URL: " + url); + callback(); + } + }); + }; + + simulator.runTest(function() { + builders.buildersFailingNonLayoutTests(function(builderNameList) { + deepEqual(builderNameList, {}); + }); + }); + + deepEqual(requestedURLs, [ + "http://build.chromium.org/p/chromium.webkit/json/builders", + "http://build.chromium.org/p/chromium.webkit/json/builders/Webkit%20Linux/builds/21460", + ]); +}); + test("builders.perfBuilders", 2, function() { var simulator = new NetworkSimulator(); + builders.clearBuildInfoCache(); + var builderStatusJSON = JSON.parse(JSON.stringify(kExamplePerfBuilderStatusJSON)); var failingBuildInfoJSON = JSON.parse(JSON.stringify(kExamplePerfBuildInfoJSON)); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js index 39ae71372..40097dcb8 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js @@ -27,21 +27,81 @@ var config = config || {}; (function() { -config.kBuilders = { - 'Webkit Win': {version: 'xp'}, - 'Webkit Vista': {version: 'vista'}, - 'Webkit Win7': {version: 'win7'}, - 'Webkit Win (dbg)(1)': {version: 'xp', debug: true}, - 'Webkit Win (dbg)(2)': {version: 'xp', debug: true}, - 'Webkit Linux': {version: 'lucid', is64bit: true}, - 'Webkit Linux 32': {version: 'lucid'}, - 'Webkit Linux (dbg)': {version: 'lucid', is64bit: true, debug: true}, - 'Webkit Mac10.5': {version: 'leopard'}, - 'Webkit Mac10.5 (dbg)(1)': {version: 'leopard', debug: true}, - 'Webkit Mac10.5 (dbg)(2)': {version: 'leopard', debug: true}, - 'Webkit Mac10.6': {version: 'snowleopard'}, - 'Webkit Mac10.6 (dbg)': {version: 'snowleopard', debug: true}, - 'Webkit Mac10.7': {version: 'lion'}, +config.kPlatforms = { + 'apple' : { + label : 'Apple', + buildConsoleURL: 'http://build.webkit.org', + layoutTestResultsURL: 'http://build.webkit.org/results', + waterfallURL: 'http://build.webkit.org/waterfall', + builders: { + 'Apple Lion Release WK1 (Tests)' : {version: 'lion' }, + 'Apple Lion Debug WK1 (Tests)' : {version: 'lion', debug: true}, + 'Apple Lion Release WK2 (Tests)' : {version: 'lion' }, + 'Apple Lion Debug WK2 (Tests)' : {version: 'lion', debug: true}, + // 'Apple Win XP Debug (Tests)' : {version: 'xp',debug: true}, + // 'Apple Win 7 Release (Tests)' : {version: 'win7'}, + }, + haveBuilderAccumulatedResults : false, + useDirectoryListingForOldBuilds: false, + useFlakinessDashboard: false, + resultsDirectoryNameFromBuilderName: function(builderName) { + return encodeURIComponent(builderName); + }, + resultsDirectoryForBuildNumber: function(buildNumber, revision) { + return encodeURIComponent('r' + revision + ' (' + buildNumber + ')'); + }, + }, + 'chromium' : { + label : 'Chromium', + buildConsoleURL: 'http://build.chromium.org/p/chromium.webkit', + layoutTestResultsURL: 'http://build.chromium.org/f/chromium/layout_test_results', + waterfallURL: 'http://build.chromium.org/p/chromium.webkit/waterfall', + builders: { + 'Webkit Win': {version: 'xp'}, + 'Webkit Vista': {version: 'vista'}, + 'Webkit Win7': {version: 'win7'}, + 'Webkit Win (dbg)(1)': {version: 'xp', debug: true}, + 'Webkit Win (dbg)(2)': {version: 'xp', debug: true}, + 'Webkit Linux': {version: 'lucid', is64bit: true}, + 'Webkit Linux 32': {version: 'lucid'}, + 'Webkit Linux (dbg)': {version: 'lucid', is64bit: true, debug: true}, + 'Webkit Mac10.5': {version: 'leopard'}, + 'Webkit Mac10.5 (dbg)(1)': {version: 'leopard', debug: true}, + 'Webkit Mac10.5 (dbg)(2)': {version: 'leopard', debug: true}, + 'Webkit Mac10.6': {version: 'snowleopard'}, + 'Webkit Mac10.6 (dbg)': {version: 'snowleopard', debug: true}, + 'Webkit Mac10.7': {version: 'lion'}, + }, + haveBuilderAccumulatedResults : true, + useDirectoryListingForOldBuilds: true, + useFlakinessDashboard: true, + resultsDirectoryNameFromBuilderName: function(builderName) { + return base.underscoredBuilderName(builderName); + }, + resultsDirectoryForBuildNumber: function(buildNumber, revision) { + return buildNumber; + }, + }, + 'gtk' : { + label : 'GTK', + buildConsoleURL: 'http://build.webkit.org', + layoutTestResultsURL: 'http://build.webkit.org/results', + waterfallURL: 'http://build.webkit.org/waterfall', + builders: { + 'GTK Linux 32-bit Release' : {version: '32-bit release'}, + 'GTK Linux 64-bit Release' : {version: '64-bit release'}, + 'GTK Linux 64-bit Debug' : {version: '64-bit debug',debug: true}, + }, + haveBuilderAccumulatedResults : false, + useDirectoryListingForOldBuilds: false, + useFlakinessDashboard: false, + resultsDirectoryNameFromBuilderName: function(builderName) { + return encodeURIComponent(builderName); + }, + resultsDirectoryForBuildNumber: function(buildNumber, revision) { + return encodeURIComponent('r' + revision + ' (' + buildNumber + ')'); + }, + }, }; config.kTracURL = 'http://trac.webkit.org'; @@ -61,4 +121,15 @@ config.kRelativeTimeUpdateFrequency = 1000 * 60; config.kExperimentalFeatures = window.location.search.search('enableExperiments=1') != -1; +config.currentPlatform = 'chromium'; + +config.setPlatform = function(platform) +{ + if (!this.kPlatforms[platform]) { + window.console.log(platform + ' is not a recognized platform'); + return; + } + config.currentPlatform = platform; +}; + })(); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js index 7772826cc..ac2d9d1a6 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js @@ -79,7 +79,21 @@ function update() updating.dismiss(); - g_revisionHint = new ui.notifications.Info('Latest revision processed by every bot: ' + model.latestRevisionWithNoBuildersInFlight()); + g_revisionHint = new ui.notifications.Info(''); + + var latestRevisionSpan = document.createElement('span'); + latestRevisionSpan.appendChild(document.createTextNode('Latest revision processed by every bot: ')); + + var latestRevision = model.latestRevisionWithNoBuildersInFlight(); + latestRevisionSpan.appendChild(base.createLinkNode(trac.changesetURL(latestRevision), latestRevision)); + + var totRevision = model.latestRevision(); + latestRevisionSpan.appendChild(document.createTextNode(' (trunk is at ')); + latestRevisionSpan.appendChild(base.createLinkNode(trac.changesetURL(totRevision), totRevision)); + latestRevisionSpan.appendChild(document.createTextNode(')')); + + g_revisionHint.updateWithNode(latestRevisionSpan); + g_info.add(g_revisionHint); }); }); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js index c2debbd6c..476e94e1d 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js @@ -109,7 +109,8 @@ model.updateRecentCommits = function(callback) }); }; -function updateCommitIndex() { +function updateCommitIndex() +{ model.state.recentCommits.forEach(function(commitData) { g_commitIndex[commitData.revision] = commitData; }); @@ -137,6 +138,11 @@ model.buildersInFlightForRevision = function(revision) return builders; }; +model.latestRevision = function() +{ + return model.state.recentCommits[0].revision; +} + model.latestRevisionWithNoBuildersInFlight = function() { var revision = 0; @@ -152,7 +158,8 @@ model.latestRevisionWithNoBuildersInFlight = function() model.updateResultsByBuilder = function(callback) { - results.fetchResultsByBuilder(Object.keys(config.kBuilders), function(resultsByBuilder) { + var platformBuilders = config.kPlatforms[config.currentPlatform].builders; + results.fetchResultsByBuilder(Object.keys(platformBuilders), function(resultsByBuilder) { model.state.resultsByBuilder = resultsByBuilder; callback(); }); @@ -189,6 +196,7 @@ model.analyzeUnexpectedFailures = function(callback, completionCallback) } model.state.failureAnalysisByTest[testName] = failureAnalysis; + callback(failureAnalysis); tracker.requestComplete(); }); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/net.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/net.js index 29753b7c1..0a4baae9c 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/net.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/net.js @@ -57,7 +57,7 @@ net.jsonp = function(url, callback) success: function(jsonp) { callback(base.parseJSONP(jsonp)); }, - error: function() { + error: function(request, textStatus, errorThrown) { callback({}); }, }); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js index eff110b1e..994c47957 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js @@ -27,7 +27,6 @@ var results = results || {}; (function() { -var kLayoutTestResultsServer = 'http://build.chromium.org/f/chromium/layout_test_results/'; var kLayoutTestResultsPath = '/results/layout-test-results/'; var kResultsName = 'full_results.json'; @@ -41,6 +40,7 @@ var CRASH = 'CRASH'; var IMAGE = 'IMAGE'; var IMAGE_TEXT = 'IMAGE+TEXT'; var AUDIO = 'AUDIO'; +var MISSING = 'MISSING'; var kFailingResults = [TIMEOUT, TEXT, CRASH, IMAGE, IMAGE_TEXT, AUDIO]; @@ -83,6 +83,11 @@ results.kAudioType = 'audio' results.kTextType = 'text' // FIXME: There are more types of tests. +function layoutTestResultsURL(platform) +{ + return config.kPlatforms[platform].layoutTestResultsURL; +} + function possibleSuffixListFor(failureTypeList) { var suffixList = []; @@ -127,6 +132,10 @@ function possibleSuffixListFor(failureTypeList) case CRASH: suffixList.push(kCrashLogSuffix); break; + case MISSING: + pushImageSuffixes(); + pushTextSuffixes(); + break; default: // FIXME: Add support for the rest of the result types. // '-expected.html', @@ -148,6 +157,7 @@ results.failureTypeToExtensionList = function(failureType) return [kWAVExtension]; case TEXT: return [kTXTExtension]; + case MISSING: case IMAGE_TEXT: return [kTXTExtension, kPNGExtension]; default: @@ -173,32 +183,32 @@ results.canRebaseline = function(failureTypeList) results.directoryForBuilder = function(builderName) { - return builderName.replace(/[ .()]/g, '_'); + return config.kPlatforms[config.currentPlatform].resultsDirectoryNameFromBuilderName(builderName); } -function resultsDirectoryURL(builderName) +function resultsDirectoryURL(platform, builderName) { - return kLayoutTestResultsServer + results.directoryForBuilder(builderName) + kLayoutTestResultsPath; + return layoutTestResultsURL(platform) + '/' + results.directoryForBuilder(builderName) + kLayoutTestResultsPath; } -function resultsDirectoryListingURL(builderName) +function resultsDirectoryListingURL(platform, builderName) { - return kLayoutTestResultsServer + results.directoryForBuilder(builderName) + '/'; + return layoutTestResultsURL(platform) + '/' + results.directoryForBuilder(builderName) + '/'; } -function resultsDirectoryURLForBuildNumber(builderName, buildNumber) +function resultsDirectoryURLForBuildNumber(platform, builderName, buildNumber, revision) { - return resultsDirectoryListingURL(builderName) + buildNumber + '/' + return resultsDirectoryListingURL(platform, builderName) + config.kPlatforms[platform].resultsDirectoryForBuildNumber(buildNumber, revision) + '/'; } -function resultsSummaryURL(builderName) +function resultsSummaryURL(platform, builderName) { - return resultsDirectoryURL(builderName) + kResultsName; + return resultsDirectoryURL(platform, builderName) + kResultsName; } -function resultsSummaryURLForBuildNumber(builderName, buildNumber) +function resultsSummaryURLForBuildNumber(platform, builderName, buildNumber, revision) { - return resultsDirectoryURLForBuildNumber(builderName, buildNumber) + kResultsName; + return resultsDirectoryURLForBuildNumber(platform, builderName, buildNumber, revision) + kResultsName; } var g_resultsCache = new base.AsynchronousCache(function (key, callback) { @@ -302,6 +312,8 @@ function resultsByTest(resultsByBuilder, filter) $.each(resultsByBuilder, function(builderName, resultsTree) { $.each(filter(resultsTree), function(testName, resultNode) { resultsByTest[testName] = resultsByTest[testName] || {}; + if (!config.kPlatforms[config.currentPlatform].haveBuilderAccumulatedResults) + resultNode._buildLocation = resultsTree._buildLocation; resultsByTest[testName][builderName] = resultNode; }); }); @@ -326,11 +338,16 @@ results.unexpectedSuccessesByTest = function(resultsByBuilder) results.failureInfoForTestAndBuilder = function(resultsByTest, testName, builderName) { - return { + var failureInfoForTest = { 'testName': testName, 'builderName': builderName, - 'failureTypeList': results.failureTypeList(resultsByTest[testName][builderName].actual) - } + 'failureTypeList': results.failureTypeList(resultsByTest[testName][builderName].actual), + }; + + if (!config.kPlatforms[config.currentPlatform].haveBuilderAccumulatedResults) + failureInfoForTest.buildLocation = resultsByTest[testName][builderName]._buildLocation; + + return failureInfoForTest; }; results.collectUnexpectedResults = function(dictionaryOfResultNodes) @@ -343,18 +360,43 @@ results.collectUnexpectedResults = function(dictionaryOfResultNodes) return base.uniquifyArray(collectedResults); }; -function historicalResultsSummaryURLs(builderName, callback) -{ - net.get(resultsDirectoryListingURL(builderName), function(directoryListing) { - var summaryURLs = directoryListing.match(kBuildLinkRegexp).map(function(buildLink) { - var buildNumber = parseInt(buildLink.match(kBuildNumberRegexp)[0]); - return resultsSummaryURLForBuildNumber(builderName, buildNumber); - }).reverse(); - callback(summaryURLs); - }); +// Callback data is [{ buildNumber:, revision:, url: }] +function historicalResultsLocations(platform, builderName, callback) +{ + if (config.kPlatforms[platform].useDirectoryListingForOldBuilds) { + var listingURL = resultsDirectoryListingURL(platform, builderName); + net.get(listingURL, function(directoryListing) { + var historicalResultsData = directoryListing.match(kBuildLinkRegexp).map(function(buildLink) { + var buildNumber = parseInt(buildLink.match(kBuildNumberRegexp)[0]); + var revision = 0; // unused for Chromium. + var resultsData = { + 'buildNumber': buildNumber, + 'revision': revision, + 'url': resultsSummaryURLForBuildNumber(platform, builderName, buildNumber, revision) + }; + return resultsData; + }).reverse(); + + callback(historicalResultsData); + }); + } else { + var historicalResultsData = []; + builders.cachedBuildInfos(platform, builderName, function(cachedBuildInfos) { + $.each(cachedBuildInfos, function(buildNumber, buildInfo) { + var resultsData = { + 'buildNumber': buildNumber, + 'revision': buildInfo.sourceStamp.revision, + 'url': resultsSummaryURLForBuildNumber(platform, builderName, buildNumber, buildInfo.sourceStamp.revision), + } + historicalResultsData.push(resultsData); + }); + + callback(historicalResultsData.reverse()); + }); + } } -function walkHistory(builderName, testName, callback) +function walkHistory(platform, builderName, testName, callback) { var indexOfNextKeyToFetch = 0; var keyList = []; @@ -366,9 +408,13 @@ function walkHistory(builderName, testName, callback) return; } - var key = keyList[indexOfNextKeyToFetch]; + var resultsURL = keyList[indexOfNextKeyToFetch].url; ++indexOfNextKeyToFetch; - g_resultsCache.get(key, function(resultsTree) { + g_resultsCache.get(resultsURL, function(resultsTree) { + if ($.isEmptyObject(resultsTree)) { + continueWalk(); + return; + } var resultNode = results.resultNodeForTest(resultsTree, testName); var revision = parseInt(resultsTree['revision']) if (isNaN(revision)) @@ -385,8 +431,8 @@ function walkHistory(builderName, testName, callback) continueWalk(); } - historicalResultsSummaryURLs(builderName, function(summaryURLs) { - keyList = summaryURLs; + historicalResultsLocations(platform, builderName, function(resultsLocations) { + keyList = resultsLocations; continueWalk(); }); } @@ -396,7 +442,8 @@ results.regressionRangeForFailure = function(builderName, testName, callback) var oldestFailingRevision = 0; var newestPassingRevision = 0; - walkHistory(builderName, testName, function(revision, resultNode) { + // FIXME: should treat {platform, builderName} as a tuple + walkHistory(config.currentPlatform, builderName, testName, function(revision, resultNode) { if (!revision) { callback(oldestFailingRevision, newestPassingRevision); return false; @@ -426,7 +473,7 @@ function mergeRegressionRanges(regressionRanges) mergedRange.newestPassingRevision = 0; $.each(regressionRanges, function(builderName, range) { - if (!range.oldestFailingRevision || !range.newestPassingRevision) + if (!range.oldestFailingRevision && !range.newestPassingRevision) return if (!mergedRange.oldestFailingRevision) @@ -434,54 +481,50 @@ function mergeRegressionRanges(regressionRanges) if (!mergedRange.newestPassingRevision) mergedRange.newestPassingRevision = range.newestPassingRevision; - if (range.oldestFailingRevision < mergedRange.oldestFailingRevision) + if (range.oldestFailingRevision && range.oldestFailingRevision < mergedRange.oldestFailingRevision) mergedRange.oldestFailingRevision = range.oldestFailingRevision; if (range.newestPassingRevision > mergedRange.newestPassingRevision) mergedRange.newestPassingRevision = range.newestPassingRevision; }); + return mergedRange; } results.unifyRegressionRanges = function(builderNameList, testName, callback) { - var queriesInFlight = builderNameList.length; - if (!queriesInFlight) - callback(0, 0); - var regressionRanges = {}; + + var tracker = new base.RequestTracker(builderNameList.length, function() { + var mergedRange = mergeRegressionRanges(regressionRanges); + callback(mergedRange.oldestFailingRevision, mergedRange.newestPassingRevision); + }); + $.each(builderNameList, function(index, builderName) { results.regressionRangeForFailure(builderName, testName, function(oldestFailingRevision, newestPassingRevision) { var range = {}; range.oldestFailingRevision = oldestFailingRevision; range.newestPassingRevision = newestPassingRevision; regressionRanges[builderName] = range; - - --queriesInFlight; - if (!queriesInFlight) { - var mergedRange = mergeRegressionRanges(regressionRanges); - callback(mergedRange.oldestFailingRevision, mergedRange.newestPassingRevision); - } + tracker.requestComplete(); }); }); }; -results.countFailureOccurances = function(builderNameList, testName, callback) +results.countFailureOccurences = function(builderNameList, testName, callback) { - var queriesInFlight = builderNameList.length; - if (!queriesInFlight) - callback(0); - var failureCount = 0; + + var tracker = new base.RequestTracker(builderNameList.length, function() { + callback(failureCount); + }); + $.each(builderNameList, function(index, builderName) { - walkHistory(builderName, testName, function(revision, resultNode) { + walkHistory(config.currentPlatform, builderName, testName, function(revision, resultNode) { if (isUnexpectedFailure(resultNode)) { ++failureCount; return true; } - - --queriesInFlight; - if (!queriesInFlight) - callback(failureCount); + tracker.requestComplete(); return false; }); }); @@ -536,54 +579,94 @@ function sortResultURLsBySuffix(urls) results.fetchResultsURLs = function(failureInfo, callback) { - var stem = resultsDirectoryURL(failureInfo.builderName); var testNameStem = base.trimExtension(failureInfo.testName); + var urlStem; + + if (config.kPlatforms[config.currentPlatform].haveBuilderAccumulatedResults) + urlStem = resultsDirectoryURL(config.currentPlatform, failureInfo.builderName); + else + urlStem = failureInfo.buildLocation.url.replace(kResultsName, ''); var suffixList = possibleSuffixListFor(failureInfo.failureTypeList); - var resultURLs = []; - var requestsInFlight = suffixList.length; - - if (!requestsInFlight) { - callback([]); - return; - } - - function checkComplete() - { - if (--requestsInFlight == 0) - callback(sortResultURLsBySuffix(resultURLs)); - } - + var tracker = new base.RequestTracker(suffixList.length, function() { + callback(sortResultURLsBySuffix(resultURLs)); + }); $.each(suffixList, function(index, suffix) { - var url = stem + testNameStem + suffix; + var url = urlStem + testNameStem + suffix; net.probe(url, { success: function() { resultURLs.push(url); - checkComplete(); + tracker.requestComplete(); + }, + error: function() { + tracker.requestComplete(); }, - error: checkComplete, }); }); }; results.fetchResultsForBuilder = function(builderName, callback) { - net.jsonp(resultsSummaryURL(builderName), callback); + var resultsURL = resultsSummaryURL(config.currentPlatform, builderName); + net.jsonp(resultsURL, callback); +}; + +results.fetchResultsForBuildOnBuilder = function(builderName, buildNumber, revision, callback) +{ + var resultsURL = resultsSummaryURLForBuildNumber(config.currentPlatform, builderName, buildNumber, revision); + net.jsonp(resultsURL, callback); +}; + +// Look for the most recent completed build that has full results. +results.fetchResultsForMostRecentCompletedBuildOnBuilder = function(builderName, callback) +{ + historicalResultsLocations(config.currentPlatform, builderName, function(buildLocations) { + var currentIndex = 0; + var resultsCallback = function(buildResults) { + if ($.isEmptyObject(buildResults)) { + ++currentIndex; + net.jsonp(buildLocations[currentIndex].url, resultsCallback); + return; + } + if (!config.kPlatforms[config.currentPlatform].haveBuilderAccumulatedResults) + buildResults._buildLocation = buildLocations[currentIndex]; + callback(buildResults); + }; + net.jsonp(buildLocations[currentIndex].url, resultsCallback); + }); }; results.fetchResultsByBuilder = function(builderNameList, callback) { - var resultsByBuilder = {} - var requestsInFlight = builderNameList.length; - $.each(builderNameList, function(index, builderName) { - results.fetchResultsForBuilder(builderName, function(resultsTree) { - resultsByBuilder[builderName] = resultsTree; - --requestsInFlight; - if (!requestsInFlight) - callback(resultsByBuilder); + var resultsByBuilder = {}; + if (config.kPlatforms[config.currentPlatform].haveBuilderAccumulatedResults) { + var tracker = new base.RequestTracker(builderNameList.length, function() { + callback(resultsByBuilder); }); - }); + $.each(builderNameList, function(index, builderName) { + results.fetchResultsForBuilder(builderName, function(resultsTree) { + resultsByBuilder[builderName] = resultsTree; + tracker.requestComplete(); + }); + }); + } else { + builders.recentBuildInfos(function(recentBuildInfos) { + var requestsInFlight = 0; + $.each(builderNameList, function(index, builderName) { + if (recentBuildInfos[builderName]) { + // FIXME: use RequestTracker + ++requestsInFlight; + results.fetchResultsForMostRecentCompletedBuildOnBuilder(builderName, function(resultsTree) { + resultsByBuilder[builderName] = resultsTree; + --requestsInFlight; + if (!requestsInFlight) + callback(resultsByBuilder); + }); + } + }); + }); + } }; })(); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results_unittests.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results_unittests.js index b5d198fc7..e731bf39a 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results_unittests.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results_unittests.js @@ -344,7 +344,7 @@ test("walkHistory", 6, function() { equals(newestPassingRevision, 90425); }); - results.countFailureOccurances(["Mock Builder", "Another Builder"], "userscripts/another-test.html", function(failureCount) { + results.countFailureOccurences(["Mock Builder", "Another Builder"], "userscripts/another-test.html", function(failureCount) { equals(failureCount, 4); }); }); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/summary-mock.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/summary-mock.js index f2d78c49e..5e732cf25 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/summary-mock.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/summary-mock.js @@ -96,7 +96,7 @@ var testNames = new Cycler([ 'tables/mozilla/bugs/bug52505.html' ]); -var builders = new Cycler(Object.keys(config.kBuilders), 3); +var builders = new Cycler(Object.keys(config.kPlatforms[config.currentPlatform].builders), 3); var expectations = new Cycler([ 'TEXT', diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js index b2930ff81..f09fe2915 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js @@ -29,7 +29,7 @@ var ui = ui || {}; ui.displayURLForBuilder = function(builderName) { - return 'http://build.chromium.org/p/chromium.webkit/waterfall?' + $.param({ + return config.kPlatforms[config.currentPlatform].waterfallURL + '?' + $.param({ 'builder': builderName }); } @@ -52,7 +52,10 @@ ui.urlForFlakinessDashboard = function(opt_testNameList) ui.urlForEmbeddedFlakinessDashboard = function(opt_testNameList) { - return ui.urlForFlakinessDashboard(opt_testNameList) + '&showChrome=false'; + if (config.kPlatforms[config.currentPlatform].useFlakinessDashboard) + return ui.urlForFlakinessDashboard(opt_testNameList) + '&showChrome=false'; + + return 'about:blank'; } ui.rolloutReasonForTestNameList = function(testNameList) @@ -67,6 +70,7 @@ ui.onebar = base.extends('div', { { this.id = 'onebar'; this.innerHTML = + '<div><select id="platform-picker"></select></div>' + '<ul>' + '<li><a href="#unexpected">Unexpected Failures</a></li>' + '<li><a href="#expected">Expected Failures</a></li>' + @@ -90,6 +94,29 @@ ui.onebar = base.extends('div', { show: function(event, ui) { this._restoreScrollOffset(ui.index); }, }); }, + _buildPlatformsPopup: function() { + // FIXME: find a better place to do this. + var urlPlatform = base.getURLParameter('platform'); + if (urlPlatform) + config.setPlatform(urlPlatform); + + var platformSelect = document.getElementById('platform-picker'); + var currentPlatformIndex = 0; + Object.keys(config.kPlatforms).sort().forEach(function(platformName) { + var option = document.createElement('option'); + option.innerText = config.kPlatforms[platformName].label; + option._platform = platformName; + if (platformName == config.currentPlatform) + currentPlatformIndex = platformSelect.childNodes.length; + platformSelect.appendChild(option); + }); + + platformSelect.addEventListener('change', function() { + window.location.search = '?platform=' + platformSelect.selectedOptions[0]._platform; + }, false); + + platformSelect.selectedIndex = currentPlatformIndex; + }, _saveScrollOffset: function() { var tabIndex = this._tabs.tabs('option', 'selected'); this._tabIndexToSavedScrollOffset[tabIndex] = document.body.scrollTop; @@ -131,6 +158,7 @@ ui.onebar = base.extends('div', { { document.body.insertBefore(this, document.body.firstChild); this._setupHistoryHandlers(); + this._buildPlatformsPopup(); }, tabNamed: function(tabName) { diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js index 2c53bfc1b..77ecda3c2 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js @@ -33,7 +33,8 @@ var kBuildingResult = 'BUILDING'; ui.failures.Builder = base.extends('a', { init: function(builderName, failures) { - var configuration = config.kBuilders[builderName]; + var platformBuilders = config.kPlatforms[config.currentPlatform].builders; + var configuration = platformBuilders[builderName]; if (configuration) { if (configuration.version) this._addSpan('version', configuration.version); @@ -108,7 +109,7 @@ ui.failures.FailureGrid = base.extends('table', { return; Object.keys(resultsByBuilder).forEach(function(builderName) { - var configuration = config.kBuilders[builderName]; + var configuration = config.kPlatforms[config.currentPlatform].builders[builderName]; if (!configuration) throw "Unknown builder name: " + builderName; var row = this._rowByResult(resultsByBuilder[builderName].actual); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js index 572082e4d..77d2cea28 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js @@ -74,7 +74,7 @@ ui.notifications.Notification = base.extends('li', { { this.parentNode && this.parentNode.removeChild(this); }); - } + }, }); ui.notifications.Info = base.extends(ui.notifications.Notification, { @@ -85,16 +85,18 @@ ui.notifications.Info = base.extends(ui.notifications.Notification, { update: function(message) { this._what.textContent = message; + }, + updateWithNode: function(node) + { + $(this._what).empty(); + this._what.appendChild(node); } }); ui.notifications.FailingTestGroup = base.extends('li', { init: function(groupName, testNameList) { - var link = this.appendChild(document.createElement('a')); - link.target = '_blank'; - link.href = ui.urlForFlakinessDashboard(testNameList); - link.textContent = groupName; + this.appendChild(base.createLinkNode(ui.urlForFlakinessDashboard(testNameList), groupName, '_blank')); } }); @@ -110,20 +112,18 @@ ui.notifications.SuspiciousCommit = base.extends(Cause, { init: function(commitData) { this._revision = commitData.revision; - var linkToRevision = this._description.appendChild(document.createElement('a')); + this._description.appendChild(base.createLinkNode(trac.changesetURL(commitData.revision), commitData.revision, '_blank')); this._details = this._description.appendChild(document.createElement('span')); - linkToRevision.href = trac.changesetURL(commitData.revision); - linkToRevision.target = '_blank'; - linkToRevision.textContent = commitData.revision; this._addDetail('summary', commitData); this._addDetail('author', commitData); this._addDetail('reviewer', commitData); + this._addDetail('bugID', commitData, bugzilla.bugURL); }, hasRevision: function(revision) { return this._revision == revision; }, - _addDetail: function(part, commitData) + _addDetail: function(part, commitData, linkFunction) { var content = commitData[part]; if (!content) @@ -131,7 +131,12 @@ ui.notifications.SuspiciousCommit = base.extends(Cause, { var span = this._details.appendChild(document.createElement('span')); span.className = part; - span.textContent = content; + + if (linkFunction) { + var link = base.createLinkNode(linkFunction(content), content, '_blank'); + span.appendChild(link); + } else + span.textContent = content; } }); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js index 6c6a18c05..cfd9dff5a 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js @@ -79,7 +79,7 @@ test('Info', 2, function() { test('FailingTestGroup', 2, function() { var failingTest = new ui.notifications.FailingTestGroup('test', ['test.html']); equal(failingTest.tagName, 'LI'); - equal(failingTest.innerHTML, '<a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test.html">test</a>'); + equal(failingTest.innerHTML, '<a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test.html" target="_blank">test</a>'); }); test('SuspiciousCommit', 2, function() { @@ -130,7 +130,7 @@ test('FailingTestsSummary', 12, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test" target="_blank">test</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -153,7 +153,7 @@ test('FailingTestsSummary', 12, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test" target="_blank">test</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -178,7 +178,7 @@ test('FailingTestsSummary', 12, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test" target="_blank">test</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -218,8 +218,8 @@ test('FailingTestsSummary', 12, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo">foo</a></li>' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo" target="_blank">foo</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test" target="_blank">test</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -263,8 +263,8 @@ test('FailingTestsSummary', 12, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo">foo</a></li>' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test">test</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=foo" target="_blank">foo</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=test" target="_blank">test</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -304,8 +304,8 @@ test('FailingTestsSummary (grouping)', 1, function() { '<div class="what">' + '<div class="problem">' + '<ul class="effects">' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=path%2Fto%2Ftest1.html%2Cpath%2Fto%2Ftest2.html%2Cpath%2Fto%2Ftest3.html%2Cpath%2Fto%2Ftest4.html">path/to (4 tests)</a></li>' + - '<li><a target="_blank" href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=path%2Fanother%2Ftest.html">path/another/test.html</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=path%2Fto%2Ftest1.html%2Cpath%2Fto%2Ftest2.html%2Cpath%2Fto%2Ftest3.html%2Cpath%2Fto%2Ftest4.html" target="_blank">path/to (4 tests)</a></li>' + + '<li><a href="http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=path%2Fanother%2Ftest.html" target="_blank">path/another/test.html</a></li>' + '</ul>' + '<ul class="actions">' + '<li><button class="action default" title="Examine these failures in detail.">Examine</button></li>' + @@ -318,7 +318,7 @@ test('FailingTestsSummary (grouping)', 1, function() { test('BuildersFailing', 1, function() { var builderFailing = new ui.notifications.BuildersFailing('Disasterifying'); - builderFailing.setFailingBuilders({'Webkit Linux': ['compile'], 'Webkit Vista': ['webkit_tests', 'update']); + builderFailing.setFailingBuilders({'Webkit Linux': ['compile'], 'Webkit Vista': ['webkit_tests', 'update']}); equal(builderFailing.innerHTML, '<div class="how">' + '<time class="relative"></time>' + diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/perf.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/perf.js index 242f21f68..ab7a26baf 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/perf.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/perf.js @@ -91,6 +91,8 @@ ui.perf.View = base.extends('div', { if (this._builderPicker) this._titleBar.removeChild(this._builderPicker); + if (!this._suitePicker.length) + return; var selectedSuite = this._suitePicker[this._suitePicker.selectedIndex].text; var builders = []; var urls = []; @@ -118,6 +120,9 @@ ui.perf.View = base.extends('div', { this.appendChild(graph); } + if (!this._builderPicker || !this._builderPicker.length) + return; + var url = this._builderPicker[this._builderPicker.selectedIndex].value; popOutLink.href = url; graph.src = url; diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js index b1f7e84e8..d624a2129 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js @@ -254,7 +254,7 @@ ui.results.TestSelector = base.extends('div', { var header = document.createElement('h3'); header.appendChild(nonLinkTitle); header.appendChild(linkTitle); - header.addEventListener('click', this._showResults.bind(this, header)); + header.addEventListener('click', this._showResults.bind(this, header, false)); topPanel.appendChild(header); }, this); @@ -290,7 +290,7 @@ ui.results.TestSelector = base.extends('div', { document.querySelector('.top-panel').style.maxHeight = percentage + '%'; }.bind(this)) }, - _showResults: function(header) + _showResults: function(header, scrollInfoView) { if (!header) return false; @@ -308,9 +308,11 @@ ui.results.TestSelector = base.extends('div', { bottomPanel.appendChild(this._delegate.contentForTest(testName)); var topPanel = this.querySelector('.top-panel'); - topPanel.scrollTop = header.offsetTop; - if (header.offsetTop - topPanel.scrollTop < header.offsetHeight) - topPanel.scrollTop = topPanel.scrollTop - header.offsetHeight; + if (scrollInfoView) { + topPanel.scrollTop = header.offsetTop; + if (header.offsetTop - topPanel.scrollTop < header.offsetHeight) + topPanel.scrollTop = topPanel.scrollTop - header.offsetHeight; + } var resultsDetails = this.querySelectorAll('.results-detail'); if (resultsDetails.length) @@ -337,18 +339,18 @@ ui.results.TestSelector = base.extends('div', { }, nextTest: function() { - return this._showResults(this.querySelector('.active').nextSibling); + return this._showResults(this.querySelector('.active').nextSibling, true); }, previousTest: function() { - var succeeded = this._showResults(this.querySelector('.active').previousSibling); + var succeeded = this._showResults(this.querySelector('.active').previousSibling, true); if (succeeded) this.querySelector('.builder-selector').lastResult(); return succeeded; }, firstResult: function() { - this._showResults(this.querySelector('h3')); + this._showResults(this.querySelector('h3'), true); }, currentTestName: function() { @@ -365,14 +367,14 @@ ui.results.BuilderSelector = base.extends('div', { var tabStrip = this.appendChild(document.createElement('ul')); Object.keys(resultsByBuilder).sort().forEach(function(builderName) { - var builderDirectory = results.directoryForBuilder(builderName); + var builderHash = base.underscoredBuilderName(builderName); var link = document.createElement('a'); - $(link).attr('href', "#" + builderDirectory).text(ui.displayNameForBuilder(builderName)); + $(link).attr('href', "#" + builderHash).text(ui.displayNameForBuilder(builderName)); tabStrip.appendChild(document.createElement('li')).appendChild(link); var content = this._delegate.contentForTestAndBuilder(testName, builderName); - content.id = builderDirectory; + content.id = builderHash; this.appendChild(content); }, this); diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui_unittests.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui_unittests.js index cd18e8888..2464045c6 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui_unittests.js +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui_unittests.js @@ -54,6 +54,7 @@ test("ui.onebar", 3, function() { onebar = new ui.onebar(); onebar.attach(); equal(onebar.innerHTML, + '<div><select id="platform-picker"><option>Apple</option><option>Chromium</option></select></div>' + '<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">' + '<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#unexpected">Unexpected Failures</a></li>' + '<li class="ui-state-default ui-corner-top"><a href="#expected">Expected Failures</a></li>' + diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css index 03c5c386b..fe818c6b3 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css @@ -48,6 +48,11 @@ a.failing-builder { padding: 0 2px; } + .effects a.failing-builder>span.architecture { + background-color: #555; + color: White; + } + a.failing-builder>span.graphics { padding: 0 2px; } diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css index 0028e1e8d..eede1896a 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css @@ -89,11 +89,12 @@ ol.notifications>li div.problem { } ol.notifications>li table.failures { - visibility: hidden; + opacity: 0.2; + -webkit-transition: opacity 0.5s; } ol.notifications>li:hover table.failures { - visibility: visible; + opacity: 1; } ol.notifications>li ul.causes>li>ul.actions { @@ -145,6 +146,16 @@ ol.notifications>li ul.causes>li>ul.actions { color: Gray; } + ol.notifications>li ul.causes>li>div.description>span>span.bugID::before { + content: 'bug '; + padding-left: 8px; + } + + ol.notifications>li ul.causes>li>div.description>span>span.bugID>a { + cursor: hand; + pointer-events: auto; + } + ol.notifications>li ul.causes>li>div.description>span>span.reviewer::before { content: ' ('; } diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css index e0ddce226..16aac11f4 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css @@ -41,6 +41,12 @@ border-radius: 0px; } +#onebar #platform-picker { + float: right; + margin: 8px; + font-size: larger; +} + #unexpected { min-height: 550px; } diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css index ae6d18d1c..28cfd09ce 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css @@ -95,6 +95,7 @@ max-height: 20%; overflow: auto; position: relative; + border: 1px solid #EEE; } .results-view .resize-handle { @@ -123,7 +124,8 @@ } .results-view h3 { - font-size: 16px; + font-size: 14px; + font-weight: normal; border-top: 1px solid #DDD; margin: 0; cursor: pointer; diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/default.css b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/default.css index 4223807a9..419807e55 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/default.css +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/default.css @@ -1,362 +1,368 @@ -div.header { display: none; } body > hr { display: none; } div.content h1 { display: none; } body.interface { - background: url(bg_gradient.jpg) repeat-x; - font-family: Verdana, Cursor; - font-size: 10px; - font-weight: bold; - background-color: #fff; - color: #333; + margin-top: 20px; + background: url(bg_gradient.jpg) repeat-x; + font-family: Verdana, Cursor; + font-size: 10px; + font-weight: bold; + background-color: #fff; + color: #333; +} + +.auth { + position: absolute; + top: 5px; + right: 40px; } a:link,a:visited,a:active { - color: #444; + color: #444; } table { - border-spacing: 1px 1px; + border-spacing: 1px 1px; } table td { - padding: 3px 2px 3px 2px; + padding: 3px 2px 3px 2px; } .Project { - min-width: 6em; + min-width: 6em; } .LastBuild,.Activity { - padding: 0 0 0 4px; + padding: 0 0 0 4px; } /* Chromium Specific styles */ div.BuildResultInfo { - color: #444; + color: #444; } div.Announcement { - margin-bottom: 1em; + margin-bottom: 1em; } div.Announcement>a:hover { - color: black; + color: black; } div.Announcement>div.Notice { - background-color: #afdaff; - padding: 0.5em; - font-size: 16px; - text-align: center; + background-color: #afdaff; + padding: 0.5em; + font-size: 16px; + text-align: center; } div.Announcement>div.Open { - border: 3px solid #8fdf5f; - padding: 0.5em; - font-size: 16px; - text-align: center; + border: 3px solid #8fdf5f; + padding: 0.5em; + font-size: 16px; + text-align: center; } div.Announcement>div.Closed { - border: 5px solid #e98080; - padding: 0.5em; - font-size: 24px; - font-weight: bold; - text-align: center; + border: 5px solid #e98080; + padding: 0.5em; + font-size: 24px; + font-weight: bold; + text-align: center; } td.Time { - color: #000; - border-bottom: 1px solid #aaa; - background-color: #eee; + color: #000; + border-bottom: 1px solid #aaa; + background-color: #eee; } td.Activity,td.Change,td.Builder { - color: #333333; - background-color: #CCCCCC; + color: #333333; + background-color: #CCCCCC; } td.Change { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; } td.Event { - color: #777; - background-color: #ddd; - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; + color: #777; + background-color: #ddd; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; } td.Activity { - border-top-left-radius: 10px; - -webkit-border-top-left-radius: 10px; - -moz-border-radius-topleft: 10px; - min-height: 20px; - padding: 2px 0 2px 0; + border-top-left-radius: 10px; + -webkit-border-top-left-radius: 10px; + -moz-border-radius-topleft: 10px; + min-height: 20px; + padding: 2px 0 2px 0; } td.idle,td.waiting,td.offline,td.building { - border-top-left-radius: 0px; - -webkit-border-top-left-radius: 0px; - -moz-border-radius-topleft: 0px; + border-top-left-radius: 0px; + -webkit-border-top-left-radius: 0px; + -moz-border-radius-topleft: 0px; } .LastBuild { - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; - border-top-right-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topleft: 5px; + border-top-right-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topright: 5px; } /* Console view styles */ td.DevRev { - padding: 4px 8px 4px 8px; - color: #333333; - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; - background-color: #eee; - width: 1%; + padding: 4px 8px 4px 8px; + color: #333333; + border-top-left-radius: 5px; + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topleft: 5px; + background-color: #eee; + width: 1%; } td.DevRevCollapse { - border-bottom-left-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; + border-bottom-left-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; } td.DevName { - padding: 4px 8px 4px 8px; - color: #333333; - background-color: #eee; - width: 1%; - text-align: left; + padding: 4px 8px 4px 8px; + color: #333333; + background-color: #eee; + width: 1%; + text-align: left; } td.DevStatus { - padding: 4px 4px 4px 4px; - color: #333333; - background-color: #eee; + padding: 4px 4px 4px 4px; + color: #333333; + background-color: #eee; } td.DevSlave { - padding: 4px 4px 4px 4px; - color: #333333; - background-color: #eee; + padding: 4px 4px 4px 4px; + color: #333333; + background-color: #eee; } td.first { - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; + border-top-left-radius: 5px; + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topleft: 5px; } td.last { - border-top-right-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topright: 5px; + border-top-right-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topright: 5px; } td.DevStatusCategory { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-width: 1px; - border-style: solid; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-width: 1px; + border-style: solid; } td.DevStatusCollapse { - border-bottom-right-radius: 5px; - -webkit-border-bottom-right-radius: 5px; - -moz-border-radius-bottomright: 5px; + border-bottom-right-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -moz-border-radius-bottomright: 5px; } td.DevDetails { - font-weight: normal; - padding: 8px 8px 8px 8px; - color: #333333; - background-color: #eee; - text-align: left; + font-weight: normal; + padding: 8px 8px 8px 8px; + color: #333333; + background-color: #eee; + text-align: left; } td.DevComment { - font-weight: normal; - padding: 8px 8px 8px 8px; - color: #333333; - border-bottom-right-radius: 5px; - -webkit-border-bottom-right-radius: 5px; - -moz-border-radius-bottomright: 5px; - border-bottom-left-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; - background-color: #eee; - text-align: left; + font-weight: normal; + padding: 8px 8px 8px 8px; + color: #333333; + border-bottom-right-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -moz-border-radius-bottomright: 5px; + border-bottom-left-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; + background-color: #eee; + text-align: left; } td.Alt { - background-color: #ddd; + background-color: #ddd; } .legend { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - width: 100px; - max-width: 100px; - text-align: center; - padding: 2px 2px 2px 2px; - height: 14px; - white-space: nowrap; + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + width: 100px; + max-width: 100px; + text-align: center; + padding: 2px 2px 2px 2px; + height: 14px; + white-space: nowrap; } .DevStatusBox { - text-align: center; - height: 20px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; + text-align: center; + height: 20px; + padding: 0 2px; + line-height: 0; + white-space: nowrap; } .DevStatusBox a { - opacity: 0.85; - border-width: 1px; - border-style: solid; - border-radius: 4px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - display: block; - width: 90%; - height: 20px; - line-height: 20px; - margin-left: auto; - margin-right: auto; + opacity: 0.85; + border-width: 1px; + border-style: solid; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + display: block; + width: 90%; + height: 20px; + line-height: 20px; + margin-left: auto; + margin-right: auto; } .DevSlaveBox { - text-align: center; - height: 10px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; + text-align: center; + height: 10px; + padding: 0 2px; + line-height: 0; + white-space: nowrap; } .DevSlaveBox a { - opacity: 0.85; - border-width: 1px; - border-style: solid; - border-radius: 4px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - display: block; - width: 90%; - height: 10px; - line-height: 20px; - margin-left: auto; - margin-right: auto; + opacity: 0.85; + border-width: 1px; + border-style: solid; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + display: block; + width: 90%; + height: 10px; + line-height: 20px; + margin-left: auto; + margin-right: auto; } a.noround { - border-radius: 0px; - -webkit-border-radius: 0px; - -moz-border-radius: 0px; - position: relative; - margin-top: -8px; - margin-bottom: -8px; - height: 36px; - border-top-width: 0; - border-bottom-width: 0; + border-radius: 0px; + -webkit-border-radius: 0px; + -moz-border-radius: 0px; + position: relative; + margin-top: -8px; + margin-bottom: -8px; + height: 36px; + border-top-width: 0; + border-bottom-width: 0; } a.begin { - border-top-width: 1px; - position: relative; - margin-top: 0px; - margin-bottom: -7px; - height: 27px; - border-top-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-right-radius: 4px; - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; + border-top-width: 1px; + position: relative; + margin-top: 0px; + margin-bottom: -7px; + height: 27px; + border-top-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-right-radius: 4px; + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; } a.end { - border-bottom-width: 1px; - position: relative; - margin-top: -7px; - margin-bottom: 0px; - height: 27px; - border-bottom-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; + border-bottom-width: 1px; + position: relative; + margin-top: -7px; + margin-bottom: 0px; + height: 27px; + border-bottom-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; } .center_align { - text-align: center; + text-align: center; } .right_align { - text-align: right; + text-align: right; } .left_align { - text-align: left; + text-align: left; } div.BuildWaterfall { - border-radius: 7px; - -webkit-border-radius: 7px; - -moz-border-radius: 7px; - position: absolute; - left: 0px; - top: 0px; - background-color: #FFFFFF; - padding: 4px 4px 4px 4px; - float: left; - display: none; - border-width: 1px; - border-style: solid; + border-radius: 7px; + -webkit-border-radius: 7px; + -moz-border-radius: 7px; + position: absolute; + left: 0px; + top: 0px; + background-color: #FFFFFF; + padding: 4px 4px 4px 4px; + float: left; + display: none; + border-width: 1px; + border-style: solid; } /* LastBuild, BuildStep states */ .success { - color: #FFFFFF; - background-color: #8FDF5F; - border-color: #4F8530; + color: #FFFFFF; + background-color: #8FDF5F; + border-color: #4F8530; } .failure { - color: #FFFFFF; - background-color: #E98080; - border-color: #A77272; + color: #FFFFFF; + background-color: #E98080; + border-color: #A77272; } .warnings { - color: #FFFFFF; - background-color: #FFC343; - border-color: #C29D46; + color: #FFFFFF; + background-color: #FFC343; + border-color: #C29D46; } .exception { - color: #FFFFFF; - background-color: #E0B0FF; - border-color: #ACA0B3; + color: #FFFFFF; + background-color: #E0B0FF; + border-color: #ACA0B3; } .start,.running,td.building { - color: #666666; - background-color: #FFFC6C; - border-color: #C5C56D; + color: #666666; + background-color: #FFFC6C; + border-color: #C5C56D; } .offline,td.offline { @@ -367,158 +373,158 @@ div.BuildWaterfall { .start { - border-bottom-left-radius: 10px; - -webkit-border-bottom-left-radius: 10px; - -moz-border-radius-bottomleft: 10px; - border-bottom-right-radius: 10px; - -webkit-border-bottom-right-radius: 10px; - -moz-border-radius-bottomright: 10px; + border-bottom-left-radius: 10px; + -webkit-border-bottom-left-radius: 10px; + -moz-border-radius-bottomleft: 10px; + border-bottom-right-radius: 10px; + -webkit-border-bottom-right-radius: 10px; + -moz-border-radius-bottomright: 10px; } .notstarted { - border-width: 1px; - border-style: solid; - border-color: #aaa; + border-width: 1px; + border-style: solid; + border-color: #aaa; background-color: #fff; } .closed { - background-color: #ff0000; + background-color: #ff0000; } .closed .large { - font-size: 1.5em; - font-weight: bolder; + font-size: 1.5em; + font-weight: bolder; } td.Project a:hover,td.start a:hover { - color: #000; + color: #000; } .mini-box { - text-align: center; - height: 20px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; + text-align: center; + height: 20px; + padding: 0 2px; + line-height: 0; + white-space: nowrap; } .mini-box a { - border-radius: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - display: block; - width: 100%; - height: 20px; - line-height: 20px; - margin-top: -30px; + border-radius: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + display: block; + width: 100%; + height: 20px; + line-height: 20px; + margin-top: -30px; } .mini-closed { - -box-sizing: border-box; - -webkit-box-sizing: border-box; - border: 4px solid red; + -box-sizing: border-box; + -webkit-box-sizing: border-box; + border: 4px solid red; } /* grid styles */ table.Grid { - border-collapse: collapse; + border-collapse: collapse; } table.Grid tr td { - padding: 0.2em; - margin: 0px; - text-align: center; + padding: 0.2em; + margin: 0px; + text-align: center; } table.Grid tr td.title { - font-size: 90%; - border-right: 1px gray solid; - border-bottom: 1px gray solid; + font-size: 90%; + border-right: 1px gray solid; + border-bottom: 1px gray solid; } table.Grid tr td.sourcestamp { - font-size: 90%; + font-size: 90%; } table.Grid tr td.builder { - text-align: right; - font-size: 90%; + text-align: right; + font-size: 90%; } table.Grid tr td.build { - border: 1px gray solid; + border: 1px gray solid; } /* column container */ div.column { - margin: 0 2em 2em 0; - float: left; + margin: 0 2em 2em 0; + float: left; } /* info tables */ table.info { - border-spacing: 1px; + border-spacing: 1px; } table.info td { - padding: 0.1em 1em 0.1em 1em; - text-align: center; + padding: 0.1em 1em 0.1em 1em; + text-align: center; } table.info th { - padding: 0.2em 1.5em 0.2em 1.5em; - text-align: center; + padding: 0.2em 1.5em 0.2em 1.5em; + text-align: center; } table.info td.left { - text-align: left + text-align: left } .alt { - background-color: #d6d6d6; + background-color: #d6d6d6; } li { - padding: 0.1em 1em 0.1em 1em; + padding: 0.1em 1em 0.1em 1em; } .result { - padding: 0.3em 1em 0.3em 1em; + padding: 0.3em 1em 0.3em 1em; } /* log view */ .log * { - vlink: #800080; - font-family: "Courier New", courier, monotype; + vlink: #800080; + font-family: "Courier New", courier, monotype; } span.stdout { - color: black; + color: black; } span.stderr { - color: red; + color: red; } span.header { - color: blue; + color: blue; } /* revision & email */ .revision .full { - display: none; + display: none; } .user .email { - display: none; + display: none; } /* change comments (use regular colors here) */ pre.comments>a:link,pre.comments>a:visited { - color: blue; + color: blue; } pre.comments>a:active { - color: purple; + color: purple; } diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/templates/builder.html b/Tools/BuildSlaveSupport/build.webkit.org-config/templates/builder.html index 2316e8b65..f8cf4b8c5 100644 --- a/Tools/BuildSlaveSupport/build.webkit.org-config/templates/builder.html +++ b/Tools/BuildSlaveSupport/build.webkit.org-config/templates/builder.html @@ -21,7 +21,7 @@ {{ b.current_step }} - {% if authz.advertiseAction('stopBuild') %} + {% if authz.advertiseAction('stopBuild', request) %} {{ forms.stop_build(b.stop_url, authz, on_all=False, short=True, label='Build') }} {% endif %} </li> @@ -37,7 +37,7 @@ {% for b in pending %} <li><small>({{ b.when }}, waiting {{ b.delay }})</small> - {% if authz.advertiseAction('cancelPendingBuild') %} + {% if authz.advertiseAction('cancelPendingBuild', request) %} {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=True, id=b.id) }} {% endif %} @@ -49,11 +49,16 @@ ({{ b.num_changes }} changes) {% endif %} + {% if 'owner' in b.properties %} + <b>Forced build</b> + by {{b.properties['owner'][0]}} + <small>{{b.properties['reason'][0]}}</small> + {% endif %} </li> {% endfor %} </ul> - {% if authz.advertiseAction('cancelPendingBuild') %} + {% if authz.advertiseAction('cancelPendingBuild', request) %} {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=False, id='all') }} {% endif %} @@ -97,14 +102,14 @@ {% endfor %} </table> -{% if authz.advertiseAction('pingBuilder') %} +{% if authz.advertiseAction('pingBuilder', request) %} <h2>Ping slaves</h2> {{ forms.ping_builder(builder_url+"/ping", authz) }} {% endif %} -{% if authz.advertiseAction('forceBuild') %} +{% if authz.advertiseAction('forceBuild', request) and force_schedulers != {} %} <h2>Force build</h2> - {{ forms.force_build(builder_url+"/force", authz, False) }} + {{ forms.force_build(builder_url+"/force", authz, request, False, force_schedulers=force_schedulers,default_props=default_props) }} {% endif %} </div> diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt index 689467061..ea7521841 100644 --- a/Tools/CMakeLists.txt +++ b/Tools/CMakeLists.txt @@ -3,6 +3,10 @@ IF ("${PORT}" STREQUAL "Efl") ADD_SUBDIRECTORY(DumpRenderTree/efl) ADD_SUBDIRECTORY(EWebLauncher) ENDIF () + + IF (ENABLE_WEBKIT2) + ADD_SUBDIRECTORY(MiniBrowser/efl) + ENDIF () ELSEIF ("${PORT}" STREQUAL "WinCE") ADD_SUBDIRECTORY(WinCELauncher) ENDIF() diff --git a/Tools/ChangeLog b/Tools/ChangeLog index 575ae45d9..76f1c34e0 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,3 +1,3492 @@ +2012-06-19 Ryuan Choi <ryuan.choi@samsung.com> + + [EFL][Regression] Build break after r120786 + https://bugs.webkit.org/show_bug.cgi?id=89549 + + Unreviewed build fix for Efl port. + + * DumpRenderTree/efl/CMakeLists.txt: Added disassembler in includes. + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + NRWT spins up and down the WebSocket server when running a single HTTP test from the command line + https://bugs.webkit.org/show_bug.cgi?id=64489 + + Reviewed by Tony Chang. + + This change changes NRWT so that we don't start the websocket + server if we aren't running websocket tests and don't start the + HTTP server if we aren't running http tests. + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (Manager._websocket_tests): + (Manager.start_servers_with_lock): + (Manager.stop_servers_with_lock): + * Scripts/webkitpy/layout_tests/controllers/manager_unittest.py: + (ManagerTest.test_servers_started): + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + test-webkitpy: add a -p flag to pass through captured output to enable debugging + https://bugs.webkit.org/show_bug.cgi?id=89158 + + Reviewed by Eric Seidel. + + Normally when outputcapture runs it intercepts stdout/stderr, + which makes running under the debugger difficult and mostly + pointless (since you can't see any output). This change adds a + flag to test-webkitpy (-p) that will cause outputcapture to pass + through the output as well as capture it. + + * Scripts/webkitpy/common/system/outputcapture.py: + (OutputCapture.stream_wrapper): + (OutputCapture._capture_output_with_name): + * Scripts/webkitpy/common/system/outputcapture_unittest.py: + (OutputCaptureTest.setUp): + * Scripts/webkitpy/test/main.py: + (Tester._parse_args): + (Tester._run_tests): + (Tester._log_exception): + (_CaptureAndPassThroughStream): + (_CaptureAndPassThroughStream.__init__): + (_CaptureAndPassThroughStream.write): + (_CaptureAndPassThroughStream._message_is_from_pdb): + (_CaptureAndPassThroughStream.flush): + (_CaptureAndPassThroughStream.getvalue): + +2012-06-19 Adam Barth <abarth@webkit.org> + + garden-o-matic fails to rebaseline tests with MISSING results + https://bugs.webkit.org/show_bug.cgi?id=89521 + + Reviewed by Kenneth Russell. + + If the bots report "MISSING", we should try to find PNG and TXT results on the server. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js: + +2012-06-19 Adam Barth <abarth@webkit.org> + + svn.delete_list fails to delete empty parent directories + https://bugs.webkit.org/show_bug.cgi?id=89520 + + Reviewed by Dirk Pranke. + + These functions were calling scm.delete and scm.add, which already + delete the parent directory. We'd get an exception when we tried to + delete the parent directory again. + + * Scripts/webkitpy/common/checkout/scm/svn.py: + (SVN._add_parent_directories): + (SVN._delete_parent_directories): + +2012-06-19 Thiago Marcos P. Santos <thiago.santos@intel.com> + + webkitpy: Simplify fetch_bugs_matching_search() + https://bugs.webkit.org/show_bug.cgi?id=89497 + + Reviewed by Adam Barth. + + Removed parameter with default value. It's not being used + and the handling of the parameter was wrong. Saves a check. + + * Scripts/webkitpy/common/net/bugzilla/bugzilla.py: + (BugzillaQueries.fetch_bugs_matching_search): + * Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py: + (MockBugzillaQueries.fetch_bugs_matching_search): + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + webkitpy: remove unneeded imports in layout_tests/port/chromium.py + https://bugs.webkit.org/show_bug.cgi?id=89522 + + Reviewed by Eric Seidel. + + They were no longer being used. No tests necessary. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2012-06-19 Adam Barth <abarth@webkit.org> + + Missing results aren't shown in garden-o-matic + + Reviewed by Kenneth Russell. + + Previously we didn't know to look for text and image results when the + bot told us that results were missing. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js: + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + Fix regression introduced in r120646 where the svn revision isn't saved in results.json + + Unreviewed, build fix. + + It turns out that we store the svn revision two different ways + in the JSON, and I only caught one of them :(. This should fix + the other. + + Also, this part of the code is poorly tested. I will investigate + adding at least a basic test for this in a separate fix. + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (summarize_results): + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + REGRESSION (NRWT): Results for new non-text-only tests are always put in the most-specific platform directory + https://bugs.webkit.org/show_bug.cgi?id=78127 + + Reviewed by Ryosuke Niwa. + + Add the --add-platform-exceptions flag from ORWT, and ensure + that --new-baseline is equivalent to --reset-results + --add-platform-exceptions. Also fix the default logic for where to + put PNGs and render tree dumps if --new-test-results is true: + if --add-platform-exceptions is False, baselines should go in + the least-specific platform directory (e.g., platform/mac) + rather than the most-specific (platform/mac-snowleopard). + + * Scripts/webkitpy/layout_tests/controllers/single_test_runner.py: + (SingleTestRunner): + (SingleTestRunner.run): + (SingleTestRunner._run_rebaseline): + (SingleTestRunner._add_missing_baselines): + (SingleTestRunner._location_for_new_baseline): + (SingleTestRunner._overwrite_baselines): + (SingleTestRunner._save_baseline_data): + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.baseline_path): + (Port): + (Port.baseline_platform_dir): + (Port.baseline_version_dir): + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + (_set_up_derived_options): + (parse_args): + * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py: + (RebaselineTest.assertBaselines): + (RebaselineTest.test_reset_results): + (RebaselineTest.test_missing_results): + (RebaselineTest.test_new_baseline): + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + NRWT should not take memory used as disk cache into account when deciding how many processes to launch + https://bugs.webkit.org/show_bug.cgi?id=81379 + + Reviewed by Eric Seidel. + + The 'free memory' calculation we were running on the mac seemed + to underestimate how many children we can run in parallel, and + it was complex. This patch replaces that calculation with a + simpler one that reserves 2GB for overhead and assumes 256MB per + DRT/WTR, so if we had 4GB of RAM we can run up to 8 DRTs. + + Also, there was a bug where we were truncating the memory + installed on the machine to 4GB by casting to an int instead of + a long; this was probably the source of some of the earlier + problems when using total memory. + + This patch also removes the no-longer-needed restrictions on the + number of workers on beefy Lion boxes for both Apple Mac and Chromium + Mac; we should now use all of the cores by default. + + The memory calculations have only been implemented on the mac; + having the calculation in base.default_child_processes() was IMO + misleading, and so this patch also moves the computation into + the MacPort. I have not heard of the # of workers being an issue + on any other ports, so this should be fine. + + * Scripts/webkitpy/common/system/platforminfo.py: + (PlatformInfo.total_bytes_memory): + * Scripts/webkitpy/common/system/platforminfo_mock.py: + (PlatformInfo.total_bytes_memory): + (PlatformInfo.total_bytes_memory): + (PlatformInfo._win_version_tuple_from_cmd): + * Scripts/webkitpy/common/system/platforminfo_unittest.py: + (TestPlatformInfo.test_total_bytes_memory): + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.default_child_processes): + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + (PortTest.test_default_child_processes): + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + (ChromiumMacPort.operating_system): + * Scripts/webkitpy/layout_tests/port/mac.py: + (MacPort.default_child_processes): + * Scripts/webkitpy/layout_tests/port/mac_unittest.py: + (TestMacPort.test_default_child_processes): + +2012-06-19 Dirk Pranke <dpranke@chromium.org> + + new-run-webkit-tests reports unexpected pass of pixel tests when pixel testing is disabled + https://bugs.webkit.org/show_bug.cgi?id=85446 + + Reviewed by Simon Fraser. + + Embed whether pixel testing was enabled into the results.json. + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (summarize_results): + +2012-06-19 Zoltan Horvath <zoltan@webkit.org> + + [Qt] Modify HTTPS port to 8443 for performance tests + https://bugs.webkit.org/show_bug.cgi?id=89442 + + Reviewed by Ryosuke Niwa. + + We should be consistent with the default HTTPS port and with the changelog of r119188. + + * Scripts/webkitpy/performance_tests/perftest.py: + (ReplayServer.__init__): + +2012-06-19 Mike West <mkwst@chromium.org> + + Introduce ENABLE_CSP_NEXT configuration flag. + https://bugs.webkit.org/show_bug.cgi?id=89300 + + Reviewed by Adam Barth. + + The 1.0 draft of the Content Security Policy spec is just about to + move to Last Call. We'll hide work on the upcoming 1.1 spec behind + this ENABLE flag, disabled by default. + + Spec: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html + + * Scripts/webkitperl/FeatureList.pm: + * qmake/mkspecs/features/features.pri: + +2012-06-19 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] EFL's LayoutTestController does not support setTextDirection + https://bugs.webkit.org/show_bug.cgi?id=87481 + + Reviewed by Hajime Morita. + + Implement setTextDirection in EFL's LayoutTestController and + properly reset its value between test cases to avoid flakiness. + + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::resetDefaultsToConsistentValues): + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::setTextDirection): + +2012-06-19 Kristóf Kosztyó <kkristof@inf.u-szeged.hu> + + [Qt] Temporarily disable xvfb driver in nrwt + https://bugs.webkit.org/show_bug.cgi?id=88414 + + Reviewed by Csaba Osztrogonác. + + * Scripts/webkitpy/layout_tests/port/qt.py: + (QtPort._build_driver): + +2012-06-18 Joone Hur <joone.hur@intel.com> + + [EFL] Fontconfig can't be linked properly + https://bugs.webkit.org/show_bug.cgi?id=89418 + + Unreviewed build fix. + + Make Fontconfig be linked correctly. + + * MiniBrowser/efl/CMakeLists.txt: add FONTCONFIG_LIBRARIES to MiniBrowser_LIBRARIES. + +2012-06-18 Joone Hur <joone.hur@intel.com> + + Unreviewed. Updating email for committers.py script. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-18 Simon Fraser <simon.fraser@apple.com> + + Fix a typo that caused TestFailures to have a syntax error. + + Sadly TestFailures is broken for another reason now too: + https://bugs.webkit.org/show_bug.cgi?id=89419 + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js: + (ViewController.prototype._domForBuildName): + +2012-06-18 Simon Fraser <simon.fraser@apple.com> + + Provide bug links for suspicious commits + https://bugs.webkit.org/show_bug.cgi?id=89408 + + Reviewed by Adam Barth. + + Add links to bugs for the suspicious commits if we have bug data. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/Bugzilla.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css: + (ol.notifications>li ul.causes>li>div.description>span>span.bugID::before): + (ol.notifications>li ul.causes>li>div.description>span>span.bugID>a): + +2012-06-18 Amy Ousterhout <aousterh@chromium.org> + + [Chromium] DeviceOrientation Cleanup + https://bugs.webkit.org/show_bug.cgi?id=89354 + + Reviewed by Kent Tamura. + + * DumpRenderTree/chromium/WebViewHost.h: added OVERRIDE specifier for virtual function + (WebViewHost): + +2012-06-18 James Robinson <jamesr@chromium.org> + + [chromium] Stop passing deprecated 'direct' parameter to webkit_support::CreateGraphicsContext3D + https://bugs.webkit.org/show_bug.cgi?id=89254 + + Reviewed by Adrienne Walker. + + This parameter doesn't mean anything since this codepath is only used for onscreen contexts and is deprecated + upstream. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::createGraphicsContext3D): + +2012-06-18 Simon Fraser <simon.fraser@apple.com> + + Minor fix suggested by Adam Barth. + + Use $(this._what).empty(); rather than removing children one at a time. + For some reason removeAllChildren() is undefined on this node. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js: + +2012-06-18 Simon Fraser <simon.fraser@apple.com> + + Show TOT revision in garden-o-matic, and make the revisions into links + https://bugs.webkit.org/show_bug.cgi?id=89396 + + Reviewed by Adam Barth. + + The "latest revision" notification now reads "Latest revision processed by every bot: NN (trunk is at NN)" + where the revisions are links to trac. + + To avoid setting innerHTML, I made base.createLinkNode() and used it in a bunch of places, which had + the knock-on effect of flipping the target and href attributes for anchors in some test output. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ViewController.js: + (ViewController.prototype._displayTesters.updateList.list): + (ViewController.prototype._displayTesters.updateList): + (ViewController.prototype._domForRegressionRange.trac.commitDataForRevisionRange): + (ViewController.prototype._domForRegressionRange): + (ViewController.prototype._domForAuxiliaryUIElements): + (ViewController.prototype._domForBuildName): + (ViewController.prototype): + (ViewController.prototype.): + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/garden-o-matic.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js: + +2012-06-18 Csaba Osztrogonác <ossy@webkit.org> + + REGRESSION(r100558): NRWT should work without SVN or GIT + https://bugs.webkit.org/show_bug.cgi?id=76630 + + Reviewed by Dirk Pranke. + + NRWT is not supposed to have a requirement that we have an + actual SVN or Git checkout, and we were unnecessarily + initializing the checkout. This patch removes that line :). + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + (main): + +2012-06-18 Zan Dobersek <zandobersek@gmail.com> + + [garden-o-matic] Add support for the GTK builders + https://bugs.webkit.org/show_bug.cgi?id=89360 + + Reviewed by Adam Barth. + + Add the 'gtk' platform, essentially a copy of the 'apple' platform since + both get their data from build.webkit.org. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js: + (.): + +2012-06-18 Nico Weber <thakis@chromium.org> + + [chromium/mac] Unbreak smooth scrolling. + https://bugs.webkit.org/show_bug.cgi?id=89327 + + Reviewed by Dimitri Glazkov. + + Broken by Sam in r115589 / r115591. + + * DumpRenderTree/mac/DumpRenderTree.mm: + (resetDefaultsToConsistentValues): + * TestWebKitAPI/mac/InjectedBundleControllerMac.mm: + (TestWebKitAPI::InjectedBundleController::platformInitialize): + * WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm: + (WTR::InjectedBundle::platformInitialize): + +2012-06-18 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120541, r120547, and r120548. + http://trac.webkit.org/changeset/120541 + http://trac.webkit.org/changeset/120547 + http://trac.webkit.org/changeset/120548 + https://bugs.webkit.org/show_bug.cgi?id=89383 + + This approach doesn't work for WebKit2 (Requested by abarth on + #webkit). + + * DumpRenderTree/LayoutTestController.cpp: + (setBackingScaleFactorCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp: + (LayoutTestController::setBackingScaleFactor): + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::setBackingScaleFactor): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setBackingScaleFactor): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setBackingScaleFactor): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::setBackingScaleFactor): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::setBackingScaleFactor): + * WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl: + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::didReceiveMessage): + (WTR::InjectedBundle::postSetBackingScaleFactor): + (WTR): + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + (InjectedBundle): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR::LayoutTestController::setBackingScaleFactor): + (WTR): + (WTR::LayoutTestController::callSetBackingScaleFactorCallback): + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + (LayoutTestController): + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + +2012-06-18 Zan Dobersek <zandobersek@gmail.com> + + REGRESSION(r120546): It made 3 webkitpy tests fail + https://bugs.webkit.org/show_bug.cgi?id=89332 + + Reviewed by Adam Barth. + + Update the BaselineOptimizer unittest after r120546. + + * Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py: + (BaselineOptimizerTest.test_no_add_mac_future): + (BaselineOptimizerTest.test_mac_future): + (BaselineOptimizerTest.test_complex_shadowing): + +2012-06-18 Dirk Pranke <dpranke@chromium.org> + + new-run-webkit-tests output gets confused when logging + https://bugs.webkit.org/show_bug.cgi?id=63793 + + Reviewed by Adam Barth. + + Ship all of the log messages generated in the worker back + to the manager; this allows the messages to be properly + serialized to stderr and for the meter to flush its output correctly. + + Note however that this will likely result in messages to be + logged out of order between workers; I'm not sure that there's + an easy way to fix this short of buffering a potentially + unbounded amount of data. It might be better to just log through + stderr unless we're in 'metering' mode, but it's also worth + noting that we already get messages out of order through stderr + on Windows. + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (Manager.handle_done): + (Manager.handle_finished_test): + (Manager._log_messages): + * Scripts/webkitpy/layout_tests/controllers/worker.py: + (Worker.__init__): + (Worker._set_up_logging): + (Worker.run): + (Worker._run_test): + (Worker.cleanup): + (Worker.run_single_test): + (_WorkerLogHandler): + (_WorkerLogHandler.__init__): + (_WorkerLogHandler.emit): + * Scripts/webkitpy/layout_tests/views/metered_stream.py: + (MeteredStream.write): + (MeteredStream.writeln): + * Scripts/webkitpy/layout_tests/views/printing.py: + (Printer.writeln): + +2012-06-18 Zan Dobersek <zandobersek@gmail.com> + + [garden-o-matic] Builder names without underscores cause incorrect BuildSelector behavior + https://bugs.webkit.org/show_bug.cgi?id=89362 + + Reviewed by Simon Fraser. + + Replace white spaces, braces and dots in the builder name with underscores. This + way the JQuery tabs will be properly matched with the according container. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js: + +2012-06-18 Dirk Pranke <dpranke@chromium.org> + + nrwt: metered output doesn't handle ^C cleanly + https://bugs.webkit.org/show_bug.cgi?id=89249 + + Reviewed by Tony Chang. + + If you ctrl-c a running nrwt (w/o --verbose), then all but + two characters of the last update are erased, and then we print + "interrupted, exiting" as an update, which itself then gets + erased. Fix this so that we flush the meter (making the last + update persistent, so that we print the ^C for a visual clue), + print the interrupt message, and move on ... + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (Manager._run_tests): + * Scripts/webkitpy/layout_tests/views/metered_stream.py: + (MeteredStream.flush): + * Scripts/webkitpy/layout_tests/views/printing.py: + (Printer._write): + (Printer): + (Printer.flush): + +2012-06-18 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium] Change back "linuxish" to "linux" and include WebFontRendering.cpp on Android + https://bugs.webkit.org/show_bug.cgi?id=89228 + + Reviewed by Tony Chang. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + * DumpRenderTree/chromium/TestShellAndroid.cpp: + +2012-06-18 Mario Sanchez Prada <msanchez@igalia.com> + + [GTK] Get rid of DumpRenderTreeSupportGtk::{in|de}crementAccessibilityValue + https://bugs.webkit.org/show_bug.cgi?id=89226 + + Reviewed by Martin Robinson. + + Implement increment() and decrement() functions in term of the AtkValue interface, + instead of using DumpRenderTreeSupportGtk helper class. + + * DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp: + (AccessibilityUIElement::intValue): + (AccessibilityUIElement::minValue): + (AccessibilityUIElement::maxValue): + (alterCurrentValue): + (AccessibilityUIElement::increment): + (AccessibilityUIElement::decrement): + +2012-06-17 Simon Fraser <simon.fraser@apple.com> + + garden-o-matic 'Results' panel is broken for the Apple platform + https://bugs.webkit.org/show_bug.cgi?id=89310 + + Reviewed by Adam Barth. + + For platforms that don't use accumulated build directories on the server, + carry along buildLocation data with buildInfo, so that we know where to + look for the test results files for a given test. + + Renamed historicalResultsSummaryURLs to historicalResultsLocations because + it now returns an array of objects with buildNumber, revision and url info. + + Fixed results.fetchResultsURLs() to use this data to find results. + + Fixed the results display to not scroll when you click on a test to see the results. + Made the h3s look less ugly + + Don't try to show the flakiness dashboard for the Apple platform. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/checkout.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css: + (.results-view .top-panel): + (.results-view h3): + +2012-06-16 Simon Fraser <simon.fraser@apple.com> + + Make garden-o-matic work for the Apple Mac port + https://bugs.webkit.org/show_bug.cgi?id=84642 + + Reviewed by Adam Barth. + + Make garden-o-matic work for the Apple, webkit.org-hosted builders and testers. This involved + educating the scripts in various ways: + * Wrap up platform-related differences in config.kPlatforms[] + * Add a <select> to switch between platforms, and support a url parameter, ?platform=chromium/apple + * The webkit.org bots don't accumulate test results into a single directory like the chromium.org ones do, + so add config.haveBuilderAccumulatedResults and logic in fetchResultsByBuilder() to find the most + recent build with valid results. + * The webkit.org bots often generate results directories with no layout test data (e.g. when testers + try to test a build that has already been deleted). Make walkHistory() more robust here. + * webkit.org uses differently named test result directories, that include the SVN revision as + well as the build number. That forces us to fetch more build info before we can get the + result directory URL. + * chromium.org serves raw directory listings for a builder's results directories. webkit.org serves + those with Twisted, so rather than scrape directory listings, we use buildbot JSON to find results + dirs. + * Various URLs differ between webkit.org and chromium.org + * Better UI for the failures info, so that some info is visible even when not hovered. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/garden-o-matic.html: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/LayoutTestResultsLoader.js: + (LayoutTestResultsLoader.prototype.set _fetchAndParseNRWTResults): + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/config.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/model.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/net.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results_unittests.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/summary-mock.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/failures.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/notifications_unittests.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/perf.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui_unittests.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/notifications.css: + (ol.notifications>li table.failures): + (ol.notifications>li:hover table.failures): + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/onebar.css: + (#onebar #platform-picker): + * Scripts/webkitpy/layout_tests/port/builders.py: + +2012-06-16 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120536. + http://trac.webkit.org/changeset/120536 + https://bugs.webkit.org/show_bug.cgi?id=89296 + + Does not compile on chromium-linux (Requested by abarth on + #webkit). + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + * DumpRenderTree/chromium/TestShellAndroid.cpp: + +2012-06-16 Adam Barth <abarth@webkit.org> + + layoutTestController.setBackingScaleFactor is redundant with (and less awesome than) internals.settings.setDeviceScaleFactor + https://bugs.webkit.org/show_bug.cgi?id=89274 + + Reviewed by Levi Weintraub. + + Delete (mostly stub) implementations of layoutTestController.setBackingScaleFactor. + Note: The WebKit2 API that setBackingScaleFactor exercises is still + tested by API-level tests. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp: + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + * WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl: + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::didReceiveMessage): + (WTR): + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + (InjectedBundle): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR): + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + (LayoutTestController): + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + +2012-06-16 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium] Move chromium/public/linuxish/WebFontRendering.h out of linuxish directory + https://bugs.webkit.org/show_bug.cgi?id=89228 + + Reviewed by Tony Chang. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + * DumpRenderTree/chromium/TestShellAndroid.cpp: + +2012-06-15 Adam Barth <abarth@webkit.org> + + garden-o-matic's results.js should use RequestTracker + https://bugs.webkit.org/show_bug.cgi?id=89257 + + Reviewed by Dimitri Glazkov. + + We wrote results.js before we recognized the RequestTracker pattern. + This patch replaces the manual implementations of RequestTracker with + the real deal. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js: + +2012-06-15 Darin Adler <darin@apple.com> + + * Scripts/webkitpy/bindings: Added property svn:ignore. + +2012-06-15 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120511. + http://trac.webkit.org/changeset/120511 + https://bugs.webkit.org/show_bug.cgi?id=89255 + + Breaks at least Android builder (Requested by wangxianzhu on + #webkit). + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + +2012-06-15 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium] Move chromium/public/linuxish/WebFontRendering.h out of linuxish directory + https://bugs.webkit.org/show_bug.cgi?id=89228 + + Reviewed by Tony Chang. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + +2012-06-15 Dirk Pranke <dpranke@chromium.org> + + webkitpy: remove DummyOptions and clean up the code in Port.get_option() and Port.set_option_default() + https://bugs.webkit.org/show_bug.cgi?id=89135 + + Re-land change in r120370 with fix in + PortFactory.get_from_builder_name() that changes BuilderOptions + to an actual optparse.Values object. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.__init__): + (Port.get_option): + (Port.set_option_default): + * Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py: + (ChromiumWinTest.test_setup_environ_for_server_register_cygwin): + * Scripts/webkitpy/layout_tests/port/factory.py: + (_builder_options): + (PortFactory.get_from_builder_name): + * Scripts/webkitpy/layout_tests/port/factory_unittest.py: + (FactoryTest.test_get_from_builder_name): + * Scripts/webkitpy/style/checkers/test_expectations.py: + (TestExpectationsChecker._determine_port_from_expectations_path): + * Scripts/webkitpy/tool/mocktool.py: + (MockOptions.ensure_value): + +2012-06-15 Bill Budge <bbudge@chromium.org> + + Add bbudge@chromium.org to committers.py + + Unreviewed. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-15 Csaba Osztrogonác <ossy@webkit.org> + + Unreviewed style fix after r120351. + + * BuildSlaveSupport/build.webkit.org-config/public_html/default.css: + (body.interface): + +2012-06-15 Csaba Osztrogonác <ossy@webkit.org> + + master.cfg cleanup, remove unnecessary workaround + https://bugs.webkit.org/show_bug.cgi?id=88994 + + Reviewed by Lucas Forschler. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (loadBuilderConfig): + +2012-06-15 Dirk Pranke <dpranke@chromium.org> + + webkit-patch rebaseline-expectations should only rebaseline the appropriate suffixes for the failure in question + https://bugs.webkit.org/show_bug.cgi?id=88581 + + Reviewed by Adam Barth. + + Make sure we only optimize the suffixes we rebaselined during + rebaseline-expectations, and not all suffixes for a test. + While optimizing is somewhere between harmless and good, it's also confusing :) + + * Scripts/webkitpy/tool/commands/rebaseline.py: + (RebaselineExpectations._rebaseline_port): + (RebaselineExpectations.execute): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + +2012-06-15 Csaba Osztrogonác <ossy@webkit.org> + + Update builder.html template for newer buildmaster + https://bugs.webkit.org/show_bug.cgi?id=89207 + + Rebasing builder.html template from v0.8.3 to v0.8.6p1. + + Reviewed by Zoltan Herczeg. + + * BuildSlaveSupport/build.webkit.org-config/templates/builder.html: + +2012-06-15 Csaba Osztrogonác <ossy@webkit.org> + + Add ForceScheduler to build.webkit.org + https://bugs.webkit.org/show_bug.cgi?id=88982 + + Reviewed by Ryosuke Niwa. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (loadBuilderConfig): + +2012-06-15 Christophe Dumez <christophe.dumez@intel.com> + + [EFL][WK2] Add title support to Ewk_View + https://bugs.webkit.org/show_bug.cgi?id=89095 + + Reviewed by Kenneth Rohde Christiansen. + + Update the MiniBrowser so it listens for the "title,change" + signal on the view and keeps the browser window title + up-to-date. + + * MiniBrowser/efl/main.c: + (on_title_changed): + (browserCreate): + +2012-06-15 Christophe Dumez <christophe.dumez@intel.com> + + [WK2][EFL] Implement navigation back/forward in Ewk_View + https://bugs.webkit.org/show_bug.cgi?id=89173 + + Reviewed by Kenneth Rohde Christiansen. + + Implement navigation back / forward in MiniBrowser. Use + 'F1' to navigate back and 'F2' to navigate forward. + + * MiniBrowser/efl/main.c: + (on_key_down): + +2012-06-15 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] EFL's LayoutTestController does not support titleTextDirection + https://bugs.webkit.org/show_bug.cgi?id=86475 + + Reviewed by Hajime Morita. + + Add titleTextDirection getter and setter to LayoutTestController and + expose its value to JavaScript. + Update the titleTextDirection value from EFL's "title,changed" + callback in DumpRenderTree. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (getTitleTextDirectionCallback): + (LayoutTestController::staticValues): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController::titleTextDirection): + (LayoutTestController::setTitleTextDirection): + (LayoutTestController): + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::onFrameTitleChanged): + +2012-06-15 Christophe Dumez <christophe.dumez@intel.com> + + [EFL][WK2] Implement reload / stop in Ewk_View + https://bugs.webkit.org/show_bug.cgi?id=89168 + + Reviewed by Kenneth Rohde Christiansen. + + Implement view reload / stop loading in MiniBrowser. + Use 'F5' for reload and 'F6' for stopping the load. + + * MiniBrowser/efl/main.c: + (on_key_down): + (browserCreate): + +2012-06-15 Hironori Bono <hbono@chromium.org> + + Allow platforms to choose whether to remove markers on editing + https://bugs.webkit.org/show_bug.cgi?id=88838 + + Reviewed by Hajime Morita. + + This change implements WebViewHost::checkTextOfParagraph so DumpRenderTree can + run grammar tests. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::checkTextOfParagraph): Implement this function with our mock spell checker and grammar checker. + * DumpRenderTree/chromium/WebViewHost.h: + (WebViewHost): Override WebSpellCheckClient::checkTextOfParagraph. + +2012-06-15 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120370. + http://trac.webkit.org/changeset/120370 + https://bugs.webkit.org/show_bug.cgi?id=89183 + + Broke webkit-patch rebaseline (Requested by zdobersek on + #webkit). + + * Scripts/webkitpy/layout_tests/port/base.py: + (DummyOptions): + (DummyOptions.__init__): + (DummyOptions.__init__.this): + (Port.__init__): + (Port.get_option): + (Port.set_option_default): + * Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py: + (ChromiumWinTest.RegisterCygwinOption): + (ChromiumWinTest.RegisterCygwinOption.__init__): + (ChromiumWinTest.test_setup_environ_for_server_register_cygwin): + * Scripts/webkitpy/style/checkers/test_expectations.py: + (TestExpectationsChecker._determine_port_from_expectations_path): + * Scripts/webkitpy/tool/mocktool.py: + (MockOptions.update): + +2012-06-14 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium-Android] Initialize font rendering in DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=89133 + + Reviewed by Adam Barth. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + * DumpRenderTree/chromium/TestShellAndroid.cpp: + (platformInit): + +2012-06-14 Dongwoo Im <dw.im@samsung.com> + + [EFL] [DRT] Reset the WebAudio setting on DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=88622 + + Reviewed by Philippe Normand. + + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: Reset the setting of the Web Audio feature as default. + (DumpRenderTreeChrome::resetDefaultsToConsistentValues): + +2012-06-14 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium-Android] Should retry a few times when failed to start DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=89124 + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/layout_tests/port/chromium_android.py: + (ChromiumAndroidDriver._start): + (ChromiumAndroidDriver): + (ChromiumAndroidDriver._start_once): + +2012-06-14 Tony Gentilcore <tonyg@chromium.org> + + Update webpagereplay to 1.1.2 + https://bugs.webkit.org/show_bug.cgi?id=89118 + + This includes the following patch which avoids pkg_resources import errors: + http://code.google.com/p/web-page-replay/source/detail?r=476 + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/thirdparty/__init__.py: + (AutoinstallImportHook._install_webpagereplay): + +2012-06-14 Ryosuke Niwa <rniwa@webkit.org> + + Get rid of FAIL test expectation + https://bugs.webkit.org/show_bug.cgi?id=89137 + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/layout_tests/controllers/manager_unittest.py: + (ResultSummaryTest.test_summarized_results_wontfix): + * Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py: + * Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py: + (JSONLayoutResultsGenerator): + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (result_was_expected): + (suffixes_for_expectations): + (TestExpectationsModel._add_test): + (TestExpectations): + (TestExpectations.get_rebaselining_failures): + (TestExpectations.remove_configuration_from_test): + * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: + (FunctionsTest.test_result_was_expected): + (FunctionsTest.test_suffixes_for_expectations): + (TestExpectationSerializerTests.test_parsed_expectations_string): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (test_test_expectations): + * Scripts/webkitpy/style/checkers/test_expectations_unittest.py: + (TestExpectationsTestCase.test_valid_expectations): + +2012-06-14 Dirk Pranke <dpranke@chromium.org> + + webkitpy: remove DummyOptions and clean up the code in Port.get_option() and Port.set_option_default() + https://bugs.webkit.org/show_bug.cgi?id=89135 + + Reviewed by Ryosuke Niwa. + + This patch is just some minor cleanup and simplification. There + should be no functional changes here. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.__init__): + (Port.get_option): + (Port.set_option_default): + * Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py: + (ChromiumWinTest.test_setup_environ_for_server_register_cygwin): + * Scripts/webkitpy/style/checkers/test_expectations.py: + (TestExpectationsChecker._determine_port_from_expectations_path): + * Scripts/webkitpy/tool/mocktool.py: + (MockOptions.ensure_value): + +2012-06-14 Ian Vollick <vollick@chromium.org> + + [chromium] Certain settings in CCSettings could be global + https://bugs.webkit.org/show_bug.cgi?id=88384 + + Reviewed by James Robinson. + + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::TestShell): + (TestShell::resetWebSettings): + (TestShell::setPerTilePaintingEnabled): + * DumpRenderTree/chromium/TestShell.h: + (TestShell): + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::reset): + (WebPreferences::applyTo): + * DumpRenderTree/chromium/WebPreferences.h: + (WebPreferences): + +2012-06-14 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120352. + http://trac.webkit.org/changeset/120352 + https://bugs.webkit.org/show_bug.cgi?id=89120 + + It seems something is still wrong with it :/ (Requested by + Ossy on #webkit). + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (Factory.__init__): + (BuildFactory.__init__): + (TestFactory.__init__): + (BuildAndTestFactory.__init__): + (BuildAndPerfTestFactory.__init__): + (BuildAndPerfTestWebKit2Factory.__init__): + (DownloadAndPerfTestFactory.__init__): + (DownloadAndPerfTestWebKit2Factory.__init__): + +2012-06-14 Jia Pu <jpu@apple.com> + + Mark text with text alternative with blue underline. + https://bugs.webkit.org/show_bug.cgi?id=83047 + + Reviewed by NOBODY Enrica Casucci. + + * DumpRenderTree/mac/TextInputController.m: + (+[TextInputController isSelectorExcludedFromWebScript:]): + (+[TextInputController webScriptNameForSelector:]): + (-[TextInputController dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:]): + +2012-06-14 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120353. + http://trac.webkit.org/changeset/120353 + https://bugs.webkit.org/show_bug.cgi?id=89119 + + It seems we still need this workaround (Requested by Ossy on + #webkit). + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (loadBuilderConfig): + +2012-06-14 Csaba Osztrogonác <ossy@webkit.org> + + master.cfg cleanup, remove unnecessary workaround + https://bugs.webkit.org/show_bug.cgi?id=88994 + + Reviewed by Lucas Forschler. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (loadBuilderConfig): + +2012-06-14 Csaba Osztrogonác <ossy@webkit.org> + + master.cfg cleanup, pass BuildStep instances instead of BuildStep subclasses + https://bugs.webkit.org/show_bug.cgi?id=89001 + + Reviewed by Lucas Forschler. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (Factory.__init__): + (BuildFactory.__init__): + (TestFactory.__init__): + (BuildAndTestFactory.__init__): + (BuildAndPerfTestFactory.__init__): + (BuildAndPerfTestWebKit2Factory.__init__): + (DownloadAndPerfTestFactory.__init__): + (DownloadAndPerfTestWebKit2Factory.__init__): + +2012-06-14 Csaba Osztrogonác <ossy@webkit.org> + + Unhide login form on the build.webkit.org + https://bugs.webkit.org/show_bug.cgi?id=88981 + + Reviewed by Lucas Forschler. + + * BuildSlaveSupport/build.webkit.org-config/public_html/default.css: + +2012-06-14 Zan Dobersek <zandobersek@gmail.com> + + [Gtk] Add support in DumpRenderTree for tracking repaints + https://bugs.webkit.org/show_bug.cgi?id=87658 + + Reviewed by Martin Robinson. + + Reimplement the displayWebView method in DumpRenderTree - force a + repaint before starting tracking repaints and resetting them. + + When gathering pixel output from a web view, if tracking repaints, + paint an overlay over the output with the overlay being clear in the + areas where the repaints occurred. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (displayWebView): + (resetDefaultsToConsistentValues): + * DumpRenderTree/gtk/PixelDumpSupportGtk.cpp: + (paintOverlay): + (fillRepaintOverlayIntoContext): + (createBitmapContextFromWebView): + +2012-06-14 Dirk Pranke <dpranke@chromium.org> + + new-run-webkit-tests doesn't find similar platform tests for a keyword + https://bugs.webkit.org/show_bug.cgi?id=37956 + + Reviewed by Ryosuke Niwa. + + This patches adds support for NRWT so that if you type + "new-run-webkit-tests foo" it will run all the tests in foo as + well as platform/foo for all of the platforms that are normally + searched (this only applies to directories, not to individual tests). + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (Manager.collect_tests): + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.tests): + (Port): + (Port._expanded_paths): + * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py: + (MainTest.test_no_http_tests): + (MainTest): + (MainTest.test_platform_tests_are_found): + +2012-06-14 Dirk Pranke <dpranke@chromium.org> + + NRWT should honor --skipped=[default|ignore|only], like ORWT does + https://bugs.webkit.org/show_bug.cgi?id=66308 + + Reviewed by Ryosuke Niwa. + + This patch adds support for ORWT's --skipped=(default|ignore|only) + flag and cleans up the interaction between that and --ignore. + + Individual tests (but not directories) explicitly listed on the + command line will always be run regardless of what is passed + for --skipped and --ignore. + + This patch also changes the "found" and "running" log messages + since it wasn't clear how the skipped tests were included in those numbers. + + * Scripts/webkitpy/layout_tests/controllers/manager.py: + (Manager.__init__): + (Manager.collect_tests): + (Manager.prepare_lists_and_print_output): + * Scripts/webkitpy/layout_tests/port/test.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + (_set_up_derived_options): + (parse_args): + * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py: + (MainTest.test_ignore_flag): + (MainTest): + (MainTest.test_skipped_flag): + +2012-06-14 Takashi Toyoshima <toyoshim@chromium.org> + + new-run-webkit-websocketserver must handle TLS related arguments + https://bugs.webkit.org/show_bug.cgi?id=89079 + + Reviewed by Dirk Pranke. + + PyWebSocket class must accept private_key, certificate, and + ca_certificate arguments and pass them to launching pywebsocket. + Also add ca_certificate handling to new-run-webkit-websocketserver. + + * Scripts/new-run-webkit-websocketserver: + (main): + * Scripts/webkitpy/layout_tests/servers/websocket_server.py: + (PyWebSocket.__init__): + (PyWebSocket._prepare_config): + +2012-06-14 Qi Zhang <qi.2.zhang@nokia.com> + + Unreviewed. Update my email. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-14 Takashi Toyoshima <toyoshim@chromium.org> + + Update pywebsocket to 0.7.6 from 0.7.4 + https://bugs.webkit.org/show_bug.cgi?id=88975 + + Reviewed by Kent Tamura. + + This new version of pywebsocket introduce following features. + - Allow handlers to send a close frame with empty body in response of + a client initiated closing handshake + - Implement perframe compression extension + - Support client certificate authentication + + * Scripts/webkitpy/thirdparty/mod_pywebsocket/COPYING: + * Scripts/webkitpy/thirdparty/mod_pywebsocket/_stream_hybi.py: + (_create_control_frame): + (Stream._receive_frame): + (Stream.send_message): + (Stream.receive_message): + (Stream._send_closing_handshake): + (Stream.close_connection): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/common.py: + (ExtensionParsingException): + (ExtensionParsingException.__init__): + (_parse_extension_param): + (_parse_extension): + (parse_extensions): + (format_extension): + (format_extensions): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/extensions.py: + (_parse_compression_method): + (_create_accepted_method_desc): + (PerFrameCompressionExtensionProcessor): + (PerFrameCompressionExtensionProcessor.__init__): + (PerFrameCompressionExtensionProcessor._lookup_compression_processor): + (PerFrameCompressionExtensionProcessor._get_compression_processor_response): + (PerFrameCompressionExtensionProcessor.get_extension_response): + (PerFrameCompressionExtensionProcessor.setup_stream_options): + (PerFrameCompressionExtensionProcessor.get_compression_processor): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/_base.py: + (parse_token_list): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/hybi.py: + (Handshaker._parse_extensions): + (Handshaker._send_handshake): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/standalone.py: + (WebSocketServer._create_sockets): + (_get_logger_from_class): + (_configure_logging): + (_build_option_parser): + (_main.if): + * Scripts/webkitpy/thirdparty/mod_pywebsocket/util.py: + (RepeatedXorMasker.mask): + +2012-06-14 Zoltan Horvath <zoltan@webkit.org> + + [Qt] Remove USE(QT_IMAGE_DECODER) macro, since we don't use it anymore + + Reviewed by Noam Rosenthal. + + * qmake/mkspecs/features/features.prf: + +2012-06-14 Christophe Dumez <christophe.dumez@intel.com> + + [WK2] Add implementation for registerIntentService in WebFrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=88399 + + Reviewed by Kenneth Rohde Christiansen. + + Update initialization of WKPageLoaderClient. + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + +2012-06-14 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [EFL] [DRT] Implement setDomainRelaxationForbiddenForURLScheme in EFL DRT + https://bugs.webkit.org/show_bug.cgi?id=84577 + + Reviewed by Ryosuke Niwa. + + Add missing implementation setDomainRelaxationForbiddenForURLScheme to EFL's + LayoutTestController. + + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::setDomainRelaxationForbiddenForURLScheme): + +2012-06-13 Christophe Dumez <christophe.dumez@intel.com> + + [WK2] Add implementation for dispatchIntent in WebFrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=88340 + + Reviewed by Kenneth Rohde Christiansen. + + Update initialization of WKPageLoaderClient. + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + +2012-06-13 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120268. + http://trac.webkit.org/changeset/120268 + https://bugs.webkit.org/show_bug.cgi?id=89060 + + WebCompositor::setPerTilePaintingEnabled hits an assertion in + DEBUG (Requested by dominicc|work on #webkit). + + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::applyTo): + +2012-06-13 Tim Horton <timothy_horton@apple.com> + + REGRESSION (r120252): run-webkit-tests on Mac fails + https://bugs.webkit.org/show_bug.cgi?id=89057 + + Reviewed by Dan Bernstein. + + get_option will happily return None (the default only kicks in if + the option is actually *not set*). We should instead check get_option's + return value and default to "x86_64" architecture ourselves. + + * Scripts/webkitpy/layout_tests/port/mac.py: + (MacPort.__init__): + +2012-06-13 Ian Vollick <vollick@chromium.org> + + [chromium] Certain settings in CCSettings could be global + https://bugs.webkit.org/show_bug.cgi?id=88384 + + Reviewed by James Robinson. + + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::applyTo): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + new-run-webkit-tests does not support --32-bit like ORWT did + https://bugs.webkit.org/show_bug.cgi?id=71634 + + Reviewed by Ojan Vafai. + + This patch adds support for 32-bit apple mac builds, adding the + --32-bit flag for compatibility with ORWT and fixing the port + architecture() definition to actually return the correct values. + + * Scripts/webkitpy/layout_tests/port/apple.py: + (ApplePort._generate_all_test_configurations): + * Scripts/webkitpy/layout_tests/port/factory.py: + (port_options): + * Scripts/webkitpy/layout_tests/port/mac.py: + (MacPort): + (MacPort.__init__): + (MacPort._build_driver_flags): + (MacPort.setup_environ_for_server): + * Scripts/webkitpy/layout_tests/port/mac_unittest.py: + (test_sample_process_throws_exception): + (test_32bit): + (test_32bit.run_script): + (test_64bit): + (test_64bit.run_script): + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitPort._build_driver): + (WebKitPort._build_driver_flags): + * Scripts/webkitpy/layout_tests/port/win.py: + (WinPort): + +2012-06-13 Ryosuke Niwa <rniwa@webkit.org> + + Remove webkitpy code to support legacy test_expectations.txt files + https://bugs.webkit.org/show_bug.cgi?id=89038 + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.path_to_test_expectations_file): + (Port.expectations_dict): + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + (PortTest.test_uses_test_expectations_file): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (WebKitPortTest.test_path_to_test_expectations_file): + (test_test_expectations): + * Scripts/webkitpy/style/checker.py: + (CheckerDispatcher.should_skip_without_warning): + (CheckerDispatcher._create_checker): + * Scripts/webkitpy/style/checkers/test_expectations_unittest.py: + (TestExpectationsTestCase._expect_port_for_expectations_path): + * Scripts/webkitpy/tool/steps/commit.py: + (Commit._check_test_expectations): + * Scripts/webkitpy/tool/steps/commit_unittest.py: + (CommitTest.test_check_test_expectations): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + nrwt: remove port.test_expectations() and port.test_expectations_overrides() + https://bugs.webkit.org/show_bug.cgi?id=88948 + + Reviewed by Ojan Vafai. + + In the final patch of this run, we remove the + test_expectations() and test_expectation_overrides() methods + from the Port class - callers must now use just + expectations_dict(). + + Note that support for the cascade in new-run-webkit-tests is + complete but only Chromium uses it; webkit-patch + rebaseline-expectations still does not support updating entries + in any file other than the first expectations file, however. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.path_to_test_expectations_file): + (Port.uses_test_expectations_file): + (Port.expectations_files): + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + (PortTest.test_additional_expectations): + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + (ChromiumPortTest.test_expectations_files): + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + (TestGoogleChromePort.test_get_google_chrome_port): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (test_test_expectations): + (test_legacy_test_expectations): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + nrwt: implement the actual cascade of TestExpectations + https://bugs.webkit.org/show_bug.cgi?id=88947 + + Reviewed by Ojan Vafai. + + This change implements the actual cascade by removing the + concept of 'overrides' from the TestExpectations object and + parsing each file separately. + + There is an actual semantic change in this patch, in that + setting an expectation on a directory in one file will override + the expectations on any individual tests set in prior files. The + test_overrides__directory() unit test verifies this. + + Otherwise, this patch mostly consists of deleting code :). + + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (TestExpectationsModel.__init__): + (TestExpectationsModel.add_expectation_line): + (TestExpectationsModel._add_test): + (TestExpectationsModel._already_seen_better_match): + (TestExpectations.__init__): + (TestExpectations._add_expectations): + * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: + (test_overrides__directory): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + webkitpy: update callers to use port.expectation_dict() instead of test_expectations() and test_expectations_overrides() + https://bugs.webkit.org/show_bug.cgi?id=88946 + + Reviewed by Ojan Vafai. + + In preparation for fully supporting cascading expectations files + and removing the 'overrides' concept. + + There should be no functional changes in this patch. + + * Scripts/webkitpy/layout_tests/controllers/manager_unittest.py: + (ManagerTest.test_update_summary_with_result): + (ResultSummaryTest.get_result_summary): + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (TestExpectations.__init__): + * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: + (parse_exp): + (SkippedTests.check): + (RemoveConfigurationsTest.test_remove): + (test_remove_line): + * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py: + (LintTest.test_all_configurations.FakePort.__init__): + (LintTest.test_all_configurations.FakePort.expectations_dict): + (LintTest.test_lint_test_files__errors): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (test_overrides_are_included_correctly): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + webkitpy: rework the TestExpectations style checker in preparation for the cascade + https://bugs.webkit.org/show_bug.cgi?id=88945 + + Reviewed by Ojan Vafai. + + This patch changes the style checker to call the + TestExpectations parser directly and be oblivious as to what the + port's actual expectations are. + + * Scripts/webkitpy/style/checkers/test_expectations.py: + (TestExpectationsChecker.__init__): + (TestExpectationsChecker.check_test_expectations): + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + nrwt: restructure the port classes to handle multiple expectations files + https://bugs.webkit.org/show_bug.cgi?id=88944 + + Reviewed by Ojan Vafai. + + This patch restructures the Port classes so that each port + returns a list of TestExpectations files to be used (in a new, public, + expectations_files() method), and the base implementation rolls them + up into the ordered expectations_dict(), which becomes a public + method. + + port.path_to_test_expectations_file(), port.test_expectations(), + and port.test_expectations_overrides() are then reimplemented as + wrappers around port.expectations_dict(). + port.test_expectations() and port.test_expectations_overrides() + will eventually be removed when the cascade is fully completed, + and port.path_to_test_expectations_file() will be removed when + the rebaselining tool supports the cascade + (expectations_files() may also become private at that point). + + There should be no functional changes in this patch, but a bunch + of custom logic gets deleted! + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.expectations_dict): + (Port): + (Port.expectations_files): + (Port.test_expectations): + (Port.test_expectations_overrides): + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + (PortTest.test_additional_expectations): + (PortTest.test_uses_test_expectations_file): + * Scripts/webkitpy/layout_tests/port/chromium.py: + (ChromiumPort.all_baseline_variants): + (ChromiumPort.expectations_files): + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + (ChromiumPortTest.test_overrides_and_builder_names): + * Scripts/webkitpy/layout_tests/port/google_chrome.py: + (_expectations_files): + (GoogleChromeLinux32Port.expectations_files): + (GoogleChromeLinux64Port.expectations_files): + (GoogleChromeMacPort.expectations_files): + (GoogleChromeWinPort.expectations_files): + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + (TestGoogleChromePort._verify_expectations_overrides): + * Scripts/webkitpy/layout_tests/port/port_testcase.py: + (PortTestCase.test_expectations_ordering): + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitPort._skipped_file_search_paths): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (TestRebaseline.test_rebaseline_updates_expectations_file_noop): + (test_rebaseline_updates_expectations_file): + (test_rebaseline_does_not_include_overrides): + (test_rebaseline_expectations): + (test_overrides_are_included_correctly): + +2012-06-13 Brent Fulgham <bfulgham@webkit.org> + + [WinCairo] Update URL of WinCairoRequirements.zip download. + https://bugs.webkit.org/show_bug.cgi?id=89009 + + Reviewed by Martin Robinson. + + * Tools/Scripts/update-webkit-dependency: Put fallback code + to download a "last update" time from servers that don't properly + report Last-Modified in their HTTP header. + * Tools/Scripts/update-webkit-wincairo-libs: Change download link + for the WinCairo build requirements bundle. + +2012-06-13 Dirk Pranke <dpranke@chromium.org> + + nrwt: preliminary cleanup before supporting cascading expectations files + https://bugs.webkit.org/show_bug.cgi?id=88942 + + Reviewed by Ojan Vafai. + + This change just prepares the TestExpectations parser to get filenames + along with the expectations, and improves the warning messages so that + they contain the filenames along with the line numbers. + + There should be no functional changes in this patch. + + * Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py: + (TestExpectationEditorTests.make_parsed_expectation_lines): + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (TestExpectationParser.parse): + (TestExpectationParser.expectation_for_skipped_test): + (TestExpectationParser._tokenize): + (TestExpectationParser._tokenize_list): + (TestExpectationLine): + (TestExpectationsModel.__init__): + (TestExpectationsModel._already_seen_better_match): + (TestExpectations.__init__): + (TestExpectations._shorten_filename): + (TestExpectations._report_warnings): + (TestExpectations._add_skipped_tests): + * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: + (TestExpectationParserTests._tokenize): + (TestExpectationParserTests.test_tokenize_blank): + (TestExpectationParserTests.test_tokenize_missing_colon): + (TestExpectationParserTests.test_tokenize_extra_colon): + (TestExpectationParserTests.test_tokenize_empty_comment): + (TestExpectationParserTests.test_tokenize_comment): + (TestExpectationParserTests.test_tokenize_missing_equal): + (TestExpectationParserTests.test_tokenize_extra_equal): + (TestExpectationParserTests.test_tokenize_valid): + (TestExpectationParserTests.test_tokenize_valid_with_comment): + (TestExpectationParserTests.test_tokenize_valid_with_multiple_modifiers): + (TestExpectationParserTests.test_parse_empty_string): + (TestExpectationSerializerTests._tokenize): + (TestExpectationSerializerTests.assert_round_trip): + (TestExpectationSerializerTests.assert_list_round_trip): + * Scripts/webkitpy/tool/servers/gardeningserver.py: + (GardeningExpectationsUpdater.update_expectations): + +2012-06-13 Zan Dobersek <zandobersek@gmail.com> + + [Gtk] Enable link prefetch support in the developer builds + https://bugs.webkit.org/show_bug.cgi?id=89011 + + Reviewed by Martin Robinson. + + Enable the link prefetch support for Gtk by default in developer + builds. + + * Scripts/webkitperl/FeatureList.pm: + +2012-06-13 Csaba Osztrogonác <ossy@webkit.org> + + Update buildbot master in autoinstaller to match build.webkit.org + https://bugs.webkit.org/show_bug.cgi?id=88992 + + Reviewed by Adam Barth. + + * Scripts/webkitpy/thirdparty/__init__.py: + (AutoinstallImportHook._install_buildbot): + +2012-06-13 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r120209. + http://trac.webkit.org/changeset/120209 + https://bugs.webkit.org/show_bug.cgi?id=89007 + + Broke the WebKit2 mac build. (Requested by andersca on + #webkit). + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + +2012-06-13 Zoltan Horvath <zoltan@webkit.org> + + check-webkit-style needs to respect Qt API coding style + https://bugs.webkit.org/show_bug.cgi?id=88995 + + Reviewed by Csaba Osztrogonác. + + Add -whitespace/declaration exception to Qt API files. + + * Scripts/webkitpy/style/checker.py: + +2012-06-13 Christophe Dumez <christophe.dumez@intel.com> + + [WK2] Add implementation for dispatchIntent in WebFrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=88340 + + Reviewed by Kenneth Rohde Christiansen. + + Update initialization of WKPageLoaderClient. + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + +2012-06-13 Allan Sandfeld Jensen <allan.jensen@nokia.com> + + [Qt] Handle multiple held buttons in touch mocking. + https://bugs.webkit.org/show_bug.cgi?id=88865 + + Reviewed by Kenneth Rohde Christiansen. + + Add handling for multiple held mouse-buttons in the appropiate places. + To do this last-pos and start-pos are now also read from the last recorded + touch-point instead from object-global variables. + + * MiniBrowser/qt/MiniBrowserApplication.cpp: + (MiniBrowserApplication::notify): + (MiniBrowserApplication::updateTouchPoint): + * MiniBrowser/qt/MiniBrowserApplication.h: + (MiniBrowserApplication): + +2012-06-13 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Make it possible to disable -Werror in production builds + + Reviewed by Tor Arne Vestbø. + + Don't do -Werror if build-webkit is called with --qmakearg=CONFIG+=production_build, + something qt5.git's qtwebkit.pri will soon do. + + * qmake/mkspecs/features/unix/default_post.prf: + +2012-06-13 Dominik Röttsches <dominik.rottsches@intel.com> + + [EFL] Store and compare md5sum of jhbuild files to trigger cleaning Dependencies + https://bugs.webkit.org/show_bug.cgi?id=85790 + + Reviewed by Gustavo Noronha Silva. + + Add md5 checks for jhbuild configuration for EFL, reusing the gtk jhbuild related + code in webkitdirs.pm. + + * Scripts/webkitdirs.pm: + (jhbuildConfigurationChanged): + (saveJhbuildMd5): + (cleanJhbuild): + (buildAutotoolsProject): + (generateBuildSystemFromCMakeProject): + +2012-06-13 Qi Zhang <qi.2.zhang@nokia.com> + + [Qt] Add configure test for zlib and set WTF_USE_ZLIB if found + https://bugs.webkit.org/show_bug.cgi?id=88763 + + Add configure test for zlib and set WTF_USE_ZLIB if found to enable websocket + extension. + + Reviewed by Simon Hausmann. + + * qmake/config.tests/libzlib: Added. + * qmake/config.tests/libzlib/libzlib.cpp: Added. + (main): + * qmake/config.tests/libzlib/libzlib.pro: Added. + * qmake/mkspecs/features/features.prf: + * qmake/sync.profile: + +2012-06-13 Robin Cao <robin.cao@torchmobile.com.cn> + + [BlackBerry] Enable MEDIA_STREAM by default + https://bugs.webkit.org/show_bug.cgi?id=88849 + + Reviewed by Antonio Gomes. + + * Scripts/webkitperl/FeatureList.pm: + +2012-06-13 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Prevent stderr output from messing up detection of build path + + https://bugs.webkit.org/show_bug.cgi?id=88075 + + Warnings such as 'perl: warning: Setting locale failed' will otherwise + end up as the build path when calling out to webkit-build-directory. + + Reviewed by Ojan Vafai. + + * Scripts/webkitpy/layout_tests/port/config.py: + (Config.build_directory): + +2012-06-13 Ryosuke Niwa <rniwa@webkit.org> + + Update the builder name for Apple Lion builders. + + * Scripts/webkitpy/layout_tests/port/builders.py: + +2012-06-13 Joel Dillon <joel.dillon@codethink.co.uk> + + [Qt][Win]QtTestBrowser somehow picks up DumpRenderTree's main.cpp, causing a failure to link + https://bugs.webkit.org/show_bug.cgi?id=88874 + + Reviewed by Simon Hausmann. + + Rename main.cpp in QtTestBrowser because on Windows + it conflicts with main.cpp from DumpRenderTree. + + * QtTestBrowser/QtTestBrowser.pro: + * QtTestBrowser/qttestbrowser.cpp: Renamed from Tools/QtTestBrowser/main.cpp. + (launcherMain): + (LauncherApplication): + (LauncherApplication::urls): + (LauncherApplication::isRobotized): + (LauncherApplication::robotTimeout): + (LauncherApplication::robotExtraTime): + (LauncherApplication::applyDefaultSettings): + (LauncherApplication::LauncherApplication): + (requiresGraphicsView): + (LauncherApplication::handleUserOptions): + (main): + +2012-06-12 Lucas Forschler <lforschler@apple.com> + + Wrap bot types inside (). + https://bugs.webkit.org/show_bug.cgi?id=88893 + + Reviewed by Stephanie Lewis. + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2012-06-12 Christophe Dumez <christophe.dumez@intel.com> + + [soup] Prevent setting or editing httpOnly cookies from JavaScript + https://bugs.webkit.org/show_bug.cgi?id=88760 + + Reviewed by Gustavo Noronha Silva. + + Update libsoup to v2.39.2, glib to v2.33.2 and glib-networking + to v2.33.2 for both GTK and EFL ports. + + * efl/jhbuild.modules: + * gtk/jhbuild.modules: + +2012-06-12 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] Enable SHADOW_DOM flag + https://bugs.webkit.org/show_bug.cgi?id=87732 + + Reviewed by Kentaro Hara. + + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::resetDefaultsToConsistentValues): Enable + SHADOW_DOM by default in DRT. + * DumpRenderTree/efl/DumpRenderTreeView.cpp: + (onFocusCanCycle): Enable focus cycling in EFL DRT to behave like + Chromium and Mac ports. + (drtViewAdd): + * Scripts/webkitperl/FeatureList.pm: Enable SHADOW_DOM flag by default + at compile time for EFL port. + +2012-06-12 Ashod Nakashian <ashodnakashian@yahoo.com> + + WinLauncher should show loading errors + https://bugs.webkit.org/show_bug.cgi?id=80760 + + Reviewed by Brent Fulgham. + + * WinLauncher/WinLauncher.cpp: Added load-fail handler to show messagebox with error. + (WinLauncherWebHost::didFailProvisionalLoadWithError): + * WinLauncher/WinLauncher.h: + (WinLauncherWebHost::didFailProvisionalLoadWithError): + (WinLauncherWebHost): + +2012-06-12 Ryuan Choi <ryuan.choi@samsung.com> + + [EFL][WK2] Add MiniBrowserEfl. + https://bugs.webkit.org/show_bug.cgi?id=61850 + + Reviewed by Chang Shu. + + Implement MiniBrowser for EFL. + + * CMakeLists.txt: + * MiniBrowser/efl/CMakeLists.txt: Added. + * MiniBrowser/efl/main.c: Added. + (_MiniBrowser): + (main_signal_exit): + (on_ecore_evas_resize): + (browserCreate): + (main): + +2012-06-12 Helder Correia <helder.correia@nokia.com> + + Unreviewed. Update my email address in committers.py. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-12 Dominik Röttsches <dominik.rottsches@intel.com> + + [EFL] Resolve CMake warnings on overlapping search paths for EFL jhbuild-enabled build + https://bugs.webkit.org/show_bug.cgi?id=84707 + + Fixing CMAKE prefix path for 64bit systems to avoid CMAKE warnings on those. + use_lib64 variable is preconfigured to True by jhbuild. + + Reviewed by Dirk Pranke. + + * efl/jhbuildrc: + +2012-06-12 Dana Jansens <danakj@chromium.org> + + Add zlieber@chromium.org to contributors list + https://bugs.webkit.org/show_bug.cgi?id=88904 + + Unreviewed. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-12 Lucas Forschler <lforschler@apple.com> + + Rename Apple bots to a standard convention. + https://bugs.webkit.org/show_bug.cgi?id=88893 + + Note: This has the side effect of grouping all of the Apple bots together in the waterfall. + + Reviewed by Simon Fraser. + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2012-06-12 Mike West <mkwst@chromium.org> + + Make document.documentURI readonly from JavaScript + https://bugs.webkit.org/show_bug.cgi?id=65187 + + Reviewed by Alexey Proskuryakov. + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/Tests/mac/SetDocumentURI.html: Added. + * TestWebKitAPI/Tests/mac/SetDocumentURI.mm: Added. + (-[SetDocumentURITest webView:didFinishLoadForFrame:]): + (TestWebKitAPI): + (TestWebKitAPI::TEST): + +2012-06-12 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] enable LEGACY_WEBKIT_BLOB_BUILDER flag + https://bugs.webkit.org/show_bug.cgi?id=88715 + + Reviewed by Noam Rosenthal. + + Enable LEGACY_WEBKIT_BLOB_BUILDER flag by default on EFL port. + + * Scripts/webkitperl/FeatureList.pm: + +2012-06-12 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Fix -Werror for the buildbots + https://bugs.webkit.org/show_bug.cgi?id=88223 + + Rubber-stamped by Tor Arne Vestbø. + + Revert a part of r119269 to enable Werror again for non qt-developer-builds. (for bots for example) + + * qmake/mkspecs/features/unix/default_post.prf: + +2012-06-12 Balazs Kelemen <kbalazs@webkit.org> + + [REGRESSION][WTR] Build fail with werror after r120054 + https://bugs.webkit.org/show_bug.cgi?id=88862 + + Reviewed by Csaba Osztrogonác. + + Some static helpers become unused after counterValueForElementById + has moved to Internals. Let's remove them. + + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR): + +2012-06-12 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Slave losts cause build break on bots + https://bugs.webkit.org/show_bug.cgi?id=38980 + + Minor fix after r59261. + + Reviewed by Tor Arne Vestbø. + + * Scripts/build-webkit: + (unlinkZeroFiles): Don't remove 0 byte sized directories, because they are always 0 byte sized on Windows. + +2012-06-11 Kaustubh Atrawalkar <kaustubh@motorola.com> + + [DRT] LTC:: counterValueForElementById() could be moved to Internals. + https://bugs.webkit.org/show_bug.cgi?id=84406 + + Reviewed by Hajime Morita. + + Move the counterValueForElementById from LayoutTestCotroller to Internals and + remove the old platform specific implementations as it exclusively tests WebCore functionality. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::setPOSIXLocale): + * DumpRenderTree/chromium/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + * DumpRenderTree/qt/LayoutTestControllerQt.h: + (LayoutTestController): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + * WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl: + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR): + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + (LayoutTestController): + +2012-06-11 Hans Wennborg <hans@chromium.org> + + Speech JavaScript API: Make SpeechRecognitionError an Event + https://bugs.webkit.org/show_bug.cgi?id=88784 + + Reviewed by Adam Barth. + + Make it possible to have MockWebSpeechRecognizer fire error events. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::setMockSpeechRecognitionError): + * DumpRenderTree/chromium/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/chromium/MockWebSpeechRecognizer.cpp: + (WebKit): + (ErrorTask): + (WebKit::ErrorTask::ErrorTask): + (MockWebSpeechRecognizer::addMockResult): + (MockWebSpeechRecognizer::setError): + * DumpRenderTree/chromium/MockWebSpeechRecognizer.h: + (MockWebSpeechRecognizer): + +2012-06-11 Ojan Vafai <ojan@chromium.org> + + Don't show the ASAN builders in garden-o-matic since they don't get block WebKit rolls. + https://bugs.webkit.org/show_bug.cgi?id=88836 + + Reviewed by Dirk Pranke. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js: + +2012-06-11 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] Remove CMakeCache.txt before building + https://bugs.webkit.org/show_bug.cgi?id=88717 + + Reviewed by Antonio Gomes. + + Remove CMake cache file before every build to avoid using outdated + build flags when new features get enabled. This will avoid unexpected + failures on the bots due to outdated build flags. + + * Scripts/webkitdirs.pm: + (generateBuildSystemFromCMakeProject): + +2012-06-11 Vincent Scheib <scheib@chromium.org> + + Add new Pointer Lock spec attribute webkitPointerLockElement. + https://bugs.webkit.org/show_bug.cgi?id=88799 + + Reviewed by Dimitri Glazkov. + + Part of a series of refactoring changes to update pointer lock API to + the fullscreen locking style. https://bugs.webkit.org/show_bug.cgi?id=84402 + + New attribute webkitPointerLockElement added. Follow up patches + will remove the previous isLocked attribute. Tests updated to use + the new attribute. + + WebViewHost logic required modification to correctly repond to + a lock, unlock, pointerLockElement call series. Specifically, + unlocking must be queued after a lock command is issued always + as the lock state may not be set yet with a lock request in flight. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::requestPointerUnlock): Always post didLosePointerLock task. + (WebViewHost::didLosePointerLock): Signal didLosePointerLock only if pointer was locked. + +2012-06-11 Alexis Menard <alexis.menard@openbossa.org> + + [CSS3 Backgrounds and Borders] Protect box-decoration-break behind a feature flag. + https://bugs.webkit.org/show_bug.cgi?id=88804 + + Reviewed by Tony Chang. + + Protect box-decoration-break behind a feature flag enabled by default. + + * Scripts/webkitperl/FeatureList.pm: + * qmake/mkspecs/features/features.pri: + +2012-06-11 Gyuyoung Kim <gyuyoung.kim@samsung.com> + + [CMAKE][EFL] Remove duplicated executable output path + https://bugs.webkit.org/show_bug.cgi?id=88765 + + Reviewed by Daniel Bates. + + CMake files for EFL port have redefined executable output path. However, EFL port doesn't + need to define again because it is already defined in top-level CMake file. + + * DumpRenderTree/efl/CMakeLists.txt: + * EWebLauncher/CMakeLists.txt: + +2012-06-11 Ojan Vafai <ojan@chromium.org> + + Don't consider show warnings in the garden-o-matic UI for non-layout test failures + https://bugs.webkit.org/show_bug.cgi?id=88816 + + Reviewed by Dirk Pranke. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/base.js: + Expose a way to clear AsynchronousCaches. + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders.js: + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/builders_unittests.js: + Clear the buildInfo cache at the beginning of each test in order to avoid having one test affect another. + +2012-06-11 Dirk Pranke <dpranke@chromium.org> + + nrwt exits early too frequently + https://bugs.webkit.org/show_bug.cgi?id=73843 + + Reviewed by Ryosuke Niwa. + + Change the defaults for new-run-webkit-tests for both + --exit-after-n-failures and --exit-after-n-crashes-or-timeouts + to zero (i.e., we will never exit early by default). + + If people want their buildbots to exit early it is their + responsibility to update their buildbot configs appropriately. + + Note that we have tests that ensure that these flags work for + non-zero numbers, but we don't have tests that either test the + default or ensure that zero means "run all of the tests". I + think that's okay but can add tests if others disagree. + + Also note that it looks like no changes on the build.webkit.org + master.cfg are necessary; all of the bots seem to be using the + RunWebKitTests wrapper which is already setting the flags. There + is a NewRunWebKitTests wrapper, but that looks to be unused; I + will delete that in a separate patch. + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + (parse_args): + +2012-06-11 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [EFL] [DRT] Reset CacheModel before running each test + https://bugs.webkit.org/show_bug.cgi?id=87534 + + Reviewed by Gustavo Noronha Silva. + + Reset cache model to default before running each test to fix some + flaky tests on EFL build bots. Also fix case value in setCacheModel. + + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::resetDefaultsToConsistentValues): + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::setCacheModel): + +2012-06-11 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [GTK] Memory leaks in DRT EventSender.cpp + https://bugs.webkit.org/show_bug.cgi?id=88774 + + Reviewed by Martin Robinson. + + Fix a few possible memory leaks in EventSender code. + + * DumpRenderTree/gtk/EventSender.cpp: + (contextClickCallback): Free the event returned by gdk_event_new(). + (mouseDownCallback): Ditto. + (mouseUpCallback): Ditto. + +2012-06-11 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [EFL] REGRESSION (r119788): tests rely on pathToLocalResource are failing after r119788 + https://bugs.webkit.org/show_bug.cgi?id=88661 + + Reviewed by Dirk Pranke. + + Pass string length explicitly when creating String object from + non-null-terminated UChar* returned by characters(). + + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::pathToLocalResource): + +2012-06-11 David Dorwin <ddorwin@chromium.org> + + [chromium] Provide access to the WebPlugin created by the helper plugin widget + https://bugs.webkit.org/show_bug.cgi?id=88028 + + Reviewed by Adam Barth. + + Added isPlaceholder() to WebPlugin. + + * DumpRenderTree/chromium/TestWebPlugin.h: + (TestWebPlugin::isPlaceholder): + +2012-06-11 Tony Chang <tony@chromium.org> + + rebaseline from garden-o-matic leaves N processes each time it is run + https://bugs.webkit.org/show_bug.cgi?id=88586 + + Reviewed by Dirk Pranke. + + This appears to only be a problem on python 2.7. Maybe a bug causing + pools to not be garbage collected? + + * Scripts/webkitpy/common/system/executive.py: + (Executive.run_in_parallel): close() and join() the process pool. + * Scripts/webkitpy/common/system/executive_unittest.py: + (ExecutiveTest.test_run_in_parallel): + +2012-06-11 Zoltan Horvath <zoltan@webkit.org> + + [Qt] Add config tests for WEBP imagedecoder library, modify HAVE(decoderlibrary) to USE(...) + https://bugs.webkit.org/show_bug.cgi?id=87841 + + Reviewed by Simon Hausmann. + + * qmake/config.tests/libwebp/libwebp.cpp: Added. + (main): + * qmake/config.tests/libwebp/libwebp.pro: Added. + * qmake/sync.profile: + +2012-06-10 Ryosuke Niwa <rniwa@webkit.org> + + Expose layoutTestController as testRunner + https://bugs.webkit.org/show_bug.cgi?id=88210 + + Reviewed by Darin Adler. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::makeWindowObject): + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::bindJSObjectsToWindow): + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::DumpRenderTree::initJSObjects): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR::LayoutTestController::makeWindowObject): + +2012-06-09 Dominic Cooney <dominicc@chromium.org> + + [Chromium] Remove JavaScriptCore dependencies from gyp + https://bugs.webkit.org/show_bug.cgi?id=88510 + + Reviewed by Adam Barth. + + Chromium doesn't support JSC any more and there doesn't seem to be + a strong interest in using GYP as the common build system in other + ports. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * Scripts/generate-project-files: Removed. + +2012-06-09 Sukolsak Sakshuwong <sukolsak@google.com> + + Add UNDO_MANAGER flag + https://bugs.webkit.org/show_bug.cgi?id=87908 + + Reviewed by Tony Chang. + + * Scripts/webkitperl/FeatureList.pm: + * qmake/mkspecs/features/features.pri: + +2012-06-08 Ryosuke Niwa <rniwa@webkit.org> + + webkit-patch land-safely should set cq? if the patch author is not in committers.py + https://bugs.webkit.org/show_bug.cgi?id=88689 + + Reviewed by Dirk Pranke. + + When posting a patch on Bugzilla, trun cq+ into cq? if the Bugzilla login is not listed + in committers.py or the contributor cannot commit. If anything, the contributor can still + set cq+ on thier patches manually so I don't think this will be an issue for people who + don't list their Bugzille email on committers.py. + + * Scripts/webkitpy/common/net/bugzilla/bugzilla.py: + (Bugzilla._commit_queue_flag): + * Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py: + (test_commit_queue_flag): + (test_commit_queue_flag.assert_commit_queue_flag): + +2012-06-08 Dirk Pranke <dpranke@chromium.org> + + remove obsolete NewRunWebKitTests buildbot master factory classes + https://bugs.webkit.org/show_bug.cgi?id=88693 + + Reviewed by Ryosuke Niwa. + + I believe these aren't used any more ... + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (RunWebKitTests.getText2): + (BuildAndTestLeaksFactory): + +2012-06-08 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium-Android] Build DumpRenderTree with Android SDK + https://bugs.webkit.org/show_bug.cgi?id=88598 + + Change WebKit side of DRT related code according to some recent changes at chromium side. + + Reviewed by Adam Barth. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * Scripts/webkitpy/layout_tests/port/chromium_android.py: + (ChromiumAndroidPort.__init__): + (ChromiumAndroidPort._path_to_driver): + +2012-06-08 Wei James <james.wei@intel.com> + + Add app_abi option for DumpRenderTree_apk + https://bugs.webkit.org/show_bug.cgi?id=88626 + + Reviewed by Adam Barth. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + +2012-06-08 Carlos Garcia Campos <cgarcia@igalia.com> + + [GTK] Add API to get the library version to WebKit2 GTK+ + https://bugs.webkit.org/show_bug.cgi?id=88426 + + Reviewed by Martin Robinson. + + * gtk/generate-gtkdoc: + (get_webkit2_options): Add built sources to the list of files, but + ignore enum types and marshallers. + +2012-06-07 Vincent Scheib <scheib@chromium.org> + + Layout Test pointer-lock/pointerlockchange-pointerlockerror-events.html is failing + https://bugs.webkit.org/show_bug.cgi?id=88604 + + Reviewed by Kent Tamura. + + DumpRenderTree fixed to not call didLosePointerLock if pointer is not currently locked. + Fixes debug only assert crash in pointer-lock/pointerlockchange-pointerlockerror-events.html test. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::requestPointerUnlock): + +2012-06-08 Hans Wennborg <hans@chromium.org> + + Speech JavaScript API: mock WebSpeechRecognizer for DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=87976 + + Reviewed by Kent Tamura. + + Provide a mock implementation of WebSpeechRecognizer for + DumpRenderTree. This will allow better testing of the API via layout + tests. + + * DumpRenderTree/DumpRenderTree.gypi: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::addMockSpeechRecognitionResult): + * DumpRenderTree/chromium/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/chromium/MockWebSpeechRecognizer.cpp: Added. + (MockWebSpeechRecognizer::create): + (MockWebSpeechRecognizer::start): + (MockWebSpeechRecognizer::stop): + (MockWebSpeechRecognizer::abort): + (MockWebSpeechRecognizer::MockWebSpeechRecognizer): + (MockWebSpeechRecognizer::~MockWebSpeechRecognizer): + (MockWebSpeechRecognizer::ResultTask::runIfValid): + * DumpRenderTree/chromium/MockWebSpeechRecognizer.h: Added. + (WebKit): + (MockWebSpeechRecognizer): + (MockWebSpeechRecognizer::addMockResult): + (MockWebSpeechRecognizer::taskList): + (ClientCallTask): + (MockWebSpeechRecognizer::ClientCallTask::ClientCallTask): + (ResultTask): + (MockWebSpeechRecognizer::ResultTask::ResultTask): + (NoMatchTask): + (MockWebSpeechRecognizer::NoMatchTask::NoMatchTask): + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::speechRecognizer): + * DumpRenderTree/chromium/WebViewHost.h: + (WebViewHost): + (WebViewHost::mockSpeechRecognizer): + +2012-06-07 Kinuko Yasuda <kinuko@chromium.org> + + check-webkit-style needs to be taught about <public/Foo.h> + https://bugs.webkit.org/show_bug.cgi?id=88524 + + Reviewed by David Levin. + + * Scripts/webkitpy/style/checkers/cpp.py: + (_classify_include): + * Scripts/webkitpy/style/checkers/cpp_unittest.py: + (OrderOfIncludesTest.test_public_primary_header): + (OrderOfIncludesTest.test_classify_include): + +2012-06-07 Joshua Lock <joshua.lock@intel.com> + + [EFL][DRT] Normalize file:///tmp/LayoutTests in LayoutTestController::pathToLocalResource() + https://bugs.webkit.org/show_bug.cgi?id=67255 + + Reviewed by Dirk Pranke. + + Implement pathToLocalResource to redirect file:///tmp URL's to + DUMPRENDERTREE_TEMP and file:///tmp/LayoutTests to point to the + LayoutTests sub-directory of the WebKit source tree. + + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: + (LayoutTestController::pathToLocalResource): + +2012-06-07 Tony Payne <tpayne@chromium.org> + + [chromium] Allow LayoutTests under new git workflow + https://bugs.webkit.org/show_bug.cgi?id=88575 + + On Windows, chromium indirects through git.bat. Adds the same hack that + is currently used for discovering svn.bat to support the new git + workflow. + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/common/checkout/scm/git.py: + (Git): Replaces all hard-coded references to 'git' with the class + variable executable_name. + (Git._check_git_architecture): + (Git.in_working_directory): + (Git.find_checkout_root): + (Git.read_git_config): + (Git.discard_local_commits): + (Git.local_commits): + (Git.working_directory_is_clean): + (Git.clean_working_directory): + (Git.status_command): + (Git.add_list): + (Git.delete_list): + (Git.exists): + (Git._current_branch): + (Git.changed_files): + (Git._changes_files_for_commit): + (Git.revisions_changing_file): + (Git.conflicted_files): + (Git.svn_revision): + (Git.create_patch): + (Git._run_git_svn_find_rev): + (Git.contents_at_revision): + (Git.diff_for_file): + (Git.show_head): + (Git.committer_email_for_revision): + (Git.apply_reverse_diff): + (Git.revert_files): + (Git.commit_with_message): + (Git._commit_on_branch): + (Git.svn_commit_log): + (Git.last_svn_commit_log): + (Git.svn_blame): + (Git._branch_ref_exists): + (Git.delete_branch): + (Git.remote_merge_base): + (Git.commit_locally_with_message): + (Git.push_local_commits_to_server): + (Git.commit_ids_from_commitish_arguments): + (Git.commit_message_for_local_commit): + (Git.files_changed_summary_for_commit): + * Scripts/webkitpy/common/host.py: + (Host._engage_awesome_windows_hacks): Adds an awesome 'git.bat' hack + that duplicates the logic in the existing 'svn.bat' hack. + +2012-06-07 Ojan Vafai <ojan@chromium.org> + + Style build architectures like build versions for non-layout test failures + https://bugs.webkit.org/show_bug.cgi?id=88590 + + Reviewed by Tony Chang. + + Since we show the list of failing tests after the architecture, we want the + buildtype and architecture to be grouped together visually. + + * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/failures.css: + (.effects a.failing-builder>span.architecture): + +2012-06-07 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium] Remove header dependency of ImageDiff to WTF + https://bugs.webkit.org/show_bug.cgi?id=88422 + + Reviewed by Ryosuke Niwa. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * DumpRenderTree/chromium/ImageDiff.cpp: + (untestedCompareImages): + +2012-06-07 Dongwoo Im <dw.im@samsung.com> + + [EFL] [DRT] DRT enables WebAudio when WebAudio feature is enabled. + https://bugs.webkit.org/show_bug.cgi?id=88491 + + Reviewed by Dirk Pranke. + + DRT should enable WebAudio when WebAudio feature is enabled, + so that the WebAudio feature could be tested by the Layouttest. + + * DumpRenderTree/efl/LayoutTestControllerEfl.cpp: Enable WebAudio when WebAudio feature is enabled. + (LayoutTestController::overridePreference): + +2012-06-07 Dirk Pranke <dpranke@chromium.org> + + webkit-patch rebaseline-expectations should only rebaseline the appropriate suffixes for the failure in question + https://bugs.webkit.org/show_bug.cgi?id=88581 + + Reviewed by Ojan Vafai. + + webkit-paptch rebaseline-expectations was ignoring what the + expected results for a test were and pulling down all the result + files from a bot. This could lead to us pulling down old, + incorrect .txt or .png files. With this patch we will now only + pull down expectations of the appropriate file types (so an + IMAGE failure will only pull the png and not the txt file). + + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (has_pixel_failures): + (suffixes_for_expectations): + * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: + (FunctionsTest.test_suffixes_for_expectations): + * Scripts/webkitpy/tool/commands/rebaseline.py: + (AbstractRebaseliningCommand.__init__): + (RebaselineExpectations._is_supported_port): + (RebaselineExpectations._update_expectations_file): + (RebaselineExpectations._tests_to_rebaseline): + (RebaselineExpectations._rebaseline_port): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (test_overrides_are_included_correctly): + +2012-06-07 Ojan Vafai <ojan@chromium.org> + + Fix recent null pointer error regression in the flakiness dashboard + https://bugs.webkit.org/show_bug.cgi?id=88573 + + Reviewed by Dirk Pranke. + + * TestResultServer/static-dashboards/builders.js: + (requestBuilderList): + * TestResultServer/static-dashboards/flakiness_dashboard_unittests.js: + +2012-06-07 Konrad Piascik <kpiascik@rim.com> + + Add Konrad Piascik to committers.py + https://bugs.webkit.org/show_bug.cgi?id=88560 + + Unreviewed. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-07 Tony Chang <tony@chromium.org> + + [chromium] Win mock scrollbars appear to overflow by a pixel to the right and bottom + https://bugs.webkit.org/show_bug.cgi?id=77368 + + Reviewed by Ojan Vafai. + + It doesn't look like we ever get a rect with width or height of 0. + I ran css1, css2.1, fast/forms, and tables without any crashes. + + * DumpRenderTree/chromium/WebThemeEngineDRTWin.cpp: + (webRectToSkIRect): Correctly convert a WebRect to a SkIRect. + +2012-06-07 Dirk Pranke <dpranke@chromium.org> + + run-webkit-tests --lint-test-files gives an error when run on linux + https://bugs.webkit.org/show_bug.cgi?id=88551 + + Reviewed by Ojan Vafai. + + We weren't mapping the expectations properly for the + google-chrome ports. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.path_to_test_expectations_file): + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + (TestGoogleChromePort.test_path_to_expectations): + +2012-06-07 Daniel Erat <derat@chromium.org> + + [chromium] Add LayoutTestController::setTextSubpixelPositioning() for Linux. + https://bugs.webkit.org/show_bug.cgi?id=88263 + + Reviewed by Tony Chang. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::reset): + (LayoutTestController::setTextSubpixelPositioning): + * DumpRenderTree/chromium/LayoutTestController.h: + (LayoutTestController): + * DumpRenderTree/chromium/fonts.conf: + +2012-06-07 Zan Dobersek <zandobersek@gmail.com> + + [Gtk] Assertions in gtk_widget_draw when acquiring pixel output + https://bugs.webkit.org/show_bug.cgi?id=88060 + + Reviewed by Martin Robinson. + + Spin the main loop before acquiring the pixel content. This ensures things + like late size allocations are finished before calling gtk_widget_draw, + avoiding assertions and subsequent empty pixel results. + + * DumpRenderTree/gtk/PixelDumpSupportGtk.cpp: + (createBitmapContextFromWebView): + +2012-06-06 Kenneth Rohde Christiansen <kenneth@webkit.org> + + [Qt] Improve the visual of the viewport info box + https://bugs.webkit.org/show_bug.cgi?id=88410 + + Reviewed by Tor Arne Vestbø. + + Improve the visual and make it possible to see the content more easy. + + * MiniBrowser/qt/qml/ViewportInfoItem.qml: + +2012-06-06 Mariusz Grzegorczyk <mariusz.g@samsung.com> + + [EFL][WK2] Compile webkit1 and webkit2 by default. + https://bugs.webkit.org/show_bug.cgi?id=85041 + + Reviewed by Chang Shu. + + Compile webkit1 and webkit2 while running Tools/Scripts/build-webkit --efl. + Webkit2 build can be skipped by adding --no-webkit2 option to build-webkit script. + + * Scripts/build-webkit: + +2012-06-06 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r119662. + http://trac.webkit.org/changeset/119662 + https://bugs.webkit.org/show_bug.cgi?id=88487 + + Broke builds (Requested by rniwa on #webkit). + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * DumpRenderTree/chromium/ImageDiff.cpp: + (untestedCompareImages): + +2012-06-06 Xianzhu Wang <wangxianzhu@chromium.org> + + [Chromium] Remove header dependency of ImageDiff to WTF + https://bugs.webkit.org/show_bug.cgi?id=88422 + + Reviewed by Adam Barth. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * DumpRenderTree/chromium/ImageDiff.cpp: + (untestedCompareImages): + +2012-06-06 Amy Ousterhout <aousterh@chromium.org> + + [WebKit] DeviceOrientation cleanup + https://bugs.webkit.org/show_bug.cgi?id=88406 + + Reviewed by Kent Tamura. + + Updated LayoutTestController to use new public default constructor in WebDeviceOrientation.h. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::setMockDeviceOrientation): + +2012-05-29 Dirk Pranke <dpranke@chromium.org> + + webkitpy: add support for an ordered dict of test expectations + https://bugs.webkit.org/show_bug.cgi?id=87802 + + Reviewed by Ojan Vafai. + + As per https://bugs.webkit.org/show_bug.cgi?id=65834 we want to + support a cascaded list of test expectations files. An easy way + to think of this is as an ordered dictionary of name -> contents + for files, where the name is usually a path on disk (I say + usually because we want to support other kinds of expectations + like the compile-time skips for unsupported features in + webkit.py, and we want to continue to support "in-memory" test + expectations that don't require a filesystem). + + Conveniently there is an OrderedDict implementation in Python + 2.7+ and it is available as a backport, so the first step in + adding this support is to use that implementation. Subsequent + patches will update the test_expectations.py module (and other + callers) to access the dict directly. + + This patch just changes the base internal implementation and + provides wrappers for compatibility. The derived ports + (WebKitPort, TestPort, etc.) still need to be updated. + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port._expectations_dict): + (Port.test_expectations): + (Port): + (Port._expectations_overrides_dict): + (Port.test_expectations_overrides): + * Scripts/webkitpy/layout_tests/port/port_testcase.py: + (PortTestCase.test_expectations_ordering): + (PortTestCase): + (PortTestCase.test_expectations_overrides_ordering): + * Scripts/webkitpy/thirdparty/ordered_dict.py: Added. + (OrderedDict): + (OrderedDict.__init__): + (OrderedDict.clear): + (OrderedDict.__setitem__): + (OrderedDict.__delitem__): + (OrderedDict.__iter__): + (OrderedDict.__reversed__): + (OrderedDict.popitem): + (OrderedDict.__reduce__): + (OrderedDict.__repr__): + (OrderedDict.copy): + (OrderedDict.fromkeys): + +2012-06-06 Mario Sanchez Prada <msanchez@igalia.com> + + Unreviewed gardening. Unit test fails on GTK 64bit debug bot. + + * gtk/run-api-tests: + (TestRunner): Skip TestWebKitAPI/WTF/TestHashMap. + +2012-06-06 Dirk Pranke <dpranke@chromium.org> + + nrwt should look in 'out' for binaries on chromium win to support ninja + https://bugs.webkit.org/show_bug.cgi?id=88273 + + Reviewed by Tony Chang. + + This patch standardizes the search algorithm the chromium ports + use to figure out which driver to run. We will look in a + chromium location before a webkit location (e.g., in + Source/WebKit/chromium/out before out/) and we will look in the + "legacy" directory (xcodebuild) before the directory ninja uses + (out). + + Unfortunately due to the way the test code is set up testing the + properly requires some duplication of test code. I will fix that + in a followup patch. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + (ChromiumPort): + (ChromiumPort._static_build_path): + (ChromiumPort._build_path): + * Scripts/webkitpy/layout_tests/port/chromium_linux.py: + (ChromiumLinuxPort): + (ChromiumLinuxPort._determine_driver_path_statically): + * Scripts/webkitpy/layout_tests/port/chromium_linux_unittest.py: + (ChromiumLinuxPortTest.test_build_path): + (ChromiumLinuxPortTest): + (ChromiumLinuxPortTest.test_driver_name_option): + (ChromiumLinuxPortTest.path_to_image_diff): + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + (ChromiumMacPort): + * Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py: + (ChromiumMacPortTest.test_build_path): + (ChromiumMacPortTest): + (ChromiumMacPortTest.test_driver_name_option): + (ChromiumMacPortTest.path_to_image_diff): + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + (ChromiumPortTest.test_overrides_and_builder_names): + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + (ChromiumWinPort): + * Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py: + (ChromiumWinTest.test_build_path): + (ChromiumWinTest.test_operating_system): + (ChromiumWinTest): + (ChromiumWinTest.test_driver_name_option): + (ChromiumWinPortTest.path_to_image_diff): + * Scripts/webkitpy/layout_tests/port/port_testcase.py: + (PortTestCase.assert_build_path): + +2012-06-06 Jessie Berlin <jberlin@apple.com> + + Remove very red Windows WebKit2 testers + https://bugs.webkit.org/show_bug.cgi?id=88452 + + Reviewed by Steve Falkenburg. + + Remove the Windows 7 Release WK2 testers so that the hardware can be repurposed. We are + need to focus on getting the WK1 testers green. + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2012-06-06 Dirk Pranke <dpranke@chromium.org> + + get rebaselining tools to kinda work with the skia overrides file + https://bugs.webkit.org/show_bug.cgi?id=88456 + + Reviewed by Ryosuke Niwa. + + Update rebaseline-expectations so that we read in the overrides + when looking for tests to rebaseline, but don't read in the + overrides when we are writing the expectations file back out. + This prevents the overrides from getting written into the main + file. This is kind of a hack but will have to do until we + support multiple expectations files properly. + + * Scripts/webkitpy/tool/commands/rebaseline.py: + (RebaselineExpectations._expectations): + (RebaselineExpectations._update_expectations_file): + (RebaselineExpectations._tests_to_rebaseline): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (test_overrides_are_included_correctly): + +2012-06-06 Dirk Pranke <dpranke@chromium.org> + + webkitpy: two manager_worker_broker_unittest tests are broken + https://bugs.webkit.org/show_bug.cgi?id=88445 + + Reviewed by Ojan Vafai. + + These tests were never updated when we removed the + --worker-model argument, and we were passing 'inline' instead of + 1 (for the number of workers) :(. As a result we were creating + multiprocessing queues unnecessarily and that was failing on cygwin. + + * Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py: + (InterfaceTest.test_managerconnection_is_abstract): + (InterfaceTest.test_workerconnection_is_abstract): + +2012-06-06 Ryosuke Niwa <rniwa@webkit.org> + + REGRESSION(r117789): "webkit-patch rebaseline-expectations" copies contents in skia_test_expectations.txt into test_expectations.txt + https://bugs.webkit.org/show_bug.cgi?id=87406 + + Reviewed by Dirk Pranke. + + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (TestExpectations.__init__): + * Scripts/webkitpy/tool/commands/rebaseline.py: + (RebaselineTest._update_expectations_file): + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (test_rebaseline_does_not_include_overrides): + +2012-06-06 Dirk Pranke <dpranke@chromium.org> + + webkitpy: perf tests unit tests fail on chromium win + https://bugs.webkit.org/show_bug.cgi?id=88279 + + Reviewed by Ryosuke Niwa. + + I'm seeing weird failures running the unit tests in my win32 + checkout, and we don't really expect webpagereplay to work on + win32 anyway, so I'm skipping the import of that module for now + and adding a warning. + + * Scripts/run-perf-tests: + * Scripts/webkitpy/performance_tests/perftest.py: + +2012-06-06 Yong Li <yoli@rim.com> + + Unreviewed. Update my email address in committers.py. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-06 Robert Kroeger <rjkroege@chromium.org> + + Add Robert Kroeger to commiters.py + https://bugs.webkit.org/show_bug.cgi?id=88415 + + Unreviewed. + + * Scripts/webkitpy/common/config/committers.py: + +2012-06-06 Mikhail Pozdnyakov <mikhail.pozdnyakov@intel.com> + + [EFL][DRT] http/tests/globalhistory testcases do not pass + https://bugs.webkit.org/show_bug.cgi?id=82579 + + Reviewed by Csaba Osztrogonác. + + DRT has provided callbacks for ewk_view "global history delegate" signals. + + * DumpRenderTree/efl/DumpRenderTree.cpp: + (isGlobalHistoryTest): Aux function to ident global history testcase. + (createLayoutTestController): + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::createView): + (DumpRenderTreeChrome::onTitleChanged): Handles also some global history testcases. + (DumpRenderTreeChrome::onWebViewNavigatedWithData): New callback function. + (DumpRenderTreeChrome::onWebViewServerRedirect): Ditto. + (DumpRenderTreeChrome::onWebViewClientRedirect): Ditto. + (DumpRenderTreeChrome::onWebViewPopulateVisitedLinks): Ditto. + * DumpRenderTree/efl/DumpRenderTreeChrome.h: + (DumpRenderTreeChrome): + +2012-06-06 János Badics <jbadics@inf.u-szeged.hu> + + [Qt] run-qtwebkit-tests hangs with -j1 + run-qtwebkit-tests used to hang when wk2 API tests were run with -j1 and --timeout. + This could happen due to an uncancelled timer after results were returned. This timer was + started only if --timeout was set. + https://bugs.webkit.org/show_bug.cgi?id=85475 + + Reviewed by Csaba Osztrogonác. + + * Scripts/run-qtwebkit-tests: + (run_test): + +2012-06-06 Michael Brüning <michael.bruning@nokia.com> + + [Qt][WK2] Add preferredMinimumContentsWidth to the viewport info in MiniBrowser. + https://bugs.webkit.org/show_bug.cgi?id=88327 + + Reviewed by Kenneth Rohde Christiansen. + + * MiniBrowser/qt/MiniBrowser.qrc: Added contents_width.png. + * MiniBrowser/qt/icons/contents_width.png: Added. + * MiniBrowser/qt/qml/BrowserWindow.qml: Added button for toggling preferredMinimumContentsWidth. + * MiniBrowser/qt/qml/ViewportInfoItem.qml: Added display of preferredMinimumContentsWidth. + +2012-06-05 Jon Lee <jonlee@apple.com> + + Buildbot fix. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: We lose the type attribute earlier + in the function. Store in a local variable. + (loadBuilderConfig): + +2012-06-05 Jon Lee <jonlee@apple.com> + + Buildbot fix. + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + (loadBuilderConfig): + +2012-06-04 Dirk Pranke <dpranke@chromium.org> + + webkitpy: clean up win-specific path handling and tests + https://bugs.webkit.org/show_bug.cgi?id=88281 + + Reviewed by Adam Barth. + + There was a bunch of inconsistent logic for handling path + conversions for win32 and cygwin paths due to us sometimes + looking at sys.platform and sometimes using mock hosts. This + patch cleans everything up so that we are required to pass + PlatformInfo objects to the path module and stop trying to do + different things when running on cygwin or win32 hosts (except + in the path_unittest module itself). + + This may slightly reduce test coverage for the win32 code paths + but will be a lot easier to follow and maintain. + + * Scripts/webkitpy/common/system/path.py: + (abspath_to_uri): + (_convert_path): + * Scripts/webkitpy/common/system/path_unittest.py: + (AbspathTest.platforminfo): + (AbspathTest.test_abspath_to_uri_cygwin): + (AbspathTest.test_abspath_to_uri_unixy): + (AbspathTest.test_abspath_to_uri_win): + (AbspathTest.test_abspath_to_uri_escaping_unixy): + (AbspathTest.test_abspath_to_uri_escaping_cygwin): + (AbspathTest.test_stop_cygpath_subprocess): + * Scripts/webkitpy/common/system/platforminfo.py: + (PlatformInfo.__init__): + (PlatformInfo.is_cygwin): + * Scripts/webkitpy/common/system/platforminfo_mock.py: + (MockPlatformInfo.is_cygwin): + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.to.show_results_html_file): + * Scripts/webkitpy/layout_tests/port/driver.py: + (Driver.test_to_uri): + (Driver.uri_to_test): + * Scripts/webkitpy/layout_tests/port/driver_unittest.py: + (DriverTest.test_test_to_uri): + (DriverTest.test_uri_to_test): + * Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py: + (MockDRTPortTest.make_port): + (MockDRTTest.input_line): + (MockChromiumDRTTest.test_pixeltest__fails): + * Scripts/webkitpy/layout_tests/port/test.py: + * Scripts/webkitpy/layout_tests/port/win.py: + (WinPort.show_results_html_file): + * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py: + (MainTest.test_unexpected_failures): + (MainTest.test_results_directory_absolute): + (MainTest.test_results_directory_default): + (MainTest.test_results_directory_relative): + +2012-06-05 Jon Lee <jonlee@apple.com> + + Workaround buildbot bug when merging build requests. + https://bugs.webkit.org/show_bug.cgi?id=88158 + + Reviewed by Mark Rowe. + + For expediency, we still want testers to pick the latest build to test, but to ensure + that the builders are reporting the correct revision number, we should let the building bots + run as they normally would. That is, the builder picks the oldest revision, and merges + subsequent requests. Because merged requests get appended to the list of changes for a given + build, the last change in that list is also the latest change. When we used pickLatestBuild + for the builders, this was not the case (it would always report the penultimate change). + + http://trac.buildbot.net/ticket/2309 is tracking the buildbot bug. + + * BuildSlaveSupport/build.webkit.org-config/config.json: Remove the mergeRequests override + for all Apple builders. + * BuildSlaveSupport/build.webkit.org-config/master.cfg: Have only non-building bots pick + the latest build to run. + (loadBuilderConfig): + +2012-06-05 Jessie Berlin <jberlin@apple.com> + + [Win] DumpRenderTree should call resetInternalsObject + https://bugs.webkit.org/show_bug.cgi?id=88346 + + Reviewed by Simon Fraser. + + Invoke it on Windows in the same place it is invoked on Mac. + + * DumpRenderTree/win/DumpRenderTree.cpp: + (resetWebViewToConsistentStateBeforeTesting): + +2012-06-05 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [GTK] Fix two more memory leaks in DRT + https://bugs.webkit.org/show_bug.cgi?id=88255 + + Reviewed by Martin Robinson. + + Fixed memory leaks in GTK's DRT code. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (dumpHistoryItem): webkit_web_history_item_get_target() returns a + g_strdup()'d string. So, use GOwnPtr to manage memory automatically. + * DumpRenderTree/gtk/PixelDumpSupportGtk.cpp: + (createBitmapContextFromWebView): Free the cairo surface. + +2012-06-05 Allan Sandfeld Jensen <allan.jensen@nokia.com> + + [Qt] Building when a top directory is named Source + https://bugs.webkit.org/show_bug.cgi?id=77727 + + Reviewed by Tor Arne Vestbø. + + Change regex to only replace the last instance of OUT_PWD. + + * qmake/mkspecs/features/default_pre.prf: + +2012-06-05 Dongwoo Im <dw.im@samsung.com> + + Add 'isProtocolHandlerRegistered' and 'unregisterProtocolHandler'. + https://bugs.webkit.org/show_bug.cgi?id=73176 + + Reviewed by Adam Barth. + + Two more APIs are added in Custom Scheme Handler specification. + http://dev.w3.org/html5/spec/Overview.html#custom-handlers + One is 'isProtocolHandlerRegistered' to query whether the specific URL + is registered or not. + The other is 'unregisterProtocolHandler' to remove the registered URL. + + * Scripts/webkitperl/FeatureList.pm: Add a macro 'ENABLE_CUSTOM_SCHEME_HANDLER'. + +2012-06-05 Mario Sanchez Prada <msanchez@igalia.com> + + [GTK][WK2] Implement API for Geolocation permission requests in the GTK port + https://bugs.webkit.org/show_bug.cgi?id=83879 + + Reviewed by Carlos Garcia Campos. + + Make minibrowser connect to the new 'permission requests' signal + to allow users handle the Geolocation permission requests. + + * MiniBrowser/gtk/BrowserWindow.c: + (geolocationRequestDialogCallback): Callback for the dialog asking + the user for allowing or not geolocation permission requests. + (webViewDecidePermissionRequest): Launch a dialog to ask the user + whether to allow or deny geolocation permission requests. + (browserWindowConstructed): Connect to 'permission-request' signal. + +2012-06-04 Chase Phillips <cmp@google.com> + + Make a builder group support+expect multiple loads. + https://bugs.webkit.org/show_bug.cgi?id=88260 + + Change BuilderGroup to allow expecting multiple + loads. This allows merging results for a given set + of builders into one group. + + Add a test that verifies that the group count + increments correctly based on successful and failed + list loads. + + Reviewed by Ojan Vafai. + + * TestResultServer/static-dashboards/builders.js: + (BuilderGroup): + (BuilderGroup.prototype.setbuilder): + (BuilderGroup.prototype.append): + (BuilderGroup.prototype.loaded): + (requestBuilderList.xhr.onload): + (requestBuilderList.xhr.onerror): + (onErrorLoadingBuilderList): + (loadBuildersList): + * TestResultServer/static-dashboards/flakiness_dashboard_unittests.js: + (test): + * TestResultServer/static-dashboards/run-unittests.html: + +2012-06-04 Ryosuke Niwa <rniwa@webkit.org> + + Python test fix attempt for Chromium Windows. + + * Scripts/webkitpy/layout_tests/port/driver.py: + (Driver.uri_to_test): + +2012-06-04 Hugo Parente Lima <hugo.lima@openbossa.org> + + Turn LEGACY_VIEWPORT_ADAPTION USE flag into an ENABLE flag. + https://bugs.webkit.org/show_bug.cgi?id=88243 + + Reviewed by Adam Barth. + + * qmake/mkspecs/features/features.prf: + +2012-06-04 Dirk Pranke <dpranke@chromium.org> + + webkitpy.layout_tests.port.server_process_unittest.TestServerProcess.test_basic is flaky + https://bugs.webkit.org/show_bug.cgi?id=88280 + + Unreviewed, build fix. + + * Scripts/webkitpy/layout_tests/port/server_process_unittest.py: + (TestServerProcess.test_basic): + +2012-06-04 Dirk Pranke <dpranke@chromium.org> + + test-webkitpy is hanging under cygwin + https://bugs.webkit.org/show_bug.cgi?id=88269 + + Reviewed by Ryosuke Niwa. + + The 'multiprocessing' module doesn't work correctly under Cygwin yet, + so we need to skip any tests that use it. + + * Scripts/webkitpy/common/system/executive.py: + (Executive.run_in_parallel): + * Scripts/webkitpy/common/system/executive_unittest.py: + (ExecutiveTest.test_run_in_parallel): + +2012-06-04 Dirk Pranke <dpranke@chromium.org> + + test-webkitpy is failing on win32 after r115054 + https://bugs.webkit.org/show_bug.cgi?id=88264 + + Reviewed by Ryosuke Niwa. + + The failing http_server test was improperly suppressed (the + tuple was missing a comma, and so wasn't a tuple at all, just a + string) and so we were skipping *all* tests on win32. The right + way to skip a single test is to disable it inside the test + itself. + + * Scripts/webkitpy/layout_tests/servers/http_server_unittest.py: + (TestHttpServer.test_start_cmd): + * Scripts/webkitpy/test/test_finder.py: + (TestFinder._default_names): + * Scripts/webkitpy/test/main.py: + (Tester.run): Add error message if we don't find any tests to run. + * Scripts/webkitpy/test/main_unittest.py: + + +2012-06-04 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [GTK] Memory leaks in AccessibilityUIElementGtk.cpp + https://bugs.webkit.org/show_bug.cgi?id=88215 + + Reviewed by Martin Robinson. + + Fixed memory leaks in AccessibilityUIElement by using GOwnPtr + for newly allocated strings. + + * DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp: + (attributeSetToString): + (AccessibilityUIElement::allAttributes): + +2012-06-04 Sudarsana Nagineni <sudarsana.nagineni@linux.intel.com> + + [GTK] Memory leaks in DumpRenderTree.cpp + https://bugs.webkit.org/show_bug.cgi?id=88213 + + Reviewed by Martin Robinson. + + Fixed memory leaks in DumpRenderTree. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (appendString): Accepts const gchar* as the second argument. + (dumpFramesAsText): Free the string returned by g_strdup_printf(). + (dumpHistoryItem): Free the string returned by g_uri_parse_scheme(). + +2012-06-04 David Dorwin <ddorwin@chromium.org> + + Enable Chromium media player to instantiate a plugin + https://bugs.webkit.org/show_bug.cgi?id=87399 + + Reviewed by Kent Tamura. + + Adds WebHelperPlugin, an off-screen widget that contains an <object> tag. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::createPopupMenu): + +2012-06-04 Mario Sanchez Prada <msanchez@igalia.com> + + [GTK][WK2] Implement geolocation provider for the GTK port + https://bugs.webkit.org/show_bug.cgi?id=83877 + + Reviewed by Carlos Garcia Campos. + + * gtk/generate-gtkdoc: + (get_webkit2_options): Ignore WebKitGeolocationProvider files. + +2012-06-04 Mikhail Pozdnyakov <mikhail.pozdnyakov@intel.com> + + [EFL] Reset "WebKitTabToLinksPreferenceKey" in DumpRenderTreeChrome::resetDefaultsToConsistentValues + https://bugs.webkit.org/show_bug.cgi?id=87668 + + Reviewed by Ryosuke Niwa. + + Layout test controller "WebKitTabToLinksPreferenceKey" setting should be reset to false + otherwise LayoutTests/fast/html/tab-order.html is failing as it has a link inside the test description which might + be included in focus chain (if "WebKitTabToLinksPreferenceKey" setting is set to true). + + * DumpRenderTree/efl/DumpRenderTreeChrome.cpp: + (DumpRenderTreeChrome::resetDefaultsToConsistentValues): + +2012-06-04 Tomasz Morawski <t.morawski@samsung.com> + + [EFL] Refactor ewk_view_context_paint code. + https://bugs.webkit.org/show_bug.cgi?id=85588 + + Reviewed by Hajime Morita. + + * DumpRenderTree/efl/CMakeLists.txt: Added include directory. + +2012-06-04 Christophe Dumez <christophe.dumez@intel.com> + + [EFL] Compilation warning in DumpRenderTreeView.cpp on 64-Bit + https://bugs.webkit.org/show_bug.cgi?id=87869 + + Reviewed by Andreas Kling. + + Replace %lld by PRId64 macro to print an int64_t value and silent a + compilation warning on 64-Bit. + + * DumpRenderTree/efl/DumpRenderTreeView.cpp: + (onExceededApplicationCacheQuota): + +2012-06-03 Varun Jain <varunjain@google.com> + + [chromium] Add new gesture type (two finger tap) that triggers context menu. + https://bugs.webkit.org/show_bug.cgi?id=88173 + + Reviewed by Adam Barth. + + * DumpRenderTree/chromium/EventSender.cpp: + (EventSender::EventSender): + (EventSender::gestureTwoFingerTap): + (EventSender::gestureEvent): + * DumpRenderTree/chromium/EventSender.h: + (EventSender): + +2012-06-02 Zeno Albisser <zeno@webkit.org> + + Fix and enable WebGL for WebKit2 on Qt. + https://bugs.webkit.org/show_bug.cgi?id=86214 + + Enable WebGL by default for Qt MiniBrowser. + + Reviewed by Noam Rosenthal. + + * MiniBrowser/qt/qml/BrowserWindow.qml: + +2012-06-02 Ryosuke Niwa <rniwa@webkit.org> + + Teach svn-apply how to apply changes in test_expectations.txt to TestExpectations + https://bugs.webkit.org/show_bug.cgi?id=88164 + + Reviewed by Kentaro Hara. + + Just like r74856, adjust git/svn headers from test_expectations.txt to TestExpectations. + Also replace all occurrences of /test_expectations.txt: by /TestExpectations: in change log entries. + + * Scripts/VCSUtils.pm: + (adjustPathForRecentRenamings): + (fixChangeLogPatch): + +2012-06-01 Ryosuke Niwa <rniwa@webkit.org> + + Rename test_expectations.txt to TestExpectations + https://bugs.webkit.org/show_bug.cgi?id=86690 + + Reviewed by Dirk Pranke. + + Make webkitpy aware of both test_expectations.txt and TestExpectations while we rename files. + We can the code to read test_expectations.txt once we've successfully transitioned. + + * Scripts/webkitpy/layout_tests/models/test_expectations.py: + (TestExpectationParser._check_path_does_not_exist): + (TestExpectationParser._tokenize): + (TestExpectations): Removed TEST_LIST, which is not used anywhere. + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.path_to_test_expectations_file): Moved from WebKitPort and ChromiumPort. Returns the path to + test_expectations.txt if one exists and the path to TestExpectations otherwise. + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + (PortTest.test_virtual_methods): path_to_test_expectations_file and test_expectations are no longer + virtual. + * Scripts/webkitpy/layout_tests/port/chromium.py: + (ChromiumPort.path_from_chromium_base): + * Scripts/webkitpy/layout_tests/port/chromium_android.py: + (ChromiumAndroidPort.test_expectations): + * Scripts/webkitpy/layout_tests/port/test.py: + (add_unit_tests_to_mock_filesystem): Use TestExpectations instead of test_expectations.txt. + (TestPort.__init__): + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitPort.baseline_search_path): + (WebKitPort.test_expectations): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: Added some test cases. We should move these + tests to base as a follow up. + (WebKitPortTest.test_path_to_test_expectations_file): + (test_test_expectations): + (test_legacy_test_expectations): + * Scripts/webkitpy/style/checker.py: + (CheckerDispatcher.should_skip_without_warning): Replace the check for legacy drt_expectations.txt + with one for TestExpectations. + * Scripts/webkitpy/style/checkers/test_expectations.py: + (TestExpectationsChecker): Accept both test_expectations.txt and TestExpectations in warning outputs. + * Scripts/webkitpy/style/checkers/test_expectations_unittest.py: + (TestExpectationsTestCase._expect_port_for_expectations_path): Test both TestExpectations and + test_expectations.txt. + (TestExpectationsTestCase.test_determine_port_from_expectations_path): + (TestExpectationsTestCase.assert_lines_lint): + * Scripts/webkitpy/tool/commands/queries.py: + (PrintExpectations.__init__): + * Scripts/webkitpy/tool/commands/rebaseline.py: + (RebaselineExpectations): + * Scripts/webkitpy/tool/steps/commit.py: + (Commit._check_test_expectations): + * Scripts/webkitpy/tool/steps/commit_unittest.py: + (CommitTest._test_check_test_expectations): Extracted from test_check_test_expectations. + (CommitTest.test_check_test_expectations): For TestExpectations. + (CommitTest.test_check_legacy_test_expectations): For test_expectations.txt + * TestResultServer/static-dashboards/dashboard_base.js: + (requestExpectationsFile): Look for TestExpectations first, and fallback to test_expectations.txt. + Error only when neither exists. + * TestResultServer/static-dashboards/flakiness_dashboard.js: + (processMissingAndExtraExpectations): + (htmlForTestsWithExpectationsButNoFailures): + * TestResultServer/static-dashboards/flakiness_dashboard_unittests.js: + +2012-06-01 Xianzhu Wang <wangxianzhu@chromium.org> + + Remove dependency from ImageDiff to WTF + https://bugs.webkit.org/show_bug.cgi?id=88147 + + Reviewed by Adam Barth. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + +2012-06-01 Dirk Pranke <dpranke@chromium.org> + + NRWT seems to leak (more?) temp dirs + https://bugs.webkit.org/show_bug.cgi?id=88126 + + Re-land r119297 with chromium fix (weren't calling the + super() method if not in --test-shell mode in start(). + Add unit tests to chromium_unittest as well to check. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + (ChromiumDriver.start): + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitDriver.__del__): + (WebKitDriver._start): + (WebKitDriver.run_test): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (WebKitDriverTest.test_check_for_driver_crash): + (WebKitDriverTest.test_stop_cleans_up_properly): + (WebKitDriverTest): + (WebKitDriverTest.test_two_starts_cleans_up_properly): + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + (ChromiumDriverTest.test_stop_cleans_up_properly): + (ChromiumDriverTest.test_two_starts_cleans_up_properly): + +2012-06-01 Tim Horton <timothy_horton@apple.com> + + Lots of "failed download-built-product" on Apple bots + https://bugs.webkit.org/show_bug.cgi?id=88158 + + Reviewed by Jessie Berlin. + + Disable mergeRequests on all Apple builders. This is a speculative fix. + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2012-06-01 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r119297. + http://trac.webkit.org/changeset/119297 + https://bugs.webkit.org/show_bug.cgi?id=88156 + + May have broken Chromium bots (Requested by rniwa on #webkit). + + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitDriver.__del__): + (WebKitDriver.run_test): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (WebKitDriverTest.test_check_for_driver_crash): + (WebKitDriverTest.test_stop_cleans_up_properly): + +2012-06-01 Dirk Pranke <dpranke@chromium.org> + + nrwt seems to leak tmpdirs + https://bugs.webkit.org/show_bug.cgi?id=88126 + + Reviewed by Ojan Vafai. + + Fix leak possibly introduced in r118979 - we now will + make sure we clean up any stale temp directories during the + start routine and attempt to clean up again in __del__. It + turns out that asserting in __del__ logs a message but is + caught by the runtime, so it's mostly useless. + + * Scripts/webkitpy/layout_tests/port/webkit.py: + (WebKitDriver.__del__): + (WebKitDriver._start): + (WebKitDriver.run_test): + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: + (WebKitDriverTest.test_check_for_driver_crash): + (WebKitDriverTest.test_stop_cleans_up_properly): + (WebKitDriverTest): + (WebKitDriverTest.test_two_starts_cleans_up_properly): + +2012-06-01 Michael Saboff <msaboff@apple.com> + + WebFrame::_stringByEvaluatingJavaScriptFromString methods don't handle nil string + https://bugs.webkit.org/show_bug.cgi?id=88109 + + Reviewed by Geoffrey Garen. + + Additional test case. + + * TestWebKitAPI/Tests/mac/StringByEvaluatingJavaScriptFromString.mm: + (TestWebKitAPI::TEST): + 2012-06-01 Simon Hausmann <simon.hausmann@nokia.com> [Qt] Use -Werror only in developer builds diff --git a/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp b/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp index edae3aaeb..1f8d2faab 100644 --- a/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp +++ b/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp @@ -56,21 +56,22 @@ 'type': 'executable', 'dependencies': [ '<(chromium_src_dir)/webkit/support/webkit_support.gyp:webkit_support_gfx', - '<(source_dir)/WTF/WTF.gyp/WTF.gyp:wtf', ], 'include_dirs': [ - '<(source_dir)/JavaScriptCore', '<(DEPTH)', ], 'sources': [ '<(tools_dir)/DumpRenderTree/chromium/ImageDiff.cpp', ], 'conditions': [ - ['OS=="android"', { + ['OS=="android" and android_build_type==0', { # The Chromium Android port will compare images on host rather # than target (a device or emulator) for performance reasons. 'toolsets': ['host'], }], + ['OS=="android" and android_build_type!=0', { + 'type': 'none', + }], ], }, { @@ -95,7 +96,6 @@ 'include_dirs': [ '<(chromium_src_dir)', '<(source_dir)/WebKit/chromium/public', - '<(source_dir)/JavaScriptCore', '<(DEPTH)', ], 'defines': [ @@ -243,7 +243,6 @@ ['OS=="android"', { 'type': 'shared_library', 'dependencies': [ - 'ImageDiff#host', '<(chromium_src_dir)/base/base.gyp:test_support_base', '<(chromium_src_dir)/tools/android/forwarder/forwarder.gyp:forwarder', '<(chromium_src_dir)/testing/android/native_test.gyp:native_test_native_code', @@ -265,6 +264,11 @@ ['exclude', 'Android\\.cpp$'], ], }], + ['OS=="android" and android_build_type==0', { + 'dependencies': [ + 'ImageDiff#host', + ], + }], ['inside_chromium_build==1 and component=="shared_library"', { 'sources': [ '<(source_dir)/WebKit/chromium/src/ChromiumCurrentTime.cpp', @@ -403,38 +407,51 @@ }], ['OS=="android"', { # Wrap libDumpRenderTree.so into an android apk for execution. - # See <(chromium_src_dir)/base/base.gyp for TODO(jrg)s about this strategy. 'targets': [{ 'target_name': 'DumpRenderTree_apk', 'type': 'none', 'dependencies': [ + '<(chromium_src_dir)/base/base.gyp:base_java', + '<(chromium_src_dir)/net/net.gyp:net_java', + '<(chromium_src_dir)/media/media.gyp:media_java', 'DumpRenderTree', ], + 'variables': { + 'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)DumpRenderTree<(SHARED_LIB_SUFFIX)', + 'input_jars_paths': [ + '<(PRODUCT_DIR)/lib.java/chromium_base.jar', + '<(PRODUCT_DIR)/lib.java/chromium_net.jar', + '<(PRODUCT_DIR)/lib.java/chromium_media.jar', + ], + }, + # Part of the following was copied from <(chromium_src_dir)/build/apk_test.gpyi. + # Not including it because gyp include doesn't support variable in path or under + # conditions. And we also have some different requirements. 'actions': [{ - # Generate apk files (including source and antfile) from - # a template, and builds them. - 'action_name': 'generate_and_build', + 'action_name': 'apk_DumpRenderTree', + 'message': 'Building DumpRenderTree test apk.', 'inputs': [ + '<(chromium_src_dir)/testing/android/AndroidManifest.xml', '<(chromium_src_dir)/testing/android/generate_native_test.py', - '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)DumpRenderTree<(SHARED_LIB_SUFFIX)', - # FIXME: Build the jar for native tests with SDK. - # For now we are using Android.mk to build the apk. + '<(input_shlib_path)', + '<@(input_jars_paths)', ], 'outputs': [ - '<(PRODUCT_DIR)/DumpRenderTree_apk/ChromeNativeTests-debug.apk', + '<(PRODUCT_DIR)/DumpRenderTree_apk/DumpRenderTree-debug.apk', ], 'action': [ '<(chromium_src_dir)/testing/android/generate_native_test.py', '--native_library', - '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)DumpRenderTree<(SHARED_LIB_SUFFIX)', - # FIXME: Build the jar for native tests with SDK. - # '--jar', - # 'foo/bar.jar', + '<(input_shlib_path)', + '--jars', + '"<@(input_jars_paths)"', '--output', '<(PRODUCT_DIR)/DumpRenderTree_apk', '--ant-args', '-DPRODUCT_DIR=<(ant_build_out)', - '--ant-compile' + '--ant-compile', + '--app_abi', + '<(android_app_abi)', ], }], }], diff --git a/Tools/DumpRenderTree/DumpRenderTree.gypi b/Tools/DumpRenderTree/DumpRenderTree.gypi index e8d88be74..5412a199e 100644 --- a/Tools/DumpRenderTree/DumpRenderTree.gypi +++ b/Tools/DumpRenderTree/DumpRenderTree.gypi @@ -28,6 +28,8 @@ 'chromium/MockWebPrerenderingSupport.h', 'chromium/MockWebSpeechInputController.cpp', 'chromium/MockWebSpeechInputController.h', + 'chromium/MockWebSpeechRecognizer.cpp', + 'chromium/MockWebSpeechRecognizer.h', 'chromium/NotificationPresenter.h', 'chromium/NotificationPresenter.cpp', 'chromium/Task.h', diff --git a/Tools/DumpRenderTree/LayoutTestController.cpp b/Tools/DumpRenderTree/LayoutTestController.cpp index 2fa80cf67..cd01d1c3b 100644 --- a/Tools/DumpRenderTree/LayoutTestController.cpp +++ b/Tools/DumpRenderTree/LayoutTestController.cpp @@ -96,6 +96,7 @@ LayoutTestController::LayoutTestController(const std::string& testPathOrURL, con , m_customFullScreenBehavior(false) , m_testPathOrURL(testPathOrURL) , m_expectedPixelHash(expectedPixelHash) + , m_titleTextDirection("ltr") { } @@ -662,22 +663,6 @@ static JSValueRef findStringCallback(JSContextRef context, JSObjectRef function, return JSValueMakeBoolean(context, controller->findString(context, target.get(), options)); } -static JSValueRef counterValueForElementByIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[0], exception)); - if (*exception) - return JSValueMakeUndefined(context); - - LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); - JSRetainPtr<JSStringRef> counterValue(controller->counterValueForElementById(elementId.get())); - if (!counterValue.get()) - return JSValueMakeUndefined(context); - return JSValueMakeString(context, counterValue.get()); -} - static JSValueRef goBackCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); @@ -2174,6 +2159,13 @@ static JSValueRef getPlatformNameCallback(JSContextRef context, JSObjectRef this } #endif +static JSValueRef getTitleTextDirectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + JSRetainPtr<JSStringRef> titleDirection(Adopt, JSStringCreateWithUTF8CString(controller->titleTextDirection().c_str())); + return JSValueMakeString(context, titleDirection.get()); +} + static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) { LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); @@ -2244,6 +2236,8 @@ static void layoutTestControllerObjectFinalize(JSObjectRef object) void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) { JSRetainPtr<JSStringRef> layoutTestContollerStr(Adopt, JSStringCreateWithUTF8CString("layoutTestController")); + JSRetainPtr<JSStringRef> testRunnerStr(Adopt, JSStringCreateWithUTF8CString("testRunner")); + ref(); ref(); JSClassRef classRef = getJSClass(); @@ -2251,6 +2245,7 @@ void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef wi JSClassRelease(classRef); JSObjectSetProperty(context, windowObject, layoutTestContollerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); + JSObjectSetProperty(context, windowObject, testRunnerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); } JSClassRef LayoutTestController::getJSClass() @@ -2274,6 +2269,7 @@ JSStaticValue* LayoutTestController::staticValues() #if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(WIN) { "platformName", getPlatformNameCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #endif + { "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0, 0 } }; return staticValues; @@ -2332,7 +2328,6 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "evaluateScriptInIsolatedWorld", evaluateScriptInIsolatedWorldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "findString", findStringCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "counterValueForElementById", counterValueForElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "originsWithApplicationCache", originsWithApplicationCacheCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "goBack", goBackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "grantDesktopNotificationPermission", grantDesktopNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/Tools/DumpRenderTree/LayoutTestController.h b/Tools/DumpRenderTree/LayoutTestController.h index 640d1c1d4..54ca9278a 100644 --- a/Tools/DumpRenderTree/LayoutTestController.h +++ b/Tools/DumpRenderTree/LayoutTestController.h @@ -56,7 +56,6 @@ public: bool callShouldCloseOnWebView(); JSStringRef copyDecodedHostName(JSStringRef name); JSStringRef copyEncodedHostName(JSStringRef name); - JSRetainPtr<JSStringRef> counterValueForElementById(JSStringRef id); void deliverWebIntent(JSStringRef action, JSStringRef type, JSStringRef data); void disableImageLoading(); void dispatchPendingLoadRequests(); @@ -360,6 +359,8 @@ public: void setMinimumTimerInterval(double); void setTextDirection(JSStringRef); + const std::string& titleTextDirection() const { return m_titleTextDirection; } + void setTitleTextDirection(const std::string& direction) { m_titleTextDirection = direction; } // Custom full screen behavior. void setHasCustomFullScreenBehavior(bool value) { m_customFullScreenBehavior = value; } @@ -424,6 +425,7 @@ private: std::string m_authenticationPassword; std::string m_testPathOrURL; std::string m_expectedPixelHash; // empty string if no hash + std::string m_titleTextDirection; std::set<std::string> m_willSendRequestClearHeaders; diff --git a/Tools/DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp b/Tools/DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp index 4f043d962..ceadb7a63 100644 --- a/Tools/DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp +++ b/Tools/DumpRenderTree/blackberry/LayoutTestControllerBlackBerry.cpp @@ -429,21 +429,6 @@ void LayoutTestController::disableImageLoading() BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->settings()->setLoadsImagesAutomatically(false); } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - String idStr = jsStringRefToWebCoreString(id); - WebCore::Element* coreElement = mainFrame->document()->getElementById(AtomicString(idStr)); - if (!coreElement) - return 0; - - CString counterValueStr = counterValueForElement(coreElement).utf8(); - if (counterValueStr.isNull()) - return 0; - - JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithUTF8CString(counterValueStr.data())); - return counterValue; -} - void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value) { if (!mainFrame) diff --git a/Tools/DumpRenderTree/chromium/EventSender.cpp b/Tools/DumpRenderTree/chromium/EventSender.cpp index 05e4eb83f..47bec2a71 100644 --- a/Tools/DumpRenderTree/chromium/EventSender.cpp +++ b/Tools/DumpRenderTree/chromium/EventSender.cpp @@ -287,6 +287,7 @@ EventSender::EventSender(TestShell* shell) bindMethod("gestureScrollUpdate", &EventSender::gestureScrollUpdate); bindMethod("gestureTap", &EventSender::gestureTap); bindMethod("gestureLongPress", &EventSender::gestureLongPress); + bindMethod("gestureTwoFingerTap", &EventSender::gestureTwoFingerTap); bindMethod("zoomPageIn", &EventSender::zoomPageIn); bindMethod("zoomPageOut", &EventSender::zoomPageOut); bindMethod("scalePageBy", &EventSender::scalePageBy); @@ -1117,6 +1118,12 @@ void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* gestureEvent(WebInputEvent::GestureLongPress, arguments); } +void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVariant* result) +{ + result->setNull(); + gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments); +} + void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppVariant* result) { result->setNull(); @@ -1170,6 +1177,10 @@ void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& event.x = point.x; event.y = point.y; break; + case WebInputEvent::GestureTwoFingerTap: + event.x = point.x; + event.y = point.y; + break; default: ASSERT_NOT_REACHED(); } diff --git a/Tools/DumpRenderTree/chromium/EventSender.h b/Tools/DumpRenderTree/chromium/EventSender.h index bc8a6baa0..9de2f760b 100644 --- a/Tools/DumpRenderTree/chromium/EventSender.h +++ b/Tools/DumpRenderTree/chromium/EventSender.h @@ -105,6 +105,7 @@ public: void gestureScrollUpdate(const CppArgumentList&, CppVariant*); void gestureTap(const CppArgumentList&, CppVariant*); void gestureLongPress(const CppArgumentList&, CppVariant*); + void gestureTwoFingerTap(const CppArgumentList&, CppVariant*); void gestureEvent(WebKit::WebInputEvent::Type, const CppArgumentList&); // Unimplemented stubs diff --git a/Tools/DumpRenderTree/chromium/ImageDiff.cpp b/Tools/DumpRenderTree/chromium/ImageDiff.cpp index 966554bab..906813d9c 100644 --- a/Tools/DumpRenderTree/chromium/ImageDiff.cpp +++ b/Tools/DumpRenderTree/chromium/ImageDiff.cpp @@ -34,8 +34,6 @@ // The exact format of this tool's output to stdout is important, to match // what the run-webkit-tests script expects. -#include "config.h" - #include "webkit/support/webkit_support_gfx.h" #include <algorithm> #include <iterator> @@ -44,12 +42,13 @@ #include <string.h> #include <vector> -#if OS(WINDOWS) +#if defined(_WIN32) #include <windows.h> #define PATH_MAX MAX_PATH +#define strtok_r strtok_s #endif -// Define macro here to make ImageDiff independent of JavaScriptCore. +// Define macro here to make ImageDiff independent of WTF. #ifdef NDEBUG #define ASSERT(assertion) do { } while (0) #else @@ -342,13 +341,8 @@ int untestedCompareImages(ImageComparisonProc comparator) while (fgets(buffer, sizeof(buffer), stdin)) { if (!strncmp("Content-length: ", buffer, 16)) { char* context; -#if OS(WINDOWS) - strtok_s(buffer, " ", &context); - int imageSize = strtol(strtok_s(0, " ", &context), 0, 10); -#else strtok_r(buffer, " ", &context); int imageSize = strtol(strtok_r(0, " ", &context), 0, 10); -#endif bool success = false; if (imageSize > 0 && !actualImage.hasImage()) { diff --git a/Tools/DumpRenderTree/chromium/LayoutTestController.cpp b/Tools/DumpRenderTree/chromium/LayoutTestController.cpp index c739143e0..120197e25 100644 --- a/Tools/DumpRenderTree/chromium/LayoutTestController.cpp +++ b/Tools/DumpRenderTree/chromium/LayoutTestController.cpp @@ -34,6 +34,7 @@ #include "DRTDevToolsAgent.h" #include "MockWebSpeechInputController.h" +#include "MockWebSpeechRecognizer.h" #include "TestShell.h" #include "WebAnimationController.h" #include "WebBindings.h" @@ -77,6 +78,10 @@ #include <wtf/OwnArrayPtr.h> #endif +#if OS(LINUX) || OS(ANDROID) +#include "linux/WebFontRendering.h" +#endif + using namespace WebCore; using namespace WebKit; using namespace std; @@ -110,12 +115,15 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("addMockSpeechInputResult", &LayoutTestController::addMockSpeechInputResult); bindMethod("setMockSpeechInputDumpRect", &LayoutTestController::setMockSpeechInputDumpRect); #endif +#if ENABLE(SCRIPTED_SPEECH) + bindMethod("addMockSpeechRecognitionResult", &LayoutTestController::addMockSpeechRecognitionResult); + bindMethod("setMockSpeechRecognitionError", &LayoutTestController::setMockSpeechRecognitionError); +#endif bindMethod("addOriginAccessWhitelistEntry", &LayoutTestController::addOriginAccessWhitelistEntry); bindMethod("addUserScript", &LayoutTestController::addUserScript); bindMethod("addUserStyleSheet", &LayoutTestController::addUserStyleSheet); bindMethod("clearAllDatabases", &LayoutTestController::clearAllDatabases); bindMethod("closeWebInspector", &LayoutTestController::closeWebInspector); - bindMethod("counterValueForElementById", &LayoutTestController::counterValueForElementById); #if ENABLE(POINTER_LOCK) bindMethod("didLosePointerLock", &LayoutTestController::didLosePointerLock); #endif @@ -211,6 +219,7 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("setPrinting", &LayoutTestController::setPrinting); bindMethod("setScrollbarPolicy", &LayoutTestController::setScrollbarPolicy); bindMethod("setSelectTrailingWhitespaceEnabled", &LayoutTestController::setSelectTrailingWhitespaceEnabled); + bindMethod("setTextSubpixelPositioning", &LayoutTestController::setTextSubpixelPositioning); bindMethod("setSmartInsertDeleteEnabled", &LayoutTestController::setSmartInsertDeleteEnabled); bindMethod("setStopProvisionalFrameLoads", &LayoutTestController::setStopProvisionalFrameLoads); bindMethod("setTabKeyCyclesThroughElements", &LayoutTestController::setTabKeyCyclesThroughElements); @@ -692,6 +701,9 @@ void LayoutTestController::reset() m_taskList.revokeAll(); m_shouldStayOnPageAfterHandlingBeforeUnload = false; m_hasCustomFullScreenBehavior = false; +#if OS(LINUX) || OS(ANDROID) + WebFontRendering::setSubpixelPositioning(false); +#endif } void LayoutTestController::locationChangeDone() @@ -1644,20 +1656,6 @@ void LayoutTestController::setPOSIXLocale(const CppArgumentList& arguments, CppV setlocale(LC_ALL, arguments[0].toString().c_str()); } -void LayoutTestController::counterValueForElementById(const CppArgumentList& arguments, CppVariant* result) -{ - result->setNull(); - if (arguments.size() < 1 || !arguments[0].isString()) - return; - WebFrame* frame = m_shell->webView()->mainFrame(); - if (!frame) - return; - WebString counterValue = frame->counterValueForElementById(cppVariantToWebString(arguments[0])); - if (counterValue.isNull()) - return; - result->set(counterValue.utf8()); -} - // Parse a single argument. The method returns true if there is an argument that // is a number or if there is no argument at all. It returns false only if there // is some argument that is not a number. The value parameter is filled with the @@ -1874,7 +1872,15 @@ void LayoutTestController::setMockDeviceOrientation(const CppArgumentList& argum if (arguments.size() < 6 || !arguments[0].isBool() || !arguments[1].isNumber() || !arguments[2].isBool() || !arguments[3].isNumber() || !arguments[4].isBool() || !arguments[5].isNumber()) return; - WebDeviceOrientation orientation(arguments[0].toBoolean(), arguments[1].toDouble(), arguments[2].toBoolean(), arguments[3].toDouble(), arguments[4].toBoolean(), arguments[5].toDouble()); + WebDeviceOrientation orientation; + orientation.setNull(false); + if (arguments[0].toBoolean()) + orientation.setAlpha(arguments[1].toDouble()); + if (arguments[2].toBoolean()) + orientation.setBeta(arguments[3].toDouble()); + if (arguments[4].toBoolean()) + orientation.setGamma(arguments[5].toDouble()); + // Note that we only call setOrientation on the main page's mock since this is all that the // tests require. If necessary, we could get a list of WebViewHosts from the TestShell and // call setOrientation on each DeviceOrientationClientMock. @@ -1940,6 +1946,28 @@ void LayoutTestController::setMockSpeechInputDumpRect(const CppArgumentList& arg } #endif +#if ENABLE(SCRIPTED_SPEECH) +void LayoutTestController::addMockSpeechRecognitionResult(const CppArgumentList& arguments, CppVariant* result) +{ + result->setNull(); + if (arguments.size() < 2 || !arguments[0].isString() || !arguments[1].isNumber()) + return; + + if (MockWebSpeechRecognizer* recognizer = m_shell->webViewHost()->mockSpeechRecognizer()) + recognizer->addMockResult(cppVariantToWebString(arguments[0]), arguments[1].toDouble()); +} + +void LayoutTestController::setMockSpeechRecognitionError(const CppArgumentList& arguments, CppVariant* result) +{ + result->setNull(); + if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isString()) + return; + + if (MockWebSpeechRecognizer* recognizer = m_shell->webViewHost()->mockSpeechRecognizer()) + recognizer->setError(arguments[0].toInt32(), cppVariantToWebString(arguments[1])); +} +#endif + void LayoutTestController::startSpeechInput(const CppArgumentList& arguments, CppVariant* result) { result->setNull(); @@ -2159,9 +2187,20 @@ void LayoutTestController::deliverWebIntent(const CppArgumentList& arguments, Cp WebSerializedScriptValue serializedData = WebSerializedScriptValue::serialize( v8::String::New(data.data(), data.length())); - WebIntent intent(action, type, serializedData.toString()); + WebIntent intent = WebIntent::create(action, type, serializedData.toString(), WebVector<WebString>(), WebVector<WebString>()); + + m_shell->webView()->mainFrame()->deliverIntent(intent, 0, m_intentClient.get()); +} - m_shell->webView()->mainFrame()->deliverIntent(intent, m_intentClient.get()); +void LayoutTestController::setTextSubpixelPositioning(const CppArgumentList& arguments, CppVariant* result) +{ +#if OS(LINUX) || OS(ANDROID) + // Since FontConfig doesn't provide a variable to control subpixel positioning, we'll fall back + // to setting it globally for all fonts. + if (arguments.size() > 0 && arguments[0].isBool()) + WebFontRendering::setSubpixelPositioning(arguments[0].value.boolValue); +#endif + result->setNull(); } void LayoutTestController::setPluginsEnabled(const CppArgumentList& arguments, CppVariant* result) diff --git a/Tools/DumpRenderTree/chromium/LayoutTestController.h b/Tools/DumpRenderTree/chromium/LayoutTestController.h index 37978657e..5a8729388 100644 --- a/Tools/DumpRenderTree/chromium/LayoutTestController.h +++ b/Tools/DumpRenderTree/chromium/LayoutTestController.h @@ -324,9 +324,6 @@ public: // Resets between tests. void setPOSIXLocale(const CppArgumentList&, CppVariant*); - // Gets the value of the counter in the element specified by its ID. - void counterValueForElementById(const CppArgumentList&, CppVariant*); - // Causes layout to happen as if targetted to printed pages. void setPrinting(const CppArgumentList&, CppVariant*); @@ -375,6 +372,10 @@ public: void addMockSpeechInputResult(const CppArgumentList&, CppVariant*); void setMockSpeechInputDumpRect(const CppArgumentList&, CppVariant*); #endif +#if ENABLE(SCRIPTED_SPEECH) + void addMockSpeechRecognitionResult(const CppArgumentList&, CppVariant*); + void setMockSpeechRecognitionError(const CppArgumentList&, CppVariant*); +#endif void startSpeechInput(const CppArgumentList&, CppVariant*); void layerTreeAsText(const CppArgumentList& args, CppVariant* result); @@ -444,6 +445,13 @@ public: // Cause the web intent to be delivered to this context. void deliverWebIntent(const CppArgumentList&, CppVariant*); + // Enables or disables subpixel positioning (i.e. fractional X positions for + // glyphs) in text rendering on Linux. Since this method changes global + // settings, tests that call it must use their own custom font family for + // all text that they render. If not, an already-cached style will be used, + // resulting in the changed setting being ignored. + void setTextSubpixelPositioning(const CppArgumentList&, CppVariant*); + public: // The following methods are not exposed to JavaScript. void setWorkQueueFrozen(bool frozen) { m_workQueue.setFrozen(frozen); } diff --git a/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.cpp b/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.cpp new file mode 100644 index 000000000..b53e1701f --- /dev/null +++ b/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MockWebSpeechRecognizer.h" + +#if ENABLE(SCRIPTED_SPEECH) + +#include "WebSpeechRecognitionResult.h" +#include "WebSpeechRecognizerClient.h" + +using namespace WebKit; + +namespace { + +// Task class for calling a client function that does not take any parameters. +typedef void (WebSpeechRecognizerClient::*ClientFunctionPointer)(const WebSpeechRecognitionHandle&); +class ClientCallTask : public MethodTask<MockWebSpeechRecognizer> { +public: + ClientCallTask(MockWebSpeechRecognizer* mock, ClientFunctionPointer function) + : MethodTask<MockWebSpeechRecognizer>(mock) + , m_function(function) + { + } + + virtual void runIfValid() OVERRIDE { (m_object->client()->*m_function)(m_object->handle()); } + +private: + ClientFunctionPointer m_function; +}; + +// Task for delivering a result event. +class ResultTask : public MethodTask<MockWebSpeechRecognizer> { +public: + ResultTask(MockWebSpeechRecognizer* mock, const WebString transcript, float confidence) + : MethodTask<MockWebSpeechRecognizer>(mock) + , m_transcript(transcript) + , m_confidence(confidence) + { + } + + virtual void runIfValid() OVERRIDE + { + WebVector<WebString> transcripts(static_cast<size_t>(1)); + WebVector<float> confidences(static_cast<size_t>(1)); + transcripts[0] = m_transcript; + confidences[0] = m_confidence; + WebSpeechRecognitionResult res; + res.assign(transcripts, confidences, true); + + m_object->client()->didReceiveResult(m_object->handle(), res, 0, WebVector<WebSpeechRecognitionResult>()); + } + +private: + WebString m_transcript; + float m_confidence; +}; + +// Task for delivering a nomatch event. +class NoMatchTask : public MethodTask<MockWebSpeechRecognizer> { +public: + NoMatchTask(MockWebSpeechRecognizer* mock) : MethodTask<MockWebSpeechRecognizer>(mock) { } + virtual void runIfValid() OVERRIDE { m_object->client()->didReceiveNoMatch(m_object->handle(), WebSpeechRecognitionResult()); } +}; + +// Task for delivering an error event. +class ErrorTask : public MethodTask<MockWebSpeechRecognizer> { +public: + ErrorTask(MockWebSpeechRecognizer* mock, int code, const WebString& message) + : MethodTask<MockWebSpeechRecognizer>(mock) + , m_code(code) + , m_message(message) + { + } + + virtual void runIfValid() OVERRIDE { m_object->client()->didReceiveError(m_object->handle(), m_message, static_cast<WebSpeechRecognizerClient::ErrorCode>(m_code)); } + +private: + int m_code; + WebString m_message; +}; + +} // namespace + +PassOwnPtr<MockWebSpeechRecognizer> MockWebSpeechRecognizer::create() +{ + return adoptPtr(new MockWebSpeechRecognizer()); +} + +void MockWebSpeechRecognizer::start(const WebSpeechRecognitionHandle& handle, const WebSpeechRecognitionParams& params, WebSpeechRecognizerClient* client) +{ + m_handle = handle; + m_client = client; + + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didStart)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didStartAudio)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didStartSound)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didStartSpeech)); + + if (!m_mockTranscripts.isEmpty()) { + ASSERT(m_mockTranscripts.size() == m_mockConfidences.size()); + + for (size_t i = 0; i < m_mockTranscripts.size(); ++i) + postTask(new ResultTask(this, m_mockTranscripts[i], m_mockConfidences[i])); + + m_mockTranscripts.clear(); + m_mockConfidences.clear(); + } else + postTask(new NoMatchTask(this)); + + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didEndSpeech)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didEndSound)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didEndAudio)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didEnd)); +} + +void MockWebSpeechRecognizer::stop(const WebSpeechRecognitionHandle& handle, WebSpeechRecognizerClient* client) +{ + m_handle = handle; + m_client = client; + + // FIXME: Implement. + ASSERT_NOT_REACHED(); +} + +void MockWebSpeechRecognizer::abort(const WebSpeechRecognitionHandle& handle, WebSpeechRecognizerClient* client) +{ + m_handle = handle; + m_client = client; + + // FIXME: Implement. + ASSERT_NOT_REACHED(); +} + +void MockWebSpeechRecognizer::addMockResult(const WebString& transcript, float confidence) +{ + m_mockTranscripts.append(transcript); + m_mockConfidences.append(confidence); +} + +void MockWebSpeechRecognizer::setError(int code, const WebString& message) +{ + m_taskList.revokeAll(); + postTask(new ErrorTask(this, code, message)); + postTask(new ClientCallTask(this, &WebSpeechRecognizerClient::didEnd)); +} + +MockWebSpeechRecognizer::MockWebSpeechRecognizer() +{ +} + +MockWebSpeechRecognizer::~MockWebSpeechRecognizer() +{ +} + + +#endif // ENABLE(SCRIPTED_SPEECH) diff --git a/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.h b/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.h new file mode 100644 index 000000000..939497686 --- /dev/null +++ b/Tools/DumpRenderTree/chromium/MockWebSpeechRecognizer.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MockWebSpeechRecognizer_h +#define MockWebSpeechRecognizer_h + +#if ENABLE(SCRIPTED_SPEECH) + +#include "Task.h" +#include "WebSpeechRecognizer.h" +#include <wtf/Compiler.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> + +namespace WebKit { +class WebSpeechRecognitionHandle; +class WebSpeechRecognitionParams; +class WebSpeechRecognizerClient; +} + +class MockWebSpeechRecognizer : public WebKit::WebSpeechRecognizer { +public: + static PassOwnPtr<MockWebSpeechRecognizer> create(); + ~MockWebSpeechRecognizer(); + + // WebSpeechRecognizer implementation: + virtual void start(const WebKit::WebSpeechRecognitionHandle&, const WebKit::WebSpeechRecognitionParams&, WebKit::WebSpeechRecognizerClient*) OVERRIDE; + virtual void stop(const WebKit::WebSpeechRecognitionHandle&, WebKit::WebSpeechRecognizerClient*) OVERRIDE; + virtual void abort(const WebKit::WebSpeechRecognitionHandle&, WebKit::WebSpeechRecognizerClient*) OVERRIDE; + + // Methods accessed by layout tests: + void addMockResult(const WebKit::WebString& transcript, float confidence); + void setError(int code, const WebKit::WebString& message); + + TaskList* taskList() { return &m_taskList; } + WebKit::WebSpeechRecognizerClient* client() { return m_client; } + WebKit::WebSpeechRecognitionHandle& handle() { return m_handle; } + +private: + MockWebSpeechRecognizer(); + + TaskList m_taskList; + WebKit::WebSpeechRecognitionHandle m_handle; + WebKit::WebSpeechRecognizerClient* m_client; + Vector<WebKit::WebString> m_mockTranscripts; + Vector<float> m_mockConfidences; +}; + +#endif // ENABLE(SCRIPTED_SPEECH) + +#endif // MockWebSpeechRecognizer_h diff --git a/Tools/DumpRenderTree/chromium/TestShell.cpp b/Tools/DumpRenderTree/chromium/TestShell.cpp index 9b9ca4a5b..b8323a39b 100644 --- a/Tools/DumpRenderTree/chromium/TestShell.cpp +++ b/Tools/DumpRenderTree/chromium/TestShell.cpp @@ -114,7 +114,6 @@ TestShell::TestShell() , m_accelerated2dCanvasEnabled(false) , m_deferred2dCanvasEnabled(false) , m_acceleratedPaintingEnabled(false) - , m_perTilePaintingEnabled(false) , m_stressOpt(false) , m_stressDeopt(false) , m_dumpWhenFinished(true) @@ -231,7 +230,6 @@ void TestShell::resetWebSettings(WebView& webView) m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled; m_prefs.deferred2dCanvasEnabled = m_deferred2dCanvasEnabled; m_prefs.acceleratedPaintingEnabled = m_acceleratedPaintingEnabled; - m_prefs.perTilePaintingEnabled = m_perTilePaintingEnabled; m_prefs.applyTo(&webView); } @@ -377,6 +375,11 @@ void TestShell::testTimedOut() testFinished(); } +void TestShell::setPerTilePaintingEnabled(bool enabled) +{ + WebCompositor::setPerTilePaintingEnabled(enabled); +} + static string dumpDocumentText(WebFrame* frame) { // We use the document element's text instead of the body text here because @@ -726,6 +729,7 @@ void TestShell::bindJSObjectsToWindow(WebFrame* frame) m_accessibilityController->bindToJavascript(frame, WebString::fromUTF8("accessibilityController")); m_gamepadController->bindToJavascript(frame, WebString::fromUTF8("gamepadController")); m_layoutTestController->bindToJavascript(frame, WebString::fromUTF8("layoutTestController")); + m_layoutTestController->bindToJavascript(frame, WebString::fromUTF8("testRunner")); m_eventSender->bindToJavascript(frame, WebString::fromUTF8("eventSender")); m_textInputController->bindToJavascript(frame, WebString::fromUTF8("textInputController")); } diff --git a/Tools/DumpRenderTree/chromium/TestShell.h b/Tools/DumpRenderTree/chromium/TestShell.h index ae9d8d8a1..8ae0c2421 100644 --- a/Tools/DumpRenderTree/chromium/TestShell.h +++ b/Tools/DumpRenderTree/chromium/TestShell.h @@ -142,7 +142,7 @@ public: void setAccelerated2dCanvasEnabled(bool enabled) { m_accelerated2dCanvasEnabled = enabled; } void setDeferred2dCanvasEnabled(bool enabled) { m_deferred2dCanvasEnabled = enabled; } void setAcceleratedPaintingEnabled(bool enabled) { m_acceleratedPaintingEnabled = enabled; } - void setPerTilePaintingEnabled(bool enabled) { m_perTilePaintingEnabled = enabled; } + void setPerTilePaintingEnabled(bool); #if defined(OS_WIN) // Access to the finished event. Used by the static WatchDog thread. HANDLE finishedEvent() { return m_finishedEvent; } diff --git a/Tools/DumpRenderTree/chromium/TestShellAndroid.cpp b/Tools/DumpRenderTree/chromium/TestShellAndroid.cpp index e77d80d48..ba182bbbb 100644 --- a/Tools/DumpRenderTree/chromium/TestShellAndroid.cpp +++ b/Tools/DumpRenderTree/chromium/TestShellAndroid.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "TestShell.h" +#include "linux/WebFontRendering.h" #include <android/log.h> #include <errno.h> #include <fcntl.h> @@ -127,4 +128,8 @@ void platformInit(int* argc, char*** argv) // Redirect stderr to stdout. dup2(1, 2); } + + // Disable auto hint and use normal hinting in layout test mode to produce the same font metrics as chromium-linux. + WebKit::WebFontRendering::setAutoHint(false); + WebKit::WebFontRendering::setHinting(SkPaint::kNormal_Hinting); } diff --git a/Tools/DumpRenderTree/chromium/TestWebPlugin.h b/Tools/DumpRenderTree/chromium/TestWebPlugin.h index 8581288ac..4c9f2f4d2 100644 --- a/Tools/DumpRenderTree/chromium/TestWebPlugin.h +++ b/Tools/DumpRenderTree/chromium/TestWebPlugin.h @@ -68,6 +68,7 @@ public: virtual void didFailLoading(const WebKit::WebURLError&) { } virtual void didFinishLoadingFrameRequest(const WebKit::WebURL&, void* notifyData) { } virtual void didFailLoadingFrameRequest(const WebKit::WebURL&, void* notifyData, const WebKit::WebURLError&) { } + virtual bool isPlaceholder() { return false; } private: enum Primitive { diff --git a/Tools/DumpRenderTree/chromium/WebPreferences.cpp b/Tools/DumpRenderTree/chromium/WebPreferences.cpp index 3227c0231..751dfeeb5 100644 --- a/Tools/DumpRenderTree/chromium/WebPreferences.cpp +++ b/Tools/DumpRenderTree/chromium/WebPreferences.cpp @@ -117,7 +117,6 @@ void WebPreferences::reset() acceleratedPaintingEnabled = false; forceCompositingMode = false; hixie76WebSocketProtocolEnabled = true; - perTilePaintingEnabled = false; mockScrollbarsEnabled = false; cssCustomFilterEnabled = false; } @@ -226,7 +225,6 @@ void WebPreferences::applyTo(WebView* webView) settings->setDeferred2dCanvasEnabled(deferred2dCanvasEnabled); settings->setAcceleratedPaintingEnabled(acceleratedPaintingEnabled); settings->setHixie76WebSocketProtocolEnabled(hixie76WebSocketProtocolEnabled); - settings->setPerTilePaintingEnabled(perTilePaintingEnabled); settings->setMockScrollbarsEnabled(mockScrollbarsEnabled); // Fixed values. diff --git a/Tools/DumpRenderTree/chromium/WebPreferences.h b/Tools/DumpRenderTree/chromium/WebPreferences.h index 31de331ed..6e951feb3 100644 --- a/Tools/DumpRenderTree/chromium/WebPreferences.h +++ b/Tools/DumpRenderTree/chromium/WebPreferences.h @@ -110,7 +110,6 @@ struct WebPreferences { bool deferred2dCanvasEnabled; bool acceleratedPaintingEnabled; bool hixie76WebSocketProtocolEnabled; - bool perTilePaintingEnabled; bool mockScrollbarsEnabled; bool cssCustomFilterEnabled; diff --git a/Tools/DumpRenderTree/chromium/WebThemeEngineDRTWin.cpp b/Tools/DumpRenderTree/chromium/WebThemeEngineDRTWin.cpp index 789b1c816..831c354fa 100755 --- a/Tools/DumpRenderTree/chromium/WebThemeEngineDRTWin.cpp +++ b/Tools/DumpRenderTree/chromium/WebThemeEngineDRTWin.cpp @@ -51,7 +51,7 @@ static const int dfcsNormal = 0x0000; static SkIRect webRectToSkIRect(const WebRect& webRect) { SkIRect irect; - irect.set(webRect.x, webRect.y, webRect.x + webRect.width, webRect.y + webRect.height); + irect.set(webRect.x, webRect.y, webRect.x + webRect.width - 1, webRect.y + webRect.height - 1); return irect; } diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.cpp b/Tools/DumpRenderTree/chromium/WebViewHost.cpp index 6c48bc1e1..88e07378f 100644 --- a/Tools/DumpRenderTree/chromium/WebViewHost.cpp +++ b/Tools/DumpRenderTree/chromium/WebViewHost.cpp @@ -34,6 +34,7 @@ #include "LayoutTestController.h" #include "MockGrammarCheck.h" #include "MockWebSpeechInputController.h" +#include "MockWebSpeechRecognizer.h" #include "TestNavigationController.h" #include "TestShell.h" #include "TestWebPlugin.h" @@ -261,6 +262,7 @@ WebWidget* WebViewHost::createPopupMenu(WebPopupType type) switch (type) { case WebKit::WebPopupTypeNone: case WebKit::WebPopupTypePage: + case WebKit::WebPopupTypeHelperPlugin: break; case WebKit::WebPopupTypeSelect: case WebKit::WebPopupTypeSuggestion: @@ -286,7 +288,7 @@ WebKit::WebGraphicsContext3D* WebViewHost::createGraphicsContext3D(const WebKit: { if (!webView()) return 0; - return webkit_support::CreateGraphicsContext3D(attributes, webView(), true); + return webkit_support::CreateGraphicsContext3D(attributes, webView()); } void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine) @@ -465,6 +467,32 @@ void WebViewHost::spellCheck(const WebString& text, int& misspelledOffset, int& m_spellcheck.spellCheckWord(text, &misspelledOffset, &misspelledLength); } +void WebViewHost::checkTextOfParagraph(const WebString& text, WebTextCheckingTypeMask mask, WebVector<WebTextCheckingResult>* webResults) +{ + Vector<WebTextCheckingResult> results; + if (mask & WebTextCheckingTypeSpelling) { + size_t offset = 0; + size_t length = text.length(); + const WebUChar* data = text.data(); + while (offset < length) { + int misspelledPosition = 0; + int misspelledLength = 0; + m_spellcheck.spellCheckWord(WebString(&data[offset], length - offset), &misspelledPosition, &misspelledLength); + if (!misspelledLength) + break; + WebTextCheckingResult result; + result.type = WebTextCheckingTypeSpelling; + result.location = offset + misspelledPosition; + result.length = misspelledLength; + results.append(result); + offset += misspelledPosition + misspelledLength; + } + } + if (mask & WebTextCheckingTypeGrammar) + MockGrammarCheck::checkGrammarOfString(text, &results); + webResults->assign(results); +} + void WebViewHost::requestCheckingOfText(const WebString& text, WebTextCheckingCompletion* completion) { if (text.isEmpty()) { @@ -714,6 +742,15 @@ WebSpeechInputController* WebViewHost::speechInputController(WebKit::WebSpeechIn } #endif +#if ENABLE(SCRIPTED_SPEECH) +WebSpeechRecognizer* WebViewHost::speechRecognizer() +{ + if (!m_mockSpeechRecognizer) + m_mockSpeechRecognizer = MockWebSpeechRecognizer::create(); + return m_mockSpeechRecognizer.get(); +} +#endif + WebDeviceOrientationClientMock* WebViewHost::deviceOrientationClientMock() { if (!m_deviceOrientationClientMock.get()) @@ -857,9 +894,10 @@ void WebViewHost::didNotAcquirePointerLock() void WebViewHost::didLosePointerLock() { - ASSERT(m_pointerLocked); + bool wasLocked = m_pointerLocked; m_pointerLocked = false; - webWidget()->didLosePointerLock(); + if (wasLocked) + webWidget()->didLosePointerLock(); } #endif diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.h b/Tools/DumpRenderTree/chromium/WebViewHost.h index 21dbb4c8d..ce189d915 100644 --- a/Tools/DumpRenderTree/chromium/WebViewHost.h +++ b/Tools/DumpRenderTree/chromium/WebViewHost.h @@ -48,6 +48,7 @@ class LayoutTestController; class MockWebSpeechInputController; +class MockWebSpeechRecognizer; class SkCanvas; class TestShell; @@ -117,6 +118,10 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, MockWebSpeechInputController* speechInputControllerMock() { return m_speechInputControllerMock.get(); } #endif +#if ENABLE(SCRIPTED_SPEECH) + MockWebSpeechRecognizer* mockSpeechRecognizer() { return m_mockSpeechRecognizer.get(); } +#endif + #if ENABLE(POINTER_LOCK) void didLosePointerLock(); void setPointerLockWillFailAsynchronously() { m_pointerLockPlannedResult = PointerLockWillFailAsync; } @@ -131,6 +136,7 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, // WebKit::WebSpellCheckClient virtual void spellCheck(const WebKit::WebString&, int& offset, int& length, WebKit::WebVector<WebKit::WebString>* optionalSuggestions); + virtual void checkTextOfParagraph(const WebKit::WebString&, WebKit::WebTextCheckingTypeMask, WebKit::WebVector<WebKit::WebTextCheckingResult>*); virtual void requestCheckingOfText(const WebKit::WebString&, WebKit::WebTextCheckingCompletion*); virtual WebKit::WebString autoCorrectWord(const WebKit::WebString&); @@ -176,7 +182,10 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, #if ENABLE(INPUT_SPEECH) virtual WebKit::WebSpeechInputController* speechInputController(WebKit::WebSpeechInputListener*); #endif - virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient(); +#if ENABLE(SCRIPTED_SPEECH) + virtual WebKit::WebSpeechRecognizer* speechRecognizer() OVERRIDE; +#endif + virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient() OVERRIDE; #if ENABLE(MEDIA_STREAM) virtual WebKit::WebUserMediaClient* userMediaClient(); #endif @@ -412,6 +421,10 @@ private: OwnPtr<MockWebSpeechInputController> m_speechInputControllerMock; #endif +#if ENABLE(SCRIPTED_SPEECH) + OwnPtr<MockWebSpeechRecognizer> m_mockSpeechRecognizer; +#endif + #if ENABLE(MEDIA_STREAM) OwnPtr<WebKit::WebUserMediaClientMock> m_userMediaClientMock; OwnPtr<webkit_support::TestMediaStreamClient> m_testMediaStreamClient; diff --git a/Tools/DumpRenderTree/chromium/fonts.conf b/Tools/DumpRenderTree/chromium/fonts.conf index b75a9322e..8e4f8d712 100644 --- a/Tools/DumpRenderTree/chromium/fonts.conf +++ b/Tools/DumpRenderTree/chromium/fonts.conf @@ -226,4 +226,17 @@ </edit> </match> + <match target="pattern"> + <!-- FontConfig doesn't currently provide a well-defined way to turn on + subpixel positioning. This is just an arbitrary pattern to use after + turning subpixel positioning on globally to ensure that we don't have + issues with our style getting cached for other tests. --> + <test name="family" compare="eq"> + <string>SubpixelPositioning</string> + </test> + <edit name="family" mode="assign"> + <string>Times New Roman</string> + </edit> + </match> + </fontconfig> diff --git a/Tools/DumpRenderTree/efl/CMakeLists.txt b/Tools/DumpRenderTree/efl/CMakeLists.txt index 06cef3a19..0a8fd065b 100644 --- a/Tools/DumpRenderTree/efl/CMakeLists.txt +++ b/Tools/DumpRenderTree/efl/CMakeLists.txt @@ -62,6 +62,7 @@ SET(DumpRenderTree_INCLUDE_DIRECTORIES ${WEBCORE_DIR}/platform/text ${WEBCORE_DIR}/platform/graphics ${WEBCORE_DIR}/platform/graphics/cairo + ${WEBCORE_DIR}/platform/graphics/transforms ${WEBCORE_DIR}/platform/network ${WEBCORE_DIR}/platform/network/soup ${WEBCORE_DIR}/plugins @@ -76,6 +77,7 @@ SET(DumpRenderTree_INCLUDE_DIRECTORIES ${JAVASCRIPTCORE_DIR}/assembler ${JAVASCRIPTCORE_DIR}/bytecode ${JAVASCRIPTCORE_DIR}/dfg + ${JAVASCRIPTCORE_DIR}/disassembler ${JAVASCRIPTCORE_DIR}/heap ${JAVASCRIPTCORE_DIR}/interpreter ${JAVASCRIPTCORE_DIR}/jit @@ -116,14 +118,12 @@ ADD_DEFINITIONS(-DFONTS_CONF_DIR="${TOOLS_DIR}/DumpRenderTree/gtk/fonts" INCLUDE_DIRECTORIES(${DumpRenderTree_INCLUDE_DIRECTORIES}) -ADD_EXECUTABLE(bin/DumpRenderTree ${DumpRenderTree_SOURCES}) -TARGET_LINK_LIBRARIES(bin/DumpRenderTree ${DumpRenderTree_LIBRARIES}) -ADD_TARGET_PROPERTIES(bin/DumpRenderTree LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}") -SET_TARGET_PROPERTIES(bin/DumpRenderTree PROPERTIES FOLDER "Tools") -SET_TARGET_PROPERTIES(bin/DumpRenderTree PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +ADD_EXECUTABLE(DumpRenderTree ${DumpRenderTree_SOURCES}) +TARGET_LINK_LIBRARIES(DumpRenderTree ${DumpRenderTree_LIBRARIES}) +ADD_TARGET_PROPERTIES(DumpRenderTree LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}") +SET_TARGET_PROPERTIES(DumpRenderTree PROPERTIES FOLDER "Tools") -ADD_EXECUTABLE(bin/ImageDiff ${ImageDiff_SOURCES}) -TARGET_LINK_LIBRARIES(bin/ImageDiff ${DumpRenderTree_LIBRARIES}) -ADD_TARGET_PROPERTIES(bin/ImageDiff LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}") -SET_TARGET_PROPERTIES(bin/ImageDiff PROPERTIES FOLDER "Tools") -SET_TARGET_PROPERTIES(bin/ImageDiff PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +ADD_EXECUTABLE(ImageDiff ${ImageDiff_SOURCES}) +TARGET_LINK_LIBRARIES(ImageDiff ${DumpRenderTree_LIBRARIES}) +ADD_TARGET_PROPERTIES(ImageDiff LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}") +SET_TARGET_PROPERTIES(ImageDiff PROPERTIES FOLDER "Tools") diff --git a/Tools/DumpRenderTree/efl/DumpRenderTree.cpp b/Tools/DumpRenderTree/efl/DumpRenderTree.cpp index f8bf85e54..aace475b5 100644 --- a/Tools/DumpRenderTree/efl/DumpRenderTree.cpp +++ b/Tools/DumpRenderTree/efl/DumpRenderTree.cpp @@ -199,6 +199,11 @@ static String getExpectedPixelHash(const String& testURL) return (hashSeparatorPos != notFound) ? testURL.substring(hashSeparatorPos + 1) : String(); } +static inline bool isGlobalHistoryTest(const String& cTestPathOrURL) +{ + return cTestPathOrURL.contains("/globalhistory/"); +} + static void createLayoutTestController(const String& testURL, const String& expectedPixelHash) { gLayoutTestController = @@ -214,6 +219,7 @@ static void createLayoutTestController(const String& testURL, const String& expe gLayoutTestController->setDumpFrameLoadCallbacks(true); gLayoutTestController->setDeveloperExtrasEnabled(true); + gLayoutTestController->setDumpHistoryDelegateCallbacks(isGlobalHistoryTest(testURL)); if (shouldDumpAsText(testURL)) { gLayoutTestController->setDumpAsText(true); diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp index 862a616a9..8a901c41d 100644 --- a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp +++ b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp @@ -110,6 +110,10 @@ Evas_Object* DumpRenderTreeChrome::createView() const evas_object_smart_callback_add(view, "mixedcontent,run", onInsecureContentRun, 0); evas_object_smart_callback_add(view, "mixedcontent,displayed", onInsecureContentDisplayed, 0); evas_object_smart_callback_add(view, "frame,created", onFrameCreated, 0); + evas_object_smart_callback_add(view, "navigate,with,data", onWebViewNavigatedWithData, 0); + evas_object_smart_callback_add(view, "perform,server,redirect", onWebViewServerRedirect, 0); + evas_object_smart_callback_add(view, "perform,client,redirect", onWebViewClientRedirect, 0); + evas_object_smart_callback_add(view, "populate,visited,links", onWebViewPopulateVisitedLinks, 0); connectEditingCallbacks(view); @@ -213,6 +217,7 @@ void DumpRenderTreeChrome::resetDefaultsToConsistentValues() ewk_settings_memory_cache_clear(); ewk_settings_application_cache_clear(); + ewk_settings_shadow_dom_enable_set(EINA_TRUE); ewk_view_setting_private_browsing_set(mainView(), EINA_FALSE); ewk_view_setting_spatial_navigation_set(mainView(), EINA_FALSE); @@ -240,13 +245,15 @@ void DumpRenderTreeChrome::resetDefaultsToConsistentValues() ewk_view_setting_minimum_timer_interval_set(browser->mainView(), 0.010); // 10 milliseconds (DOMTimer::s_minDefaultTimerInterval) ewk_view_setting_enable_webgl_set(mainView(), EINA_TRUE); ewk_view_setting_enable_hyperlink_auditing_set(mainView(), EINA_FALSE); - ewk_view_setting_include_links_in_focus_chain_set(mainView(), EINA_TRUE); + ewk_view_setting_include_links_in_focus_chain_set(mainView(), EINA_FALSE); ewk_view_setting_scripts_can_access_clipboard_set(mainView(), EINA_TRUE); + ewk_view_setting_web_audio_set(mainView(), EINA_FALSE); ewk_view_zoom_set(mainView(), 1.0, 0, 0); ewk_view_scale_set(mainView(), 1.0, 0, 0); ewk_view_text_zoom_set(mainView(), 1.0); ewk_view_visibility_state_set(mainView(), EWK_PAGE_VISIBILITY_STATE_VISIBLE, true); + ewk_view_text_direction_set(mainView(), EWK_TEXT_DIRECTION_DEFAULT); ewk_history_clear(ewk_view_history_get(mainView())); @@ -268,7 +275,12 @@ void DumpRenderTreeChrome::resetDefaultsToConsistentValues() DumpRenderTreeSupportEfl::setDefersLoading(mainView(), false); DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(mainView(), false); DumpRenderTreeSupportEfl::setSerializeHTTPLoads(false); + + // Reset capacities for the memory cache for dead objects. + static const unsigned cacheTotalCapacity = 8192 * 1024; + ewk_settings_object_cache_capacity_set(0, cacheTotalCapacity, cacheTotalCapacity); DumpRenderTreeSupportEfl::setDeadDecodedDataDeletionInterval(0); + ewk_settings_page_cache_capacity_set(3); if (m_currentIntentRequest) { ewk_intent_request_unref(m_currentIntentRequest); @@ -454,6 +466,12 @@ void DumpRenderTreeChrome::onFrameTitleChanged(void*, Evas_Object* frame, void* if (!done && gLayoutTestController->dumpTitleChanges()) printf("TITLE CHANGED: %s\n", (titleText && titleText->string) ? titleText->string : ""); + + if (!done && gLayoutTestController->dumpHistoryDelegateCallbacks()) + printf("WebView updated the title for history URL \"%s\" to \"%s\".\n", ewk_frame_uri_get(frame) + , (titleText && titleText->string) ? titleText->string : ""); + + gLayoutTestController->setTitleTextDirection(titleText->direction == EWK_TEXT_DIRECTION_LEFT_TO_RIGHT ? "ltr" : "rtl"); } void DumpRenderTreeChrome::onDocumentLoadFinished(void*, Evas_Object*, void* eventInfo) @@ -550,6 +568,57 @@ void DumpRenderTreeChrome::onFrameCreated(void*, Evas_Object*, void* eventInfo) evas_object_smart_callback_add(frame, "xss,detected", onDidDetectXSS, 0); } +void DumpRenderTreeChrome::onWebViewNavigatedWithData(void*, Evas_Object*, void* eventInfo) +{ + if (done || !gLayoutTestController->dumpHistoryDelegateCallbacks()) + return; + + ASSERT(eventInfo); + const Ewk_View_Navigation_Data* navigationData = static_cast<Ewk_View_Navigation_Data*>(eventInfo); + + ASSERT(navigationData->request); + ASSERT(navigationData->response); + + const bool wasFailure = navigationData->has_substitute_data || navigationData->response->status_code >= 400; + const bool wasRedirected = navigationData->client_redirect_source && *(navigationData->client_redirect_source); + + printf("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\". The navigation was %s and was %s%s.\n", + navigationData->url, + navigationData->title, + navigationData->request->http_method, + wasFailure? "a failure" : "successful", + (wasRedirected ? "a client redirect from " : "not a client redirect"), + (wasRedirected ? navigationData->client_redirect_source : "")); +} + +void DumpRenderTreeChrome::onWebViewServerRedirect(void*, Evas_Object*, void* eventInfo) +{ + if (done || !gLayoutTestController->dumpHistoryDelegateCallbacks()) + return; + + ASSERT(eventInfo); + const Ewk_View_Redirection_Data* data = static_cast<Ewk_View_Redirection_Data*>(eventInfo); + printf("WebView performed a server redirect from \"%s\" to \"%s\".\n", data->source_url, data->destination_url); +} + +void DumpRenderTreeChrome::onWebViewClientRedirect(void*, Evas_Object*, void* eventInfo) +{ + if (done || !gLayoutTestController->dumpHistoryDelegateCallbacks()) + return; + + ASSERT(eventInfo); + const Ewk_View_Redirection_Data* data = static_cast<Ewk_View_Redirection_Data*>(eventInfo); + printf("WebView performed a client redirect from \"%s\" to \"%s\".\n", data->source_url, data->destination_url); +} + +void DumpRenderTreeChrome::onWebViewPopulateVisitedLinks(void*, Evas_Object* ewkView, void*) +{ + if (done || !gLayoutTestController->dumpHistoryDelegateCallbacks()) + return; + + printf("Asked to populate visited links for WebView \"%s\"\n", ewk_view_uri_get(ewkView)); +} + void DumpRenderTreeChrome::onFrameProvisionalLoad(void*, Evas_Object* frame, void*) { if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h index 9b65b4102..9e2f32372 100644 --- a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h +++ b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h @@ -91,6 +91,14 @@ private: static void onWebViewOnloadEvent(void*, Evas_Object*, void*); + static void onWebViewNavigatedWithData(void*, Evas_Object*, void*); + + static void onWebViewServerRedirect(void*, Evas_Object*, void*); + + static void onWebViewClientRedirect(void*, Evas_Object*, void*); + + static void onWebViewPopulateVisitedLinks(void*, Evas_Object*, void*); + static void onInsecureContentRun(void*, Evas_Object*, void*); static void onInsecureContentDisplayed(void*, Evas_Object*, void*); diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp b/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp index f07d3815b..32f4c39b3 100644 --- a/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp +++ b/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp @@ -23,6 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define __STDC_FORMAT_MACROS #include "config.h" #include "DumpRenderTreeView.h" @@ -36,6 +37,7 @@ #include <Evas.h> #include <cstdio> #include <cstdlib> +#include <inttypes.h> #include <wtf/NotFound.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -129,7 +131,7 @@ static int64_t onExceededApplicationCacheQuota(Ewk_View_Smart_Data*, Ewk_Securit // sufficient to just get a range of 10000 to determine if we were // above or below a threshold. int64_t truncatedSpaceNeeded = (totalSpaceNeeded / 10000) * 10000; - printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i} totalSpaceNeeded:~%lld\n", + printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i} totalSpaceNeeded:~%" PRId64 "\n", ewk_security_origin_protocol_get(origin), ewk_security_origin_host_get(origin), ewk_security_origin_port_get(origin), @@ -187,6 +189,12 @@ static Eina_Bool onNavigationPolicyDecision(Ewk_View_Smart_Data*, Ewk_Frame_Reso return policyDelegatePermissive; } +static Eina_Bool onFocusCanCycle(Ewk_View_Smart_Data*, Ewk_Focus_Direction) +{ + // This is the behavior of Mac and Chromium ports and is expected by some test cases. + return true; +} + Evas_Object* drtViewAdd(Evas* evas) { static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("DRT_View"); @@ -206,6 +214,7 @@ Evas_Object* drtViewAdd(Evas* evas) api.exceeded_application_cache_quota = onExceededApplicationCacheQuota; api.exceeded_database_quota = onExceededDatabaseQuota; api.navigation_policy_decision = onNavigationPolicyDecision; + api.focus_can_cycle = onFocusCanCycle; return evas_object_smart_add(evas, evas_smart_class_new(&api.sc)); } diff --git a/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp b/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp index 0e8a66e2e..070af8c14 100644 --- a/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp +++ b/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp @@ -7,6 +7,7 @@ * Copyright (C) 2010 Joone Hur <joone@kldp.org> * Copyright (C) 2011 ProFUSION Embedded Systems * Copyright (C) 2011 Samsung Electronics + * Copyright (C) 2012 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,6 +55,13 @@ #include <stdio.h> #include <wtf/text/WTFString.h> +// Same as Mac cache model enum in Source/WebKit/mac/WebView/WebPreferences.h. +enum { + WebCacheModelDocumentViewer = 0, + WebCacheModelDocumentBrowser = 1, + WebCacheModelPrimaryWebBrowser = 2 +}; + LayoutTestController::~LayoutTestController() { } @@ -99,13 +107,6 @@ void LayoutTestController::display() displayWebView(); } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - const Evas_Object* mainFrame = browser->mainFrame(); - const String counterValue(DumpRenderTreeSupportEfl::counterValueByElementId(mainFrame, id->ustring().utf8().data())); - return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(counterValue.utf8().data())); -} - void LayoutTestController::keepWebHistory() { notImplemented(); @@ -177,8 +178,28 @@ void LayoutTestController::notifyDone() JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url) { - // Function introduced in r28690. This may need special-casing on Windows. - return JSStringRetain(url); // Do nothing on Unix. + String requestedUrl(url->characters(), url->length()); + String resourceRoot; + String requestedRoot; + + if (requestedUrl.find("LayoutTests") != notFound) { + // If the URL contains LayoutTests we need to remap that to + // LOCAL_RESOURCE_ROOT which is the path of the LayoutTests directory + // within the WebKit source tree. + requestedRoot = "/tmp/LayoutTests"; + resourceRoot = getenv("LOCAL_RESOURCE_ROOT"); + } else if (requestedUrl.find("tmp") != notFound) { + // If the URL is a child of /tmp we need to convert it to be a child + // DUMPRENDERTREE_TEMP replace tmp with DUMPRENDERTREE_TEMP + requestedRoot = "/tmp"; + resourceRoot = getenv("DUMPRENDERTREE_TEMP"); + } + + size_t indexOfRootStart = requestedUrl.reverseFind(requestedRoot); + size_t indexOfSeparatorAfterRoot = indexOfRootStart + requestedRoot.length(); + String fullPathToUrl = "file://" + resourceRoot + requestedUrl.substring(indexOfSeparatorAfterRoot); + + return JSStringCreateWithUTF8CString(fullPathToUrl.utf8().data()); } void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target) @@ -527,21 +548,21 @@ void LayoutTestController::setCacheModel(int cacheModel) // These constants are derived from the Mac cache model enum in Source/WebKit/mac/WebView/WebPreferences.h. switch (cacheModel) { - case 0: // WebCacheModelDocumentViewer + case WebCacheModelDocumentViewer: pageCacheCapacity = 0; cacheTotalCapacity = 0; cacheMinDeadCapacity = 0; cacheMaxDeadCapacity = 0; deadDecodedDataDeletionInterval = 0; break; - case 1: // WebCacheModelDocumentBrowser + case WebCacheModelDocumentBrowser: pageCacheCapacity = 2; cacheTotalCapacity = 16 * 1024 * 1024; cacheMinDeadCapacity = cacheTotalCapacity / 8; cacheMaxDeadCapacity = cacheTotalCapacity / 4; deadDecodedDataDeletionInterval = 0; break; - case 3: // WebCacheModelPrimaryWebBrowser + case WebCacheModelPrimaryWebBrowser: pageCacheCapacity = 3; cacheTotalCapacity = 32 * 1024 * 1024; cacheMinDeadCapacity = cacheTotalCapacity / 4; @@ -645,9 +666,9 @@ void LayoutTestController::syncLocalStorage() notImplemented(); } -void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool, JSStringRef) +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme) { - notImplemented(); + DumpRenderTreeSupportEfl::setDomainRelaxationForbiddenForURLScheme(forbidden, WTF::String(scheme->ustring().impl())); } void LayoutTestController::goBack() @@ -716,6 +737,8 @@ void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value DumpRenderTreeSupportEfl::setLoadsSiteIconsIgnoringImageLoadingSetting(browser->mainView(), toBool(value)); else if (equals(key, "WebKitCSSGridLayoutEnabled")) DumpRenderTreeSupportEfl::setCSSGridLayoutEnabled(browser->mainView(), toBool(value)); + else if (equals(key, "WebKitWebAudioEnabled")) + ewk_view_setting_web_audio_set(browser->mainView(), toBool(value)); else fprintf(stderr, "LayoutTestController::overridePreference tried to override unknown preference '%s'.\n", value->ustring().utf8().data()); } @@ -828,9 +851,21 @@ void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval) ewk_view_setting_minimum_timer_interval_set(browser->mainView(), minimumTimerInterval); } -void LayoutTestController::setTextDirection(JSStringRef) +void LayoutTestController::setTextDirection(JSStringRef direction) { - notImplemented(); + Ewk_Text_Direction ewkDirection; + if (JSStringIsEqualToUTF8CString(direction, "auto")) + ewkDirection = EWK_TEXT_DIRECTION_DEFAULT; + else if (JSStringIsEqualToUTF8CString(direction, "rtl")) + ewkDirection = EWK_TEXT_DIRECTION_RIGHT_TO_LEFT; + else if (JSStringIsEqualToUTF8CString(direction, "ltr")) + ewkDirection = EWK_TEXT_DIRECTION_LEFT_TO_RIGHT; + else { + fprintf(stderr, "LayoutTestController::setTextDirection called with unknown direction: '%s'.\n", direction->ustring().utf8().data()); + return; + } + + ewk_view_text_direction_set(browser->mainView(), ewkDirection); } void LayoutTestController::addChromeInputField() diff --git a/Tools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp b/Tools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp index cedacdb65..bee371960 100644 --- a/Tools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp +++ b/Tools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp @@ -140,7 +140,8 @@ gchar* attributeSetToString(AtkAttributeSet* attributeSet) GString* str = g_string_new(0); for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) { AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data); - g_string_append(str, g_strconcat(attribute->name, ":", attribute->value, NULL)); + GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL)); + g_string_append(str, attributeData.get()); if (attributes->next) g_string_append(str, ", "); } @@ -154,7 +155,8 @@ JSStringRef AccessibilityUIElement::allAttributes() return JSStringCreateWithCharacters(0, 0); ASSERT(ATK_IS_OBJECT(m_element)); - return JSStringCreateWithUTF8CString(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element)))); + GOwnPtr<gchar> attributeData(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element)))); + return JSStringCreateWithUTF8CString(attributeData.get()); } JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements() @@ -328,13 +330,9 @@ double AccessibilityUIElement::intValue() const return 0.0f; atk_value_get_current_value(ATK_VALUE(m_element), &value); - - if (G_VALUE_HOLDS_DOUBLE(&value)) - return g_value_get_double(&value); - else if (G_VALUE_HOLDS_INT(&value)) - return static_cast<double>(g_value_get_int(&value)); - else + if (!G_VALUE_HOLDS_FLOAT(&value)) return 0.0f; + return g_value_get_float(&value); } double AccessibilityUIElement::minValue() @@ -345,13 +343,9 @@ double AccessibilityUIElement::minValue() return 0.0f; atk_value_get_minimum_value(ATK_VALUE(m_element), &value); - - if (G_VALUE_HOLDS_DOUBLE(&value)) - return g_value_get_double(&value); - else if (G_VALUE_HOLDS_INT(&value)) - return static_cast<double>(g_value_get_int(&value)); - else + if (!G_VALUE_HOLDS_FLOAT(&value)) return 0.0f; + return g_value_get_float(&value); } double AccessibilityUIElement::maxValue() @@ -362,13 +356,9 @@ double AccessibilityUIElement::maxValue() return 0.0f; atk_value_get_maximum_value(ATK_VALUE(m_element), &value); - - if (G_VALUE_HOLDS_DOUBLE(&value)) - return g_value_get_double(&value); - else if (G_VALUE_HOLDS_INT(&value)) - return static_cast<double>(g_value_get_int(&value)); - else + if (!G_VALUE_HOLDS_FLOAT(&value)) return 0.0f; + return g_value_get_float(&value); } JSStringRef AccessibilityUIElement::valueDescription() @@ -644,22 +634,38 @@ bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute) return false; } -void AccessibilityUIElement::increment() +static void alterCurrentValue(PlatformUIElement element, int factor) { - if (!m_element) + if (!element) return; - ASSERT(ATK_IS_OBJECT(m_element)); - DumpRenderTreeSupportGtk::incrementAccessibilityValue(ATK_OBJECT(m_element)); + ASSERT(ATK_IS_VALUE(element)); + + GValue currentValue = G_VALUE_INIT; + atk_value_get_current_value(ATK_VALUE(element), ¤tValue); + + GValue increment = G_VALUE_INIT; + atk_value_get_minimum_increment(ATK_VALUE(element), &increment); + + GValue newValue = G_VALUE_INIT; + g_value_init(&newValue, G_TYPE_FLOAT); + + g_value_set_float(&newValue, g_value_get_float(¤tValue) + factor * g_value_get_float(&increment)); + atk_value_set_current_value(ATK_VALUE(element), &newValue); + + g_value_unset(&newValue); + g_value_unset(&increment); + g_value_unset(¤tValue); } -void AccessibilityUIElement::decrement() +void AccessibilityUIElement::increment() { - if (!m_element) - return; + alterCurrentValue(m_element, 1); +} - ASSERT(ATK_IS_OBJECT(m_element)); - DumpRenderTreeSupportGtk::decrementAccessibilityValue(ATK_OBJECT(m_element)); +void AccessibilityUIElement::decrement() +{ + alterCurrentValue(m_element, -1); } void AccessibilityUIElement::press() diff --git a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp b/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp index 18aafafd1..9740d276f 100644 --- a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ b/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -128,10 +128,12 @@ void dumpFrameScrollPosition(WebKitWebFrame* frame) void displayWebView() { - gtk_widget_queue_draw(GTK_WIDGET(webView)); + DumpRenderTreeSupportGtk::forceWebViewPaint(webView); + DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, true); + DumpRenderTreeSupportGtk::resetTrackedRepaints(mainFrame); } -static void appendString(gchar*& target, gchar* string) +static void appendString(gchar*& target, const gchar* string) { gchar* oldString = target; target = g_strconcat(target, string, NULL); @@ -246,8 +248,10 @@ static gchar* dumpFramesAsText(WebKitWebFrame* frame) if (gLayoutTestController->dumpChildFramesAsText()) { GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame); - for (GSList* child = children; child; child = g_slist_next(child)) - appendString(result, dumpFramesAsText(static_cast<WebKitWebFrame* >(child->data))); + for (GSList* child = children; child; child = g_slist_next(child)) { + GOwnPtr<gchar> childData(dumpFramesAsText(static_cast<WebKitWebFrame*>(child->data))); + appendString(result, childData.get()); + } g_slist_free(children); } @@ -278,8 +282,10 @@ static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current gchar* uriScheme = g_uri_parse_scheme(uri); if (g_strcmp0(uriScheme, "file") == 0) { gchar* pos = g_strstr_len(uri, -1, "/LayoutTests/"); - if (!pos) + if (!pos) { + g_free(uriScheme); return; + } GString* result = g_string_sized_new(strlen(uri)); result = g_string_append(result, "(file test):"); @@ -291,9 +297,9 @@ static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current g_free(uriScheme); - const gchar* target = webkit_web_history_item_get_target(item); - if (target && strlen(target) > 0) - printf(" (in frame \"%s\")", target); + GOwnPtr<gchar> target(webkit_web_history_item_get_target(item)); + if (target.get() && strlen(target.get()) > 0) + printf(" (in frame \"%s\")", target.get()); if (webkit_web_history_item_is_target_item(item)) printf(" **nav target**"); putchar('\n'); @@ -456,6 +462,7 @@ static void resetDefaultsToConsistentValues() axController->resetToConsistentState(); DumpRenderTreeSupportGtk::clearOpener(mainFrame); + DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, false); DumpRenderTreeSupportGtk::resetGeolocationClientMock(webView); diff --git a/Tools/DumpRenderTree/gtk/EventSender.cpp b/Tools/DumpRenderTree/gtk/EventSender.cpp index bc38a2029..102bb660f 100644 --- a/Tools/DumpRenderTree/gtk/EventSender.cpp +++ b/Tools/DumpRenderTree/gtk/EventSender.cpp @@ -205,8 +205,10 @@ static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef functio { GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS); - if (!prepareMouseButtonEvent(pressEvent, 2, 0)) + if (!prepareMouseButtonEvent(pressEvent, 2, 0)) { + gdk_event_free(pressEvent); return JSObjectMakeArray(context, 0, 0, 0); + } GdkEvent* releaseEvent = gdk_event_copy(pressEvent); sendOrQueueEvent(pressEvent); @@ -315,12 +317,16 @@ static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0; GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); - if (!prepareMouseButtonEvent(event, button, modifiers)) + if (!prepareMouseButtonEvent(event, button, modifiers)) { + gdk_event_free(event); return JSValueMakeUndefined(context); + } // If the same mouse button is already in the down position don't send another event as it may confuse Xvfb. - if (buttonCurrentlyDown == event->button.button) + if (buttonCurrentlyDown == event->button.button) { + gdk_event_free(event); return JSValueMakeUndefined(context); + } buttonCurrentlyDown = event->button.button; @@ -363,8 +369,10 @@ static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JS guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0; GdkEvent* event = gdk_event_new(GDK_BUTTON_RELEASE); - if (!prepareMouseButtonEvent(event, button, modifiers)) + if (!prepareMouseButtonEvent(event, button, modifiers)) { + gdk_event_free(event); return JSValueMakeUndefined(context); + } lastClickPositionX = lastMousePositionX; lastClickPositionY = lastMousePositionY; diff --git a/Tools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/Tools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index 275c2e029..72d69fa0a 100644 --- a/Tools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/Tools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -102,17 +102,6 @@ void LayoutTestController::display() displayWebView(); } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - gchar* idGChar = JSStringCopyUTF8CString(id); - CString counterValueGChar = DumpRenderTreeSupportGtk::counterValueForElementById(mainFrame, idGChar); - g_free(idGChar); - if (counterValueGChar.isNull()) - return 0; - JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithUTF8CString(counterValueGChar.data())); - return counterValue; -} - void LayoutTestController::keepWebHistory() { // FIXME: implement diff --git a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp b/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp index 3eabfd96c..0a800ec13 100644 --- a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp +++ b/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp @@ -35,6 +35,41 @@ #include "WebCoreSupport/DumpRenderTreeSupportGtk.h" #include <webkit/webkit.h> +static void paintOverlay(cairo_surface_t* surface) +{ + cairo_t* context = cairo_create(surface); + + // Paint a transparent black overlay from which the repainted rectangles are then cleared. + // The alpha component of the overlay should have a value of 0.66, as on other ports. + cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.66); + cairo_rectangle(context, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); + cairo_fill(context); + + GSList* trackedRectsList = DumpRenderTreeSupportGtk::trackedRepaintRects(mainFrame); + for (GSList* listElement = trackedRectsList; listElement; listElement = g_slist_next(listElement)) { + GdkRectangle* rect = static_cast<GdkRectangle*>(listElement->data); + + cairo_set_operator(context, CAIRO_OPERATOR_CLEAR); + cairo_rectangle(context, rect->x, rect->y, rect->width, rect->height); + cairo_fill(context); + } + + g_slist_free_full(trackedRectsList, g_free); + cairo_destroy(context); +} + +static void fillRepaintOverlayIntoContext(cairo_t* context, gint width, gint height) +{ + cairo_surface_t* overlaySurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + paintOverlay(overlaySurface); + + cairo_set_source_surface(context, overlaySurface, 0, 0); + cairo_rectangle(context, 0, 0, width, height); + cairo_fill(context); + + cairo_surface_destroy(overlaySurface); +} + PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool drawSelectionRect) { WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); @@ -48,6 +83,9 @@ PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool height = gtk_widget_get_allocated_height(viewContainer); #endif + while (gtk_events_pending()) + gtk_main_iteration(); + cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t* context = cairo_create(imageSurface); @@ -59,6 +97,9 @@ PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool gtk_widget_draw(viewContainer, context); #endif + if (DumpRenderTreeSupportGtk::isTrackingRepaints(mainFrame)) + fillRepaintOverlayIntoContext(context, width, height); + if (drawSelectionRect) { cairo_rectangle_int_t rectangle; DumpRenderTreeSupportGtk::rectangleForSelection(mainFrame, &rectangle); @@ -69,5 +110,6 @@ PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool cairo_stroke(context); } + cairo_surface_destroy(imageSurface); return BitmapContext::createByAdoptingBitmapAndContext(0, context); } diff --git a/Tools/DumpRenderTree/mac/DumpRenderTree.mm b/Tools/DumpRenderTree/mac/DumpRenderTree.mm index 00bdb2184..271683f7a 100644 --- a/Tools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/Tools/DumpRenderTree/mac/DumpRenderTree.mm @@ -590,7 +590,7 @@ static void resetDefaultsToConsistentValues() #endif -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(CHROMIUM) [defaults setBool:NO forKey:@"NSScrollAnimationEnabled"]; #else [defaults setBool:NO forKey:@"AppleScrollAnimationEnabled"]; diff --git a/Tools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/Tools/DumpRenderTree/mac/LayoutTestControllerMac.mm index 72c0cea47..884572e9b 100644 --- a/Tools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/Tools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -249,19 +249,6 @@ void LayoutTestController::display() displayWebView(); } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id)); - NSString *idNS = (NSString *)idCF.get(); - - DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS]; - if (!element) - return 0; - - JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame counterValueForElement:element])); - return counterValue; -} - void LayoutTestController::keepWebHistory() { if (![WebHistory optionalSharedHistory]) { diff --git a/Tools/DumpRenderTree/mac/TextInputController.m b/Tools/DumpRenderTree/mac/TextInputController.m index f78079446..afeb16e4d 100644 --- a/Tools/DumpRenderTree/mac/TextInputController.m +++ b/Tools/DumpRenderTree/mac/TextInputController.m @@ -31,6 +31,10 @@ #import "DumpRenderTreeMac.h" #import <AppKit/NSInputManager.h> +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#define SUPPORT_DICTATION_ALTERNATIVES +#import <AppKit/NSTextAlternatives.h> +#endif #import <WebKit/WebDocument.h> #import <WebKit/WebFrame.h> #import <WebKit/WebFramePrivate.h> @@ -170,7 +174,8 @@ || aSelector == @selector(characterIndexForPointX:Y:) || aSelector == @selector(validAttributesForMarkedText) || aSelector == @selector(attributedStringWithString:) - || aSelector == @selector(setInputMethodHandler:)) + || aSelector == @selector(setInputMethodHandler:) + || aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:)) return NO; return YES; } @@ -194,7 +199,9 @@ else if (aSelector == @selector(attributedStringWithString:)) return @"makeAttributedString"; // just a factory method, doesn't call into NSTextInput else if (aSelector == @selector(setInputMethodHandler:)) - return @"setInputMethodHandler"; + return @"setInputMethodHandler"; + else if (aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:)) + return @"makeDictatedString"; return nil; } @@ -375,6 +382,27 @@ return [[[NSMutableAttributedString alloc] initWithString:aString] autorelease]; } +- (NSMutableAttributedString*)dictatedStringWithPrimaryString:(NSString*)aString alternative:(NSString*)alternative alternativeOffset:(int)offset alternativeLength:(int)length +{ +#if defined(SUPPORT_DICTATION_ALTERNATIVES) + NSMutableAttributedString* dictatedString = [self attributedStringWithString:aString]; + NSRange rangeWithAlternative = NSMakeRange((NSUInteger)offset, (NSUInteger)length); + NSString* subStringWithAlternative = [aString substringWithRange:rangeWithAlternative]; + if (!subStringWithAlternative) + return nil; + + NSTextAlternatives* alternativeObject = [[[NSTextAlternatives alloc] initWithPrimaryString:subStringWithAlternative alternativeStrings:[NSArray arrayWithObject:alternative]] autorelease]; + if (!alternativeObject) + return nil; + + [dictatedString addAttribute:NSTextAlternativesAttributeName value:alternativeObject range:rangeWithAlternative]; + + return dictatedString; +#else + return nil; +#endif +} + - (void)setInputMethodHandler:(WebScriptObject *)handler { if (inputMethodHandler == handler) diff --git a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index df70e08a6..d77faa6f3 100644 --- a/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp +++ b/Tools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -743,6 +743,7 @@ void DumpRenderTree::initJSObjects() QWebFrame *frame = qobject_cast<QWebFrame*>(sender()); Q_ASSERT(frame); frame->addToJavaScriptWindowObject(QLatin1String("layoutTestController"), m_controller); + frame->addToJavaScriptWindowObject(QLatin1String("testRunner"), m_controller); frame->addToJavaScriptWindowObject(QLatin1String("eventSender"), m_eventSender); frame->addToJavaScriptWindowObject(QLatin1String("textInputController"), m_textInputController); frame->addToJavaScriptWindowObject(QLatin1String("GCController"), m_gcController); diff --git a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index 9bbf439bc..7689d5b4b 100644 --- a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -155,11 +155,6 @@ void LayoutTestController::waitUntilDone() m_timeoutTimer.start(m_timeout, this); } -QString LayoutTestController::counterValueForElementById(const QString& id) -{ - return DumpRenderTreeSupportQt::counterValueForElementById(m_drt->webPage()->mainFrame(), id); -} - void LayoutTestController::setViewModeMediaFeature(const QString& mode) { m_drt->webPage()->setProperty("_q_viewMode", mode); diff --git a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h index ef68b36e9..88b57cffa 100644 --- a/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h +++ b/Tools/DumpRenderTree/qt/LayoutTestControllerQt.h @@ -105,7 +105,6 @@ public slots: void setCanOpenWindows() { m_canOpenWindows = true; } void setPrinting() { m_isPrinting = true; } void waitUntilDone(); - QString counterValueForElementById(const QString& id); int webHistoryItemCount(); void keepWebHistory(); void notifyDone(); diff --git a/Tools/DumpRenderTree/win/DumpRenderTree.cpp b/Tools/DumpRenderTree/win/DumpRenderTree.cpp index 92ab8632c..a6f583f60 100644 --- a/Tools/DumpRenderTree/win/DumpRenderTree.cpp +++ b/Tools/DumpRenderTree/win/DumpRenderTree.cpp @@ -37,6 +37,7 @@ #include "PolicyDelegate.h" #include "ResourceLoadDelegate.h" #include "UIDelegate.h" +#include "WebCoreTestSupport.h" #include "WorkQueueItem.h" #include "WorkQueue.h" @@ -893,6 +894,11 @@ static void resetWebViewToConsistentStateBeforeTesting() if (SUCCEEDED(webView->preferences(&preferences))) resetDefaultsToConsistentValues(preferences.get()); + if (gLayoutTestController) { + JSGlobalContextRef context = frame->globalContext(); + WebCoreTestSupport::resetInternalsObject(context); + } + COMPtr<IWebViewEditing> viewEditing; if (SUCCEEDED(webView->QueryInterface(&viewEditing))) viewEditing->setSmartInsertDeleteEnabled(TRUE); diff --git a/Tools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/Tools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 123944929..9d03abc77 100644 --- a/Tools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/Tools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -1300,25 +1300,6 @@ void LayoutTestController::removeAllVisitedLinks() sharedHistoryPrivate->removeAllVisitedLinks(); } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - COMPtr<IWebFramePrivate> framePrivate(Query, frame); - if (!framePrivate) - return 0; - - wstring idWstring = jsStringRefToWString(id); - BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length()); - BSTR counterValueBSTR; - if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR))) - return 0; - - wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR)); - SysFreeString(idBSTR); - SysFreeString(counterValueBSTR); - JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length())); - return counterValueJS; -} - int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels) { COMPtr<IWebFramePrivate> framePrivate(Query, frame); diff --git a/Tools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/Tools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index 08d2832ac..e0c05843d 100644 --- a/Tools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/Tools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -472,11 +472,6 @@ void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringR // FIXME: implement } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) -{ - return 0; -} - int LayoutTestController::pageNumberForElementById(JSStringRef, float, float) { // FIXME: implement diff --git a/Tools/EWebLauncher/CMakeLists.txt b/Tools/EWebLauncher/CMakeLists.txt index 3bf709f7d..f2c263f33 100644 --- a/Tools/EWebLauncher/CMakeLists.txt +++ b/Tools/EWebLauncher/CMakeLists.txt @@ -39,8 +39,7 @@ SET(EWebLauncher_LINK_FLAGS ADD_DEFINITIONS(-DDATA_DIR=\"${THEME_BINARY_DIR}\") INCLUDE_DIRECTORIES(${EWebLauncher_INCLUDE_DIRECTORIES}) -ADD_EXECUTABLE(bin/EWebLauncher ${EWebLauncher_SOURCES}) -TARGET_LINK_LIBRARIES(bin/EWebLauncher ${EWebLauncher_LIBRARIES}) -ADD_TARGET_PROPERTIES(bin/EWebLauncher LINK_FLAGS "${EWebLauncher_LINK_FLAGS}") -SET_TARGET_PROPERTIES(bin/EWebLauncher PROPERTIES FOLDER "Tools") -SET_TARGET_PROPERTIES(bin/EWebLauncher PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +ADD_EXECUTABLE(EWebLauncher ${EWebLauncher_SOURCES}) +TARGET_LINK_LIBRARIES(EWebLauncher ${EWebLauncher_LIBRARIES}) +ADD_TARGET_PROPERTIES(EWebLauncher LINK_FLAGS "${EWebLauncher_LINK_FLAGS}") +SET_TARGET_PROPERTIES(EWebLauncher PROPERTIES FOLDER "Tools") diff --git a/Tools/MiniBrowser/efl/CMakeLists.txt b/Tools/MiniBrowser/efl/CMakeLists.txt new file mode 100644 index 000000000..a6fd2d57e --- /dev/null +++ b/Tools/MiniBrowser/efl/CMakeLists.txt @@ -0,0 +1,66 @@ +SET(MiniBrowser_DIR "${TOOLS_DIR}/MiniBrowser/efl") + +SET(MiniBrowser_SOURCES + ${MiniBrowser_DIR}/main.c +) + +SET(MiniBrowser_INCLUDE_DIRECTORIES + ${CAIRO_INCLUDE_DIRS} + ${ECORE_X_INCLUDE_DIRS} + ${EDJE_INCLUDE_DIRS} + ${EFLDEPS_INCLUDE_DIRS} + ${EVAS_INCLUDE_DIRS} + ${WEBKIT2_DIR}/UIProcess/API/efl + ${WEBKIT2_DIR} + ${DERIVED_SOURCES_WEBKIT2_DIR}/include + ${CMAKE_SOURCE_DIR}/Source +) + +SET(MiniBrowser_LIBRARIES + ${JavaScriptCore_LIBRARY_NAME} + ${WebCore_LIBRARY_NAME} + ${WebKit2_LIBRARY_NAME} + ${CAIRO_LIBRARIES} + ${ECORE_X_LIBRARIES} + ${EDJE_LIBRARIES} + ${EFLDEPS_LIBRARIES} + ${EVAS_LIBRARIES} + ${FONTCONFIG_LIBRARIES} + ${LIBSOUP24_LIBRARIES} + ${LIBXML2_LIBRARIES} + ${LIBXSLT_LIBRARIES} + ${SQLITE_LIBRARIES} +) + +SET(MiniBrowser_LINK_FLAGS + ${ECORE_X_LDFLAGS} + ${EDJE_LDFLAGS} + ${EFLDEPS_LDFLAGS} + ${EVAS_LDFLAGS} + ${LIBSOUP24_LDFLAGS} +) + +IF (ENABLE_GLIB_SUPPORT) + LIST(APPEND MiniBrowser_LIBRARIES + ${Glib_LIBRARIES} + ${Gthread_LIBRARIES} + ) +ENDIF () + +ADD_CUSTOM_TARGET(forwarding-headerMiniBrowserEfl + COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl ${MiniBrowser_DIR} ${DERIVED_SOURCES_WEBKIT2_DIR}/include efl +) + +ADD_CUSTOM_TARGET(forwarding-headerMiniBrowserSoup + COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl ${MiniBrowser_DIR} ${DERIVED_SOURCES_WEBKIT2_DIR}/include soup +) + +INCLUDE_DIRECTORIES(${MiniBrowser_INCLUDE_DIRECTORIES}) + +ADD_EXECUTABLE(MiniBrowser ${MiniBrowser_SOURCES}) +TARGET_LINK_LIBRARIES(MiniBrowser ${MiniBrowser_LIBRARIES}) +ADD_TARGET_PROPERTIES(MiniBrowser LINK_FLAGS "${MiniBrowser_LINK_FLAGS}") +SET_TARGET_PROPERTIES(MiniBrowser PROPERTIES FOLDER "Tools") + +ADD_DEPENDENCIES(MiniBrowser forwarding-headerMiniBrowserEfl) +ADD_DEPENDENCIES(MiniBrowser forwarding-headerMiniBrowserSoup) diff --git a/Tools/MiniBrowser/efl/main.c b/Tools/MiniBrowser/efl/main.c new file mode 100644 index 000000000..73c253bea --- /dev/null +++ b/Tools/MiniBrowser/efl/main.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "EWebKit2.h" +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Eina.h> +#include <Evas.h> + +static const int DEFAULT_WIDTH = 800; +static const int DEFAULT_HEIGHT = 600; +static const char DEFAULT_URL[] = "http://www.google.com/"; + +#define info(format, args...) \ + do { \ + if (verbose) \ + printf(format, ##args); \ + } while (0) + +static int verbose = 0; + +typedef struct _MiniBrowser { + Ecore_Evas *ee; + Evas *evas; + Evas_Object *bg; + Evas_Object *browser; +} MiniBrowser; + +static Eina_Bool main_signal_exit(void *data, int ev_type, void *ev) +{ + ecore_main_loop_quit(); + return EINA_TRUE; +} + +static void on_ecore_evas_resize(Ecore_Evas *ee) +{ + Evas_Object *webview; + Evas_Object *bg; + int w, h; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + + bg = evas_object_name_find(ecore_evas_get(ee), "bg"); + evas_object_move(bg, 0, 0); + evas_object_resize(bg, w, h); + + webview = evas_object_name_find(ecore_evas_get(ee), "browser"); + evas_object_move(webview, 0, 0); + evas_object_resize(webview, w, h); +} + +static void +on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info; + if (!strcmp(ev->key, "F1")) { + info("Back (F1) was pressed\n"); + if (!ewk_view_back(obj)) + info("Back ignored: No back history\n"); + } else if (!strcmp(ev->key, "F2")) { + info("Forward (F2) was pressed\n"); + if (!ewk_view_forward(obj)) + info("Forward ignored: No forward history\n"); + } else if (!strcmp(ev->key, "F5")) { + info("Reload (F5) was pressed, reloading.\n"); + ewk_view_reload(obj); + } else if (!strcmp(ev->key, "F6")) { + info("Stop (F6) was pressed, stop loading.\n"); + ewk_view_stop(obj); + } +} + +static void +on_title_changed(void *user_data, Evas_Object *webview, void *event_info) +{ + MiniBrowser *app = (MiniBrowser *)user_data; + const char *title = (const char *)event_info; + + ecore_evas_title_set(app->ee, title); +} + +static MiniBrowser *browserCreate(const char *url) +{ + MiniBrowser *app = malloc(sizeof(MiniBrowser)); + + app->ee = ecore_evas_new(0, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0); + + ecore_evas_title_set(app->ee, "EFL MiniBrowser"); + ecore_evas_callback_resize_set(app->ee, on_ecore_evas_resize); + ecore_evas_borderless_set(app->ee, 0); + ecore_evas_show(app->ee); + + app->evas = ecore_evas_get(app->ee); + + app->bg = evas_object_rectangle_add(app->evas); + evas_object_name_set(app->bg, "bg"); + evas_object_size_hint_weight_set(app->bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + + evas_object_move(app->bg, 0, 0); + evas_object_resize(app->bg, DEFAULT_WIDTH, DEFAULT_HEIGHT); + evas_object_color_set(app->bg, 255, 150, 150, 255); + evas_object_show(app->bg); + + /* Create webview */ + app->browser = ewk_view_add(app->evas); + evas_object_name_set(app->browser, "browser"); + + evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app); + + evas_object_event_callback_add(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, app); + + evas_object_size_hint_weight_set(app->browser, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_resize(app->browser, DEFAULT_WIDTH, DEFAULT_HEIGHT); + evas_object_show(app->browser); + evas_object_focus_set(app->browser, EINA_TRUE); + + ewk_view_uri_set(app->browser, url); + + return app; +} + +int main(int argc, char *argv[]) +{ + const char *url; + int args = 1; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + if (args < argc) + url = argv[args]; + else + url = DEFAULT_URL; + + MiniBrowser *browser = browserCreate(url); + + Ecore_Event_Handler *handle = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, 0); + + ecore_main_loop_begin(); + + ecore_event_handler_del(handle); + ecore_evas_free(browser->ee); + free(browser); + + ecore_evas_shutdown(); + + return 0; +} diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c index 68101667d..cef9e7d46 100644 --- a/Tools/MiniBrowser/gtk/BrowserWindow.c +++ b/Tools/MiniBrowser/gtk/BrowserWindow.c @@ -213,6 +213,21 @@ static void backForwadlistChanged(WebKitBackForwardList *backForwadlist, WebKitB browserWindowUpdateNavigationActions(window, backForwadlist); } +static void geolocationRequestDialogCallback(GtkDialog *dialog, gint response, WebKitPermissionRequest *request) +{ + switch (response) { + case GTK_RESPONSE_YES: + webkit_permission_request_allow(request); + break; + default: + webkit_permission_request_deny(request); + break; + } + + gtk_widget_destroy(GTK_WIDGET(dialog)); + g_object_unref(request); +} + static void webViewClose(WebKitWebView *webView, BrowserWindow *window) { gtk_widget_destroy(GTK_WIDGET(window)); @@ -277,6 +292,24 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision return TRUE; } +static gboolean webViewDecidePermissionRequest(WebKitWebView *webView, WebKitPermissionRequest *request, BrowserWindow *window) +{ + if (!WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request)) + return FALSE; + + GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "Geolocation request"); + + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "Allow geolocation request?"); + g_signal_connect(dialog, "response", G_CALLBACK(geolocationRequestDialogCallback), g_object_ref(request)); + gtk_widget_show(dialog); + + return TRUE; +} + static void webViewMouseTargetChanged(WebKitWebView *webView, WebKitHitTestResult *hitTestResult, guint mouseModifiers, BrowserWindow *window) { if (!webkit_hit_test_result_context_is_link(hitTestResult)) { @@ -434,6 +467,7 @@ static void browserWindowConstructed(GObject *gObject) g_signal_connect(window->webView, "create", G_CALLBACK(webViewCreate), window); g_signal_connect(window->webView, "load-failed", G_CALLBACK(webViewLoadFailed), window); g_signal_connect(window->webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), window); + g_signal_connect(window->webView, "permission-request", G_CALLBACK(webViewDecidePermissionRequest), window); g_signal_connect(window->webView, "mouse-target-changed", G_CALLBACK(webViewMouseTargetChanged), window); g_signal_connect(window->webView, "notify::zoom-level", G_CALLBACK(webViewZoomLevelChanged), window); diff --git a/Tools/MiniBrowser/mac/BrowserWindowController.m b/Tools/MiniBrowser/mac/BrowserWindowController.m index 131bfa4dd..5d465f6cf 100644 --- a/Tools/MiniBrowser/mac/BrowserWindowController.m +++ b/Tools/MiniBrowser/mac/BrowserWindowController.m @@ -612,6 +612,8 @@ static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParameters 0, // willGoToBackForwardListItem 0, // interactionOccurredWhileProcessUnresponsive 0, // pluginDidFail + 0, // didReceiveIntentForFrame + 0, // registerIntentServiceForFrame }; WKPageSetPageLoaderClient(_webView.pageRef, &loadClient); diff --git a/Tools/MiniBrowser/qt/MiniBrowser.qrc b/Tools/MiniBrowser/qt/MiniBrowser.qrc index b5490bec1..37fb9a37c 100644 --- a/Tools/MiniBrowser/qt/MiniBrowser.qrc +++ b/Tools/MiniBrowser/qt/MiniBrowser.qrc @@ -2,6 +2,7 @@ <qresource prefix="/"> <file>icons/checkbox_checked.png</file> <file>icons/checkbox_unchecked.png</file> + <file>icons/contents_width.png</file> <file>icons/favicon.png</file> <file>icons/folder.png</file> <file>icons/info.png</file> diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp index e42c558d2..b85b234e1 100644 --- a/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp +++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp @@ -133,18 +133,6 @@ bool MiniBrowserApplication::notify(QObject* target, QEvent* event) m_holdingControl = mouseEvent->modifiers().testFlag(Qt::ControlModifier); QTouchEvent::TouchPoint touchPoint; - - touchPoint.setRect(touchRectForPosition(mouseEvent->localPos())); - touchPoint.setLastPos(m_lastPos); - m_lastPos = mouseEvent->localPos(); - - // Gesture recognition uses the screen position for the initial threshold - // but since the canvas translates touch events we actually need to pass - // the screen position as the scene position to deliver the appropriate - // coordinates to the target. - touchPoint.setSceneRect(touchRectForPosition(mouseEvent->screenPos())); - touchPoint.setLastScenePos(m_lastScreenPos); - m_lastScreenPos = mouseEvent->screenPos(); touchPoint.setPressure(1); QEvent::Type touchType = QEvent::None; @@ -158,12 +146,15 @@ bool MiniBrowserApplication::notify(QObject* target, QEvent* event) touchType = QEvent::TouchUpdate; } else { touchPoint.setState(Qt::TouchPointPressed); - touchType = QEvent::TouchBegin; - m_startScreenPos = mouseEvent->screenPos(); + // Check if more buttons are held down than just the event triggering one. + if (mouseEvent->buttons() > mouseEvent->button()) + touchType = QEvent::TouchUpdate; + else + touchType = QEvent::TouchBegin; } break; case QEvent::MouseMove: - if (!mouseEvent->buttons() || !m_touchPoints.contains(mouseEvent->buttons())) { + if (!mouseEvent->buttons()) { // We have to swallow the event instead of propagating it, // since we avoid sending the mouse release events and if the // Flickable is the mouse grabber it would receive the event @@ -176,32 +167,37 @@ bool MiniBrowserApplication::notify(QObject* target, QEvent* event) touchPoint.setState(Qt::TouchPointMoved); break; case QEvent::MouseButtonRelease: - touchType = QEvent::TouchEnd; - touchPoint.setState(Qt::TouchPointReleased); + // Check if any buttons are still held down after this event. + if (mouseEvent->buttons()) + touchType = QEvent::TouchUpdate; + else + touchType = QEvent::TouchEnd; touchPoint.setId(mouseEvent->button()); - if (m_holdingControl) { - m_heldTouchPoints.insert(touchPoint.id()); - - // We avoid sending the release event because the Flickable is - // listening to mouse events and would start a bounce-back - // animation if it received a mouse release. - event->accept(); - return true; - } + touchPoint.setState(Qt::TouchPointReleased); break; default: Q_ASSERT_X(false, "multi-touch mocking", "unhandled event type"); } - // Set the screen pos as the scene pos as canvas translates the touch events. - touchPoint.setStartScenePos(m_startScreenPos); - - // Update current touch-point - m_touchPoints.insert(touchPoint.id(), touchPoint); + // A move can have resulted in multiple buttons, so we need check them individually. + if (touchPoint.id() & Qt::LeftButton) + updateTouchPoint(mouseEvent, touchPoint, Qt::LeftButton); + if (touchPoint.id() & Qt::MidButton) + updateTouchPoint(mouseEvent, touchPoint, Qt::MidButton); + if (touchPoint.id() & Qt::RightButton) + updateTouchPoint(mouseEvent, touchPoint, Qt::RightButton); + + if (m_holdingControl && touchPoint.state() == Qt::TouchPointReleased) { + // We avoid sending the release event because the Flickable is + // listening to mouse events and would start a bounce-back + // animation if it received a mouse release. + event->accept(); + return true; + } // Update states for all other touch-points for (QHash<int, QTouchEvent::TouchPoint>::iterator it = m_touchPoints.begin(), end = m_touchPoints.end(); it != end; ++it) { - if (it.value().id() != touchPoint.id()) + if (!(it.value().id() & touchPoint.id())) it.value().setState(Qt::TouchPointStationary); } @@ -217,6 +213,34 @@ bool MiniBrowserApplication::notify(QObject* target, QEvent* event) return QGuiApplication::notify(target, event); } +void MiniBrowserApplication::updateTouchPoint(const QMouseEvent* mouseEvent, QTouchEvent::TouchPoint touchPoint, Qt::MouseButton mouseButton) +{ + if (m_holdingControl && touchPoint.state() == Qt::TouchPointReleased) { + m_heldTouchPoints.insert(mouseButton); + return; + } + // Gesture recognition uses the screen position for the initial threshold + // but since the canvas translates touch events we actually need to pass + // the screen position as the scene position to deliver the appropriate + // coordinates to the target. + touchPoint.setRect(touchRectForPosition(mouseEvent->localPos())); + touchPoint.setSceneRect(touchRectForPosition(mouseEvent->screenPos())); + + if (touchPoint.state() == Qt::TouchPointPressed) + touchPoint.setStartScenePos(mouseEvent->screenPos()); + else { + const QTouchEvent::TouchPoint& oldTouchPoint = m_touchPoints[mouseButton]; + touchPoint.setStartScenePos(oldTouchPoint.startScenePos()); + touchPoint.setLastPos(oldTouchPoint.pos()); + touchPoint.setLastScenePos(oldTouchPoint.scenePos()); + } + + // Update current touch-point. + touchPoint.setId(mouseButton); + m_touchPoints.insert(mouseButton, touchPoint); +} + + bool MiniBrowserApplication::sendTouchEvent(BrowserWindow* browserWindow, QEvent::Type type, ulong timestamp) { static QTouchDevice* device = 0; diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.h b/Tools/MiniBrowser/qt/MiniBrowserApplication.h index e58c9a196..7d3c7a4ae 100644 --- a/Tools/MiniBrowser/qt/MiniBrowserApplication.h +++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.h @@ -101,6 +101,7 @@ public: virtual bool notify(QObject*, QEvent*); private: + void updateTouchPoint(const QMouseEvent*, QTouchEvent::TouchPoint, Qt::MouseButton); bool sendTouchEvent(BrowserWindow*, QEvent::Type, ulong timestamp); void handleUserOptions(); @@ -112,10 +113,6 @@ private: int m_robotExtraTimeSeconds; QStringList m_urls; - QPointF m_lastPos; - QPointF m_lastScreenPos; - QPointF m_startScreenPos; - QHash<int, QTouchEvent::TouchPoint> m_touchPoints; QSet<int> m_heldTouchPoints; diff --git a/Tools/MiniBrowser/qt/icons/contents_width.png b/Tools/MiniBrowser/qt/icons/contents_width.png Binary files differnew file mode 100644 index 000000000..f2a79ebbc --- /dev/null +++ b/Tools/MiniBrowser/qt/icons/contents_width.png diff --git a/Tools/MiniBrowser/qt/qml/BrowserWindow.qml b/Tools/MiniBrowser/qt/qml/BrowserWindow.qml index 0ebf02860..77b6c369f 100644 --- a/Tools/MiniBrowser/qt/qml/BrowserWindow.qml +++ b/Tools/MiniBrowser/qt/qml/BrowserWindow.qml @@ -192,6 +192,27 @@ Rectangle { } Rectangle { + id: preferredMininumContentsWidthButton + height: parent.height + width: height + color: "#efefef" + opacity: { webView.experimental.preferredMinimumContentsWidth === 0 ? 0.1 : 0.6 } + radius: 6 + + Image { + anchors.centerIn: parent + source: "../icons/contents_width.png" + } + + MouseArea { + anchors.fill: parent + onClicked: { + webView.experimental.preferredMinimumContentsWidth = webView.experimental.preferredMinimumContentsWidth === 0 ? 980 : 0 + } + } + } + + Rectangle { id: touchEventsButton height: parent.height width: height @@ -335,6 +356,7 @@ Rectangle { experimental.devicePixelRatio: 1.5 experimental.preferences.fullScreenEnabled: true + experimental.preferences.webGLEnabled: true experimental.preferredMinimumContentsWidth: 980 experimental.itemSelector: ItemSelector { } experimental.alertDialog: AlertDialog { } @@ -379,5 +401,6 @@ Rectangle { } visible: false test : webView.experimental.test + preferredMinimumContentsWidth: webView.experimental.preferredMinimumContentsWidth } } diff --git a/Tools/MiniBrowser/qt/qml/ViewportInfoItem.qml b/Tools/MiniBrowser/qt/qml/ViewportInfoItem.qml index 88ac01275..15fd97f79 100644 --- a/Tools/MiniBrowser/qt/qml/ViewportInfoItem.qml +++ b/Tools/MiniBrowser/qt/qml/ViewportInfoItem.qml @@ -1,84 +1,136 @@ import QtQuick 2.0 import QtWebKit 3.0 -Rectangle { +Item { property var test + property var preferredMinimumContentsWidth - color: "black" - opacity: 0.8 + function formatScale(value) { + return "<b>" + parseFloat(value.toFixed(4)) + "</b>x"; + } - Item { - anchors.fill: parent - anchors.margins: 20 + function formatSize(value) { + return "<b>" + value.width.toFixed() + "x" + value.height.toFixed() + "</b>px" + } - property string fontFamily: "Nokia Pure, Helvetica" - property color fontColor: "white" + function formatBool(value) { + return "<b>" + (value ? "yes" : "no") + "</b>" + } + + Rectangle { + id: title; + + anchors { + top: parent.top + left: parent.left + margins: 10 + } + + height: 50 + width: 250 + + color: "blue" Text { id: viewportInfoLabel + + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 10 + } + text: "Viewport Info" color: "white" - font.family: "Nokia Pure, Helvetica" + font.family: "Nokia Pure" font.pointSize: 24 } - Text { - id: currentScaleLabel - anchors.top: viewportInfoLabel.bottom - anchors.topMargin: 30 - text: "Current scale: " + parseFloat(test.contentsScale.toFixed(4)) - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: initialScaleLabel - anchors.top: currentScaleLabel.bottom - text: "Initial scale: " + parseFloat(test.initialScale.toFixed(4)) - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: minimumScaleLabel - anchors.top: initialScaleLabel.bottom - text: "Minimum scale: " + parseFloat(test.minimumScale.toFixed(4)) - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: maximumScaleLabel - anchors.top: minimumScaleLabel.bottom - text: "Maximum scale: " + parseFloat(test.maximumScale.toFixed(4)) - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: devicePixelRatioLabel - anchors.top: maximumScaleLabel.bottom - anchors.topMargin: 30 - text: "Device pixel ratio: " + parseFloat(test.devicePixelRatio.toFixed(4)) - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: contentsSizeLabel - anchors.top: devicePixelRatioLabel.bottom - text: "Contents size: " + test.contentsSize.width + "x" + test.contentsSize.height - font.family: parent.fontFamily - color: parent.fontColor - } - Text { - id: layoutSizeLabel - anchors.top: contentsSizeLabel.bottom - text: "Viewport layout size: " + test.layoutSize.width + "x" + test.layoutSize.height - font.family: parent.fontFamily - color: parent.fontColor + } + + Rectangle { + color: "gray" + opacity: 0.9 + + anchors { + top: title.bottom + left: title.left + topMargin: 10 } - Text { - id: scalableLabel - anchors.top: layoutSizeLabel.bottom - anchors.topMargin: 30 - text: "View " + (test.isScalable ? "is " : "is not " ) + "scalable." - font.family: parent.fontFamily - color: parent.fontColor + + width: 340 + height: 270 + + Item { + id: textBox + + anchors { + fill: parent + margins: 10 + } + + property string fontFamily: "Nokia Pure" + property color fontColor: "black" + + Column { + anchors.fill: parent + spacing: 20 + Column { + Text { + text: "Current scale: " + formatScale(test.contentsScale) + font.family: textBox.fontFamily + color: textBox.fontColor + } + } + + Column { + Text { + text: "Initial scale: " + formatScale(test.initialScale) + font.family: textBox.fontFamily + color: textBox.fontColor + } + Text { + text: "Minimum scale: " + formatScale(test.minimumScale) + font.family: textBox.fontFamily + color: textBox.fontColor + } + Text { + text: "Maximum scale: " + formatScale(test.maximumScale) + font.family: textBox.fontFamily + color: textBox.fontColor + } + } + + Column { + Text { + text: "Device pixel ratio: " + formatScale(test.devicePixelRatio) + font.family: textBox.fontFamily + color: textBox.fontColor + } + Text { + text: "Contents size: " + formatSize(test.contentsSize) + font.family: textBox.fontFamily + color: textBox.fontColor + } + Text { + text: "Viewport layout size: " + formatSize(test.layoutSize) + font.family: textBox.fontFamily + color: textBox.fontColor + } + } + + Column { + Text { + text: "Adapt for small screens: " + formatBool(preferredMinimumContentsWidth) + font.family: textBox.fontFamily + color: textBox.fontColor + } + Text { + text: "Allows scaling: " + formatBool(test.isScalable) + font.family: textBox.fontFamily + color: textBox.fontColor + } + } + } } } } diff --git a/Tools/QtTestBrowser/QtTestBrowser.pro b/Tools/QtTestBrowser/QtTestBrowser.pro index 6d8a41b72..3bff49062 100644 --- a/Tools/QtTestBrowser/QtTestBrowser.pro +++ b/Tools/QtTestBrowser/QtTestBrowser.pro @@ -17,7 +17,7 @@ SOURCES += \ $${ROOT_WEBKIT_DIR}/Tools/DumpRenderTree/qt/QtInitializeTestFonts.cpp \ locationedit.cpp \ launcherwindow.cpp \ - main.cpp \ + qttestbrowser.cpp \ mainwindow.cpp \ urlloader.cpp \ utils.cpp \ diff --git a/Tools/QtTestBrowser/main.cpp b/Tools/QtTestBrowser/qttestbrowser.cpp index 34852910b..ab4bc70d4 100644 --- a/Tools/QtTestBrowser/main.cpp +++ b/Tools/QtTestBrowser/qttestbrowser.cpp @@ -318,4 +318,4 @@ int main(int argc, char **argv) return launcherMain(app); } -#include "main.moc" +#include "qttestbrowser.moc" diff --git a/Tools/Scripts/VCSUtils.pm b/Tools/Scripts/VCSUtils.pm index b4b15a8df..dd404ce00 100644 --- a/Tools/Scripts/VCSUtils.pm +++ b/Tools/Scripts/VCSUtils.pm @@ -444,6 +444,7 @@ sub adjustPathForRecentRenamings($) $fullPath =~ s|WebCore/webaudio|WebCore/Modules/webaudio|g; $fullPath =~ s|JavaScriptCore/wtf|WTF/wtf|g; + $fullPath =~ s|test_expectations.txt|TestExpectations|g; return $fullPath; } @@ -1461,6 +1462,8 @@ sub fixChangeLogPatch($) { my $patch = shift; # $patch will only contain patch fragments for ChangeLog. + $patch =~ s|test_expectations.txt:|TestExpectations:|g; + $patch =~ /(\r?\n)/; my $lineEnding = $1; my @lines = split(/$lineEnding/, $patch); diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit index 20595244b..8ade40890 100755 --- a/Tools/Scripts/build-webkit +++ b/Tools/Scripts/build-webkit @@ -183,8 +183,10 @@ File::Find::find(\&unlinkZeroFiles, $productDir) if (isQt() && -e $productDir); sub unlinkZeroFiles() { my $file = $File::Find::name; - # Remove 0 size files, except .d files used for dependency tracking - if (! -s $file && $file !~ m/\.d$/) { + # Remove 0 byte sized files, except + # - directories (Because they are always 0 byte sized on Windows) + # - .d files used for dependency tracking + if (! -d $file && ! -s $file && $file !~ m/\.d$/) { unlink $file; print "0 byte sized file removed from build directory: $file\n"; } @@ -324,6 +326,8 @@ if (isChromium()) { if (isEfl()) { # By default we build using all of the available CPUs. $makeArgs .= ($makeArgs ? " " : "") . "-j" . numberOfCPUs() if $makeArgs !~ /-j\s*\d+/; + $cmakeArgs .= ($cmakeArgs ? " " : "") . "-DENABLE_WEBKIT=ON"; + $cmakeArgs .= " -DENABLE_WEBKIT2=ON" if !$noWebKit2; buildCMakeProjectOrExit($clean, "Efl", $prefixPath, $makeArgs, (cmakeBasedPortArguments(), cMakeArgsFromFeatures()), $cmakeArgs); } diff --git a/Tools/Scripts/generate-project-files b/Tools/Scripts/generate-project-files deleted file mode 100755 index 60a32e191..000000000 --- a/Tools/Scripts/generate-project-files +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/perl -w - -# Copyright (C) 2011 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of -# its contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use strict; -use FindBin; -use lib $FindBin::Bin; -use webkitdirs; - -chdirWebKit(); - -# This simple wrapper exists so that the configure logic can live in the Source directory. -# This allows building from Source without a copy of Tools (as Apple's internal builds do). -system("python", "Source/gyp/configure", @ARGV) == 0 or die "Failed to run Source/gyp/configure"; diff --git a/Tools/Scripts/new-run-webkit-websocketserver b/Tools/Scripts/new-run-webkit-websocketserver index b888004fe..15ed1f99e 100755 --- a/Tools/Scripts/new-run-webkit-websocketserver +++ b/Tools/Scripts/new-run-webkit-websocketserver @@ -55,6 +55,9 @@ def main(): default='', help='TLS private key file.') option_parser.add_option('-c', '--certificate', dest='certificate', default='', help='TLS certificate file.') + option_parser.add_option('--ca-certificate', dest='ca_certificate', + default='', help='TLS CA certificate file for ' + 'client authentication.') option_parser.add_option('--chromium', action='store_true', dest='chromium', default=False, @@ -88,6 +91,8 @@ def main(): kwds['private_key'] = options.private_key if options.certificate: kwds['certificate'] = options.certificate + if options.ca_certificate: + kwds['ca_certificate'] = options.ca_certificate if options.pidfile: kwds['pidfile'] = options.pidfile diff --git a/Tools/Scripts/run-perf-tests b/Tools/Scripts/run-perf-tests index 95e04a0d3..8eebedfad 100755 --- a/Tools/Scripts/run-perf-tests +++ b/Tools/Scripts/run-perf-tests @@ -36,4 +36,8 @@ from webkitpy.performance_tests.perftestsrunner import PerfTestsRunner if '__main__' == __name__: logging.basicConfig(level=logging.INFO, format="%(message)s") + + if sys.platform == 'win32': + _log.error("run-perf-tests doesn't work on win32; needs webpagereplay support.") + sys.exit(1) sys.exit(PerfTestsRunner().run()) diff --git a/Tools/Scripts/run-qtwebkit-tests b/Tools/Scripts/run-qtwebkit-tests index 288bd57d6..ded87c5fa 100755 --- a/Tools/Scripts/run-qtwebkit-tests +++ b/Tools/Scripts/run-qtwebkit-tests @@ -154,6 +154,8 @@ def run_test(args): else: test_suite.set_output(tst.communicate()[0]) # takes stdout only, in developer mode it would be None. log.info("Finished %s", test_suite.test_file_name()) + if timeout: + timer.cancel() return test_suite diff --git a/Tools/Scripts/update-webkit-dependency b/Tools/Scripts/update-webkit-dependency index 075691229..71d46728f 100755 --- a/Tools/Scripts/update-webkit-dependency +++ b/Tools/Scripts/update-webkit-dependency @@ -76,16 +76,26 @@ print "Checking Last-Modified date of $zipFile...\n"; my $result = system "curl -s -I -k --sslv3 $libsURL | grep Last-Modified > \"$tmpAbsDir/$file.headers\""; if (WEXITSTATUS($result)) { - print STDERR "Couldn't check Last-Modified date of new $zipFile.\n"; - print STDERR "Please ensure that $libsURL is reachable.\n"; - if (! -f "$webkitLibrariesDir/$file.headers") { - print STDERR "Unable to check Last-Modified date and no version of $file to fall back to.\n"; - exit 1; - } + #Note: Neither GitHub nor DropBox emit the Last-Modified HTTP header, so fall back to a file + #containing the necessary information if we do not receive the information in our initial query. + my $headerURL = $libsURL; + $headerURL =~ s/\.zip$/\.headers/; + + $result = system "curl -k --sslv3 -o \"$tmpAbsDir/$file.headers\" $headerURL"; + + if (WEXITSTATUS($result)) { + print STDERR "Couldn't check Last-Modified date of new $zipFile.\n"; + print STDERR "Please ensure that $libsURL is reachable.\n"; - print STDERR "Falling back to existing version of $file.\n"; - exit 0; + if (! -f "$webkitLibrariesDir/$file.headers") { + print STDERR "Unable to check Last-Modified date and no version of $file to fall back to.\n"; + exit 1; + } + + print STDERR "Falling back to existing version of $file.\n"; + exit 0; + } } if (open NEW, "$tmpAbsDir/$file.headers") { diff --git a/Tools/Scripts/update-webkit-wincairo-libs b/Tools/Scripts/update-webkit-wincairo-libs index 15c718275..52d052e72 100755 --- a/Tools/Scripts/update-webkit-wincairo-libs +++ b/Tools/Scripts/update-webkit-wincairo-libs @@ -1,5 +1,6 @@ #!/usr/bin/perl -w +# Copyright (C) 2012 Brent Fulgham <bfulgham@webkit.org>. All rights reserved. # Copyright (C) 2011 Carl Lobo. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,8 +34,8 @@ use warnings; use FindBin; my $file = "WinCairoRequirements"; -my $zipFile = "$file.zip"; -my $winCairoLibsURL = "http://idisk.mac.com/bfulgham-Public/$zipFile"; +my $zipFile = "$file.zip"; +my $winCairoLibsURL = "http://dl.dropbox.com/u/39598926/$zipFile"; my $command = "$FindBin::Bin/update-webkit-dependency"; system("perl", $command, $winCairoLibsURL, ".") == 0 or die; diff --git a/Tools/Scripts/webkitdirs.pm b/Tools/Scripts/webkitdirs.pm index b728bad0b..366d22923 100755 --- a/Tools/Scripts/webkitdirs.pm +++ b/Tools/Scripts/webkitdirs.pm @@ -1892,9 +1892,10 @@ sub jhbuildConfigurationChanged() return 1; } - # Get the md5 sum of the file we're testing. + # Get the md5 sum of the file we're testing, look in the right platform directory. $file =~ m/(.+)\.md5sum/; - my $actualFile = join('/', $sourceDir, 'Tools', 'gtk', $1); + my $platformDir = isEfl() ? 'efl' : 'gtk'; + my $actualFile = join('/', $sourceDir, 'Tools', $platformDir, $1); my $currentSum = getMD5HashForFile($actualFile); # Get our previous record. @@ -1908,6 +1909,33 @@ sub jhbuildConfigurationChanged() } } +sub saveJhbuildMd5() { + my $platform = isEfl() ? 'efl' : 'gtk'; + # Save md5sum for jhbuild-related files. + foreach my $file (qw(jhbuildrc jhbuild.modules)) { + my $source = join('/', $sourceDir, "Tools", $platform, $file); + my $destination = join('/', getJhbuildPath(), $file); + open(SUM, ">$destination" . ".md5sum"); + print SUM getMD5HashForFile($source); + close(SUM); + } +} + +sub cleanJhbuild() { + # If the configuration changed, dependencies may have been removed. + # Since we lack a granular way of uninstalling those we wipe out the + # jhbuild root and start from scratch. + my $jhbuildPath = getJhbuildPath(); + if (system("rm -rf $jhbuildPath/Root") ne 0) { + die "Cleaning jhbuild root failed!"; + } + + my $platform = isEfl() ? 'efl' : 'gtk'; + if (system("perl $sourceDir/Tools/jhbuild/jhbuild-wrapper --$platform clean") ne 0) { + die "Cleaning jhbuild modules failed!"; + } +} + sub mustReRunAutogen($@) { my ($sourceDir, $filename, @currentArguments) = @_; @@ -1997,18 +2025,7 @@ sub buildAutotoolsProject($@) # We might need to update jhbuild dependencies. my $needUpdate = 0; if (jhbuildConfigurationChanged()) { - # If the configuration changed, dependencies may have been removed. - # Since we lack a granular way of uninstalling those we wipe out the - # jhbuild root and start from scratch. - my $jhbuildPath = getJhbuildPath(); - if (system("rm -rf $jhbuildPath/Root") ne 0) { - die "Cleaning jhbuild root failed!"; - } - - if (system("perl $sourceDir/Tools/jhbuild/jhbuild-wrapper --gtk clean") ne 0) { - die "Cleaning jhbuild modules failed!"; - } - + cleanJhbuild(); $needUpdate = 1; } @@ -2023,14 +2040,7 @@ sub buildAutotoolsProject($@) system("perl", "$sourceDir/Tools/Scripts/update-webkitgtk-libs") == 0 or die $!; } - # Save md5sum for jhbuild-related files. - foreach my $file (qw(jhbuildrc jhbuild.modules)) { - my $source = join('/', $sourceDir, "Tools", "gtk", $file); - my $destination = join('/', getJhbuildPath(), $file); - open(SUM, ">$destination" . ".md5sum"); - print SUM getMD5HashForFile($source); - close(SUM); - } + saveJhbuildMd5(); # If GNUmakefile exists, don't run autogen.sh unless its arguments # have changed. The makefile should be smart enough to track autotools @@ -2095,6 +2105,21 @@ sub generateBuildSystemFromCMakeProject $ENV{'CXXFLAGS'} = "-march=pentium4 -msse2 -mfpmath=sse " . ($ENV{'CXXFLAGS'} || ""); } + if (isEfl() && jhbuildConfigurationChanged()) { + cleanJhbuild(); + system("perl", "$sourceDir/Tools/Scripts/update-webkitefl-libs") == 0 or die $!; + } + + if (isEfl()) { + saveJhbuildMd5(); + } + + # Remove CMakeCache.txt to avoid using outdated build flags + if (isEfl()) { + my $cacheFilePath = File::Spec->catdir($buildPath, "CMakeCache.txt"); + unlink($cacheFilePath) if -e $cacheFilePath; + } + # We call system("cmake @args") instead of system("cmake", @args) so that @args is # parsed for shell metacharacters. my $wrapper = jhbuildWrapperPrefixIfNeeded() . " "; diff --git a/Tools/Scripts/webkitperl/FeatureList.pm b/Tools/Scripts/webkitperl/FeatureList.pm index e96851f09..9fbae3ec7 100644 --- a/Tools/Scripts/webkitperl/FeatureList.pm +++ b/Tools/Scripts/webkitperl/FeatureList.pm @@ -48,13 +48,16 @@ my ( $batteryStatusSupport, $blobSupport, $channelMessagingSupport, + $cspNextSupport, $css3FlexboxSupport, + $cssBoxDecorationBreakSupport, $cssExclusionsSupport, $cssFiltersSupport, $cssImageResolutionSupport, $cssRegionsSupport, $cssShadersSupport, $cssVariablesSupport, + $customSchemeHandlerSupport, $dataTransferItemsSupport, $datalistSupport, $detailsSupport, @@ -116,6 +119,7 @@ my ( $tiledBackingStoreSupport, $touchEventsSupport, $touchIconLoadingSupport, + $undoManagerSupport, $vibrationSupport, $videoSupport, $videoTrackSupport, @@ -146,6 +150,9 @@ my @features = ( { option => "channel-messaging", desc => "Toggle Channel Messaging support", define => "ENABLE_CHANNEL_MESSAGING", default => 1, value => \$channelMessagingSupport }, + { option => "csp-next", desc => "Toggle Content Security Policy 1.1 support", + define => "ENABLE_CSP_NEXT", default => 0, value => \$cspNextSupport }, + { option => "css-exclusions", desc => "Toggle CSS Exclusions support", define => "ENABLE_CSS_EXCLUSIONS", default => 1, value => \$cssExclusionsSupport }, @@ -155,6 +162,9 @@ my @features = ( { option => "css3-flexbox", desc => "Toggle CSS3 Flexbox support", define => "ENABLE_CSS3_FLEXBOX", default => 1, value => \$css3FlexboxSupport }, + { option => "css-box-decoration-break", desc => "Toggle CSS box-decoration-break support", + define => "ENABLE_CSS_BOX_DECORATION_BREAK", default => 1, value => \$cssBoxDecorationBreakSupport }, + { option => "css-image-resolution", desc => "Toggle CSS image-resolution support", define => "ENABLE_CSS_IMAGE_RESOLUTION", default => 0, value => \$cssImageResolutionSupport }, @@ -167,6 +177,9 @@ my @features = ( { option => "css-variables", desc => "Toggle CSS Variable support", define => "ENABLE_CSS_VARIABLES", default => 0, value => \$cssVariablesSupport }, + { option => "custom-scheme-handler", desc => "Toggle Custom Scheme Handler support", + define => "ENABLE_CUSTOM_SCHEME_HANDLER", default => 0, value => \$customSchemeHandlerSupport }, + { option => "datalist", desc => "Toggle Datalist support", define => "ENABLE_DATALIST", default => 0, value => \$datalistSupport }, @@ -252,10 +265,10 @@ my @features = ( define => "ENABLE_LEGACY_NOTIFICATIONS", default => isBlackBerry(), value => \$legacyNotificationsSupport }, { option => "legacy-webkit-blob-builder", desc => "Toggle Legacy WebKit Blob Builder support", - define => "ENABLE_LEGACY_WEBKIT_BLOB_BUILDER", default => (isGtk() || isChromium() || isBlackBerry()), value => \$legacyWebKitBlobBuilderSupport }, + define => "ENABLE_LEGACY_WEBKIT_BLOB_BUILDER", default => (isGtk() || isChromium() || isBlackBerry() || isEfl()), value => \$legacyWebKitBlobBuilderSupport }, { option => "link-prefetch", desc => "Toggle Link Prefetch support", - define => "ENABLE_LINK_PREFETCH", default => 0, value => \$linkPrefetchSupport }, + define => "ENABLE_LINK_PREFETCH", default => isGtk(), value => \$linkPrefetchSupport }, { option => "link-prerender", desc => "Toggle Link Prerender support", define => "ENABLE_LINK_PRERENDER", default => 0, value => \$linkPrerenderSupport }, @@ -270,7 +283,7 @@ my @features = ( define => "ENABLE_MEDIA_STATISTICS", default => 0, value => \$mediaStatisticsSupport }, { option => "media-stream", desc => "Toggle Media Stream support", - define => "ENABLE_MEDIA_STREAM", default => (isChromium() || isGtk()), value => \$mediaStreamSupport }, + define => "ENABLE_MEDIA_STREAM", default => (isChromium() || isGtk() || isBlackBerry()), value => \$mediaStreamSupport }, { option => "meter-tag", desc => "Toggle Meter Tag support", define => "ENABLE_METER_TAG", default => !isAppleWinWebKit(), value => \$meterTagSupport }, @@ -315,7 +328,7 @@ my @features = ( define => "ENABLE_SCRIPTED_SPEECH", default => 0, value => \$scriptedSpeechSupport }, { option => "shadow-dom", desc => "Toggle Shadow DOM support", - define => "ENABLE_SHADOW_DOM", default => isGtk(), value => \$shadowDOMSupport }, + define => "ENABLE_SHADOW_DOM", default => (isGtk() || isEfl()), value => \$shadowDOMSupport }, { option => "shared-workers", desc => "Toggle Shared Workers support", define => "ENABLE_SHARED_WORKERS", default => (isAppleWebKit() || isGtk() || isBlackBerry() || isEfl()), value => \$sharedWorkersSupport }, @@ -347,6 +360,9 @@ my @features = ( { option => "touch-icon-loading", desc => "Toggle Touch Icon Loading Support", define => "ENABLE_TOUCH_ICON_LOADING", default => 0, value => \$touchIconLoadingSupport }, + { option => "undo-manager", desc => "Toggle Undo Manager support", + define => "ENABLE_UNDO_MANAGER", default => 0, value => \$undoManagerSupport }, + { option => "vibration", desc => "Toggle Vibration support", define => "ENABLE_VIBRATION", default => (isEfl() || isBlackBerry()), value => \$vibrationSupport }, diff --git a/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py b/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py index 82a637f08..b70e5d06f 100644 --- a/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py +++ b/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py @@ -78,13 +78,13 @@ class BaselineOptimizerTest(unittest.TestCase): def test_no_add_mac_future(self): self._assertOptimization({ 'LayoutTests/platform/mac': '29a1715a6470d5dd9486a142f609708de84cdac8', - 'LayoutTests/platform/win': '453e67177a75b2e79905154ece0efba6e5bfb65d', - 'LayoutTests/platform/mac-snowleopard': 'c43eaeb358f49d5e835236ae23b7e49d7f2b089f', + 'LayoutTests/platform/win-xp': '453e67177a75b2e79905154ece0efba6e5bfb65d', + 'LayoutTests/platform/mac-lion': 'c43eaeb358f49d5e835236ae23b7e49d7f2b089f', 'LayoutTests/platform/chromium-mac': 'a9ba153c700a94ae1b206d8e4a75a621a89b4554', }, { 'LayoutTests/platform/mac': '29a1715a6470d5dd9486a142f609708de84cdac8', - 'LayoutTests/platform/win': '453e67177a75b2e79905154ece0efba6e5bfb65d', - 'LayoutTests/platform/mac-snowleopard': 'c43eaeb358f49d5e835236ae23b7e49d7f2b089f', + 'LayoutTests/platform/win-xp': '453e67177a75b2e79905154ece0efba6e5bfb65d', + 'LayoutTests/platform/mac-lion': 'c43eaeb358f49d5e835236ae23b7e49d7f2b089f', 'LayoutTests/platform/chromium-mac': 'a9ba153c700a94ae1b206d8e4a75a621a89b4554', }) @@ -107,9 +107,9 @@ class BaselineOptimizerTest(unittest.TestCase): def test_mac_future(self): self._assertOptimization({ - 'LayoutTests/platform/mac-snowleopard': '462d03b9c025db1b0392d7453310dbee5f9a9e74', + 'LayoutTests/platform/mac-lion': '462d03b9c025db1b0392d7453310dbee5f9a9e74', }, { - 'LayoutTests/platform/mac-snowleopard': '462d03b9c025db1b0392d7453310dbee5f9a9e74', + 'LayoutTests/platform/mac-lion': '462d03b9c025db1b0392d7453310dbee5f9a9e74', }) def test_qt_unknown(self): @@ -154,17 +154,17 @@ class BaselineOptimizerTest(unittest.TestCase): 'LayoutTests/platform/mac': '5daa78e55f05d9f0d1bb1f32b0cd1bc3a01e9364', 'LayoutTests/platform/chromium-win-xp': '462d03b9c025db1b0392d7453310dbee5f9a9e74', 'LayoutTests/platform/chromium-mac-leopard': '65e7d42f8b4882b29d46dc77bb879dd41bc074dc', - 'LayoutTests/platform/mac-leopard': '7ad045ece7c030e2283c5d21d9587be22bcba56e', + 'LayoutTests/platform/mac-lion': '7ad045ece7c030e2283c5d21d9587be22bcba56e', 'LayoutTests/platform/chromium-win-vista': 'f83af9732ce74f702b8c9c4a3d9a4c6636b8d3bd', - 'LayoutTests/platform/win': '5b1253ef4d5094530d5f1bc6cdb95c90b446bec7', + 'LayoutTests/platform/win-xp': '5b1253ef4d5094530d5f1bc6cdb95c90b446bec7', 'LayoutTests/platform/chromium-linux': 'f52fcdde9e4be8bd5142171cd859230bd4471036', }, { 'LayoutTests/platform/chromium-win': '462d03b9c025db1b0392d7453310dbee5f9a9e74', 'LayoutTests/platform/mac': '5daa78e55f05d9f0d1bb1f32b0cd1bc3a01e9364', 'LayoutTests/platform/chromium-win-xp': '462d03b9c025db1b0392d7453310dbee5f9a9e74', 'LayoutTests/platform/chromium-mac-leopard': '65e7d42f8b4882b29d46dc77bb879dd41bc074dc', - 'LayoutTests/platform/mac-leopard': '7ad045ece7c030e2283c5d21d9587be22bcba56e', + 'LayoutTests/platform/mac-lion': '7ad045ece7c030e2283c5d21d9587be22bcba56e', 'LayoutTests/platform/chromium-win-vista': 'f83af9732ce74f702b8c9c4a3d9a4c6636b8d3bd', - 'LayoutTests/platform/win': '5b1253ef4d5094530d5f1bc6cdb95c90b446bec7', + 'LayoutTests/platform/win-xp': '5b1253ef4d5094530d5f1bc6cdb95c90b446bec7', 'LayoutTests/platform/chromium-linux': 'f52fcdde9e4be8bd5142171cd859230bd4471036' }) diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/Tools/Scripts/webkitpy/common/checkout/scm/git.py index 43fdb9c00..802d81db0 100644 --- a/Tools/Scripts/webkitpy/common/checkout/scm/git.py +++ b/Tools/Scripts/webkitpy/common/checkout/scm/git.py @@ -61,6 +61,8 @@ class Git(SCM, SVNRepository): # 1 or 128, mostly. ERROR_FILE_IS_MISSING = 128 + executable_name = 'git' + def __init__(self, cwd, **kwargs): SCM.__init__(self, cwd, **kwargs) self._check_git_architecture() @@ -89,7 +91,7 @@ class Git(SCM, SVNRepository): # We could path-search entirely in python or with # which.py (http://code.google.com/p/which), but this is easier: - git_path = self.run(['which', 'git']).rstrip() + git_path = self.run(['which', self.executable_name]).rstrip() if self._executable_is_64bit(git_path): return @@ -100,14 +102,14 @@ class Git(SCM, SVNRepository): def in_working_directory(cls, path): try: # FIXME: This should use an Executive. - return run_command(['git', 'rev-parse', '--is-inside-work-tree'], cwd=path, error_handler=Executive.ignore_error).rstrip() == "true" + return run_command([cls.executable_name, 'rev-parse', '--is-inside-work-tree'], cwd=path, error_handler=Executive.ignore_error).rstrip() == "true" except OSError, e: # The Windows bots seem to through a WindowsError when git isn't installed. return False def find_checkout_root(self, path): # "git rev-parse --show-cdup" would be another way to get to the root - git_output = self._executive.run_command(['git', 'rev-parse', '--git-dir'], cwd=(path or "./")) + git_output = self._executive.run_command([self.executable_name, 'rev-parse', '--git-dir'], cwd=(path or "./")) (checkout_root, dot_git) = self._filesystem.split(git_output) if not self._filesystem.isabs(checkout_root): # Sometimes git returns relative paths checkout_root = self._filesystem.join(path, checkout_root) @@ -125,7 +127,7 @@ class Git(SCM, SVNRepository): # Pass --get-all for cases where the config has multiple values # Pass the cwd if provided so that we can handle the case of running webkit-patch outside of the working directory. # FIXME: This should use an Executive. - return run_command(["git", "config", "--get-all", key], error_handler=Executive.ignore_error, cwd=cwd).rstrip('\n') + return run_command([cls.executable_name, "config", "--get-all", key], error_handler=Executive.ignore_error, cwd=cwd).rstrip('\n') @staticmethod def commit_success_regexp(): @@ -133,48 +135,48 @@ class Git(SCM, SVNRepository): def discard_local_commits(self): # FIXME: This should probably use cwd=self.checkout_root - self.run(['git', 'reset', '--hard', self.remote_branch_ref()]) + self.run([self.executable_name, 'reset', '--hard', self.remote_branch_ref()]) def local_commits(self): - return self.run(['git', 'log', '--pretty=oneline', 'HEAD...' + self.remote_branch_ref()], cwd=self.checkout_root).splitlines() + return self.run([self.executable_name, 'log', '--pretty=oneline', 'HEAD...' + self.remote_branch_ref()], cwd=self.checkout_root).splitlines() def rebase_in_progress(self): return self._filesystem.exists(self.absolute_path(self._filesystem.join('.git', 'rebase-apply'))) def working_directory_is_clean(self): - return self.run(['git', 'diff', 'HEAD', '--no-renames', '--name-only'], cwd=self.checkout_root) == "" + return self.run([self.executable_name, 'diff', 'HEAD', '--no-renames', '--name-only'], cwd=self.checkout_root) == "" def clean_working_directory(self): # FIXME: These should probably use cwd=self.checkout_root. # Could run git clean here too, but that wouldn't match working_directory_is_clean - self.run(['git', 'reset', '--hard', 'HEAD']) + self.run([self.executable_name, 'reset', '--hard', 'HEAD']) # Aborting rebase even though this does not match working_directory_is_clean if self.rebase_in_progress(): - self.run(['git', 'rebase', '--abort']) + self.run([self.executable_name, 'rebase', '--abort']) def status_command(self): # git status returns non-zero when there are changes, so we use git diff name --name-status HEAD instead. # No file contents printed, thus utf-8 autodecoding in self.run is fine. - return ["git", "diff", "--name-status", "--no-renames", "HEAD"] + return [self.executable_name, "diff", "--name-status", "--no-renames", "HEAD"] def _status_regexp(self, expected_types): return '^(?P<status>[%s])\t(?P<filename>.+)$' % expected_types def add_list(self, paths, return_exit_code=False): - return self.run(["git", "add"] + paths, return_exit_code=return_exit_code) + return self.run([self.executable_name, "add"] + paths, return_exit_code=return_exit_code) def delete_list(self, paths): - return self.run(["git", "rm", "-f"] + paths) + return self.run([self.executable_name, "rm", "-f"] + paths) def exists(self, path): - return_code = self.run(["git", "show", "HEAD:%s" % path], return_exit_code=True, decode_output=False) + return_code = self.run([self.executable_name, "show", "HEAD:%s" % path], return_exit_code=True, decode_output=False) return return_code != self.ERROR_FILE_IS_MISSING def _branch_from_ref(self, ref): return ref.replace('refs/heads/', '') def _current_branch(self): - return self._branch_from_ref(self.run(['git', 'symbolic-ref', '-q', 'HEAD'], cwd=self.checkout_root).strip()) + return self._branch_from_ref(self.run([self.executable_name, 'symbolic-ref', '-q', 'HEAD'], cwd=self.checkout_root).strip()) def _upstream_branch(self): current_branch = self._current_branch() @@ -201,14 +203,14 @@ class Git(SCM, SVNRepository): def changed_files(self, git_commit=None): # FIXME: --diff-filter could be used to avoid the "extract_filenames" step. - status_command = ['git', 'diff', '-r', '--name-status', "--no-renames", "--no-ext-diff", "--full-index", self.merge_base(git_commit)] + status_command = [self.executable_name, 'diff', '-r', '--name-status', "--no-renames", "--no-ext-diff", "--full-index", self.merge_base(git_commit)] # FIXME: I'm not sure we're returning the same set of files that SVN.changed_files is. # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) return self.run_status_and_extract_filenames(status_command, self._status_regexp("ADM")) def _changes_files_for_commit(self, git_commit): # --pretty="format:" makes git show not print the commit log header, - changed_files = self.run(["git", "show", "--pretty=format:", "--name-only", git_commit]).splitlines() + changed_files = self.run([self.executable_name, "show", "--pretty=format:", "--name-only", git_commit]).splitlines() # instead it just prints a blank line at the top, so we skip the blank line: return changed_files[1:] @@ -222,13 +224,13 @@ class Git(SCM, SVNRepository): raise ScriptError(message="Path %s does not exist." % path) # git rev-list head --remove-empty --limit=5 -- path would be equivalent. - commit_ids = self.run(["git", "log", "--remove-empty", "--pretty=format:%H", "-%s" % limit, "--", path]).splitlines() + commit_ids = self.run([self.executable_name, "log", "--remove-empty", "--pretty=format:%H", "-%s" % limit, "--", path]).splitlines() return filter(lambda revision: revision, map(self.svn_revision_from_git_commit, commit_ids)) def conflicted_files(self): # We do not need to pass decode_output for this diff command # as we're passing --name-status which does not output any data. - status_command = ['git', 'diff', '--name-status', '--no-renames', '--diff-filter=U'] + status_command = [self.executable_name, 'diff', '--name-status', '--no-renames', '--diff-filter=U'] return self.run_status_and_extract_filenames(status_command, self._status_regexp("U")) def added_files(self): @@ -246,7 +248,7 @@ class Git(SCM, SVNRepository): def svn_revision(self, path): _log.debug('Running git.head_svn_revision... (Temporary logging message)') - git_log = self.run(['git', 'log', '-25', path]) + git_log = self.run([self.executable_name, 'log', '-25', path]) match = re.search("^\s*git-svn-id:.*@(?P<svn_revision>\d+)\ ", git_log, re.MULTILINE) if not match: return "" @@ -272,14 +274,14 @@ class Git(SCM, SVNRepository): if self._filesystem.exists(order_file): order = "-O%s" % order_file - command = ['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "--no-renames", order, self.merge_base(git_commit), "--"] + command = [self.executable_name, 'diff', '--binary', "--no-ext-diff", "--full-index", "--no-renames", order, self.merge_base(git_commit), "--"] if changed_files: command += changed_files return self.prepend_svn_revision(self.run(command, decode_output=False, cwd=self.checkout_root)) def _run_git_svn_find_rev(self, arg): # git svn find-rev always exits 0, even when the revision or commit is not found. - return self.run(['git', 'svn', 'find-rev', arg], cwd=self.checkout_root).rstrip() + return self.run([self.executable_name, 'svn', 'find-rev', arg], cwd=self.checkout_root).rstrip() def _string_to_int_or_none(self, string): try: @@ -303,21 +305,21 @@ class Git(SCM, SVNRepository): def contents_at_revision(self, path, revision): """Returns a byte array (str()) containing the contents of path @ revision in the repository.""" - return self.run(["git", "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)], decode_output=False) + return self.run([self.executable_name, "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)], decode_output=False) def diff_for_revision(self, revision): git_commit = self.git_commit_from_svn_revision(revision) return self.create_patch(git_commit) def diff_for_file(self, path, log=None): - return self.run(['git', 'diff', 'HEAD', '--no-renames', '--', path], cwd=self.checkout_root) + return self.run([self.executable_name, 'diff', 'HEAD', '--no-renames', '--', path], cwd=self.checkout_root) def show_head(self, path): - return self.run(['git', 'show', 'HEAD:' + self.to_object_name(path)], decode_output=False) + return self.run([self.executable_name, 'show', 'HEAD:' + self.to_object_name(path)], decode_output=False) def committer_email_for_revision(self, revision): git_commit = self.git_commit_from_svn_revision(revision) - committer_email = self.run(["git", "log", "-1", "--pretty=format:%ce", git_commit]) + committer_email = self.run([self.executable_name, "log", "-1", "--pretty=format:%ce", git_commit]) # Git adds an extra @repository_hash to the end of every committer email, remove it: return committer_email.rsplit("@", 1)[0] @@ -325,10 +327,10 @@ class Git(SCM, SVNRepository): # Assume the revision is an svn revision. git_commit = self.git_commit_from_svn_revision(revision) # I think this will always fail due to ChangeLogs. - self.run(['git', 'revert', '--no-commit', git_commit], error_handler=Executive.ignore_error) + self.run([self.executable_name, 'revert', '--no-commit', git_commit], error_handler=Executive.ignore_error) def revert_files(self, file_paths): - self.run(['git', 'checkout', 'HEAD'] + file_paths) + self.run([self.executable_name, 'checkout', 'HEAD'] + file_paths) def _assert_can_squash(self, working_directory_is_clean): squash = Git.read_git_config('webkit-patch.commit-should-always-squash', cwd=self.checkout_root) @@ -362,7 +364,7 @@ class Git(SCM, SVNRepository): if not force_squash: self._assert_can_squash(working_directory_is_clean) - self.run(['git', 'reset', '--soft', self.remote_merge_base()], cwd=self.checkout_root) + self.run([self.executable_name, 'reset', '--soft', self.remote_merge_base()], cwd=self.checkout_root) self.commit_locally_with_message(message) return self.push_local_commits_to_server(username=username, password=password) @@ -385,16 +387,16 @@ class Git(SCM, SVNRepository): # We wrap in a try...finally block so if anything goes wrong, we clean up the branches. commit_succeeded = True try: - self.run(['git', 'checkout', '-q', '-b', MERGE_BRANCH_NAME, self.remote_branch_ref()]) + self.run([self.executable_name, 'checkout', '-q', '-b', MERGE_BRANCH_NAME, self.remote_branch_ref()]) for commit in commit_ids: # We're on a different branch now, so convert "head" to the branch name. commit = re.sub(r'(?i)head', branch_name, commit) # FIXME: Once changed_files and create_patch are modified to separately handle each # commit in a commit range, commit each cherry pick so they'll get dcommitted separately. - self.run(['git', 'cherry-pick', '--no-commit', commit]) + self.run([self.executable_name, 'cherry-pick', '--no-commit', commit]) - self.run(['git', 'commit', '-m', message]) + self.run([self.executable_name, 'commit', '-m', message]) output = self.push_local_commits_to_server(username=username, password=password) except Exception, e: log("COMMIT FAILED: " + str(e)) @@ -403,31 +405,31 @@ class Git(SCM, SVNRepository): finally: # And then swap back to the original branch and clean up. self.clean_working_directory() - self.run(['git', 'checkout', '-q', branch_name]) + self.run([self.executable_name, 'checkout', '-q', branch_name]) self.delete_branch(MERGE_BRANCH_NAME) return output def svn_commit_log(self, svn_revision): svn_revision = self.strip_r_from_svn_revision(svn_revision) - return self.run(['git', 'svn', 'log', '-r', svn_revision]) + return self.run([self.executable_name, 'svn', 'log', '-r', svn_revision]) def last_svn_commit_log(self): - return self.run(['git', 'svn', 'log', '--limit=1']) + return self.run([self.executable_name, 'svn', 'log', '--limit=1']) def svn_blame(self, path): - return self.run(['git', 'svn', 'blame', path]) + return self.run([self.executable_name, 'svn', 'blame', path]) # Git-specific methods: def _branch_ref_exists(self, branch_ref): - return self.run(['git', 'show-ref', '--quiet', '--verify', branch_ref], return_exit_code=True) == 0 + return self.run([self.executable_name, 'show-ref', '--quiet', '--verify', branch_ref], return_exit_code=True) == 0 def delete_branch(self, branch_name): if self._branch_ref_exists('refs/heads/' + branch_name): - self.run(['git', 'branch', '-D', branch_name]) + self.run([self.executable_name, 'branch', '-D', branch_name]) def remote_merge_base(self): - return self.run(['git', 'merge-base', self.remote_branch_ref(), 'HEAD'], cwd=self.checkout_root).strip() + return self.run([self.executable_name, 'merge-base', self.remote_branch_ref(), 'HEAD'], cwd=self.checkout_root).strip() def remote_branch_ref(self): # Use references so that we can avoid collisions, e.g. we don't want to operate on refs/heads/trunk if it exists. @@ -444,10 +446,10 @@ class Git(SCM, SVNRepository): return first_remote_branch_ref.split(':')[1] def commit_locally_with_message(self, message): - self.run(['git', 'commit', '--all', '-F', '-'], input=message, cwd=self.checkout_root) + self.run([self.executable_name, 'commit', '--all', '-F', '-'], input=message, cwd=self.checkout_root) def push_local_commits_to_server(self, username=None, password=None): - dcommit_command = ['git', 'svn', 'dcommit'] + dcommit_command = [self.executable_name, 'svn', 'dcommit'] if (not username or not password) and not self.has_authorization_for_realm(SVN.svn_server_realm): raise AuthenticationError(SVN.svn_server_host, prompt_for_password=True) if username: @@ -469,14 +471,14 @@ class Git(SCM, SVNRepository): if '...' in commitish: raise ScriptError(message="'...' is not supported (found in '%s'). Did you mean '..'?" % commitish) elif '..' in commitish: - commit_ids += reversed(self.run(['git', 'rev-list', commitish]).splitlines()) + commit_ids += reversed(self.run([self.executable_name, 'rev-list', commitish]).splitlines()) else: # Turn single commits or branch or tag names into commit ids. - commit_ids += self.run(['git', 'rev-parse', '--revs-only', commitish]).splitlines() + commit_ids += self.run([self.executable_name, 'rev-parse', '--revs-only', commitish]).splitlines() return commit_ids def commit_message_for_local_commit(self, commit_id): - commit_lines = self.run(['git', 'cat-file', 'commit', commit_id]).splitlines() + commit_lines = self.run([self.executable_name, 'cat-file', 'commit', commit_id]).splitlines() # Skip the git headers. first_line_after_headers = 0 @@ -487,4 +489,4 @@ class Git(SCM, SVNRepository): return CommitMessage(commit_lines[first_line_after_headers:]) def files_changed_summary_for_commit(self, commit_id): - return self.run(['git', 'diff-tree', '--shortstat', '--no-renames', '--no-commit-id', commit_id]) + return self.run([self.executable_name, 'diff-tree', '--shortstat', '--no-renames', '--no-commit-id', commit_id]) diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py index 3c269175c..a22063f0e 100644 --- a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py +++ b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py @@ -172,10 +172,6 @@ class SVN(SCM, SVNRepository): """Does 'svn add' to the path and its parents.""" if self.in_working_directory(path): return - dirname = os.path.dirname(path) - # We have dirname directry - ensure it added. - if dirname != path: - self._add_parent_directories(dirname) self.add(path) def add_list(self, paths, return_exit_code=False): @@ -189,9 +185,6 @@ class SVN(SCM, SVNRepository): if set(os.listdir(path)) - self._svn_metadata_files: return # Directory has non-trivial files in it. self.delete(path) - dirname = os.path.dirname(path) - if dirname != path: - self._delete_parent_directories(dirname) def delete_list(self, paths): for path in paths: diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py index 673406c33..835b048bc 100644 --- a/Tools/Scripts/webkitpy/common/config/committers.py +++ b/Tools/Scripts/webkitpy/common/config/committers.py @@ -160,6 +160,7 @@ contributors_who_are_not_committers = [ Contributor("Tom Hudson", "tomhudson@google.com"), Contributor("WebKit Review Bot", "webkit.review.bot@gmail.com", "sheriff-bot"), Contributor("Wyatt Carss", ["wcarss@chromium.org", "wcarss@google.com"], "wcarss"), + Contributor("Zeev Lieber", "zlieber@chromium.org"), Contributor("Zoltan Arvai", "zarvai@inf.u-szeged.hu", "azbest_hu"), Contributor("Zsolt Feher", "feherzs@inf.u-szeged.hu", "Smith"), ] @@ -205,6 +206,7 @@ committers_unable_to_review = [ Committer("Benjamin C Meyer", ["ben@meyerhome.net", "ben@webkit.org", "bmeyer@rim.com"], "icefox"), Committer("Benjamin Kalman", ["kalman@chromium.org", "kalman@google.com"], "kalman"), Committer("Benjamin Otte", ["otte@gnome.org", "otte@webkit.org"], "otte"), + Committer("Bill Budge", ["bbudge@chromium.org", "bbudge@gmail.com"], "bbudge"), Committer("Brett Wilson", "brettw@chromium.org", "brettx"), Committer("Caio Marcelo de Oliveira Filho", ["cmarcelo@webkit.org", "caio.oliveira@openbossa.org"], "cmarcelo"), Committer("Cameron McCormack", ["cam@mcc.id.au", "cam@webkit.org"], "heycam"), @@ -252,7 +254,7 @@ committers_unable_to_review = [ Committer("Hans Wennborg", "hans@chromium.org", "hwennborg"), Committer("Hayato Ito", "hayato@chromium.org", "hayato"), Committer("Hironori Bono", "hbono@chromium.org", "hbono"), - Committer("Helder Correia", "helder@sencha.com", "helder"), + Committer("Helder Correia", "helder.correia@nokia.com", "helder"), Committer("Hin-Chung Lam", ["hclam@google.com", "hclam@chromium.org"]), Committer("Igor Trindade Oliveira", ["igor.oliveira@webkit.org", "igor.o@sisa.samsung.com"], "igoroliveira"), Committer("Ilya Sherman", "isherman@chromium.org", "isherman"), @@ -280,7 +282,7 @@ committers_unable_to_review = [ Committer("John Knottenbelt", "jknotten@chromium.org", "jknotten"), Committer("Johnny Ding", ["jnd@chromium.org", "johnnyding.webkit@gmail.com"], "johnnyding"), Committer("Jon Lee", "jonlee@apple.com", "jonlee"), - Committer("Joone Hur", "joone@webkit.org", "joone"), + Committer("Joone Hur", ["joone@webkit.org", "joone.hur@intel.com"], "joone"), Committer("Joost de Valk", ["joost@webkit.org", "webkit-dev@joostdevalk.nl"], "Altha"), Committer("Joshua Bell", ["jsbell@chromium.org", "jsbell@google.com"], "jsbell"), Committer("Julie Parent", ["jparent@google.com", "jparent@chromium.org"], "jparent"), @@ -296,6 +298,7 @@ committers_unable_to_review = [ Committer(u"Kim Gr\u00f6nholm", "kim.1.gronholm@nokia.com"), Committer("Kimmo Kinnunen", ["kimmo.t.kinnunen@nokia.com", "kimmok@iki.fi", "ktkinnun@webkit.org"], "kimmok"), Committer("Kinuko Yasuda", "kinuko@chromium.org", "kinuko"), + Committer("Konrad Piascik", "kpiascik@rim.com", "kpiascik"), Committer("Kristof Kosztyo", "kkristof@inf.u-szeged.hu", "kkristof"), Committer("Krzysztof Kowalczyk", "kkowalczyk@gmail.com"), Committer("Kwang Yul Seo", ["kwangyul.seo@gmail.com", "skyul@company100.net", "kseo@webkit.org"], "kwangseo"), @@ -341,7 +344,7 @@ committers_unable_to_review = [ Committer("Pierre-Olivier Latour", "pol@apple.com", "pol"), Committer("Pierre Rossi", "pierre.rossi@gmail.com", "elproxy"), Committer("Pratik Solanki", "psolanki@apple.com", "psolanki"), - Committer("Qi Zhang", ["qi.2.zhang@nokia.com", "qi.zhang02180@gmail.com"], "qi"), + Committer("Qi Zhang", "qi.zhang02180@gmail.com", "qi"), Committer("Rafael Antognolli", "antognolli@profusion.mobi", "antognolli"), Committer("Rafael Brandao", "rafael.lobo@openbossa.org", "rafaelbrandao"), Committer("Rafael Weinstein", "rafaelw@chromium.org", "rafaelw"), @@ -349,6 +352,7 @@ committers_unable_to_review = [ Committer("Ravi Kasibhatla", "ravi.kasibhatla@motorola.com", "kphanee"), Committer("Renata Hodovan", "reni@webkit.org", "reni"), Committer("Robert Hogan", ["robert@webkit.org", "robert@roberthogan.net", "lists@roberthogan.net"], "mwenge"), + Committer("Robert Kroeger", "rjkroege@chromium.org", "rjkroege"), Committer("Roland Steiner", "rolandsteiner@chromium.org"), Committer("Ryuan Choi", "ryuan.choi@samsung.com", "ryuan"), Committer("Satish Sampath", "satish@chromium.org"), @@ -379,7 +383,7 @@ committers_unable_to_review = [ Committer("Yael Aharon", "yael.aharon@nokia.com", "yael"), Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]), Committer("Yi Shen", ["yi.4.shen@nokia.com", "shenyi2006@gmail.com"]), - Committer("Yong Li", ["yong.li.webkit@gmail.com", "yong.li@torchmobile.com", "yoli@rim.com"], "yong"), + Committer("Yong Li", ["yoli@rim.com", "yong.li.webkit@gmail.com"], "yoli"), Committer("Yongjun Zhang", ["yongjun.zhang@nokia.com", "yongjun_zhang@apple.com"]), Committer("Yoshifumi Inoue", "yosin@chromium.org", "yosin"), Committer("Yuqiang Xian", "yuqiang.xian@intel.com"), diff --git a/Tools/Scripts/webkitpy/common/host.py b/Tools/Scripts/webkitpy/common/host.py index ffc13bf98..083120227 100644 --- a/Tools/Scripts/webkitpy/common/host.py +++ b/Tools/Scripts/webkitpy/common/host.py @@ -104,6 +104,26 @@ class Host(SystemHost): SVN.executable_name = 'svn.bat' except OSError, e: _log.debug('Failed to engage svn.bat Windows hack.') + try: + self.executive.run_command(['git', 'help']) + except OSError, e: + try: + self.executive.run_command(['git.bat', 'help']) + # Chromium Win uses the depot_tools package, which contains a number + # of development tools, including Python and git. Instead of using a + # real git executable, depot_tools indirects via a batch file, called + # git.bat. This batch file allows depot_tools to auto-update the real + # git executable, which is contained in a subdirectory. + # + # That's all fine and good, except that subprocess.popen can detect + # the difference between a real git executable and batch file when we + # don't provide use shell=True. Rather than use shell=True on Windows, + # We hack the git.bat name into the SVN class. + _log.debug('Engaging git.bat Windows hack.') + from webkitpy.common.checkout.scm.git import Git + Git.executable_name = 'git.bat' + except OSError, e: + _log.debug('Failed to engage git.bat Windows hack.') def _initialize_scm(self, patch_directories=None): if sys.platform == "win32": diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py index 1afa287de..58d497dc6 100644 --- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py +++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py @@ -209,12 +209,10 @@ class BugzillaQueries(object): # Currently this returns all bugs across all components. # In the future we may wish to extend this API to construct more restricted searches. - def fetch_bugs_matching_search(self, search_string, author_email=None): + def fetch_bugs_matching_search(self, search_string): query = "buglist.cgi?query_format=advanced" if search_string: query += "&short_desc_type=allwordssubstr&short_desc=%s" % urllib.quote(search_string) - if author_email: - query += "&emailreporter1=1&emailtype1=substring&email1=%s" % urllib.quote(search_string) return self._fetch_bugs_from_advanced_query(query) def fetch_patches_from_pending_commit_list(self): @@ -515,10 +513,21 @@ class Bugzilla(object): self.authenticated = True self.username = username + # FIXME: Use enum instead of two booleans def _commit_queue_flag(self, mark_for_landing, mark_for_commit_queue): if mark_for_landing: + user = self.committers.account_by_email(self.username) + mark_for_commit_queue = True + if not user: + log("Your Bugzilla login is not listed in committers.py. Uploading with cq? instead of cq+") + mark_for_landing = False + elif not user.can_commit: + log("You're not a committer yet or haven't updated committers.py yet. Uploading with cq? instead of cq+") + mark_for_landing = False + + if mark_for_landing: return '+' - elif mark_for_commit_queue: + if mark_for_commit_queue: return '?' return 'X' diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py index 36b465920..4e50189a1 100644 --- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py +++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py @@ -269,7 +269,7 @@ class MockBugzillaQueries(object): def fetch_patches_from_pending_commit_list(self): return sum([bug.reviewed_patches() for bug in self._all_bugs()], []) - def fetch_bugs_matching_search(self, search_string, author_email=None): + def fetch_bugs_matching_search(self, search_string): return [self._bugzilla.fetch_bug(50004), self._bugzilla.fetch_bug(50003)] def fetch_bugs_matching_quicksearch(self, search_string): diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py index 986ce3bac..6108b5e8a 100644 --- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py +++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py @@ -33,6 +33,7 @@ import StringIO from .bugzilla import Bugzilla, BugzillaQueries, EditUsersParser from webkitpy.common.config import urls +from webkitpy.common.config.committers import Reviewer, Committer, Contributor, CommitterList from webkitpy.common.system.outputcapture import OutputCapture from webkitpy.common.net.web_mock import MockBrowser from webkitpy.thirdparty.mock import Mock @@ -299,6 +300,43 @@ Ignore this bug. Just for testing failure modes of webkit-patch and the commit- filename = bugzilla._filename_for_upload(StringIO.StringIO(), 1234, extension="patch", timestamp=mock_timestamp) self.assertEqual(filename, "bug-1234-now.patch") + def test_commit_queue_flag(self): + bugzilla = Bugzilla() + + bugzilla.committers = CommitterList(reviewers=[Reviewer("WebKit Reviewer", "reviewer@webkit.org")], + committers=[Committer("WebKit Committer", "committer@webkit.org")], + contributors=[Contributor("WebKit Contributor", "contributor@webkit.org")], + watchers=[]) + + def assert_commit_queue_flag(mark_for_landing, mark_for_commit_queue, expected, username=None): + bugzilla.username = username + capture = OutputCapture() + capture.capture_output() + try: + self.assertEqual(bugzilla._commit_queue_flag(mark_for_landing=mark_for_landing, mark_for_commit_queue=mark_for_commit_queue), expected) + finally: + capture.restore_output() + + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=False, expected='X', username='unknown@webkit.org') + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=True, expected='?', username='unknown@webkit.org') + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=True, expected='?', username='unknown@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=True, expected='?', username='unknown@webkit.org') + + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=False, expected='X', username='contributor@webkit.org') + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=True, expected='?', username='contributor@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=False, expected='?', username='contributor@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=True, expected='?', username='contributor@webkit.org') + + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=False, expected='X', username='committer@webkit.org') + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=True, expected='?', username='committer@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=False, expected='+', username='committer@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=True, expected='+', username='committer@webkit.org') + + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=False, expected='X', username='reviewer@webkit.org') + assert_commit_queue_flag(mark_for_landing=False, mark_for_commit_queue=True, expected='?', username='reviewer@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=False, expected='+', username='reviewer@webkit.org') + assert_commit_queue_flag(mark_for_landing=True, mark_for_commit_queue=True, expected='+', username='reviewer@webkit.org') + class BugzillaQueriesTest(unittest.TestCase): _sample_request_page = """ diff --git a/Tools/Scripts/webkitpy/common/system/executive.py b/Tools/Scripts/webkitpy/common/system/executive.py index 8759c719a..cb36b5dc0 100644 --- a/Tools/Scripts/webkitpy/common/system/executive.py +++ b/Tools/Scripts/webkitpy/common/system/executive.py @@ -454,7 +454,13 @@ class Executive(object): def run_in_parallel(self, command_lines_and_cwds, processes=None): """Runs a list of (cmd_line list, cwd string) tuples in parallel and returns a list of (retcode, stdout, stderr) tuples.""" - return multiprocessing.Pool(processes=processes).map(_run_command_thunk, command_lines_and_cwds) + if sys.platform in ('cygwin', 'win32'): + return map(_run_command_thunk, command_lines_and_cwds) + pool = multiprocessing.Pool(processes=processes) + results = pool.map(_run_command_thunk, command_lines_and_cwds) + pool.close() + pool.join() + return results def _run_command_thunk(cmd_line_and_cwd): diff --git a/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/Tools/Scripts/webkitpy/common/system/executive_unittest.py index 466e2ec02..212896a4a 100644 --- a/Tools/Scripts/webkitpy/common/system/executive_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/executive_unittest.py @@ -218,6 +218,10 @@ class ExecutiveTest(unittest.TestCase): self.assertTrue(os.getpid() in pids) def test_run_in_parallel(self): + if sys.platform in ("win32", "cygwin"): + return # This function isn't implemented properly on windows yet. + import multiprocessing + NUM_PROCESSES = 4 DELAY_SECS = 0.25 cmd_line = [sys.executable, '-c', 'import time; time.sleep(%f); print "hello"' % DELAY_SECS] @@ -228,6 +232,7 @@ class ExecutiveTest(unittest.TestCase): done = time.time() self.assertTrue(done - start < NUM_PROCESSES * DELAY_SECS) self.assertEquals([output[1] for output in command_outputs], ["hello\n"] * NUM_PROCESSES) + self.assertEquals([], multiprocessing.active_children()) def main(platform, stdin, stdout, cmd, args): diff --git a/Tools/Scripts/webkitpy/common/system/outputcapture.py b/Tools/Scripts/webkitpy/common/system/outputcapture.py index 66188c0cb..4f931b7d1 100644 --- a/Tools/Scripts/webkitpy/common/system/outputcapture.py +++ b/Tools/Scripts/webkitpy/common/system/outputcapture.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -35,6 +35,13 @@ from StringIO import StringIO class OutputCapture(object): + # By default we capture the output to a stream. Other modules may override + # this function in order to do things like pass through the output. See + # webkitpy.test.main for an example. + @staticmethod + def stream_wrapper(stream): + return StringIO() + def __init__(self): self.saved_outputs = dict() self._log_level = logging.INFO @@ -45,8 +52,9 @@ class OutputCapture(object): self._logs_handler.setLevel(self._log_level) def _capture_output_with_name(self, output_name): - self.saved_outputs[output_name] = getattr(sys, output_name) - captured_output = StringIO() + stream = getattr(sys, output_name) + captured_output = self.stream_wrapper(stream) + self.saved_outputs[output_name] = stream setattr(sys, output_name, captured_output) return captured_output diff --git a/Tools/Scripts/webkitpy/common/system/path.py b/Tools/Scripts/webkitpy/common/system/path.py index b7ad3723a..e5a66bf87 100644 --- a/Tools/Scripts/webkitpy/common/system/path.py +++ b/Tools/Scripts/webkitpy/common/system/path.py @@ -35,11 +35,9 @@ import threading import urllib -def abspath_to_uri(path, platform=None): +def abspath_to_uri(platform, path): """Converts a platform-specific absolute path to a file: URL.""" - if platform is None: - platform = sys.platform - return "file:" + _escape(_convert_path(path, platform)) + return "file:" + _escape(_convert_path(platform, path)) def cygpath(path): @@ -118,12 +116,12 @@ def _escape(path): return urllib.quote(path, safe='/+:') -def _convert_path(path, platform): +def _convert_path(platform, path): """Handles any os-specific path separators, mappings, etc.""" - if platform == 'win32': - return _winpath_to_uri(path) - if platform == 'cygwin': + if platform.is_cygwin(): return _winpath_to_uri(cygpath(path)) + if platform.is_win(): + return _winpath_to_uri(path) return _unixypath_to_uri(path) diff --git a/Tools/Scripts/webkitpy/common/system/path_unittest.py b/Tools/Scripts/webkitpy/common/system/path_unittest.py index e08212a2c..954d32d71 100644 --- a/Tools/Scripts/webkitpy/common/system/path_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/path_unittest.py @@ -29,69 +29,41 @@ import unittest import sys -import path +from webkitpy.common.system.systemhost import SystemHost +from webkitpy.common.system.platforminfo import PlatformInfo +from webkitpy.common.system.platforminfo_mock import MockPlatformInfo +from webkitpy.common.system import path class AbspathTest(unittest.TestCase): - def assertMatch(self, test_path, expected_uri, - platform=None): - if platform == 'cygwin' and sys.platform != 'cygwin': - return - self.assertEqual(path.abspath_to_uri(test_path, platform=platform), - expected_uri) + def platforminfo(self): + return SystemHost().platform def test_abspath_to_uri_cygwin(self): if sys.platform != 'cygwin': return + self.assertEquals(path.abspath_to_uri(self.platforminfo(), '/cygdrive/c/foo/bar.html'), + 'file:///C:/foo/bar.html') - self.assertMatch('/cygdrive/c/foo/bar.html', - 'file:///C:/foo/bar.html', - platform='cygwin') - self.assertEqual(path.abspath_to_uri('/cygdrive/c/foo/bar.html', - platform='cygwin'), - 'file:///C:/foo/bar.html') - - def test_abspath_to_uri_darwin(self): - self.assertMatch('/foo/bar.html', - 'file:///foo/bar.html', - platform='darwin') - self.assertEqual(path.abspath_to_uri("/foo/bar.html", - platform='darwin'), - "file:///foo/bar.html") - - def test_abspath_to_uri_linux2(self): - self.assertMatch('/foo/bar.html', - 'file:///foo/bar.html', - platform='darwin') - self.assertEqual(path.abspath_to_uri("/foo/bar.html", - platform='linux2'), - "file:///foo/bar.html") - self.assertEqual(path.abspath_to_uri("/foo/bar.html", - platform='linux3'), - "file:///foo/bar.html") + def test_abspath_to_uri_unixy(self): + self.assertEquals(path.abspath_to_uri(MockPlatformInfo(), "/foo/bar.html"), + 'file:///foo/bar.html') def test_abspath_to_uri_win(self): - self.assertMatch('c:\\foo\\bar.html', - 'file:///c:/foo/bar.html', - platform='win32') - self.assertEqual(path.abspath_to_uri("c:\\foo\\bar.html", - platform='win32'), - "file:///c:/foo/bar.html") + if sys.platform != 'win32': + return + self.assertEquals(path.abspath_to_uri(self.platforminfo(), 'c:\\foo\\bar.html'), + 'file:///c:/foo/bar.html') - def test_abspath_to_uri_escaping(self): - self.assertMatch('/foo/bar + baz%?.html', - 'file:///foo/bar%20+%20baz%25%3F.html', - platform='darwin') - self.assertMatch('/foo/bar + baz%?.html', - 'file:///foo/bar%20+%20baz%25%3F.html', - platform='linux2') - self.assertMatch('/foo/bar + baz%?.html', - 'file:///foo/bar%20+%20baz%25%3F.html', - platform='linux3') + def test_abspath_to_uri_escaping_unixy(self): + self.assertEquals(path.abspath_to_uri(MockPlatformInfo(), '/foo/bar + baz%?.html'), + 'file:///foo/bar%20+%20baz%25%3F.html') # Note that you can't have '?' in a filename on windows. - self.assertMatch('/cygdrive/c/foo/bar + baz%.html', - 'file:///C:/foo/bar%20+%20baz%25.html', - platform='cygwin') + def test_abspath_to_uri_escaping_cygwin(self): + if sys.platform != 'cygwin': + return + self.assertEquals(path.abspath_to_uri(self.platforminfo(), '/cygdrive/c/foo/bar + baz%.html'), + 'file:///C:/foo/bar%20+%20baz%25.html') def test_stop_cygpath_subprocess(self): if sys.platform != 'cygwin': @@ -106,6 +78,3 @@ class AbspathTest(unittest.TestCase): # Ensure that it is stopped. self.assertFalse(path._CygPath._singleton.is_running()) - -if __name__ == '__main__': - unittest.main() diff --git a/Tools/Scripts/webkitpy/common/system/platforminfo.py b/Tools/Scripts/webkitpy/common/system/platforminfo.py index 22cafbbee..74cff5412 100644 --- a/Tools/Scripts/webkitpy/common/system/platforminfo.py +++ b/Tools/Scripts/webkitpy/common/system/platforminfo.py @@ -54,6 +54,7 @@ class PlatformInfo(object): self.os_version = self._determine_mac_version(platform_module.mac_ver()[0]) if self.os_name.startswith('win'): self.os_version = self._determine_win_version(self._win_version_tuple(sys_module)) + self._is_cygwin = sys_module.platform == 'cygwin' def is_mac(self): return self.os_name == 'mac' @@ -61,6 +62,9 @@ class PlatformInfo(object): def is_win(self): return self.os_name == 'win' + def is_cygwin(self): + return self._is_cygwin + def is_linux(self): return self.os_name == 'linux' @@ -77,18 +81,9 @@ class PlatformInfo(object): # Windows-2008ServerR2-6.1.7600 return self._platform_module.platform() - def free_bytes_memory(self): - if self.is_mac(): - vm_stat_output = self._executive.run_command(["vm_stat"]) - free_bytes = self._compute_bytes_from_vm_stat_output("Pages free", vm_stat_output) - # Per https://bugs.webkit.org/show_bug.cgi?id=74650 include inactive memory since the OS is lazy about freeing memory. - free_bytes += self._compute_bytes_from_vm_stat_output("Pages inactive", vm_stat_output) - return free_bytes - return None - def total_bytes_memory(self): if self.is_mac(): - return int(self._executive.run_command(["sysctl", "-n", "hw.memsize"])) + return long(self._executive.run_command(["sysctl", "-n", "hw.memsize"])) return None def _determine_os_name(self, sys_platform): @@ -137,14 +132,3 @@ class PlatformInfo(object): match_object = re.search(r'(?P<major>\d)\.(?P<minor>\d)\.(?P<build>\d+)', ver_output) assert match_object, 'cmd returned an unexpected version string: ' + ver_output return tuple(map(int, match_object.groups())) - - def _compute_bytes_from_vm_stat_output(self, label_text, vm_stat_output): - page_size_match = re.search(r"page size of (\d+) bytes", vm_stat_output) - free_pages_match = re.search(r"%s:\s+(\d+)." % label_text, vm_stat_output) - - # Fail hard if vmstat's output isn't what we expect. - assert(page_size_match and free_pages_match) - - free_page_count = int(free_pages_match.group(1)) - page_size = int(page_size_match.group(1)) - return free_page_count * page_size diff --git a/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py b/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py index c953aa185..34fa97fb4 100644 --- a/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py +++ b/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py @@ -41,6 +41,9 @@ class MockPlatformInfo(object): def is_win(self): return self.os_name == 'win' + def is_cygwin(self): + return False + def is_freebsd(self): return self.os_name == 'freebsd' @@ -48,7 +51,4 @@ class MockPlatformInfo(object): return "MockPlatform 1.0" def total_bytes_memory(self): - return 2 * 1024 * 1024 * 1024 # 2GB is a reasonable amount of ram to mock. - - def free_bytes_memory(self): - return 1 * 1024 * 1024 * 1024 # 1GB is a reasonable amount of ram to mock as free. + return 3 * 1024 * 1024 * 1024 # 3GB is a reasonable amount of ram to mock. diff --git a/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py b/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py index 5a1f85fc3..8fc961b08 100644 --- a/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py @@ -82,10 +82,8 @@ class TestPlatformInfo(unittest.TestCase): if info.is_mac(): self.assertTrue(info.total_bytes_memory() > 0) - self.assertTrue(info.free_bytes_memory() > 0) else: self.assertEquals(info.total_bytes_memory(), None) - self.assertEquals(info.free_bytes_memory(), None) def test_os_name_and_wrappers(self): info = self.make_info(fake_sys('linux2')) @@ -180,22 +178,6 @@ class TestPlatformInfo(unittest.TestCase): info = self.make_info(fake_sys('freebsd9')) self.assertEquals(info.total_bytes_memory(), None) - def test_free_bytes_memory(self): - vmstat_output = ("Mach Virtual Memory Statistics: (page size of 4096 bytes)\n" - "Pages free: 1.\n" - "Pages inactive: 1.\n") - info = self.make_info(fake_sys('darwin'), fake_platform('10.6.3'), fake_executive(vmstat_output)) - self.assertEquals(info.free_bytes_memory(), 8192) - - info = self.make_info(fake_sys('win32', tuple([6, 1, 7600]))) - self.assertEquals(info.free_bytes_memory(), None) - - info = self.make_info(fake_sys('linux2')) - self.assertEquals(info.free_bytes_memory(), None) - - info = self.make_info(fake_sys('freebsd9')) - self.assertEquals(info.free_bytes_memory(), None) - if __name__ == '__main__': unittest.main() diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py index e762cfda0..3189563d2 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py @@ -236,10 +236,13 @@ def summarize_results(port_obj, expectations, result_summary, retry_summary, tes results['layout_tests_dir'] = port_obj.layout_tests_dir() results['has_wdiff'] = port_obj.wdiff_available() results['has_pretty_patch'] = port_obj.pretty_patch_available() + results['pixel_tests_enabled'] = port_obj.get_option('pixel_tests') + try: # We only use the svn revision for using trac links in the results.html file, # Don't do this by default since it takes >100ms. if use_trac_links_in_results_html(port_obj): + port_obj.host._initialize_scm() results['revision'] = port_obj.host.scm().head_svn_revision() except Exception, e: _log.warn("Failed to determine svn revision for checkout (cwd: %s, webkit_base: %s), leaving 'revision' key blank in full_results.json.\n%s" % (port_obj._filesystem.getcwd(), port_obj.path_from_webkit_base(), e)) @@ -316,6 +319,8 @@ class Manager(object): # a set of test files, and the same tests as a list + self._paths = set() + # FIXME: Rename to test_names. self._test_files = set() self._test_files_list = None @@ -340,6 +345,7 @@ class Manager(object): paths = self._strip_test_dir_prefixes(args) if self._options.test_list: paths += self._strip_test_dir_prefixes(read_test_files(self._filesystem, self._options.test_list, self._port.TEST_PATH_SEPARATOR)) + self._paths = set(paths) self._test_files = self._port.tests(paths) def _strip_test_dir_prefixes(self, paths): @@ -360,6 +366,9 @@ class Manager(object): def _http_tests(self): return set(test for test in self._test_files if self._is_http_test(test)) + def _websocket_tests(self): + return set(test for test in self._test_files if self.WEBSOCKET_SUBDIR in test) + def _is_perf_test(self, test): return self.PERF_SUBDIR == test or (self.PERF_SUBDIR + self._port.TEST_PATH_SEPARATOR) in test @@ -456,24 +465,40 @@ class Manager(object): # Remove skipped - both fixable and ignored - files from the # top-level list of files to test. + found_test_files = set(self._test_files) num_all_test_files = len(self._test_files) - self._printer.print_expected("Found: %d tests" % (len(self._test_files))) - if not num_all_test_files: - _log.critical('No tests to run.') - return None - - skipped = set() + skipped = self._expectations.get_tests_with_result_type(test_expectations.SKIP) if not self._options.http: - skipped = skipped.union(self._http_tests()) + skipped.update(set(self._http_tests())) + + if self._options.skipped == 'only': + self._test_files = self._test_files.intersection(skipped) + elif self._options.skipped == 'default': + self._test_files -= skipped + elif self._options.skipped == 'ignore': + pass # just to be clear that we're ignoring the skip list. - if num_all_test_files > 1 and not self._options.force: - skipped.update(self._expectations.get_tests_with_result_type(test_expectations.SKIP)) - if self._options.skip_failing_tests: - skipped.update(self._expectations.get_tests_with_result_type(test_expectations.FAIL)) - skipped.update(self._expectations.get_tests_with_result_type(test_expectations.FLAKY)) + if self._options.skip_failing_tests: + self._test_files -= self._expectations.get_tests_with_result_type(test_expectations.FAIL) + self._test_files -= self._expectations.get_tests_with_result_type(test_expectations.FLAKY) - self._test_files -= skipped + # now make sure we're explicitly running any tests passed on the command line. + self._test_files.update(found_test_files.intersection(self._paths)) + + if not num_all_test_files: + _log.critical('No tests to run.') + return None + + num_skipped = num_all_test_files - len(self._test_files) + if num_skipped: + self._printer.print_expected("Running %s (found %d, skipping %d)." % ( + grammar.pluralize('test', num_all_test_files - num_skipped), + num_all_test_files, num_skipped)) + elif len(self._test_files) > 1: + self._printer.print_expected("Running all %d tests." % len(self._test_files)) + else: + self._printer.print_expected("Running %1 test.") # Create a sorted list of test files so the subset chunk, # if used, contains alphabetically consecutive tests. @@ -504,9 +529,7 @@ class Manager(object): self._print_expected_results_of_type(result_summary, test_expectations.FLAKY, "flaky") self._print_expected_results_of_type(result_summary, test_expectations.SKIP, "skipped") - if self._options.force: - self._printer.print_expected('Running all tests, including skips (--force)') - else: + if self._options.skipped != 'ignore': # Note that we don't actually run the skipped tests (they were # subtracted out of self._test_files, above), but we stub out the # results here so the statistics can remain accurate. @@ -742,7 +765,7 @@ class Manager(object): all_shards = locked_shards + unlocked_shards self._remaining_locked_shards = locked_shards - if locked_shards and self._options.http: + if self._options.http and (self._http_tests() or self._websocket_tests()): self.start_servers_with_lock() num_workers = min(num_workers, len(all_shards)) @@ -797,7 +820,8 @@ class Manager(object): _log.error('Worker %d did not exit in time.' % worker_state.number) except KeyboardInterrupt: - self._printer.print_update('Interrupted, exiting ...') + self._printer.flush() + self._printer.write('Interrupted, exiting ...') self.cancel_workers() keyboard_interrupted = True except TestRunInterruptedException, e: @@ -946,21 +970,24 @@ class Manager(object): return self._port.exit_code_from_summarized_results(unexpected_results) def start_servers_with_lock(self): - assert(self._options.http) self._printer.print_update('Acquiring http lock ...') self._port.acquire_http_lock() - self._printer.print_update('Starting HTTP server ...') - self._port.start_http_server() - self._printer.print_update('Starting WebSocket server ...') - self._port.start_websocket_server() + if self._http_tests(): + self._printer.print_update('Starting HTTP server ...') + self._port.start_http_server() + if self._websocket_tests(): + self._printer.print_update('Starting WebSocket server ...') + self._port.start_websocket_server() self._has_http_lock = True def stop_servers_with_lock(self): if self._has_http_lock: - self._printer.print_update('Stopping HTTP server ...') - self._port.stop_http_server() - self._printer.print_update('Stopping WebSocket server ...') - self._port.stop_websocket_server() + if self._http_tests(): + self._printer.print_update('Stopping HTTP server ...') + self._port.stop_http_server() + if self._websocket_tests(): + self._printer.print_update('Stopping WebSocket server ...') + self._port.stop_websocket_server() self._printer.print_update('Releasing server lock ...') self._port.release_http_lock() self._has_http_lock = False @@ -1445,9 +1472,10 @@ class Manager(object): worker_state.current_test_name = test_info.test_name worker_state.next_timeout = time.time() + hang_timeout - def handle_done(self, source): + def handle_done(self, source, log_messages=None): worker_state = self._worker_states[source] worker_state.done = True + self._log_messages(log_messages) def handle_exception(self, source, exception_type, exception_value, stack): if exception_type in (KeyboardInterrupt, TestRunInterruptedException): @@ -1474,16 +1502,21 @@ class Manager(object): if not self._remaining_locked_shards: self.stop_servers_with_lock() - def handle_finished_test(self, source, result, elapsed_time): + def handle_finished_test(self, source, result, elapsed_time, log_messages=None): worker_state = self._worker_states[source] worker_state.next_timeout = None worker_state.current_test_name = None worker_state.stats['total_time'] += elapsed_time worker_state.stats['num_tests'] += 1 + self._log_messages(log_messages) self._all_results.append(result) self._update_summary_with_result(self._current_result_summary, result) + def _log_messages(self, messages): + for message in messages: + self._printer.writeln(*message) + def _log_worker_stack(self, stack): webkitpydir = self._port.path_from_webkit_base('Tools', 'Scripts', 'webkitpy') + self._filesystem.sep for filename, line_number, function_name, text in stack: diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py index 3ddab8ec3..13011883f 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py @@ -280,7 +280,7 @@ class ManagerTest(unittest.TestCase): host = MockHost() port = host.port_factory.get('test-win-xp') test = 'failures/expected/reftest.html' - port.test_expectations = lambda: 'WONTFIX : failures/expected/reftest.html = IMAGE' + port.expectations_dict = lambda: {'': 'WONTFIX : failures/expected/reftest.html = IMAGE'} expectations = TestExpectations(port, tests=[test]) # Reftests expected to be image mismatch should be respected when pixel_tests=False. manager = Manager(port=port, options=MockOptions(pixel_tests=False, exit_after_n_failures=None, exit_after_n_crashes_or_timeouts=None), printer=Mock()) @@ -342,6 +342,58 @@ class ManagerTest(unittest.TestCase): manager = get_manager_with_tests(tests) manager._look_for_new_crash_logs(rs, time.time()) + def test_servers_started(self): + + def start_http_server(): + self.http_started = True + + def start_websocket_server(): + self.websocket_started = True + + def stop_http_server(): + self.http_stopped = True + + def stop_websocket_server(): + self.websocket_stopped = True + + host = MockHost() + port = host.port_factory.get('test-mac-leopard') + port.start_http_server = start_http_server + port.start_websocket_server = start_websocket_server + port.stop_http_server = stop_http_server + port.stop_websocket_server = stop_websocket_server + + self.http_started = self.http_stopped = self.websocket_started = self.websocket_stopped = False + manager = Manager(port=port, options=MockOptions(http=True), printer=Mock()) + manager._test_files = ['http/tests/pass.txt'] + manager.start_servers_with_lock() + self.assertEquals(self.http_started, True) + self.assertEquals(self.websocket_started, False) + manager.stop_servers_with_lock() + self.assertEquals(self.http_stopped, True) + self.assertEquals(self.websocket_stopped, False) + + self.http_started = self.http_stopped = self.websocket_started = self.websocket_stopped = False + manager = Manager(port=port, options=MockOptions(http=True), printer=Mock()) + manager._test_files = ['websocket/pass.txt'] + manager.start_servers_with_lock() + self.assertEquals(self.http_started, True) + self.assertEquals(self.websocket_started, True) + manager.stop_servers_with_lock() + self.assertEquals(self.http_stopped, True) + self.assertEquals(self.websocket_stopped, True) + + self.http_started = self.http_stopped = self.websocket_started = self.websocket_stopped = False + manager = Manager(port=port, options=MockOptions(http=True), printer=Mock()) + manager._test_files = ['perf/foo/test.html'] + manager.start_servers_with_lock() + self.assertEquals(self.http_started, False) + self.assertEquals(self.websocket_started, False) + manager.stop_servers_with_lock() + self.assertEquals(self.http_stopped, False) + self.assertEquals(self.websocket_stopped, False) + + class NaturalCompareTest(unittest.TestCase): def assert_cmp(self, x, y, result): @@ -422,7 +474,7 @@ class ResultSummaryTest(unittest.TestCase): return test_results.TestResult(test_name, failures=failures, test_run_time=run_time) def get_result_summary(self, port, test_names, expectations_str): - port.test_expectations = lambda: expectations_str + port.expectations_dict = lambda: {'': expectations_str} expectations = test_expectations.TestExpectations(port, test_names) return test_names, result_summary.ResultSummary(expectations, test_names), expectations @@ -481,7 +533,7 @@ class ResultSummaryTest(unittest.TestCase): port = host.port_factory.get('test') port._options.builder_name = 'dummy builder' port._filesystem.write_text_file(port._filesystem.join(port.layout_tests_dir(), "failures/expected/wontfix.html"), "Dummy test contents") - expected_results, unexpected_results = self.summarized_results(port, expected=False, passing=False, flaky=False, extra_tests=['failures/expected/wontfix.html'], extra_expectations='BUGX WONTFIX : failures/expected/wontfix.html = FAIL\n') + expected_results, unexpected_results = self.summarized_results(port, expected=False, passing=False, flaky=False, extra_tests=['failures/expected/wontfix.html'], extra_expectations='BUGX WONTFIX : failures/expected/wontfix.html = TEXT\n') self.assertTrue(expected_results['tests']['failures']['expected']['wontfix.html']['wontfix']) if __name__ == '__main__': diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py index 93806e7d8..046425664 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker_unittest.py @@ -215,14 +215,14 @@ class InterfaceTest(unittest.TestCase): def test_managerconnection_is_abstract(self): # Test that all the base class methods are abstract and have the # signature we expect. - broker = make_broker(self, 'inline') + broker = make_broker(self, 1) obj = manager_worker_broker._ManagerConnection(broker._broker, self, None) self.assertRaises(NotImplementedError, obj.start_worker) def test_workerconnection_is_abstract(self): # Test that all the base class methods are abstract and have the # signature we expect. - broker = make_broker(self, 'inline') + broker = make_broker(self, 1) obj = manager_worker_broker._WorkerConnection(broker._broker, _TestWorker, None) self.assertRaises(NotImplementedError, obj.cancel) self.assertRaises(NotImplementedError, obj.is_alive) diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py index 529aea222..fa07e88ff 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py @@ -46,7 +46,8 @@ def run_single_test(port, options, test_input, driver, worker_name): return runner.run() -class SingleTestRunner: +class SingleTestRunner(object): + (ALONGSIDE_TEST, PLATFORM_DIR, VERSION_DIR, UPDATE) = ('alongside', 'platform', 'version', 'update') def __init__(self, options, port, driver, test_input, worker_name): self._options = options @@ -94,12 +95,12 @@ class SingleTestRunner: def run(self): if self._reference_files: - if self._port.get_option('no_ref_tests') or self._options.new_baseline or self._options.reset_results: + if self._port.get_option('no_ref_tests') or self._options.reset_results: result = TestResult(self._test_name) result.type = test_expectations.SKIP return result return self._run_reftest() - if self._options.new_baseline or self._options.reset_results: + if self._options.reset_results: return self._run_rebaseline() return self._run_compare_test() @@ -121,7 +122,7 @@ class SingleTestRunner: driver_output = self._driver.run_test(self._driver_input()) failures = self._handle_error(driver_output) test_result_writer.write_test_result(self._filesystem, self._port, self._test_name, driver_output, None, failures) - # FIXME: It the test crashed or timed out, it might be bettter to avoid + # FIXME: It the test crashed or timed out, it might be better to avoid # to write new baselines. self._overwrite_baselines(driver_output) return TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr()) @@ -131,49 +132,50 @@ class SingleTestRunner: def _add_missing_baselines(self, test_result, driver_output): missingImage = test_result.has_failure_matching_types(test_failures.FailureMissingImage, test_failures.FailureMissingImageHash) if test_result.has_failure_matching_types(test_failures.FailureMissingResult): - self._save_baseline_data(driver_output.text, ".txt", SingleTestRunner._render_tree_dump_pattern.match(driver_output.text)) + self._save_baseline_data(driver_output.text, '.txt', self._location_for_new_baseline(driver_output.text, '.txt')) if test_result.has_failure_matching_types(test_failures.FailureMissingAudio): - self._save_baseline_data(driver_output.audio, ".wav", generate_new_baseline=False) + self._save_baseline_data(driver_output.audio, '.wav', self._location_for_new_baseline(driver_output.audio, '.wav')) if missingImage: - self._save_baseline_data(driver_output.image, ".png", generate_new_baseline=True) + self._save_baseline_data(driver_output.image, '.png', self._location_for_new_baseline(driver_output.image, '.png')) + + def _location_for_new_baseline(self, data, extension): + if self._options.add_platform_exceptions: + return self.VERSION_DIR + if extension == '.png': + return self.PLATFORM_DIR + if extension == '.wav': + return self.ALONGSIDE_TEST + if extension == '.txt' and self._render_tree_dump_pattern.match(data): + return self.PLATFORM_DIR + return self.ALONGSIDE_TEST def _overwrite_baselines(self, driver_output): - # Although all DumpRenderTree output should be utf-8, - # we do not ever decode it inside run-webkit-tests. For some tests - # DumpRenderTree may not output utf-8 text (e.g. webarchives). - self._save_baseline_data(driver_output.text, ".txt", generate_new_baseline=self._options.new_baseline) - self._save_baseline_data(driver_output.audio, ".wav", generate_new_baseline=self._options.new_baseline) + location = self.VERSION_DIR if self._options.add_platform_exceptions else self.UPDATE + self._save_baseline_data(driver_output.text, '.txt', location) + self._save_baseline_data(driver_output.audio, '.wav', location) if self._options.pixel_tests: - self._save_baseline_data(driver_output.image, ".png", generate_new_baseline=self._options.new_baseline) + self._save_baseline_data(driver_output.image, '.png', location) - def _save_baseline_data(self, data, modifier, generate_new_baseline=True): - """Saves a new baseline file into the port's baseline directory. - - The file will be named simply "<test>-expected<modifier>", suitable for - use as the expected results in a later run. - - Args: - data: result to be saved as the new baseline - modifier: type of the result file, e.g. ".txt" or ".png" - generate_new_baseline: whether to enerate a new, platform-specific - baseline, or update the existing one - """ + def _save_baseline_data(self, data, extension, location): if data is None: return port = self._port fs = self._filesystem - if generate_new_baseline: - relative_dir = fs.dirname(self._test_name) - baseline_path = port.baseline_path() - output_dir = fs.join(baseline_path, relative_dir) - output_file = fs.basename(fs.splitext(self._test_name)[0] + "-expected" + modifier) - fs.maybe_make_directory(output_dir) - output_path = fs.join(output_dir, output_file) + if location == self.ALONGSIDE_TEST: + output_dir = fs.dirname(port.abspath_for_test(self._test_name)) + elif location == self.VERSION_DIR: + output_dir = fs.join(port.baseline_version_dir(), fs.dirname(self._test_name)) + elif location == self.PLATFORM_DIR: + output_dir = fs.join(port.baseline_platform_dir(), fs.dirname(self._test_name)) + elif location == self.UPDATE: + output_dir = fs.dirname(port.expected_filename(self._test_name, extension)) else: - output_path = port.expected_filename(self._test_name, modifier) + raise AssertionError('unrecognized baseline location: %s' % location) - result_name = fs.relpath(output_path, port.layout_tests_dir()) - _log.info('Writing new expected result "%s"' % result_name) + fs.maybe_make_directory(output_dir) + output_basename = fs.basename(fs.splitext(self._test_name)[0] + "-expected" + extension) + output_path = fs.join(output_dir, output_basename) + _log.info('Writing new expected result "%s"' % port.relative_test_filename(output_path)) port.update_baseline(output_path, data) def _handle_error(self, driver_output, reference_filename=None): diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py b/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py index 31029a35f..09f9670a0 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py @@ -77,7 +77,7 @@ class TestExpectationEditorTests(unittest.TestCase): def make_parsed_expectation_lines(self, in_string): parser = TestExpectationParser(self.test_port, self.full_test_list, allow_rebaseline_modifier=False) - expectation_lines = parser.parse(in_string) + expectation_lines = parser.parse('path', in_string) for expectation_line in expectation_lines: self.assertFalse(expectation_line.is_invalid()) return expectation_lines @@ -164,8 +164,8 @@ BUGX2 XP DEBUG : failures/expected/keyboard.html = IMAGE""", 'failures/expected/ BUGX2 XP DEBUG : failures/expected/keyboard.html = IMAGE""") self.assert_remove_roundtrip(""" -BUGX1 WIN : failures/expected = FAIL""", 'failures/expected/keyboard.html', """ -BUGX1 WIN : failures/expected = FAIL""") +BUGX1 WIN : failures/expected = TEXT""", 'failures/expected/keyboard.html', """ +BUGX1 WIN : failures/expected = TEXT""") self.assert_remove_roundtrip(""" BUGX1 XP RELEASE : failures/expected/keyboard.html = IMAGE PASS @@ -326,11 +326,11 @@ BUG_UPDATE2 XP DEBUG : failures/expected/keyboard.html = TEXT BUG_UPDATE3 WIN RELEASE : failures/expected/keyboard.html = CRASH BUGX2 WIN : failures/expected/audio.html = IMAGE""") - editor.update_expectation(test, self.RELEASE_CONFIGS, set([FAIL]), ['BUG_UPDATE4']) + editor.update_expectation(test, self.RELEASE_CONFIGS, set([IMAGE_PLUS_TEXT]), ['BUG_UPDATE4']) self.assertEquals(TestExpectationSerializer.list_to_string(expectation_lines, converter), """ BUGX1 VISTA WIN7 DEBUG : failures/expected/keyboard.html = IMAGE BUG_UPDATE2 XP DEBUG : failures/expected/keyboard.html = TEXT -BUG_UPDATE4 RELEASE : failures/expected/keyboard.html = FAIL +BUG_UPDATE4 RELEASE : failures/expected/keyboard.html = IMAGE+TEXT BUGX2 WIN : failures/expected/audio.html = IMAGE""") editor.update_expectation(test, set(self.test_port.all_test_configurations()), set([TIMEOUT]), ['BUG_UPDATE5']) diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py b/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py index a1e3bee70..d321b5a41 100644 --- a/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py @@ -29,6 +29,7 @@ """Handle messages from the Manager and executes actual tests.""" import logging +import os import sys import threading import time @@ -65,7 +66,9 @@ class Worker(manager_worker_broker.AbstractWorker): self._driver = None self._tests_run_file = None self._tests_run_filename = None - self._meter = None + self._log_messages = [] + self._logger = None + self._log_handler = None def __del__(self): self.cleanup() @@ -83,29 +86,19 @@ class Worker(manager_worker_broker.AbstractWorker): self._tests_run_file = self._filesystem.open_text_file_for_writing(tests_run_filename) def _set_up_logging(self): + self._logger = logging.getLogger() + # The unix multiprocessing implementation clones the MeteredStream log handler - # into the child process, so we need to remove it before we can - # add a new one to get the correct pid logged. - root_logger = logging.getLogger() - handler_to_remove = None - for h in root_logger.handlers: + # into the child process, so we need to remove it to avoid duplicate logging. + for h in self._logger.handlers: # log handlers don't have names until python 2.7. if getattr(h, 'name', '') == metered_stream.LOG_HANDLER_NAME: - handler_to_remove = h + self._logger.removeHandler(h) break - if handler_to_remove: - root_logger.removeHandler(handler_to_remove) - - # FIXME: This won't work if the calling process is logging - # somewhere other than sys.stderr, but I'm not sure - # if this will be an issue in practice. Also, it would be - # nice if we trapped all of the messages for a given test - # and sent them back in finished_test() rather than logging - # them to stderr. - if not root_logger.handlers: - options = self._options - root_logger.setLevel(logging.DEBUG if options.verbose else logging.INFO) - self._meter = metered_stream.MeteredStream(sys.stderr, options.verbose, logger=root_logger) + + self._logger.setLevel(logging.DEBUG if self._options.verbose else logging.INFO) + self._log_handler = _WorkerLogHandler(self) + self._logger.addHandler(self._log_handler) def _set_up_host_and_port(self): options = self._options @@ -132,9 +125,9 @@ class Worker(manager_worker_broker.AbstractWorker): super(Worker, self).run() finally: self.kill_driver() - self._worker_connection.post_message('done') _log.debug("%s exiting" % self._name) self.cleanup() + self._worker_connection.post_message('done', self._log_messages) def handle_test_list(self, src, list_name, test_list): start_time = time.time() @@ -171,7 +164,9 @@ class Worker(manager_worker_broker.AbstractWorker): result = self.run_test_with_timeout(test_input, test_timeout_sec) elapsed_time = time.time() - start - self._worker_connection.post_message('finished_test', result, elapsed_time) + log_messages = self._log_messages + self._log_messages = [] + self._worker_connection.post_message('finished_test', result, elapsed_time, log_messages) self.clean_up_after_test(test_input, result) @@ -181,9 +176,10 @@ class Worker(manager_worker_broker.AbstractWorker): if self._tests_run_file: self._tests_run_file.close() self._tests_run_file = None - if self._meter: - self._meter.cleanup() - self._meter = None + if self._log_handler and self._logger: + self._logger.removeHandler(self._log_handler) + self._log_handler = None + self._logger = None def timeout(self, test_input): """Compute the appropriate timeout value for a test.""" @@ -300,3 +296,13 @@ class Worker(manager_worker_broker.AbstractWorker): def run_single_test(self, driver, test_input): return single_test_runner.run_single_test(self._port, self._options, test_input, driver, self._name) + + +class _WorkerLogHandler(logging.Handler): + def __init__(self, worker): + logging.Handler.__init__(self) + self._worker = worker + self._pid = os.getpid() + + def emit(self, record): + self._worker._log_messages.append(tuple([record.getMessage(), record.created, self._pid])) diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py index 0ff0d2f19..af36b2733 100644 --- a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py +++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py @@ -42,7 +42,6 @@ class JSONLayoutResultsGenerator(json_results_generator.JSONResultsGeneratorBase FAILURE_TO_CHAR = {test_expectations.PASS: json_results_generator.JSONResultsGeneratorBase.PASS_RESULT, test_expectations.SKIP: json_results_generator.JSONResultsGeneratorBase.SKIP_RESULT, - test_expectations.FAIL: "Y", test_expectations.CRASH: "C", test_expectations.TIMEOUT: "T", test_expectations.IMAGE: "I", diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py index c18452421..93ef517f4 100644 --- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py +++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py @@ -57,8 +57,6 @@ def result_was_expected(result, expected_results, test_needs_rebaselining, test_ test_is_skipped: whether test was marked as SKIP""" if result in expected_results: return True - if result in (IMAGE, TEXT, IMAGE_PLUS_TEXT) and FAIL in expected_results: - return True if result == MISSING and test_needs_rebaselining: return True if result == SKIP and test_is_skipped: @@ -85,6 +83,21 @@ def has_pixel_failures(actual_results): return IMAGE in actual_results or IMAGE_PLUS_TEXT in actual_results +# FIXME: Perhas these two routines should be part of the Port instead? +BASELINE_SUFFIX_LIST = ('png', 'wav', 'txt') + + +def suffixes_for_expectations(expectations): + suffixes = set() + if expectations.intersection(set([TEXT, IMAGE_PLUS_TEXT])): + suffixes.add('txt') + if expectations.intersection(set([IMAGE, IMAGE_PLUS_TEXT])): + suffixes.add('png') + if AUDIO in expectations: + suffixes.add('wav') + return set(suffixes) + + # FIXME: This method is no longer used here in this module. Remove remaining callsite in manager.py and this method. def strip_comments(line): """Strips comments from a line and return None if the line is empty @@ -210,8 +223,8 @@ class TestExpectationParser(object): self._full_test_list = full_test_list self._allow_rebaseline_modifier = allow_rebaseline_modifier - def parse(self, expectations_string): - expectations = TestExpectationParser._tokenize_list(expectations_string) + def parse(self, filename, expectations_string): + expectations = TestExpectationParser._tokenize_list(filename, expectations_string) for expectation_line in expectations: self._parse_line(expectation_line) return expectations @@ -221,6 +234,9 @@ class TestExpectationParser(object): expectation_line.original_string = test_name expectation_line.modifiers = [TestExpectationParser.DUMMY_BUG_MODIFIER, TestExpectationParser.SKIP_MODIFIER] expectation_line.name = test_name + # FIXME: we should pass in a more descriptive string here. + expectation_line.filename = '<Skipped file>' + expectation_line.line_number = 0 expectation_line.expectations = [TestExpectationParser.PASS_EXPECTATION] self._parse_line(expectation_line) return expectation_line @@ -292,7 +308,7 @@ class TestExpectationParser(object): if (not self._port.test_exists(expectation_line.name) and not self._port.test_exists(expectation_line.name + '-disabled')): # Log a warning here since you hit this case any - # time you update test_expectations.txt without syncing + # time you update TestExpectations without syncing # the LayoutTests directory expectation_line.warnings.append('Path does not exist.') return True @@ -322,8 +338,8 @@ class TestExpectationParser(object): expectation_line.matching_tests.append(expectation_line.path) @classmethod - def _tokenize(cls, expectation_string, line_number=None): - """Tokenizes a line from test_expectations.txt and returns an unparsed TestExpectationLine instance. + def _tokenize(cls, filename, expectation_string, line_number): + """Tokenizes a line from TestExpectations and returns an unparsed TestExpectationLine instance. The format of a test expectation line is: @@ -335,6 +351,7 @@ class TestExpectationParser(object): expectation_line = TestExpectationLine() expectation_line.original_string = expectation_string expectation_line.line_number = line_number + expectation_line.filename = filename comment_index = expectation_string.find("//") if comment_index == -1: comment_index = len(expectation_string) @@ -361,13 +378,13 @@ class TestExpectationParser(object): return expectation_line @classmethod - def _tokenize_list(cls, expectations_string): + def _tokenize_list(cls, filename, expectations_string): """Returns a list of TestExpectationLines, one for each line in expectations_string.""" expectation_lines = [] line_number = 0 for line in expectations_string.split("\n"): line_number += 1 - expectation_lines.append(cls._tokenize(line, line_number)) + expectation_lines.append(cls._tokenize(filename, line, line_number)) return expectation_lines @classmethod @@ -377,7 +394,7 @@ class TestExpectationParser(object): return [part.strip().lower() for part in space_separated_string.strip().split(' ')] -class TestExpectationLine: +class TestExpectationLine(object): """Represents a line in test expectations file.""" def __init__(self): @@ -417,7 +434,7 @@ class TestExpectationLine: class TestExpectationsModel(object): """Represents relational store of all expectations and provides CRUD semantics to manage it.""" - def __init__(self): + def __init__(self, shorten_filename=None): # Maps a test to its list of expectations. self._test_to_expectations = {} @@ -427,18 +444,13 @@ class TestExpectationsModel(object): # Maps a test to a TestExpectationLine instance. self._test_to_expectation_line = {} - # List of tests that are in the overrides file (used for checking for - # duplicates inside the overrides file itself). Note that just because - # a test is in this set doesn't mean it's necessarily overridding a - # expectation in the regular expectations; the test might not be - # mentioned in the regular expectations file at all. - self._overridding_tests = set() - self._modifier_to_tests = self._dict_of_sets(TestExpectations.MODIFIERS) self._expectation_to_tests = self._dict_of_sets(TestExpectations.EXPECTATIONS) self._timeline_to_tests = self._dict_of_sets(TestExpectations.TIMELINES) self._result_type_to_tests = self._dict_of_sets(TestExpectations.RESULT_TYPES) + self._shorten_filename = shorten_filename or (lambda x: x) + def _dict_of_sets(self, strings_to_constants): """Takes a dict of strings->constants and returns a dict mapping each constant to an empty set.""" @@ -503,31 +515,26 @@ class TestExpectationsModel(object): def get_expectations(self, test): return self._test_to_expectations[test] - def add_expectation_line(self, expectation_line, in_overrides=False, in_skipped=False): + def add_expectation_line(self, expectation_line, in_skipped=False): """Returns a list of warnings encountered while matching modifiers.""" if expectation_line.is_invalid(): return for test in expectation_line.matching_tests: - if not in_skipped and self._already_seen_better_match(test, expectation_line, in_overrides): + if not in_skipped and self._already_seen_better_match(test, expectation_line): continue self._clear_expectations_for_test(test, expectation_line) self._test_to_expectation_line[test] = expectation_line - self._add_test(test, expectation_line, in_overrides) + self._add_test(test, expectation_line) - def _add_test(self, test, expectation_line, in_overrides): + def _add_test(self, test, expectation_line): """Sets the expected state for a given test. This routine assumes the test has not been added before. If it has, use _clear_expectations_for_test() to reset the state prior to - calling this. - - Args: - test: test to add - expectation_line: expectation to add - in_overrides: whether we're parsing the regular expectations or the overridding expectations""" + calling this.""" self._test_to_expectations[test] = expectation_line.parsed_expectations for expectation in expectation_line.parsed_expectations: self._expectation_to_tests[expectation].add(test) @@ -549,11 +556,9 @@ class TestExpectationsModel(object): elif expectation_line.is_flaky(): self._result_type_to_tests[FLAKY].add(test) else: + # FIXME: What is this? self._result_type_to_tests[FAIL].add(test) - if in_overrides: - self._overridding_tests.add(test) - def _clear_expectations_for_test(self, test, expectation_line): """Remove prexisting expectations for this test. This happens if we are seeing a more precise path @@ -576,7 +581,7 @@ class TestExpectationsModel(object): if test in set_of_tests: set_of_tests.remove(test) - def _already_seen_better_match(self, test, expectation_line, in_overrides): + def _already_seen_better_match(self, test, expectation_line): """Returns whether we've seen a better match already in the file. Returns True if we've already seen a expectation_line.name that matches more of the test @@ -589,6 +594,10 @@ class TestExpectationsModel(object): prev_expectation_line = self._test_to_expectation_line[test] + if prev_expectation_line.filename != expectation_line.filename: + # We've moved on to a new expectation file, which overrides older ones. + return False + if len(prev_expectation_line.path) > len(expectation_line.path): # The previous path matched more of the test. return True @@ -597,20 +606,9 @@ class TestExpectationsModel(object): # This path matches more of the test. return False - if in_overrides and test not in self._overridding_tests: - # We have seen this path, but that's okay because it is - # in the overrides and the earlier path was in the - # expectations (not the overrides). - return False - # At this point we know we have seen a previous exact match on this # base path, so we need to check the two sets of modifiers. - if in_overrides: - expectation_source = "override" - else: - expectation_source = "expectation" - # FIXME: This code was originally designed to allow lines that matched # more modifiers to override lines that matched fewer modifiers. # However, we currently view these as errors. @@ -619,20 +617,28 @@ class TestExpectationsModel(object): # to be warnings and return False". if prev_expectation_line.matching_configurations == expectation_line.matching_configurations: - expectation_line.warnings.append('Duplicate or ambiguous %s.' % expectation_source) + expectation_line.warnings.append('Duplicate or ambiguous entry for %s on lines %s:%d and %s:%d.' % (expectation_line.name, + self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number, + self._shorten_filename(expectation_line.filename), expectation_line.line_number)) return True if prev_expectation_line.matching_configurations >= expectation_line.matching_configurations: - expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (expectation_line.line_number, prev_expectation_line.line_number)) + expectation_line.warnings.append('More specific entry for %s on line %s:%d overrides line %s:%d.' % (expectation_line.name, + self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number, + self._shorten_filename(expectation_line.filename), expectation_line.line_number)) # FIXME: return False if we want more specific to win. return True if prev_expectation_line.matching_configurations <= expectation_line.matching_configurations: - expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (prev_expectation_line.line_number, expectation_line.line_number)) + expectation_line.warnings.append('More specific entry for %s on line %s:%d overrides line %s:%d.' % (expectation_line.name, + self._shorten_filename(expectation_line.filename), expectation_line.line_number, + self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number)) return True if prev_expectation_line.matching_configurations & expectation_line.matching_configurations: - expectation_line.warnings.append('Entries on line %d and line %d match overlapping sets of configurations' % (prev_expectation_line.line_number, expectation_line.line_number)) + expectation_line.warnings.append('Entries for %s on lines %s:%d and %s:%d match overlapping sets of configurations.' % (expectation_line.name, + self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number, + self._shorten_filename(expectation_line.filename), expectation_line.line_number)) return True # Configuration sets are disjoint, then. @@ -645,9 +651,9 @@ class TestExpectations(object): in which case the expectations apply to all test cases in that directory and any subdirectory. The format is along the lines of: - LayoutTests/fast/js/fixme.js = FAIL - LayoutTests/fast/js/flaky.js = FAIL PASS - LayoutTests/fast/js/crash.js = CRASH TIMEOUT FAIL PASS + LayoutTests/fast/js/fixme.js = TEXT + LayoutTests/fast/js/flaky.js = TEXT PASS + LayoutTests/fast/js/crash.js = CRASH TIMEOUT TEXT PASS ... To add modifiers: @@ -663,20 +669,13 @@ class TestExpectations(object): Notes: -A test cannot be both SLOW and TIMEOUT - -A test should only be one of IMAGE, TEXT, IMAGE+TEXT, AUDIO, or FAIL. - FAIL is a legacy value that currently means either IMAGE, - TEXT, or IMAGE+TEXT. Once we have finished migrating the expectations, - we should change FAIL to have the meaning of IMAGE+TEXT and remove the - IMAGE+TEXT identifier. + -A test should only be one of IMAGE, TEXT, IMAGE+TEXT, or AUDIO. -A test can be included twice, but not via the same path. -If a test is included twice, then the more precise path wins. -CRASH tests cannot be WONTFIX """ - TEST_LIST = "test_expectations.txt" - EXPECTATIONS = {'pass': PASS, - 'fail': FAIL, 'text': TEXT, 'image': IMAGE, 'image+text': IMAGE_PLUS_TEXT, @@ -687,7 +686,6 @@ class TestExpectations(object): EXPECTATION_DESCRIPTIONS = {SKIP: ('skipped', 'skipped'), PASS: ('pass', 'passes'), - FAIL: ('failure', 'failures'), TEXT: ('text diff mismatch', 'text diff mismatch'), IMAGE: ('image mismatch', 'image mismatch'), @@ -699,7 +697,7 @@ class TestExpectations(object): MISSING: ('no expected result found', 'no expected results found')} - EXPECTATION_ORDER = (PASS, CRASH, TIMEOUT, MISSING, IMAGE_PLUS_TEXT, TEXT, IMAGE, AUDIO, FAIL, SKIP) + EXPECTATION_ORDER = (PASS, CRASH, TIMEOUT, MISSING, IMAGE_PLUS_TEXT, TEXT, IMAGE, AUDIO, SKIP) BUILD_TYPES = ('debug', 'release') @@ -722,23 +720,24 @@ class TestExpectations(object): assert(' ' not in string) # This only handles one expectation at a time. return cls.EXPECTATIONS.get(string.lower()) - def __init__(self, port, tests=None, is_lint_mode=False): + def __init__(self, port, tests=None, is_lint_mode=False, include_overrides=True): self._full_test_list = tests self._test_config = port.test_configuration() self._is_lint_mode = is_lint_mode - self._model = TestExpectationsModel() + self._model = TestExpectationsModel(self._shorten_filename) self._parser = TestExpectationParser(port, tests, is_lint_mode) self._port = port self._skipped_tests_warnings = [] - self._expectations = self._parser.parse(port.test_expectations()) - self._add_expectations(self._expectations, in_overrides=False) + expectations_dict = port.expectations_dict() + self._expectations = self._parser.parse(expectations_dict.keys()[0], expectations_dict.values()[0]) + self._add_expectations(self._expectations) - overrides = port.test_expectations_overrides() - if overrides: - overrides_expectations = self._parser.parse(overrides) - self._add_expectations(overrides_expectations, in_overrides=True) - self._expectations += overrides_expectations + if len(expectations_dict) > 1 and include_overrides: + for name in expectations_dict.keys()[1:]: + expectations = self._parser.parse(name, expectations_dict[name]) + self._add_expectations(expectations) + self._expectations += expectations # FIXME: move ignore_tests into port.skipped_layout_tests() self._add_skipped_tests(port.skipped_layout_tests(tests).union(set(port.get_option('ignore_tests', [])))) @@ -753,8 +752,7 @@ class TestExpectations(object): return self._model def get_rebaselining_failures(self): - return (self._model.get_test_set(REBASELINE, FAIL) | - self._model.get_test_set(REBASELINE, IMAGE) | + return (self._model.get_test_set(REBASELINE, IMAGE) | self._model.get_test_set(REBASELINE, TEXT) | self._model.get_test_set(REBASELINE, IMAGE_PLUS_TEXT) | self._model.get_test_set(REBASELINE, AUDIO)) @@ -813,17 +811,16 @@ class TestExpectations(object): def is_rebaselining(self, test): return self._model.has_modifier(test, REBASELINE) + def _shorten_filename(self, filename): + if filename.startswith(self._port.path_from_webkit_base()): + return self._port.host.filesystem.relpath(filename, self._port.path_from_webkit_base()) + return filename + def _report_warnings(self): warnings = [] - test_expectation_path = self._port.path_to_test_expectations_file() - if test_expectation_path.startswith(self._port.path_from_webkit_base()): - test_expectation_path = self._port.host.filesystem.relpath(test_expectation_path, self._port.path_from_webkit_base()) for expectation in self._expectations: for warning in expectation.warnings: - warnings.append('%s:%d %s %s' % (test_expectation_path, expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string)) - - for warning in self._skipped_tests_warnings: - warnings.append('%s%s' % (test_expectation_path, warning)) + warnings.append('%s:%d %s %s' % (self._shorten_filename(expectation.filename), expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string)) if warnings: self._has_warnings = True @@ -846,7 +843,7 @@ class TestExpectations(object): for expectation in self._expectations: if expectation.name != test or expectation.is_flaky() or not expectation.parsed_expectations: continue - if iter(expectation.parsed_expectations).next() not in (FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO): + if iter(expectation.parsed_expectations).next() not in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO): continue if test_configuration not in expectation.matching_configurations: continue @@ -869,20 +866,20 @@ class TestExpectations(object): return TestExpectationSerializer.list_to_string(filter(without_rebaseline_modifier, self._expectations)) - def _add_expectations(self, expectation_list, in_overrides): + def _add_expectations(self, expectation_list): for expectation_line in expectation_list: if not expectation_line.expectations: continue if self._is_lint_mode or self._test_config in expectation_line.matching_configurations: - self._model.add_expectation_line(expectation_line, in_overrides) + self._model.add_expectation_line(expectation_line) def _add_skipped_tests(self, tests_to_skip): if not tests_to_skip: return - for index, test in enumerate(self._expectations, start=1): + for test in self._expectations: if test.name and test.name in tests_to_skip: - self._skipped_tests_warnings.append(':%d %s is also in a Skipped file.' % (index, test.name)) + test.warnings.append('%s:%d %s is also in a Skipped file.' % (test.filename, test.line_number, test.name)) for test_name in tests_to_skip: expectation_line = self._parser.expectation_for_skipped_test(test_name) diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py index 0453a0818..7b589b501 100644 --- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py @@ -35,6 +35,12 @@ from webkitpy.layout_tests.models.test_configuration import * from webkitpy.layout_tests.models.test_expectations import * from webkitpy.layout_tests.models.test_configuration import * +try: + from collections import OrderedDict +except ImportError: + # Needed for Python < 2.7 + from webkitpy.thirdparty.ordered_dict import OrderedDict + class MockBugManager(object): def close_bug(self, bug_id, reference_bug_id=None): @@ -52,16 +58,6 @@ class FunctionsTest(unittest.TestCase): self.assertEquals(result_was_expected(TEXT, set([PASS]), False, False), False) - # test handling of FAIL expectations - self.assertEquals(result_was_expected(IMAGE_PLUS_TEXT, set([FAIL]), - False, False), True) - self.assertEquals(result_was_expected(IMAGE, set([FAIL]), - False, False), True) - self.assertEquals(result_was_expected(TEXT, set([FAIL]), - False, False), True) - self.assertEquals(result_was_expected(CRASH, set([FAIL]), - False, False), False) - # test handling of SKIPped tests and results self.assertEquals(result_was_expected(SKIP, set([CRASH]), False, True), True) @@ -86,6 +82,14 @@ class FunctionsTest(unittest.TestCase): self.assertEquals(remove_pixel_failures(set([PASS, IMAGE, CRASH])), set([PASS, CRASH])) + def test_suffixes_for_expectations(self): + self.assertEquals(suffixes_for_expectations(set([TEXT])), set(['txt'])) + self.assertEquals(suffixes_for_expectations(set([IMAGE_PLUS_TEXT])), set(['txt', 'png'])) + self.assertEquals(suffixes_for_expectations(set([IMAGE])), set(['png'])) + self.assertEquals(suffixes_for_expectations(set([AUDIO])), set(['wav'])) + self.assertEquals(suffixes_for_expectations(set([TEXT, IMAGE, CRASH])), set(['txt', 'png'])) + self.assertEquals(suffixes_for_expectations(set()), set()) + class Base(unittest.TestCase): # Note that all of these tests are written assuming the configuration @@ -119,8 +123,11 @@ BUG_TEST WONTFIX MAC : failures/expected/image.html = IMAGE """ def parse_exp(self, expectations, overrides=None, is_lint_mode=False): - self._port.test_expectations = lambda: expectations - self._port.test_expectations_overrides = lambda: overrides + self._expectations_dict = OrderedDict() + self._expectations_dict['expectations'] = expectations + if overrides: + self._expectations_dict['overrides'] = overrides + self._port.expectations_dict = lambda: self._expectations_dict self._exp = TestExpectations(self._port, self.get_basic_tests(), is_lint_mode) def assert_exp(self, test, result): @@ -197,17 +204,17 @@ BUGX WONTFIX : failures/expected = IMAGE SKIP : failures/expected/image.html""", is_lint_mode=True) self.assertFalse(True, "ParseError wasn't raised") except ParseError, e: - warnings = [u":1 Test lacks BUG modifier. failures/expected/text.html", - u":1 Unrecognized modifier 'foo' failures/expected/text.html", - u":2 Missing expectations SKIP : failures/expected/image.html"] - self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(warning) for warning in warnings)) + warnings = ("expectations:1 Test lacks BUG modifier. failures/expected/text.html\n" + "expectations:1 Unrecognized modifier 'foo' failures/expected/text.html\n" + "expectations:2 Missing expectations SKIP : failures/expected/image.html") + self.assertEqual(str(e), warnings) try: self.parse_exp('SKIP : failures/expected/text.html = TEXT', is_lint_mode=True) self.assertFalse(True, "ParseError wasn't raised") except ParseError, e: - warnings = [u':1 Test lacks BUG modifier. failures/expected/text.html'] - self.assertEqual(str(e), '\n'.join(self._port.path_to_test_expectations_file() + str(warning) for warning in warnings)) + warnings = u'expectations:1 Test lacks BUG modifier. failures/expected/text.html' + self.assertEqual(str(e), warnings) def test_error_on_different_platform(self): # parse_exp uses a Windows port. Assert errors on Mac show up in lint mode. @@ -226,6 +233,12 @@ SKIP : failures/expected/image.html""", is_lint_mode=True) "BUG_OVERRIDE : failures/expected/text.html = IMAGE") self.assert_exp('failures/expected/text.html', IMAGE) + def test_overrides__directory(self): + self.parse_exp("BUG_EXP: failures/expected/text.html = TEXT", + "BUG_OVERRIDE: failures/expected = CRASH") + self.assert_exp('failures/expected/text.html', CRASH) + self.assert_exp('failures/expected/image.html', CRASH) + def test_overrides__duplicate(self): self.assert_bad_expectations("BUG_EXP: failures/expected/text.html = TEXT", "BUG_OVERRIDE : failures/expected/text.html = IMAGE\n" @@ -261,8 +274,11 @@ class SkippedTests(Base): def check(self, expectations, overrides, skips, lint=False): port = MockHost().port_factory.get('qt') port._filesystem.write_text_file(port._filesystem.join(port.layout_tests_dir(), 'failures/expected/text.html'), 'foo') - port.test_expectations = lambda: expectations - port.test_expectations_overrides = lambda: overrides + self._expectations_dict = OrderedDict() + self._expectations_dict['expectations'] = expectations + if overrides: + self._expectations_dict['overrides'] = overrides + port.expectations_dict = lambda: self._expectations_dict port.skipped_layout_tests = lambda tests: set(skips) exp = TestExpectations(port, ['failures/expected/text.html'], lint) @@ -407,9 +423,9 @@ class RemoveConfigurationsTest(Base): test_port.test_isfile = lambda test: True test_config = test_port.test_configuration() - test_port.test_expectations = lambda: """BUGX LINUX WIN RELEASE : failures/expected/foo.html = TEXT + test_port.expectations_dict = lambda: {"expectations": """BUGX LINUX WIN RELEASE : failures/expected/foo.html = TEXT BUGY WIN MAC DEBUG : failures/expected/foo.html = CRASH -""" +"""} expectations = TestExpectations(test_port, self.get_basic_tests()) actual_expectations = expectations.remove_configuration_from_test('failures/expected/foo.html', test_config) @@ -425,9 +441,9 @@ BUGY WIN MAC DEBUG : failures/expected/foo.html = CRASH test_port.test_isfile = lambda test: True test_config = test_port.test_configuration() - test_port.test_expectations = lambda: """BUGX WIN RELEASE : failures/expected/foo.html = TEXT + test_port.expectations_dict = lambda: {'expectations': """BUGX WIN RELEASE : failures/expected/foo.html = TEXT BUGY WIN DEBUG : failures/expected/foo.html = CRASH -""" +"""} expectations = TestExpectations(test_port) actual_expectations = expectations.remove_configuration_from_test('failures/expected/foo.html', test_config) @@ -459,51 +475,54 @@ class RebaseliningTest(Base): class TestExpectationParserTests(unittest.TestCase): + def _tokenize(self, line): + return TestExpectationParser._tokenize('path', line, 0) + def test_tokenize_blank(self): - expectation = TestExpectationParser._tokenize('') + expectation = self._tokenize('') self.assertEqual(expectation.comment, None) self.assertEqual(len(expectation.warnings), 0) def test_tokenize_missing_colon(self): - expectation = TestExpectationParser._tokenize('Qux.') + expectation = self._tokenize('Qux.') self.assertEqual(str(expectation.warnings), '["Missing a \':\'"]') def test_tokenize_extra_colon(self): - expectation = TestExpectationParser._tokenize('FOO : : bar') + expectation = self._tokenize('FOO : : bar') self.assertEqual(str(expectation.warnings), '["Extraneous \':\'"]') def test_tokenize_empty_comment(self): - expectation = TestExpectationParser._tokenize('//') + expectation = self._tokenize('//') self.assertEqual(expectation.comment, '') self.assertEqual(len(expectation.warnings), 0) def test_tokenize_comment(self): - expectation = TestExpectationParser._tokenize('//Qux.') + expectation = self._tokenize('//Qux.') self.assertEqual(expectation.comment, 'Qux.') self.assertEqual(len(expectation.warnings), 0) def test_tokenize_missing_equal(self): - expectation = TestExpectationParser._tokenize('FOO : bar') + expectation = self._tokenize('FOO : bar') self.assertEqual(str(expectation.warnings), "['Missing expectations\']") def test_tokenize_extra_equal(self): - expectation = TestExpectationParser._tokenize('FOO : bar = BAZ = Qux.') + expectation = self._tokenize('FOO : bar = BAZ = Qux.') self.assertEqual(str(expectation.warnings), '["Extraneous \'=\'"]') def test_tokenize_valid(self): - expectation = TestExpectationParser._tokenize('FOO : bar = BAZ') + expectation = self._tokenize('FOO : bar = BAZ') self.assertEqual(expectation.comment, None) self.assertEqual(len(expectation.warnings), 0) def test_tokenize_valid_with_comment(self): - expectation = TestExpectationParser._tokenize('FOO : bar = BAZ //Qux.') + expectation = self._tokenize('FOO : bar = BAZ //Qux.') self.assertEqual(expectation.comment, 'Qux.') self.assertEqual(str(expectation.modifiers), '[\'foo\']') self.assertEqual(str(expectation.expectations), '[\'baz\']') self.assertEqual(len(expectation.warnings), 0) def test_tokenize_valid_with_multiple_modifiers(self): - expectation = TestExpectationParser._tokenize('FOO1 FOO2 : bar = BAZ //Qux.') + expectation = self._tokenize('FOO1 FOO2 : bar = BAZ //Qux.') self.assertEqual(expectation.comment, 'Qux.') self.assertEqual(str(expectation.modifiers), '[\'foo1\', \'foo2\']') self.assertEqual(str(expectation.expectations), '[\'baz\']') @@ -515,7 +534,7 @@ class TestExpectationParserTests(unittest.TestCase): test_port.test_exists = lambda test: True test_config = test_port.test_configuration() full_test_list = [] - expectation_line = TestExpectationParser._tokenize('') + expectation_line = self._tokenize('') parser = TestExpectationParser(test_port, full_test_list, allow_rebaseline_modifier=False) parser._parse_line(expectation_line) self.assertFalse(expectation_line.is_invalid()) @@ -529,14 +548,17 @@ class TestExpectationSerializerTests(unittest.TestCase): self._serializer = TestExpectationSerializer(self._converter) unittest.TestCase.__init__(self, testFunc) + def _tokenize(self, line): + return TestExpectationParser._tokenize('path', line, 0) + def assert_round_trip(self, in_string, expected_string=None): - expectation = TestExpectationParser._tokenize(in_string) + expectation = self._tokenize(in_string) if expected_string is None: expected_string = in_string self.assertEqual(expected_string, self._serializer.to_string(expectation)) def assert_list_round_trip(self, in_string, expected_string=None): - expectations = TestExpectationParser._tokenize_list(in_string) + expectations = TestExpectationParser._tokenize_list('path', in_string) if expected_string is None: expected_string = in_string self.assertEqual(expected_string, TestExpectationSerializer.list_to_string(expectations, self._converter)) @@ -588,10 +610,10 @@ class TestExpectationSerializerTests(unittest.TestCase): self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), '') expectation_line.parsed_expectations = set([IMAGE_PLUS_TEXT]) self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'image+text') - expectation_line.parsed_expectations = set([PASS, FAIL]) - self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass fail') - expectation_line.parsed_expectations = set([FAIL, PASS]) - self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass fail') + expectation_line.parsed_expectations = set([PASS, IMAGE]) + self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass image') + expectation_line.parsed_expectations = set([TEXT, PASS]) + self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass text') def test_parsed_modifier_string(self): expectation_line = TestExpectationLine() diff --git a/Tools/Scripts/webkitpy/layout_tests/port/apple.py b/Tools/Scripts/webkitpy/layout_tests/port/apple.py index b6e3b1d2e..8807d40d7 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/apple.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/apple.py @@ -90,6 +90,6 @@ class ApplePort(WebKitPort): version = self.FUTURE_VERSION for build_type in self.ALL_BUILD_TYPES: - # But at some later point we may need to make these configurable by the MacPort and WinPort subclasses. - configurations.append(TestConfiguration(version=version, architecture='x86', build_type=build_type)) + for architecture in self.ARCHITECTURES: + configurations.append(TestConfiguration(version=version, architecture=architecture, build_type=build_type)) return configurations diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py index c0e13dfcb..9e73b2c55 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/base.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py @@ -34,8 +34,16 @@ import cgi import difflib import errno import os +import optparse import re +try: + from collections import OrderedDict +except ImportError: + # Needed for Python < 2.7 + from webkitpy.thirdparty.ordered_dict import OrderedDict + + from webkitpy.common import find_files from webkitpy.common import read_checksum_from_png from webkitpy.common.memoized import memoized @@ -54,19 +62,6 @@ from webkitpy.layout_tests.servers import websocket_server _log = logutils.get_logger(__file__) -class DummyOptions(object): - """Fake implementation of optparse.Values. Cloned from webkitpy.tool.mocktool.MockOptions.""" - - def __init__(self, *args, **kwargs): - # The caller can set option values using keyword arguments. We don't - # set any values by default because we don't know how this - # object will be used. Generally speaking unit tests should - # subclass this or provider wrapper functions that set a common - # set of options. - for key, value in kwargs.items(): - self.__dict__[key] = value - - # FIXME: This class should merge with WebKitPort now that Chromium behaves mostly like other webkit ports. class Port(object): """Abstract class for Port-specific hooks for the layout_test package.""" @@ -104,7 +99,7 @@ class Port(object): # FIXME: Ideally we'd have a package-wide way to get a # well-formed options object that had all of the necessary # options defined on it. - self._options = options or DummyOptions() + self._options = options or optparse.Values() self.host = host self._executive = host.executive @@ -159,17 +154,7 @@ class Port(object): def default_child_processes(self): """Return the number of DumpRenderTree instances to use for this port.""" - cpu_count = self._executive.cpu_count() - # Make sure we have enough ram to support that many instances: - free_memory = self.host.platform.free_bytes_memory() - if free_memory: - bytes_per_drt = 200 * 1024 * 1024 # Assume each DRT needs 200MB to run. - supportable_instances = max(free_memory / bytes_per_drt, 1) # Always use one process, even if we don't have space for it. - if supportable_instances < cpu_count: - # FIXME: The Printer isn't initialized when this is called, so using _log would just show an unitialized logger error. - print "This machine could support %s child processes, but only has enough memory for %s." % (cpu_count, supportable_instances) - return min(supportable_instances, cpu_count) - return cpu_count + return self._executive.cpu_count() def worker_startup_delay_secs(self): # FIXME: If we start workers up too quickly, DumpRenderTree appears @@ -180,6 +165,15 @@ class Port(object): def baseline_path(self): """Return the absolute path to the directory to store new baselines in for this port.""" + # FIXME: remove once all callers are calling either baseline_version_dir() or baseline_platform_dir() + return self.baseline_version_dir() + + def baseline_platform_dir(self): + """Return the absolute path to the default (version-independent) platform-specific results.""" + return self._filesystem.join(self.layout_tests_dir(), 'platform', self.port_name) + + def baseline_version_dir(self): + """Return the absolute path to the platform-and-version-specific results.""" baseline_search_paths = self.get_option('additional_platform_directory', []) + self.baseline_search_path() return baseline_search_paths[0] @@ -489,8 +483,22 @@ class Port(object): return reftest_list.get(self._filesystem.join(self.layout_tests_dir(), test_name), []) def tests(self, paths): - """Return the list of tests found.""" - return self._real_tests(paths).union(self._virtual_tests(paths, self.populated_virtual_test_suites())) + """Return the list of tests found. Both generic and platform-specific tests matching paths should be returned.""" + expanded_paths = self._expanded_paths(paths) + return self._real_tests(expanded_paths).union(self._virtual_tests(expanded_paths, self.populated_virtual_test_suites())) + + def _expanded_paths(self, paths): + expanded_paths = [] + fs = self._filesystem + all_platform_dirs = [path for path in fs.glob(fs.join(self.layout_tests_dir(), 'platform', '*')) if fs.isdir(path)] + for path in paths: + expanded_paths.append(path) + if self.test_isdir(path) and not path.startswith('platform'): + for platform_dir in all_platform_dirs: + if fs.isdir(fs.join(platform_dir, path)): + expanded_paths.append(self.relative_test_filename(fs.join(platform_dir, path))) + + return expanded_paths def _real_tests(self, paths): # When collecting test cases, skip these directories @@ -657,30 +665,31 @@ class Port(object): return self._architecture def get_option(self, name, default_value=None): - # FIXME: Eventually we should not have to do a test for - # hasattr(), and we should be able to just do - # self.options.value. See additional FIXME in the constructor. - if hasattr(self._options, name): - return getattr(self._options, name) - return default_value + return getattr(self._options, name, default_value) def set_option_default(self, name, default_value): - # FIXME: Callers could also use optparse_parser.Values.ensure_value, - # since this should always be a optparse_parser.Values object. - if not hasattr(self._options, name) or getattr(self._options, name) is None: - return setattr(self._options, name, default_value) + return self._options.ensure_value(name, default_value) 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|.""" return self._config.path_from_webkit_base(*comps) + @memoized 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') + + # FIXME: We need to remove this when we make rebaselining work with multiple files and just generalize expectations_files(). + + # test_expectations are always in mac/ not mac-leopard/ by convention, hence we use port_name instead of name(). + port_name = self.port_name + if port_name.startswith('chromium') or port_name.startswith('google-chrome'): + port_name = 'chromium' + + return self._filesystem.join(self._webkit_baseline_path(port_name), 'TestExpectations') def relative_test_filename(self, filename): """Returns a test_name a realtive unix-style path for a filename under the LayoutTests @@ -765,7 +774,7 @@ class Port(object): def show_results_html_file(self, results_filename): """This routine should display the HTML file pointed at by results_filename in a users' browser.""" - return self.host.user.open_url(path.abspath_to_uri(results_filename)) + return self.host.user.open_url(path.abspath_to_uri(self.host.platform, results_filename)) def create_driver(self, worker_number, no_timeout=False): """Return a newly created Driver subclass for starting/stopping the test driver.""" @@ -876,28 +885,32 @@ class Port(object): # some ports have Skipped files which are returned as part of test_expectations(). return self._filesystem.exists(self.path_to_test_expectations_file()) - 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.""" - return self._filesystem.read_text_file(self.path_to_test_expectations_file()) + def expectations_dict(self): + """Returns an OrderedDict of name -> expectations strings. + The names are expected to be (but not required to be) paths in the filesystem. + If the name is a path, the file can be considered updatable for things like rebaselining, + so don't use names that are paths if they're not paths. + Generally speaking the ordering should be files in the filesystem in cascade order + (TestExpectations followed by Skipped, if the port honors both formats), + then any built-in expectations (e.g., from compile-time exclusions), then --additional-expectations options.""" + # FIXME: rename this to test_expectations() once all the callers are updated to know about the ordered dict. + expectations = OrderedDict() - def test_expectations_overrides(self): - """Returns an optional set of overrides for the test_expectations. + for path in self.expectations_files(): + expectations[path] = self._filesystem.read_text_file(path) - This is used by ports that have code in two repositories, and where - it is possible that you might need "downstream" expectations that - temporarily override the "upstream" expectations until the port can - sync up the two repos.""" - overrides = '' for path in self.get_option('additional_expectations', []): - if self._filesystem.exists(self._filesystem.expanduser(path)): + expanded_path = self._filesystem.expanduser(path) + if self._filesystem.exists(expanded_path): _log.debug("reading additional_expectations from path '%s'" % path) - overrides += self._filesystem.read_text_file(self._filesystem.expanduser(path)) + expectations[path] = self._filesystem.read_text_file(expanded_path) else: _log.warning("additional_expectations path '%s' does not exist" % path) - return overrides or None + return expectations + + def expectations_files(self): + # FIXME: see comment in path_to_expectations_file(). + return [self.path_to_test_expectations_file()] def repository_paths(self): """Returns a list of (repository_name, repository_path) tuples of its depending code base. diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py index 92edfe232..f7afb7b22 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py @@ -60,21 +60,7 @@ class PortTest(unittest.TestCase): def test_default_child_processes(self): port = self.make_port() - # Even though the MockPlatformInfo shows 1GB free memory (enough for 5 DRT instances) - # we're still limited by the 2 mock cores we have: - self.assertEqual(port.default_child_processes(), 2) - bytes_for_drt = 200 * 1024 * 1024 - - port.host.platform.free_bytes_memory = lambda: bytes_for_drt - expected_stdout = "This machine could support 2 child processes, but only has enough memory for 1.\n" - child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_stdout=expected_stdout) - self.assertEqual(child_processes, 1) - - # Make sure that we always use one process, even if we don't have the memory for it. - port.host.platform.free_bytes_memory = lambda: bytes_for_drt - 1 - expected_stdout = "This machine could support 2 child processes, but only has enough memory for 1.\n" - child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_stdout=expected_stdout) - self.assertEqual(child_processes, 1) + self.assertNotEquals(port.default_child_processes(), None) def test_format_wdiff_output_as_html(self): output = "OUTPUT %s %s %s" % (Port._WDIFF_DEL, Port._WDIFF_ADD, Port._WDIFF_END) @@ -280,31 +266,33 @@ class PortTest(unittest.TestCase): def test_additional_expectations(self): port = self.make_port(port_name='foo') - + port.port_name = 'foo' + port._filesystem.write_text_file('/mock-checkout/LayoutTests/platform/foo/TestExpectations', '') port._filesystem.write_text_file( '/tmp/additional-expectations-1.txt', 'content1\n') port._filesystem.write_text_file( '/tmp/additional-expectations-2.txt', 'content2\n') - self.assertEquals(None, port.test_expectations_overrides()) + self.assertEquals('\n'.join(port.expectations_dict().values()), '') port._options.additional_expectations = [ '/tmp/additional-expectations-1.txt'] - self.assertEquals('content1\n', port.test_expectations_overrides()) + self.assertEquals('\n'.join(port.expectations_dict().values()), '\ncontent1\n') port._options.additional_expectations = [ '/tmp/nonexistent-file', '/tmp/additional-expectations-1.txt'] - self.assertEquals('content1\n', port.test_expectations_overrides()) + self.assertEquals('\n'.join(port.expectations_dict().values()), '\ncontent1\n') port._options.additional_expectations = [ '/tmp/additional-expectations-1.txt', '/tmp/additional-expectations-2.txt'] - self.assertEquals('content1\ncontent2\n', port.test_expectations_overrides()) + self.assertEquals('\n'.join(port.expectations_dict().values()), '\ncontent1\n\ncontent2\n') def test_uses_test_expectations_file(self): port = self.make_port(port_name='foo') - port.path_to_test_expectations_file = lambda: '/mock-results/test_expectations.txt' + port.port_name = 'foo' + port.path_to_test_expectations_file = lambda: '/mock-results/TestExpectations' self.assertFalse(port.uses_test_expectations_file()) - port._filesystem = MockFileSystem({'/mock-results/test_expectations.txt': ''}) + port._filesystem = MockFileSystem({'/mock-results/TestExpectations': ''}) self.assertTrue(port.uses_test_expectations_file()) def test_find_no_paths_specified(self): @@ -406,9 +394,7 @@ class PortTest(unittest.TestCase): self.assertVirtual(port.check_image_diff) self.assertVirtual(port.create_driver, 0) self.assertVirtual(port.diff_image, None, None) - self.assertVirtual(port.path_to_test_expectations_file) self.assertVirtual(port.default_results_directory) - self.assertVirtual(port.test_expectations) self.assertVirtual(port._path_to_apache) self.assertVirtual(port._path_to_apache_config_file) self.assertVirtual(port._path_to_driver) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/builders.py b/Tools/Scripts/webkitpy/layout_tests/port/builders.py index 1249bb543..cc0fa6932 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/builders.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/builders.py @@ -53,13 +53,16 @@ _exact_matches = { "Webkit Mac10.7": {"port_name": "chromium-mac-lion", "specifiers": set(["lion"])}, # These builders are on build.webkit.org. + "Apple Lion Release WK1 (Tests)": {"port_name": "mac-lion", "specifiers": set(["lion"])}, + "Apple Lion Debug WK1 (Tests)": {"port_name": "mac-lion", "specifiers": set(["lion", "debug"])}, + "Apple Lion Release WK2 (Tests)": {"port_name": "mac-lion", "specifiers": set(["lion", "wk2"])}, + "Apple Lion Debug WK2 (Tests)": {"port_name": "mac-lion", "specifiers": set(["lion", "wk2", "debug"])}, + + "Apple Win XP Debug (Tests)": {"port_name": "win-xp", "specifiers": set(["win", "debug"])}, + "Apple Win 7 Release (Tests)": {"port_name": "win-xp", "specifiers": set(["win"])}, + "GTK Linux 32-bit Debug": {"port_name": "gtk", "specifiers": set(["gtk"])}, - "Leopard Intel Debug (Tests)": {"port_name": "mac-leopard", "specifiers": set(["leopard"])}, - "SnowLeopard Intel Release (Tests)": {"port_name": "mac-snowleopard", "specifiers": set(["snowleopard"])}, - "SnowLeopard Intel Release (WebKit2 Tests)": {"port_name": "mac-snowleopard-wk2", "specifiers": set(["wk2"])}, "Qt Linux Release": {"port_name": "qt-linux", "specifiers": set(["win", "linux", "mac"])}, - "Windows XP Debug (Tests)": {"port_name": "win-xp", "specifiers": set(["win"])}, - "Windows 7 Release (WebKit2 Tests)": {"port_name": "win-future-wk2", "specifiers": set(["wk2"])}, "EFL Linux Release": {"port_name": "efl", "specifiers": set(["efl"])}, } @@ -67,7 +70,7 @@ _exact_matches = { _fuzzy_matches = { # These builders are on build.webkit.org. r"SnowLeopard": "mac-snowleopard", - r"Lion": "mac-lion", + r"Apple Lion": "mac-lion", r"Leopard": "mac-leopard", r"Windows": "win", r"GTK": "gtk", diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py index 9db4cb570..2c1911072 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py @@ -37,20 +37,12 @@ import signal import subprocess import sys import time -import webbrowser -from webkitpy.common.config import urls from webkitpy.common.system import executive -from webkitpy.common.system.path import cygpath -from webkitpy.layout_tests.controllers.manager import Manager -from webkitpy.layout_tests.models import test_expectations from webkitpy.layout_tests.models.test_configuration import TestConfiguration from webkitpy.layout_tests.port.base import Port, VirtualTestSuite from webkitpy.layout_tests.port.driver import DriverOutput from webkitpy.layout_tests.port.webkit import WebKitDriver -from webkitpy.layout_tests.port import builders -from webkitpy.layout_tests.servers import http_server -from webkitpy.layout_tests.servers import websocket_server _log = logging.getLogger(__name__) @@ -85,6 +77,26 @@ class ChromiumPort(Port): 'android': ['icecreamsandwich'], } + DEFAULT_BUILD_DIRECTORIES = ('out',) + + @classmethod + def _static_build_path(cls, filesystem, build_directory, chromium_base, webkit_base, *comps): + if build_directory: + return filesystem.join(build_directory, *comps) + + for directory in cls.DEFAULT_BUILD_DIRECTORIES: + base_dir = filesystem.join(chromium_base, directory) + if filesystem.exists(base_dir): + return filesystem.join(base_dir, *comps) + + for directory in cls.DEFAULT_BUILD_DIRECTORIES: + base_dir = filesystem.join(webkit_base, directory) + if filesystem.exists(base_dir): + return filesystem.join(base_dir, *comps) + + # We have to default to something, so pick the last one. + return filesystem.join(base_dir, *comps) + @classmethod def _chromium_base_dir(cls, filesystem): module_path = filesystem.path_to_module(cls.__module__) @@ -232,9 +244,6 @@ class ChromiumPort(Port): self._chromium_base_dir_path = self._chromium_base_dir(self._filesystem) return self._filesystem.join(self._chromium_base_dir_path, *comps) - def path_to_test_expectations_file(self): - return self.path_from_webkit_base('LayoutTests', 'platform', 'chromium', 'test_expectations.txt') - def setup_environ_for_server(self, server_name=None): clean_env = super(ChromiumPort, self).setup_environ_for_server(server_name) # Webkit Linux (valgrind layout) bot needs these envvars. @@ -293,14 +302,6 @@ class ChromiumPort(Port): def all_baseline_variants(self): return self.ALL_BASELINE_VARIANTS - 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_path = self.path_to_test_expectations_file() - return self._filesystem.read_text_file(expectations_path) - def _generate_all_test_configurations(self): """Returns a sequence of the TestConfigurations the port supports.""" # By default, we assume we want to test every graphics type in @@ -320,37 +321,12 @@ class ChromiumPort(Port): 'win_layout_rel', ]) - def _expectations_file_contents(self, filetype, filepath): - if self._filesystem.exists(filepath): - _log.debug( - "reading %s test_expectations overrides from file '%s'" % - (filetype, filepath)) - return (self._filesystem.read_text_file(filepath) or '') - else: - # FIXME: This allows this to work with mock checkouts; - # This probably shouldn't be used with a mock checkout, though. - if not 'mock-checkout' in filepath: - _log.warning( - "%s test_expectations overrides file '%s' does not exist" % - (filetype, filepath)) - return '' - - def test_expectations_overrides(self): - combined_overrides = '' - combined_overrides += self._expectations_file_contents( - 'skia', self.path_from_chromium_base( - 'skia', 'skia_test_expectations.txt')) - # FIXME: It seems bad that run_webkit_tests.py uses a hardcoded dummy - # builder string instead of just using None. + def expectations_files(self): + paths = [self.path_to_test_expectations_file(), self.path_from_chromium_base('skia', 'skia_test_expectations.txt')] builder_name = self.get_option('builder_name', 'DUMMY_BUILDER_NAME') if builder_name == 'DUMMY_BUILDER_NAME' or '(deps)' in builder_name or builder_name in self.try_builder_names: - combined_overrides += self._expectations_file_contents( - 'chromium', self.path_from_chromium_base( - 'webkit', 'tools', 'layout_tests', 'test_expectations.txt')) - - base_overrides = super(ChromiumPort, self).test_expectations_overrides() - combined_overrides += (base_overrides or '') - return combined_overrides + paths.append(self.path_from_chromium_base('webkit', 'tools', 'layout_tests', 'test_expectations.txt')) + return paths def repository_paths(self): repos = super(ChromiumPort, self).repository_paths() @@ -387,6 +363,9 @@ class ChromiumPort(Port): # or any subclasses. # + def _build_path(self, *comps): + return self._static_build_path(self._filesystem, self.get_option('build_directory'), self.path_from_chromium_base(), self.path_from_webkit_base(), *comps) + def _check_driver_build_up_to_date(self, configuration): if configuration in ('Debug', 'Release'): try: @@ -667,6 +646,9 @@ class ChromiumDriver(WebKitDriver): test_time=run_time, timeout=timeout, error=error) def start(self, pixel_tests, per_test_args): + if not self._test_shell: + return super(ChromiumDriver, self).start(pixel_tests, per_test_args) + if not self._proc: self._start(pixel_tests, per_test_args) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py index c701fbfb3..6568692e8 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py @@ -152,6 +152,12 @@ class ChromiumAndroidPort(chromium.ChromiumPort): def __init__(self, host, port_name, **kwargs): chromium.ChromiumPort.__init__(self, host, port_name, **kwargs) + # FIXME: Stop using test_shell mode: https://bugs.webkit.org/show_bug.cgi?id=88542 + if not hasattr(self._options, 'additional_drt_flag'): + self._options.additional_drt_flag = [] + if not '--test-shell' in self._options.additional_drt_flag: + self._options.additional_drt_flag.append('--test-shell') + # The Chromium port for Android always uses the hardware GPU path. self._options.enable_hardware_gpu = True @@ -209,7 +215,7 @@ class ChromiumAndroidPort(chromium.ChromiumPort): # chromium-android. # FIXME: This is a temporary measure to reduce the manual work when # updating WebKit. This method should be removed when we merge - # test_expectations_android.txt into test_expectations.txt. + # test_expectations_android.txt into TestExpectations. expectations = chromium.ChromiumPort.test_expectations(self) return expectations.replace('LINUX ', 'LINUX ANDROID ') @@ -267,7 +273,7 @@ class ChromiumAndroidPort(chromium.ChromiumPort): def _path_to_driver(self, configuration=None): if not configuration: configuration = self.get_option('configuration') - return self._build_path(configuration, 'DumpRenderTree_apk/ChromeNativeTests-debug.apk') + return self._build_path(configuration, 'DumpRenderTree_apk/DumpRenderTree-debug.apk') def _path_to_helper(self): return self._build_path(self.get_option('configuration'), 'forwarder') @@ -477,9 +483,23 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver): ChromiumAndroidDriver._started_driver = self + retries = 0 + while not self._start_once(pixel_tests, per_test_args): + _log.error('Failed to start DumpRenderTree application. Log:\n' + self._port._get_logcat()) + retries += 1 + if retries >= 3: + raise AssertionError('Failed to start DumpRenderTree application multiple times. Give up.') + self.stop() + time.sleep(2) + + def _start_once(self, pixel_tests, per_test_args): self._port._run_adb_command(['logcat', '-c']) self._port._run_adb_command(['shell', 'echo'] + self.cmd_line(pixel_tests, per_test_args) + ['>', COMMAND_LINE_FILE]) - self._port._run_adb_command(['shell', 'am', 'start', '-n', DRT_ACTIVITY_FULL_NAME]) + start_result = self._port._run_adb_command(['shell', 'am', 'start', '-n', DRT_ACTIVITY_FULL_NAME]) + if start_result.find('Exception') != -1: + _log.error('Failed to start DumpRenderTree application. Exception:\n' + start_result) + return False + seconds = 0 while (not self._file_exists_on_device(self._in_fifo_path) or not self._file_exists_on_device(self._out_fifo_path) or @@ -487,8 +507,7 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver): time.sleep(1) seconds += 1 if seconds >= DRT_START_STOP_TIMEOUT_SECS: - _log.error('Failed to start DumpRenderTreeApplication. Log:\n' + self._port._get_logcat()) - raise AssertionError('Failed to start DumpRenderTree application.') + return False shell_cmd = self._port._adb_command + ['shell'] executive = self._port._executive @@ -531,7 +550,7 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver): else: # Inform the deadlock detector that the startup is successful without deadlock. normal_startup_event.set() - return + return True def run_test(self, driver_input): driver_output = chromium.ChromiumDriver.run_test(self, driver_input) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py index 3e07a6a73..05ee62dd6 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py @@ -57,6 +57,8 @@ class ChromiumLinuxPort(chromium.ChromiumPort): ], } + DEFAULT_BUILD_DIRECTORIES = ('sconsbuild', 'out') + @classmethod def _determine_driver_path_statically(cls, host, options): config_object = config.Config(host.executive, host.filesystem) @@ -70,18 +72,6 @@ class ChromiumLinuxPort(chromium.ChromiumPort): return cls._static_build_path(host.filesystem, build_directory, chromium_base, webkit_base, configuration, 'DumpRenderTree') @staticmethod - def _static_build_path(filesystem, build_directory, chromium_base, webkit_base, *comps): - if build_directory: - return filesystem.join(build_directory, *comps) - if filesystem.exists(filesystem.join(chromium_base, 'sconsbuild')): - return filesystem.join(chromium_base, 'sconsbuild', *comps) - if filesystem.exists(filesystem.join(chromium_base, 'out')): - return filesystem.join(chromium_base, 'out', *comps) - if filesystem.exists(filesystem.join(webkit_base, 'sconsbuild')): - return filesystem.join(webkit_base, 'sconsbuild', *comps) - return filesystem.join(webkit_base, 'out', *comps) - - @staticmethod def _determine_architecture(filesystem, executive, driver_path): file_output = '' if filesystem.exists(driver_path): @@ -137,9 +127,6 @@ class ChromiumLinuxPort(chromium.ChromiumPort): # PROTECTED METHODS # - def _build_path(self, *comps): - return self._static_build_path(self._filesystem, self.get_option('build_directory'), self.path_from_chromium_base(), self.path_from_webkit_base(), *comps) - def _check_apache_install(self): result = self._check_file_exists(self._path_to_apache(), "apache2") result = self._check_file_exists(self._path_to_apache_config_file(), "apache2 config file") and result diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux_unittest.py index 647596227..e0ef728bd 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux_unittest.py @@ -30,6 +30,7 @@ import unittest from webkitpy.common.system import executive_mock from webkitpy.common.system.systemhost_mock import MockSystemHost +from webkitpy.tool.mocktool import MockOptions from webkitpy.layout_tests.port import chromium_linux from webkitpy.layout_tests.port import port_testcase @@ -89,6 +90,29 @@ class ChromiumLinuxPortTest(port_testcase.PortTestCase): def test_operating_system(self): self.assertEqual('linux', self.make_port().operating_system()) + def test_build_path(self): + # Test that optional paths are used regardless of whether they exist. + options = MockOptions(configuration='Release', build_directory='/foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], '/foo') + + # Test that optional relative paths are returned unmodified. + options = MockOptions(configuration='Release', build_directory='foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], 'foo') + + # Test that we look in a chromium directory before the webkit directory. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out', '/mock-checkout/out'], '/mock-checkout/Source/WebKit/chromium/out') + + # Test that we prefer the legacy dir over the new dir. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/sconsbuild', '/mock-checkout/Source/WebKit/chromium/out'], '/mock-checkout/Source/WebKit/chromium/sconsbuild') + + def test_driver_name_option(self): + self.assertTrue(self.make_port()._path_to_driver().endswith('DumpRenderTree')) + self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver'))._path_to_driver().endswith('OtherDriver')) + + def test_path_to_image_diff(self): + self.assertEquals(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/ImageDiff') if __name__ == '__main__': port_testcase.main() diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py index e1cafccfd..698db7266 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py @@ -68,6 +68,8 @@ class ChromiumMacPort(chromium.ChromiumPort): ], } + DEFAULT_BUILD_DIRECTORIES = ('xcodebuild', 'out') + @classmethod def determine_full_port_name(cls, host, options, port_name): if port_name.endswith('-mac'): @@ -99,40 +101,10 @@ class ChromiumMacPort(chromium.ChromiumPort): def operating_system(self): return 'mac' - def default_child_processes(self): - # FIXME: As a temporary workaround while we figure out what's going - # on with https://bugs.webkit.org/show_bug.cgi?id=83076, reduce by - # half the # of workers we run by default on bigger machines. - default_count = super(ChromiumMacPort, self).default_child_processes() - if default_count >= 8: - cpu_count = self._executive.cpu_count() - return max(1, min(default_count, int(cpu_count / 2))) - return default_count - # # PROTECTED METHODS # - def _build_path(self, *comps): - if self.get_option('build_directory'): - return self._filesystem.join(self.get_option('build_directory'), - *comps) - base = self.path_from_chromium_base() - path = self._filesystem.join(base, 'out', *comps) - if self._filesystem.exists(path): - return path - - path = self._filesystem.join(base, 'xcodebuild', *comps) - if self._filesystem.exists(path): - return path - - base = self.path_from_webkit_base() - path = self._filesystem.join(base, 'out', *comps) - if self._filesystem.exists(path): - return path - - return self._filesystem.join(base, 'xcodebuild', *comps) - def check_wdiff(self, logging=True): try: # We're ignoring the return and always returning True diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py index 51948eceb..a85beca74 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py @@ -30,6 +30,7 @@ import unittest from webkitpy.layout_tests.port import chromium_mac from webkitpy.layout_tests.port import port_testcase +from webkitpy.tool.mocktool import MockOptions class ChromiumMacPortTest(port_testcase.PortTestCase): @@ -81,6 +82,30 @@ class ChromiumMacPortTest(port_testcase.PortTestCase): def test_operating_system(self): self.assertEqual('mac', self.make_port().operating_system()) + def test_build_path(self): + # Test that optional paths are used regardless of whether they exist. + options = MockOptions(configuration='Release', build_directory='/foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], '/foo') + + # Test that optional relative paths are returned unmodified. + options = MockOptions(configuration='Release', build_directory='foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], 'foo') + + # Test that we look in a chromium directory before the webkit directory. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out', '/mock-checkout/out'], '/mock-checkout/Source/WebKit/chromium/out') + + # Test that we prefer the legacy dir over the new dir. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/xcodebuild', '/mock-checkout/Source/WebKit/chromium/out'], '/mock-checkout/Source/WebKit/chromium/xcodebuild') + + def test_driver_name_option(self): + self.assertTrue(self.make_port()._path_to_driver().endswith('DumpRenderTree')) + self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver'))._path_to_driver().endswith('OtherDriver')) + + def test_path_to_image_diff(self): + self.assertEquals(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/ImageDiff') + if __name__ == '__main__': port_testcase.main() diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py index 16275d70e..532843a9f 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py @@ -160,6 +160,21 @@ class ChromiumDriverTest(unittest.TestCase): driver2.stop() self.assertTrue(time.time() - start_time < 20) + def test_stop_cleans_up_properly(self): + self.driver._test_shell = False + self.driver.start(True, []) + last_tmpdir = self.port._filesystem.last_tmpdir + self.assertNotEquals(last_tmpdir, None) + self.driver.stop() + self.assertFalse(self.port._filesystem.isdir(last_tmpdir)) + + def test_two_starts_cleans_up_properly(self): + # clone the WebKitDriverTest tests here since we override start() and stop() + self.driver._test_shell = False + self.driver.start(True, []) + last_tmpdir = self.port._filesystem.last_tmpdir + self.driver._start(True, []) + self.assertFalse(self.port._filesystem.isdir(last_tmpdir)) class ChromiumPortTest(port_testcase.PortTestCase): port_name = 'chromium-mac' @@ -237,12 +252,6 @@ class ChromiumPortTest(port_testcase.PortTestCase): self.default_configuration_called = True return 'default' - def test_path_to_image_diff(self): - # FIXME: These don't need to use endswith now that the port uses a MockFileSystem. - self.assertTrue(ChromiumPortTest.TestLinuxPort()._path_to_image_diff().endswith('/out/default/ImageDiff')) - self.assertTrue(ChromiumPortTest.TestMacPort()._path_to_image_diff().endswith('/xcodebuild/default/ImageDiff')) - self.assertTrue(ChromiumPortTest.TestWinPort()._path_to_image_diff().endswith('/default/ImageDiff.exe')) - def test_default_configuration(self): mock_options = MockOptions() port = ChromiumPortTest.TestLinuxPort(options=mock_options) @@ -283,62 +292,30 @@ class ChromiumPortTest(port_testcase.PortTestCase): exception_raised = True self.assertFalse(exception_raised) - def test_overrides_and_builder_names(self): + def test_expectations_files(self): port = self.make_port() + port.port_name = 'chromium' - filesystem = MockFileSystem() - port._filesystem = filesystem - port.path_from_chromium_base = lambda *comps: '/' + '/'.join(comps) - + expectations_path = port.path_to_test_expectations_file() chromium_overrides_path = port.path_from_chromium_base( 'webkit', 'tools', 'layout_tests', 'test_expectations.txt') - CHROMIUM_OVERRIDES = 'contents of %s\n' % chromium_overrides_path - filesystem.write_text_file(chromium_overrides_path, CHROMIUM_OVERRIDES) skia_overrides_path = port.path_from_chromium_base( 'skia', 'skia_test_expectations.txt') - SKIA_OVERRIDES = 'contents of %s\n' % skia_overrides_path - filesystem.write_text_file(skia_overrides_path, SKIA_OVERRIDES) - - additional_expectations_path = port.path_from_chromium_base( - 'additional_expectations.txt') - ADDITIONAL_EXPECTATIONS = 'contents of %s\n' % additional_expectations_path - filesystem.write_text_file(additional_expectations_path, ADDITIONAL_EXPECTATIONS) port._options.builder_name = 'DUMMY_BUILDER_NAME' - port._options.additional_expectations = [] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES + CHROMIUM_OVERRIDES) - port._options.additional_expectations = [additional_expectations_path] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES + CHROMIUM_OVERRIDES + ADDITIONAL_EXPECTATIONS) + self.assertEquals(port.expectations_files(), [expectations_path, skia_overrides_path, chromium_overrides_path]) port._options.builder_name = 'builder (deps)' - port._options.additional_expectations = [] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES + CHROMIUM_OVERRIDES) - port._options.additional_expectations = [additional_expectations_path] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES + CHROMIUM_OVERRIDES + ADDITIONAL_EXPECTATIONS) + self.assertEquals(port.expectations_files(), [expectations_path, skia_overrides_path, chromium_overrides_path]) # A builder which does NOT observe the Chromium test_expectations, # but still observes the Skia test_expectations... port._options.builder_name = 'builder' - port._options.additional_expectations = [] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES) - port._options.additional_expectations = [additional_expectations_path] - self.assertEquals(port.test_expectations_overrides(), - SKIA_OVERRIDES + ADDITIONAL_EXPECTATIONS) - - def test_driver_name_option(self): - self.assertTrue(ChromiumPortTest.TestLinuxPort()._path_to_driver().endswith('/out/default/DumpRenderTree')) - self.assertTrue(ChromiumPortTest.TestMacPort()._path_to_driver().endswith('/xcodebuild/default/DumpRenderTree.app/Contents/MacOS/DumpRenderTree')) - self.assertTrue(ChromiumPortTest.TestWinPort()._path_to_driver().endswith('/default/DumpRenderTree.exe')) - - options = MockOptions(driver_name='OtherDriver') - self.assertTrue(ChromiumPortTest.TestLinuxPort(options)._path_to_driver().endswith('/out/default/OtherDriver')) - self.assertTrue(ChromiumPortTest.TestMacPort(options)._path_to_driver().endswith('/xcodebuild/default/OtherDriver.app/Contents/MacOS/OtherDriver')) - self.assertTrue(ChromiumPortTest.TestWinPort(options)._path_to_driver().endswith('/default/OtherDriver.exe')) + self.assertEquals(port.expectations_files(), [expectations_path, skia_overrides_path]) + + def test_expectations_ordering(self): + # since we don't implement self.port_name in ChromiumPort. + pass class ChromiumPortLoggingTest(logtesting.LoggingTestCase): diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_win.py index b06fe9135..b76f7ee68 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_win.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_win.py @@ -66,6 +66,8 @@ class ChromiumWinPort(chromium.ChromiumPort): ], } + DEFAULT_BUILD_DIRECTORIES = ('build', 'out') + @classmethod def determine_full_port_name(cls, host, options, port_name): if port_name.endswith('-win'): @@ -128,14 +130,6 @@ class ChromiumWinPort(chromium.ChromiumPort): # # PROTECTED ROUTINES # - def _build_path(self, *comps): - if self.get_option('build_directory'): - return self._filesystem.join(self.get_option('build_directory'), *comps) - - p = self.path_from_chromium_base('build', *comps) - if self._filesystem.exists(p): - return p - return self._filesystem.join(self.path_from_webkit_base(), 'Source', 'WebKit', 'chromium', 'build', *comps) def _uses_apache(self): return False diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py index 5bff7e129..759bc7e1d 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_win_unittest.py @@ -34,14 +34,10 @@ from webkitpy.common.system.executive_mock import MockExecutive from webkitpy.common.system.filesystem_mock import MockFileSystem from webkitpy.layout_tests.port import chromium_win from webkitpy.layout_tests.port import port_testcase +from webkitpy.tool.mocktool import MockOptions class ChromiumWinTest(port_testcase.PortTestCase): - class RegisterCygwinOption(object): - def __init__(self): - self.register_cygwin = True - self.results_directory = '/' - port_name = 'chromium-win' port_maker = chromium_win.ChromiumWinPort os_name = 'win' @@ -66,7 +62,7 @@ class ChromiumWinTest(port_testcase.PortTestCase): self.assertEquals(env['CYGWIN_PATH'], '/mock-checkout/Source/WebKit/chromium/third_party/cygwin/bin') def test_setup_environ_for_server_register_cygwin(self): - port = self.make_port(options=ChromiumWinTest.RegisterCygwinOption()) + port = self.make_port(options=MockOptions(register_cygwin=True, results_directory='/')) port._executive = MockExecutive(should_log=True) expected_stderr = "MOCK run_command: ['/mock-checkout/Source/WebKit/chromium/third_party/cygwin/setup_mount.bat'], cwd=None\n" output = outputcapture.OutputCapture() @@ -111,16 +107,28 @@ class ChromiumWinTest(port_testcase.PortTestCase): self.assertEquals(port.baseline_path(), port._webkit_baseline_path('chromium-win')) def test_build_path(self): - port = self.make_port() - port._filesystem.files = { - '/mock-checkout/Source/WebKit/chromium/build/Release/DumpRenderTree.exe': 'exe', - } - self.assertEquals( - '/mock-checkout/Source/WebKit/chromium/build/Release/DumpRenderTree.exe', - port._path_to_driver('Release')) - self.assertEquals( - '/mock-checkout/Source/WebKit/chromium/build/Debug/DumpRenderTree.exe', - port._path_to_driver('Debug')) + # Test that optional paths are used regardless of whether they exist. + options = MockOptions(configuration='Release', build_directory='/foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], '/foo') + + # Test that optional relative paths are returned unmodified. + options = MockOptions(configuration='Release', build_directory='foo') + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out'], 'foo') + + # Test that we look in a chromium directory before the webkit directory. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/out', '/mock-checkout/out'], '/mock-checkout/Source/WebKit/chromium/out') + + # Test that we prefer the legacy dir over the new dir. + options = MockOptions(configuration='Release', build_directory=None) + self.assert_build_path(options, ['/mock-checkout/Source/WebKit/chromium/build', '/mock-checkout/Source/WebKit/chromium/out'], '/mock-checkout/Source/WebKit/chromium/build') def test_operating_system(self): self.assertEqual('win', self.make_port().operating_system()) + + def test_driver_name_option(self): + self.assertTrue(self.make_port()._path_to_driver().endswith('DumpRenderTree.exe')) + self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver'))._path_to_driver().endswith('OtherDriver.exe')) + + def test_path_to_image_diff(self): + self.assertEquals(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/ImageDiff.exe') diff --git a/Tools/Scripts/webkitpy/layout_tests/port/config.py b/Tools/Scripts/webkitpy/layout_tests/port/config.py index 6a1045f12..9297b8872 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/config.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/config.py @@ -78,7 +78,7 @@ class Config(object): if not self._build_directories.get(configuration): args = ["perl", self.script_path("webkit-build-directory")] + flags - output = self._executive.run_command(args, cwd=self.webkit_base_dir()).rstrip() + output = self._executive.run_command(args, cwd=self.webkit_base_dir(), return_stderr=False).rstrip() parts = output.split("\n") self._build_directories[configuration] = parts[0] diff --git a/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py index 08b9af16c..c7d22c966 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py @@ -46,8 +46,8 @@ class ConfigTest(unittest.TestCase): def tearDown(self): config.clear_cached_configuration() - def make_config(self, output='', files=None, exit_code=0, exception=None, run_command_fn=None): - e = MockExecutive2(output=output, exit_code=exit_code, exception=exception, run_command_fn=run_command_fn) + def make_config(self, output='', files=None, exit_code=0, exception=None, run_command_fn=None, stderr=''): + e = MockExecutive2(output=output, exit_code=exit_code, exception=exception, run_command_fn=run_command_fn, stderr=stderr) fs = MockFileSystem(files) return config.Config(e, fs) @@ -87,6 +87,10 @@ class ConfigTest(unittest.TestCase): self.assertTrue(c.build_directory('Debug').endswith('/Debug')) self.assertRaises(KeyError, c.build_directory, 'Unknown') + # Test that stderr output from webkit-build-directory won't mangle the build dir + c = self.make_config(output='/WebKitBuild/', stderr="mock stderr output from webkit-build-directory") + self.assertEqual(c.build_directory(None), '/WebKitBuild/') + def test_default_configuration__release(self): self.assert_configuration('Release', 'Release') diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver.py b/Tools/Scripts/webkitpy/layout_tests/port/driver.py index a113da3a8..f65db2f7b 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/driver.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/driver.py @@ -132,7 +132,7 @@ class Driver(object): def test_to_uri(self, test_name): """Convert a test name to a URI.""" if not self.is_http_test(test_name): - return path.abspath_to_uri(self._port.abspath_for_test(test_name)) + return path.abspath_to_uri(self._port.host.platform, self._port.abspath_for_test(test_name)) relative_path = test_name[len(self.HTTP_DIR):] @@ -150,7 +150,10 @@ class Driver(object): """ if uri.startswith("file:///"): - return uri[len(path.abspath_to_uri(self._port.layout_tests_dir()) + "/"):] + prefix = path.abspath_to_uri(self._port.host.platform, self._port.layout_tests_dir()) + if not prefix.endswith('/'): + prefix += '/' + return uri[len(prefix):] if uri.startswith("http://"): return uri.replace('http://127.0.0.1:8000/', self.HTTP_DIR) if uri.startswith("https://"): diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py index 08d4d9882..00a42f42f 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py @@ -29,7 +29,6 @@ import sys import unittest -from webkitpy.common.system.path import abspath_to_uri from webkitpy.common.system.systemhost_mock import MockSystemHost from webkitpy.layout_tests.port import Port, Driver, DriverOutput @@ -105,20 +104,14 @@ class DriverTest(unittest.TestCase): def test_test_to_uri(self): port = self.make_port() driver = Driver(port, None, pixel_tests=False) - if sys.platform in ('cygwin', 'win32'): - self.assertEqual(driver.test_to_uri('foo/bar.html'), 'file:///%s/foo/bar.html' % port.layout_tests_dir()) - else: - self.assertEqual(driver.test_to_uri('foo/bar.html'), 'file://%s/foo/bar.html' % port.layout_tests_dir()) + self.assertEqual(driver.test_to_uri('foo/bar.html'), 'file://%s/foo/bar.html' % port.layout_tests_dir()) self.assertEqual(driver.test_to_uri('http/tests/foo.html'), 'http://127.0.0.1:8000/foo.html') self.assertEqual(driver.test_to_uri('http/tests/ssl/bar.html'), 'https://127.0.0.1:8443/ssl/bar.html') def test_uri_to_test(self): port = self.make_port() driver = Driver(port, None, pixel_tests=False) - if sys.platform in ('cygwin', 'win32'): - self.assertEqual(driver.uri_to_test('file:///%s/foo/bar.html' % port.layout_tests_dir()), 'foo/bar.html') - else: - self.assertEqual(driver.uri_to_test('file://%s/foo/bar.html' % port.layout_tests_dir()), 'foo/bar.html') + self.assertEqual(driver.uri_to_test('file://%s/foo/bar.html' % port.layout_tests_dir()), 'foo/bar.html') self.assertEqual(driver.uri_to_test('http://127.0.0.1:8000/foo.html'), 'http/tests/foo.html') self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/ssl/bar.html'), 'http/tests/ssl/bar.html') diff --git a/Tools/Scripts/webkitpy/layout_tests/port/factory.py b/Tools/Scripts/webkitpy/layout_tests/port/factory.py index 9f5df7c7e..881a80bec 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/factory.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/factory.py @@ -53,13 +53,15 @@ def port_options(**help_strings): optparse.make_option('--gtk', action='store_const', const='gtk', dest="platform", help='Alias for --platform=gtk'), optparse.make_option('--qt', action='store_const', const='qt', dest="platform", - help='Alias for --platform=qt')] + help='Alias for --platform=qt'), + optparse.make_option('--32-bit', action='store_const', const='x86', default=None, dest="architecture", + help='use 32-bit binaries by default (x86 instead of x86_64)')] -class BuilderOptions(object): - def __init__(self, builder_name): - self.configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release" - self.builder_name = builder_name +def _builder_options(builder_name): + configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release" + builder_name = builder_name + return optparse.Values({'builder_name': builder_name, 'configuration': configuration}) class PortFactory(object): @@ -127,6 +129,6 @@ class PortFactory(object): def get_from_builder_name(self, builder_name): port_name = builders.port_name_for_builder_name(builder_name) assert(port_name) # Need to update port_name_for_builder_name - port = self.get(port_name, BuilderOptions(builder_name)) + port = self.get(port_name, _builder_options(builder_name)) assert(port) # Need to update port_name_for_builder_name return port diff --git a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py index 9fc20582f..700399e28 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py @@ -120,6 +120,10 @@ class FactoryTest(unittest.TestCase): def test_unknown_default(self): self.assertRaises(NotImplementedError, factory.PortFactory(MockSystemHost(os_name='vms')).get) + def test_get_from_builder_name(self): + self.assertEquals(factory.PortFactory(MockSystemHost()).get_from_builder_name('Webkit Mac10.7').name(), + 'chromium-mac-lion') + if __name__ == '__main__': unittest.main() diff --git a/Tools/Scripts/webkitpy/layout_tests/port/google_chrome.py b/Tools/Scripts/webkitpy/layout_tests/port/google_chrome.py index 6d5d9276b..8d2df0ee9 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/google_chrome.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/google_chrome.py @@ -29,21 +29,8 @@ import chromium_mac import chromium_win -def _test_expectations_overrides(port, super): - # The chrome ports use the regular overrides plus anything in the - # official test_expectations as well. Hopefully we don't get collisions. - chromium_overrides = super.test_expectations_overrides(port) - - # FIXME: It used to be that AssertionError would get raised by - # path_from_chromium_base() if we weren't in a Chromium checkout, but - # this changed in r60427. This should probably be changed back. - overrides_path = port.path_from_chromium_base('webkit', 'tools', - 'layout_tests', 'test_expectations_chrome.txt') - if not port._filesystem.exists(overrides_path): - return chromium_overrides - - chromium_overrides = chromium_overrides or '' - return chromium_overrides + port._filesystem.read_text_file(overrides_path) +def _expectations_files(port, super): + return super.expectations_files(port) + [port.path_from_chromium_base('webkit', 'tools', 'layout_tests', 'test_expectations_chrome.txt')] class GoogleChromeLinux32Port(chromium_linux.ChromiumLinuxPort): @@ -59,8 +46,8 @@ class GoogleChromeLinux32Port(chromium_linux.ChromiumLinuxPort): paths.insert(0, self._webkit_baseline_path('google-chrome-linux32')) return paths - def test_expectations_overrides(self): - return _test_expectations_overrides(self, chromium_linux.ChromiumLinuxPort) + def expectations_files(self): + return _expectations_files(self, chromium_linux.ChromiumLinuxPort) def architecture(self): return 'x86' @@ -79,8 +66,8 @@ class GoogleChromeLinux64Port(chromium_linux.ChromiumLinuxPort): paths.insert(0, self._webkit_baseline_path('google-chrome-linux64')) return paths - def test_expectations_overrides(self): - return _test_expectations_overrides(self, chromium_linux.ChromiumLinuxPort) + def expectations_files(self): + return _expectations_files(self, chromium_linux.ChromiumLinuxPort) def architecture(self): return 'x86_64' @@ -99,8 +86,8 @@ class GoogleChromeMacPort(chromium_mac.ChromiumMacPort): paths.insert(0, self._webkit_baseline_path('google-chrome-mac')) return paths - def test_expectations_overrides(self): - return _test_expectations_overrides(self, chromium_mac.ChromiumMacPort) + def expectations_files(self): + return _expectations_files(self, chromium_mac.ChromiumMacPort) class GoogleChromeWinPort(chromium_win.ChromiumWinPort): @@ -116,5 +103,5 @@ class GoogleChromeWinPort(chromium_win.ChromiumWinPort): paths.insert(0, self._webkit_baseline_path('google-chrome-win')) return paths - def test_expectations_overrides(self): - return _test_expectations_overrides(self, chromium_win.ChromiumWinPort) + def expectations_files(self): + return _expectations_files(self, chromium_win.ChromiumWinPort) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py index 9d3653ae5..6d3c1a7dd 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py @@ -38,23 +38,10 @@ class TestGoogleChromePort(unittest.TestCase): def _verify_expectations_overrides(self, port_name): host = MockSystemHost() - chromium_port = PortFactory(host).get("chromium-mac-leopard") - chromium_base = chromium_port.path_from_chromium_base() port = PortFactory(host).get(port_name=port_name, options=None) - - expected_chromium_overrides = '// chromium overrides\n' - expected_chrome_overrides = '// chrome overrides\n' - chromium_path = host.filesystem.join(chromium_base, 'webkit', 'tools', 'layout_tests', 'test_expectations.txt') - chrome_path = host.filesystem.join(chromium_base, 'webkit', 'tools', 'layout_tests', 'test_expectations_chrome.txt') - - host.filesystem.files[chromium_path] = expected_chromium_overrides - host.filesystem.files[chrome_path] = None - actual_chrome_overrides = port.test_expectations_overrides() - self.assertEqual(expected_chromium_overrides, actual_chrome_overrides) - - host.filesystem.files[chrome_path] = expected_chrome_overrides - actual_chrome_overrides = port.test_expectations_overrides() - self.assertEqual(actual_chrome_overrides, expected_chromium_overrides + expected_chrome_overrides) + self.assertTrue('TestExpectations' in port.expectations_files()[0]) + self.assertTrue('skia_test_expectations.txt' in port.expectations_files()[1]) + self.assertTrue('test_expectations_chrome.txt' in port.expectations_files()[-1]) def test_get_google_chrome_port(self): self._verify_baseline_search_path_startswith('google-chrome-linux32', ['google-chrome-linux32', 'chromium-linux-x86']) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mac.py b/Tools/Scripts/webkitpy/layout_tests/port/mac.py index fa57cc3f7..a3ec6a4b9 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/mac.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/mac.py @@ -31,6 +31,7 @@ import logging import os import re import subprocess +import sys import time from webkitpy.common.system.crashlogs import CrashLogs @@ -49,14 +50,24 @@ class MacPort(ApplePort): # and the order of fallback between them. Matches ORWT. VERSION_FALLBACK_ORDER = ["mac-leopard", "mac-snowleopard", "mac-lion", "mac"] + ARCHITECTURES = ['x86_64', 'x86'] + def __init__(self, host, port_name, **kwargs): ApplePort.__init__(self, host, port_name, **kwargs) + self._architecture = self.get_option('architecture') + + if not self._architecture: + self._architecture = 'x86_64' + self._leak_detector = LeakDetector(self) if self.get_option("leaks"): # DumpRenderTree slows down noticably if we run more than about 1000 tests in a batch # with MallocStackLogging enabled. self.set_option_default("batch_size", 1000) + def _build_driver_flags(self): + return ['ARCHS=i386'] if self.architecture() == 'x86' else [] + def _most_recent_version(self): # This represents the most recently-shipping version of the operating system. return self.VERSION_FALLBACK_ORDER[-2] @@ -107,18 +118,22 @@ class MacPort(ApplePort): return self._version == "lion" def default_child_processes(self): + # FIXME: The Printer isn't initialized when this is called, so using _log would just show an unitialized logger error. + if self.is_snowleopard(): - _log.warn("Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525.") + print >> sys.stderr, "Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525." return 1 - # FIXME: As a temporary workaround while we figure out what's going - # on with https://bugs.webkit.org/show_bug.cgi?id=83076, reduce by - # half the # of workers we run by default on bigger machines. default_count = super(MacPort, self).default_child_processes() - if default_count >= 8: - cpu_count = self._executive.cpu_count() - return max(1, min(default_count, int(cpu_count / 2))) - return default_count + + # Make sure we have enough ram to support that many instances: + total_memory = self.host.platform.total_bytes_memory() + bytes_per_drt = 256 * 1024 * 1024 # Assume each DRT needs 256MB to run. + overhead = 2048 * 1024 * 1024 # Assume we need 2GB free for the O/S + supportable_instances = max((total_memory - overhead) / bytes_per_drt, 1) # Always use one process, even if we don't have space for it. + if supportable_instances < default_count: + print >> sys.stderr, "This machine could support %s child processes, but only has enough memory for %s." % (default_count, supportable_instances) + return min(supportable_instances, default_count) def _build_java_test_support(self): java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java") diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py index 0b9bca978..2ebf255ae 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py @@ -183,10 +183,22 @@ java/ # MockPlatformInfo only has 2 mock cores. The important part is that 2 > 1. self.assertEqual(port.default_child_processes(), 2) + bytes_for_drt = 200 * 1024 * 1024 + port.host.platform.total_bytes_memory = lambda: bytes_for_drt + expected_stderr = "This machine could support 2 child processes, but only has enough memory for 1.\n" + child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_stderr=expected_stderr) + self.assertEqual(child_processes, 1) + + # Make sure that we always use one process, even if we don't have the memory for it. + port.host.platform.total_bytes_memory = lambda: bytes_for_drt - 1 + expected_stderr = "This machine could support 2 child processes, but only has enough memory for 1.\n" + child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_stderr=expected_stderr) + self.assertEqual(child_processes, 1) + # SnowLeopard has a CFNetwork bug which causes crashes if we execute more than one copy of DRT at once. port = self.make_port(port_name='mac-snowleopard') - expected_logs = "Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525.\n" - child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_logs=expected_logs) + expected_stderr = "Cannot run tests in parallel on Snow Leopard due to rdar://problem/10621525.\n" + child_processes = OutputCapture().assert_outputs(self, port.default_child_processes, (), expected_stderr=expected_stderr) self.assertEqual(child_processes, 1) def test_get_crash_log(self): @@ -253,3 +265,26 @@ java/ port = self.make_port() port._executive = MockExecutive2(run_command_fn=throwing_run_command) OutputCapture().assert_outputs(self, port.sample_process, args=['test', 42]) + + def test_32bit(self): + port = self.make_port(options=MockOptions(architecture='x86')) + + def run_script(script, args=None, env=None): + self.args = args + + port._run_script = run_script + self.assertEquals(port.architecture(), 'x86') + port._build_driver() + self.assertEquals(self.args, ['ARCHS=i386']) + + def test_64bit(self): + # Apple Mac port is 64-bit by default + port = self.make_port() + self.assertEquals(port.architecture(), 'x86_64') + + def run_script(script, args=None, env=None): + self.args = args + + port._run_script = run_script + port._build_driver() + self.assertEquals(self.args, []) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py index 605071805..570a9e4ad 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py @@ -49,11 +49,6 @@ class MockDRTPortTest(port_testcase.PortTestCase): def make_port(self, options=mock_options): host = MockSystemHost() test.add_unit_tests_to_mock_filesystem(host.filesystem) - if sys.platform == 'win32': - # We use this because the 'win' port doesn't work yet. - host.platform.os_name = 'win' - host.platform.os_version = 'xp' - return mock_drt.MockDRTPort(host, port_name='mock-chromium-win', options=options) return mock_drt.MockDRTPort(host, port_name='mock-mac', options=options) def test_port_name_in_constructor(self): @@ -93,10 +88,7 @@ class MockDRTTest(unittest.TestCase): def input_line(self, port, test_name, checksum=None): url = port.create_driver(0).test_to_uri(test_name) if url.startswith('file://'): - if sys.platform == 'win32': - url = url[len('file:///'):] - else: - url = url[len('file://'):] + url = url[len('file://'):] if checksum: return url + "'" + checksum + '\n' @@ -247,9 +239,6 @@ class MockChromiumDRTTest(MockDRTTest): def test_pixeltest__fails(self): host = MockSystemHost() url = '#URL:file://' - if sys.platform == 'win32': - host = MockSystemHost(os_name='win', os_version='xp') - url = '#URL:file:///' url = url + '%s/failures/expected/image_checksum.html' % PortFactory(host).get('test').layout_tests_dir() self.assertTest('failures/expected/image_checksum.html', pixel_tests=True, expected_checksum='image_checksum', diff --git a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py index 4bdc3ed13..f37273f78 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py @@ -333,6 +333,30 @@ class PortTestCase(unittest.TestCase): u'STDOUT: foo\ufffdbar\n' u'STDERR: foo\ufffdbar\n')) + def assert_build_path(self, options, dirs, expected_path): + port = self.make_port(options=options) + for directory in dirs: + port.host.filesystem.maybe_make_directory(directory) + self.assertEquals(port._build_path(), expected_path) + + def test_expectations_ordering(self): + port = self.make_port() + for path in port.expectations_files(): + port._filesystem.write_text_file(path, '') + ordered_dict = port.expectations_dict() + self.assertEquals(port.path_to_test_expectations_file(), ordered_dict.keys()[0]) + + options = MockOptions(additional_expectations=['/tmp/foo', '/tmp/bar']) + port = self.make_port(options=options) + for path in port.expectations_files(): + port._filesystem.write_text_file(path, '') + port._filesystem.write_text_file('/tmp/foo', 'foo') + port._filesystem.write_text_file('/tmp/bar', 'bar') + ordered_dict = port.expectations_dict() + self.assertEquals(ordered_dict.keys()[-2:], options.additional_expectations) + self.assertEquals(ordered_dict.values()[-2:], ['foo', 'bar']) + + # FIXME: This class and main() should be merged into test-webkitpy. class EnhancedTestLoader(unittest.TestLoader): integration_tests = False diff --git a/Tools/Scripts/webkitpy/layout_tests/port/qt.py b/Tools/Scripts/webkitpy/layout_tests/port/qt.py index 520575952..2488936fe 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/qt.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/qt.py @@ -81,9 +81,6 @@ class QtPort(WebKitPort): # The Qt port builds DRT as part of the main build step return True - def _driver_class(self): - return XvfbDriver - def _path_to_driver(self): return self._build_path('bin/%s' % self.driver_name()) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py index 4257d5455..b5ce05391 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py @@ -100,11 +100,15 @@ class TestServerProcess(unittest.TestCase): line = proc.read_stdout_line(now - 1) self.assertEquals(line, None) + # FIXME: This part appears to be flaky. line should always be non-None. + # FIXME: https://bugs.webkit.org/show_bug.cgi?id=88280 line = proc.read_stdout_line(now + 1.0) - self.assertEquals(line.strip(), "stdout") + if line: + self.assertEquals(line.strip(), "stdout") line = proc.read_stderr_line(now + 1.0) - self.assertEquals(line.strip(), "stderr") + if line: + self.assertEquals(line.strip(), "stderr") proc.stop() diff --git a/Tools/Scripts/webkitpy/layout_tests/port/test.py b/Tools/Scripts/webkitpy/layout_tests/port/test.py index 8abd81235..25c6a13be 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/test.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/test.py @@ -174,6 +174,7 @@ layer at (0,0) size 800x34 tests.add('passes/checksum_in_image.html', expected_checksum=None, expected_image='tEXtchecksum\x00checksum_in_image-checksum') + tests.add('passes/skipped/skip.html') # Note that here the checksums don't match but the images do, so this test passes "unexpectedly". # See https://bugs.webkit.org/show_bug.cgi?id=69444 . @@ -233,12 +234,8 @@ layer at (0,0) size 800x34 # this works. The path contains a '.' in the name because we've seen bugs # related to this before. -if sys.platform == 'win32': - LAYOUT_TEST_DIR = 'c:/test.checkout/LayoutTests' - PERF_TEST_DIR = 'c:/test.checkout/PerformanceTests' -else: - LAYOUT_TEST_DIR = '/test.checkout/LayoutTests' - PERF_TEST_DIR = '/test.checkout/PerformanceTests' +LAYOUT_TEST_DIR = '/test.checkout/LayoutTests' +PERF_TEST_DIR = '/test.checkout/PerformanceTests' # Here we synthesize an in-memory filesystem from the test list @@ -247,8 +244,8 @@ else: def add_unit_tests_to_mock_filesystem(filesystem): # Add the test_expectations file. filesystem.maybe_make_directory(LAYOUT_TEST_DIR + '/platform/test') - if not filesystem.exists(LAYOUT_TEST_DIR + '/platform/test/test_expectations.txt'): - filesystem.write_text_file(LAYOUT_TEST_DIR + '/platform/test/test_expectations.txt', """ + if not filesystem.exists(LAYOUT_TEST_DIR + '/platform/test/TestExpectations'): + filesystem.write_text_file(LAYOUT_TEST_DIR + '/platform/test/TestExpectations', """ WONTFIX : failures/expected/crash.html = CRASH WONTFIX : failures/expected/image.html = IMAGE WONTFIX : failures/expected/audio.html = AUDIO @@ -267,6 +264,7 @@ WONTFIX : failures/expected/timeout.html = TIMEOUT WONTFIX SKIP : failures/expected/hang.html = TIMEOUT WONTFIX SKIP : failures/expected/keyboard.html = CRASH WONTFIX SKIP : failures/expected/exception.html = CRASH +WONTFIX SKIP : passes/skipped/skip.html = PASS """) filesystem.maybe_make_directory(LAYOUT_TEST_DIR + '/reftests/foo') @@ -340,7 +338,7 @@ class TestPort(Port): Port.__init__(self, host, port_name, **kwargs) self._tests = unit_test_list() self._flakes = set() - self._expectations_path = LAYOUT_TEST_DIR + '/platform/test/test_expectations.txt' + self._expectations_path = LAYOUT_TEST_DIR + '/platform/test/TestExpectations' self._results_directory = None self._operating_system = 'mac' diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py index 879c79abf..ab35a6463 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py @@ -77,10 +77,6 @@ class WebKitPort(Port): search_paths.append(self.port_name) return map(self._webkit_baseline_path, search_paths) - def path_to_test_expectations_file(self): - # test_expectations are always in mac/ not mac-leopard/ by convention, hence we use port_name instead of name(). - return self._filesystem.join(self._webkit_baseline_path(self.port_name), 'test_expectations.txt') - def _port_flag_for_scripts(self): # This is overrriden by ports which need a flag passed to scripts to distinguish the use of that port. # For example --qt on linux, since a user might have both Gtk and Qt libraries installed. @@ -118,14 +114,17 @@ class WebKitPort(Port): # These two projects should be factored out into their own # projects. try: - self._run_script("build-dumprendertree", env=env) + self._run_script("build-dumprendertree", args=self._build_driver_flags(), env=env) if self.get_option('webkit_test_runner'): - self._run_script("build-webkittestrunner", env=env) + self._run_script("build-webkittestrunner", args=self._build_driver_flags(), env=env) except ScriptError, e: _log.error(e.message_with_output(output_limit=None)) return False return True + def _build_driver_flags(self): + return [] + def _check_driver(self): driver_path = self._path_to_driver() if not self._filesystem.exists(driver_path): @@ -360,15 +359,6 @@ class WebKitPort(Port): return search_paths - def test_expectations(self): - # This allows ports to use a combination of test_expectations.txt files and Skipped lists. - expectations = '' - expectations_path = self.path_to_test_expectations_file() - if self._filesystem.exists(expectations_path): - _log.debug("Using test_expectations.txt: %s" % expectations_path) - expectations = self._filesystem.read_text_file(expectations_path) - return expectations - def skipped_layout_tests(self, test_list): tests_to_skip = set(self._expectations_from_skipped_files(self._skipped_file_search_paths())) tests_to_skip.update(self._tests_for_other_platforms()) @@ -462,8 +452,7 @@ class WebKitDriver(Driver): self._server_process = None def __del__(self): - assert(self._server_process is None) - assert(self._driver_tempdir is None) + self.stop() def cmd_line(self, pixel_tests, per_test_args): cmd = self._command_wrapper(self._port.get_option('wrapper')) @@ -488,6 +477,7 @@ class WebKitDriver(Driver): return cmd def _start(self, pixel_tests, per_test_args): + self.stop() self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % self._port.driver_name()) server_name = self._port.driver_name() environment = self._port.setup_environ_for_server(server_name) @@ -565,8 +555,7 @@ class WebKitDriver(Driver): def run_test(self, driver_input): start_time = time.time() - if not self._server_process: - self._start(driver_input.should_run_pixel_test, driver_input.args) + self.start(driver_input.should_run_pixel_test, driver_input.args) self.error_from_test = str() self.err_seen_eof = False diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py index 33e422866..f7e9525d6 100755 --- a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py @@ -94,9 +94,16 @@ class WebKitPortTest(port_testcase.PortTestCase): def test_path_to_test_expectations_file(self): port = TestWebKitPort() port._options = MockOptions(webkit_test_runner=False) - self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/test_expectations.txt') + self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations') + + port = TestWebKitPort() port._options = MockOptions(webkit_test_runner=True) - self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/test_expectations.txt') + self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations') + + port = TestWebKitPort() + port.host.filesystem.files['/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations'] = 'some content' + port._options = MockOptions(webkit_test_runner=False) + self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations') def test_skipped_directories_for_symbols(self): # This first test confirms that the commonly found symbols result in the expected skipped directories. @@ -165,10 +172,10 @@ class WebKitPortTest(port_testcase.PortTestCase): def test_test_expectations(self): # Check that we read the expectations file host = MockSystemHost() - host.filesystem.write_text_file('/mock-checkout/LayoutTests/platform/testwebkitport/test_expectations.txt', - 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = FAIL\n') + host.filesystem.write_text_file('/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations', + 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = TEXT\n') port = TestWebKitPort(host=host) - self.assertEqual(port.test_expectations(), 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = FAIL\n') + self.assertEqual(''.join(port.expectations_dict().values()), 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = TEXT\n') def test_build_driver(self): output = OutputCapture() @@ -349,7 +356,7 @@ class WebKitDriverTest(unittest.TestCase): driver._server_process = FakeServerProcess(False) driver._subprocess_was_unresponsive = False assert_crash(driver, '#CRASHED - WebProcess (pid 8675)\n', True, 'WebProcess', 8675) - + driver._crashed_process_name = None driver._crashed_pid = None driver._server_process = FakeServerProcess(False) @@ -376,3 +383,11 @@ class WebKitDriverTest(unittest.TestCase): self.assertNotEquals(last_tmpdir, None) driver.stop() self.assertFalse(port._filesystem.isdir(last_tmpdir)) + + def test_two_starts_cleans_up_properly(self): + port = TestWebKitPort() + driver = WebKitDriver(port, 0, pixel_tests=True) + driver.start(True, []) + last_tmpdir = port._filesystem.last_tmpdir + driver._start(True, []) + self.assertFalse(port._filesystem.isdir(last_tmpdir)) diff --git a/Tools/Scripts/webkitpy/layout_tests/port/win.py b/Tools/Scripts/webkitpy/layout_tests/port/win.py index da3209ead..420f4db04 100644 --- a/Tools/Scripts/webkitpy/layout_tests/port/win.py +++ b/Tools/Scripts/webkitpy/layout_tests/port/win.py @@ -30,6 +30,7 @@ import logging import re import sys +from webkitpy.common.system.systemhost import SystemHost from webkitpy.common.system.executive import ScriptError, Executive from webkitpy.common.system.path import abspath_to_uri from webkitpy.layout_tests.port.apple import ApplePort @@ -45,6 +46,8 @@ class WinPort(ApplePort): # and the order of fallback between them. Matches ORWT. VERSION_FALLBACK_ORDER = ["win-xp", "win-vista", "win-7sp0", "win"] + ARCHITECTURES = ['x86'] + def do_text_results_differ(self, expected_text, actual_text): # Sanity was restored in WK2, so we don't need this hack there. if self.get_option('webkit_test_runner'): @@ -75,7 +78,7 @@ class WinPort(ApplePort): return 'win' def show_results_html_file(self, results_filename): - self._run_script('run-safari', [abspath_to_uri(results_filename)]) + self._run_script('run-safari', [abspath_to_uri(SystemHost().platform, results_filename)]) # FIXME: webkitperl/httpd.pm installs /usr/lib/apache/libphp4.dll on cycwin automatically # as part of running old-run-webkit-tests. That's bad design, but we may need some similar hack. diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index d4eccb0fa..3d7b20f41 100755 --- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py @@ -157,8 +157,8 @@ def _set_up_derived_options(port, options): normalized_platform_directories.append(port.host.filesystem.normpath(path)) options.additional_platform_directory = normalized_platform_directories - if not options.http and options.force: - warnings.append("--no-http is ignored since --force is also provided") + if not options.http and options.skipped in ('ignore', 'only'): + warnings.append("--force/--skipped=%s overrides --no-http." % (options.skipped)) options.http = True if options.skip_pixel_test_if_no_baseline and not options.pixel_tests: @@ -167,6 +167,10 @@ def _set_up_derived_options(port, options): if options.ignore_metrics and (options.new_baseline or options.reset_results): warnings.append("--ignore-metrics has no effect with --new-baselines or with --reset-results") + if options.new_baseline: + options.reset_results = True + options.add_platform_exceptions = True + return warnings @@ -277,10 +281,12 @@ def parse_args(args=None): optparse.make_option("--results-directory", help="Location of test results"), optparse.make_option("--build-directory", help="Path to the directory under which build files are kept (should not include configuration)"), + optparse.make_option("--add-platform-exceptions", action="store_true", default=False, + help="Save generated results into the *most-specific-platform* directory rather than the *generic-platform* directory"), optparse.make_option("--new-baseline", action="store_true", default=False, help="Save generated results as new baselines " - "into the *platform* directory, overwriting whatever's " - "already there."), + "into the *most-specific-platform* directory, overwriting whatever's " + "already there. Equivalent to --reset-results --add-platform-exceptions"), optparse.make_option("--reset-results", action="store_true", default=False, help="Reset expectations to the " "generated results in their existing location."), @@ -347,17 +353,14 @@ def parse_args(args=None): help="wrapper command to insert before invocations of " "DumpRenderTree; option is split on whitespace before " "running. (Example: --wrapper='valgrind --smc-check=all')"), - # old-run-webkit-tests: - # -i|--ignore-tests Comma-separated list of directories - # or tests to ignore optparse.make_option("-i", "--ignore-tests", action="append", default=[], help="directories or test to ignore (may specify multiple times)"), optparse.make_option("--test-list", action="append", help="read list of tests to run from file", metavar="FILE"), - # old-run-webkit-tests uses --skipped==[default|ignore|only] - # instead of --force: - optparse.make_option("--force", action="store_true", default=False, - help="Run all tests, even those marked SKIP in the test list"), + optparse.make_option("--skipped", action="store", default="default", + help="control how tests marked SKIP are run. 'default' == Skip, 'ignore' == Run them anyway, 'only' == only run the SKIP tests."), + optparse.make_option("--force", dest="skipped", action="store_const", const='ignore', + help="Run all tests, even those marked SKIP in the test list (same as --skipped=ignore)"), optparse.make_option("--time-out-ms", help="Set the timeout for each test"), # old-run-webkit-tests calls --randomize-order --random: @@ -383,11 +386,11 @@ def parse_args(args=None): # FIXME: Display default number of child processes that will run. optparse.make_option("-f", "--fully-parallel", action="store_true", help="run all tests in parallel"), - optparse.make_option("--exit-after-n-failures", type="int", default=500, + optparse.make_option("--exit-after-n-failures", type="int", default=None, help="Exit after the first N failures instead of running all " "tests"), optparse.make_option("--exit-after-n-crashes-or-timeouts", type="int", - default=20, help="Exit after the first N crashes instead of " + default=None, help="Exit after the first N crashes instead of " "running all tests"), optparse.make_option("--iterations", type="int", help="Number of times to run the set of tests (e.g. ABCABCABC)"), optparse.make_option("--repeat-each", type="int", help="Number of times to run each test (e.g. AAABBBCCC)"), @@ -443,7 +446,6 @@ def main(): host = MockHost() else: host = Host() - host._initialize_scm() port = host.port_factory.get(options.platform, options) logging.getLogger().setLevel(logging.DEBUG if options.verbose else logging.INFO) return run(port, options, args) diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py index 96fb6853d..bfdb55cc9 100755 --- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py +++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py @@ -197,18 +197,15 @@ class LintTest(unittest.TestCase, StreamTestingMixin): self.name = name self.path = path - def test_expectations(self): - self.host.ports_parsed.append(self.name) - return '' - def path_to_test_expectations_file(self): return self.path def test_configuration(self): return None - def test_expectations_overrides(self): - return None + def expectations_dict(self): + self.host.ports_parsed.append(self.name) + return {self.path: ''} def skipped_layout_tests(self, tests): return set([]) @@ -261,7 +258,7 @@ class LintTest(unittest.TestCase, StreamTestingMixin): options, parsed_args = parse_args(['--lint-test-files']) host = MockHost() port_obj = host.port_factory.get(options.platform, options=options) - port_obj.test_expectations = lambda: "# syntax error" + port_obj.expectations_dict = lambda: {'': '# syntax error'} res, out, err = run_and_capture(port_obj, options, parsed_args) self.assertEqual(res, -1) @@ -404,19 +401,29 @@ class MainTest(unittest.TestCase, StreamTestingMixin): tests_run = get_tests_run(['--skip-pixel-test-if-no-baseline'] + tests_to_run, tests_included=True, flatten_batches=True) self.assertEquals(tests_run, ['passes/image.html', 'passes/text.html']) - def test_ignore_tests(self): - def assert_ignored(args, tests_expected_to_run): - tests_to_run = ['failures/expected/image.html', 'passes/image.html'] - tests_run = get_tests_run(args + tests_to_run, tests_included=True, flatten_batches=True) - self.assertEquals(tests_run, tests_expected_to_run) + def test_ignore_flag(self): + # Note that passes/image.html is expected to be run since we specified it directly. + tests_run = get_tests_run(['-i', 'passes', 'passes/image.html'], flatten_batches=True, tests_included=True) + self.assertFalse('passes/text.html' in tests_run) + self.assertTrue('passes/image.html' in tests_run) + + def test_skipped_flag(self): + tests_run = get_tests_run(['passes'], tests_included=True, flatten_batches=True) + self.assertFalse('passes/skipped/skip.html' in tests_run) + num_tests_run_by_default = len(tests_run) - assert_ignored(['-i', 'failures/expected/image.html'], ['passes/image.html']) - assert_ignored(['-i', 'passes'], ['failures/expected/image.html']) + # Check that nothing changes when we specify skipped=default. + self.assertEquals(len(get_tests_run(['--skipped=default', 'passes'], tests_included=True, flatten_batches=True)), + num_tests_run_by_default) - # Note here that there is an expectation for failures/expected/image.html already, but - # it is overriden by the command line arg. This might be counter-intuitive. - # FIXME: This isn't currently working ... - # assert_ignored(['-i', 'failures/expected'], ['passes/image.html']) + # Now check that we run one more test (the skipped one). + tests_run = get_tests_run(['--skipped=ignore', 'passes'], tests_included=True, flatten_batches=True) + self.assertTrue('passes/skipped/skip.html' in tests_run) + self.assertEquals(len(tests_run), num_tests_run_by_default + 1) + + # Now check that we only run the skipped test. + self.assertEquals(get_tests_run(['--skipped=only', 'passes'], tests_included=True, flatten_batches=True), + ['passes/skipped/skip.html']) def test_iterations(self): tests_to_run = ['passes/image.html', 'passes/text.html'] @@ -537,7 +544,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin): self.assertEqual(res, unexpected_tests_count) self.assertNotEmpty(out) self.assertNotEmpty(err) - self.assertEqual(user.opened_urls, [path.abspath_to_uri('/tmp/layout-test-results/results.html')]) + self.assertEqual(user.opened_urls, [path.abspath_to_uri(MockHost().platform, '/tmp/layout-test-results/results.html')]) def test_missing_and_unexpected_results(self): # Test that we update expectations in place. If the expectation @@ -715,7 +722,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin): with host.filesystem.mkdtemp() as tmpdir: res, out, err, user = logging_run(['--results-directory=' + str(tmpdir)], tests_included=True, host=host) - self.assertEqual(user.opened_urls, [path.abspath_to_uri(host.filesystem.join(tmpdir, 'results.html'))]) + self.assertEqual(user.opened_urls, [path.abspath_to_uri(host.platform, host.filesystem.join(tmpdir, 'results.html'))]) def test_results_directory_default(self): # We run a configuration that should fail, to generate output, then @@ -723,7 +730,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin): # This is the default location. res, out, err, user = logging_run(tests_included=True) - self.assertEqual(user.opened_urls, [path.abspath_to_uri('/tmp/layout-test-results/results.html')]) + self.assertEqual(user.opened_urls, [path.abspath_to_uri(MockHost().platform, '/tmp/layout-test-results/results.html')]) def test_results_directory_relative(self): # We run a configuration that should fail, to generate output, then @@ -733,7 +740,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin): host.filesystem.chdir('/tmp/cwd') res, out, err, user = logging_run(['--results-directory=foo'], tests_included=True, host=host) - self.assertEqual(user.opened_urls, [path.abspath_to_uri('/tmp/cwd/foo/results.html')]) + self.assertEqual(user.opened_urls, [path.abspath_to_uri(host.platform, '/tmp/cwd/foo/results.html')]) def test_retrying_and_flaky_tests(self): host = MockHost() @@ -874,6 +881,10 @@ class MainTest(unittest.TestCase, StreamTestingMixin): self.assertTrue(MainTest.has_test_of_type(batch_tests_run_http, 'http')) self.assertTrue(MainTest.has_test_of_type(batch_tests_run_http, 'websocket')) + def test_platform_tests_are_found(self): + tests_run = get_tests_run(['http'], tests_included=True, flatten_batches=True) + self.assertTrue('platform/test-snow-leopard/http/test.html' in tests_run) + class EndToEndTest(unittest.TestCase): def parse_full_results(self, full_results_text): @@ -919,7 +930,7 @@ class RebaselineTest(unittest.TestCase, StreamTestingMixin): "assert that the file_list contains the baselines.""" for ext in extensions: baseline = file + "-expected" + ext - baseline_msg = 'Writing new expected result "%s"\n' % baseline[1:] + baseline_msg = 'Writing new expected result "%s"\n' % baseline self.assertTrue(any(f.find(baseline) != -1 for f in file_list)) self.assertContainsLine(err, baseline_msg) @@ -940,8 +951,8 @@ class RebaselineTest(unittest.TestCase, StreamTestingMixin): self.assertEquals(res, 0) self.assertEmpty(out) self.assertEqual(len(file_list), 4) - self.assertBaselines(file_list, "/passes/image", [".txt", ".png"], err) - self.assertBaselines(file_list, "/failures/expected/missing_image", [".txt", ".png"], err) + self.assertBaselines(file_list, "passes/image", [".txt", ".png"], err) + self.assertBaselines(file_list, "failures/expected/missing_image", [".txt", ".png"], err) def test_missing_results(self): # Test that we update expectations in place. If the expectation @@ -958,13 +969,13 @@ class RebaselineTest(unittest.TestCase, StreamTestingMixin): self.assertEquals(res, 0) self.assertNotEmpty(out) self.assertEqual(len(file_list), 6) - self.assertBaselines(file_list, "/failures/unexpected/missing_text", [".txt"], err) - self.assertBaselines(file_list, "/platform/test-mac-leopard/failures/unexpected/missing_image", [".png"], err) - self.assertBaselines(file_list, "/platform/test-mac-leopard/failures/unexpected/missing_render_tree_dump", [".txt"], err) + self.assertBaselines(file_list, "failures/unexpected/missing_text", [".txt"], err) + self.assertBaselines(file_list, "platform/test/failures/unexpected/missing_image", [".png"], err) + self.assertBaselines(file_list, "platform/test/failures/unexpected/missing_render_tree_dump", [".txt"], err) def test_new_baseline(self): - # Test that we update the platform expectations. If the expectation - # is mssing, then create a new expectation in the platform dir. + # Test that we update the platform expectations in the version-specific directories + # for both existing and new baselines. host = MockHost() res, out, err, _ = logging_run(['--pixel-tests', '--new-baseline', @@ -977,9 +988,9 @@ class RebaselineTest(unittest.TestCase, StreamTestingMixin): self.assertEmpty(out) self.assertEqual(len(file_list), 4) self.assertBaselines(file_list, - "/platform/test-mac-leopard/passes/image", [".txt", ".png"], err) + "platform/test-mac-leopard/passes/image", [".txt", ".png"], err) self.assertBaselines(file_list, - "/platform/test-mac-leopard/failures/expected/missing_image", [".txt", ".png"], err) + "platform/test-mac-leopard/failures/expected/missing_image", [".txt", ".png"], err) if __name__ == '__main__': diff --git a/Tools/Scripts/webkitpy/layout_tests/servers/http_server_unittest.py b/Tools/Scripts/webkitpy/layout_tests/servers/http_server_unittest.py index a037a37dd..7a14526d1 100644 --- a/Tools/Scripts/webkitpy/layout_tests/servers/http_server_unittest.py +++ b/Tools/Scripts/webkitpy/layout_tests/servers/http_server_unittest.py @@ -28,6 +28,7 @@ import unittest import re +import sys from webkitpy.common.host_mock import MockHost from webkitpy.layout_tests.port import test @@ -37,6 +38,10 @@ from webkitpy.layout_tests.servers.http_server_base import ServerError class TestHttpServer(unittest.TestCase): def test_start_cmd(self): + # Fails on win - see https://bugs.webkit.org/show_bug.cgi?id=84726 + if sys.platform in ('cygwin', 'win32'): + return + host = MockHost() test_port = test.TestPort(host) host.filesystem.write_text_file( diff --git a/Tools/Scripts/webkitpy/layout_tests/servers/websocket_server.py b/Tools/Scripts/webkitpy/layout_tests/servers/websocket_server.py index 296ab9882..93747f690 100644 --- a/Tools/Scripts/webkitpy/layout_tests/servers/websocket_server.py +++ b/Tools/Scripts/webkitpy/layout_tests/servers/websocket_server.py @@ -51,6 +51,7 @@ _DEFAULT_WSS_PORT = 9323 class PyWebSocket(http_server.Lighttpd): def __init__(self, port_obj, output_dir, port=_DEFAULT_WS_PORT, root=None, use_tls=False, + private_key=None, certificate=None, ca_certificate=None, pidfile=None): """Args: output_dir: the absolute path to the layout test result directory @@ -70,8 +71,15 @@ class PyWebSocket(http_server.Lighttpd): if self._use_tls: self._name = 'pywebsocket_secure' - self._private_key = self._pem_file - self._certificate = self._pem_file + if private_key: + self._private_key = private_key + else: + self._private_key = self._pem_file + if certificate: + self._certificate = certificate + else: + self._certificate = self._pem_file + self._ca_certificate = ca_certificate if self._port: self._port = int(self._port) self._wsin = None @@ -137,6 +145,9 @@ class PyWebSocket(http_server.Lighttpd): if self._use_tls: start_cmd.extend(['-t', '-k', self._private_key, '-c', self._certificate]) + if self._ca_certificate: + start_cmd.append('--ca-certificate') + start_cmd.append(self._ca_certificate) self._start_cmd = start_cmd server_name = self._filesystem.basename(pywebsocket_script) diff --git a/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py b/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py index 49a507ed6..814437780 100644 --- a/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py +++ b/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py @@ -91,14 +91,15 @@ class MeteredStream(object): if self._erasing: self._last_partial_line = txt[txt.rfind('\n') + 1:] - def write(self, txt, now=None): + def write(self, txt, now=None, pid=None): now = now or self._time_fn() + pid = pid or self._pid self._last_write_time = now if self._last_partial_line: self._erase_last_partial_line() if self._verbose: now_tuple = time.localtime(now) - msg = '%02d:%02d:%02d.%03d %d %s' % (now_tuple.tm_hour, now_tuple.tm_min, now_tuple.tm_sec, int((now * 1000) % 1000), self._pid, self._ensure_newline(txt)) + msg = '%02d:%02d:%02d.%03d %d %s' % (now_tuple.tm_hour, now_tuple.tm_min, now_tuple.tm_sec, int((now * 1000) % 1000), pid, self._ensure_newline(txt)) elif self._isatty: msg = txt else: @@ -106,14 +107,19 @@ class MeteredStream(object): self._stream.write(msg) - def writeln(self, txt, now=None): - self.write(self._ensure_newline(txt), now) + def writeln(self, txt, now=None, pid=None): + self.write(self._ensure_newline(txt), now, pid) def _erase_last_partial_line(self): num_chars = len(self._last_partial_line) self._stream.write(self._erasure(self._last_partial_line)) self._last_partial_line = '' + def flush(self): + if self._last_partial_line: + self._stream.write('\n') + self._last_partial_line = '' + self._stream.flush() class _LogHandler(logging.Handler): def __init__(self, meter): diff --git a/Tools/Scripts/webkitpy/layout_tests/views/printing.py b/Tools/Scripts/webkitpy/layout_tests/views/printing.py index 3df2956c1..3d98c6c59 100644 --- a/Tools/Scripts/webkitpy/layout_tests/views/printing.py +++ b/Tools/Scripts/webkitpy/layout_tests/views/printing.py @@ -407,5 +407,11 @@ class Printer(object): return self._write(msg) + def writeln(self, *args, **kwargs): + self._meter.writeln(*args, **kwargs) + def _write(self, msg): self._meter.writeln(msg) + + def flush(self): + self._meter.flush() diff --git a/Tools/Scripts/webkitpy/performance_tests/perftest.py b/Tools/Scripts/webkitpy/performance_tests/perftest.py index 20d3d5838..896bad4fa 100644 --- a/Tools/Scripts/webkitpy/performance_tests/perftest.py +++ b/Tools/Scripts/webkitpy/performance_tests/perftest.py @@ -36,10 +36,13 @@ import os import signal import socket import subprocess +import sys import time # Import for auto-install -import webkitpy.thirdparty.autoinstalled.webpagereplay.replay +if sys.platform != 'win32': + # FIXME: webpagereplay doesn't work on win32. See https://bugs.webkit.org/show_bug.cgi?id=88279. + import webkitpy.thirdparty.autoinstalled.webpagereplay.replay from webkitpy.layout_tests.controllers.test_result_writer import TestResultWriter from webkitpy.layout_tests.port.driver import DriverInput @@ -216,10 +219,10 @@ class ReplayServer(object): def __init__(self, archive, record): self._process = None - # FIXME: Should error if local proxy isn't set to forward requests to localhost:8080 and localhost:8413 + # FIXME: Should error if local proxy isn't set to forward requests to localhost:8080 and localhost:8443 replay_path = webkitpy.thirdparty.autoinstalled.webpagereplay.replay.__file__ - args = ['python', replay_path, '--no-dns_forwarding', '--port', '8080', '--ssl_port', '8413', '--use_closest_match', '--log_level', 'warning'] + args = ['python', replay_path, '--no-dns_forwarding', '--port', '8080', '--ssl_port', '8443', '--use_closest_match', '--log_level', 'warning'] if record: args.append('--record') args.append(archive) diff --git a/Tools/Scripts/webkitpy/style/checker.py b/Tools/Scripts/webkitpy/style/checker.py index e72a025f4..dff790ec1 100644 --- a/Tools/Scripts/webkitpy/style/checker.py +++ b/Tools/Scripts/webkitpy/style/checker.py @@ -140,11 +140,17 @@ _PATH_RULES_SPECIFIER = [ # Qt code uses '_' in some places (such as private slots # and on test xxx_data methos on tests) "Source/JavaScriptCore/qt/", - "Source/WebKit/qt/Api/", "Source/WebKit/qt/tests/", "Source/WebKit/qt/declarative/", "Source/WebKit/qt/examples/"], ["-readability/naming"]), + + ([# The Qt APIs use Qt declaration style, it puts the * to + # the variable name, not to the class. + "Source/WebKit/qt/Api/"], + ["-readability/naming", + "-whitespace/declaration"]), + ([# Qt's MiniBrowser has no config.h "Tools/MiniBrowser/qt"], ["-build/include"]), @@ -517,15 +523,14 @@ class CheckerDispatcher(object): # Since "LayoutTests" is in _SKIPPED_FILES_WITHOUT_WARNING, make # an exception to prevent files like "LayoutTests/ChangeLog" and # "LayoutTests/ChangeLog-2009-06-16" from being skipped. - # Files like 'test_expectations.txt' and 'drt_expectations.txt' - # are also should not be skipped. + # Files like 'TestExpectations' are also should not be skipped. # # FIXME: Figure out a good way to avoid having to add special logic # for this special case. basename = os.path.basename(file_path) if basename.startswith('ChangeLog'): return False - elif basename == 'test_expectations.txt' or basename == 'drt_expectations.txt': + elif basename == 'TestExpectations': return False for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING: if self._should_skip_file_path(file_path, skipped_file): @@ -593,7 +598,7 @@ class CheckerDispatcher(object): checker = PNGChecker(file_path, handle_style_error) elif file_type == FileType.TEXT: basename = os.path.basename(file_path) - if basename == 'test_expectations.txt' or basename == 'drt_expectations.txt': + if basename == 'TestExpectations': checker = TestExpectationsChecker(file_path, handle_style_error) else: checker = TextChecker(file_path, handle_style_error) diff --git a/Tools/Scripts/webkitpy/style/checkers/cpp.py b/Tools/Scripts/webkitpy/style/checkers/cpp.py index 1eea4973f..aaad85d5c 100644 --- a/Tools/Scripts/webkitpy/style/checkers/cpp.py +++ b/Tools/Scripts/webkitpy/style/checkers/cpp.py @@ -2632,7 +2632,7 @@ def _classify_include(filename, include, is_system, include_state): """ # If it is a system header we know it is classified as _OTHER_HEADER. - if is_system: + if is_system and not include.startswith('public/'): return _OTHER_HEADER # If the include is named config.h then this is WebCore/config.h. diff --git a/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py b/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py index cba917108..1675c7010 100644 --- a/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py +++ b/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py @@ -2696,6 +2696,30 @@ class OrderOfIncludesTest(CppStyleTestBase): os.path.isfile = self.os_path_isfile_orig + def test_public_primary_header(self): + # System header is not considered a primary header. + self.assert_language_rules_check('foo.cpp', + '#include "config.h"\n' + '#include <other/foo.h>\n' + '\n' + '#include "a.h"\n', + 'Alphabetical sorting problem. [build/include_order] [4]') + + # ...except that it starts with public/. + self.assert_language_rules_check('foo.cpp', + '#include "config.h"\n' + '#include <public/foo.h>\n' + '\n' + '#include "a.h"\n', + '') + + # Even if it starts with public/ its base part must match with the source file name. + self.assert_language_rules_check('foo.cpp', + '#include "config.h"\n' + '#include <public/foop.h>\n' + '\n' + '#include "a.h"\n', + 'Alphabetical sorting problem. [build/include_order] [4]') def test_check_wtf_includes(self): self.assert_language_rules_check('foo.cpp', @@ -2751,6 +2775,19 @@ class OrderOfIncludesTest(CppStyleTestBase): classify_include('foo.cpp', 'moc_foo.cpp', False, include_state)) + # <public/foo.h> must be considered as primary even if is_system is True. + self.assertEqual(cpp_style._PRIMARY_HEADER, + classify_include('foo/foo.cpp', + 'public/foo.h', + True, include_state)) + self.assertEqual(cpp_style._OTHER_HEADER, + classify_include('foo.cpp', + 'foo.h', + True, include_state)) + self.assertEqual(cpp_style._OTHER_HEADER, + classify_include('foo.cpp', + 'public/foop.h', + True, include_state)) # Qt private APIs use _p.h suffix. self.assertEqual(cpp_style._PRIMARY_HEADER, classify_include('foo.cpp', diff --git a/Tools/Scripts/webkitpy/style/checkers/test_expectations.py b/Tools/Scripts/webkitpy/style/checkers/test_expectations.py index 616959f76..c95c4120f 100644 --- a/Tools/Scripts/webkitpy/style/checkers/test_expectations.py +++ b/Tools/Scripts/webkitpy/style/checkers/test_expectations.py @@ -29,27 +29,27 @@ """Checks WebKit style for test_expectations files.""" import logging +import optparse import os import re import sys from common import TabChecker from webkitpy.common.host import Host -from webkitpy.layout_tests.models import test_expectations -from webkitpy.layout_tests.port.base import DummyOptions +from webkitpy.layout_tests.models.test_expectations import TestExpectationParser _log = logging.getLogger(__name__) class TestExpectationsChecker(object): - """Processes test_expectations.txt lines for validating the syntax.""" + """Processes TestExpectations lines for validating the syntax.""" categories = set(['test/expectations']) def _determine_port_from_expectations_path(self, host, expectations_path): # Pass a configuration to avoid calling default_configuration() when initializing the port (takes 0.5 seconds on a Mac Pro!). - options = DummyOptions(configuration='Release') + options = optparse.Values({'configuration': 'Release'}) for port_name in host.port_factory.all_port_names(): port = host.port_factory.get(port_name, options=options) if port.path_to_test_expectations_file().replace(port.path_from_webkit_base() + host.filesystem.sep, '') == expectations_path: @@ -61,7 +61,6 @@ class TestExpectationsChecker(object): self._handle_style_error = handle_style_error self._handle_style_error.turn_off_line_filtering() self._tab_checker = TabChecker(file_path, handle_style_error) - self._output_regex = re.compile('.*test_expectations.txt:(?P<line>\d+)\s*(?P<message>.+)') # FIXME: host should be a required parameter, not an optional one. host = host or Host() @@ -77,32 +76,17 @@ class TestExpectationsChecker(object): pass def check_test_expectations(self, expectations_str, tests=None, overrides=None): - err = None - expectations = None - # FIXME: We need to rework how we lint strings so that we can do it independently of what a - # port's existing expectations are. Linting should probably just call the parser directly. - # For now we override the port hooks. This will also need to be reworked when expectations - # can cascade arbitrarily, rather than just have expectations and overrides. - orig_expectations = self._port_obj.test_expectations - orig_overrides = self._port_obj.test_expectations_overrides - try: - self._port_obj.test_expectations = lambda: expectations_str - self._port_obj.test_expectations_overrides = lambda: overrides - expectations = test_expectations.TestExpectations(self._port_obj, tests, True) - except test_expectations.ParseError, error: - err = error - finally: - self._port_obj.text_expectations = orig_expectations - self._port_obj.text_expectations_overrides = orig_overrides - - if err: - level = 5 - for warning in err.warnings: - matched = self._output_regex.match(warning) - if matched: - lineno, message = matched.group('line', 'message') - self._handle_style_error(int(lineno), 'test/expectations', level, message) - + # FIXME: we should pass in the filenames here if possible, and ensure + # that this works with with cascading expectations files and remove the overrides param. + parser = TestExpectationParser(self._port_obj, tests, False) + expectations = parser.parse('expectations', expectations_str) + if overrides: + expectations += parser.parse('overrides', overrides) + + level = 5 + for expectation_line in expectations: + for warning in expectation_line.warnings: + self._handle_style_error(expectation_line.line_number, 'test/expectations', level, warning) def check_tabs(self, lines): self._tab_checker.check(lines) diff --git a/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py b/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py index b6e3595fa..8cc91b1ac 100644 --- a/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py +++ b/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py @@ -75,16 +75,16 @@ class TestExpectationsTestCase(unittest.TestCase): def test_determine_port_from_expectations_path(self): self._expect_port_for_expectations_path(None, '/') - self._expect_port_for_expectations_path(None, 'LayoutTests/chromium-mac/test_expectations.txt') - self._expect_port_for_expectations_path('chromium', 'LayoutTests/platform/chromium/test_expectations.txt') - self._expect_port_for_expectations_path(None, '/mock-checkout/LayoutTests/platform/win/test_expectations.txt') - self._expect_port_for_expectations_path('win', 'LayoutTests/platform/win/test_expectations.txt') + self._expect_port_for_expectations_path(None, 'LayoutTests/chromium-mac/TestExpectations') + self._expect_port_for_expectations_path('chromium', 'LayoutTests/platform/chromium/TestExpectations') + self._expect_port_for_expectations_path(None, '/mock-checkout/LayoutTests/platform/win/TestExpectations') + self._expect_port_for_expectations_path('win', 'LayoutTests/platform/win/TestExpectations') def assert_lines_lint(self, lines, should_pass, expected_output=None): self._error_collector.reset_errors() host = MockHost() - checker = TestExpectationsChecker('test/test_expectations.txt', + checker = TestExpectationsChecker('test/TestExpectations', self._error_collector, host=host) # We should have failed to find a valid port object for that path. @@ -105,7 +105,7 @@ class TestExpectationsTestCase(unittest.TestCase): self.assertTrue(self._error_collector.turned_off_filtering) def test_valid_expectations(self): - self.assert_lines_lint(["BUGCR1234 MAC : passes/text.html = PASS FAIL"], should_pass=True) + self.assert_lines_lint(["BUGCR1234 MAC : passes/text.html = PASS TEXT"], should_pass=True) def test_invalid_expectations(self): self.assert_lines_lint(["BUG1234 : passes/text.html = GIVE UP"], should_pass=False) diff --git a/Tools/Scripts/webkitpy/test/main.py b/Tools/Scripts/webkitpy/test/main.py index af3123a01..c5dc39433 100644 --- a/Tools/Scripts/webkitpy/test/main.py +++ b/Tools/Scripts/webkitpy/test/main.py @@ -25,12 +25,14 @@ import logging import optparse +import os import StringIO import sys import traceback import unittest from webkitpy.common.system.filesystem import FileSystem +from webkitpy.common.system import outputcapture from webkitpy.test.test_finder import TestFinder from webkitpy.test.runner import TestRunner @@ -59,6 +61,8 @@ class Tester(object): help='verbose output (specify once for individual test results, twice for debug messages)') parser.add_option('--skip-integrationtests', action='store_true', default=False, help='do not run the integration tests') + parser.add_option('-p', '--pass-through', action='store_true', default=False, + help='be debugger friendly by passing captured output through to the system') parser.epilog = ('[args...] is an optional list of modules, test_classes, or individual tests. ' 'If no args are given, all the tests will be run.') @@ -135,6 +139,10 @@ class Tester(object): self.finder.clean_trees() names = self.finder.find_names(args, self._options.skip_integrationtests, self._options.all) + if not names: + _log.error('No tests to run') + return False + return self._run_tests(names) def _run_tests(self, names): @@ -172,6 +180,8 @@ class Tester(object): test_runner = TestRunner(self.stream, self._options, loader) _log.debug("Running the tests.") + if self._options.pass_through: + outputcapture.OutputCapture.stream_wrapper = _CaptureAndPassThroughStream result = test_runner.run(test_suite) if self._options.coverage: cov.stop() @@ -184,3 +194,32 @@ class Tester(object): traceback.print_exc(file=s) for l in s.buflist: _log.error(' ' + l.rstrip()) + + +class _CaptureAndPassThroughStream(object): + def __init__(self, stream): + self._buffer = StringIO.StringIO() + self._stream = stream + + def write(self, msg): + self._stream.write(msg) + + # Note that we don't want to capture any output generated by the debugger + # because that could cause the results of capture_output() to be invalid. + if not self._message_is_from_pdb(): + self._buffer.write(msg) + + def _message_is_from_pdb(self): + # We will assume that if the pdb module is in the stack then the output + # is being generated by the python debugger (or the user calling something + # from inside the debugger). + import inspect + import pdb + stack = inspect.stack() + return any(frame[1] == pdb.__file__.replace('.pyc', '.py') for frame in stack) + + def flush(self): + self._stream.flush() + + def getvalue(self): + return self._buffer.getvalue() diff --git a/Tools/Scripts/webkitpy/test/main_unittest.py b/Tools/Scripts/webkitpy/test/main_unittest.py new file mode 100644 index 000000000..1a60beef3 --- /dev/null +++ b/Tools/Scripts/webkitpy/test/main_unittest.py @@ -0,0 +1,54 @@ +# Copyright (C) 2012 Google, Inc. +# +# 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. + +import logging +import unittest +import StringIO + +from webkitpy.common.system.outputcapture import OutputCapture +from webkitpy.test.main import Tester + + +class TesterTest(unittest.TestCase): + + def test_no_tests_found(self): + tester = Tester() + errors = StringIO.StringIO() + + # Here we need to remove any existing log handlers so that they + # don't log the messages webkitpy.test while we're testing it. + root_logger = logging.getLogger() + root_handlers = root_logger.handlers + root_logger.handlers = [] + + tester.stream = errors + tester.finder.find_names = lambda args, skip_integration, run_all: [] + oc = OutputCapture() + try: + oc.capture_output() + self.assertFalse(tester.run()) + finally: + out, err, logs = oc.restore_output() + root_logger.handlers = root_handlers + + self.assertTrue('No tests to run' in errors.getvalue()) + self.assertTrue('No tests to run' in logs) diff --git a/Tools/Scripts/webkitpy/test/test_finder.py b/Tools/Scripts/webkitpy/test/test_finder.py index b2671e917..3a90197e9 100644 --- a/Tools/Scripts/webkitpy/test/test_finder.py +++ b/Tools/Scripts/webkitpy/test/test_finder.py @@ -166,9 +166,6 @@ class TestFinder(object): 'webkitpy.tool') self._exclude(modules, win32_blacklist, 'fail horribly on win32', 54526) - win32_blacklist_84726 = ('webkitpy.layout_tests.servers.http_server_unittest.TestHttpServer.test_start_cmd') - self._exclude(modules, win32_blacklist_84726, 'fails on win32', 84726) - return modules def _exclude(self, modules, module_prefixes, reason, bugid): diff --git a/Tools/Scripts/webkitpy/thirdparty/__init__.py b/Tools/Scripts/webkitpy/thirdparty/__init__.py index 26245bacc..078e18041 100644 --- a/Tools/Scripts/webkitpy/thirdparty/__init__.py +++ b/Tools/Scripts/webkitpy/thirdparty/__init__.py @@ -106,7 +106,12 @@ class AutoinstallImportHook(object): installer.install(url="http://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.6.tar.gz#md5=1c49a8825c993bfdcf55bb36897d28a2", url_subpath="Jinja2-2.6/jinja2") - self._install("http://pypi.python.org/packages/source/b/buildbot/buildbot-0.8.4p2.tar.gz#md5=7597d945724c80c0ab476e833a1026cb", "buildbot-0.8.4p2/buildbot") + SQLAlchemy_dir = self._fs.join(_AUTOINSTALLED_DIR, "sqlalchemy") + installer = AutoInstaller(append_to_search_path=True, target_dir=SQLAlchemy_dir) + installer.install(url="http://pypi.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.7.7.tar.gz#md5=ddf6df7e014cea318fa981364f3f93b9", + url_subpath="SQLAlchemy-0.7.7/lib/sqlalchemy") + + self._install("http://pypi.python.org/packages/source/b/buildbot/buildbot-0.8.6p1.tar.gz#md5=b6727d2810c692062c657492bcbeac6a", "buildbot-0.8.6p1/buildbot") def _install_coverage(self): installer = AutoInstaller(target_dir=_AUTOINSTALLED_DIR) @@ -130,8 +135,8 @@ class AutoinstallImportHook(object): def _install_webpagereplay(self): if not self._fs.exists(self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay")): - self._install("http://web-page-replay.googlecode.com/files/webpagereplay-1.1.1.tar.gz", "webpagereplay-1.1.1") - self._fs.move(self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay-1.1.1"), self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay")) + self._install("http://web-page-replay.googlecode.com/files/webpagereplay-1.1.2.tar.gz", "webpagereplay-1.1.2") + self._fs.move(self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay-1.1.2"), self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay")) init_path = self._fs.join(_AUTOINSTALLED_DIR, "webpagereplay", "__init__.py") if not self._fs.exists(init_path): diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/COPYING b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/COPYING index ab9d52ddf..989d02e4c 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/COPYING +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/COPYING @@ -1,4 +1,4 @@ -Copyright 2009, Google Inc. +Copyright 2012, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/_stream_hybi.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/_stream_hybi.py index c00f5692b..34fa7a60e 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/_stream_hybi.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/_stream_hybi.py @@ -39,6 +39,7 @@ http://tools.ietf.org/html/rfc6455 from collections import deque import os import struct +import time from mod_pywebsocket import common from mod_pywebsocket import util @@ -208,7 +209,17 @@ class FragmentedFrameBuilder(object): def _create_control_frame(opcode, body, mask, frame_filters): frame = Frame(opcode=opcode, payload=body) - return _filter_and_format_frame_object(frame, mask, frame_filters) + for frame_filter in frame_filters: + frame_filter.filter(frame) + + if len(frame.payload) > 125: + raise BadOperationException( + 'Payload data size of control frames must be 125 bytes or less') + + header = create_header( + frame.opcode, len(frame.payload), frame.fin, + frame.rsv1, frame.rsv2, frame.rsv3, mask) + return _build_frame(header, frame.payload, mask) def create_ping_frame(body, mask=False, frame_filters=[]): @@ -286,6 +297,9 @@ class Stream(StreamBase): InvalidFrameException: when the frame contains invalid data. """ + self._logger.log(common.LOGLEVEL_FINE, + 'Receive the first 2 octets of a frame') + received = self.receive_bytes(2) first_byte = ord(received[0]) @@ -299,6 +313,11 @@ class Stream(StreamBase): mask = (second_byte >> 7) & 1 payload_length = second_byte & 0x7f + self._logger.log(common.LOGLEVEL_FINE, + 'FIN=%s, RSV1=%s, RSV2=%s, RSV3=%s, opcode=%s, ' + 'Mask=%s, Payload_length=%s', + fin, rsv1, rsv2, rsv3, opcode, mask, payload_length) + if (mask == 1) != self._options.unmask_receive: raise InvalidFrameException( 'Mask bit on the received frame did\'nt match masking ' @@ -310,6 +329,9 @@ class Stream(StreamBase): valid_length_encoding = True length_encoding_bytes = 1 if payload_length == 127: + self._logger.log(common.LOGLEVEL_FINE, + 'Receive 8-octet extended payload length') + extended_payload_length = self.receive_bytes(8) payload_length = struct.unpack( '!Q', extended_payload_length)[0] @@ -319,7 +341,13 @@ class Stream(StreamBase): if self._request.ws_version >= 13 and payload_length < 0x10000: valid_length_encoding = False length_encoding_bytes = 8 + + self._logger.log(common.LOGLEVEL_FINE, + 'Decoded_payload_length=%s', payload_length) elif payload_length == 126: + self._logger.log(common.LOGLEVEL_FINE, + 'Receive 2-octet extended payload length') + extended_payload_length = self.receive_bytes(2) payload_length = struct.unpack( '!H', extended_payload_length)[0] @@ -327,6 +355,9 @@ class Stream(StreamBase): valid_length_encoding = False length_encoding_bytes = 2 + self._logger.log(common.LOGLEVEL_FINE, + 'Decoded_payload_length=%s', payload_length) + if not valid_length_encoding: self._logger.warning( 'Payload length is not encoded using the minimal number of ' @@ -335,12 +366,38 @@ class Stream(StreamBase): length_encoding_bytes) if mask == 1: + self._logger.log(common.LOGLEVEL_FINE, 'Receive mask') + masking_nonce = self.receive_bytes(4) masker = util.RepeatedXorMasker(masking_nonce) + + self._logger.log(common.LOGLEVEL_FINE, 'Mask=%r', masking_nonce) else: masker = _NOOP_MASKER - bytes = masker.mask(self.receive_bytes(payload_length)) + self._logger.log(common.LOGLEVEL_FINE, 'Receive payload data') + if self._logger.isEnabledFor(common.LOGLEVEL_FINE): + receive_start = time.time() + + raw_payload_bytes = self.receive_bytes(payload_length) + + if self._logger.isEnabledFor(common.LOGLEVEL_FINE): + self._logger.log( + common.LOGLEVEL_FINE, + 'Done receiving payload data at %s MB/s', + payload_length / (time.time() - receive_start) / 1000 / 1000) + self._logger.log(common.LOGLEVEL_FINE, 'Unmask payload data') + + if self._logger.isEnabledFor(common.LOGLEVEL_FINE): + unmask_start = time.time() + + bytes = masker.mask(raw_payload_bytes) + + if self._logger.isEnabledFor(common.LOGLEVEL_FINE): + self._logger.log( + common.LOGLEVEL_FINE, + 'Done unmasking payload data at %s MB/s', + payload_length / (time.time() - unmask_start) / 1000 / 1000) return opcode, bytes, fin, rsv1, rsv2, rsv3 @@ -359,8 +416,8 @@ class Stream(StreamBase): Raises: BadOperationException: when called on a server-terminated - connection or called with inconsistent message type or binary - parameter. + connection or called with inconsistent message type or + binary parameter. """ if self._request.server_terminated: @@ -408,6 +465,15 @@ class Stream(StreamBase): frame = self._receive_frame_as_frame_object() + # Check the constraint on the payload size for control frames + # before extension processes the frame. + # See also http://tools.ietf.org/html/rfc6455#section-5.5 + if (common.is_control_opcode(frame.opcode) and + len(frame.payload) > 125): + raise InvalidFrameException( + 'Payload data size of control frames must be 125 bytes or ' + 'less') + for frame_filter in self._options.incoming_frame_filters: frame_filter.filter(frame) @@ -450,12 +516,6 @@ class Stream(StreamBase): if frame.fin: # Unfragmented frame - if (common.is_control_opcode(frame.opcode) and - len(frame.payload) > 125): - raise InvalidFrameException( - 'Application data size of control frames must be ' - '125 bytes or less') - self._original_opcode = frame.opcode message = frame.payload else: @@ -488,7 +548,11 @@ class Stream(StreamBase): # - no application data: no code no reason # - 2 octet of application data: has code but no reason # - 3 or more octet of application data: both code and reason - if len(message) == 1: + if len(message) == 0: + self._logger.debug('Received close frame (empty body)') + self._request.ws_close_code = ( + common.STATUS_NO_STATUS_RECEIVED) + elif len(message) == 1: raise InvalidFrameException( 'If a close frame has status code, the length of ' 'status code must be 2 octet') @@ -507,8 +571,7 @@ class Stream(StreamBase): if self._request.server_terminated: self._logger.debug( - 'Received ack for server-initiated closing ' - 'handshake') + 'Received ack for server-initiated closing handshake') return None self._logger.debug( @@ -520,9 +583,16 @@ class Stream(StreamBase): dispatcher = self._request._dispatcher code, reason = dispatcher.passive_closing_handshake( self._request) + if code is None and reason is not None and len(reason) > 0: + self._logger.warning( + 'Handler specified reason despite code being None') + reason = '' + if reason is None: + reason = '' self._send_closing_handshake(code, reason) self._logger.debug( - 'Sent ack for client-initiated closing handshake') + 'Sent ack for client-initiated closing handshake ' + '(code=%r, reason=%r)', code, reason) return None elif self._original_opcode == common.OPCODE_PING: try: @@ -571,17 +641,21 @@ class Stream(StreamBase): 'Opcode %d is not supported' % self._original_opcode) def _send_closing_handshake(self, code, reason): - if code >= (1 << 16) or code < 0: - raise BadOperationException('Status code is out of range') - - encoded_reason = reason.encode('utf-8') - if len(encoded_reason) + 2 > 125: - raise BadOperationException( - 'Application data size of close frames must be 125 bytes or ' - 'less') + body = '' + if code is not None: + if (code > common.STATUS_USER_PRIVATE_MAX or + code < common.STATUS_NORMAL_CLOSURE): + raise BadOperationException('Status code is out of range') + if (code == common.STATUS_NO_STATUS_RECEIVED or + code == common.STATUS_ABNORMAL_CLOSURE or + code == common.STATUS_TLS_HANDSHAKE): + raise BadOperationException('Status code is reserved pseudo ' + 'code') + encoded_reason = reason.encode('utf-8') + body = struct.pack('!H', code) + encoded_reason frame = create_close_frame( - struct.pack('!H', code) + encoded_reason, + body, self._options.mask_send, self._options.outgoing_frame_filters) @@ -590,15 +664,36 @@ class Stream(StreamBase): self._write(frame) def close_connection(self, code=common.STATUS_NORMAL_CLOSURE, reason=''): - """Closes a WebSocket connection.""" + """Closes a WebSocket connection. + + Args: + code: Status code for close frame. If code is None, a close + frame with empty body will be sent. + reason: string representing close reason. + Raises: + BadOperationException: when reason is specified with code None + or reason is not an instance of both str and unicode. + """ if self._request.server_terminated: self._logger.debug( 'Requested close_connection but server is already terminated') return + if code is None: + if reason is not None and len(reason) > 0: + raise BadOperationException( + 'close reason must not be specified if code is None') + reason = '' + else: + if not isinstance(reason, str) and not isinstance(reason, unicode): + raise BadOperationException( + 'close reason must be an instance of str or unicode') + self._send_closing_handshake(code, reason) - self._logger.debug('Sent server-initiated closing handshake') + self._logger.debug( + 'Sent server-initiated closing handshake (code=%r, reason=%r)', + code, reason) if (code == common.STATUS_GOING_AWAY or code == common.STATUS_PROTOCOL_ERROR): @@ -621,10 +716,6 @@ class Stream(StreamBase): # note: mod_python Connection (mp_conn) doesn't have close method. def send_ping(self, body=''): - if len(body) > 125: - raise ValueError( - 'Application data size of control frames must be 125 bytes or ' - 'less') frame = create_ping_frame( body, self._options.mask_send, @@ -634,10 +725,6 @@ class Stream(StreamBase): self._ping_queue.append(body) def _send_pong(self, body): - if len(body) > 125: - raise ValueError( - 'Application data size of control frames must be 125 bytes or ' - 'less') frame = create_pong_frame( body, self._options.mask_send, diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/common.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/common.py index ba670bb42..710967c80 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/common.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/common.py @@ -28,6 +28,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""This file must not depend on any module specific to the WebSocket protocol. +""" + + +from mod_pywebsocket import http_header_util + + +# Additional log level definitions. +LOGLEVEL_FINE = 9 + # Constants indicating WebSocket protocol version. VERSION_HIXIE75 = -1 VERSION_HYBI00 = 0 @@ -93,6 +103,7 @@ SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location' # Extensions DEFLATE_STREAM_EXTENSION = 'deflate-stream' DEFLATE_FRAME_EXTENSION = 'deflate-frame' +PERFRAME_COMPRESSION_EXTENSION = 'perframe-compress' X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame' # Status codes @@ -176,4 +187,118 @@ class ExtensionParameter(object): return param_value +class ExtensionParsingException(Exception): + def __init__(self, name): + super(ExtensionParsingException, self).__init__(name) + + +def _parse_extension_param(state, definition, allow_quoted_string): + param_name = http_header_util.consume_token(state) + + if param_name is None: + raise ExtensionParsingException('No valid parameter name found') + + http_header_util.consume_lwses(state) + + if not http_header_util.consume_string(state, '='): + definition.add_parameter(param_name, None) + return + + http_header_util.consume_lwses(state) + + if allow_quoted_string: + # TODO(toyoshim): Add code to validate that parsed param_value is token + param_value = http_header_util.consume_token_or_quoted_string(state) + else: + param_value = http_header_util.consume_token(state) + if param_value is None: + raise ExtensionParsingException( + 'No valid parameter value found on the right-hand side of ' + 'parameter %r' % param_name) + + definition.add_parameter(param_name, param_value) + + +def _parse_extension(state, allow_quoted_string): + extension_token = http_header_util.consume_token(state) + if extension_token is None: + return None + + extension = ExtensionParameter(extension_token) + + while True: + http_header_util.consume_lwses(state) + + if not http_header_util.consume_string(state, ';'): + break + + http_header_util.consume_lwses(state) + + try: + _parse_extension_param(state, extension, allow_quoted_string) + except ExtensionParsingException, e: + raise ExtensionParsingException( + 'Failed to parse parameter for %r (%r)' % + (extension_token, e)) + + return extension + + +def parse_extensions(data, allow_quoted_string=False): + """Parses Sec-WebSocket-Extensions header value returns a list of + ExtensionParameter objects. + + Leading LWSes must be trimmed. + """ + + state = http_header_util.ParsingState(data) + + extension_list = [] + while True: + extension = _parse_extension(state, allow_quoted_string) + if extension is not None: + extension_list.append(extension) + + http_header_util.consume_lwses(state) + + if http_header_util.peek(state) is None: + break + + if not http_header_util.consume_string(state, ','): + raise ExtensionParsingException( + 'Failed to parse Sec-WebSocket-Extensions header: ' + 'Expected a comma but found %r' % + http_header_util.peek(state)) + + http_header_util.consume_lwses(state) + + if len(extension_list) == 0: + raise ExtensionParsingException( + 'No valid extension entry found') + + return extension_list + + +def format_extension(extension): + """Formats an ExtensionParameter object.""" + + formatted_params = [extension.name()] + for param_name, param_value in extension.get_parameters(): + if param_value is None: + formatted_params.append(param_name) + else: + quoted_value = http_header_util.quote_if_necessary(param_value) + formatted_params.append('%s=%s' % (param_name, quoted_value)) + return '; '.join(formatted_params) + + +def format_extensions(extension_list): + """Formats a list of ExtensionParameter objects.""" + + formatted_extension_list = [] + for extension in extension_list: + formatted_extension_list.append(format_extension(extension)) + return ', '.join(formatted_extension_list) + + # vi:sts=4 sw=4 et diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/extensions.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/extensions.py index ce3784658..52b7a4a19 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/extensions.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/extensions.py @@ -1,4 +1,4 @@ -# Copyright 2011, Google Inc. +# Copyright 2012, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ from mod_pywebsocket import common from mod_pywebsocket import util +from mod_pywebsocket.http_header_util import quote_if_necessary _available_processors = {} @@ -254,6 +255,96 @@ _available_processors[common.X_WEBKIT_DEFLATE_FRAME_EXTENSION] = ( DeflateFrameExtensionProcessor) +def _parse_compression_method(data): + """Parses the value of "method" extension parameter.""" + + return common.parse_extensions(data, allow_quoted_string=True) + + +def _create_accepted_method_desc(method_name, method_params): + """Creates accepted-method-desc from given method name and parameters""" + + extension = common.ExtensionParameter(method_name) + for name, value in method_params: + extension.add_parameter(name, value) + return common.format_extension(extension) + + +class PerFrameCompressionExtensionProcessor(ExtensionProcessorInterface): + """WebSocket Per-frame compression extension processor.""" + + _METHOD_PARAM = 'method' + _DEFLATE_METHOD = 'deflate' + + def __init__(self, request): + self._logger = util.get_class_logger(self) + self._request = request + self._compression_method_name = None + self._compression_processor = None + + def _lookup_compression_processor(self, method_desc): + if method_desc.name() == self._DEFLATE_METHOD: + return DeflateFrameExtensionProcessor(method_desc) + return None + + def _get_compression_processor_response(self): + """Looks up the compression processor based on the self._request and + returns the compression processor's response. + """ + + method_list = self._request.get_parameter_value(self._METHOD_PARAM) + if method_list is None: + return None + methods = _parse_compression_method(method_list) + if methods is None: + return None + comression_processor = None + # The current implementation tries only the first method that matches + # supported algorithm. Following methods aren't tried even if the + # first one is rejected. + # TODO(bashi): Need to clarify this behavior. + for method_desc in methods: + compression_processor = self._lookup_compression_processor( + method_desc) + if compression_processor is not None: + self._compression_method_name = method_desc.name() + break + if compression_processor is None: + return None + processor_response = compression_processor.get_extension_response() + if processor_response is None: + return None + self._compression_processor = compression_processor + return processor_response + + def get_extension_response(self): + processor_response = self._get_compression_processor_response() + if processor_response is None: + return None + + response = common.ExtensionParameter(self._request.name()) + accepted_method_desc = _create_accepted_method_desc( + self._compression_method_name, + processor_response.get_parameters()) + response.add_parameter(self._METHOD_PARAM, accepted_method_desc) + self._logger.debug( + 'Enable %s extension (method: %s)' % + (self._request.name(), self._compression_method_name)) + return response + + def setup_stream_options(self, stream_options): + if self._compression_processor is None: + return + self._compression_processor.setup_stream_options(stream_options) + + def get_compression_processor(self): + return self._compression_processor + + +_available_processors[common.PERFRAME_COMPRESSION_EXTENSION] = ( + PerFrameCompressionExtensionProcessor) + + def get_extension_processor(extension_request): global _available_processors processor_class = _available_processors.get(extension_request.name()) diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/_base.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/_base.py index 4d7c32e35..bc095b129 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/_base.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/_base.py @@ -1,4 +1,4 @@ -# Copyright 2011, Google Inc. +# Copyright 2012, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -216,108 +216,4 @@ def parse_token_list(data): return token_list -def _parse_extension_param(state, definition, allow_quoted_string): - param_name = http_header_util.consume_token(state) - - if param_name is None: - raise HandshakeException('No valid parameter name found') - - http_header_util.consume_lwses(state) - - if not http_header_util.consume_string(state, '='): - definition.add_parameter(param_name, None) - return - - http_header_util.consume_lwses(state) - - if allow_quoted_string: - # TODO(toyoshim): Add code to validate that parsed param_value is token - param_value = http_header_util.consume_token_or_quoted_string(state) - else: - param_value = http_header_util.consume_token(state) - if param_value is None: - raise HandshakeException( - 'No valid parameter value found on the right-hand side of ' - 'parameter %r' % param_name) - - definition.add_parameter(param_name, param_value) - - -def _parse_extension(state, allow_quoted_string): - extension_token = http_header_util.consume_token(state) - if extension_token is None: - return None - - extension = common.ExtensionParameter(extension_token) - - while True: - http_header_util.consume_lwses(state) - - if not http_header_util.consume_string(state, ';'): - break - - http_header_util.consume_lwses(state) - - try: - _parse_extension_param(state, extension, allow_quoted_string) - except HandshakeException, e: - raise HandshakeException( - 'Failed to parse Sec-WebSocket-Extensions header: ' - 'Failed to parse parameter for %r (%r)' % - (extension_token, e)) - - return extension - - -def parse_extensions(data, allow_quoted_string=False): - """Parses Sec-WebSocket-Extensions header value returns a list of - common.ExtensionParameter objects. - - Leading LWSes must be trimmed. - """ - - state = http_header_util.ParsingState(data) - - extension_list = [] - while True: - extension = _parse_extension(state, allow_quoted_string) - if extension is not None: - extension_list.append(extension) - - http_header_util.consume_lwses(state) - - if http_header_util.peek(state) is None: - break - - if not http_header_util.consume_string(state, ','): - raise HandshakeException( - 'Failed to parse Sec-WebSocket-Extensions header: ' - 'Expected a comma but found %r' % - http_header_util.peek(state)) - - http_header_util.consume_lwses(state) - - if len(extension_list) == 0: - raise HandshakeException( - 'Sec-WebSocket-Extensions header contains no valid extension') - - return extension_list - - -def format_extensions(extension_list): - formatted_extension_list = [] - for extension in extension_list: - formatted_params = [extension.name()] - for param_name, param_value in extension.get_parameters(): - if param_value is None: - formatted_params.append(param_name) - else: - quoted_value = http_header_util.quote_if_necessary(param_value) - formatted_params.append('%s=%s' % (param_name, quoted_value)) - - formatted_extension_list.append('; '.join(formatted_params)) - - return ', '.join(formatted_extension_list) - - # vi:sts=4 sw=4 et diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/hybi.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/hybi.py index 3bc84bd26..2883acbf8 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/hybi.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/handshake/hybi.py @@ -1,4 +1,4 @@ -# Copyright 2011, Google Inc. +# Copyright 2012, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -50,11 +50,9 @@ import re from mod_pywebsocket import common from mod_pywebsocket.extensions import get_extension_processor from mod_pywebsocket.handshake._base import check_request_line -from mod_pywebsocket.handshake._base import format_extensions from mod_pywebsocket.handshake._base import format_header from mod_pywebsocket.handshake._base import get_mandatory_header from mod_pywebsocket.handshake._base import HandshakeException -from mod_pywebsocket.handshake._base import parse_extensions from mod_pywebsocket.handshake._base import parse_token_list from mod_pywebsocket.handshake._base import validate_mandatory_header from mod_pywebsocket.handshake._base import validate_subprotocol @@ -290,8 +288,12 @@ class Handshaker(object): allow_quoted_string=False else: allow_quoted_string=True - self._request.ws_requested_extensions = parse_extensions( - extensions_header, allow_quoted_string=allow_quoted_string) + try: + self._request.ws_requested_extensions = common.parse_extensions( + extensions_header, allow_quoted_string=allow_quoted_string) + except common.ExtensionParsingException, e: + raise HandshakeException( + 'Failed to parse Sec-WebSocket-Extensions header: %r' % e) self._logger.debug( 'Extensions requested: %r', @@ -358,7 +360,7 @@ class Handshaker(object): len(self._request.ws_extensions) != 0): response.append(format_header( common.SEC_WEBSOCKET_EXTENSIONS_HEADER, - format_extensions(self._request.ws_extensions))) + common.format_extensions(self._request.ws_extensions))) response.append('\r\n') raw_response = ''.join(response) diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/standalone.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/standalone.py index dc143ea00..850aa5cd4 100755 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/standalone.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/standalone.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011, Google Inc. +# Copyright 2012, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -55,6 +55,20 @@ handlers. If this path is relative, <document_root> is used as the base. handlers under scan_dir are scanned. This is useful in saving scan time. +SUPPORTING TLS + +To support TLS, run standalone.py with -t, -k, and -c options. + + +SUPPORTING CLIENT AUTHENTICATION + +To support client authentication with TLS, run standalone.py with -t, -k, -c, +and --ca-certificate options. + +E.g., $./standalone.py -d ../example -p 10443 -t -c ../test/cert/cert.pem -k +../test/cert/key.pem --ca-certificate=../test/cert/cacert.pem + + CONFIGURATION FILE You can also write a configuration file and use it by specifying the path to @@ -311,10 +325,16 @@ class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): continue if self.websocket_server_options.use_tls: if _HAS_SSL: + if self.websocket_server_options.ca_certificate: + client_cert_ = ssl.CERT_REQUIRED + else: + client_cert_ = ssl.CERT_NONE socket_ = ssl.wrap_socket(socket_, keyfile=self.websocket_server_options.private_key, certfile=self.websocket_server_options.certificate, - ssl_version=ssl.PROTOCOL_SSLv23) + ssl_version=ssl.PROTOCOL_SSLv23, + ca_certs=self.websocket_server_options.ca_certificate, + cert_reqs=client_cert_) if _HAS_OPEN_SSL: ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) ctx.use_privatekey_file( @@ -601,7 +621,13 @@ class WebSocketRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler): return False +def _get_logger_from_class(c): + return logging.getLogger('%s.%s' % (c.__module__, c.__name__)) + + def _configure_logging(options): + logging.addLevelName(common.LOGLEVEL_FINE, 'FINE') + logger = logging.getLogger() logger.setLevel(logging.getLevelName(options.log_level.upper())) if options.log_file: @@ -614,6 +640,13 @@ def _configure_logging(options): handler.setFormatter(formatter) logger.addHandler(handler) + deflate_log_level_name = logging.getLevelName( + options.deflate_log_level.upper()) + _get_logger_from_class(util._Deflater).setLevel( + deflate_log_level_name) + _get_logger_from_class(util._Inflater).setLevel( + deflate_log_level_name) + def _alias_handlers(dispatcher, websock_handlers_map_file): """Set aliases specified in websock_handler_map_file in dispatcher. @@ -702,13 +735,25 @@ def _build_option_parser(): default='', help='TLS private key file.') parser.add_option('-c', '--certificate', dest='certificate', default='', help='TLS certificate file.') + parser.add_option('--ca-certificate', dest='ca_certificate', default='', + help=('TLS CA certificate file for client ' + 'authentication.')) parser.add_option('-l', '--log-file', '--log_file', dest='log_file', default='', help='Log file.') + # Custom log level: + # - FINE: Prints status of each frame processing step parser.add_option('--log-level', '--log_level', type='choice', dest='log_level', default='warn', - choices=['debug', 'info', 'warning', 'warn', 'error', + choices=['fine', + 'debug', 'info', 'warning', 'warn', 'error', 'critical'], help='Log level.') + parser.add_option('--deflate-log-level', '--deflate_log_level', + type='choice', + dest='deflate_log_level', default='warn', + choices=['debug', 'info', 'warning', 'warn', 'error', + 'critical'], + help='Log level for _Deflater and _Inflater.') parser.add_option('--thread-monitor-interval-in-sec', '--thread_monitor_interval_in_sec', dest='thread_monitor_interval_in_sec', @@ -825,13 +870,20 @@ def _main(args=None): if options.use_tls: if not (_HAS_SSL or _HAS_OPEN_SSL): - logging.critical('TLS support requires ssl or pyOpenSSL.') + logging.critical('TLS support requires ssl or pyOpenSSL module.') sys.exit(1) if not options.private_key or not options.certificate: logging.critical( 'To use TLS, specify private_key and certificate.') sys.exit(1) + if options.ca_certificate: + if not options.use_tls: + logging.critical('TLS must be enabled for client authentication.') + sys.exit(1) + if not _HAS_SSL: + logging.critical('Client authentication requires ssl module.') + if not options.scan_dir: options.scan_dir = options.websock_handlers diff --git a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/util.py b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/util.py index 9a0ab5de6..6146e052f 100644 --- a/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/util.py +++ b/Tools/Scripts/webkitpy/thirdparty/mod_pywebsocket/util.py @@ -177,9 +177,16 @@ class RepeatedXorMasker(object): def mask(self, s): result = array.array('B') result.fromstring(s) + # Use temporary local variables to eliminate the cost to access + # attributes + count = self._count + mask = self._mask + mask_size = self._mask_size for i in xrange(len(result)): - result[i] ^= self._mask[self._count] - self._count = (self._count + 1) % self._mask_size + result[i] ^= mask[count] + count = (count + 1) % mask_size + self._count = count + return result.tostring() diff --git a/Tools/Scripts/webkitpy/thirdparty/ordered_dict.py b/Tools/Scripts/webkitpy/thirdparty/ordered_dict.py new file mode 100644 index 000000000..3dc735a4a --- /dev/null +++ b/Tools/Scripts/webkitpy/thirdparty/ordered_dict.py @@ -0,0 +1,89 @@ +# Copyright (c) 2009 Raymond Hettinger. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# This code is obtained from http://code.activestate.com/recipes/576669/ + +from collections import MutableMapping + +class OrderedDict(dict, MutableMapping): + + # Methods with direct access to underlying attributes + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at 1 argument, got %d', len(args)) + if not hasattr(self, '_keys'): + self._keys = [] + self.update(*args, **kwds) + + def clear(self): + del self._keys[:] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + self._keys.append(key) + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __iter__(self): + return iter(self._keys) + + def __reversed__(self): + return reversed(self._keys) + + def popitem(self): + if not self: + raise KeyError + key = self._keys.pop() + value = dict.pop(self, key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + inst_dict.pop('_keys', None) + return (self.__class__, (items,), inst_dict) + + # Methods with indirect access via the above methods + + setdefault = MutableMapping.setdefault + update = MutableMapping.update + pop = MutableMapping.pop + keys = MutableMapping.keys + values = MutableMapping.values + items = MutableMapping.items + + def __repr__(self): + pairs = ', '.join(map('%r: %r'.__mod__, self.items())) + return '%s({%s})' % (self.__class__.__name__, pairs) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d diff --git a/Tools/Scripts/webkitpy/tool/commands/queries.py b/Tools/Scripts/webkitpy/tool/commands/queries.py index ab9db4aca..f69971e59 100644 --- a/Tools/Scripts/webkitpy/tool/commands/queries.py +++ b/Tools/Scripts/webkitpy/tool/commands/queries.py @@ -395,7 +395,7 @@ class PrintExpectations(AbstractDeclarativeCommand): make_option('--csv', action='store_true', default=False, help='Print a CSV-style report that includes the port name, modifiers, tests, and expectations'), make_option('-f', '--full', action='store_true', default=False, - help='Print a full test_expectations.txt-style line for every match'), + help='Print a full TestExpectations-style line for every match'), ] + port_options(platform='port/platform to use. Use glob-style wildcards for multiple ports (implies --csv)') AbstractDeclarativeCommand.__init__(self, options=options) diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py index 5a184f19e..bd890cc8e 100644 --- a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py +++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py @@ -43,16 +43,12 @@ from webkitpy.common.system.user import User from webkitpy.layout_tests.controllers.test_result_writer import TestResultWriter from webkitpy.layout_tests.models import test_failures from webkitpy.layout_tests.models.test_configuration import TestConfiguration -from webkitpy.layout_tests.models.test_expectations import TestExpectations +from webkitpy.layout_tests.models.test_expectations import TestExpectations, suffixes_for_expectations, BASELINE_SUFFIX_LIST from webkitpy.layout_tests.port import builders from webkitpy.tool.grammar import pluralize from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand -# FIXME: Pull this from Port.baseline_extensions(). -_baseline_suffix_list = ['png', 'wav', 'txt'] - - _log = logging.getLogger(__name__) # FIXME: Should TestResultWriter know how to compute this string? @@ -64,10 +60,10 @@ class AbstractRebaseliningCommand(AbstractDeclarativeCommand): def __init__(self, options=None): options = options or [] options.extend([ - optparse.make_option('--suffixes', default=','.join(_baseline_suffix_list), action='store', + optparse.make_option('--suffixes', default=','.join(BASELINE_SUFFIX_LIST), action='store', help='file types to rebaseline')]) AbstractDeclarativeCommand.__init__(self, options=options) - self._baseline_suffix_list = _baseline_suffix_list + self._baseline_suffix_list = BASELINE_SUFFIX_LIST class RebaselineTest(AbstractRebaseliningCommand): @@ -140,7 +136,7 @@ class RebaselineTest(AbstractRebaseliningCommand): def _update_expectations_file(self, builder_name, test_name): port = self._tool.port_factory.get_from_builder_name(builder_name) - expectations = TestExpectations(port) + expectations = TestExpectations(port, include_overrides=False) for test_configuration in port.all_test_configurations(): if test_configuration.version == port.test_configuration().version: @@ -239,7 +235,7 @@ class AnalyzeBaselines(AbstractRebaseliningCommand): class RebaselineExpectations(AbstractDeclarativeCommand): name = "rebaseline-expectations" - help_text = "Rebaselines the tests indicated in test_expectations.txt." + help_text = "Rebaselines the tests indicated in TestExpectations." def __init__(self): options = [ @@ -260,19 +256,25 @@ class RebaselineExpectations(AbstractDeclarativeCommand): # FIXME: Support non-Chromium ports. return port_name.startswith('chromium-') - def _expectations(self, port): - return TestExpectations(port) - def _update_expectations_file(self, port_name): if not self._is_supported_port(port_name): return port = self._tool.port_factory.get(port_name) - expectations = self._expectations(port) + + # FIXME: This will intentionally skip over any REBASELINE expectations that were in an overrides file. + # This is not good, but avoids having the overrides getting written into the main file. + # See https://bugs.webkit.org/show_bug.cgi?id=88456 for context. This will no longer be needed + # once we properly support cascading expectations files. + expectations = TestExpectations(port, include_overrides=False) path = port.path_to_test_expectations_file() self._tool.filesystem.write_text_file(path, expectations.remove_rebaselined_tests(expectations.get_rebaselining_failures())) def _tests_to_rebaseline(self, port): - return self._expectations(port).get_rebaselining_failures() + tests_to_rebaseline = {} + expectations = TestExpectations(port, include_overrides=True) + for test in expectations.get_rebaselining_failures(): + tests_to_rebaseline[test] = suffixes_for_expectations(expectations.get_expectations(test)) + return tests_to_rebaseline def _rebaseline_port(self, port_name): if not self._is_supported_port(port_name): @@ -281,23 +283,23 @@ class RebaselineExpectations(AbstractDeclarativeCommand): if not builder_name: return _log.info("Retrieving results for %s from %s." % (port_name, builder_name)) - for test_name in self._tests_to_rebaseline(self._tool.port_factory.get(port_name)): - self._touched_test_names.add(test_name) - _log.info(" %s" % test_name) - # FIXME: need to extract the correct list of suffixes here. - self._run_webkit_patch(['rebaseline-test', builder_name, test_name]) + for test_name, suffixes in self._tests_to_rebaseline(self._tool.port_factory.get(port_name)).iteritems(): + self._touched_tests.setdefault(test_name, set()).update(set(suffixes)) + _log.info(" %s (%s)" % (test_name, ','.join(suffixes))) + # FIXME: we should use executive.run_in_parallel() to speed this up. + self._run_webkit_patch(['rebaseline-test', '--suffixes', ','.join(suffixes), builder_name, test_name]) def execute(self, options, args, tool): - self._touched_test_names = set([]) + self._touched_tests = {} for port_name in tool.port_factory.all_port_names(): self._rebaseline_port(port_name) for port_name in tool.port_factory.all_port_names(): self._update_expectations_file(port_name) if not options.optimize: return - for test_name in self._touched_test_names: - _log.info("Optimizing baselines for %s." % test_name) - self._run_webkit_patch(['optimize-baselines', test_name]) + for test_name, suffixes in self._touched_tests.iteritems(): + _log.info("Optimizing baselines for %s (%s)." % (test_name, ','.join(suffixes))) + self._run_webkit_patch(['optimize-baselines', '--suffixes', ','.join(suffixes), test_name]) class Rebaseline(AbstractDeclarativeCommand): diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py index f8d9dfc1b..b5a043ff8 100644 --- a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py +++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py @@ -48,6 +48,8 @@ class TestRebaseline(unittest.TestCase): command.bind_to_tool(tool) lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7") + for path in lion_port.expectations_files(): + tool.filesystem.write_text_file(path, '') tool.filesystem.write_text_file(lion_port.path_to_test_expectations_file(), """BUGB MAC LINUX XP DEBUG : fast/dom/Window/window-postmessage-clone-really-deep-array.html = PASS BUGA DEBUG : fast/css/large-list-of-rules-crash.html = TEXT """) @@ -72,6 +74,7 @@ BUGA DEBUG : fast/css/large-list-of-rules-crash.html = TEXT command.bind_to_tool(tool) lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7") + tool.filesystem.write_text_file(lion_port.path_from_chromium_base('skia', 'skia_test_expectations.txt'), '') tool.filesystem.write_text_file(lion_port.path_to_test_expectations_file(), "BUGX MAC : userscripts/another-test.html = IMAGE\nBUGZ LINUX : userscripts/another-test.html = IMAGE\n") tool.filesystem.write_text_file(os.path.join(lion_port.layout_tests_dir(), "userscripts/another-test.html"), "Dummy test contents") @@ -84,6 +87,26 @@ Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-resu new_expectations = tool.filesystem.read_text_file(lion_port.path_to_test_expectations_file()) self.assertEqual(new_expectations, "BUGX LEOPARD SNOWLEOPARD : userscripts/another-test.html = IMAGE\nBUGZ LINUX : userscripts/another-test.html = IMAGE\n") + def test_rebaseline_does_not_include_overrides(self): + command = RebaselineTest() + tool = MockTool() + command.bind_to_tool(tool) + + lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7") + tool.filesystem.write_text_file(lion_port.path_from_chromium_base('skia', 'skia_test_expectations.txt'), '') + tool.filesystem.write_text_file(lion_port.path_to_test_expectations_file(), "BUGX MAC : userscripts/another-test.html = IMAGE\nBUGZ LINUX : userscripts/another-test.html = IMAGE\n") + tool.filesystem.write_text_file(lion_port.path_from_chromium_base('skia', 'skia_test_expectations.txt'), "BUGY MAC : other-test.html = TEXT\n") + tool.filesystem.write_text_file(os.path.join(lion_port.layout_tests_dir(), "userscripts/another-test.html"), "Dummy test contents") + + expected_logs = """Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.png. +Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.wav. +Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.txt. +""" + OutputCapture().assert_outputs(self, command._rebaseline_test_and_update_expectations, ["Webkit Mac10.7", "userscripts/another-test.html", None], expected_logs=expected_logs) + + new_expectations = tool.filesystem.read_text_file(lion_port.path_to_test_expectations_file()) + self.assertEqual(new_expectations, "BUGX LEOPARD SNOWLEOPARD : userscripts/another-test.html = IMAGE\nBUGZ LINUX : userscripts/another-test.html = IMAGE\n") + def test_rebaseline_test(self): command = RebaselineTest() command.bind_to_tool(MockTool()) @@ -160,64 +183,87 @@ Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-resu for port_name in tool.port_factory.all_port_names(): port = tool.port_factory.get(port_name) - tool.filesystem.write_text_file(port.path_to_test_expectations_file(), '') + for path in port.expectations_files(): + tool.filesystem.write_text_file(path, '') # Don't enable logging until after we create the mock expectation files as some Port.__init__'s run subcommands. tool.executive = MockExecutive(should_log=True) expected_logs = """Retrieving results for chromium-linux-x86 from Webkit Linux 32. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-linux-x86_64 from Webkit Linux. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-mac-leopard from Webkit Mac10.5. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-mac-lion from Webkit Mac10.7. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-mac-snowleopard from Webkit Mac10.6. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-win-vista from Webkit Vista. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-win-win7 from Webkit Win7. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) Retrieving results for chromium-win-xp from Webkit Win. - userscripts/another-test.html - userscripts/images.svg + userscripts/another-test.html (txt) + userscripts/images.svg (png) """ - expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux 32', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux 32', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.5', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.5', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.7', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.7', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.6', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.6', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Vista', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Vista', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win7', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win7', 'userscripts/images.svg'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win', 'userscripts/another-test.html'], cwd=/mock-checkout -MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win', 'userscripts/images.svg'], cwd=/mock-checkout + expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Linux 32', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Linux 32', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Linux', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Linux', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Mac10.5', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Mac10.5', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Mac10.7', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Mac10.7', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Mac10.6', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Mac10.6', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Vista', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Vista', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Win7', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Win7', 'userscripts/images.svg'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'txt', 'Webkit Win', 'userscripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'rebaseline-test', '--suffixes', 'png', 'Webkit Win', 'userscripts/images.svg'], cwd=/mock-checkout """ - command._tests_to_rebaseline = lambda port: ['userscripts/another-test.html', 'userscripts/images.svg'] + command._tests_to_rebaseline = lambda port: {'userscripts/another-test.html': set(['txt']), 'userscripts/images.svg': set(['png'])} OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=False), [], tool], expected_logs=expected_logs, expected_stderr=expected_stderr) expected_logs_with_optimize = expected_logs + ( - "Optimizing baselines for userscripts/another-test.html.\n" - "Optimizing baselines for userscripts/images.svg.\n") + "Optimizing baselines for userscripts/another-test.html (txt).\n" + "Optimizing baselines for userscripts/images.svg (png).\n") expected_stderr_with_optimize = expected_stderr + ( - "MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/another-test.html'], cwd=/mock-checkout\n" - "MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/images.svg'], cwd=/mock-checkout\n") + "MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'userscripts/another-test.html'], cwd=/mock-checkout\n" + "MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'png', 'userscripts/images.svg'], cwd=/mock-checkout\n") - command._tests_to_rebaseline = lambda port: ['userscripts/another-test.html', 'userscripts/images.svg'] + command._tests_to_rebaseline = lambda port: {'userscripts/another-test.html': set(['txt']), 'userscripts/images.svg': set(['png'])} OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True), [], tool], expected_logs=expected_logs_with_optimize, expected_stderr=expected_stderr_with_optimize) + + def test_overrides_are_included_correctly(self): + command = RebaselineExpectations() + tool = MockTool() + command.bind_to_tool(tool) + port = tool.port_factory.get('chromium-mac-lion') + + # This tests that the any tests marked as REBASELINE in the overrides are found, but + # that the overrides do not get written into the main file. + expectations_path = port.expectations_files()[0] + expectations_contents = '' + port._filesystem.write_text_file(expectations_path, expectations_contents) + port.expectations_dict = lambda: { + expectations_path: expectations_contents, + 'overrides': ('BUGX REBASELINE : userscripts/another-test.html = TEXT\n' + 'BUGY : userscripts/test.html = CRASH\n')} + + for path in port.expectations_files(): + port._filesystem.write_text_file(path, '') + port._filesystem.write_text_file(port.layout_tests_dir() + '/userscripts/another-test.html', '') + self.assertEquals(command._tests_to_rebaseline(port), {'userscripts/another-test.html': set(['txt'])}) + self.assertEquals(port._filesystem.read_text_file(expectations_path), expectations_contents) diff --git a/Tools/Scripts/webkitpy/tool/mocktool.py b/Tools/Scripts/webkitpy/tool/mocktool.py index 55fde64ad..21ee91fc9 100644 --- a/Tools/Scripts/webkitpy/tool/mocktool.py +++ b/Tools/Scripts/webkitpy/tool/mocktool.py @@ -36,8 +36,7 @@ from webkitpy.common.net.irc.irc_mock import MockIRC from webkitpy.common.config.ports_mock import MockPort -# FIXME: This should be moved somewhere in common and renamed -# something without Mock in the name. +# FIXME: We should just replace this with optparse.Values(default=kwargs) class MockOptions(object): """Mock implementation of optparse.Values.""" @@ -53,6 +52,11 @@ class MockOptions(object): self.__dict__.update(**kwargs) return self + def ensure_value(self, key, value): + if getattr(self, key, None) == None: + self.__dict__[key] = value + return self.__dict__[key] + # FIXME: This should be renamed MockWebKitPatch. class MockTool(MockHost): diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py index 369070982..bfe003fe9 100644 --- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py +++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py @@ -69,7 +69,7 @@ class GardeningExpectationsUpdater(BugManager): return "BUG_NEW" def update_expectations(self, failure_info_list): - expectation_lines = self._parser.parse(self._tool.filesystem.read_text_file(self._path_to_test_expectations_file)) + expectation_lines = self._parser.parse(self._path_to_test_expectations_file, self._tool.filesystem.read_text_file(self._path_to_test_expectations_file)) editor = TestExpectationsEditor(expectation_lines, self) updated_expectation_lines = [] # FIXME: Group failures by testName+failureTypeList. diff --git a/Tools/Scripts/webkitpy/tool/steps/commit.py b/Tools/Scripts/webkitpy/tool/steps/commit.py index 2f245e024..0e5ca9157 100644 --- a/Tools/Scripts/webkitpy/tool/steps/commit.py +++ b/Tools/Scripts/webkitpy/tool/steps/commit.py @@ -54,11 +54,7 @@ class Commit(AbstractStep): error.num_local_commits, working_directory_message)) def _check_test_expectations(self, changed_files): - test_expectations_files = [] - for filename in changed_files: - if filename.endswith('test_expectations.txt'): - test_expectations_files.append(filename) - + test_expectations_files = [filename for filename in changed_files if filename.endswith('TestExpectations')] if not test_expectations_files: return diff --git a/Tools/Scripts/webkitpy/tool/steps/commit_unittest.py b/Tools/Scripts/webkitpy/tool/steps/commit_unittest.py index 50dfaea2b..25d9b61a1 100644 --- a/Tools/Scripts/webkitpy/tool/steps/commit_unittest.py +++ b/Tools/Scripts/webkitpy/tool/steps/commit_unittest.py @@ -36,7 +36,7 @@ from webkitpy.tool.steps.commit import Commit class CommitTest(unittest.TestCase): - def test_check_test_expectations(self): + def _test_check_test_expectations(self, filename): capture = OutputCapture() options = MockOptions() options.git_commit = "" @@ -46,16 +46,20 @@ class CommitTest(unittest.TestCase): tool.user = None # Will cause any access of tool.user to raise an exception. step = Commit(tool, options) state = { - "changed_files": ["test_expectations.txtXXX"], + "changed_files": [filename + "XXX"], } tool.executive = MockExecutive(should_log=True, should_throw_when_run=False) capture.assert_outputs(self, step.run, [state], expected_stderr="Committed r49824: <http://trac.webkit.org/changeset/49824>\n") state = { - "changed_files": ["platform/chromium/test_expectations.txt"], + "changed_files": ["platform/chromium/" + filename], } - capture.assert_outputs(self, step.run, [state], expected_stderr="MOCK run_and_throw_if_fail: ['mock-check-webkit-style', '--diff-files', 'platform/chromium/test_expectations.txt'], cwd=/mock-checkout\nCommitted r49824: <http://trac.webkit.org/changeset/49824>\n") + capture.assert_outputs(self, step.run, [state], expected_stderr="MOCK run_and_throw_if_fail: ['mock-check-webkit-style', '--diff-files', 'platform/chromium/" + + filename + "'], cwd=/mock-checkout\nCommitted r49824: <http://trac.webkit.org/changeset/49824>\n") - tool.executive = MockExecutive(should_log=True, should_throw_when_run=set(["platform/chromium/test_expectations.txt"])) + tool.executive = MockExecutive(should_log=True, should_throw_when_run=set(["platform/chromium/" + filename])) self.assertRaises(ScriptError, capture.assert_outputs, self, step.run, [state]) + + def test_check_test_expectations(self): + self._test_check_test_expectations('TestExpectations') diff --git a/Tools/TestResultServer/static-dashboards/builders.js b/Tools/TestResultServer/static-dashboards/builders.js index e9f45f1d9..9d3567423 100644 --- a/Tools/TestResultServer/static-dashboards/builders.js +++ b/Tools/TestResultServer/static-dashboards/builders.js @@ -46,6 +46,9 @@ BuilderMaster.prototype.builderJsonPath = function() }; CHROMIUM_BUILDER_MASTER = new BuilderMaster('Chromium', 'http://build.chromium.org/p/chromium/'); +CHROMIUM_WIN_BUILDER_MASTER = new BuilderMaster('ChromiumWin', 'http://build.chromium.org/p/chromium.win/'); +CHROMIUM_MAC_BUILDER_MASTER = new BuilderMaster('ChromiumMac', 'http://build.chromium.org/p/chromium.mac/'); +CHROMIUM_LINUX_BUILDER_MASTER = new BuilderMaster('ChromiumLinux', 'http://build.chromium.org/p/chromium.linux/'); CHROMIUMOS_BUILDER_MASTER = new BuilderMaster('ChromiumChromiumOS', 'http://build.chromium.org/p/chromium.chromiumos/'); CHROMIUM_GPU_BUILDER_MASTER = new BuilderMaster('ChromiumGPU', 'http://build.chromium.org/p/chromium.gpu/'); CHROMIUM_GPU_FYI_BUILDER_MASTER = new BuilderMaster('ChromiumGPUFYI', 'http://build.chromium.org/p/chromium.gpu.fyi/'); @@ -61,20 +64,36 @@ var LEGACY_BUILDER_MASTERS_TO_GROUPS = { 'webkit.org': '@ToT - webkit.org' }; -function BuilderGroup(isToTWebKit, builders) +function BuilderGroup(isToTWebKit) { this.isToTWebKit = isToTWebKit; // Map of builderName (the name shown in the waterfall) to builderPath (the // path used in the builder's URL) this.builders = {}; + this.groups = 0; + this.expectedGroups = 0; +} + +BuilderGroup.prototype.setbuilder = function(builder, flags) { + this.builders[builder] = builder.replace(/[ .()]/g, '_'); + // FIXME: Remove this at some point, we don't actually use DEFAULT_BUILDER + // in any meaningful way anymore. We always just default to the + // first builder in alphabetical order. + if (flags & BuilderGroup.DEFAULT_BUILDER) + this.defaultBuilder = builder; +}; + +BuilderGroup.prototype.append = function(builders) { builders.forEach(function(builderAndFlags) { var builder = builderAndFlags[0]; var flags = builderAndFlags[1]; - - this.builders[builder] = builder.replace(/[ .()]/g, '_'); - if (flags & BuilderGroup.DEFAULT_BUILDER) - this.defaultBuilder = builder; + this.setbuilder(builder, flags); }, this); + this.groups += 1; +}; + +BuilderGroup.prototype.loaded = function() { + return this.groups >= this.expectedGroups; } BuilderGroup.prototype.setup = function() @@ -98,22 +117,29 @@ function associateBuildersWithMaster(builders, master) }); } -function requestBuilderList(builderGroups, builderFilter, master, groupName, groupEnum) +function doXHR(url, onLoad, builderGroups, groupName) { - var onLoad = partial(onBuilderListLoad, builderGroups, builderFilter, master, groupName, groupEnum); var xhr = new XMLHttpRequest(); - var url = master.builderJsonPath(); xhr.open('GET', url, true); xhr.onload = function() { if (xhr.status == 200) onLoad(JSON.parse(xhr.response)); else - onErrorLoadingBuilderList(url); + onErrorLoadingBuilderList(url, builderGroups, groupName); }; - xhr.onerror = function() { onErrorLoadingBuilderList(url); }; + xhr.onerror = function() { onErrorLoadingBuilderList(url, builderGroups, groupName); }; xhr.send(); } +function requestBuilderList(builderGroups, builderFilter, master, groupName, groupEnum, builderGroup) +{ + if (!builderGroups[groupName]) + builderGroups[groupName] = builderGroup; + var onLoad = partial(onBuilderListLoad, builderGroups, builderFilter, master, groupName, groupEnum); + doXHR(master.builderJsonPath(), onLoad, builderGroups, groupName); + builderGroups[groupName].expectedGroups += 1; +} + function isChromiumDepsGpuTestRunner(builder) { return true; @@ -179,56 +205,70 @@ function onBuilderListLoad(builderGroups, builderFilter, master, groupName, grou { var builders = generateBuildersFromBuilderList(Object.keys(json), builderFilter); associateBuildersWithMaster(builders, master); - builderGroups[groupName] = new BuilderGroup(groupEnum, builders); - g_handleBuildersListLoaded(); + builderGroups[groupName].append(builders); + if (builderGroups[groupName].loaded()) + g_handleBuildersListLoaded(); } -function onErrorLoadingBuilderList(url) +function onErrorLoadingBuilderList(url, builderGroups, groupName) { - alert('Could not load list of builders from ' + url + '. Try reloading.'); + builderGroups[groupName].groups += 1; + console.log('Could not load list of builders from ' + url + '. Try reloading.'); } -function loadBuildersList(group, testType) { +function loadBuildersList(groupName, testType) { if (testType == 'gpu_tests') { - switch(group) { + switch(groupName) { case '@DEPS - chromium.org': - requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumDepsGpuTestRunner, CHROMIUM_GPU_BUILDER_MASTER, group, BuilderGroup.DEPS_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.DEPS_WEBKIT); + requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumDepsGpuTestRunner, CHROMIUM_GPU_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); break; case '@DEPS FYI - chromium.org': - requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumDepsFyiGpuTestRunner, CHROMIUM_GPU_FYI_BUILDER_MASTER, group, BuilderGroup.DEPS_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.DEPS_WEBKIT); + requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumDepsFyiGpuTestRunner, CHROMIUM_GPU_FYI_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); break; case '@ToT - chromium.org': - requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumTipOfTreeGpuTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, group, BuilderGroup.TOT_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.TOT_WEBKIT); + requestBuilderList(CHROMIUM_GPU_TESTS_BUILDER_GROUPS, isChromiumTipOfTreeGpuTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.TOT_WEBKIT, builderGroup); break; } } else if (testType == 'layout-tests') { - switch(group) { + switch(groupName) { case '@ToT - chromium.org': - requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitTipOfTreeTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, group, BuilderGroup.TOT_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.TOT_WEBKIT); + requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitTipOfTreeTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.TOT_WEBKIT, builderGroup); break; case '@ToT - webkit.org': - requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isWebkitTestRunner, WEBKIT_BUILDER_MASTER, group, BuilderGroup.TOT_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.TOT_WEBKIT); + requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isWebkitTestRunner, WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.TOT_WEBKIT, builderGroup); break; case '@DEPS - chromium.org': - requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitDepsTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, group, BuilderGroup.DEPS_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.DEPS_WEBKIT); + requestBuilderList(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitDepsTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); break; } } else { - switch(group) { + switch(groupName) { case '@DEPS - chromium.org': - requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsGTestRunner, CHROMIUM_BUILDER_MASTER, group, BuilderGroup.DEPS_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.DEPS_WEBKIT); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsGTestRunner, CHROMIUM_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsGTestRunner, CHROMIUM_WIN_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsGTestRunner, CHROMIUM_MAC_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsGTestRunner, CHROMIUM_LINUX_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); break; case '@DEPS CrOS - chromium.org': - requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsCrosGTestRunner, CHROMIUMOS_BUILDER_MASTER, group, BuilderGroup.DEPS_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.DEPS_WEBKIT); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumDepsCrosGTestRunner, CHROMIUMOS_BUILDER_MASTER, groupName, BuilderGroup.DEPS_WEBKIT, builderGroup); break; case '@ToT - chromium.org': - requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumTipOfTreeGTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, group, BuilderGroup.TOT_WEBKIT); + var builderGroup = new BuilderGroup(BuilderGroup.TOT_WEBKIT); + requestBuilderList(CHROMIUM_GTESTS_BUILDER_GROUPS, isChromiumTipOfTreeGTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.TOT_WEBKIT, builderGroup); break; } } diff --git a/Tools/TestResultServer/static-dashboards/dashboard_base.js b/Tools/TestResultServer/static-dashboards/dashboard_base.js index 34e546e4d..9d47a8f9e 100644 --- a/Tools/TestResultServer/static-dashboards/dashboard_base.js +++ b/Tools/TestResultServer/static-dashboards/dashboard_base.js @@ -542,7 +542,8 @@ function pathToBuilderResultsFile(builderName) } // FIXME: Make the dashboard understand different ports' expectations files. -var CHROMIUM_EXPECTATIONS_URL = 'http://svn.webkit.org/repository/webkit/trunk/LayoutTests/platform/chromium/test_expectations.txt'; +var CHROMIUM_EXPECTATIONS_URL = 'http://svn.webkit.org/repository/webkit/trunk/LayoutTests/platform/chromium/TestExpectations'; +var LEGACY_CHROMIUM_EXPECTATIONS_URL = 'http://svn.webkit.org/repository/webkit/trunk/LayoutTests/platform/chromium/test_expectations.txt'; function requestExpectationsFile() { @@ -552,7 +553,13 @@ function requestExpectationsFile() handleResourceLoad(); }, function() { - console.error('Could not load expectations file from ' + CHROMIUM_EXPECTATIONS_URL); + request(LEGACY_CHROMIUM_EXPECTATIONS_URL, function(xhr) { + g_waitingOnExpectations = false; + g_expectations = xhr.responseText; + handleResourceLoad(); + }, function() { + console.error('Could not load expectations file from ' + CHROMIUM_EXPECTATIONS_URL + ' or ' + LEGACY_CHROMIUM_EXPECTATIONS_URL); + }); }); } diff --git a/Tools/TestResultServer/static-dashboards/flakiness_dashboard.js b/Tools/TestResultServer/static-dashboards/flakiness_dashboard.js index 0e6311a07..59b2ba946 100644 --- a/Tools/TestResultServer/static-dashboards/flakiness_dashboard.js +++ b/Tools/TestResultServer/static-dashboards/flakiness_dashboard.js @@ -39,7 +39,7 @@ var TEST_RESULTS_BASE_PATH = 'http://build.chromium.org/f/chromium/layout_test_r var GPU_RESULTS_BASE_PATH = 'http://chromium-browser-gpu-tests.commondatastorage.googleapis.com/runs/' // FIXME: These platform names should probably be changed to match the directories in LayoutTests/platform -// instead of matching the values we use in the test_expectations.txt file. +// instead of matching the values we use in the TestExpectations file. var PLATFORMS = ['LION', 'SNOWLEOPARD', 'LEOPARD', 'XP', 'VISTA', 'WIN7', 'LUCID', 'APPLE_LION', 'APPLE_LEOPARD', 'APPLE_SNOWLEOPARD', 'APPLE_XP', 'APPLE_WIN7', 'GTK_LINUX', 'QT_LINUX']; var PLATFORM_UNIONS = { 'MAC': ['LEOPARD', 'SNOWLEOPARD', 'LION'], @@ -211,7 +211,7 @@ var g_perBuilderFailures = {}; // but have for that builder. var g_perBuilderWithExpectationsButNoFailures = {}; // Map of builder to arrays of paths that are skipped. This shows the raw -// path used in test_expectations.txt rather than the test path since we +// path used in TestExpectations rather than the test path since we // don't actually have any data here for skipped tests. var g_perBuilderSkippedPaths = {}; // Maps test path to an array of {builder, testResults} objects. @@ -820,7 +820,7 @@ function processMissingAndExtraExpectations(resultsForTest) extraExpectations = expectationsArray.filter( function(element) { // FIXME: Once all the FAIL lines are removed from - // test_expectations.txt, delete all the legacyExpectationsSemantics + // TestExpectations, delete all the legacyExpectationsSemantics // code. if (g_currentState.legacyExpectationsSemantics) { if (element == 'FAIL') { @@ -841,7 +841,7 @@ function processMissingAndExtraExpectations(resultsForTest) for (var i = 0; i < expectationsArray.length; i++) { var expectation = expectationsArray[i]; // FIXME: Once all the FAIL lines are removed from - // test_expectations.txt, delete all the legacyExpectationsSemantics + // TestExpectations, delete all the legacyExpectationsSemantics // code. if (g_currentState.legacyExpectationsSemantics) { if (expectation == 'FAIL') { @@ -1076,7 +1076,7 @@ function htmlForTestsWithExpectationsButNoFailures(builder) var tests = g_perBuilderWithExpectationsButNoFailures[builder]; var skippedPaths = g_perBuilderSkippedPaths[builder]; var showUnexpectedPassesLink = linkHTMLToToggleState('showUnexpectedPasses', 'tests that have not failed in last ' + g_resultsByBuilder[builder].buildNumbers.length + ' runs'); - var showSkippedLink = linkHTMLToToggleState('showSkipped', 'skipped tests in test_expectations.txt'); + var showSkippedLink = linkHTMLToToggleState('showSkipped', 'skipped tests in TestExpectations'); var html = ''; diff --git a/Tools/TestResultServer/static-dashboards/flakiness_dashboard_unittests.js b/Tools/TestResultServer/static-dashboards/flakiness_dashboard_unittests.js index 0da199725..bc2bc4d08 100644 --- a/Tools/TestResultServer/static-dashboards/flakiness_dashboard_unittests.js +++ b/Tools/TestResultServer/static-dashboards/flakiness_dashboard_unittests.js @@ -169,7 +169,7 @@ test('platformAndBuildType', 88, function() { runPlatformAndBuildTypeTest('Chromium Linux Release (Tests)', 'LUCID', 'RELEASE'); runPlatformAndBuildTypeTest('Chromium Mac Release (Tests)', 'SNOWLEOPARD', 'RELEASE'); - // FIXME: These platforms should match whatever we use in the test_expectations.txt format. + // FIXME: These platforms should match whatever we use in the TestExpectations format. runPlatformAndBuildTypeTest('Lion Release (Tests)', 'APPLE_LION', 'RELEASE'); runPlatformAndBuildTypeTest('Lion Debug (Tests)', 'APPLE_LION', 'DEBUG'); runPlatformAndBuildTypeTest('Leopard Intel Release (Tests)', 'APPLE_LEOPARD', 'RELEASE'); @@ -630,18 +630,57 @@ test('addBuilderLoadErrors', 1, function() { test('builderGroupIsToTWebKitAttribute', 2, function() { var dummyMaster = new BuilderMaster('dummy.org', 'http://build.dummy.org'); var testBuilderGroups = { - '@ToT - dummy.org': null, - '@DEPS - dummy.org': null, + '@ToT - dummy.org': new BuilderGroup(BuilderGroup.TOT_WEBKIT), + '@DEPS - dummy.org': new BuilderGroup(BuilderGroup.DEPS_WEBKIT), } - var testJSONData = "{ \"Dummy Builder 1\": null, \"Dummy Builder 2\": null }"; + testBuilderGroups['@ToT - dummy.org'].expectedGroups = 1; + testBuilderGroups['@DEPS - dummy.org'].expectedGroups = 1; + var testJSONData = "{ \"Dummy Builder 1\": null, \"Dummy Builder 2\": null }"; onBuilderListLoad(testBuilderGroups, function() { return true; }, dummyMaster, '@ToT - dummy.org', BuilderGroup.TOT_WEBKIT, JSON.parse(testJSONData)); equal(testBuilderGroups['@ToT - dummy.org'].isToTWebKit, true); - onBuilderListLoad(testBuilderGroups, function() { return true; }, dummyMaster, '@DEPS - dummy.org', BuilderGroup.DEPS_WEBKIT, JSON.parse(testJSONData)); equal(testBuilderGroups['@DEPS - dummy.org'].isToTWebKit, false); }); +test('builderGroupExpectedGroups', 4, function() { + var dummyMaster = new BuilderMaster('dummy.org', 'http://build.dummy.org'); + var testBuilderGroups = { + '@ToT - dummy.org': new BuilderGroup(BuilderGroup.TOT_WEBKIT), + } + testBuilderGroups['@ToT - dummy.org'].expectedGroups = 3; + + var testJSONData = "{ \"Dummy Builder 1\": null }"; + equal(testBuilderGroups['@ToT - dummy.org'].expectedGroups, 3); + onBuilderListLoad(testBuilderGroups, function() { return true; }, dummyMaster, '@ToT - dummy.org', BuilderGroup.TOT_WEBKIT, JSON.parse(testJSONData)); + equal(testBuilderGroups['@ToT - dummy.org'].groups, 1); + var testJSONData = "{ \"Dummy Builder 2\": null }"; + onBuilderListLoad(testBuilderGroups, function() { return true; }, dummyMaster, '@ToT - dummy.org', BuilderGroup.TOT_WEBKIT, JSON.parse(testJSONData)); + equal(testBuilderGroups['@ToT - dummy.org'].groups, 2); + onErrorLoadingBuilderList('http://build.dummy.org', testBuilderGroups, '@ToT - dummy.org'); + equal(testBuilderGroups['@ToT - dummy.org'].groups, 3); +}); + +test('requestBuilderListAddsBuilderGroupEntry', 2, function() { + var testBuilderGroups = { '@ToT - dummy.org': null }; + + var oldDoXHR = doXHR; + try { + doXHR = function() {}; + var builderFilter = null; + var master = { builderJsonPath: function() {} }; + var groupName = '@ToT - dummy.org'; + var groupEnum = null; + var builderGroup = { expectedGroups: 0 }; + requestBuilderList(testBuilderGroups, builderFilter, master, groupName, groupEnum, builderGroup); + + equal(testBuilderGroups['@ToT - dummy.org'], builderGroup); + equal(testBuilderGroups['@ToT - dummy.org'].expectedGroups, 1); + } finally { + doXHR = oldDoXHR; + } +}) + test('sortTests', 4, function() { var test1 = createResultsObjectForTest('foo/test1.html', 'dummyBuilder'); var test2 = createResultsObjectForTest('foo/test2.html', 'dummyBuilder'); diff --git a/Tools/TestResultServer/static-dashboards/run-unittests.html b/Tools/TestResultServer/static-dashboards/run-unittests.html index b7451b5f0..5fd81d5ad 100644 --- a/Tools/TestResultServer/static-dashboards/run-unittests.html +++ b/Tools/TestResultServer/static-dashboards/run-unittests.html @@ -52,9 +52,11 @@ function g_handleBuildersListLoaded() {}; <script> window.location.href = '#useTestData=true'; -var builderGroup = '@ToT - chromium.org'; +var groupName = '@ToT - chromium.org'; var builders = {'Webkit Linux': '', 'Webkit Linux (dbg)': '', 'Webkit Mac10.5': '', 'Webkit Win': ''}; -onBuilderListLoad(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitTipOfTreeTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, builderGroup, BuilderGroup.TOT_WEBKIT, builders); +LAYOUT_TESTS_BUILDER_GROUPS[groupName] = new BuilderGroup(BuilderGroup.TOT_WEBKIT); +LAYOUT_TESTS_BUILDER_GROUPS[groupName].expectedGroups = 4; +onBuilderListLoad(LAYOUT_TESTS_BUILDER_GROUPS, isChromiumWebkitTipOfTreeTestRunner, CHROMIUM_WEBKIT_BUILDER_MASTER, groupName, BuilderGroup.TOT_WEBKIT, builders); initBuilders(); </script> diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj index c519c0231..628a59586 100644 --- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj +++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj @@ -50,6 +50,8 @@ 51FCF7A11534B2A000104491 /* ShouldGoToBackForwardListItem_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51FCF7971534AC6D00104491 /* ShouldGoToBackForwardListItem_Bundle.cpp */; }; 520BCF4C141EB09E00937EA8 /* WebArchive_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 520BCF4A141EB09E00937EA8 /* WebArchive_Bundle.cpp */; }; 520BCF4D141EB09E00937EA8 /* WebArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 520BCF4B141EB09E00937EA8 /* WebArchive.cpp */; }; + 52B8CF9615868CF000281053 /* SetDocumentURI.mm in Sources */ = {isa = PBXBuildFile; fileRef = 52B8CF9515868CF000281053 /* SetDocumentURI.mm */; }; + 52B8CF9815868D9100281053 /* SetDocumentURI.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 52B8CF9415868CF000281053 /* SetDocumentURI.html */; }; 52CB47411448FB9300873995 /* LoadAlternateHTMLStringWithNonDirectoryURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52CB47401448FB9300873995 /* LoadAlternateHTMLStringWithNonDirectoryURL.cpp */; }; 52E5CE4614D21E9D003B2BD8 /* ParentFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4514D21E9D003B2BD8 /* ParentFrame.cpp */; }; 52E5CE4914D21EAB003B2BD8 /* ParentFrame_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */; }; @@ -179,6 +181,7 @@ dstPath = TestWebKitAPI.resources; dstSubfolderSpec = 7; files = ( + 52B8CF9815868D9100281053 /* SetDocumentURI.html in Copy Resources */, B55F11BE15191A0600915916 /* Ahem.ttf in Copy Resources */, B55F11B71517D03300915916 /* attributedStringCustomFont.html in Copy Resources */, 76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */, @@ -254,6 +257,8 @@ 51FCF7981534AC6D00104491 /* ShouldGoToBackForwardListItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShouldGoToBackForwardListItem.cpp; sourceTree = "<group>"; }; 520BCF4A141EB09E00937EA8 /* WebArchive_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebArchive_Bundle.cpp; sourceTree = "<group>"; }; 520BCF4B141EB09E00937EA8 /* WebArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebArchive.cpp; sourceTree = "<group>"; }; + 52B8CF9415868CF000281053 /* SetDocumentURI.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = SetDocumentURI.html; sourceTree = "<group>"; }; + 52B8CF9515868CF000281053 /* SetDocumentURI.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SetDocumentURI.mm; sourceTree = "<group>"; }; 52CB47401448FB9300873995 /* LoadAlternateHTMLStringWithNonDirectoryURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadAlternateHTMLStringWithNonDirectoryURL.cpp; sourceTree = "<group>"; }; 52E5CE4514D21E9D003B2BD8 /* ParentFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame.cpp; sourceTree = "<group>"; }; 52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame_Bundle.cpp; sourceTree = "<group>"; }; @@ -657,6 +662,7 @@ E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */, 517E7DFB15110EA600D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.mm */, 3722C8681461E03E00C45D00 /* RenderedImageFromDOMRange.mm */, + 52B8CF9515868CF000281053 /* SetDocumentURI.mm */, C540F775152E4DA000A40C8C /* SimplifyMarkup.mm */, 3799AD3914120A43005EB0C6 /* StringByEvaluatingJavaScriptFromString.mm */, 37A6895D148A9B50005100FA /* SubresourceErrorCrash.mm */, @@ -669,6 +675,7 @@ C07E6CB013FD737C0038B22B /* Resources */ = { isa = PBXGroup; children = ( + 52B8CF9415868CF000281053 /* SetDocumentURI.html */, B55F11B9151916E600915916 /* Ahem.ttf */, B55F11B01517A2C400915916 /* attributedStringCustomFont.html */, 379028B814FABE49007E6B43 /* acceptsFirstMouse.html */, @@ -883,6 +890,7 @@ E1220DA0155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */, F6F49C6915545C8E0007F39D /* DOMWindowExtensionNoCache.cpp in Sources */, 51E93017156B13E1004C99DF /* WKPageGetScaleFactorNotZero.cpp in Sources */, + 52B8CF9615868CF000281053 /* SetDocumentURI.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.html b/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.html new file mode 100644 index 000000000..ad3714bb0 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.html @@ -0,0 +1,8 @@ +<!doctype html> +<html> + <body> + <p>This is a document to load so that the ObjC [document setDocumentURI:] + API can be tested.</p> + <a href="relativeURL.html" id="relative"></a> + </body> +</html> diff --git a/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.mm b/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.mm new file mode 100644 index 000000000..f077ed95b --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/mac/SetDocumentURI.mm @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include "config.h" +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <wtf/RetainPtr.h> + +#import <WebKit/DOM.h> +#import <WebKit/WebViewPrivate.h> + +@interface SetDocumentURITest : NSObject { +} +@end + +static bool didFinishLoad; + +@implementation SetDocumentURITest + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + didFinishLoad = true; +} +@end + +namespace TestWebKitAPI { + +TEST(WebKit1, SetDocumentURITestFile) +{ + RetainPtr<WebView> webView(AdoptNS, [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); + RetainPtr<SetDocumentURITest> testController(AdoptNS, [SetDocumentURITest new]); + webView.get().frameLoadDelegate = testController.get(); + [[webView.get() mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"SetDocumentURI" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]]; + Util::run(&didFinishLoad); + didFinishLoad = false; + DOMDocument *document = webView.get().mainFrameDocument; + + [document setDocumentURI:@"file:///test"]; + // documentURI set correctly. + EXPECT_WK_STREQ(@"file:///test", [document documentURI]); + // baseURI follows along. + EXPECT_WK_STREQ(@"file:///test", [document baseURI]); +} + +TEST(WebKit1, SetDocumentURITestURL) +{ + RetainPtr<WebView> webView(AdoptNS, [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); + RetainPtr<SetDocumentURITest> testController(AdoptNS, [SetDocumentURITest new]); + webView.get().frameLoadDelegate = testController.get(); + [[webView.get() mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"SetDocumentURI" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]]; + Util::run(&didFinishLoad); + didFinishLoad = false; + DOMDocument *document = webView.get().mainFrameDocument; + + [document setDocumentURI:@"http://example.com/"]; + // documentURI set correctly. + EXPECT_WK_STREQ(@"http://example.com/", [document documentURI]); + // baseURI follows along. + EXPECT_WK_STREQ(@"http://example.com/", [document baseURI]); + // Relative links too. + NSString *result = [webView.get() stringByEvaluatingJavaScriptFromString:@"document.getElementById('relative').href"]; + EXPECT_WK_STREQ(@"http://example.com/relativeURL.html", result); +} + +TEST(WebKit1, SetDocumentURITestString) +{ + RetainPtr<WebView> webView(AdoptNS, [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); + RetainPtr<SetDocumentURITest> testController(AdoptNS, [SetDocumentURITest new]); + webView.get().frameLoadDelegate = testController.get(); + [[webView.get() mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"SetDocumentURI" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]]; + Util::run(&didFinishLoad); + didFinishLoad = false; + DOMDocument *document = webView.get().mainFrameDocument; + + [document setDocumentURI:@"A non-URL string."]; + // documentURI accepts random strings. + EXPECT_WK_STREQ(@"A non-URL string.", [document documentURI]); + // baseURI is empty for non-URL strings. + EXPECT_WK_STREQ(@"", [document baseURI]); +} + +TEST(WebKit1, SetDocumentURITestNull) +{ + RetainPtr<WebView> webView(AdoptNS, [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]); + RetainPtr<SetDocumentURITest> testController(AdoptNS, [SetDocumentURITest new]); + webView.get().frameLoadDelegate = testController.get(); + [[webView.get() mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"SetDocumentURI" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]]; + Util::run(&didFinishLoad); + didFinishLoad = false; + DOMDocument *document = webView.get().mainFrameDocument; + + [document setDocumentURI:nil]; + // documenturi is empty. + EXPECT_WK_STREQ(@"", [document documentURI]); + // baseURI is null as well. + EXPECT_WK_STREQ(@"", [document baseURI]); +} + +} // namespace TestWebKitAPI diff --git a/Tools/TestWebKitAPI/Tests/mac/StringByEvaluatingJavaScriptFromString.mm b/Tools/TestWebKitAPI/Tests/mac/StringByEvaluatingJavaScriptFromString.mm index 1e64fb794..4e3e3ec75 100644 --- a/Tools/TestWebKitAPI/Tests/mac/StringByEvaluatingJavaScriptFromString.mm +++ b/Tools/TestWebKitAPI/Tests/mac/StringByEvaluatingJavaScriptFromString.mm @@ -55,6 +55,10 @@ TEST(WebKit1, StringByEvaluatingJavaScriptFromString) RetainPtr<WebView> webView (AdoptNS, [[WebView alloc] initWithFrame:NSZeroRect frameName:@"" groupName:@""]); + // Test a nil string + NSString *result = [webView.get() stringByEvaluatingJavaScriptFromString:nil]; + EXPECT_WK_STREQ(@"", result); + for (id expression in expressions.get()) { NSString *expectedResult = [expressions.get() objectForKey:expression]; NSString *result = [webView.get() stringByEvaluatingJavaScriptFromString:expression]; diff --git a/Tools/TestWebKitAPI/mac/InjectedBundleControllerMac.mm b/Tools/TestWebKitAPI/mac/InjectedBundleControllerMac.mm index 65891ce81..4dd4ef020 100644 --- a/Tools/TestWebKitAPI/mac/InjectedBundleControllerMac.mm +++ b/Tools/TestWebKitAPI/mac/InjectedBundleControllerMac.mm @@ -40,7 +40,7 @@ void InjectedBundleController::platformInitialize() NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:4], @"AppleAntiAliasingThreshold", [NSNumber numberWithInteger:0], @"AppleFontSmoothing", -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(CHROMIUM) [NSNumber numberWithBool:NO], @"NSScrollAnimationEnabled", #else [NSNumber numberWithBool:NO], @"AppleScrollAnimationEnabled", diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl index 819ea4600..b5766c01c 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl @@ -66,7 +66,6 @@ module WTR { // Special DOM functions. void clearBackForwardList(); object computedStyleIncludingVisitedInfo(in object element); - DOMString counterValueForElementById(in DOMString elementId); void execCommand(in DOMString name, in DOMString argument); boolean isCommandEnabled(in DOMString name); DOMString markerTextForListItem(in object element); diff --git a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp index cca4de681..df9dfa407 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp @@ -52,40 +52,6 @@ namespace WTR { // Eventually it should be changed to match. const double LayoutTestController::waitToDumpWatchdogTimerInterval = 6; -static JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName) -{ - if (!object) - return 0; - JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); - JSValueRef exception; - return JSObjectGetProperty(context, object, propertyNameString.get(), &exception); -} - -static JSObjectRef propertyObject(JSContextRef context, JSObjectRef object, const char* propertyName) -{ - JSValueRef value = propertyValue(context, object, propertyName); - if (!value || !JSValueIsObject(context, value)) - return 0; - return const_cast<JSObjectRef>(value); -} - -static JSObjectRef getElementById(WKBundleFrameRef frame, JSStringRef elementId) -{ - JSContextRef context = WKBundleFrameGetJavaScriptContext(frame); - JSObjectRef document = propertyObject(context, JSContextGetGlobalObject(context), "document"); - if (!document) - return 0; - JSValueRef getElementById = propertyObject(context, document, "getElementById"); - if (!getElementById || !JSValueIsObject(context, getElementById)) - return 0; - JSValueRef elementIdValue = JSValueMakeString(context, elementId); - JSValueRef exception; - JSValueRef element = JSObjectCallAsFunction(context, const_cast<JSObjectRef>(getElementById), document, 1, &elementIdValue, &exception); - if (!element || !JSValueIsObject(context, element)) - return 0; - return const_cast<JSObjectRef>(element); -} - PassRefPtr<LayoutTestController> LayoutTestController::create() { return adoptRef(new LayoutTestController); @@ -254,16 +220,6 @@ JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSValueRef el return value; } -JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef elementId) -{ - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); - JSObjectRef element = getElementById(mainFrame, elementId); - if (!element) - return 0; - WKRetainPtr<WKStringRef> value(AdoptWK, WKBundleFrameCopyCounterValue(mainFrame, const_cast<JSObjectRef>(element))); - return toJS(value); -} - JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSValueRef element) { WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); @@ -459,6 +415,7 @@ void LayoutTestController::clearBackForwardList() void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) { setProperty(context, windowObject, "layoutTestController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); + setProperty(context, windowObject, "testRunner", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); } void LayoutTestController::showWebInspector() diff --git a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h index 945a6609e..c0500f78e 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h +++ b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h @@ -100,7 +100,6 @@ public: // Special DOM functions. JSValueRef computedStyleIncludingVisitedInfo(JSValueRef element); - JSRetainPtr<JSStringRef> counterValueForElementById(JSStringRef elementId); void clearBackForwardList(); void execCommand(JSStringRef name, JSStringRef argument); bool isCommandEnabled(JSStringRef name); diff --git a/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm b/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm index d964cb6d3..e5499b80a 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm +++ b/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm @@ -34,7 +34,7 @@ void InjectedBundle::platformInitialize(WKTypeRef) NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:4], @"AppleAntiAliasingThreshold", [NSNumber numberWithInteger:0], @"AppleFontSmoothing", -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) && !PLATFORM(CHROMIUM) [NSNumber numberWithBool:NO], @"NSScrollAnimationEnabled", #else [NSNumber numberWithBool:NO], @"AppleScrollAnimationEnabled", diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp index ffdc2cc66..fd6885793 100644 --- a/Tools/WebKitTestRunner/TestController.cpp +++ b/Tools/WebKitTestRunner/TestController.cpp @@ -409,6 +409,8 @@ void TestController::initialize(int argc, const char* argv[]) 0, // willGoToBackForwardListItem 0, // interactionOccurredWhileProcessUnresponsive 0, // pluginDidFail + 0, // didReceiveIntentForFrame + 0, // registerIntentServiceForFrame }; WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient); } diff --git a/Tools/WinLauncher/WinLauncher.cpp b/Tools/WinLauncher/WinLauncher.cpp index 096bd9634..0e47f9996 100644 --- a/Tools/WinLauncher/WinLauncher.cpp +++ b/Tools/WinLauncher/WinLauncher.cpp @@ -142,6 +142,20 @@ exit: return 0; } +HRESULT STDMETHODCALLTYPE WinLauncherWebHost::didFailProvisionalLoadWithError(IWebView*, IWebError *error, IWebFrame*) +{ + BSTR errorDescription = 0; + HRESULT hr = error->localizedDescription(&errorDescription); + if (FAILED(hr)) + errorDescription = L"Failed to load page and to localize error description."; + + ::MessageBoxW(0, static_cast<LPCWSTR>(errorDescription), L"Error", MB_APPLMODAL | MB_OK); + if (SUCCEEDED(hr)) + SysFreeString(errorDescription); + + return S_OK; +} + HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject) { *ppvObject = 0; diff --git a/Tools/WinLauncher/WinLauncher.h b/Tools/WinLauncher/WinLauncher.h index 4c8143f72..04c2b493b 100644 --- a/Tools/WinLauncher/WinLauncher.h +++ b/Tools/WinLauncher/WinLauncher.h @@ -50,7 +50,7 @@ public: virtual HRESULT STDMETHODCALLTYPE didFailProvisionalLoadWithError( /* [in] */ IWebView *webView, /* [in] */ IWebError *error, - /* [in] */ IWebFrame *frame) { return S_OK; } + /* [in] */ IWebFrame*); virtual HRESULT STDMETHODCALLTYPE didCommitLoadForFrame( /* [in] */ IWebView *webView, diff --git a/Tools/efl/jhbuild.modules b/Tools/efl/jhbuild.modules index 11ecb090e..14faf784c 100644 --- a/Tools/efl/jhbuild.modules +++ b/Tools/efl/jhbuild.modules @@ -110,20 +110,20 @@ <dependencies> <dep package="libffi"/> </dependencies> - <branch module="/pub/GNOME/sources/glib/2.32/glib-2.32.2.tar.xz" version="2.32.2" + <branch module="/pub/GNOME/sources/glib/2.33/glib-2.33.2.tar.xz" version="2.33.2" repo="ftp.gnome.org" - hash="sha256:b1764abf00bac96e0e93e29fb9715ce75f3583579acac40648e18771d43d6136" - md5sum="5bfdb6197afb90e4dbc7b1bb98f0eae0"/> + hash="sha256:b7163e9f159775d13ecfb433d67c3f0883e0e518e85b2e970d4ad9773d7cd0b4" + md5sum="06ef0099fed22afcf34ade39ddff9a5b"/> </autotools> <autotools id="glib-networking"> <dependencies> <dep package="gnutls"/> </dependencies> - <branch module="/pub/GNOME/sources/glib-networking/2.31/glib-networking-2.31.2.tar.xz" version="2.31.2" + <branch module="/pub/GNOME/sources/glib-networking/2.33/glib-networking-2.33.2.tar.xz" version="2.33.2" repo="ftp.gnome.org" - hash="sha256:03e3a2881d2626d1206e72972531661037fe0d32e745bf9b2f63c0d6f5e32a9c" - md5sum="b649b457bd9fd5e0e9b9c4dcb1a74a37"/> + hash="e298cff3935eb752be290bbf734e457f1870bdb5370ee292606e6040a82074e7" + md5sum="5abb364f2a0babe2ec1e3a6d59f69043"/> </autotools> <autotools id="gnutls" @@ -143,9 +143,9 @@ <dependencies> <dep package="glib-networking"/> </dependencies> - <branch module="libsoup" version="2.38.1" + <branch module="libsoup" version="2.39.2" repo="git.gnome.org" - tag="LIBSOUP_2_38_1"/> + tag="LIBSOUP_2_39_2"/> </autotools> <autotools id="fontconfig" autogen-sh="configure"> diff --git a/Tools/efl/jhbuildrc b/Tools/efl/jhbuildrc index 2ef84c776..ffa6df9d9 100644 --- a/Tools/efl/jhbuildrc +++ b/Tools/efl/jhbuildrc @@ -61,6 +61,10 @@ addpath('PKG_CONFIG_PATH', os.path.join(os.sep, 'usr', 'share', 'pkgconfig')) addpath('XDG_DATA_DIRS', '/usr/share') addpath('XDG_CONFIG_DIRS', '/etc/xdg') -addpath('CMAKE_PREFIX_PATH', prefix) +# Avoid overlapping search path CMAKE warning on 64bit systems. +if (use_lib64): + addpath('CMAKE_PREFIX_PATH', os.path.join(os.sep, prefix, 'lib64')) +else: + addpath('CMAKE_PREFIX_PATH', prefix) partial_build = False diff --git a/Tools/gtk/generate-gtkdoc b/Tools/gtk/generate-gtkdoc index cc33c4824..88e62e750 100755 --- a/Tools/gtk/generate-gtkdoc +++ b/Tools/gtk/generate-gtkdoc @@ -88,7 +88,7 @@ def get_webkit2_options(): 'module_name' : 'webkit2gtk', 'doc_dir' : src_path('docs'), 'output_dir' : common.build_path('Documentation', 'webkit2gtk'), - 'source_dirs' : [src_path()], + 'source_dirs' : [src_path(), derived_sources_path('webkit2gtk', 'webkit2')], 'cflags' : ' -I' + derived_sources_path('webkit2gtk', 'include') + \ ' -I' + derived_sources_path('webkit2gtk') + \ ' -I' + derived_sources_path('include') + \ @@ -98,6 +98,9 @@ def get_webkit2_options(): 'ignored_files': glob.glob(src_path('*Private.h')) + \ glob.glob(src_path('*Client*')) + \ glob.glob(src_path('WebKitWebViewBaseAccessible.*')) + \ + glob.glob(src_path('WebKitGeolocationProvider.*')) + \ + glob.glob(derived_sources_path('webkit2gtk', 'webkit2', 'WebKitMarshal.*')) + \ + glob.glob(derived_sources_path('webkit2gtk', 'webkit2', 'WebKitEnumTypes.*')) + \ glob.glob(src_path('tests/*.h')) }) return options diff --git a/Tools/gtk/jhbuild.modules b/Tools/gtk/jhbuild.modules index c93e39f9f..3306d74ee 100644 --- a/Tools/gtk/jhbuild.modules +++ b/Tools/gtk/jhbuild.modules @@ -131,10 +131,10 @@ <dependencies> <dep package="libffi"/> </dependencies> - <branch module="/pub/GNOME/sources/glib/2.32/glib-2.32.0.tar.xz" version="2.32.0" + <branch module="/pub/GNOME/sources/glib/2.33/glib-2.33.2.tar.xz" version="2.33.2" repo="ftp.gnome.org" - hash="sha256:cde9d9f25ed648069c547e323897ad9379974e1f936b4477fa51bcf1bb261ae4" - md5sum="c5fa76fbf9184d20dfb04af66b598190"/> + hash="sha256:b7163e9f159775d13ecfb433d67c3f0883e0e518e85b2e970d4ad9773d7cd0b4" + md5sum="06ef0099fed22afcf34ade39ddff9a5b"/> </autotools> <autotools id="glib-networking"> @@ -142,10 +142,10 @@ <dep package="glib"/> <dep package="gnutls"/> </dependencies> - <branch module="/pub/GNOME/sources/glib-networking/2.31/glib-networking-2.31.2.tar.xz" version="2.31.2" + <branch module="/pub/GNOME/sources/glib-networking/2.33/glib-networking-2.33.2.tar.xz" version="2.33.2" repo="ftp.gnome.org" - hash="sha256:03e3a2881d2626d1206e72972531661037fe0d32e745bf9b2f63c0d6f5e32a9c" - md5sum="b649b457bd9fd5e0e9b9c4dcb1a74a37"/> + hash="sha256:e298cff3935eb752be290bbf734e457f1870bdb5370ee292606e6040a82074e7" + md5sum="5abb364f2a0babe2ec1e3a6d59f69043"/> </autotools> <autotools id="gnutls" @@ -161,9 +161,9 @@ <dependencies> <dep package="glib-networking"/> </dependencies> - <branch module="libsoup" version="2.38.1" + <branch module="libsoup" version="2.39.2" repo="git.gnome.org" - tag="LIBSOUP_2_38_1"/> + tag="LIBSOUP_2_39_2"/> </autotools> <autotools id="fontconfig" autogen-sh="configure"> diff --git a/Tools/gtk/run-api-tests b/Tools/gtk/run-api-tests index 62957fa21..37939ca25 100755 --- a/Tools/gtk/run-api-tests +++ b/Tools/gtk/run-api-tests @@ -88,7 +88,10 @@ class TestRunner: 85037), SkippedTest("TestWebKitAPI/WebKit2/TestMouseMoveAfterCrash", "Test is flaky", - 85066) + 85066), + SkippedTest("TestWebKitAPI/WTF/TestHashMap", + "Test fails", + 88419) ] def __init__(self, options, tests=[]): diff --git a/Tools/qmake/config.tests/libwebp/libwebp.cpp b/Tools/qmake/config.tests/libwebp/libwebp.cpp new file mode 100644 index 000000000..974603d3b --- /dev/null +++ b/Tools/qmake/config.tests/libwebp/libwebp.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) Zoltan Horvath (zoltan@webkit.org) 2012 University of Szeged. + * + * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "webp/decode.h" + +int main(int, char**) +{ + WebPDecoderConfig config; + WebPInitDecoderConfig(&config); + return 0; +} diff --git a/Tools/qmake/config.tests/libwebp/libwebp.pro b/Tools/qmake/config.tests/libwebp/libwebp.pro new file mode 100644 index 000000000..925725270 --- /dev/null +++ b/Tools/qmake/config.tests/libwebp/libwebp.pro @@ -0,0 +1,3 @@ +SOURCES = libwebp.cpp +OBJECTS_DIR = obj +LIBS += -lwebp diff --git a/Tools/qmake/config.tests/libzlib/libzlib.cpp b/Tools/qmake/config.tests/libzlib/libzlib.cpp new file mode 100644 index 000000000..6beab57dc --- /dev/null +++ b/Tools/qmake/config.tests/libzlib/libzlib.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <zlib.h> + +int main(int, char**) +{ + (void)zlibVersion(); + return 0; +} diff --git a/Tools/qmake/config.tests/libzlib/libzlib.pro b/Tools/qmake/config.tests/libzlib/libzlib.pro new file mode 100644 index 000000000..816a455c4 --- /dev/null +++ b/Tools/qmake/config.tests/libzlib/libzlib.pro @@ -0,0 +1,3 @@ +SOURCES = libzlib.cpp +OBJECTS_DIR = obj +LIBS += -lz diff --git a/Tools/qmake/mkspecs/features/default_pre.prf b/Tools/qmake/mkspecs/features/default_pre.prf index 01b8f2857..31c5ef996 100644 --- a/Tools/qmake/mkspecs/features/default_pre.prf +++ b/Tools/qmake/mkspecs/features/default_pre.prf @@ -23,9 +23,9 @@ isEmpty(pro_file): CONFIG += recursive_include } # Resolve root directories for source and build -ROOT_WEBKIT_DIR = $$replace(IN_PWD, /Tools/qmake/mkspecs/features,) +ROOT_WEBKIT_DIR = $$replace(IN_PWD, /Tools/qmake/mkspecs/features$,) WEBKIT_SUBDIR = $$replace(_PRO_FILE_PWD_, $${ROOT_WEBKIT_DIR},) -ROOT_BUILD_DIR = $$replace(OUT_PWD, $$WEBKIT_SUBDIR,) +ROOT_BUILD_DIR = $$replace(OUT_PWD, $${WEBKIT_SUBDIR}$,) # We want the QtWebKit API forwarding includes to live in the root build dir, # except when we are running the config.tests in Tools/qmake. diff --git a/Tools/qmake/mkspecs/features/features.prf b/Tools/qmake/mkspecs/features/features.prf index 2d385cae6..29d41f033 100644..100755 --- a/Tools/qmake/mkspecs/features/features.prf +++ b/Tools/qmake/mkspecs/features/features.prf @@ -73,13 +73,16 @@ haveQt(5) { haveQt(5):contains(config_test_libxslt, yes): DEFINES += ENABLE_XSLT=1 } -!contains(DEFINES, WTF_USE_QT_IMAGE_DECODER=.): DEFINES += WTF_USE_QT_IMAGE_DECODER=1 +# We need libzlib config test to determine to use enable websocket extension or not +!contains(DEFINES, WTF_USE_ZLIB=.) { + haveQt(5):contains(config_test_libzlib, yes): DEFINES += WTF_USE_ZLIB=1 +} # Tiled Backing Store support !contains(DEFINES, WTF_USE_TILED_BACKING_STORE=.): DEFINES += WTF_USE_TILED_BACKING_STORE=1 # Turn on legacy viewport adaption -!contains(DEFINES, WTF_USE_LEGACY_VIEWPORT_ADAPTION=.): DEFINES += WTF_USE_LEGACY_VIEWPORT_ADAPTION=1 +!contains(DEFINES, ENABLE_LEGACY_VIEWPORT_ADAPTION=.): DEFINES += ENABLE_LEGACY_VIEWPORT_ADAPTION=1 # Nescape plugins support (NPAPI) !contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=.) { diff --git a/Tools/qmake/mkspecs/features/features.pri b/Tools/qmake/mkspecs/features/features.pri index 4de5c64cb..a4b2c377e 100644 --- a/Tools/qmake/mkspecs/features/features.pri +++ b/Tools/qmake/mkspecs/features/features.pri @@ -19,6 +19,8 @@ FEATURE_DEFAULTS = \ ENABLE_BATTERY_STATUS=0 \ ENABLE_BLOB=1 \ ENABLE_CHANNEL_MESSAGING=1 \ + ENABLE_CSP_NEXT=0 \ + ENABLE_CSS_BOX_DECORATION_BREAK=1 \ ENABLE_CSS_EXCLUSIONS=1 \ ENABLE_CSS_FILTERS=1 \ ENABLE_CSS_GRID_LAYOUT=0 \ @@ -93,6 +95,7 @@ FEATURE_DEFAULTS = \ ENABLE_TOUCH_ADJUSTMENT=1 \ ENABLE_TOUCH_EVENTS=1 \ ENABLE_TOUCH_ICON_LOADING=0 \ + ENABLE_UNDO_MANAGER=0 \ ENABLE_VIBRATION=0 \ ENABLE_VIDEO=0 \ ENABLE_VIDEO_TRACK=0 \ diff --git a/Tools/qmake/mkspecs/features/unix/default_post.prf b/Tools/qmake/mkspecs/features/unix/default_post.prf index 32646ddc0..82e254eee 100644 --- a/Tools/qmake/mkspecs/features/unix/default_post.prf +++ b/Tools/qmake/mkspecs/features/unix/default_post.prf @@ -13,7 +13,7 @@ linux-g++*:isEqual(QT_ARCH,i386) { } # Treat warnings as errors on x86/Linux/GCC -qt_developer_build:linux-g++* { +!production_build:linux-g++* { isEqual(QT_ARCH,x86_64)|isEqual(QT_ARCH,i386): QMAKE_CXXFLAGS += -Werror greaterThan(QT_GCC_MAJOR_VERSION, 3):greaterThan(QT_GCC_MINOR_VERSION, 5) { !contains(QMAKE_CXXFLAGS, -std=(c|gnu)\\+\\+(0x|11)) { diff --git a/Tools/qmake/sync.profile b/Tools/qmake/sync.profile index c073460b1..136f9961c 100644 --- a/Tools/qmake/sync.profile +++ b/Tools/qmake/sync.profile @@ -4,6 +4,8 @@ gccdepends => {}, libpng => {}, libjpeg => {}, + libwebp => {}, libxml2 => {}, libxslt => {}, + libzlib => {}, ); |