diff options
author | Kristian Monsen <kristianm@google.com> | 2010-09-30 15:42:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-10-07 10:59:29 +0100 |
commit | bec39347bb3bb5bf1187ccaf471d26247f28b585 (patch) | |
tree | 56bdc4c2978fbfd3d79d0d36d5d6c640ecc09cc8 /WebKitTools | |
parent | 90b7966e7815b262cd19ac25f03aaad9b21fdc06 (diff) | |
download | external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.zip external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.tar.gz external_webkit-bec39347bb3bb5bf1187ccaf471d26247f28b585.tar.bz2 |
Merge WebKit at r68651 : Initial merge by git.
Change-Id: I3d6bff59f17eedd6722723354f386fec9be8ad12
Diffstat (limited to 'WebKitTools')
194 files changed, 6794 insertions, 1437 deletions
diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json index 54a0dfe..2a4a351 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json @@ -16,6 +16,7 @@ { "name": "apple-macpro-2", "platform": "mac-snowleopard" }, { "name": "apple-macpro-3", "platform": "mac-snowleopard" }, { "name": "apple-macpro-4", "platform": "mac-leopard" }, + { "name": "apple-macpro-5", "platform": "mac-leopard" }, { "name": "apple-windows-1", "platform": "win"}, { "name": "apple-windows-2", "platform": "win"}, @@ -64,7 +65,7 @@ }, { "name": "Leopard Intel Debug (Tests)", "type": "Test", "builddir": "leopard-intel-debug-tests", "platform": "mac-leopard", "configuration": "debug", "architectures": ["i386"], - "slavenames": ["apple-xserve-3", "test-slave"] + "slavenames": ["apple-xserve-3", "test-slave", "apple-macpro-5"] }, { "name": "SnowLeopard Intel Release (Build)", "type": "Build", "builddir": "snowleopard-intel-release", "platform": "mac-snowleopard", "configuration": "release", "architectures": ["x86_64"], diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg index aca3c65..d5cd6fb 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg @@ -317,6 +317,14 @@ class RunWebKit2Tests(RunWebKitTests): return RunWebKitTests.start(self) +class RunChromiumWebKitUnitTests(shell.Test): + name = "webkit-unit-tests" + description = ["webkit-unit-tests running"] + descriptionDone = ["webkit-unit-tests"] + command = ["perl", "./WebKitTools/Scripts/run-chromium-webkit-unit-tests", + WithProperties("--%(configuration)s")] + + class ArchiveTestResults(shell.ShellCommand): command = ["python", "./WebKitTools/BuildSlaveSupport/test-result-archive", WithProperties("--platform=%(platform)s"), WithProperties("--%(configuration)s"), "archive"] @@ -399,6 +407,8 @@ class BuildAndTestFactory(Factory): self.addStep(CompileWebKit) if not platform.startswith("chromium"): self.addStep(RunJavaScriptCoreTests) + if platform.startswith("chromium"): + self.addStep(RunChromiumWebKitUnitTests) self.addStep(self.TestClass) # Tiger's Python 2.3 is too old. WebKit Python requires 2.5+. # Sadly we have no way to detect the version on the slave from here. diff --git a/WebKitTools/CMakeListsEfl.txt b/WebKitTools/CMakeListsEfl.txt index b9086ac..732b4b3 100644 --- a/WebKitTools/CMakeListsEfl.txt +++ b/WebKitTools/CMakeListsEfl.txt @@ -1,5 +1,4 @@ SET(EWebLauncher_SOURCES - ${WebKit_THEME} ${WEBKITTOOLS_DIR}/EWebLauncher/main.c ) @@ -50,6 +49,10 @@ IF (WTF_USE_CURL) LIST(APPEND EWebLauncher_LINK_FLAGS ${CURL_LDFLAGS}) ENDIF () +# Override data directory. We always want to get a fresh theme. +REMOVE_DEFINITIONS(-DDATA_DIR=\"${DATA_DIR}\") +ADD_DEFINITIONS(-DDATA_DIR=\"${BUILD_DATA_DIR}\") + INCLUDE_DIRECTORIES(${EWebLauncher_INCLUDE_DIRECTORIES}) ADD_EXECUTABLE(Programs/EWebLauncher ${EWebLauncher_SOURCES}) TARGET_LINK_LIBRARIES(Programs/EWebLauncher ${EWebLauncher_LIBRARIES}) diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.css b/WebKitTools/CSSTestSuiteHarness/harness/harness.css new file mode 100644 index 0000000..8c0e7d1 --- /dev/null +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.css @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2010 Apple 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. + */ + +body { + font-family: Helvetica, sans-serif; + background-color: #DDD; +} + +.controls { + border: 1px solid black; + width: 300px; + height: 660px; + float: left; + font-size: smaller; + padding: 4px; +} + +.controls div { + margin: 4px; +} + +.controls select { + width: 100%; +} + +.details > div { + margin: 4px 0; +} + +.actions { + margin-left: 320px; + border: 1px solid black; + font-size: smaller; + height: 30px; + padding: 4px; + margin-bottom: 8px; +} + +.actions button { + font-size: 13px; + width: 5em; +} + +.note { + font-size: 10px; + color: gray; +} +.action-buttons { + float: right; +} + +#test-content { + margin-left: 320px; + height: 612px; + border: 1px solid black; + padding: 4px; + background-color: white; +} + +.info > div { + margin: 6px 0; +} + +.info .title { + font-size: larger; + font-weight: bold; +} + +.info .url { + font-family: monospace; +} + +.info .assertion, .info .flags { + font-size: smaller; +} + +#test-content iframe { + border: 1px solid gray; + margin: 2px; +} + +#test-content h2 { + font-size: 11pt; + margin: 2px 0 2px 0; + color: darkgray; +} + +#test-list > option.untested { + +} + +#test-list > option.completed { + color: gray; +} + +#test-content.with-ref { +} + +.frame-wrapper { + +} + +.frame-wrapper iframe { + width: 98%; + height: 460px; +} + +.frame-wrapper { + height: 500px; + width: 99%; + display: inline-block; +} + +.with-ref > .frame-wrapper { + width: 49%; +} + +#ref-wrapper { + height: 500px; + width: 49%; + display: none; +} + +.with-ref > #ref-wrapper { + display: inline-block; +} + +.results { + border: 1px solid black; + padding: 4px; + margin-top: 6px; +} + +#output { + border: 1px solid black; + font-size: smaller; + height: 220px; + margin: 4px; + padding: 4px; + overflow-y: auto; + background-color: white; +} + +#output > p { + margin: 0; +} +#output .pass { + color: green; +} + +#output .fail { + color: red; +} + +#output .skipped { + color: orange; +} + +#output .invalid { + background: red; +} + +.output-options { + float: right; + border: 1px solid black; + width: 200px; + height: 220px; + margin: 4px; + padding: 4px; + font-size: smaller; +} + +.output-options select { + width: 90%; +} + +.summary { + font-size: smaller; + margin: 4px; +} + +.summary .label { + display: inline-block; + min-width: 5em; + margin: 0; +} + +.summary span { + display: inline-block; + min-width: 3em; + text-align: right; + margin: 0; +} + +.summary td { + text-align: right; + padding: 4px; +} diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.html b/WebKitTools/CSSTestSuiteHarness/harness/harness.html new file mode 100644 index 0000000..6bd47e5 --- /dev/null +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.html @@ -0,0 +1,206 @@ +<!-- +/* + * Copyright (C) 2010 Apple 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. + */ +--> + +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <title>CSS 2.1 Test Harness</title> + <link rel="stylesheet" href="harness.css" type="text/css" media="screen" charset="utf-8"> + + <script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript" charset="utf-8"></script> + <script src="harness.js" type="text/javascript" charset="utf-8"></script> + + <script type="text/javascript" charset="utf-8"> + var gTestSuite; + function setupTests() + { + gTestSuite = new TestSuite(); + } + + window.addEventListener('load', setupTests, false); + + function skipTest() + { + gTestSuite.skipTest(document.getElementById('skip-reason').value); + } + + function invalidTest() + { + gTestSuite.invalidTest(); + } + + function failTest() + { + gTestSuite.failTest(); + } + + function passTest() + { + gTestSuite.passTest(); + } + + function formatChanged() + { + var newFormat; + if (document.harness.format.html4.checked) + newFormat = 'html4'; + else + newFormat = 'xhtml1'; + gTestSuite.formatChanged(newFormat); + } + + function testSelected() + { + var list = document.getElementById('test-list') + if (list.selectedIndex >= 0) + gTestSuite.goToTestIndex(list.selectedIndex); + else + gTestSuite.clearTest(); + } + + function resultsPopupChanged(popup) + { + gTestSuite.resultsPopupChanged(popup.selectedIndex); + } + + function doExport() + { + gTestSuite.exportResults(document.getElementById('results-popup').selectedIndex); + } + + /* + This conflicts badly with key handling in selects. + function keyHandler(event) + { + var charCode = String.fromCharCode(event.keyCode); + window.console.log('keyHandler') + switch (charCode) { + case 'P': + passTest(); + break; + + case 'F': + failTest(); + break; + + case 'I': + invalidTest(); + break; + + case 'S': + skipTest(); + break; + } + + event.stopPropagation(); + event.preventDefault(); + } + + document.addEventListener('keyup', keyHandler, false); + */ + </script> + +</head> +<body> + + <div class="controls"> + <form name="harness" onsubmit="return false;"> + <select id="chapters"> + <option>Test category</option> + </select> + <div class="progress"> + <div><span id="test-index">1</span> of <span id="chapter-test-count">200</span> unique tests</div> + </div> + <div class="details"> + <div class="name"> + <div class="test-type"> + <input type="radio" name="format" id="html4" onchange="formatChanged()" checked><label for="html4">HTML4</label><br> + <input type="radio" name="format" id="xhtml1" onchange="formatChanged()"><label for="xhtml1">XHTML1</label> + </div> + </div> + </div> + + <div> + <select id="test-list" size="40" onchange="testSelected()"></select> + </div> + </form> + </div> + + <div class="actions"> + <span>Skip reason:</span> <input type="text" id="skip-reason" size="50"> + <button onclick="skipTest()" accesskey="s">Skip</button> + <span class="note">Use <i>Control-Option-letter</i> to trigger buttons via the keyboard.</span> + <div class="action-buttons"> + <button onclick="invalidTest()" accesskey="i">Invalid</button> + <button onclick="failTest()" accesskey="f">Fail</button> + <button onclick="passTest()" accesskey="p">Pass</button> + </div> + </div> + <div id="test-content"> + <div class="info"> + <div class="title">Title: <span id="test-title"></span></div> + <div class="url">URL: <span id="test-url"></span></div> + <div class="assertion">Assertion: <span id="test-assertion"></span></div> + <div class="flags">Flags: <span id="test-flags"></span></div> + </div> + + <div id="test-wrapper" class="frame-wrapper"> + <h2>Test</h2> + <iframe id="test-frame"></iframe> + </div> + <div id="ref-wrapper" class="frame-wrapper"> + <h2>Reference</h2> + <iframe id="ref-frame"></iframe> + </div> + </div> + + <div class="results"> + <div class="output-options"> + <p>Show results for:</p> + <select id="results-popup" onchange="resultsPopupChanged(this)"> + </select> + <button id="export-button" onclick="doExport()">Export...</button> + </div> + <div id="output"></div> + <div class="summary"> + <table> + <tr> + <th></th><th>Passed</th><th>Failed</th><th>Skipped</th><th>Invalid</th><th>Tested</th><th>Total</th><th>% done</th> + </tr> + <tr> + <td class="label">HTML4:</td><td id="h-passed"></td><td id="h-failed"></td><td id="h-skipped"></td><td id="h-invalid"></td><td id="h-tested"></td><td id="h-total"></td><td id="h-percent"></td> + </tr> + <tr> + <td class="label">XHTML1:</td><td id="x-passed"></td><td id="x-failed"></td><td id="x-skipped"></td><td id="x-invalid"></td><td id="x-tested"></td><td id="x-total"></td><td id="x-percent"></td> + </tr> + </table> + </div> + </div> + +</body> +</html>
\ No newline at end of file diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.js b/WebKitTools/CSSTestSuiteHarness/harness/harness.js new file mode 100644 index 0000000..95262af --- /dev/null +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.js @@ -0,0 +1,1314 @@ +/* + * Copyright (C) 2010 Apple 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. + */ + +// requires jQuery + +const kTestSuiteVersion = '20100917'; +const kTestSuiteHome = '../' + kTestSuiteVersion + '/'; +const kTestInfoDataFile = 'testinfo.data'; + +const kChapterData = [ + { + 'file' : 'about.html', + 'title' : 'About the CSS 2.1 Specification', + }, + { + 'file' : 'intro.html', + 'title' : 'Introduction to CSS 2.1', + }, + { + 'file' : 'conform.html', + 'title' : 'Conformance: Requirements and Recommendations', + }, + { + 'file' : "syndata.html", + 'title' : 'Syntax and basic data types', + }, + { + 'file' : 'selector.html' , + 'title' : 'Selectors', + }, + { + 'file' : 'cascade.html', + 'title' : 'Assigning property values, Cascading, and Inheritance', + }, + { + 'file' : 'media.html', + 'title' : 'Media types', + }, + { + 'file' : 'box.html' , + 'title' : 'Box model', + }, + { + 'file' : 'visuren.html', + 'title' : 'Visual formatting model', + }, + { + 'file' :'visudet.html', + 'title' : 'Visual formatting model details', + }, + { + 'file' : 'visufx.html', + 'title' : 'Visual effects', + }, + { + 'file' : 'generate.html', + 'title' : 'Generated content, automatic numbering, and lists', + }, + { + 'file' : 'page.html', + 'title' : 'Paged media', + }, + { + 'file' : 'colors.html', + 'title' : 'Colors and Backgrounds', + }, + { + 'file' : 'fonts.html', + 'title' : 'Fonts', + }, + { + 'file' : 'text.html', + 'title' : 'Text', + }, + { + 'file' : 'tables.html', + 'title' : 'Tables', + }, + { + 'file' : 'ui.html', + 'title' : 'User interface', + }, + { + 'file' : 'aural.html', + 'title' : 'Appendix A. Aural style sheets', + }, + { + 'file' : 'refs.html', + 'title' : 'Appendix B. Bibliography', + }, + { + 'file' : 'changes.html', + 'title' : 'Appendix C. Changes', + }, + { + 'file' : 'sample.html', + 'title' : 'Appendix D. Default style sheet for HTML 4', + }, + { + 'file' : 'zindex.html', + 'title' : 'Appendix E. Elaborate description of Stacking Contexts', + }, + { + 'file' : 'propidx.html', + 'title' : 'Appendix F. Full property table', + }, + { + 'file' : 'grammar.html', + 'title' : 'Appendix G. Grammar of CSS', + }, + { + 'file' : 'other.html', + 'title' : 'Other', + }, +]; + + +const kHTML4Data = { + 'path' : 'html4', + 'suffix' : '.htm' +}; + +const kXHTML1Data = { + 'path' : 'xhtml1', + 'suffix' : '.xht' +}; + +// Results popup +const kResultsSelector = [ + { + 'name': 'All Tests', + 'handler' : function(self) { self.showResultsForAllTests(); }, + 'exporter' : function(self) { self.exportResultsForAllTests(); } + }, + { + 'name': 'Completed Tests', + 'handler' : function(self) { self.showResultsForCompletedTests(); }, + 'exporter' : function(self) { self.exportResultsForCompletedTests(); } + }, + { + 'name': 'Passing Tests', + 'handler' : function(self) { self.showResultsForTestsWithStatus('pass'); }, + 'exporter' : function(self) { self.exportResultsForTestsWithStatus('pass'); } + }, + { + 'name': 'Failing Tests', + 'handler' : function(self) { self.showResultsForTestsWithStatus('fail'); }, + 'exporter' : function(self) { self.exportResultsForTestsWithStatus('fail'); } + }, + { + 'name': 'Skipped Tests', + 'handler' : function(self) { self.showResultsForTestsWithStatus('skipped'); }, + 'exporter' : function(self) { self.exportResultsForTestsWithStatus('skipped'); } + }, + { + 'name': 'Invalid Tests', + 'handler' : function(self) { self.showResultsForTestsWithStatus('invalid'); }, + 'exporter' : function(self) { self.exportResultsForTestsWithStatus('invalid'); } + }, + { + 'name': 'Tests where HTML4 and XHTML1 results differ', + 'handler' : function(self) { self.showResultsForTestsWithMismatchedResults(); }, + 'exporter' : function(self) { self.exportResultsForTestsWithMismatchedResults(); } + }, + { + 'name': 'Tests Not Run', + 'handler' : function(self) { self.showResultsForTestsNotRun(); }, + 'exporter' : function(self) { self.exportResultsForTestsNotRun(); } + } +]; + +function Test(testInfoLine) +{ + var fields = testInfoLine.split('\t'); + + this.id = fields[0]; + this.reference = fields[1]; + this.title = fields[2]; + this.flags = fields[3]; + this.links = fields[4]; + this.assertion = fields[5]; + + this.completed = false; // true if this test has a result (pass, fail or skip) + + if (!this.links) + this.links = "other.html" +} + +function ChapterSection(link) +{ + var result= link.match(/^([.\w]+)(#.+)?$/); + if (result != null) { + this.file = result[1]; + this.anchor = result[2]; + } + + this.tests = []; +} + +function Chapter(chapterInfo) +{ + this.file = chapterInfo.file; + this.title = chapterInfo.title; + this.testCount = 0; + this.sections = []; // array of ChapterSection +} + +Chapter.prototype.description = function() +{ + return this.title + ' (' + this.testCount + ' tests)'; +} + +// Utils +String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); } + +function TestSuite() +{ + this.chapterSections = {}; // map of links to ChapterSections + this.tests = {}; // map of test id to test info + + this.chapters = {}; // map of file name to chapter + this.currentChapter = null; + + this.currentChapterTests = []; // array of tests for the current chapter. + this.currChapterTestIndex = -1; // index of test in the current chapter + + this.format = ''; + this.formatChanged('html4'); + + this.testInfoLoaded = false; + + this.populatingDatabase = false; + + var testInfoPath = kTestSuiteHome + kTestInfoDataFile; + this.loadTestInfo(testInfoPath); +} + +TestSuite.prototype.loadTestInfo = function(testInfoPath) +{ + var _self = this; + this.asyncLoad(testInfoPath, 'data', function(data, status) { + _self.testInfoDataLoaded(data, status); + }); +} + +TestSuite.prototype.testInfoDataLoaded = function(data, status) +{ + if (status != 'success') { + alert("Failed to load testinfo.data. Database of tests will not be initialized."); + return; + } + + this.parseTests(data); + this.buildChapters(); + + this.testInfoLoaded = true; + + this.fillChapterPopup(document.getElementById('chapters')); + + this.initializeControls(); + + this.openDatabase(); +} + +TestSuite.prototype.parseTests = function(data) +{ + var lines = data.split('\n'); + + // First line is column labels + for (var i = 1; i < lines.length; ++i) { + var test = new Test(lines[i]); + if (test.id.length > 0) + this.tests[test.id] = test; + } +} + +TestSuite.prototype.buildChapters = function() +{ + for (var testID in this.tests) { + var currTest = this.tests[testID]; + + // FIXME: tests with more than one link will be presented to the user + // twice. Be smarter about avoiding this. + var testLinks = currTest.links.split(','); + for (var i = 0; i < testLinks.length; ++i) { + var link = testLinks[i]; + var section = this.chapterSections[link]; + if (!section) { + section = new ChapterSection(link); + this.chapterSections[link] = section; + } + + section.tests.push(currTest); + } + } + + for (var i = 0; i < kChapterData.length; ++i) { + var chapter = new Chapter(kChapterData[i]); + chapter.index = i; + this.chapters[chapter.file] = chapter; + } + + for (var sectionName in this.chapterSections) { + var section = this.chapterSections[sectionName]; + + var file = section.file; + var chapter = this.chapters[file]; + if (!chapter) + window.console.log('failed to find chapter ' + file + ' in chapter data.'); + chapter.sections.push(section); + } + + for (var chapterName in this.chapters) { + var currChapter = this.chapters[chapterName]; + currChapter.sections.sort(); + + var testCount = 0; + for (var s = 0; s < currChapter.sections.length; ++s) + testCount += currChapter.sections[s].tests.length; + + currChapter.testCount = testCount; + } +} + +TestSuite.prototype.indexOfChapter = function(chapter) +{ + for (var i = 0; i < kChapterData.length; ++i) { + if (kChapterData[i].file == chapter.file) + return i; + } + + window.console.log('indexOfChapter for ' + chapter.file + ' failed'); + return -1; +} + +TestSuite.prototype.chapterAtIndex = function(index) +{ + if (index < 0 || index >= kChapterData.length) + return null; + + return this.chapters[kChapterData[index].file]; +} + +TestSuite.prototype.fillChapterPopup = function(select) +{ + select.innerHTML = ''; // Remove all children. + + for (var i = 0; i < kChapterData.length; ++i) { + var chapterData = kChapterData[i]; + var chapter = this.chapters[chapterData.file]; + + var option = document.createElement('option'); + option.innerText = chapter.description(); + option._chapter = chapter; + + select.appendChild(option); + } +} + +TestSuite.prototype.buildTestListForChapter = function(chapter) +{ + this.currentChapterTests = []; + + for (var i in chapter.sections) { + var currSection = chapter.sections[i]; + // FIXME: why do I need the assignment? + this.currentChapterTests = this.currentChapterTests.concat(currSection.tests); + } + + // FIXME: test may occur more than once. + this.currentChapterTests.sort(function(a, b) { + return a.id.localeCompare(b.id); + }); +} + +TestSuite.prototype.initializeControls = function() +{ + var chaptersPopup = document.getElementById('chapters'); + + var _self = this; + chaptersPopup.addEventListener('change', function() { + _self.chapterPopupChanged(); + }, false); + + this.chapterPopupChanged(); + + // Results popup + var resultsPopup = document.getElementById('results-popup'); + resultsPopup.innerHTML = ''; + + for (var i = 0; i < kResultsSelector.length; ++i) { + var option = document.createElement('option'); + option.innerText = kResultsSelector[i].name; + + resultsPopup.appendChild(option); + } +} + +TestSuite.prototype.chapterPopupChanged = function() +{ + var chaptersPopup = document.getElementById('chapters'); + var selectedChapter = chaptersPopup.options[chaptersPopup.selectedIndex]._chapter; + + this.setSelectedChapter(selectedChapter); +} + +TestSuite.prototype.fillTestList = function() +{ + var testList = document.getElementById('test-list'); + testList.innerHTML = ''; + + for (var i = 0; i < this.currentChapterTests.length; ++i) { + var currTest = this.currentChapterTests[i]; + + var option = document.createElement('option'); + option.innerText = currTest.id; + option.className = currTest.completed ? 'completed' : 'untested'; + option._test = currTest; + testList.appendChild(option); + } +} + +TestSuite.prototype.updateTestList = function() +{ + var testList = document.getElementById('test-list'); + + var options = testList.getElementsByTagName('option'); + for (var i = 0; i < options.length; ++i) { + var currOption = options[i]; + currOption.className = currOption._test.completed ? 'completed' : 'untested'; + } +} + +TestSuite.prototype.setSelectedChapter = function(chapter) +{ + this.currentChapter = chapter; + this.buildTestListForChapter(this.currentChapter); + this.currChapterTestIndex = -1; + + this.fillTestList(); + this.goToTestIndex(0); + + var chaptersPopup = document.getElementById('chapters'); + chaptersPopup.selectedIndex = this.indexOfChapter(chapter); +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.passTest = function() +{ + this.recordResult(this.currentTestName(), 'pass'); + this.nextTest(); +} + +TestSuite.prototype.failTest = function() +{ + this.recordResult(this.currentTestName(), 'fail'); + this.nextTest(); +} + +TestSuite.prototype.invalidTest = function() +{ + this.recordResult(this.currentTestName(), 'invalid'); + this.nextTest(); +} + +TestSuite.prototype.skipTest = function(reason) +{ + this.recordResult(this.currentTestName(), 'skipped', reason); + this.nextTest(); +} + +TestSuite.prototype.nextTest = function() +{ + if (this.currChapterTestIndex < this.currentChapterTests.length - 1) + this.goToTestIndex(this.currChapterTestIndex + 1); + else { + var currChapterIndex = this.indexOfChapter(this.currentChapter); + this.goToChapterIndex(currChapterIndex + 1); + } +} + +TestSuite.prototype.previousTest = function() +{ + if (this.currChapterTestIndex > 0) + this.goToTestIndex(this.currChapterTestIndex - 1); + else { + var currChapterIndex = this.indexOfChapter(this.currentChapter); + if (currChapterIndex > 0) + this.goToChapterIndex(currChapterIndex - 1); + } +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.goToTestIndex = function(index) +{ + if (index >= 0 && index < this.currentChapterTests.length) { + this.currChapterTestIndex = index; + this.loadCurrentTest(); + } +} + +TestSuite.prototype.goToChapterIndex = function(chapterIndex) +{ + if (chapterIndex >= 0 && chapterIndex < kChapterData.length) { + var chapterFile = kChapterData[chapterIndex].file; + this.setSelectedChapter(this.chapters[chapterFile]); + } +} + +TestSuite.prototype.currentTestName = function() +{ + if (this.currChapterTestIndex < 0 || this.currChapterTestIndex >= this.currentChapterTests.length) + return undefined; + + return this.currentChapterTests[this.currChapterTestIndex].id; +} + +TestSuite.prototype.loadCurrentTest = function() +{ + var theTest = this.currentChapterTests[this.currChapterTestIndex]; + if (!theTest) { + this.configureForManualTest(); + this.clearTest(); + return; + } + + if (theTest.reference) { + this.configureForRefTest(); + this.loadRef(theTest); + } else { + this.configureForManualTest(); + } + + this.loadTest(theTest); + + document.getElementById('test-index').innerText = this.currChapterTestIndex + 1; + document.getElementById('chapter-test-count').innerText = this.currentChapterTests.length; + + document.getElementById('test-list').selectedIndex = this.currChapterTestIndex; +} + +TestSuite.prototype.configureForRefTest = function() +{ + $('#test-content').addClass('with-ref'); +} + +TestSuite.prototype.configureForManualTest = function() +{ + $('#test-content').removeClass('with-ref'); +} + +TestSuite.prototype.loadTest = function(test) +{ + var iframe = document.getElementById('test-frame'); + iframe.src = this.urlForTest(test.id); + + document.getElementById('test-title').innerText = test.title; + document.getElementById('test-url').innerText = this.pathForTest(test.id); + document.getElementById('test-assertion').innerText = test.assertion; + document.getElementById('test-flags').innerText = test.flags; +} + +TestSuite.prototype.clearTest = function() +{ + var iframe = document.getElementById('test-frame'); + iframe.src = 'about:blank'; + + document.getElementById('test-title').innerText = ''; + document.getElementById('test-url').innerText = ''; + document.getElementById('test-assertion').innerText = ''; + document.getElementById('test-flags').innerText = ''; +} + +TestSuite.prototype.loadRef = function(test) +{ + var iframe = document.getElementById('ref-frame'); + iframe.src = this.urlForTest(testInfo.reference); +} + +TestSuite.prototype.loadTestByName = function(testName) +{ + var currChapterInfo = this.chapterInfoMap[this.currChapterName]; + + var testIndex = currChapterInfo.testNames.indexOf(testName); + if (testIndex >= 0 && testIndex < currChapterInfo.testNames.length) + this.goToTestIndex(testIndex); +} + +TestSuite.prototype.pathForTest = function(testName) +{ + var prefix = this.formatInfo.path; + var suffix = this.formatInfo.suffix; + + return prefix + '/' + testName + suffix; +} + +TestSuite.prototype.urlForTest = function(testName) +{ + return kTestSuiteHome + this.pathForTest(testName); +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.recordResult = function(testName, resolution, comment) +{ + if (!testName) + return; + + this.beginAppendingOutput(); + this.appendResultToOutput(this.formatInfo, testName, resolution, comment); + this.endAppendingOutput(); + + if (comment == undefined) + comment = ''; + + this.storeTestResult(testName, this.format, resolution, comment, navigator.userAgent); + this.markTestCompleted(testName); + this.updateTestList(); + + this.updateSummaryData(); +} + +TestSuite.prototype.beginAppendingOutput = function() +{ +} + +TestSuite.prototype.endAppendingOutput = function() +{ + var output = document.getElementById('output'); + output.scrollTop = output.scrollHeight; +} + +TestSuite.prototype.appendResultToOutput = function(formatData, testName, resolution, comment) +{ + var output = document.getElementById('output'); + + var result = formatData.path + '/' + testName + formatData.suffix + '\t' + resolution; + if (comment) + result += '\t(' + comment + ')'; + + var line = document.createElement('p'); + line.className = resolution; + line.appendChild(document.createTextNode(result)); + output.appendChild(line); +} + +TestSuite.prototype.clearOutput = function() +{ + document.getElementById('output').innerHTML = ''; +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.formatChanged = function(formatString) +{ + if (this.format == formatString) + return; + + this.format = formatString; + + if (formatString == 'html4') + this.formatInfo = kHTML4Data; + else + this.formatInfo = kXHTML1Data; + + this.loadCurrentTest(); +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.asyncLoad = function(url, type, handler) +{ + $.get(url, handler, type); +} + +/* ------------------------------------------------------- */ + +TestSuite.prototype.exportResults = function(resultTypeIndex) +{ + var resultInfo = kResultsSelector[resultTypeIndex]; + if (!resultInfo) + return; + + resultInfo.exporter(this); +} + +TestSuite.prototype.exportHeader = function() +{ + var result = '# Safari 5.0.2' + ' ' + navigator.platform + '\n'; + result += '# ' + navigator.userAgent + '\n'; + result += '# http://test.csswg.org/suites/css2.1/' + kTestSuiteVersion + '/\n'; + result += 'testname\tresult\n'; + + return result; +} + +TestSuite.prototype.createExportLine = function(formatData, testName, resolution, comment) +{ + var result = formatData.path + '/' + testName + '\t' + resolution; + if (comment) + result += '\t(' + comment + ')'; + return result; +} + +TestSuite.prototype.exportQueryComplete = function(data) +{ + window.open("data:text/plain," + escape(data)) +} + +TestSuite.prototype.resultsPopupChanged = function(index) +{ + var resultInfo = kResultsSelector[index]; + if (!resultInfo) + return; + + this.clearOutput(); + resultInfo.handler(this); + + var enableExport = resultInfo.exporter != undefined; + document.getElementById('export-button').disabled = !enableExport; +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.exportResultsCompletion = function(exportTests) +{ + window.console.log('exportResultsCompletion') + // Lame workaround for ORDER BY not working + exportTests.sort(function(a, b) { + return a.test.localeCompare(b.test); + }); + + var exportLines = []; + for (var i = 0; i < exportTests.length; ++i) { + var currTest = exportTests[i]; + if (currTest.html4 != '') + exportLines.push(currTest.html4); + if (currTest.xhtml1 != '') + exportLines.push(currTest.xhtml1); + } + + var exportString = this.exportHeader() + exportLines.join('\n'); + this.exportQueryComplete(exportString); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.showResultsForCompletedTests = function() +{ + this.beginAppendingOutput(); + + var _self = this; + this.queryDatabaseForCompletedTests( + function(item) { + if (item.hstatus) + _self.appendResultToOutput(kHTML4Data, item.test, item.hstatus, item.hcomment); + + if (item.xstatus) + _self.appendResultToOutput(kXHTML1Data, item.test, item.xstatus, item.xcomment); + }, + function() { + _self.endAppendingOutput(); + } + ); +} + +TestSuite.prototype.exportResultsForCompletedTests = function() +{ + var exportTests = []; // each test will have html and xhtml items on it + + var _self = this; + this.queryDatabaseForCompletedTests( + function(item) { + var htmlLine = ''; + if (item.hstatus) + htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus, item.hcomment); + + var xhtmlLine = ''; + if (item.xstatus) + xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus, item.xcomment); + + exportTests.push({ + 'test' : item.test, + 'html4' : htmlLine, + 'xhtml1' : xhtmlLine }); + }, + function() { + _self.exportResultsCompletion(exportTests); + } + ); +} + + +/* -------------------------------------------------------- */ + +TestSuite.prototype.showResultsForAllTests = function() +{ + this.beginAppendingOutput(); + + var _self = this; + this.queryDatabaseForAllTests('test', + function(item) { + _self.appendResultToOutput(kHTML4Data, item.test, item.hstatus, item.hcomment); + _self.appendResultToOutput(kXHTML1Data, item.test, item.xstatus, item.xcomment); + }, + function() { + _self.endAppendingOutput(); + }); +} + +TestSuite.prototype.exportResultsForAllTests = function() +{ + var exportTests = []; + + var _self = this; + this.queryDatabaseForAllTests('test', + function(item) { + var htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus, item.hcomment); + var xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus, item.xcomment); + exportTests.push({ + 'test' : item.test, + 'html4' : htmlLine, + 'xhtml1' : xhtmlLine }); + }, + function() { + _self.exportResultsCompletion(exportTests); + } + ); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.showResultsForTestsNotRun = function() +{ + this.beginAppendingOutput(); + + var _self = this; + this.queryDatabaseForTestsNotRun( + function(item) { + if (!item.hstatus) + _self.appendResultToOutput(kHTML4Data, item.test, '?', item.hcomment); + if (!item.xstatus) + _self.appendResultToOutput(kXHTML1Data, item.test, '?', item.xcomment); + }, + function() { + _self.endAppendingOutput(); + } + ); +} + +TestSuite.prototype.exportResultsForTestsNotRun = function() +{ + var exportTests = []; + + var _self = this; + this.queryDatabaseForTestsNotRun( + function(item) { + var htmlLine = ''; + if (!item.hstatus) + htmlLine= _self.createExportLine(kHTML4Data, item.test, '?', item.hcomment); + + var xhtmlLine = ''; + if (!item.xstatus) + xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, '?', item.xcomment); + + exportTests.push({ + 'test' : item.test, + 'html4' : htmlLine, + 'xhtml1' : xhtmlLine }); + }, + function() { + _self.exportResultsCompletion(exportTests); + } + ); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.showResultsForTestsWithStatus = function(status) +{ + this.beginAppendingOutput(); + + var _self = this; + this.queryDatabaseForTestsWithStatus(status, + function(item) { + if (item.hstatus == status) + _self.appendResultToOutput(kHTML4Data, item.test, item.hstatus, item.hcomment); + if (item.xstatus == status) + _self.appendResultToOutput(kXHTML1Data, item.test, item.xstatus, item.xcomment); + }, + function() { + _self.endAppendingOutput(); + } + ); +} + +TestSuite.prototype.exportResultsForTestsWithStatus = function(status) +{ + var exportTests = []; + + var _self = this; + this.queryDatabaseForTestsWithStatus(status, + function(item) { + var htmlLine = ''; + if (item.hstatus == status) + htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus, item.hcomment); + + var xhtmlLine = ''; + if (item.xstatus == status) + xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus, item.xcomment); + + exportTests.push({ + 'test' : item.test, + 'html4' : htmlLine, + 'xhtml1' : xhtmlLine }); + }, + function() { + _self.exportResultsCompletion(exportTests); + } + ); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.showResultsForTestsWithMismatchedResults = function() +{ + this.beginAppendingOutput(); + + var _self = this; + this.queryDatabaseForTestsWithMixedStatus( + function(item) { + _self.appendResultToOutput(kHTML4Data, item.test, item.hstatus, item.hcomment); + _self.appendResultToOutput(kXHTML1Data, item.test, item.xstatus, item.xcomment); + }, + function() { + _self.endAppendingOutput(); + } + ); +} + +TestSuite.prototype.exportResultsForTestsWithMismatchedResults = function() +{ + var exportTests = []; + + var _self = this; + this.queryDatabaseForTestsWithMixedStatus( + function(item) { + var htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus, item.hcomment); + var xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus, item.xcomment); + exportTests.push({ + 'test' : item.test, + 'html4' : htmlLine, + 'xhtml1' : xhtmlLine }); + }, + function() { + _self.exportResultsCompletion(exportTests); + } + ); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.markTestCompleted = function(testID) +{ + var test = this.tests[testID]; + if (!test) { + window.console.log('markTestCompleted to find test ' + testID); + return; + } + + test.completed = true; +} + +TestSuite.prototype.testCompletionStateChanged = function() +{ + // update the test list + this.updateTestList(); +} + +TestSuite.prototype.loadTestStatus = function() +{ + var _self = this; + this.queryDatabaseForCompletedTests( + function(item) { + _self.markTestCompleted(item.test); + }, + function() { + _self.testCompletionStateChanged(); + } + ); +} + +/* -------------------------------------------------------- */ + +TestSuite.prototype.updateSummaryData = function() +{ + this.queryDatabaseForSummary( + function(results) { + + var hTotal, xTotal; + var hDone, xDone; + + for (var i = 0; i < results.length; ++i) { + var result = results[i]; + + switch (result.name) { + case 'h-total': hTotal = result.count; break; + case 'x-total': xTotal = result.count; break; + case 'h-tested': hDone = result.count; break; + case 'x-tested': xDone = result.count; break; + } + + document.getElementById(result.name).innerText = result.count; + } + + // We should get these all together. + if (hTotal) { + document.getElementById('h-percent').innerText = Math.round(100.0 * hDone / hTotal); + document.getElementById('x-percent').innerText = Math.round(100.0 * xDone / xTotal); + } + } + ); +} + +/* ------------------------------------------------------- */ +// Database stuff + +function errorHandler(transaction, error) +{ + alert('Database error: ' + error.message); + window.console.log('Database error: ' + error.message); +} + +TestSuite.prototype.openDatabase = function() +{ + if (!'openDatabase' in window) { + alert('Your browser does not support client-side SQL databases, so results will not be stored.'); + return; + } + + var _self = this; + this.db = window.openDatabase('css21testsuite', '1.0', 'CSS 2.1 test suite results', 10 * 1024 * 1024, function() { + _self.databaseCreated(); + }, errorHandler); + + this.updateSummaryData(); + this.loadTestStatus(); +} + +TestSuite.prototype.databaseCreated = function(db) +{ + this.populatingDatabase = true; + + var _self = this; + this.db.transaction(function (tx) { + // hstatus: HTML4 result + // xstatus: XHTML1 result + tx.executeSql('CREATE TABLE tests (test PRIMARY KEY UNIQUE, ref, title, flags, links, assertion, hstatus, hcomment, xstatus, xcomment)', null, + function(tx, results) { + _self.populateDatabaseFromTestInfoData(); + }, errorHandler); + }); +} + +TestSuite.prototype.storeTestResult = function(test, format, result, comment, useragent) +{ + if (!this.db) + return; + + this.db.transaction(function (tx) { + if (format == 'html4') + tx.executeSql('UPDATE tests SET hstatus=?, hcomment=? WHERE test=?\n', [result, comment, test], null, errorHandler); + else if (format == 'xhtml1') + tx.executeSql('UPDATE tests SET xstatus=?, xcomment=? WHERE test=?\n', [result, comment, test], null, errorHandler); + }); +} + +TestSuite.prototype.populateDatabaseFromTestInfoData = function(testInfoURL) +{ + if (!this.testInfoLoaded) { + window.console.log('Tring to populate database before testinfo.data has been loaded'); + return; + } + + var _self = this; + this.db.transaction(function (tx) { + for (var testID in _self.tests) { + var currTest = _self.tests[testID]; + tx.executeSql('INSERT INTO tests (test, ref, title, flags, links, assertion) VALUES (?, ?, ?, ?, ?, ?)', [currTest.id, currTest.reference, currTest.title, currTest.flags, currTest.links, currTest.assertion], null, errorHandler); + } + + _self.populatingDatabase = false; + }); + +} + +TestSuite.prototype.queryDatabaseForAllTests = function(sortKey, perRowHandler, completionHandler) +{ + if (this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + if (_self.populatingDatabase) + return; + var query; + var args = []; + if (sortKey != '') { + query = 'SELECT * FROM tests ORDER BY ? ASC'; // ORDER BY doesn't seem to work + args.push(sortKey); + } + else + query = 'SELECT * FROM tests'; + + tx.executeSql(query, args, function(tx, results) { + + var len = results.rows.length; + for (var i = 0; i < len; ++i) + perRowHandler(results.rows.item(i)); + + completionHandler(); + }, errorHandler); + }); +} + +TestSuite.prototype.queryDatabaseForTestsWithStatus = function(status, perRowHandler, completionHandler) +{ + if (this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + if (_self.populatingDatabase) + return; + tx.executeSql('SELECT * FROM tests WHERE hstatus=? OR xstatus=?', [status, status], function(tx, results) { + + var len = results.rows.length; + for (var i = 0; i < len; ++i) + perRowHandler(results.rows.item(i)); + + completionHandler(); + }, errorHandler); + }); +} + +TestSuite.prototype.queryDatabaseForTestsWithMixedStatus = function(perRowHandler, completionHandler) +{ + if (this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + if (_self.populatingDatabase) + return; + tx.executeSql('SELECT * FROM tests WHERE hstatus IS NOT NULL AND xstatus IS NOT NULL AND hstatus <> xstatus', [], function(tx, results) { + + var len = results.rows.length; + for (var i = 0; i < len; ++i) + perRowHandler(results.rows.item(i)); + + completionHandler(); + }, errorHandler); + }); +} + +TestSuite.prototype.queryDatabaseForCompletedTests = function(perRowHandler, completionHandler) +{ + if (this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + + if (_self.populatingDatabase) + return; + + tx.executeSql('SELECT * FROM tests WHERE hstatus IS NOT NULL OR xstatus IS NOT NULL', [], function(tx, results) { + var len = results.rows.length; + for (var i = 0; i < len; ++i) + perRowHandler(results.rows.item(i)); + + completionHandler(); + }, errorHandler); + }); +} + +TestSuite.prototype.queryDatabaseForTestsNotRun = function(perRowHandler, completionHandler) +{ + if (this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + if (_self.populatingDatabase) + return; + + tx.executeSql('SELECT * FROM tests WHERE hstatus IS NULL OR xstatus IS NULL', [], function(tx, results) { + + var len = results.rows.length; + for (var i = 0; i < len; ++i) + perRowHandler(results.rows.item(i)); + + completionHandler(); + }, errorHandler); + }); +} + +/* + + completionHandler gets called an array of results, + which may be some or all of: + + data = [ + { 'name' : , + 'count' : + }, + ] + + where name is one of: + + 'h-total' + 'h-tested' + 'h-passed' + 'h-failed' + 'h-skipped' + + 'x-total' + 'x-tested' + 'x-passed' + 'x-failed' + 'x-skipped' + + */ + + +TestSuite.prototype.countTestsWithColumnValue = function(tx, completionHandler, column, value, label) +{ + var allRowsCount = 'COUNT(*)'; + + tx.executeSql('SELECT COUNT(*) FROM tests WHERE ' + column + '=?', [value], function(tx, results) { + var data = []; + if (results.rows.length > 0) + data.push({ 'name' : label, 'count' : results.rows.item(0)[allRowsCount] }) + completionHandler(data); + }, errorHandler); +} + +TestSuite.prototype.queryDatabaseForSummary = function(completionHandler) +{ + if (!this.db || this.populatingDatabase) + return; + + var _self = this; + this.db.transaction(function (tx) { + + if (_self.populatingDatabase) + return; + + var allRowsCount = 'COUNT(*)'; + var html4RowsCount = 'COUNT(hstatus)'; + var xhtml1RowsCount = 'COUNT(xstatus)'; + + tx.executeSql('SELECT COUNT(*), COUNT(hstatus), COUNT(xstatus) FROM tests', [], function(tx, results) { + + var data = []; + if (results.rows.length > 0) { + var rowItem = results.rows.item(0); + data.push({ 'name' : 'h-total' , 'count' : rowItem[allRowsCount] }) + data.push({ 'name' : 'x-total' , 'count' : rowItem[allRowsCount] }) + data.push({ 'name' : 'h-tested', 'count' : rowItem[html4RowsCount] }) + data.push({ 'name' : 'x-tested', 'count' : rowItem[xhtml1RowsCount] }) + } + completionHandler(data); + + }, errorHandler); + + _self.countTestsWithColumnValue(tx, completionHandler, 'hstatus', 'pass', 'h-passed'); + _self.countTestsWithColumnValue(tx, completionHandler, 'xstatus', 'pass', 'x-passed'); + + _self.countTestsWithColumnValue(tx, completionHandler, 'hstatus', 'fail', 'h-failed'); + _self.countTestsWithColumnValue(tx, completionHandler, 'xstatus', 'fail', 'x-failed'); + + _self.countTestsWithColumnValue(tx, completionHandler, 'hstatus', 'skipped', 'h-skipped'); + _self.countTestsWithColumnValue(tx, completionHandler, 'xstatus', 'skipped', 'x-skipped'); + + _self.countTestsWithColumnValue(tx, completionHandler, 'hstatus', 'invalid', 'h-invalid'); + _self.countTestsWithColumnValue(tx, completionHandler, 'xstatus', 'invalid', 'x-invalid'); + }); +} + diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog index eace217..b2a3791 100644 --- a/WebKitTools/ChangeLog +++ b/WebKitTools/ChangeLog @@ -1,3 +1,1500 @@ +2010-09-28 Johnny Ding <jnd@chromium.org> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=41292 + Add a new parameter to the test plugin to allow specifying a script + and a mouse/keyboard event. The specified script will be evaluated + in the browser when the specified event is received by the plugin. + + * DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp: + (pluginAllocate): + * DumpRenderTree/TestNetscapePlugIn/PluginObject.h: + * DumpRenderTree/TestNetscapePlugIn/main.cpp: + (NPP_New): + (handleEventCarbon): + (handleEventCocoa): + +2010-09-28 Simon Fraser <simon.fraser@apple.com> + + Fix export by adding missing argument. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.showResultsForAllTests): + +2010-09-28 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Build fix, add missing import. + + * wx/packaging/build-win-installer.py: + +2010-09-28 Simon Fraser <simon.fraser@apple.com> + + No review + + Show which tests have been run by dimming them out in the test list. + + Adjust some element sizes. + + * CSSTestSuiteHarness/harness/harness.css: + (#test-list > option.untested): + (#test-list > option.completed): + (#output): + (.output-options): + * CSSTestSuiteHarness/harness/harness.js: + (Test): + (TestSuite.prototype.fillTestList): + (TestSuite.prototype.updateTestList): + (TestSuite.prototype.setSelectedChapter): + (TestSuite.prototype.recordResult): + (TestSuite.prototype.markTestCompleted): + (TestSuite.prototype.testCompletionStateChanged): + (TestSuite.prototype.loadTestStatus): + +2010-09-28 Simon Fraser <simon.fraser@apple.com> + + No review. + + Implement export of various queries on the test database, sharing + code with that which displays results inline. + + * CSSTestSuiteHarness/harness/harness.js: + (): + (TestSuite.prototype.exportResultsCompletion.var): + (TestSuite.prototype.exportResultsCompletion): + (TestSuite.prototype.showResultsForCompletedTests): + (TestSuite.prototype.exportResultsForCompletedTests): + (TestSuite.prototype.showResultsForAllTests): + (TestSuite.prototype.exportResultsForAllTests): + (TestSuite.prototype.exportResultsForTestsNotRun): + (TestSuite.prototype.exportResultsForTestsWithStatus): + (TestSuite.prototype.exportResultsForTestsWithMismatchedResults): + +2010-09-28 Simon Fraser <simon.fraser@apple.com> + + No review. + + Work around uncertainty about the order of database + transactions when creating the database, so that we don't + try to query the table before it has been created. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite): + (TestSuite.prototype.databaseCreated): + (TestSuite.prototype.storeTestResult): + (TestSuite.prototype.populateDatabaseFromTestInfoData): + (TestSuite.prototype.queryDatabaseForTestsWithStatus): + (TestSuite.prototype.queryDatabaseForTestsWithMixedStatus): + (TestSuite.prototype.queryDatabaseForCompletedTests): + (TestSuite.prototype.queryDatabaseForTestsNotRun): + +2010-09-28 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + add python keyring support to webkit-patch + https://bugs.webkit.org/show_bug.cgi?id=41269 + + * Scripts/webkitpy/common/net/credentials.py: Add the ability to read passwords using + the python keyring module + * Scripts/webkitpy/common/net/credentials_unittest.py: + * Scripts/webkitpy/common/system/user.py: Allow confirm() to default to no and add testing params. + * Scripts/webkitpy/common/system/user_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-09-28 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [Cairo] FreeType fonts should obey FontConfig hinting/anti-aliasing settings + https://bugs.webkit.org/show_bug.cgi?id=46740 + + * DumpRenderTree/gtk/fonts/fonts.conf: Add specialized variants of common + fonts which can be used to fully test FontConfig rendering settings. + +2010-09-28 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [gtk] Fedora has a different path for the liberation fonts + https://bugs.webkit.org/show_bug.cgi?id=46709 + + When searching for DRT fonts, also look in the path where those fonts + are commonly found on Fedora systems. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (initializeFonts): Include logic for looking for Fedora-style font paths. + +2010-09-28 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Andreas Kling. + + run-webkit-tests needs an updated list of directories with webgl tests + https://bugs.webkit.org/show_bug.cgi?id=46747 + + Update the list of directories containing WebGL tests and a unit test + which depends on this list. + + * Scripts/old-run-webkit-tests: Update the list of directories. + * Scripts/webkitpy/layout_tests/port/webkit.py: Ditto. + * Scripts/webkitpy/layout_tests/port/webkit_unittest.py: Update the expected result. + +2010-09-28 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Introduce FailureMap to summaries the failures status of all the bots + https://bugs.webkit.org/show_bug.cgi?id=46700 + + This patch gives the SheriffBot a handle on the list of failing tests. + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/failuremap.py: Added. + * Scripts/webkitpy/tool/commands/queries.py: + * Scripts/webkitpy/tool/commands/sheriffbot.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-09-28 Adam Roben <aroben@apple.com> + + Update for the addition of WKPageUIClient::didNotHandleKeyEvent + + Fixes <http://webkit.org/b/46660> <rdar://problem/8483465> Need API to + tell a WebKit2 client application that a key event was not handled + + Reviewed by Kenneth Rohde Christiansen and Sam Weinig. + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * MiniBrowser/win/BrowserView.cpp: + (BrowserView::create): + * WebKitTestRunner/TestController.cpp: + (WTR::createOtherPage): + (WTR::TestController::initialize): + +2010-09-28 Simon Fraser <simon.fraser@apple.com> + + Unreviewed. + + Update the CSSTestSuiteHarness to not scrape the XHTML chapter files + for the test order, but instead use information from testinfo.data. + + * CSSTestSuiteHarness/harness/harness.html: + * CSSTestSuiteHarness/harness/harness.js: + +2010-09-28 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Build fix, don't try to get the svn revision from the git repo when packaging, + it causes the process to hang on the gitorious repo. + + * wx/packaging/build-mac-installer.py: + * wx/packaging/build-win-installer.py: + +2010-09-28 Adam Roben <aroben@apple.com> + + Test that a plugin's HWND is sized/positioned before NPP_SetWindow is + called + + Reviewed by Anders Carlsson. + + Test for <http://webkit.org/b/46716> <rdar://problem/8482014> + Full-page Adobe Reader does not paint until window is resized + + * DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp: + (PluginTest::NPP_SetWindow): Added. Just returns NPERR_NO_ERROR at + this level. + + * DumpRenderTree/TestNetscapePlugIn/PluginTest.h: Declared + NPP_SetWindow. + + * DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp: Added. + (WindowGeometryInitializedBeforeSetWindow::NPP_SetWindow): Checks that + the plugin's HWND has a non-zero size and that its size/position + matches that specified in the NPWindow. + + * DumpRenderTree/TestNetscapePlugIn/main.cpp: + (NPP_SetWindow): Call through to the PluginTest. + + * DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj: + Added WindowGeometryInitializedBeforeSetWindow.cpp, and let VS reorder + the files as it saw fit. + +2010-09-28 Benjamin Poulain <benjamin.poulain@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] Remove support for Qt 4.5 + https://bugs.webkit.org/show_bug.cgi?id=46718 + + Remove the code for versions of Qt prior to 4.6. + + * DumpRenderTree/qt/EventSenderQt.cpp: + (EventSender::addTouchPoint): + (EventSender::updateTouchPoint): + (EventSender::setTouchModifier): + (EventSender::touchStart): + (EventSender::touchMove): + (EventSender::touchEnd): + (EventSender::clearTouchPoints): + (EventSender::releaseTouchPoint): + (EventSender::sendTouchEvent): + * DumpRenderTree/qt/EventSenderQt.h: + * DumpRenderTree/qt/TextInputControllerQt.cpp: + (TextInputController::setMarkedText): + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::LauncherWindow): + (LauncherWindow::initializeView): + (LauncherWindow::createChrome): + (LauncherWindow::sendTouchEvent): + (LauncherWindow::eventFilter): + (LauncherWindow::applyZoom): + (LauncherWindow::setTouchMocking): + * QtTestBrowser/launcherwindow.h: + * QtTestBrowser/utils.cpp: + (urlFromUserInput): + * QtTestBrowser/webview.cpp: + (WebViewGraphicsBased::animatedFlip): + (WebViewGraphicsBased::animatedYFlip): + * QtTestBrowser/webview.h: + (WebViewGraphicsBased::setYRotation): + +2010-09-28 İsmail Dönmez <ismail@namtrac.org> + + Reviewed by Andreas Kling. + + Fix DRT compilation on WinCE. Introduce a WCECOMPAT variable + which should point to wcecompat installation. Needs wcecompat + library from http://github.com/mauricek/wcecompat . + + * DumpRenderTree/qt/DumpRenderTree.pro: + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::DumpRenderTree::resetToConsistentStateBeforeTesting): + +2010-09-28 Daniel Bates <dbates@rim.com> + + Rollout changeset 68493 <http://trac.webkit.org/changeset/68493> + <https://bugs.webkit.org/show_bug.cgi?id=39136> + + Rollout changeset 68493 because it broke Sheriffbot's rollout feature. + In particular, this change caused Sheriffbot to raise an exception when + trying to parse the bug id on a bug page. We need to look into this + some more. + + * Scripts/webkitpy/common/net/bugzilla.py: + * Scripts/webkitpy/common/net/bugzilla_unittest.py: + * Scripts/webkitpy/tool/bot/sheriff.py: + * Scripts/webkitpy/tool/commands/download.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/upload.py: + * Scripts/webkitpy/tool/steps/closebug.py: + * Scripts/webkitpy/tool/steps/obsoletepatches.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + * Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py: + +2010-09-28 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Move RegressionWindow further up the dependency chain + https://bugs.webkit.org/show_bug.cgi?id=46698 + + Baby steps towards pushing this information into bug posts. + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/buildbot_unittest.py: + * Scripts/webkitpy/common/net/regressionwindow.py: + * Scripts/webkitpy/tool/commands/queries.py: + +2010-09-27 Daniel Bates <dbates@rim.com> + + Reviewed by Adam Barth. + + sheriffbot can't roll out security patches + https://bugs.webkit.org/show_bug.cgi?id=39136 + + Make SheriffBot determine if it's authorized to view a bug + whose change it wants to rollout before it tries to rollout + the change. + + Moreover, make both webkit-patch and Sheriffbot provide human- + readable error messages when they are not authorized to view + a bug and when a bug number is invalid. + + Currently, Sheriffbot does not parse Bugzilla bugs for + <bug error="...">, which indicates an error when retrieving + a bug. In particular, error="NotPermitted" if a person (or bot) + is not authorized to view a bug. For such error="NotPermitted" bugs, + Sheriffbot raises an exception when parsing the bug report and + this exception does not explicitly indicate Sheriffbot's lack + of authorization. Instead, Sheriffbot should explicitly check + for the presence <bug error="..."> before operating on a bug + and error with a human-readable message if it's not permitted + to view it. + + * Scripts/webkitpy/common/net/bugzilla.py: Added BugzillaError class. + * Scripts/webkitpy/common/net/bugzilla_unittest.py: + - Added unit test test_bug_parsing_for_bugzilla_not_permitted_error(). + - Added unit test test_bug_parsing_for_bugzilla_not_found_error(). + - Added unit test test_bug_parsing_for_bugzilla_invalid_bug_id_error(). + * Scripts/webkitpy/tool/bot/sheriff.py: Modified to catch BugzillaError. + * Scripts/webkitpy/tool/commands/download.py: Ditto. + * Scripts/webkitpy/tool/commands/queues.py: Ditto. + * Scripts/webkitpy/tool/commands/upload.py: Ditto. + * Scripts/webkitpy/tool/steps/closebug.py: Ditto. + * Scripts/webkitpy/tool/steps/obsoletepatches.py: Ditto. + * Scripts/webkitpy/tool/steps/preparechangelog.py: Ditto. + * Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py: Ditto. + +2010-09-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Expose more more failure information from Buildbot to SheriffBot + https://bugs.webkit.org/show_bug.cgi?id=46697 + + This patch moves the information about what tests failured closer to + SheriffBot. There are still a couple more patches to go before + SheriffBot can post this information to bugs, but this is a step in + that direction. Yay for unit tests, which caught some bugs in earlier + versions of this patch. + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/buildbot_unittest.py: + * Scripts/webkitpy/common/net/regressionwindow.py: Added. + * Scripts/webkitpy/tool/commands/queries.py: + +2010-09-27 Eric Seidel <eric@webkit.org> + + Unreviewed. Fixing 500 error seen in the status server. + + It turns out that a = b = []; b.append(1); then a[0] will be 1! + This should have been obvious to me, I guess, but it was not what I was expecting. + + * QueueStatusServer/model/activeworkitems.py: + +2010-09-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + commit-queue should reject patches that fail to land + https://bugs.webkit.org/show_bug.cgi?id=46694 + + This can happen, for example, if there's no reviewer. Without this + patch, we'll keep retrying the patch. + + * Scripts/webkitpy/tool/bot/commitqueuetask.py: + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: + +2010-09-27 Simon Fraser <simon.fraser@apple.com> + + Rubber-stamped by Adele Peterson. + + Add a harness for running the CSS 2.1 test suite. + + This harness assumes that you've got a local a copy of the suite + adjacent to the 'harness' directory. + + The harness lets you go through the tests in chapter order, + denoting pass/fail/skipped for each test. + + It uses a client-side database to store the results of testing. + + * CSSTestSuiteHarness/harness/harness.css: Added. + * CSSTestSuiteHarness/harness/harness.html: Added. + * CSSTestSuiteHarness/harness/harness.js: Added. + +2010-09-27 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Patch locks should expire if a patch is marked for retry + https://bugs.webkit.org/show_bug.cgi?id=46682 + + This was part Adam's original CommitQueueTask design, + but support for it was missing from the server. + I added the support, but triggering lock-release based on this + special "retry" status feels a bit strange so I added a FIXME. + + I also changed the text in queuestatus.html to say "Lock Acquired" + since "Last Activity" isn't really true. We only update the lock + date when the patch is started, not on every status update. + + I also noticed an exception in next-patch, which I fixed by re-writing + the unzip logic in activeworkitems.py again. + + * QueueStatusServer/handlers/updatestatus.py: + * QueueStatusServer/model/activeworkitems.py: + * QueueStatusServer/templates/queuestatus.html: + +2010-09-27 Tony Chang <tony@chromium.org> + + Reviewed by David Levin. + + [chromium] fix a warning when compiling DRT on 32-bit linux + https://bugs.webkit.org/show_bug.cgi?id=46641 + + * DumpRenderTree/chromium/TestEventPrinter.cpp: + (DRTPrinter::handleImage): + +2010-09-27 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + queue-status should report when the patch was last locked to a queue + https://bugs.webkit.org/show_bug.cgi?id=46674 + + This isn't necessarily the best way to expose this information + but having this accessible via the web interface is very + useful until we come up with a nicer way to display this. + + I also cleaned up the code in activeworkitems.py a little + to use list comprehensions and to have the code work with + pairs instead of two lists at once. Eventually I think those + item/time pairs need to be their own little helper class. + + * QueueStatusServer/handlers/queuestatus.py: + * QueueStatusServer/model/activeworkitems.py: + * QueueStatusServer/templates/queuestatus.html: + +2010-09-27 Tony Chang <tony@chromium.org> + + Reviewed by David Levin. + + [chromium] fix detection of missing fonts on DRT + https://bugs.webkit.org/show_bug.cgi?id=46651 + + * DumpRenderTree/chromium/TestShellGtk.cpp: + (setupFontconfig): Only print an error message if lohit isn't found in both locations. + +2010-09-27 Tony Chang <tony@chromium.org> + + Reviewed by Dimitri Glazkov. + + add webkit unit tests to the chromium testers + https://bugs.webkit.org/show_bug.cgi?id=46669 + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + * Scripts/run-chromium-webkit-unit-tests: Fix a bug where we weren't using the right configuration. + +2010-09-27 Kwang Yul Seo <skyul@company100.net> + + Unreviewed. + + Adding myself to the committers list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-09-27 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Eric Seidel. + + webkitpy.common.system.user_unittest.UserTest.test_prompt_with_list spams the console + https://bugs.webkit.org/show_bug.cgi?id=46634 + + Use OutputCapture to prevent console spam (and also check for expected + output). + + * Scripts/webkitpy/common/system/user_unittest.py: + +2010-09-27 Eric Seidel <eric@webkit.org> + + Reviewed by James Robinson. + + start-commit-queue should abort any rebases in progress + https://bugs.webkit.org/show_bug.cgi?id=46640 + + webkit-patch commit-queue would do this itself, but this just + helps ensure that the commit-queue script is properly updated + before we run it (in the case where a previous rebase is in + progress the git svn rebase would not work before we run the + commit-queue). + + * EWSTools/start-commit-queue.sh: + +2010-09-18 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Clean up the DRT fonts.conf and switch to Liberation + https://bugs.webkit.org/show_bug.cgi?id=46038 + + Switch to Liberation fonts for GTK+ layout tests. This will make our + test results metric-compatible with many Windows/Chromium results. It + also simplifies the fonts.conf that we load and prepares the way for + fixing many font bugs. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (initializeFonts): Initialize a known list of fonts instead of loading + every font in the WEBKIT_TESTFONTS directory. + * DumpRenderTree/gtk/fonts.conf: Removed. + * DumpRenderTree/gtk/fonts/AHEM____.TTF: Copied from WebKitTools/DumpRenderTree/qt/fonts/AHEM____.TTF. + * DumpRenderTree/gtk/fonts/fonts.conf: Added. + * GNUmakefile.am: Modify FONTS_CONF_FILE to be FONTS_CONF_DIR, so that + we can load both fonts.conf and AHEM____.TTF from this location. + * Scripts/old-run-webkit-tests: Remove the check for WEBKIT_TESTFONTS, since + it is no longer used. + +2010-09-26 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Ojan Vafai. + + new-run-webkit-httpd fails if Perl is not installed + https://bugs.webkit.org/show_bug.cgi?id=46602 + + Make Port._read_configuration catch all exceptions, since trying to run + perl (because of _webkit_build_directory) when it's not installed throws + a WindowsError or OSError, not an IOError (this became an issue after + r68268, since ChromiumPort ends up calling Port.default_configuration in + its constructor, which means that we're ending up on this codepath in + non-NRWT cases too, e.g. for the Chromium NaCl tests, which use + new-run-webkit-httpd). + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + +2010-09-26 Gyuyoung Kim <gyuyoung.kim@samsung.com> + + Reviewed by Antonio Gomes. + + [EFL] Add setting API to set a local storage database path. + https://bugs.webkit.org/show_bug.cgi?id=45446 + + Add a setting API to set local storage database path. + + * EWebLauncher/main.c: + (on_key_down): + (browserCreate): + (main): + +2010-09-26 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Move shared WebKit2 API (used by both bundle and main API) to WebKit2/Shared/API + https://bugs.webkit.org/show_bug.cgi?id=46587 + + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + +2010-09-26 Antonio Gomes <agomes@rim.com> + + Reviewed by Kenneth Rohde Christiansen. + + DRT/Mac nodesFromRect support + + [Mac][DRT] Implement LayoutTestController::nodesFromRect + https://bugs.webkit.org/show_bug.cgi?id=46580 + + Implements LayoutTestController::nodesFromRect for Mac DRT, and + adding stubs for GTK+ and Windows. + + * DumpRenderTree/LayoutTestController.cpp: + (nodesFromRectCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController::LayoutTestController::nodesFromRect): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::nodesFromRect): + +2010-09-25 Nicolas Weber <thakis@chromium.org> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=46555 + Fix typo in prepare-ChangeLog's help output. + + * Scripts/prepare-ChangeLog: + +2010-09-24 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler. + + Implement WebKit2 callback equivalent to -[WebUIDelegate mouseDidMoveOverElement:modifierFlags:] + <rdar://problem/8359279> + https://bugs.webkit.org/show_bug.cgi?id=46546 + + * MiniBrowser/mac/BrowserWindowController.m: + (mouseDidMoveOverElement): + (-[BrowserWindowController awakeFromNib]): + * MiniBrowser/win/BrowserView.cpp: + (mouseDidMoveOverElement): + (BrowserView::create): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::InjectedBundlePage): + * WebKitTestRunner/TestController.cpp: + (WTR::createOtherPage): + (WTR::TestController::initialize): + +2010-09-24 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Adam Barth. + + Allow rebaselines for webkit-patch rebaseline to be chosen + https://bugs.webkit.org/show_bug.cgi?id=46407 + + Instead of always rebaselining all failing tests, allow a subset to be + chosen. + + * Scripts/webkitpy/common/system/user.py: + * Scripts/webkitpy/tool/commands/rebaseline.py: + +2010-09-24 Ryosuke Niwa <rniwa@webkit.org> + + Reviewed by Tony Chang. + + [chromium] Implement TextInputController::firstRectForCharacterRange + https://bugs.webkit.org/show_bug.cgi?id=38100 + + Implemented TextInputController::firstRectForCharacterRange for chromium platform. + No new tests are added since we need to implement the same feature in chromium side + in order to enable any tests that uses this function. + + * DumpRenderTree/chromium/TextInputController.cpp: + (TextInputController::firstRectForCharacterRange): Added. + +2010-09-24 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + commit-queue reports land failures as "PASS" + https://bugs.webkit.org/show_bug.cgi?id=46530 + + We were ignoring the return value of land instead of passing it back to + CommitQueue. Of course, this was the one case I forgot to test! + + * Scripts/webkitpy/tool/bot/commitqueuetask.py: + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: + +2010-09-24 Kenichi Ishibashi <bashi@google.com> + + Reviewed by Eric Seidel. + + new-run-webkit-tests prints out nothing when build-dumprendertree fails + https://bugs.webkit.org/show_bug.cgi?id=37563 + + Print error message when build-dumprendertree fails. + + * Scripts/webkitpy/layout_tests/port/webkit.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-09-24 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Tony Chang. + + NRWT doesn't respect config set with set-webkit-configuration + https://bugs.webkit.org/show_bug.cgi?id=46278 + + Use Port.default_configuration() instead of hardcoding Release in + ChromiumPort configuration initialization, so that we still inherit the + configuration set by set-webkit-configuration. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-09-24 Chang Shu <chang.shu@nokia.com> + + Reviewed by Csaba Osztrogonác. + + [Qt] Fix the code to check file existence. + https://bugs.webkit.org/show_bug.cgi?id=46465 + + * QtTestBrowser/main.cpp: + (main): + +2010-09-23 Tony Chang <tony@chromium.org> + + Unreviewed, rolling out r68232. + http://trac.webkit.org/changeset/68232 + + Broken NRWT on the canary bots. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-09-23 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + r68008 broke new-run-webkit-tests in that the chromium ports no + longer respect set-webkit-configuration. The correct fix for this + is being pursued in bug 46278 (along with a bunch of unit tests), + but in the meantime I'm reverting the particular lines that broke + things. This was tested by hand. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-09-23 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + WebKit2 API: Need way to know when a frame is removed from the hierarchy + <rdar://problem/8414062> + https://bugs.webkit.org/show_bug.cgi?id=46432 + + * MiniBrowser/mac/BrowserWindowController.m: + (didRemoveFrameFromHierarchy): + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::InjectedBundlePage): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + +2010-09-23 Tony Chang <tony@chromium.org> + + Reviewed by Dimitri Glazkov. + + [chromium] implement layoutTestController.sampleSVGAnimationForElementAtTime + https://bugs.webkit.org/show_bug.cgi?id=46426 + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::sampleSVGAnimationForElementAtTime): + * DumpRenderTree/chromium/LayoutTestController.h: + +2010-09-23 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Nate Chapin. + + [GTK] r68199 introduced two test failures + https://bugs.webkit.org/show_bug.cgi?id=46424 + + Fix a regression handling preference overrides that are attached to boolean properties. + + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::overridePreference): g_strcasecmp returns 0 when strings match + so we must check for that when converting a string to a boolean. + +2010-09-23 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by David Levin. + + Fix a condition check in ServerProcess, which becomes relevant when reading binary data. + https://bugs.webkit.org/show_bug.cgi?id=46406 + + This breaks when the method is called with specified size of data (image data), and the + buffer hasn't yet reached this size. + + * Scripts/webkitpy/layout_tests/port/server_process.py: Changed to check for values of + index larger than 0. + +2010-09-23 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Nate Chapin. + + [GTK] Some tests from r68174 fail on the GTK+ bots + https://bugs.webkit.org/show_bug.cgi?id=46396 + + Simplify LayoutTestController::overridePreference to make it easier for + people unfamiliar with the code to keep the list of preferences up to date. + Add the conversion for enable-hyperlink-auditing. + + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::overridePreference): Use a simple if-else block to determine + out the property name for overrridePreference. Also simplify the logic for setting + string properties. Add the conversion for enable-hyperlink-auditing. + +2010-09-23 Tony Chang <tony@chromium.org> + + Reviewed by David Levin. + + [chromium] add caretBrowsingEnabled to WebSettings and DRT + https://bugs.webkit.org/show_bug.cgi?id=46388 + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::overridePreference): + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::reset): + (WebPreferences::applyTo): + * DumpRenderTree/chromium/WebPreferences.h: + +2010-09-23 Nate Chapin <japhet@chromium.org> + + Reviewed by Darin Fisher. + + Allow DRT to toggle hyperlink auditing (i.e., <a ping>). + https://bugs.webkit.org/show_bug.cgi?id=30458 + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::overridePreference): + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::reset): + (WebPreferences::applyTo): + * DumpRenderTree/chromium/WebPreferences.h: + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::overridePreference): + +2010-09-21 Stephen White <senorblanco@chromium.org> + + Reviewed by David Levin. + + Implement --enable-accelerated-2d-canvas flag in DumpRenderTree. + https://bugs.webkit.org/show_bug.cgi?id=46208 + + This flag allows the layout tests to be run with or without accelerated + 2D canvas rendering. + + * DumpRenderTree/chromium/DumpRenderTree.cpp: + (main): + Declare the new flag string, and check for it on startup. + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::TestShell): + Add a boolean for the new flag, in order to preserve its value over + preferences reset. + (TestShell::resetWebSettings): + Set the new flag to the stored value on reset. + * DumpRenderTree/chromium/TestShell.h: + (TestShell::setAccelerated2dCanvasEnabled): + Add an accessor for the new flag. + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::reset): + Initialize the new flag to false. + (WebPreferences::applyTo): + Copy the flag's value to the WebSettings. + * DumpRenderTree/chromium/WebPreferences.h: + Add the new flag. + +2010-09-23 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Refactor QtWebKitPlatformPlugin interface + + Make it easier to keep source-compability for the + QtWebKitPlatformPlugin interface, and run qmake + on the example (but not build) for convenience. + + https://bugs.webkit.org/show_bug.cgi?id=46345 + + * Scripts/webkitdirs.pm: + +2010-09-23 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Tweak some status messages that Eric thought were confusing + https://bugs.webkit.org/show_bug.cgi?id=46342 + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-09-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Fix comm-queue typo + https://bugs.webkit.org/show_bug.cgi?id=46339 + + We were missing a "self". The real problem is that we didn't have an + integration test for the failure case. + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-09-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + commit-queue should log more detailed messages to the QueueStatusServer + https://bugs.webkit.org/show_bug.cgi?id=46333 + + When I created CommitQueueTask, I removed most of the previous logging. + This patch adds back more detailed logging so folks can see their patch + progress through the queue. + + * Scripts/webkitpy/tool/bot/commitqueuetask.py: + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-09-22 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] User style layout tests don't pass on Chromium + https://bugs.webkit.org/show_bug.cgi?id=46069 + + Fix a typo in LayoutTestController::addUserStyleSheet that was causing a + crash the Chromium DRT. Pass InjectInExistingDocuments to mimic DRT + behavior from other ports. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::addUserStyleSheet): + +2010-09-22 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Martin Robinson. + + [WinCairo] Part 2: Update WebKitTestRunner and DumpRenderTree Build. + https://bugs.webkit.org/show_bug.cgi?id=46303. + + * MiniBrowser/Configurations/MiniBrowserCFLite.vsprops: Added. + * MiniBrowser/Configurations/MiniBrowserCommon.vsprops: Moved + CoreFoundation-specific stuff to new MiniBrowserCoreFoundation + property sheet. + * MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops: Added. + * MiniBrowser/MiniBrowser.vcproj: Updated configuration to use + appropriate property sheet for the build types. + * WebKitTestRunner/win/WebKitTestRunner.vcproj: Updated the + configuration to use appropriate property sheet for CoreFoundation + and CFLite-style builds. + +2010-09-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Optimize commit-queue performance for green trees + https://bugs.webkit.org/show_bug.cgi?id=46254 + + This patch redesigns the controller logic for the commit-queue. In the + new design, the controller exercises much finer-grained control over + the landing process. In particular: + + - Patches that fail to apply now get rejected almost immediately. + - Patches that fail to build get rejects after two builds (instead of + three builds and one test run). + - Patches that run into a flaky test now get accepted after one build + and two test runs instead of three full build-and-test runs. + + The main cost of these optimizations is that we don't find out the tree + has a failing test until the very end of the process, but if the tree + has a busted test, there's not much we can do anyway. We might as well + burn commit-queue resources spinning optimisticly. + + * Scripts/webkitpy/tool/bot/commitqueuetask.py: Added. + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: Added. + * Scripts/webkitpy/tool/commands/queues.py: + +2010-09-22 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Martin Robinson. + + [WinCairo] Update WebKitTestRunner and DumpRenderTree Build. + https://bugs.webkit.org/show_bug.cgi?id=46303. + + * DumpRenderTree/win/DumpRenderTree.vcproj: Disable local MD5 sources + for Cairo build. Copy wtf MD5 header to ForwardingHeaders for the + WinCairo build. + * WebKitTestRunner/Configurations/InjectedBundleCFLite.vsprops: Added. + * WebKitTestRunner/win/InjectedBundle.vcproj: Update win new *_Cairo + build targets that use the new InjectedBundleCFLite.vsprops file. + +2010-09-22 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Fix bustage of rebaseline-chromium-webkit-tests resulting from + r67974. Really need better unit tests for this tool :( + + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + +2010-09-22 Adam Roben <aroben@apple.com> + + Unbreak test-webkitpy + + * Scripts/webkitpy/test/main.py: + (Tester.run_tests): Add a line that mysteriously got deleted. + +2010-09-22 Adam Roben <aroben@apple.com> + + Make test-webkitpy test WebKit2's scripts + + These scripts can't be in WebKitTools due to limitations of Apple's + build process. But that doesn't mean we can't test them! + + Fixes <http://webkit.org/b/46297> test-webkitpy should test code in + WebKit2/Scripts + + Reviewed by Adam Barth. + + * Scripts/test-webkitpy: + (_clean_packages_with_test): Renamed from _clean_webkitpy_with_test. + Now takes an external_package_paths parameter and cleans both webkitpy + and any external packages. + (init): Added an external_package_paths parameter which we pass along + to _clean_packages_with_test. + (top level): Add WebKit2/Scripts/webkit2 as our only external package + and pass it along to init and Tester.run_tests. + + * Scripts/webkitpy/test/main.py: + (Tester.run_tests): Added an optional external_package_paths + parameter. We modify sys.path so that the external packages can be + imported, and search for unittest files inside all external packages + in addition to inside webkitpy. + +2010-09-22 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Tony Chang. + + new-run-webkit-tests: r68063 broke linux python tests + + Add a missing "from __future__ import with_statement" to this + new file; the perils of testing only on the Mac and by review :( + + https://bugs.webkit.org/show_bug.cgi?id=46293 + + * Scripts/webkitpy/layout_tests/port/chromium_gpu.py: + +2010-09-22 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Tony Chang. + + Add a 'chromium-gpu' set of ports that will test the accelerated + GPU paths. This patch adds: + + - support for the '--accelerated-compositing' and + 'accelerated-2d-canvas' flags to new-run-webkit-tests (and the + 'no-' flags) + - adds a new set of Ports that will look under + platform/chromium-gpu-$OS/ for baselines before looking in the + regular chromium search path + - adds a new test_expectations.txt file in platform/chromium-gpu + that skips all but the tests we actually want to run with + acceleration. + + This patch will allow us to run both with and without acceleration + and to change the defaults for both the regular and -gpu options + as the code evolves. + + We plan to add both --chromium-$OS and --chromium-gpu-$OS runs to + each test bot. + + https://bugs.webkit.org/show_bug.cgi?id=46225 + + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/chromium_gpu.py: + * Scripts/webkitpy/layout_tests/port/factory.py: + * Scripts/webkitpy/layout_tests/port/webkit.py: + +2010-09-22 Jamey Hicks <jamey.hicks@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Web Inspector: Remote Web Inspector support for QtWebKit + https://bugs.webkit.org/show_bug.cgi?id=43988 + + Runs a web debug server on port specified by QtTestBrowser + argument -remote-inspector-port. Property + _q_webInspectorServerPort of the QWebPage instance will be set + according to the argument. All pages with that property set will + be remotely inspectable. + + URL for remote inspection of first QWebPage is + http://localhost:9222/webkit/inspector/inspector.html?page=1 + where 1 is the number of the QWebPage instance. + + The base URL yields an index page with links to the individual inspectors: + http://localhost:9222/ + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::init): + * QtTestBrowser/launcherwindow.h: + * QtTestBrowser/main.cpp: + (LauncherApplication::handleUserOptions): + +2010-09-22 Adam Roben <aroben@apple.com> + + Fix webkit-patch failure-reason now that build.webkit.org has been + updated + + Fixes <http://webkit.org/b/46273> webkit-patch failure-reason crashes + every time + + Reviewed by Eric Seidel. + + * Scripts/webkitpy/common/net/buildbot.py: + (BuildBot._file_cell_text): Added. Travels down the firstChild chain + looking for an element that contains text, then returns it. + (BuildBot._parse_twisted_file_row): Use _file_cell_text to get the + text out of the cells. This way it doesn't matter whether the cells + have <b> children (as for cells in directory rows) or not (as for + cells in file rows) + (BuildBot._parse_twisted_directory_listing): Look for rows that have + the "directory" or "file" class, rather than rows with any class, + since header rows now have a class attribute. + + * Scripts/webkitpy/common/net/buildbot_unittest.py: + (BuildBotTest._example_directory_listing): Updated to more closely + match the markup that build.webkit.org is producing now. + +2010-09-21 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + new-run-webkit-tests: fix bug introduced in r68008 where if you + specify --chromium and no --platform, and you're running on + windows, you use the 'chromium-win' port by default instead of the + version-specific port. This breaks the buildbots. + + It will be good for this refactoring to settle down so I can + rewrite the logic for default ports and the unit tests to be + clearer (and the testing more comprehensive). + + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + +2010-09-21 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Adam Barth. + + Modify the Port interface to take only a series of keyword arguments + in the constructor, and modify Port/factory.get() to accomodate that, + and to accept user=XXX as an argument so we can pass + webkitpy.common.system.user.User objects in. + + Then, modify new-run-webkit-tests and rebaseline-chromium-webkit-tests + to use the common routine in webkitpy.common.system.user.open_url() + to display HTML files. + + There was a routine in the Port interface to do the same thing, + but I see no need for a port-specific hook for this, since it is + something that will always be executed by the host environment + and displaying web pages has nothing to do with running layout tests. + + Note that new-run-webkit-tests used to use test_shell to display + the page; this is potentially useful so that you can actually click + from a result to the broken page; however, since DumpRenderTree + doesn't support this functionality, it will be going away eventually. + + https://bugs.webkit.org/show_bug.cgi?id=46128 + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/chromium_linux.py: + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + * Scripts/webkitpy/layout_tests/port/dryrun.py: + * Scripts/webkitpy/layout_tests/port/factory.py: + * Scripts/webkitpy/layout_tests/port/google_chrome.py: + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + * Scripts/webkitpy/layout_tests/port/gtk.py: + * Scripts/webkitpy/layout_tests/port/mac.py: + * Scripts/webkitpy/layout_tests/port/qt.py: + * Scripts/webkitpy/layout_tests/port/test.py: + * Scripts/webkitpy/layout_tests/port/webkit.py: + * Scripts/webkitpy/layout_tests/port/win.py: + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-09-21 Lucas De Marchi <lucas.demarchi@profusion.mobi> + + Reviewed by Kenneth Rohde Christiansen. + + [EFL] Get fresh theme when running EWebLauncher + https://bugs.webkit.org/show_bug.cgi?id=46210 + + If user tried to run EWebLauncher outside of the build tree, it would + not find the theme and fallback to the installed one. However, since + EWebLauncher is not installed, we always want to take the theme from + the just compiled source code. If user had never installed WebKit's + EFL port it could even receive a segv since no theme would be found. + + Now EWebLauncher does not fallback to the installed theme and CMake + gives as DATA_DIR the directory of the theme it has just built. + + * CMakeListsEfl.txt: Pass the build directory as DATA_DIR to + EWebLauncher. + * EWebLauncher/main.c: Use only the theme from build director. Do not + fallback to others as this could hide real bugs. + (quit): + (browserCreate): + (findThemePath): + (main): + +2010-09-21 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Don't pass the --test-shell arg to the Chromium Mac port of DRT; + it just confuses it. + + https://bugs.webkit.org/show_bug.cgi?id=46230 + + * Scripts/webkitpy/layout_tests/port/webkit.py: + +2010-09-21 Lucas Forschler <lforschler@apple.com> + + Reviewed by Stephanie Lewis. + + Make a new buildbot for Leopard Debug Test + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2010-09-21 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Fix breakage of Chromium Mac DRT port caused by r67905. + + https://bugs.webkit.org/show_bug.cgi?id=46230 + + * Scripts/webkitpy/layout_tests/port/webkit.py: + +2010-09-21 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Add missing import of 'tempfile'. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-09-17 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Ojan Vafai. + + new-run-webkit-tests: pull the list of tests from the Port, and + make it possible to run with no actual test files in the filesystem. + + This set of changes allows us to delete the special + webkitpy/layout_tests/data directory and test the generic code without + touching the filesystem (except to write results). This speeds up + test-webkitpy substantially. + + This also cleans up and removes several code paths in the generic + code and fixes some minor bugs, notably in the test_expectations + parsing, which was previously fragile if the tests weren't present. + + We also change the way we diff image results to be able to do so + in memory, without relying on files. This slows down chromium + test_shell, which always writes images to files, but should speed + up DRT and ImageDiff-based implementations slightly. + + Note that pulling the list of tests to run from the Port will allow + ports to specify what tests to run as an inclusive list; previously + you could only do this as an exclusive list by using a + test_expectations file or Skipped files; nothing actually uses this + feature yet and it's unclear if it should be used. + + Note that there are no functional changes -- apart from now + always printing out the location of the checksum file when we are + tracing test runs -- and the total number of lines of non-test code + actually drops by two. + + There is some more cleanup that can be done in the Port/Driver + interface and in some handling of filenames, but I'll save that + for another change. + + https://bugs.webkit.org/show_bug.cgi?id=45801 + + * Scripts/webkitpy/layout_tests/data/*: Removed. + - no longer need special mock layout_tests_directory in the + repository. + * Scripts/webkitpy/layout_tests/layout_package/printing.py: + - add code to display missing text files, checksums when tracing + - update to not look at the filesystem directly. + * Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py: + - add more unit tests + * Scripts/webkitpy/layout_tests/layout_package/test_expectations.py: + - remove tests_are_present flag + - update with changes in Port interface - no longer access + the filesystem directly, although we still use os.path for + filename manipulation. + * Scripts/webkitpy/layout_tests/layout_package/test_expectations_unittest.py: + - add more unit tests + * Scripts/webkitpy/layout_tests/layout_package/test_files.py: Removed. + - renamed to port/test_files.py + * Scripts/webkitpy/layout_tests/port/base.py: + - change diff_image() to expect actual image data, not filenames + - add expected_checksum(), expected_image(), expected_text() to + return the content of the files so that we don't need a filesystem + - add path_exists(), path_isdir() for filesystem-like access. + - add test_dirs() to keep clobber-test-results from needing to + actually look at a real layout tests dir + - add tests() to return the list of tests to run on the port + (calls port/test_files to do the work). + - add update_baseline() to be able to save new baselines + - add uri_to_test_name() from port/dryrun.py so we can easily check + filename_to_uri() + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + - add more unit tests + * Scripts/webkitpy/layout_tests/port/chromium.py: + - change diff_image() to accept image content, not filenames. + This will be slower for test_shell/image_diff, but faster + for DRT/ImageDiff. + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + - add more unit tests + * Scripts/webkitpy/layout_tests/port/dryrun.py: + - simplify greatly + * Scripts/webkitpy/layout_tests/port/port_testcase.py: + - add more unit tests + * Scripts/webkitpy/layout_tests/port/test.py: + - massive rewrite to use in-script list of tests and expectations + * Scripts/webkitpy/layout_tests/port/test_files.py: + - rename from layout_package/test_files. + * Scripts/webkitpy/layout_tests/port/test_files_unittest.py: + - add unit tests + * Scripts/webkitpy/layout_tests/port/webkit.py: + - update diff_image() to take image contents, not files. Should + make things slightly faster. + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + - update with changes to diff_image() + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py: + - update with changes to diff_image() + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + - remove tests_are_present from test_expectations + - pull the list of tests from port.tests() instead + of calling test_files.py directly. + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + - update unit tests + * Scripts/webkitpy/layout_tests/test_types/image_diff.py: + - update with changes to + * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: + - update with change in Port interface + * Scripts/webkitpy/layout_tests/test_types/text_diff.py: + - update with change in Port interface + * Scripts/webkitpy/style/checkers/test_expectations.py: + - remove the tests_are_present flag + +2010-09-21 Anders Carlsson <andersca@apple.com> + + Disable logging. + + * MiniBrowser/mac/MiniBrowser_Prefix.pch: + +2010-09-21 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + add a script for running webkit_unit_tests + https://bugs.webkit.org/show_bug.cgi?id=46014 + + * Scripts/run-chromium-webkit-unit-tests: Added. + +2010-09-21 Fridrich Strba <fridrich.strba@bluewin.ch> + + Reviewed by Martin Robinson. + + Fix linking problems on Windows. + https://bugs.webkit.org/show_bug.cgi?id=45844 + + * GNUmakefile.am: link the executables with winmm.dll + +2010-09-21 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + feeder-queue svn updates more often than needed + https://bugs.webkit.org/show_bug.cgi?id=46171 + + We don't need to poll SVN every time we feed the feeders. Rather, we + can count on the wrapper shell script to auto-update the queue. + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-09-21 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] Add robot loader timeout and extra time options. + https://bugs.webkit.org/show_bug.cgi?id=46172 + + [-robot-timeout <s>]: Load the next page after s seconds if the current + page didn't finish loading. + [-robot-extra-time <s>]: Wait s seconds after the current page finished + loading before loading the next one. This should allow some time for the + page's JavaScript to execute. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::applyPrefs): + * QtTestBrowser/main.cpp: + (LauncherApplication::robotTimeout): + (LauncherApplication::robotExtraTime): + (LauncherApplication::LauncherApplication): + (LauncherApplication::handleUserOptions): + (main): + * QtTestBrowser/urlloader.cpp: + (UrlLoader::UrlLoader): + (UrlLoader::loadNext): + (UrlLoader::loadUrlList): + * QtTestBrowser/urlloader.h: + +2010-09-21 Pavel Podivilov <podivilov@chromium.org> + + Unreviewed. + + Adding myself to the committers list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-09-20 Philippe Normand <pnormand@igalia.com> + + Reviewed by Eric Carlson. + + [GTK] enhanced context menu for media elements + https://bugs.webkit.org/show_bug.cgi?id=45021 + + EventSender::contextClick() now returns an array of js + objects. Each object has a title property and a click() method. + + * DumpRenderTree/gtk/EventSender.cpp: + (getMenuItemTitleCallback): + (setMenuItemTitleCallback): + (menuItemClickCallback): + (getMenuItemClass): + (contextClickCallback): + +2010-09-20 Hayato Ito <hayato@chromium.org> + + Unreviewed. + Adding myself to the committers list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-09-20 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + The tool member variable should be called _tool + https://bugs.webkit.org/show_bug.cgi?id=46160 + + Created by find-and-replace. + + * Scripts/webkitpy/tool/commands/download.py: + * Scripts/webkitpy/tool/commands/openbugs.py: + * Scripts/webkitpy/tool/commands/queries.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/commands/rebaseline.py: + * Scripts/webkitpy/tool/commands/sheriffbot.py: + * Scripts/webkitpy/tool/commands/upload.py: + * Scripts/webkitpy/tool/multicommandtool.py: + +2010-09-20 Adam Barth <abarth@webkit.org> + + I ran the tests before landing but ignored the fact that they failed. :( + + * Scripts/webkitpy/tool/commands/queues.py: + +2010-09-20 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add a feeder queue that polls bugs.webkit.org for the commit-cluster + https://bugs.webkit.org/show_bug.cgi?id=46141 + + The feeder-queue polls bugs.webkit.org every 30 seconds and updates the + list of work items on the status server. The individual commit-cluster + nodes then grab the patches from the server and process them. + + * Scripts/webkitpy/tool/bot/feeders.py: Added. + * Scripts/webkitpy/tool/bot/feeders_unittest.py: Added. + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/commands/queuestest.py: + +2010-09-20 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Darin Adler. + + build-webkit: Add support for CMake build system + https://bugs.webkit.org/show_bug.cgi?id=44979 + + * Scripts/build-webkit: Add "--efl" command-line option to build the + EFL port of WebKit. + * Scripts/webkitdirs.pm: Define buildCMakeProject() and + buildEflCMakeProject() subroutines. + 2010-09-20 Dirk Pranke <dpranke@chromium.org> Reviewed by Ojan Vafai. diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp index 1643ba6..ee44325 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -513,6 +513,24 @@ static JSValueRef computedStyleIncludingVisitedInfoCallback(JSContextRef context return controller->computedStyleIncludingVisitedInfo(context, arguments[0]); } +static JSValueRef nodesFromRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount != 8) + return JSValueMakeUndefined(context); + + int x = JSValueToNumber(context, arguments[1], NULL); + int y = JSValueToNumber(context, arguments[2], NULL); + int top = static_cast<unsigned>(JSValueToNumber(context, arguments[3], NULL)); + int right = static_cast<unsigned>(JSValueToNumber(context, arguments[4], NULL)); + int bottom = static_cast<unsigned>(JSValueToNumber(context, arguments[5], NULL)); + int left = static_cast<unsigned>(JSValueToNumber(context, arguments[6], NULL)); + bool ignoreClipping = JSValueToBoolean(context, arguments[7]); + + // Has mac implementation. + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + return controller->nodesFromRect(context, arguments[0], x, y, top, right, bottom, left, ignoreClipping); +} + static JSValueRef layerTreeAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -1843,6 +1861,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "closeWebInspector", closeWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "computedStyleIncludingVisitedInfo", computedStyleIncludingVisitedInfoCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "nodesFromRect", nodesFromRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "disableImageLoading", disableImageLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dispatchPendingLoadRequests", dispatchPendingLoadRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h index 2bf7a75..755a2b2 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -60,6 +60,7 @@ public: bool isCommandEnabled(JSStringRef name); void keepWebHistory(); JSValueRef computedStyleIncludingVisitedInfo(JSContextRef, JSValueRef); + JSValueRef nodesFromRect(JSContextRef, JSValueRef, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping); void notifyDone(); int numberOfPages(float pageWidthInPixels, float pageHeightInPixels); void overridePreference(JSStringRef key, JSStringRef value); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp index 5002400..1df1c76 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp @@ -971,15 +971,18 @@ static NPObject *pluginAllocate(NPP npp, NPClass *theClass) newInstance->returnNegativeOneFromWrite = FALSE; newInstance->stream = 0; - newInstance->firstUrl = NULL; - newInstance->firstHeaders = NULL; - newInstance->lastUrl = NULL; - newInstance->lastHeaders = NULL; + newInstance->firstUrl = 0; + newInstance->firstHeaders = 0; + newInstance->lastUrl = 0; + newInstance->lastHeaders = 0; newInstance->testGetURLOnDestroy = FALSE; newInstance->testWindowOpen = FALSE; newInstance->testKeyboardFocusForPlugins = FALSE; + newInstance->mouseDownForEvaluateScript = FALSE; + newInstance->evaluateScriptOnMouseDownOrKeyDown = 0; + return (NPObject*)newInstance; } diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.h index 2c1d325..6c30578 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.h +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginObject.h @@ -57,6 +57,7 @@ typedef struct { NPBool testGetURLOnDestroy; NPBool testWindowOpen; NPBool testKeyboardFocusForPlugins; + NPBool mouseDownForEvaluateScript; char* onStreamLoad; char* onStreamDestroy; char* onDestroy; @@ -66,6 +67,7 @@ typedef struct { char* firstHeaders; char* lastUrl; char* lastHeaders; + char* evaluateScriptOnMouseDownOrKeyDown; #ifdef XP_MACOSX NPEventModel eventModel; #endif diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp index 0ff7029..83eda3a 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp @@ -60,6 +60,11 @@ NPError PluginTest::NPP_GetValue(NPPVariable variable, void *value) return NPERR_GENERIC_ERROR; } +NPError PluginTest::NPP_SetWindow(NPP, NPWindow*) +{ + return NPERR_NO_ERROR; +} + NPIdentifier PluginTest::NPN_GetStringIdentifier(const NPUTF8 *name) { return browser->getstringidentifier(name); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h index ecc0185..2e896a6 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h @@ -57,6 +57,7 @@ public: // NPP functions. virtual NPError NPP_DestroyStream(NPStream* stream, NPReason reason); virtual NPError NPP_GetValue(NPPVariable, void* value); + virtual NPError NPP_SetWindow(NPP, NPWindow*); // NPN functions. NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp new file mode 100644 index 0000000..40bceb9 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 Apple 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 "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Plugin's HWND should be sized/positioned before NPP_SetWindow is called. + +class WindowGeometryInitializedBeforeSetWindow : public PluginTest { +public: + WindowGeometryInitializedBeforeSetWindow(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + virtual NPError NPP_SetWindow(NPP instance, NPWindow* window) + { + if (window->type != NPWindowTypeWindow) { + pluginLog(instance, "window->type should be NPWindowTypeWindow but was %d", window->type); + return NPERR_GENERIC_ERROR; + } + + HWND hwnd = reinterpret_cast<HWND>(window->window); + RECT rect; + if (!::GetClientRect(hwnd, &rect)) { + pluginLog(instance, "::GetClientRect failed"); + return NPERR_GENERIC_ERROR; + } + + if (::IsRectEmpty(&rect)) { + pluginLog(instance, "Plugin's HWND has not been sized when NPP_SetWindow is called"); + return NPERR_GENERIC_ERROR; + } + + HWND parent = ::GetParent(hwnd); + if (!parent) { + pluginLog(instance, "::GetParent failed"); + return NPERR_GENERIC_ERROR; + } + + // MSDN says that calling ::MapWindowPoints this way will tell it we're passing a RECT rather than two POINTs. + if (!::MapWindowPoints(hwnd, parent, reinterpret_cast<POINT*>(&rect), 2)) { + pluginLog(instance, "::MapWindowPoints failed"); + return NPERR_GENERIC_ERROR; + } + + if (rect.left != window->x || rect.top != window->y || (rect.right - rect.left) != window->width || (rect.bottom - rect.top) != window->height) { + pluginLog(instance, "HWND's rect and NPWindow's rect are not equal"); + return NPERR_GENERIC_ERROR; + } + + pluginLog(instance, "Plugin's HWND has been sized and positioned before NPP_SetWindow was called"); + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<WindowGeometryInitializedBeforeSetWindow> windowGeometryInitializedBeforeSetWindow("window-geometry-initialized-before-set-window"); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp index c02e918..dd894f4 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp @@ -218,8 +218,20 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc // FIXME: When https://bugs.webkit.org/show_bug.cgi?id=41831 is fixed, this #ifdef can be removed. obj->testGetURLOnDestroy = TRUE; #endif - } else if (strcasecmp(argn[i], "src") == 0 && strstr(argv[i], "plugin-document-has-focus.pl")) + } else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-document-has-focus.pl")) obj->testKeyboardFocusForPlugins = TRUE; + else if (!strcasecmp(argn[i], "evaluatescript")) { + char* script = argv[i]; + if (script == strstr(script, "mouse::")) { + obj->mouseDownForEvaluateScript = true; + obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("mouse::") - 1); + } else if (script == strstr(script, "key::")) { + obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("key::") - 1); + } + // When testing evaluate script on mouse-down or key-down, allow event logging to handle events. + if (obj->evaluateScriptOnMouseDownOrKeyDown) + obj->eventLogging = true; + } } #if XP_MACOSX @@ -300,7 +312,7 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) } } - return NPERR_NO_ERROR; + return obj->pluginTest->NPP_SetWindow(instance, window); } static void executeScript(const PluginObject* obj, const char* script) @@ -401,6 +413,8 @@ static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* e case mouseDown: GlobalToLocal(&pt); pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v); + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); break; case mouseUp: GlobalToLocal(&pt); @@ -408,6 +422,8 @@ static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* e break; case keyDown: pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); break; case keyUp: pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF)); @@ -481,6 +497,8 @@ static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* e case NPCocoaEventKeyDown: if (event->data.key.characters) pluginLog(instance, "keyDown '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef>(event->data.key.characters), 0)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); return 1; case NPCocoaEventKeyUp: @@ -501,6 +519,8 @@ static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* e pluginLog(instance, "mouseDown at (%d, %d)", (int)event->data.mouse.pluginX, (int)event->data.mouse.pluginY); + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); return 1; case NPCocoaEventMouseUp: pluginLog(instance, "mouseUp at (%d, %d)", diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj index c36666f..5ffb832 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj @@ -367,6 +367,34 @@ <References>
</References>
<Files>
+ <Filter
+ Name="Tests"
+ >
+ <File
+ RelativePath="..\Tests\DocumentOpenInDestroyStream.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\NPRuntimeObjectFromDestroyedPlugin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\NPRuntimeRemoveProperty.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\PluginScriptableNPObjectInvokeDefault.cpp"
+ >
+ </File>
+ <Filter
+ Name="win"
+ >
+ <File
+ RelativePath="..\Tests\win\WindowGeometryInitializedBeforeSetWindow.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
<File
RelativePath="..\main.cpp"
>
@@ -456,26 +484,6 @@ RelativePath="..\TestObject.h"
>
</File>
- <Filter
- Name="Tests"
- >
- <File
- RelativePath="..\Tests\DocumentOpenInDestroyStream.cpp"
- >
- </File>
- <File
- RelativePath="..\Tests\NPRuntimeObjectFromDestroyedPlugin.cpp"
- >
- </File>
- <File
- RelativePath="..\Tests\NPRuntimeRemoveProperty.cpp"
- >
- </File>
- <File
- RelativePath="..\Tests\PluginScriptableNPObjectInvokeDefault.cpp"
- >
- </File>
- </Filter>
</Files>
<Globals>
</Globals>
diff --git a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp index 6e180d0..b2e50f7 100644 --- a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp @@ -48,6 +48,7 @@ static const char optionTestShell[] = "--test-shell"; static const char optionAllowExternalPages[] = "--allow-external-pages"; static const char optionStartupDialog[] = "--testshell-startup-dialog"; static const char optionCheckLayoutTestSystemDeps[] = "--check-layout-test-sys-deps"; +static const char optionEnableAccelerated2DCanvas[] = "--enable-accelerated-2d-canvas"; static void runTest(TestShell& shell, TestParams& params, const string& testName, bool testShellMode) { @@ -92,6 +93,7 @@ int main(int argc, char* argv[]) bool testShellMode = false; bool allowExternalPages = false; bool startupDialog = false; + bool accelerated2DCanvasEnabled = false; for (int i = 1; i < argc; ++i) { string argument(argv[i]); if (argument == "-") @@ -112,6 +114,8 @@ int main(int argc, char* argv[]) startupDialog = true; else if (argument == optionCheckLayoutTestSystemDeps) exit(checkLayoutTestSystemDependencies() ? EXIT_SUCCESS : EXIT_FAILURE); + else if (argument == optionEnableAccelerated2DCanvas) + accelerated2DCanvasEnabled = true; else if (argument.size() && argument[0] == '-') fprintf(stderr, "Unknown option: %s\n", argv[i]); else @@ -128,6 +132,7 @@ int main(int argc, char* argv[]) { // Explicit scope for the TestShell instance. TestShell shell(testShellMode); shell.setAllowExternalPages(allowExternalPages); + shell.setAccelerated2dCanvasEnabled(accelerated2DCanvasEnabled); if (serverMode && !tests.size()) { params.printSeparators = true; char testString[2048]; // 2048 is the same as the sizes of other platforms. diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp index 2c6c600..3d3c204 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp @@ -126,6 +126,7 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("removeOriginAccessWhitelistEntry", &LayoutTestController::removeOriginAccessWhitelistEntry); bindMethod("repaintSweepHorizontally", &LayoutTestController::repaintSweepHorizontally); bindMethod("resumeAnimations", &LayoutTestController::resumeAnimations); + bindMethod("sampleSVGAnimationForElementAtTime", &LayoutTestController::sampleSVGAnimationForElementAtTime); bindMethod("setAcceptsEditing", &LayoutTestController::setAcceptsEditing); bindMethod("setAllowFileAccessFromFileURLs", &LayoutTestController::setAllowFileAccessFromFileURLs); bindMethod("setAllowUniversalAccessFromFileURLs", &LayoutTestController::setAllowUniversalAccessFromFileURLs); @@ -959,6 +960,19 @@ void LayoutTestController::resumeAnimations(const CppArgumentList&, CppVariant* result->setNull(); } +void LayoutTestController::sampleSVGAnimationForElementAtTime(const CppArgumentList& arguments, CppVariant* result) +{ + if (arguments.size() != 3) { + result->setNull(); + return; + } + WebString animationId = cppVariantToWebString(arguments[0]); + double time = arguments[1].toDouble(); + WebString elementId = cppVariantToWebString(arguments[2]); + bool success = m_shell->webView()->mainFrame()->pauseSVGAnimation(animationId, time, elementId); + result->set(success); +} + void LayoutTestController::disableImageLoading(const CppArgumentList&, CppVariant* result) { m_shell->preferences()->loadsImagesAutomatically = false; @@ -1251,6 +1265,10 @@ void LayoutTestController::overridePreference(const CppArgumentList& arguments, prefs->tabsToLinks = cppVariantToBool(value); else if (key == "WebKitWebGLEnabled") prefs->experimentalWebGLEnabled = cppVariantToBool(value); + else if (key == "WebKitHyperlinkAuditingEnabled") + prefs->hyperlinkAuditingEnabled = cppVariantToBool(value); + else if (key == "WebKitEnableCaretBrowsing") + prefs->caretBrowsingEnabled = cppVariantToBool(value); else { string message("Invalid name for preference: "); message.append(key); @@ -1443,7 +1461,10 @@ void LayoutTestController::addUserStyleSheet(const CppArgumentList& arguments, C return; WebView::addUserStyleSheet( cppVariantToWebString(arguments[0]), WebVector<WebString>(), - arguments[2].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly); + arguments[1].toBoolean() ? WebView::UserContentInjectInAllFrames : WebView::UserContentInjectInTopFrameOnly, + // Chromium defaults to InjectInSubsequentDocuments, but for compatibility + // with the other ports' DRTs, we use UserStyleInjectInExistingDocuments. + WebView::UserStyleInjectInExistingDocuments); } void LayoutTestController::setEditingBehavior(const CppArgumentList& arguments, CppVariant* results) diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h index ec2503f..8467097 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h @@ -223,6 +223,7 @@ public: void numberOfActiveAnimations(const CppArgumentList&, CppVariant*); void suspendAnimations(const CppArgumentList&, CppVariant*); void resumeAnimations(const CppArgumentList&, CppVariant*); + void sampleSVGAnimationForElementAtTime(const CppArgumentList&, CppVariant*); void disableImageLoading(const CppArgumentList&, CppVariant*); void setIconDatabaseEnabled(const CppArgumentList&, CppVariant*); void dumpSelectionRect(const CppArgumentList&, CppVariant*); diff --git a/WebKitTools/DumpRenderTree/chromium/TestEventPrinter.cpp b/WebKitTools/DumpRenderTree/chromium/TestEventPrinter.cpp index d9e79a0..2130534 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestEventPrinter.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestEventPrinter.cpp @@ -99,7 +99,8 @@ void DRTPrinter::handleImage(const char* actualHash, const char* expectedHash, c printf("\nExpectedHash: %s\n", expectedHash); if (imageData && imageSize) { printf("Content-Type: image/png\n"); - printf("Content-Length: %lu\n", imageSize); + // Printf formatting for size_t on 32-bit, 64-bit, and on Windows is hard so just cast to an int. + printf("Content-Length: %d\n", static_cast<int>(imageSize)); if (fwrite(imageData, 1, imageSize, stdout) != imageSize) { fprintf(stderr, "Short write to stdout.\n"); exit(1); diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp index 15d6dee..1a99b7d 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp @@ -83,6 +83,7 @@ TestShell::TestShell(bool testShellMode) , m_focusedWidget(0) , m_testShellMode(testShellMode) , m_allowExternalPages(false) + , m_accelerated2dCanvasEnabled(false) , m_devTools(0) { WebRuntimeFeatures::enableGeolocation(true); @@ -155,6 +156,7 @@ void TestShell::closeDevTools() void TestShell::resetWebSettings(WebView& webView) { m_prefs.reset(); + m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled; m_prefs.applyTo(&webView); } diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.h b/WebKitTools/DumpRenderTree/chromium/TestShell.h index 6d93d4a..4d022dc 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.h +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.h @@ -123,6 +123,8 @@ public: bool allowExternalPages() const { return m_allowExternalPages; } void setAllowExternalPages(bool allowExternalPages) { m_allowExternalPages = allowExternalPages; } + void setAccelerated2dCanvasEnabled(bool enabled) { m_accelerated2dCanvasEnabled = enabled; } + #if defined(OS_WIN) // Access to the finished event. Used by the static WatchDog thread. HANDLE finishedEvent() { return m_finishedEvent; } @@ -176,6 +178,7 @@ private: TestParams m_params; int m_timeout; // timeout value in millisecond bool m_allowExternalPages; + bool m_accelerated2dCanvasEnabled; WebPreferences m_prefs; // List of all windows in this process. diff --git a/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp b/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp index 60408b9..1cf7c56 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp @@ -134,22 +134,23 @@ static void setupFontconfig() // few layout tests. static const char* const optionalFonts[] = { "/usr/share/fonts/truetype/ttf-lucida/LucidaSansRegular.ttf", - - // This font changed paths across Ubuntu releases. "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_pa.ttf", - "/usr/share/fonts/truetype/ttf-punjabi-fonts/lohit_pa.ttf", }; for (size_t i = 0; i < arraysize(optionalFonts); ++i) { const char* font = optionalFonts[i]; + + // This font changed paths across Ubuntu releases, so try checking in both locations. + if (!strcmp(font, "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_pa.ttf") + && access(font, R_OK) < 0) + font = "/usr/share/fonts/truetype/ttf-punjabi-fonts/lohit_pa.ttf"; + if (access(font, R_OK) < 0) { fprintf(stderr, "You are missing %s. Without this, some layout tests may fail. " "See http://code.google.com/p/chromium/wiki/LinuxBuildInstructionsPrerequisites " "for more.\n", font); - } else { - if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) font)) { - fprintf(stderr, "Failed to load font %s\n", font); - exit(1); - } + } else if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) font)) { + fprintf(stderr, "Failed to load font %s\n", font); + exit(1); } } diff --git a/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp b/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp index 16f1575..4f06874 100644 --- a/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp @@ -32,6 +32,7 @@ #include "TextInputController.h" #include "TestShell.h" +#include "public/WebBindings.h" #include "public/WebFrame.h" #include "public/WebRange.h" #include "public/WebString.h" @@ -186,10 +187,27 @@ void TextInputController::selectedRange(const CppArgumentList&, CppVariant* resu result->set(string(buffer)); } -void TextInputController::firstRectForCharacterRange(const CppArgumentList&, CppVariant* result) +void TextInputController::firstRectForCharacterRange(const CppArgumentList& arguments, CppVariant* result) { - // FIXME: Implement this. result->setNull(); + + WebFrame* mainFrame = getMainFrame(); + if (!mainFrame) + return; + + if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) + return; + + WebRect rect; + if (!mainFrame->firstRectForCharacterRange(arguments[0].toInt32(), arguments[1].toInt32(), rect)) + return; + + Vector<int> intArray(4); + intArray[0] = rect.x; + intArray[1] = rect.y; + intArray[2] = rect.width; + intArray[3] = rect.height; + result->set(WebBindings::makeIntArray(intArray)); } void TextInputController::characterIndexForPoint(const CppArgumentList&, CppVariant* result) diff --git a/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp b/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp index 004865a..35247ef 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp @@ -88,6 +88,7 @@ void WebPreferences::reset() userStyleSheetLocation = WebURL(); usesPageCache = false; webSecurityEnabled = true; + caretBrowsingEnabled = false; // Allow those layout tests running as local files, i.e. under // LayoutTests/http/tests/local, to access http server. @@ -100,6 +101,8 @@ void WebPreferences::reset() #endif tabsToLinks = false; + hyperlinkAuditingEnabled = false; + accelerated2dCanvasEnabled = false; } void WebPreferences::applyTo(WebView* webView) @@ -139,9 +142,11 @@ void WebPreferences::applyTo(WebView* webView) settings->setWebSecurityEnabled(webSecurityEnabled); settings->setAllowUniversalAccessFromFileURLs(allowUniversalAccessFromFileURLs); settings->setEditingBehavior(editingBehavior); + settings->setHyperlinkAuditingEnabled(hyperlinkAuditingEnabled); // LayoutTests were written with Safari Mac in mind which does not allow // tabbing to links by default. webView->setTabsToLinks(tabsToLinks); + settings->setCaretBrowsingEnabled(caretBrowsingEnabled); // Fixed values. settings->setShouldPaintCustomScrollbars(true); @@ -157,5 +162,7 @@ void WebPreferences::applyTo(WebView* webView) // FIXME: crbug.com/51879 settings->setAcceleratedCompositingEnabled(false); + + settings->setAccelerated2dCanvasEnabled(accelerated2dCanvasEnabled); } diff --git a/WebKitTools/DumpRenderTree/chromium/WebPreferences.h b/WebKitTools/DumpRenderTree/chromium/WebPreferences.h index f197c16..c0ea70f 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebPreferences.h +++ b/WebKitTools/DumpRenderTree/chromium/WebPreferences.h @@ -75,6 +75,9 @@ struct WebPreferences { bool allowUniversalAccessFromFileURLs; WebKit::WebSettings::EditingBehavior editingBehavior; bool tabsToLinks; + bool hyperlinkAuditingEnabled; + bool caretBrowsingEnabled; + bool accelerated2dCanvasEnabled; WebPreferences() { reset(); } void reset(); diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp index af2e403..521a0e1 100644 --- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -35,6 +35,7 @@ #include "AccessibilityController.h" #include "EventSender.h" #include "GCController.h" +#include "GOwnPtr.h" #include "LayoutTestController.h" #include "PixelDumpSupport.h" #include "WorkQueue.h" @@ -133,37 +134,81 @@ static void appendString(gchar*& target, gchar* string) static void initializeFonts() { #if PLATFORM(X11) - static int numFonts = -1; - FcInit(); - // Some tests may add or remove fonts via the @font-face rule. - // If that happens, font config should be re-created to suppress any unwanted change. + // If a test resulted a font being added or removed via the @font-face rule, then + // we want to reset the FontConfig configuration to prevent it from affecting other tests. + static int numFonts = 0; FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication); - if (appFontSet && numFonts >= 0 && appFontSet->nfont == numFonts) + if (appFontSet && numFonts && appFontSet->nfont == numFonts) return; - const char* fontDirEnv = g_getenv("WEBKIT_TESTFONTS"); - if (!fontDirEnv) - g_error("WEBKIT_TESTFONTS environment variable is not set, but it should point to the directory " - "containing the fonts you can clone from git://gitorious.org/qtwebkit/testfonts.git\n"); + // Load our configuration file, which sets up proper aliases for family + // names like sans, serif and monospace. + FcConfig* config = FcConfigCreate(); + GOwnPtr<gchar> fontConfigFilename(g_build_filename(FONTS_CONF_DIR, "fonts.conf", NULL)); + if (!FcConfigParseAndLoad(config, reinterpret_cast<FcChar8*>(fontConfigFilename.get()), true)) + g_error("Couldn't load font configuration file from: %s", fontConfigFilename.get()); + + static const char *const fontPaths[][2] = { + { "/usr/share/fonts/truetype/ttf-liberation/LiberationMono-BoldItalic.ttf", + "/usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Bold.ttf", + "/usr/share/fonts/liberation/LiberationMono-Bold.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Italic.ttf", + "/usr/share/fonts/liberation/LiberationMono-Italic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf", + "/usr/share/fonts/liberation/LiberationMono-Regular.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSans-BoldItalic.ttf", + "/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Bold.ttf", + "/usr/share/fonts/liberation/LiberationSans-Bold.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Italic.ttf", + "/usr/share/fonts/liberation/LiberationSans-Italic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Regular.ttf", + "/usr/share/fonts/liberation/LiberationSans-Regular.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-BoldItalic.ttf", + "/usr/share/fonts/liberation/LiberationSerif-BoldItalic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Bold.ttf", + "/usr/share/fonts/liberation/LiberationSerif-Bold.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Italic.ttf", + "/usr/share/fonts/liberation/LiberationSerif-Italic.ttf", }, + { "/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Regular.ttf", + "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf", }, + { "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", + "/usr/share/fonts/dejavu/DejaVuSans.ttf", }, + }; - GFile* fontDir = g_file_new_for_path(fontDirEnv); - if (!fontDir || !g_file_query_exists(fontDir, NULL)) - g_error("WEBKIT_TESTFONTS environment variable is not set correctly - it should point to the directory " - "containing the fonts you can clone from git://gitorious.org/qtwebkit/testfonts.git\n"); + // TODO: Some tests use Lucida. We should load these as well, once it becomes + // clear how to install these fonts easily on Fedora. + for (size_t font = 0; font < G_N_ELEMENTS(fontPaths); font++) { + bool found = false; + for (size_t path = 0; path < 2; path++) { + + if (g_file_test(fontPaths[font][path], G_FILE_TEST_EXISTS)) { + found = true; + if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(fontPaths[font][path]))) + g_error("Could not load font at %s!", fontPaths[font][path]); + else + break; + } + } + + if (!found) + g_error("Could not find font at %s. Either install this font or file a bug " + "at http://bugs.webkit.org if it is installed in another location.", + fontPaths[font][0]); + } - FcConfig *config = FcConfigCreate(); - if (!FcConfigParseAndLoad (config, (FcChar8*) FONTS_CONF_FILE, true)) - g_error("Couldn't load font configuration file"); - if (!FcConfigAppFontAddDir (config, (FcChar8*) g_file_get_path(fontDir))) - g_error("Couldn't add font dir!"); - FcConfigSetCurrent(config); + // Ahem is used by many layout tests. + GOwnPtr<gchar> ahemFontFilename(g_build_filename(FONTS_CONF_DIR, "AHEM____.TTF", NULL)); + if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(ahemFontFilename.get()))) + g_error("Could not load font at %s!", ahemFontFilename.get()); - g_object_unref(fontDir); + if (!FcConfigSetCurrent(config)) + g_error("Could not set the current font configuration!"); - appFontSet = FcConfigGetFonts(config, FcSetApplication); - numFonts = appFontSet->nfont; + numFonts = FcConfigGetFonts(config, FcSetApplication)->nfont; #endif } @@ -336,6 +381,7 @@ static void resetDefaultsToConsistentValues() "auto-resize-window", TRUE, "enable-java-applet", FALSE, "enable-plugins", TRUE, + "enable-hyperlink-auditing", FALSE, "editing-behavior", WEBKIT_EDITING_BEHAVIOR_MAC, NULL); diff --git a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp index d1529db..6e5fa5f 100644 --- a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp +++ b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp @@ -147,6 +147,58 @@ bool prepareMouseButtonEvent(GdkEvent* event, int eventSenderButtonNumber, guint return true; } +static JSValueRef getMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) +{ + GtkWidget* widget = GTK_WIDGET(JSObjectGetPrivate(object)); + CString label; + if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) + label = "<separator>"; + else + label = gtk_menu_item_get_label(GTK_MENU_ITEM(widget)); + + return JSValueMakeString(context, JSStringCreateWithUTF8CString(label.data())); +} + +static bool setMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + return true; +} + +static JSValueRef menuItemClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + GtkMenuItem* item = GTK_MENU_ITEM(JSObjectGetPrivate(thisObject)); + gtk_menu_item_activate(item); + return JSValueMakeUndefined(context); +} + +static JSStaticFunction staticMenuItemFunctions[] = { + { "click", menuItemClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 } +}; + +static JSStaticValue staticMenuItemValues[] = { + { "title", getMenuItemTitleCallback, setMenuItemTitleCallback, kJSPropertyAttributeNone }, + { 0, 0, 0, 0 } +}; + +static JSClassRef getMenuItemClass() +{ + static JSClassRef menuItemClass = 0; + + if (!menuItemClass) { + JSClassDefinition classDefinition = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + classDefinition.staticFunctions = staticMenuItemFunctions; + classDefinition.staticValues = staticMenuItemValues; + + menuItemClass = JSClassCreate(&classDefinition); + } + + return menuItemClass; +} + + static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS); @@ -165,13 +217,7 @@ static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef functio JSValueRef arrayValues[g_list_length(items)]; int index = 0; for (GList* item = g_list_first(items); item; item = g_list_next(item)) { - CString label; - if (GTK_IS_SEPARATOR_MENU_ITEM(item->data)) - label = "<separator>"; - else - label = gtk_menu_item_get_label(GTK_MENU_ITEM(item->data)); - - arrayValues[index] = JSValueMakeString(context, JSStringCreateWithUTF8CString(label.data())); + arrayValues[index] = JSObjectMake(context, getMenuItemClass(), item->data); index++; } if (index) diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index 32be43d..d831076 100644 --- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -38,7 +38,6 @@ #include "WorkQueueItem.h" #include <JavaScriptCore/JSRetainPtr.h> #include <JavaScriptCore/JSStringRef.h> - #include <cstring> #include <iostream> #include <sstream> @@ -46,6 +45,7 @@ #include <glib.h> #include <libsoup/soup.h> #include <webkit/webkit.h> +#include <wtf/gobject/GOwnPtr.h> extern "C" { bool webkit_web_frame_pause_animation(WebKitWebFrame* frame, const gchar* name, double time, const gchar* element); @@ -66,24 +66,6 @@ void webkit_web_view_execute_core_command_by_name(WebKitWebView* webView, const gboolean webkit_web_view_is_command_enabled(WebKitWebView* webView, const gchar* name); } -static gchar* copyWebSettingKey(gchar* preferenceKey) -{ - static GHashTable* keyTable; - - if (!keyTable) { - // If you add a pref here, make sure you reset the value in - // DumpRenderTree::resetDefaultsToConsistentValues. - keyTable = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert(keyTable, g_strdup("WebKitJavaScriptEnabled"), g_strdup("enable-scripts")); - g_hash_table_insert(keyTable, g_strdup("WebKitDefaultFontSize"), g_strdup("default-font-size")); - g_hash_table_insert(keyTable, g_strdup("WebKitEnableCaretBrowsing"), g_strdup("enable-caret-browsing")); - g_hash_table_insert(keyTable, g_strdup("WebKitUsesPageCachePreferenceKey"), g_strdup("enable-page-cache")); - g_hash_table_insert(keyTable, g_strdup("WebKitPluginsEnabled"), g_strdup("enable-plugins")); - } - - return g_strdup(static_cast<gchar*>(g_hash_table_lookup(keyTable, preferenceKey))); -} - LayoutTestController::~LayoutTestController() { // FIXME: implement @@ -155,6 +137,12 @@ JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef return JSValueMakeUndefined(context); } +JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) +{ + // FIXME: Implement this. + return JSValueMakeUndefined(context); +} + JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const { // FIXME: implement @@ -664,48 +652,53 @@ void LayoutTestController::resumeAnimations() const void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value) { - gchar* name = JSStringCopyUTF8CString(key); - gchar* strValue = JSStringCopyUTF8CString(value); + GOwnPtr<gchar> originalName(JSStringCopyUTF8CString(key)); + GOwnPtr<gchar> valueAsString(JSStringCopyUTF8CString(value)); WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); ASSERT(view); - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - gchar* webSettingKey = copyWebSettingKey(name); - - if (webSettingKey) { - GValue stringValue = { 0, { { 0 } } }; - g_value_init(&stringValue, G_TYPE_STRING); - g_value_set_string(&stringValue, const_cast<gchar*>(strValue)); - - WebKitWebSettingsClass* klass = WEBKIT_WEB_SETTINGS_GET_CLASS(settings); - GParamSpec* pspec = g_object_class_find_property(G_OBJECT_CLASS(klass), webSettingKey); - GValue propValue = { 0, { { 0 } } }; - g_value_init(&propValue, pspec->value_type); - - if (g_value_type_transformable(G_TYPE_STRING, pspec->value_type)) { - g_value_transform(const_cast<GValue*>(&stringValue), &propValue); - g_object_set_property(G_OBJECT(settings), webSettingKey, const_cast<GValue*>(&propValue)); - } else if (G_VALUE_HOLDS_BOOLEAN(&propValue)) { - char* lowered = g_utf8_strdown(strValue, -1); - g_object_set(G_OBJECT(settings), webSettingKey, - g_str_equal(lowered, "true") - || g_str_equal(strValue, "1"), - NULL); - g_free(lowered); - } else if (G_VALUE_HOLDS_INT(&propValue)) { - std::string str(strValue); - std::stringstream ss(str); - int val = 0; - if (!(ss >> val).fail()) - g_object_set(G_OBJECT(settings), webSettingKey, val, NULL); - } else - printf("LayoutTestController::overridePreference failed to override preference '%s'.\n", name); + // This transformation could be handled by a hash table (and it once was), but + // having it prominent, makes it easier for people from other ports to keep the + // list up to date. + const gchar* propertyName = 0; + if (g_str_equal(originalName.get(), "WebKitJavaScriptEnabled")) + propertyName = "enable-scripts"; + else if (g_str_equal(originalName.get(), "WebKitDefaultFontSize")) + propertyName = "default-font-size"; + else if (g_str_equal(originalName.get(), "WebKitEnableCaretBrowsing")) + propertyName = "enable-caret-browsing"; + else if (g_str_equal(originalName.get(), "WebKitUsesPageCachePreferenceKey")) + propertyName = "enable-page-cache"; + else if (g_str_equal(originalName.get(), "WebKitPluginsEnabled")) + propertyName = "enable-plugins"; + else if (g_str_equal(originalName.get(), "WebKitHyperlinkAuditingEnabled")) + propertyName = "enable-hyperlink-auditing"; + else { + fprintf(stderr, "LayoutTestController::overridePreference tried to override " + "unknown preference '%s'.\n", originalName.get()); + return; } - g_free(webSettingKey); - g_free(name); - g_free(strValue); + WebKitWebSettings* settings = webkit_web_view_get_settings(view); + GParamSpec* pspec = g_object_class_find_property(G_OBJECT_CLASS( + WEBKIT_WEB_SETTINGS_GET_CLASS(settings)), propertyName); + GValue currentPropertyValue = { 0, { { 0 } } }; + g_value_init(¤tPropertyValue, pspec->value_type); + + if (G_VALUE_HOLDS_STRING(¤tPropertyValue)) + g_object_set(settings, propertyName, valueAsString.get(), NULL); + else if (G_VALUE_HOLDS_BOOLEAN(¤tPropertyValue)) + g_object_set(G_OBJECT(settings), propertyName, !g_ascii_strcasecmp(valueAsString.get(), "true") + || !g_ascii_strcasecmp(valueAsString.get(), "1"), NULL); + else if (G_VALUE_HOLDS_INT(¤tPropertyValue)) + g_object_set(G_OBJECT(settings), propertyName, atoi(valueAsString.get()), NULL); + else if (G_VALUE_HOLDS_FLOAT(¤tPropertyValue)) { + gfloat newValue = g_ascii_strtod(valueAsString.get(), 0); + g_object_set(G_OBJECT(settings), propertyName, newValue, NULL); + } else + fprintf(stderr, "LayoutTestController::overridePreference failed to override " + "preference '%s'.\n", originalName.get()); } void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart, bool allFrames) diff --git a/WebKitTools/DumpRenderTree/gtk/fonts.conf b/WebKitTools/DumpRenderTree/gtk/fonts.conf deleted file mode 100644 index 3540c47..0000000 --- a/WebKitTools/DumpRenderTree/gtk/fonts.conf +++ /dev/null @@ -1,258 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> -<fontconfig> - -<!-- - Accept deprecated 'mono' alias, replacing it with 'monospace' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>mono</string> - </test> - <edit name="family" mode="assign"> - <string>monospace</string> - </edit> - </match> - -<!-- - Accept alternate 'sans serif' spelling, replacing it with 'sans-serif' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>sans serif</string> - </test> - <edit name="family" mode="assign"> - <string>sans-serif</string> - </edit> - </match> - -<!-- - Accept deprecated 'sans' alias, replacing it with 'sans-serif' ---> - <match target="pattern"> - <test qual="any" name="family"> - <string>sans</string> - </test> - <edit name="family" mode="assign"> - <string>sans-serif</string> - </edit> - </match> - - - <config> -<!-- - These are the default Unicode chars that are expected to be blank - in fonts. All other blank chars are assumed to be broken and - won't appear in the resulting charsets - --> - <blank> - <int>0x0020</int> <!-- SPACE --> - <int>0x00A0</int> <!-- NO-BREAK SPACE --> - <int>0x00AD</int> <!-- SOFT HYPHEN --> - <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER --> - <int>0x0600</int> <!-- ARABIC NUMBER SIGN --> - <int>0x0601</int> <!-- ARABIC SIGN SANAH --> - <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER --> - <int>0x0603</int> <!-- ARABIC SIGN SAFHA --> - <int>0x06DD</int> <!-- ARABIC END OF AYAH --> - <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK --> - <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER --> - <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER --> - <int>0x1680</int> <!-- OGHAM SPACE MARK --> - <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ --> - <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA --> - <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR --> - <int>0x2000</int> <!-- EN QUAD --> - <int>0x2001</int> <!-- EM QUAD --> - <int>0x2002</int> <!-- EN SPACE --> - <int>0x2003</int> <!-- EM SPACE --> - <int>0x2004</int> <!-- THREE-PER-EM SPACE --> - <int>0x2005</int> <!-- FOUR-PER-EM SPACE --> - <int>0x2006</int> <!-- SIX-PER-EM SPACE --> - <int>0x2007</int> <!-- FIGURE SPACE --> - <int>0x2008</int> <!-- PUNCTUATION SPACE --> - <int>0x2009</int> <!-- THIN SPACE --> - <int>0x200A</int> <!-- HAIR SPACE --> - <int>0x200B</int> <!-- ZERO WIDTH SPACE --> - <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER --> - <int>0x200D</int> <!-- ZERO WIDTH JOINER --> - <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK --> - <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK --> - <int>0x2028</int> <!-- LINE SEPARATOR --> - <int>0x2029</int> <!-- PARAGRAPH SEPARATOR --> - <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING --> - <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING --> - <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING --> - <int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE --> - <int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE --> - <int>0x202F</int> <!-- NARROW NO-BREAK SPACE --> - <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE --> - <int>0x2060</int> <!-- WORD JOINER --> - <int>0x2061</int> <!-- FUNCTION APPLICATION --> - <int>0x2062</int> <!-- INVISIBLE TIMES --> - <int>0x2063</int> <!-- INVISIBLE SEPARATOR --> - <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING --> - <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING --> - <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING --> - <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING --> - <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES --> - <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES --> - <int>0x3000</int> <!-- IDEOGRAPHIC SPACE --> - <int>0x3164</int> <!-- HANGUL FILLER --> - <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE --> - <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER --> - <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR --> - <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR --> - <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR --> - </blank> -<!-- - Rescan configuration every 30 seconds when FcFontSetList is called - --> - <rescan> - <int>30</int> - </rescan> - </config> - -<!-- - URW provides metric and shape compatible fonts for these 10 Adobe families. - - However, these fonts are quite ugly and do not render well on-screen, - so we avoid matching them if the application said `anymetrics'; in that - case, a more generic font with different metrics but better appearance - will be used. - --> - <match target="pattern"> - <test name="family"> - <string>Avant Garde</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>URW Gothic L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Bookman</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>URW Bookman L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Courier</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>Nimbus Mono L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Helvetica</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>Nimbus Sans L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>New Century Schoolbook</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>Century Schoolbook L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Palatino</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>URW Palladio L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Times</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>Nimbus Roman No9 L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Zapf Chancery</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>URW Chancery L</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Zapf Dingbats</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append"> - <string>Dingbats</string> - </edit> - </match> - <match target="pattern"> - <test name="family"> - <string>Symbol</string> - </test> - <test name="anymetrics" qual="all" compare="not_eq"> - <bool>true</bool> - </test> - <edit name="family" mode="append" binding="same"> - <string>Standard Symbols L</string> - </edit> - </match> - -<!-- - Serif faces - --> - <alias> - <family>Nimbus Roman No9 L</family> - <default><family>serif</family></default> - </alias> -<!-- - Sans-serif faces - --> - <alias> - <family>Nimbus Sans L</family> - <default><family>sans-serif</family></default> - </alias> -<!-- - Monospace faces - --> - <alias> - <family>Nimbus Mono L</family> - <default><family>monospace</family></default> - </alias> - - -</fontconfig> diff --git a/WebKitTools/DumpRenderTree/gtk/fonts/AHEM____.TTF b/WebKitTools/DumpRenderTree/gtk/fonts/AHEM____.TTF Binary files differnew file mode 100644 index 0000000..ac81cb0 --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/fonts/AHEM____.TTF diff --git a/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf b/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf new file mode 100644 index 0000000..520f96e --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf @@ -0,0 +1,282 @@ +<?xml version="1.0"?> +<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> +<fontconfig> + + <!-- The sans-serif font should be Liberation Serif --> + <match target="pattern"> + <test qual="any" name="family"> + <string>serif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Times</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Times New Roman</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + </match> + + <!-- The sans-serif font should be Liberation Sans --> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans serif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + </match> + <!-- We need to ensure that layout tests that use "Helvetica" don't + fall back to the default serif font --> + <match target="pattern"> + <test qual="any" name="family"> + <string>Helvetica</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + </match> + + <!-- The Monospace font should be Liberation Mono --> + <match target="pattern"> + <test qual="any" name="family"> + <string>monospace</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Mono</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>mono</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Mono</string> + </edit> + </match> + <!-- We need to ensure that layout tests that use "Courier", "Courier New", + and "Monaco" (all monospace fonts) don't fall back to the default + serif font --> + <match target="pattern"> + <test qual="any" name="family"> + <string>Courier</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Mono</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Courier New</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Mono</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Monaco</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Mono</string> + </edit> + </match> + + <!-- The following hinting specializations are adapted from those in the + Chromium test_shell. We try to duplicate their incredibly thorough + testing here --> + <match target="pattern"> + <test name="family" compare="eq"> + <string>NonAntiAliasedSans</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + <edit name="antialias" mode="assign"> + <bool>false</bool> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>SlightHintedSerif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + <edit name="hintstyle" mode="assign"> + <const>hintslight</const> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>NonHintedSans</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + <!-- These deliberately contradict each other. The 'hinting' preference + should take priority --> + <edit name="hintstyle" mode="assign"> + <const>hintfull</const> + </edit> + <edit name="hinting" mode="assign"> + <bool>false</bool> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>AutohintedSerif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + <edit name="autohint" mode="assign"> + <bool>true</bool> + </edit> + <edit name="hintstyle" mode="assign"> + <const>hintmedium</const> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>HintedSerif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + <edit name="autohint" mode="assign"> + <bool>false</bool> + </edit> + <edit name="hintstyle" mode="assign"> + <const>hintmedium</const> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>FullAndAutoHintedSerif</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + <edit name="autohint" mode="assign"> + <bool>true</bool> + </edit> + <edit name="hintstyle" mode="assign"> + <const>hintfull</const> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>SubpixelEnabledSans</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + <edit name="rgba" mode="assign"> + <const>rgb</const> + </edit> + </match> + + <match target="pattern"> + <test name="family" compare="eq"> + <string>SubpixelDisabledSans</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + <edit name="rgba" mode="assign"> + <const>none</const> + </edit> + </match> + + <config> + <!-- These are the default Unicode chars that are expected to be blank + in fonts. All other blank chars are assumed to be broken and won't + appear in the resulting charsets --> + <blank> + <int>0x0020</int> <!-- SPACE --> + <int>0x00A0</int> <!-- NO-BREAK SPACE --> + <int>0x00AD</int> <!-- SOFT HYPHEN --> + <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER --> + <int>0x0600</int> <!-- ARABIC NUMBER SIGN --> + <int>0x0601</int> <!-- ARABIC SIGN SANAH --> + <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER --> + <int>0x0603</int> <!-- ARABIC SIGN SAFHA --> + <int>0x06DD</int> <!-- ARABIC END OF AYAH --> + <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK --> + <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER --> + <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER --> + <int>0x1680</int> <!-- OGHAM SPACE MARK --> + <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ --> + <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA --> + <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR --> + <int>0x2000</int> <!-- EN QUAD --> + <int>0x2001</int> <!-- EM QUAD --> + <int>0x2002</int> <!-- EN SPACE --> + <int>0x2003</int> <!-- EM SPACE --> + <int>0x2004</int> <!-- THREE-PER-EM SPACE --> + <int>0x2005</int> <!-- FOUR-PER-EM SPACE --> + <int>0x2006</int> <!-- SIX-PER-EM SPACE --> + <int>0x2007</int> <!-- FIGURE SPACE --> + <int>0x2008</int> <!-- PUNCTUATION SPACE --> + <int>0x2009</int> <!-- THIN SPACE --> + <int>0x200A</int> <!-- HAIR SPACE --> + <int>0x200B</int> <!-- ZERO WIDTH SPACE --> + <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER --> + <int>0x200D</int> <!-- ZERO WIDTH JOINER --> + <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK --> + <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK --> + <int>0x2028</int> <!-- LINE SEPARATOR --> + <int>0x2029</int> <!-- PARAGRAPH SEPARATOR --> + <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING --> + <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING --> + <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING --> + <int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE --> + <int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE --> + <int>0x202F</int> <!-- NARROW NO-BREAK SPACE --> + <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE --> + <int>0x2060</int> <!-- WORD JOINER --> + <int>0x2061</int> <!-- FUNCTION APPLICATION --> + <int>0x2062</int> <!-- INVISIBLE TIMES --> + <int>0x2063</int> <!-- INVISIBLE SEPARATOR --> + <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING --> + <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING --> + <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING --> + <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING --> + <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES --> + <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES --> + <int>0x3000</int> <!-- IDEOGRAPHIC SPACE --> + <int>0x3164</int> <!-- HANGUL FILLER --> + <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE --> + <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER --> + <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR --> + <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR --> + <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR --> + </blank> + </config> +</fontconfig> diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index f55093e..d2a6f79 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -198,6 +198,11 @@ JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef return [[mainFrame webView] _computedStyleIncludingVisitedInfo:context forElement:value]; } +JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) +{ + return [[mainFrame webView] _nodesFromRect:context forDocument:value x:x y:y top:top right:right bottom:bottom left:left ignoreClipping:ignoreClipping]; +} + JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const { JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame _layerTreeAsText])); diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro index 5b81901..801251d 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro @@ -43,4 +43,9 @@ unix:!mac { QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR } +wince*: { + INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat $$WCECOMPAT/include + LIBS += $$WCECOMPAT/lib/wcecompat.lib +} + DEFINES+=USE_SYSTEM_MALLOC diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index 4e6f049..80fa441 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -564,7 +564,10 @@ void DumpRenderTree::resetToConsistentStateBeforeTesting() DumpRenderTreeSupportQt::setEditingBehavior(m_page, "win"); QLocale::setDefault(QLocale::c()); + +#ifndef Q_OS_WINCE setlocale(LC_ALL, ""); +#endif } static bool isGlobalHistoryTest(const QUrl& url) diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp index 63dbd2a..fd7c925 100644 --- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp @@ -381,7 +381,6 @@ void EventSender::scheduleAsynchronousClick() void EventSender::addTouchPoint(int x, int y) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) // Use index to refer to the position in the vector that this touch // is stored. We then create a unique id for the touch that will be // passed into WebCore. @@ -391,24 +390,20 @@ void EventSender::addTouchPoint(int x, int y) m_touchPoints.append(point); updateTouchPoint(index, x, y); m_touchPoints[index].setState(Qt::TouchPointPressed); -#endif } void EventSender::updateTouchPoint(int index, int x, int y) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (index < 0 || index >= m_touchPoints.count()) return; QTouchEvent::TouchPoint &p = m_touchPoints[index]; p.setPos(QPointF(x, y)); p.setState(Qt::TouchPointMoved); -#endif } void EventSender::setTouchModifier(const QString &modifier, bool enable) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) Qt::KeyboardModifier mod = Qt::NoModifier; if (!modifier.compare(QLatin1String("shift"), Qt::CaseInsensitive)) mod = Qt::ShiftModifier; @@ -423,30 +418,24 @@ void EventSender::setTouchModifier(const QString &modifier, bool enable) m_touchModifiers |= mod; else m_touchModifiers &= ~mod; -#endif } void EventSender::touchStart() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (!m_touchActive) { sendTouchEvent(QEvent::TouchBegin); m_touchActive = true; } else sendTouchEvent(QEvent::TouchUpdate); -#endif } void EventSender::touchMove() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) sendTouchEvent(QEvent::TouchUpdate); -#endif } void EventSender::touchEnd() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) for (int i = 0; i < m_touchPoints.count(); ++i) if (m_touchPoints[i].state() != Qt::TouchPointReleased) { sendTouchEvent(QEvent::TouchUpdate); @@ -454,31 +443,25 @@ void EventSender::touchEnd() } sendTouchEvent(QEvent::TouchEnd); m_touchActive = false; -#endif } void EventSender::clearTouchPoints() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) m_touchPoints.clear(); m_touchModifiers = Qt::KeyboardModifiers(); m_touchActive = false; -#endif } void EventSender::releaseTouchPoint(int index) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (index < 0 || index >= m_touchPoints.count()) return; m_touchPoints[index].setState(Qt::TouchPointReleased); -#endif } void EventSender::sendTouchEvent(QEvent::Type type) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers); event.setTouchPoints(m_touchPoints); sendEvent(m_page, &event); @@ -491,7 +474,6 @@ void EventSender::sendTouchEvent(QEvent::Type type) ++it; } } -#endif } void EventSender::zoomPageIn() diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h index a17e938..4ba8382 100644 --- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h +++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h @@ -41,13 +41,11 @@ #include <QPoint> #include <QString> #include <QStringList> +#include <QTouchEvent> #include <qwebpage.h> #include <qwebframe.h> -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) -#include <QTouchEvent> -#endif class EventSender : public QObject { Q_OBJECT @@ -107,10 +105,8 @@ private: QEventLoop* m_eventLoop; QWebFrame* frameUnderMouse() const; QBasicTimer m_clickTimer; -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QList<QTouchEvent::TouchPoint> m_touchPoints; Qt::KeyboardModifiers m_touchModifiers; bool m_touchActive; -#endif }; #endif // EventSenderQt_h diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index b2ef716..90a04c4 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -591,6 +591,8 @@ void LayoutTestController::overridePreference(const QString& name, const QVarian settings->setAttribute(QWebSettings::PluginsEnabled, value.toBool()); else if (name == "WebKitWebGLEnabled") settings->setAttribute(QWebSettings::WebGLEnabled, value.toBool()); + else if (name == "WebKitHyperlinkAuditingEnabled") + settings->setAttribute(QWebSettings::HyperlinkAuditingEnabled, value.toBool()); else printf("ERROR: LayoutTestController::overridePreference() does not support the '%s' preference\n", name.toLatin1().data()); diff --git a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp index e0c9b61..08d8850 100644 --- a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp @@ -133,10 +133,8 @@ void TextInputController::doCommand(const QString& command) void TextInputController::setMarkedText(const QString& string, int start, int end) { QList<QInputMethodEvent::Attribute> attributes; -#if QT_VERSION >= 0x040600 QInputMethodEvent::Attribute selection(QInputMethodEvent::Selection, start, end, QVariant()); attributes << selection; -#endif QInputMethodEvent event(string, attributes); QApplication::sendEvent(parent(), &event); } diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj index 1e765c6..1cba86a 100644 --- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj @@ -242,7 +242,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
xcopy /y /d "$(TargetDir)\..\include\WebCore\ForwardingHeaders\wtf\MD5.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -316,7 +316,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
xcopy /y /d "$(TargetDir)\..\include\WebCore\ForwardingHeaders\wtf\MD5.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -566,23 +566,23 @@ </File>
</Filter>
<File
- RelativePath="..\AccessibilityUIElement.cpp"
+ RelativePath="..\AccessibilityTextMarker.cpp"
>
</File>
<File
- RelativePath="..\AccessibilityUIElement.h"
+ RelativePath="..\AccessibilityTextMarker.h"
>
</File>
<File
- RelativePath=".\AccessibilityUIElementWin.cpp"
+ RelativePath="..\AccessibilityUIElement.cpp"
>
</File>
<File
- RelativePath="..\AccessibilityTextMarker.cpp"
+ RelativePath="..\AccessibilityUIElement.h"
>
</File>
<File
- RelativePath="..\AccessibilityTextMarker.h"
+ RelativePath=".\AccessibilityUIElementWin.cpp"
>
</File>
<File
@@ -608,10 +608,42 @@ <File
RelativePath=".\MD5.cpp"
>
+ <FileConfiguration
+ Name="Debug_Cairo|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release_Cairo|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
</File>
<File
RelativePath=".\MD5.h"
>
+ <FileConfiguration
+ Name="Debug_Cairo|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release_Cairo|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
</File>
<File
RelativePath="..\PixelDumpSupport.cpp"
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 68f4a6a..6dd609c 100644 --- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -179,6 +179,12 @@ JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef return JSValueMakeUndefined(context); } +JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) +{ + // FIXME: Implement this. + return JSValueMakeUndefined(context); +} + JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const { COMPtr<IWebFramePrivate> framePrivate(Query, frame); diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index f36c290..5fba1cf 100644 --- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -486,6 +486,12 @@ JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef, return 0; } +JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) +{ + // FIXME: Implement this. + return 0; +} + void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef) { } diff --git a/WebKitTools/EWSTools/start-commit-queue.sh b/WebKitTools/EWSTools/start-commit-queue.sh index 998300e..c55029a 100755 --- a/WebKitTools/EWSTools/start-commit-queue.sh +++ b/WebKitTools/EWSTools/start-commit-queue.sh @@ -30,8 +30,9 @@ cd "$HOME/Projects/CommitQueue" while : do - git reset --hard + git reset --hard trunk git clean -f + git rebase --abort git svn rebase ./WebKitTools/Scripts/webkit-patch commit-queue --no-confirm --exit-after-iteration 10 done diff --git a/WebKitTools/EWebLauncher/main.c b/WebKitTools/EWebLauncher/main.c index c1956a2..8965c42 100644 --- a/WebKitTools/EWebLauncher/main.c +++ b/WebKitTools/EWebLauncher/main.c @@ -147,7 +147,7 @@ typedef struct _ELauncher { static void browserDestroy(Ecore_Evas *ee); static void closeWindow(Ecore_Evas *ee); -static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen); +static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen, const char *databasePath); static void print_history(Eina_List *list) @@ -562,7 +562,7 @@ on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) info("Create new window (F9) was pressed.\n"); Eina_Rectangle geometry = {0, 0, 0, 0}; browserCreate("http://www.google.com", - app->theme, app->userAgent, geometry, NULL, 0); + app->theme, app->userAgent, geometry, NULL, 0, NULL); } else if (!strcmp(ev->key, "F10")) { Evas_Coord x, y, w, h; Evas_Object *frame = ewk_view_frame_main_get(obj); @@ -605,7 +605,10 @@ quit(Eina_Bool success, const char *msg) if (msg) fputs(msg, (success) ? stdout : stderr); - free(themePath); + if (themePath) { + free(themePath); + themePath = NULL; + } if (!success) return EXIT_FAILURE; @@ -614,7 +617,7 @@ quit(Eina_Bool success, const char *msg) } static int -browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen) +browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen, const char *databasePath) { if ((geometry.w <= 0) && (geometry.h <= 0)) { geometry.w = DEFAULT_WIDTH; @@ -642,9 +645,6 @@ browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Re if (!app->evas) return quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n"); - if (!theme) - theme = themePath; - app->theme = theme; app->userAgent = userAgent; @@ -660,6 +660,8 @@ browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Re ewk_view_theme_set(app->browser, theme); if (userAgent) ewk_view_setting_user_agent_set(app->browser, userAgent); + ewk_view_setting_local_storage_database_path_set(app->browser, databasePath); + evas_object_name_set(app->browser, "browser"); evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app); @@ -741,26 +743,25 @@ main_signal_exit(void *data, int ev_type, void *ev) } static char * -findThemePath(void) +findThemePath(const char *theme) { - const char **itr, *locations[] = { - "./default.edj", - "./WebKit/efl/DefaultTheme/default.edj", - "../WebKit/efl/DefaultTheme/default.edj", - DATA_DIR"/themes/default.edj", - NULL - }; + const char *defaultTheme = DATA_DIR"/default.edj"; + char *rpath; + struct stat st; - for (itr = locations; *itr; itr++) { - struct stat st; - if (!stat(*itr, &st)) { - char path[PATH_MAX]; - if (realpath(*itr, path)) - return strdup(path); - } + if (!theme) + theme = defaultTheme; + + rpath = realpath(theme, NULL); + if (!rpath) + return NULL; + + if (stat(rpath, &st)) { + free(rpath); + return NULL; } - return NULL; + return rpath; } int @@ -824,7 +825,9 @@ main(int argc, char *argv[]) if (sudoWorkaround) strcat(getenv("HOME"), "blah"); - themePath = findThemePath(); + themePath = findThemePath(theme); + if (!themePath) + return quit(EINA_FALSE, "ERROR: could not find theme.\n"); ewk_init(); tmp = getenv("TMPDIR"); @@ -839,7 +842,7 @@ main(int argc, char *argv[]) if (proxyUri) ewk_settings_proxy_uri_set(proxyUri); - browserCreate(url, theme, userAgent, geometry, engine, isFullscreen); + browserCreate(url, themePath, userAgent, geometry, engine, isFullscreen, path); ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows); ecore_main_loop_begin(); diff --git a/WebKitTools/GNUmakefile.am b/WebKitTools/GNUmakefile.am index 292ca7e..1599e89 100644 --- a/WebKitTools/GNUmakefile.am +++ b/WebKitTools/GNUmakefile.am @@ -24,7 +24,8 @@ Programs_GtkLauncher_CFLAGS = \ Programs_GtkLauncher_LDADD = \ libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \ $(GTK_LIBS) \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(WINMM_LIBS) Programs_GtkLauncher_LDFLAGS = \ -no-fast-install \ @@ -100,7 +101,8 @@ Programs_DumpRenderTree_LDADD = \ $(GTK_LIBS) \ $(GLIB_LIBS) \ $(LIBSOUP_LIBS) \ - $(FREETYPE_LIBS) + $(FREETYPE_LIBS) \ + $(WINMM_LIBS) Programs_DumpRenderTree_LDFLAGS = \ -no-fast-install \ @@ -145,7 +147,7 @@ noinst_LTLIBRARIES += \ dumprendertree_cppflags += \ -DTEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \ - -DFONTS_CONF_FILE=\"${shell pwd}/${srcdir}/WebKitTools/DumpRenderTree/gtk/fonts.conf\" + -DFONTS_CONF_DIR=\"${shell pwd}/${srcdir}/WebKitTools/DumpRenderTree/gtk/fonts\" TestNetscapePlugin_libtestnetscapeplugin_la_CPPFLAGS = \ -I$(srcdir)/WebKitTools/DumpRenderTree \ diff --git a/WebKitTools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops new file mode 100644 index 0000000..4e1e538 --- /dev/null +++ b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserCFLite"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib WebKit$(WebKitDLLConfigSuffix).lib CFLite$(LibraryConfigSuffix).lib"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops index 0031e14..f64d6ca 100644 --- a/WebKitTools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops +++ b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops @@ -10,14 +10,6 @@ UsePrecompiledHeader="2"
/>
<Tool
- Name="VCLinkerTool"
- AdditionalDependencies="shlwapi.lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib"
- />
- <Tool
- Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
- />
- <Tool
Name="VCPreBuildEventTool"
CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%

if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"
"
/>
diff --git a/WebKitTools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops new file mode 100644 index 0000000..a34efd2 --- /dev/null +++ b/WebKitTools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserCoreFoundation"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" xcopy /y /d "$(WebKitLibrariesDir)\bin\QuartzCore$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/MiniBrowser/MiniBrowser.vcproj b/WebKitTools/MiniBrowser/MiniBrowser.vcproj index 3ae3f60..7af24ec 100644 --- a/WebKitTools/MiniBrowser/MiniBrowser.vcproj +++ b/WebKitTools/MiniBrowser/MiniBrowser.vcproj @@ -18,7 +18,7 @@ <Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;.\Configurations\MiniBrowserCoreFoundation.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
UseOfATL="1"
CharacterSet="1"
>
@@ -80,7 +80,7 @@ <Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;.\Configurations\MiniBrowserCoreFoundation.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
UseOfATL="1"
CharacterSet="1"
WholeProgramOptimization="1"
@@ -143,7 +143,7 @@ <Configuration
Name="Debug_Internal|Win32"
ConfigurationType="1"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;.\Configurations\MiniBrowserCoreFoundation.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
UseOfATL="1"
CharacterSet="1"
>
@@ -205,7 +205,7 @@ <Configuration
Name="Debug_All|Win32"
ConfigurationType="1"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops;.\Configurations\MiniBrowserCoreFoundation.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
UseOfATL="1"
CharacterSet="1"
>
@@ -264,6 +264,135 @@ Name="VCPostBuildEventTool"
/>
</Configuration>
+ <Configuration
+ Name="Debug_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_wincairo.vsprops;.\Configurations\MiniBrowserCFLite.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ UseOfATL="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;.\Configurations\MiniBrowserCFLite.vsprops;.\Configurations\MiniBrowserCommon.vsprops"
+ UseOfATL="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
@@ -324,6 +453,22 @@ UsePrecompiledHeader="1"
/>
</FileConfiguration>
+ <FileConfiguration
+ Name="Debug_CFLite|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release_CFLite|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
</File>
</Filter>
<Filter
diff --git a/WebKitTools/MiniBrowser/mac/BrowserWindowController.m b/WebKitTools/MiniBrowser/mac/BrowserWindowController.m index 9398e56..cb4c56a 100644 --- a/WebKitTools/MiniBrowser/mac/BrowserWindowController.m +++ b/WebKitTools/MiniBrowser/mac/BrowserWindowController.m @@ -300,6 +300,11 @@ static void didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef fr LOG(@"didFirstVisuallyNonEmptyLayoutForFrame"); } +static void didRemoveFrameFromHierarchy(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo) +{ + LOG(@"didRemoveFrameFromHierarchy"); +} + static void didStartProgress(WKPageRef page, const void *clientInfo) { [(BrowserWindowController *)clientInfo didStartProgress]; @@ -469,6 +474,11 @@ static void setStatusText(WKPageRef page, WKStringRef text, const void* clientIn LOG(@"setStatusText"); } +static void mouseDidMoveOverElement(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo) +{ + LOG(@"mouseDidMoveOverElement"); +} + static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRef frame, const void *clientInfo) { LOG(@"contentsSizeChanged"); @@ -496,6 +506,7 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe didReceiveTitleForFrame, didFirstLayoutForFrame, didFirstVisuallyNonEmptyLayoutForFrame, + didRemoveFrameFromHierarchy, didStartProgress, didChangeProgress, didFinishProgress, @@ -525,7 +536,9 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe runJavaScriptConfirm, runJavaScriptPrompt, setStatusText, - contentsSizeChanged + mouseDidMoveOverElement, + contentsSizeChanged, + 0 /* didNotHandleKeyEvent */ }; WKPageSetPageUIClient(_webView.pageRef, &uiClient); } diff --git a/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch b/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch index 0670cf4..a4e648e 100644 --- a/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch +++ b/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch @@ -29,7 +29,7 @@ #import <WebKit2/WebKit2.h> -#define ENABLE_LOGGING 1 +#define ENABLE_LOGGING 0 #if ENABLE_LOGGING #define LOG NSLog diff --git a/WebKitTools/MiniBrowser/win/BrowserView.cpp b/WebKitTools/MiniBrowser/win/BrowserView.cpp index 5e90fe2..76848fa 100644 --- a/WebKitTools/MiniBrowser/win/BrowserView.cpp +++ b/WebKitTools/MiniBrowser/win/BrowserView.cpp @@ -74,6 +74,10 @@ static void setStatusText(WKPageRef page, WKStringRef text, const void* clientIn { } +static void mouseDidMoveOverElement(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo) +{ +} + static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRef frame, const void *clientInfo) { } @@ -104,7 +108,9 @@ void BrowserView::create(RECT webViewRect, BrowserWindow* parentWindow) runJavaScriptConfirm, runJavaScriptPrompt, setStatusText, - contentsSizeChanged + mouseDidMoveOverElement, + contentsSizeChanged, + 0 /* didNotHandleKeyEvent */ }; WKPageSetPageUIClient(WKViewGetPage(m_webView), &uiClient); diff --git a/WebKitTools/QtTestBrowser/launcherwindow.cpp b/WebKitTools/QtTestBrowser/launcherwindow.cpp index 65bcee7..df29f11 100644 --- a/WebKitTools/QtTestBrowser/launcherwindow.cpp +++ b/WebKitTools/QtTestBrowser/launcherwindow.cpp @@ -41,9 +41,7 @@ LauncherWindow::LauncherWindow(WindowOptions* data, QGraphicsScene* sharedScene) , m_view(0) , m_inspector(0) , m_formatMenuAction(0) -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) , m_zoomAnimation(0) -#endif { if (data) m_windowOptions = *data; @@ -91,6 +89,9 @@ void LauncherWindow::init() m_inspector->hide(); connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater())); + if (m_windowOptions.remoteInspectorPort) + page()->setProperty("_q_webInspectorServerPort", m_windowOptions.remoteInspectorPort); + // the zoom values are chosen to be like in Mozilla Firefox 3 if (!m_zoomLevels.count()) { m_zoomLevels << 30 << 50 << 67 << 80 << 90; @@ -134,9 +135,7 @@ void LauncherWindow::initializeView() if (url.isValid()) page()->mainFrame()->load(url); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) m_touchMocking = false; -#endif } void LauncherWindow::applyPrefs() @@ -240,11 +239,9 @@ void LauncherWindow::createChrome() toggleFrameFlattening->setCheckable(true); toggleFrameFlattening->setChecked(settings->testAttribute(QWebSettings::FrameFlatteningEnabled)); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QAction* touchMockAction = toolsMenu->addAction("Toggle touch mocking", this, SLOT(setTouchMocking(bool))); touchMockAction->setCheckable(true); touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T)); -#endif toolsMenu->addSeparator(); @@ -406,7 +403,6 @@ void LauncherWindow::grabZoomKeys(bool grab) #endif } -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) void LauncherWindow::sendTouchEvent() { if (m_touchPoints.isEmpty()) @@ -430,7 +426,6 @@ void LauncherWindow::sendTouchEvent() if (m_touchPoints.size() > 1 && m_touchPoints[1].state() == Qt::TouchPointReleased) m_touchPoints.removeAt(1); } -#endif // QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) bool LauncherWindow::eventFilter(QObject* obj, QEvent* event) { @@ -446,7 +441,6 @@ bool LauncherWindow::eventFilter(QObject* obj, QEvent* event) } } -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (!m_touchMocking) return QObject::eventFilter(obj, event); @@ -508,7 +502,6 @@ bool LauncherWindow::eventFilter(QObject* obj, QEvent* event) m_touchPoints.last().setState(Qt::TouchPointStationary); } } -#endif // QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) return false; } @@ -546,7 +539,6 @@ void LauncherWindow::zoomAnimationFinished() void LauncherWindow::applyZoom() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (isGraphicsBased() && page()->settings()->testAttribute(QWebSettings::TiledBackingStoreEnabled)) { QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView(); view->setTiledBackingStoreFrozen(true); @@ -564,7 +556,6 @@ void LauncherWindow::applyZoom() m_zoomAnimation->start(); return; } -#endif page()->mainFrame()->setZoomFactor(qreal(m_currentZoom) / 100.0); } @@ -674,9 +665,7 @@ void LauncherWindow::selectElements() void LauncherWindow::setTouchMocking(bool on) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) m_touchMocking = on; -#endif } void LauncherWindow::toggleWebView(bool graphicsBased) diff --git a/WebKitTools/QtTestBrowser/launcherwindow.h b/WebKitTools/QtTestBrowser/launcherwindow.h index d3b7f8e..84dedaa 100644 --- a/WebKitTools/QtTestBrowser/launcherwindow.h +++ b/WebKitTools/QtTestBrowser/launcherwindow.h @@ -110,6 +110,7 @@ public: bool useQGLWidgetViewport; #endif QUrl inspectorUrl; + quint16 remoteInspectorPort; }; class LauncherWindow : public MainWindow { @@ -122,9 +123,7 @@ public: virtual void keyPressEvent(QKeyEvent* event); void grabZoomKeys(bool grab); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) void sendTouchEvent(); -#endif bool eventFilter(QObject* obj, QEvent* event); @@ -199,11 +198,9 @@ private: QAction* m_formatMenuAction; -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QPropertyAnimation* m_zoomAnimation; QList<QTouchEvent::TouchPoint> m_touchPoints; bool m_touchMocking; -#endif }; #endif diff --git a/WebKitTools/QtTestBrowser/main.cpp b/WebKitTools/QtTestBrowser/main.cpp index ec864e9..41471fa 100644 --- a/WebKitTools/QtTestBrowser/main.cpp +++ b/WebKitTools/QtTestBrowser/main.cpp @@ -54,6 +54,8 @@ public: LauncherApplication(int& argc, char** argv); QStringList urls() const { return m_urls; } bool isRobotized() const { return m_isRobotized; } + int robotTimeout() const { return m_robotTimeoutSeconds; } + int robotExtraTime() const { return m_robotExtraTimeSeconds; } private: void handleUserOptions(); @@ -61,6 +63,8 @@ private: private: bool m_isRobotized; + int m_robotTimeoutSeconds; + int m_robotExtraTimeSeconds; QStringList m_urls; }; @@ -78,6 +82,8 @@ void LauncherApplication::applyDefaultSettings() LauncherApplication::LauncherApplication(int& argc, char** argv) : QApplication(argc, argv, QApplication::GuiServer) , m_isRobotized(false) + , m_robotTimeoutSeconds(0) + , m_robotExtraTimeSeconds(0) { // To allow QWebInspector's configuration persistence setOrganizationName("Nokia"); @@ -115,6 +121,8 @@ void LauncherApplication::handleUserOptions() << "[-cache-webview]" << "[-show-fps]" << "[-r list]" + << "[-robot-timeout seconds]" + << "[-robot-extra-time seconds]" << "[-inspector-url location]" << "[-tiled-backing-store]" << "[-resizes-to-contents]" @@ -180,6 +188,11 @@ void LauncherApplication::handleUserOptions() if (inspectorUrlIndex != -1) windowOptions.inspectorUrl = takeOptionValue(&args, inspectorUrlIndex); + QString remoteInspectorPortArg("-remote-inspector-port"); + int remoteInspectorPortIndex = args.indexOf(remoteInspectorPortArg); + if (remoteInspectorPortIndex != -1) + windowOptions.remoteInspectorPort = takeOptionValue(&args, remoteInspectorPortIndex).toInt(); + int robotIndex = args.indexOf("-r"); if (robotIndex != -1) { QString listFile = takeOptionValue(&args, robotIndex); @@ -190,11 +203,18 @@ void LauncherApplication::handleUserOptions() m_isRobotized = true; m_urls = QStringList(listFile); - return; + } else { + int lastArg = args.lastIndexOf(QRegExp("^-.*")); + m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1); } - int lastArg = args.lastIndexOf(QRegExp("^-.*")); - m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1); + int robotTimeoutIndex = args.indexOf("-robot-timeout"); + if (robotTimeoutIndex != -1) + m_robotTimeoutSeconds = takeOptionValue(&args, robotTimeoutIndex).toInt(); + + int robotExtraTimeIndex = args.indexOf("-robot-extra-time"); + if (robotExtraTimeIndex != -1) + m_robotExtraTimeSeconds = takeOptionValue(&args, robotExtraTimeIndex).toInt(); } @@ -204,8 +224,7 @@ int main(int argc, char **argv) if (app.isRobotized()) { LauncherWindow* window = new LauncherWindow(); - UrlLoader loader(window->page()->mainFrame(), app.urls().at(0)); - QObject::connect(window->page()->mainFrame(), SIGNAL(loadFinished(bool)), &loader, SLOT(loadNext())); + UrlLoader loader(window->page()->mainFrame(), app.urls().at(0), app.robotTimeout(), app.robotExtraTime()); loader.loadNext(); window->show(); return launcherMain(app); @@ -214,9 +233,9 @@ int main(int argc, char **argv) QStringList urls = app.urls(); if (urls.isEmpty()) { - QString defaultUrl = QString("file://%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html")); - if (QDir(defaultUrl).exists()) - urls.append(defaultUrl); + QString defaultIndexFile = QString("%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html")); + if (QFile(defaultIndexFile).exists()) + urls.append(QString("file://") + defaultIndexFile); else urls.append(""); } diff --git a/WebKitTools/QtTestBrowser/urlloader.cpp b/WebKitTools/QtTestBrowser/urlloader.cpp index 630ead6..abe9902 100644 --- a/WebKitTools/QtTestBrowser/urlloader.cpp +++ b/WebKitTools/QtTestBrowser/urlloader.cpp @@ -31,16 +31,31 @@ #include <QFile> #include <QDebug> -UrlLoader::UrlLoader(QWebFrame* frame, const QString& inputFileName) +UrlLoader::UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds) : m_frame(frame) , m_stdOut(stdout) , m_loaded(0) { - init(inputFileName); + if (timeoutSeconds) { + m_timeoutTimer.setInterval(timeoutSeconds * 1000); + m_timeoutTimer.setSingleShot(true); + connect(frame, SIGNAL(loadStarted()), &m_timeoutTimer, SLOT(start())); + connect(&m_timeoutTimer, SIGNAL(timeout()), this, SLOT(loadNext())); + } + if (extraTimeSeconds) { + m_extraTimeTimer.setInterval(extraTimeSeconds * 1000); + m_extraTimeTimer.setSingleShot(true); + connect(frame, SIGNAL(loadFinished(bool)), &m_extraTimeTimer, SLOT(start())); + connect(&m_extraTimeTimer, SIGNAL(timeout()), this, SLOT(loadNext())); + } else + connect(frame, SIGNAL(loadFinished(bool)), this, SLOT(loadNext())); + loadUrlList(inputFileName); } void UrlLoader::loadNext() { + m_timeoutTimer.stop(); + m_extraTimeTimer.stop(); QString qstr; if (getUrl(qstr)) { QUrl url(qstr, QUrl::StrictMode); @@ -53,7 +68,7 @@ void UrlLoader::loadNext() disconnect(m_frame, 0, this, 0); } -void UrlLoader::init(const QString& inputFileName) +void UrlLoader::loadUrlList(const QString& inputFileName) { QFile inputFile(inputFileName); if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { diff --git a/WebKitTools/QtTestBrowser/urlloader.h b/WebKitTools/QtTestBrowser/urlloader.h index ed14adc..e2a6d87 100644 --- a/WebKitTools/QtTestBrowser/urlloader.h +++ b/WebKitTools/QtTestBrowser/urlloader.h @@ -32,19 +32,20 @@ #include "qwebframe.h" #include <QTextStream> +#include <QTimer> #include <QVector> class UrlLoader : public QObject { Q_OBJECT public: - UrlLoader(QWebFrame* frame, const QString& inputFileName); + UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds); public slots: void loadNext(); private: - void init(const QString& inputFileName); + void loadUrlList(const QString& inputFileName); bool getUrl(QString& qstr); private: @@ -53,6 +54,8 @@ private: QWebFrame* m_frame; QTextStream m_stdOut; int m_loaded; + QTimer m_timeoutTimer; + QTimer m_extraTimeTimer; }; #endif diff --git a/WebKitTools/QtTestBrowser/utils.cpp b/WebKitTools/QtTestBrowser/utils.cpp index 2d45dd0..567c989 100644 --- a/WebKitTools/QtTestBrowser/utils.cpp +++ b/WebKitTools/QtTestBrowser/utils.cpp @@ -82,11 +82,7 @@ QUrl urlFromUserInput(const QString& string) if (fi.exists() && fi.isRelative()) input = fi.absoluteFilePath(); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) return QUrl::fromUserInput(input); -#else - return QUrl(input); -#endif } diff --git a/WebKitTools/QtTestBrowser/webview.cpp b/WebKitTools/QtTestBrowser/webview.cpp index d8d89a9..242daf6 100644 --- a/WebKitTools/QtTestBrowser/webview.cpp +++ b/WebKitTools/QtTestBrowser/webview.cpp @@ -151,7 +151,6 @@ void WebViewGraphicsBased::updateFrameRate() void WebViewGraphicsBased::animatedFlip() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QSizeF center = graphicsWebView()->boundingRect().size() / 2; QPointF centerPoint = QPointF(center.width(), center.height()); graphicsWebView()->setTransformOriginPoint(centerPoint); @@ -165,12 +164,10 @@ void WebViewGraphicsBased::animatedFlip() animation->setEndValue(rotation + 180 - (rotation % 180)); animation->start(QAbstractAnimation::DeleteWhenStopped); -#endif } void WebViewGraphicsBased::animatedYFlip() { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (!m_machine) { m_machine = new QStateMachine(this); @@ -202,7 +199,6 @@ void WebViewGraphicsBased::animatedYFlip() } m_machine->start(); -#endif } void WebViewGraphicsBased::paintEvent(QPaintEvent* event) diff --git a/WebKitTools/QtTestBrowser/webview.h b/WebKitTools/QtTestBrowser/webview.h index aadf85c..e34d081 100644 --- a/WebKitTools/QtTestBrowser/webview.h +++ b/WebKitTools/QtTestBrowser/webview.h @@ -117,13 +117,11 @@ private: inline void WebViewGraphicsBased::setYRotation(qreal angle) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QRectF r = graphicsWebView()->boundingRect(); graphicsWebView()->setTransform(QTransform() .translate(r.width() / 2, r.height() / 2) .rotate(angle, Qt::YAxis) .translate(-r.width() / 2, -r.height() / 2)); -#endif m_yRotation = angle; } diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus.py b/WebKitTools/QueueStatusServer/handlers/queuestatus.py index f76157d..0259c37 100644 --- a/WebKitTools/QueueStatusServer/handlers/queuestatus.py +++ b/WebKitTools/QueueStatusServer/handlers/queuestatus.py @@ -31,24 +31,27 @@ from google.appengine.ext.webapp import template from model.queues import queues, display_name_for_queue from model.workitems import WorkItems +from model.activeworkitems import ActiveWorkItems from model import queuestatus class QueueStatus(webapp.RequestHandler): - def _rows_for_work_items(self, work_items): - if not work_items: + def _rows_for_work_items(self, queued_items, active_items): + if not queued_items: return [] rows = [] - for item_id in work_items.item_ids: + for item_id in queued_items.item_ids: rows.append({ "attachment_id": item_id, "bug_id": 1, + "lock_time": active_items and active_items.time_for_item(item_id), }) return rows def get(self, queue_name): - work_items = WorkItems.all().filter("queue_name =", queue_name).get() + queued_items = WorkItems.all().filter("queue_name =", queue_name).get() + active_items = ActiveWorkItems.all().filter("queue_name =", queue_name).get() statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue_name).order("-date").fetch(15) status_groups = [] @@ -67,7 +70,7 @@ class QueueStatus(webapp.RequestHandler): template_values = { "display_queue_name": display_name_for_queue(queue_name), - "work_item_rows": self._rows_for_work_items(work_items), + "work_item_rows": self._rows_for_work_items(queued_items, active_items), "status_groups": status_groups, } self.response.out.write(template.render("templates/queuestatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/handlers/updatestatus.py b/WebKitTools/QueueStatusServer/handlers/updatestatus.py index 5a93dbd..89858b6 100644 --- a/WebKitTools/QueueStatusServer/handlers/updatestatus.py +++ b/WebKitTools/QueueStatusServer/handlers/updatestatus.py @@ -31,6 +31,7 @@ from google.appengine.ext import webapp, db from google.appengine.ext.webapp import template from handlers.updatebase import UpdateBase +from model.activeworkitems import ActiveWorkItems from model.attachment import Attachment from model.queuestatus import QueueStatus @@ -56,8 +57,24 @@ class UpdateStatus(UpdateBase): queue_status.results_file = db.Blob(str(results_file)) return queue_status + @staticmethod + def _expire_item(key, item_id): + active_work_items = db.get(key) + active_work_items.expire_item(item_id) + active_work_items.put() + + # FIXME: An explicit lock_release request would be cleaner than this magical "Retry" status. + def _update_active_work_items(self, queue_status): + if queue_status.message != "Retry": # From AbstractQueue._retry_status + return + active_items = ActiveWorkItems.all().filter("queue_name =", queue_status.queue_name).get() + if not active_items: + return + return db.run_in_transaction(self._expire_item, active_items.key(), queue_status.active_patch_id) + def post(self): queue_status = self._queue_status_from_request() queue_status.put() + self._update_active_work_items(queue_status) Attachment.dirty(queue_status.active_patch_id) self.response.out.write(queue_status.key().id()) diff --git a/WebKitTools/QueueStatusServer/model/activeworkitems.py b/WebKitTools/QueueStatusServer/model/activeworkitems.py index e24e6ca..a244c7d 100644 --- a/WebKitTools/QueueStatusServer/model/activeworkitems.py +++ b/WebKitTools/QueueStatusServer/model/activeworkitems.py @@ -28,7 +28,7 @@ from google.appengine.ext import db -from datetime import timedelta +from datetime import timedelta, datetime import time @@ -38,21 +38,41 @@ class ActiveWorkItems(db.Model): item_dates = db.ListProperty(float) date = db.DateTimeProperty(auto_now_add=True) + # The id/date pairs should probably just be their own class. + def _item_time_pairs(self): + return zip(self.item_ids, self.item_dates) + + def _set_item_time_pairs(self, pairs): + if pairs: + # The * operator raises on an empty list. + # db.Model does not tuples, we have to make lists. + self.item_ids, self.item_dates = map(list, zip(*pairs)) + else: + self.item_ids = [] + self.item_dates = [] + + def _append_item_time_pair(self, pair): + self.item_ids.append(pair[0]) + self.item_dates.append(pair[1]) + + def expire_item(self, item_id): + nonexpired_pairs = [pair for pair in self._item_time_pairs() if pair[0] != item_id] + self._set_item_time_pairs(nonexpired_pairs) + def deactivate_expired(self, now): one_hour_ago = time.mktime((now - timedelta(minutes=60)).timetuple()) - nonexpired_item_ids = [] - nonexpired_item_dates = [] - for i in range(len(self.item_ids)): - if self.item_dates[i] > one_hour_ago: - nonexpired_item_ids.append(self.item_ids[i]) - nonexpired_item_dates.append(self.item_dates[i]) - self.item_ids = nonexpired_item_ids - self.item_dates = nonexpired_item_dates + nonexpired_pairs = [pair for pair in self._item_time_pairs() if pair[1] > one_hour_ago] + self._set_item_time_pairs(nonexpired_pairs) def next_item(self, work_item_ids, now): for item_id in work_item_ids: if item_id not in self.item_ids: - self.item_ids.append(item_id) - self.item_dates.append(time.mktime(now.timetuple())) + self._append_item_time_pair([item_id, time.mktime(now.timetuple())]) return item_id return None + + def time_for_item(self, item_id): + for active_item_id, time in self._item_time_pairs(): + if active_item_id == item_id: + return datetime.fromtimestamp(time) + return None diff --git a/WebKitTools/QueueStatusServer/templates/queuestatus.html b/WebKitTools/QueueStatusServer/templates/queuestatus.html index d2d72c7..1b98952 100644 --- a/WebKitTools/QueueStatusServer/templates/queuestatus.html +++ b/WebKitTools/QueueStatusServer/templates/queuestatus.html @@ -42,13 +42,18 @@ <h3>Patches in queue</h3> <table> - <tr><th>Position</th><th>Patch</th></tr> + <tr><th>Position</th><th>Patch</th><th>Lock Acquired</th></tr> {% for row in work_item_rows %} <tr> <td>#{{ forloop.counter }}</td> <td> {{ row.attachment_id|force_escape|webkit_attachment_id|safe }} </td> + <td> + {% if row.lock_time %} + {{ row.lock_time|timesince }} ago + {% endif %} + </td> </tr> {% endfor %} </table> diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit index cd43499..bc1e8ad 100755 --- a/WebKitTools/Scripts/build-webkit +++ b/WebKitTools/Scripts/build-webkit @@ -106,7 +106,7 @@ my @features = ( define => "ENABLE_EVENTSOURCE", default => 1, value => \$eventsourceSupport }, { option => "filters", desc => "Toggle Filters support", - define => "ENABLE_FILTERS", default => (isAppleWebKit() || isGtk() || isQt()), value => \$filtersSupport }, + define => "ENABLE_FILTERS", default => (isAppleWebKit() || isGtk() || isQt() || isEfl()), value => \$filtersSupport }, { option => "geolocation", desc => "Toggle Geolocation support", define => "ENABLE_GEOLOCATION", default => (isAppleWebKit() || isGtk()), value => \$geolocationSupport }, @@ -245,13 +245,14 @@ Usage: $programName [options] [options to pass to build system] --chromium Build the Chromium port on Mac/Win/Linux --gtk Build the GTK+ port --qt Build the Qt port + --efl Build the EFL port --inspector-frontend Copy changes to the inspector front-end files to the build directory --install-headers=<path> Set installation path for the headers (Qt only) --install-libs=<path> Set installation path for the libraries (Qt only) --v8 Use V8 as JavaScript engine (Qt only) - --prefix=<path> Set installation prefix to the given path (Gtk only) + --prefix=<path> Set installation prefix to the given path (Gtk/Efl only) --makeargs=<arguments> Optional Makefile flags --minimal No optional features, unless explicitly enabled. @@ -428,6 +429,22 @@ if (isChromium()) { exit exitStatus($result) if exitStatus($result); } +if (isEfl()) { + @options = (); + @projects = (); + foreach (@features) { + my $featureName = $_->{define}; + if ($featureName) { + my $featureEnabled = ${$_->{value}} ? "ON" : "OFF"; + push @options, "-D$featureName=$featureEnabled"; + } + } + push @options, "--makeargs=" . $makeArgs if defined($makeArgs); + push @options, "--prefix=" . $prefixPath if defined($prefixPath); + my $result = buildCMakeEflProject($clean, @options); + exit exitStatus($result) if exitStatus($result); +} + # Build, and abort if the build fails. for my $dir (@projects) { chdir $dir or die; diff --git a/WebKitTools/Scripts/old-run-webkit-tests b/WebKitTools/Scripts/old-run-webkit-tests index 886b4a8..80801dc 100755 --- a/WebKitTools/Scripts/old-run-webkit-tests +++ b/WebKitTools/Scripts/old-run-webkit-tests @@ -236,7 +236,7 @@ if (isAppleMacWebKit()) { } } -if (isQt() || isGtk() || isCygwin()) { +if (isQt() || isCygwin()) { my $testfontPath = $ENV{"WEBKIT_TESTFONTS"}; if (!$testfontPath || !-d "$testfontPath") { print "The WEBKIT_TESTFONTS environment variable is not defined or not set properly\n"; @@ -528,6 +528,7 @@ if (!$has3DRendering) { if (!checkWebCoreFeatureSupport("3D Canvas", 0)) { $ignoredDirectories{'fast/canvas/webgl'} = 1; $ignoredDirectories{'compositing/webgl'} = 1; + $ignoredDirectories{'http/tests/canvas/webgl'} = 1; } if (checkWebCoreFeatureSupport("WML", 0)) { diff --git a/WebKitTools/Scripts/prepare-ChangeLog b/WebKitTools/Scripts/prepare-ChangeLog index c2adaf5..608c9ce 100755 --- a/WebKitTools/Scripts/prepare-ChangeLog +++ b/WebKitTools/Scripts/prepare-ChangeLog @@ -269,7 +269,7 @@ if ($bugNumber) { if (`curl --version | grep ^Protocols` !~ /\bhttps\b/) { print STDERR " Could not get description for bug $bugNumber.\n"; print STDERR " It looks like your version of curl does not support ssl.\n"; - print STDERR " If you are using macports, this can be fixed with sudo port install curl+ssl.\n"; + print STDERR " If you are using macports, this can be fixed with sudo port install curl +ssl.\n"; } else { print STDERR " Bug $bugNumber has no bug description. Maybe you set wrong bug ID?\n"; print STDERR " The bug URL: $bugXMLURL\n"; diff --git a/WebKitTools/Scripts/run-chromium-webkit-unit-tests b/WebKitTools/Scripts/run-chromium-webkit-unit-tests new file mode 100755 index 0000000..62646af --- /dev/null +++ b/WebKitTools/Scripts/run-chromium-webkit-unit-tests @@ -0,0 +1,51 @@ +#!/usr/bin/perl -w +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use strict; +use File::Spec; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +# Allow running this script from any directory. +my $sourceRootDir = File::Spec->catfile($FindBin::Bin, "../.."); +chdir($sourceRootDir); + +setConfiguration(); + +my $pathToBinary; +if (isDarwin()) { + $pathToBinary = "WebKit/chromium/xcodebuild/" . configuration() . "/webkit_unit_tests"; +} elsif (isCygwin() || isWindows()) { + $pathToBinary = "WebKit/chromium/" . configuration() . "/webkit_unit_tests.exe"; +} elsif (isLinux()) { + $pathToBinary = "out/" . configuration() . "/webkit_unit_tests"; +} + +exit system ($pathToBinary, @ARGV); diff --git a/WebKitTools/Scripts/test-webkitpy b/WebKitTools/Scripts/test-webkitpy index e35c6e6..be7e870 100755 --- a/WebKitTools/Scripts/test-webkitpy +++ b/WebKitTools/Scripts/test-webkitpy @@ -137,8 +137,9 @@ def _clean_pyc_files(dir_to_clean, paths_not_to_log): # As a substitute for a unit test, this method tests _clean_pyc_files() # in addition to calling it. We chose not to use the unittest module # because _clean_pyc_files() is called only once and is not used elsewhere. -def _clean_webkitpy_with_test(): +def _clean_packages_with_test(external_package_paths): webkitpy_dir = os.path.join(os.path.dirname(__file__), "webkitpy") + package_paths = [webkitpy_dir] + external_package_paths # The test .pyc file is-- # webkitpy/python24/TEMP_test-webkitpy_test_pyc_file.pyc. @@ -156,13 +157,14 @@ def _clean_webkitpy_with_test(): if not os.path.exists(test_path): raise Exception("Test .pyc file not created: %s" % test_path) - _clean_pyc_files(webkitpy_dir, [test_path]) + for path in package_paths: + _clean_pyc_files(path, [test_path]) if os.path.exists(test_path): raise Exception("Test .pyc file not deleted: %s" % test_path) -def init(command_args): +def init(command_args, external_package_paths): """Execute code prior to importing from webkitpy.unittests. Args: @@ -186,8 +188,8 @@ def init(command_args): configure_logging(is_verbose_logging) _log.debug("Verbose WebKit logging enabled.") - # We clean orphaned *.pyc files from webkitpy prior to importing from - # webkitpy to make sure that no import statements falsely succeed. + # We clean orphaned *.pyc files from the packages prior to importing from + # them to make sure that no import statements falsely succeed. # This helps to check that import statements have been updated correctly # after any file moves. Otherwise, incorrect import statements can # be masked. @@ -208,7 +210,7 @@ def init(command_args): # # Deleting the orphaned .pyc file prior to importing, however, would # cause an ImportError to occur on import as desired. - _clean_webkitpy_with_test() + _clean_packages_with_test(external_package_paths) import webkitpy.python24.versioning as versioning @@ -227,7 +229,8 @@ def init(command_args): if __name__ == "__main__": - init(sys.argv[1:]) + external_package_paths = [os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'WebKit2', 'Scripts', 'webkit2')] + init(sys.argv[1:], external_package_paths) # We import the unit test code after init() to ensure that any # Python version warnings are displayed in case an error occurs @@ -237,4 +240,4 @@ if __name__ == "__main__": # running the unit tests. from webkitpy.test.main import Tester - Tester().run_tests(sys.argv) + Tester().run_tests(sys.argv, external_package_paths) diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm index 2980750..08e14ab 100644 --- a/WebKitTools/Scripts/webkitdirs.pm +++ b/WebKitTools/Scripts/webkitdirs.pm @@ -1408,6 +1408,72 @@ sub buildAutotoolsProject($@) return $result; } +sub buildCMakeProject($@) +{ + my ($port, $clean, @buildParams) = @_; + my $dir = File::Spec->canonpath(baseProductDir()); + my $config = configuration(); + my $result; + my $makeArgs = ""; + my @buildArgs; + + $makeArgs .= " -j" . numberOfCPUs() if ($makeArgs !~ m/-j\s*\d+/); + + if ($clean) { + print "Cleaning the build directory '$dir'\n"; + $dir = File::Spec->catfile($dir, $config); + File::Path::remove_tree($dir, {keep_root => 1}); + $result = 0; + } else { + my $cmakebin = "cmake"; + my $make = "make"; + + push @buildArgs, "-DPORT=$port"; + + for my $i (0 .. $#buildParams) { + my $opt = $buildParams[$i]; + if ($opt =~ /^--makeargs=(.*)/i ) { + $makeArgs = $1; + } elsif ($opt =~ /^--prefix=(.*)/i ) { + push @buildArgs, "-DCMAKE_INSTALL_PREFIX=$1"; + } else { + push @buildArgs, $opt; + } + } + + if ($config =~ m/debug/i) { + push @buildArgs, "-DCMAKE_BUILD_TYPE=Debug"; + } elsif ($config =~ m/release/i) { + push @buildArgs, "-DCMAKE_BUILD_TYPE=Release"; + } + + push @buildArgs, sourceDir(); + + $dir = File::Spec->catfile($dir, $config); + File::Path::mkpath($dir); + chdir $dir or die "Failed to cd into " . $dir . "\n"; + + print "Calling '$cmakebin @buildArgs' in " . $dir . "\n\n"; + my $result = system "$cmakebin @buildArgs"; + if ($result ne 0) { + die "Failed while running $cmakebin to generate makefiles!\n"; + } + + print "Calling '$make $makeArgs' in " . $dir . "\n\n"; + $result = system "$make $makeArgs"; + + chdir ".." or die; + } + + return $result; +} + +sub buildCMakeEflProject($@) +{ + my ($clean, @buildArgs) = @_; + return buildCMakeProject("Efl", $clean, @buildArgs); +} + sub buildQMakeProject($@) { my ($clean, @buildParams) = @_; @@ -1480,7 +1546,6 @@ sub buildQMakeProject($@) } } - push @buildArgs, sourceDir() . "/WebKit.pro"; if ($config =~ m/debug/i) { push @buildArgs, "CONFIG-=release"; push @buildArgs, "CONFIG+=debug"; @@ -1495,6 +1560,8 @@ sub buildQMakeProject($@) } } + push @buildArgs, sourceDir() . "/WebKit.pro"; + print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n"; print "Installation headers directory: $installHeaders\n" if(defined($installHeaders)); print "Installation libraries directory: $installLibs\n" if(defined($installLibs)); @@ -1504,6 +1571,16 @@ sub buildQMakeProject($@) die "Failed to setup build environment using $qmakebin!\n"; } + # Manually create makefiles for the examples so we don't build by default + my $examplesDir = $dir . "/WebKit/qt/examples"; + File::Path::mkpath($examplesDir); + $buildArgs[-1] = sourceDir() . "/WebKit/qt/examples/examples.pro"; + chdir $examplesDir or die; + print "Calling '$qmakebin @buildArgs' in " . $examplesDir . "\n\n"; + $result = system "$qmakebin @buildArgs"; + die "Failed to create makefiles for the examples!\n" if $result ne 0; + chdir $dir or die; + if ($clean) { print "Calling '$make $makeargs distclean' in " . $dir . "\n\n"; $result = system "$make $makeargs distclean"; diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py index 113131f..2d07158 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/committers.py +++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py @@ -111,6 +111,7 @@ committers_unable_to_review = [ Committer("Graham Dennis", ["Graham.Dennis@gmail.com", "gdennis@webkit.org"]), Committer("Greg Bolsinga", "bolsinga@apple.com"), Committer("Hans Wennborg", "hans@chromium.org", "hwennborg"), + Committer("Hayato Ito", "hayato@chromium.org", "hayato"), Committer("Hin-Chung Lam", ["hclam@google.com", "hclam@chromium.org"]), Committer("Ilya Tikhonovsky", "loislo@chromium.org", "loislo"), Committer("Jakob Petsovits", ["jpetsovits@rim.com", "jpetso@gmx.at"], "jpetso"), @@ -136,6 +137,7 @@ committers_unable_to_review = [ Committer("Kent Hansen", "kent.hansen@nokia.com", "khansen"), Committer("Kinuko Yasuda", "kinuko@chromium.org", "kinuko"), Committer("Krzysztof Kowalczyk", "kkowalczyk@gmail.com"), + Committer("Kwang Yul Seo", ["kwangyul.seo@gmail.com", "skyul@company100.net", "kseo@webkit.org"], "kwangseo"), Committer("Leandro Pereira", ["leandro@profusion.mobi", "leandro@webkit.org"], "acidx"), Committer("Levi Weintraub", "lweintraub@apple.com"), Committer("Lucas De Marchi", ["lucas.demarchi@profusion.mobi", "demarchi@webkit.org"], "demarchi"), @@ -158,6 +160,7 @@ committers_unable_to_review = [ Committer("Noam Rosenthal", "noam.rosenthal@nokia.com", "noamr"), Committer("Pam Greene", "pam@chromium.org", "pamg"), Committer("Patrick Gansterer", ["paroga@paroga.com", "paroga@webkit.org"], "paroga"), + Committer("Pavel Podivilov", "podivilov@chromium.org", "podivilov"), Committer("Peter Kasting", ["pkasting@google.com", "pkasting@chromium.org"], "pkasting"), Committer("Philippe Normand", ["pnormand@igalia.com", "philn@webkit.org"], "philn-tp"), Committer("Pierre d'Herbemont", ["pdherbemont@free.fr", "pdherbemont@apple.com"], "pdherbemont"), diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py index 593ebc1..17f6c7a 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py @@ -34,6 +34,8 @@ import urllib import urllib2 import xmlrpclib +from webkitpy.common.net.failuremap import FailureMap +from webkitpy.common.net.regressionwindow import RegressionWindow from webkitpy.common.system.logutils import get_logger from webkitpy.thirdparty.autoinstalled.mechanize import Browser from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup @@ -145,9 +147,9 @@ class Builder(object): ) return build - def find_failure_transition(self, red_build, look_back_limit=30): + def find_regression_window(self, red_build, look_back_limit=30): if not red_build or red_build.is_green(): - return (None, None) + return RegressionWindow(None, None) common_failures = None current_build = red_build build_after_current_build = None @@ -172,34 +174,25 @@ class Builder(object): break look_back_count += 1 if look_back_count > look_back_limit: - return (None, current_build) + return RegressionWindow(None, current_build, common_failures=common_failures) build_after_current_build = current_build current_build = current_build.previous_build() # We must iterate at least once because red_build is red. assert(build_after_current_build) # Current build must either be green or have no failures in common # with red build, so we've found our failure transition. - return (current_build, build_after_current_build) + return RegressionWindow(current_build, build_after_current_build, common_failures=common_failures) - # FIXME: This likely does not belong on Builder - def suspect_revisions_for_transition(self, last_good_build, first_bad_build): - suspect_revisions = range(first_bad_build.revision(), - last_good_build.revision(), - -1) - suspect_revisions.reverse() - return suspect_revisions - - def blameworthy_revisions(self, red_build_number, look_back_limit=30, avoid_flakey_tests=True): + def find_blameworthy_regression_window(self, red_build_number, look_back_limit=30, avoid_flakey_tests=True): red_build = self.build(red_build_number) - (last_good_build, first_bad_build) = \ - self.find_failure_transition(red_build, look_back_limit) - if not last_good_build: - return [] # We ran off the limit of our search + regression_window = self.find_regression_window(red_build, look_back_limit) + if not regression_window.build_before_failure(): + return None # We ran off the limit of our search # If avoid_flakey_tests, require at least 2 bad builds before we # suspect a real failure transition. - if avoid_flakey_tests and first_bad_build == red_build: - return [] - return self.suspect_revisions_for_transition(last_good_build, first_bad_build) + if avoid_flakey_tests and regression_window.failing_build() == red_build: + return None + return regression_window # FIXME: This should be unified with all the layout test results code in the layout_tests package @@ -414,20 +407,27 @@ class BuildBot(object): build_status_url = "http://%s/one_box_per_builder" % self.buildbot_host return urllib2.urlopen(build_status_url) + def _file_cell_text(self, file_cell): + """Traverses down through firstChild elements until one containing a string is found, then returns that string""" + element = file_cell + while element.string is None and element.contents: + element = element.contents[0] + return element.string + def _parse_twisted_file_row(self, file_row): - string_or_empty = lambda soup: unicode(soup.string) if soup.string else u"" + string_or_empty = lambda string: unicode(string) if string else u"" file_cells = file_row.findAll('td') return { - "filename": string_or_empty(file_cells[0].find("a")), - "size": string_or_empty(file_cells[1]), - "type": string_or_empty(file_cells[2]), - "encoding": string_or_empty(file_cells[3]), + "filename": string_or_empty(self._file_cell_text(file_cells[0])), + "size": string_or_empty(self._file_cell_text(file_cells[1])), + "type": string_or_empty(self._file_cell_text(file_cells[2])), + "encoding": string_or_empty(self._file_cell_text(file_cells[3])), } def _parse_twisted_directory_listing(self, page): soup = BeautifulSoup(page) # HACK: Match only table rows with a class to ignore twisted header/footer rows. - file_rows = soup.find('table').findAll('tr', { "class" : True }) + file_rows = soup.find('table').findAll('tr', {'class': re.compile(r'\b(?:directory|file)\b')}) return [self._parse_twisted_file_row(file_row) for file_row in file_rows] # FIXME: There should be a better way to get this information directly from twisted. @@ -452,19 +452,17 @@ class BuildBot(object): self._builder_by_name[name] = builder return builder - def revisions_causing_failures(self, only_core_builders=True): + def failure_map(self, only_core_builders=True): builder_statuses = self.core_builder_statuses() if only_core_builders else self.builder_statuses() + failure_map = FailureMap() revision_to_failing_bots = {} for builder_status in builder_statuses: if builder_status["is_green"]: continue builder = self.builder_with_name(builder_status["name"]) - revisions = builder.blameworthy_revisions(builder_status["build_number"]) - for revision in revisions: - failing_bots = revision_to_failing_bots.get(revision, []) - failing_bots.append(builder) - revision_to_failing_bots[revision] = failing_bots - return revision_to_failing_bots + regression_window = builder.find_blameworthy_regression_window(builder_status["build_number"]) + failure_map.add_regression_window(builder, regression_window) + return failure_map # This makes fewer requests than calling Builder.latest_build would. It grabs all builder # statuses in one request using self.builder_statuses (fetching /one_box_per_builder instead of builder pages). diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py index b48f0e4..c99ab32 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py @@ -54,53 +54,53 @@ class BuilderTest(unittest.TestCase): self.builder = Builder(u"Test Builder \u2661", self.buildbot) self._install_fetch_build(lambda build_number: ["test1", "test2"]) - def test_find_failure_transition(self): - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build.revision(), 1003) - self.assertEqual(red_build.revision(), 1004) + def test_find_regression_window(self): + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure().revision(), 1003) + self.assertEqual(regression_window.failing_build().revision(), 1004) - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10), look_back_limit=2) - self.assertEqual(green_build, None) - self.assertEqual(red_build.revision(), 1008) + regression_window = self.builder.find_regression_window(self.builder.build(10), look_back_limit=2) + self.assertEqual(regression_window.build_before_failure(), None) + self.assertEqual(regression_window.failing_build().revision(), 1008) def test_none_build(self): self.builder._fetch_build = lambda build_number: None - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build, None) - self.assertEqual(red_build, None) + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure(), None) + self.assertEqual(regression_window.failing_build(), None) def test_flaky_tests(self): self._install_fetch_build(lambda build_number: ["test1"] if build_number % 2 else ["test2"]) - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build.revision(), 1009) - self.assertEqual(red_build.revision(), 1010) + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure().revision(), 1009) + self.assertEqual(regression_window.failing_build().revision(), 1010) def test_failure_and_flaky(self): self._install_fetch_build(lambda build_number: ["test1", "test2"] if build_number % 2 else ["test2"]) - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build.revision(), 1003) - self.assertEqual(red_build.revision(), 1004) + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure().revision(), 1003) + self.assertEqual(regression_window.failing_build().revision(), 1004) def test_no_results(self): self._install_fetch_build(lambda build_number: ["test1", "test2"] if build_number % 2 else ["test2"]) - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build.revision(), 1003) - self.assertEqual(red_build.revision(), 1004) + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure().revision(), 1003) + self.assertEqual(regression_window.failing_build().revision(), 1004) def test_failure_after_flaky(self): self._install_fetch_build(lambda build_number: ["test1", "test2"] if build_number > 6 else ["test3"]) - (green_build, red_build) = self.builder.find_failure_transition(self.builder.build(10)) - self.assertEqual(green_build.revision(), 1006) - self.assertEqual(red_build.revision(), 1007) + regression_window = self.builder.find_regression_window(self.builder.build(10)) + self.assertEqual(regression_window.build_before_failure().revision(), 1006) + self.assertEqual(regression_window.failing_build().revision(), 1007) - def test_blameworthy_revisions(self): - self.assertEqual(self.builder.blameworthy_revisions(10), [1004]) - self.assertEqual(self.builder.blameworthy_revisions(10, look_back_limit=2), []) + def test_find_blameworthy_regression_window(self): + self.assertEqual(self.builder.find_blameworthy_regression_window(10).revisions(), [1004]) + self.assertEqual(self.builder.find_blameworthy_regression_window(10, look_back_limit=2), None) # Flakey test avoidance requires at least 2 red builds: - self.assertEqual(self.builder.blameworthy_revisions(4), []) - self.assertEqual(self.builder.blameworthy_revisions(4, avoid_flakey_tests=False), [1004]) + self.assertEqual(self.builder.find_blameworthy_regression_window(4), None) + self.assertEqual(self.builder.find_blameworthy_regression_window(4, avoid_flakey_tests=False).revisions(), [1004]) # Green builder: - self.assertEqual(self.builder.blameworthy_revisions(3), []) + self.assertEqual(self.builder.find_blameworthy_regression_window(3), None) def test_build_caching(self): self.assertEqual(self.builder.build(10), self.builder.build(10)) @@ -361,22 +361,19 @@ class BuildBotTest(unittest.TestCase): <h1>Directory listing for /results/SnowLeopard Intel Leaks/</h1> <table> - <thead> - <tr> + <tr class="alt"> <th>Filename</th> <th>Size</th> <th>Content type</th> <th>Content encoding</th> </tr> - </thead> - <tbody> -<tr class="odd"> - <td><a href="r47483%20%281%29/">r47483 (1)/</a></td> - <td></td> - <td>[Directory]</td> - <td></td> +<tr class="directory "> + <td><a href="r47483%20%281%29/"><b>r47483 (1)/</b></a></td> + <td><b></b></td> + <td><b>[Directory]</b></td> + <td><b></b></td> </tr> -<tr class="odd"> +<tr class="file alt"> <td><a href="r47484%20%282%29.zip">r47484 (2).zip</a></td> <td>89K</td> <td>[application/zip]</td> diff --git a/WebKitTools/Scripts/webkitpy/common/net/credentials.py b/WebKitTools/Scripts/webkitpy/common/net/credentials.py index 1d5f83d..1c3e6c0 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/credentials.py +++ b/WebKitTools/Scripts/webkitpy/common/net/credentials.py @@ -39,14 +39,23 @@ from webkitpy.common.system.executive import Executive, ScriptError from webkitpy.common.system.user import User from webkitpy.common.system.deprecated_logging import log +try: + # Use keyring, a cross platform keyring interface, as a fallback: + # http://pypi.python.org/pypi/keyring + import keyring +except ImportError: + keyring = None + class Credentials(object): - def __init__(self, host, git_prefix=None, executive=None, cwd=os.getcwd()): + def __init__(self, host, git_prefix=None, executive=None, cwd=os.getcwd(), + keyring=keyring): self.host = host self.git_prefix = "%s." % git_prefix if git_prefix else "" self.executive = executive or Executive() self.cwd = cwd + self._keyring = keyring def _credentials_from_git(self): return [Git.read_git_config(self.git_prefix + "username"), @@ -117,10 +126,19 @@ class Credentials(object): if not username or not password: (username, password) = self._credentials_from_keychain(username) + if username and not password and self._keyring: + password = self._keyring.get_password(self.host, username) + if not username: username = User.prompt("%s login: " % self.host) if not password: password = getpass.getpass("%s password for %s: " % (self.host, username)) + if self._keyring: + store_password = User().confirm( + "Store password in system keyring?", User.DEFAULT_NO) + if store_password: + self._keyring.set_password(self.host, username, password) + return [username, password] diff --git a/WebKitTools/Scripts/webkitpy/common/net/credentials_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/credentials_unittest.py index 9a42bdd..d30291b 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/credentials_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/credentials_unittest.py @@ -113,5 +113,28 @@ password: "SECRETSAUCE" self.assertEqual(credentials.read_credentials(), ["test@webkit.org", "SECRETSAUCE"]) os.rmdir(temp_dir_path) + def test_keyring_without_git_repo(self): + class MockKeyring(object): + def get_password(self, host, username): + return "NOMNOMNOM" + + class FakeCredentials(Credentials): + def __init__(self, cwd): + Credentials.__init__(self, "fake.hostname", cwd=cwd, + keyring=MockKeyring()) + + def _is_mac_os_x(self): + return True + + def _credentials_from_keychain(self, username): + return ("test@webkit.org", None) + + temp_dir_path = tempfile.mkdtemp(suffix="not_a_git_repo") + credentials = FakeCredentials(temp_dir_path) + try: + self.assertEqual(credentials.read_credentials(), ["test@webkit.org", "NOMNOMNOM"]) + finally: + os.rmdir(temp_dir_path) + if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/common/net/failuremap.py b/WebKitTools/Scripts/webkitpy/common/net/failuremap.py new file mode 100644 index 0000000..98e4b8f --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/net/failuremap.py @@ -0,0 +1,48 @@ +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +class FailureMap(object): + def __init__(self): + self._failures = [] + + def add_regression_window(self, builder, regression_window): + self._failures.append({ + 'builder': builder, + 'regression_window': regression_window, + }) + + def revisions_causing_failures(self): + revision_to_failing_bots = {} + for failure_info in self._failures: + revisions = failure_info['regression_window'].revisions() + for revision in revisions: + failing_bots = revision_to_failing_bots.get(revision, []) + failing_bots.append(failure_info['builder']) + revision_to_failing_bots[revision] = failing_bots + return revision_to_failing_bots diff --git a/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py b/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py new file mode 100644 index 0000000..231459f --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py @@ -0,0 +1,48 @@ +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +class RegressionWindow(object): + def __init__(self, build_before_failure, failing_build, common_failures=None): + self._build_before_failure = build_before_failure + self._failing_build = failing_build + self._common_failures = common_failures + + def build_before_failure(self): + return self._build_before_failure + + def failing_build(self): + return self._failing_build + + def common_failures(self): + return self._common_failures + + def revisions(self): + revisions = range(self._failing_build.revision(), self._build_before_failure.revision(), -1) + revisions.reverse() + return revisions diff --git a/WebKitTools/Scripts/webkitpy/common/system/user.py b/WebKitTools/Scripts/webkitpy/common/system/user.py index 9444c00..240b67b 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/user.py +++ b/WebKitTools/Scripts/webkitpy/common/system/user.py @@ -28,6 +28,7 @@ import logging import os +import re import shlex import subprocess import sys @@ -51,6 +52,9 @@ except ImportError: class User(object): + DEFAULT_NO = 'n' + DEFAULT_YES = 'y' + # FIXME: These are @classmethods because bugzilla.py doesn't have a Tool object (thus no User instance). @classmethod def prompt(cls, message, repeat=1, raw_input=raw_input): @@ -61,14 +65,30 @@ class User(object): return response @classmethod - def prompt_with_list(cls, list_title, list_items): + def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input): print list_title i = 0 for item in list_items: i += 1 print "%2d. %s" % (i, item) - result = int(cls.prompt("Enter a number: ")) - 1 - return list_items[result] + + # Loop until we get valid input + while True: + if can_choose_multiple: + response = cls.prompt("Enter one or more numbers (comma-separated), or \"all\": ", raw_input=raw_input) + if not response.strip() or response == "all": + return list_items + try: + indices = [int(r) - 1 for r in re.split("\s*,\s*", response)] + except ValueError, err: + continue + return [list_items[i] for i in indices] + else: + try: + result = int(cls.prompt("Enter a number: ", raw_input=raw_input)) - 1 + except ValueError, err: + continue + return list_items[result] def edit(self, files): editor = os.environ.get("EDITOR") or "vi" @@ -98,11 +118,14 @@ class User(object): except IOError, e: pass - def confirm(self, message=None): + def confirm(self, message=None, default=DEFAULT_YES, raw_input=raw_input): if not message: message = "Continue?" - response = raw_input("%s [Y/n]: " % message) - return not response or response.lower() == "y" + choice = {'y': 'Y/n', 'n': 'y/N'}[default] + response = raw_input("%s [%s]: " % (message, choice)) + if not response: + response = default + return response.lower() == 'y' def can_open_url(self): try: diff --git a/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py index dadead3..ae1bad5 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py @@ -28,6 +28,7 @@ import unittest +from webkitpy.common.system.outputcapture import OutputCapture from webkitpy.common.system.user import User class UserTest(unittest.TestCase): @@ -50,5 +51,51 @@ class UserTest(unittest.TestCase): return None self.assertEqual(User.prompt("input", repeat=self.repeatsRemaining, raw_input=mock_raw_input), None) + def test_prompt_with_list(self): + def run_prompt_test(inputs, expected_result, can_choose_multiple=False): + def mock_raw_input(message): + return inputs.pop(0) + output_capture = OutputCapture() + actual_result = output_capture.assert_outputs( + self, + User.prompt_with_list, + args=["title", ["foo", "bar"]], + kwargs={"can_choose_multiple": can_choose_multiple, "raw_input": mock_raw_input}, + expected_stdout="title\n 1. foo\n 2. bar\n") + self.assertEqual(actual_result, expected_result) + self.assertEqual(len(inputs), 0) + + run_prompt_test(["1"], "foo") + run_prompt_test(["badinput", "2"], "bar") + + run_prompt_test(["1,2"], ["foo", "bar"], can_choose_multiple=True) + run_prompt_test([" 1, 2 "], ["foo", "bar"], can_choose_multiple=True) + run_prompt_test(["all"], ["foo", "bar"], can_choose_multiple=True) + run_prompt_test([""], ["foo", "bar"], can_choose_multiple=True) + run_prompt_test([" "], ["foo", "bar"], can_choose_multiple=True) + run_prompt_test(["badinput", "all"], ["foo", "bar"], can_choose_multiple=True) + + def test_confirm(self): + test_cases = ( + (("Continue? [Y/n]: ", True), (User.DEFAULT_YES, 'y')), + (("Continue? [Y/n]: ", False), (User.DEFAULT_YES, 'n')), + (("Continue? [Y/n]: ", True), (User.DEFAULT_YES, '')), + (("Continue? [Y/n]: ", False), (User.DEFAULT_YES, 'q')), + (("Continue? [y/N]: ", True), (User.DEFAULT_NO, 'y')), + (("Continue? [y/N]: ", False), (User.DEFAULT_NO, 'n')), + (("Continue? [y/N]: ", False), (User.DEFAULT_NO, '')), + (("Continue? [y/N]: ", False), (User.DEFAULT_NO, 'q')), + ) + for test_case in test_cases: + expected, inputs = test_case + + def mock_raw_input(message): + self.assertEquals(expected[0], message) + return inputs[1] + + result = User().confirm(default=inputs[0], + raw_input=mock_raw_input) + self.assertEquals(expected[1], result) + if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.checksum deleted file mode 100644 index 5890112..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -checksum-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.png deleted file mode 100644 index 83a5de3..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.png +++ /dev/null @@ -1 +0,0 @@ -checksum-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.txt deleted file mode 100644 index 5628d69..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum-expected.txt +++ /dev/null @@ -1 +0,0 @@ -checksum-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum.html deleted file mode 100644 index 2b78d31..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/checksum.html +++ /dev/null @@ -1 +0,0 @@ -image_checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/crash.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/crash.html deleted file mode 100644 index 0bc3798..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/crash.html +++ /dev/null @@ -1 +0,0 @@ -crash diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/exception.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/exception.html deleted file mode 100644 index 38c54e3..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/exception.html +++ /dev/null @@ -1 +0,0 @@ -exception diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/hang.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/hang.html deleted file mode 100644 index 4e0de08..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/hang.html +++ /dev/null @@ -1 +0,0 @@ -timeout-thread diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.checksum deleted file mode 100644 index 24b887a..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -image-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.png deleted file mode 100644 index 4c23996..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.png +++ /dev/null @@ -1 +0,0 @@ -image-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.txt deleted file mode 100644 index c6ee718..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image-expected.txt +++ /dev/null @@ -1 +0,0 @@ -image-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image.html deleted file mode 100644 index 53e4b27..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image.html +++ /dev/null @@ -1 +0,0 @@ -image_failure diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.checksum deleted file mode 100644 index 8fa0851..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -image_checksum-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.png deleted file mode 100644 index d677d2e..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.png +++ /dev/null @@ -1 +0,0 @@ -image_checksum-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.txt deleted file mode 100644 index 453f213..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum-expected.txt +++ /dev/null @@ -1 +0,0 @@ -image_checksum-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum.html deleted file mode 100644 index 2b78d31..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/image_checksum.html +++ /dev/null @@ -1 +0,0 @@ -image_checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/keyboard.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/keyboard.html deleted file mode 100644 index c253983..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/keyboard.html +++ /dev/null @@ -1 +0,0 @@ -keyboard diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.png deleted file mode 100644 index e45c7af..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.png +++ /dev/null @@ -1 +0,0 @@ -missing_check-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.txt deleted file mode 100644 index 0ea9227..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check-expected.txt +++ /dev/null @@ -1 +0,0 @@ -missing_check-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check.html deleted file mode 100644 index 0af8000..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_check.html +++ /dev/null @@ -1 +0,0 @@ -missing_image diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_image.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_image.html deleted file mode 100644 index 0af8000..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_image.html +++ /dev/null @@ -1 +0,0 @@ -missing_image diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_text.html deleted file mode 100644 index 47b8ad6..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/missing_text.html +++ /dev/null @@ -1 +0,0 @@ -missing_text diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text-expected.txt deleted file mode 100644 index e21ea45..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text-expected.txt +++ /dev/null @@ -1 +0,0 @@ -text_failures-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text.html deleted file mode 100644 index 91f5fc7..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/text.html +++ /dev/null @@ -1 +0,0 @@ -text_failure diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/timeout.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/timeout.html deleted file mode 100644 index 790851a..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/expected/timeout.html +++ /dev/null @@ -1 +0,0 @@ -timeout diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.checksum deleted file mode 100644 index 0c4f6da..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -fail_checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.png deleted file mode 100644 index db483ee..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.png +++ /dev/null @@ -1 +0,0 @@ -fail_png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.txt deleted file mode 100644 index a1f3c24..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum-expected.txt +++ /dev/null @@ -1 +0,0 @@ -fail_output diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum.html deleted file mode 100644 index b325924..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/failures/unexpected/text-image-checksum.html +++ /dev/null @@ -1 +0,0 @@ -Google diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text-expected.txt deleted file mode 100644 index 2b38a06..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text-expected.txt +++ /dev/null @@ -1 +0,0 @@ -text-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text.html deleted file mode 100644 index 8e27be7..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/passes/text.html +++ /dev/null @@ -1 +0,0 @@ -text diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text-expected.txt deleted file mode 100644 index 2b38a06..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text-expected.txt +++ /dev/null @@ -1 +0,0 @@ -text-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text.html deleted file mode 100644 index 8e27be7..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/http/tests/ssl/text.html +++ /dev/null @@ -1 +0,0 @@ -text diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error-expected.txt deleted file mode 100644 index 9427269..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error-expected.txt +++ /dev/null @@ -1 +0,0 @@ -error-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error.html deleted file mode 100644 index 8276753..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/error.html +++ /dev/null @@ -1 +0,0 @@ -error diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.checksum deleted file mode 100644 index 24b887a..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -image-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.png deleted file mode 100644 index 4c23996..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.png +++ /dev/null @@ -1 +0,0 @@ -image-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.txt deleted file mode 100644 index c6ee718..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image-expected.txt +++ /dev/null @@ -1 +0,0 @@ -image-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image.html deleted file mode 100644 index 773b222..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/image.html +++ /dev/null @@ -1 +0,0 @@ -image diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.checksum deleted file mode 100644 index 52038ae..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -platform_image-generic-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.png deleted file mode 100644 index 087872b..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.png +++ /dev/null @@ -1 +0,0 @@ -platform_image-generic-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.txt deleted file mode 100644 index f71680c..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image-expected.txt +++ /dev/null @@ -1 +0,0 @@ -platform_image-generic-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image.html deleted file mode 100644 index ca48a7b..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/platform_image.html +++ /dev/null @@ -1 +0,0 @@ -platform_image diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text-expected.txt deleted file mode 100644 index 2b38a06..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text-expected.txt +++ /dev/null @@ -1 +0,0 @@ -text-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text.html deleted file mode 100644 index 8e27be7..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/passes/text.html +++ /dev/null @@ -1 +0,0 @@ -text diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.checksum b/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.checksum deleted file mode 100644 index ea557cf..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.checksum +++ /dev/null @@ -1 +0,0 @@ -platform_image-checksum diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.png b/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.png deleted file mode 100644 index ec42fc1..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.png +++ /dev/null @@ -1 +0,0 @@ -platform_image-png diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.txt deleted file mode 100644 index ff8bf43..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/passes/platform_image-expected.txt +++ /dev/null @@ -1 +0,0 @@ -platform_image-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/test_expectations.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/test_expectations.txt deleted file mode 100644 index 0619fde..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/platform/test/test_expectations.txt +++ /dev/null @@ -1,13 +0,0 @@ -WONTFIX : failures/expected/checksum.html = IMAGE -WONTFIX : failures/expected/crash.html = CRASH -// This one actually passes because the checksums will match. -WONTFIX : failures/expected/image.html = PASS -WONTFIX : failures/expected/image_checksum.html = IMAGE -WONTFIX : failures/expected/missing_check.html = MISSING PASS -WONTFIX : failures/expected/missing_image.html = MISSING PASS -WONTFIX : failures/expected/missing_text.html = MISSING PASS -WONTFIX : failures/expected/text.html = TEXT -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 diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/resources/README.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/resources/README.txt deleted file mode 100644 index b806b06..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/resources/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -This directory exists solely to make sure that when we gather the lists of -tests, we skip over directories named 'resources'. diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text-expected.txt b/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text-expected.txt deleted file mode 100644 index 2b38a06..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text-expected.txt +++ /dev/null @@ -1 +0,0 @@ -text-txt diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text.html b/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text.html deleted file mode 100644 index 8e27be7..0000000 --- a/WebKitTools/Scripts/webkitpy/layout_tests/data/websocket/tests/passes/text.html +++ /dev/null @@ -1 +0,0 @@ -text diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py index d420631..00ff211 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py @@ -351,11 +351,20 @@ class Printer(object): filename = result.filename test_name = self._port.relative_test_filename(filename) self._write('trace: %s' % test_name) - self._write(' txt: %s' % - self._port.relative_test_filename( - self._port.expected_filename(filename, '.txt'))) + txt_file = self._port.expected_filename(filename, '.txt') + if self._port.path_exists(txt_file): + self._write(' txt: %s' % + self._port.relative_test_filename(txt_file)) + else: + self._write(' txt: <none>') + checksum_file = self._port.expected_filename(filename, '.checksum') + if self._port.path_exists(checksum_file): + self._write(' sum: %s' % + self._port.relative_test_filename(checksum_file)) + else: + self._write(' sum: <none>') png_file = self._port.expected_filename(filename, '.png') - if os.path.exists(png_file): + if self._port.path_exists(png_file): self._write(' png: %s' % self._port.relative_test_filename(png_file)) else: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py index 29139d0..0344aa7 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py @@ -151,7 +151,7 @@ class Testprinter(unittest.TestCase): expectations = test_expectations.TestExpectations( self._port, test_paths, expectations_str, self._port.test_platform_name(), is_debug_mode=False, - is_lint_mode=False, tests_are_present=False) + is_lint_mode=False) rs = run_webkit_tests.ResultSummary(expectations, test_paths) return test_paths, rs, expectations @@ -318,6 +318,16 @@ class Testprinter(unittest.TestCase): self.assertFalse(err.empty()) printer, err, out = self.get_printer(['--print', 'trace-everything']) + result = self.get_result('passes/image.html') + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + result = self.get_result('failures/expected/missing_text.html') + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + result = self.get_result('failures/expected/missing_check.html') + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + result = self.get_result('failures/expected/missing_image.html') printer.print_test_result(result, expected=True, exp_str='', got_str='') self.assertFalse(err.empty()) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py index 3d8349b..508a6ad 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py @@ -87,8 +87,7 @@ class TestExpectations: TEST_LIST = "test_expectations.txt" def __init__(self, port, tests, expectations, test_platform_name, - is_debug_mode, is_lint_mode, tests_are_present=True, - overrides=None): + is_debug_mode, is_lint_mode, overrides=None): """Loads and parses the test expectations given in the string. Args: port: handle to object containing platform-specific functionality @@ -101,10 +100,6 @@ class TestExpectations: in the expectations is_lint_mode: If True, just parse the expectations string looking for errors. - tests_are_present: whether the test files exist in the file - system and can be probed for. This is useful for distinguishing - test files from directories, and is needed by the LTTF - dashboard, where the files aren't actually locally present. overrides: test expectations that are allowed to override any entries in |expectations|. This is used by callers that need to manage two sets of expectations (e.g., upstream @@ -112,7 +107,7 @@ class TestExpectations: """ self._expected_failures = TestExpectationsFile(port, expectations, tests, test_platform_name, is_debug_mode, is_lint_mode, - tests_are_present=tests_are_present, overrides=overrides) + overrides=overrides) # TODO(ojan): Allow for removing skipped tests when getting the list of # tests to run, but not when getting metrics. @@ -302,8 +297,7 @@ class TestExpectationsFile: 'flaky': FLAKY} def __init__(self, port, expectations, full_test_list, test_platform_name, - is_debug_mode, is_lint_mode, suppress_errors=False, - tests_are_present=True, overrides=None): + is_debug_mode, is_lint_mode, suppress_errors=False, overrides=None): """ expectations: Contents of the expectations file full_test_list: The list of all tests to be run pending processing of @@ -314,9 +308,6 @@ class TestExpectationsFile: is_debug_mode: Whether we testing a test_shell built debug mode. is_lint_mode: Whether this is just linting test_expecatations.txt. suppress_errors: Whether to suppress lint errors. - tests_are_present: Whether the test files are present in the local - filesystem. The LTTF Dashboard uses False here to avoid having to - keep a local copy of the tree. overrides: test expectations that are allowed to override any entries in |expectations|. This is used by callers that need to manage two sets of expectations (e.g., upstream @@ -329,7 +320,6 @@ class TestExpectationsFile: self._test_platform_name = test_platform_name self._is_debug_mode = is_debug_mode self._is_lint_mode = is_lint_mode - self._tests_are_present = tests_are_present self._overrides = overrides self._suppress_errors = suppress_errors self._errors = [] @@ -462,7 +452,7 @@ class TestExpectationsFile: def remove_platform_from_expectations(self, tests, platform): """Returns a copy of the expectations with the tests matching the - platform remove. + platform removed. If a test is in the test list and has an option that matches the given platform, remove the matching platform and save the updated test back @@ -699,8 +689,8 @@ class TestExpectationsFile: # WebKit's way of skipping tests is to add a -disabled suffix. # So we should consider the path existing if the path or the # -disabled version exists. - if (self._tests_are_present and not os.path.exists(full_path) - and not os.path.exists(full_path + '-disabled')): + if (not self._port.path_exists(full_path) + and not self._port.path_exists(full_path + '-disabled')): # Log a non fatal error here since you hit this case any # time you update test_expectations.txt without syncing # the LayoutTests directory @@ -735,7 +725,8 @@ class TestExpectationsFile: path and make sure directories end with the OS path separator.""" path = os.path.join(self._port.layout_tests_dir(), test_list_path) path = os.path.normpath(path) - path = self._fix_dir(path) + if self._port.path_isdir(path): + path = os.path.join(path, '') result = [] for test in self._full_test_list: @@ -743,20 +734,6 @@ class TestExpectationsFile: result.append(test) return result - def _fix_dir(self, path): - """Check to see if the path points to a directory, and if so, append - the directory separator if necessary.""" - if self._tests_are_present: - if os.path.isdir(path): - path = os.path.join(path, '') - else: - # If we can't check the filesystem to see if this is a directory, - # we assume that files w/o an extension are directories. - # TODO(dpranke): What happens w/ LayoutTests/css2.1 ? - if os.path.splitext(path)[1] == '': - path = os.path.join(path, '') - return path - def _add_tests(self, tests, expectations, test_list_path, lineno, modifiers, options, overrides_allowed): for test in tests: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations_unittest.py index 26eb18d..2e1b6ec 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_expectations_unittest.py @@ -106,14 +106,13 @@ BUG_TEST WONTFIX WIN : failures/expected/image.html = IMAGE """ def parse_exp(self, expectations, overrides=None, is_lint_mode=False, - is_debug_mode=False, tests_are_present=True): + is_debug_mode=False): self._exp = TestExpectations(self._port, tests=self.get_basic_tests(), expectations=expectations, test_platform_name=self._port.test_platform_name(), is_debug_mode=is_debug_mode, is_lint_mode=is_lint_mode, - tests_are_present=tests_are_present, overrides=overrides) def assert_exp(self, test, result): @@ -151,10 +150,6 @@ BUGX DEFER : failures/expected = IMAGE self.assert_exp('failures/expected/text.html', TEXT) self.assert_exp('failures/expected/crash.html', IMAGE) - self.parse_exp(exp_str, tests_are_present=False) - self.assert_exp('failures/expected/text.html', TEXT) - self.assert_exp('failures/expected/crash.html', IMAGE) - def test_release_mode(self): self.parse_exp('BUGX DEBUG : failures/expected/text.html = TEXT', is_debug_mode=True) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py index 70beac3..6a5d43b 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py @@ -42,11 +42,13 @@ import sys import time import apache_http_server +import test_files import http_server import websocket_server from webkitpy.common.system import logutils from webkitpy.common.system.executive import Executive, ScriptError +from webkitpy.common.system.user import User _log = logutils.get_logger(__file__) @@ -81,14 +83,15 @@ class Port(object): } return flags_by_configuration[configuration] - def __init__(self, port_name=None, options=None, executive=Executive()): - self._name = port_name - self._options = options + def __init__(self, **kwargs): + self._name = kwargs.get('port_name', None) + self._options = kwargs.get('options', None) + self._executive = kwargs.get('executive', Executive()) + self._user = kwargs.get('user', User()) self._helper = None self._http_server = None self._webkit_base_dir = None self._websocket_server = None - self._executive = executive def default_child_processes(self): """Return the number of DumpRenderTree instances to use for this @@ -130,11 +133,11 @@ class Port(object): interface so that it can be overriden for testing purposes.""" return expected_text != actual_text - def diff_image(self, expected_filename, actual_filename, + def diff_image(self, expected_contents, actual_contents, diff_filename=None, tolerance=0): - """Compare two image files and produce a delta image file. + """Compare two images and produce a delta image file. - Return True if the two files are different, False if they are the same. + Return True if the two images are different, False if they are the same. Also produce a delta image of the two images and write that into |diff_filename| if it is not None. @@ -252,6 +255,31 @@ class Port(object): return os.path.join(platform_dir, baseline_filename) return os.path.join(self.layout_tests_dir(), baseline_filename) + def _expected_file_contents(self, test, extension, encoding): + path = self.expected_filename(test, extension) + if not os.path.exists(path): + return None + with codecs.open(path, 'r', encoding) as file: + return file.read() + + def expected_checksum(self, test): + """Returns the checksum of the image we expect the test to produce, or None if it is a text-only test.""" + return self._expected_file_contents(test, '.checksum', 'ascii') + + def expected_image(self, test): + """Returns the image we expect the test to produce.""" + return self._expected_file_contents(test, '.png', None) + + def expected_text(self, test): + """Returns the text output we expect the test to produce.""" + # NOTE: -expected.txt files are ALWAYS utf-8. However, + # we do not decode the output from DRT, so we should not + # decode the -expected.txt values either to allow comparisons. + text = self._expected_file_contents(test, '.txt', None) + if not text: + return '' + return text.strip("\r\n").replace("\r\n", "\n") + "\n" + def filename_to_uri(self, filename): """Convert a test file to a URI.""" LAYOUTTEST_HTTP_DIR = "http/tests/" @@ -287,6 +315,73 @@ class Port(object): return "file:///" + self.get_absolute_path(filename) return "file://" + self.get_absolute_path(filename) + def tests(self, paths): + """Return the list of tests found (relative to layout_tests_dir().""" + return test_files.find(self, paths) + + def test_dirs(self): + """Returns the list of top-level test directories. + + Used by --clobber-old-results.""" + layout_tests_dir = self.layout_tests_dir() + return filter(lambda x: os.path.isdir(os.path.join(layout_tests_dir, x)), + os.listdir(layout_tests_dir)) + + def path_isdir(self, path): + """Returns whether the path refers to a directory of tests. + + Used by test_expectations.py to apply rules to whole directories.""" + return os.path.isdir(path) + + def path_exists(self, path): + """Returns whether the path refers to an existing test or baseline.""" + # Used by test_expectations.py to determine if an entry refers to a + # valid test and by printing.py to determine if baselines exist.""" + return os.path.exists(path) + + def update_baseline(self, path, data, encoding): + """Updates the baseline for a test. + + Args: + path: the actual path to use for baseline, not the path to + the test. This function is used to update either generic or + platform-specific baselines, but we can't infer which here. + data: contents of the baseline. + encoding: file encoding to use for the baseline. + """ + with codecs.open(path, "w", encoding=encoding) as file: + file.write(data) + + def uri_to_test_name(self, uri): + """Return the base layout test name for a given URI. + + This returns the test name for a given URI, e.g., if you passed in + "file:///src/LayoutTests/fast/html/keygen.html" it would return + "fast/html/keygen.html". + + """ + test = uri + if uri.startswith("file:///"): + if sys.platform == 'win32': + test = test.replace('file:///', '') + test = test.replace('/', '\\') + else: + test = test.replace('file://', '') + return self.relative_test_filename(test) + + if uri.startswith("http://127.0.0.1:8880/"): + # websocket tests + return test.replace('http://127.0.0.1:8880/', '') + + if uri.startswith("http://"): + # regular HTTP test + return test.replace('http://127.0.0.1:8000/', 'http/tests/') + + if uri.startswith("https://"): + return test.replace('https://127.0.0.1:8443/', 'http/tests/') + + raise NotImplementedError('unknown url type: %s' % uri) + def get_absolute_path(self, filename): """Return the absolute path in unix format for the given filename. @@ -369,10 +464,10 @@ class Port(object): """ return os.environ.copy() - def show_html_results_file(self, results_filename): + def show_results_html_file(self, results_filename): """This routine should display the HTML file pointed at by results_filename in a users' browser.""" - raise NotImplementedError('Port.show_html_results_file') + return self._user.open_url(results_filename) def create_driver(self, image_path, options): """Return a newly created base.Driver subclass for starting/stopping @@ -588,7 +683,7 @@ class Port(object): try: with self._open_configuration_file() as file: return file.readline().rstrip() - except IOError, e: + except: return None # FIXME: This list may be incomplete as Apple has some sekret configs. diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py index 780cd22..71877b3 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py @@ -57,16 +57,17 @@ class MockExecutive(): class UnitTestPort(base.Port): """Subclass of base.Port used for unit testing.""" - def __init__(self, configuration_contents=None, executive_exception=None): + def __init__(self, configuration_contents=None, configuration_exception=IOError, executive_exception=None): base.Port.__init__(self) self._configuration_contents = configuration_contents + self._configuration_exception = configuration_exception if executive_exception: self._executive = MockExecutive(executive_exception) def _open_configuration_file(self): if self._configuration_contents: return NewStringIO(self._configuration_contents) - raise IOError + raise self._configuration_exception class PortTest(unittest.TestCase): @@ -191,9 +192,14 @@ class PortTest(unittest.TestCase): self.assertFalse('nosuchthing' in diff) def test_default_configuration_notfound(self): + # Regular IOError thrown while trying to get the configuration. port = UnitTestPort() self.assertEqual(port.default_configuration(), "Release") + # More exotic OSError thrown. + port = UnitTestPort(configuration_exception=OSError) + self.assertEqual(port.default_configuration(), "Release") + def test_layout_tests_skipping(self): port = base.Port() port.skipped_layout_tests = lambda: ['foo/bar.html', 'media'] @@ -214,6 +220,11 @@ class PortTest(unittest.TestCase): # This routine is a no-op. We just test it for coverage. port.setup_test_run() + def test_test_dirs(self): + port = base.Port() + dirs = port.test_dirs() + self.assertTrue('canvas' in dirs) + self.assertTrue('css2.1' in dirs) class VirtualTest(unittest.TestCase): """Tests that various methods expected to be virtual are.""" @@ -231,7 +242,6 @@ class VirtualTest(unittest.TestCase): self.assertVirtual(port.path_to_test_expectations_file) self.assertVirtual(port.test_platform_name) self.assertVirtual(port.results_directory) - self.assertVirtual(port.show_html_results_file, None) self.assertVirtual(port.test_expectations) self.assertVirtual(port.test_base_platform_names) self.assertVirtual(port.test_platform_name) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py index 3fc4613..a72627a 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py @@ -39,6 +39,7 @@ import shutil import signal import subprocess import sys +import tempfile import time import webbrowser @@ -46,7 +47,6 @@ import base import http_server from webkitpy.common.system.executive import Executive -from webkitpy.layout_tests.layout_package import test_files from webkitpy.layout_tests.layout_package import test_expectations # Chromium DRT on OSX uses WebKitDriver. @@ -82,8 +82,13 @@ def check_file_exists(path_to_file, file_description, override_step=None, class ChromiumPort(base.Port): """Abstract base class for Chromium implementations of the Port class.""" - def __init__(self, port_name=None, options=None, **kwargs): - base.Port.__init__(self, port_name, options, **kwargs) + def __init__(self, **kwargs): + base.Port.__init__(self, **kwargs) + if 'options' in kwargs: + options = kwargs['options'] + if (options and (not hasattr(options, 'configuration') or + options.configuration is None)): + options.configuration = self.default_configuration() self._chromium_base_dir = None def baseline_path(self): @@ -126,14 +131,18 @@ class ChromiumPort(base.Port): return check_file_exists(image_diff_path, 'image diff exe', override_step, logging) - def diff_image(self, expected_filename, actual_filename, + def diff_image(self, expected_contents, actual_contents, diff_filename=None, tolerance=0): executable = self._path_to_image_diff() + expected_tmpfile = tempfile.NamedTemporaryFile() + expected_tmpfile.write(expected_contents) + actual_tmpfile = tempfile.NamedTemporaryFile() + actual_tmpfile.write(actual_contents) if diff_filename: - cmd = [executable, '--diff', expected_filename, actual_filename, - diff_filename] + cmd = [executable, '--diff', expected_tmpfile.name, + actual_tmpfile.name, diff_filename] else: - cmd = [executable, expected_filename, actual_filename] + cmd = [executable, expected_tmpfile.name, actual_tmpfile.name] result = True try: @@ -144,6 +153,9 @@ class ChromiumPort(base.Port): _compare_available = False else: raise e + finally: + expected_tmpfile.close() + actual_tmpfile.close() return result def driver_name(self): @@ -183,15 +195,6 @@ class ChromiumPort(base.Port): if os.path.exists(cachedir): shutil.rmtree(cachedir) - def show_results_html_file(self, results_filename): - uri = self.get_absolute_path(results_filename) - if self._options.use_drt: - # FIXME: This should use User.open_url - webbrowser.open(uri, new=1) - else: - # Note: Not thread safe: http://bugs.python.org/issue2320 - subprocess.Popen([self._path_to_driver(), uri]) - def create_driver(self, image_path, options): """Starts a new Driver and returns a handle to it.""" if options.use_drt and sys.platform == 'darwin': @@ -236,7 +239,7 @@ class ChromiumPort(base.Port): # FIXME: This drt_overrides handling should be removed when we switch # from tes_shell to DRT. drt_overrides = '' - if self._options.use_drt: + if self._options and self._options.use_drt: drt_overrides_path = self.path_from_webkit_base('LayoutTests', 'platform', 'chromium', 'drt_expectations.txt') if os.path.exists(drt_overrides_path): @@ -259,14 +262,13 @@ class ChromiumPort(base.Port): test_platform_name = self.test_platform_name() is_debug_mode = False - all_test_files = test_files.gather_test_files(self, '*') + all_test_files = self.tests([]) if extra_test_files: all_test_files.update(extra_test_files) expectations = test_expectations.TestExpectations( self, all_test_files, expectations_str, test_platform_name, - is_debug_mode, is_lint_mode=True, - tests_are_present=False, overrides=overrides_str) + is_debug_mode, is_lint_mode=True, overrides=overrides_str) tests_dir = self.layout_tests_dir() return [self.relative_test_filename(test) for test in expectations.get_tests_with_result_type(test_expectations.SKIP)] @@ -354,6 +356,12 @@ class ChromiumDriver(base.Driver): if self._options.gp_fault_error_box: driver_args.append('--gp-fault-error-box') + + if self._options.accelerated_compositing: + driver_args.append('--enable-accelerated-compositing') + + if self._options.accelerated_2d_canvas: + driver_args.append('--enable-accelerated-2d-canvas') return driver_args def start(self): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py new file mode 100644 index 0000000..80602d9 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. + +# 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. + +from __future__ import with_statement + +import codecs +import os +import sys + +import chromium_linux +import chromium_mac +import chromium_win + + +def get(**kwargs): + """Some tests have slightly different results when run while using + hardware acceleration. In those cases, we prepend an additional directory + to the baseline paths.""" + port_name = kwargs.get('port_name', None) + if port_name == 'chromium-gpu': + if sys.platform in ('cygwin', 'win32'): + port_name = 'chromium-gpu-win' + elif sys.platform == 'linux2': + port_name = 'chromium-gpu-linux' + elif sys.platform == 'darwin': + port_name = 'chromium-gpu-mac' + else: + raise NotImplementedError('unsupported platform: %s' % + sys.platform) + + if port_name == 'chromium-gpu-linux': + return ChromiumGpuLinuxPort(**kwargs) + + if port_name.startswith('chromium-gpu-mac'): + return ChromiumGpuMacPort(**kwargs) + + if port_name.startswith('chromium-gpu-win'): + return ChromiumGpuWinPort(**kwargs) + + raise NotImplementedError('unsupported port: %s' % port_name) + + +def _set_gpu_options(options): + if options: + if options.accelerated_compositing is None: + options.accelerated_composting = True + if options.accelerated_2d_canvas is None: + options.accelerated_2d_canvas = True + + +def _gpu_overrides(port): + try: + overrides_path = port.path_from_chromium_base('webkit', 'tools', + 'layout_tests', 'test_expectations_gpu.txt') + except AssertionError: + return None + if not os.path.exists(overrides_path): + return None + with codecs.open(overrides_path, "r", "utf-8") as file: + return file.read() + + +class ChromiumGpuLinuxPort(chromium_linux.ChromiumLinuxPort): + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-gpu-linux') + _set_gpu_options(kwargs.get('options')) + chromium_linux.ChromiumLinuxPort.__init__(self, **kwargs) + + def baseline_search_path(self): + return ([self._webkit_baseline_path('chromium-gpu-linux')] + + chromium_linux.ChromiumLinuxPort.baseline_search_path(self)) + + def path_to_test_expectations_file(self): + return self.path_from_webkit_base('LayoutTests', 'platform', + 'chromium-gpu', 'test_expectations.txt') + + def test_expectations_overrides(self): + return _gpu_overrides(self) + + +class ChromiumGpuMacPort(chromium_mac.ChromiumMacPort): + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-gpu-mac') + _set_gpu_options(kwargs.get('options')) + chromium_mac.ChromiumMacPort.__init__(self, **kwargs) + + def baseline_search_path(self): + return ([self._webkit_baseline_path('chromium-gpu-mac')] + + chromium_mac.ChromiumMacPort.baseline_search_path(self)) + + def path_to_test_expectations_file(self): + return self.path_from_webkit_base('LayoutTests', 'platform', + 'chromium-gpu', 'test_expectations.txt') + + def test_expectations_overrides(self): + return _gpu_overrides(self) + + +class ChromiumGpuWinPort(chromium_win.ChromiumWinPort): + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-gpu-win' + self.version()) + _set_gpu_options(kwargs.get('options')) + chromium_win.ChromiumWinPort.__init__(self, **kwargs) + + def baseline_search_path(self): + return ([self._webkit_baseline_path('chromium-gpu-win')] + + chromium_win.ChromiumWinPort.baseline_search_path(self)) + + def path_to_test_expectations_file(self): + return self.path_from_webkit_base('LayoutTests', 'platform', + 'chromium-gpu', 'test_expectations.txt') + + def test_expectations_overrides(self): + return _gpu_overrides(self) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py new file mode 100644 index 0000000..5c79a3f --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import unittest +import chromium_gpu + + +class ChromiumGpuTest(unittest.TestCase): + def test_get_chromium_gpu_linux(self): + self.assertOverridesWorked('chromium-gpu-linux') + + def test_get_chromium_gpu_mac(self): + self.assertOverridesWorked('chromium-gpu-mac') + + def test_get_chromium_gpu_win(self): + self.assertOverridesWorked('chromium-gpu-win') + + def assertOverridesWorked(self, port_name): + # test that we got the right port + port = chromium_gpu.get(port_name=port_name, options=None) + + # we use startswith() instead of Equal to gloss over platform versions. + self.assertTrue(port.name().startswith(port_name)) + + # test that it has the right directory in front of the search path. + path = port.baseline_search_path()[0] + self.assertEqual(port._webkit_baseline_path(port_name), path) + + # test that we have the right expectations file. + self.assertTrue('chromium-gpu' in + port.path_to_test_expectations_file()) + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py index 4df43e0..176991b 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py @@ -41,12 +41,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.chromium_linux") class ChromiumLinuxPort(chromium.ChromiumPort): """Chromium Linux implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'chromium-linux' - if options and not hasattr(options, 'configuration'): - options.configuration = 'Release' - chromium.ChromiumPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-linux') + chromium.ChromiumPort.__init__(self, **kwargs) def baseline_search_path(self): port_names = ["chromium-linux", "chromium-win", "chromium", "win", "mac"] diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py index abd84ae..64016ab 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py @@ -44,12 +44,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.chromium_mac") class ChromiumMacPort(chromium.ChromiumPort): """Chromium Mac implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'chromium-mac' - if options and not hasattr(options, 'configuration'): - options.configuration = 'Release' - chromium.ChromiumPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-mac') + chromium.ChromiumPort.__init__(self, **kwargs) def baseline_search_path(self): port_names = ["chromium-mac", "chromium", "mac" + self.version(), "mac"] diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py index 7a005b1..a4a9ea6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py @@ -83,17 +83,39 @@ class ChromiumDriverTest(unittest.TestCase): self.driver._proc.stdout.readline = mock_readline self._assert_write_command_and_read_line(expected_crash=True) + +class ChromiumPortTest(unittest.TestCase): + class TestMacPort(chromium_mac.ChromiumMacPort): + def __init__(self, options): + chromium_mac.ChromiumMacPort.__init__(self, + port_name='test-port', + options=options) + + def default_configuration(self): + self.default_configuration_called = True + return 'default' + + class TestLinuxPort(chromium_linux.ChromiumLinuxPort): + def __init__(self, options): + chromium_linux.ChromiumLinuxPort.__init__(self, + port_name='test-port', + options=options) + + def default_configuration(self): + self.default_configuration_called = True + return 'default' + def test_path_to_image_diff(self): class MockOptions: def __init__(self): self.use_drt = True - port = chromium_linux.ChromiumLinuxPort('test-port', options=MockOptions()) + port = ChromiumPortTest.TestLinuxPort(options=MockOptions()) self.assertTrue(port._path_to_image_diff().endswith( - '/out/Release/ImageDiff')) - port = chromium_mac.ChromiumMacPort('test-port', options=MockOptions()) + '/out/default/ImageDiff'), msg=port._path_to_image_diff()) + port = ChromiumPortTest.TestMacPort(options=MockOptions()) self.assertTrue(port._path_to_image_diff().endswith( - '/xcodebuild/Release/ImageDiff')) + '/xcodebuild/default/ImageDiff')) # FIXME: Figure out how this is going to work on Windows. #port = chromium_win.ChromiumWinPort('test-port', options=MockOptions()) @@ -102,16 +124,37 @@ class ChromiumDriverTest(unittest.TestCase): def __init__(self): self.use_drt = True - port = chromium_linux.ChromiumLinuxPort('test-port', options=MockOptions()) + port = ChromiumPortTest.TestLinuxPort(options=MockOptions()) fake_test = os.path.join(port.layout_tests_dir(), "fast/js/not-good.js") port.test_expectations = lambda: """BUG_TEST SKIP : fast/js/not-good.js = TEXT DEFER LINUX WIN : fast/js/very-good.js = TIMEOUT PASS""" port.test_expectations_overrides = lambda: '' + port.tests = lambda paths: set() + port.path_exists = lambda test: True skipped_tests = port.skipped_layout_tests(extra_test_files=[fake_test, ]) self.assertTrue("fast/js/not-good.js" in skipped_tests) + def test_default_configuration(self): + class EmptyOptions: + def __init__(self): + pass + + options = EmptyOptions() + port = ChromiumPortTest.TestLinuxPort(options) + self.assertEquals(options.configuration, 'default') + self.assertTrue(port.default_configuration_called) + + class OptionsWithUnsetConfiguration: + def __init__(self): + self.configuration = None + + options = OptionsWithUnsetConfiguration() + port = ChromiumPortTest.TestLinuxPort(options) + self.assertEquals(options.configuration, 'default') + self.assertTrue(port.default_configuration_called) + if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py index e9a81e7..d2b0265 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py @@ -41,12 +41,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.chromium_win") class ChromiumWinPort(chromium.ChromiumPort): """Chromium Win implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = "chromium-win" + self.version() - if options and not hasattr(options, "configuration"): - options.configuration = "Release" - chromium.ChromiumPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'chromium-win' + self.version()) + chromium.ChromiumPort.__init__(self, **kwargs) def setup_environ_for_server(self): env = chromium.ChromiumPort.setup_environ_for_server(self) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py index 4940e4c..648ccad 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py @@ -46,48 +46,24 @@ from __future__ import with_statement +import os import sys import base import factory -def _read_file(path, mode='r'): - """Return the contents of a file as a string. - - Returns '' if anything goes wrong, instead of throwing an IOError. - - """ - contents = '' - try: - with open(path, mode) as f: - contents = f.read() - except IOError: - pass - return contents - - -def _write_file(path, contents, mode='w'): - """Write the string to the specified path. - - Writes should never fail, so we may raise IOError. - - """ - with open(path, mode) as f: - f.write(contents) - - class DryRunPort(object): """DryRun implementation of the Port interface.""" - def __init__(self, port_name=None, options=None): + def __init__(self, **kwargs): pfx = 'dryrun-' - if port_name.startswith(pfx): - port_name = port_name[len(pfx):] - else: - port_name = None - self._options = options - self.__delegate = factory.get(port_name, options) + if 'port_name' in kwargs: + if kwargs['port_name'].startswith(pfx): + kwargs['port_name'] = kwargs['port_name'][len(pfx):] + else: + kwargs['port_name'] = None + self.__delegate = factory.get(**kwargs) def __getattr__(self, name): return getattr(self.__delegate, name) @@ -134,19 +110,16 @@ class DryrunDriver(base.Driver): return None def run_test(self, uri, timeoutms, image_hash): - test_name = self._uri_to_test(uri) - - text_filename = self._port.expected_filename(test_name, '.txt') - text_output = _read_file(text_filename) + test_name = self._port.uri_to_test_name(uri) + path = os.path.join(self._port.layout_tests_dir(), test_name) + text_output = self._port.expected_text(path) if image_hash is not None: - image_filename = self._port.expected_filename(test_name, '.png') - image = _read_file(image_filename, 'rb') - if self._image_path: - _write_file(self._image_path, image) - hash_filename = self._port.expected_filename(test_name, - '.checksum') - hash = _read_file(hash_filename) + image = self._port.expected_image(path) + if image and self._image_path: + with open(self._image_path, 'w') as f: + f.write(image) + hash = self._port.expected_checksum(path) else: hash = None return (False, False, hash, text_output, None) @@ -156,39 +129,3 @@ class DryrunDriver(base.Driver): def stop(self): pass - - def _uri_to_test(self, uri): - """Return the base layout test name for a given URI. - - This returns the test name for a given URI, e.g., if you passed in - "file:///src/LayoutTests/fast/html/keygen.html" it would return - "fast/html/keygen.html". - - """ - if not self._layout_tests_dir: - self._layout_tests_dir = self._port.layout_tests_dir() - test = uri - - if uri.startswith("file:///"): - if sys.platform == 'win32': - test = test.replace('file:///', '') - test = test.replace('/', '\\') - else: - test = test.replace('file://', '') - return test - elif uri.startswith("http://127.0.0.1:8880/"): - # websocket tests - test = test.replace('http://127.0.0.1:8880/', - self._layout_tests_dir + '/') - return test - elif uri.startswith("http://"): - # regular HTTP test - test = test.replace('http://127.0.0.1:8000/', - self._layout_tests_dir + '/http/tests/') - return test - elif uri.startswith("https://"): - test = test.replace('https://127.0.0.1:8443/', - self._layout_tests_dir + '/http/tests/') - return test - else: - raise NotImplementedError('unknown url type: %s' % uri) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory.py index 5704f65..6935744 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory.py @@ -37,11 +37,21 @@ ALL_PORT_NAMES = ['test', 'dryrun', 'mac', 'win', 'gtk', 'qt', 'chromium-mac', 'google-chrome-mac', 'google-chrome-linux32', 'google-chrome-linux64'] -def get(port_name=None, options=None): +def get(port_name=None, options=None, **kwargs): """Returns an object implementing the Port interface. If port_name is None, this routine attempts to guess at the most appropriate port on this platform.""" - port_to_use = port_name + # Wrapped for backwards-compatibility + if port_name: + kwargs['port_name'] = port_name + if options: + kwargs['options'] = options + return _get_kwargs(**kwargs) + + +def _get_kwargs(**kwargs): + port_to_use = kwargs.get('port_name', None) + options = kwargs.get('options', None) if port_to_use is None: if sys.platform == 'win32' or sys.platform == 'cygwin': if options and hasattr(options, 'chromium') and options.chromium: @@ -62,37 +72,40 @@ def get(port_name=None, options=None): if port_to_use == 'test': import test - return test.TestPort(port_name, options) + maker = test.TestPort elif port_to_use.startswith('dryrun'): import dryrun - return dryrun.DryRunPort(port_name, options) + maker = dryrun.DryRunPort elif port_to_use.startswith('mac'): import mac - return mac.MacPort(port_name, options) + maker = mac.MacPort elif port_to_use.startswith('win'): import win - return win.WinPort(port_name, options) + maker = win.WinPort elif port_to_use.startswith('gtk'): import gtk - return gtk.GtkPort(port_name, options) + maker = gtk.GtkPort elif port_to_use.startswith('qt'): import qt - return qt.QtPort(port_name, options) + maker = qt.QtPort + elif port_to_use.startswith('chromium-gpu'): + import chromium_gpu + maker = chromium_gpu.get elif port_to_use.startswith('chromium-mac'): import chromium_mac - return chromium_mac.ChromiumMacPort(port_name, options) + maker = chromium_mac.ChromiumMacPort elif port_to_use.startswith('chromium-linux'): import chromium_linux - return chromium_linux.ChromiumLinuxPort(port_name, options) + maker = chromium_linux.ChromiumLinuxPort elif port_to_use.startswith('chromium-win'): import chromium_win - return chromium_win.ChromiumWinPort(port_name, options) + maker = chromium_win.ChromiumWinPort elif port_to_use.startswith('google-chrome'): import google_chrome - return google_chrome.GetGoogleChromePort(port_name, options) - - raise NotImplementedError('unsupported port: %s' % port_to_use) - + maker = google_chrome.GetGoogleChromePort + else: + raise NotImplementedError('unsupported port: %s' % port_to_use) + return maker(**kwargs) def get_all(options=None): """Returns all the objects implementing the Port interface.""" diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py index c0a4c5e..81c3732 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py @@ -29,6 +29,7 @@ import sys import unittest +import chromium_gpu import chromium_linux import chromium_mac import chromium_win @@ -133,6 +134,15 @@ class FactoryTest(unittest.TestCase): def test_qt(self): self.assert_port("qt", qt.QtPort) + def test_chromium_gpu_linux(self): + self.assert_port("chromium-gpu-linux", chromium_gpu.ChromiumGpuLinuxPort) + + def test_chromium_gpu_mac(self): + self.assert_port("chromium-gpu-mac", chromium_gpu.ChromiumGpuMacPort) + + def test_chromium_gpu_win(self): + self.assert_port("chromium-gpu-win", chromium_gpu.ChromiumGpuWinPort) + def test_chromium_mac(self): self.assert_port("chromium-mac", chromium_mac.ChromiumMacPort) self.assert_platform_port("darwin", self.chromium_options, diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py index 46ab3ed..bffc860 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py @@ -25,10 +25,12 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -def GetGoogleChromePort(port_name, options): +def GetGoogleChromePort(**kwargs): """Some tests have slightly different results when compiled as Google Chrome vs Chromium. In those cases, we prepend an additional directory to to the baseline paths.""" + port_name = kwargs['port_name'] + del kwargs['port_name'] if port_name == 'google-chrome-linux32': import chromium_linux @@ -39,7 +41,7 @@ def GetGoogleChromePort(port_name, options): paths.insert(0, self._webkit_baseline_path( 'google-chrome-linux32')) return paths - return GoogleChromeLinux32Port(None, options) + return GoogleChromeLinux32Port(**kwargs) elif port_name == 'google-chrome-linux64': import chromium_linux @@ -50,7 +52,7 @@ def GetGoogleChromePort(port_name, options): paths.insert(0, self._webkit_baseline_path( 'google-chrome-linux64')) return paths - return GoogleChromeLinux64Port(None, options) + return GoogleChromeLinux64Port(**kwargs) elif port_name.startswith('google-chrome-mac'): import chromium_mac @@ -61,7 +63,7 @@ def GetGoogleChromePort(port_name, options): paths.insert(0, self._webkit_baseline_path( 'google-chrome-mac')) return paths - return GoogleChromeMacPort(None, options) + return GoogleChromeMacPort(**kwargs) elif port_name.startswith('google-chrome-win'): import chromium_win @@ -72,5 +74,5 @@ def GetGoogleChromePort(port_name, options): paths.insert(0, self._webkit_baseline_path( 'google-chrome-win')) return paths - return GoogleChromeWinPort(None, options) + return GoogleChromeWinPort(**kwargs) raise NotImplementedError('unsupported port: %s' % port_name) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py index a2d7056..85e9338 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py @@ -41,6 +41,7 @@ class GetGoogleChromePortTest(unittest.TestCase): self._verify_baseline_path('google-chrome-win', 'google-chrome-win-vista') def _verify_baseline_path(self, expected_path, port_name): - port = google_chrome.GetGoogleChromePort(port_name, None) + port = google_chrome.GetGoogleChromePort(port_name=port_name, + options=None) path = port.baseline_search_path()[0] self.assertEqual(expected_path, os.path.split(path)[1]) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py index 59dc1d9..c60909e 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py @@ -39,10 +39,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.gtk") class GtkPort(WebKitPort): """WebKit Gtk implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'gtk' - WebKitPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'gtk') + WebKitPort.__init__(self, **kwargs) def _tests_for_other_platforms(self): # FIXME: This list could be dynamic based on platform name and diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py index 413b5f2..696e339 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py @@ -43,10 +43,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.mac") class MacPort(WebKitPort): """WebKit Mac implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'mac' + self.version() - WebKitPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'mac' + self.version()) + WebKitPort.__init__(self, **kwargs) def default_child_processes(self): # FIXME: new-run-webkit-tests is unstable on Mac running more than diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py index 2d650f5..47597d6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py @@ -68,14 +68,20 @@ class PortTestCase(unittest.TestCase): dir = port.layout_tests_dir() file1 = os.path.join(dir, 'fast', 'css', 'button_center.png') + fh1 = file(file1) + contents1 = fh1.read() file2 = os.path.join(dir, 'fast', 'css', 'remove-shorthand-expected.png') + fh2 = file(file2) + contents2 = fh2.read() tmpfile = tempfile.mktemp() - self.assertFalse(port.diff_image(file1, file1)) - self.assertTrue(port.diff_image(file1, file2)) + self.assertFalse(port.diff_image(contents1, contents1)) + self.assertTrue(port.diff_image(contents1, contents2)) - self.assertTrue(port.diff_image(file1, file2, tmpfile)) + self.assertTrue(port.diff_image(contents1, contents2, tmpfile)) + fh1.close() + fh2.close() # FIXME: this may not be being written? # self.assertTrue(os.path.exists(tmpfile)) # os.remove(tmpfile) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py index 158c633..4c8fa0a 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py @@ -42,10 +42,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.qt") class QtPort(WebKitPort): """QtWebKit implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'qt' - WebKitPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'qt') + WebKitPort.__init__(self, **kwargs) def _tests_for_other_platforms(self): # FIXME: This list could be dynamic based on platform name and diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py index 8e0bc11..5a0a40c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py @@ -179,7 +179,7 @@ class ServerProcess: elif size == 0: index = self._output.find('\n') + 1 - if index or self.crashed or self.timed_out: + if index > 0 or self.crashed or self.timed_out: output = self._output[0:index] self._output = self._output[index:] return output diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py index 2ccddb0..3b81167 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py @@ -31,17 +31,100 @@ from __future__ import with_statement import codecs +import fnmatch import os +import sys import time import base +# This sets basic expectations for a test. Each individual expectation +# can be overridden by a keyword argument in TestList.add(). +class TestInstance: + def __init__(self, name): + self.name = name + self.base = name[(name.rfind("/") + 1):name.rfind(".html")] + self.crash = False + self.exception = False + self.hang = False + self.keyboard = False + self.error = '' + self.timeout = False + self.actual_text = self.base + '-txt\n' + self.actual_checksum = self.base + '-checksum\n' + self.actual_image = self.base + '-png\n' + self.expected_text = self.actual_text + self.expected_checksum = self.actual_checksum + self.expected_image = self.actual_image + + +# This is an in-memory list of tests, what we want them to produce, and +# what we want to claim are the expected results. +class TestList: + def __init__(self, port): + self.port = port + self.tests = {} + + def add(self, name, **kwargs): + test = TestInstance(name) + for key, value in kwargs.items(): + test.__dict__[key] = value + self.tests[name] = test + + def keys(self): + return self.tests.keys() + + def __contains__(self, item): + return item in self.tests + + def __getitem__(self, item): + return self.tests[item] + + class TestPort(base.Port): """Test implementation of the Port interface.""" - def __init__(self, port_name=None, options=None): - base.Port.__init__(self, port_name, options) + def __init__(self, **kwargs): + base.Port.__init__(self, **kwargs) + tests = TestList(self) + tests.add('passes/image.html') + tests.add('passes/text.html') + tests.add('failures/expected/checksum.html', + actual_checksum='checksum_fail-checksum') + tests.add('failures/expected/crash.html', crash=True) + tests.add('failures/expected/exception.html', exception=True) + tests.add('failures/expected/timeout.html', timeout=True) + tests.add('failures/expected/hang.html', hang=True) + tests.add('failures/expected/missing_text.html', + expected_text=None) + tests.add('failures/expected/image.html', + actual_image='image_fail-png', + expected_image='image-png') + tests.add('failures/expected/image_checksum.html', + actual_checksum='image_checksum_fail-checksum', + actual_image='image_checksum_fail-png') + tests.add('failures/expected/keyboard.html', + keyboard=True) + tests.add('failures/expected/missing_check.html', + expected_checksum=None) + tests.add('failures/expected/missing_image.html', + expected_image=None) + tests.add('failures/expected/missing_text.html', + expected_text=None) + tests.add('failures/expected/text.html', + actual_text='text_fail-png') + tests.add('failures/unexpected/text-image-checksum.html', + actual_text='text-image-checksum_fail-txt', + actual_checksum='text-image-checksum_fail-checksum') + tests.add('http/tests/passes/text.html') + tests.add('http/tests/ssl/text.html') + tests.add('passes/error.html', error='stuff going to stderr') + tests.add('passes/image.html') + tests.add('passes/platform_image.html') + tests.add('passes/text.html') + tests.add('websocket/tests/passes/text.html') + self._tests = tests def baseline_path(self): return os.path.join(self.layout_tests_dir(), 'platform', @@ -53,12 +136,8 @@ class TestPort(base.Port): def check_build(self, needs_http): return True - def diff_image(self, expected_filename, actual_filename, + def diff_image(self, expected_contents, actual_contents, diff_filename=None, tolerance=0): - with codecs.open(actual_filename, "r", "utf-8") as actual_fh: - actual_contents = actual_fh.read() - with codecs.open(expected_filename, "r", "utf-8") as expected_fh: - expected_contents = expected_fh.read() diffed = actual_contents != expected_contents if diffed and diff_filename: with codecs.open(diff_filename, "w", "utf-8") as diff_fh: @@ -66,24 +145,79 @@ class TestPort(base.Port): (expected_contents, actual_contents)) return diffed + def expected_checksum(self, test): + test = self.relative_test_filename(test) + return self._tests[test].expected_checksum + + def expected_image(self, test): + test = self.relative_test_filename(test) + return self._tests[test].expected_image + + def expected_text(self, test): + test = self.relative_test_filename(test) + text = self._tests[test].expected_text + if not text: + text = '' + return text + + def tests(self, paths): + # Test the idea of port-specific overrides for test lists. Also + # keep in memory to speed up the test harness. + if not paths: + paths = ['*'] + + matched_tests = [] + for p in paths: + if self.path_isdir(p): + matched_tests.extend(fnmatch.filter(self._tests.keys(), p + '*')) + else: + matched_tests.extend(fnmatch.filter(self._tests.keys(), p)) + layout_tests_dir = self.layout_tests_dir() + return set([os.path.join(layout_tests_dir, p) for p in matched_tests]) + + def path_exists(self, path): + # used by test_expectations.py and printing.py + rpath = self.relative_test_filename(path) + if rpath in self._tests: + return True + if self.path_isdir(rpath): + return True + if rpath.endswith('-expected.txt'): + test = rpath.replace('-expected.txt', '.html') + return (test in self._tests and + self._tests[test].expected_text) + if rpath.endswith('-expected.checksum'): + test = rpath.replace('-expected.checksum', '.html') + return (test in self._tests and + self._tests[test].expected_checksum) + if rpath.endswith('-expected.png'): + test = rpath.replace('-expected.png', '.html') + return (test in self._tests and + self._tests[test].expected_image) + return False + def layout_tests_dir(self): return self.path_from_webkit_base('WebKitTools', 'Scripts', 'webkitpy', 'layout_tests', 'data') + def path_isdir(self, path): + # Used by test_expectations.py + # + # We assume that a path is a directory if we have any tests that + # whose prefix matches the path plus a directory modifier. + if path[-1] != '/': + path += '/' + return any([t.startswith(path) for t in self._tests.keys()]) + + def test_dirs(self): + return ['passes', 'failures'] + def name(self): return self._name def options(self): return self._options - def skipped_layout_tests(self): - return [] - - def path_to_test_expectations_file(self): - return self.path_from_webkit_base('WebKitTools', 'Scripts', - 'webkitpy', 'layout_tests', 'data', 'platform', 'test', - 'test_expectations.txt') - def _path_to_wdiff(self): return None @@ -93,9 +227,6 @@ class TestPort(base.Port): def setup_test_run(self): pass - def show_results_html_file(self, filename): - pass - def create_driver(self, image_path, options): return TestDriver(self, image_path, options, executive=None) @@ -116,9 +247,21 @@ class TestPort(base.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() - with codecs.open(expectations_path, "r", "utf-8") as file: - return file.read() + return """ +WONTFIX : failures/expected/checksum.html = IMAGE +WONTFIX : failures/expected/crash.html = CRASH +// This one actually passes because the checksums will match. +WONTFIX : failures/expected/image.html = PASS +WONTFIX : failures/expected/image_checksum.html = IMAGE +WONTFIX : failures/expected/missing_check.html = MISSING PASS +WONTFIX : failures/expected/missing_image.html = MISSING PASS +WONTFIX : failures/expected/missing_text.html = MISSING PASS +WONTFIX : failures/expected/text.html = TEXT +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 +""" def test_base_platform_names(self): return ('mac', 'win') @@ -150,68 +293,21 @@ class TestDriver(base.Driver): return True def run_test(self, uri, timeoutms, image_hash): - basename = uri[(uri.rfind("/") + 1):uri.rfind(".html")] - - if 'error' in basename: - error = basename + "_error\n" - else: - error = '' - checksum = None - # There are four currently supported types of tests: text, image, - # image hash (checksum), and stderr output. The fake output - # is the basename of the file + "-" plus the type of test output - # (or a blank string for stderr). - # - # If 'image' or 'check' appears in the basename, we assume this is - # simulating a pixel test. - # - # If 'failures' appears in the URI, then we assume this test should - # fail. Which type of failures are determined by which strings appear - # in the basename of the test. For failures that produce outputs, - # we change the fake output to basename + "_failed-". - # - # The fact that each test produces (more or less) unique output data - # will allow us to see if any results get crossed by the rest of the - # program. - if 'failures' in uri: - if 'keyboard' in basename: - raise KeyboardInterrupt - if 'exception' in basename: - raise ValueError('exception from ' + basename) - - crash = 'crash' in basename - timeout = 'timeout' in basename or 'hang' in basename - timeout = 'timeout' in basename - if 'text' in basename: - output = basename + '_failed-txt\n' - else: - output = basename + '-txt\n' - if self._port.options().pixel_tests: - if ('image' in basename or 'check' in basename): - checksum = basename + "-checksum\n" - - if 'image' in basename: - with open(self._image_path, "w") as f: - f.write(basename + "_failed-png\n") - elif 'check' in basename: - with open(self._image_path, "w") as f: - f.write(basename + "-png\n") - if 'checksum' in basename: - checksum = basename + "_failed-checksum\n" - - if 'hang' in basename: - time.sleep((float(timeoutms) * 4) / 1000.0) - else: - crash = False - timeout = False - output = basename + '-txt\n' - if self._options.pixel_tests and ( - 'image' in basename or 'check' in basename): - checksum = basename + '-checksum\n' - with open(self._image_path, "w") as f: - f.write(basename + "-png") - - return (crash, timeout, checksum, output, error) + test_name = self._port.uri_to_test_name(uri) + test = self._port._tests[test_name] + if test.keyboard: + raise KeyboardInterrupt + if test.exception: + raise ValueError('exception from ' + test_name) + if test.hang: + time.sleep((float(timeoutms) * 4) / 1000.0) + + if self._port.options().pixel_tests and test.actual_image: + with open(self._image_path, 'w') as file: + file.write(test.actual_image) + + return (test.crash, test.timeout, test.actual_checksum, + test.actual_text, test.error) def start(self): pass diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test_files.py index 8f79505..3fa0fb3 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test_files.py @@ -27,11 +27,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""This module is used to find all of the layout test files used by Chromium -(across all platforms). It exposes one public function - GatherTestFiles() - +"""This module is used to find all of the layout test files used by +run-webkit-tests. It exposes one public function - find() - which takes an optional list of paths. If a list is passed in, the returned list of test files is constrained to those found under the paths passed in, -i.e. calling GatherTestFiles(["LayoutTests/fast"]) will only return files +i.e. calling find(["LayoutTests/fast"]) will only return files under that directory.""" import glob @@ -51,12 +51,12 @@ _supported_file_extensions = set(['.html', '.shtml', '.xml', '.xhtml', '.xhtmlmp _skipped_directories = set(['.svn', '_svn', 'resources', 'script-tests']) -def gather_test_files(port, paths): - """Generate a set of test files and return them. +def find(port, paths): + """Finds the set of tests under port.layout_tests_dir(). Args: - paths: a list of command line paths relative to the webkit/tests - directory. glob patterns are ok. + paths: a list of command line paths relative to the layout_tests_dir() + to limit the search to. glob patterns are ok. """ gather_start_time = time.time() paths_to_walk = set() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test_files_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test_files_unittest.py new file mode 100644 index 0000000..c37eb92 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test_files_unittest.py @@ -0,0 +1,68 @@ +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import unittest + +import base +import test_files + + +class TestFilesTest(unittest.TestCase): + def test_find_no_paths_specified(self): + port = base.Port() + layout_tests_dir = port.layout_tests_dir() + port.layout_tests_dir = lambda: os.path.join(layout_tests_dir, + 'fast', 'html') + tests = test_files.find(port, []) + self.assertNotEqual(tests, 0) + + def test_find_one_test(self): + port = base.Port() + # This is just a test picked at random but known to exist. + tests = test_files.find(port, ['fast/html/keygen.html']) + self.assertEqual(len(tests), 1) + + def test_find_glob(self): + port = base.Port() + tests = test_files.find(port, ['fast/html/key*']) + self.assertEqual(len(tests), 1) + + def test_find_with_skipped_directories(self): + port = base.Port() + tests = port.tests('userscripts') + self.assertTrue('userscripts/resources/frame1.html' not in tests) + + def test_find_with_skipped_directories_2(self): + port = base.Port() + tests = test_files.find(port, ['userscripts/resources']) + self.assertEqual(tests, set([])) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py index 88c9bdf..ed19c09 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py @@ -58,16 +58,16 @@ _log = logging.getLogger("webkitpy.layout_tests.port.webkit") class WebKitPort(base.Port): """WebKit implementation of the Port class.""" - def __init__(self, port_name=None, options=None, **kwargs): - base.Port.__init__(self, port_name, options, **kwargs) + def __init__(self, **kwargs): + base.Port.__init__(self, **kwargs) self._cached_build_root = None self._cached_apache_path = None # FIXME: disable pixel tests until they are run by default on the # build machines. - if options and (not hasattr(options, "pixel_tests") or - options.pixel_tests is None): - options.pixel_tests = False + if self._options and (not hasattr(self._options, "pixel_tests") or + self._options.pixel_tests is None): + self._options.pixel_tests = False def baseline_path(self): return self._webkit_baseline_path(self._name) @@ -84,10 +84,14 @@ class WebKitPort(base.Port): return '' def _build_driver(self): - return not self._executive.run_command([ + exit_code = self._executive.run_command([ self.script_path("build-dumprendertree"), self.flag_from_configuration(self._options.configuration), ], return_exit_code=True) + if exit_code != 0: + _log.error("Failed to build DumpRenderTree") + return False + return True def _check_driver(self): driver_path = self._path_to_driver() @@ -119,7 +123,7 @@ class WebKitPort(base.Port): return False return True - def diff_image(self, expected_filename, actual_filename, + def diff_image(self, expected_contents, actual_contents, diff_filename=None, tolerance=0.1): """Return True if the two files are different. Also write a delta image of the two images into |diff_filename| if it is not None.""" @@ -128,31 +132,24 @@ class WebKitPort(base.Port): # parameter, or make it go away and always use exact matches. # Handle the case where the test didn't actually generate an image. - actual_length = os.stat(actual_filename).st_size - if actual_length == 0: - if diff_filename: - shutil.copyfile(actual_filename, expected_filename) + if not actual_contents: return True - sp = self._diff_image_request(expected_filename, actual_filename, tolerance) - return self._diff_image_reply(sp, expected_filename, diff_filename) + sp = self._diff_image_request(expected_contents, actual_contents, + tolerance) + return self._diff_image_reply(sp, diff_filename) - def _diff_image_request(self, expected_filename, actual_filename, tolerance): + def _diff_image_request(self, expected_contents, actual_contents, tolerance): command = [self._path_to_image_diff(), '--tolerance', str(tolerance)] sp = server_process.ServerProcess(self, 'ImageDiff', command) - actual_length = os.stat(actual_filename).st_size - with open(actual_filename) as file: - actual_file = file.read() - expected_length = os.stat(expected_filename).st_size - with open(expected_filename) as file: - expected_file = file.read() sp.write('Content-Length: %d\n%sContent-Length: %d\n%s' % - (actual_length, actual_file, expected_length, expected_file)) + (len(actual_contents), actual_contents, + len(expected_contents), expected_contents)) return sp - def _diff_image_reply(self, sp, expected_filename, diff_filename): + def _diff_image_reply(self, sp, diff_filename): timeout = 2.0 deadline = time.time() + timeout output = sp.read_line(timeout) @@ -178,7 +175,7 @@ class WebKitPort(base.Port): with open(diff_filename, 'w') as file: file.write(output) elif sp.timed_out: - _log.error("ImageDiff timed out on %s" % expected_filename) + _log.error("ImageDiff timed out") elif sp.crashed: _log.error("ImageDiff crashed") sp.stop() @@ -193,11 +190,6 @@ class WebKitPort(base.Port): # This port doesn't require any specific configuration. pass - def show_results_html_file(self, results_filename): - uri = self.filename_to_uri(results_filename) - # FIXME: We should open results in the version of WebKit we built. - webbrowser.open(uri, new=1) - def create_driver(self, image_path, options): return WebKitDriver(self, image_path, options, executive=self._executive) @@ -255,7 +247,7 @@ class WebKitPort(base.Port): "MathMLElement": ["mathml"], "GraphicsLayer": ["compositing"], "WebCoreHas3DRendering": ["animations/3d", "transforms/3d"], - "WebGLShader": ["fast/canvas/webgl"], + "WebGLShader": ["fast/canvas/webgl", "compositing/webgl", "http/tests/canvas/webgl"], "WMLElement": ["http/tests/wml", "fast/wml", "wml"], "parseWCSSInputProperty": ["fast/wcss"], "isXHTMLMPDocument": ["fast/xhtmlmp"], @@ -418,12 +410,17 @@ class WebKitDriver(base.Driver): def _driver_args(self): driver_args = [] + if self._image_path: driver_args.append('--pixel-tests') - # These are used by the Chromium DRT port if self._options.use_drt: - driver_args.append('--test-shell') + if self._options.accelerated_compositing: + driver_args.append('--enable-accelerated-compositing') + + if self._options.accelerated_2d_canvas: + driver_args.append('--enable-accelerated-2d-canvas') + return driver_args def start(self): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py index fbfadc3..7b68310 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py @@ -53,7 +53,7 @@ class WebKitPortTest(unittest.TestCase): def test_skipped_directories_for_symbols(self): supported_symbols = ["GraphicsLayer", "WebCoreHas3DRendering", "isXHTMLMPDocument", "fooSymbol"] - expected_directories = set(["mathml", "fast/canvas/webgl", "http/tests/wml", "fast/wml", "wml", "fast/wcss"]) + expected_directories = set(["mathml", "fast/canvas/webgl", "compositing/webgl", "http/tests/canvas/webgl", "http/tests/wml", "fast/wml", "wml", "fast/wcss"]) result_directories = set(TestWebKitPort(supported_symbols, None)._skipped_tests_for_unsupported_features()) self.assertEqual(result_directories, expected_directories) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py index e05a69d..9e30155 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py @@ -39,10 +39,9 @@ _log = logging.getLogger("webkitpy.layout_tests.port.win") class WinPort(WebKitPort): """WebKit Win implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - if port_name is None: - port_name = 'win' - WebKitPort.__init__(self, port_name, options) + def __init__(self, **kwargs): + kwargs.setdefault('port_name', 'win') + WebKitPort.__init__(self, **kwargs) def baseline_search_path(self): # Based on code from old-run-webkit-tests expectedDirectoryForTest() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py index 3a9f923..e57ceb2 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py @@ -55,9 +55,9 @@ import sys import tempfile import time import urllib -import webbrowser import zipfile +from webkitpy.common.system import user from webkitpy.common.system.executive import run_command, ScriptError import webkitpy.common.checkout.scm as scm @@ -518,8 +518,15 @@ class Rebaseliner(object): fallback_fullpath = os.path.normpath( os.path.join(fallback_dir, fallback_file)) if fallback_fullpath.lower() != baseline_path.lower(): - if not self._diff_baselines(new_baseline, - fallback_fullpath): + with codecs.open(new_baseline, "r", + None) as file_handle1: + new_output = file_handle1.read() + with codecs.open(fallback_fullpath, "r", + None) as file_handle2: + fallback_output = file_handle2.read() + is_image = baseline_path.lower().endswith('.png') + if not self._diff_baselines(new_output, fallback_output, + is_image): _log.info(' Found same baseline at %s', fallback_fullpath) return True @@ -528,31 +535,20 @@ class Rebaseliner(object): return False - def _diff_baselines(self, file1, file2): + def _diff_baselines(self, output1, output2, is_image): """Check whether two baselines are different. Args: - file1, file2: full paths of the baselines to compare. + output1, output2: contents of the baselines to compare. Returns: True if two files are different or have different extensions. False otherwise. """ - ext1 = os.path.splitext(file1)[1].upper() - ext2 = os.path.splitext(file2)[1].upper() - if ext1 != ext2: - _log.warn('Files to compare have different ext. ' - 'File1: %s; File2: %s', file1, file2) - return True - - if ext1 == '.PNG': - return self._port.diff_image(file1, file2) + if is_image: + return self._port.diff_image(output1, output2) else: - with codecs.open(file1, "r", "utf8") as file_handle1: - output1 = file_handle1.read() - with codecs.open(file2, "r", "utf8") as file_handle2: - output2 = file_handle2.read() return self._port.compare_text(output1, output2) def _delete_baseline(self, filename): @@ -593,7 +589,7 @@ class Rebaseliner(object): # Or is new_expectations always a byte array? with open(path, "w") as file: file.write(new_expectations) - self._scm.add(path) + # self._scm.add(path) else: _log.info('No test was rebaselined so nothing to remove.') @@ -737,10 +733,7 @@ class HtmlGenerator(object): """Launch the rebaselining html in brwoser.""" _log.info('Launching html: "%s"', self._html_file) - - html_uri = self._target_port.filename_to_uri(self._html_file) - webbrowser.open(html_uri, 1) - + user.User().open_url(self._html_file) _log.info('Html launched.') def _generate_baseline_links(self, test_basename, suffix, platform): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py index dbb2b91..9ba3d6b 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py @@ -103,15 +103,20 @@ class TestRebaseliner(unittest.TestCase): def test_diff_baselines_txt(self): rebaseliner = self.make_rebaseliner() - path = os.path.join(rebaseliner._port.layout_tests_dir(), - "passes", "text-expected.txt") - self.assertFalse(rebaseliner._diff_baselines(path, path)) + output = rebaseliner._port.expected_text( + os.path.join(rebaseliner._port.layout_tests_dir(), + 'passes/text.html')) + self.assertFalse(rebaseliner._diff_baselines(output, output, + is_image=False)) def test_diff_baselines_png(self): + return rebaseliner = self.make_rebaseliner() - path = os.path.join(rebaseliner._port.layout_tests_dir(), - "passes", "image-expected.png") - self.assertFalse(rebaseliner._diff_baselines(path, path)) + image = rebaseliner._port.expected_image( + os.path.join(rebaseliner._port.layout_tests_dir(), + 'passes/image.html')) + self.assertFalse(rebaseliner._diff_baselines(image, image, + is_image=True)) if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index 14d4f0e..e9c6d2c 100755 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py @@ -68,12 +68,12 @@ from layout_package import json_layout_results_generator from layout_package import printing from layout_package import test_expectations from layout_package import test_failures -from layout_package import test_files from layout_package import test_results_uploader from test_types import image_diff from test_types import text_diff from test_types import test_type_base +from webkitpy.common.system import user from webkitpy.thirdparty import simplejson import port @@ -96,28 +96,21 @@ class TestInfo: timeout: Timeout for running the test in TestShell. """ self.filename = filename + self._port = port self.uri = port.filename_to_uri(filename) self.timeout = timeout - # FIXME: Confusing that the file is .checksum and we call it "hash" - self._expected_hash_path = port.expected_filename(filename, '.checksum') - self._have_read_expected_hash = False - self._image_hash = None - - def _read_image_hash(self): - if not os.path.exists(self._expected_hash_path): - return None - - with codecs.open(self._expected_hash_path, "r", "ascii") as hash_file: - return hash_file.read() + self._image_checksum = -1 def image_hash(self): # Read the image_hash lazily to reduce startup time. # This class is accessed across threads, but only one thread should # ever be dealing with any given TestInfo so no locking is needed. - if not self._have_read_expected_hash: - self._have_read_expected_hash = True - self._image_hash = self._read_image_hash() - return self._image_hash + # + # Note that we use -1 to indicate that we haven't read the value, + # because expected_checksum() returns a string or None. + if self._image_checksum == -1: + self._image_checksum = self._port.expected_checksum(self.filename) + return self._image_checksum class ResultSummary(object): @@ -292,7 +285,7 @@ class TestRunner: paths += last_unexpected_results if self._options.test_list: paths += read_test_files(self._options.test_list) - self._test_files = test_files.gather_test_files(self._port, paths) + self._test_files = self._port.tests(paths) def lint(self): # Creating the expecations for each platform/configuration pair does @@ -321,7 +314,7 @@ class TestRunner: self._expectations = test_expectations.TestExpectations( self._port, test_files, expectations_str, test_platform_name, is_debug_mode, self._options.lint_test_files, - tests_are_present=True, overrides=overrides_str) + overrides=overrides_str) return self._expectations except SyntaxError, err: if self._options.lint_test_files: @@ -865,7 +858,7 @@ class TestRunner: self._printer.print_update("Clobbering old results in %s" % self._options.results_directory) layout_tests_dir = self._port.layout_tests_dir() - possible_dirs = os.listdir(layout_tests_dir) + possible_dirs = self._port.test_dirs() for dirname in possible_dirs: if os.path.isdir(os.path.join(layout_tests_dir, dirname)): shutil.rmtree(os.path.join(self._options.results_directory, @@ -1408,6 +1401,7 @@ def run(port, options, args, regular_output=sys.stderr, printer.print_update("Checking build ...") if not port.check_build(test_runner.needs_http()): + _log.error("Build check failed") return -1 result_summary = test_runner.set_up_run() @@ -1515,6 +1509,20 @@ def parse_args(args=None): optparse.make_option("--use-drt", action="store_true", default=False, help="Use DumpRenderTree instead of test_shell"), + optparse.make_option("--accelerated-compositing", + action="store_true", + help="Use hardware-accelated compositing for rendering"), + optparse.make_option("--no-accelerated-compositing", + action="store_false", + dest="accelerated_compositing", + help="Don't use hardware-accelerated compositing for rendering"), + optparse.make_option("--accelerated-2d-canvas", + action="store_true", + help="Use hardware-accelerated 2D Canvas calls"), + optparse.make_option("--no-accelerated-2d-canvas", + action="store_false", + dest="accelerated_2d_canvas", + help="Don't use hardware-accelerated 2D Canvas calls"), ] # Missing Mac-specific old-run-webkit-tests options: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py index aa96962..6fe99d6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py @@ -42,6 +42,7 @@ import unittest from webkitpy.common import array_stream from webkitpy.common.system import outputcapture +from webkitpy.common.system import user from webkitpy.layout_tests import port from webkitpy.layout_tests import run_webkit_tests from webkitpy.layout_tests.layout_package import dump_render_tree_thread @@ -49,6 +50,14 @@ from webkitpy.layout_tests.layout_package import dump_render_tree_thread from webkitpy.thirdparty.mock import Mock +class MockUser(): + def __init__(self): + self.url = None + + def open_url(self, url): + self.url = url + + def passing_run(args=[], port_obj=None, record_results=False, tests_included=False): new_args = ['--print', 'nothing'] @@ -65,7 +74,8 @@ def passing_run(args=[], port_obj=None, record_results=False, 'failures/expected/*']) options, parsed_args = run_webkit_tests.parse_args(new_args) if port_obj is None: - port_obj = port.get(options.platform, options) + port_obj = port.get(port_name=options.platform, options=options, + user=MockUser()) res = run_webkit_tests.run(port_obj, options, parsed_args) return res == 0 @@ -77,20 +87,31 @@ def logging_run(args=[], tests_included=False): new_args.extend(args) if not tests_included: new_args.extend(['passes', - 'http/tests' + 'http/tests', 'websocket/tests', 'failures/expected/*']) options, parsed_args = run_webkit_tests.parse_args(new_args) - port_obj = port.get(options.platform, options) + user = MockUser() + port_obj = port.get(port_name=options.platform, options=options, user=user) buildbot_output = array_stream.ArrayStream() regular_output = array_stream.ArrayStream() res = run_webkit_tests.run(port_obj, options, parsed_args, buildbot_output=buildbot_output, regular_output=regular_output) - return (res, buildbot_output, regular_output) + return (res, buildbot_output, regular_output, user) class MainTest(unittest.TestCase): + def test_accelerated_compositing(self): + # This just tests that we recognize the command line args + self.assertTrue(passing_run(['--accelerated-compositing'])) + self.assertTrue(passing_run(['--no-accelerated-compositing'])) + + def test_accelerated_2d_canvas(self): + # This just tests that we recognize the command line args + self.assertTrue(passing_run(['--accelerated-2d-canvas'])) + self.assertTrue(passing_run(['--no-accelerated-2d-canvas'])) + def test_basic(self): self.assertTrue(passing_run()) @@ -99,13 +120,13 @@ class MainTest(unittest.TestCase): self.assertTrue(passing_run(['--batch-size', '2'])) def test_child_process_1(self): - (res, buildbot_output, regular_output) = logging_run( + (res, buildbot_output, regular_output, user) = logging_run( ['--print', 'config', '--child-processes', '1']) self.assertTrue('Running one DumpRenderTree\n' in regular_output.get()) def test_child_processes_2(self): - (res, buildbot_output, regular_output) = logging_run( + (res, buildbot_output, regular_output, user) = logging_run( ['--print', 'config', '--child-processes', '2']) self.assertTrue('Running 2 DumpRenderTrees in parallel\n' in regular_output.get()) @@ -119,15 +140,15 @@ class MainTest(unittest.TestCase): self.assertTrue(passing_run(['--full-results-html'])) def test_help_printing(self): - res, out, err = logging_run(['--help-printing']) + res, out, err, user = logging_run(['--help-printing']) self.assertEqual(res, 0) self.assertTrue(out.empty()) self.assertFalse(err.empty()) def test_hung_thread(self): - res, out, err = logging_run(['--run-singly', '--time-out-ms=50', - 'failures/expected/hang.html'], - tests_included=True) + res, out, err, user = logging_run(['--run-singly', '--time-out-ms=50', + 'failures/expected/hang.html'], + tests_included=True) self.assertEqual(res, 0) self.assertFalse(out.empty()) self.assertFalse(err.empty()) @@ -140,26 +161,27 @@ class MainTest(unittest.TestCase): def test_last_results(self): passing_run(['--clobber-old-results'], record_results=True) - (res, buildbot_output, regular_output) = logging_run( + (res, buildbot_output, regular_output, user) = logging_run( ['--print-last-failures']) self.assertEqual(regular_output.get(), ['\n\n']) self.assertEqual(buildbot_output.get(), []) def test_lint_test_files(self): # FIXME: add errors? - res, out, err = logging_run(['--lint-test-files'], tests_included=True) + res, out, err, user = logging_run(['--lint-test-files'], + tests_included=True) self.assertEqual(res, 0) self.assertTrue(out.empty()) self.assertTrue(any(['lint succeeded' in msg for msg in err.get()])) def test_no_tests_found(self): - res, out, err = logging_run(['resources'], tests_included=True) + res, out, err, user = logging_run(['resources'], tests_included=True) self.assertEqual(res, -1) self.assertTrue(out.empty()) self.assertTrue('No tests to run.\n' in err.get()) def test_no_tests_found_2(self): - res, out, err = logging_run(['foo'], tests_included=True) + res, out, err, user = logging_run(['foo'], tests_included=True) self.assertEqual(res, -1) self.assertTrue(out.empty()) self.assertTrue('No tests to run.\n' in err.get()) @@ -196,17 +218,19 @@ class MainTest(unittest.TestCase): self.assertTrue(passing_run(['--test-list=%s' % filename], tests_included=True)) os.remove(filename) - res, out, err = logging_run(['--test-list=%s' % filename], - tests_included=True) + res, out, err, user = logging_run(['--test-list=%s' % filename], + tests_included=True) self.assertEqual(res, -1) self.assertFalse(err.empty()) def test_unexpected_failures(self): # Run tests including the unexpected failures. - res, out, err = logging_run(tests_included=True) + self._url_opened = None + res, out, err, user = logging_run(tests_included=True) self.assertEqual(res, 1) self.assertFalse(out.empty()) self.assertFalse(err.empty()) + self.assertEqual(user.url, '/tmp/layout-test-results/results.html') def _mocked_open(original_open, file_list): @@ -269,6 +293,7 @@ class RebaselineTest(unittest.TestCase): finally: codecs.open = original_open + class TestRunnerTest(unittest.TestCase): def test_results_html(self): mock_port = Mock() @@ -306,11 +331,8 @@ class DryrunTest(unittest.TestCase): 'fast/html'])) def test_test(self): - res, out, err = logging_run(['--platform', 'dryrun-test', - '--pixel-tests']) - self.assertEqual(res, 2) - self.assertFalse(out.empty()) - self.assertFalse(err.empty()) + self.assertTrue(passing_run(['--platform', 'dryrun-test', + '--pixel-tests'])) class TestThread(dump_render_tree_thread.WatchableThread): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py index 879646c..1ad0fe6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py @@ -103,7 +103,11 @@ class ImageDiff(test_type_base.TestTypeBase): expected_filename = self.output_filename(filename, self.FILENAME_SUFFIX_EXPECTED + '.png') - result = port.diff_image(expected_filename, actual_filename, + expected_image = port.expected_image(filename) + with codecs.open(actual_filename, 'r', None) as file: + actual_image = file.read() + + result = port.diff_image(expected_image, actual_image, diff_filename) return result @@ -124,19 +128,12 @@ class ImageDiff(test_type_base.TestTypeBase): return failures # Compare hashes. - expected_hash_file = self._port.expected_filename(filename, - '.checksum') - expected_png_file = self._port.expected_filename(filename, '.png') - - # FIXME: We repeat this pattern often, we should share code. - expected_hash = '' - if os.path.exists(expected_hash_file): - with codecs.open(expected_hash_file, "r", "ascii") as file: - expected_hash = file.read() + expected_hash = self._port.expected_checksum(filename) + expected_png = self._port.expected_image(filename) - if not os.path.isfile(expected_png_file): + if not expected_png: # Report a missing expected PNG file. - self.write_output_files(port, filename, '.checksum', + self.write_output_files(filename, '.checksum', test_args.hash, expected_hash, encoding="ascii", print_text_diffs=False) @@ -147,17 +144,21 @@ class ImageDiff(test_type_base.TestTypeBase): # Hash matched (no diff needed, okay to return). return failures - self.write_output_files(port, filename, '.checksum', + self.write_output_files(filename, '.checksum', test_args.hash, expected_hash, encoding="ascii", print_text_diffs=False) + + # FIXME: combine next two lines self._copy_output_png(filename, test_args.png_path, '-actual.png') - self._copy_output_png(filename, expected_png_file, '-expected.png') + self.write_output_files(filename, '.png', output=None, + expected=expected_png, + encoding=None, print_text_diffs=False) # Even though we only use the result in one codepath below but we # still need to call CreateImageDiff for other codepaths. images_are_different = self._create_image_diff(port, filename, configuration) - if expected_hash == '': + if not expected_hash: failures.append(test_failures.FailureMissingImageHash()) elif test_args.hash != expected_hash: if images_are_different: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py index 753dbee..3a6e92b 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py @@ -120,7 +120,7 @@ class TestTypeBase(object): output_path = self._port.expected_filename(filename, modifier) _log.debug('resetting baseline result "%s"' % output_path) - self._write_into_file_at_path(output_path, data, encoding) + self._port.update_baseline(output_path, data, encoding) def output_filename(self, filename, modifier): """Returns a filename inside the output dir that contains modifier. @@ -164,7 +164,7 @@ class TestTypeBase(object): with codecs.open(file_path, "w", encoding=encoding) as file: file.write(contents) - def write_output_files(self, port, filename, file_type, + def write_output_files(self, filename, file_type, output, expected, encoding, print_text_diffs=False): """Writes the test output, the expected output and optionally the diff @@ -201,16 +201,16 @@ class TestTypeBase(object): # Note: We pass encoding=None for all diff writes, as we treat diff # output as binary. Diff output may contain multiple files in # conflicting encodings. - diff = port.diff_text(expected, output, expected_filename, actual_filename) + diff = self._port.diff_text(expected, output, expected_filename, actual_filename) diff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_DIFF + file_type) self._write_into_file_at_path(diff_filename, diff, encoding=None) # Shell out to wdiff to get colored inline diffs. - wdiff = port.wdiff_text(expected_filename, actual_filename) + wdiff = self._port.wdiff_text(expected_filename, actual_filename) wdiff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_WDIFF) self._write_into_file_at_path(wdiff_filename, wdiff, encoding=None) # Use WebKit's PrettyPatch.rb to get an HTML diff. - pretty_patch = port.pretty_patch_text(diff_filename) + pretty_patch = self._port.pretty_patch_text(diff_filename) pretty_patch_filename = self.output_filename(filename, self.FILENAME_SUFFIX_PRETTY_PATCH) self._write_into_file_at_path(pretty_patch_filename, pretty_patch, encoding=None) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py index 50a9995..b1f621e 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py @@ -59,24 +59,7 @@ class TestTextDiff(test_type_base.TestTypeBase): """Given the filename of the test, read the expected output from a file and normalize the text. Returns a string with the expected text, or '' if the expected output file was not found.""" - # Read the port-specific expected text. - expected_filename = self._port.expected_filename(filename, '.txt') - return self._get_normalized_text(expected_filename) - - def _get_normalized_text(self, filename): - # FIXME: We repeat this pattern often, we should share code. - if not os.path.exists(filename): - return '' - - # NOTE: -expected.txt files are ALWAYS utf-8. However, - # we do not decode the output from DRT, so we should not - # decode the -expected.txt values either to allow comparisons. - with codecs.open(filename, "r", encoding=None) as file: - text = file.read() - # We could assert that the text is valid utf-8. - - # Normalize line endings - return text.strip("\r\n").replace("\r\n", "\n") + "\n" + return self._port.expected_text(filename) def compare_output(self, port, filename, output, test_args, configuration): """Implementation of CompareOutput that checks the output text against @@ -99,7 +82,7 @@ class TestTextDiff(test_type_base.TestTypeBase): # Write output files for new tests, too. if port.compare_text(output, expected): # Text doesn't match, write output files. - self.write_output_files(port, filename, ".txt", output, + self.write_output_files(filename, ".txt", output, expected, encoding=None, print_text_diffs=True) diff --git a/WebKitTools/Scripts/webkitpy/style/checkers/test_expectations.py b/WebKitTools/Scripts/webkitpy/style/checkers/test_expectations.py index ddc3983..d2d67f3 100644 --- a/WebKitTools/Scripts/webkitpy/style/checkers/test_expectations.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/test_expectations.py @@ -93,8 +93,7 @@ class TestExpectationsChecker(object): expectations = test_expectations.TestExpectationsFile( port=self._port_obj, expectations=expectations_str, full_test_list=tests, test_platform_name=self._port_to_check, is_debug_mode=False, - is_lint_mode=True, suppress_errors=False, tests_are_present=True, - overrides=overrides) + is_lint_mode=True, suppress_errors=False, overrides=overrides) except SyntaxError, error: errors = str(error).splitlines() diff --git a/WebKitTools/Scripts/webkitpy/test/main.py b/WebKitTools/Scripts/webkitpy/test/main.py index daf255f..9351768 100644 --- a/WebKitTools/Scripts/webkitpy/test/main.py +++ b/WebKitTools/Scripts/webkitpy/test/main.py @@ -78,7 +78,7 @@ class Tester(object): return modules - def run_tests(self, sys_argv): + def run_tests(self, sys_argv, external_package_paths=None): """Run the unit tests in all *_unittest.py modules in webkitpy. This method excludes "webkitpy.common.checkout.scm_unittest" unless @@ -88,6 +88,11 @@ class Tester(object): sys_argv: A reference to sys.argv. """ + if external_package_paths is None: + external_package_paths = [] + else: + sys.path.extend(set(os.path.dirname(path) for path in external_package_paths)) + if len(sys_argv) > 1 and not sys_argv[-1].startswith("-"): # Then explicit modules or test names were provided, which # the unittest module is equipped to handle. @@ -97,9 +102,10 @@ class Tester(object): # Otherwise, auto-detect all unit tests. webkitpy_dir = os.path.dirname(webkitpy.__file__) - unittest_paths = self._find_unittest_files(webkitpy_dir) - modules = self._modules_from_paths(webkitpy_dir, unittest_paths) + modules = [] + for path in [webkitpy_dir] + external_package_paths: + modules.extend(self._modules_from_paths(path, self._find_unittest_files(path))) modules.sort() # This is a sanity check to ensure that the unit-test discovery diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py new file mode 100644 index 0000000..a347972 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py @@ -0,0 +1,158 @@ +# Copyright (c) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from webkitpy.common.system.executive import ScriptError + + +class CommitQueueTask(object): + def __init__(self, tool, commit_queue, patch): + self._tool = tool + self._commit_queue = commit_queue + self._patch = patch + self._script_error = None + + def _validate(self): + # Bugs might get closed, or patches might be obsoleted or r-'d while the + # commit-queue is processing. + self._patch = self._tool.bugs.fetch_attachment(self._patch.id()) + if self._patch.is_obsolete(): + return False + if self._patch.bug().is_closed(): + return False + if not self._patch.committer(): + return False + # Reviewer is not required. Missing reviewers will be caught during + # the ChangeLog check during landing. + return True + + def _run_command(self, command, success_message, failure_message): + try: + self._commit_queue.run_webkit_patch(command) + self._commit_queue.command_passed(success_message, patch=self._patch) + return True + except ScriptError, e: + self._script_error = e + self.failure_status_id = self._commit_queue.command_failed(failure_message, script_error=self._script_error, patch=self._patch) + return False + + def _apply(self): + return self._run_command([ + "apply-attachment", + "--force-clean", + "--non-interactive", + "--quiet", + self._patch.id(), + ], + "Applied patch", + "Patch does not apply") + + def _build(self): + return self._run_command([ + "build", + "--no-clean", + "--no-update", + "--build", + "--build-style=both", + "--quiet", + ], + "Built patch", + "Patch does not build") + + def _build_without_patch(self): + return self._run_command([ + "build", + "--force-clean", + "--no-update", + "--build", + "--build-style=both", + "--quiet", + ], + "Able to build without patch", + "Unable to build without patch") + + def _test(self): + return self._run_command([ + "build-and-test", + "--no-clean", + "--no-update", + # Notice that we don't pass --build, which means we won't build! + "--test", + "--quiet", + "--non-interactive", + ], + "Passed tests", + "Patch does not pass tests") + + def _build_and_test_without_patch(self): + return self._run_command([ + "build-and-test", + "--force-clean", + "--no-update", + "--build", + "--test", + "--quiet", + "--non-interactive", + ], + "Able to pass tests without patch", + "Unable to pass tests without patch (tree is red?)") + + def _land(self): + return self._run_command([ + "land-attachment", + "--force-clean", + "--ignore-builders", + "--quiet", + "--non-interactive", + "--parent-command=commit-queue", + self._patch.id(), + ], + "Landed patch", + "Unable to land patch") + + def run(self): + if not self._validate(): + return False + if not self._apply(): + raise self._script_error + if not self._build(): + if not self._build_without_patch(): + return False + raise self._script_error + if not self._patch.is_rollout(): + if not self._test(): + if not self._test(): + if not self._build_and_test_without_patch(): + return False + raise self._script_error + # Make sure the patch is still valid before landing (e.g., make sure + # no one has set commit-queue- since we started working on the patch.) + if not self._validate(): + return False + if not self._land(): + raise self._script_error + return True diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py new file mode 100644 index 0000000..8b46146 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py @@ -0,0 +1,194 @@ +# Copyright (c) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from datetime import datetime +import unittest + +from webkitpy.common.system.deprecated_logging import error, log +from webkitpy.common.system.outputcapture import OutputCapture +from webkitpy.thirdparty.mock import Mock +from webkitpy.tool.bot.commitqueuetask import * +from webkitpy.tool.mocktool import MockTool + + +class MockCommitQueue: + def __init__(self, error_plan): + self._error_plan = error_plan + + def run_webkit_patch(self, command): + log("run_webkit_patch: %s" % command) + if self._error_plan: + error = self._error_plan.pop(0) + if error: + raise error + + def command_passed(self, success_message, patch): + log("command_passed: success_message='%s' patch='%s'" % ( + success_message, patch.id())) + + def command_failed(self, failure_message, script_error, patch): + log("command_failed: failure_message='%s' script_error='%s' patch='%s'" % ( + failure_message, script_error, patch.id())) + return 3947 + + +class CommitQueueTaskTest(unittest.TestCase): + def _run_through_task(self, commit_queue, expected_stderr, expected_exception=None): + tool = MockTool(log_executive=True) + patch = tool.bugs.fetch_attachment(197) + task = CommitQueueTask(tool, commit_queue, patch) + OutputCapture().assert_outputs(self, task.run, expected_stderr=expected_stderr, expected_exception=expected_exception) + + def test_success_case(self): + commit_queue = MockCommitQueue([]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Built patch' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_passed: success_message='Passed tests' patch='197' +run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--quiet', '--non-interactive', '--parent-command=commit-queue', 197] +command_passed: success_message='Landed patch' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr) + + def test_apply_failure(self): + commit_queue = MockCommitQueue([ + ScriptError("MOCK apply failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_failed: failure_message='Patch does not apply' script_error='MOCK apply failure' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr, ScriptError) + + def test_build_failure(self): + commit_queue = MockCommitQueue([ + None, + ScriptError("MOCK build failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='197' +run_webkit_patch: ['build', '--force-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Able to build without patch' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr, ScriptError) + + def test_red_build_failure(self): + commit_queue = MockCommitQueue([ + None, + ScriptError("MOCK build failure"), + ScriptError("MOCK clean build failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='197' +run_webkit_patch: ['build', '--force-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_failed: failure_message='Unable to build without patch' script_error='MOCK clean build failure' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr) + + def test_flaky_test_failure(self): + commit_queue = MockCommitQueue([ + None, + None, + ScriptError("MOCK tests failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Built patch' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Patch does not pass tests' script_error='MOCK tests failure' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_passed: success_message='Passed tests' patch='197' +run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--quiet', '--non-interactive', '--parent-command=commit-queue', 197] +command_passed: success_message='Landed patch' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr) + + def test_test_failure(self): + commit_queue = MockCommitQueue([ + None, + None, + ScriptError("MOCK test failure"), + ScriptError("MOCK test failure again"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Built patch' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197' +run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--quiet', '--non-interactive'] +command_passed: success_message='Able to pass tests without patch' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr, ScriptError) + + def test_red_test_failure(self): + commit_queue = MockCommitQueue([ + None, + None, + ScriptError("MOCK test failure"), + ScriptError("MOCK test failure again"), + ScriptError("MOCK clean test failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Built patch' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197' +run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--quiet', '--non-interactive'] +command_failed: failure_message='Unable to pass tests without patch (tree is red?)' script_error='MOCK clean test failure' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr) + + def test_land_failure(self): + commit_queue = MockCommitQueue([ + None, + None, + None, + ScriptError("MOCK land failure"), + ]) + expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +command_passed: success_message='Applied patch' patch='197' +run_webkit_patch: ['build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +command_passed: success_message='Built patch' patch='197' +run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +command_passed: success_message='Passed tests' patch='197' +run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--quiet', '--non-interactive', '--parent-command=commit-queue', 197] +command_failed: failure_message='Unable to land patch' script_error='MOCK land failure' patch='197' +""" + self._run_through_task(commit_queue, expected_stderr, ScriptError) diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py new file mode 100644 index 0000000..15eaaf3 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py @@ -0,0 +1,73 @@ +# Copyright (c) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from webkitpy.common.system.deprecated_logging import log +from webkitpy.common.net.bugzilla import CommitterValidator + + +class AbstractFeeder(object): + def __init__(self, tool): + self._tool = tool + + def feed(tool): + raise NotImplementedError, "subclasses must implement" + + def update_work_items(self, item_ids): + self._tool.status_server.update_work_items(self.queue_name, item_ids) + log("Feeding %s items %s" % (self.queue_name, item_ids)) + + +class CommitQueueFeeder(AbstractFeeder): + queue_name = "commit-queue" + + def __init__(self, tool): + AbstractFeeder.__init__(self, tool) + self.committer_validator = CommitterValidator(self._tool.bugs) + + def feed(self): + patches = self._validate_patches() + patches = sorted(patches, self._patch_cmp) + patch_ids = [patch.id() for patch in patches] + self.update_work_items(patch_ids) + + def _patches_for_bug(self, bug_id): + return self._tool.bugs.fetch_bug(bug_id).commit_queued_patches(include_invalid=True) + + def _validate_patches(self): + # Not using BugzillaQueries.fetch_patches_from_commit_queue() so we can reject patches with invalid committers/reviewers. + bug_ids = self._tool.bugs.queries.fetch_bug_ids_from_commit_queue() + all_patches = sum([self._patches_for_bug(bug_id) for bug_id in bug_ids], []) + return self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches) + + def _patch_cmp(self, a, b): + # Sort first by is_rollout, then by attach_date. + # Reversing the order so that is_rollout is first. + rollout_cmp = cmp(b.is_rollout(), a.is_rollout()) + if rollout_cmp != 0: + return rollout_cmp + return cmp(a.attach_date(), b.attach_date()) diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py new file mode 100644 index 0000000..5ce00b4 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py @@ -0,0 +1,70 @@ +# Copyright (c) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from datetime import datetime +import unittest + +from webkitpy.common.system.outputcapture import OutputCapture +from webkitpy.thirdparty.mock import Mock +from webkitpy.tool.bot.feeders import * +from webkitpy.tool.mocktool import MockTool + + +class FeedersTest(unittest.TestCase): + def test_commit_queue_feeder(self): + feeder = CommitQueueFeeder(MockTool()) + expected_stderr = u"""Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) +Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) +MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. + +- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. + +- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.' +MOCK: update_work_items: commit-queue [106, 197] +Feeding commit-queue items [106, 197] +""" + OutputCapture().assert_outputs(self, feeder.feed, expected_stderr=expected_stderr) + + def _mock_attachment(self, is_rollout, attach_date): + attachment = Mock() + attachment.is_rollout = lambda: is_rollout + attachment.attach_date = lambda: attach_date + return attachment + + def test_patch_cmp(self): + long_ago_date = datetime(1900, 1, 21) + recent_date = datetime(2010, 1, 21) + attachment1 = self._mock_attachment(is_rollout=False, attach_date=recent_date) + attachment2 = self._mock_attachment(is_rollout=False, attach_date=long_ago_date) + attachment3 = self._mock_attachment(is_rollout=True, attach_date=recent_date) + attachment4 = self._mock_attachment(is_rollout=True, attach_date=long_ago_date) + attachments = [attachment1, attachment2, attachment3, attachment4] + expected_sort = [attachment4, attachment3, attachment2, attachment1] + queue = CommitQueueFeeder(MockTool()) + attachments.sort(queue._patch_cmp) + self.assertEqual(attachments, expected_sort) diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py index 289dc4a..8118653 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py @@ -141,6 +141,8 @@ class QueueEngine: def _open_work_log(self, work_item): work_item_log_path = self._delegate.work_item_log_path(work_item) + if not work_item_log_path: + return self._work_log = self._output_tee.add_log(work_item_log_path) def _ensure_work_log_closed(self): diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download.py b/WebKitTools/Scripts/webkitpy/tool/commands/download.py index ed0e3d6..9916523 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/download.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/download.py @@ -289,7 +289,7 @@ class AbstractRolloutPrepCommand(AbstractSequencedCommand): argument_names = "REVISION REASON" def _commit_info(self, revision): - commit_info = self.tool.checkout().commit_info_for_revision(revision) + commit_info = self._tool.checkout().commit_info_for_revision(revision) if commit_info and commit_info.bug_id(): # Note: Don't print a bug URL here because it will confuse the # SheriffBot because the SheriffBot just greps the output diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/openbugs.py b/WebKitTools/Scripts/webkitpy/tool/commands/openbugs.py index 5da5bbb..1b51c9f 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/openbugs.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/openbugs.py @@ -41,8 +41,8 @@ class OpenBugs(AbstractDeclarativeCommand): def _open_bugs(self, bug_ids): for bug_id in bug_ids: - bug_url = self.tool.bugs.bug_url_for_bug_id(bug_id) - self.tool.user.open_url(bug_url) + bug_url = self._tool.bugs.bug_url_for_bug_id(bug_id) + self._tool.user.open_url(bug_url) # _find_bugs_in_string mostly exists for easy unit testing. def _find_bugs_in_string(self, string): diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queries.py b/WebKitTools/Scripts/webkitpy/tool/commands/queries.py index 9b8d162..c6e45aa 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queries.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queries.py @@ -33,6 +33,7 @@ from optparse import make_option from webkitpy.common.checkout.commitinfo import CommitInfo from webkitpy.common.config.committers import CommitterList from webkitpy.common.net.buildbot import BuildBot +from webkitpy.common.net.regressionwindow import RegressionWindow from webkitpy.common.system.user import User from webkitpy.tool.grammar import pluralize from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand @@ -112,7 +113,7 @@ class LastGreenRevision(AbstractDeclarativeCommand): help_text = "Prints the last known good revision" def execute(self, options, args, tool): - print self.tool.buildbot.last_green_revision() + print self._tool.buildbot.last_green_revision() class WhatBroke(AbstractDeclarativeCommand): @@ -122,29 +123,26 @@ class WhatBroke(AbstractDeclarativeCommand): def _print_builder_line(self, builder_name, max_name_width, status_message): print "%s : %s" % (builder_name.ljust(max_name_width), status_message) - # FIXME: This is slightly different from Builder.suspect_revisions_for_green_to_red_transition - # due to needing to detect the "hit the limit" case an print a special message. def _print_blame_information_for_builder(self, builder_status, name_width, avoid_flakey_tests=True): - builder = self.tool.buildbot.builder_with_name(builder_status["name"]) + builder = self._tool.buildbot.builder_with_name(builder_status["name"]) red_build = builder.build(builder_status["build_number"]) - (last_green_build, first_red_build) = builder.find_failure_transition(red_build) - if not first_red_build: + regression_window = builder.find_regression_window(red_build) + if not regression_window.failing_build(): self._print_builder_line(builder.name(), name_width, "FAIL (error loading build information)") return - if not last_green_build: - self._print_builder_line(builder.name(), name_width, "FAIL (blame-list: sometime before %s?)" % first_red_build.revision()) + if not regression_window.build_before_failure(): + self._print_builder_line(builder.name(), name_width, "FAIL (blame-list: sometime before %s?)" % regression_window.failing_build().revision()) return - suspect_revisions = range(first_red_build.revision(), last_green_build.revision(), -1) - suspect_revisions.reverse() + revisions = regression_window.revisions() first_failure_message = "" - if (first_red_build == builder.build(builder_status["build_number"])): + if (regression_window.failing_build() == builder.build(builder_status["build_number"])): first_failure_message = " FIRST FAILURE, possibly a flaky test" - self._print_builder_line(builder.name(), name_width, "FAIL (blame-list: %s%s)" % (suspect_revisions, first_failure_message)) - for revision in suspect_revisions: - commit_info = self.tool.checkout().commit_info_for_revision(revision) + self._print_builder_line(builder.name(), name_width, "FAIL (blame-list: %s%s)" % (revisions, first_failure_message)) + for revision in revisions: + commit_info = self._tool.checkout().commit_info_for_revision(revision) if commit_info: - print commit_info.blame_string(self.tool.bugs) + print commit_info.blame_string(self._tool.bugs) else: print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision @@ -169,7 +167,7 @@ class WhoBrokeIt(AbstractDeclarativeCommand): help_text = "Print a list of revisions causing failures on %s" % BuildBot.default_host def execute(self, options, args, tool): - for revision, builders in self.tool.buildbot.revisions_causing_failures(False).items(): + for revision, builders in self._tool.buildbot.failure_map(False).revisions_causing_failures().items(): print "r%s appears to have broken %s" % (revision, [builder.name() for builder in builders]) @@ -188,7 +186,7 @@ class ResultsFor(AbstractDeclarativeCommand): print " %s" % filename def execute(self, options, args, tool): - builders = self.tool.buildbot.builders() + builders = self._tool.buildbot.builders() for builder in builders: print "%s:" % builder.name() build = builder.build_for_revision(args[0], allow_failed_lookups=True) @@ -200,13 +198,14 @@ class FailureReason(AbstractDeclarativeCommand): help_text = "Lists revisions where individual test failures started at %s" % BuildBot.default_host def _print_blame_information_for_transition(self, green_build, red_build, failing_tests): - suspect_revisions = green_build.builder().suspect_revisions_for_transition(green_build, red_build) + regression_window = RegressionWindow(green_build, red_build) + revisions = regression_window.revisions() print "SUCCESS: Build %s (r%s) was the first to show failures: %s" % (red_build._number, red_build.revision(), failing_tests) print "Suspect revisions:" - for revision in suspect_revisions: - commit_info = self.tool.checkout().commit_info_for_revision(revision) + for revision in revisions: + commit_info = self._tool.checkout().commit_info_for_revision(revision) if commit_info: - print commit_info.blame_string(self.tool.bugs) + print commit_info.blame_string(self._tool.bugs) else: print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision @@ -255,7 +254,7 @@ class FailureReason(AbstractDeclarativeCommand): return 0 def _builder_to_explain(self): - builder_statuses = self.tool.buildbot.builder_statuses() + builder_statuses = self._tool.buildbot.builder_statuses() red_statuses = [status for status in builder_statuses if not status["is_green"]] print "%s failing" % (pluralize("builder", len(red_statuses))) builder_choices = [status["name"] for status in red_statuses] @@ -264,11 +263,11 @@ class FailureReason(AbstractDeclarativeCommand): # FIXME: prompt_with_list should really take a set of objects and a set of names and then return the object. for status in red_statuses: if status["name"] == chosen_name: - return (self.tool.buildbot.builder_with_name(chosen_name), status["built_revision"]) + return (self._tool.buildbot.builder_with_name(chosen_name), status["built_revision"]) def execute(self, options, args, tool): (builder, latest_revision) = self._builder_to_explain() - start_revision = self.tool.user.prompt("Revision to walk backwards from? [%s] " % latest_revision) or latest_revision + start_revision = self._tool.user.prompt("Revision to walk backwards from? [%s] " % latest_revision) or latest_revision if not start_revision: print "Revision required." return 1 diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py index bc9ee42..80fd2ea 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py @@ -27,6 +27,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import time import traceback import os @@ -39,6 +40,8 @@ from webkitpy.common.net.statusserver import StatusServer from webkitpy.common.system.executive import ScriptError from webkitpy.common.system.deprecated_logging import error, log from webkitpy.tool.commands.stepsequence import StepSequenceErrorHandler +from webkitpy.tool.bot.commitqueuetask import CommitQueueTask +from webkitpy.tool.bot.feeders import CommitQueueFeeder from webkitpy.tool.bot.patchcollection import PersistentPatchCollection, PersistentPatchCollectionDelegate from webkitpy.tool.bot.queueengine import QueueEngine, QueueEngineDelegate from webkitpy.tool.grammar import pluralize @@ -50,6 +53,7 @@ class AbstractQueue(Command, QueueEngineDelegate): _pass_status = "Pass" _fail_status = "Fail" + _retry_status = "Retry" _error_status = "Error" def __init__(self, options=None): # Default values should never be collections (like []) as default values are shared between invocations @@ -62,20 +66,20 @@ class AbstractQueue(Command, QueueEngineDelegate): def _cc_watchers(self, bug_id): try: - self.tool.bugs.add_cc_to_bug(bug_id, self.watchers) + self._tool.bugs.add_cc_to_bug(bug_id, self.watchers) except Exception, e: traceback.print_exc() log("Failed to CC watchers.") def run_webkit_patch(self, args): - webkit_patch_args = [self.tool.path()] + webkit_patch_args = [self._tool.path()] # FIXME: This is a hack, we should have a more general way to pass global options. # FIXME: We must always pass global options and their value in one argument # because our global option code looks for the first argument which does # not begin with "-" and assumes that is the command name. - webkit_patch_args += ["--status-host=%s" % self.tool.status_server.host] + webkit_patch_args += ["--status-host=%s" % self._tool.status_server.host] webkit_patch_args.extend(args) - return self.tool.executive.run_and_throw_if_fail(webkit_patch_args) + return self._tool.executive.run_and_throw_if_fail(webkit_patch_args) def _log_directory(self): return "%s-logs" % self.name @@ -89,16 +93,16 @@ class AbstractQueue(Command, QueueEngineDelegate): raise NotImplementedError, "subclasses must implement" def begin_work_queue(self): - log("CAUTION: %s will discard all local changes in \"%s\"" % (self.name, self.tool.scm().checkout_root)) + log("CAUTION: %s will discard all local changes in \"%s\"" % (self.name, self._tool.scm().checkout_root)) if self.options.confirm: - response = self.tool.user.prompt("Are you sure? Type \"yes\" to continue: ") + response = self._tool.user.prompt("Are you sure? Type \"yes\" to continue: ") if (response != "yes"): error("User declined.") log("Running WebKit %s." % self.name) - self.tool.status_server.update_status(self.name, "Starting Queue") + self._tool.status_server.update_status(self.name, "Starting Queue") def stop_work_queue(self, reason): - self.tool.status_server.update_status(self.name, "Stopping Queue, reason: %s" % reason) + self._tool.status_server.update_status(self.name, "Stopping Queue, reason: %s" % reason) def should_continue_work_queue(self): self._iteration_count += 1 @@ -120,8 +124,8 @@ class AbstractQueue(Command, QueueEngineDelegate): def execute(self, options, args, tool, engine=QueueEngine): self.options = options # FIXME: This code is wrong. Command.options is a list, this assumes an Options element! - self.tool = tool # FIXME: This code is wrong too! Command.bind_to_tool handles this! - return engine(self.name, self, self.tool.wakeup_event).run() + self._tool = tool # FIXME: This code is wrong too! Command.bind_to_tool handles this! + return engine(self.name, self, self._tool.wakeup_event).run() @classmethod def _log_from_script_error_for_upload(cls, script_error, output_limit=None): @@ -144,20 +148,47 @@ class AbstractQueue(Command, QueueEngineDelegate): return tool.status_server.update_status(cls.name, message, state["patch"], failure_log) +class FeederQueue(AbstractQueue): + name = "feeder-queue" + + _sleep_duration = 30 # seconds + + # AbstractPatchQueue methods + + def begin_work_queue(self): + AbstractQueue.begin_work_queue(self) + self.feeders = [ + CommitQueueFeeder(self._tool), + ] + + def next_work_item(self): + # This really show inherit from some more basic class that doesn't + # understand work items, but the base class in the heirarchy currently + # understands work items. + return "synthetic-work-item" + + def should_proceed_with_work_item(self, work_item): + return True + + def process_work_item(self, work_item): + for feeder in self.feeders: + feeder.feed() + time.sleep(self._sleep_duration) + return True + + def work_item_log_path(self, work_item): + return None + + def handle_unexpected_error(self, work_item, message): + log(message) + + class AbstractPatchQueue(AbstractQueue): def _update_status(self, message, patch=None, results_file=None): - self.tool.status_server.update_status(self.name, message, patch, results_file) - - # Note, eventually this will be done by a separate "feeder" queue - # whose job it is to poll bugzilla and feed work items into the - # status server for other queues to munch on. - def _update_work_items(self, patch_ids): - self.tool.status_server.update_work_items(self.name, patch_ids) - if patch_ids: - self.log_progress(patch_ids) + return self._tool.status_server.update_status(self.name, message, patch, results_file) def _fetch_next_work_item(self): - return self.tool.status_server.next_work_item(self.name) + return self._tool.status_server.next_work_item(self.name) def _did_pass(self, patch): self._update_status(self._pass_status, patch) @@ -165,6 +196,9 @@ class AbstractPatchQueue(AbstractQueue): def _did_fail(self, patch): self._update_status(self._fail_status, patch) + def _did_retry(self, patch): + self._update_status(self._retry_status, patch) + def _did_error(self, patch, reason): message = "%s: %s" % (self._error_status, reason) self._update_status(message, patch) @@ -172,178 +206,63 @@ class AbstractPatchQueue(AbstractQueue): def work_item_log_path(self, patch): return os.path.join(self._log_directory(), "%s.log" % patch.bug_id()) - def log_progress(self, patch_ids): - log("%s in %s [%s]" % (pluralize("patch", len(patch_ids)), self.name, ", ".join(map(str, patch_ids)))) - class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): name = "commit-queue" - def __init__(self): - AbstractPatchQueue.__init__(self) # AbstractPatchQueue methods def begin_work_queue(self): AbstractPatchQueue.begin_work_queue(self) - self.committer_validator = CommitterValidator(self.tool.bugs) - - def _validate_patches_in_commit_queue(self): - # Not using BugzillaQueries.fetch_patches_from_commit_queue() so we can reject patches with invalid committers/reviewers. - bug_ids = self.tool.bugs.queries.fetch_bug_ids_from_commit_queue() - all_patches = sum([self.tool.bugs.fetch_bug(bug_id).commit_queued_patches(include_invalid=True) for bug_id in bug_ids], []) - return self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches) - - def _patch_cmp(self, a, b): - # Sort first by is_rollout, then by attach_date. - # Reversing the order so that is_rollout is first. - rollout_cmp = cmp(b.is_rollout(), a.is_rollout()) - if (rollout_cmp != 0): - return rollout_cmp - return cmp(a.attach_date(), b.attach_date()) - - def _feed_work_items_to_server(self): - # Grab the set of patches from bugzilla, sort them, and update the status server. - # Eventually this will all be done by a separate feeder queue. - patches = self._validate_patches_in_commit_queue() - patches = sorted(patches, self._patch_cmp) - self._update_work_items([patch.id() for patch in patches]) + self.committer_validator = CommitterValidator(self._tool.bugs) def next_work_item(self): - self._feed_work_items_to_server() - # The grab the next patch to work on back from the status server. patch_id = self._fetch_next_work_item() if not patch_id: return None - return self.tool.bugs.fetch_attachment(patch_id) - - def _can_build_and_test_without_patch(self): - try: - self.run_webkit_patch([ - "build-and-test", - "--force-clean", - "--build", - "--test", - "--non-interactive", - "--no-update", - "--build-style=both", - "--quiet"]) - return True - except ScriptError, e: - failure_log = self._log_from_script_error_for_upload(e) - self._update_status("Unable to build and test without patch", results_file=failure_log) - return False + return self._tool.bugs.fetch_attachment(patch_id) def should_proceed_with_work_item(self, patch): patch_text = "rollout patch" if patch.is_rollout() else "patch" - self._update_status("Landing %s" % patch_text, patch) + self._update_status("Processing %s" % patch_text, patch) return True - def _build_and_test_patch(self, patch, first_run=False): + def process_work_item(self, patch): + self._cc_watchers(patch.bug_id()) + task = CommitQueueTask(self._tool, self, patch) try: - args = [ - "build-and-test-attachment", - "--force-clean", - "--build", - "--non-interactive", - "--build-style=both", - "--quiet", - patch.id() - ] - # We don't bother to run tests for rollouts as that makes them too slow. - if not patch.is_rollout(): - args.append("--test") - if not first_run: - # The first time through, we don't reject the patch from the - # commit queue because we want to make sure we can build and - # test ourselves. However, the second time through, we - # register ourselves as the parent-command so we can reject - # the patch on failure. - args.append("--parent-command=commit-queue") - # The second time through, we also don't want to update so we - # know we're testing the same revision that we successfully - # built and tested. - args.append("--no-update") - self.run_webkit_patch(args) - return True + if task.run(): + self._did_pass(patch) + return True + self._did_retry(patch) except ScriptError, e: - failure_log = self._log_from_script_error_for_upload(e) - self._update_status("Unable to build and test patch", patch=patch, results_file=failure_log) - if first_run: - return False + validator = CommitterValidator(self._tool.bugs) + validator.reject_patch_from_commit_queue(patch.id(), self._error_message_for_bug(task.failure_status_id, e)) self._did_fail(patch) - raise - - def _revalidate_patch(self, patch): - # Bugs might get closed, or patches might be obsoleted or r-'d while the - # commit-queue is processing. Do one last minute check before landing. - patch = self.tool.bugs.fetch_attachment(patch.id()) - if patch.is_obsolete(): - return None - if patch.bug().is_closed(): - return None - if not patch.committer(): - return None - # Reviewer is not required. Misisng reviewers will be caught during the ChangeLog check during landing. - return patch - - def _land(self, patch): - try: - args = [ - "land-attachment", - "--force-clean", - "--non-interactive", - "--ignore-builders", - "--quiet", - "--parent-command=commit-queue", - patch.id(), - ] - self.run_webkit_patch(args) - self._did_pass(patch) - except ScriptError, e: - failure_log = self._log_from_script_error_for_upload(e) - self._update_status("Unable to land patch", patch=patch, results_file=failure_log) - self._did_fail(patch) - raise - - def process_work_item(self, patch): - self._cc_watchers(patch.bug_id()) - if not self._build_and_test_patch(patch, first_run=True): - self._update_status("Building and testing without the patch as a sanity check", patch) - # The patch failed to build and test. It's possible that the - # tree is busted. To check that case, we try to build and test - # without the patch. - if not self._can_build_and_test_without_patch(): - return False - self._update_status("Build and test succeeded, trying again with patch", patch) - # Hum, looks like the patch is actually bad. Of course, we could - # have been bitten by a flaky test the first time around. We try - # to build and test again. If it fails a second time, we're pretty - # sure its a bad test and re can reject it outright. - self._build_and_test_patch(patch) - # Do one last check to catch any bug changes (cq-, closed, reviewer changed, etc.) - # This helps catch races between the bots if locks expire. - patch = self._revalidate_patch(patch) - if not patch: - return False - self._land(patch) - return True def handle_unexpected_error(self, patch, message): self.committer_validator.reject_patch_from_commit_queue(patch.id(), message) - # StepSequenceErrorHandler methods - @staticmethod - def _error_message_for_bug(tool, status_id, script_error): + def command_passed(self, message, patch): + self._update_status(message, patch=patch) + + def command_failed(self, message, script_error, patch): + failure_log = self._log_from_script_error_for_upload(script_error) + return self._update_status(message, patch=patch, results_file=failure_log) + + def _error_message_for_bug(self, status_id, script_error): if not script_error.output: return script_error.message_with_output() - results_link = tool.status_server.results_url_for_status(status_id) + results_link = self._tool.status_server.results_url_for_status(status_id) return "%s\nFull output: %s" % (script_error.message_with_output(), results_link) - @classmethod + # StepSequenceErrorHandler methods + def handle_script_error(cls, tool, state, script_error): - status_id = cls._update_status_for_script_error(tool, state, script_error) - validator = CommitterValidator(tool.bugs) - validator.reject_patch_from_commit_queue(state["patch"].id(), cls._error_message_for_bug(tool, status_id, script_error)) + # Hitting this error handler should be pretty rare. It does occur, + # however, when a patch no longer applies to top-of-tree in the final + # land step. + log(script_error.message_with_output()) @classmethod def handle_checkout_needs_update(cls, tool, state, options, error): @@ -368,7 +287,7 @@ class RietveldUploadQueue(AbstractPatchQueue, StepSequenceErrorHandler): # AbstractPatchQueue methods def next_work_item(self): - patch_id = self.tool.bugs.queries.fetch_first_patch_from_rietveld_queue() + patch_id = self._tool.bugs.queries.fetch_first_patch_from_rietveld_queue() if patch_id: return patch_id self._update_status("Empty queue") @@ -393,7 +312,7 @@ class RietveldUploadQueue(AbstractPatchQueue, StepSequenceErrorHandler): def handle_unexpected_error(self, patch, message): log(message) - self._reject_patch(self.tool, patch.id()) + self._reject_patch(self._tool, patch.id()) # StepSequenceErrorHandler methods @@ -417,10 +336,10 @@ class AbstractReviewQueue(AbstractPatchQueue, PersistentPatchCollectionDelegate, return self.name def fetch_potential_patch_ids(self): - return self.tool.bugs.queries.fetch_attachment_ids_from_review_queue() + return self._tool.bugs.queries.fetch_attachment_ids_from_review_queue() def status_server(self): - return self.tool.status_server + return self._tool.status_server def is_terminal_status(self, status): return status == "Pass" or status == "Fail" or status.startswith("Error:") @@ -434,7 +353,7 @@ class AbstractReviewQueue(AbstractPatchQueue, PersistentPatchCollectionDelegate, def next_work_item(self): patch_id = self._patches.next() if patch_id: - return self.tool.bugs.fetch_attachment(patch_id) + return self._tool.bugs.fetch_attachment(patch_id) def should_proceed_with_work_item(self, patch): raise NotImplementedError, "subclasses must implement" diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py index 2deee76..029814e 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py @@ -47,20 +47,16 @@ class TestReviewQueue(AbstractReviewQueue): name = "test-review-queue" +class TestFeederQueue(FeederQueue): + _sleep_duration = 0 + + class MockRolloutPatch(MockPatch): def is_rollout(self): return True class AbstractQueueTest(CommandsTest): - def _assert_log_progress_output(self, patch_ids, progress_output): - OutputCapture().assert_outputs(self, TestQueue().log_progress, [patch_ids], expected_stderr=progress_output) - - def test_log_progress(self): - self._assert_log_progress_output([1,2,3], "3 patches in test-queue [1, 2, 3]\n") - self._assert_log_progress_output(["1","2","3"], "3 patches in test-queue [1, 2, 3]\n") - self._assert_log_progress_output([1], "1 patch in test-queue [1]\n") - def test_log_directory(self): self.assertEquals(TestQueue()._log_directory(), "test-queue-logs") @@ -115,6 +111,29 @@ class AbstractQueueTest(CommandsTest): self._assert_log_message(script_error, expected_output) +class FeederQueueTest(QueuesTest): + def test_feeder_queue(self): + queue = TestFeederQueue() + tool = MockTool(log_executive=True) + expected_stderr = { + "begin_work_queue": self._default_begin_work_queue_stderr("feeder-queue", MockSCM.fake_checkout_root), + "should_proceed_with_work_item": "", + "next_work_item": "", + "process_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) +Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) +MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. + +- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. + +- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.' +MOCK: update_work_items: commit-queue [106, 197] +Feeding commit-queue items [106, 197] +""", + "handle_unexpected_error": "Mock error message\n", + } + self.assert_queue_outputs(queue, tool=tool, expected_stderr=expected_stderr) + + class AbstractPatchQueueTest(CommandsTest): def test_fetch_next_work_item(self): queue = AbstractPatchQueue() @@ -167,7 +186,7 @@ class SecondThoughtsCommitQueue(CommitQueue): "attacher_email": "Contributer1", } patch = Attachment(attachment_dictionary, None) - self.tool.bugs.set_override_patch(patch) + self._tool.bugs.set_override_patch(patch) return True @@ -175,40 +194,58 @@ class CommitQueueTest(QueuesTest): def test_commit_queue(self): expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr("commit-queue", MockSCM.fake_checkout_root), - "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing patch\n", - # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. - "next_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py.\n\n- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.\n\n- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.' -MOCK: update_work_items: commit-queue [106, 197] -2 patches in commit-queue [106, 197] + "should_proceed_with_work_item": "MOCK: update_status: commit-queue Processing patch\n", + "next_work_item": "", + "process_work_item": """MOCK: update_status: commit-queue Applied patch +MOCK: update_status: commit-queue Built patch +MOCK: update_status: commit-queue Passed tests +MOCK: update_status: commit-queue Landed patch +MOCK: update_status: commit-queue Pass """, - "process_work_item": "MOCK: update_status: commit-queue Pass\n", "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'Mock error message'\n", - "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'ScriptError error message'\n", + "handle_script_error": "ScriptError error message\n", } self.assert_queue_outputs(CommitQueue(), expected_stderr=expected_stderr) + def test_commit_queue_failure(self): + expected_stderr = { + "begin_work_queue": self._default_begin_work_queue_stderr("commit-queue", MockSCM.fake_checkout_root), + "should_proceed_with_work_item": "MOCK: update_status: commit-queue Processing patch\n", + "next_work_item": "", + "process_work_item": """MOCK: update_status: commit-queue Patch does not apply +MOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'MOCK script error' +MOCK: update_status: commit-queue Fail +""", + "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'Mock error message'\n", + "handle_script_error": "ScriptError error message\n", + } + queue = CommitQueue() + + def mock_run_webkit_patch(command): + raise ScriptError('MOCK script error') + + queue.run_webkit_patch = mock_run_webkit_patch + self.assert_queue_outputs(queue, expected_stderr=expected_stderr) + def test_rollout(self): tool = MockTool(log_executive=True) tool.buildbot.light_tree_on_fire() expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr("commit-queue", MockSCM.fake_checkout_root), - "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing patch\n", - # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. - "next_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. - -- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. - -- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.' -MOCK: update_work_items: commit-queue [106, 197] -2 patches in commit-queue [106, 197] + "should_proceed_with_work_item": "MOCK: update_status: commit-queue Processing patch\n", + "next_work_item": "", + "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +MOCK: update_status: commit-queue Applied patch +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +MOCK: update_status: commit-queue Built patch +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +MOCK: update_status: commit-queue Passed tests +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--ignore-builders', '--quiet', '--non-interactive', '--parent-command=commit-queue', 197] +MOCK: update_status: commit-queue Landed patch +MOCK: update_status: commit-queue Pass """, - "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build-and-test-attachment', '--force-clean', '--build', '--non-interactive', '--build-style=both', '--quiet', 197, '--test']\nMOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--non-interactive', '--ignore-builders', '--quiet', '--parent-command=commit-queue', 197]\nMOCK: update_status: commit-queue Pass\n", "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'Mock error message'\n", - "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'ScriptError error message'\n", + "handle_script_error": "ScriptError error message\n", } self.assert_queue_outputs(CommitQueue(), tool=tool, expected_stderr=expected_stderr) @@ -218,52 +255,23 @@ MOCK: update_work_items: commit-queue [106, 197] rollout_patch = MockRolloutPatch() expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr("commit-queue", MockSCM.fake_checkout_root), - "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing rollout patch\n", - # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. - "next_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) -MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. - -- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. - -- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.' -MOCK: update_work_items: commit-queue [106, 197] -2 patches in commit-queue [106, 197] + "should_proceed_with_work_item": "MOCK: update_status: commit-queue Processing rollout patch\n", + "next_work_item": "", + "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--force-clean', '--non-interactive', '--quiet', 197] +MOCK: update_status: commit-queue Applied patch +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build', '--no-clean', '--no-update', '--build', '--build-style=both', '--quiet'] +MOCK: update_status: commit-queue Built patch +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build-and-test', '--no-clean', '--no-update', '--test', '--quiet', '--non-interactive'] +MOCK: update_status: commit-queue Passed tests +MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--ignore-builders', '--quiet', '--non-interactive', '--parent-command=commit-queue', 197] +MOCK: update_status: commit-queue Landed patch +MOCK: update_status: commit-queue Pass """, - "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build-and-test-attachment', '--force-clean', '--build', '--non-interactive', '--build-style=both', '--quiet', 197]\nMOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--non-interactive', '--ignore-builders', '--quiet', '--parent-command=commit-queue', 197]\nMOCK: update_status: commit-queue Pass\n", "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'Mock error message'\n", - "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '197' with comment 'Rejecting patch 197 from commit-queue.' and additional comment 'ScriptError error message'\n", + "handle_script_error": "ScriptError error message\n", } self.assert_queue_outputs(CommitQueue(), tool=tool, work_item=rollout_patch, expected_stderr=expected_stderr) - def test_can_build_and_test(self): - queue = CommitQueue() - tool = MockTool() - tool.executive = Mock() - queue.bind_to_tool(tool) - self.assertTrue(queue._can_build_and_test_without_patch()) - expected_run_args = ["echo", "--status-host=example.com", "build-and-test", "--force-clean", "--build", "--test", "--non-interactive", "--no-update", "--build-style=both", "--quiet"] - tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args) - - def _mock_attachment(self, is_rollout, attach_date): - attachment = Mock() - attachment.is_rollout = lambda: is_rollout - attachment.attach_date = lambda: attach_date - return attachment - - def test_patch_cmp(self): - long_ago_date = datetime(1900, 1, 21) - recent_date = datetime(2010, 1, 21) - attachment1 = self._mock_attachment(is_rollout=False, attach_date=recent_date) - attachment2 = self._mock_attachment(is_rollout=False, attach_date=long_ago_date) - attachment3 = self._mock_attachment(is_rollout=True, attach_date=recent_date) - attachment4 = self._mock_attachment(is_rollout=True, attach_date=long_ago_date) - attachments = [attachment1, attachment2, attachment3, attachment4] - expected_sort = [attachment4, attachment3, attachment2, attachment1] - queue = CommitQueue() - attachments.sort(queue._patch_cmp) - self.assertEqual(attachments, expected_sort) - def test_auto_retry(self): queue = CommitQueue() options = Mock() @@ -282,7 +290,13 @@ MOCK: update_work_items: commit-queue [106, 197] def test_manual_reject_during_processing(self): queue = SecondThoughtsCommitQueue() queue.bind_to_tool(MockTool()) - queue.process_work_item(MockPatch()) + expected_stderr = """MOCK: update_status: commit-queue Applied patch +MOCK: update_status: commit-queue Built patch +MOCK: update_status: commit-queue Passed tests +MOCK: update_status: commit-queue Landed patch +MOCK: update_status: commit-queue Pass +""" + OutputCapture().assert_outputs(self, queue.process_work_item, [MockPatch()], expected_stderr=expected_stderr) class RietveldUploadQueueTest(QueuesTest): diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py index aa3cef4..9f3583d 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py @@ -32,6 +32,7 @@ from webkitpy.common.net.bugzilla import Attachment from webkitpy.common.system.outputcapture import OutputCapture from webkitpy.common.system.executive import ScriptError from webkitpy.thirdparty.mock import Mock +from webkitpy.tool.commands.stepsequence import StepSequenceErrorHandler from webkitpy.tool.mocktool import MockTool @@ -100,4 +101,6 @@ class QueuesTest(unittest.TestCase): self.assert_outputs(queue.should_proceed_with_work_item, "should_proceed_with_work_item", [work_item], expected_stdout, expected_stderr, expected_exceptions) self.assert_outputs(queue.process_work_item, "process_work_item", [work_item], expected_stdout, expected_stderr, expected_exceptions) self.assert_outputs(queue.handle_unexpected_error, "handle_unexpected_error", [work_item, "Mock error message"], expected_stdout, expected_stderr, expected_exceptions) - self.assert_outputs(queue.handle_script_error, "handle_script_error", [tool, {"patch": MockPatch()}, ScriptError(message="ScriptError error message", script_args="MockErrorCommand")], expected_stdout, expected_stderr, expected_exceptions) + # Should we have a different function for testing StepSequenceErrorHandlers? + if isinstance(queue, StepSequenceErrorHandler): + self.assert_outputs(queue.handle_script_error, "handle_script_error", [tool, {"patch": MockPatch()}, ScriptError(message="ScriptError error message", script_args="MockErrorCommand")], expected_stdout, expected_stderr, expected_exceptions) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/rebaseline.py b/WebKitTools/Scripts/webkitpy/tool/commands/rebaseline.py index 78e06c6..abfa850 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/rebaseline.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/rebaseline.py @@ -72,15 +72,15 @@ class Rebaseline(AbstractDeclarativeCommand): # FIXME: This should share more code with FailureReason._builder_to_explain def _builder_to_pull_from(self): - builder_statuses = self.tool.buildbot.builder_statuses() + builder_statuses = self._tool.buildbot.builder_statuses() red_statuses = [status for status in builder_statuses if not status["is_green"]] print "%s failing" % (pluralize("builder", len(red_statuses))) builder_choices = [status["name"] for status in red_statuses] - chosen_name = self.tool.user.prompt_with_list("Which builder to pull results from:", builder_choices) + chosen_name = self._tool.user.prompt_with_list("Which builder to pull results from:", builder_choices) # FIXME: prompt_with_list should really take a set of objects and a set of names and then return the object. for status in red_statuses: if status["name"] == chosen_name: - return (self.tool.buildbot.builder_with_name(chosen_name), status["build_number"]) + return (self._tool.buildbot.builder_with_name(chosen_name), status["build_number"]) def _replace_expectation_with_remote_result(self, local_file, remote_file): (downloaded_file, headers) = urllib.urlretrieve(remote_file) @@ -90,7 +90,8 @@ class Rebaseline(AbstractDeclarativeCommand): parsed_results = build.layout_test_results().parsed_results() # FIXME: This probably belongs as API on LayoutTestResults # but .failing_tests() already means something else. - return parsed_results[LayoutTestResults.fail_key] + failing_tests = parsed_results[LayoutTestResults.fail_key] + return self._tool.user.prompt_with_list("Which test(s) to rebaseline:", failing_tests, can_choose_multiple=True) def _results_url_for_test(self, build, test): test_base = os.path.splitext(test)[0] diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py index 24c8517..23d013d 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py @@ -50,9 +50,9 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler): def begin_work_queue(self): AbstractQueue.begin_work_queue(self) - self._sheriff = Sheriff(self.tool, self) - self._irc_bot = SheriffIRCBot(self.tool, self._sheriff) - self.tool.ensure_irc_connected(self._irc_bot.irc_delegate()) + self._sheriff = Sheriff(self._tool, self) + self._irc_bot = SheriffIRCBot(self._tool, self._sheriff) + self._tool.ensure_irc_connected(self._irc_bot.irc_delegate()) def work_item_log_path(self, new_failures): return os.path.join("%s-logs" % self.name, "%s.log" % new_failures.keys()[0]) @@ -86,12 +86,12 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler): self._update() # We do one read from buildbot to ensure a consistent view. - revisions_causing_failures = self.tool.buildbot.revisions_causing_failures() + revisions_causing_failures = self._tool.buildbot.failure_map().revisions_causing_failures() # Similarly, we read once from our the status_server. old_failing_svn_revisions = [] for svn_revision in revisions_causing_failures.keys(): - if self.tool.status_server.svn_revision(svn_revision): + if self._tool.status_server.svn_revision(svn_revision): old_failing_svn_revisions.append(svn_revision) new_failures = self._new_failures(revisions_causing_failures, @@ -108,7 +108,7 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler): blame_list = new_failures.keys() for svn_revision, builders in new_failures.items(): try: - commit_info = self.tool.checkout().commit_info_for_revision(svn_revision) + commit_info = self._tool.checkout().commit_info_for_revision(svn_revision) if not commit_info: print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision continue @@ -120,7 +120,7 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler): builders) finally: for builder in builders: - self.tool.status_server.update_svn_revision(svn_revision, + self._tool.status_server.update_svn_revision(svn_revision, builder.name()) return True diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py index 4a15ed6..107d8db 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py @@ -82,14 +82,14 @@ class CleanPendingCommit(AbstractDeclarativeCommand): def execute(self, options, args, tool): committers = CommitterList() for bug_id in tool.bugs.queries.fetch_bug_ids_from_pending_commit_list(): - bug = self.tool.bugs.fetch_bug(bug_id) + bug = self._tool.bugs.fetch_bug(bug_id) patches = bug.patches(include_obsolete=True) for patch in patches: flags_to_clear = self._flags_to_clear_on_patch(patch) if not flags_to_clear: continue message = "Cleared %s from obsolete attachment %s so that this bug does not appear in http://webkit.org/pending-commit." % (flags_to_clear, patch.id()) - self.tool.bugs.obsolete_attachment(patch.id(), message) + self._tool.bugs.obsolete_attachment(patch.id(), message) class AssignToCommitter(AbstractDeclarativeCommand): @@ -104,7 +104,7 @@ class AssignToCommitter(AbstractDeclarativeCommand): def _assign_bug_to_last_patch_attacher(self, bug_id): committers = CommitterList() - bug = self.tool.bugs.fetch_bug(bug_id) + bug = self._tool.bugs.fetch_bug(bug_id) if not bug.is_unassigned(): assigned_to_email = bug.assigned_to_email() log("Bug %s is already assigned to %s (%s)." % (bug_id, assigned_to_email, committers.committer_by_email(assigned_to_email))) @@ -128,7 +128,7 @@ class AssignToCommitter(AbstractDeclarativeCommand): return reassign_message = "Attachment %s was posted by a committer and has review+, assigning to %s for commit." % (latest_patch.id(), committer.full_name) - self.tool.bugs.reassign_bug(bug_id, committer.bugzilla_email(), reassign_message) + self._tool.bugs.reassign_bug(bug_id, committer.bugzilla_email(), reassign_message) def execute(self, options, args, tool): for bug_id in tool.bugs.queries.fetch_bug_ids_from_pending_commit_list(): diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool.py b/WebKitTools/Scripts/webkitpy/tool/mocktool.py index 8a6188a..277bd08 100644 --- a/WebKitTools/Scripts/webkitpy/tool/mocktool.py +++ b/WebKitTools/Scripts/webkitpy/tool/mocktool.py @@ -350,6 +350,16 @@ class MockBuilder(object): self._name, username, comments)) +class MockFailureMap(): + def __init__(self, buildbot): + self._buildbot = buildbot + + def revisions_causing_failures(self): + return { + "29837": [self._buildbot.builder_with_name("Builder1")], + } + + class MockBuildBot(object): buildbot_host = "dummy_buildbot_host" def __init__(self): @@ -394,10 +404,8 @@ class MockBuildBot(object): def light_tree_on_fire(self): self._mock_builder2_status["is_green"] = False - def revisions_causing_failures(self): - return { - "29837": [self.builder_with_name("Builder1")], - } + def failure_map(self): + return MockFailureMap(self) class MockSCM(Mock): @@ -483,8 +491,8 @@ class MockUser(object): def page(self, message): pass - def confirm(self, message=None): - return True + def confirm(self, message=None, default='y'): + return default == 'y' def can_open_url(self): return True diff --git a/WebKitTools/Scripts/webkitpy/tool/multicommandtool.py b/WebKitTools/Scripts/webkitpy/tool/multicommandtool.py index 12ede2e..4848ae5 100644 --- a/WebKitTools/Scripts/webkitpy/tool/multicommandtool.py +++ b/WebKitTools/Scripts/webkitpy/tool/multicommandtool.py @@ -53,7 +53,7 @@ class Command(object): self.required_arguments = self._parse_required_arguments(argument_names) self.options = options self.requires_local_commits = requires_local_commits - self.tool = None + self._tool = None # option_parser can be overriden by the tool using set_option_parser # This default parser will be used for standalone_help printing. self.option_parser = HelpPrintingOptionParser(usage=SUPPRESS_USAGE, add_help_option=False, option_list=self.options) @@ -73,9 +73,9 @@ class Command(object): # The tool calls bind_to_tool on each Command after adding it to its list. def bind_to_tool(self, tool): # Command instances can only be bound to one tool at a time. - if self.tool and tool != self.tool: + if self._tool and tool != self._tool: raise Exception("Command already bound to tool!") - self.tool = tool + self._tool = tool @staticmethod def _parse_required_arguments(argument_names): @@ -179,17 +179,17 @@ class HelpCommand(AbstractDeclarativeCommand): # Only show commands which are relevant to this checkout's SCM system. Might this be confusing to some users? if self.show_all_commands: epilog = "All %prog commands:\n" - relevant_commands = self.tool.commands[:] + relevant_commands = self._tool.commands[:] else: epilog = "Common %prog commands:\n" - relevant_commands = filter(self.tool.should_show_in_main_help, self.tool.commands) + relevant_commands = filter(self._tool.should_show_in_main_help, self._tool.commands) longest_name_length = max(map(lambda command: len(command.name), relevant_commands)) relevant_commands.sort(lambda a, b: cmp(a.name, b.name)) command_help_texts = map(lambda command: " %s %s\n" % (command.name.ljust(longest_name_length), command.help_text), relevant_commands) epilog += "%s\n" % "".join(command_help_texts) epilog += "See '%prog help --all-commands' to list all commands.\n" epilog += "See '%prog help COMMAND' for more information on a specific command.\n" - return epilog.replace("%prog", self.tool.name()) # Use of %prog here mimics OptionParser.expand_prog_name(). + return epilog.replace("%prog", self._tool.name()) # Use of %prog here mimics OptionParser.expand_prog_name(). # FIXME: This is a hack so that we don't show --all-commands as a global option: def _remove_help_options(self): @@ -198,7 +198,7 @@ class HelpCommand(AbstractDeclarativeCommand): def execute(self, options, args, tool): if args: - command = self.tool.command_by_name(args[0]) + command = self._tool.command_by_name(args[0]) if command: print command.standalone_help() return 0 diff --git a/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCFLite.vsprops b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCFLite.vsprops new file mode 100644 index 0000000..03c7501 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCFLite.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="InjectedBundleCFLite"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CFLite$(LibraryConfigSuffix).lib"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix).dll"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCommon.vsprops b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCommon.vsprops index e90ddb1..4e7b84e 100644 --- a/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCommon.vsprops +++ b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCommon.vsprops @@ -10,11 +10,6 @@ ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
/>
<Tool
- Name="VCLinkerTool"
- AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
- OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix).dll"
- />
- <Tool
Name="VCPostBuildEventTool"
CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed""
/>
diff --git a/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCoreFoundation.vsprops b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCoreFoundation.vsprops new file mode 100644 index 0000000..d58b221 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/Configurations/InjectedBundleCoreFoundation.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="InjectedBundleCoreFoundation"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix).dll"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h index d094f42..520ea1f 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h @@ -30,7 +30,6 @@ #include "GCController.h" #include "LayoutTestController.h" #include <WebKit2/WKBase.h> -#include <WebKit2/WKBundleBase.h> #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp index dd92eca..32b92cb 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp @@ -169,6 +169,7 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) didReceiveTitleForFrame, 0, 0, + 0, didClearWindowForFrame, didCancelClientRedirectForFrame, willPerformClientRedirectForFrame, @@ -186,7 +187,8 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) willSetStatusbarText, willRunJavaScriptAlert, willRunJavaScriptConfirm, - willRunJavaScriptPrompt + willRunJavaScriptPrompt, + 0 /*mouseDidMoveOverElement*/ }; WKBundlePageSetUIClient(m_page, &uiClient); diff --git a/WebKitTools/WebKitTestRunner/TestController.cpp b/WebKitTools/WebKitTestRunner/TestController.cpp index a71b07d..fc2e28d 100644 --- a/WebKitTools/WebKitTestRunner/TestController.cpp +++ b/WebKitTools/WebKitTestRunner/TestController.cpp @@ -84,6 +84,8 @@ static WKPageRef createOtherPage(WKPageRef oldPage, const void*) 0, 0, 0, + 0, + 0, 0 }; WKPageSetPageUIClient(newPage, &otherPageUIClient); @@ -163,6 +165,8 @@ void TestController::initialize(int argc, const char* argv[]) 0, 0, 0, + 0, + 0, 0 }; WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient); @@ -186,6 +190,7 @@ void TestController::initialize(int argc, const char* argv[]) 0, 0, 0, + 0, 0 }; WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient); diff --git a/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj b/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj index 22c9a89..0412562 100644 --- a/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj +++ b/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj @@ -18,7 +18,7 @@ <Configuration
Name="Debug|Win32"
ConfigurationType="2"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;..\Configurations\InjectedBundleCoreFoundation.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
CharacterSet="1"
>
<Tool
@@ -79,7 +79,7 @@ <Configuration
Name="Release|Win32"
ConfigurationType="2"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;..\Configurations\InjectedBundleCoreFoundation.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
CharacterSet="1"
WholeProgramOptimization="1"
>
@@ -141,7 +141,7 @@ <Configuration
Name="Debug_All|Win32"
ConfigurationType="2"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops;..\Configurations\InjectedBundleCoreFoundation.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
CharacterSet="1"
>
<Tool
@@ -202,7 +202,7 @@ <Configuration
Name="Debug_Internal|Win32"
ConfigurationType="2"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;..\Configurations\InjectedBundleCoreFoundation.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
CharacterSet="1"
>
<Tool
@@ -260,6 +260,133 @@ Name="VCPostBuildEventTool"
/>
</Configuration>
+ <Configuration
+ Name="Debug_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_wincairo.vsprops;..\Configurations\InjectedBundleCFLite.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;..\Configurations\InjectedBundleCFLite.vsprops;..\Configurations\InjectedBundleCommon.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
diff --git a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj index d7ddd5c..e4cd870 100644 --- a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj +++ b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj @@ -298,6 +298,153 @@ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)

mkdir 2>NUL "$(WebKitOutputDir)\bin"

if not exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" exit /b

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
"
/>
</Configuration>
+ <Configuration
+ Name="Debug_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_wincairo.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner"
mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders\wtf"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ PreprocessorDefinitions="__WIN32__;_CONSOLE"
+ DisableSpecificWarnings="4146"
+ ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/NXCOMPAT"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CFLite$(LibraryConfigSuffix).lib shlwapi.lib"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)

mkdir 2>NUL "$(WebKitOutputDir)\bin"

if not exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" exit /b

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner"
mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\WebKitTestRunner\ForwardingHeaders\wtf"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ PreprocessorDefinitions="__WIN32__;_CONSOLE"
+ DisableSpecificWarnings="4146"
+ ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/NXCOMPAT"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CFLite$(LibraryConfigSuffix).lib shlwapi.lib"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)

mkdir 2>NUL "$(WebKitOutputDir)\bin"

if not exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" exit /b

xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CFNetwork.resources" "$(WebKitOutputDir)\bin\CFNetwork.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CharacterSets" "$(WebKitOutputDir)\bin\CharacterSets"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\dnssd.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb"xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
diff --git a/WebKitTools/wx/packaging/build-mac-installer.py b/WebKitTools/wx/packaging/build-mac-installer.py index a0c1b22..5b76b0b 100644 --- a/WebKitTools/wx/packaging/build-mac-installer.py +++ b/WebKitTools/wx/packaging/build-mac-installer.py @@ -26,6 +26,7 @@ # Script for building Mac .pkg installer import commands +import datetime import distutils.sysconfig import glob import optparse @@ -48,11 +49,11 @@ wxwebkit_dir = os.path.abspath(os.path.join(wxwk_root, "WebKitBuild", get_config wx_version = wx.__version__[:5] py_version = sys.version[:3] -wxwk_version = svn_revision() +date = str(datetime.date.today()) platform = "osx" -pkgname = "wxWebKit-%s-wx%s-py%s" % (platform, wx_version[:3], py_version) +pkgname = "wxWebKit-%s-wx%s-py%s-%s" % (platform, wx_version[:3], py_version, date) tempdir = "/tmp/%s" % (pkgname) @@ -141,7 +142,7 @@ try: pkg_args = ['--title ' + pkgname, '--out %s.pkg' % pkgname, - '--version ' + wxwk_version.strip(), + '--version ' + date.strip(), '--id org.wxwebkit.wxwebkit', '--domain system', '--root-volume-only', diff --git a/WebKitTools/wx/packaging/build-win-installer.py b/WebKitTools/wx/packaging/build-win-installer.py index 2bb8034..ffbdd19 100644 --- a/WebKitTools/wx/packaging/build-win-installer.py +++ b/WebKitTools/wx/packaging/build-win-installer.py @@ -27,6 +27,7 @@ import sys, os, string import commands +import datetime import glob from subprocess import * @@ -62,7 +63,7 @@ if __name__ == "__main__": innoSetup = getInnoSetupPath() os.chdir(sys.path[0]) - svnrevision = svn_revision() + date = str(datetime.date.today()) if not os.path.exists(innoSetup): print "ERROR: Cannot find InnoSetup." @@ -84,7 +85,7 @@ CopyMode: alwaysoverwrite; Source: *.py; DestDir: "{app}" installerTemplate = open("wxWebKitInstaller.iss.in", "r").read() - installerTemplate = installerTemplate.replace("<<VERSION>>", svnrevision) + installerTemplate = installerTemplate.replace("<<VERSION>>", date) installerTemplate = installerTemplate.replace("<<ROOTDIR>>", wxwebkit_dir ) installerTemplate = installerTemplate.replace("<<PYTHONVER>>", sys.version[0:3] ) installerTemplate = installerTemplate.replace("<<FILES>>", fileList ) |