diff options
author | Ben Murdoch <benm@google.com> | 2010-10-22 13:02:20 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-10-26 15:21:41 +0100 |
commit | a94275402997c11dd2e778633dacf4b7e630a35d (patch) | |
tree | e66f56c67e3b01f22c9c23cd932271ee9ac558ed /WebKitTools | |
parent | 09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff) | |
download | external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2 |
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'WebKitTools')
336 files changed, 14925 insertions, 2159 deletions
diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json index 2a4a351..91a13e7 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json @@ -45,7 +45,11 @@ { "name": "google-windows-2", "platform": "chromium-win" }, { "name": "google-mac-2", "platform": "chromium-mac" }, { "name": "google-linux-2", "platform": "chromium-linux" }, - { "name": "google-new-tests", "platform": "mac-leopard" } + { "name": "google-new-tests", "platform": "mac-leopard" }, + + { "name": "wincairo-1", "platform": "wincairo" }, + + { "name": "efl-linux-slave-1", "platform": "efl" } ], "builders": [ { "name": "Leopard Intel Release (Build)", "type": "Build", "builddir": "leopard-intel-release", @@ -93,7 +97,7 @@ { "name": "Windows Release (Tests)", "type": "Test", "builddir": "win-release-tests", "platform": "win", "configuration": "release", "architectures": ["i386"], - "slavenames": ["apple-windows-4", "apple-windows-3", "apple-windows-5", "apple-windows-6", "test-slave"] + "slavenames": ["apple-windows-3", "apple-windows-5", "test-slave"] }, { "name": "Windows Debug (Build)", "type": "Build", "builddir": "win-debug", @@ -104,7 +108,7 @@ { "name": "Windows Debug (Tests)", "type": "Test", "builddir": "win-debug-tests", "platform": "win", "configuration": "debug", "architectures": ["i386"], - "slavenames": ["apple-windows-4", "apple-windows-3", "apple-windows-5", "apple-windows-6", "test-slave"] + "slavenames": ["apple-windows-4", "apple-windows-6", "test-slave"] }, { "name": "Windows Debug (WebKit2 Tests)", "type": "TestWebKit2", "builddir": "win-debug-tests-wk2", "platform": "win", "configuration": "debug", "architectures": ["i386"], @@ -194,6 +198,16 @@ "name": "New run-webkit-tests", "type": "NewBuildAndTest", "builddir": "google-new-tests", "platform": "mac-leopard", "configuration": "release", "architectures": ["i386"], "slavenames": ["google-new-tests"] + }, + { + "name": "WinCairo Debug (Build)", "type": "Build", "builddir": "win-cairo-debug", + "platform": "wincairo", "configuration": "debug", "architectures": ["i386"], + "slavenames": ["wincairo-1"] + }, + { + "name": "EFL Linux Release (Build)", "type": "Build", "builddir": "efl-linux-release", + "platform": "efl", "configuration": "release", "architectures": ["i386"], + "slavenames": ["efl-linux-slave-1"] } ], @@ -205,7 +219,8 @@ "Qt Linux Release", "Qt Linux Release minimal", "Qt Linux ARMv5 Release", "Qt Linux ARMv7 Release", "Qt Windows 32-bit Release", "Qt Windows 32-bit Debug", "Chromium Win Release", "Chromium Mac Release", "Chromium Linux Release", - "Chromium Win Release (Tests)", "Chromium Mac Release (Tests)", "Chromium Linux Release (Tests)"] + "Chromium Win Release (Tests)", "Chromium Mac Release (Tests)", "Chromium Linux Release (Tests)", + "WinCairo Debug (Build)", "EFL Linux Release (Build)"] }, { "type": "Triggerable", "name": "leopard-intel-release-tests", "builderNames": ["Leopard Intel Release (Tests)"] diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg index d5cd6fb..47af8d2 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg @@ -78,7 +78,7 @@ class CleanupChromiumLinuxCrashLogs(shell.ShellCommand): def appendCustomBuildFlags(step, platform): - if platform in ('gtk', 'wx', 'qt', 'chromium'): + if platform in ('gtk', 'wx', 'qt', 'chromium', 'wincairo', 'efl'): step.setCommand(step.command + ['--' + platform]) @@ -487,3 +487,8 @@ c['slavePortnum'] = 17000 c['projectName'] = "WebKit" c['projectURL'] = "http://webkit.org" c['buildbotURL'] = "http://build.webkit.org/" + +c['buildHorizon'] = 1000 +c['logHorizon'] = 500 +c['eventHorizon'] = 200 +c['buildCacheSize'] = 60 diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.css b/WebKitTools/CSSTestSuiteHarness/harness/harness.css index 8c0e7d1..3f4c97d 100644 --- a/WebKitTools/CSSTestSuiteHarness/harness/harness.css +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.css @@ -49,6 +49,15 @@ body { margin: 4px 0; } +.test-type { + float: left; +} + +.name > button { + margin-top: 20px; + float: right; +} + .actions { margin-left: 320px; border: 1px solid black; @@ -64,7 +73,9 @@ body { } .note { + display: inline-block; font-size: 10px; + margin-left: 5px; color: gray; } .action-buttons { @@ -96,6 +107,28 @@ body { font-size: smaller; } +#warning { + padding-left: 1em; + color: red; + display: none; +} + +#print-button { + float: right; + display: none; +} + +#test-content.print { +} + +#test-content.print #print-button { + display: inline; +} + +#test-content.warn #warning { + display: inline; +} + #test-content iframe { border: 1px solid gray; margin: 2px; @@ -108,11 +141,18 @@ body { } #test-list > option.untested { - } -#test-list > option.completed { - color: gray; +#test-list > option.pass { + color: rgba(0, 128, 0, 0.6); +} + +#test-list > option.fail { + color: rgba(255, 0, 0, 0.6); +} + +#test-list > option.skipped { + color: rgba(255, 128, 0, 0.6); } #test-content.with-ref { @@ -218,3 +258,51 @@ body { text-align: right; padding: 4px; } + +.custom button { + display: block; + margin: 12px 0; +} + +/* Overlay */ + +#overlay { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.6); + display: none; +} + +#overlay.visible { + display: block; +} + +.overlay-contents { + position: relative; + background-color: white; + margin: 50px auto; + width: 1000px; + padding: 20px; +} + +.overlay-contents textarea { + width: 90em; + height: 50em; +} +.overlay-contents .buttons { + text-align: right; +} + +.overlay-contents .note { + float: left; +} + +.overlay-contents .buttons button { + font-size: 13px; + width: 6em; + margin: 12px 8px; +} + diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.html b/WebKitTools/CSSTestSuiteHarness/harness/harness.html index 6bd47e5..3877f49 100644 --- a/WebKitTools/CSSTestSuiteHarness/harness/harness.html +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.html @@ -63,7 +63,26 @@ { gTestSuite.passTest(); } + + function goToNextUntested() + { + gTestSuite.goToNextIncompleteTest(); + } + function goToTest() + { + var testName = prompt('Go to test:', ''); + + // This accepts any of the following: + // at-charset-010 + // at-charset-010.xht + // xhtml1/at-charset-010 + // xhtml1/at-charset-010.xht + // and will choose the format if specified. + if (!gTestSuite.goToTestByName(testName)) + alert('Failed to find test ' + testName); + } + function formatChanged() { var newFormat; @@ -92,37 +111,48 @@ { gTestSuite.exportResults(document.getElementById('results-popup').selectedIndex); } + + function printTestIframe() + { + var testFrame = document.getElementById('test-frame'); + testFrame.contentWindow.print(); + } - /* - 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; + var gOverlayConfirmCallback; + function showOverlay(overlayConfirmCallback) + { + document.getElementById('overlay-data').value = ''; + gOverlayConfirmCallback = overlayConfirmCallback; + $('#overlay').addClass('visible'); + } - case 'I': - invalidTest(); - break; - - case 'S': - skipTest(); - break; - } - - event.stopPropagation(); - event.preventDefault(); + function overlayCancel() + { + $('#overlay').removeClass('visible'); + } + + function overlayConfirm() + { + var data = document.getElementById('overlay-data').value; + gOverlayConfirmCallback(data); + $('#overlay').removeClass('visible'); } - document.addEventListener('keyup', keyHandler, false); - */ + function doImport() + { + document.getElementById('overlay-action').innerText = 'Enter results to import (in the same format as the exported results):'; + showOverlay(function(data) { + gTestSuite.importResults(data); + }); + } + + function doClear() + { + document.getElementById('overlay-action').innerText = 'Enter list of tests for which to clear results (so they can be re-tested):'; + showOverlay(function(data) { + gTestSuite.clearResults(data); + }); + } </script> </head> @@ -137,11 +167,13 @@ <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="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> + <button onclick="goToNextUntested()" accesskey="n"><strong>N</strong>ext Untested</button> + <button onclick="goToTest()" accesskey="g">Go to Test...</button> </div> </div> @@ -153,12 +185,12 @@ <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> + <button onclick="skipTest()" accesskey="s"><strong>S</strong>kip</button> + <div class="note">Use <i>Control-Option-letter</i> to<br> trigger buttons via the keyboard.</div> <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> + <button onclick="failTest()" accesskey="f"><strong>F</strong>ail</button> + <button onclick="passTest()" accesskey="p"><strong>P</strong>ass</button> </div> </div> <div id="test-content"> @@ -166,7 +198,10 @@ <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 class="flags">Flags: <span id="test-flags"></span> + <span id="warning">This test must be run over HTTP.</span> + <button id="print-button" onclick="printTestIframe()">Print Preview</button> + </div> </div> <div id="test-wrapper" class="frame-wrapper"> @@ -180,12 +215,21 @@ </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> + <button id="export-button" onclick="doExport()">Export...</button> + </div> + + <div class="custom"> + <button id="import-button" onclick="doImport()">Import...</button> + <button id="import-button" onclick="doClear()">Clear Results...</button> + </div> </div> + <div id="output"></div> <div class="summary"> <table> @@ -202,5 +246,17 @@ </div> </div> + <div id="overlay"> + + <div class="overlay-contents"> + <p id="overlay-action"></p> + <textarea id="overlay-data"></textarea> + <p class="note">Pasting many lines of text here can be very slow in Safari 5. You can quit Safari and use a <a href="http://nightly.webkit.org/" title="WebKit Nightly Builds">WebKit nightly build</a> for importing or clearing.</p> + <div class="buttons"> + <button onclick="overlayCancel()">Cancel</button><button onclick="overlayConfirm()">OK</button> + </div> + </div> + + </div> </body> </html>
\ No newline at end of file diff --git a/WebKitTools/CSSTestSuiteHarness/harness/harness.js b/WebKitTools/CSSTestSuiteHarness/harness/harness.js index 95262af..ed7cb7d 100644 --- a/WebKitTools/CSSTestSuiteHarness/harness/harness.js +++ b/WebKitTools/CSSTestSuiteHarness/harness/harness.js @@ -25,7 +25,7 @@ // requires jQuery -const kTestSuiteVersion = '20100917'; +const kTestSuiteVersion = '20101001'; const kTestSuiteHome = '../' + kTestSuiteVersion + '/'; const kTestInfoDataFile = 'testinfo.data'; @@ -201,13 +201,64 @@ function Test(testInfoLine) this.flags = fields[3]; this.links = fields[4]; this.assertion = fields[5]; + + this.paged = false; + this.testHTML = true; + this.testXHTML = true; + + if (this.flags) { + this.paged = this.flags.indexOf('paged') != -1; + + if (this.flags.indexOf('nonHTML') != -1) + this.testHTML = false; + + if (this.flags.indexOf('HTMLonly') != -1) + this.testXHTML = false; + } - this.completed = false; // true if this test has a result (pass, fail or skip) + this.completedHTML = false; // true if this test has a result (pass, fail or skip) + this.completedXHTML = false; // true if this test has a result (pass, fail or skip) + + this.statusHTML = ''; + this.statusXHTML = ''; if (!this.links) this.links = "other.html" } +Test.prototype.runForFormat = function(format) +{ + if (format == 'html4') + return this.testHTML; + + if (format == 'xhtml1') + return this.testXHTML; + + return true; +} + +Test.prototype.completedForFormat = function(format) +{ + if (format == 'html4') + return this.completedHTML; + + if (format == 'xhtml1') + return this.completedXHTML; + + return true; +} + +Test.prototype.statusForFormat = function(format) +{ + if (format == 'html4') + return this.statusHTML; + + if (format == 'xhtml1') + return this.statusXHTML; + + return true; +} + function ChapterSection(link) { var result= link.match(/^([.\w]+)(#.+)?$/); @@ -215,21 +266,84 @@ function ChapterSection(link) this.file = result[1]; this.anchor = result[2]; } - + + this.testCountHTML = 0; + this.testCountXHTML = 0; + this.tests = []; } +ChapterSection.prototype.countTests = function() +{ + this.testCountHTML = 0; + this.testCountXHTML = 0; + + for (var i = 0; i < this.tests.length; ++i) { + var currTest = this.tests[i]; + + if (currTest.testHTML) + ++this.testCountHTML; + + if (currTest.testXHTML) + ++this.testCountXHTML; + } +} + function Chapter(chapterInfo) { this.file = chapterInfo.file; this.title = chapterInfo.title; - this.testCount = 0; + this.testCountHTML = 0; + this.testCountXHTML = 0; this.sections = []; // array of ChapterSection } -Chapter.prototype.description = function() +Chapter.prototype.description = function(format) { - return this.title + ' (' + this.testCount + ' tests)'; + + + return this.title + ' (' + this.testCount(format) + ' tests, ' + this.untestedCount(format) + ' untested)'; +} + +Chapter.prototype.countTests = function() +{ + this.testCountHTML = 0; + this.testCountXHTML = 0; + + for (var i = 0; i < this.sections.length; ++i) { + var currSection = this.sections[i]; + + currSection.countTests(); + + this.testCountHTML += currSection.testCountHTML; + this.testCountXHTML += currSection.testCountXHTML; + } +} + +Chapter.prototype.testCount = function(format) +{ + if (format == 'html4') + return this.testCountHTML; + + if (format == 'xhtml1') + return this.testCountXHTML; + + return 0; +} + +Chapter.prototype.untestedCount = function(format) +{ + var completedProperty = format == 'html4' ? 'completedHTML' : 'completedXHTML'; + + var count = 0; + for (var i = 0; i < this.sections.length; ++i) { + var currSection = this.sections[i]; + for (var j = 0; j < currSection.tests.length; ++j) { + count += currSection.tests[j].completedForFormat(format) ? 0 : 1; + } + } + return count; + } // Utils @@ -277,7 +391,7 @@ TestSuite.prototype.testInfoDataLoaded = function(data, status) this.testInfoLoaded = true; - this.fillChapterPopup(document.getElementById('chapters')); + this.fillChapterPopup(); this.initializeControls(); @@ -335,12 +449,7 @@ TestSuite.prototype.buildChapters = function() 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; + currChapter.countTests(); } } @@ -363,8 +472,9 @@ TestSuite.prototype.chapterAtIndex = function(index) return this.chapters[kChapterData[index].file]; } -TestSuite.prototype.fillChapterPopup = function(select) +TestSuite.prototype.fillChapterPopup = function() { + var select = document.getElementById('chapters') select.innerHTML = ''; // Remove all children. for (var i = 0; i < kChapterData.length; ++i) { @@ -372,27 +482,53 @@ TestSuite.prototype.fillChapterPopup = function(select) var chapter = this.chapters[chapterData.file]; var option = document.createElement('option'); - option.innerText = chapter.description(); + option.innerText = chapter.description(this.format); option._chapter = chapter; select.appendChild(option); } } +TestSuite.prototype.updateChapterPopup = function() +{ + var select = document.getElementById('chapters') + var currOption = select.firstChild; + + for (var i = 0; i < kChapterData.length; ++i) { + var chapterData = kChapterData[i]; + var chapter = this.chapters[chapterData.file]; + if (!chapter) + continue; + currOption.innerText = chapter.description(this.format); + currOption = currOption.nextSibling; + } +} + TestSuite.prototype.buildTestListForChapter = function(chapter) { - this.currentChapterTests = []; + this.currentChapterTests = this.testListForChapter(chapter); +} + +TestSuite.prototype.testListForChapter = function(chapter) +{ + var testList = []; 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); + + for (var j = 0; j < currSection.tests.length; ++j) { + var currTest = currSection.tests[j]; + if (currTest.runForFormat(this.format)) + testList.push(currTest); + } } // FIXME: test may occur more than once. - this.currentChapterTests.sort(function(a, b) { + testList.sort(function(a, b) { return a.id.localeCompare(b.id); }); + + return testList; } TestSuite.prototype.initializeControls = function() @@ -428,6 +564,8 @@ TestSuite.prototype.chapterPopupChanged = function() TestSuite.prototype.fillTestList = function() { + var statusProperty = this.format == 'html4' ? 'statusHTML' : 'statusXHTML'; + var testList = document.getElementById('test-list'); testList.innerHTML = ''; @@ -436,7 +574,7 @@ TestSuite.prototype.fillTestList = function() var option = document.createElement('option'); option.innerText = currTest.id; - option.className = currTest.completed ? 'completed' : 'untested'; + option.className = currTest[statusProperty]; option._test = currTest; testList.appendChild(option); } @@ -444,12 +582,13 @@ TestSuite.prototype.fillTestList = function() TestSuite.prototype.updateTestList = function() { + var statusProperty = this.format == 'html4' ? 'statusHTML' : 'statusXHTML'; 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'; + currOption.className = currOption._test[statusProperty]; } } @@ -513,8 +652,105 @@ TestSuite.prototype.previousTest = function() } } +TestSuite.prototype.goToNextIncompleteTest = function() +{ + var completedProperty = this.format == 'html4' ? 'completedHTML' : 'completedXHTML'; + + // Look to the end of this chapter. + for (var i = this.currChapterTestIndex + 1; i < this.currentChapterTests.length; ++i) { + if (!this.currentChapterTests[i][completedProperty]) { + this.goToTestIndex(i); + return; + } + } + + // Start looking through later chapter + var currChapterIndex = this.indexOfChapter(this.currentChapter); + for (var c = currChapterIndex + 1; c < kChapterData.length; ++c) { + var chapterData = this.chapterAtIndex(c); + + var testIndex = this.firstIncompleteTestIndex(chapterData); + if (testIndex != -1) { + this.goToChapterIndex(c); + this.goToTestIndex(testIndex); + break; + } + } +} + +TestSuite.prototype.firstIncompleteTestIndex = function(chapter) +{ + var completedProperty = this.format == 'html4' ? 'completedHTML' : 'completedXHTML'; + + var chapterTests = this.testListForChapter(chapter); + for (var i = 0; i < chapterTests.length; ++i) { + if (!chapterTests[i][completedProperty]) + return i; + } + + return -1; +} + /* ------------------------------------------------------- */ +TestSuite.prototype.goToTestByName = function(testName) +{ + var match = testName.match(/^(?:(html4|xhtml1)\/)?([\w-_]+)(\.xht|\.htm)?/); + if (!match) + return false; + + var prefix = match[1]; + var testId = match[2]; + var extension = match[3]; + + var format = this.format; + if (prefix) + format = prefix; + else if (extension) { + if (extension == kXHTML1Data.suffix) + format = kXHTML1Data.path; + else if (extension == kHTML4Data.suffix) + format = kHTML4Data.path; + } + + this.switchToFormat(format); + + var test = this.tests[testId]; + if (!test) + return false; + + // Find the first chapter. + var links = test.links.split(','); + if (links.length == 0) { + window.console.log('test ' + test.id + 'had no links.'); + return false; + } + + var firstLink = links[0]; + var result = firstLink.match(/^([.\w]+)(#.+)?$/); + if (result) + firstLink = result[1]; + + // Find the chapter and index of the test. + for (var i = 0; i < kChapterData.length; ++i) { + var chapterData = kChapterData[i]; + if (chapterData.file == firstLink) { + + this.goToChapterIndex(i); + + for (var j = 0; j < this.currentChapterTests.length; ++j) { + var currTest = this.currentChapterTests[j]; + if (currTest.id == testId) { + this.goToTestIndex(j); + return true; + } + } + } + } + + return false; +} + TestSuite.prototype.goToTestIndex = function(index) { if (index >= 0 && index < this.currentChapterTests.length) { @@ -557,12 +793,17 @@ TestSuite.prototype.loadCurrentTest = function() this.loadTest(theTest); - document.getElementById('test-index').innerText = this.currChapterTestIndex + 1; - document.getElementById('chapter-test-count').innerText = this.currentChapterTests.length; + this.updateProgressLabel(); document.getElementById('test-list').selectedIndex = this.currChapterTestIndex; } +TestSuite.prototype.updateProgressLabel = function() +{ + document.getElementById('test-index').innerText = this.currChapterTestIndex + 1; + document.getElementById('chapter-test-count').innerText = this.currentChapterTests.length; +} + TestSuite.prototype.configureForRefTest = function() { $('#test-content').addClass('with-ref'); @@ -576,12 +817,52 @@ TestSuite.prototype.configureForManualTest = function() TestSuite.prototype.loadTest = function(test) { var iframe = document.getElementById('test-frame'); - iframe.src = this.urlForTest(test.id); + iframe.src = 'about:blank'; + + var url = this.urlForTest(test.id); + window.setTimeout(function() { + iframe.src = url; + }, 0); 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; + + this.processFlags(test); +} + +TestSuite.prototype.processFlags = function(test) +{ + if (test.paged) + $('#test-content').addClass('print'); + else + $('#test-content').removeClass('print'); + + var showWarning = false; + var warning = ''; + if (test.flags.indexOf('font') != -1) + warning = 'Requires a specific font to be installed.'; + + if (test.flags.indexOf('http') != -1) { + if (warning != '') + warning += ' '; + warning += 'Must be tested over HTTP, with custom HTTP headers.'; + } + + if (test.paged) { + if (warning != '') + warning += ' '; + warning += 'Test via the browser\'s Print Preview.'; + } + + document.getElementById('warning').innerText = warning; + + if (warning.length > 0) + $('#test-content').addClass('warn'); + else + $('#test-content').removeClass('warn'); + } TestSuite.prototype.clearTest = function() @@ -593,21 +874,20 @@ TestSuite.prototype.clearTest = function() document.getElementById('test-url').innerText = ''; document.getElementById('test-assertion').innerText = ''; document.getElementById('test-flags').innerText = ''; + + $('#test-content').removeClass('print'); + $('#test-content').removeClass('warn'); + document.getElementById('warning').innerText = ''; } TestSuite.prototype.loadRef = function(test) { + // Suites 20101001 and earlier used .xht refs, even for HTML tests, so strip off + // the extension and use the same format as the test. + var ref = test.reference.replace(/(\.xht)?$/, ''); + 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); + iframe.src = this.urlForTest(ref); } TestSuite.prototype.pathForTest = function(testName) @@ -638,10 +918,19 @@ TestSuite.prototype.recordResult = function(testName, resolution, comment) comment = ''; this.storeTestResult(testName, this.format, resolution, comment, navigator.userAgent); - this.markTestCompleted(testName); + + var htmlStatus = null; + var xhtmlStatus = null; + if (this.format == 'html4') + htmlStatus = resolution; + if (this.format == 'xhtml1') + xhtmlStatus = resolution; + + this.markTestCompleted(testName, htmlStatus, xhtmlStatus); this.updateTestList(); this.updateSummaryData(); + this.updateChapterPopup(); } TestSuite.prototype.beginAppendingOutput = function() @@ -675,6 +964,16 @@ TestSuite.prototype.clearOutput = function() /* ------------------------------------------------------- */ +TestSuite.prototype.switchToFormat = function(formatString) +{ + if (formatString == 'html4') + document.harness.format.html4.checked = true; + else + document.harness.format.xhtml1.checked = true; + + this.formatChanged(formatString); +} + TestSuite.prototype.formatChanged = function(formatString) { if (this.format == formatString) @@ -687,7 +986,20 @@ TestSuite.prototype.formatChanged = function(formatString) else this.formatInfo = kXHTML1Data; - this.loadCurrentTest(); + // try to keep the current test selected + var selectedTestName; + if (this.currChapterTestIndex >= 0 && this.currChapterTestIndex < this.currentChapterTests.length) + selectedTestName = this.currentChapterTests[this.currChapterTestIndex].id; + + if (this.currentChapter) { + this.buildTestListForChapter(this.currentChapter); + this.fillTestList(); + this.goToTestByName(selectedTestName); + } + + this.updateChapterPopup(); + this.updateTestList(); + this.updateProgressLabel(); } /* ------------------------------------------------------- */ @@ -744,11 +1056,97 @@ TestSuite.prototype.resultsPopupChanged = function(index) document.getElementById('export-button').disabled = !enableExport; } +/* ------------------------- Import ------------------------------- */ +/* + Import format is the same as the export format, namely: + + testname<tab>result + + with optional trailing <tab>comment. + +html4/absolute-non-replaced-height-002<tab>pass +xhtml1/absolute-non-replaced-height-002<tab>? + + Lines starting with # are ignored. + The "testname<tab>result" line is ignored. +*/ +TestSuite.prototype.importResults = function(data) +{ + var testsToImport = []; + + var lines = data.split('\n'); + for (var i = 0; i < lines.length; ++i) { + var currLine = lines[i]; + if (currLine.length == 0 || currLine.charAt(0) == '#') + continue; + + var match = currLine.match(/^(html4|xhtml1)\/([\w-_]+)\t([\w?]+)\t?(.+)?$/); + if (match) { + var test = { 'id' : match[2] }; + test.format = match[1]; + test.result = match[3]; + test.comment = match[4]; + + if (test.result != '?') + testsToImport.push(test); + } else { + window.console.log('failed to match line \'' + currLine + '\''); + } + } + + this.importTestResults(testsToImport); + + this.resetTestStatus(); + this.updateSummaryData(); +} + + + +/* --------------------- Clear Results --------------------------- */ +/* + Clear results format is either same as the export format, or + a list of bare test IDs (e.g. absolute-non-replaced-height-001) + in which case both HTML4 and XHTML1 results are cleared. +*/ +TestSuite.prototype.clearResults = function(data) +{ + var testsToClear = []; + + var lines = data.split('\n'); + for (var i = 0; i < lines.length; ++i) { + var currLine = lines[i]; + if (currLine.length == 0 || currLine.charAt(0) == '#') + continue; + + // Look for format/test with possible extension + var result = currLine.match(/^((html4|xhtml1)?)\/?([\w-_]+)/); + if (result) { + var testId = result[3]; + var format = result[1]; + + var clearHTML = format.length == 0 || format == 'html4'; + var clearXHTML = format.length == 0 || format == 'xhtml1'; + + var result = { 'id' : testId }; + result.clearHTML = clearHTML; + result.clearXHTML = clearXHTML; + + testsToClear.push(result); + } else { + window.console.log('failed to match line ' + currLine); + } + } + + this.clearTestResults(testsToClear); + + this.resetTestStatus(); + this.updateSummaryData(); +} + /* -------------------------------------------------------- */ 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); @@ -839,8 +1237,8 @@ TestSuite.prototype.exportResultsForAllTests = function() 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); + var htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus ? item.hstatus : '?', item.hcomment); + var xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus ? item.xstatus : '?', item.xcomment); exportTests.push({ 'test' : item.test, 'html4' : htmlLine, @@ -969,8 +1367,8 @@ TestSuite.prototype.exportResultsForTestsWithMismatchedResults = function() 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); + var htmlLine= _self.createExportLine(kHTML4Data, item.test, item.hstatus ? item.hstatus : '?', item.hcomment); + var xhtmlLine = _self.createExportLine(kXHTML1Data, item.test, item.xstatus ? item.xstatus : '?', item.xcomment); exportTests.push({ 'test' : item.test, 'html4' : htmlLine, @@ -984,21 +1382,28 @@ TestSuite.prototype.exportResultsForTestsWithMismatchedResults = function() /* -------------------------------------------------------- */ -TestSuite.prototype.markTestCompleted = function(testID) +TestSuite.prototype.markTestCompleted = function(testID, htmlStatus, xhtmlStatus) { var test = this.tests[testID]; if (!test) { - window.console.log('markTestCompleted to find test ' + testID); + window.console.log('markTestCompleted failed to find test ' + testID); return; } - - test.completed = true; + + if (htmlStatus) { + test.completedHTML = true; + test.statusHTML = htmlStatus; + } + if (xhtmlStatus) { + test.completedXHTML = true; + test.statusXHTML = xhtmlStatus; + } } TestSuite.prototype.testCompletionStateChanged = function() { - // update the test list this.updateTestList(); + this.updateChapterPopup(); } TestSuite.prototype.loadTestStatus = function() @@ -1006,12 +1411,24 @@ TestSuite.prototype.loadTestStatus = function() var _self = this; this.queryDatabaseForCompletedTests( function(item) { - _self.markTestCompleted(item.test); + _self.markTestCompleted(item.test, item.hstatus, item.xstatus); }, function() { _self.testCompletionStateChanged(); } ); + + this.updateChapterPopup(); +} + +TestSuite.prototype.resetTestStatus = function() +{ + for (var testID in this.tests) { + var currTest = this.tests[testID]; + currTest.completedHTML = false; + currTest.completedXHTML = false; + } + this.loadTestStatus(); } /* -------------------------------------------------------- */ @@ -1063,27 +1480,61 @@ TestSuite.prototype.openDatabase = function() } var _self = this; - this.db = window.openDatabase('css21testsuite', '1.0', 'CSS 2.1 test suite results', 10 * 1024 * 1024, function() { - _self.databaseCreated(); - }, errorHandler); + this.db = window.openDatabase('css21testsuite', '', 'CSS 2.1 test suite results', 10 * 1024 * 1024); - this.updateSummaryData(); - this.loadTestStatus(); + // Migration handling. We assume migration will happen whenever the suite version changes, + // so that we can check for new or obsoleted tests. + function creation(tx) { + _self.databaseCreated(tx); + } + + function migration1_0To1_1(tx) { + window.console.log('updating 1.0 to 1.1'); + // We'll use the 'seen' column to cross-check with testinfo.data. + tx.executeSql('ALTER TABLE tests ADD COLUMN seen BOOLEAN DEFAULT \"FALSE\"', null, function() { + _self.syncDatabaseWithTestInfoData(); + }, errorHandler); + } + + if (this.db.version == '') { + _self.db.changeVersion('', '1.0', creation, null, function() { + _self.db.changeVersion('1.0', '1.1', migration1_0To1_1, null, function() { + _self.databaseReady(); + }, errorHandler); + }, errorHandler); + + return; + } + + if (this.db.version == '1.0') { + _self.db.changeVersion('1.0', '1.1', migration1_0To1_1, null, function() { + window.console.log('ready') + _self.databaseReady(); + }, errorHandler); + return; + } + + this.databaseReady(); } -TestSuite.prototype.databaseCreated = function(db) +TestSuite.prototype.databaseCreated = function(tx) { + window.console.log('databaseCreated'); this.populatingDatabase = true; + // hstatus: HTML4 result + // xstatus: XHTML1 result 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); - }); + 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.databaseReady = function() +{ + this.updateSummaryData(); + this.loadTestStatus(); } TestSuite.prototype.storeTestResult = function(test, format, result, comment, useragent) @@ -1096,28 +1547,134 @@ TestSuite.prototype.storeTestResult = function(test, format, result, comment, us 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) +TestSuite.prototype.importTestResults = function(results) +{ + if (!this.db) + return; + + this.db.transaction(function (tx) { + + for (var i = 0; i < results.length; ++i) { + var currResult = results[i]; + + var query; + if (currResult.format == 'html4') + query = 'UPDATE tests SET hstatus=?, hcomment=? WHERE test=?\n'; + else if (currResult.format == 'xhtml1') + query = 'UPDATE tests SET xstatus=?, xcomment=? WHERE test=?\n'; + + tx.executeSql(query, [currResult.result, currResult.comment, currResult.id], null, errorHandler); + } + }); +} + +TestSuite.prototype.clearTestResults = function(results) +{ + if (!this.db) + return; + + this.db.transaction(function (tx) { + + for (var i = 0; i < results.length; ++i) { + var currResult = results[i]; + + if (currResult.clearHTML) + tx.executeSql('UPDATE tests SET hstatus=NULL, hcomment=NULL WHERE test=?\n', [currResult.id], null, errorHandler); + + if (currResult.clearXHTML) + tx.executeSql('UPDATE tests SET xstatus=NULL, xcomment=NULL WHERE test=?\n', [currResult.id], null, errorHandler); + + } + }); +} + +TestSuite.prototype.populateDatabaseFromTestInfoData = function() { if (!this.testInfoLoaded) { window.console.log('Tring to populate database before testinfo.data has been loaded'); return; } + window.console.log('populateDatabaseFromTestInfoData') 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); + var test = _self.tests[testID]; + // Version 1.0, so no 'seen' column. + tx.executeSql('INSERT INTO tests (test, ref, title, flags, links, assertion) VALUES (?, ?, ?, ?, ?, ?)', + [test.id, test.reference, test.title, test.flags, test.links, test.assertion], null, errorHandler); } - _self.populatingDatabase = false; }); } +TestSuite.prototype.insertTest = function(tx, test) +{ + tx.executeSql('INSERT INTO tests (test, ref, title, flags, links, assertion, seen) VALUES (?, ?, ?, ?, ?, ?, ?)', + [test.id, test.reference, test.title, test.flags, test.links, test.assertion, 'TRUE'], null, errorHandler); +} + +// Deal with removed/renamed tests in a new version of the suite. +// self.tests is canonical; the database may contain stale entries. +TestSuite.prototype.syncDatabaseWithTestInfoData = function() +{ + if (!this.testInfoLoaded) { + window.console.log('Trying to sync database before testinfo.data has been loaded'); + return; + } + + // Make an object with all tests that we'll use to track new tests. + var testsToInsert = {}; + for (var testId in this.tests) { + var currTest = this.tests[testId]; + testsToInsert[currTest.id] = currTest; + } + + var _self = this; + this.db.transaction(function (tx) { + // Find tests that are not in the database yet. + // (Wasn't able to get INSERT ... IF NOT working.) + tx.executeSql('SELECT * FROM tests', [], function(tx, results) { + var len = results.rows.length; + for (var i = 0; i < len; ++i) { + var item = results.rows.item(i); + delete testsToInsert[item.test]; + } + }, errorHandler); + }); + + this.db.transaction(function (tx) { + for (var testId in testsToInsert) { + var currTest = testsToInsert[testId]; + window.console.log(currTest.id + ' is new; inserting'); + _self.insertTest(tx, currTest); + } + }); + + this.db.transaction(function (tx) { + for (var testID in _self.tests) + tx.executeSql('UPDATE tests SET seen=\"TRUE\" WHERE test=?\n', [testID], null, errorHandler); + + tx.executeSql('SELECT * FROM tests WHERE seen=\"FALSE\"', [], function(tx, results) { + var len = results.rows.length; + for (var i = 0; i < len; ++i) { + var item = results.rows.item(i); + window.console.log('Test ' + item.test + ' was in the database but is no longer in the suite; deleting.'); + } + }, errorHandler); + + // Delete rows for disappeared tests. + tx.executeSql('DELETE FROM tests WHERE seen=\"FALSE\"', [], function(tx, results) { + _self.populatingDatabase = false; + _self.databaseReady(); + }, errorHandler); + }); +} + TestSuite.prototype.queryDatabaseForAllTests = function(sortKey, perRowHandler, completionHandler) { if (this.populatingDatabase) @@ -1269,28 +1826,58 @@ TestSuite.prototype.countTestsWithColumnValue = function(tx, completionHandler, }, errorHandler); } +TestSuite.prototype.countTestsWithFlag = function(tx, completionHandler, flag) +{ + var allRowsCount = 'COUNT(*)'; + + tx.executeSql('SELECT COUNT(*) FROM tests WHERE flags LIKE \"%' + flag + '%\"', [], function(tx, results) { + var rowCount = 0; + if (results.rows.length > 0) + rowCount = results.rows.item(0)[allRowsCount]; + completionHandler(rowCount); + }, errorHandler); +} + TestSuite.prototype.queryDatabaseForSummary = function(completionHandler) { if (!this.db || this.populatingDatabase) return; var _self = this; + + var htmlOnlyTestCount = 0; + var xHtmlOnlyTestCount = 0; + this.db.transaction(function (tx) { + if (_self.populatingDatabase) + return; + var allRowsCount = 'COUNT(*)'; + + _self.countTestsWithFlag(tx, function(count) { + htmlOnlyTestCount = count; + }, 'htmlOnly'); + + _self.countTestsWithFlag(tx, function(count) { + xHtmlOnlyTestCount = count; + }, 'nonHTML'); + }); + + 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-total' , 'count' : rowItem[allRowsCount] - xHtmlOnlyTestCount }) + data.push({ 'name' : 'x-total' , 'count' : rowItem[allRowsCount] - htmlOnlyTestCount }) data.push({ 'name' : 'h-tested', 'count' : rowItem[html4RowsCount] }) data.push({ 'name' : 'x-tested', 'count' : rowItem[xhtml1RowsCount] }) } @@ -1298,6 +1885,7 @@ TestSuite.prototype.queryDatabaseForSummary = function(completionHandler) }, errorHandler); + _self.countTestsWithColumnValue(tx, completionHandler, 'hstatus', 'pass', 'h-passed'); _self.countTestsWithColumnValue(tx, completionHandler, 'xstatus', 'pass', 'x-passed'); diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog index b2a3791..d138f3d 100644 --- a/WebKitTools/ChangeLog +++ b/WebKitTools/ChangeLog @@ -1,3 +1,3513 @@ +2010-10-20 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/47754> New script to verify explicit source file types in Xcode project files + + Reviewed by Darin Adler. + + The script parses an Xcode project file and makes sure the file + extension matches the explicit file type set for all source + files. Note that the majority of source files will have their + type set by Xcode, so the script doesn't check them since there + is no need to second-guess Xcode. + + * Scripts/check-Xcode-source-file-types: Added. Code borrowed + heavily from sort-Xcode-project-file. + +2010-10-20 Adam Roben <aroben@apple.com> + + Windows build fix + + * TestWebKitAPI/win/PlatformUtilitiesWin.cpp: Added missing #include. + +2010-10-20 Adam Roben <aroben@apple.com> + + Qt test fix + + * DumpRenderTree/qt/TestNetscapePlugin/TestNetscapePlugin.pro: Added + PassDifferentNPPStruct.cpp. + +2010-10-20 Sam Weinig <sam@webkit.org> + + Reviewed by Adam Roben. + + https://bugs.webkit.org/show_bug.cgi?id=48027 + Add ability to test injected bundle API using TestWebKitAPI + + * TestWebKitAPI/InjectedBundleController.cpp: Added. + * TestWebKitAPI/InjectedBundleController.h: Added. + Shared main object for bundle functionality. + + * TestWebKitAPI/InjectedBundleMain.cpp: Added. + Bundle entry point. + + * TestWebKitAPI/InjectedBundleTest.h: Added. + Base class for which the bundle portion of a test derives from. + + * TestWebKitAPI/PlatformUtilities.h: + * TestWebKitAPI/PlatformUtilities.cpp: Added. + * TestWebKitAPI/mac/PlatformUtilitiesMac.mm: + * TestWebKitAPI/win/PlatformUtilitiesWin.cpp: + (TestWebKitAPI::Util::createInjectedBundlePath): + (TestWebKitAPI::Util::createURLForResource): + (TestWebKitAPI::Util::URLForNonExistentResource): + Add helper to create a context with the shared injected bundle, + and send the initial message to set up the test. + + * TestWebKitAPI/Configurations/InjectedBundle.xcconfig: Added. + * TestWebKitAPI/InjectedBundle-Info.plist: Added. + Add mac configuration files. + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + Add the new files. + + * TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp: Added. + * TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp: Added. + Add a simple initial bundle test. + +2010-10-20 Eric Seidel <eric@webkit.org> + + Unreviewed. Fixing /release-patch url used by the EWS bots. + + EWS should test patches with r+ + https://bugs.webkit.org/show_bug.cgi?id=35460 + + * Scripts/webkitpy/common/net/statusserver.py: + - I changed the URL during development, and 404s are + intentionally silenced during release_patch. + +2010-10-14 Adam Roben <aroben@apple.com> + + Test that passing a different NPP struct back to the browser doesn't + cause an assertion failure + + Test for <http://webkit.org/b/47690> <rdar://problem/8553020> + Assertion failure in NetscapePlugin::fromNPP when using Shockwave in + WebKit2 + + Reviewed by John Sullivan. + + * DumpRenderTree/TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp: Copied from WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/GetValueNetscapeWindow.cpp. + (PassDifferentNPPStruct::PassDifferentNPPStruct): Initialize our + members. + (PassDifferentNPPStruct::NPP_SetWindow): Pass a different NPP to the + browser than the one it gave us in NPP_New and see if it works. + + * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj: + * DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj: + Added PassDifferentNPPStruct. + +2010-10-19 Adam Roben <aroben@apple.com> + + Gently nudge old-run-webkit-tests toward working with Win32 Perl + + This makes old-run-webkit-tests able to build DRT and find all the + tests to run. It even invokes DRT and passes it the list of tests. But + DRT ends up hung blocking on I/O. + + Fixes <http://webkit.org/b/47961> Get old-run-webkit-tests mostly + working with Win32 Perl + + Reviewed by David Kilzer. + + * Scripts/old-run-webkit-tests: + - Use File::Spec instead of manually concatenating paths + - Use dirname instead of manually stripping off the base name + - Use isCygwin/isWindows/isAppleWinWebKit more judiciously + - Explicitly invoke Perl when running Perl scripts + - Quote paths when using them in regular expressions to allow them + to include characters that have special meanings in regular + expressions + + * Scripts/run-webkit-tests: Use File::Spec instead of manually + concatenating paths. + + * Scripts/webkitdirs.pm: + - Remove the unused $windowsTmpPath variable + - Use isCygwin/isWindows/isAppleWinWebKit more judiciously + - Only pass paths to cygpath when using Cygwin Perl + - Only use pdevenv when using Cygwin Perl, for now + +2010-10-20 Daniel Bates <dbates@rim.com> + + Reviewed by Martin Robinson. + + Add Git-support to do-file-rename + https://bugs.webkit.org/show_bug.cgi?id=48015 + + Also, abstracts the SCM move/rename functionality in do-file-rename and + do-webcore-rename into a common function VCSUtils::scmMoveOrRenameFile(). + + Currently, do-file-rename is hard coded to assume the SCM is Subversion. + Instead, we should abstract the rename logic to be SCM-independent. This + will allow us to add Git support as well move such functionality into + our SCM library VCSUtils, where it can be shared by do-webcore-rename. + + * Scripts/VCSUtils.pm: + - Added function scmMoveOrRenameFile. + * Scripts/do-file-rename: Modified to call VCSUtils::scmMoveOrRenameFile(). + * Scripts/do-webcore-rename: Ditto. + +2010-10-20 Adam Roben <aroben@apple.com> + + Fix old-run-webkit-tests when there's a space in the path to DRT + + Reviewed by Jon Honeycutt. + + * Scripts/old-run-webkit-tests: Quote the path to DRT before executing + it. + +2010-10-20 Kenneth Russell <kbr@google.com> + + Reviewed by Dimitri Glazkov. + + Regression in chromium_gpu_unittests after r70175 + https://bugs.webkit.org/show_bug.cgi?id=48008 + + * Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py: + +2010-10-20 Kenneth Russell <kbr@google.com> + + Reviewed by James Robinson. + + chromium_gpu port of new-run-webkit-tests must do Linux -> Win expectations fallback + https://bugs.webkit.org/show_bug.cgi?id=48005 + + * Scripts/webkitpy/layout_tests/port/chromium_gpu.py: + +2010-10-20 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch doesn't get along with git rm + https://bugs.webkit.org/show_bug.cgi?id=47940 + + Turns out we need to pass "--" to tell git this is a path. + + * Scripts/webkitpy/common/checkout/scm.py: + +2010-10-20 Robert Hogan <robert@webkit.org> + + Reviewed by Antonio Gomes. + + [Qt] Fix layoutTestController.getJsObjectCount + + Qt Bridge doesn't know size_t so pass result as unsigned int. + + Unskip fast/dom/gc-10.html + + https://bugs.webkit.org/show_bug.cgi?id=47931 + + * DumpRenderTree/qt/GCControllerQt.cpp: + (GCController::getJSObjectCount): + * DumpRenderTree/qt/GCControllerQt.h: + +2010-10-20 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r70149. + http://trac.webkit.org/changeset/70149 + https://bugs.webkit.org/show_bug.cgi?id=47989 + + "Build breaks in mac and win" (Requested by satish on + #webkit). + + * DumpRenderTree/LayoutTestController.cpp: + (setMockSpeechInputResultCallback): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::setMockSpeechInputResult): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setMockSpeechInputResult): + +2010-10-19 Leandro Gracia Gil <leandrogracia@google.com> + + Reviewed by Jeremy Orlow. + + Added a second parameter to setMockSpeechInputResult for + the language used in speech input. + https://bugs.webkit.org/show_bug.cgi?id=47089 + + * DumpRenderTree/LayoutTestController.cpp: + (setMockSpeechInputResultCallback): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::setMockSpeechInputResult): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setMockSpeechInputResult): + +2010-10-19 Adam Roben <aroben@apple.com> + + Teach update-webkit-support-libs about the new versioning of + WebKitSupportLibrary + + Fixes <http://webkit.org/b/47915> update-webkit-support-libs should + check version numbers instead of modification times + + Reviewed by Sam Weinig. + + * Scripts/update-webkit-support-libs: Fetch the expected version + number from developer.apple.com, then compare with the version number + of the extracted library and of the zipped library to see if anything + needs to be done. Removed code that tracked the modified timestamp of + the library, as it is no longer needed. + +2010-10-19 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + EWS should test patches with r+ + https://bugs.webkit.org/show_bug.cgi?id=35460 + + * QueueStatusServer/handlers/submittoews.py: + * QueueStatusServer/model/queues.py: + * Scripts/webkitpy/tool/bot/patchcollection.py: Removed. + * Scripts/webkitpy/tool/bot/patchcollection_unittest.py: Removed. + * Scripts/webkitpy/tool/commands/queues.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Teach feeder-queue how to feed the EWS bots + https://bugs.webkit.org/show_bug.cgi?id=47943 + + queues.webkit.org already knew how to accept EWS submissions + via /submit-to-ews. This teaches the feeder queue how to post + to that page with any new r? patches it sees. + + * QueueStatusServer/model/activeworkitems_unitest.py: Added. + - More unit testing is always a good thing. + * Scripts/webkitpy/common/net/bugzilla.py: + * Scripts/webkitpy/common/net/statusserver.py: + * Scripts/webkitpy/tool/bot/feeders.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Unreviewed, just fixing test-webkitpy. I'm really on a roll today. + + commit-queue gets stuck when release-patch returns 404 + https://bugs.webkit.org/show_bug.cgi?id=47935 + + Fix test-webkitpy and unittest NetworkTransaction. + + * Scripts/webkitpy/common/net/networktransaction.py: + * Scripts/webkitpy/common/net/networktransaction_unittest.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Unreviewed. + + commit-queue gets stuck when release-patch returns 404 + https://bugs.webkit.org/show_bug.cgi?id=47935 + + Turns out ClientForm gets upset if passed an int() instead of a string type. + Yay for untestable code. + + * Scripts/webkitpy/common/net/statusserver.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Unreviewed. Will get Adam's commentary after his meeting + for now this gets the commit-cluster back running. + + commit-queue gets stuck when release-patch returns 404 + https://bugs.webkit.org/show_bug.cgi?id=47935 + + I taught NetworkTransaction the basics of 404 handling. + We'll want to go back and teach it how to handle urllib2 404's too + and then deploy it to the places that want it. + + * QueueStatusServer/handlers/releasepatch.py: + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/networktransaction.py: + * Scripts/webkitpy/common/net/statusserver.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Unreviewed. Fixing typos in my previous commit. + + Make patch release explicit and not a magic part of "retry" status + https://bugs.webkit.org/show_bug.cgi?id=47909 + + All of these typos again due to our inability to unit + test much of this code. I added one unit test where + possible. activeworkitems_unittest.py will be in a separate patch. + + * QueueStatusServer/handlers/releasepatch.py: + * QueueStatusServer/main.py: + * QueueStatusServer/model/activeworkitems.py: + * QueueStatusServer/model/workitems.py: + * QueueStatusServer/model/workitems_unittest.py: + * QueueStatusServer/templates/releasepatch.html: + * Scripts/webkitpy/common/net/statusserver.py: + +2010-10-19 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + [chromium] Use webkit's TestNetscapePlugIn in DRT mac + https://bugs.webkit.org/show_bug.cgi?id=47850 + + * DumpRenderTree/chromium/TestNetscapePlugIn/Info.plist: Added. Forked + because we're going to name our plugin WebKitTestNetscapePlugIn + temporarily until the chromium forked plugin goes away. + +2010-10-19 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Make patch release explicit and not a magic part of "retry" status + https://bugs.webkit.org/show_bug.cgi?id=47909 + + This moves us another step closer to running r+ patches on the EWS bots. + Currently all bots just spam /update-work-items with their list of current + work items. queues.webkit.org uses that data for display. As part of making + the EWS run r+ patches, we're moving the official list of patches-to-process + into the server, and feeding them out to bots one at a time. We need to be + able to remove patches from the queues one at a time instead of just spamming + /update-work-items with a new complete list. That's what this patch adds. + + * QueueStatusServer/handlers/nextpatch.py: + * QueueStatusServer/handlers/queuestatus.py: + * QueueStatusServer/handlers/releasepatch.py: Added. + * QueueStatusServer/handlers/statusbubble_unittest.py: + - Fix a typo causing test failure. This was not caught by the bots + because they don't have AppEngineLauncher installed and thus don't run + the QueueStatusServer tests. + * QueueStatusServer/handlers/updatestatus.py: + * QueueStatusServer/model/activeworkitems.py: + * QueueStatusServer/templates/releasepatch.html: Added. + * Scripts/webkitpy/common/net/statusserver.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-10-19 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + cr-mac bubble has caused status bubbles to wrap + https://bugs.webkit.org/show_bug.cgi?id=47928 + + We now have too many EWSes to fit in the bugs.webkit.org + status-bubble iframe when more than a couple EWS builds are pending. + To fix this I've reduced the space taken up by queue position, + and also moved cr-mac to the end of the list (since it's going to be + triple-digits for a while). + + * QueueStatusServer/model/queues.py: + * QueueStatusServer/templates/statusbubble.html: + +2010-10-19 Kenneth Russell <kbr@google.com> + + Reviewed by David Levin. + + chromium_gpu port of new-run-webkit-tests must search chromium-gpu directory for expectations + https://bugs.webkit.org/show_bug.cgi?id=47874 + + * Scripts/webkitpy/layout_tests/port/chromium_gpu.py: + * Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py: + +2010-10-19 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + [chromium] DumpRenderTree shouldn't put '.' in include path + https://bugs.webkit.org/show_bug.cgi?id=47877 + + Fix include paths. + + * DumpRenderTree/chromium/AccessibilityController.cpp: + * DumpRenderTree/chromium/AccessibilityUIElement.cpp: + * DumpRenderTree/chromium/AccessibilityUIElement.h: + * DumpRenderTree/chromium/CppBoundClass.cpp: + * DumpRenderTree/chromium/CppVariant.cpp: + * DumpRenderTree/chromium/CppVariant.h: + * DumpRenderTree/chromium/DRTDevToolsAgent.cpp: + * DumpRenderTree/chromium/DRTDevToolsAgent.h: + * DumpRenderTree/chromium/DRTDevToolsCallArgs.h: + * DumpRenderTree/chromium/DRTDevToolsClient.cpp: + * DumpRenderTree/chromium/DRTDevToolsClient.h: + * DumpRenderTree/chromium/EventSender.cpp: + * DumpRenderTree/chromium/EventSender.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/MockSpellCheck.cpp: + * DumpRenderTree/chromium/NotificationPresenter.cpp: + * DumpRenderTree/chromium/NotificationPresenter.h: + * DumpRenderTree/chromium/PlainTextController.cpp: + * DumpRenderTree/chromium/Task.cpp: + * DumpRenderTree/chromium/TestNavigationController.h: + * DumpRenderTree/chromium/TestShell.cpp: + * DumpRenderTree/chromium/TestWebWorker.h: + * DumpRenderTree/chromium/TextInputController.cpp: + * DumpRenderTree/chromium/WebPreferences.cpp: + * DumpRenderTree/chromium/WebPreferences.h: + * DumpRenderTree/chromium/WebThemeEngineDRT.cpp: + * DumpRenderTree/chromium/WebThemeEngineDRT.h: + * DumpRenderTree/chromium/WebViewHost.cpp: + * DumpRenderTree/chromium/WebViewHost.h: + +2010-10-19 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Need to include WKErrorRef in the WKPageDidFail... functions + https://bugs.webkit.org/show_bug.cgi?id=47871 + + Update tools for new parameter in failure callbacks. + + * MiniBrowser/mac/BrowserWindowController.m: + (didFailProvisionalLoadWithErrorForFrame): + (didFailLoadWithErrorForFrame): + (-[BrowserWindowController updateProvisionalURLForFrame:]): + * TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp: + (TestWebKitAPI::didFailProvisionalLoadWithErrorForFrame): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame): + (WTR::InjectedBundlePage::didFailLoadWithErrorForFrame): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.h: + +2010-10-19 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Antti Koivisto. + + [Qt] WebKit2 MacOS build fix + https://bugs.webkit.org/show_bug.cgi?id=47897 + + Qt WebKit2 MacOS build fix. + + * WebKitTestRunner/PlatformWebView.h: + * WebKitTestRunner/qt/TestControllerQt.cpp: + +2010-10-19 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch stats the filesystem too many times + https://bugs.webkit.org/show_bug.cgi?id=47883 + + This patch attempts to cache the list of changed files more agressively + and to use that list to compute the diff instead of stating the file + system again. + + * Scripts/webkitpy/common/checkout/api.py: + * Scripts/webkitpy/common/checkout/scm.py: + * Scripts/webkitpy/tool/mocktool.py: + * Scripts/webkitpy/tool/steps/abstractstep.py: + * Scripts/webkitpy/tool/steps/editchangelog.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + +2010-10-19 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/47741> Make sort-Xcode-project-file a little more friendly + + Reviewed by Darin Adler. + + * Scripts/sort-Xcode-project-file: + - Don't print an error message about missing arguments when + -h|--help is used. + - Allow Xcode project files to be specified as Project.xcodeproj + instead of Project.xcodeproj/project.pbxproj. + +2010-10-18 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Andreas Kling. + + [Qt] QtTestBrowser: Prevent calling load() directly from loadFinished() in robot mode. + https://bugs.webkit.org/show_bug.cgi?id=47809 + + Connecting a call to load from the loadFinished signal can cause + re-entrance crashes in WebCore. This patch uses a timer to do so, + also giving some time to subsequent frames to finish loading. + + * QtTestBrowser/urlloader.cpp: + (UrlLoader::UrlLoader): + (UrlLoader::loadNext): + (UrlLoader::checkIfFinished): + (UrlLoader::frameLoadStarted): + (UrlLoader::frameLoadFinished): + * QtTestBrowser/urlloader.h: + +2010-10-19 Sergio Villar SenÃn <svillar@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] http/history tests are failing + https://bugs.webkit.org/show_bug.cgi?id=36173 + + Clear the history each time a test is run. Return the actual + history item count when calling + LayoutTestController::webHistoryItemCount + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::webHistoryItemCount): + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Add Chromium Mac EWS to the list of queues at queues.webkit.org + https://bugs.webkit.org/show_bug.cgi?id=47878 + + * QueueStatusServer/model/queues.py: + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + queues.webkit.org/next_patch is always 404 + https://bugs.webkit.org/show_bug.cgi?id=47881 + + With the addition of the Queue class, I changed most of the + code to lookup WorkItems using get_or_insert with a key_name + instead of WorkItems.all().filter(queue_name=). + Because the new get_or_insert code uses an explicit key_name + (which is obviously different from the previously autogenerated + ones), there were new WorkItem records created for each queue. + However, some parts of the code still use WorkItems.all().filter, + thus some parts were getting the new record and some parts the old record. + + The same basic bug was occurring with ActiveWorkItems, because I + changed the key_name for that class as well. + + To fix this I've moved more of the code over to using Queue.*work_items. + I've also enabled the datastore_admin (new in GAE 1.3.8) so that + we can go delete the old WorkItems records. + I also changed remote_api to use the new builtin: syntax (also added in GAE 1.3.8). + + * QueueStatusServer/app.yaml: + * QueueStatusServer/handlers/queuestatus.py: + * QueueStatusServer/handlers/recentstatus.py: + * QueueStatusServer/handlers/updatestatus.py: + * QueueStatusServer/handlers/updateworkitems.py: + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Correct a bunch of typos in QueueStatusServer + https://bugs.webkit.org/show_bug.cgi?id=47880 + + These are all due to our complete lack of unit testing in QueueStatusServer. + I added a couple unit tests to cover a few of these fixes, but most of these + are still only caught by actually running the application. + + * QueueStatusServer/handlers/nextpatch.py: + * QueueStatusServer/handlers/statusbubble.py: + * QueueStatusServer/handlers/statusbubble_unittest.py: Added. + * QueueStatusServer/handlers/updateworkitems.py: + * QueueStatusServer/model/attachment.py: + * QueueStatusServer/model/queuepropertymixin.py: + * QueueStatusServer/model/queuepropertymixin_unittest.py: + * QueueStatusServer/model/workitems.py: + * QueueStatusServer/model/workitems_unittest.py: Added. + +2010-10-18 Adam Barth <abarth@webkit.org> + + Disable this test because it's failing on the bots and the authors + aren't around to fix it. + + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-18 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + CC authors of flaky tests when the commit-queue hits a flaky test + https://bugs.webkit.org/show_bug.cgi?id=47872 + + * Scripts/webkitpy/common/checkout/api.py: + * Scripts/webkitpy/common/net/layouttestresults.py: + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Make it possible to run a chromium-mac-ews builder + https://bugs.webkit.org/show_bug.cgi?id=47876 + + Since we can't run Mac OS X in a VM, we need to only run committer patches. + There was a multiple inheritance problem which was holding this patch back, + but I decided to just ignore the problem and go with a functional hack for now. + + * Scripts/webkitpy/tool/commands/earlywarningsystem.py: + * Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py: + +2010-10-18 Kenneth Russell <kbr@google.com> + + Reviewed by Tony Chang. + + Regression in run_webkit_tests_unittest from r70017 + https://bugs.webkit.org/show_bug.cgi?id=47875 + + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-18 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Implement webkit-patch suggest-reviewers + https://bugs.webkit.org/show_bug.cgi?id=47866 + + * Scripts/webkitpy/common/checkout/api.py: + - The main logic. We look at the last five changes to each + modified (non-ChangeLog) file and collect up the reviewers of + those changes as well as the authors of those changes who are + reviewers. + * Scripts/webkitpy/common/checkout/api_unittest.py: + - Test the logic with some fun mocks. + * Scripts/webkitpy/common/checkout/scm.py: + - Fix a bug when you have local git commits. + * Scripts/webkitpy/common/checkout/scm_unittest.py: + - Test that the bug is fixed. + * Scripts/webkitpy/tool/commands/queries.py: + - Add the query. + +2010-10-18 Kenneth Russell <kbr@google.com> + + Reviewed by Eric Seidel. + + new-run-webkit-tests produces corrupt PNG baselines on Windows + https://bugs.webkit.org/show_bug.cgi?id=47867 + + * Scripts/webkitpy/layout_tests/port/base.py: + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Make it possible to submit patches to the EWS bots + https://bugs.webkit.org/show_bug.cgi?id=47869 + + * QueueStatusServer/handlers/nextpatch.py: + - Move more logic into Queue, so that it can be shared with SubmitToEWS. + * QueueStatusServer/handlers/queuestatus.py: + - Fix two typos from a previous commit. + * QueueStatusServer/handlers/submittoews.py: Added. + * QueueStatusServer/handlers/updatestatus.py: + - Use the new is_retry_request method to share this (hacky) code with SubmitToEWS + * QueueStatusServer/main.py: + - Add /submit-to-ews + * QueueStatusServer/model/queuepropertymixin.py: + - Fix circular imports caused by adding Queue.work_items() + * QueueStatusServer/model/queues.py: + - Add work_items() and active_work_items() + * QueueStatusServer/model/queuestatus.py: + * QueueStatusServer/model/workitems.py: + - Add transaction-safe add/remove methods. + * QueueStatusServer/templates/submittoews.html: Added. + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Deploy Queue class in more places throughout QueueStatusServer + https://bugs.webkit.org/show_bug.cgi?id=47855 + + I also caught two typos from the previous change. Unfortunately + I don't yet know how to unittest request handlers yet. + + * QueueStatusServer/handlers/dashboard.py: + * QueueStatusServer/handlers/statusbubble.py: + * QueueStatusServer/handlers/updateworkitems.py: + * QueueStatusServer/model/activeworkitems.py: + * QueueStatusServer/model/attachment.py: + * QueueStatusServer/model/queuepropertymixin.py: Added. + * QueueStatusServer/model/queuepropertymixin_unittest.py: Added. + * QueueStatusServer/model/queuestatus.py: + * QueueStatusServer/model/workitems.py: + +2010-10-18 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + scm.py should be able tell us what revisions made changes to a given file + https://bugs.webkit.org/show_bug.cgi?id=47863 + + Look again, your SCM.py can now log files. + + * Scripts/webkitpy/common/checkout/scm.py: + * Scripts/webkitpy/common/checkout/scm_unittest.py: + +2010-10-18 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Siedel. + + new-run-webkit-tests: clean up the options-parsing code in the port + classes. + + This change modifies the Port interface to have a get_option() and + set_option_default() method for accessing the options argument + passed to the constructor. If the constructor is not passed an + options argument, we default to a MockOptions() argument from + mocktool, which has the same semantics we want. + + Note that there is a disadvantage to port.get_option('foo') over + port._options.foo, which is that you lose some of the checking + for whether 'foo' is set (typos result in the default value, not + an exception being raised. This is desired in this case, since the + Port class is not allowed to assume that options does have any + particular values set, and so this change ensures that all of + the subclasses are following the same, intended, logic. + + Arguably this is the wrong semantics to have, and the Port + classes should be able to assume a default set of + attributes/arguments, but that change will need to wait for a + different CL where we can modify new-run-webkit-tests to pull a + list of arguments from the port factory routines. + + Also, add unit tests for webkitpy.tool.mocktool.MockOptions . + + https://bugs.webkit.org/show_bug.cgi?id=47510 + + * 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_gpu_unittest.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_unittest.py: + * Scripts/webkitpy/layout_tests/port/mac_unittest.py: + * Scripts/webkitpy/layout_tests/port/port_testcase.py: + * Scripts/webkitpy/layout_tests/port/test.py: + * Scripts/webkitpy/layout_tests/port/webkit.py: + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py: + * Scripts/webkitpy/tool/mocktool_unittest.py: Added. + +2010-10-18 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + Re-submit a revised version of r69638 - enabling new-run-webkit-tests + under cygwin. The initial version had a bug in base:uri_to_test_name + that was causing tests to fail. This version corrects that bug, but + also makes the code safer by calling cygpath more reliably, and + leaving a long-running cygpath process open. + + This patch also corrects a couple of minor bugs in http_lock_unittest, + chromium_unittest, and dedpulicate_tests_unittest that showed up + while testing this. + + https://bugs.webkit.org/show_bug.cgi?id=47220 + + * Scripts/webkitpy/common/system/path.py: + * Scripts/webkitpy/common/system/path_unittest.py: + * Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py: + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + * 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_unittest.py: + * Scripts/webkitpy/layout_tests/port/http_lock_unittest.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-10-18 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Add Queue class and add minimal unittesting of QueueStatusServer code + https://bugs.webkit.org/show_bug.cgi?id=47847 + + * QueueStatusServer/handlers/dashboard.py: + * QueueStatusServer/handlers/queuestatus.py: + * QueueStatusServer/handlers/recentstatus.py: + * QueueStatusServer/handlers/statusbubble.py: + * QueueStatusServer/handlers/updateworkitems.py: + * QueueStatusServer/model/attachment.py: + * QueueStatusServer/model/queues.py: + * QueueStatusServer/model/queues_unittest.py: Added. + * QueueStatusServer/model/svnrevision.py: + * Scripts/test-webkitpy: + * Scripts/webkitpy/test/main.py: + +2010-10-18 Anders Carlsson <andersca@apple.com> + + Fix build. + + * DumpRenderTree/TestNetscapePlugIn/main.cpp: + (handleEventCarbon): + +2010-10-18 Stuart Morgan <stuartmorgan@chromium.org> + + Reviewed by Eric Seidel. + + Switch to using the new Carbon NPAPI event declarations, and remove + the old ones. + + https://bugs.webkit.org/show_bug.cgi?id=40784 + + * DumpRenderTree/TestNetscapePlugIn/main.cpp: + (handleEventCarbon): + +2010-10-18 David Levin <levin@chromium.org> + + Reviewed by Adam Barth. + + check-webkit-style should treat the GObject binding directory like other GTK directories. + https://bugs.webkit.org/show_bug.cgi?id=47796 + + * Scripts/webkitpy/style/checker.py: Added the GObject binding directory + with the other gtk directories (and fixed typo). + +2010-10-18 David Levin <levin@chromium.org> + + Reviewed by Oliver Hunt. + + check-webkit-style needs to ignore underscores in opcode names and vm_throw + https://bugs.webkit.org/show_bug.cgi?id=47789 + + * Scripts/webkitpy/style/checker.py: Added the exception for the assembler directory. + * Scripts/webkitpy/style/checkers/cpp.py: Added special cased names. + * Scripts/webkitpy/style/checkers/cpp_unittest.py: Added unit tests for the special cases. + +2010-10-18 MORITA Hajime <morrita@google.com> + + Reviewed by Kent Tamura. + + TextInputController.hasSpellingMarkers() should be owned by LayoutTestController + https://bugs.webkit.org/show_bug.cgi?id=47659 + + Moved hasSpellingMarkers() from TextInputController to + LayoutTestController. Currently the implementation is available + only for Mac and for Chromium. + + * DumpRenderTree/LayoutTestController.cpp: + (hasSpellingMarkerCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::hasSpellingMarker): + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/TextInputController.cpp: + (TextInputController::TextInputController): + (TextInputController::makeAttributedString): + * DumpRenderTree/chromium/TextInputController.h: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::hasSpellingMarker): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::hasSpellingMarker): + * DumpRenderTree/mac/TextInputController.m: + (+[TextInputController isSelectorExcludedFromWebScript:]): + (+[TextInputController webScriptNameForSelector:]): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::hasSpellingMarker): + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::hasSpellingMarker): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::hasSpellingMarker): + +2010-10-18 Adam Barth <abarth@webkit.org> + + Reviewed by David Levin. + + commit-queue's flaky test notice is very Pythony + https://bugs.webkit.org/show_bug.cgi?id=47790 + + This patch make the list of tests delimted by \n instead of just + converting the array to a string. + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-10-14 Antonio Gomes <agomes@rim.com> + + Reviewed by Martin Robinson and Xan Lopez. + + [Gtk]: DRT does not support frame flattening testing + https://bugs.webkit.org/show_bug.cgi?id=38650 + + Implement DRT's support for toggling on/off frame flattening + support. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setFrameFlatteningEnabled): + +2010-10-15 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Siedel. + + mocktool.MockOptions is inheriting from Mock, which has the side + effect of defaulting any attribute to another MockObject. So, + MockOptions().foo would always evaluate to true. This was + covering over bugs in the unit tests, and is probably the wrong + default behavior for anything attempting to mock out the options + argument returned from optparse.parse_args(). + + This patch changes the default behavior. The new MockOptions() + class takes an optional list of keyword parameters to set; this + patch doesn't use that feature but the fix for bug 47510 will. + + Also, this patch just fills in the default values necessary to + get all of the tests to pass; I didn't stare at each test by + hand to determine the "right" values. We can either fix that in + subsequent patches or let me know if we want to do that now (and + give me some guidance on what those values might want to be). + + https://bugs.webkit.org/show_bug.cgi?id=47709 + + * Scripts/webkitpy/tool/commands/commandtest.py: + * Scripts/webkitpy/tool/commands/download_unittest.py: + * Scripts/webkitpy/tool/commands/upload_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + * Scripts/webkitpy/tool/steps/steps_unittest.py: + * Scripts/webkitpy/tool/steps/updatechangelogswithreview_unittest.py: + +2010-10-15 Simon Fraser <simon.fraser@apple.com> + + Fix the build; need to add new slot to PageUIClient callbacks. + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::createOtherPage): + (WTR::TestController::initialize): + +2010-10-15 Simon Fraser <simon.fraser@apple.com> + + Add Matt Delaney to committers.py. + + * Scripts/webkitpy/common/config/committers.py: + +2010-10-15 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + [chromium] compile TestNetscapePlugIn on Chromium mac + https://bugs.webkit.org/show_bug.cgi?id=47633 + + * DumpRenderTree/DumpRenderTree.gypi: files to compile + * DumpRenderTree/TestNetscapePlugIn/main.cpp: Use ifdef because gcc was complaining + (NP_GetEntryPoints): + (NPP_New): + (NPP_Destroy): + (NPP_HandleEvent): + (NPP_GetValue): + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h: Added. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h: Added. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h: Added. + +2010-10-15 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + build-webkit: Should die when make fails when build a CMake project + https://bugs.webkit.org/show_bug.cgi?id=47726 + + * Scripts/webkitdirs.pm: If make fails, die immediately. + +2010-10-15 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r69809. + http://trac.webkit.org/changeset/69809 + https://bugs.webkit.org/show_bug.cgi?id=47725 + + Broke chromium mac compile (Requested by japhet on #webkit). + + * DumpRenderTree/DumpRenderTree.gypi: + * DumpRenderTree/TestNetscapePlugIn/main.cpp: + (NP_GetEntryPoints): + (NPP_New): + (NPP_Destroy): + (NPP_HandleEvent): + (NPP_GetValue): + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h: Removed. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h: Removed. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h: Removed. + +2010-10-15 Adam Barth <abarth@webkit.org> + + Reviewed by Adam Barth. + + test-webkitpy fails on Linux + https://bugs.webkit.org/show_bug.cgi?id=47713 + + The old code failed on Linux because the MacPort tries to read + something out of platform that doesn't make sense on Linux. + + * Scripts/webkitpy/tool/mocktool.py: + +2010-10-14 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] WTR is sloooow + https://bugs.webkit.org/show_bug.cgi?id=47695 + + * WebKitTestRunner/qt/TestControllerQt.cpp: + Change the timer interval of RunUntilConditionLoop from + 50 milliseconds to 1 to avoid wasting time after the + test had been finished. + +2010-10-14 Eric Seidel <eric@webkit.org> + + Unreviewed, just fixing an exception seen on the commit-queue. + + I should have unit tested this function before. + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-10-14 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + commit-queue should not fail patches due to flaky tests + https://bugs.webkit.org/show_bug.cgi?id=47647 + + This patch makes it so that the *same* flaky test has to fail + twice in a row to have a false negative from a flaky test. + + If different flaky tests fail (or if a test fails and then passes + in a second run) then we will warn in the bug that we encountered + a flaky test. + + This patch grew to include moving port off of steps onto tool + (which Adam wrote and then I integrated), as well as removing the + use of tool from CommitQueueTask. + + * Scripts/webkitpy/common/config/ports.py: + - Added a layout_test_results_path method. This covers old-run-webkit-tests + but doesn't cover NRWT. This is probably not the long term solution, but + putting this knowledge on port makes more sense than in LayoutTestResults. + * Scripts/webkitpy/common/net/buildbot.py: + - LayoutTestResults shouldn't know how to fetch from the network, make + the Build code do that instead. + * Scripts/webkitpy/common/net/buildbot_unittest.py: + - Code style fix. + * Scripts/webkitpy/common/net/layouttestresults.py: + - Remove code for reading from the network. + * Scripts/webkitpy/common/net/layouttestresults_unittest.py: + - Test the new entrypoint. + * Scripts/webkitpy/tool/bot/commitqueuetask.py: + - Make the delegate interface explicit. + - Remove the _tool member, since using the delegate for + everything is cleaner. + - Teach the testing logic how to deal with flaky tests. + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: + - Update to match the CommitQueueTask changes. + * Scripts/webkitpy/tool/commands/queues.py: + - Use the new CommitQueueTaskDelegate interface. + * Scripts/webkitpy/tool/commands/queues_unittest.py: + - Fix the SecondThoughtsCommitQueue test which was broken. + - Add a new test to make sure the flaky test reporting works. + * Scripts/webkitpy/tool/main.py: + - Store the port on the tool object. + * Scripts/webkitpy/tool/mocktool.py: + - Add a port() accessor to MockTool + * Scripts/webkitpy/tool/steps/abstractstep.py: + - Move port() off of Step and onto Tool. + * Scripts/webkitpy/tool/steps/build.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + * Scripts/webkitpy/tool/steps/runtests.py: + * Scripts/webkitpy/tool/steps/steps_unittest.py: + - Two tests with the same name! only the latter was being run. + * Scripts/webkitpy/tool/steps/update.py: + +2010-10-14 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + new-run-webkit-tests will now handle missing Ruby installs (or + missing PrettyPatch scripts) more cleanly - previously this + would be detected when we actually tried to create the diff, and + the error message was obscure. Now we'll log a warning up front + and otherwise be silent. + + This change also refactors some global variables to be class or + instance variables to be slightly more testable and more + modular. There are no cases where we create lots of port objects + and can't afford to test for configurations repeatedly, so + there's no performance concern here. + + https://bugs.webkit.org/show_bug.cgi?id=47466 + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-10-08 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] Form controls do not respect GTK+ font size + https://bugs.webkit.org/show_bug.cgi?id=47134 + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (initializeGtkFontSettings): Initialize the font control size when running + DumpRenderTree to a standard value. + +2010-10-14 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + [chromium] compile TestNetscapePlugIn on Chromium mac + https://bugs.webkit.org/show_bug.cgi?id=47633 + + * DumpRenderTree/DumpRenderTree.gypi: files to compile + * DumpRenderTree/TestNetscapePlugIn/main.cpp: Use ifdef because gcc was complaining + (NP_GetEntryPoints): + (NPP_New): + (NPP_Destroy): + (NPP_HandleEvent): + (NPP_GetValue): + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h: Added. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h: Added. + * DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h: Added. + +2010-10-14 Victor Wang <victorw@chromium.org> + + Reviewed by Nate Chapin. + + [Chromium] Fix rebaseline_chromium_webkit_tests to use 0 tolerance image diff. + + https://bugs.webkit.org/show_bug.cgi?id=47686 + + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + +2010-10-14 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + test-webkitpy spews Delegate terminated queue messages + https://bugs.webkit.org/show_bug.cgi?id=47678 + + * Scripts/webkitpy/tool/bot/queueengine_unittest.py: + +2010-10-14 Adam Roben <aroben@apple.com> + + Test that pressing the Alt key generates a WM_SYSCOMMAND message + + Test for <http://webkit.org/b/47671> <rdar://problem/8435594> Pressing + the Alt key when MiniBrowser's WKView is focused doesn't send focus to + the menu bar + + Reviewed by Steve Falkenburg. + + * TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops: Added + TestWebKitAPI/win to the include path so that WindowMessageObserver + can be found. + + * TestWebKitAPI/PlatformWebView.h: Added simulateAltKeyPress and + Windows-specific members. + (TestWebKitAPI::PlatformWebView::setParentWindowMessageObserver): + Added this simple setter. + + * TestWebKitAPI/Tests/WebKit2/win/AltKeyGeneratesWMSysCommand.cpp: Added. + (TestWebKitAPI::WMSysCommandObserver::WMSysCommandObserver): + Initialize our lone data member. + (TestWebKitAPI::WMSysCommandObserver::windowDidReceiveWMSysCommand): + Simple getter. + (TestWebKitAPI::WMSysCommandObserver::windowReceivedMessage): Record + when a WM_SYSCOMMAND message is received. + (TestWebKitAPI::didNotHandleKeyEventCallback): Record when a + WM_SYSKEYUP message is not handled. + (TestWebKitAPI::WebKit2_AltKeyGeneratesWMSysCommand): Simulate + pressing the Alt key and check that a WM_SYSCOMMAND message got sent + to the WKView's parent window. + + * TestWebKitAPI/win/PlatformWebViewWin.cpp: + (TestWebKitAPI::PlatformWebView::registerWindowClass): Made this a + member function so it could access PlatformWebView::wndProc. Use + PlatformWebView::wndProc as the WNDPROC. + (TestWebKitAPI::PlatformWebView::PlatformWebView): Initialize our new + data member and pass the this pointer to CreateWindowEx so we can + store it on the HWND. + (TestWebKitAPI::PlatformWebView::simulateSpacebarKeyPress): Moved some + constants from here to the top of the file. + (TestWebKitAPI::PlatformWebView::simulateAltKeyPress): Added. Sends + the same messages that Notepad receives when you press the Alt key. + (TestWebKitAPI::PlatformWebView::wndProc): Added. + - When WM_CREATE is received, we set the PlatformWebView instance + pointer as a property on the HWND so we can access it later. + - For other messages, we try to get the PlatformWebView instance + pointer from the HWND property. + - When WM_NCDESTROY is received (which is the last message we will + receive), we remove the PlatformWebView instance property. + - Pass messages to the parent window's message observer, if there is + one. + - Pass all messages through to ::DefWindowProcW. + + * TestWebKitAPI/win/TestWebKitAPI.vcproj: Added WindowMessageObserver + and AltKeyGeneratesWMSysCommand. + + * TestWebKitAPI/win/WindowMessageObserver.h: Added. This class can be + used to observe messages sent to one or more windows. + +2010-10-01 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Holger Freyther. + + [GTK] REGRESSION: FreeType backend does not respect XSettings font settings after r68558 + https://bugs.webkit.org/show_bug.cgi?id=47033 + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (initializeGtkFontSettings): Added this method which initializes XSettings + font settings to consistent values before running a test. For the one test + in which we need subpixel aliasing turned on, do that. + (initializeFonts): Accepts a testURL parameter now and delegates to initializeGtkFontSettings. + (runTest): Pass the testURL to initializeFonts. + +2010-10-14 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + ChromiumXVFBPort.run_webkit_tests_command has infinite recursion + https://bugs.webkit.org/show_bug.cgi?id=47655 + + * Scripts/webkitpy/common/config/ports.py: + * Scripts/webkitpy/common/config/ports_unittest.py: + +2010-10-13 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + beat diff_parser with the ugly stick + https://bugs.webkit.org/show_bug.cgi?id=47626 + + * Scripts/webkitpy/common/checkout/diff_parser.py: + * Scripts/webkitpy/style/patchreader.py: + * Scripts/webkitpy/style/patchreader_unittest.py: + +2010-10-13 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Break LayoutTestResults out into its own file + https://bugs.webkit.org/show_bug.cgi?id=47637 + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/buildbot_unittest.py: + * Scripts/webkitpy/common/net/layouttestresults.py: Added. + * Scripts/webkitpy/common/net/layouttestresults_unittest.py: Added. + +2010-10-13 Adam Barth <abarth@webkit.org> + + Unreviewed. + + Chromium port can't run JavaScriptCore tests + https://bugs.webkit.org/show_bug.cgi?id=47654 + + This lets webkit-patch build-and-test work on Chromium. + + * Scripts/webkitpy/common/config/ports.py: + * Scripts/webkitpy/tool/steps/runtests.py: + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Make --port a global option and pass the port information to the commit-queue subprocess + https://bugs.webkit.org/show_bug.cgi?id=47650 + + This patch paves the way to run the commit-queue on a non-Mac port. + + * Scripts/webkitpy/tool/commands/queues.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/commands/queuestest.py: + * Scripts/webkitpy/tool/main.py: + * Scripts/webkitpy/tool/steps/options.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + * Scripts/webkitpy/tool/steps/runtests.py: + * Scripts/webkitpy/tool/steps/update.py: + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Introduce the ChromiumXVFBPort for running commit-queue on EC2 + https://bugs.webkit.org/show_bug.cgi?id=47653 + + I'm not entirely sure this is the best way to do this, but we need to + run the tests under XVFB on EC2 because the EC2 instances don't have a + real monitor hooked up. This patch adds a ChromiumXVFBPort that runs + that way. The idea is that XVFB is like a platform for the Chromium + port, but we don't have a real notion of platform separate from port. + + * Scripts/webkitpy/common/config/ports.py: + +2010-10-13 Sergio Villar Senin <svillar@igalia.com> + + Reviewed by Martin Robinson. + + [GTK] Add HTTP caching support + https://bugs.webkit.org/show_bug.cgi?id=44261 + + Add include paths for the new soup HTTP cache code. + + * GNUmakefile.am: Add paths for the new soup HTTP cache code. + +2010-10-13 Yi Shen <yi.4.shen@nokia.com> + + Reviewed by Antonio Gomes. + + [Qt] QtTestBrowser shows two Url input fields + https://bugs.webkit.org/show_bug.cgi?id=47613 + + * QtTestBrowser/mainwindow.cpp: + (MainWindow::MainWindow): + (MainWindow::buildUI): + +2010-10-13 Yi Shen <yi.4.shen@nokia.com> + + Reviewed by Tony Chang. + + [gdb] Add pretty-print supports for UString, Identifier and JSString + https://bugs.webkit.org/show_bug.cgi?id=47601 + + * gdb/webkit.py: + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add list of Ubuntu packages needed by the EWS bots + https://bugs.webkit.org/show_bug.cgi?id=47628 + + I've been copy/pasting this list between bots, but it's better to have + this checked in. + + * EWSTools/ubuntu-ews-packages: Added. + +2010-10-13 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Csaba Osztrogonác. + + [EFL] Adds a build slave. + https://bugs.webkit.org/show_bug.cgi?id=47290 + + * BuildSlaveSupport/build.webkit.org-config/config.json: Add an + entry for a release build of the EFL port. + * BuildSlaveSupport/build.webkit.org-config/master.cfg: Add platform + flag to build the EFL port. + +2010-10-13 Adam Barth <abarth@webkit.org> + + Reviewed by Csaba Osztrogonác. + + webkit-patch build shouldn't need --build to actually build! + https://bugs.webkit.org/show_bug.cgi?id=47438 + + Yeah, requiring --build for the build command is really dumb. We did + this originally because the build step is usually optional in other + commands. We don't have a good way of reversing the default for an + option in one command. This approach is slightly hacky since --build + still shows up as an option on the help page, but at least it makes + progress. Passing --build is harmless, so the EWS bots shouldn't + explode because of this change. + + * Scripts/webkitpy/tool/bot/commitqueuetask.py: + * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: + * Scripts/webkitpy/tool/commands/download.py: + * Scripts/webkitpy/tool/commands/earlywarningsystem.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + +2010-10-13 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r69638. + http://trac.webkit.org/changeset/69638 + https://bugs.webkit.org/show_bug.cgi?id=47595 + + "Broke win and chromium-win bots" (Requested by dglazkov on + #webkit). + + * Scripts/webkitpy/common/system/path.py: + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + * 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/run_webkit_tests.py: + +2010-10-13 John Knottenbelt <jknotten@chromium.org> + + Reviewed by Steve Block. + + First step towards client-based Geolocation in Chromium. Build + fixes for CLIENT_BASED_GEOLOCATION preprocessor feature define. + https://bugs.webkit.org/show_bug.cgi?id=47586 + + * DumpRenderTree/chromium/WebViewHost.cpp: + * DumpRenderTree/chromium/WebViewHost.h: + +2010-10-13 Adam Roben <aroben@apple.com> + + Test that pressing the spacebar in a text field does not scroll the + document + + Test for <http://webkit.org/b/47544> <rdar://problem/8540645> + REGRESSION: Pressing spacebar in a text field in WebKit2 does not + insert a space, scrolls the page instead + + Reviewed by Sam Weinig. + + * TestWebKitAPI/PlatformUtilities.h: Added isKeyDown. + + * TestWebKitAPI/PlatformWebView.h: Added simulateSpacebarKeyPress. + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/win/TestWebKitAPI.vcproj: + * TestWebKitAPI/win/copy-resources.cmd: + Added new files. + + * TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp: Added. + (TestWebKitAPI::JavaScriptCallbackContext::JavaScriptCallbackContext): + We use this to track what the result of calling into JavaScript was. + (TestWebKitAPI::didFinishLoadForFrame): Records when the page + finishes loading. + (TestWebKitAPI::didNotHandleKeyEventCallback): Records when a key down + event is not handled. + (TestWebKitAPI::javaScriptCallback): Records that JavaScript finished + executing and whether the result matched our expectation. + (TestWebKitAPI::wk): Turns a UTF-8 C string into a WKStringRef. + (TestWebKitAPI::runJSTest): Calls into JS, waits for the call to + complete, and returns whether we got back the expected result. + (TestWebKitAPI::WebKit2_SpacebarScrolling): Tests that pressing + spacebar inside a text field does not scroll the document and that + pressing it outside the text field does scroll the document. + + * TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html: Added. + + * TestWebKitAPI/mac/PlatformUtilitiesMac.mm: + (TestWebKitAPI::Util::isKeyDown): Checks the event's type. + + * TestWebKitAPI/mac/PlatformWebViewMac.mm: + (TestWebKitAPI::PlatformWebView::simulateSpacebarKeyPress): Copied + code from DRT's EventSendingController. + + * TestWebKitAPI/win/PlatformUtilitiesWin.cpp: + (TestWebKitAPI::Util::isKeyDown): Checks the message's type. + + * TestWebKitAPI/win/PlatformWebViewWin.cpp: + (TestWebKitAPI::PlatformWebView::simulateSpacebarKeyPress): Send the + same messages that get sent when you press spacebar in Notepad. + +2010-10-13 Adam Roben <aroben@apple.com> + + Fix a couple of issues with the TestWebKitAPI build + + * TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops: + * TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops: + Fixed a typo. + + * TestWebKitAPI/win/TestWebKitAPIGenerated.vcproj: Use common.vsprops + to set our output and intermediate directories so that we don't spew + files into the source tree. + +2010-10-13 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Csaba Osztrogonác. + + WTR should accept relative paths + https://bugs.webkit.org/show_bug.cgi?id=47486 + + * WebKitTestRunner/StringFunctions.h: + * WebKitTestRunner/TestInvocation.cpp: + (WTR::createWKURL): Moved from StringFunctions.h since it is + used only here. Extend relative paths to absolute. + +2010-10-12 Adam Roben <aroben@apple.com> + + Make TestWebKitAPI work on Windows + + Fixes <http://webkit.org/b/47552> <rdar://problem/8541708>. + + Reviewed by Sam Weinig. + + * Scripts/build-api-tests: Build TestWebKitAPI.sln on Windows. + + * Scripts/run-api-tests: Fix the PATH so that TestWebKitAPI can be + run on Windows. + (runTest): Added code to run TestWebKitAPI.exe on Windows and to die + on unsupported platforms. + (populateTests): Added code to run TestWebKitAPI.exe on Windows and to + die on other platforms. Extracted some formerly-Mac-specific code to + be cross-platform and made it handle any style of line-endings. + + * TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops: Added. + Links against CFLite. + + * TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops: Added. + Contains most properties for the project. + + * TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops: + Added. Links against CoreFoundation. + + * TestWebKitAPI/TestWebKitAPIPrefix.h: Added a Windows-specific + section and moved the cross-platform section after the + platform-specific parts. + + * TestWebKitAPI/win/PlatformUtilitiesWin.cpp: Added. + (TestWebKitAPI::Util::run): Runs a normal message pump until we're + done. + (TestWebKitAPI::Util::cf): Turns a UTF-8 C string into a CFString. + (TestWebKitAPI::Util::createURLForResource): Uses CFBundle to get the + resource path. + (TestWebKitAPI::Util::URLForNonExistentResource): Creates a bogus + WKURL. + + * TestWebKitAPI/win/PlatformWebViewWin.cpp: Added. + (TestWebKitAPI::registerWindowClass): + (TestWebKitAPI::PlatformWebView::PlatformWebView): + (TestWebKitAPI::PlatformWebView::~PlatformWebView): + (TestWebKitAPI::PlatformWebView::page): + This was mostly copied from WebKitTestRunner's PlatformWebView. + + * TestWebKitAPI/win/TestWebKitAPI.sln: Added. Builds both + TestWebKitAPI and TestWebKitAPIGeneratd. This is used by the + build-api-tests script. + + * TestWebKitAPI/win/TestWebKitAPI.vcproj: Added. Builds + TestWebKitAPI.exe. + + * TestWebKitAPI/win/TestWebKitAPIGenerated.vcproj: Added. Just calls + through to copy-resources.cmd. + + * TestWebKitAPI/win/copy-resources.cmd: Added. Copies resources into + or deletes resources from TestWebKitAPI.resources. + + * TestWebKitAPI/win/main.cpp: Added. + (main): Calls through to TestsController. + +2010-10-13 Gyuyoung Kim <gyuyoung.kim@samsung.com> + + Reviewed by Kenneth Rohde Christiansen. + + [EFL] Support viewport configuration and add new arguments for WebKit EFL + https://bugs.webkit.org/show_bug.cgi?id=47084 + + Opera spec regarding to viewport meta tag was adjusted to WebCore. So, EFL port + needs to be modified according to the changes. + + * EWebLauncher/main.c: + (on_viewport_changed): + +2010-10-12 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + This patch enables new-run-webkit-tests (in particular the + chromium-win port) to run under Cygwin as well as Win32. Mostly + this just required some conversions from cygwin paths to Win32 + paths when we spawn off Win32 binaries like test_shell. + + https://bugs.webkit.org/show_bug.cgi?id=47220 + + * Scripts/webkitpy/common/system/path.py: + - Expose the cygpath() function for path conversion + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + - shift filename->uri conversion in the TestInfo objects to the + dump_render_tree thread + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/chromium.py: + - use cygpath() + +2010-10-12 Yuta Kitamura <yutak@chromium.org> + + Unreviewed. Add Yuta Kitamura (yutak) to the committers list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-10-12 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + When a provisional load fails, the provisional URL returned + from WKFrameCopyProvisionalURL should be empty + <rdar://problem/8540878> + https://bugs.webkit.org/show_bug.cgi?id=47546 + + Add test. + + * TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp: + (TestWebKitAPI::didFailProvisionalLoadWithErrorForFrame): + +2010-10-12 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Start fleshing out find page overlays + https://bugs.webkit.org/show_bug.cgi?id=47559 + + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController find:]): + Pass kWKFindOptionsShowOverlay to WKPageFindString. + +2010-10-12 Robert Hogan <robert@webkit.org> + + Reviewed by Antonio Gomes. + + [Qt] editing/input/emacs-ctrl-o.html + + ctrl-o is bound to a sequence of commands on Mac, namely: + insertParagraphSeparator then moveLeft. In the DRT, we just interpret + ctrl-o in EventSenderQt as '\n', i.e. insertParagraphSeparator. As a + result we only issue one command, so don't generate the change in caret + position that results in the extra editing delegate messages. + + So for the sake of not managing suspicious-looking differences, just + make DRT issue the appropriate edit commands to pass the test. + + https://bugs.webkit.org/show_bug.cgi?id=47548 + + * DumpRenderTree/qt/EventSenderQt.cpp: + (EventSender::keyDown): + +2010-10-12 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Add a simple Find UI to MiniBrowser + https://bugs.webkit.org/show_bug.cgi?id=47553 + + * MiniBrowser/mac/BrowserWindow.xib: + Add Find panel. + + * MiniBrowser/mac/BrowserWindowController.h: + * MiniBrowser/mac/BrowserWindowController.m: + (-[BrowserWindowController performFindPanelAction:]): + Show the find panel. + + (-[BrowserWindowController find:]): + Tell the WKPageRef to find the given string. + +2010-10-12 Tony Chang <tony@chromium.org> + + Unreviewed, fixing DRT compile on Windows after r69586. + + * DumpRenderTree/chromium/WebThemeEngineDRT.h: + +2010-10-12 Tony Chang <tony@chromium.org> + + Unreviewed, trying to fix NRWT on Windows. + + * Scripts/webkitpy/layout_tests/port/http_lock.py: + +2010-10-12 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt][WTR] Checking the path of the injected bundle is bogus + https://bugs.webkit.org/show_bug.cgi?id=47541 + + * WebKitTestRunner/qt/TestControllerQt.cpp: + (WTR::isExistingLibrary): Added (static helper). + Extend the path with the appropriate suffix(es) on the + platform and check that the file exists. + (WTR::TestController::initializeInjectedBundlePath): + There were two bugs with the path checking: + - the condition should have been inverted + - QLibrary::fileName does not give back the filename + with the library suffix so we cannot check + that existance of the file this way. + +2010-10-12 Gabor Rapcsanyi <rgabor@inf.u-szeged.hu> + + Reviewed by Tony Chang. + + Implement http locking in NRWT. + https://bugs.webkit.org/show_bug.cgi?id=47072 + + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/http_lock.py: Added. + * Scripts/webkitpy/layout_tests/port/http_lock_unittest.py: Added. + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-10-12 Mark Rowe <mrowe@apple.com> + + Fix the 32-bit WebKit2 build. + + * MiniBrowser/mac/BrowserWindowController.m: + (getWindowFrame): Use NSRect rather than CGRect since that's what -frame returns. + (setWindowFrame): Use NSMakeRect rather than CGRectMake since that's what -setFrame:display: expects. + +2010-10-11 Tony Chang <tony@chromium.org> + + Reviewed by Adam Barth. + + change the order of mrobinson's email addresses so bugs.webkit.org suggests the right one + https://bugs.webkit.org/show_bug.cgi?id=47513 + + bugs.webkit.org suggests mrobinson@igalia.com as an autocomplete, + which doesn't actually work. + + * Scripts/webkitpy/common/config/committers.py: + +2010-10-11 Prasad Tammana <prasadt@chromium.org> + + Reviewed by Dmitry Titov. + + Added support for showModalDialog on chromium port. + + Implement showModalDialog for Layout tests for chromium port + https://bugs.webkit.org/show_bug.cgi?id=46759 + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::closeWidgetSoon): Quit current message loop if in a modal loop. + (WebViewHost::runModal): Start a nested message loop and remember that. + (WebViewHost::WebViewHost): Initialize m_inModalLoop. + * DumpRenderTree/chromium/WebViewHost.h: Add m_inModalLoop. + +2010-10-11 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Cleanup font selection code for the Freetype backend + https://bugs.webkit.org/show_bug.cgi?id=47503 + + Update DRT to set values for the cursive and fantasy font families, so + that we can generate consistent results for tests that use these families. + Add some missing information to fonts.conf. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): Always set the fantasy and cursive font + family names. + * DumpRenderTree/gtk/fonts/fonts.conf: Add aliases for cursive and fantasy fonts + to our default serif font. Eventually we may want to import or require some "real" + fonts, but this should at least ensure consistent rendering during test runs. Also + add aliases for some other commonly used fonts in tests (Arial and Lucida Grande). + Finally, add a missing oblique specification for DejaVu Serif, which was resulting + in some incorrect baselines for the synthetic oblique test. + +2010-10-11 Adam Barth <abarth@webkit.org> + + Unreviewed. + + Fix sheriffbot not to crash when there are failing tests. It turns out + Python sets don't support the + operator. We need to use union + instead. There's a more elegant way to do this in Python 2.6, but we + need this code to work in 2.5. + + * Scripts/webkitpy/common/net/failuremap.py: + * Scripts/webkitpy/common/net/failuremap_unittest.py: + +2010-10-10 Robert Hogan <robert@webkit.org> + + Unreviewed, fix failing test from r69468. + + [Qt] Put all DRT-created pages in a page group + + Fix on r69468. + + Because we don't delete closed pages immediately in DRT we need + to remove them from the page group explicitly instead. + + Fixes failure of fast/events/popup-blocked-from-fake-user-gesture.html + + https://bugs.webkit.org/show_bug.cgi?id=47469 + + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::DumpRenderTree::windowCloseRequested): + +2010-10-10 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Adam Barth. + + commit-queue: Add EFL-EWS status bubble to Bugzilla, now that the + EFL-EWS bot is up and running. + https://bugs.webkit.org/show_bug.cgi?id=47277 + + * QueueStatusServer/handlers/statusbubble.py: + +2010-10-10 Robert Hogan <robert@webkit.org> + + Reviewed by Antonio Gomes. + + [Qt] Put all DRT-created pages in a page group + + https://bugs.webkit.org/show_bug.cgi?id=47469 + + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::DumpRenderTree::DumpRenderTree): + (WebCore::DumpRenderTree::createWindow): + +2010-10-09 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + WKFrameGetFrameLoadState() returns kWKFrameLoadStateCommitted after the load has been stopped + <rdar://problem/8173667> + https://bugs.webkit.org/show_bug.cgi?id=47461 + + * TestWebKitAPI/PlatformUtilities.h: + * TestWebKitAPI/Test.h: + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp: Added. + (TestWebKitAPI::didFailProvisionalLoadWithErrorForFrame): + (TestWebKitAPI::TEST): + * TestWebKitAPI/mac/PlatformUtilitiesMac.mm: + (TestWebKitAPI::Util::URLForNonExistentResource): + Adds a test for the frame load state after a failed provisional load. I wanted to test + the frame load state after a committed load failed, but I don't believe that is possible + to do without hooking up the http server to serve a long loading page. + +2010-10-09 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Add WebKit2 version of runBeforeUnloadConfirmPanelWithMessage + <rdar://problem/8447690> + https://bugs.webkit.org/show_bug.cgi?id=47459 + + * MiniBrowser/mac/BrowserWindowController.m: + (runBeforeUnloadConfirmPanel): + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/TestController.cpp: + (WTR::createOtherPage): + (WTR::TestController::initialize): + +2010-10-09 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Need implementation of ChromeClient windowRect related functions. + <rdar://problem/8469476> + https://bugs.webkit.org/show_bug.cgi?id=47386 + + * MiniBrowser/mac/BrowserWindowController.m: + (getWindowFrame): + (setWindowFrame): + (-[BrowserWindowController awakeFromNib]): + * WebKitTestRunner/PlatformWebView.h: + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::initialize): + * WebKitTestRunner/mac/PlatformWebViewMac.mm: + (WTR::PlatformWebView::windowFrame): + (WTR::PlatformWebView::setWindowFrame): + * WebKitTestRunner/qt/PlatformWebViewQt.cpp: + (WTR::PlatformWebView::windowFrame): + (WTR::PlatformWebView::setWindowFrame): + * WebKitTestRunner/win/PlatformWebViewWin.cpp: + (WTR::PlatformWebView::windowFrame): + (WTR::PlatformWebView::setWindowFrame): + +2010-10-08 Adam Barth <abarth@webkit.org> + + Unreviewed (Eric is on vacation in this change is trivial). + + Add a "clean" command to webkit-patch to clean the working directory + https://bugs.webkit.org/show_bug.cgi?id=47436 + + This command is useful when using SVN because "svn revert" leaves + unversioned files behind. + + * Scripts/webkitpy/tool/commands/download.py: + +2010-10-08 Andras Becsi <abecsi@webkit.org> + + Unreviewed build fix. + + [Qt] Add missing limits.h include since the Qt version currently + ran on the bot does need that. + + * WebKitTestRunner/InjectedBundle/qt/ActivateFontsQt.cpp: + +2010-10-08 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Csaba Osztrogonác. + + [Qt] Turn on building WTR + https://bugs.webkit.org/show_bug.cgi?id=47349 + + * Scripts/webkitdirs.pm: + +2010-10-08 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Andreas Kling. + + [Qt] TestController needs its platform dependent methods + https://bugs.webkit.org/show_bug.cgi?id=47413 + + * WebKitTestRunner/qt/TestControllerQt.cpp: + (WTR::TestController::initializeInjectedBundlePath): + If the WTR_INJECTEDBUNDLE_PATH environmental variable is + set then use that otherwise use the path where the bundle + lives in a normal trunk build. + (WTR::TestController::initializeTestPluginDirectory): + Set the bundle's value. It is not used currently. + (WTR::TestController::platformInitializeContext): + * WebKitTestRunner/qt/WebKitTestRunner.pro: + +2010-10-08 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + WTR: Prevent sending the Done message twice on test timeout. + https://bugs.webkit.org/show_bug.cgi?id=47410 + + When InjectedBundle::done() calls stopLoading, this may trigger + InjectedBundlePage::didFailLoadWithErrorForFrame which calls + InjectedBundle::done() itself later in the stack. + This would output the timeout failure message twice and confuse + the run-webkit-tests script. + + This patch adds a third state, Stopping, which prevents WebCore + errors to trigger done() when testing is over. + + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::done): + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + +2010-10-08 Andras Becsi <abecsi@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add an activateFonts() implementation similar to DRT's initializeFonts(). + Original code by Simon Hausmann. + https://bugs.webkit.org/show_bug.cgi?id=47402 + + * WebKitTestRunner/InjectedBundle/qt/ActivateFontsQt.cpp: Added. + (WTR::activateFonts): + +2010-10-08 Andras Becsi <abecsi@webkit.org> + + Reviewed by Csaba Osztrogonác. + + [Qt] Add support for Qt's WebKitTestRunner to old-run-webkit-tests. + https://bugs.webkit.org/show_bug.cgi?id=47401 + + * Scripts/build-webkittestrunner: + * Scripts/old-run-webkit-tests: + +2010-10-07 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] WTR first compile: fix compile issues. + https://bugs.webkit.org/show_bug.cgi?id=47343 + + * WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h: + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + * WebKitTestRunner/TestController.cpp: + * WebKitTestRunner/TestInvocation.cpp: + +2010-10-07 Antonio Gomes <agomes@rim.com> + + Reviewed by Simon Fraser. + + [Mac] [DRT] implement setSpatialNavigationEnabled + https://bugs.webkit.org/show_bug.cgi?id=47291 + + Implemented LayoutTestController::setSpatialNavigationEnabled for Mac's DRT + so it can track regression on the existing implementation and future improvements + we are making. + + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setSpatialNavigationEnabled): + +2010-10-07 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Adam Barth. + + rebaseline-chromium-webkit-tests relied on the filename_to_uri() + hook in the Port infrastructure to generate URIs for the files + in its summary HTML report; however, that method is supposed to only + be used for test files (and should really be renamed), so this would + crash. + + This change adds a new "path" module to the system package with a + routine called abspath_to_uri() that handles converting paths to + file: URIs independently of anything in the layout_tests package, + and changes the code to use this. At some point in the near future + the layout_tests/port/* code should use this as well. + + This change also deletes a bunch of unused code and fixes some + comments in rebaseline_chromium_webkit_tests.py. + + https://bugs.webkit.org/show_bug.cgi?id=47319 + + * Scripts/webkitpy/common/system/path.py: Added. + * Scripts/webkitpy/common/system/path_unittest.py: Added. + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py: + +2010-10-07 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] The FreeType backend does not respect the FC_EMBOLDEN property + https://bugs.webkit.org/show_bug.cgi?id=46216 + + Fix my latest commit, as it contained some bad changes from a merge gone wrong. + + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (initializeFonts): Also initialize the DevaVu Sans font. + +2010-10-07 Daniel Cheng <dcheng@chromium.org> + + Reviewed by Tony Chang. + + [chromium] Minor naming cleanup in WebDragData, part 2 + https://bugs.webkit.org/show_bug.cgi?id=47227 + + Update DRT to use the renamed methods. + + * DumpRenderTree/chromium/EventSender.cpp: + (EventSender::beginDragWithFiles): + * DumpRenderTree/chromium/WebViewHost.cpp: + (addDRTFakeFileToDataObject): + +2010-10-07 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Add a WKPageFindClient, hook up WKPageCountStringMatches + https://bugs.webkit.org/show_bug.cgi?id=47373 + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + Remove hard coded paths. + + * TestWebKitAPI/Tests/WTF/VectorBasic.cpp: + (TestWebKitAPI::TEST): + Fix expected result. + + * TestWebKitAPI/Tests/WebKit2/Find.cpp: Added. + (TestWebKitAPI::didFinishLoadForFrame): + (TestWebKitAPI::didCountStringMatches): + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/find.html: Added. + Add test for WKPageCountStringMatches. + +2010-09-21 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Chris Fleizach. + + [GTK] The FreeType backend does not respect the FC_EMBOLDEN property + https://bugs.webkit.org/show_bug.cgi?id=46216 + + * DumpRenderTree/gtk/fonts/fonts.conf: Add a setting which enables FC_EMBOLDEN + for DejaVu Serif when there is no bold version available. This is necessary to + properly test the property in layout tests. + +2010-10-07 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>, Andras Becsi <abecsi@webkit.org>, Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add WTR's InjectedBundle build files. + https://bugs.webkit.org/show_bug.cgi?id=47333 + + * Scripts/webkitdirs.pm: + * WebKitTestRunner/DerivedSources.pro: Added. + * WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro: Added. + * WebKitTestRunner/WebKitTestRunner.pro: Added. + * WebKitTestRunner/qt/DerivedSources.pro: Removed. + Content merged in ../DerivedSources.pro + +2010-10-07 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r69315. + http://trac.webkit.org/changeset/69315 + https://bugs.webkit.org/show_bug.cgi?id=47363 + + Forgot to add the new files (Requested by kbalazs on #webkit). + + * Scripts/webkitdirs.pm: + * WebKitTestRunner/qt/DerivedSources.pro: Added. + +2010-10-07 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Change API tester to ask the executable for the list of all + tests instead of relying on the directory structure. + https://bugs.webkit.org/show_bug.cgi?id=47359 + + * Scripts/run-test-webkit-api: Added. + * Scripts/webkitdirs.pm: + Add additional script to just launch the api tester with the correct settings. + + * Scripts/run-api-tests: + Change to use the new --dump-tests options to build the list of tests and change + output to reflect a (suite, testcase) tuple for each test. Also adds some color. + + * TestWebKitAPI/Test.h: + (TestWebKitAPI::Test::Register::Register): + * TestWebKitAPI/Tests/WTF/VectorBasic.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/WKString.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp: + (TestWebKitAPI::TEST): + Give each test a suite name in addition to the test name. + + * TestWebKitAPI/TestsController.cpp: + (TestWebKitAPI::TestsController::dumpTestNames): + (TestWebKitAPI::TestsController::runTestNamed): + * TestWebKitAPI/TestsController.h: + * TestWebKitAPI/mac/main.mm: + (main): + Add option to print all registered tests. + +2010-10-07 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>, Andras Becsi <abecsi@webkit.org>, Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add WTR's InjectedBundle build files. + https://bugs.webkit.org/show_bug.cgi?id=47333 + + * Scripts/webkitdirs.pm: + * WebKitTestRunner/DerivedSources.pro: Added. + * WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro: Added. + * WebKitTestRunner/WebKitTestRunner.pro: Added. + * WebKitTestRunner/qt/DerivedSources.pro: Removed. + Content merged in ../DerivedSources.pro + +2010-10-07 Balazs Kelemen <kbalazs@webkit.org> + + Unreviewed. Do a renaming that was recommended by the reviewer + (Kenneth) but I forgot to do before landing (http://trac.webkit.org/changeset/69253) + + * WebKitTestRunner/qt/TestControllerQt.cpp: + (WTR::RunUntilConditionLoop::start): + (WTR::RunUntilConditionLoop::RunUntilConditionLoop): + (WTR::TestController::runUntil): + +2010-10-07 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Watchdog timer implementation for WTR + https://bugs.webkit.org/show_bug.cgi?id=47337 + + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: Factor out + the definition of the timer type to a typedef. + * WebKitTestRunner/InjectedBundle/qt/LayoutTestControllerQt.cpp: Added. + Timer implementation with QTimer and a helper QObject class. + (WTR::WatchdogTimerHelper::instance): + (WTR::WatchdogTimerHelper::timerFired): + (WTR::WatchdogTimerHelper::WatchdogTimerHelper): + (WTR::LayoutTestController::platformInitialize): + (WTR::LayoutTestController::invalidateWaitToDumpWatchdogTimer): + (WTR::LayoutTestController::initializeWaitToDumpWatchdogTimerIfNeeded): + +2010-10-07 Balazs Kelemen <kbalazs@webkit.org> + + Unreviewed buildfix for 69297 again + + * WebKitTestRunner/TestController.cpp: + (WTR::blankURL): + +2010-10-07 Balazs Kelemen <Balazs Kelemen> + + Unreviewed trivial build fix for r69297 + + * WebKitTestRunner/TestController.cpp: + (WTR::blankURL): + +2010-10-07 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + WebKitTestRunner should be portable + https://bugs.webkit.org/show_bug.cgi?id=45393 + + Use only the WebKit API for working with urls. + * WebKitTestRunner/StringFunctions.h: + (WTR::createWKURL): + * WebKitTestRunner/TestController.cpp: + (WTR::blankURL): + (WTR::TestController::resetStateToConsistentValues): + (WTR::TestController::didFinishLoadForFrame): + +2010-10-07 Carlos Garcia Campos <cgarcia@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] Use gtk_widget_draw() instead of gtk_widget_get_snapshot() in PixelDumpSupportGtk when building with gtk3 + https://bugs.webkit.org/show_bug.cgi?id=47332 + + * DumpRenderTree/gtk/PixelDumpSupportGtk.cpp: + (createBitmapContextFromWebView): + +2010-10-06 Chris Guillory <chris.guillory@google.com> + + Reviewed by Chris Fleizach. + + Remove unused accessibility functions from webkit. + https://bugs.webkit.org/attachment.cgi?bugid=46707 + + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::postAccessibilityNotification): + * DumpRenderTree/chromium/WebViewHost.h: + +2010-10-06 Lucas Forschler <lforschler@apple.com> + + Reviewed by Adam Roben. + + Fix the sunspider-compare-results to actually use the passed in value for $root. + + * Scripts/sunspider-compare-results: + +2010-10-06 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Runloop implementation for WTR + https://bugs.webkit.org/show_bug.cgi?id=47280 + + * WebKitTestRunner/qt/TestControllerQt.cpp: + Implemented TestController::runUntil by a timerEvent + and a QEventLoop. We step into the event loop from runUntil. + While we are waiting in the loop a timerEvent is periodically + checking the value of the condition. Once the condition has + becoming true the timerEvent wakes us up. + (WTR::RunUntilLoop::start): + (WTR::RunUntilLoop::RunUntilLoop): + (WTR::RunUntilLoop::run): + (WTR::RunUntilLoop::timerEvent): + (WTR::TestController::platformInitialize): + (WTR::TestController::runUntil): + * WebKitTestRunner/qt/main.cpp: + Start the main event loop first and creating the TestController later. + (Launcher::Launcher): + (Launcher::~Launcher): + (Launcher::launch): Creating the TestController. + (main): Setting up a timer for calling Launcher::launch from + the main event loop. + +2010-10-06 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Kenneth Russell. + + new-run-webkit-tests: fix typo in chromium-gpu that was trying to + enable 'accelerated-composting' instead of 'accelerated-compositing'. + + https://bugs.webkit.org/show_bug.cgi?id=47312 + + * Scripts/webkitpy/layout_tests/port/chromium_gpu.py: + * Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py: + +2010-10-06 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] PlatformWebView implementation for WebKitTestRunner + https://bugs.webkit.org/show_bug.cgi?id=47276 + + The implementation follows the way how + we use the API in MiniBrowser. + * WebKitTestRunner/PlatformWebView.h: + * WebKitTestRunner/qt/PlatformWebViewQt.cpp: + (WTR::WebView::wkView): + (WTR::WebView::~WebView): + (WTR::WebView::WebView): + (WTR::PlatformWebView::PlatformWebView): + (WTR::PlatformWebView::~PlatformWebView): + (WTR::PlatformWebView::resizeTo): + (WTR::PlatformWebView::page): + (WTR::PlatformWebView::focus): + * WebKitTestRunner/qt/WebKitTestRunner.pro: + +2010-10-06 Balazs Kelemen <kbalazs@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add WebKitTestRunner's build files + https://bugs.webkit.org/show_bug.cgi?id=44155 + + Parts was taken by Zoltan Horvath's patch. + + * Scripts/generate-forwarding-headers.pl: Moved from WebKit2. + * Scripts/webkitdirs.pm: Make the generated files needed by WTR. + * WebKitTestRunner/PlatformWebView.h: Addeed typedefs for + PlatformWKView and PlatformWindow (void* for now). + Buildfix the case when __APPLE__ is not defined. + * WebKitTestRunner/qt/DerivedSources.pro: Added. + * WebKitTestRunner/qt/PlatformWebViewQt.cpp: Added. + Empty stub implementation. + (WTR::registerWindowClass): + (WTR::PlatformWebView::PlatformWebView): + (WTR::PlatformWebView::~PlatformWebView): + (WTR::PlatformWebView::resizeTo): + (WTR::PlatformWebView::page): + (WTR::PlatformWebView::focus): + * WebKitTestRunner/qt/TestControllerQt.cpp: Added. + Empty stub implementation. + (WTR::registerWindowClass): + (WTR::TestController::runUntil): + (WTR::TestController::platformInitialize): + (WTR::TestController::initializeInjectedBundlePath): + (WTR::TestController::initializeTestPluginDirectory): + (WTR::TestController::platformInitializeContext): + * WebKitTestRunner/qt/WebKitTestRunner.pro: Added. + * WebKitTestRunner/qt/main.cpp: Added. + (main): + +2010-10-06 Tony Chang <tony@chromium.org> + + Unreviewed, rolling out r69202. + http://trac.webkit.org/changeset/69202 + https://bugs.webkit.org/show_bug.cgi?id=46937 + + Broke compile of test_shell + + * DumpRenderTree/chromium/EventSender.cpp: + (EventSender::beginDragWithFiles): + * DumpRenderTree/chromium/WebViewHost.cpp: + (addDRTFakeFileToDataObject): + +2010-10-06 Daniel Cheng <dcheng@chromium.org> + + Reviewed by Tony Chang. + + [chromium] Minor naming cleanup in WebDragData, part 2 + https://bugs.webkit.org/show_bug.cgi?id=46937 + + Update DRT to use the renamed methods. + + * DumpRenderTree/chromium/EventSender.cpp: + (EventSender::beginDragWithFiles): + * DumpRenderTree/chromium/WebViewHost.cpp: + (addDRTFakeFileToDataObject): + +2010-10-06 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/47270> Move WebArchive serialization code into its own file + + Reviewed by Adam Roben. + + This is the first step in making webarchive tests work on + Windows. + + * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj: Added + new files to the project. + * DumpRenderTree/mac/DumpRenderTree.mm: Removed code that moved + to WebArchiveDumpSupport.mm. + * DumpRenderTree/mac/WebArchiveDumpSupport.h: Added. + * DumpRenderTree/mac/WebArchiveDumpSupport.mm: Copied from WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm. + (serializeWebArchiveToXML): + +2010-10-05 Daniel Bates <dbates@rim.com> + + Reviewed by David Kilzer. + + Add infrastructure to towards detecting change log diffs that aren't at the top of the ChangeLog + https://bugs.webkit.org/show_bug.cgi?id=46058 + + Make VCSUtils::fixChangeLogPatch() return a reference to a hash + structure so as to support returning additional information + about a change log diff. + + Currently, VCSUtils::fixChangeLogPatch() returns a string that + represents the change log diff. Towards supporting the return + of additional information, such as whether the change log diff + inserts an entry at the top of the ChangeLog file, we need to + make VCSUtils::fixChangeLogPatch() return a reference to hash + structure. + + * Scripts/VCSUtils.pm: + - Modified fixChangeLogPatch() to return a reference to a + hash structure. + - Added documentation to fixChangeLogPatch(). + - Modified call site in mergeChangeLogs() as necessary. + * Scripts/svn-apply: + - Modified call site in patch() as necessary. + * Scripts/svn-create-patch: + - Modified call site in generateDiff() as necessary. + * Scripts/svn-unapply: + - Modified call site in patch() as necessary. + * Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl: + - Modified the unit tests as necessary. + +2010-10-05 Tony Chang <tony@chromium.org> + + Reviewed by Darin Adler. + + fix the link to the expected image on windows + https://bugs.webkit.org/show_bug.cgi?id=47228 + + * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: On + windows, the file must be opened in binary mode when writing + binary data. + +2010-10-05 Adam Barth <abarth@webkit.org> + + Update expected result of unittest to match Tony's change below. + + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-10-05 Tony Chang <tony@chromium.org> + + Reviewed by Ojan Vafai (over the shoulder). + + Paper over errors in image_diff so we don't crash the whole test run. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-10-05 Tony Chang <tony@chromium.org> + + Unreviewed, make shutil.rmtree more resiliant to errors + since windows was raising WindowsError: The process cannot access the file because it + is being used by another process. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-10-05 Tony Chang <tony@chromium.org> + + Reviewed by Ojan Vafai. + + [chromium] fix image diffing in NRWT + https://bugs.webkit.org/show_bug.cgi?id=47128 + + * Scripts/webkitpy/layout_tests/port/chromium.py: Stop using + NamedTemporaryFile since it doesn't work on Windows. + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-10-05 Kenneth Russell <kbr@google.com> + + Reviewed by Tony Chang. + + [chromium] Implement layerTreeAsText in DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=47216 + + Plumbed Frame::layerTreeAsText through Chromium's WebKit API to + make it callable from DumpRenderTree. + + No new tests; verified with existing compositor layout tests. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::layerTreeAsText): + * DumpRenderTree/chromium/LayoutTestController.h: + +2010-10-05 Brent Fulgham <bfulgham@webkit.org> + + Unreviewed build correction. + + * DumpRenderTree/win/ImageDiff.vcproj: Use WinCairo debug + property sheet so proper libraries are linked. + +2010-10-05 Robert Hogan <robert@webkit.org> + + Reviewed by Andreas Kling. + + [Qt] Fix url conversion in QWebHistory + + Converting from KURL to WFT::String to QUrl does not + permit proper percent encoding later. + + https://bugs.webkit.org/show_bug.cgi?id=47048 + + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::dumpHistoryItem): + +2010-10-05 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + REGRESSION (r68966?): All dumpAsText test fail on WebKit2 + https://bugs.webkit.org/show_bug.cgi?id=47188 + <rdar://problem/8514104> + + When constructing the std::string, use the real string length instead of the maximum buffer size. + + * TestWebKitAPI/PlatformUtilities.h: + (TestWebKitAPI::Util::toSTD): + * WebKitTestRunner/StringFunctions.h: + (WTR::toSTD): + +2010-10-04 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Add MIMEType accessor to WKFrame + <rdar://problem/8347683> + https://bugs.webkit.org/show_bug.cgi?id=47138 + + * TestWebKitAPI/PlatformUtilities.h: + (TestWebKitAPI::Util::toSTD): + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp: Added. + (TestWebKitAPI::didStartProvisionalLoadForFrame): + (TestWebKitAPI::didCommitLoadForFrame): + (TestWebKitAPI::didFinishLoadForFrame): + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp: Added. + (TestWebKitAPI::didStartProvisionalLoadForFrame): + (TestWebKitAPI::didCommitLoadForFrame): + (TestWebKitAPI::didFinishLoadForFrame): + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/basic-1.html: Removed. + * TestWebKitAPI/Tests/WebKit2/icon.png: Added. + * TestWebKitAPI/Tests/WebKit2/simple.html: Added. + * TestWebKitAPI/mac/PlatformUtilitiesMac.mm: + (TestWebKitAPI::Util::createURLForResource): + +2010-10-05 Gabor Rapcsanyi <rgabor@inf.u-szeged.hu> + + Reviewed by Ojan Vafai. + + [NRWT] Rename current_dir to current_group because it's not a directory + https://bugs.webkit.org/show_bug.cgi?id=47169 + + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-10-04 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + r69065 broke test-webkitpy by trying to create a '/tmp-X' directory, + which can't always be done. This test uses tempfile.mkdtemp(), which + should be safe. + + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-04 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Add missing "from __future__ import with_statement" that was + breaking test-webkitpy on the Leopard bots (broke in r69040). + + * Scripts/webkitpy/layout_tests/port/google_chrome.py: + +2010-10-04 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r69066. + http://trac.webkit.org/changeset/69066 + https://bugs.webkit.org/show_bug.cgi?id=47163 + + Made NRWT reliability worse. (Requested by tkent on #webkit). + + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-10-04 Gabor Rapcsanyi <rgabor@inf.u-szeged.hu> + + Reviewed by Tony Chang. + + [NRWT] Reverse the http tests to alphabetical order. + https://bugs.webkit.org/show_bug.cgi?id=47075 + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-10-04 Robert Hogan <robert@webkit.org> + + Reviewed by Andreas Kling. + + [Qt] Fix timeout on http/tests/navigation/post-goback2.html and postredirect-goback2.html + + We need to queue back and forward navigations in the DRT from the + LayoutTestController so that maybeDump() knows about them. + + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::queueBackNavigation): + (LayoutTestController::queueForwardNavigation): + +2010-10-04 Tony Chang <tony@chromium.org> + + Reviewed by Kent Tamura. + + [chromium] fix image diffing in NRWT + https://bugs.webkit.org/show_bug.cgi?id=47128 + + * Scripts/webkitpy/layout_tests/port/chromium.py: Flush data to the + temp file and check the image_diff error code more carefully + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-10-04 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Adam Barth. + + aroben's change in r68792 actually broke new-run-webkit-tests when + running the DRT code path. His change was intended to fix the + way we were converting windows paths to URIs when running under + Cygwin (the paths were getting one too many "/" on the front). + However, the change ended up breaking the chromium_win port, which + had slightly different logic. + + This patch removes the port-specific code and adds tests to make + sure we're getting the behavior we expect. The Port object no longer + exposes a get_absolute_path() method that can be used outside of + of converting test filenames, because it's unreliable otherwise + (we don't have the right context to know which conversion is intended). + + https://bugs.webkit.org/show_bug.cgi?id=47140 + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-04 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + Handle crash introduced in r69040 if we are not running in a + Chromium checkout. + + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + +2010-10-04 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Tony Chang. + + Add a way for us to have test expectations that are specific to the + official builds of Google Chrome (as opposed to Chromium). This change + looks for an additional "test_expectations_chrome.txt" file in + Chromium's repository (webkit/tools/layout_tests), and uses the + concatenation of that file and the regular test_expectations.txt + file for test overrides. + + https://bugs.webkit.org/show_bug.cgi?id=46854 + + * Scripts/webkitpy/layout_tests/port/google_chrome.py: + * Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py: + +2010-10-04 Simon Fraser <simon.fraser@apple.com> + + Color tests in the list based on existing pass/fail result. + + Fix the summary data to account for htmlOnly and nonHTML tests. + + * CSSTestSuiteHarness/harness/harness.css: + (#test-list > option.pass): + (#test-list > option.fail): + (#test-list > option.skipped): + * CSSTestSuiteHarness/harness/harness.js: + (Test): + (Test.prototype.statusForFormat): + (TestSuite.prototype.fillTestList): + (TestSuite.prototype.updateTestList): + (TestSuite.prototype.recordResult): + (TestSuite.prototype.markTestCompleted): + (TestSuite.prototype.countTestsWithFlag): + (TestSuite.prototype.queryDatabaseForSummary.this.db.transaction): + (TestSuite.prototype.queryDatabaseForSummary): + +2010-10-04 Chris Fleizach <cfleizach@apple.com> + + Reviewed by Beth Dakin. + + AX: doAXRangeForLine does not work + https://bugs.webkit.org/show_bug.cgi?id=47101 + + DRT support to handle NSAccessibilityRangeForLineParameterizedAttribute. + + * DumpRenderTree/AccessibilityUIElement.cpp: + (rangeForLineCallback): + (AccessibilityUIElement::rangeForLine): + (AccessibilityUIElement::getJSClass): + * DumpRenderTree/AccessibilityUIElement.h: + * DumpRenderTree/mac/AccessibilityUIElementMac.mm: + (AccessibilityUIElement::rangeForLine): + +2010-10-04 Andrey Kosyakov <caseq@chromium.org> + + Unreviewed. Adding myself to the committers list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-10-04 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Add ability to set the CacheModel in Webkit2 + https://bugs.webkit.org/show_bug.cgi?id=47066 + + * MiniBrowser/mac/AppDelegate.m: + (-[BrowserAppDelegate init]): Opt minibrowser into + a PrimaryWebBrowser cache model. + +2010-10-03 Simon Fraser <simon.fraser@apple.com> + + Make sure to enter all tests when creating the database + for the first time. + + When migrating to a new version of the suite, be sure to + sync up the database and testinfo.data by removing old + tests, and inserting new ones. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.openDatabase.creation): + (TestSuite.prototype.databaseCreated): + (TestSuite.prototype.populateDatabaseFromTestInfoData): + (TestSuite.prototype.insertTest): + +2010-10-03 Simon Fraser <simon.fraser@apple.com> + + More work on treating HTML4 and XHTML1 independently; when + changing the format, rebuild the test list, and update the + numbers in the chapter popup. + + * CSSTestSuiteHarness/harness/harness.js: + (Test): + (Test.prototype.runForFormat): + (Test.prototype.completedForFormat): + (ChapterSection): + (ChapterSection.prototype.countTests): + (Chapter): + (Chapter.prototype.description): + (Chapter.prototype.countTests): + (Chapter.prototype.testCount): + (Chapter.prototype.untestedCount): + (TestSuite.prototype.buildChapters): + (TestSuite.prototype.loadCurrentTest): + (TestSuite.prototype.updateProgressLabel): + (TestSuite.prototype.processFlags): + (TestSuite.prototype.formatChanged): + +2010-10-03 Simon Fraser <simon.fraser@apple.com> + + Update test suite version 20101001. + + Handle database migration, and delete tests from the db that are + not present in testinfo.data. + + Load about:blank into the test frame before the test url, to make + missing tests more obvious. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.loadTest): + (TestSuite.prototype.openDatabase.creation): + (TestSuite.prototype.openDatabase.migration1_0To1_1): + (TestSuite.prototype.openDatabase.if.return): + (TestSuite.prototype.databaseReady): + (TestSuite.prototype.populateDatabaseFromTestInfoData): + (TestSuite.prototype.syncDatabaseWithTestInfoData.this.db.transaction): + (TestSuite.prototype.syncDatabaseWithTestInfoData): + +2010-10-02 Simon Fraser <simon.fraser@apple.com> + + Add the ability to jump to a specific test. + + * CSSTestSuiteHarness/harness/harness.html: + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.goToTestByName): + (TestSuite.prototype.switchToFormat): + +2010-10-02 Simon Fraser <simon.fraser@apple.com> + + For a ref test, load the ref in the same format (HTML4 vs XHTML1) + as the test. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.loadRef): + +2010-10-02 Simon Fraser <simon.fraser@apple.com> + + Update the UI to reflect the fact that each test needs to be tested + in both HTML4 and XHTML1 format. + + * CSSTestSuiteHarness/harness/harness.js: + (Test): + (Chapter.prototype.description): + (Chapter.prototype.untestedCount): + (TestSuite.prototype.fillChapterPopup): + (TestSuite.prototype.updateChapterPopup): + (TestSuite.prototype.fillTestList): + (TestSuite.prototype.updateTestList): + (TestSuite.prototype.goToNextIncompleteTest): + (TestSuite.prototype.firstIncompleteTestIndex): + (TestSuite.prototype.recordResult): + (TestSuite.prototype.formatChanged): + (TestSuite.prototype.markTestCompleted): + (TestSuite.prototype.resetTestStatus): + +2010-10-01 Simon Fraser <simon.fraser@apple.com> + + Add the ability to remove results for re-testing, and + to import results. + + * CSSTestSuiteHarness/harness/harness.css: + (.custom button): + (#overlay): + (#overlay.visible): + (.overlay-contents): + (.overlay-contents textarea): + (.overlay-contents .buttons): + (.overlay-contents .note): + (.overlay-contents .buttons button): + * CSSTestSuiteHarness/harness/harness.html: + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.importResults): + (TestSuite.prototype.clearResults): + (TestSuite.prototype.markTestCompleted): + (TestSuite.prototype.resetTestStatus): + (TestSuite.prototype.storeTestResult): + (TestSuite.prototype.importTestResults): + (TestSuite.prototype.clearTestResults): + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Jon Honeycutt. + + Deploy the new WKString functions to remove most uses of CF from + the WebKitTestRunner. + + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::didReceiveMessage): + (WTR::InjectedBundle::done): + * WebKitTestRunner/StringFunctions.h: + (WTR::toWK): + (WTR::toJS): + (WTR::toSTD): + (WTR::operator<<): + (WTR::copyURLString): + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::resetStateToConsistentValues): + (WTR::TestController::didFinishLoadForFrame): + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::invoke): + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + +2010-10-01 Mihai Parparita <mihaip@chromium.org> + + Unreviewed TestResultsServer change. + + Add files introduced by http://crrev.com/61273 to the list of dashboard + files to update. + + * TestResultServer/handlers/dashboardhandler.py: + +2010-10-01 Brian Weinstein <bweinstein@apple.com> + + Build Fix for Windows. + + * WebKitTestRunner/win/WebKitTestRunner.vcproj: Don't copy ForwardingHeaders from + WebKitTestRunner/ForwardingHeaders, instead, add $(WebKitOutputDir)/include/WebCore/ + ForwardingHeaders to the include path. + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Add SPI to convert a WKStringRef to a JSStringRef and vice-versa. + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/Tests/WebKit2/WKString.cpp: + (TestWebKitAPI::TEST): + * TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp: Added. + (TestWebKitAPI::TEST): + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + Add additional WKString API + https://bugs.webkit.org/show_bug.cgi?id=46958 + + Add basic WKStringRef tests. + + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: + * TestWebKitAPI/Tests/WebKit2/WKString.cpp: Added. + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Add makefile for TestWebKitAPI and call it from the base makefile. + + * Makefile: + * TestWebKitAPI/Makefile: Added. + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Adam Roben. + + Remove unnecessary ForwardingHeaders from test runners. + https://bugs.webkit.org/show_bug.cgi?id=47010 + + * TestWebKitAPI/Configurations/Base.xcconfig: + * TestWebKitAPI/ForwardingHeaders: Removed. + * WebKitTestRunner/Configurations/Base.xcconfig: + * WebKitTestRunner/ForwardingHeaders: Removed. + +2010-09-30 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + WebSocket tests are flaky + https://bugs.webkit.org/show_bug.cgi?id=46956 + + Update these tools to understand how to run the WebSocket tests off the + Apache server. + + * Scripts/old-run-webkit-tests: + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-01 Adam Roben <aroben@apple.com> + + Encode Executive command arguments using UTF-8 on Cygwin + + Cygwin's Python's os.execv doesn't support unicode command arguments. + Cygwin's execv expects arguments to be encoded using the current code + page. But code pages are limited in what characters they can handle, + and our tests include characters that the English code page can't + handle. So for now we'll just encode everything in UTF-8 on Cygwin, + which can handle all characters but might confuse some commands, for + expediency's sake. I'm sure we'll run into cases where UTF-8 isn't + good enough, but we can deal with that when the problem arises. + + Reviewed by Adam Barth. + + Fixes <http://webkit.org/b/46892> <rdar://problem/8496639> + webkitpy.common.system.executive_unittest.ExecutiveTest.test_run_command_with_unicode + fails on Windows + + * Scripts/webkitpy/common/system/executive.py: + (Executive._run_command_with_teed_output): + (Executive.run_command): + On Cygwin, encode arguments using UTF-8. + +2010-10-01 Sam Weinig <sam@webkit.org> + + Reviewed by Adam Roben. + + Add simple API tester for WebKit2 + https://bugs.webkit.org/show_bug.cgi?id=46953 + + This adds a very simple testing infrastructure for testing APIs exposed + through the WebKit project. It consists of two parts: 1) a project that + builds the all the tests 2) a script that searches the tests directory and + calls the tester once for each test. + + This adds the infrastructure and two tests: + - Tests/WTF/Vector1.cpp - A proof of concept test of WTF data-structures. + - Tests/WebKit2/BasicTest1.cpp - A proof of concept test of WebKit2 API. + + This currently only works on the mac, but is designed to be easily ported + to any platform. + + * Scripts/run-api-tests: Added. + * Scripts/build-api-tests: Added. + Scripts to build/run the tests. + + * TestWebKitAPI: Added. + * TestWebKitAPI/Configurations: Added. + * TestWebKitAPI/Configurations/Base.xcconfig: Added. + * TestWebKitAPI/Configurations/DebugRelease.xcconfig: Added. + * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig: Added. + * TestWebKitAPI/ForwardingHeaders: Added. + * TestWebKitAPI/ForwardingHeaders/wtf: Added. + * TestWebKitAPI/PlatformUtilities.h: Added. + * TestWebKitAPI/PlatformWebView.h: Added. + (TestWebKitAPI::PlatformWebView::platformView): + * TestWebKitAPI/StringFunctions.h: Added. + * TestWebKitAPI/Test.h: Added. + (TestWebKitAPI::Test::~Test): + (TestWebKitAPI::Test::name): + (TestWebKitAPI::Test::Register::Register): + (TestWebKitAPI::Test::Register::create): + (TestWebKitAPI::Test::Test): + * TestWebKitAPI/TestWebKitAPI.xcodeproj: Added. + * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added. + * TestWebKitAPI/TestWebKitAPIPrefix.h: Added. + * TestWebKitAPI/TestsController.cpp: Added. + (TestWebKitAPI::TestsController::shared): + (TestWebKitAPI::TestsController::TestsController): + (TestWebKitAPI::TestsController::runTestNamed): + (TestWebKitAPI::TestsController::testFailed): + (TestWebKitAPI::TestsController::registerCreateTestFunction): + * TestWebKitAPI/TestsController.h: Added. + * TestWebKitAPI/mac: Added. + * TestWebKitAPI/mac/PlatformUtilitiesMac.mm: Added. + (TestWebKitAPI::Util::run): + (TestWebKitAPI::Util::createURLForResource): + * TestWebKitAPI/mac/PlatformWebViewMac.mm: Added. + (TestWebKitAPI::PlatformWebView::PlatformWebView): + (TestWebKitAPI::PlatformWebView::resizeTo): + (TestWebKitAPI::PlatformWebView::~PlatformWebView): + (TestWebKitAPI::PlatformWebView::page): + (TestWebKitAPI::PlatformWebView::focus): + * TestWebKitAPI/mac/main.mm: Added. + Infrastructure. + + * TestWebKitAPI/Tests: Added. + * TestWebKitAPI/Tests/WTF: Added. + * TestWebKitAPI/Tests/WTF/Vector1.cpp: Added. + * TestWebKitAPI/Tests/WebKit2: Added. + * TestWebKitAPI/Tests/WebKit2/BasicTest1.cpp: Added. + (TestWebKitAPI::State::State): + * TestWebKitAPI/Tests/WebKit2/basic-1.html: Added. + Proof of concept tests. + +2010-10-01 Adam Roben <aroben@apple.com> + + Don't assume AccessibleObjectFromEvent succeeds + + Fixes <http://webkit.org/b/44136> <rdar://problem/8321684> Crash in + DumpRenderTree!notificationListenerProc when running + plugins/access-after-page-destroyed.html + + Reviewed by Sam Weinig. + + * DumpRenderTree/win/AccessibilityControllerWin.cpp: + (notificationListenerProc): Check both the return value of + AccessibleObjectFromEvent and the object it returns, as MSDN + recommends. + +2010-10-01 Gabor Rapcsanyi <rgabor@inf.u-szeged.hu> + + Reviewed by Tony Chang. + + [NRWT] Put the http and websocket tests first in the test list. + https://bugs.webkit.org/show_bug.cgi?id=46453 + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-10-01 Fady Samuel <fsamuel@chromium.org> + + Unreviewed, adding myself to the committer list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-10-01 Adam Roben <aroben@apple.com> + + Test NPN_GetValue(NPNVnetscapeWindow) + + Test for <http://webkit.org/b/46726> <rdar://problem/8486319> + Right-clicking on windowless Flash plugin in WebKit2 makes a context + menu appear in the bottom-right corner of the screen + + Reviewed by Anders Carlsson. + + * DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp: + (PluginTest::NPN_GetValue): Added. Calls through to the browser. + + * DumpRenderTree/TestNetscapePlugIn/PluginTest.h: Added NPN_GetValue. + + * DumpRenderTree/TestNetscapePlugIn/Tests/win/GetValueNetscapeWindow.cpp: Added. + (GetValueNetscapeWindow::GetValueNetscapeWindow): Initialize members. + (GetValueNetscapeWindow::NPP_SetWindow): Test that + NPN_GetValue(NPNVnetscapeWindow) returns a valid HWND and that it + isn't our HWND. + + * DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj: + Added GetValueNetscapeWindow. + +2010-10-01 Andreas Kling <andreas.kling@nokia.com> + + Unreviewed, adding my webkit.org identity to reviewer list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-09-30 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + The WebSocket server should flush its logs + https://bugs.webkit.org/show_bug.cgi?id=46946 + + The WebSocket server logs are truncated because the driver just + terminates the child. It should run Python without buffering so we can + see the end of the log. + + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + +2010-09-30 Simon Fraser <simon.fraser@apple.com> + + Add a button to jump to the next untested test. + + * CSSTestSuiteHarness/harness/harness.css: + (.test-type): + (.name > button): + * CSSTestSuiteHarness/harness/harness.html: + * CSSTestSuiteHarness/harness/harness.js: + (Chapter.prototype.description): + (Chapter.prototype.untestedCount): + (TestSuite.prototype.testInfoDataLoaded): + (TestSuite.prototype.fillChapterPopup): + (TestSuite.prototype.updateChapterPopup): + (TestSuite.prototype.buildTestListForChapter): + (TestSuite.prototype.goToNextIncompleteTest): + (TestSuite.prototype.firstIncompleteTestIndex): + (TestSuite.prototype.testCompletionStateChanged): + +2010-09-29 Jon Honeycutt <jhoneycutt@apple.com> + + WebKit2 on Windows should use Windows fonts for the various standard + font families + https://bugs.webkit.org/show_bug.cgi?id=43499 + <rdar://problem/8272758> + + Reviewed by Adam Roben. + + * WebKitTestRunner/TestController.cpp: + (WTR::TestController::resetStateToConsistentValues): + Use the Mac fonts for running tests. This matches DRT behavior. + +2010-09-30 Adam Barth <abarth@webkit.org> + + Third attempt. We need a better integration test environment. + + * Scripts/webkitpy/common/net/failuremap.py: + * Scripts/webkitpy/common/net/failuremap_unittest.py: + +2010-09-30 Robert Hogan <robert@webkit.org> + + Reviewed by Andreas Kling. + + [Qt] Support for PlainTextController + + Unskip editing/text-iterator/basic-iteration.html + + https://bugs.webkit.org/show_bug.cgi?id=38805 + + * DumpRenderTree/qt/DumpRenderTree.pro: + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::DumpRenderTree::DumpRenderTree): + (WebCore::DumpRenderTree::initJSObjects): + * DumpRenderTree/qt/DumpRenderTreeQt.h: + * DumpRenderTree/qt/PlainTextControllerQt.cpp: Added. + (PlainTextController::PlainTextController): + (PlainTextController::plainText): + * DumpRenderTree/qt/PlainTextControllerQt.h: Added. + +2010-09-30 Adam Barth <abarth@webkit.org> + + Unreviewed. Second attempt to fix sheriffbot. + + * Scripts/webkitpy/common/net/buildbot.py: + +2010-09-30 Adam Barth <abarth@webkit.org> + + Unreviewed. + + This patch should stop the sheriffbot from throwing an exception. + + * Scripts/webkitpy/common/net/buildbot.py: + +2010-09-30 Brian Weinstein <bweinstein@apple.com> + + Reviewed by Adam Roben. + + The same bots shouldn't run both Windows Debug Tests and Windows Release Tests. + https://bugs.webkit.org/show_bug.cgi?id=46926 + + * BuildSlaveSupport/build.webkit.org-config/config.json: Have two bots running Windows + Release Tests, and two bots running Windows Debug Tests, instead of four running both. + +2010-09-30 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch find-flaky-tests should print results URLs + https://bugs.webkit.org/show_bug.cgi?id=46917 + + Printing out the results URL makes find-flaky-tests more actionable + because you can see what happens when a test fails. The output from + the script is still pretty noisy, but it seems useful. + + * Scripts/webkitpy/tool/commands/queries.py: + +2010-09-30 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Make 2D accelerated canvas rendering build on Mac + https://bugs.webkit.org/show_bug.cgi?id=46007 + + Added ACCELERATED_2D_CANVAS to build-webkit + + * Scripts/build-webkit: + +2010-09-29 Kenneth Russell <kbr@google.com> + + Reviewed by Dimitri Glazkov. + + [chromium] Add accelerated compositing support to DumpRenderTree and test_shell + https://bugs.webkit.org/show_bug.cgi?id=46849 + + Added offscreen code path for WebGraphicsContext3DDefaultImpl which + works with the compositor integration in both DumpRenderTree and + test_shell, since both pass a non-null WebCanvas* to WebViewImpl::paint + and thereby trigger the compositor's readback code path. Added support + for --enable-accelerated-compositing to DumpRenderTree. + + Tested in both test_shell and DumpRenderTree on Linux, the latter by + modifying a compositing layout test, dumping the pixels and verifying + that they matched the output when the compositor was active. + + * DumpRenderTree/chromium/DumpRenderTree.cpp: + (main): + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::TestShell): + (TestShell::resetWebSettings): + * DumpRenderTree/chromium/TestShell.h: + (TestShell::setAcceleratedCompositingEnabled): + * DumpRenderTree/chromium/WebPreferences.cpp: + (WebPreferences::reset): + (WebPreferences::applyTo): + * DumpRenderTree/chromium/WebPreferences.h: + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::scheduleComposite): + * DumpRenderTree/chromium/WebViewHost.h: + +2010-09-30 Adam Roben <aroben@apple.com> + + Ensure that QueueEngine cleans up its log files when its delegate + tells it to stop processing work + + Reviewed by Adam Barth. + + Fixes <http://webkit.org/b/46891> <rdar://problem/8496638> Many tests + in webkitpy.tool.bot.queueengine_unittest.QueueEngineTest crash on + Windows + + * Scripts/webkitpy/tool/bot/queueengine.py: + (QueueEngine.run): Stop ourselves normally (including cleaning up log + files) when the delegate tells us to stop processing work. + + * Scripts/webkitpy/tool/bot/queueengine_unittest.py: + (LoggingDelegate.__init__): Moved code here from + RaisingDelegate.__init__. + (LoggingDelegate.expeced_callbacks): Added the stop_work_queue + callback. + (LoggingDelegate.stop_work_queue): Moved here from RaisingDelegate. + (RaisingDelegate.__init__): Removed code that LoggingDelegate takes + care of for us now. + (QueueEngineTest.test_trivial): Make sure we got the expected stop + message. + (QueueEngineTest.test_not_safe_to_proceed): Changed to explicitly + remove the callbacks that are related to processing a single work + item, rather than removing all callbacks after a certain point, as + there are now more callbacks we expect to receive at the end. + +2010-09-30 Adam Roben <aroben@apple.com> + + Fix path -> URL conversion on Cygwin + + Reviewed by Adam Barth. + + Fixes <http://webkit.org/b/46890> <rdar://problem/8496637> Many tests + in webkitpy.layout_tests.run_webkit_tests_unittest assert on Windows + + * Scripts/webkitpy/layout_tests/port/base.py: + (Port.filename_to_uri): Treat Cygwin like other UNIX-y platforms by + assuming paths already have a leading slash. + +2010-09-30 Adam Roben <aroben@apple.com> + + Teach WindowGeometryInitializedBeforeSetWindow that NPP_SetWindow can + be called more than once + + The NPP_SetWindow call made when the plugin is torn down was confusing + us, and was causing us to spew an error into the next test. + + Fixes <http://webkit.org/b/46900> <rdar://problem/8496888> REGRESSION + (r68520): plugins/access-after-page-destroyed.html failing on Windows + + Reviewed by Anders Carlsson. + + * DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp: + (WindowGeometryInitializedBeforeSetWindow::WindowGeometryInitializedBeforeSetWindow): + Initialize member. + (WindowGeometryInitializedBeforeSetWindow::NPP_SetWindow): Bail if + this isn't the first time this is called. + +2010-09-30 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + webkit-patch upload warns that I'm using Xcode when I'm not + https://bugs.webkit.org/show_bug.cgi?id=46869 + + String.find returns -1 when not found, so switched to "in". + + * Scripts/webkitpy/common/system/user.py: + * Scripts/webkitpy/common/system/user_unittest.py: + +2010-09-30 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + webkit-patch failure-reason dies if non-trunk commits are in the blame range + https://bugs.webkit.org/show_bug.cgi?id=46866 + + I also made failure-reason use RegressionWindow in a cleaner way. + + * Scripts/webkitpy/tool/commands/queries.py: + +2010-09-29 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch find-flaky-tests + https://bugs.webkit.org/show_bug.cgi?id=46876 + + This command helps us find flaky tests so we can squash them. + + * Scripts/webkitpy/tool/commands/queries.py: + +2010-09-29 Simon Fraser <simon.fraser@apple.com> + + Fix export to use '?' instead of 'null' for + tests with no results. + + * CSSTestSuiteHarness/harness/harness.js: + +2010-09-29 Simon Fraser <simon.fraser@apple.com> + + Add a warning when a test requires special steps. + Add a Print Preview button for 'paged' tests that + brings up the print dialog, allowing the user to + judge paged media tests. + + * CSSTestSuiteHarness/harness/harness.css: + * CSSTestSuiteHarness/harness/harness.html: + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.loadTest): + (TestSuite.prototype.processFlags): + +2010-09-29 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Remove revisions_casuing_failures + https://bugs.webkit.org/show_bug.cgi?id=46872 + + This function exists only to be unit tested. + + * Scripts/webkitpy/common/net/failuremap.py: + * Scripts/webkitpy/common/net/failuremap_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-09-29 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + SheriffBot should post the list of failing tests to bugs + https://bugs.webkit.org/show_bug.cgi?id=46871 + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/failuremap.py: + * Scripts/webkitpy/common/net/regressionwindow.py: + * Scripts/webkitpy/tool/bot/sheriff.py: + * Scripts/webkitpy/tool/bot/sheriff_unittest.py: + * Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py: + * Scripts/webkitpy/tool/commands/queues_unittest.py: + * Scripts/webkitpy/tool/commands/sheriffbot.py: + * Scripts/webkitpy/tool/commands/sheriffbot_unittest.py: + * Scripts/webkitpy/tool/commands/upload_unittest.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-09-29 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Martin Robinson, Eric Seidel, and Mark Rowe. + + [WinCairo] Adds a build slave. + https://bugs.webkit.org/show_bug.cgi?id=46360 + + * BuildSlaveSupport/build.webkit.org-config/config.json: Add + entries for a debug build of the WinCairo port. + * BuildSlaveSupport/build.webkit.org-config/master.cfg: Add + platform flag to configuration for wincairo (like gtk, chromium, etc.) + * Scripts/build-webkit: Change 'cairo-win32' labeling to 'wincairo' + * Scripts/webkitdirs.pm: Change 'cairo-win32' labeling to 'wincairo' + +2010-09-29 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Move more SheriffBot smarts into FailureMap + https://bugs.webkit.org/show_bug.cgi?id=46703 + + This patch pushes the FailureMap model object further into the + SheriffBot machine. In addition, it moves a couple operations on this + object from SheriffBot itself to the model. + + Eventually, FailureMap will be the canonical context object for + SheriffBot operations. FailureMap represents a map of the current + failures on the bots that might require remediation. + + * Scripts/webkitpy/common/net/failuremap.py: + * Scripts/webkitpy/common/net/regressionwindow.py: + * Scripts/webkitpy/tool/commands/queries.py: + * Scripts/webkitpy/tool/commands/sheriffbot.py: + * Scripts/webkitpy/tool/mocktool.py: + +2010-09-29 Tony Chang <tony@chromium.org> + + Reviewed by James Robinson. + + [chromium] enable -Werror for DRT and webkit_unit_tests on Linux + https://bugs.webkit.org/show_bug.cgi?id=46829 + + * DumpRenderTree/chromium/DRTDevToolsClient.cpp: + (DRTDevToolsClient::DRTDevToolsClient): + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::TestShell): + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::postAccessibilityNotification): + (WebViewHost::WebViewHost): + +2010-09-29 Chris Fleizach <cfleizach@apple.com> + + Reviewed by Darin Adler. + + AX: implement CSS3 Speech "speak" + https://bugs.webkit.org/show_bug.cgi?id=46827 + + * DumpRenderTree/AccessibilityUIElement.cpp: + (speakCallback): + (AccessibilityUIElement::speak): + (AccessibilityUIElement::getJSClass): + * DumpRenderTree/AccessibilityUIElement.h: + * DumpRenderTree/mac/AccessibilityUIElementMac.mm: + (AccessibilityUIElement::speak): + +2010-09-29 Mihai Parparita <mihaip@chromium.org> + + Reviewed by Adam Barth. + + Record bot ID when updating queue status + https://bugs.webkit.org/show_bug.cgi?id=46764 + + Since we now have multiple bots handling patches from the commit queue, + we need to differentiate status updates from them, so that we can group + the queue status page in a less confusing way. + + * QueueStatusServer/handlers/updatestatus.py: Accept bot_id as input + * QueueStatusServer/model/queuestatus.py: Add bot_id property + * QueueStatusServer/templates/updatestatus.html: Add bot_id input + * Scripts/webkitpy/common/net/bugzilla_unittest.py: Extract MockBrowser + * Scripts/webkitpy/common/net/statusserver.py: Add bot_id + * Scripts/webkitpy/common/net/statusserver_unittest.py: Added. + * Scripts/webkitpy/tool/main.py: Add --bot-id + * Scripts/webkitpy/tool/mocktool.py: Add MockBrowser + +2010-09-29 Simon Fraser <simon.fraser@apple.com> + + No review. + + References always refert to a file in .xht format, even + for HTML tests, so fix their loading. + + * CSSTestSuiteHarness/harness/harness.js: + (TestSuite.prototype.loadRef): + 2010-09-28 Johnny Ding <jnd@chromium.org> Reviewed by Adam Barth. diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp index 13c642a..52d238d 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp +++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp @@ -128,6 +128,16 @@ static JSValueRef lineForIndexCallback(JSContextRef context, JSObjectRef functio return JSValueMakeNumber(context, toAXElement(thisObject)->lineForIndex(indexNumber)); } +static JSValueRef rangeForLineCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + int indexNumber = -1; + if (argumentCount == 1) + indexNumber = JSValueToNumber(context, arguments[0], exception); + + JSRetainPtr<JSStringRef> rangeLine(Adopt, toAXElement(thisObject)->rangeForLine(indexNumber)); + return JSValueMakeString(context, rangeLine.get()); +} + static JSValueRef boundsForRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { unsigned location = UINT_MAX, length = 0; @@ -679,6 +689,12 @@ static JSValueRef isIgnoredCallback(JSContextRef context, JSObjectRef thisObject return JSValueMakeBoolean(context, toAXElement(thisObject)->isIgnored()); } +static JSValueRef speakCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + JSRetainPtr<JSStringRef> speakString(Adopt, toAXElement(thisObject)->speak()); + return JSValueMakeString(context, speakString.get()); +} + static JSValueRef getHasPopupCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) { return JSValueMakeBoolean(context, toAXElement(thisObject)->hasPopup()); @@ -737,6 +753,12 @@ static JSValueRef removeNotificationListenerCallback(JSContextRef context, JSObj // Implementation +// Unsupported methods on various platforms. +#if !PLATFORM(MAC) +JSStringRef AccessibilityUIElement::speak() { return 0; } +JSStringRef AccessibilityUIElement::rangeForLine(int line) { return 0; } +#endif + #if !SUPPORTS_AX_TEXTMARKERS AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement*) @@ -837,6 +859,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "ariaIsGrabbed", getARIAIsGrabbedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "ariaDropEffects", getARIADropEffectsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isIgnored", isIgnoredCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "speak", speakCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0, 0 } }; @@ -847,6 +870,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "attributesOfChildren", attributesOfChildrenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "parameterizedAttributeNames", parameterizedAttributeNamesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "lineForIndex", lineForIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "rangeForLine", rangeForLineCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "boundsForRange", boundsForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "stringForRange", stringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributedStringForRange", attributedStringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h index 5170f20..9311dfd 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h +++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h @@ -147,6 +147,9 @@ public: JSStringRef documentURI(); JSStringRef url(); + // CSS3-speech properties. + JSStringRef speak(); + // Table-specific attributes JSStringRef attributesOfColumnHeaders(); JSStringRef attributesOfRowHeaders(); @@ -176,6 +179,7 @@ public: // Parameterized attributes int lineForIndex(int); + JSStringRef rangeForLine(int); JSStringRef boundsForRange(unsigned location, unsigned length); void setSelectedTextRange(unsigned location, unsigned length); JSStringRef stringForRange(unsigned location, unsigned length); diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.gypi b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi index 58ccaae..b437eaf 100644 --- a/WebKitTools/DumpRenderTree/DumpRenderTree.gypi +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.gypi @@ -44,6 +44,20 @@ 'chromium/WebViewHost.cpp', 'chromium/WebViewHost.h', ], + 'test_plugin_files': [ + 'TestNetscapePlugIn/PluginObject.cpp', + 'TestNetscapePlugIn/PluginObject.h', + 'TestNetscapePlugIn/PluginObjectMac.mm', + 'TestNetscapePlugIn/PluginTest.cpp', + 'TestNetscapePlugIn/PluginTest.h', + 'TestNetscapePlugIn/TestObject.cpp', + 'TestNetscapePlugIn/TestObject.h', + 'TestNetscapePlugIn/Tests/DocumentOpenInDestroyStream.cpp', + 'TestNetscapePlugIn/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp', + 'TestNetscapePlugIn/Tests/NPRuntimeRemoveProperty.cpp', + 'TestNetscapePlugIn/Tests/PluginScriptableNPObjectInvokeDefault.cpp', + 'TestNetscapePlugIn/main.cpp', + ], 'conditions': [ ['OS=="win"', { 'drt_files': [ diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj index c01ca4e..51d8e7f 100644 --- a/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 29CFBA2E12273A1000BC30C0 /* AccessibilityTextMarkerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29CFBA2D12273A1000BC30C0 /* AccessibilityTextMarkerMac.mm */; }; 3713EDE2115BE19300705720 /* ColorBits-A.png in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 3713EDDF115BE16F00705720 /* ColorBits-A.png */; }; 3713EDE3115BE19300705720 /* ColorBits.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 3713EDE0115BE16F00705720 /* ColorBits.ttf */; }; + 4437730E125CBC3600AAE02C /* WebArchiveDumpSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44A997830FCDE86400580F10 /* WebArchiveDumpSupport.mm */; }; + 4437730F125CBC4D00AAE02C /* WebArchiveDumpSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */; }; 5185F6B210714E07007AA393 /* HistoryDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5185F69F10714A57007AA393 /* HistoryDelegate.mm */; }; 5185F6B310714E12007AA393 /* HistoryDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5185F69E10714A57007AA393 /* HistoryDelegate.h */; }; 5DB9AC970F722C3600684641 /* AHEM____.TTF in Copy Font Files */ = {isa = PBXBuildFile; fileRef = AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */; }; @@ -128,6 +130,7 @@ BCD08B3A0E1057EF00A7D0C1 /* AccessibilityController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD08B390E1057EF00A7D0C1 /* AccessibilityController.cpp */; }; BCD08B710E1059D200A7D0C1 /* AccessibilityControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCD08B700E1059D200A7D0C1 /* AccessibilityControllerMac.mm */; }; BCF6C6500C98E9C000AC063E /* GCController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCF6C64F0C98E9C000AC063E /* GCController.cpp */; }; + C06F9ABC1267A7060058E1F6 /* PassDifferentNPPStruct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C06F9ABB1267A7060058E1F6 /* PassDifferentNPPStruct.cpp */; }; E1B7816511AF31B7007E1BC2 /* MockGeolocationProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1B7808711AF1669007E1BC2 /* MockGeolocationProvider.mm */; }; E1B7816711AF31C3007E1BC2 /* MockGeolocationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B7808511AF1643007E1BC2 /* MockGeolocationProvider.h */; }; /* End PBXBuildFile section */ @@ -220,6 +223,8 @@ 375F09770DAC3CB600C8B4E5 /* WebKitWeightWatcher700.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher700.ttf; path = fonts/WebKitWeightWatcher700.ttf; sourceTree = "<group>"; }; 375F09780DAC3CB600C8B4E5 /* WebKitWeightWatcher800.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher800.ttf; path = fonts/WebKitWeightWatcher800.ttf; sourceTree = "<group>"; }; 375F09790DAC3CB600C8B4E5 /* WebKitWeightWatcher900.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher900.ttf; path = fonts/WebKitWeightWatcher900.ttf; sourceTree = "<group>"; }; + 44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebArchiveDumpSupport.h; path = mac/WebArchiveDumpSupport.h; sourceTree = "<group>"; }; + 44A997830FCDE86400580F10 /* WebArchiveDumpSupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebArchiveDumpSupport.mm; path = mac/WebArchiveDumpSupport.mm; sourceTree = "<group>"; }; 5185F69E10714A57007AA393 /* HistoryDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryDelegate.h; path = mac/HistoryDelegate.h; sourceTree = "<group>"; }; 5185F69F10714A57007AA393 /* HistoryDelegate.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = HistoryDelegate.mm; path = mac/HistoryDelegate.mm; sourceTree = "<group>"; }; 8465E2C60FFA8DF2003B8342 /* PixelDumpSupport.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = PixelDumpSupport.cpp; sourceTree = "<group>"; }; @@ -298,6 +303,7 @@ BCD08B390E1057EF00A7D0C1 /* AccessibilityController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityController.cpp; sourceTree = "<group>"; }; BCD08B700E1059D200A7D0C1 /* AccessibilityControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AccessibilityControllerMac.mm; path = mac/AccessibilityControllerMac.mm; sourceTree = "<group>"; }; BCF6C64F0C98E9C000AC063E /* GCController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = GCController.cpp; sourceTree = "<group>"; }; + C06F9ABB1267A7060058E1F6 /* PassDifferentNPPStruct.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PassDifferentNPPStruct.cpp; sourceTree = "<group>"; }; E1B7808511AF1643007E1BC2 /* MockGeolocationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MockGeolocationProvider.h; path = mac/MockGeolocationProvider.h; sourceTree = "<group>"; }; E1B7808711AF1669007E1BC2 /* MockGeolocationProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MockGeolocationProvider.mm; path = mac/MockGeolocationProvider.mm; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -358,6 +364,8 @@ BCA18B740C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm */, A8D79CE80FC28B2C004AC8FE /* DumpRenderTreeFileDraggingSource.h */, A8D79CE90FC28B2C004AC8FE /* DumpRenderTreeFileDraggingSource.m */, + 44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */, + 44A997830FCDE86400580F10 /* WebArchiveDumpSupport.mm */, BC9D90210C97472D0099A4A3 /* WorkQueue.cpp */, BC9D90220C97472E0099A4A3 /* WorkQueue.h */, BC9D90230C97472E0099A4A3 /* WorkQueueItem.h */, @@ -451,6 +459,7 @@ 1A215A7511F26072008AD0F5 /* DocumentOpenInDestroyStream.cpp */, 1A24BAA8120734EE00FBB059 /* NPRuntimeObjectFromDestroyedPlugin.cpp */, 1AC77DCE120605B6005C19EF /* NPRuntimeRemoveProperty.cpp */, + C06F9ABB1267A7060058E1F6 /* PassDifferentNPPStruct.cpp */, 1AD9D2FD12028409001A70D1 /* PluginScriptableNPObjectInvokeDefault.cpp */, ); path = Tests; @@ -590,6 +599,7 @@ BCA18B670C9B08C200114369 /* ResourceLoadDelegate.h in Headers */, BCA18B3C0C9B024900114369 /* TextInputController.h in Headers */, BCA18B690C9B08C200114369 /* UIDelegate.h in Headers */, + 4437730F125CBC4D00AAE02C /* WebArchiveDumpSupport.h in Headers */, BC9D90250C97472E0099A4A3 /* WorkQueue.h in Headers */, BC9D90260C97472E0099A4A3 /* WorkQueueItem.h in Headers */, 5185F6B310714E12007AA393 /* HistoryDelegate.h in Headers */, @@ -726,6 +736,7 @@ 1AD9D2FE12028409001A70D1 /* PluginScriptableNPObjectInvokeDefault.cpp in Sources */, 1AC77DCF120605B6005C19EF /* NPRuntimeRemoveProperty.cpp in Sources */, 1A24BAA9120734EE00FBB059 /* NPRuntimeObjectFromDestroyedPlugin.cpp in Sources */, + C06F9ABC1267A7060058E1F6 /* PassDifferentNPPStruct.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -764,6 +775,7 @@ BCA18B680C9B08C200114369 /* ResourceLoadDelegate.mm in Sources */, BCA18B490C9B02C400114369 /* TextInputController.m in Sources */, BCA18B6A0C9B08C200114369 /* UIDelegate.mm in Sources */, + 4437730E125CBC3600AAE02C /* WebArchiveDumpSupport.mm in Sources */, BC9D90240C97472E0099A4A3 /* WorkQueue.cpp in Sources */, BCA18B260C9B015C00114369 /* WorkQueueItemMac.mm in Sources */, 5185F6B210714E07007AA393 /* HistoryDelegate.mm in Sources */, diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp index ee44325..b5cc874 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -1219,6 +1219,7 @@ static JSValueRef setXSSAuditorEnabledCallback(JSContextRef context, JSObjectRef static JSValueRef setSpatialNavigationEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { + // Has mac implementation. if (argumentCount < 1) return JSValueMakeUndefined(context); @@ -1722,6 +1723,19 @@ static JSValueRef abortModalCallback(JSContextRef context, JSObjectRef function, return JSValueMakeUndefined(context); } +static JSValueRef hasSpellingMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount != 2) + return JSValueMakeUndefined(context); + + int from = JSValueToNumber(context, arguments[0], 0); + int length = JSValueToNumber(context, arguments[1], 0); + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + bool ok = controller->hasSpellingMarker(from, length); + + return JSValueMakeBoolean(context, ok); +} + static JSValueRef markerTextForListItemCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); @@ -1890,6 +1904,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "counterValueForElementById", counterValueForElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "grantDesktopNotificationPermission", grantDesktopNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "hasSpellingMarker", hasSpellingMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isPageBoxVisible", isPageBoxVisibleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h index 755a2b2..689e114 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -279,6 +279,8 @@ public: void abortModal(); + bool hasSpellingMarker(int from, int length); + // The following API test functions should probably be moved to platform-specific // unit tests outside of DRT once they exist. void apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp index 83eda3a..d435a2e 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp @@ -75,6 +75,11 @@ NPIdentifier PluginTest::NPN_GetIntIdentifier(int32_t intid) return browser->getintidentifier(intid); } +NPError PluginTest::NPN_GetValue(NPNVariable variable, void* value) +{ + return browser->getvalue(m_npp, variable, value); +} + NPObject* PluginTest::NPN_CreateObject(NPClass* npClass) { return browser->createobject(m_npp, npClass); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h index 2e896a6..cbc7934 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h @@ -62,6 +62,7 @@ public: // NPN functions. NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name); NPIdentifier NPN_GetIntIdentifier(int32_t intid); + NPError NPN_GetValue(NPNVariable, void* value); NPObject* NPN_CreateObject(NPClass*); bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp new file mode 100644 index 0000000..e464996 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp @@ -0,0 +1,70 @@ +/* + * 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; + +// Passing a different NPP struct that has the same ndata value as the one passed to NPP_New should +// not trigger an assertion failure. + +class PassDifferentNPPStruct : public PluginTest { +public: + PassDifferentNPPStruct(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_didReceiveInitialSetWindowCall(false) + { + } + +private: + virtual NPError NPP_SetWindow(NPP instance, NPWindow* window) + { + if (m_didReceiveInitialSetWindowCall) + return NPERR_NO_ERROR; + m_didReceiveInitialSetWindowCall = true; + + NPP oldNPP = m_npp; + NPP_t differentNPP = *m_npp; + m_npp = &differentNPP; + + NPBool privateMode; + NPError error = NPN_GetValue(NPNVprivateModeBool, &privateMode); + + m_npp = oldNPP; + + if (error != NPERR_NO_ERROR) { + pluginLog(instance, "NPN_GetValue(NPNVprivateModeBool) with a different NPP struct failed with error %d", error); + return NPERR_GENERIC_ERROR; + } + pluginLog(instance, "NPN_GetValue(NPNVprivateModeBool) with a different NPP struct succeeded"); + return NPERR_NO_ERROR; + } + + bool m_didReceiveInitialSetWindowCall; +}; + +static PluginTest::Register<PassDifferentNPPStruct> getValueNetscapeWindow("pass-different-npp-struct"); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/GetValueNetscapeWindow.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/GetValueNetscapeWindow.cpp new file mode 100644 index 0000000..32fd99b --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/GetValueNetscapeWindow.cpp @@ -0,0 +1,73 @@ +/* + * 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; + +// NPN_GetValue(NPNVnetscapeWindow) should return a valid HWND. + +class GetValueNetscapeWindow : public PluginTest { +public: + GetValueNetscapeWindow(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_didReceiveInitialSetWindowCall(false) + { + } + +private: + virtual NPError NPP_SetWindow(NPP instance, NPWindow* window) + { + if (m_didReceiveInitialSetWindowCall) + return NPERR_NO_ERROR; + m_didReceiveInitialSetWindowCall = true; + + HWND hwnd; + NPError error = NPN_GetValue(NPNVnetscapeWindow, &hwnd); + if (error != NPERR_NO_ERROR) { + pluginLog(instance, "NPN_GetValue(NPNVnetscapeWindow) failed with error %d", error); + return NPERR_GENERIC_ERROR; + } + + if (!::IsWindow(hwnd)) { + pluginLog(instance, "::IsWindow returned FALSE"); + return NPERR_GENERIC_ERROR; + } + + if (hwnd == window->window) { + pluginLog(instance, "NPN_GetValue(NPNVnetscapeWindow) returned the same value as NPWindow::window"); + return NPERR_GENERIC_ERROR; + } + + pluginLog(instance, "NPN_GetValue(NPNVnetscapeWindow) succeeded"); + return NPERR_NO_ERROR; + } + + bool m_didReceiveInitialSetWindowCall; +}; + +static PluginTest::Register<GetValueNetscapeWindow> getValueNetscapeWindow("get-value-netscape-window"); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp index 40bceb9..8054497 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/Tests/win/WindowGeometryInitializedBeforeSetWindow.cpp @@ -35,12 +35,17 @@ class WindowGeometryInitializedBeforeSetWindow : public PluginTest { public: WindowGeometryInitializedBeforeSetWindow(NPP npp, const string& identifier) : PluginTest(npp, identifier) + , m_didReceiveInitialSetWindowCall(false) { } private: virtual NPError NPP_SetWindow(NPP instance, NPWindow* window) { + if (m_didReceiveInitialSetWindowCall) + return NPERR_NO_ERROR; + m_didReceiveInitialSetWindowCall = true; + if (window->type != NPWindowTypeWindow) { pluginLog(instance, "window->type should be NPWindowTypeWindow but was %d", window->type); return NPERR_GENERIC_ERROR; @@ -77,7 +82,9 @@ private: pluginLog(instance, "Plugin's HWND has been sized and positioned before NPP_SetWindow was called"); return NPERR_NO_ERROR; - } + } + + bool m_didReceiveInitialSetWindowCall; }; 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 dd894f4..e240c42 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/main.cpp @@ -75,7 +75,7 @@ NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) { getEntryPointsWasCalled = true; -#if XP_MACOSX +#ifdef XP_MACOSX // Simulate Silverlight's behavior of crashing when NP_GetEntryPoints is called before NP_Initialize. if (!initializeWasCalled) CRASH(); @@ -111,7 +111,7 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc { bool forceCarbon = false; -#if XP_MACOSX +#ifdef XP_MACOSX NPEventModel eventModel; // Always turn on the CG model @@ -158,7 +158,7 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); instance->pdata = obj; -#if XP_MACOSX +#ifdef XP_MACOSX obj->eventModel = eventModel; #if !defined(BUILDING_ON_TIGER) obj->coreAnimationLayer = 0; @@ -198,7 +198,7 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc else if (strcasecmp(argn[i], "testwindowopen") == 0) obj->testWindowOpen = TRUE; else if (strcasecmp(argn[i], "drawingmodel") == 0) { -#if XP_MACOSX && !defined(BUILDING_ON_TIGER) +#if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER) const char* value = argv[i]; if (strcasecmp(value, "coreanimation") == 0) { if (supportsCoreAnimation) @@ -234,7 +234,7 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc } } -#if XP_MACOSX +#ifdef XP_MACOSX browser->setvalue(instance, NPPVpluginDrawingModel, (void *)drawingModelToUse); #if !defined(BUILDING_ON_TIGER) if (drawingModelToUse == NPDrawingModelCoreAnimation) @@ -276,7 +276,7 @@ NPError NPP_Destroy(NPP instance, NPSavedData **save) if (obj->logDestroy) pluginLog(instance, "NPP_Destroy"); -#if XP_MACOSX && !defined(BUILDING_ON_TIGER) +#if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER) if (obj->coreAnimationLayer) CFRelease(obj->coreAnimationLayer); #endif @@ -400,7 +400,7 @@ void NPP_Print(NPP instance, NPPrint *platformPrint) { } -#if XP_MACOSX +#ifdef XP_MACOSX #ifndef NP_NO_CARBON static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* event) { @@ -462,13 +462,13 @@ static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* e pluginLog(instance, "kHighLevelEvent"); break; // NPAPI events - case getFocusEvent: + case NPEventType_GetFocusEvent: pluginLog(instance, "getFocusEvent"); break; - case loseFocusEvent: + case NPEventType_LoseFocusEvent: pluginLog(instance, "loseFocusEvent"); break; - case adjustCursorEvent: + case NPEventType_AdjustCursorEvent: pluginLog(instance, "adjustCursorEvent"); break; default: @@ -548,7 +548,7 @@ int16_t NPP_HandleEvent(NPP instance, void *event) if (!obj->eventLogging) return 0; -#if XP_MACOSX +#ifdef XP_MACOSX #ifndef NP_NO_CARBON if (obj->eventModel == NPEventModelCarbon) return handleEventCarbon(instance, obj, static_cast<EventRecord*>(event)); @@ -588,7 +588,7 @@ NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) return NPERR_NO_ERROR; } -#if XP_MACOSX && !defined(BUILDING_ON_TIGER) +#if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER) if (variable == NPPVpluginCoreAnimationLayer) { if (!obj->coreAnimationLayer) return NPERR_GENERIC_ERROR; diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj index 5ffb832..cdd7729 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn/win/TestNetscapePlugin.vcproj @@ -383,6 +383,10 @@ >
</File>
<File
+ RelativePath="..\Tests\PassDifferentNPPStruct.cpp"
+ >
+ </File>
+ <File
RelativePath="..\Tests\PluginScriptableNPObjectInvokeDefault.cpp"
>
</File>
@@ -390,6 +394,10 @@ Name="win"
>
<File
+ RelativePath="..\Tests\win\GetValueNetscapeWindow.cpp"
+ >
+ </File>
+ <File
RelativePath="..\Tests\win\WindowGeometryInitializedBeforeSetWindow.cpp"
>
</File>
diff --git a/WebKitTools/DumpRenderTree/chromium/AccessibilityController.cpp b/WebKitTools/DumpRenderTree/chromium/AccessibilityController.cpp index 2487e1a..5601d9d 100644 --- a/WebKitTools/DumpRenderTree/chromium/AccessibilityController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/AccessibilityController.cpp @@ -32,11 +32,11 @@ #include "AccessibilityController.h" #include "TestShell.h" -#include "public/WebAccessibilityCache.h" -#include "public/WebAccessibilityObject.h" -#include "public/WebFrame.h" -#include "public/WebString.h" -#include "public/WebView.h" +#include "WebAccessibilityCache.h" +#include "WebAccessibilityObject.h" +#include "WebFrame.h" +#include "WebString.h" +#include "WebView.h" using namespace WebKit; diff --git a/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.cpp b/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.cpp index 8698e25..dbd025a 100644 --- a/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.cpp +++ b/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "AccessibilityUIElement.h" -#include "public/WebAccessibilityObject.h" -#include "public/WebCString.h" -#include "public/WebString.h" +#include "WebAccessibilityObject.h" +#include "WebCString.h" +#include "WebString.h" #include <wtf/Assertions.h> using namespace WebKit; diff --git a/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.h b/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.h index df3f5b9..366ed42 100644 --- a/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.h +++ b/WebKitTools/DumpRenderTree/chromium/AccessibilityUIElement.h @@ -32,7 +32,7 @@ #define AccessibilityUIElement_h #include "CppBoundClass.h" -#include "public/WebAccessibilityObject.h" +#include "WebAccessibilityObject.h" #include <wtf/Vector.h> class AccessibilityUIElement : public CppBoundClass { diff --git a/WebKitTools/DumpRenderTree/chromium/CppBoundClass.cpp b/WebKitTools/DumpRenderTree/chromium/CppBoundClass.cpp index 839787a..1348bbf 100644 --- a/WebKitTools/DumpRenderTree/chromium/CppBoundClass.cpp +++ b/WebKitTools/DumpRenderTree/chromium/CppBoundClass.cpp @@ -42,9 +42,9 @@ #include "config.h" #include "CppBoundClass.h" -#include "public/WebBindings.h" -#include "public/WebFrame.h" -#include "public/WebString.h" +#include "WebBindings.h" +#include "WebFrame.h" +#include "WebString.h" #include <wtf/Assertions.h> #include <wtf/OwnPtr.h> diff --git a/WebKitTools/DumpRenderTree/chromium/CppVariant.cpp b/WebKitTools/DumpRenderTree/chromium/CppVariant.cpp index 9539907..22e0013 100644 --- a/WebKitTools/DumpRenderTree/chromium/CppVariant.cpp +++ b/WebKitTools/DumpRenderTree/chromium/CppVariant.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "CppVariant.h" -#include "public/WebBindings.h" +#include "WebBindings.h" #include <limits> #include <wtf/Assertions.h> #include <wtf/StringExtras.h> diff --git a/WebKitTools/DumpRenderTree/chromium/CppVariant.h b/WebKitTools/DumpRenderTree/chromium/CppVariant.h index 3aa5abb..3032310 100644 --- a/WebKitTools/DumpRenderTree/chromium/CppVariant.h +++ b/WebKitTools/DumpRenderTree/chromium/CppVariant.h @@ -42,7 +42,7 @@ #ifndef CppVariant_h #define CppVariant_h -#include "public/WebBindings.h" +#include "WebBindings.h" #include "webkit/support/webkit_support.h" #include <string> #include <wtf/Vector.h> diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp index a9a891b..78c86e7 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp @@ -34,10 +34,10 @@ #include "DRTDevToolsCallArgs.h" #include "DRTDevToolsClient.h" -#include "public/WebCString.h" -#include "public/WebDevToolsAgent.h" -#include "public/WebString.h" -#include "public/WebView.h" +#include "WebCString.h" +#include "WebDevToolsAgent.h" +#include "WebString.h" +#include "WebView.h" #include "webkit/support/webkit_support.h" using namespace WebKit; diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h index c988fa1..e1478d0 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h @@ -33,7 +33,7 @@ #include "DRTDevToolsCallArgs.h" #include "Task.h" -#include "public/WebDevToolsAgentClient.h" +#include "WebDevToolsAgentClient.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h index b1ac2ec..a548159 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h @@ -31,7 +31,7 @@ #ifndef DRTDevToolsCallArgs_h #define DRTDevToolsCallArgs_h -#include "public/WebString.h" +#include "WebString.h" #include <wtf/Assertions.h> class DRTDevToolsCallArgs { diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp index a53f0db..acccf18 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp @@ -34,19 +34,19 @@ #include "DRTDevToolsAgent.h" #include "DRTDevToolsCallArgs.h" -#include "public/WebDevToolsAgent.h" -#include "public/WebDevToolsFrontend.h" -#include "public/WebFrame.h" -#include "public/WebScriptSource.h" -#include "public/WebString.h" -#include "public/WebView.h" +#include "WebDevToolsAgent.h" +#include "WebDevToolsFrontend.h" +#include "WebFrame.h" +#include "WebScriptSource.h" +#include "WebString.h" +#include "WebView.h" #include "webkit/support/webkit_support.h" using namespace WebKit; DRTDevToolsClient::DRTDevToolsClient(DRTDevToolsAgent* agent, WebView* webView) - : m_drtDevToolsAgent(agent) - , m_webView(webView) + : m_webView(webView) + , m_drtDevToolsAgent(agent) { m_webDevToolsFrontend.set(WebDevToolsFrontend::create(m_webView, this, diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h index f7c8fbf..9ca1402 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h @@ -33,7 +33,7 @@ #include "DRTDevToolsCallArgs.h" #include "Task.h" -#include "public/WebDevToolsFrontendClient.h" +#include "WebDevToolsFrontendClient.h" #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> diff --git a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp index b2e50f7..72c0c3c 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 optionEnableAcceleratedCompositing[] = "--enable-accelerated-compositing"; static const char optionEnableAccelerated2DCanvas[] = "--enable-accelerated-2d-canvas"; static void runTest(TestShell& shell, TestParams& params, const string& testName, bool testShellMode) @@ -93,6 +94,7 @@ int main(int argc, char* argv[]) bool testShellMode = false; bool allowExternalPages = false; bool startupDialog = false; + bool acceleratedCompositingEnabled = false; bool accelerated2DCanvasEnabled = false; for (int i = 1; i < argc; ++i) { string argument(argv[i]); @@ -114,6 +116,8 @@ int main(int argc, char* argv[]) startupDialog = true; else if (argument == optionCheckLayoutTestSystemDeps) exit(checkLayoutTestSystemDependencies() ? EXIT_SUCCESS : EXIT_FAILURE); + else if (argument == optionEnableAcceleratedCompositing) + acceleratedCompositingEnabled = true; else if (argument == optionEnableAccelerated2DCanvas) accelerated2DCanvasEnabled = true; else if (argument.size() && argument[0] == '-') @@ -132,6 +136,7 @@ int main(int argc, char* argv[]) { // Explicit scope for the TestShell instance. TestShell shell(testShellMode); shell.setAllowExternalPages(allowExternalPages); + shell.setAcceleratedCompositingEnabled(acceleratedCompositingEnabled); shell.setAccelerated2dCanvasEnabled(accelerated2DCanvasEnabled); if (serverMode && !tests.size()) { params.printSeparators = true; diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp index 5f51553..e250dfc 100644 --- a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp +++ b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp @@ -44,18 +44,18 @@ #include "EventSender.h" #include "TestShell.h" -#include "public/WebDragData.h" -#include "public/WebDragOperation.h" -#include "public/WebPoint.h" -#include "public/WebString.h" -#include "public/WebTouchPoint.h" -#include "public/WebView.h" +#include "WebDragData.h" +#include "WebDragOperation.h" +#include "WebPoint.h" +#include "WebString.h" +#include "WebTouchPoint.h" +#include "WebView.h" #include "webkit/support/webkit_support.h" #include <wtf/Deque.h> #include <wtf/StringExtras.h> #if OS(WINDOWS) -#include "public/win/WebInputEventFactory.h" +#include "win/WebInputEventFactory.h" #endif // FIXME: layout before each event? @@ -779,7 +779,7 @@ void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVarian currentDragData.initialize(); Vector<string> files = arguments[0].toStringVector(); for (size_t i = 0; i < files.size(); ++i) - currentDragData.appendToFileNames(webkit_support::GetAbsoluteWebStringFromUTF8Path(files[i])); + currentDragData.appendToFilenames(webkit_support::GetAbsoluteWebStringFromUTF8Path(files[i])); currentDragEffectsAllowed = WebKit::WebDragOperationCopy; // Provide a drag source. diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.h b/WebKitTools/DumpRenderTree/chromium/EventSender.h index 399a132..118509b 100644 --- a/WebKitTools/DumpRenderTree/chromium/EventSender.h +++ b/WebKitTools/DumpRenderTree/chromium/EventSender.h @@ -39,9 +39,9 @@ #include "CppBoundClass.h" #include "Task.h" -#include "public/WebDragOperation.h" -#include "public/WebInputEvent.h" -#include "public/WebPoint.h" +#include "WebDragOperation.h" +#include "WebInputEvent.h" +#include "WebPoint.h" class TestShell; diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp index 3d3c204..82fd085 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp @@ -34,27 +34,27 @@ #include "DRTDevToolsAgent.h" #include "TestShell.h" +#include "WebAnimationController.h" +#include "WebBindings.h" +#include "WebConsoleMessage.h" +#include "WebData.h" +#include "WebDeviceOrientation.h" +#include "WebDeviceOrientationClientMock.h" +#include "WebDocument.h" +#include "WebElement.h" +#include "WebFrame.h" +#include "WebGeolocationServiceMock.h" +#include "WebInputElement.h" +#include "WebKit.h" +#include "WebNotificationPresenter.h" +#include "WebScriptSource.h" +#include "WebSecurityPolicy.h" +#include "WebSettings.h" +#include "WebSize.h" +#include "WebSpeechInputControllerMock.h" +#include "WebURL.h" +#include "WebView.h" #include "WebViewHost.h" -#include "public/WebAnimationController.h" -#include "public/WebBindings.h" -#include "public/WebConsoleMessage.h" -#include "public/WebData.h" -#include "public/WebDeviceOrientation.h" -#include "public/WebDeviceOrientationClientMock.h" -#include "public/WebDocument.h" -#include "public/WebElement.h" -#include "public/WebFrame.h" -#include "public/WebGeolocationServiceMock.h" -#include "public/WebInputElement.h" -#include "public/WebKit.h" -#include "public/WebNotificationPresenter.h" -#include "public/WebScriptSource.h" -#include "public/WebSecurityPolicy.h" -#include "public/WebSettings.h" -#include "public/WebSize.h" -#include "public/WebSpeechInputControllerMock.h" -#include "public/WebURL.h" -#include "public/WebView.h" #include "webkit/support/webkit_support.h" #include <algorithm> #include <cstdlib> @@ -106,7 +106,9 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("forceRedSelectionColors", &LayoutTestController::forceRedSelectionColors); bindMethod("grantDesktopNotificationPermission", &LayoutTestController::grantDesktopNotificationPermission); bindMethod("isCommandEnabled", &LayoutTestController::isCommandEnabled); + bindMethod("layerTreeAsText", &LayoutTestController::layerTreeAsText); bindMethod("markerTextForListItem", &LayoutTestController::markerTextForListItem); + bindMethod("hasSpellingMarker", &LayoutTestController::hasSpellingMarker); bindMethod("notifyDone", &LayoutTestController::notifyDone); bindMethod("numberOfActiveAnimations", &LayoutTestController::numberOfActiveAnimations); bindMethod("numberOfPages", &LayoutTestController::numberOfPages); @@ -1537,6 +1539,11 @@ WebKit::WebSpeechInputController* LayoutTestController::speechInputController(We return m_speechInputControllerMock.get(); } +void LayoutTestController::layerTreeAsText(const CppArgumentList& args, CppVariant* result) +{ + result->set(m_shell->webView()->mainFrame()->layerTreeAsText().utf8()); +} + void LayoutTestController::markerTextForListItem(const CppArgumentList& args, CppVariant* result) { WebElement element; @@ -1552,3 +1559,10 @@ WebDeviceOrientationClient* LayoutTestController::deviceOrientationClient() m_deviceOrientationClientMock.set(WebDeviceOrientationClientMock::create()); return m_deviceOrientationClientMock.get(); } + +void LayoutTestController::hasSpellingMarker(const CppArgumentList& arguments, CppVariant* result) +{ + if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) + return; + result->set(m_shell->webView()->mainFrame()->selectionStartHasSpellingMarkerFor(arguments[0].toInt32(), arguments[1].toInt32())); +} diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h index 8467097..ae1a7a2 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h @@ -43,8 +43,8 @@ #include "CppBoundClass.h" #include "Task.h" -#include "public/WebString.h" -#include "public/WebURL.h" +#include "WebString.h" +#include "WebURL.h" #include <wtf/Deque.h> #include <wtf/OwnPtr.h> @@ -325,7 +325,10 @@ public: // Speech input related functions. void setMockSpeechInputResult(const CppArgumentList&, CppVariant*); + void layerTreeAsText(const CppArgumentList& args, CppVariant* result); + void markerTextForListItem(const CppArgumentList&, CppVariant*); + void hasSpellingMarker(const CppArgumentList&, CppVariant*); public: // The following methods are not exposed to JavaScript. diff --git a/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.cpp b/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.cpp index 0bf3802..bf39f60 100644 --- a/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.cpp +++ b/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.cpp @@ -31,12 +31,11 @@ #include "config.h" #include "MockSpellCheck.h" +#include "WebString.h" #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> #include <wtf/text/WTFString.h> -#include "public/WebString.h" - using namespace WebKit; MockSpellCheck::MockSpellCheck() diff --git a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp index 7d4cbe3..7e7053b 100644 --- a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp +++ b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.cpp @@ -31,14 +31,14 @@ #include "config.h" #include "NotificationPresenter.h" +#include "WebKit.h" +#include "WebKitClient.h" +#include "WebNotification.h" +#include "WebNotificationPermissionCallback.h" +#include "WebSecurityOrigin.h" +#include "WebString.h" +#include "WebURL.h" #include "googleurl/src/gurl.h" -#include "public/WebKit.h" -#include "public/WebKitClient.h" -#include "public/WebNotification.h" -#include "public/WebNotificationPermissionCallback.h" -#include "public/WebSecurityOrigin.h" -#include "public/WebString.h" -#include "public/WebURL.h" #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> diff --git a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h index 896f345..689a908 100644 --- a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h +++ b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h @@ -31,8 +31,8 @@ #ifndef NotificationPresenter_h #define NotificationPresenter_h -#include "public/WebNotification.h" -#include "public/WebNotificationPresenter.h" +#include "WebNotification.h" +#include "WebNotificationPresenter.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/text/StringHash.h> diff --git a/WebKitTools/DumpRenderTree/chromium/PlainTextController.cpp b/WebKitTools/DumpRenderTree/chromium/PlainTextController.cpp index 6e6cf11..c8bdabd 100644 --- a/WebKitTools/DumpRenderTree/chromium/PlainTextController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/PlainTextController.cpp @@ -33,9 +33,9 @@ #include "PlainTextController.h" #include "TestShell.h" -#include "public/WebBindings.h" -#include "public/WebRange.h" -#include "public/WebString.h" +#include "WebBindings.h" +#include "WebRange.h" +#include "WebString.h" using namespace WebKit; diff --git a/WebKitTools/DumpRenderTree/chromium/Task.cpp b/WebKitTools/DumpRenderTree/chromium/Task.cpp index 3f90d8c..5719bac 100644 --- a/WebKitTools/DumpRenderTree/chromium/Task.cpp +++ b/WebKitTools/DumpRenderTree/chromium/Task.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "Task.h" -#include "public/WebKit.h" -#include "public/WebKitClient.h" +#include "WebKit.h" +#include "WebKitClient.h" #include "webkit/support/webkit_support.h" WebTask::WebTask(TaskList* list): m_taskList(list) { m_taskList->registerTask(this); } diff --git a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h index d75c3bf..b671489 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h +++ b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h @@ -31,10 +31,10 @@ #ifndef TestNavigationController_h #define TestNavigationController_h -#include "public/WebDataSource.h" -#include "public/WebHistoryItem.h" -#include "public/WebString.h" -#include "public/WebURL.h" +#include "WebDataSource.h" +#include "WebHistoryItem.h" +#include "WebString.h" +#include "WebURL.h" #include "webkit/support/webkit_support.h" #include <string> #include <wtf/RefCounted.h> diff --git a/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h new file mode 100644 index 0000000..49f72a6 --- /dev/null +++ b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h @@ -0,0 +1 @@ +#include "bindings/npapi.h" diff --git a/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h new file mode 100644 index 0000000..61588ca --- /dev/null +++ b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h @@ -0,0 +1,7 @@ +#include "bindings/npfunctions.h" + +// Non-standard event types can be passed to HandleEvent. +// npapi.h that comes with WebKit.framework adds these events. +#define getFocusEvent (osEvt + 16) +#define loseFocusEvent (osEvt + 17) +#define adjustCursorEvent (osEvt + 18) diff --git a/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h new file mode 100644 index 0000000..597d4ad --- /dev/null +++ b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h @@ -0,0 +1 @@ +#include "bindings/npruntime.h" diff --git a/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/Info.plist b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/Info.plist new file mode 100644 index 0000000..663f058 --- /dev/null +++ b/WebKitTools/DumpRenderTree/chromium/TestNetscapePlugIn/Info.plist @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>WebKitTestNetscapePlugIn</string> + <key>CFBundleGetInfoString</key> + <string>420+, Copyright 2006-2009 Apple Inc.</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.apple.testnetscapeplugin</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BRPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFPlugInDynamicRegisterFunction</key> + <string></string> + <key>CFPlugInDynamicRegistration</key> + <string>NO</string> + <key>CFPlugInFactories</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <string>MyFactoryFunction</string> + </dict> + <key>CFPlugInTypes</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <array> + <string>00000000-0000-0000-0000-000000000000</string> + </array> + </dict> + <key>CFPlugInUnloadFunction</key> + <string></string> + <key>WebPluginDescription</key> + <string>Simple Netscape plug-in that handles test content for WebKit</string> + <key>WebPluginMIMETypes</key> + <dict> + <key>application/x-webkit-test-netscape</key> + <dict> + <key>WebPluginExtensions</key> + <array> + <string>testnetscape</string> + </array> + <key>WebPluginTypeDescription</key> + <string>test netscape content</string> + </dict> + </dict> + <key>WebPluginName</key> + <string>WebKit Test PlugIn</string> +</dict> +</plist> diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp index 1a99b7d..0b27c78 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp @@ -34,22 +34,22 @@ #include "DRTDevToolsAgent.h" #include "DRTDevToolsClient.h" #include "LayoutTestController.h" +#include "WebDataSource.h" +#include "WebDocument.h" +#include "WebElement.h" +#include "WebFrame.h" +#include "WebHistoryItem.h" +#include "WebKit.h" +#include "WebRuntimeFeatures.h" +#include "WebScriptController.h" +#include "WebSettings.h" +#include "WebSize.h" +#include "WebSpeechInputControllerMock.h" +#include "WebString.h" +#include "WebURLRequest.h" +#include "WebURLResponse.h" +#include "WebView.h" #include "WebViewHost.h" -#include "public/WebDataSource.h" -#include "public/WebDocument.h" -#include "public/WebElement.h" -#include "public/WebFrame.h" -#include "public/WebHistoryItem.h" -#include "public/WebKit.h" -#include "public/WebRuntimeFeatures.h" -#include "public/WebScriptController.h" -#include "public/WebSettings.h" -#include "public/WebSize.h" -#include "public/WebSpeechInputControllerMock.h" -#include "public/WebString.h" -#include "public/WebURLRequest.h" -#include "public/WebURLResponse.h" -#include "public/WebView.h" #include "skia/ext/bitmap_platform_device.h" #include "skia/ext/platform_canvas.h" #include "webkit/support/webkit_support.h" @@ -82,9 +82,10 @@ TestShell::TestShell(bool testShellMode) , m_testIsPreparing(false) , m_focusedWidget(0) , m_testShellMode(testShellMode) + , m_devTools(0) , m_allowExternalPages(false) + , m_acceleratedCompositingEnabled(false) , m_accelerated2dCanvasEnabled(false) - , m_devTools(0) { WebRuntimeFeatures::enableGeolocation(true); WebRuntimeFeatures::enableIndexedDatabase(true); @@ -156,6 +157,7 @@ void TestShell::closeDevTools() void TestShell::resetWebSettings(WebView& webView) { m_prefs.reset(); + m_prefs.acceleratedCompositingEnabled = m_acceleratedCompositingEnabled; m_prefs.accelerated2dCanvasEnabled = m_accelerated2dCanvasEnabled; m_prefs.applyTo(&webView); } diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.h b/WebKitTools/DumpRenderTree/chromium/TestShell.h index 4d022dc..a15d9ec 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.h +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.h @@ -123,6 +123,7 @@ public: bool allowExternalPages() const { return m_allowExternalPages; } void setAllowExternalPages(bool allowExternalPages) { m_allowExternalPages = allowExternalPages; } + void setAcceleratedCompositingEnabled(bool enabled) { m_acceleratedCompositingEnabled = enabled; } void setAccelerated2dCanvasEnabled(bool enabled) { m_accelerated2dCanvasEnabled = enabled; } #if defined(OS_WIN) @@ -178,6 +179,7 @@ private: TestParams m_params; int m_timeout; // timeout value in millisecond bool m_allowExternalPages; + bool m_acceleratedCompositingEnabled; bool m_accelerated2dCanvasEnabled; WebPreferences m_prefs; diff --git a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h index 9470804..a29e45f 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h +++ b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h @@ -31,9 +31,9 @@ #ifndef TestWebWorker_h #define TestWebWorker_h -#include "public/WebMessagePortChannel.h" -#include "public/WebWorker.h" -#include "public/WebWorkerClient.h" +#include "WebMessagePortChannel.h" +#include "WebWorker.h" +#include "WebWorkerClient.h" #include <wtf/RefCounted.h> namespace WebKit { diff --git a/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp b/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp index 4f06874..7af4e9f 100644 --- a/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TextInputController.cpp @@ -32,11 +32,11 @@ #include "TextInputController.h" #include "TestShell.h" -#include "public/WebBindings.h" -#include "public/WebFrame.h" -#include "public/WebRange.h" -#include "public/WebString.h" -#include "public/WebView.h" +#include "WebBindings.h" +#include "WebFrame.h" +#include "WebRange.h" +#include "WebString.h" +#include "WebView.h" #include <wtf/StringExtras.h> #include <string> @@ -58,7 +58,6 @@ TextInputController::TextInputController(TestShell* shell) bindMethod("doCommand", &TextInputController::doCommand); bindMethod("firstRectForCharacterRange", &TextInputController::firstRectForCharacterRange); bindMethod("hasMarkedText", &TextInputController::hasMarkedText); - bindMethod("hasSpellingMarker", &TextInputController::hasSpellingMarker); bindMethod("insertText", &TextInputController::insertText); bindMethod("makeAttributedString", &TextInputController::makeAttributedString); bindMethod("markedRange", &TextInputController::markedRange); @@ -233,14 +232,3 @@ void TextInputController::makeAttributedString(const CppArgumentList&, CppVarian // FIXME: Implement this. result->setNull(); } - -void TextInputController::hasSpellingMarker(const CppArgumentList& arguments, CppVariant* result) -{ - if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) - return; - WebFrame* mainFrame = getMainFrame(); - if (!mainFrame) - return; - // Returns as a number for a compatibility reason. - result->set(mainFrame->selectionStartHasSpellingMarkerFor(arguments[0].toInt32(), arguments[1].toInt32()) ? 1 : 0); -} diff --git a/WebKitTools/DumpRenderTree/chromium/TextInputController.h b/WebKitTools/DumpRenderTree/chromium/TextInputController.h index ddacefe..9896be5 100644 --- a/WebKitTools/DumpRenderTree/chromium/TextInputController.h +++ b/WebKitTools/DumpRenderTree/chromium/TextInputController.h @@ -61,7 +61,6 @@ public: void characterIndexForPoint(const CppArgumentList&, CppVariant*); void validAttributesForMarkedText(const CppArgumentList&, CppVariant*); void makeAttributedString(const CppArgumentList&, CppVariant*); - void hasSpellingMarker(const CppArgumentList&, CppVariant*); private: // Returns the test shell's main WebFrame. diff --git a/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp b/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp index 35247ef..948b448 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebPreferences.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "WebPreferences.h" -#include "public/WebView.h" +#include "WebView.h" using namespace WebKit; @@ -102,6 +102,7 @@ void WebPreferences::reset() tabsToLinks = false; hyperlinkAuditingEnabled = false; + acceleratedCompositingEnabled = false; accelerated2dCanvasEnabled = false; } @@ -159,10 +160,7 @@ void WebPreferences::applyTo(WebView* webView) settings->setTextDirectionSubmenuInclusionBehaviorNeverIncluded(); settings->setUsesEncodingDetector(false); settings->setImagesEnabled(true); - - // FIXME: crbug.com/51879 - settings->setAcceleratedCompositingEnabled(false); - + settings->setAcceleratedCompositingEnabled(acceleratedCompositingEnabled); settings->setAccelerated2dCanvasEnabled(accelerated2dCanvasEnabled); } diff --git a/WebKitTools/DumpRenderTree/chromium/WebPreferences.h b/WebKitTools/DumpRenderTree/chromium/WebPreferences.h index c0ea70f..46877c0 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebPreferences.h +++ b/WebKitTools/DumpRenderTree/chromium/WebPreferences.h @@ -31,9 +31,9 @@ #ifndef WebPreferences_h #define WebPerferences_h -#include "public/WebSettings.h" -#include "public/WebString.h" -#include "public/WebURL.h" +#include "WebSettings.h" +#include "WebString.h" +#include "WebURL.h" namespace WebKit { class WebView; @@ -77,6 +77,7 @@ struct WebPreferences { bool tabsToLinks; bool hyperlinkAuditingEnabled; bool caretBrowsingEnabled; + bool acceleratedCompositingEnabled; bool accelerated2dCanvasEnabled; WebPreferences() { reset(); } diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp index ef6c26a..6a8af81 100755 --- a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "WebThemeEngineDRT.h" +#include "WebRect.h" #include "WebThemeControlDRT.h" -#include "public/WebRect.h" #include "third_party/skia/include/core/SkRect.h" // Although all this code is generic, we include these headers diff --git a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h index c731540..e50886b 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h +++ b/WebKitTools/DumpRenderTree/chromium/WebThemeEngineDRT.h @@ -47,7 +47,7 @@ #ifndef WebThemeEngineDRT_h #define WebThemeEngineDRT_h -#include "public/WebThemeEngine.h" +#include "win/WebThemeEngine.h" #include <wtf/Noncopyable.h> class WebThemeEngineDRT : public WebKit::WebThemeEngine, public Noncopyable { diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp index 9a086e4..ab8dbf0 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp @@ -35,25 +35,25 @@ #include "TestNavigationController.h" #include "TestShell.h" #include "TestWebWorker.h" -#include "public/WebCString.h" -#include "public/WebConsoleMessage.h" -#include "public/WebContextMenuData.h" -#include "public/WebDataSource.h" -#include "public/WebDragData.h" -#include "public/WebElement.h" -#include "public/WebFrame.h" -#include "public/WebGeolocationServiceMock.h" -#include "public/WebHistoryItem.h" -#include "public/WebNode.h" -#include "public/WebRange.h" -#include "public/WebRect.h" -#include "public/WebScreenInfo.h" -#include "public/WebSize.h" -#include "public/WebStorageNamespace.h" -#include "public/WebURLRequest.h" -#include "public/WebURLResponse.h" -#include "public/WebView.h" -#include "public/WebWindowFeatures.h" +#include "WebCString.h" +#include "WebConsoleMessage.h" +#include "WebContextMenuData.h" +#include "WebDataSource.h" +#include "WebDragData.h" +#include "WebElement.h" +#include "WebFrame.h" +#include "WebGeolocationServiceMock.h" +#include "WebHistoryItem.h" +#include "WebNode.h" +#include "WebRange.h" +#include "WebRect.h" +#include "WebScreenInfo.h" +#include "WebSize.h" +#include "WebStorageNamespace.h" +#include "WebURLRequest.h" +#include "WebURLResponse.h" +#include "WebView.h" +#include "WebWindowFeatures.h" #include "skia/ext/platform_canvas.h" #include "webkit/support/webkit_support.h" #include <wtf/Assertions.h> @@ -124,7 +124,7 @@ static string descriptionSuitableForTestResult(const string& url) // dragging a file. static void addDRTFakeFileToDataObject(WebDragData* dragData) { - dragData->appendToFileNames(WebString::fromUTF8("DRTFakeFile")); + dragData->appendToFilenames(WebString::fromUTF8("DRTFakeFile")); } // Get a debugging string from a WebNavigationType. @@ -485,13 +485,11 @@ int WebViewHost::historyForwardListCount() return navigationController()->entryCount() - currentIndex - 1; } -void WebViewHost::focusAccessibilityObject(const WebAccessibilityObject& object) -{ - m_shell->accessibilityController()->setFocusedElement(object); -} - void WebViewHost::postAccessibilityNotification(const WebAccessibilityObject& obj, WebAccessibilityNotification notification) { + if (notification == WebAccessibilityNotificationFocusedUIElementChanged) + m_shell->accessibilityController()->setFocusedElement(obj); + if (m_shell->accessibilityController()->shouldDumpAccessibilityNotifications()) { printf("AccessibilityNotification - "); @@ -541,6 +539,8 @@ void WebViewHost::postAccessibilityNotification(const WebAccessibilityObject& ob case WebAccessibilityNotificationRowExpanded: printf("RowExpanded"); break; + default: + break; } WebKit::WebNode node = obj.node(); @@ -559,12 +559,14 @@ WebNotificationPresenter* WebViewHost::notificationPresenter() return m_shell->notificationPresenter(); } +#if !ENABLE(CLIENT_BASED_GEOLOCATION) WebKit::WebGeolocationService* WebViewHost::geolocationService() { if (!m_geolocationServiceMock.get()) m_geolocationServiceMock.set(WebGeolocationServiceMock::createWebGeolocationServiceMock()); return m_geolocationServiceMock.get(); } +#endif WebSpeechInputController* WebViewHost::speechInputController(WebKit::WebSpeechInputListener* listener) { @@ -592,6 +594,13 @@ void WebViewHost::didScrollRect(int, int, const WebRect& clipRect) didInvalidateRect(clipRect); } +void WebViewHost::scheduleComposite() +{ + WebSize widgetSize = webWidget()->size(); + WebRect clientRect(0, 0, widgetSize.width, widgetSize.height); + didInvalidateRect(clientRect); +} + void WebViewHost::didFocus() { m_shell->setFocus(webWidget(), true); @@ -628,6 +637,10 @@ void WebViewHost::closeWidgetSoon() { m_hasWindow = false; m_shell->closeWindow(this); + if (m_inModalLoop) { + m_inModalLoop = false; + webkit_support::QuitMessageLoop(); + } } void WebViewHost::didChangeCursor(const WebCursorInfo& cursorInfo) @@ -670,7 +683,11 @@ WebRect WebViewHost::windowResizerRect() void WebViewHost::runModal() { - // FIXME: Should we implement this in DRT? + bool oldState = webkit_support::MessageLoopNestableTasksAllowed(); + webkit_support::MessageLoopSetNestableTasksAllowed(true); + m_inModalLoop = true; + webkit_support::RunMessageLoop(); + webkit_support::MessageLoopSetNestableTasksAllowed(oldState); } // WebFrameClient ------------------------------------------------------------ @@ -1041,10 +1058,12 @@ WebViewHost::WebViewHost(TestShell* shell) , m_policyDelegateIsPermissive(false) , m_policyDelegateShouldNotifyDone(false) , m_shell(shell) + , m_webWidget(0) , m_topLoadingFrame(0) - , m_hasWindow(false) , m_pageId(-1) , m_lastPageIdUpdated(-1) + , m_hasWindow(false) + , m_inModalLoop(false) , m_smartInsertDeleteEnabled(true) #if OS(WINDOWS) , m_selectTrailingWhitespaceEnabled(true) @@ -1054,7 +1073,6 @@ WebViewHost::WebViewHost(TestShell* shell) , m_blocksRedirects(false) , m_requestReturnNull(false) , m_isPainting(false) - , m_webWidget(0) { m_navigationController.set(new TestNavigationController(this)); } diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h index bbb132d..429d3ab 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h @@ -33,10 +33,10 @@ #include "MockSpellCheck.h" #include "TestNavigationController.h" -#include "public/WebAccessibilityNotification.h" -#include "public/WebCursorInfo.h" -#include "public/WebFrameClient.h" -#include "public/WebViewClient.h" +#include "WebAccessibilityNotification.h" +#include "WebCursorInfo.h" +#include "WebFrameClient.h" +#include "WebViewClient.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/Vector.h> @@ -127,16 +127,18 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, virtual void navigateBackForwardSoon(int offset); virtual int historyBackListCount(); virtual int historyForwardListCount(); - virtual void focusAccessibilityObject(const WebKit::WebAccessibilityObject&); virtual void postAccessibilityNotification(const WebKit::WebAccessibilityObject&, WebKit::WebAccessibilityNotification); virtual WebKit::WebNotificationPresenter* notificationPresenter(); +#if !ENABLE(CLIENT_BASED_GEOLOCATION) virtual WebKit::WebGeolocationService* geolocationService(); +#endif virtual WebKit::WebSpeechInputController* speechInputController(WebKit::WebSpeechInputListener*); virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient(); // WebKit::WebWidgetClient virtual void didInvalidateRect(const WebKit::WebRect&); virtual void didScrollRect(int dx, int dy, const WebKit::WebRect&); + virtual void scheduleComposite(); virtual void didFocus(); virtual void didBlur(); virtual void didChangeCursor(const WebKit::WebCursorInfo&); @@ -257,6 +259,7 @@ private: WebKit::WebCursorInfo m_currentCursor; bool m_hasWindow; + bool m_inModalLoop; WebKit::WebRect m_windowRect; // true if we want to enable smart insert/delete. @@ -286,8 +289,10 @@ private: WebKit::WebRect m_paintRect; bool m_isPainting; +#if !ENABLE(CLIENT_BASED_GEOLOCATION) // Geolocation OwnPtr<WebKit::WebGeolocationServiceMock> m_geolocationServiceMock; +#endif OwnPtr<TestNavigationController*> m_navigationController; }; diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp index 521a0e1..e115683 100644 --- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -131,9 +131,29 @@ static void appendString(gchar*& target, gchar* string) g_free(oldString); } -static void initializeFonts() +static void initializeGtkFontSettings(const char* testURL) +{ + GtkSettings* settings = gtk_settings_get_default(); + if (!settings) + return; + g_object_set(settings, "gtk-xft-antialias", 1, NULL); + g_object_set(settings, "gtk-xft-hinting", 1, NULL); + g_object_set(settings, "gtk-xft-hintstyle", "hintfull", NULL); + g_object_set(settings, "gtk-font-name", "Liberation Sans 16", NULL); + + // One test needs subpixel anti-aliasing turned on, but generally we + // want all text in other tests to use to grayscale anti-aliasing. + if (testURL && strstr(testURL, "xsettings_antialias_settings.html")) + g_object_set(settings, "gtk-xft-rgba", "rgb", NULL); + else + g_object_set(settings, "gtk-xft-rgba", "none", NULL); +} + +static void initializeFonts(const char* testURL = 0) { #if PLATFORM(X11) + initializeGtkFontSettings(testURL); + FcInit(); // If a test resulted a font being added or removed via the @font-face rule, then @@ -177,6 +197,8 @@ static void initializeFonts() "/usr/share/fonts/liberation/LiberationSerif-Regular.ttf", }, { "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", "/usr/share/fonts/dejavu/DejaVuSans.ttf", }, + { "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf", + "/usr/share/fonts/dejavu/DejaVuSerif.ttf", }, }; // TODO: Some tests use Lucida. We should load these as well, once it becomes @@ -363,6 +385,7 @@ static void resetDefaultsToConsistentValues() "enable-html5-local-storage", TRUE, "enable-xss-auditor", FALSE, "enable-spatial-navigation", FALSE, + "enable-frame-flattening", FALSE, "javascript-can-access-clipboard", TRUE, "javascript-can-open-windows-automatically", TRUE, "enable-offline-web-application-cache", TRUE, @@ -373,6 +396,8 @@ static void resetDefaultsToConsistentValues() "monospace-font-family", "Courier", "serif-font-family", "Times", "sans-serif-font-family", "Helvetica", + "cursive-font-family", "cursive", + "fantasy-font-family", "fantasy", "default-font-size", 16, "default-monospace-font-size", 13, "minimum-font-size", 1, @@ -394,6 +419,9 @@ static void resetDefaultsToConsistentValues() webkit_reset_origin_access_white_lists(); + WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView); + webkit_web_back_forward_list_clear(list); + #ifdef HAVE_LIBSOUP_2_29_90 SoupSession* session = webkit_get_default_session(); SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR)); @@ -610,7 +638,7 @@ static void runTest(const string& testPathOrURL) if (prevTestBFItem) g_object_ref(prevTestBFItem); - initializeFonts(); + initializeFonts(testURL.c_str()); // Focus the web view before loading the test to avoid focusing problems gtk_widget_grab_focus(GTK_WIDGET(webView)); diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index d831076..181ef9f 100644 --- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -183,8 +183,16 @@ JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pa size_t LayoutTestController::webHistoryItemCount() { - // FIXME: implement - return 0; + WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); + WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView); + + if (!list) + return -1; + + // We do not add the current page to the total count as it's not + // considered in DRT tests + return webkit_web_back_forward_list_get_back_length(list) + + webkit_web_back_forward_list_get_forward_length(list); } unsigned LayoutTestController::workerThreadCount() const @@ -423,7 +431,11 @@ void LayoutTestController::setXSSAuditorEnabled(bool flag) void LayoutTestController::setFrameFlatteningEnabled(bool flag) { - // FIXME: implement + WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); + ASSERT(view); + + WebKitWebSettings* settings = webkit_web_view_get_settings(view); + g_object_set(G_OBJECT(settings), "enable-frame-flattening", flag, NULL); } void LayoutTestController::setSpatialNavigationEnabled(bool flag) @@ -804,3 +816,9 @@ void LayoutTestController::setEditingBehavior(const char* editingBehavior) void LayoutTestController::abortModal() { } + +bool LayoutTestController::hasSpellingMarker(int, int) +{ + // FIXME: Implement this. + return false; +} diff --git a/WebKitTools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp b/WebKitTools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp index f0f461c..4073403 100644 --- a/WebKitTools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp @@ -36,15 +36,24 @@ PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool) { WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - GdkPixmap* pixmap = gtk_widget_get_snapshot(GTK_WIDGET(view), 0); gint width, height; +#ifdef GTK_API_VERSION_2 + GdkPixmap* pixmap = gtk_widget_get_snapshot(GTK_WIDGET(view), 0); gdk_drawable_get_size(GDK_DRAWABLE(pixmap), &width, &height); +#else + width = gtk_widget_get_allocated_width(GTK_WIDGET(view)); + height = gtk_widget_get_allocated_height(GTK_WIDGET(view)); +#endif cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t* context = cairo_create(imageSurface); +#ifdef GTK_API_VERSION_2 gdk_cairo_set_source_pixmap(context, pixmap, 0, 0); cairo_paint(context); g_object_unref(pixmap); +#else + gtk_widget_draw(GTK_WIDGET(view), context); +#endif return BitmapContext::createByAdoptingBitmapAndContext(0, context); } diff --git a/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf b/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf index 520f96e..6eb057e 100644 --- a/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf +++ b/WebKitTools/DumpRenderTree/gtk/fonts/fonts.conf @@ -28,6 +28,25 @@ </edit> </match> + <!-- Until we find good fonts to use for cursive and fantasy + just use our serif font. --> + <match target="pattern"> + <test qual="any" name="family"> + <string>cursive</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Serif</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>fantasy</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"> @@ -55,6 +74,22 @@ <string>Liberation Sans</string> </edit> </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Arial</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + </match> + <match target="pattern"> + <test qual="any" name="family"> + <string>Lucida Grande</string> + </test> + <edit name="family" mode="assign"> + <string>Liberation Sans</string> + </edit> + </match> <!-- The Monospace font should be Liberation Mono --> <match target="pattern"> @@ -214,6 +249,54 @@ </edit> </match> + <!-- We need to enable simulated bold to for DejaVu Serif to ensure that we interpret + this property correctly in: platform/gtk/fonts/fontconfig-synthetic-bold.html --> + <match target="font"> + <test qual="any" name="family"> + <string>DejaVu Serif</string> + </test> + <test name="weight" compare="less_eq"> + <const>medium</const> + </test> + <test target="pattern" name="weight" compare="more"> + <const>medium</const> + </test> + <edit name="embolden" mode="assign"> + <bool>true</bool> + </edit> + <edit name="weight" mode="assign"> + <const>bold</const> + </edit> + </match> + + <!-- We need to enable simulated oblique to for DejaVu Serif to ensure that we interpret + this property correctly in: platform/gtk/fonts/fontconfig-synthetic-oblique.html --> + <match target="font"> + <test qual="any" name="family"> + <string>DejaVu Serif</string> + </test> + <test name="slant"> + <const>roman</const> + </test> + <test target="pattern" name="slant" compare="not_eq"> + <const>roman</const> + </test> + <edit name="matrix" mode="assign"> + <times> + <name>matrix</name> + <matrix><double>1</double><double>0.2</double> + <double>0</double><double>1</double> + </matrix> + </times> + </edit> + <edit name="slant" mode="assign"> + <const>oblique</const> + </edit> + <edit name="embeddedbitmap" mode="assign"> + <bool>false</bool> + </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 diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm index 5f9705a..2ca5755 100644 --- a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm @@ -780,6 +780,17 @@ int AccessibilityUIElement::hierarchicalLevel() const return 0; } +JSStringRef AccessibilityUIElement::speak() +{ + BEGIN_AX_OBJC_EXCEPTIONS + id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"]; + if ([value isKindOfClass:[NSString class]]) + return [value createJSStringRef]; + END_AX_OBJC_EXCEPTIONS + + return 0; +} + bool AccessibilityUIElement::ariaIsGrabbed() const { BEGIN_AX_OBJC_EXCEPTIONS @@ -824,6 +835,18 @@ int AccessibilityUIElement::lineForIndex(int index) return -1; } +JSStringRef AccessibilityUIElement::rangeForLine(int line) +{ + BEGIN_AX_OBJC_EXCEPTIONS + id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]]; + if ([value isKindOfClass:[NSValue class]]) { + return [NSStringFromRange([value rangeValue]) createJSStringRef]; + } + END_AX_OBJC_EXCEPTIONS + + return 0; +} + JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length) { NSRange range = NSMakeRange(location, length); diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm index 3732247..68765f6 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -49,6 +49,7 @@ #import "PolicyDelegate.h" #import "ResourceLoadDelegate.h" #import "UIDelegate.h" +#import "WebArchiveDumpSupport.h" #import "WorkQueue.h" #import "WorkQueueItem.h" #import <Carbon/Carbon.h> @@ -56,6 +57,7 @@ #import <WebKit/DOMElement.h> #import <WebKit/DOMExtensions.h> #import <WebKit/DOMRange.h> +#import <WebKit/WebArchive.h> #import <WebKit/WebBackForwardList.h> #import <WebKit/WebCache.h> #import <WebKit/WebCoreStatistics.h> @@ -65,7 +67,6 @@ #import <WebKit/WebDeviceOrientationProviderMock.h> #import <WebKit/WebEditingDelegate.h> #import <WebKit/WebFrameView.h> -#import <WebKit/WebHTMLRepresentationInternal.h> #import <WebKit/WebHistory.h> #import <WebKit/WebHistoryItemPrivate.h> #import <WebKit/WebInspector.h> @@ -822,176 +823,6 @@ static NSData *dumpFrameAsPDF(WebFrame *frame) return pdfData; } -static void convertMIMEType(NSMutableString *mimeType) -{ -#ifdef BUILDING_ON_LEOPARD - // Workaround for <rdar://problem/5539824> on Leopard - if ([mimeType isEqualToString:@"text/xml"]) - [mimeType setString:@"application/xml"]; -#endif - // Workaround for <rdar://problem/6234318> with Dashcode 2.0 - if ([mimeType isEqualToString:@"application/x-javascript"]) - [mimeType setString:@"text/javascript"]; -} - -static void convertWebResourceDataToString(NSMutableDictionary *resource) -{ - NSMutableString *mimeType = [resource objectForKey:@"WebResourceMIMEType"]; - convertMIMEType(mimeType); - - if ([mimeType hasPrefix:@"text/"] || [[WebHTMLRepresentation supportedNonImageMIMETypes] containsObject:mimeType]) { - NSString *textEncodingName = [resource objectForKey:@"WebResourceTextEncodingName"]; - NSStringEncoding stringEncoding; - if ([textEncodingName length] > 0) - stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)textEncodingName)); - else - stringEncoding = NSUTF8StringEncoding; - - NSData *data = [resource objectForKey:@"WebResourceData"]; - NSString *dataAsString = [[NSString alloc] initWithData:data encoding:stringEncoding]; - if (dataAsString) - [resource setObject:dataAsString forKey:@"WebResourceData"]; - [dataAsString release]; - } -} - -static void normalizeHTTPResponseHeaderFields(NSMutableDictionary *fields) -{ - // Normalize headers - if ([fields objectForKey:@"Date"]) - [fields setObject:@"Sun, 16 Nov 2008 17:00:00 GMT" forKey:@"Date"]; - if ([fields objectForKey:@"Last-Modified"]) - [fields setObject:@"Sun, 16 Nov 2008 16:55:00 GMT" forKey:@"Last-Modified"]; - if ([fields objectForKey:@"Etag"]) - [fields setObject:@"\"301925-21-45c7d72d3e780\"" forKey:@"Etag"]; - if ([fields objectForKey:@"Server"]) - [fields setObject:@"Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l PHP/5.2.6" forKey:@"Server"]; - - // Remove headers - if ([fields objectForKey:@"Connection"]) - [fields removeObjectForKey:@"Connection"]; - if ([fields objectForKey:@"Keep-Alive"]) - [fields removeObjectForKey:@"Keep-Alive"]; -} - -static void normalizeWebResourceURL(NSMutableString *webResourceURL) -{ - static int fileUrlLength = [(NSString *)@"file://" length]; - NSRange layoutTestsWebArchivePathRange = [webResourceURL rangeOfString:@"/LayoutTests/" options:NSBackwardsSearch]; - if (layoutTestsWebArchivePathRange.location == NSNotFound) - return; - NSRange currentWorkingDirectoryRange = NSMakeRange(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength); - [webResourceURL replaceCharactersInRange:currentWorkingDirectoryRange withString:@""]; -} - -static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList) -{ - NSURLResponse *response = nil; - NSData *responseData = [propertyList objectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m - if ([responseData isKindOfClass:[NSData class]]) { - // Decode NSURLResponse - NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData]; - response = [unarchiver decodeObjectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m - [unarchiver finishDecoding]; - [unarchiver release]; - } - - NSMutableDictionary *responseDictionary = [[NSMutableDictionary alloc] init]; - - NSMutableString *urlString = [[[response URL] description] mutableCopy]; - normalizeWebResourceURL(urlString); - [responseDictionary setObject:urlString forKey:@"URL"]; - [urlString release]; - - NSMutableString *mimeTypeString = [[response MIMEType] mutableCopy]; - convertMIMEType(mimeTypeString); - [responseDictionary setObject:mimeTypeString forKey:@"MIMEType"]; - [mimeTypeString release]; - - NSString *textEncodingName = [response textEncodingName]; - if (textEncodingName) - [responseDictionary setObject:textEncodingName forKey:@"textEncodingName"]; - [responseDictionary setObject:[NSNumber numberWithLongLong:[response expectedContentLength]] forKey:@"expectedContentLength"]; - - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - - NSMutableDictionary *allHeaderFields = [[httpResponse allHeaderFields] mutableCopy]; - normalizeHTTPResponseHeaderFields(allHeaderFields); - [responseDictionary setObject:allHeaderFields forKey:@"allHeaderFields"]; - [allHeaderFields release]; - - [responseDictionary setObject:[NSNumber numberWithInt:[httpResponse statusCode]] forKey:@"statusCode"]; - } - - [propertyList setObject:responseDictionary forKey:@"WebResourceResponse"]; - [responseDictionary release]; -} - -static NSInteger compareResourceURLs(id resource1, id resource2, void *context) -{ - NSString *url1 = [resource1 objectForKey:@"WebResourceURL"]; - NSString *url2 = [resource2 objectForKey:@"WebResourceURL"]; - - return [url1 compare:url2]; -} - -static NSString *serializeWebArchiveToXML(WebArchive *webArchive) -{ - NSString *errorString; - NSMutableDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:[webArchive data] - mutabilityOption:NSPropertyListMutableContainersAndLeaves - format:NULL - errorDescription:&errorString]; - if (!propertyList) - return errorString; - - NSMutableArray *resources = [NSMutableArray arrayWithCapacity:1]; - [resources addObject:propertyList]; - - while ([resources count]) { - NSMutableDictionary *resourcePropertyList = [resources objectAtIndex:0]; - [resources removeObjectAtIndex:0]; - - NSMutableDictionary *mainResource = [resourcePropertyList objectForKey:@"WebMainResource"]; - normalizeWebResourceURL([mainResource objectForKey:@"WebResourceURL"]); - convertWebResourceDataToString(mainResource); - - // Add subframeArchives to list for processing - NSMutableArray *subframeArchives = [resourcePropertyList objectForKey:@"WebSubframeArchives"]; // WebSubframeArchivesKey in WebArchive.m - if (subframeArchives) - [resources addObjectsFromArray:subframeArchives]; - - NSMutableArray *subresources = [resourcePropertyList objectForKey:@"WebSubresources"]; // WebSubresourcesKey in WebArchive.m - NSEnumerator *enumerator = [subresources objectEnumerator]; - NSMutableDictionary *subresourcePropertyList; - while ((subresourcePropertyList = [enumerator nextObject])) { - normalizeWebResourceURL([subresourcePropertyList objectForKey:@"WebResourceURL"]); - convertWebResourceResponseToDictionary(subresourcePropertyList); - convertWebResourceDataToString(subresourcePropertyList); - } - - // Sort the subresources so they're always in a predictable order for the dump - if (NSArray *sortedSubresources = [subresources sortedArrayUsingFunction:compareResourceURLs context:nil]) - [resourcePropertyList setObject:sortedSubresources forKey:@"WebSubresources"]; - } - - NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:propertyList - format:NSPropertyListXMLFormat_v1_0 - errorDescription:&errorString]; - if (!xmlData) - return errorString; - - NSMutableString *string = [[[NSMutableString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding] autorelease]; - - // Replace "Apple Computer" with "Apple" in the DTD declaration. - NSRange range = [string rangeOfString:@"-//Apple Computer//"]; - if (range.location != NSNotFound) - [string replaceCharactersInRange:range withString:@"-//Apple//"]; - - return string; -} - static void dumpBackForwardListForWebView(WebView *view) { printf("\n============== Back Forward List ==============\n"); diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index d2a6f79..c5d5a90 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -422,7 +422,7 @@ void LayoutTestController::setFrameFlatteningEnabled(bool enabled) void LayoutTestController::setSpatialNavigationEnabled(bool enabled) { - // FIXME: Implement for SpatialNavigation layout tests. + [[[mainFrame webView] preferences] setSpatialNavigationEnabled:enabled]; } void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled) @@ -944,3 +944,8 @@ void LayoutTestController::abortModal() { [NSApp abortModal]; } + +bool LayoutTestController::hasSpellingMarker(int from, int length) +{ + return [mainFrame hasSpellingMarker:from length:length]; +} diff --git a/WebKitTools/DumpRenderTree/mac/TextInputController.m b/WebKitTools/DumpRenderTree/mac/TextInputController.m index a049ac5..f780794 100644 --- a/WebKitTools/DumpRenderTree/mac/TextInputController.m +++ b/WebKitTools/DumpRenderTree/mac/TextInputController.m @@ -170,8 +170,7 @@ || aSelector == @selector(characterIndexForPointX:Y:) || aSelector == @selector(validAttributesForMarkedText) || aSelector == @selector(attributedStringWithString:) - || aSelector == @selector(setInputMethodHandler:) - || aSelector == @selector(hasSpellingMarker:length:)) + || aSelector == @selector(setInputMethodHandler:)) return NO; return YES; } @@ -196,8 +195,6 @@ return @"makeAttributedString"; // just a factory method, doesn't call into NSTextInput else if (aSelector == @selector(setInputMethodHandler:)) return @"setInputMethodHandler"; - else if (aSelector == @selector(hasSpellingMarker:length:)) - return @"hasSpellingMarker"; return nil; } @@ -431,9 +428,4 @@ return YES; } -- (BOOL)hasSpellingMarker:(int)from length:(int)length -{ - return [[webView mainFrame] hasSpellingMarker:from length:length]; -} - @end diff --git a/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.h b/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.h new file mode 100644 index 0000000..8654dd5 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007, 2008, 2009, 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebArchiveDumpSupport_h +#define WebArchiveDumpSupport_h + +@class NSString; +@class WebArchive; + +NSString *serializeWebArchiveToXML(WebArchive *webArchive); + +#endif /* WebArchiveDumpSupport_h */ diff --git a/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.mm b/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.mm new file mode 100644 index 0000000..7c52c6a --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/WebArchiveDumpSupport.mm @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2007, 2008, 2009, 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebArchiveDumpSupport.h" + +#import <Foundation/Foundation.h> +#import <WebKit/WebArchive.h> +#import <WebKit/WebHTMLRepresentationInternal.h> + +static void convertMIMEType(NSMutableString *mimeType) +{ +#ifdef BUILDING_ON_LEOPARD + // Workaround for <rdar://problem/5539824> on Leopard + if ([mimeType isEqualToString:@"text/xml"]) + [mimeType setString:@"application/xml"]; +#endif + // Workaround for <rdar://problem/6234318> with Dashcode 2.0 + if ([mimeType isEqualToString:@"application/x-javascript"]) + [mimeType setString:@"text/javascript"]; +} + +static void convertWebResourceDataToString(NSMutableDictionary *resource) +{ + NSMutableString *mimeType = [resource objectForKey:@"WebResourceMIMEType"]; + convertMIMEType(mimeType); + + if ([mimeType hasPrefix:@"text/"] || [[WebHTMLRepresentation supportedNonImageMIMETypes] containsObject:mimeType]) { + NSString *textEncodingName = [resource objectForKey:@"WebResourceTextEncodingName"]; + NSStringEncoding stringEncoding; + if ([textEncodingName length] > 0) + stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)textEncodingName)); + else + stringEncoding = NSUTF8StringEncoding; + + NSData *data = [resource objectForKey:@"WebResourceData"]; + NSString *dataAsString = [[NSString alloc] initWithData:data encoding:stringEncoding]; + if (dataAsString) + [resource setObject:dataAsString forKey:@"WebResourceData"]; + [dataAsString release]; + } +} + +static void normalizeHTTPResponseHeaderFields(NSMutableDictionary *fields) +{ + // Normalize headers + if ([fields objectForKey:@"Date"]) + [fields setObject:@"Sun, 16 Nov 2008 17:00:00 GMT" forKey:@"Date"]; + if ([fields objectForKey:@"Last-Modified"]) + [fields setObject:@"Sun, 16 Nov 2008 16:55:00 GMT" forKey:@"Last-Modified"]; + if ([fields objectForKey:@"Etag"]) + [fields setObject:@"\"301925-21-45c7d72d3e780\"" forKey:@"Etag"]; + if ([fields objectForKey:@"Server"]) + [fields setObject:@"Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l PHP/5.2.6" forKey:@"Server"]; + + // Remove headers + if ([fields objectForKey:@"Connection"]) + [fields removeObjectForKey:@"Connection"]; + if ([fields objectForKey:@"Keep-Alive"]) + [fields removeObjectForKey:@"Keep-Alive"]; +} + +static void normalizeWebResourceURL(NSMutableString *webResourceURL) +{ + static int fileUrlLength = [(NSString *)@"file://" length]; + NSRange layoutTestsWebArchivePathRange = [webResourceURL rangeOfString:@"/LayoutTests/" options:NSBackwardsSearch]; + if (layoutTestsWebArchivePathRange.location == NSNotFound) + return; + NSRange currentWorkingDirectoryRange = NSMakeRange(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength); + [webResourceURL replaceCharactersInRange:currentWorkingDirectoryRange withString:@""]; +} + +static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList) +{ + NSURLResponse *response = nil; + NSData *responseData = [propertyList objectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m + if ([responseData isKindOfClass:[NSData class]]) { + // Decode NSURLResponse + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData]; + response = [unarchiver decodeObjectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m + [unarchiver finishDecoding]; + [unarchiver release]; + } + + NSMutableDictionary *responseDictionary = [[NSMutableDictionary alloc] init]; + + NSMutableString *urlString = [[[response URL] description] mutableCopy]; + normalizeWebResourceURL(urlString); + [responseDictionary setObject:urlString forKey:@"URL"]; + [urlString release]; + + NSMutableString *mimeTypeString = [[response MIMEType] mutableCopy]; + convertMIMEType(mimeTypeString); + [responseDictionary setObject:mimeTypeString forKey:@"MIMEType"]; + [mimeTypeString release]; + + NSString *textEncodingName = [response textEncodingName]; + if (textEncodingName) + [responseDictionary setObject:textEncodingName forKey:@"textEncodingName"]; + [responseDictionary setObject:[NSNumber numberWithLongLong:[response expectedContentLength]] forKey:@"expectedContentLength"]; + + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + NSMutableDictionary *allHeaderFields = [[httpResponse allHeaderFields] mutableCopy]; + normalizeHTTPResponseHeaderFields(allHeaderFields); + [responseDictionary setObject:allHeaderFields forKey:@"allHeaderFields"]; + [allHeaderFields release]; + + [responseDictionary setObject:[NSNumber numberWithInt:[httpResponse statusCode]] forKey:@"statusCode"]; + } + + [propertyList setObject:responseDictionary forKey:@"WebResourceResponse"]; + [responseDictionary release]; +} + +static NSInteger compareResourceURLs(id resource1, id resource2, void *context) +{ + NSString *url1 = [resource1 objectForKey:@"WebResourceURL"]; + NSString *url2 = [resource2 objectForKey:@"WebResourceURL"]; + + return [url1 compare:url2]; +} + +NSString *serializeWebArchiveToXML(WebArchive *webArchive) +{ + NSString *errorString; + NSMutableDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:[webArchive data] + mutabilityOption:NSPropertyListMutableContainersAndLeaves + format:NULL + errorDescription:&errorString]; + if (!propertyList) + return errorString; + + NSMutableArray *resources = [NSMutableArray arrayWithCapacity:1]; + [resources addObject:propertyList]; + + while ([resources count]) { + NSMutableDictionary *resourcePropertyList = [resources objectAtIndex:0]; + [resources removeObjectAtIndex:0]; + + NSMutableDictionary *mainResource = [resourcePropertyList objectForKey:@"WebMainResource"]; + normalizeWebResourceURL([mainResource objectForKey:@"WebResourceURL"]); + convertWebResourceDataToString(mainResource); + + // Add subframeArchives to list for processing + NSMutableArray *subframeArchives = [resourcePropertyList objectForKey:@"WebSubframeArchives"]; // WebSubframeArchivesKey in WebArchive.m + if (subframeArchives) + [resources addObjectsFromArray:subframeArchives]; + + NSMutableArray *subresources = [resourcePropertyList objectForKey:@"WebSubresources"]; // WebSubresourcesKey in WebArchive.m + NSEnumerator *enumerator = [subresources objectEnumerator]; + NSMutableDictionary *subresourcePropertyList; + while ((subresourcePropertyList = [enumerator nextObject])) { + normalizeWebResourceURL([subresourcePropertyList objectForKey:@"WebResourceURL"]); + convertWebResourceResponseToDictionary(subresourcePropertyList); + convertWebResourceDataToString(subresourcePropertyList); + } + + // Sort the subresources so they're always in a predictable order for the dump + if (NSArray *sortedSubresources = [subresources sortedArrayUsingFunction:compareResourceURLs context:nil]) + [resourcePropertyList setObject:sortedSubresources forKey:@"WebSubresources"]; + } + + NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:propertyList + format:NSPropertyListXMLFormat_v1_0 + errorDescription:&errorString]; + if (!xmlData) + return errorString; + + NSMutableString *string = [[[NSMutableString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding] autorelease]; + + // Replace "Apple Computer" with "Apple" in the DTD declaration. + NSRange range = [string rangeOfString:@"-//Apple Computer//"]; + if (range.location != NSNotFound) + [string replaceCharactersInRange:range withString:@"-//Apple//"]; + + return string; +} diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro index 801251d..54d5af7 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro @@ -27,12 +27,14 @@ HEADERS = $$BASEDIR/WorkQueue.h \ WorkQueueItemQt.h \ LayoutTestControllerQt.h \ GCControllerQt.h \ + PlainTextControllerQt.h \ testplugin.h SOURCES = ../../../JavaScriptCore/wtf/Assertions.cpp \ $$BASEDIR/WorkQueue.cpp \ DumpRenderTreeQt.cpp \ EventSenderQt.cpp \ TextInputControllerQt.cpp \ + PlainTextControllerQt.cpp \ WorkQueueItemQt.cpp \ LayoutTestControllerQt.cpp \ GCControllerQt.cpp \ diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index 80fa441..50ae605 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -37,6 +37,7 @@ #include "GCControllerQt.h" #include "LayoutTestControllerQt.h" #include "TextInputControllerQt.h" +#include "PlainTextControllerQt.h" #include "testplugin.h" #include "WorkQueue.h" @@ -450,6 +451,9 @@ DumpRenderTree::DumpRenderTree() view->setPage(m_page); m_mainView = view; } + // Use a frame group name for all pages created by DumpRenderTree to allow + // testing of cross-page frame lookup. + DumpRenderTreeSupportQt::webPageSetGroupName(m_page, "org.webkit.qt.DumpRenderTree"); m_mainView->setContextMenuPolicy(Qt::NoContextMenu); m_mainView->resize(QSize(LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight)); @@ -470,6 +474,7 @@ DumpRenderTree::DumpRenderTree() connect(m_controller, SIGNAL(done()), this, SLOT(dump())); m_eventSender = new EventSender(m_page); m_textInputController = new TextInputController(m_page); + m_plainTextController = new PlainTextController(m_page); m_gcController = new GCController(m_page); // now connect our different signals @@ -752,6 +757,7 @@ void DumpRenderTree::initJSObjects() frame->addToJavaScriptWindowObject(QLatin1String("eventSender"), m_eventSender); frame->addToJavaScriptWindowObject(QLatin1String("textInputController"), m_textInputController); frame->addToJavaScriptWindowObject(QLatin1String("GCController"), m_gcController); + frame->addToJavaScriptWindowObject(QLatin1String("plainText"), m_plainTextController); } void DumpRenderTree::showPage() @@ -827,7 +833,7 @@ static QString dumpHistoryItem(const QWebHistoryItem& item, int indent, bool cur for (int i = start; i < indent; i++) result.append(' '); - QString url = item.url().toString(); + QString url = item.url().toEncoded(); if (url.contains("file://")) { static QString layoutTestsString("/LayoutTests/"); static QString fileTestString("(file test):"); @@ -1059,6 +1065,11 @@ QWebPage *DumpRenderTree::createWindow() connectFrame(page->mainFrame()); connect(page, SIGNAL(loadFinished(bool)), m_controller, SLOT(maybeDump(bool))); connect(page, SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested())); + + // Use a frame group name for all pages created by DumpRenderTree to allow + // testing of cross-page frame lookup. + DumpRenderTreeSupportQt::webPageSetGroupName(page, "org.webkit.qt.DumpRenderTree"); + return page; } @@ -1067,6 +1078,9 @@ void DumpRenderTree::windowCloseRequested() QWebPage* page = qobject_cast<QWebPage*>(sender()); QObject* container = page->parent(); windows.removeAll(container); + // Our use of container->deleteLater() means we need to remove closed pages + // from the org.webkit.qt.DumpRenderTree group explicitly. + DumpRenderTreeSupportQt::webPageSetGroupName(page, ""); container->deleteLater(); } diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h index 3d34443..b3e4e32 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h @@ -60,6 +60,7 @@ class DumpRenderTreeSupportQt; class EventSender; class TextInputController; class GCController; +class PlainTextController; namespace WebCore { @@ -148,6 +149,7 @@ private: EventSender *m_eventSender; TextInputController *m_textInputController; GCController* m_gcController; + PlainTextController* m_plainTextController; NetworkAccessManager* m_networkAccessManager; QFile *m_stdin; diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp index fd7c925..6fb75a5 100644 --- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp @@ -254,9 +254,18 @@ void EventSender::keyDown(const QString& string, const QStringList& modifiers, u modifs = Qt::ControlModifier; s = QString(); } else if (code == 'o' && modifs == Qt::ControlModifier) { + // Mimic the emacs ctrl-o binding on Mac by inserting a paragraph + // separator and then putting the cursor back to its original + // position. Allows us to pass emacs-ctrl-o.html s = QLatin1String("\n"); code = '\n'; modifs = 0; + QKeyEvent event(QEvent::KeyPress, code, modifs, s); + sendEvent(m_page, &event); + QKeyEvent event2(QEvent::KeyRelease, code, modifs, s); + sendEvent(m_page, &event2); + s = QString(); + code = Qt::Key_Left; } else if (code == 'y' && modifs == Qt::ControlModifier) { s = QLatin1String("c"); code = 'c'; diff --git a/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp index ba7e2c3..3aa507f 100644 --- a/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp @@ -48,7 +48,7 @@ void GCController::collectOnAlternateThread(bool waitUntilDone) const DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); } -size_t GCController::getJSObjectCount() const +unsigned int GCController::getJSObjectCount() const { return DumpRenderTreeSupportQt::javaScriptObjectsCount(); } diff --git a/WebKitTools/DumpRenderTree/qt/GCControllerQt.h b/WebKitTools/DumpRenderTree/qt/GCControllerQt.h index ed2a858..d3c83b9 100644 --- a/WebKitTools/DumpRenderTree/qt/GCControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/GCControllerQt.h @@ -43,7 +43,7 @@ public: public slots: void collect() const; void collectOnAlternateThread(bool waitUntilDone) const; - size_t getJSObjectCount() const; + unsigned int getJSObjectCount() const; }; diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index 90a04c4..d36a074 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -284,13 +284,15 @@ void LayoutTestController::setDeferMainResourceDataLoad(bool defer) void LayoutTestController::queueBackNavigation(int howFarBackward) { //qDebug() << ">>>queueBackNavigation" << howFarBackward; - WorkQueue::shared()->queue(new BackItem(howFarBackward, m_drt->webPage())); + for (int i = 0; i != howFarBackward; ++i) + WorkQueue::shared()->queue(new BackItem(1, m_drt->webPage())); } void LayoutTestController::queueForwardNavigation(int howFarForward) { //qDebug() << ">>>queueForwardNavigation" << howFarForward; - WorkQueue::shared()->queue(new ForwardItem(howFarForward, m_drt->webPage())); + for (int i = 0; i != howFarForward; ++i) + WorkQueue::shared()->queue(new ForwardItem(1, m_drt->webPage())); } void LayoutTestController::queueLoad(const QString& url, const QString& target) @@ -796,5 +798,11 @@ void LayoutTestController::removeAllVisitedLinks() DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(true); } +bool LayoutTestController::hasSpellingMarker(int, int) +{ + // FIXME: Implement. + return false; +} + const unsigned LayoutTestController::maxViewWidth = 800; const unsigned LayoutTestController::maxViewHeight = 600; diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h index ec89acb..3684946 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h @@ -219,6 +219,7 @@ public slots: // Empty stub method to keep parity with object model exposed by global LayoutTestController. void abortModal() {} + bool hasSpellingMarker(int from, int length); /* Policy values: 'on', 'auto' or 'off'. diff --git a/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.cpp new file mode 100644 index 0000000..441a37c --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#include "PlainTextControllerQt.h" + +#include "../../../WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h" +#include <QApplication> +#include <QInputMethodEvent> +#include <QKeyEvent> + +PlainTextController::PlainTextController(QWebPage* parent) + : QObject(parent) +{ +} + +QString PlainTextController::plainText(const QVariant& range) +{ + return DumpRenderTreeSupportQt::plainText(range); +} diff --git a/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.h b/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.h new file mode 100644 index 0000000..e78e110 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/PlainTextControllerQt.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PlainTextControllerQt_h +#define PlainTextControllerQt_h + +#include <QList> +#include <QObject> +#include <QString> +#include <QVariant> + +#include "qwebpage.h" + +class PlainTextController : public QObject { + Q_OBJECT +public: + PlainTextController(QWebPage* parent); + +public slots: + QString plainText(const QVariant& range); +}; + +#endif // PlainTextControllerQt_h diff --git a/WebKitTools/DumpRenderTree/qt/TestNetscapePlugin/TestNetscapePlugin.pro b/WebKitTools/DumpRenderTree/qt/TestNetscapePlugin/TestNetscapePlugin.pro index e48b035..740ebb8 100644 --- a/WebKitTools/DumpRenderTree/qt/TestNetscapePlugin/TestNetscapePlugin.pro +++ b/WebKitTools/DumpRenderTree/qt/TestNetscapePlugin/TestNetscapePlugin.pro @@ -31,6 +31,7 @@ SOURCES = PluginObject.cpp \ Tests/DocumentOpenInDestroyStream.cpp \ Tests/NPRuntimeObjectFromDestroyedPlugin.cpp \ Tests/NPRuntimeRemoveProperty.cpp \ + Tests/PassDifferentNPPStruct.cpp \ Tests/PluginScriptableNPObjectInvokeDefault.cpp mac { diff --git a/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp b/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp index 255bfc3..f03c102 100644 --- a/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp @@ -232,7 +232,8 @@ static void CALLBACK notificationListenerProc(HWINEVENTHOOK, DWORD event, HWND h VariantInit(&vChild); HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild); - ASSERT(SUCCEEDED(hr)); + if (FAILED(hr) || !parentObject) + return; COMPtr<IDispatch> childDispatch; if (FAILED(parentObject->get_accChild(vChild, &childDispatch))) { diff --git a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj index 0a02110..fde5e47 100644 --- a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj +++ b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj @@ -287,6 +287,76 @@ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

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

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

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 /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
"
/>
</Configuration>
+ <Configuration
+ Name="Debug_Cairo|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops"
+ CharacterSet="2"
+ >
+ <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"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/NXCOMPAT"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalLibraryDirectories=""
+ SubSystem="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"

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

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

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 /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 6dd609c..d2140d1 100644 --- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -1390,3 +1390,9 @@ void LayoutTestController::setEditingBehavior(const char* editingBehavior) void LayoutTestController::abortModal() { } + +bool LayoutTestController::hasSpellingMarker(int, int) +{ + // FIXME: Implement this. + return false; +} diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index 5fba1cf..eefc587 100644 --- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -505,6 +505,12 @@ void LayoutTestController::abortModal() { } +bool LayoutTestController::hasSpellingMarker(int, int) +{ + // FIXME: Implement + return false; +} + JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const { // FIXME: Implement diff --git a/WebKitTools/EWSTools/create-webkit-git b/WebKitTools/EWSTools/create-webkit-git index 0088a47..0088a47 100644..100755 --- a/WebKitTools/EWSTools/create-webkit-git +++ b/WebKitTools/EWSTools/create-webkit-git diff --git a/WebKitTools/EWSTools/start-queue.sh b/WebKitTools/EWSTools/start-queue.sh index 1e0403f..1e0403f 100644..100755 --- a/WebKitTools/EWSTools/start-queue.sh +++ b/WebKitTools/EWSTools/start-queue.sh diff --git a/WebKitTools/EWSTools/ubuntu-ews-packages b/WebKitTools/EWSTools/ubuntu-ews-packages new file mode 100644 index 0000000..a7917a0 --- /dev/null +++ b/WebKitTools/EWSTools/ubuntu-ews-packages @@ -0,0 +1,61 @@ +subversion +git-core +git-svn +binutils-gold +python-mechanize +libqt4-dev +gperf +bison +fakeroot +flex +g++ +g++-multilib +gperf +autoconf +automake +libapache2-mod-php5 +libasound2-dev +libbz2-dev +libicu-dev +libphonon-dev +libsqlite3-dev +libcairo2-dev +libdbus-glib-1-dev +libgconf2-dev +libgl1-mesa-dev +libglu1-mesa-dev +libglib2.0-dev +libjpeg62-dev +libnspr4-dev +libnss3-dev +libpam0g-dev +libtool +libgtk2.0-dev +libpango1.0-dev +libicu-dev +libxslt-dev +libxslt1-dev +libxss-dev +libsoup2.4-dev +libsqlite3-dev +mesa-common-dev +patch +perl +pkg-config +python +libcupsys2-dev +libgnome-keyring-dev +libcurl4-gnutls-dev +libcupsys2-dev +gperf +bison +flex +libjpeg62-dev +libpng12-dev +libxt-dev +autotools-dev +libgstreamer-plugins-base0.10-dev +libenchant-dev +libgail-dev +gtk-doc-tools +libgeoclue-dev diff --git a/WebKitTools/EWebLauncher/main.c b/WebKitTools/EWebLauncher/main.c index 8965c42..8ba58d8 100644 --- a/WebKitTools/EWebLauncher/main.c +++ b/WebKitTools/EWebLauncher/main.c @@ -132,6 +132,7 @@ typedef struct _Viewport { float initScale; float minScale; float maxScale; + float devicePixelRatio; Eina_Bool userScalable; } Viewport; @@ -402,9 +403,10 @@ on_viewport_changed(void* user_data, Evas_Object* webview, void* event_info) { ELauncher *app = (ELauncher *)user_data; - float w, h, initScale, minScale, maxScale, userScalable; + float w, h, initScale, minScale, maxScale, devicePixelRatio; + Eina_Bool userScalable; - ewk_view_viewport_get(webview, &w, &h, &initScale, &maxScale, &minScale, &userScalable); + ewk_view_viewport_attributes_get(webview, &w, &h, &initScale, &maxScale, &minScale, &devicePixelRatio, &userScalable); /** * If there is no argument in viewport tag, argument's value is -1. @@ -419,6 +421,8 @@ on_viewport_changed(void* user_data, Evas_Object* webview, void* event_info) minScale = ewk_view_zoom_range_min_get(webview); if ((int)maxScale == -1) maxScale = ewk_view_zoom_range_max_get(webview); + if ((int)devicePixelRatio == -1) + devicePixelRatio = ewk_view_device_pixel_ratio_get(webview); if ((int)userScalable == -1) userScalable = EINA_TRUE; @@ -427,7 +431,8 @@ on_viewport_changed(void* user_data, Evas_Object* webview, void* event_info) app->viewport.initScale = initScale; app->viewport.minScale = minScale; app->viewport.maxScale = maxScale; - app->viewport.userScalable = (Eina_Bool)userScalable; + app->viewport.devicePixelRatio = devicePixelRatio; + app->viewport.userScalable = userScalable; viewport_set(); } diff --git a/WebKitTools/GNUmakefile.am b/WebKitTools/GNUmakefile.am index 1599e89..5257ece 100644 --- a/WebKitTools/GNUmakefile.am +++ b/WebKitTools/GNUmakefile.am @@ -6,6 +6,7 @@ noinst_PROGRAMS += \ # GtkLauncher Programs_GtkLauncher_CPPFLAGS = \ -I$(srcdir)/WebKit/gtk \ + -I$(srcdir)/WebCore/platform/network/soup/cache/ \ -I$(top_builddir)/WebKit/gtk \ -I$(top_builddir)/DerivedSources \ $(global_cppflags) \ @@ -38,6 +39,7 @@ dumprendertree_cppflags := \ -I$(srcdir)/WebKitTools/DumpRenderTree/gtk \ -I$(srcdir)/WebKit/gtk \ -I$(srcdir)/WebCore/platform/gtk \ + -I$(srcdir)/WebCore/platform/network/soup/cache/ \ -I$(top_builddir)/WebKit/gtk \ -I$(top_builddir)/DerivedSources \ $(global_cppflags) \ diff --git a/WebKitTools/Makefile b/WebKitTools/Makefile index 57ea097..51ac703 100644 --- a/WebKitTools/Makefile +++ b/WebKitTools/Makefile @@ -1,4 +1,4 @@ -MODULES = DumpRenderTree WebKitTestRunner MiniBrowser +MODULES = DumpRenderTree WebKitTestRunner MiniBrowser TestWebKitAPI all: @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ diff --git a/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj b/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj index f05c351..1a7ccbb 100644 --- a/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj +++ b/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj @@ -256,7 +256,14 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MiniBrowser" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* MiniBrowser */; projectDirPath = ""; projectRoot = ""; diff --git a/WebKitTools/MiniBrowser/mac/AppDelegate.m b/WebKitTools/MiniBrowser/mac/AppDelegate.m index 7098cea..3747e28 100644 --- a/WebKitTools/MiniBrowser/mac/AppDelegate.m +++ b/WebKitTools/MiniBrowser/mac/AppDelegate.m @@ -118,7 +118,6 @@ static void populateVisitedLinks(WKContextRef context, const void *clientInfo) else currentProcessModel = kProcessModelSharedSecondaryProcess; - WKContextRef threadContext = WKContextGetSharedThreadContext(); WKContextHistoryClient historyClient = { 0, self, @@ -128,8 +127,11 @@ static void populateVisitedLinks(WKContextRef context, const void *clientInfo) didUpdateHistoryTitle, populateVisitedLinks }; + + WKContextRef threadContext = WKContextGetSharedThreadContext(); WKContextSetHistoryClient(threadContext, &historyClient); - + WKContextSetCacheModel(threadContext, kWKCacheModelPrimaryWebBrowser); + threadPageNamespace = WKPageNamespaceCreate(threadContext); WKRelease(threadContext); @@ -146,7 +148,8 @@ static void populateVisitedLinks(WKContextRef context, const void *clientInfo) }; WKContextSetInjectedBundleClient(processContext, &bundleClient); WKContextSetHistoryClient(processContext, &historyClient); - + WKContextSetCacheModel(processContext, kWKCacheModelPrimaryWebBrowser); + processPageNamespace = WKPageNamespaceCreate(processContext); WKRelease(processContext); diff --git a/WebKitTools/MiniBrowser/mac/BrowserWindow.xib b/WebKitTools/MiniBrowser/mac/BrowserWindow.xib index 52558a7..5984fe5 100644 --- a/WebKitTools/MiniBrowser/mac/BrowserWindow.xib +++ b/WebKitTools/MiniBrowser/mac/BrowserWindow.xib @@ -2,17 +2,18 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">1060</int> - <string key="IBDocument.SystemVersion">10F569</string> - <string key="IBDocument.InterfaceBuilderVersion">762</string> - <string key="IBDocument.AppKitVersion">1038.29</string> + <string key="IBDocument.SystemVersion">10H545</string> + <string key="IBDocument.InterfaceBuilderVersion">820</string> + <string key="IBDocument.AppKitVersion">1038.35</string> <string key="IBDocument.HIToolboxVersion">461.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> - <string key="NS.object.0">762</string> + <string key="NS.object.0">820</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="2"/> + <integer value="9"/> + <integer value="71"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -92,7 +93,7 @@ </object> <reference key="NSControlView" ref="690456651"/> <bool key="NSDrawsBackground">YES</bool> - <object class="NSColor" key="NSBackgroundColor"> + <object class="NSColor" key="NSBackgroundColor" id="1032961300"> <int key="NSColorSpace">6</int> <string key="NSCatalogName">System</string> <string key="NSColorName">textBackgroundColor</string> @@ -317,6 +318,93 @@ <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSFrameAutosaveName">Main Window</string> </object> + <object class="NSWindowTemplate" id="833876351"> + <int key="NSWindowStyleMask">147</int> + <int key="NSWindowBacking">2</int> + <string key="NSWindowRect">{{230, 479}, {452, 62}}</string> + <int key="NSWTFlags">-461897728</int> + <string key="NSWindowTitle">Find</string> + <string key="NSWindowClass">NSPanel</string> + <nil key="NSViewClass"/> + <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> + <object class="NSView" key="NSWindowView" id="585866018"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">256</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSSearchField" id="841639270"> + <reference key="NSNextResponder" ref="585866018"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{20, 20}, {412, 22}}</string> + <reference key="NSSuperview" ref="585866018"/> + <bool key="NSEnabled">YES</bool> + <object class="NSSearchFieldCell" key="NSCell" id="41426839"> + <int key="NSCellFlags">343014976</int> + <int key="NSCellFlags2">268436544</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="1064395332"/> + <reference key="NSControlView" ref="841639270"/> + <bool key="NSDrawsBackground">YES</bool> + <int key="NSTextBezelStyle">1</int> + <reference key="NSBackgroundColor" ref="1032961300"/> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <reference key="NSColor" ref="365730878"/> + </object> + <object class="NSButtonCell" key="NSSearchButtonCell"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">search</string> + <reference key="NSControlView" ref="841639270"/> + <string key="NSAction">_searchFieldSearch:</string> + <reference key="NSTarget" ref="41426839"/> + <int key="NSButtonFlags">138690815</int> + <int key="NSButtonFlags2">0</int> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <object class="NSButtonCell" key="NSCancelButtonCell"> + <int key="NSCellFlags">130560</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">clear</string> + <object class="NSMutableArray" key="NSAccessibilityOverriddenAttributes"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableDictionary"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>AXDescription</string> + <string>NSAccessibilityEncodedAttributesValueType</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>cancel</string> + <integer value="1"/> + </object> + </object> + </object> + <reference key="NSControlView" ref="841639270"/> + <string key="NSAction">_searchFieldCancel:</string> + <reference key="NSTarget" ref="41426839"/> + <int key="NSButtonFlags">138690815</int> + <int key="NSButtonFlags2">0</int> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <int key="NSMaximumRecents">255</int> + </object> + </object> + </object> + <string key="NSFrameSize">{452, 62}</string> + <reference key="NSSuperview"/> + </object> + <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> + <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + </object> </object> <object class="IBObjectContainer" key="IBDocument.Objects"> <object class="NSMutableArray" key="connectionRecords"> @@ -425,6 +513,22 @@ </object> <int key="connectionID">67</int> </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">find:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="841639270"/> + </object> + <int key="connectionID">76</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">findPanelWindow</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="833876351"/> + </object> + <int key="connectionID">77</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -596,6 +700,38 @@ <reference key="object" ref="128750774"/> <reference key="parent" ref="457655522"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">70</int> + <reference key="object" ref="833876351"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="585866018"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">71</int> + <reference key="object" ref="585866018"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="841639270"/> + </object> + <reference key="parent" ref="833876351"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">74</int> + <reference key="object" ref="841639270"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="41426839"/> + </object> + <reference key="parent" ref="585866018"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">75</int> + <reference key="object" ref="41426839"/> + <reference key="parent" ref="841639270"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -627,13 +763,21 @@ <string>56.CustomClassName</string> <string>57.CustomClassName</string> <string>58.CustomClassName</string> + <string>70.IBEditorWindowLastContentRect</string> + <string>70.IBPluginDependency</string> + <string>70.IBWindowTemplateEditedContentRect</string> + <string>70.NSWindowTemplate.visibleAtLaunch</string> + <string>71.IBPluginDependency</string> + <string>74.IBPluginDependency</string> + <string>75.IBPluginDependency</string> <string>9.IBPluginDependency</string> + <string>9.IBViewBoundsToFrameTransform</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> - <string>{{276, 45}, {776, 608}}</string> + <string>{{404, 157}, {776, 608}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{276, 45}, {776, 608}}</string> + <string>{{404, 157}, {776, 608}}</string> <integer value="1"/> <string>{196, 240}</string> <string>{{202, 428}, {480, 270}}</string> @@ -656,7 +800,15 @@ <string>MBToolbarItem</string> <string>MBToolbarItem</string> <string>MBToolbarItem</string> + <string>{{558, 468}, {452, 62}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{558, 468}, {452, 62}}</string> + <boolean value="NO"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <object class="NSAffineTransform"/> </object> </object> <object class="NSMutableDictionary" key="unlocalizedProperties"> @@ -675,7 +827,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">67</int> + <int key="maxID">77</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -687,13 +839,19 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>dumpSourceToConsole:</string> <string>fetch:</string> + <string>find:</string> <string>forceRepaint:</string> <string>goBack:</string> <string>goForward:</string> <string>reload:</string> <string>removeReinsertWebView:</string> + <string>resetZoom:</string> <string>showHideWebView:</string> + <string>toggleZoomMode:</string> + <string>zoomIn:</string> + <string>zoomOut:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -704,6 +862,86 @@ <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="NSMutableDictionary" key="actionInfosByName"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>dumpSourceToConsole:</string> + <string>fetch:</string> + <string>find:</string> + <string>forceRepaint:</string> + <string>goBack:</string> + <string>goForward:</string> + <string>reload:</string> + <string>removeReinsertWebView:</string> + <string>resetZoom:</string> + <string>showHideWebView:</string> + <string>toggleZoomMode:</string> + <string>zoomIn:</string> + <string>zoomOut:</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBActionInfo"> + <string key="name">dumpSourceToConsole:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">fetch:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">find:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">forceRepaint:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">goBack:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">goForward:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">reload:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">removeReinsertWebView:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">resetZoom:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">showHideWebView:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">toggleZoomMode:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">zoomIn:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">zoomOut:</string> + <string key="candidateClassName">id</string> + </object> </object> </object> <object class="NSMutableDictionary" key="outlets"> @@ -712,6 +950,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>backButton</string> <string>containerView</string> + <string>findPanelWindow</string> <string>forwardButton</string> <string>progressIndicator</string> <string>reloadButton</string> @@ -722,6 +961,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>NSButton</string> <string>NSView</string> + <string>NSWindow</string> <string>NSButton</string> <string>NSProgressIndicator</string> <string>NSButton</string> @@ -729,6 +969,55 @@ <string>NSTextField</string> </object> </object> + <object class="NSMutableDictionary" key="toOneOutletInfosByName"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>backButton</string> + <string>containerView</string> + <string>findPanelWindow</string> + <string>forwardButton</string> + <string>progressIndicator</string> + <string>reloadButton</string> + <string>toolbar</string> + <string>urlText</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBToOneOutletInfo"> + <string key="name">backButton</string> + <string key="candidateClassName">NSButton</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">containerView</string> + <string key="candidateClassName">NSView</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">findPanelWindow</string> + <string key="candidateClassName">NSWindow</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">forwardButton</string> + <string key="candidateClassName">NSButton</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">progressIndicator</string> + <string key="candidateClassName">NSProgressIndicator</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">reloadButton</string> + <string key="candidateClassName">NSButton</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">toolbar</string> + <string key="candidateClassName">NSToolbar</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">urlText</string> + <string key="candidateClassName">NSTextField</string> + </object> + </object> + </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">mac/BrowserWindowController.h</string> @@ -1097,6 +1386,14 @@ </object> </object> <object class="IBPartialClassDescription"> + <string key="className">NSPanel</string> + <string key="superclassName">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSPanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">NSProgressIndicator</string> <string key="superclassName">NSView</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -1120,6 +1417,22 @@ </object> </object> <object class="IBPartialClassDescription"> + <string key="className">NSSearchField</string> + <string key="superclassName">NSTextField</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSSearchField.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSSearchFieldCell</string> + <string key="superclassName">NSTextFieldCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSSearchFieldCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">NSTextField</string> <string key="superclassName">NSControl</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -1203,6 +1516,13 @@ <string key="NS.key.0">showWindow:</string> <string key="NS.object.0">id</string> </object> + <object class="NSMutableDictionary" key="actionInfosByName"> + <string key="NS.key.0">showWindow:</string> + <object class="IBActionInfo" key="NS.object.0"> + <string key="name">showWindow:</string> + <string key="candidateClassName">id</string> + </object> + </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string> diff --git a/WebKitTools/MiniBrowser/mac/BrowserWindowController.h b/WebKitTools/MiniBrowser/mac/BrowserWindowController.h index 98c6bf7..6b6aeb8 100644 --- a/WebKitTools/MiniBrowser/mac/BrowserWindowController.h +++ b/WebKitTools/MiniBrowser/mac/BrowserWindowController.h @@ -31,7 +31,9 @@ IBOutlet NSToolbar *toolbar; IBOutlet NSTextField *urlText; IBOutlet NSView *containerView; - + + IBOutlet NSWindow *findPanelWindow; + WKPageNamespaceRef _pageNamespace; WKView *_webView; BOOL _zoomTextOnly; @@ -60,4 +62,6 @@ - (IBAction)dumpSourceToConsole:(id)sender; +- (IBAction)find:(id)sender; + @end diff --git a/WebKitTools/MiniBrowser/mac/BrowserWindowController.m b/WebKitTools/MiniBrowser/mac/BrowserWindowController.m index cb4c56a..6fad41a 100644 --- a/WebKitTools/MiniBrowser/mac/BrowserWindowController.m +++ b/WebKitTools/MiniBrowser/mac/BrowserWindowController.m @@ -258,7 +258,7 @@ static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, W [(BrowserWindowController *)clientInfo didReceiveServerRedirectForProvisionalLoadForFrame:frame]; } -static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo) +static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo) { [(BrowserWindowController *)clientInfo didFailProvisionalLoadWithErrorForFrame:frame]; } @@ -278,7 +278,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us LOG(@"didFinishLoadForFrame"); } -static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo) +static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo) { [(BrowserWindowController *)clientInfo didFailLoadWithErrorForFrame:frame]; } @@ -484,6 +484,46 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe LOG(@"contentsSizeChanged"); } +static WKRect getWindowFrame(WKPageRef page, const void* clientInfo) +{ + NSRect rect = [[(BrowserWindowController *)clientInfo window] frame]; + WKRect wkRect; + wkRect.origin.x = rect.origin.x; + wkRect.origin.y = rect.origin.y; + wkRect.size.width = rect.size.width; + wkRect.size.height = rect.size.height; + return wkRect; +} + +static void setWindowFrame(WKPageRef page, WKRect rect, const void* clientInfo) +{ + [[(BrowserWindowController *)clientInfo window] setFrame:NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) display:YES]; +} + +static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo) +{ + NSAlert *alert = [[NSAlert alloc] init]; + + WKURLRef wkURL = WKFrameCopyURL(frame); + CFURLRef cfURL = WKURLCopyCFURL(0, wkURL); + WKRelease(wkURL); + + [alert setMessageText:[NSString stringWithFormat:@"BeforeUnload confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]]; + CFRelease(cfURL); + + CFStringRef cfMessage = WKStringCopyCFString(0, message); + [alert setInformativeText:(NSString *)cfMessage]; + CFRelease(cfMessage); + + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + + NSInteger button = [alert runModal]; + [alert release]; + + return button == NSAlertFirstButtonReturn; +} + - (void)awakeFromNib { _webView = [[WKView alloc] initWithFrame:[containerView frame] pageNamespaceRef:_pageNamespace]; @@ -538,7 +578,11 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe setStatusText, mouseDidMoveOverElement, contentsSizeChanged, - 0 /* didNotHandleKeyEvent */ + 0, /* didNotHandleKeyEvent */ + getWindowFrame, + setWindowFrame, + runBeforeUnloadConfirmPanel, + 0 /* didDraw */ }; WKPageSetPageUIClient(_webView.pageRef, &uiClient); } @@ -562,9 +606,15 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe - (void)updateProvisionalURLForFrame:(WKFrameRef)frame { + static WKURLRef emptyURL = 0; + if (!emptyURL) + emptyURL = WKURLCreateWithUTF8CString(""); + WKURLRef url = WKFrameCopyProvisionalURL(frame); - if (!url) + if (WKURLIsEqual(url, emptyURL)) { + WKRelease(url); return; + } CFURLRef cfSourceURL = WKURLCopyCFURL(0, url); WKRelease(url); @@ -616,4 +666,17 @@ static void contentsSizeChanged(WKPageRef page, int width, int height, WKFrameRe [self fetch:nil]; } +- (IBAction)performFindPanelAction:(id)sender +{ + [findPanelWindow makeKeyAndOrderFront:sender]; +} + +- (IBAction)find:(id)sender +{ + WKStringRef string = WKStringCreateWithCFString((CFStringRef)[sender stringValue]); + + WKPageFindString(_webView.pageRef, string, kWKFindDirectionForward, + kWKFindOptionsCaseInsensitive | kWKFindOptionsWrapAround | kWKFindOptionsShowFindIndicator | kWKFindOptionsShowOverlay, 100); +} + @end diff --git a/WebKitTools/QtTestBrowser/mainwindow.cpp b/WebKitTools/QtTestBrowser/mainwindow.cpp index fa8b87d..68002e1 100644 --- a/WebKitTools/QtTestBrowser/mainwindow.cpp +++ b/WebKitTools/QtTestBrowser/mainwindow.cpp @@ -38,6 +38,7 @@ MainWindow::MainWindow() : m_page(new WebPage(this)) , m_toolBar(0) + , urlEdit(0) { setAttribute(Qt::WA_DeleteOnClose); if (qgetenv("QTTESTBROWSER_USE_ARGB_VISUALS").toInt() == 1) @@ -48,6 +49,9 @@ MainWindow::MainWindow() void MainWindow::buildUI() { +#if defined(Q_OS_SYMBIAN) + delete urlEdit; +#endif delete m_toolBar; m_toolBar = addToolBar("Navigation"); diff --git a/WebKitTools/QtTestBrowser/urlloader.cpp b/WebKitTools/QtTestBrowser/urlloader.cpp index abe9902..2ae722b 100644 --- a/WebKitTools/QtTestBrowser/urlloader.cpp +++ b/WebKitTools/QtTestBrowser/urlloader.cpp @@ -30,12 +30,21 @@ #include <QFile> #include <QDebug> +#include <QWebPage> UrlLoader::UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds) : m_frame(frame) , m_stdOut(stdout) , m_loaded(0) + , m_numFramesLoading(0) { + m_checkIfFinishedTimer.setInterval(200); + m_checkIfFinishedTimer.setSingleShot(true); + connect(&m_checkIfFinishedTimer, SIGNAL(timeout()), this, SLOT(checkIfFinished())); + // loadStarted and loadFinished on QWebPage is emitted for each frame/sub-frame + connect(m_frame->page(), SIGNAL(loadStarted()), this, SLOT(frameLoadStarted())); + connect(m_frame->page(), SIGNAL(loadFinished(bool)), this, SLOT(frameLoadFinished())); + if (timeoutSeconds) { m_timeoutTimer.setInterval(timeoutSeconds * 1000); m_timeoutTimer.setSingleShot(true); @@ -45,10 +54,10 @@ UrlLoader::UrlLoader(QWebFrame* frame, const QString& inputFileName, int timeout if (extraTimeSeconds) { m_extraTimeTimer.setInterval(extraTimeSeconds * 1000); m_extraTimeTimer.setSingleShot(true); - connect(frame, SIGNAL(loadFinished(bool)), &m_extraTimeTimer, SLOT(start())); + connect(this, SIGNAL(pageLoadFinished()), &m_extraTimeTimer, SLOT(start())); connect(&m_extraTimeTimer, SIGNAL(timeout()), this, SLOT(loadNext())); } else - connect(frame, SIGNAL(loadFinished(bool)), this, SLOT(loadNext())); + connect(this, SIGNAL(pageLoadFinished()), this, SLOT(loadNext())); loadUrlList(inputFileName); } @@ -56,6 +65,8 @@ void UrlLoader::loadNext() { m_timeoutTimer.stop(); m_extraTimeTimer.stop(); + m_checkIfFinishedTimer.stop(); + m_numFramesLoading = 0; QString qstr; if (getUrl(qstr)) { QUrl url(qstr, QUrl::StrictMode); @@ -68,6 +79,27 @@ void UrlLoader::loadNext() disconnect(m_frame, 0, this, 0); } +void UrlLoader::checkIfFinished() +{ + if (!m_numFramesLoading) + emit pageLoadFinished(); +} + +void UrlLoader::frameLoadStarted() +{ + ++m_numFramesLoading; + m_checkIfFinishedTimer.stop(); +} + +void UrlLoader::frameLoadFinished() +{ + Q_ASSERT(m_numFramesLoading > 0); + --m_numFramesLoading; + // Once our frame has finished loading, wait a moment to call loadNext for cases + // where a sub-frame starts loading or another frame is loaded through JavaScript. + m_checkIfFinishedTimer.start(); +} + void UrlLoader::loadUrlList(const QString& inputFileName) { QFile inputFile(inputFileName); diff --git a/WebKitTools/QtTestBrowser/urlloader.h b/WebKitTools/QtTestBrowser/urlloader.h index e2a6d87..8ce24c0 100644 --- a/WebKitTools/QtTestBrowser/urlloader.h +++ b/WebKitTools/QtTestBrowser/urlloader.h @@ -44,6 +44,14 @@ public: public slots: void loadNext(); +private slots: + void checkIfFinished(); + void frameLoadStarted(); + void frameLoadFinished(); + +signals: + void pageLoadFinished(); + private: void loadUrlList(const QString& inputFileName); bool getUrl(QString& qstr); @@ -56,6 +64,8 @@ private: int m_loaded; QTimer m_timeoutTimer; QTimer m_extraTimeTimer; + QTimer m_checkIfFinishedTimer; + int m_numFramesLoading; }; #endif diff --git a/WebKitTools/QueueStatusServer/app.yaml b/WebKitTools/QueueStatusServer/app.yaml index 76d8963..e320eb0 100644 --- a/WebKitTools/QueueStatusServer/app.yaml +++ b/WebKitTools/QueueStatusServer/app.yaml @@ -3,13 +3,13 @@ version: 1 runtime: python api_version: 1 +builtins: +- datastore_admin: on +- remote_api: on + handlers: - url: /stylesheets static_dir: stylesheets -- url: /remote_api - script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py - login: admin - - url: /.* script: main.py diff --git a/WebKitTools/QueueStatusServer/handlers/dashboard.py b/WebKitTools/QueueStatusServer/handlers/dashboard.py index 26de263..660c595 100644 --- a/WebKitTools/QueueStatusServer/handlers/dashboard.py +++ b/WebKitTools/QueueStatusServer/handlers/dashboard.py @@ -32,31 +32,16 @@ from google.appengine.ext import webapp from google.appengine.ext.webapp import template from model.attachment import Attachment -from model.queues import queues +from model.queues import Queue class Dashboard(webapp.RequestHandler): + # We may want to sort these? + _ordered_queues = Queue.all() + _header_names = [queue.short_name() for queue in _ordered_queues] - # FIXME: This list probably belongs as part of a Queue object in queues.py - # Arrays are bubble_name, queue_name - # FIXME: Can this be unified with StatusBubble._queues_to_display? - _queues_to_display = [ - ["Style", "style-queue"], - ["Cr-Linux", "chromium-ews"], - ["Qt", "qt-ews"], - ["Gtk", "gtk-ews"], - ["Mac", "mac-ews"], - ["Win", "win-ews"], - ["Commit", "commit-queue"], - ] - # Split the zipped list into component parts - _header_names, _ordered_queue_names = zip(*_queues_to_display) - - # This asserts that all of the queues listed above are valid queue names. - assert(reduce(operator.and_, map(lambda name: name in queues, _ordered_queue_names))) - - def _build_bubble(self, attachment, queue_name): - queue_status = attachment.status_for_queue(queue_name) + def _build_bubble(self, attachment, queue): + queue_status = attachment.status_for_queue(queue) bubble = { "status_class": attachment.state_from_queue_status(queue_status) if queue_status else "none", "status_date": queue_status.date if queue_status else None, @@ -67,7 +52,7 @@ class Dashboard(webapp.RequestHandler): row = { "bug_id": attachment.bug_id(), "attachment_id": attachment.id, - "bubbles": [self._build_bubble(attachment, queue_name) for queue_name in self._ordered_queue_names], + "bubbles": [self._build_bubble(attachment, queue) for queue in self._ordered_queues], } return row diff --git a/WebKitTools/QueueStatusServer/handlers/nextpatch.py b/WebKitTools/QueueStatusServer/handlers/nextpatch.py index edb702a..5f6d71d 100644 --- a/WebKitTools/QueueStatusServer/handlers/nextpatch.py +++ b/WebKitTools/QueueStatusServer/handlers/nextpatch.py @@ -26,26 +26,24 @@ # (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 + from google.appengine.ext import db from google.appengine.ext import webapp -from model.workitems import WorkItems -from model.activeworkitems import ActiveWorkItems -from model import queuestatus - -from datetime import datetime, timedelta +from model.queues import Queue class NextPatch(webapp.RequestHandler): - def _get_next_patch_id(self, queue_name): - work_items = WorkItems.all().filter("queue_name =", queue_name).get() - if not work_items: - return None - active_work_items = ActiveWorkItems.get_or_insert(key_name=queue_name, queue_name=queue_name) - return db.run_in_transaction(self._assign_patch, active_work_items.key(), work_items.item_ids) - + # FIXME: This should probably be a post, or an explict lock_patch + # since GET requests shouldn't really modify the datastore. def get(self, queue_name): - patch_id = self._get_next_patch_id(queue_name) + queue = Queue.queue_with_name(queue_name) + if not queue: + self.error(404) + return + # FIXME: Patch assignment should probably move into Queue. + patch_id = db.run_in_transaction(self._assign_patch, queue.active_work_items().key(), queue.work_items().item_ids) if not patch_id: self.error(404) return diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus.py b/WebKitTools/QueueStatusServer/handlers/queuestatus.py index 0259c37..5c31537 100644 --- a/WebKitTools/QueueStatusServer/handlers/queuestatus.py +++ b/WebKitTools/QueueStatusServer/handlers/queuestatus.py @@ -29,15 +29,15 @@ from google.appengine.ext import webapp 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.queues import Queue from model import queuestatus class QueueStatus(webapp.RequestHandler): - def _rows_for_work_items(self, queued_items, active_items): + def _rows_for_work_items(self, queue): + queued_items = queue.work_items() + active_items = queue.active_work_items() if not queued_items: return [] rows = [] @@ -50,14 +50,17 @@ class QueueStatus(webapp.RequestHandler): return rows def get(self, queue_name): - 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) + queue_name = queue_name.lower() + queue = Queue.queue_with_name(queue_name) + if not queue: + self.error(404) + return status_groups = [] last_patch_id = None synthetic_patch_id_counter = 0 + statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue.name()).order("-date").fetch(15) for status in statuses: patch_id = status.active_patch_id if not patch_id or last_patch_id != patch_id: @@ -69,8 +72,8 @@ class QueueStatus(webapp.RequestHandler): last_patch_id = patch_id template_values = { - "display_queue_name": display_name_for_queue(queue_name), - "work_item_rows": self._rows_for_work_items(queued_items, active_items), + "display_queue_name": queue.display_name(), + "work_item_rows": self._rows_for_work_items(queue), "status_groups": status_groups, } self.response.out.write(template.render("templates/queuestatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/handlers/recentstatus.py b/WebKitTools/QueueStatusServer/handlers/recentstatus.py index e2b8c2f..fddc93a 100644 --- a/WebKitTools/QueueStatusServer/handlers/recentstatus.py +++ b/WebKitTools/QueueStatusServer/handlers/recentstatus.py @@ -31,23 +31,24 @@ import datetime from google.appengine.ext import webapp from google.appengine.ext.webapp import template -from model.queues import queues, display_name_for_queue +from model.queues import Queue from model.queuestatus import QueueStatus from model.workitems import WorkItems class QueueBubble(object): """View support class for recentstatus.html""" - def __init__(self, queue_name): - self._queue_name = queue_name - self._work_items = WorkItems.all().filter("queue_name =", queue_name).get() - self._last_status = QueueStatus.all().filter("queue_name =", queue_name).order("-date").get() + def __init__(self, queue): + self._queue = queue + self._work_items = queue.work_items() + self._last_status = QueueStatus.all().filter("queue_name =", queue.name()).order("-date").get() + # FIXME: name and display_name should be replaced by a .queue() accessor. def name(self): - return self._queue_name + return self._queue.name() def display_name(self): - return display_name_for_queue(self._queue_name) + return self._queue.display_name() def _last_status_date(self): if not self._last_status: @@ -88,6 +89,6 @@ class QueuesOverview(webapp.RequestHandler): def get(self): template_values = { - "queues": [QueueBubble(queue_name) for queue_name in queues], + "queues": [QueueBubble(queue) for queue in Queue.all()], } self.response.out.write(template.render("templates/recentstatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/handlers/releasepatch.py b/WebKitTools/QueueStatusServer/handlers/releasepatch.py new file mode 100644 index 0000000..0e46e69 --- /dev/null +++ b/WebKitTools/QueueStatusServer/handlers/releasepatch.py @@ -0,0 +1,62 @@ +# 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 google.appengine.ext import webapp, db +from google.appengine.ext.webapp import template + +from handlers.updatebase import UpdateBase +from model.attachment import Attachment +from model.queues import Queue + + +class ReleasePatch(UpdateBase): + def get(self): + self.response.out.write(template.render("templates/releasepatch.html", None)) + + def post(self): + queue_name = self.request.get("queue_name") + # FIXME: This queue lookup should be shared between handlers. + queue = Queue.queue_with_name(queue_name) + if not queue: + self.error(404) + return + + attachment_id = self._int_from_request("attachment_id") + attachment = Attachment(attachment_id) + last_status = attachment.status_for_queue(queue) + + # Ideally we should use a transaction for the calls to + # WorkItems and ActiveWorkItems. + + # Only remove it from the queue if the last message is not a retry request. + # Allow removing it from the queue even if there is no last_status for easier testing. + if not last_status or not last_status.is_retry_request(): + queue.work_items().remove_work_item(attachment_id) + + # Always release the lock on the item. + queue.active_work_items().expire_item(attachment_id) diff --git a/WebKitTools/QueueStatusServer/handlers/statusbubble.py b/WebKitTools/QueueStatusServer/handlers/statusbubble.py index bfbe958..5690484 100644 --- a/WebKitTools/QueueStatusServer/handlers/statusbubble.py +++ b/WebKitTools/QueueStatusServer/handlers/statusbubble.py @@ -33,33 +33,18 @@ from google.appengine.ext.webapp import template from model.attachment import Attachment from model.workitems import WorkItems -from model.queues import queues, name_with_underscores +from model.queues import Queue class StatusBubble(webapp.RequestHandler): - # FIXME: This list probably belongs as part of a Queue object in queues.py - # Arrays are bubble_name, queue_name - _queues_to_display = [ - ["style", "style-queue"], - ["cr-linux", "chromium-ews"], - ["gtk", "gtk-ews"], - ["qt", "qt-ews"], - ["mac", "mac-ews"], - ["win", "win-ews"], - ] + _queues_to_display = [queue for queue in Queue.all() if queue.is_ews()] - # This asserts that all of the queues listed above are valid queue names. - assert(reduce(operator.and_, map(lambda name_pair: name_pair[1] in queues, _queues_to_display))) - - def _build_bubble(self, queue_name_pair, attachment): - bubble_name = queue_name_pair[0] - queue_name = queue_name_pair[1] - - queue_status = attachment.status_for_queue(queue_name) + def _build_bubble(self, queue, attachment): + queue_status = attachment.status_for_queue(queue) bubble = { - "name": bubble_name, + "name": queue.short_name().lower(), "attachment_id": attachment.id, - "queue_position": attachment.position_in_queue(queue_name), + "queue_position": attachment.position_in_queue(queue), "state": attachment.state_from_queue_status(queue_status) if queue_status else "none", "status": queue_status, } @@ -67,7 +52,7 @@ class StatusBubble(webapp.RequestHandler): def get(self, attachment_id): attachment = Attachment(int(attachment_id)) - bubbles = [self._build_bubble(name_pair, attachment) for name_pair in self._queues_to_display] + bubbles = [self._build_bubble(queue, attachment) for queue in self._queues_to_display] template_values = { "bubbles": bubbles, } diff --git a/WebKitTools/QueueStatusServer/handlers/statusbubble_unittest.py b/WebKitTools/QueueStatusServer/handlers/statusbubble_unittest.py new file mode 100644 index 0000000..3ffbdaf --- /dev/null +++ b/WebKitTools/QueueStatusServer/handlers/statusbubble_unittest.py @@ -0,0 +1,62 @@ +# 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 Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + + +from handlers.statusbubble import StatusBubble +from model.queues import Queue + + +class MockAttachment(object): + def __init__(self): + self.id = 1 + + def status_for_queue(self, queue): + return None + + def position_in_queue(self, queue): + return 1 + + +class StatusBubbleTest(unittest.TestCase): + def test_build_bubble(self): + bubble = StatusBubble() + queue = Queue("mac-ews") + attachment = MockAttachment() + bubble_dict = bubble._build_bubble(queue, attachment) + # FIXME: assertDictEqual (in Python 2.7) would be better to use here. + self.assertEqual(bubble_dict["name"], "mac") + self.assertEqual(bubble_dict["attachment_id"], 1) + self.assertEqual(bubble_dict["queue_position"], 1) + self.assertEqual(bubble_dict["state"], "none") + self.assertEqual(bubble_dict["status"], None) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/handlers/submittoews.py b/WebKitTools/QueueStatusServer/handlers/submittoews.py new file mode 100644 index 0000000..3ba4373 --- /dev/null +++ b/WebKitTools/QueueStatusServer/handlers/submittoews.py @@ -0,0 +1,64 @@ +# 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 google.appengine.ext import webapp, db +from google.appengine.ext.webapp import template + +from handlers.updatebase import UpdateBase +from model.attachment import Attachment +from model.queues import Queue + + +class SubmitToEWS(UpdateBase): + def get(self): + self.response.out.write(template.render("templates/submittoews.html", None)) + + def _should_add_to_ews_queue(self, queue, attachment): + # This assert() is here to make sure we're not submitting to the commit-queue. + # The commit-queue clients check each patch anyway, but there is not sense + # in adding things to the commit-queue when they won't be processed by it. + assert(queue.is_ews()) + latest_status = attachment.status_for_queue(queue) + if not latest_status: + return True + # Only ever re-submit to the EWS if the EWS specifically requested a retry. + # This allows us to restart the EWS feeder queue, without all r? patches + # being retried as a result of that restart! + # In some future version we might add a "force" button to allow the user + # to override this restriction. + return latest_status.is_retry_request() + + def _add_attachment_to_ews_queues(self, attachment): + for queue in Queue.all_ews(): # all_ews() currently includes the style-queue + if self._should_add_to_ews_queue(queue, attachment): + queue.work_items().add_work_item(attachment.id) + + def post(self): + attachment_id = self._int_from_request("attachment_id") + attachment = Attachment(attachment_id) + self._add_attachment_to_ews_queues(attachment) diff --git a/WebKitTools/QueueStatusServer/handlers/updatestatus.py b/WebKitTools/QueueStatusServer/handlers/updatestatus.py index 89858b6..7301101 100644 --- a/WebKitTools/QueueStatusServer/handlers/updatestatus.py +++ b/WebKitTools/QueueStatusServer/handlers/updatestatus.py @@ -31,10 +31,10 @@ 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 + class UpdateStatus(UpdateBase): def get(self): self.response.out.write(template.render("templates/updatestatus.html", None)) @@ -49,7 +49,9 @@ class UpdateStatus(UpdateBase): bug_id = self._int_from_request("bug_id") patch_id = self._int_from_request("patch_id") queue_name = self.request.get("queue_name") + bot_id = self.request.get("bot_id") queue_status.queue_name = queue_name + queue_status.bot_id = bot_id queue_status.active_bug_id = bug_id queue_status.active_patch_id = patch_id queue_status.message = self.request.get("status") @@ -57,24 +59,8 @@ 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/handlers/updateworkitems.py b/WebKitTools/QueueStatusServer/handlers/updateworkitems.py index f91beb4..16a9d49 100644 --- a/WebKitTools/QueueStatusServer/handlers/updateworkitems.py +++ b/WebKitTools/QueueStatusServer/handlers/updateworkitems.py @@ -30,7 +30,7 @@ from google.appengine.ext import webapp, db from google.appengine.ext.webapp import template from handlers.updatebase import UpdateBase -from model.queues import queues +from model.queues import Queue from model.workitems import WorkItems from datetime import datetime @@ -40,16 +40,6 @@ class UpdateWorkItems(UpdateBase): def get(self): self.response.out.write(template.render("templates/updateworkitems.html", None)) - def _work_items_for_queue(self, queue_name): - if queue_name not in queues: - self.response.out.write("\"%s\" is not in queues %s" % (queue_name, queues)) - return None - work_items = WorkItems.all().filter("queue_name =", queue_name).get() - if not work_items: - work_items = WorkItems() - work_items.queue_name = queue_name - return work_items - def _parse_work_items_string(self, items_string): # Our parsing could be much more robust. item_strings = items_string.split(" ") if items_string else [] @@ -57,10 +47,13 @@ class UpdateWorkItems(UpdateBase): def _work_items_from_request(self): queue_name = self.request.get("queue_name") - work_items = self._work_items_for_queue(queue_name) - if not work_items: + queue = Queue.queue_with_name(queue_name) + if not queue: + self.response.out.write("\"%s\" is not in queues %s" % (queue_name, Queue.all())) return None + items_string = self.request.get("work_items") + work_items = queue.work_items() work_items.item_ids = self._parse_work_items_string(items_string) work_items.date = datetime.now() return work_items diff --git a/WebKitTools/QueueStatusServer/main.py b/WebKitTools/QueueStatusServer/main.py index 93227ca..3fbee5c 100644 --- a/WebKitTools/QueueStatusServer/main.py +++ b/WebKitTools/QueueStatusServer/main.py @@ -40,8 +40,10 @@ from handlers.patch import Patch from handlers.patchstatus import PatchStatus from handlers.queuestatus import QueueStatus from handlers.recentstatus import QueuesOverview +from handlers.releasepatch import ReleasePatch from handlers.showresults import ShowResults from handlers.statusbubble import StatusBubble +from handlers.submittoews import SubmitToEWS from handlers.svnrevision import SVNRevision from handlers.updatestatus import UpdateStatus from handlers.updatesvnrevision import UpdateSVNRevision @@ -56,11 +58,13 @@ routes = [ ('/gc', GC), (r'/patch-status/(.*)/(.*)', PatchStatus), (r'/patch/(.*)', Patch), + (r'/submit-to-ews', SubmitToEWS), (r'/results/(.*)', ShowResults), (r'/status-bubble/(.*)', StatusBubble), (r'/svn-revision/(.*)', SVNRevision), (r'/queue-status/(.*)', QueueStatus), (r'/next-patch/(.*)', NextPatch), + (r'/release-patch', ReleasePatch), ('/update-status', UpdateStatus), ('/update-work-items', UpdateWorkItems), ('/update-svn-revision', UpdateSVNRevision), diff --git a/WebKitTools/QueueStatusServer/model/activeworkitems.py b/WebKitTools/QueueStatusServer/model/activeworkitems.py index a244c7d..ab5d7a6 100644 --- a/WebKitTools/QueueStatusServer/model/activeworkitems.py +++ b/WebKitTools/QueueStatusServer/model/activeworkitems.py @@ -31,8 +31,10 @@ from google.appengine.ext import db from datetime import timedelta, datetime import time +from model.queuepropertymixin import QueuePropertyMixin -class ActiveWorkItems(db.Model): + +class ActiveWorkItems(db.Model, QueuePropertyMixin): queue_name = db.StringProperty() item_ids = db.ListProperty(int) item_dates = db.ListProperty(float) @@ -55,10 +57,19 @@ class ActiveWorkItems(db.Model): self.item_ids.append(pair[0]) self.item_dates.append(pair[1]) - def expire_item(self, item_id): + def _remove_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) + @staticmethod + def _expire_item(key, item_id): + active_work_items = db.get(key) + active_work_items._remove_item(item_id) + active_work_items.put() + + def expire_item(self, item_id): + return db.run_in_transaction(self._expire_item, self.key(), item_id) + def deactivate_expired(self, now): one_hour_ago = time.mktime((now - timedelta(minutes=60)).timetuple()) nonexpired_pairs = [pair for pair in self._item_time_pairs() if pair[1] > one_hour_ago] diff --git a/WebKitTools/QueueStatusServer/model/activeworkitems_unitest.py b/WebKitTools/QueueStatusServer/model/activeworkitems_unitest.py new file mode 100644 index 0000000..6d915a1 --- /dev/null +++ b/WebKitTools/QueueStatusServer/model/activeworkitems_unitest.py @@ -0,0 +1,52 @@ +# 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 Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +from datetime import datetime + +from model.activeworkitems import ActiveWorkItems + + +class ActiveWorkItemsTest(unittest.TestCase): + def test_basic(self): + items = ActiveWorkItems() + queued_items = [1, 2] + time = datetime.now() + self.assertEqual(items.next_item(queued_items, time), 1) + self.assertEqual(items.next_item([1], time), None) + self.assertEqual(items.next_item([], time), None) + + self.assertEqual(items.time_for_item(1), time) + self.assertEqual(items.time_for_item(2), None) + + items.expire_item(1) + self.assertEqual(items.time_for_item(1), None) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/model/attachment.py b/WebKitTools/QueueStatusServer/model/attachment.py index 9ae59e8..f98f265 100644 --- a/WebKitTools/QueueStatusServer/model/attachment.py +++ b/WebKitTools/QueueStatusServer/model/attachment.py @@ -30,7 +30,7 @@ import re from google.appengine.api import memcache -from model.queues import queues, name_with_underscores +from model.queues import Queue from model.queuestatus import QueueStatus from model.workitems import WorkItems @@ -87,13 +87,12 @@ class Attachment(object): return "pending" return None - def position_in_queue(self, queue_name): - return self._queue_positions().get(queue_name) + def position_in_queue(self, queue): + return self._queue_positions().get(queue.name()) - def status_for_queue(self, queue_name): - underscore_queue_name = name_with_underscores(queue_name) + def status_for_queue(self, queue): # summary() is a horrible API and should be killed. - queue_summary = self.summary().get(underscore_queue_name) + queue_summary = self.summary().get(queue.name_with_underscores()) if not queue_summary: return None return queue_summary.get("status") @@ -109,16 +108,8 @@ class Attachment(object): return self._cached_queue_positions def _calculate_queue_positions(self): - queue_positions = {} - for work_items in WorkItems.all().fetch(limit=len(queues)): - queue_name = str(work_items.queue_name) - try: - position = work_items.item_ids.index(self.id) - # Display 1-based indecies to the user. - queue_positions[queue_name] = position + 1 - except ValueError, e: - queue_positions[queue_name] = None - return queue_positions + all_work_items = WorkItems.all().fetch(limit=len(Queue.all())) + return dict([(items.queue.name(), items.display_position_for_attachment(self.id)) for items in all_work_items]) # FIXME: This is controller/view code and does not belong in a model. def _fetch_summary(self): @@ -130,11 +121,12 @@ class Attachment(object): return summary summary["bug_id"] = first_status.active_bug_id - for queue in queues: - summary[queue] = None - status = QueueStatus.all().filter('queue_name =', queue).filter('active_patch_id =', self.id).order('-date').get() + for queue in Queue.all(): + summary[queue.name_with_underscores()] = None + status = QueueStatus.all().filter('queue_name =', queue.name()).filter('active_patch_id =', self.id).order('-date').get() if status: - summary[name_with_underscores(queue)] = { + # summary() is a horrible API and should be killed. + summary[queue.name_with_underscores()] = { "state": self.state_from_queue_status(status), "status": status, } diff --git a/WebKitTools/QueueStatusServer/model/queuepropertymixin.py b/WebKitTools/QueueStatusServer/model/queuepropertymixin.py new file mode 100644 index 0000000..a462586 --- /dev/null +++ b/WebKitTools/QueueStatusServer/model/queuepropertymixin.py @@ -0,0 +1,39 @@ +# 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 QueuePropertyMixin(object): + def _queue_getter(self): + # Import at runtime to avoid circular imports + from model.queues import Queue + return Queue.queue_with_name(self.queue_name) + + def _queue_setter(self, queue): + self.queue_name = queue.name() if queue else None + + queue = property(_queue_getter, _queue_setter) diff --git a/WebKitTools/QueueStatusServer/model/queuepropertymixin_unittest.py b/WebKitTools/QueueStatusServer/model/queuepropertymixin_unittest.py new file mode 100644 index 0000000..9a301fe --- /dev/null +++ b/WebKitTools/QueueStatusServer/model/queuepropertymixin_unittest.py @@ -0,0 +1,52 @@ +# 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 Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from model.queuepropertymixin import QueuePropertyMixin +from model.queues import Queue + + +class ObjectWithQueueName(QueuePropertyMixin): + def __init__(self): + self.queue_name = None + + +class QueuePropertyMixinTest(unittest.TestCase): + def test_queue_property(self): + test_object = ObjectWithQueueName() + mac_ews = Queue("mac-ews") + test_object.queue = mac_ews + self.assertEquals(test_object.queue.name(), "mac-ews") + self.assertEquals(test_object.queue_name, "mac-ews") + test_object.queue = None + self.assertEquals(test_object.queue_name, None) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/model/queues.py b/WebKitTools/QueueStatusServer/model/queues.py index 9658dd4..1d46f89 100644 --- a/WebKitTools/QueueStatusServer/model/queues.py +++ b/WebKitTools/QueueStatusServer/model/queues.py @@ -26,39 +26,88 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + import re +from model.activeworkitems import ActiveWorkItems +from model.workitems import WorkItems + + +class Queue(object): + + # Eventually the list of queues may be stored in the data store. + _all_queue_names = [ + "commit-queue", + "style-queue", + "chromium-ews", + "qt-ews", + "gtk-ews", + "mac-ews", + "win-ews", + "efl-ews", + "cr-mac-ews", + ] + + def __init__(self, name): + assert(name in self._all_queue_names) + self._name = name + + @classmethod + def queue_with_name(cls, queue_name): + if queue_name not in cls._all_queue_names: + return None + return Queue(queue_name) + + @classmethod + def all(cls): + return [Queue(name) for name in cls._all_queue_names] + + @classmethod + def all_ews(cls): + return [queue for queue in cls.all() if queue.is_ews()] + + def name(self): + return self._name + + def work_items(self): + key_name = "work-items-%s" % (self._name) + return WorkItems.get_or_insert(key_name=key_name, queue_name=self._name) -queues = [ - "commit-queue", - "style-queue", - "chromium-ews", - "qt-ews", - "gtk-ews", - "mac-ews", - "win-ews", - "efl-ews", -] + # FIXME: active_work_items is a bad name for this lock-table. + def active_work_items(self): + key_name = "active-work-items-%s" % (self._name) + return ActiveWorkItems.get_or_insert(key_name=key_name, queue_name=self._name) + def _caplitalize_after_dash(self, string): + return "-".join([word[0].upper() + word[1:] for word in string.split("-")]) -# FIXME: We need some sort of Queue object. -def _title_case(string): - words = string.split(" ") - words = map(lambda word: word.capitalize(), words) - return " ".join(words) + # For use in status bubbles or table headers + def short_name(self): + # HACK: chromium-ews is incorrectly named. + short_name = self._name.replace("chromium-ews", "Cr-Linux-ews") + short_name = short_name.replace("-ews", "") + short_name = short_name.replace("-queue", "") + return self._caplitalize_after_dash(short_name.capitalize()) + def display_name(self): + # HACK: chromium-ews is incorrectly named. + display_name = self._name.replace("chromium-ews", "cr-linux-ews") -def display_name_for_queue(queue_name): - # HACK: chromium-ews is incorrectly named. - display_name = queue_name.replace("chromium-ews", "cr-linux-ews") + display_name = display_name.replace("-", " ") + display_name = display_name.replace("cr", "chromium") + display_name = display_name.title() + display_name = display_name.replace("Ews", "EWS") + return display_name - display_name = display_name.replace("-", " ") - display_name = display_name.replace("cr", "chromium") - display_name = _title_case(display_name) - display_name = display_name.replace("Ews", "EWS") - return display_name + _dash_regexp = re.compile("-") + def name_with_underscores(self): + return self._dash_regexp.sub("_", self._name) -def name_with_underscores(dashed_name): - regexp = re.compile("-") - return regexp.sub("_", dashed_name) + def is_ews(self): + # Note: The style-queue is just like an EWS in that it has an EWS + # bubble, and it works off of the r? patches. If at some later + # point code wants to not treat the style-queue as an EWS + # (e.g. expecting is_ews() queues to have build results?) + # then we should fix all callers and change this check. + return self._name.endswith("-ews") or self._name == "style-queue" diff --git a/WebKitTools/QueueStatusServer/model/queues_unittest.py b/WebKitTools/QueueStatusServer/model/queues_unittest.py new file mode 100644 index 0000000..33070a8 --- /dev/null +++ b/WebKitTools/QueueStatusServer/model/queues_unittest.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 Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + + +from model.queues import Queue + + +class QueueTest(unittest.TestCase): + def test_is_ews(self): + mac_ews = Queue("mac-ews") + self.assertTrue(mac_ews.is_ews()) + + def test_queue_with_name(self): + self.assertEqual(Queue.queue_with_name("bogus"), None) + self.assertEqual(Queue.queue_with_name("mac-ews").name(), "mac-ews") + self.assertRaises(AssertionError, Queue, ("bogus")) + + def _assert_short_name(self, queue_name, short_name): + self.assertEquals(Queue(queue_name).short_name(), short_name) + + def test_short_name(self): + self._assert_short_name("mac-ews", "Mac") + self._assert_short_name("chromium-ews", "Cr-Linux") + self._assert_short_name("commit-queue", "Commit") + self._assert_short_name("style-queue", "Style") + + def _assert_display_name(self, queue_name, short_name): + self.assertEquals(Queue(queue_name).display_name(), short_name) + + def test_display_name(self): + self._assert_display_name("mac-ews", "Mac EWS") + self._assert_display_name("chromium-ews", "Chromium Linux EWS") + self._assert_display_name("commit-queue", "Commit Queue") + self._assert_display_name("style-queue", "Style Queue") + + def _assert_name_with_underscores(self, queue_name, short_name): + self.assertEquals(Queue(queue_name).name_with_underscores(), short_name) + + def test_name_with_underscores(self): + self._assert_name_with_underscores("mac-ews", "mac_ews") + self._assert_name_with_underscores("chromium-ews", "chromium_ews") + self._assert_name_with_underscores("commit-queue", "commit_queue") + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/model/queuestatus.py b/WebKitTools/QueueStatusServer/model/queuestatus.py index 3d7e599..8002f89 100644 --- a/WebKitTools/QueueStatusServer/model/queuestatus.py +++ b/WebKitTools/QueueStatusServer/model/queuestatus.py @@ -27,12 +27,18 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from google.appengine.ext import db +from model.queuepropertymixin import QueuePropertyMixin -class QueueStatus(db.Model): + +class QueueStatus(db.Model, QueuePropertyMixin): author = db.UserProperty() queue_name = db.StringProperty() + bot_id = db.StringProperty() active_bug_id = db.IntegerProperty() active_patch_id = db.IntegerProperty() message = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) results_file = db.BlobProperty() + + def is_retry_request(self): + return self.message == "Retry" # From AbstractQueue._retry_status diff --git a/WebKitTools/QueueStatusServer/model/svnrevision.py b/WebKitTools/QueueStatusServer/model/svnrevision.py index 70ec0cc..f5d3644 100644 --- a/WebKitTools/QueueStatusServer/model/svnrevision.py +++ b/WebKitTools/QueueStatusServer/model/svnrevision.py @@ -28,6 +28,7 @@ from google.appengine.ext import db + class SVNRevision(db.Model): number = db.IntegerProperty() broken_bots = db.StringListProperty(default=[]) diff --git a/WebKitTools/QueueStatusServer/model/workitems.py b/WebKitTools/QueueStatusServer/model/workitems.py index 3ea59cb..fae6830 100644 --- a/WebKitTools/QueueStatusServer/model/workitems.py +++ b/WebKitTools/QueueStatusServer/model/workitems.py @@ -28,8 +28,40 @@ from google.appengine.ext import db +from model.queuepropertymixin import QueuePropertyMixin -class WorkItems(db.Model): + +class WorkItems(db.Model, QueuePropertyMixin): queue_name = db.StringProperty() item_ids = db.ListProperty(int) date = db.DateTimeProperty(auto_now_add=True) + + def display_position_for_attachment(self, attachment_id): + """Returns a 1-based index corresponding to the position + of the attachment_id in the queue. If the attachment is + not in this queue, this returns None""" + if attachment_id in self.item_ids: + return self.item_ids.index(attachment_id) + 1 + return None + + @staticmethod + def _unguarded_add(key, attachment_id): + work_items = db.get(key) + if attachment_id in work_items.item_ids: + return + work_items.item_ids.append(attachment_id) + work_items.put() + + def add_work_item(self, attachment_id): + db.run_in_transaction(self._unguarded_add, self.key(), attachment_id) + + @staticmethod + def _unguarded_remove(key, attachment_id): + work_items = db.get(key) + if attachment_id in work_items.item_ids: + # We should never have more than one entry for a work item, so we only need remove the first. + work_items.item_ids.remove(attachment_id) + work_items.put() + + def remove_work_item(self, attachment_id): + db.run_in_transaction(self._unguarded_remove, self.key(), attachment_id) diff --git a/WebKitTools/QueueStatusServer/model/workitems_unittest.py b/WebKitTools/QueueStatusServer/model/workitems_unittest.py new file mode 100644 index 0000000..d53302e --- /dev/null +++ b/WebKitTools/QueueStatusServer/model/workitems_unittest.py @@ -0,0 +1,53 @@ +# 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 Research in Motion Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + + +from model.workitems import WorkItems + + +class WorkItemsTest(unittest.TestCase): + def test_display_position_for_attachment(self): + items = WorkItems() + items.item_ids = [0, 1, 2] + self.assertEquals(items.display_position_for_attachment(0), 1) + self.assertEquals(items.display_position_for_attachment(1), 2) + self.assertEquals(items.display_position_for_attachment(3), None) + + def test_remove_work_item(self): + items = WorkItems() + items.item_ids = [0, 1, 2] + items.remove_work_item(0) + self.assertEqual(items.item_ids, [1, 2]) + items.remove_work_item(4) # Should not throw + self.assertEqual(items.item_ids, [1, 2]) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/QueueStatusServer/templates/releasepatch.html b/WebKitTools/QueueStatusServer/templates/releasepatch.html new file mode 100644 index 0000000..cbd6d6f --- /dev/null +++ b/WebKitTools/QueueStatusServer/templates/releasepatch.html @@ -0,0 +1,3 @@ +<form name="release_patch" enctype="multipart/form-data" method="post"> +Patch to release: <input name="attachment_id"> from <input name="queue_name"><input type="submit" value="Release locks and remove from queue"></div> +</form> diff --git a/WebKitTools/QueueStatusServer/templates/statusbubble.html b/WebKitTools/QueueStatusServer/templates/statusbubble.html index 3102741..f11544d 100644 --- a/WebKitTools/QueueStatusServer/templates/statusbubble.html +++ b/WebKitTools/QueueStatusServer/templates/statusbubble.html @@ -39,6 +39,9 @@ body { background-color: #E0B0FF; border: 1px solid #ACA0B3; } +.queue_position { + font-size: 9px; +} </style> <script> function statusDetail(patch_id) { @@ -53,7 +56,7 @@ function statusDetail(patch_id) { title="{{ bubble.status.date|timesince }} ago"{% endif %}> {{ bubble.name }} {% if bubble.queue_position %} - (#{{ bubble.queue_position }}) + <span class="queue_position">#{{ bubble.queue_position }}</span> {% endif %} </div> {% endfor %} diff --git a/WebKitTools/QueueStatusServer/templates/submittoews.html b/WebKitTools/QueueStatusServer/templates/submittoews.html new file mode 100644 index 0000000..fb9d8aa --- /dev/null +++ b/WebKitTools/QueueStatusServer/templates/submittoews.html @@ -0,0 +1,3 @@ +<form name="submit_to_ews" enctype="multipart/form-data" method="post"> +Patch to submit: <input name="attachment_id"><input type="submit" value="Submit for EWS Processing"></div> +</form> diff --git a/WebKitTools/QueueStatusServer/templates/updatestatus.html b/WebKitTools/QueueStatusServer/templates/updatestatus.html index 9343c60..0f98ba4 100644 --- a/WebKitTools/QueueStatusServer/templates/updatestatus.html +++ b/WebKitTools/QueueStatusServer/templates/updatestatus.html @@ -1,6 +1,10 @@ <form name="update_status" enctype="multipart/form-data" method="post"> Update status for a queue: <input name="queue_name"> <div> + Bot Id: + <input name="bot_id"> + </div> + <div> Active Bug Id: <input name="bug_id"> </div> diff --git a/WebKitTools/Scripts/VCSUtils.pm b/WebKitTools/Scripts/VCSUtils.pm index dd08baa..8d7e766 100644 --- a/WebKitTools/Scripts/VCSUtils.pm +++ b/WebKitTools/Scripts/VCSUtils.pm @@ -1,5 +1,6 @@ # Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. # Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com) +# Copyright (C) Research In Motion Limited 2010. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -136,6 +137,18 @@ sub toWindowsLineEndings return $text; } +# Note, this method will not error if the file corresponding to the $source path does not exist. +sub scmMoveOrRenameFile +{ + my ($source, $destination) = @_; + return if ! -e $source; + if (isSVN()) { + system("svn", "move", $source, $destination); + } elsif (isGit()) { + system("git", "mv", $source, $destination); + } +} + # Note, this method will not error if the file corresponding to the path does not exist. sub scmToggleExecutableBit { @@ -1284,6 +1297,16 @@ sub setChangeLogDateAndReviewer($$$) # context. # # This subroutine has unit tests in VCSUtils_unittest.pl. +# +# Returns $changeLogHashRef: +# $changeLogHashRef: a hash reference representing a change log patch. +# patch: a ChangeLog patch equivalent to the given one, but with the +# newest ChangeLog entry inserted at the top of the file, if possible. +# hasOverlappingLines: the value 1 if the change log entry overlaps +# some lines of another change log entry. This can +# happen when deliberately inserting a new ChangeLog +# entry earlier in the file above an entry with +# the same date and author. sub fixChangeLogPatch($) { my $patch = shift; # $patch will only contain patch fragments for ChangeLog. @@ -1301,10 +1324,12 @@ sub fixChangeLogPatch($) } } my $chunkStartIndex = ++$i; + my %changeLogHashRef; # Optimization: do not process if new lines already begin the chunk. if (substr($lines[$i], 0, 1) eq "+") { - return $patch; + $changeLogHashRef{patch} = $patch; + return \%changeLogHashRef; } # Skip to first line of newly added ChangeLog entry. @@ -1321,10 +1346,12 @@ sub fixChangeLogPatch($) } elsif ($firstChar eq " " or $firstChar eq "+") { next; } - return $patch; # Do not change if, for example, "-" or "@" found. + $changeLogHashRef{patch} = $patch; # Do not change if, for example, "-" or "@" found. + return \%changeLogHashRef; } if ($i >= @lines) { - return $patch; # Do not change if date not found. + $changeLogHashRef{patch} = $patch; # Do not change if date not found. + return \%changeLogHashRef; } my $dateStartIndex = $i; @@ -1367,7 +1394,8 @@ sub fixChangeLogPatch($) my $text = substr($line, 1); my $newLine = pop(@overlappingLines); if ($text ne substr($newLine, 1)) { - return $patch; # Unexpected difference. + $changeLogHashRef{patch} = $patch; # Unexpected difference. + return \%changeLogHashRef; } $lines[$i] = "+$text"; } @@ -1379,7 +1407,8 @@ sub fixChangeLogPatch($) # FIXME: Handle errors differently from ChangeLog files that # are okay but should not be altered. That way we can find out # if improvements to the script ever become necessary. - return $patch; # Error: unexpected patch string format. + $changeLogHashRef{patch} = $patch; # Error: unexpected patch string format. + return \%changeLogHashRef; } my $skippedFirstLineCount = $1 - 1; my $oldSourceLineCount = $2; @@ -1388,7 +1417,9 @@ sub fixChangeLogPatch($) if (@overlappingLines != $skippedFirstLineCount) { # This can happen, for example, when deliberately inserting # a new ChangeLog entry earlier in the file. - return $patch; + $changeLogHashRef{hasOverlappingLines} = 1; + $changeLogHashRef{patch} = $patch; + return \%changeLogHashRef; } # If @overlappingLines > 0, this is where we make use of the # assumption that the beginning of the source file was not modified. @@ -1398,7 +1429,8 @@ sub fixChangeLogPatch($) my $targetLineCount = $oldTargetLineCount + @overlappingLines - $deletedLineCount; $lines[$chunkStartIndex - 1] = "@@ -1,$sourceLineCount +1,$targetLineCount @@"; - return join($lineEnding, @lines) . "\n"; # patch(1) expects an extra trailing newline. + $changeLogHashRef{patch} = join($lineEnding, @lines) . "\n"; # patch(1) expects an extra trailing newline. + return \%changeLogHashRef; } # This is a supporting method for runPatchCommand. @@ -1550,7 +1582,12 @@ sub mergeChangeLogs($$$) unlink("${fileNewer}.rej"); open(PATCH, "| patch --force --fuzz=3 --binary $fileNewer > " . File::Spec->devnull()) or die $!; - print PATCH ($traditionalReject ? $patch : fixChangeLogPatch($patch)); + if ($traditionalReject) { + print PATCH $patch; + } else { + my $changeLogHash = fixChangeLogPatch($patch); + print PATCH $changeLogHash->{patch}; + } close(PATCH); my $result = !exitStatus($?); diff --git a/WebKitTools/Scripts/build-api-tests b/WebKitTools/Scripts/build-api-tests new file mode 100755 index 0000000..9db6653 --- /dev/null +++ b/WebKitTools/Scripts/build-api-tests @@ -0,0 +1,70 @@ +#!/usr/bin/perl -w + +# 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. + +use strict; +use File::Basename; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +my $showHelp = 0; +my $clean = 0; + +my $programName = basename($0); +my $usage = <<EOF; +Usage: $programName [options] [options to pass to build system] + --help Show this help message + --clean Clean up the build directory +EOF + +GetOptions( + 'help' => \$showHelp, + 'clean' => \$clean, +); + +if ($showHelp) { + print STDERR $usage; + exit 1; +} + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); + +# Build +chdir "WebKitTools/TestWebKitAPI" or die; + +my $result; +if (isAppleMacWebKit()) { + $result = buildXCodeProject("TestWebKitAPI", $clean, XcodeOptions(), @ARGV); +} elsif (isAppleWinWebKit()) { + $result = buildVisualStudioProject("win/TestWebKitAPI.sln", $clean); +} else { + die "TestWebKitAPI is not supported on this platform.\n"; +} + +exit exitStatus($result); diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit index bc1e8ad..e7f9d1f 100755 --- a/WebKitTools/Scripts/build-webkit +++ b/WebKitTools/Scripts/build-webkit @@ -57,7 +57,7 @@ my $prefixPath; my $makeArgs; my $startTime = time(); -my ($linkPrefetchSupport, $threeDCanvasSupport, $threeDRenderingSupport, $channelMessagingSupport, $clientBasedGeolocationSupport, $databaseSupport, $datagridSupport, $datalistSupport, +my ($linkPrefetchSupport, $accelerated2dCanvasSupport, $threeDCanvasSupport, $threeDRenderingSupport, $channelMessagingSupport, $clientBasedGeolocationSupport, $databaseSupport, $datagridSupport, $datalistSupport, $domStorageSupport, $eventsourceSupport, $filtersSupport, $geolocationSupport, $iconDatabaseSupport, $imageResizerSupport, $indexedDatabaseSupport, $inputSpeechSupport, $javaScriptDebuggerSupport, $mathmlSupport, $offlineWebApplicationSupport, $rubySupport, $systemMallocSupport, $sandboxSupport, $sharedWorkersSupport, $svgSupport, $svgAnimationSupport, $svgAsImageSupport, $svgDOMObjCBindingsSupport, $svgFontsSupport, @@ -69,6 +69,9 @@ my @features = ( { option => "link-prefetch", desc => "Toggle pre fetching support", define => "ENABLE_LINK_PREFETCH", default => 0, value => \$linkPrefetchSupport }, + { option => "accelerated-2d-canvas", desc => "Toggle accelerated 2D canvas support", + define => "ENABLE_ACCELERATED_2D_CANVAS", default => 0, value => \$accelerated2dCanvasSupport }, + { option => "3d-canvas", desc => "Toggle 3D canvas support", define => "ENABLE_3D_CANVAS", default => (isAppleMacWebKit() && !isTiger() && !isLeopard()), value => \$threeDCanvasSupport }, @@ -241,7 +244,7 @@ Usage: $programName [options] [options to pass to build system] --help Show this help message --clean Cleanup the build directory --debug Compile in debug mode - --cairo-win32 Build using Cairo (rather than CoreGraphics) on Windows + --wincairo Build using Cairo (rather than CoreGraphics) on Windows --chromium Build the Chromium port on Mac/Win/Linux --gtk Build the GTK+ port --qt Build the Qt port diff --git a/WebKitTools/Scripts/build-webkittestrunner b/WebKitTools/Scripts/build-webkittestrunner index dbc36d1..6cb6ac8 100755 --- a/WebKitTools/Scripts/build-webkittestrunner +++ b/WebKitTools/Scripts/build-webkittestrunner @@ -63,6 +63,9 @@ if (isAppleMacWebKit()) { $result = buildXCodeProject("WebKitTestRunner", $clean, XcodeOptions(), @ARGV); } elsif (isAppleWinWebKit()) { $result = buildVisualStudioProject("WebKitTestRunner.sln", $clean); +} elsif (isQt()) { + # Qt builds everything in one shot. No need to build anything here. + $result = 0; } else { die "WebKitTestRunner is not supported on this platform.\n"; } diff --git a/WebKitTools/Scripts/check-Xcode-source-file-types b/WebKitTools/Scripts/check-Xcode-source-file-types new file mode 100755 index 0000000..57a70b9 --- /dev/null +++ b/WebKitTools/Scripts/check-Xcode-source-file-types @@ -0,0 +1,168 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007, 2008, 2009, 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 AND ITS CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Script to check that source file extensions match file types in Xcode project.pbxproj files. + +# TODO +# - Add support for file types other than source code files. +# - Can't differentiate between sourcecode.c.h and sourcecode.cpp.h. +# (Hint: Use gcc -x c/objective-c/c++/objective-c++ -E. It will +# take time to check each header using gcc, so make it a switch.) + +use strict; + +use File::Basename; +use File::Spec; +use File::Temp qw(tempfile); +use Getopt::Long; + +# Map of Xcode file types to file extensions. +my %typeExtensionMap = qw( + sourcecode.c.c .c + sourcecode.c.h .h + sourcecode.c.objc .m + sourcecode.cpp.h .h + sourcecode.cpp.cpp .cpp + sourcecode.cpp.objcpp .mm + sourcecode.exports .exp + sourcecode.javascript .js + sourcecode.make .make + sourcecode.mig .defs + sourcecode.yacc .y +); + +# Map of file extensions to Xcode file types. +my %extensionTypeMap = map { $typeExtensionMap{$_} => $_ } keys %typeExtensionMap; +$extensionTypeMap{'.h'} = 'sourcecode.c.h'; # See TODO list. + +my $shouldFixIssues = 0; +my $printWarnings = 1; +my $showHelp; + +my $getOptionsResult = GetOptions( + 'f|fix' => \$shouldFixIssues, + 'h|help' => \$showHelp, + 'w|warnings!' => \$printWarnings, +); + +if (scalar(@ARGV) == 0 && !$showHelp) { + print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n"; + undef $getOptionsResult; +} + +if (!$getOptionsResult || $showHelp) { + print STDERR <<__END__; +Usage: @{[ basename($0) ]} [options] path/to/project.pbxproj [path/to/project.pbxproj ...] + -f|--fix fix mismatched types in Xcode project file + -h|--help show this help message + -w|--[no-]warnings show or suppress warnings (default: show warnings) +__END__ + exit 1; +} + +for my $projectFile (@ARGV) { + my $issuesFound = 0; + my $issuesFixed = 0; + + if (basename($projectFile) =~ /\.xcodeproj$/) { + $projectFile = File::Spec->catfile($projectFile, "project.pbxproj"); + } + + if (basename($projectFile) ne "project.pbxproj") { + print STDERR "WARNING: Not an Xcode project file: $projectFile\n" if $printWarnings; + next; + } + + open(IN, "< $projectFile") || die "Could not open $projectFile: $!"; + + my ($OUT, $tempFileName); + if ($shouldFixIssues) { + ($OUT, $tempFileName) = tempfile( + basename($projectFile) . "-XXXXXXXX", + DIR => dirname($projectFile), + UNLINK => 0, + ); + + # Clean up temp file in case of die() + $SIG{__DIE__} = sub { + close(IN); + close($OUT); + unlink($tempFileName); + }; + } + + # Fast-forward to "Begin PBXFileReference section". + while (my $line = <IN>) { + print $OUT $line if $shouldFixIssues; + last if $line =~ m#^\Q/* Begin PBXFileReference section */\E$#; + } + + while (my $line = <IN>) { + if ($line =~ m#^\Q/* End PBXFileReference section */\E$#) { + print $OUT $line if $shouldFixIssues; + last; + } + + if ($line =~ m#^\s*[A-Z0-9]{24} /\* (.+) \*/\s+=\s+\{.*\s+explicitFileType = (sourcecode[^;]*);.*\s+path = ([^;]+);.*\};$#) { + my $fileName = $1; + my $fileType = $2; + my $filePath = $3; + my (undef, undef, $fileExtension) = map { lc($_) } fileparse(basename($filePath), qr{\.[^.]+$}); + + if (!exists $typeExtensionMap{$fileType}) { + $issuesFound++; + print STDERR "WARNING: Unknown file type '$fileType' for file '$filePath'.\n" if $printWarnings; + } elsif ($typeExtensionMap{$fileType} ne $fileExtension) { + $issuesFound++; + print STDERR "WARNING: Incorrect file type '$fileType' for file '$filePath'.\n" if $printWarnings; + $line =~ s/(\s+)explicitFileType( = )(sourcecode[^;]*);/$1lastKnownFileType$2$extensionTypeMap{$fileExtension};/; + $issuesFixed++ if $shouldFixIssues; + } + } + + print $OUT $line if $shouldFixIssues; + } + + # Output the rest of the file. + print $OUT <IN> if $shouldFixIssues; + + close(IN); + + if ($shouldFixIssues) { + close($OUT); + + unlink($projectFile) || die "Could not delete $projectFile: $!"; + rename($tempFileName, $projectFile) || die "Could not rename $tempFileName to $projectFile: $!"; + } + + if ($printWarnings) { + printf STDERR "%s issues found for $projectFile.\n", ($issuesFound ? $issuesFound : "No"); + print STDERR "$issuesFixed issues fixed for $projectFile.\n" if $issuesFixed && $shouldFixIssues; + print STDERR "NOTE: Open $projectFile in Xcode to let it have its way with the file.\n" if $issuesFixed; + print STDERR "\n"; + } +} + +exit 0; diff --git a/WebKitTools/Scripts/do-file-rename b/WebKitTools/Scripts/do-file-rename index ac5099e..b81b9dc 100755 --- a/WebKitTools/Scripts/do-file-rename +++ b/WebKitTools/Scripts/do-file-rename @@ -29,10 +29,11 @@ # Script to do file renaming. use strict; +use File::Find; use FindBin; use lib $FindBin::Bin; use webkitdirs; -use File::Find; +use VCSUtils; setConfiguration(); chdirWebKit(); @@ -86,7 +87,7 @@ for my $file (sort @paths) { if ($newFile{$file}) { my $newFile = $newFile{$file}; print "Renaming $file to $newFile\n"; - system "svn move $file $newFile"; + scmMoveOrRenameFile($file, $newFile); } } diff --git a/WebKitTools/Scripts/do-webcore-rename b/WebKitTools/Scripts/do-webcore-rename index a1674de..6dcb719 100755 --- a/WebKitTools/Scripts/do-webcore-rename +++ b/WebKitTools/Scripts/do-webcore-rename @@ -207,18 +207,11 @@ for my $file (sort @paths) { } } - -my $isGit = isGit(); - for my $file (sort @paths) { if ($newFile{$file}) { my $newFile = $newFile{$file}; print "Renaming $file to $newFile\n"; - if ($isGit) { - system "git mv $file $newFile"; - } else { - system "svn move $file $newFile"; - } + scmMoveOrRenameFile($file, $newFile); } } diff --git a/WebKitTools/Scripts/generate-forwarding-headers.pl b/WebKitTools/Scripts/generate-forwarding-headers.pl new file mode 100755 index 0000000..ed58702 --- /dev/null +++ b/WebKitTools/Scripts/generate-forwarding-headers.pl @@ -0,0 +1,99 @@ +#!/usr/bin/perl -w +# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged +# 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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. +# +# A script which searches for headers included by WebKit2 files +# and generates forwarding headers for these headers. + +use strict; +use Cwd qw(abs_path realpath); +use File::Find; +use File::Basename; +use File::Spec::Functions; + +my $srcRoot = realpath(File::Spec->catfile(dirname(abs_path($0)), "../..")); +my $incFromRoot = abs_path($ARGV[0]); +my @platformPrefixes = ("android", "brew", "cf", "chromium", "curl", "efl", "gtk", "haiku", "mac", "qt", "soup", "v8", "win", "wx"); +my @frameworks = ( "JavaScriptCore", "WebCore", "WebKit2"); +my @skippedPrefixes; +my @frameworkHeaders; +my $framework; +my %neededHeaders; + +shift; +my $outputDirectory = $ARGV[0]; +shift; +my $platform = $ARGV[0]; + +foreach my $prefix (@platformPrefixes) { + push(@skippedPrefixes, $prefix) unless ($prefix =~ $platform); +} + +foreach (@frameworks) { + $framework = $_; + find(\&collectNeededHeaders, $incFromRoot); + find(\&collectFameworkHeaderPaths, File::Spec->catfile($srcRoot, $framework)); + createForwardingHeadersForFramework(); +} + +sub collectNeededHeaders { + my $filePath = $File::Find::name; + my $file = $_; + if ($filePath =~ '\.h$|\.cpp$') { + open(FILE, "<$file") or die "Could not open $filePath.\n"; + while (<FILE>) { + if (m/^#.*<$framework\/(.*\.h)/) { + $neededHeaders{$1} = 1; + } + } + close(FILE); + } +} + +sub collectFameworkHeaderPaths { + my $filePath = $File::Find::name; + my $file = $_; + if ($filePath =~ '\.h$' && $filePath !~ "ForwardingHeaders" && grep{$file eq $_} keys %neededHeaders) { + my $headerPath = substr($filePath, length("$srcRoot/$framework/")); + push(@frameworkHeaders, $headerPath) unless (grep($headerPath =~ "$_/", @skippedPrefixes)); + } +} + +sub createForwardingHeadersForFramework { + foreach my $header (@frameworkHeaders) { + my $forwardingHeaderPath = File::Spec->catfile($outputDirectory, $framework, basename($header)); + my $expectedIncludeStatement = "#include \"$header\""; + my $foundIncludeStatement = 0; + $foundIncludeStatement = <EXISTING_HEADER> if open(EXISTING_HEADER, "<$forwardingHeaderPath"); + chomp($foundIncludeStatement); + if (! $foundIncludeStatement || $foundIncludeStatement ne $expectedIncludeStatement) { + print "[Creating forwarding header for $framework/$header]\n"; + open(FORWARDING_HEADER, ">$forwardingHeaderPath") or die "Could not open $forwardingHeaderPath."; + print FORWARDING_HEADER "$expectedIncludeStatement\n"; + close(FORWARDING_HEADER); + } + close(EXISTING_HEADER); + } +} + diff --git a/WebKitTools/Scripts/old-run-webkit-tests b/WebKitTools/Scripts/old-run-webkit-tests index 80801dc..a468b4d 100755 --- a/WebKitTools/Scripts/old-run-webkit-tests +++ b/WebKitTools/Scripts/old-run-webkit-tests @@ -49,6 +49,7 @@ use strict; use warnings; +use Config; use Cwd; use Data::Dumper; use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); @@ -157,7 +158,7 @@ my $testHTTP = 1; my $testWebSocket = 1; my $testMedia = 1; my $tmpDir = "/tmp"; -my $testResultsDirectory = File::Spec->catfile($tmpDir, "layout-test-results"); +my $testResultsDirectory = File::Spec->catdir($tmpDir, "layout-test-results"); my $testsPerDumpTool = 1000; my $threaded = 0; # DumpRenderTree has an internal timeout of 30 seconds, so this must be > 30. @@ -180,6 +181,8 @@ if (isWindows() || isMsys()) { # Default to --no-http for wx for now. $testHTTP = 0 if (isWx()); +my $perlInterpreter = "perl"; + my $expectedTag = "expected"; my $actualTag = "actual"; my $prettyDiffTag = "pretty-diff"; @@ -224,7 +227,7 @@ if (isAppleMacWebKit()) { $platform = "gtk"; } elsif (isWx()) { $platform = "wx"; -} elsif (isCygwin()) { +} elsif (isCygwin() || isWindows()) { if (isWindowsXP()) { $platform = "win-xp"; } elsif (isWindowsVista()) { @@ -236,7 +239,7 @@ if (isAppleMacWebKit()) { } } -if (isQt() || isCygwin()) { +if (isQt() || isAppleWinWebKit()) { my $testfontPath = $ENV{"WEBKIT_TESTFONTS"}; if (!$testfontPath || !-d "$testfontPath") { print "The WEBKIT_TESTFONTS environment variable is not defined or not set properly\n"; @@ -364,6 +367,9 @@ if ($useWebKitTestRunner) { $stripEditingCallbacks = 0 unless defined $stripEditingCallbacks; $realPlatform = $platform; $platform = "win-wk2"; + } elsif (isQt()) { + $realPlatform = $platform; + $platform = "qt-wk2"; } } @@ -409,8 +415,11 @@ if (!defined($root)) { my $dumpToolName = $useWebKitTestRunner ? "WebKitTestRunner" : "DumpRenderTree"; -$dumpToolName .= "_debug" if isCygwin() && configurationForVisualStudio() !~ /^Release|Debug_Internal$/; -my $dumpTool = "$productDir/$dumpToolName"; +if (isAppleWinWebKit()) { + $dumpToolName .= "_debug" if configurationForVisualStudio() !~ /^Release|Debug_Internal$/; + $dumpToolName .= $Config{_exe}; +} +my $dumpTool = File::Spec->catfile($productDir, $dumpToolName); die "can't find executable $dumpToolName (looked in $productDir)\n" unless -x $dumpTool; my $imageDiffTool = "$productDir/ImageDiff"; @@ -501,7 +510,7 @@ my $supportedFeaturesResult = ""; if (isCygwin()) { # Collect supported features list setPathForRunningWebKitApp(\%ENV); - my $supportedFeaturesCommand = $dumpTool . " --print-supported-features 2>&1"; + my $supportedFeaturesCommand = "\"$dumpTool\" --print-supported-features 2>&1"; $supportedFeaturesResult = `$supportedFeaturesCommand 2>&1`; } @@ -681,7 +690,7 @@ for my $test (@tests) { my $suffixExpectedHash = ""; if ($pixelTests && !$resetResults) { my $expectedPixelDir = expectedDirectoryForTest($base, 0, "png"); - if (open EXPECTEDHASH, "$expectedPixelDir/$base-$expectedTag.checksum") { + if (open EXPECTEDHASH, File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.checksum")) { my $expectedHash = <EXPECTEDHASH>; chomp($expectedHash); close EXPECTEDHASH; @@ -693,7 +702,34 @@ for my $test (@tests) { if ($test =~ /^http\//) { configureAndOpenHTTPDIfNeeded(); - if ($test !~ /^http\/tests\/local\// && $test !~ /^http\/tests\/ssl\// && $test !~ /^http\/tests\/wml\// && $test !~ /^http\/tests\/media\//) { + if ($test =~ /^http\/tests\/websocket\//) { + if ($test =~ /^websocket\/tests\/local\//) { + my $testPath = "$testDirectory/$test"; + if (isCygwin()) { + $testPath = toWindowsPath($testPath); + } else { + $testPath = canonpath($testPath); + } + print OUT "$testPath\n"; + } else { + if (openWebSocketServerIfNeeded()) { + my $path = canonpath($test); + if ($test =~ /^http\/tests\/websocket\/tests\/ssl\//) { + # wss is disabled until all platforms support pyOpenSSL. + print STDERR "Error: wss is disabled until all platforms support pyOpenSSL."; + } else { + $path =~ s/^http\/tests\///; + print OUT "http://127.0.0.1:$httpdPort/$path\n"; + } + } else { + # We failed to launch the WebSocket server. Display a useful error message rather than attempting + # to run tests that expect the server to be available. + my $errorMessagePath = "$testDirectory/http/tests/websocket/resources/server-failed-to-start.html"; + $errorMessagePath = isCygwin() ? toWindowsPath($errorMessagePath) : canonpath($errorMessagePath); + print OUT "$errorMessagePath\n"; + } + } + } elsif ($test !~ /^http\/tests\/local\// && $test !~ /^http\/tests\/ssl\// && $test !~ /^http\/tests\/wml\// && $test !~ /^http\/tests\/media\//) { my $path = canonpath($test); $path =~ s/^http\/tests\///; print OUT "http://127.0.0.1:$httpdPort/$path$suffixExpectedHash\n"; @@ -710,33 +746,6 @@ for my $test (@tests) { } print OUT "$testPath$suffixExpectedHash\n"; } - } elsif ($test =~ /^websocket\//) { - if ($test =~ /^websocket\/tests\/local\//) { - my $testPath = "$testDirectory/$test"; - if (isCygwin()) { - $testPath = toWindowsPath($testPath); - } else { - $testPath = canonpath($testPath); - } - print OUT "$testPath\n"; - } else { - if (openWebSocketServerIfNeeded()) { - my $path = canonpath($test); - if ($test =~ /^websocket\/tests\/ssl\//) { - # wss is disabled until all platforms support pyOpenSSL. - print STDERR "Error: wss is disabled until all platforms support pyOpenSSL."; - # print OUT "https://127.0.0.1:$webSocketSecurePort/$path\n"; - } else { - print OUT "http://127.0.0.1:$webSocketPort/$path\n"; - } - } else { - # We failed to launch the WebSocket server. Display a useful error message rather than attempting - # to run tests that expect the server to be available. - my $errorMessagePath = "$testDirectory/websocket/resources/server-failed-to-start.html"; - $errorMessagePath = isCygwin() ? toWindowsPath($errorMessagePath) : canonpath($errorMessagePath); - print OUT "$errorMessagePath\n"; - } - } } else { my $testPath = "$testDirectory/$test"; if (isCygwin()) { @@ -763,7 +772,7 @@ for my $test (@tests) { my $isText = isTextOnlyTest($actual); my $expectedDir = expectedDirectoryForTest($base, $isText, $expectedExtension); - $expectedResultPaths{$base} = "$expectedDir/$expectedFileName"; + $expectedResultPaths{$base} = File::Spec->catfile($expectedDir, $expectedFileName); unless ($readResults->{status} eq "success") { my $crashed = $readResults->{status} eq "crashed"; @@ -777,7 +786,7 @@ for my $test (@tests) { my $expected; - if (!$resetResults && open EXPECTED, "<", "$expectedDir/$expectedFileName") { + if (!$resetResults && open EXPECTED, "<", $expectedResultPaths{$base}) { $expected = ""; while (<EXPECTED>) { next if $stripEditingCallbacks && $_ =~ /^EDITING DELEGATE:/; @@ -827,12 +836,13 @@ for my $test (@tests) { if ($actualPNGSize > 0) { my $expectedPixelDir = expectedDirectoryForTest($base, 0, "png"); + my $expectedPNGPath = File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.png"); if (!$resetResults && ($expectedHash ne $actualHash || ($actualHash eq "" && $expectedHash eq ""))) { - if (-f "$expectedPixelDir/$base-$expectedTag.png") { - my $expectedPNGSize = -s "$expectedPixelDir/$base-$expectedTag.png"; + if (-f $expectedPNGPath) { + my $expectedPNGSize = -s $expectedPNGPath; my $expectedPNG = ""; - open EXPECTEDPNG, "$expectedPixelDir/$base-$expectedTag.png"; + open EXPECTEDPNG, $expectedPNGPath; read(EXPECTEDPNG, $expectedPNG, $expectedPNGSize); openDiffTool(); @@ -863,13 +873,14 @@ for my $test (@tests) { } } - if ($resetResults || !-f "$expectedPixelDir/$base-$expectedTag.png") { + if ($resetResults || !-f $expectedPNGPath) { mkpath catfile($expectedPixelDir, dirname($base)) if $testDirectory ne $expectedPixelDir; - writeToFile("$expectedPixelDir/$base-$expectedTag.png", $actualPNG); + writeToFile($expectedPNGPath, $actualPNG); } - if ($actualHash ne "" && ($resetResults || !-f "$expectedPixelDir/$base-$expectedTag.checksum")) { - writeToFile("$expectedPixelDir/$base-$expectedTag.checksum", $actualHash); + my $expectedChecksumPath = File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.checksum"); + if ($actualHash ne "" && ($resetResults || !-f $expectedChecksumPath)) { + writeToFile($expectedChecksumPath, $actualHash); } } @@ -1006,11 +1017,10 @@ for my $test (@tests) { } if ($error) { - my $dir = "$testResultsDirectory/$base"; - $dir =~ s|/([^/]+)$|| or die "Failed to find test name from base\n"; + my $dir = dirname(File::Spec->catdir($testResultsDirectory, $base)); mkpath $dir; - writeToFile("$testResultsDirectory/$base-$errorTag.txt", $error); + writeToFile(File::Spec->catfile($testResultsDirectory, "$base-$errorTag.txt"), $error); $counts{error}++; push @{$tests{error}}, $test; @@ -1118,6 +1128,8 @@ if (isGtk()) { system "WebKitTools/Scripts/run-launcher", @configurationArgs, "file://".$testResults if $launchSafari; } elsif (isCygwin()) { system "cygstart", $testResults if $launchSafari; +} elsif (isWindows()) { + system "start", $testResults if $launchSafari; } else { system "WebKitTools/Scripts/run-safari", @configurationArgs, "-NSOpen", $testResults if $launchSafari; } @@ -1319,7 +1331,7 @@ sub launchWithEnv(\@\%) unshift @{$args}, "\"$allEnvVars\""; my $execScript = File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts execAppWithEnv)); - unshift @{$args}, $execScript; + unshift @{$args}, $perlInterpreter, $execScript; return @{$args}; } @@ -1361,7 +1373,7 @@ sub buildDumpTool($) } my @args = argumentsForConfiguration(); - my $buildProcess = open3($childIn, $childOut, $childErr, "WebKitTools/Scripts/$dumpToolBuildScript", @args) or die "Failed to run build-dumprendertree"; + my $buildProcess = open3($childIn, $childOut, $childErr, $perlInterpreter, File::Spec->catfile(qw(WebKitTools Scripts), $dumpToolBuildScript), @args) or die "Failed to run build-dumprendertree"; close($childIn); waitpid $buildProcess, 0; my $buildResult = $?; @@ -1504,7 +1516,7 @@ sub configureAndOpenHTTPDIfNeeded() sub checkPythonVersion() { # we have not chdir to sourceDir yet. - system sourceDir() . "/WebKitTools/Scripts/ensure-valid-python", "--check-only"; + system $perlInterpreter, File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts ensure-valid-python)), "--check-only"; return exitStatus($?) == 0; } @@ -1607,12 +1619,12 @@ sub expectedDirectoryForTest($;$;$) my ($base, $isText, $expectedExtension) = @_; my @directories = @platformResultHierarchy; - push @directories, map { catdir($platformBaseDirectory, $_) } qw(mac-snowleopard mac) if isCygwin(); + push @directories, map { catdir($platformBaseDirectory, $_) } qw(mac-snowleopard mac) if isAppleWinWebKit(); push @directories, $expectedDirectory; # If we already have expected results, just return their location. foreach my $directory (@directories) { - return $directory if (-f "$directory/$base-$expectedTag.$expectedExtension"); + return $directory if -f File::Spec->catfile($directory, "$base-$expectedTag.$expectedExtension"); } # For cross-platform tests, text-only results should go in the cross-platform directory, @@ -1628,9 +1640,9 @@ sub countFinishedTest($$$$) if ($shouldCheckLeaks) { my $fileName; if ($testsPerDumpTool == 1) { - $fileName = "$testResultsDirectory/$base-leaks.txt"; + $fileName = File::Spec->catfile($testResultsDirectory, "$base-leaks.txt"); } else { - $fileName = "$testResultsDirectory/" . fileNameWithNumber($dumpToolName, $leaksOutputFileNumber) . "-leaks.txt"; + $fileName = File::Spec->catfile($testResultsDirectory, fileNameWithNumber($dumpToolName, $leaksOutputFileNumber) . "-leaks.txt"); } my $leakCount = countAndPrintLeaks($dumpToolName, $dumpToolPID, $fileName); $totalLeaks += $leakCount; @@ -1653,14 +1665,13 @@ sub testCrashedOrTimedOut($$$$$) sampleDumpTool() unless $didCrash; - my $dir = "$testResultsDirectory/$base"; - $dir =~ s|/([^/]+)$|| or die "Failed to find test name from base\n"; + my $dir = dirname(File::Spec->catdir($testResultsDirectory, $base)); mkpath $dir; deleteExpectedAndActualResults($base); if (defined($error) && length($error)) { - writeToFile("$testResultsDirectory/$base-$errorTag.txt", $error); + writeToFile(File::Spec->catfile($testResultsDirectory, "$base-$errorTag.txt"), $error); } recordActualResultsAndDiff($base, $actual); @@ -1898,8 +1909,8 @@ sub recordActualResultsAndDiff($$) my $expectedResultPath = $expectedResultPaths{$base}; my ($expectedResultFileNameMinusExtension, $expectedResultDirectoryPath, $expectedResultExtension) = fileparse($expectedResultPath, qr{\.[^.]+$}); - my $actualResultsPath = "$testResultsDirectory/$base-$actualTag$expectedResultExtension"; - my $copiedExpectedResultsPath = "$testResultsDirectory/$base-$expectedTag$expectedResultExtension"; + my $actualResultsPath = File::Spec->catfile($testResultsDirectory, "$base-$actualTag$expectedResultExtension"); + my $copiedExpectedResultsPath = File::Spec->catfile($testResultsDirectory, "$base-$expectedTag$expectedResultExtension"); mkpath(dirname($actualResultsPath)); writeToFile("$actualResultsPath", $actualResults); @@ -1911,7 +1922,7 @@ sub recordActualResultsAndDiff($$) close EMPTY; } - my $diffOuputBasePath = "$testResultsDirectory/$base"; + my $diffOuputBasePath = File::Spec->catfile($testResultsDirectory, $base); my $diffOutputPath = "$diffOuputBasePath-$diffsTag.txt"; system "diff -u \"$copiedExpectedResultsPath\" \"$actualResultsPath\" > \"$diffOutputPath\""; @@ -2271,7 +2282,7 @@ sub findTestsToRun my @testsToRun = (); for my $test (@ARGV) { - $test =~ s/^($layoutTestsName|$testDirectory)\///; + $test =~ s/^(\Q$layoutTestsName\E|\Q$testDirectory\E)\///; my $fullPath = catfile($testDirectory, $test); if (file_name_is_absolute($test)) { print "can't run test $test outside $testDirectory\n"; diff --git a/WebKitTools/Scripts/run-api-tests b/WebKitTools/Scripts/run-api-tests new file mode 100755 index 0000000..3d08013 --- /dev/null +++ b/WebKitTools/Scripts/run-api-tests @@ -0,0 +1,246 @@ +#!/usr/bin/perl -w + +# 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. + +# Features to add: +# - Command line option to run a single test. +# - Command line option to run all tests in a suite. + +use strict; +use warnings; + +use File::Basename; +use FindBin; +use Getopt::Long qw(:config pass_through); +use IPC::Open3; +use lib $FindBin::Bin; +use webkitdirs; +use Term::ANSIColor qw(:constants); + +sub dumpAllTests(); +sub runAllTests(); +sub runAllTestsInSuite($); +sub runTest($$); +sub populateTests(); +sub buildTestTool(); + +my $showHelp = 0; +my $quiet = 0; +my $dump = 0; + +my $programName = basename($0); +my $usage = <<EOF; +Usage: $programName [options] + --help Show this help message + -q|--quite Less verbose output + -d|--dump-tests Dump the names of testcases without running them +EOF + +GetOptions( + 'help' => \$showHelp, + 'quiet|q' => \$quiet, + 'dump|d' => \$dump, +); + +if ($showHelp) { + print STDERR $usage; + exit 1; +} + +setConfiguration(); +buildTestTool(); +setPathForRunningWebKitApp(\%ENV); +my %testsToRun = populateTests(); + +if ($dump) { + dumpAllTests(); + exit 0; +} + +runAllTests(); + +sub dumpAllTests() +{ + print "Dumping test cases\n"; + print "------------------\n"; + for my $suite (keys %testsToRun) { + print $suite . ":\n"; + print map { " " . $_ . "\n" } @{ $testsToRun{$suite} }; + } + print "------------------\n"; +} + +sub runAllTests() +{ + my $anyFailures = 0; + for my $suite (keys %testsToRun) { + my $failed = runAllTestsInSuite($suite); + if ($failed) { + $anyFailures = 1; + } + } + return $anyFailures; +} + +sub runAllTestsInSuite($) +{ + my ($suite) = @_; + print "Suite: $suite\n"; + + my $anyFailures = 0; + for my $test (@{$testsToRun{$suite}}) { + my $failed = runTest($suite, $test); + if ($failed) { + $anyFailures = 1; + } + } + + return $anyFailures; +} + +sub runTest($$) +{ + my ($suite, $testName) = @_; + my $test = $suite . "/" . $testName; + + print " Test: $testName -> "; + + my $result = 0; + if (isAppleMacWebKit()) { + my $productDir = productDir(); + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + my $apiTesterPath = "$productDir/TestWebKitAPI"; + if (architecture()) { + $result = system "arch", "-" . architecture(), $apiTesterPath, $test, @ARGV; + } else { + $result = system $apiTesterPath, $test, @ARGV; + } + } elsif (isAppleWinWebKit()) { + my $apiTesterNameSuffix; + if (configurationForVisualStudio() =~ /^Release|Debug_Internal$/) { + $apiTesterNameSuffix = ""; + } else { + $apiTesterNameSuffix = "_debug"; + } + my $apiTesterPath = File::Spec->catfile(productDir(), "TestWebKitAPI$apiTesterNameSuffix.exe"); + $result = system $apiTesterPath, $test, @ARGV; + } else { + die "run-api-tests is not supported on this platform.\n" + } + + if ($result == 0) { + print BOLD GREEN, "Passed", RESET, "\n"; + } else { + print BOLD RED, "Failed", RESET, "\n"; + } +} + + +sub populateTests() +{ + my @tests; + + if (isAppleMacWebKit()) { + my $productDir = productDir(); + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + my $apiTesterPath = "$productDir/TestWebKitAPI"; + + my ($pid, $childIn, $childOut); + if (architecture()) { + $pid = open3($childIn, $childOut, ">&STDERR", "arch", "-" . architecture(), $apiTesterPath, "--dump-tests") or die "Failed to build list of tests!"; + } else { + $pid = open3($childIn, $childOut, ">&STDERR", $apiTesterPath, "--dump-tests") or die "Failed to build list of tests!"; + } + close($childIn); + @tests = <$childOut>; + close($childOut); + + waitpid($pid, 0); + my $result = $?; + + if ($result) { + print STDERR "Failed to build list of tests!\n"; + exit exitStatus($result); + } + } elsif (isAppleWinWebKit()) { + my $apiTesterNameSuffix; + if (configurationForVisualStudio() =~ /^Release|Debug_Internal$/) { + $apiTesterNameSuffix = ""; + } else { + $apiTesterNameSuffix = "_debug"; + } + my $apiTesterPath = File::Spec->catfile(productDir(), "TestWebKitAPI$apiTesterNameSuffix.exe"); + open(TESTS, "-|", $apiTesterPath, "--dump-tests") or die $!; + @tests = <TESTS>; + close(TESTS) or die $!; + } else { + die "run-api-tests is not supported on this platform.\n" + } + + my %keyedTests = (); + for my $test (@tests) { + $test =~ s/[\r\n]*$//; + my ($suite, $testName) = split(/\//, $test); + push @{$keyedTests{$suite}}, $testName; + } + + return %keyedTests; +} + +sub buildTestTool() +{ + chdirWebKit(); + + my $buildTestTool = "build-api-tests"; + print STDERR "Running $buildTestTool\n"; + + local *DEVNULL; + my ($childIn, $childOut, $childErr); + if ($quiet) { + open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null"; + $childOut = ">&DEVNULL"; + $childErr = ">&DEVNULL"; + } else { + # When not quiet, let the child use our stdout/stderr. + $childOut = ">&STDOUT"; + $childErr = ">&STDERR"; + } + + my @args = argumentsForConfiguration(); + my $buildProcess = open3($childIn, $childOut, $childErr, "WebKitTools/Scripts/$buildTestTool", @args) or die "Failed to run " . $buildTestTool; + close($childIn); + waitpid $buildProcess, 0; + my $buildResult = $?; + close($childOut); + close($childErr); + + close DEVNULL if ($quiet); + + if ($buildResult) { + print STDERR "Compiling TestWebKitAPI failed!\n"; + exit exitStatus($buildResult); + } +} diff --git a/WebKitTools/Scripts/run-test-webkit-api b/WebKitTools/Scripts/run-test-webkit-api new file mode 100755 index 0000000..dfd85d5 --- /dev/null +++ b/WebKitTools/Scripts/run-test-webkit-api @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w + +# 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. +# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of +# its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Simplified "run" script for launching the WebKit2 estWebKitAPI. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); + +exit exitStatus(runTestWebKitAPI()); diff --git a/WebKitTools/Scripts/run-webkit-tests b/WebKitTools/Scripts/run-webkit-tests index 8fe8360..6b530e1 100755 --- a/WebKitTools/Scripts/run-webkit-tests +++ b/WebKitTools/Scripts/run-webkit-tests @@ -41,6 +41,7 @@ use strict; use warnings; +use File::Spec; use FindBin; use lib $FindBin::Bin; use webkitdirs; @@ -79,5 +80,5 @@ if (useNewRunWebKitTests()) { } } -my $harnessPath = sprintf("%s/%s", relativeScriptsDir(), $harnessName); +my $harnessPath = File::Spec->catfile(relativeScriptsDir(), $harnessName); exec $harnessPath ($harnessPath, @ARGV) or die "Failed to execute $harnessPath"; diff --git a/WebKitTools/Scripts/sort-Xcode-project-file b/WebKitTools/Scripts/sort-Xcode-project-file index 044186f..705b41d 100755 --- a/WebKitTools/Scripts/sort-Xcode-project-file +++ b/WebKitTools/Scripts/sort-Xcode-project-file @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -# Copyright (C) 2007, 2008 Apple Inc. All rights reserved. +# Copyright (C) 2007, 2008, 2009, 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 @@ -31,6 +31,7 @@ use strict; use File::Basename; +use File::Spec; use File::Temp qw(tempfile); use Getopt::Long; @@ -54,7 +55,7 @@ my $getOptionsResult = GetOptions( 'w|warnings!' => \$printWarnings, ); -if (scalar(@ARGV) == 0) { +if (scalar(@ARGV) == 0 && !$showHelp) { print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n"; undef $getOptionsResult; } @@ -69,6 +70,10 @@ __END__ } for my $projectFile (@ARGV) { + if (basename($projectFile) =~ /\.xcodeproj$/) { + $projectFile = File::Spec->catfile($projectFile, "project.pbxproj"); + } + if (basename($projectFile) ne "project.pbxproj") { print STDERR "WARNING: Not an Xcode project file: $projectFile\n" if $printWarnings; next; diff --git a/WebKitTools/Scripts/sunspider-compare-results b/WebKitTools/Scripts/sunspider-compare-results index 8c3f7f5..193ee8f 100755 --- a/WebKitTools/Scripts/sunspider-compare-results +++ b/WebKitTools/Scripts/sunspider-compare-results @@ -55,7 +55,7 @@ Usage: $programName [options] FILE FILE --parse-only Use the parse-only benchmark suite. Same as --suite=parse-only EOF -GetOptions('root=s' => sub { my ($argName, $value) = @_; setConfigurationProductDir(Cwd::abs_path($value)); }, +GetOptions('root=s' => sub { my ($argName, $value) = @_; setConfigurationProductDir(Cwd::abs_path($value)); $root = $value; }, 'suite=s' => \$suite, 'ubench' => \$ubench, 'v8' => \$v8, diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply index 1cf9c01..cab7fb4 100755 --- a/WebKitTools/Scripts/svn-apply +++ b/WebKitTools/Scripts/svn-apply @@ -316,7 +316,8 @@ sub patch($) # Standard patch, patch tool can handle this. if (basename($fullPath) eq "ChangeLog") { my $changeLogDotOrigExisted = -f "${fullPath}.orig"; - my $newPatch = setChangeLogDateAndReviewer(fixChangeLogPatch($patch), $reviewer, $epochTime); + my $changeLogHash = fixChangeLogPatch($patch); + my $newPatch = setChangeLogDateAndReviewer($changeLogHash->{patch}, $reviewer, $epochTime); applyPatch($newPatch, $fullPath, ["--fuzz=3"]); unlink("${fullPath}.orig") if (! $changeLogDotOrigExisted); } else { diff --git a/WebKitTools/Scripts/svn-create-patch b/WebKitTools/Scripts/svn-create-patch index 5aead2e..863998d 100755 --- a/WebKitTools/Scripts/svn-create-patch +++ b/WebKitTools/Scripts/svn-create-patch @@ -232,7 +232,10 @@ sub generateDiff($$) $patch .= $_; } close DIFF; - $patch = fixChangeLogPatch($patch) if basename($file) eq "ChangeLog"; + if (basename($file) eq "ChangeLog") { + my $changeLogHash = fixChangeLogPatch($patch); + $patch = $changeLogHash->{patch}; + } print $patch; if ($fileData->{isBinary}) { print "\n" if ($patch && $patch =~ m/\n\S+$/m); diff --git a/WebKitTools/Scripts/svn-unapply b/WebKitTools/Scripts/svn-unapply index 53ab1b5..1dca11c 100755 --- a/WebKitTools/Scripts/svn-unapply +++ b/WebKitTools/Scripts/svn-unapply @@ -158,7 +158,8 @@ sub patch($) # Standard patch, patch tool can handle this. if (basename($fullPath) eq "ChangeLog") { my $changeLogDotOrigExisted = -f "${fullPath}.orig"; - unapplyPatch(unsetChangeLogDate($fullPath, fixChangeLogPatch($patch)), $fullPath, ["--fuzz=3"]); + my $changeLogHash = fixChangeLogPatch($patch); + unapplyPatch(unsetChangeLogDate($fullPath, $changeLogHash->{patch}), $fullPath, ["--fuzz=3"]); unlink("${fullPath}.orig") if (! $changeLogDotOrigExisted); } else { unapplyPatch($patch, $fullPath); diff --git a/WebKitTools/Scripts/test-webkitpy b/WebKitTools/Scripts/test-webkitpy index be7e870..fcff4b4 100755 --- a/WebKitTools/Scripts/test-webkitpy +++ b/WebKitTools/Scripts/test-webkitpy @@ -227,9 +227,30 @@ def init(command_args, external_package_paths): _log.warn(message) -if __name__ == "__main__": +def _path_from_webkit_root(*components): + webkit_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) + return os.path.join(webkit_root, *components) + + +def _test_import(module_path): + try: + sys.path.append(os.path.dirname(module_path)) + module_name = os.path.basename(module_path) + __import__(module_name) + return True + except Exception, e: + message = "Skipping tests in %s due to failure (%s)." % (module_path, e) + if module_name.endswith("QueueStatusServer"): + message += " This module is optional. The failure is likely due to a missing Google AppEngine install. (http://code.google.com/appengine/downloads.html)" + _log.warn(message) + return False - external_package_paths = [os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'WebKit2', 'Scripts', 'webkit2')] +if __name__ == "__main__": + # FIXME: We should probably test each package separately to avoid naming conflicts. + external_package_paths = [ + _path_from_webkit_root('WebKit2', 'Scripts', 'webkit2'), + _path_from_webkit_root('WebKitTools', 'QueueStatusServer'), + ] init(sys.argv[1:], external_package_paths) # We import the unit test code after init() to ensure that any @@ -240,4 +261,6 @@ if __name__ == "__main__": # running the unit tests. from webkitpy.test.main import Tester + external_package_paths = filter(_test_import, external_package_paths) + Tester().run_tests(sys.argv, external_package_paths) diff --git a/WebKitTools/Scripts/update-webkit-support-libs b/WebKitTools/Scripts/update-webkit-support-libs index 7065293..fa2afd0 100755 --- a/WebKitTools/Scripts/update-webkit-support-libs +++ b/WebKitTools/Scripts/update-webkit-support-libs @@ -38,43 +38,33 @@ use FindBin; use lib $FindBin::Bin; use webkitdirs; -my $expectedMD5 = "a1341aadbcce1ef26dad2b2895457314"; - my $sourceDir = sourceDir(); my $file = "WebKitSupportLibrary"; my $zipFile = "$file.zip"; my $zipDirectory = toUnixPath($ENV{'WEBKITSUPPORTLIBRARIESZIPDIR'}) || $sourceDir; my $pathToZip = File::Spec->catfile($zipDirectory, $zipFile); my $webkitLibrariesDir = toUnixPath($ENV{'WEBKITLIBRARIESDIR'}) || "$sourceDir/WebKitLibraries/win"; +my $versionFile = $file . "Version"; +my $pathToVersionFile = File::Spec->catfile($webkitLibrariesDir, $versionFile); my $tmpDir = File::Spec->rel2abs(File::Temp::tempdir("webkitlibsXXXXXXX", TMPDIR => 1, CLEANUP => 1)); -# Make sure the file zipfile exists and matches the expected MD5 before doing anything. - --f $pathToZip or dieAndInstructToDownload("$zipFile could not be find in your root source directory."); - -`md5sum "$pathToZip"` =~ /^([0-9a-fA-F]{32}).*/ or die "Error running md5sum on \"$pathToZip\""; -my $actualMD5 = $1; -$actualMD5 eq $expectedMD5 or dieAndInstructToDownload("$zipFile is out of date."); - -print "Checking mod-date of $zipFile...\n"; -open MOD, ">$tmpDir/$file.modified" or die "Couldn't open $tmpDir/$file.modified for writing"; -print MOD (stat $pathToZip)[9] . "\n"; -close MOD; +chomp(my $expectedVersion = `curl -s http://developer.apple.com/opensource/internet/$versionFile`); -if (open NEW, "$tmpDir/$file.modified") { - my $new = <NEW>; - close NEW; - - if (open OLD, "$webkitLibrariesDir/$file.modified") { - my $old = <OLD>; - close OLD; - if ($old eq $new) { - print "Current $file is up to date\n"; - exit 0; - } +# Check whether the extracted library is up-to-date. If it is, we don't have anything to do. +if (open VERSION, "<", $pathToVersionFile) { + chomp(my $extractedVersion = <VERSION>); + close VERSION; + if ($extractedVersion eq $expectedVersion) { + print "$file is up-to-date.\n"; + exit; } } +# Check whether the downloaded library is up-to-date. If it isn't, the user needs to download it. +-f $pathToZip or dieAndInstructToDownload("$zipFile could not be found in $zipDirectory."); +chomp(my $zipFileVersion = `unzip -p "$pathToZip" $file/win/$versionFile`); +dieAndInstructToDownload("$zipFile is out-of-date.") if $zipFileVersion ne $expectedVersion; + my $result = system "unzip", "-q", "-d", $tmpDir, $pathToZip; die "Couldn't unzip $zipFile." if $result; @@ -95,9 +85,6 @@ sub wanted File::Find::find(\&wanted, "$tmpDir/$file"); -$result = system "mv", "$tmpDir/$file.modified", $webkitLibrariesDir; -print STDERR "Couldn't move $file.modified to $webkitLibrariesDir" . ".\n" if $result; - print "The $file has been sucessfully installed in\n $webkitLibrariesDir\n"; exit; diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm index 08e14ab..fa85667 100644 --- a/WebKitTools/Scripts/webkitdirs.pm +++ b/WebKitTools/Scripts/webkitdirs.pm @@ -71,7 +71,6 @@ my $isInspectorFrontend; # Variables for Win32 support my $vcBuildPath; -my $windowsTmpPath; my $windowsSourceDir; my $winVersion; my $willUseVCExpressWhenBuilding = 0; @@ -173,9 +172,6 @@ sub determineBaseProductDir my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`; chomp $dosBuildPath; $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath; - } - - if (isAppleWinWebKit()) { my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`; chomp $unixBuildPath; $baseProductDir = $unixBuildPath; @@ -289,8 +285,9 @@ sub determineConfigurationForVisualStudio $configurationForVisualStudio = $configuration; return unless $configuration eq "Debug"; setupCygwinEnv(); - chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`); - $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll"; + my $dir = $ENV{WEBKITLIBRARIESDIR}; + chomp($dir = `cygpath -ua '$dir'`) if isCygwin(); + $configurationForVisualStudio = "Debug_Internal" if -f File::Spec->catfile($dir, "bin", "CoreFoundation_debug.dll"); } sub determineConfigurationProductDir @@ -299,7 +296,7 @@ sub determineConfigurationProductDir determineBaseProductDir(); determineConfiguration(); if (isAppleWinWebKit() && !isWx()) { - $configurationProductDir = "$baseProductDir/bin"; + $configurationProductDir = File::Spec->catdir($baseProductDir, "bin"); } else { # [Gtk][Efl] We don't have Release/Debug configurations in straight # autotool builds (non build-webkit). In this case and if @@ -415,7 +412,7 @@ sub determinePassedConfiguration return if $searchedForPassedConfiguration; $searchedForPassedConfiguration = 1; - my $isWinCairo = checkForArgumentAndRemoveFromARGV("--cairo-win32"); + my $isWinCairo = checkForArgumentAndRemoveFromARGV("--wincairo"); for my $i (0 .. $#ARGV) { my $opt = $ARGV[$i]; @@ -529,7 +526,7 @@ sub installedSafariPath } elsif (isAppleWinWebKit()) { $safariBundle = `"$configurationProductDir/FindSafari.exe"`; $safariBundle =~ s/[\r\n]+$//; - $safariBundle = `cygpath -u '$safariBundle'`; + $safariBundle = `cygpath -u '$safariBundle'` if isCygwin(); $safariBundle =~ s/[\r\n]+$//; $safariBundle .= "Safari.exe"; } @@ -624,7 +621,7 @@ sub builtDylibPathForName # Check to see that all the frameworks are built. sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework. { - return if isCygwin(); + return if isCygwin() || isWindows(); my @frameworks = ("JavaScriptCore", "WebCore"); push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days. for my $framework (@frameworks) { @@ -873,7 +870,7 @@ sub isAppleMacWebKit() sub isAppleWinWebKit() { - return isAppleWebKit() && isCygwin(); + return isAppleWebKit() && (isCygwin() || isWindows()); } sub isPerianInstalled() @@ -1009,8 +1006,8 @@ sub checkRequiredSystemConfig sub determineWindowsSourceDir() { return if $windowsSourceDir; - my $sourceDir = sourceDir(); - chomp($windowsSourceDir = `cygpath -w '$sourceDir'`); + $windowsSourceDir = sourceDir(); + chomp($windowsSourceDir = `cygpath -w '$windowsSourceDir'`) if isCygwin(); } sub windowsSourceDir() @@ -1070,25 +1067,25 @@ sub setupAppleWinEnv() sub setupCygwinEnv() { - return if !isCygwin(); + return if !isCygwin() && !isWindows(); return if $vcBuildPath; my $vsInstallDir; - my $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files"; + my $programFilesPath = $ENV{'PROGRAMFILES(X86)'} || $ENV{'PROGRAMFILES'} || "C:\\Program Files"; if ($ENV{'VSINSTALLDIR'}) { $vsInstallDir = $ENV{'VSINSTALLDIR'}; } else { - $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8"; + $vsInstallDir = File::Spec->catdir($programFilesPath, "Microsoft Visual Studio 8"); } - $vsInstallDir = `cygpath "$vsInstallDir"`; - chomp $vsInstallDir; - $vcBuildPath = "$vsInstallDir/Common7/IDE/devenv.com"; + chomp($vsInstallDir = `cygpath "$vsInstallDir"`) if isCygwin(); + $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE devenv.com)); if (-e $vcBuildPath) { # Visual Studio is installed; we can use pdevenv to build. - $vcBuildPath = File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts pdevenv)); + # FIXME: Make pdevenv work with non-Cygwin Perl. + $vcBuildPath = File::Spec->catfile(sourceDir(), qw(WebKitTools Scripts pdevenv)) if isCygwin(); } else { # Visual Studio not found, try VC++ Express - $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe"; + $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE VCExpress.exe)); if (! -e $vcBuildPath) { print "*************************************************************\n"; print "Cannot find '$vcBuildPath'\n"; @@ -1101,7 +1098,7 @@ sub setupCygwinEnv() $willUseVCExpressWhenBuilding = 1; } - my $qtSDKPath = "$programFilesPath/QuickTime SDK"; + my $qtSDKPath = File::Spec->catdir($programFilesPath, "QuickTime SDK"); if (0 && ! -e $qtSDKPath) { print "*************************************************************\n"; print "Cannot find '$qtSDKPath'\n"; @@ -1111,10 +1108,11 @@ sub setupCygwinEnv() die; } - chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'}; + unless ($ENV{WEBKITLIBRARIESDIR}) { + $ENV{'WEBKITLIBRARIESDIR'} = File::Spec->catdir($sourceDir, "WebKitLibraries", "win"); + chomp($ENV{WEBKITLIBRARIESDIR} = `cygpath -wa $ENV{WEBKITLIBRARIESDIR}`) if isCygwin(); + } - $windowsTmpPath = `cygpath -w /tmp`; - chomp $windowsTmpPath; print "Building results into: ", baseProductDir(), "\n"; print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n"; print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n"; @@ -1197,14 +1195,14 @@ sub buildVisualStudioProject dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding; - chomp(my $winProjectPath = `cygpath -w "$project"`); + chomp($project = `cygpath -w "$project"`) if isCygwin(); my $action = "/build"; if ($clean) { $action = "/clean"; } - my @command = ($vcBuildPath, $winProjectPath, $action, $config); + my @command = ($vcBuildPath, $project, $action, $config); print join(" ", @command), "\n"; return system @command; @@ -1461,6 +1459,9 @@ sub buildCMakeProject($@) print "Calling '$make $makeArgs' in " . $dir . "\n\n"; $result = system "$make $makeArgs"; + if ($result ne 0) { + die "Failed to build $port port\n"; + } chdir ".." or die; } @@ -1530,6 +1531,7 @@ sub buildQMakeProject($@) my @subdirs = ("JavaScriptCore", "WebCore", "WebKit/qt/Api"); if (grep { $_ eq "CONFIG+=webkit2"} @buildArgs) { push @subdirs, "WebKit2"; + push @subdirs, "WebKitTools/WebKitTestRunner"; } for my $subdir (@subdirs) { @@ -1831,4 +1833,22 @@ sub debugWebKitTestRunner return 1; } +sub runTestWebKitAPI +{ + if (isAppleMacWebKit()) { + my $productDir = productDir(); + print "Starting TestWebKitAPI with DYLD_FRAMEWORK_PATH set to point to $productDir.\n"; + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + my $testWebKitAPIPath = "$productDir/TestWebKitAPI"; + if (!isTiger() && architecture()) { + return system "arch", "-" . architecture(), $testWebKitAPIPath, @ARGV; + } else { + return system $testWebKitAPIPath, @ARGV; + } + } + + return 1; +} + 1; diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl index ee258da..a7282c7 100644 --- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl @@ -1,6 +1,7 @@ #!/usr/bin/perl # # Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com) +# Copyright (C) Research In Motion 2010. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -30,7 +31,10 @@ # Unit tests of VCSUtils::fixChangeLogPatch(). -use Test::Simple tests => 12; +use strict; +use warnings; + +use Test::More; use VCSUtils; # The source ChangeLog for these tests is the following: @@ -53,14 +57,10 @@ use VCSUtils; # * File: # * File2: -my $title; -my $in; -my $out; - -# New test -$title = "fixChangeLogPatch: [no change] In-place change."; - -$in = <<'END'; +my @testCaseHashRefs = ( +{ # New test + diffName => "fixChangeLogPatch: [no change] In-place change.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -1,5 +1,5 @@ @@ -71,13 +71,23 @@ $in = <<'END'; Changed some code on 2010-12-22. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] Remove first entry."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -1,5 +1,5 @@ + 2010-12-22 Bob <bob@email.address> + +- Reviewed by Sue. ++ Reviewed by Ray. + + Changed some code on 2010-12-22. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] Remove first entry.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -1,11 +1,3 @@ @@ -93,13 +103,28 @@ $in = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] Remove entry in the middle."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -1,11 +1,3 @@ +-2010-12-22 Bob <bob@email.address> +- +- Reviewed by Ray. +- +- Changed some code on 2010-12-22. +- +- * File: +- + 2010-12-22 Alice <alice@email.address> + + Reviewed by Ray. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] Remove entry in the middle.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@@ -7,10 +7,6 @@ @@ -114,13 +139,27 @@ $in = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] Far apart changes (i.e. more than one chunk)."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@@ -7,10 +7,6 @@ + + * File: + +-2010-12-22 Bob <bob@email.address> +- +- Changed some code on 2010-12-22. +- + 2010-12-22 Alice <alice@email.address> + + Reviewed by Ray. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] Far apart changes (i.e. more than one chunk).", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -7,7 +7,7 @@ @@ -141,13 +180,33 @@ $in = <<'END'; Changed some code on 2010-12-21. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] First line is new line."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -7,7 +7,7 @@ + + * File: + +-2010-12-22 Bob <bob@email.address> ++2010-12-22 Bobby <bob@email.address> + + Changed some code on 2010-12-22. + +@@ -21,7 +21,7 @@ + + * File2: + +-2010-12-21 Bob <bob@email.address> ++2010-12-21 Bobby <bob@email.address> + + Changed some code on 2010-12-21. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] First line is new line.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -1,3 +1,11 @@ @@ -163,13 +222,28 @@ $in = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] No date string."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -1,3 +1,11 @@ ++2009-12-22 Bob <bob@email.address> ++ ++ Reviewed by Ray. ++ ++ Changed some more code on 2009-12-22. ++ ++ * File: ++ + 2009-12-22 Alice <alice@email.address> + + Reviewed by Ray. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] No date string.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -6,6 +6,7 @@ @@ -181,13 +255,24 @@ $in = <<'END'; 2009-12-21 Alice <alice@email.address> END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] New entry inserted in middle."; - -$in = <<'END'; + expectedReturn => { + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -6,6 +6,7 @@ + + * File: + * File2: ++ * File3: + + 2009-12-21 Alice <alice@email.address> + +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] New entry inserted in middle.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -11,6 +11,14 @@ @@ -206,13 +291,32 @@ $in = <<'END'; * File: END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: [no change] New entry inserted earlier in the file, but after an entry with the same author and date."; - -$in = <<'END'; + expectedReturn => { + hasOverlappingLines => 1, + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -11,6 +11,14 @@ + + Reviewed by Ray. + ++ Changed some more code on 2009-12-21. ++ ++ * File: ++ ++2009-12-21 Alice <alice@email.address> ++ ++ Reviewed by Ray. ++ + Changed some code on 2009-12-21. + + * File: +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: [no change] New entry inserted earlier in the file, but after an entry with the same author and date.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -70,6 +70,14 @@ @@ -231,13 +335,32 @@ $in = <<'END'; Changed some code on 2009-12-22. END - -ok(fixChangeLogPatch($in) eq $in, $title); - -# New test -$title = "fixChangeLogPatch: Leading context includes first line."; - -$in = <<'END'; + expectedReturn => { + hasOverlappingLines => 1, + patch => <<'END', +--- ChangeLog ++++ ChangeLog +@@ -70,6 +70,14 @@ + + 2009-12-22 Alice <alice@email.address> + ++ Reviewed by Sue. ++ ++ Changed some more code on 2009-12-22. ++ ++ * File: ++ ++2009-12-22 Alice <alice@email.address> ++ + Reviewed by Ray. + + Changed some code on 2009-12-22. +END + } +}, +{ # New test + diffName => "fixChangeLogPatch: Leading context includes first line.", + inputText => <<'END', --- ChangeLog +++ ChangeLog @@ -1,5 +1,13 @@ @@ -255,8 +378,8 @@ $in = <<'END'; Changed some code on 2009-12-22. END - -$out = <<'END'; + expectedReturn => { + patch => <<'END', --- ChangeLog +++ ChangeLog @@ -1,3 +1,11 @@ @@ -272,13 +395,11 @@ $out = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $out, $title); - -# New test -$title = "fixChangeLogPatch: Leading context does not include first line."; - -$in = <<'END'; + } +}, +{ # New test + diffName => "fixChangeLogPatch: Leading context does not include first line.", + inputText => <<'END', @@ -2,6 +2,14 @@ Reviewed by Ray. @@ -295,8 +416,8 @@ $in = <<'END'; * File: END - -$out = <<'END'; + expectedReturn => { + patch => <<'END', @@ -1,3 +1,11 @@ +2009-12-22 Alice <alice@email.address> + @@ -310,18 +431,17 @@ $out = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $out, $title); - -# New test -$title = "fixChangeLogPatch: Non-consecutive line additions."; + } +}, +{ # New test + diffName => "fixChangeLogPatch: Non-consecutive line additions.", # This can occur, for example, if the new ChangeLog entry includes # trailing white space in the first blank line but not the second. # A diff command can then match the second blank line of the new # ChangeLog entry with the first blank line of the old. # The svn diff command with the default --diff-cmd has done this. -$in = <<'END'; + inputText => <<'END', @@ -1,5 +1,11 @@ 2009-12-22 Alice <alice@email.address> + <pretend-whitespace> @@ -335,8 +455,8 @@ $in = <<'END'; Changed some code on 2009-12-22. END - -$out = <<'END'; + expectedReturn => { + patch => <<'END', @@ -1,3 +1,9 @@ +2009-12-22 Alice <alice@email.address> + <pretend-whitespace> @@ -348,13 +468,11 @@ $out = <<'END'; Reviewed by Ray. END - -ok(fixChangeLogPatch($in) eq $out, $title); - -# New test -$title = "fixChangeLogPatch: Additional edits after new entry."; - -$in = <<'END'; + } +}, +{ # New test + diffName => "fixChangeLogPatch: Additional edits after new entry.", + inputText => <<'END', @@ -2,10 +2,17 @@ Reviewed by Ray. @@ -375,8 +493,8 @@ $in = <<'END'; 2009-12-21 Alice <alice@email.address> END - -$out = <<'END'; + expectedReturn => { + patch => <<'END', @@ -1,11 +1,18 @@ +2009-12-22 Alice <alice@email.address> + @@ -398,5 +516,18 @@ $out = <<'END'; 2009-12-21 Alice <alice@email.address> END + } +}, +); + +my $testCasesCount = @testCaseHashRefs; +plan(tests => $testCasesCount); # Total number of assertions. -ok(fixChangeLogPatch($in) eq $out, $title); +foreach my $testCase (@testCaseHashRefs) { + my $testNameStart = "fixChangeLogPatch(): $testCase->{diffName}: comparing"; + + my $got = VCSUtils::fixChangeLogPatch($testCase->{inputText}); + my $expectedReturn = $testCase->{expectedReturn}; + + is_deeply($got, $expectedReturn, "$testNameStart return value."); +} diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/api.py b/WebKitTools/Scripts/webkitpy/common/checkout/api.py index ca28e32..72cad8d 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/api.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/api.py @@ -83,13 +83,20 @@ class Checkout(object): def bug_id_for_revision(self, revision): return self.commit_info_for_revision(revision).bug_id() - def modified_changelogs(self, git_commit): + def _modified_files_matching_predicate(self, git_commit, predicate, changed_files=None): # SCM returns paths relative to scm.checkout_root # Callers (especially those using the ChangeLog class) may # expect absolute paths, so this method returns absolute paths. - changed_files = self._scm.changed_files(git_commit) + if not changed_files: + changed_files = self._scm.changed_files(git_commit) absolute_paths = [os.path.join(self._scm.checkout_root, path) for path in changed_files] - return [path for path in absolute_paths if self._is_path_to_changelog(path)] + return [path for path in absolute_paths if predicate(path)] + + def modified_changelogs(self, git_commit, changed_files=None): + return self._modified_files_matching_predicate(git_commit, self._is_path_to_changelog, changed_files=changed_files) + + def modified_non_changelogs(self, git_commit, changed_files=None): + return self._modified_files_matching_predicate(git_commit, lambda path: not self._is_path_to_changelog(path), changed_files=changed_files) def commit_message_for_this_commit(self, git_commit): changelog_paths = self.modified_changelogs(git_commit) @@ -109,6 +116,17 @@ class Checkout(object): # FIXME: We should sort and label the ChangeLog messages like commit-log-editor does. return CommitMessage("".join(changelog_messages).splitlines()) + def recent_commit_infos_for_files(self, paths): + revisions = set(sum(map(self._scm.revisions_changing_file, paths), [])) + return set(map(self.commit_info_for_revision, revisions)) + + def suggested_reviewers(self, git_commit): + changed_files = self.modified_non_changelogs(git_commit) + commit_infos = self.recent_commit_infos_for_files(changed_files) + reviewers = [commit_info.reviewer() for commit_info in commit_infos if commit_info.reviewer()] + reviewers.extend([commit_info.author() for commit_info in commit_infos if commit_info.author() and commit_info.author().can_review]) + return sorted(set(reviewers)) + def bug_id_for_this_commit(self, git_commit): try: return parse_bug_id(self.commit_message_for_this_commit(git_commit).message()) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py index fdfd879..d7bd95e 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py @@ -173,3 +173,24 @@ class CheckoutTest(unittest.TestCase): checkout = Checkout(scm) expected_changlogs = ["/foo/bar/ChangeLog", "/foo/bar/relative/path/ChangeLog"] self.assertEqual(checkout.modified_changelogs(git_commit=None), expected_changlogs) + + def test_suggested_reviewers(self): + def mock_changelog_entries_for_revision(revision): + if revision % 2 == 0: + return [ChangeLogEntry(_changelog1entry1)] + return [ChangeLogEntry(_changelog1entry2)] + + def mock_revisions_changing_file(path, limit=5): + if path.endswith("ChangeLog"): + return [3] + return [4, 8] + + scm = Mock() + scm.checkout_root = "/foo/bar" + scm.changed_files = lambda git_commit: ["file1", "file2", "relative/path/ChangeLog"] + scm.revisions_changing_file = mock_revisions_changing_file + checkout = Checkout(scm) + checkout.changelog_entries_for_revision = mock_changelog_entries_for_revision + reviewers = checkout.suggested_reviewers(git_commit=None) + reviewer_names = [reviewer.full_name for reviewer in reviewers] + self.assertEqual(reviewer_names, [u'Tor Arne Vestb\xf8']) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/diff_parser.py b/WebKitTools/Scripts/webkitpy/common/checkout/diff_parser.py index d8ebae6..a6ea756 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/diff_parser.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/diff_parser.py @@ -33,9 +33,13 @@ import re _log = logging.getLogger("webkitpy.common.checkout.diff_parser") + +# FIXME: This is broken. We should compile our regexps up-front +# instead of using a custom cache. _regexp_compile_cache = {} +# FIXME: This function should be removed. def match(pattern, string): """Matches the string with the pattern, caching the compiled regexp.""" if not pattern in _regexp_compile_cache: @@ -43,12 +47,15 @@ def match(pattern, string): return _regexp_compile_cache[pattern].match(string) +# FIXME: This belongs on DiffParser (e.g. as to_svn_diff()). def git_diff_to_svn_diff(line): """Converts a git formatted diff line to a svn formatted line. Args: line: A string representing a line of the diff. """ + # FIXME: This list should be a class member on DiffParser. + # These regexp patterns should be compiled once instead of every time. conversion_patterns = (("^diff --git \w/(.+) \w/(?P<FilePath>.+)", lambda matched: "Index: " + matched.group('FilePath') + "\n"), ("^new file.*", lambda matched: "\n"), ("^index [0-9a-f]{7}\.\.[0-9a-f]{7} [0-9]{6}", lambda matched: "===================================================================\n"), @@ -62,6 +69,7 @@ def git_diff_to_svn_diff(line): return line +# FIXME: This method belongs on DiffParser def get_diff_converter(first_diff_line): """Gets a converter function of diff lines. @@ -80,7 +88,7 @@ _DECLARED_FILE_PATH = 2 _PROCESSING_CHUNK = 3 -class DiffFile: +class DiffFile(object): """Contains the information for one file in a patch. The field "lines" is a list which contains tuples in this format: @@ -88,6 +96,13 @@ class DiffFile: If deleted_line_number is zero, it means this line is newly added. If new_line_number is zero, it means this line is deleted. """ + # FIXME: Tuples generally grow into classes. We should consider + # adding a DiffLine object. + + def added_or_modified_line_numbers(self): + # This logic was moved from patchreader.py, but may not be + # the right API for this object long-term. + return [line[1] for line in self.lines if not line[0]] def __init__(self, filename): self.filename = filename @@ -103,13 +118,14 @@ class DiffFile: self.lines.append((deleted_line_number, new_line_number, line)) -class DiffParser: +class DiffParser(object): """A parser for a patch file. The field "files" is a dict whose key is the filename and value is a DiffFile object. """ + # FIXME: This function is way too long and needs to be broken up. def __init__(self, diff_input): """Parses a diff. diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py index 793d96d..4bd9ed6 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py @@ -245,7 +245,10 @@ class SCM: def changed_files(self, git_commit=None): self._subclass_must_implement() - def changed_files_for_revision(self): + def changed_files_for_revision(self, revision): + self._subclass_must_implement() + + def revisions_changing_file(self, path, limit=5): self._subclass_must_implement() def added_files(self): @@ -257,7 +260,7 @@ class SCM: def display_name(self): self._subclass_must_implement() - def create_patch(self, git_commit=None): + def create_patch(self, git_commit=None, changed_files=[]): self._subclass_must_implement() def committer_email_for_revision(self, revision): @@ -427,6 +430,16 @@ class SVN(SCM): status_command = ["svn", "diff", "--summarize", "-c", revision] return self.run_status_and_extract_filenames(status_command, self._status_regexp("ACDMR")) + def revisions_changing_file(self, path, limit=5): + revisions = [] + log_command = ['svn', 'log', '--quiet', '--limit=%s' % limit, path] + for line in self.run(log_command, cwd=self.checkout_root).splitlines(): + match = re.search('^r(?P<revision>\d+) ', line) + if not match: + continue + revisions.append(int(match.group('revision'))) + return revisions + def conflicted_files(self): return self.run_status_and_extract_filenames(self.status_command(), self._status_regexp("C")) @@ -444,11 +457,11 @@ class SVN(SCM): return "svn" # FIXME: This method should be on Checkout. - def create_patch(self, git_commit=None): + def create_patch(self, git_commit=None, changed_files=[]): """Returns a byte array (str()) representing the patch file. Patch files are effectively binary since they may contain files of multiple different encodings.""" - return self.run([self.script_path("svn-create-patch")], + return self.run([self.script_path("svn-create-patch")] + changed_files, cwd=self.checkout_root, return_stderr=False, decode_output=False) @@ -653,6 +666,10 @@ class Git(SCM): commit_id = self.git_commit_from_svn_revision(revision) return self._changes_files_for_commit(commit_id) + def revisions_changing_file(self, path, limit=5): + commit_ids = self.run(["git", "log", "--pretty=format:%H", "-%s" % limit, path]).splitlines() + return filter(lambda revision: revision, map(self.svn_revision_from_git_commit, commit_ids)) + def conflicted_files(self): # We do not need to pass decode_output for this diff command # as we're passing --name-status which does not output any data. @@ -672,12 +689,12 @@ class Git(SCM): def display_name(self): return "git" - def create_patch(self, git_commit=None): + def create_patch(self, git_commit=None, changed_files=[]): """Returns a byte array (str()) representing the patch file. Patch files are effectively binary since they may contain files of multiple different encodings.""" # FIXME: This should probably use cwd=self.checkout_root - return self.run(['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "-M", self.merge_base(git_commit)], decode_output=False) + return self.run(['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "-M", self.merge_base(git_commit), "--"] + changed_files, decode_output=False) @classmethod def git_commit_from_svn_revision(cls, revision): @@ -688,6 +705,12 @@ class Git(SCM): raise ScriptError(message='Failed to find git commit for revision %s, your checkout likely needs an update.' % revision) return git_commit + def svn_revision_from_git_commit(self, commit_id): + try: + return int(self.run(['git', 'svn', 'find-rev', commit_id]).rstrip()) + except ValueError, e: + return None + def contents_at_revision(self, path, revision): """Returns a byte array (str()) containing the contents of path @ revision in the repository.""" diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py index 87d5539..4aa5279 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py @@ -352,6 +352,10 @@ class SCMTest(unittest.TestCase): self.assertRaises(ScriptError, self.scm.contents_at_revision, "test_file2", 2) self.assertRaises(ScriptError, self.scm.contents_at_revision, "does_not_exist", 2) + def _shared_test_revisions_changing_file(self): + self.assertEqual(self.scm.revisions_changing_file("test_file"), [5, 4, 3, 2]) + self.assertRaises(ScriptError, self.scm.revisions_changing_file, "non_existent_file") + def _shared_test_committer_email_for_revision(self): self.assertEqual(self.scm.committer_email_for_revision(3), getpass.getuser()) # Committer "email" will be the current user @@ -696,6 +700,9 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== def test_contents_at_revision(self): self._shared_test_contents_at_revision() + def test_revisions_changing_file(self): + self._shared_test_revisions_changing_file() + def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision() @@ -964,6 +971,10 @@ class GitSVNTest(SCMTest): self.scm.commit_locally_with_message("another test commit") self._two_local_commits() + def test_revisions_changing_files_with_local_commit(self): + self._one_local_commit() + self.assertEquals(self.scm.revisions_changing_file('test_file_commit1'), []) + def test_commit_with_message(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) @@ -1087,6 +1098,20 @@ class GitSVNTest(SCMTest): self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) + def test_create_patch_with_changed_files(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(changed_files=['test_file_commit2']) + self.assertTrue(re.search(r'test_file_commit2', patch)) + + def test_create_patch_with_rm_and_changed_files(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + os.remove('test_file_commit1') + patch = scm.create_patch() + patch_with_changed_files = scm.create_patch(changed_files=['test_file_commit1', 'test_file_commit2']) + self.assertEquals(patch, patch_with_changed_files) + def test_create_patch_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) @@ -1199,6 +1224,9 @@ class GitSVNTest(SCMTest): def test_contents_at_revision(self): self._shared_test_contents_at_revision() + def test_revisions_changing_file(self): + self._shared_test_revisions_changing_file() + def test_added_files(self): self._shared_test_added_files() diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py index 2d07158..f768cf9 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/committers.py +++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py @@ -73,6 +73,7 @@ committers_unable_to_review = [ Committer("Andre Boule", "aboule@apple.com"), Committer("Andrei Popescu", "andreip@google.com", "andreip"), Committer("Andrew Wellington", ["andrew@webkit.org", "proton@wiretapped.net"], "proton"), + Committer("Andrey Kosyakov", "caseq@chromium.org", "caseq"), Committer("Andras Becsi", "abecsi@webkit.org", "bbandix"), Committer("Andy Estes", "aestes@apple.com", "estes"), Committer("Anthony Ricaud", "rik@webkit.org", "rik"), @@ -104,6 +105,7 @@ committers_unable_to_review = [ Committer("Eric Roman", "eroman@chromium.org", "eroman"), Committer("Evan Martin", "evan@chromium.org", "evmar"), Committer("Evan Stade", "estade@chromium.org", "estade"), + Committer("Fady Samuel", "fsamuel@chromium.org", "fsamuel"), Committer("Feng Qian", "feng@chromium.org"), Committer("Fumitoshi Ukai", "ukai@chromium.org", "ukai"), Committer("Gabor Loki", "loki@webkit.org", "loki04"), @@ -144,10 +146,12 @@ committers_unable_to_review = [ Committer("Luiz Agostini", ["luiz@webkit.org", "luiz.agostini@openbossa.org"], "lca"), Committer("Mads Ager", "ager@chromium.org"), Committer("Marcus Voltis Bulach", "bulach@chromium.org"), + Committer("Matt Delaney", "mdelaney@apple.com"), Committer("Matt Lilek", ["webkit@mattlilek.com", "pewtermoose@webkit.org"]), Committer("Matt Perry", "mpcomplete@chromium.org"), Committer("Maxime Britto", ["maxime.britto@gmail.com", "britto@apple.com"]), Committer("Maxime Simon", ["simon.maxime@gmail.com", "maxime.simon@webkit.org"], "maxime.simon"), + Committer("Michael Nordman", "michaeln@google.com", "michaeln"), Committer("Michael Saboff", "msaboff@apple.com"), Committer("Michelangelo De Simone", "michelangelo@webkit.org", "michelangelo"), Committer("Mihai Parparita", "mihaip@chromium.org", "mihaip"), @@ -183,6 +187,7 @@ committers_unable_to_review = [ Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]), Committer("Yong Li", ["yong.li.webkit@gmail.com", "yong.li@torchmobile.com"], "yong"), Committer("Yongjun Zhang", "yongjun.zhang@nokia.com"), + Committer("Yuta Kitamura", "yutak@chromium.org", "yutak"), Committer("Yuzo Fujishima", "yuzo@google.com", "yuzo"), Committer("Zhenyao Mo", "zmo@google.com", "zhenyao"), Committer("Zoltan Herczeg", "zherczeg@webkit.org", "zherczeg"), @@ -205,7 +210,7 @@ reviewers_list = [ Reviewer("Alice Liu", "alice.liu@apple.com", "aliu"), Reviewer("Alp Toker", ["alp@nuanti.com", "alp@atoker.com", "alp@webkit.org"], "alp"), Reviewer("Anders Carlsson", ["andersca@apple.com", "acarlsson@apple.com"], "andersca"), - Reviewer("Andreas Kling", "andreas.kling@nokia.com", "kling"), + Reviewer("Andreas Kling", ["kling@webkit.org", "andreas.kling@nokia.com"], "kling"), Reviewer("Antonio Gomes", ["tonikitoo@webkit.org", "agomes@rim.com"], "tonikitoo"), Reviewer("Antti Koivisto", ["koivisto@iki.fi", "antti@apple.com", "antti.j.koivisto@nokia.com"], "anttik"), Reviewer("Ariya Hidayat", ["ariya@sencha.com", "ariya.hidayat@gmail.com", "ariya@webkit.org"], "ariya"), @@ -256,7 +261,7 @@ reviewers_list = [ Reviewer("Laszlo Gombos", "laszlo.1.gombos@nokia.com", "lgombos"), Reviewer("Maciej Stachowiak", "mjs@apple.com", "othermaciej"), Reviewer("Mark Rowe", "mrowe@apple.com", "bdash"), - Reviewer("Martin Robinson", ["mrobinson@igalia.com", "mrobinson@webkit.org", "martin.james.robinson@gmail.com"], "mrobinson"), + Reviewer("Martin Robinson", ["mrobinson@webkit.org", "mrobinson@igalia.com", "martin.james.robinson@gmail.com"], "mrobinson"), Reviewer("Nate Chapin", "japhet@chromium.org", "japhet"), Reviewer("Nikolas Zimmermann", ["zimmermann@kde.org", "zimmermann@physik.rwth-aachen.de", "zimmermann@webkit.org"], "wildfox"), Reviewer("Ojan Vafai", "ojan@chromium.org", "ojan"), diff --git a/WebKitTools/Scripts/webkitpy/common/config/ports.py b/WebKitTools/Scripts/webkitpy/common/config/ports.py index ebd88b1..d268865 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/ports.py +++ b/WebKitTools/Scripts/webkitpy/common/config/ports.py @@ -45,6 +45,7 @@ class WebKitPort(object): def port(port_name): ports = { "chromium": ChromiumPort, + "chromium-xvfb": ChromiumXVFBPort, "gtk": GtkPort, "mac": MacPort, "win": WinPort, @@ -102,6 +103,10 @@ class WebKitPort(object): def run_perl_unittests_command(cls): return [cls.script_path("test-webkitperl")] + @classmethod + def layout_tests_results_path(cls): + return "/tmp/layout-test-results/results.html" + class MacPort(WebKitPort): @@ -217,3 +222,28 @@ class ChromiumPort(WebKitPort): command = WebKitPort.build_webkit_command(build_style=build_style) command.append("--chromium") return command + + @classmethod + def run_webkit_tests_command(cls): + return [ + cls.script_path("new-run-webkit-tests"), + "--chromium", + "--use-drt", + "--no-pixel-tests", + ] + + @classmethod + def run_javascriptcore_tests_command(cls): + return None + + +class ChromiumXVFBPort(ChromiumPort): + + @classmethod + def flag(cls): + return "--port=chromium-xvfb" + + @classmethod + def run_webkit_tests_command(cls): + # FIXME: We should find a better way to do this. + return ["xvfb-run"] + ChromiumPort.run_webkit_tests_command() diff --git a/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py b/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py index 42c4f2d..3bdf0e6 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/config/ports_unittest.py @@ -29,7 +29,7 @@ import unittest -from webkitpy.common.config.ports import WebKitPort, MacPort, GtkPort, QtPort, ChromiumPort +from webkitpy.common.config.ports import * class WebKitPortTest(unittest.TestCase): @@ -64,11 +64,13 @@ class WebKitPortTest(unittest.TestCase): def test_chromium_port(self): self.assertEquals(ChromiumPort.name(), "Chromium") self.assertEquals(ChromiumPort.flag(), "--port=chromium") - self.assertEquals(ChromiumPort.run_webkit_tests_command(), [WebKitPort.script_path("run-webkit-tests")]) + self.assertEquals(ChromiumPort.run_webkit_tests_command(), [WebKitPort.script_path("new-run-webkit-tests"), "--chromium", "--use-drt", "--no-pixel-tests"]) self.assertEquals(ChromiumPort.build_webkit_command(), [WebKitPort.script_path("build-webkit"), "--chromium"]) self.assertEquals(ChromiumPort.build_webkit_command(build_style="debug"), [WebKitPort.script_path("build-webkit"), "--debug", "--chromium"]) self.assertEquals(ChromiumPort.update_webkit_command(), [WebKitPort.script_path("update-webkit"), "--chromium"]) + def test_chromium_xvfb_port(self): + self.assertEquals(ChromiumXVFBPort.run_webkit_tests_command(), ["xvfb-run", "WebKitTools/Scripts/new-run-webkit-tests", "--chromium", "--use-drt", "--no-pixel-tests"]) if __name__ == '__main__': unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py index cc64fac..94519a7 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py +++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py @@ -301,15 +301,14 @@ class BugzillaQueries(object): review_queue_url = "buglist.cgi?query_format=advanced&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&field0-0-0=flagtypes.name&type0-0-0=equals&value0-0-0=review?" return self._fetch_bug_ids_advanced_query(review_queue_url) + # This method will make several requests to bugzilla. def fetch_patches_from_review_queue(self, limit=None): # [:None] returns the whole array. return sum([self._fetch_bug(bug_id).unreviewed_patches() for bug_id in self._fetch_bug_ids_from_review_queue()[:limit]], []) - # FIXME: Why do we have both fetch_patches_from_review_queue and - # fetch_attachment_ids_from_review_queue?? - # NOTE: This is also the only client of _fetch_attachment_ids_request_query - + # NOTE: This is the only client of _fetch_attachment_ids_request_query + # This method only makes one request to bugzilla. def fetch_attachment_ids_from_review_queue(self): review_queue_url = "request.cgi?action=queue&type=review&group=type" return self._fetch_attachment_ids_request_query(review_queue_url) diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py index 32f23cd..3a454d6 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py @@ -33,24 +33,11 @@ import datetime from webkitpy.common.config.committers import CommitterList, Reviewer, Committer from webkitpy.common.net.bugzilla import Bugzilla, BugzillaQueries, parse_bug_id, CommitterValidator, Bug from webkitpy.common.system.outputcapture import OutputCapture +from webkitpy.tool.mocktool import MockBrowser from webkitpy.thirdparty.mock import Mock from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup -class MockBrowser(object): - def open(self, url): - pass - - def select_form(self, name): - pass - - def __setitem__(self, key, value): - pass - - def submit(self): - pass - - class BugTest(unittest.TestCase): def test_is_unassigned(self): for email in Bug.unassigned_emails: diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py index 17f6c7a..a14bc7f 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py @@ -35,12 +35,12 @@ import urllib2 import xmlrpclib from webkitpy.common.net.failuremap import FailureMap +from webkitpy.common.net.layouttestresults import LayoutTestResults 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 - _log = get_logger(__file__) @@ -108,6 +108,7 @@ class Builder(object): def _fetch_revision_to_build_map(self): # All _fetch requests go through _buildbot for easier mocking + # FIXME: This should use NetworkTransaction's 404 handling instead. try: # FIXME: This method is horribly slow due to the huge network load. # FIXME: This is a poor way to do revision -> build mapping. @@ -166,22 +167,23 @@ class Builder(object): failures = set(results.failing_tests()) if common_failures == None: common_failures = failures - common_failures = common_failures.intersection(failures) - if not common_failures: - # current_build doesn't have any failures in common with - # the red build we're worried about. We assume that any - # failures in current_build were due to flakiness. - break + else: + common_failures = common_failures.intersection(failures) + if not common_failures: + # current_build doesn't have any failures in common with + # the red build we're worried about. We assume that any + # failures in current_build were due to flakiness. + break look_back_count += 1 if look_back_count > look_back_limit: - return RegressionWindow(None, current_build, common_failures=common_failures) + return RegressionWindow(None, current_build, failing_tests=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 RegressionWindow(current_build, build_after_current_build, common_failures=common_failures) + return RegressionWindow(current_build, build_after_current_build, failing_tests=common_failures) def find_blameworthy_regression_window(self, red_build_number, look_back_limit=30, avoid_flakey_tests=True): red_build = self.build(red_build_number) @@ -195,66 +197,6 @@ class Builder(object): return regression_window -# FIXME: This should be unified with all the layout test results code in the layout_tests package -class LayoutTestResults(object): - stderr_key = u'Tests that had stderr output:' - fail_key = u'Tests where results did not match expected results:' - timeout_key = u'Tests that timed out:' - crash_key = u'Tests that caused the DumpRenderTree tool to crash:' - missing_key = u'Tests that had no expected results (probably new):' - - expected_keys = [ - stderr_key, - fail_key, - crash_key, - timeout_key, - missing_key, - ] - - @classmethod - def _parse_results_html(cls, page): - parsed_results = {} - tables = BeautifulSoup(page).findAll("table") - for table in tables: - table_title = unicode(table.findPreviousSibling("p").string) - if table_title not in cls.expected_keys: - # This Exception should only ever be hit if run-webkit-tests changes its results.html format. - raise Exception("Unhandled title: %s" % table_title) - # We might want to translate table titles into identifiers before storing. - parsed_results[table_title] = [unicode(row.find("a").string) for row in table.findAll("tr")] - - return parsed_results - - @classmethod - def _fetch_results_html(cls, base_url): - results_html = "%s/results.html" % base_url - # FIXME: We need to move this sort of 404 logic into NetworkTransaction or similar. - try: - page = urllib2.urlopen(results_html) - return cls._parse_results_html(page) - except urllib2.HTTPError, error: - if error.code != 404: - raise - - @classmethod - def results_from_url(cls, base_url): - parsed_results = cls._fetch_results_html(base_url) - if not parsed_results: - return None - return cls(base_url, parsed_results) - - def __init__(self, base_url, parsed_results): - self._base_url = base_url - self._parsed_results = parsed_results - - def parsed_results(self): - return self._parsed_results - - def failing_tests(self): - failing_keys = [self.fail_key, self.crash_key, self.timeout_key] - return sorted(sum([tests for key, tests in self._parsed_results.items() if key in failing_keys], [])) - - class Build(object): def __init__(self, builder, build_number, revision, is_green): self._builder = builder @@ -274,9 +216,19 @@ class Build(object): results_directory = "r%s (%s)" % (self.revision(), self._number) return "%s/%s" % (self._builder.results_url(), urllib.quote(results_directory)) + def _fetch_results_html(self): + results_html = "%s/results.html" % (self.results_url()) + # FIXME: This should use NetworkTransaction's 404 handling instead. + try: + return urllib2.urlopen(results_html) + except urllib2.HTTPError, error: + if error.code != 404: + raise + def layout_test_results(self): if not self._layout_test_results: - self._layout_test_results = LayoutTestResults.results_from_url(self.results_url()) + # FIXME: This should cache that the result was a 404 and stop hitting the network. + self._layout_test_results = LayoutTestResults.results_from_string(self._fetch_results_html()) return self._layout_test_results def builder(self): @@ -461,7 +413,8 @@ class BuildBot(object): continue builder = self.builder_with_name(builder_status["name"]) regression_window = builder.find_blameworthy_regression_window(builder_status["build_number"]) - failure_map.add_regression_window(builder, regression_window) + if regression_window: + 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 diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py index c99ab32..afc9a39 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py @@ -29,7 +29,6 @@ import unittest from webkitpy.common.net.buildbot import BuildBot, Builder, Build, LayoutTestResults - from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup @@ -42,10 +41,8 @@ class BuilderTest(unittest.TestCase): revision=build_number + 1000, is_green=build_number < 4 ) - build._layout_test_results = LayoutTestResults( - "http://buildbot.example.com/foo", { - LayoutTestResults.fail_key: failure(build_number), - }) + parsed_results = {LayoutTestResults.fail_key: failure(build_number)} + build._layout_test_results = LayoutTestResults(parsed_results) return build self.builder._fetch_build = _mock_fetch_build @@ -114,45 +111,6 @@ class BuilderTest(unittest.TestCase): self.assertEqual(self.builder._revision_and_build_for_filename(filename), revision_and_build) -class LayoutTestResultsTest(unittest.TestCase): - _example_results_html = """ -<html> -<head> -<title>Layout Test Results</title> -</head> -<body> -<p>Tests that had stderr output:</p> -<table> -<tr> -<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/accessibility/aria-activedescendant-crash.html">accessibility/aria-activedescendant-crash.html</a></td> -<td><a href="accessibility/aria-activedescendant-crash-stderr.txt">stderr</a></td> -</tr> -<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/http/tests/security/canvas-remote-read-svg-image.html">http/tests/security/canvas-remote-read-svg-image.html</a></td> -<td><a href="http/tests/security/canvas-remote-read-svg-image-stderr.txt">stderr</a></td> -</tr> -</table><p>Tests that had no expected results (probably new):</p> -<table> -<tr> -<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/fast/repaint/no-caret-repaint-in-non-content-editable-element.html">fast/repaint/no-caret-repaint-in-non-content-editable-element.html</a></td> -<td><a href="fast/repaint/no-caret-repaint-in-non-content-editable-element-actual.txt">result</a></td> -</tr> -</table></body> -</html> -""" - - _expected_layout_test_results = { - 'Tests that had stderr output:' : [ - 'accessibility/aria-activedescendant-crash.html' - ], - 'Tests that had no expected results (probably new):' : [ - 'fast/repaint/no-caret-repaint-in-non-content-editable-element.html' - ] - } - def test_parse_layout_test_results(self): - results = LayoutTestResults._parse_results_html(self._example_results_html) - self.assertEqual(self._expected_layout_test_results, results) - - class BuildBotTest(unittest.TestCase): _example_one_box_status = ''' diff --git a/WebKitTools/Scripts/webkitpy/common/net/failuremap.py b/WebKitTools/Scripts/webkitpy/common/net/failuremap.py index 98e4b8f..e2d53ae 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/failuremap.py +++ b/WebKitTools/Scripts/webkitpy/common/net/failuremap.py @@ -37,12 +37,48 @@ class FailureMap(object): '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 + def is_empty(self): + return not self._failures + + def failing_revisions(self): + failing_revisions = [failure_info['regression_window'].revisions() + for failure_info in self._failures] + return sorted(set(sum(failing_revisions, []))) + + def builders_failing_for(self, revision): + return self._builders_failing_because_of([revision]) + + def tests_failing_for(self, revision): + tests = [failure_info['regression_window'].failing_tests() + for failure_info in self._failures + if revision in failure_info['regression_window'].revisions() + and failure_info['regression_window'].failing_tests()] + result = set() + for test in tests: + result = result.union(test) + return sorted(result) + + def _old_failures(self, is_old_failure): + return filter(lambda revision: is_old_failure(revision), + self.failing_revisions()) + + def _builders_failing_because_of(self, revisions): + revision_set = set(revisions) + return [failure_info['builder'] for failure_info in self._failures + if revision_set.intersection( + failure_info['regression_window'].revisions())] + + # FIXME: We should re-process old failures after some time delay. + # https://bugs.webkit.org/show_bug.cgi?id=36581 + def filter_out_old_failures(self, is_old_failure): + old_failures = self._old_failures(is_old_failure) + old_failing_builder_names = set([builder.name() + for builder in self._builders_failing_because_of(old_failures)]) + + # We filter out all the failing builders that could have been caused + # by old_failures. We could miss some new failures this way, but + # emperically, this reduces the amount of spam we generate. + failures = self._failures + self._failures = [failure_info for failure_info in failures + if failure_info['builder'].name() not in old_failing_builder_names] + self._cache = {} diff --git a/WebKitTools/Scripts/webkitpy/common/net/failuremap_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/failuremap_unittest.py new file mode 100644 index 0000000..2f0b49d --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/net/failuremap_unittest.py @@ -0,0 +1,76 @@ +# Copyright (c) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from webkitpy.common.net.buildbot import Build +from webkitpy.common.net.failuremap import * +from webkitpy.common.net.regressionwindow import RegressionWindow +from webkitpy.tool.mocktool import MockBuilder + + +class FailureMapTest(unittest.TestCase): + builder1 = MockBuilder("Builder1") + builder2 = MockBuilder("Builder2") + + build1a = Build(builder1, build_number=22, revision=1233, is_green=True) + build1b = Build(builder1, build_number=23, revision=1234, is_green=False) + build2a = Build(builder2, build_number=89, revision=1233, is_green=True) + build2b = Build(builder2, build_number=90, revision=1235, is_green=False) + + regression_window1 = RegressionWindow(build1a, build1b, failing_tests=[u'test1', u'test1']) + regression_window2 = RegressionWindow(build2a, build2b, failing_tests=[u'test1']) + + def _make_failure_map(self): + failure_map = FailureMap() + failure_map.add_regression_window(self.builder1, self.regression_window1) + failure_map.add_regression_window(self.builder2, self.regression_window2) + return failure_map + + def test_failing_revisions(self): + failure_map = self._make_failure_map() + self.assertEquals(failure_map.failing_revisions(), [1234, 1235]) + + def test_new_failures(self): + failure_map = self._make_failure_map() + failure_map.filter_out_old_failures(lambda revision: False) + self.assertEquals(failure_map.failing_revisions(), [1234, 1235]) + + def test_new_failures_with_old_revisions(self): + failure_map = self._make_failure_map() + failure_map.filter_out_old_failures(lambda revision: revision == 1234) + self.assertEquals(failure_map.failing_revisions(), []) + + def test_new_failures_with_more_old_revisions(self): + failure_map = self._make_failure_map() + failure_map.filter_out_old_failures(lambda revision: revision == 1235) + self.assertEquals(failure_map.failing_revisions(), [1234]) + + def test_tests_failing_for(self): + failure_map = self._make_failure_map() + self.assertEquals(failure_map.tests_failing_for(1234), [u'test1']) diff --git a/WebKitTools/Scripts/webkitpy/common/net/layouttestresults.py b/WebKitTools/Scripts/webkitpy/common/net/layouttestresults.py new file mode 100644 index 0000000..2f7b3e6 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/net/layouttestresults.py @@ -0,0 +1,88 @@ +# 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. +# +# A module for parsing results.html files generated by old-run-webkit-tests + +from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup, SoupStrainer + + +# FIXME: This should be unified with all the layout test results code in the layout_tests package +# This doesn't belong in common.net, but we don't have a better place for it yet. +def path_for_layout_test(test_name): + return "LayoutTests/%s" % test_name + + +# FIXME: This should be unified with all the layout test results code in the layout_tests package +# This doesn't belong in common.net, but we don't have a better place for it yet. +class LayoutTestResults(object): + """This class knows how to parse old-run-webkit-tests results.html files.""" + + stderr_key = u'Tests that had stderr output:' + fail_key = u'Tests where results did not match expected results:' + timeout_key = u'Tests that timed out:' + crash_key = u'Tests that caused the DumpRenderTree tool to crash:' + missing_key = u'Tests that had no expected results (probably new):' + + expected_keys = [ + stderr_key, + fail_key, + crash_key, + timeout_key, + missing_key, + ] + + @classmethod + def _parse_results_html(cls, page): + parsed_results = {} + tables = BeautifulSoup(page).findAll("table") + for table in tables: + table_title = unicode(table.findPreviousSibling("p").string) + if table_title not in cls.expected_keys: + # This Exception should only ever be hit if run-webkit-tests changes its results.html format. + raise Exception("Unhandled title: %s" % table_title) + # We might want to translate table titles into identifiers before storing. + parsed_results[table_title] = [unicode(row.find("a").string) for row in table.findAll("tr")] + + return parsed_results + + @classmethod + def results_from_string(cls, string): + parsed_results = cls._parse_results_html(string) + if not parsed_results: + return None + return cls(parsed_results) + + def __init__(self, parsed_results): + self._parsed_results = parsed_results + + def parsed_results(self): + return self._parsed_results + + def failing_tests(self): + failing_keys = [self.fail_key, self.crash_key, self.timeout_key] + return sorted(sum([tests for key, tests in self._parsed_results.items() if key in failing_keys], [])) diff --git a/WebKitTools/Scripts/webkitpy/common/net/layouttestresults_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/layouttestresults_unittest.py new file mode 100644 index 0000000..44e4dbc --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/net/layouttestresults_unittest.py @@ -0,0 +1,76 @@ +# Copyright (c) 2010, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from webkitpy.common.net.layouttestresults import LayoutTestResults + + +class LayoutTestResultsTest(unittest.TestCase): + _example_results_html = """ +<html> +<head> +<title>Layout Test Results</title> +</head> +<body> +<p>Tests that had stderr output:</p> +<table> +<tr> +<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/accessibility/aria-activedescendant-crash.html">accessibility/aria-activedescendant-crash.html</a></td> +<td><a href="accessibility/aria-activedescendant-crash-stderr.txt">stderr</a></td> +</tr> +<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/http/tests/security/canvas-remote-read-svg-image.html">http/tests/security/canvas-remote-read-svg-image.html</a></td> +<td><a href="http/tests/security/canvas-remote-read-svg-image-stderr.txt">stderr</a></td> +</tr> +</table><p>Tests that had no expected results (probably new):</p> +<table> +<tr> +<td><a href="/var/lib/buildbot/build/gtk-linux-64-release/build/LayoutTests/fast/repaint/no-caret-repaint-in-non-content-editable-element.html">fast/repaint/no-caret-repaint-in-non-content-editable-element.html</a></td> +<td><a href="fast/repaint/no-caret-repaint-in-non-content-editable-element-actual.txt">result</a></td> +</tr> +</table></body> +</html> +""" + + _expected_layout_test_results = { + 'Tests that had stderr output:': [ + 'accessibility/aria-activedescendant-crash.html', + ], + 'Tests that had no expected results (probably new):': [ + 'fast/repaint/no-caret-repaint-in-non-content-editable-element.html', + ], + } + + def test_parse_layout_test_results(self): + results = LayoutTestResults._parse_results_html(self._example_results_html) + self.assertEqual(self._expected_layout_test_results, results) + + def test_results_from_string(self): + self.assertEqual(LayoutTestResults.results_from_string(""), None) + results = LayoutTestResults.results_from_string(self._example_results_html) + self.assertEqual(len(results.failing_tests()), 0) diff --git a/WebKitTools/Scripts/webkitpy/common/net/networktransaction.py b/WebKitTools/Scripts/webkitpy/common/net/networktransaction.py index c82fc6f..de19e94 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/networktransaction.py +++ b/WebKitTools/Scripts/webkitpy/common/net/networktransaction.py @@ -29,7 +29,7 @@ import logging import time -from webkitpy.thirdparty.autoinstalled.mechanize import HTTPError +from webkitpy.thirdparty.autoinstalled import mechanize from webkitpy.common.system.deprecated_logging import log @@ -41,10 +41,11 @@ class NetworkTimeout(Exception): class NetworkTransaction(object): - def __init__(self, initial_backoff_seconds=10, grown_factor=1.5, timeout_seconds=10*60): + def __init__(self, initial_backoff_seconds=10, grown_factor=1.5, timeout_seconds=(10 * 60), convert_404_to_None=False): self._initial_backoff_seconds = initial_backoff_seconds self._grown_factor = grown_factor self._timeout_seconds = timeout_seconds + self._convert_404_to_None = convert_404_to_None def run(self, request): self._total_sleep = 0 @@ -52,7 +53,10 @@ class NetworkTransaction(object): while True: try: return request() - except HTTPError, e: + # FIXME: We should catch urllib2.HTTPError here too. + except mechanize.HTTPError, e: + if self._convert_404_to_None and e.code == 404: + return None self._check_for_timeout() _log.warn("Received HTTP status %s from server. Retrying in " "%s seconds..." % (e.code, self._backoff_seconds)) diff --git a/WebKitTools/Scripts/webkitpy/common/net/networktransaction_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/networktransaction_unittest.py index cd0702b..49aaeed 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/networktransaction_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/networktransaction_unittest.py @@ -56,29 +56,36 @@ class NetworkTransactionTest(LoggingTestCase): self.assertTrue(did_throw_exception) self.assertTrue(did_process_exception) - def _raise_http_error(self): + def _raise_500_error(self): self._run_count += 1 if self._run_count < 3: - raise HTTPError("http://example.com/", 500, "inteneral server error", None, None) + raise HTTPError("http://example.com/", 500, "internal server error", None, None) return 42 + def _raise_404_error(self): + raise HTTPError("http://foo.com/", 404, "not found", None, None) + def test_retry(self): self._run_count = 0 transaction = NetworkTransaction(initial_backoff_seconds=0) - self.assertEqual(transaction.run(lambda: self._raise_http_error()), 42) + self.assertEqual(transaction.run(lambda: self._raise_500_error()), 42) self.assertEqual(self._run_count, 3) self.assertLog(['WARNING: Received HTTP status 500 from server. ' 'Retrying in 0 seconds...\n', 'WARNING: Received HTTP status 500 from server. ' 'Retrying in 0.0 seconds...\n']) + def test_convert_404_to_None(self): + transaction = NetworkTransaction(convert_404_to_None=True) + self.assertEqual(transaction.run(lambda: self._raise_404_error()), None) + def test_timeout(self): self._run_count = 0 transaction = NetworkTransaction(initial_backoff_seconds=60*60, timeout_seconds=60) did_process_exception = False did_throw_exception = True try: - transaction.run(lambda: self._raise_http_error()) + transaction.run(lambda: self._raise_500_error()) did_throw_exception = False except NetworkTimeout, e: did_process_exception = True diff --git a/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py b/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py index 231459f..ad89815 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py +++ b/WebKitTools/Scripts/webkitpy/common/net/regressionwindow.py @@ -28,10 +28,11 @@ class RegressionWindow(object): - def __init__(self, build_before_failure, failing_build, common_failures=None): + def __init__(self, build_before_failure, failing_build, failing_tests=None): self._build_before_failure = build_before_failure self._failing_build = failing_build - self._common_failures = common_failures + self._failing_tests = failing_tests + self._revisions = None def build_before_failure(self): return self._build_before_failure @@ -39,10 +40,12 @@ class RegressionWindow(object): def failing_build(self): return self._failing_build - def common_failures(self): - return self._common_failures + def failing_tests(self): + return self._failing_tests def revisions(self): - revisions = range(self._failing_build.revision(), self._build_before_failure.revision(), -1) - revisions.reverse() - return revisions + # Cache revisions to avoid excessive allocations. + if not self._revisions: + self._revisions = range(self._failing_build.revision(), self._build_before_failure.revision(), -1) + self._revisions.reverse() + return self._revisions diff --git a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py index 57390b8..3d03dcd 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py +++ b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py @@ -41,14 +41,18 @@ _log = logging.getLogger("webkitpy.common.net.statusserver") class StatusServer: default_host = "queues.webkit.org" - def __init__(self, host=default_host): + def __init__(self, host=default_host, browser=None, bot_id=None): self.set_host(host) - self.browser = Browser() + self._browser = browser or Browser() + self.set_bot_id(bot_id) def set_host(self, host): self.host = host self.url = "http://%s" % self.host + def set_bot_id(self, bot_id): + self.bot_id = bot_id + def results_url_for_status(self, status_id): return "%s/results/%s" % (self.url, status_id) @@ -56,14 +60,14 @@ class StatusServer: if not patch: return if patch.bug_id(): - self.browser["bug_id"] = unicode(patch.bug_id()) + self._browser["bug_id"] = unicode(patch.bug_id()) if patch.id(): - self.browser["patch_id"] = unicode(patch.id()) + self._browser["patch_id"] = unicode(patch.id()) def _add_results_file(self, results_file): if not results_file: return - self.browser.add_file(results_file, "text/plain", "results.txt", 'results_file') + self._browser.add_file(results_file, "text/plain", "results.txt", 'results_file') def _post_status_to_server(self, queue_name, status, patch, results_file): if results_file: @@ -71,36 +75,61 @@ class StatusServer: results_file.seek(0) update_status_url = "%s/update-status" % self.url - self.browser.open(update_status_url) - self.browser.select_form(name="update_status") - self.browser["queue_name"] = queue_name + self._browser.open(update_status_url) + self._browser.select_form(name="update_status") + self._browser["queue_name"] = queue_name + if self.bot_id: + self._browser["bot_id"] = self.bot_id self._add_patch(patch) - self.browser["status"] = status + self._browser["status"] = status self._add_results_file(results_file) - return self.browser.submit().read() # This is the id of the newly created status object. + return self._browser.submit().read() # This is the id of the newly created status object. def _post_svn_revision_to_server(self, svn_revision_number, broken_bot): update_svn_revision_url = "%s/update-svn-revision" % self.url - self.browser.open(update_svn_revision_url) - self.browser.select_form(name="update_svn_revision") - self.browser["number"] = unicode(svn_revision_number) - self.browser["broken_bot"] = broken_bot - return self.browser.submit().read() + self._browser.open(update_svn_revision_url) + self._browser.select_form(name="update_svn_revision") + self._browser["number"] = unicode(svn_revision_number) + self._browser["broken_bot"] = broken_bot + return self._browser.submit().read() def _post_work_items_to_server(self, queue_name, work_items): update_work_items_url = "%s/update-work-items" % self.url - self.browser.open(update_work_items_url) - self.browser.select_form(name="update_work_items") - self.browser["queue_name"] = queue_name + self._browser.open(update_work_items_url) + self._browser.select_form(name="update_work_items") + self._browser["queue_name"] = queue_name work_items = map(unicode, work_items) # .join expects strings - self.browser["work_items"] = " ".join(work_items) - return self.browser.submit().read() + self._browser["work_items"] = " ".join(work_items) + return self._browser.submit().read() + + def _post_work_item_to_ews(self, attachment_id): + submit_to_ews_url = "%s/submit-to-ews" % self.url + self._browser.open(submit_to_ews_url) + self._browser.select_form(name="submit_to_ews") + self._browser["attachment_id"] = unicode(attachment_id) + self._browser.submit() + + def submit_to_ews(self, attachment_id): + _log.info("Submitting attachment %s to EWS queues" % attachment_id) + return NetworkTransaction().run(lambda: self._post_work_item_to_ews(attachment_id)) def next_work_item(self, queue_name): _log.debug("Fetching next work item for %s" % queue_name) patch_status_url = "%s/next-patch/%s" % (self.url, queue_name) return self._fetch_url(patch_status_url) + def _post_release_work_item(self, queue_name, patch): + release_patch_url = "%s/release-patch" % (self.url) + self._browser.open(release_patch_url) + self._browser.select_form(name="release_patch") + self._browser["queue_name"] = queue_name + self._browser["attachment_id"] = unicode(patch.id()) + self._browser.submit() + + def release_work_item(self, queue_name, patch): + _log.debug("Releasing work item %s from %s" % (patch.id(), queue_name)) + return NetworkTransaction(convert_404_to_None=True).run(lambda: self._post_release_work_item(queue_name, patch)) + def update_work_items(self, queue_name, work_items): _log.debug("Recording work items: %s for %s" % (work_items, queue_name)) return NetworkTransaction().run(lambda: self._post_work_items_to_server(queue_name, work_items)) @@ -114,6 +143,7 @@ class StatusServer: return NetworkTransaction().run(lambda: self._post_svn_revision_to_server(svn_revision_number, broken_bot)) def _fetch_url(self, url): + # FIXME: This should use NetworkTransaction's 404 handling instead. try: return urllib2.urlopen(url).read() except urllib2.HTTPError, e: diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/patchcollection_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/statusserver_unittest.py index 4ec6e25..1169ba0 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/patchcollection_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/statusserver_unittest.py @@ -1,9 +1,9 @@ -# Copyright (c) 2009 Google Inc. All rights reserved. +# Copyright (c) 2010 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above @@ -13,7 +13,7 @@ # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -28,25 +28,16 @@ import unittest -from webkitpy.tool.bot.patchcollection import PersistentPatchCollection, PersistentPatchCollectionDelegate -from webkitpy.thirdparty.mock import Mock - - -class TestPersistentPatchCollectionDelegate(PersistentPatchCollectionDelegate): - def collection_name(self): - return "test-collection" - - def fetch_potential_patch_ids(self): - return [42, 192, 87] - - def status_server(self): - return Mock() - - def is_terminal_status(self, status): - return False +from webkitpy.common.net.statusserver import StatusServer +from webkitpy.common.system.outputcapture import OutputCaptureTestCaseBase +from webkitpy.tool.mocktool import MockBrowser -class PersistentPatchCollectionTest(unittest.TestCase): - def test_next(self): - collection = PersistentPatchCollection(TestPersistentPatchCollectionDelegate()) - collection.next() +class StatusServerTest(OutputCaptureTestCaseBase): + def test_url_for_issue(self): + mock_browser = MockBrowser() + status_server = StatusServer(browser=mock_browser, bot_id='123') + status_server.update_status('queue name', 'the status') + self.assertEqual('queue name', mock_browser.params['queue_name']) + self.assertEqual('the status', mock_browser.params['status']) + self.assertEqual('123', mock_browser.params['bot_id']) diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive.py b/WebKitTools/Scripts/webkitpy/common/system/executive.py index 7c00f22..216cf58 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/executive.py +++ b/WebKitTools/Scripts/webkitpy/common/system/executive.py @@ -103,6 +103,13 @@ class Executive(object): def _run_command_with_teed_output(self, args, teed_output): args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int()) + if sys.platform == 'cygwin': + # Cygwin's Python's os.execv doesn't support unicode command + # arguments, and neither does Cygwin's execv itself. + # FIXME: Using UTF-8 here will confuse Windows-native commands + # which will expect arguments to be encoded using the current code + # page. + args = [arg.encode('utf-8') for arg in args] child_process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -281,6 +288,13 @@ class Executive(object): assert(isinstance(args, list) or isinstance(args, tuple)) start_time = time.time() args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int()) + if sys.platform == 'cygwin': + # Cygwin's Python's os.execv doesn't support unicode command + # arguments, and neither does Cygwin's execv itself. + # FIXME: Using UTF-8 here will confuse Windows-native commands + # which will expect arguments to be encoded using the current code + # page. + args = [arg.encode('utf-8') for arg in args] stdin, string_to_communicate = self._compute_stdin(input) stderr = subprocess.STDOUT if return_stderr else None diff --git a/WebKitTools/Scripts/webkitpy/common/system/outputcapture.py b/WebKitTools/Scripts/webkitpy/common/system/outputcapture.py index 68a3919..45e0e3f 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/outputcapture.py +++ b/WebKitTools/Scripts/webkitpy/common/system/outputcapture.py @@ -29,6 +29,7 @@ # Class for unittest support. Used for capturing stderr/stdout. import sys +import unittest from StringIO import StringIO class OutputCapture(object): @@ -37,7 +38,9 @@ class OutputCapture(object): def _capture_output_with_name(self, output_name): self.saved_outputs[output_name] = getattr(sys, output_name) - setattr(sys, output_name, StringIO()) + captured_output = StringIO() + setattr(sys, output_name, captured_output) + return captured_output def _restore_output_with_name(self, output_name): captured_output = getattr(sys, output_name).getvalue() @@ -46,8 +49,7 @@ class OutputCapture(object): return captured_output def capture_output(self): - self._capture_output_with_name("stdout") - self._capture_output_with_name("stderr") + return (self._capture_output_with_name("stdout"), self._capture_output_with_name("stderr")) def restore_output(self): return (self._restore_output_with_name("stdout"), self._restore_output_with_name("stderr")) @@ -63,3 +65,22 @@ class OutputCapture(object): testcase.assertEqual(stderr_string, expected_stderr) # This is a little strange, but I don't know where else to return this information. return return_value + + +class OutputCaptureTestCaseBase(unittest.TestCase): + def setUp(self): + unittest.TestCase.setUp(self) + self.output_capture = OutputCapture() + (self.__captured_stdout, self.__captured_stderr) = self.output_capture.capture_output() + + def tearDown(self): + del self.__captured_stdout + del self.__captured_stderr + self.output_capture.restore_output() + unittest.TestCase.tearDown(self) + + def assertStdout(self, expected_stdout): + self.assertEquals(expected_stdout, self.__captured_stdout.getvalue()) + + def assertStderr(self, expected_stderr): + self.assertEquals(expected_stderr, self.__captured_stderr.getvalue()) diff --git a/WebKitTools/Scripts/webkitpy/common/system/path.py b/WebKitTools/Scripts/webkitpy/common/system/path.py new file mode 100644 index 0000000..43c6410 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/system/path.py @@ -0,0 +1,134 @@ +# 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. + +"""generic routines to convert platform-specific paths to URIs.""" +from __future__ import with_statement + +import atexit +import subprocess +import sys +import threading +import urllib + + +def abspath_to_uri(path, platform=None): + """Converts a platform-specific absolute path to a file: URL.""" + if platform is None: + platform = sys.platform + return "file:" + _escape(_convert_path(path, platform)) + + +def cygpath(path): + """Converts a cygwin path to Windows path.""" + return _CygPath.convert_using_singleton(path) + + +# Note that this object is not threadsafe and must only be called +# from multiple threads under protection of a lock (as is done in cygpath()) +class _CygPath(object): + """Manages a long-running 'cygpath' process for file conversion.""" + _lock = None + _singleton = None + + @staticmethod + def stop_cygpath_subprocess(): + if not _CygPath._lock: + return + + with _CygPath._lock: + if _CygPath._singleton: + _CygPath._singleton.stop() + + @staticmethod + def convert_using_singleton(path): + if not _CygPath._lock: + _CygPath._lock = threading.Lock() + + with _CygPath._lock: + if not _CygPath._singleton: + _CygPath._singleton = _CygPath() + # Make sure the cygpath subprocess always gets shutdown cleanly. + atexit.register(_CygPath.stop_cygpath_subprocess) + + return _CygPath._singleton.convert(path) + + def __init__(self): + self._child_process = None + + def start(self): + assert(self._child_process is None) + args = ['cygpath', '-f', '-', '-wa'] + self._child_process = subprocess.Popen(args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + + def is_running(self): + if not self._child_process: + return False + return self._child_process.returncode is None + + def stop(self): + if self._child_process: + self._child_process.stdin.close() + self._child_process.wait() + self._child_process = None + + def convert(self, path): + if not self.is_running(): + self.start() + self._child_process.stdin.write("%s\r\n" % path) + self._child_process.stdin.flush() + return self._child_process.stdout.readline().rstrip() + + +def _escape(path): + """Handle any characters in the path that should be escaped.""" + # FIXME: web browsers don't appear to blindly quote every character + # when converting filenames to files. Instead of using urllib's default + # rules, we allow a small list of other characters through un-escaped. + # It's unclear if this is the best possible solution. + return urllib.quote(path, safe='/+:') + + +def _convert_path(path, platform): + """Handles any os-specific path separators, mappings, etc.""" + if platform == 'win32': + return _winpath_to_uri(path) + if platform == 'cygwin': + return _winpath_to_uri(cygpath(path)) + return _unixypath_to_uri(path) + + +def _winpath_to_uri(path): + """Converts a window absolute path to a file: URL.""" + return "///" + path.replace("\\", "/") + + +def _unixypath_to_uri(path): + """Converts a unix-style path to a file: URL.""" + return "//" + path diff --git a/WebKitTools/Scripts/webkitpy/common/system/path_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/path_unittest.py new file mode 100644 index 0000000..4dbd38a --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/system/path_unittest.py @@ -0,0 +1,105 @@ +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +import sys + +import path + +class AbspathTest(unittest.TestCase): + def assertMatch(self, test_path, expected_uri, + platform=None): + if platform == 'cygwin' and sys.platform != 'cygwin': + return + self.assertEqual(path.abspath_to_uri(test_path, platform=platform), + expected_uri) + + def test_abspath_to_uri_cygwin(self): + if sys.platform != 'cygwin': + return + + self.assertMatch('/cygdrive/c/foo/bar.html', + 'file:///C:/foo/bar.html', + platform='cygwin') + self.assertEqual(path.abspath_to_uri('/cygdrive/c/foo/bar.html', + platform='cygwin'), + 'file:///C:/foo/bar.html') + + def test_abspath_to_uri_darwin(self): + self.assertMatch('/foo/bar.html', + 'file:///foo/bar.html', + platform='darwin') + self.assertEqual(path.abspath_to_uri("/foo/bar.html", + platform='darwin'), + "file:///foo/bar.html") + + def test_abspath_to_uri_linux2(self): + self.assertMatch('/foo/bar.html', + 'file:///foo/bar.html', + platform='darwin') + self.assertEqual(path.abspath_to_uri("/foo/bar.html", + platform='linux2'), + "file:///foo/bar.html") + + def test_abspath_to_uri_win(self): + self.assertMatch('c:\\foo\\bar.html', + 'file:///c:/foo/bar.html', + platform='win32') + self.assertEqual(path.abspath_to_uri("c:\\foo\\bar.html", + platform='win32'), + "file:///c:/foo/bar.html") + + def test_abspath_to_uri_escaping(self): + self.assertMatch('/foo/bar + baz%?.html', + 'file:///foo/bar%20+%20baz%25%3F.html', + platform='darwin') + self.assertMatch('/foo/bar + baz%?.html', + 'file:///foo/bar%20+%20baz%25%3F.html', + platform='linux2') + + # Note that you can't have '?' in a filename on windows. + self.assertMatch('/cygdrive/c/foo/bar + baz%.html', + 'file:///C:/foo/bar%20+%20baz%25.html', + platform='cygwin') + + def test_stop_cygpath_subprocess(self): + if sys.platform != 'cygwin': + return + + # Call cygpath to ensure the subprocess is running. + path.cygpath("/cygdrive/c/foo.txt") + self.assertTrue(path._CygPath._singleton.is_running()) + + # Stop it. + path._CygPath.stop_cygpath_subprocess() + + # Ensure that it is stopped. + self.assertFalse(path._CygPath._singleton.is_running()) + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/common/system/user.py b/WebKitTools/Scripts/webkitpy/common/system/user.py index 240b67b..8917137 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/user.py +++ b/WebKitTools/Scripts/webkitpy/common/system/user.py @@ -96,6 +96,10 @@ class User(object): # Note: Not thread safe: http://bugs.python.org/issue2320 subprocess.call(args + files) + def _warn_if_application_is_xcode(self, edit_application): + if "Xcode" in edit_application: + print "Instead of using Xcode.app, consider using EDITOR=\"xed --wait\"." + def edit_changelog(self, files): edit_application = os.environ.get("CHANGE_LOG_EDIT_APPLICATION") if edit_application and sys.platform == "darwin": @@ -103,8 +107,7 @@ class User(object): args = shlex.split(edit_application) print "Using editor in the CHANGE_LOG_EDIT_APPLICATION environment variable." print "Please quit the editor application when done editing." - if edit_application.find("Xcode.app"): - print "Instead of using Xcode.app, consider using EDITOR=\"xed --wait\"." + self._warn_if_application_is_xcode(edit_application) subprocess.call(["open", "-W", "-n", "-a"] + args + files) return self.edit(files) diff --git a/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py index ae1bad5..7ec9b34 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/system/user_unittest.py @@ -97,5 +97,13 @@ class UserTest(unittest.TestCase): raw_input=mock_raw_input) self.assertEquals(expected[1], result) -if __name__ == '__main__': - unittest.main() + def test_warn_if_application_is_xcode(self): + output = OutputCapture() + user = User() + output.assert_outputs(self, user._warn_if_application_is_xcode, ["TextMate"]) + output.assert_outputs(self, user._warn_if_application_is_xcode, ["/Applications/TextMate.app"]) + output.assert_outputs(self, user._warn_if_application_is_xcode, ["XCode"]) # case sensitive matching + + xcode_warning = "Instead of using Xcode.app, consider using EDITOR=\"xed --wait\".\n" + output.assert_outputs(self, user._warn_if_application_is_xcode, ["Xcode"], expected_stdout=xcode_warning) + output.assert_outputs(self, user._warn_if_application_is_xcode, ["/Developer/Applications/Xcode.app"], expected_stdout=xcode_warning) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py index bb9604f..309bf8d 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py @@ -205,3 +205,6 @@ class ListDuplicatesTest(unittest.TestCase): for expected, inputs in test_cases: self.assertEquals(expected, deduplicate_tests.get_relative_test_path(*inputs)) + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py index 970de60..e0fd1b6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py @@ -1,5 +1,6 @@ #!/usr/bin/env python # Copyright (C) 2010 Google Inc. All rights reserved. +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -271,23 +272,26 @@ class TestShellThread(WatchableThread): self._test_types = test_types self._test_args = test_args self._driver = None - self._directory_timing_stats = {} + self._test_group_timing_stats = {} self._test_results = [] self._num_tests = 0 self._start_time = 0 self._stop_time = 0 - - # Current directory of tests we're running. - self._current_dir = None - # Number of tests in self._current_dir. - self._num_tests_in_current_dir = None - # Time at which we started running tests from self._current_dir. - self._current_dir_start_time = None - - def get_directory_timing_stats(self): - """Returns a dictionary mapping test directory to a tuple of - (number of tests in that directory, time to run the tests)""" - return self._directory_timing_stats + self._have_http_lock = False + self._http_lock_wait_begin = 0 + self._http_lock_wait_end = 0 + + # Current group of tests we're running. + self._current_group = None + # Number of tests in self._current_group. + self._num_tests_in_current_group = None + # Time at which we started running tests from self._current_group. + self._current_group_start_time = None + + def get_test_group_timing_stats(self): + """Returns a dictionary mapping test group to a tuple of + (number of tests in that group, time to run the tests)""" + return self._test_group_timing_stats def get_test_results(self): """Return the list of all tests run on this thread. @@ -298,7 +302,8 @@ class TestShellThread(WatchableThread): return self._test_results def get_total_time(self): - return max(self._stop_time - self._start_time, 0.0) + return max(self._stop_time - self._start_time - + self._http_lock_wait_time(), 0.0) def get_num_tests(self): return self._num_tests @@ -337,6 +342,25 @@ class TestShellThread(WatchableThread): do multi-threaded debugging.""" self._run(test_runner, result_summary) + def cancel(self): + """Clean up http lock and set a flag telling this thread to quit.""" + self._stop_http_lock() + WatchableThread.cancel(self) + + def next_timeout(self): + """Return the time the test is supposed to finish by.""" + if self._next_timeout: + return self._next_timeout + self._http_lock_wait_time() + return self._next_timeout + + def _http_lock_wait_time(self): + """Return the time what http locking takes.""" + if self._http_lock_wait_begin == 0: + return 0 + if self._http_lock_wait_end == 0: + return time.time() - self._http_lock_wait_begin + return self._http_lock_wait_end - self._http_lock_wait_begin + def _run(self, test_runner, result_summary): """Main work entry point of the thread. Basically we pull urls from the filename queue and run the tests until we run out of urls. @@ -359,21 +383,35 @@ class TestShellThread(WatchableThread): return if len(self._filename_list) is 0: - if self._current_dir is not None: - self._directory_timing_stats[self._current_dir] = \ - (self._num_tests_in_current_dir, - time.time() - self._current_dir_start_time) + if self._current_group is not None: + self._test_group_timing_stats[self._current_group] = \ + (self._num_tests_in_current_group, + time.time() - self._current_group_start_time) try: - self._current_dir, self._filename_list = \ + self._current_group, self._filename_list = \ self._filename_list_queue.get_nowait() except Queue.Empty: + self._stop_http_lock() self._kill_dump_render_tree() tests_run_file.close() return - self._num_tests_in_current_dir = len(self._filename_list) - self._current_dir_start_time = time.time() + if self._options.wait_for_httpd: + if self._current_group == "tests_to_http_lock": + self._http_lock_wait_begin = time.time() + self._port.acquire_http_lock() + + self._port.start_http_server() + self._port.start_websocket_server() + + self._have_http_lock = True + self._http_lock_wait_end = time.time() + elif self._have_http_lock: + self._stop_http_lock() + + self._num_tests_in_current_group = len(self._filename_list) + self._current_group_start_time = time.time() test_info = self._filename_list.pop() @@ -517,6 +555,14 @@ class TestShellThread(WatchableThread): self._options) self._driver.start() + def _stop_http_lock(self): + """Stop the servers and release http lock.""" + if self._have_http_lock: + self._port.stop_http_server() + self._port.stop_websocket_server() + self._port.release_http_lock() + self._have_http_lock = False + def _kill_dump_render_tree(self): """Kill the DumpRenderTree process if it's running.""" if self._driver: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py index 6a5d43b..cd7d663 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py @@ -42,33 +42,35 @@ import sys import time import apache_http_server -import test_files +import http_lock import http_server +import test_files import websocket_server from webkitpy.common.system import logutils from webkitpy.common.system.executive import Executive, ScriptError +from webkitpy.common.system.path import abspath_to_uri from webkitpy.common.system.user import User _log = logutils.get_logger(__file__) -# Python's Popen has a bug that causes any pipes opened to a -# process that can't be executed to be leaked. Since this -# code is specifically designed to tolerate exec failures -# to gracefully handle cases where wdiff is not installed, -# the bug results in a massive file descriptor leak. As a -# workaround, if an exec failure is ever experienced for -# wdiff, assume it's not available. This will leak one -# file descriptor but that's better than leaking each time -# wdiff would be run. -# -# http://mail.python.org/pipermail/python-list/ -# 2008-August/505753.html -# http://bugs.python.org/issue3210 -_wdiff_available = True -_pretty_patch_available = True +class DummyOptions(object): + """Fake implementation of optparse.Values. Cloned from + webkitpy.tool.mocktool.MockOptions. + + """ + + def __init__(self, **kwargs): + # The caller can set option values using keyword arguments. We don't + # set any values by default because we don't know how this + # object will be used. Generally speaking unit tests should + # subclass this or provider wrapper functions that set a common + # set of options. + for key, value in kwargs.items(): + self.__dict__[key] = value + # FIXME: This class should merge with webkitpy.webkit_port at some point. class Port(object): @@ -85,13 +87,41 @@ class Port(object): def __init__(self, **kwargs): self._name = kwargs.get('port_name', None) - self._options = kwargs.get('options', None) + self._options = kwargs.get('options') + if self._options is None: + # FIXME: Ideally we'd have a package-wide way to get a + # well-formed options object that had all of the necessary + # options defined on it. + self._options = DummyOptions() 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._http_lock = None + + # Python's Popen has a bug that causes any pipes opened to a + # process that can't be executed to be leaked. Since this + # code is specifically designed to tolerate exec failures + # to gracefully handle cases where wdiff is not installed, + # the bug results in a massive file descriptor leak. As a + # workaround, if an exec failure is ever experienced for + # wdiff, assume it's not available. This will leak one + # file descriptor but that's better than leaking each time + # wdiff would be run. + # + # http://mail.python.org/pipermail/python-list/ + # 2008-August/505753.html + # http://bugs.python.org/issue3210 + self._wdiff_available = True + + self._pretty_patch_path = self.path_from_webkit_base("BugsSite", + "PrettyPatch", "prettify.rb") + self._pretty_patch_available = True + self.set_option_default('configuration', None) + if self._options.configuration is None: + self._options.configuration = self.default_configuration() def default_child_processes(self): """Return the number of DumpRenderTree instances to use for this @@ -125,6 +155,27 @@ class Port(object): """This routine is used to check whether image_diff binary exists.""" raise NotImplementedError('Port.check_image_diff') + def check_pretty_patch(self): + """Checks whether we can use the PrettyPatch ruby script.""" + + # check if Ruby is installed + try: + result = self._executive.run_command(['ruby', '--version']) + except OSError, e: + if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]: + _log.error("Ruby is not installed; " + "can't generate pretty patches.") + _log.error('') + return False + + if not self.path_exists(self._pretty_patch_path): + _log.error('Unable to find %s .' % self._pretty_patch_path) + _log.error("Can't generate pretty patches.") + _log.error('') + return False + + return True + def compare_text(self, expected_text, actual_text): """Return whether or not the two strings are *not* equal. This routine is used to diff text output. @@ -259,7 +310,10 @@ class Port(object): path = self.expected_filename(test, extension) if not os.path.exists(path): return None - with codecs.open(path, 'r', encoding) as file: + open_mode = 'r' + if encoding is None: + open_mode = 'r+b' + with codecs.open(path, open_mode, encoding) as file: return file.read() def expected_checksum(self, test): @@ -281,22 +335,18 @@ class Port(object): return text.strip("\r\n").replace("\r\n", "\n") + "\n" def filename_to_uri(self, filename): - """Convert a test file to a URI.""" + """Convert a test file (which is an absolute path) to a URI.""" LAYOUTTEST_HTTP_DIR = "http/tests/" - LAYOUTTEST_WEBSOCKET_DIR = "websocket/tests/" + LAYOUTTEST_WEBSOCKET_DIR = "http/tests/websocket/tests/" relative_path = self.relative_test_filename(filename) port = None use_ssl = False - if relative_path.startswith(LAYOUTTEST_HTTP_DIR): - # http/tests/ run off port 8000 and ssl/ off 8443 + if (relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR) + or relative_path.startswith(LAYOUTTEST_HTTP_DIR)): relative_path = relative_path[len(LAYOUTTEST_HTTP_DIR):] port = 8000 - elif relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR): - # websocket/tests/ run off port 8880 and 9323 - # Note: the root is /, not websocket/tests/ - port = 8880 # Make http/tests/local run as local files. This is to mimic the # logic in run-webkit-tests. @@ -311,9 +361,7 @@ class Port(object): protocol = "http" return "%s://127.0.0.1:%u/%s" % (protocol, port, relative_path) - if sys.platform in ('cygwin', 'win32'): - return "file:///" + self.get_absolute_path(filename) - return "file://" + self.get_absolute_path(filename) + return abspath_to_uri(os.path.abspath(filename)) def tests(self, paths): """Return the list of tests found (relative to layout_tests_dir().""" @@ -349,7 +397,10 @@ class Port(object): data: contents of the baseline. encoding: file encoding to use for the baseline. """ - with codecs.open(path, "w", encoding=encoding) as file: + write_mode = "w" + if encoding is None: + write_mode = "wb" + with codecs.open(path, write_mode, encoding=encoding) as file: file.write(data) def uri_to_test_name(self, uri): @@ -362,12 +413,8 @@ class Port(object): """ 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) + prefix = abspath_to_uri(self.layout_tests_dir()) + "/" + return test[len(prefix):] if uri.startswith("http://127.0.0.1:8880/"): # websocket tests @@ -382,13 +429,6 @@ class Port(object): raise NotImplementedError('unknown url type: %s' % uri) - def get_absolute_path(self, filename): - """Return the absolute path in unix format for the given filename. - - This routine exists so that platforms that don't use unix filenames - can convert accordingly.""" - return os.path.abspath(filename) - def layout_tests_dir(self): """Return the absolute path to the top of the LayoutTests directory.""" return self.path_from_webkit_base('LayoutTests') @@ -420,6 +460,18 @@ class Port(object): may be different (e.g., 'win-xp' instead of 'chromium-win-xp'.""" return self._name + def get_option(self, name, default_value=None): + # FIXME: Eventually we should not have to do a test for + # hasattr(), and we should be able to just do + # self.options.value. See additional FIXME in the constructor. + if hasattr(self._options, name): + return getattr(self._options, name) + return default_value + + def set_option_default(self, name, default_value): + if not hasattr(self._options, name): + return setattr(self._options, name, default_value) + # FIXME: This could be replaced by functions in webkitpy.common.checkout.scm. def path_from_webkit_base(self, *comps): """Returns the full path to path made by joining the top of the @@ -445,7 +497,7 @@ class Port(object): """Relative unix-style path for a filename under the LayoutTests directory. Filenames outside the LayoutTests directory should raise an error.""" - assert(filename.startswith(self.layout_tests_dir())) + #assert(filename.startswith(self.layout_tests_dir())) return filename[len(self.layout_tests_dir()) + 1:] def results_directory(self): @@ -484,12 +536,12 @@ class Port(object): """Start a web server if it is available. Do nothing if it isn't. This routine is allowed to (and may) fail if a server is already running.""" - if self._options.use_apache: + if self.get_option('use_apache'): self._http_server = apache_http_server.LayoutTestApacheHttpd(self, - self._options.results_directory) + self.get_option('results_directory')) else: self._http_server = http_server.Lighttpd(self, - self._options.results_directory) + self.get_option('results_directory')) self._http_server.start() def start_websocket_server(self): @@ -497,9 +549,13 @@ class Port(object): it isn't. This routine is allowed to (and may) fail if a server is already running.""" self._websocket_server = websocket_server.PyWebSocket(self, - self._options.results_directory) + self.get_option('results_directory')) self._websocket_server.start() + def acquire_http_lock(self): + self._http_lock = http_lock.HttpLock(None) + self._http_lock.wait_for_httpd_lock() + def stop_helper(self): """Shut down the test helper if it is running. Do nothing if it isn't, or it isn't available. If a port overrides start_helper() @@ -518,6 +574,10 @@ class Port(object): if self._websocket_server: self._websocket_server.stop() + def release_http_lock(self): + if self._http_lock: + self._http_lock.cleanup_http_lock() + def test_expectations(self): """Returns the test expectations for this port. @@ -628,8 +688,7 @@ class Port(object): """Returns a string of HTML indicating the word-level diff of the contents of the two filenames. Returns an empty string if word-level diffing isn't available.""" - global _wdiff_available # See explaination at top of file. - if not _wdiff_available: + if not self._wdiff_available: return "" try: # It's possible to raise a ScriptError we pass wdiff invalid paths. @@ -637,33 +696,33 @@ class Port(object): except OSError, e: if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]: # Silently ignore cases where wdiff is missing. - _wdiff_available = False + self._wdiff_available = False return "" raise - _pretty_patch_error_html = "Failed to run PrettyPatch, see error console." + # This is a class variable so we can test error output easily. + _pretty_patch_error_html = "Failed to run PrettyPatch, see error log." def pretty_patch_text(self, diff_path): - # FIXME: Much of this function could move to prettypatch.rb - global _pretty_patch_available - if not _pretty_patch_available: + if not self._pretty_patch_available: return self._pretty_patch_error_html - pretty_patch_path = self.path_from_webkit_base("BugsSite", "PrettyPatch") - prettify_path = os.path.join(pretty_patch_path, "prettify.rb") - command = ["ruby", "-I", pretty_patch_path, prettify_path, diff_path] + command = ("ruby", "-I", os.path.dirname(self._pretty_patch_path), + self._pretty_patch_path, diff_path) try: # Diffs are treated as binary (we pass decode_output=False) as they # may contain multiple files of conflicting encodings. return self._executive.run_command(command, decode_output=False) except OSError, e: # If the system is missing ruby log the error and stop trying. - _pretty_patch_available = False + self._pretty_patch_available = False _log.error("Failed to run PrettyPatch (%s): %s" % (command, e)) return self._pretty_patch_error_html except ScriptError, e: - # If ruby failed to run for some reason, log the command output and stop trying. - _pretty_patch_available = False - _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, e.message_with_output())) + # If ruby failed to run for some reason, log the command + # output and stop trying. + self._pretty_patch_available = False + _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, + e.message_with_output())) return self._pretty_patch_error_html def _webkit_build_directory(self, args): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py index 71877b3..93f8808 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py @@ -26,16 +26,19 @@ # (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 base +import optparse import os import StringIO import sys import tempfile import unittest +from webkitpy.common.system.path import abspath_to_uri from webkitpy.common.system.executive import Executive, ScriptError from webkitpy.thirdparty.mock import Mock +from webkitpy.tool import mocktool +import base # FIXME: This makes StringIO objects work with "with". Remove # when we upgrade to 2.6. @@ -139,11 +142,11 @@ class PortTest(unittest.TestCase): expected_wdiff = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre><span class=del>foo</span><span class=add>bar</span></pre>" self.assertEqual(wdiff, expected_wdiff) # Running the full wdiff_text method should give the same result. - base._wdiff_available = True # In case it's somehow already disabled. + port._wdiff_available = True # In case it's somehow already disabled. wdiff = port.wdiff_text(actual.name, expected.name) self.assertEqual(wdiff, expected_wdiff) # wdiff should still be available after running wdiff_text with a valid diff. - self.assertTrue(base._wdiff_available) + self.assertTrue(port._wdiff_available) actual.close() expected.close() @@ -151,7 +154,7 @@ class PortTest(unittest.TestCase): self.assertRaises(ScriptError, port._run_wdiff, "/does/not/exist", "/does/not/exist2") self.assertRaises(ScriptError, port.wdiff_text, "/does/not/exist", "/does/not/exist2") # wdiff will still be available after running wdiff_text with invalid paths. - self.assertTrue(base._wdiff_available) + self.assertTrue(port._wdiff_available) base._wdiff_available = True # If wdiff does not exist _run_wdiff should throw an OSError. @@ -161,8 +164,7 @@ class PortTest(unittest.TestCase): # wdiff_text should not throw an error if wdiff does not exist. self.assertEqual(port.wdiff_text("foo", "bar"), "") # However wdiff should not be available after running wdiff_text if wdiff is missing. - self.assertFalse(base._wdiff_available) - base._wdiff_available = True + self.assertFalse(port._wdiff_available) def test_diff_text(self): port = base.Port() @@ -226,6 +228,63 @@ class PortTest(unittest.TestCase): self.assertTrue('canvas' in dirs) self.assertTrue('css2.1' in dirs) + def test_filename_to_uri(self): + + port = base.Port() + layout_test_dir = port.layout_tests_dir() + test_file = os.path.join(layout_test_dir, "foo", "bar.html") + + # On Windows, absolute paths are of the form "c:\foo.txt". However, + # all current browsers (except for Opera) normalize file URLs by + # prepending an additional "/" as if the absolute path was + # "/c:/foo.txt". This means that all file URLs end up with "file:///" + # at the beginning. + if sys.platform == 'win32': + prefix = "file:///" + path = test_file.replace("\\", "/") + else: + prefix = "file://" + path = test_file + + self.assertEqual(port.filename_to_uri(test_file), + abspath_to_uri(test_file)) + + def test_get_option__set(self): + options, args = optparse.OptionParser().parse_args() + options.foo = 'bar' + port = base.Port(options=options) + self.assertEqual(port.get_option('foo'), 'bar') + + def test_get_option__unset(self): + port = base.Port() + self.assertEqual(port.get_option('foo'), None) + + def test_get_option__default(self): + port = base.Port() + self.assertEqual(port.get_option('foo', 'bar'), 'bar') + + def test_set_option_default__unset(self): + port = base.Port() + port.set_option_default('foo', 'bar') + self.assertEqual(port.get_option('foo'), 'bar') + + def test_set_option_default__set(self): + options, args = optparse.OptionParser().parse_args() + options.foo = 'bar' + port = base.Port(options=options) + # This call should have no effect. + port.set_option_default('foo', 'new_bar') + self.assertEqual(port.get_option('foo'), 'bar') + + def test_name__unset(self): + port = base.Port() + self.assertEqual(port.name(), None) + + def test_name__set(self): + port = base.Port(port_name='foo') + self.assertEqual(port.name(), 'foo') + + class VirtualTest(unittest.TestCase): """Tests that various methods expected to be virtual are.""" def assertVirtual(self, method, *args, **kwargs): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py index a72627a..4d17b51 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py @@ -43,6 +43,10 @@ import tempfile import time import webbrowser +from webkitpy.common.system.executive import Executive +from webkitpy.common.system.path import cygpath +from webkitpy.layout_tests.layout_package import test_expectations + import base import http_server @@ -84,11 +88,6 @@ class ChromiumPort(base.Port): 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): @@ -100,9 +99,9 @@ class ChromiumPort(base.Port): dump_render_tree_binary_path = self._path_to_driver() result = check_file_exists(dump_render_tree_binary_path, 'test driver') and result - if result and self._options.build: + if result and self.get_option('build'): result = self._check_driver_build_up_to_date( - self._options.configuration) + self.get_option('configuration')) else: _log.error('') @@ -111,10 +110,14 @@ class ChromiumPort(base.Port): result = check_file_exists(helper_path, 'layout test helper') and result - if self._options.pixel_tests: + if self.get_option('pixel_tests'): result = self.check_image_diff( 'To override, invoke with --no-pixel-tests') and result + # It's okay if pretty patch isn't available, but we will at + # least log a message. + self.check_pretty_patch() + return result def check_sys_deps(self, needs_http): @@ -134,28 +137,43 @@ class ChromiumPort(base.Port): 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) + + tempdir = tempfile.mkdtemp() + expected_filename = os.path.join(tempdir, "expected.png") + with open(expected_filename, 'w+b') as file: + file.write(expected_contents) + actual_filename = os.path.join(tempdir, "actual.png") + with open(actual_filename, 'w+b') as file: + file.write(actual_contents) + if diff_filename: - cmd = [executable, '--diff', expected_tmpfile.name, - actual_tmpfile.name, diff_filename] + cmd = [executable, '--diff', expected_filename, + actual_filename, diff_filename] else: - cmd = [executable, expected_tmpfile.name, actual_tmpfile.name] + cmd = [executable, expected_filename, actual_filename] result = True try: - if self._executive.run_command(cmd, return_exit_code=True) == 0: - return False + exit_code = self._executive.run_command(cmd, return_exit_code=True) + if exit_code == 0: + # The images are the same. + result = False + elif exit_code != 1: + _log.error("image diff returned an exit code of " + + str(exit_code)) + # Returning False here causes the script to think that we + # successfully created the diff even though we didn't. If + # we return True, we think that the images match but the hashes + # don't match. + # FIXME: Figure out why image_diff returns other values. + result = False except OSError, e: if e.errno == errno.ENOENT or e.errno == errno.EACCES: _compare_available = False else: raise e finally: - expected_tmpfile.close() - actual_tmpfile.close() + shutil.rmtree(tempdir, ignore_errors=True) return result def driver_name(self): @@ -182,10 +200,11 @@ class ChromiumPort(base.Port): def results_directory(self): try: return self.path_from_chromium_base('webkit', - self._options.configuration, self._options.results_directory) + self.get_option('configuration'), + self.get_option('results_directory')) except AssertionError: - return self._build_path(self._options.configuration, - self._options.results_directory) + return self._build_path(self.get_option('configuration'), + self.get_option('results_directory')) def setup_test_run(self): # Delete the disk cache if any to ensure a clean test run. @@ -239,7 +258,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 and self._options.use_drt: + if self.get_option('use_drt'): drt_overrides_path = self.path_from_webkit_base('LayoutTests', 'platform', 'chromium', 'drt_expectations.txt') if os.path.exists(drt_overrides_path): @@ -325,11 +344,18 @@ class ChromiumPort(base.Port): platform = self.name() return self.path_from_webkit_base('LayoutTests', 'platform', platform) + def _convert_path(self, path): + """Handles filename conversion for subprocess command line args.""" + # See note above in diff_image() for why we need this. + if sys.platform == 'cygwin': + return cygpath(path) + return path + def _path_to_image_diff(self): binary_name = 'image_diff' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'ImageDiff' - return self._build_path(self._options.configuration, binary_name) + return self._build_path(self.get_option('configuration'), binary_name) class ChromiumDriver(base.Driver): @@ -344,29 +370,31 @@ class ChromiumDriver(base.Driver): def _driver_args(self): driver_args = [] if self._image_path: - driver_args.append("--pixel-tests=" + self._image_path) + # See note above in diff_image() for why we need _convert_path(). + driver_args.append("--pixel-tests=" + + self._port._convert_path(self._image_path)) - if self._options.use_drt: + if self._port.get_option('use_drt'): driver_args.append('--test-shell') else: driver_args.append('--layout-tests') - if self._options.startup_dialog: + if self._port.get_option('startup_dialog'): driver_args.append('--testshell-startup-dialog') - if self._options.gp_fault_error_box: + if self._port.get_option('gp_fault_error_box'): driver_args.append('--gp-fault-error-box') - if self._options.accelerated_compositing: + if self._port.get_option('accelerated_compositing'): driver_args.append('--enable-accelerated-compositing') - if self._options.accelerated_2d_canvas: + if self._port.get_option('accelerated_2d_canvas'): driver_args.append('--enable-accelerated-2d-canvas') return driver_args def start(self): # FIXME: Should be an error to call this method twice. - cmd = self._command_wrapper(self._options.wrapper) + cmd = self._command_wrapper(self._port.get_option('wrapper')) cmd.append(self._port._path_to_driver()) cmd += self._driver_args() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py index 80602d9..95c716e 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py @@ -66,7 +66,7 @@ def get(**kwargs): def _set_gpu_options(options): if options: if options.accelerated_compositing is None: - options.accelerated_composting = True + options.accelerated_compositing = True if options.accelerated_2d_canvas is None: options.accelerated_2d_canvas = True @@ -90,7 +90,8 @@ class ChromiumGpuLinuxPort(chromium_linux.ChromiumLinuxPort): chromium_linux.ChromiumLinuxPort.__init__(self, **kwargs) def baseline_search_path(self): - return ([self._webkit_baseline_path('chromium-gpu-linux')] + + # Mimic the Linux -> Win expectations fallback in the ordinary Chromium port. + return (map(self._webkit_baseline_path, ['chromium-gpu-linux', 'chromium-gpu-win', 'chromium-gpu']) + chromium_linux.ChromiumLinuxPort.baseline_search_path(self)) def path_to_test_expectations_file(self): @@ -108,7 +109,7 @@ class ChromiumGpuMacPort(chromium_mac.ChromiumMacPort): chromium_mac.ChromiumMacPort.__init__(self, **kwargs) def baseline_search_path(self): - return ([self._webkit_baseline_path('chromium-gpu-mac')] + + return (map(self._webkit_baseline_path, ['chromium-gpu-mac', 'chromium-gpu']) + chromium_mac.ChromiumMacPort.baseline_search_path(self)) def path_to_test_expectations_file(self): @@ -126,7 +127,7 @@ class ChromiumGpuWinPort(chromium_win.ChromiumWinPort): chromium_win.ChromiumWinPort.__init__(self, **kwargs) def baseline_search_path(self): - return ([self._webkit_baseline_path('chromium-gpu-win')] + + return (map(self._webkit_baseline_path, ['chromium-gpu-win', 'chromium-gpu']) + chromium_win.ChromiumWinPort.baseline_search_path(self)) def path_to_test_expectations_file(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 index 5c79a3f..7a13b1c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py @@ -26,6 +26,8 @@ import os import unittest + +from webkitpy.tool import mocktool import chromium_gpu @@ -41,16 +43,25 @@ class ChromiumGpuTest(unittest.TestCase): def assertOverridesWorked(self, port_name): # test that we got the right port - port = chromium_gpu.get(port_name=port_name, options=None) + mock_options = mocktool.MockOptions(accelerated_compositing=None, + accelerated_2d_canvas=None) + port = chromium_gpu.get(port_name=port_name, options=mock_options) + self.assertTrue(port._options.accelerated_compositing) + self.assertTrue(port._options.accelerated_2d_canvas) # 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 it has the right directories in front of the search path. + paths = port.baseline_search_path() + self.assertEqual(port._webkit_baseline_path(port_name), paths[0]) + if port_name == 'chromium-gpu-linux': + self.assertEqual(port._webkit_baseline_path('chromium-gpu-win'), paths[1]) + self.assertEqual(port._webkit_baseline_path('chromium-gpu'), paths[2]) + else: + self.assertEqual(port._webkit_baseline_path('chromium-gpu'), paths[1]) - # test that we have the right expectations file. + # Test that we have the right expectations file. self.assertTrue('chromium-gpu' in port.path_to_test_expectations_file()) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py index 176991b..b26a6b5 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py @@ -52,7 +52,7 @@ class ChromiumLinuxPort(chromium.ChromiumPort): def check_build(self, needs_http): result = chromium.ChromiumPort.check_build(self, needs_http) if needs_http: - if self._options.use_apache: + if self.get_option('use_apache'): result = self._check_apache_install() and result else: result = self._check_lighttpd_install() and result @@ -81,7 +81,7 @@ class ChromiumLinuxPort(chromium.ChromiumPort): base = self.path_from_chromium_base() if os.path.exists(os.path.join(base, 'sconsbuild')): return os.path.join(base, 'sconsbuild', *comps) - if os.path.exists(os.path.join(base, 'out', *comps)) or not self._options.use_drt: + if os.path.exists(os.path.join(base, 'out', *comps)) or not self.get_option('use_drt'): return os.path.join(base, 'out', *comps) base = self.path_from_webkit_base() if os.path.exists(os.path.join(base, 'sconsbuild')): @@ -147,9 +147,9 @@ class ChromiumLinuxPort(chromium.ChromiumPort): def _path_to_driver(self, configuration=None): if not configuration: - configuration = self._options.configuration + configuration = self.get_option('configuration') binary_name = 'test_shell' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'DumpRenderTree' return self._build_path(configuration, binary_name) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py index 64016ab..d1c383c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py @@ -73,7 +73,7 @@ class ChromiumMacPort(chromium.ChromiumPort): def driver_name(self): """name for this port's equivalent of DumpRenderTree.""" - if self._options.use_drt: + if self.get_option('use_drt'): return "DumpRenderTree" return "TestShell" @@ -100,7 +100,7 @@ class ChromiumMacPort(chromium.ChromiumPort): def _build_path(self, *comps): path = self.path_from_chromium_base('xcodebuild', *comps) - if os.path.exists(path) or not self._options.use_drt: + if os.path.exists(path) or not self.get_option('use_drt'): return path return self.path_from_webkit_base('WebKit', 'chromium', 'xcodebuild', *comps) @@ -138,15 +138,15 @@ class ChromiumMacPort(chromium.ChromiumPort): # FIXME: make |configuration| happy with case-sensitive file # systems. if not configuration: - configuration = self._options.configuration + configuration = self.get_option('configuration') return self._build_path(configuration, self.driver_name() + '.app', 'Contents', 'MacOS', self.driver_name()) def _path_to_helper(self): binary_name = 'layout_test_helper' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'LayoutTestHelper' - return self._build_path(self._options.configuration, binary_name) + return self._build_path(self.get_option('configuration'), binary_name) def _path_to_wdiff(self): return 'wdiff' diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py index a4a9ea6..cb45430 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py @@ -26,24 +26,22 @@ # (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 chromium -import chromium_linux -import chromium_mac -import chromium_win +import os import unittest import StringIO -import os +from webkitpy.tool import mocktool from webkitpy.thirdparty.mock import Mock +import chromium +import chromium_linux +import chromium_mac +import chromium_win class ChromiumDriverTest(unittest.TestCase): def setUp(self): mock_port = Mock() - # FIXME: The Driver should not be grabbing at port._options! - mock_port._options = Mock() - mock_port._options.wrapper = "" self.driver = chromium.ChromiumDriver(mock_port, image_path=None, options=None) def test_test_shell_command(self): @@ -106,25 +104,19 @@ class ChromiumPortTest(unittest.TestCase): return 'default' def test_path_to_image_diff(self): - class MockOptions: - def __init__(self): - self.use_drt = True - - port = ChromiumPortTest.TestLinuxPort(options=MockOptions()) + mock_options = mocktool.MockOptions(use_drt=True) + port = ChromiumPortTest.TestLinuxPort(options=mock_options) self.assertTrue(port._path_to_image_diff().endswith( '/out/default/ImageDiff'), msg=port._path_to_image_diff()) - port = ChromiumPortTest.TestMacPort(options=MockOptions()) + port = ChromiumPortTest.TestMacPort(options=mock_options) self.assertTrue(port._path_to_image_diff().endswith( '/xcodebuild/default/ImageDiff')) # FIXME: Figure out how this is going to work on Windows. #port = chromium_win.ChromiumWinPort('test-port', options=MockOptions()) def test_skipped_layout_tests(self): - class MockOptions: - def __init__(self): - self.use_drt = True - - port = ChromiumPortTest.TestLinuxPort(options=MockOptions()) + mock_options = mocktool.MockOptions(use_drt=True) + port = ChromiumPortTest.TestLinuxPort(options=mock_options) fake_test = os.path.join(port.layout_tests_dir(), "fast/js/not-good.js") @@ -138,23 +130,56 @@ DEFER LINUX WIN : fast/js/very-good.js = TIMEOUT PASS""" 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') + mock_options = mocktool.MockOptions() + port = ChromiumPortTest.TestLinuxPort(options=mock_options) + self.assertEquals(mock_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') + mock_options = mocktool.MockOptions(configuration=None) + port = ChromiumPortTest.TestLinuxPort(mock_options) + self.assertEquals(mock_options.configuration, 'default') self.assertTrue(port.default_configuration_called) + def test_diff_image(self): + class TestPort(ChromiumPortTest.TestLinuxPort): + def _path_to_image_diff(self): + return "/path/to/image_diff" + + class MockExecute: + def __init__(self, result): + self._result = result + + def run_command(self, + args, + cwd=None, + input=None, + error_handler=None, + return_exit_code=False, + return_stderr=True, + decode_output=False): + if return_exit_code: + return self._result + return '' + + mock_options = mocktool.MockOptions(use_drt=False) + port = ChromiumPortTest.TestLinuxPort(mock_options) + + # Images are different. + port._executive = MockExecute(0) + self.assertEquals(False, port.diff_image("EXPECTED", "ACTUAL")) + + # Images are the same. + port._executive = MockExecute(1) + self.assertEquals(True, port.diff_image("EXPECTED", "ACTUAL")) + + # There was some error running image_diff. + port._executive = MockExecute(2) + exception_raised = False + try: + port.diff_image("EXPECTED", "ACTUAL") + except ValueError, e: + exception_raised = True + self.assertFalse(exception_raised) + 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 d2b0265..69b529a 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py @@ -55,9 +55,7 @@ class ChromiumWinPort(chromium.ChromiumPort): # python executable to run cgi program. env["CYGWIN_PATH"] = self.path_from_chromium_base( "third_party", "cygwin", "bin") - if (sys.platform == "win32" and self._options and - hasattr(self._options, "register_cygwin") and - self._options.register_cygwin): + if (sys.platform == "win32" and self.get_option('register_cygwin')): setup_mount = self.path_from_chromium_base("third_party", "cygwin", "setup_mount.bat") @@ -84,11 +82,6 @@ class ChromiumWinPort(chromium.ChromiumPort): 'build-instructions-windows') return result - def get_absolute_path(self, filename): - """Return the absolute path in unix format for the given filename.""" - abspath = os.path.abspath(filename) - return abspath.replace('\\', '/') - def relative_test_filename(self, filename): path = filename[len(self.layout_tests_dir()) + 1:] return path.replace('\\', '/') @@ -118,7 +111,7 @@ class ChromiumWinPort(chromium.ChromiumPort): if os.path.exists(p): return p p = self.path_from_chromium_base('chrome', *comps) - if os.path.exists(p) or not self._options.use_drt: + if os.path.exists(p) or not self.get_option('use_drt'): return p return os.path.join(self.path_from_webkit_base(), 'WebKit', 'chromium', *comps) @@ -146,23 +139,23 @@ class ChromiumWinPort(chromium.ChromiumPort): def _path_to_driver(self, configuration=None): if not configuration: - configuration = self._options.configuration + configuration = self.get_option('configuration') binary_name = 'test_shell.exe' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'DumpRenderTree.exe' return self._build_path(configuration, binary_name) def _path_to_helper(self): binary_name = 'layout_test_helper.exe' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'LayoutTestHelper.exe' - return self._build_path(self._options.configuration, binary_name) + return self._build_path(self.get_option('configuration'), binary_name) def _path_to_image_diff(self): binary_name = 'image_diff.exe' - if self._options.use_drt: + if self.get_option('use_drt'): binary_name = 'ImageDiff.exe' - return self._build_path(self._options.configuration, binary_name) + return self._build_path(self.get_option('configuration'), binary_name) def _path_to_wdiff(self): return self.path_from_chromium_base('third_party', 'cygwin', 'bin', diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py index 648ccad..8a6af56 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py @@ -101,7 +101,6 @@ class DryrunDriver(base.Driver): def __init__(self, port, image_path, options, executive): self._port = port - self._options = options self._image_path = image_path self._executive = executive self._layout_tests_dir = None diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py index 81c3732..978a557 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py @@ -29,6 +29,8 @@ import sys import unittest +from webkitpy.tool import mocktool + import chromium_gpu import chromium_linux import chromium_mac @@ -52,21 +54,11 @@ class FactoryTest(unittest.TestCase): # FIXME: The ports themselves should expose what options they require, # instead of passing generic "options". - class WebKitOptions(object): - """Represents the minimum options for WebKit port.""" - def __init__(self): - self.pixel_tests = False - - class ChromiumOptions(WebKitOptions): - """Represents minimum options for Chromium port.""" - def __init__(self): - FactoryTest.WebKitOptions.__init__(self) - self.chromium = True - def setUp(self): self.real_sys_platform = sys.platform - self.webkit_options = FactoryTest.WebKitOptions() - self.chromium_options = FactoryTest.ChromiumOptions() + self.webkit_options = mocktool.MockOptions(pixel_tests=False) + self.chromium_options = mocktool.MockOptions(pixel_tests=False, + chromium=True) def tearDown(self): sys.platform = self.real_sys_platform diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py index bffc860..8d94bb5 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py @@ -24,6 +24,30 @@ # (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 + + +def _test_expectations_overrides(port, super): + # The chrome ports use the regular overrides plus anything in the + # official test_expectations as well. Hopefully we don't get collisions. + chromium_overrides = super.test_expectations_overrides(port) + + # FIXME: It used to be that AssertionError would get raised by + # path_from_chromium_base() if we weren't in a Chromium checkout, but + # this changed in r60427. This should probably be changed back. + overrides_path = port.path_from_chromium_base('webkit', 'tools', + 'layout_tests', 'test_expectations_chrome.txt') + if not os.path.exists(overrides_path): + return chromium_overrides + + with codecs.open(overrides_path, "r", "utf-8") as file: + if chromium_overrides: + return chromium_overrides + file.read() + else: + return file.read() def GetGoogleChromePort(**kwargs): """Some tests have slightly different results when compiled as Google @@ -41,6 +65,11 @@ def GetGoogleChromePort(**kwargs): paths.insert(0, self._webkit_baseline_path( 'google-chrome-linux32')) return paths + + def test_expectations_overrides(self): + return _test_expectations_overrides(self, + chromium_linux.ChromiumLinuxPort) + return GoogleChromeLinux32Port(**kwargs) elif port_name == 'google-chrome-linux64': import chromium_linux @@ -52,6 +81,11 @@ def GetGoogleChromePort(**kwargs): paths.insert(0, self._webkit_baseline_path( 'google-chrome-linux64')) return paths + + def test_expectations_overrides(self): + return _test_expectations_overrides(self, + chromium_linux.ChromiumLinuxPort) + return GoogleChromeLinux64Port(**kwargs) elif port_name.startswith('google-chrome-mac'): import chromium_mac @@ -63,6 +97,11 @@ def GetGoogleChromePort(**kwargs): paths.insert(0, self._webkit_baseline_path( 'google-chrome-mac')) return paths + + def test_expectations_overrides(self): + return _test_expectations_overrides(self, + chromium_mac.ChromiumMacPort) + return GoogleChromeMacPort(**kwargs) elif port_name.startswith('google-chrome-win'): import chromium_win @@ -74,5 +113,10 @@ def GetGoogleChromePort(**kwargs): paths.insert(0, self._webkit_baseline_path( 'google-chrome-win')) return paths + + def test_expectations_overrides(self): + return _test_expectations_overrides(self, + chromium_win.ChromiumWinPort) + 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 85e9338..c4c885d 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py @@ -24,8 +24,12 @@ # (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 codecs import os import unittest + +import base_unittest +import factory import google_chrome @@ -35,6 +39,7 @@ class GetGoogleChromePortTest(unittest.TestCase): 'google-chrome-mac', 'google-chrome-win') for port in test_ports: self._verify_baseline_path(port, port) + self._verify_expectations_overrides(port) self._verify_baseline_path('google-chrome-mac', 'google-chrome-mac-leopard') self._verify_baseline_path('google-chrome-win', 'google-chrome-win-xp') @@ -45,3 +50,53 @@ class GetGoogleChromePortTest(unittest.TestCase): options=None) path = port.baseline_search_path()[0] self.assertEqual(expected_path, os.path.split(path)[1]) + + def _verify_expectations_overrides(self, port_name): + # FIXME: make this more robust when we have the Tree() abstraction. + # we should be able to test for the files existing or not, and + # be able to control the contents better. + + chromium_port = factory.get("chromium-mac") + chromium_overrides = chromium_port.test_expectations_overrides() + port = google_chrome.GetGoogleChromePort(port_name=port_name, + options=None) + + orig_exists = os.path.exists + orig_open = codecs.open + expected_string = "// hello, world\n" + + def mock_exists_chrome_not_found(path): + if 'test_expectations_chrome.txt' in path: + return False + return orig_exists(path) + + def mock_exists_chrome_found(path): + if 'test_expectations_chrome.txt' in path: + return True + return orig_exists(path) + + def mock_open(path, mode, encoding): + if 'test_expectations_chrome.txt' in path: + return base_unittest.NewStringIO(expected_string) + return orig_open(path, mode, encoding) + + try: + os.path.exists = mock_exists_chrome_not_found + chrome_overrides = port.test_expectations_overrides() + self.assertEqual(chromium_overrides, chrome_overrides) + + os.path.exists = mock_exists_chrome_found + codecs.open = mock_open + chrome_overrides = port.test_expectations_overrides() + if chromium_overrides: + self.assertEqual(chrome_overrides, + chromium_overrides + expected_string) + else: + self.assertEqual(chrome_overrides, expected_string) + finally: + os.path.exists = orig_exists + codecs.open = orig_open + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py new file mode 100644 index 0000000..73200a0 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged +# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged +# +# 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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. + +"""This class helps to block NRWT threads when more NRWTs run +http and websocket tests in a same time.""" + +import glob +import os +import sys +import tempfile +import time + + +class HttpLock(object): + + def __init__(self, lock_path, lock_file_prefix="WebKitHttpd.lock.", + guard_lock="WebKit.lock"): + if not lock_path: + self._lock_path = tempfile.gettempdir() + self._lock_file_prefix = lock_file_prefix + self._lock_file_path_prefix = os.path.join(self._lock_path, + self._lock_file_prefix) + self._guard_lock_file = os.path.join(self._lock_path, guard_lock) + self._process_lock_file_name = "" + + def cleanup_http_lock(self): + """Delete the lock file if exists.""" + if os.path.exists(self._process_lock_file_name): + os.unlink(self._process_lock_file_name) + + def _extract_lock_number(self, lock_file_name): + """Return the lock number from lock file.""" + prefix_length = len(self._lock_file_path_prefix) + return int(lock_file_name[prefix_length:]) + + def _lock_file_list(self): + """Return the list of lock files sequentially.""" + lock_list = glob.glob(self._lock_file_path_prefix + '*') + lock_list.sort(key=self._extract_lock_number) + return lock_list + + def _next_lock_number(self): + """Return the next available lock number.""" + lock_list = self._lock_file_list() + if not lock_list: + return 0 + return self._extract_lock_number(lock_list[-1]) + 1 + + def _check_pid(self, current_pid): + """Return True if pid is alive, otherwise return False.""" + try: + os.kill(current_pid, 0) + except OSError: + return False + else: + return True + + def _curent_lock_pid(self): + """Return with the current lock pid. If the lock is not valid + it deletes the lock file.""" + lock_list = self._lock_file_list() + if not lock_list: + return + try: + current_lock_file = open(lock_list[0], 'r') + current_pid = current_lock_file.readline() + current_lock_file.close() + if not (current_pid and + sys.platform in ('darwin', 'linux2') and + self._check_pid(int(current_pid))): + os.unlink(lock_list[0]) + return + except IOError, OSError: + return + return int(current_pid) + + def _create_lock_file(self): + """The lock files are used to schedule the running test sessions in first + come first served order. The sequential guard lock ensures that the lock + numbers are sequential.""" + while(True): + try: + sequential_guard_lock = os.open(self._guard_lock_file, + os.O_CREAT | os.O_NONBLOCK | os.O_EXCL) + + self._process_lock_file_name = (self._lock_file_path_prefix + + str(self._next_lock_number())) + lock_file = open(self._process_lock_file_name, 'w') + lock_file.write(str(os.getpid())) + lock_file.close() + os.close(sequential_guard_lock) + os.unlink(self._guard_lock_file) + break + except OSError: + pass + + def wait_for_httpd_lock(self): + """Create a lock file and wait until it's turn comes.""" + self._create_lock_file() + while self._curent_lock_pid() != os.getpid(): + time.sleep(1) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py new file mode 100644 index 0000000..85c760a --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged +# +# 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 glob +import http_lock +import os +import unittest + + +class HttpLockTest(unittest.TestCase): + + def __init__(self, testFunc): + self.http_lock_obj = http_lock.HttpLock(None, "WebKitTestHttpd.lock.", "WebKitTest.lock") + self.lock_file_path_prefix = os.path.join(self.http_lock_obj._lock_path, + self.http_lock_obj._lock_file_prefix) + self.lock_file_name = self.lock_file_path_prefix + "0" + self.guard_lock_file = self.http_lock_obj._guard_lock_file + self.clean_all_lockfile() + unittest.TestCase.__init__(self, testFunc) + + def clean_all_lockfile(self): + if os.path.exists(self.guard_lock_file): + os.unlink(self.guard_lock_file) + lock_list = glob.glob(self.lock_file_path_prefix + '*') + for file_name in lock_list: + os.unlink(file_name) + + def assertEqual(self, first, second): + if first != second: + self.clean_all_lockfile() + unittest.TestCase.assertEqual(self, first, second) + + def _check_lock_file(self): + if os.path.exists(self.lock_file_name): + pid = os.getpid() + lock_file = open(self.lock_file_name, 'r') + lock_file_pid = lock_file.readline() + lock_file.close() + self.assertEqual(pid, int(lock_file_pid)) + return True + return False + + def test_lock_lifecycle(self): + self.http_lock_obj._create_lock_file() + + self.assertEqual(True, self._check_lock_file()) + self.assertEqual(1, self.http_lock_obj._next_lock_number()) + + self.http_lock_obj.cleanup_http_lock() + + self.assertEqual(False, self._check_lock_file()) + self.assertEqual(0, self.http_lock_obj._next_lock_number()) + + def test_extract_lock_number(self,): + lock_file_list = ( + self.lock_file_path_prefix + "00", + self.lock_file_path_prefix + "9", + self.lock_file_path_prefix + "001", + self.lock_file_path_prefix + "021", + ) + + expected_number_list = (0, 9, 1, 21) + + for lock_file, expected in zip(lock_file_list, expected_number_list): + self.assertEqual(self.http_lock_obj._extract_lock_number(lock_file), expected) + + def test_lock_file_list(self): + lock_file_list = [ + self.lock_file_path_prefix + "6", + self.lock_file_path_prefix + "1", + self.lock_file_path_prefix + "4", + self.lock_file_path_prefix + "3", + ] + + expected_file_list = [ + self.lock_file_path_prefix + "1", + self.lock_file_path_prefix + "3", + self.lock_file_path_prefix + "4", + self.lock_file_path_prefix + "6", + ] + + for file_name in lock_file_list: + open(file_name, 'w') + + self.assertEqual(self.http_lock_obj._lock_file_list(), expected_file_list) + + for file_name in lock_file_list: + os.unlink(file_name) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py index 327b19e..d383a4c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py @@ -35,7 +35,7 @@ import port_testcase class MacTest(port_testcase.PortTestCase): - def make_port(self, options=port_testcase.MockOptions()): + def make_port(self, options=port_testcase.mock_options): if sys.platform != 'darwin': return None port_obj = mac.MacPort(options=options) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py index 47597d6..04ada50 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py @@ -32,20 +32,15 @@ import os import tempfile import unittest - -class MockOptions(object): - def __init__(self, - results_directory='layout-test-results', - use_apache=True, - configuration='Release'): - self.results_directory = results_directory - self.use_apache = use_apache - self.configuration = configuration +from webkitpy.tool import mocktool +mock_options = mocktool.MockOptions(results_directory='layout-test-results', + use_apache=True, + configuration='Release') class PortTestCase(unittest.TestCase): """Tests the WebKit port implementation.""" - def make_port(self, options=MockOptions()): + def make_port(self, options=mock_options): """Override in subclass.""" raise NotImplementedError() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py index 3b81167..3691c5a 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py @@ -215,14 +215,11 @@ class TestPort(base.Port): def name(self): return self._name - def options(self): - return self._options - def _path_to_wdiff(self): return None def results_directory(self): - return '/tmp/' + self._options.results_directory + return '/tmp/' + self.get_option('results_directory') def setup_test_run(self): pass @@ -285,7 +282,6 @@ class TestDriver(base.Driver): def __init__(self, port, image_path, options, executive): self._port = port self._image_path = image_path - self._options = options self._executive = executive self._image_written = False @@ -302,7 +298,7 @@ class TestDriver(base.Driver): if test.hang: time.sleep((float(timeoutms) * 4) / 1000.0) - if self._port.options().pixel_tests and test.actual_image: + if self._port.get_option('pixel_tests') and test.actual_image: with open(self._image_path, 'w') as file: file.write(test.actual_image) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py index ed19c09..c940f1e 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py @@ -65,9 +65,7 @@ class WebKitPort(base.Port): # FIXME: disable pixel tests until they are run by default on the # build machines. - if self._options and (not hasattr(self._options, "pixel_tests") or - self._options.pixel_tests is None): - self._options.pixel_tests = False + self.set_option_default('pixel_tests', False) def baseline_path(self): return self._webkit_baseline_path(self._name) @@ -86,7 +84,7 @@ class WebKitPort(base.Port): def _build_driver(self): exit_code = self._executive.run_command([ self.script_path("build-dumprendertree"), - self.flag_from_configuration(self._options.configuration), + self.flag_from_configuration(self.get_option('configuration')), ], return_exit_code=True) if exit_code != 0: _log.error("Failed to build DumpRenderTree") @@ -101,11 +99,11 @@ class WebKitPort(base.Port): return True def check_build(self, needs_http): - if self._options.build and not self._build_driver(): + if self.get_option('build') and not self._build_driver(): return False if not self._check_driver(): return False - if self._options.pixel_tests: + if self.get_option('pixel_tests'): if not self.check_image_diff(): return False if not self._check_port_build(): @@ -184,7 +182,7 @@ class WebKitPort(base.Port): def results_directory(self): # Results are store relative to the built products to make it easy # to have multiple copies of webkit checked out and built. - return self._build_path(self._options.results_directory) + return self._build_path(self.get_option('results_directory')) def setup_test_run(self): # This port doesn't require any specific configuration. @@ -360,7 +358,7 @@ class WebKitPort(base.Port): if not self._cached_build_root: self._cached_build_root = self._webkit_build_directory([ "--configuration", - self.flag_from_configuration(self._options.configuration), + self.flag_from_configuration(self.get_option('configuration')), ]) return os.path.join(self._cached_build_root, *comps) @@ -401,7 +399,6 @@ class WebKitDriver(base.Driver): def __init__(self, port, image_path, options, executive=Executive()): self._port = port self._image_path = image_path - self._options = options self._executive = executive self._driver_tempdir = tempfile.mkdtemp(prefix='DumpRenderTree-') @@ -414,17 +411,17 @@ class WebKitDriver(base.Driver): if self._image_path: driver_args.append('--pixel-tests') - if self._options.use_drt: - if self._options.accelerated_compositing: + if self._port.get_option('use_drt'): + if self._port.get_option('accelerated_compositing'): driver_args.append('--enable-accelerated-compositing') - if self._options.accelerated_2d_canvas: + if self._port.get_option('accelerated_2d_canvas'): driver_args.append('--enable-accelerated-2d-canvas') return driver_args def start(self): - command = self._command_wrapper(self._options.wrapper) + command = self._command_wrapper(self._port.get_option('wrapper')) command += [self._port._path_to_driver(), '-'] command += self._driver_args() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py index 7346671..926bc04 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py @@ -124,12 +124,13 @@ class PyWebSocket(http_server.Lighttpd): if self._root: self._layout_tests = os.path.abspath(self._root) self._web_socket_tests = os.path.abspath( - os.path.join(self._root, 'websocket', 'tests')) + os.path.join(self._root, 'http', 'tests', + 'websocket', 'tests')) else: try: self._layout_tests = self._port_obj.layout_tests_dir() self._web_socket_tests = os.path.join(self._layout_tests, - 'websocket', 'tests') + 'http', 'tests', 'websocket', 'tests') except: self._web_socket_tests = None @@ -164,10 +165,10 @@ class PyWebSocket(http_server.Lighttpd): pywebsocket_script = os.path.join(pywebsocket_base, 'mod_pywebsocket', 'standalone.py') start_cmd = [ - python_interp, pywebsocket_script, + python_interp, '-u', pywebsocket_script, '--server-host', '127.0.0.1', '--port', str(self._port), - '--document-root', self._layout_tests, + '--document-root', os.path.join(self._layout_tests, 'http', 'tests'), '--scan-dir', self._web_socket_tests, '--cgi-paths', '/websocket/tests', '--log-file', error_log, diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py index e57ceb2..a47370d 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py @@ -57,8 +57,9 @@ import time import urllib import zipfile +from webkitpy.common.system import path from webkitpy.common.system import user -from webkitpy.common.system.executive import run_command, ScriptError +from webkitpy.common.system.executive import Executive, ScriptError import webkitpy.common.checkout.scm as scm import port @@ -81,58 +82,6 @@ ARCHIVE_DIR_NAME_DICT = {'win': 'webkit-rel', 'linux-canary': 'webkit-rel-linux-webkit-org'} -# FIXME: Should be rolled into webkitpy.Executive -def run_shell_with_return_code(command, print_output=False): - """Executes a command and returns the output and process return code. - - Args: - command: program and arguments. - print_output: if true, print the command results to standard output. - - Returns: - command output, return code - """ - - # Use a shell for subcommands on Windows to get a PATH search. - # FIXME: shell=True is a trail of tears, and should be removed. - use_shell = sys.platform.startswith('win') - # Note: Not thread safe: http://bugs.python.org/issue2320 - p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, shell=use_shell) - if print_output: - output_array = [] - while True: - line = p.stdout.readline() - if not line: - break - if print_output: - print line.strip('\n') - output_array.append(line) - output = ''.join(output_array) - else: - output = p.stdout.read() - p.wait() - p.stdout.close() - - return output, p.returncode - - -# FIXME: Should be rolled into webkitpy.Executive -def run_shell(command, print_output=False): - """Executes a command and returns the output. - - Args: - command: program and arguments. - print_output: if true, print the command results to standard output. - - Returns: - command output - """ - - output, return_code = run_shell_with_return_code(command, print_output) - return output - - def log_dashed_string(text, platform, logging_level=logging.INFO): """Log text message with dashes on both sides.""" @@ -547,7 +496,7 @@ class Rebaseliner(object): """ if is_image: - return self._port.diff_image(output1, output2) + return self._port.diff_image(output1, output2, None, 0) else: return self._port.compare_text(output1, output2) @@ -628,7 +577,6 @@ class Rebaseliner(object): base_file = get_result_file_fullpath(self._options.html_directory, baseline_filename, self._platform, 'old') - # FIXME: This assumes run_shell returns a byte array. # We should be using an explicit encoding here. with open(base_file, "wb") as file: file.write(output) @@ -642,12 +590,12 @@ class Rebaseliner(object): diff_file = get_result_file_fullpath( self._options.html_directory, baseline_filename, self._platform, 'diff') - # FIXME: This assumes run_shell returns a byte array, not unicode() with open(diff_file, 'wb') as file: file.write(output) _log.info(' Html: created baseline diff file: "%s".', diff_file) + class HtmlGenerator(object): """Class to generate rebaselining result comparison html.""" @@ -694,14 +642,20 @@ class HtmlGenerator(object): '<img style="width: 200" src="%(uri)s" /></a></td>') HTML_TR = '<tr>%s</tr>' - def __init__(self, target_port, options, platforms, rebaselining_tests): + def __init__(self, target_port, options, platforms, rebaselining_tests, + executive): self._html_directory = options.html_directory self._target_port = target_port self._platforms = platforms self._rebaselining_tests = rebaselining_tests + self._executive = executive self._html_file = os.path.join(options.html_directory, 'rebaseline.html') + def abspath_to_uri(self, filename): + """Converts an absolute path to a file: URI.""" + return path.abspath_to_uri(filename, self._executive) + def generate_html(self): """Generate html file for rebaselining result comparison.""" @@ -769,14 +723,13 @@ class HtmlGenerator(object): links = '' if os.path.exists(old_file): links += html_td_link % { - 'uri': self._target_port.filename_to_uri(old_file), + 'uri': self.abspath_to_uri(old_file), 'name': baseline_filename} else: _log.info(' No old baseline file: "%s"', old_file) links += self.HTML_TD_NOLINK % '' - links += html_td_link % {'uri': self._target_port.filename_to_uri( - new_file), + links += html_td_link % {'uri': self.abspath_to_uri(new_file), 'name': baseline_filename} diff_file = get_result_file_fullpath(self._html_directory, @@ -784,8 +737,8 @@ class HtmlGenerator(object): 'diff') _log.info(' Baseline diff file: "%s"', diff_file) if os.path.exists(diff_file): - links += html_td_link % {'uri': self._target_port.filename_to_uri( - diff_file), 'name': 'Diff'} + links += html_td_link % {'uri': self.abspath_to_uri(diff_file), + 'name': 'Diff'} else: _log.info(' No baseline diff file: "%s"', diff_file) links += self.HTML_TD_NOLINK % '' @@ -825,8 +778,7 @@ class HtmlGenerator(object): if rows: test_path = os.path.join(self._target_port.layout_tests_dir(), test) - html = self.HTML_TR_TEST % ( - self._target_port.filename_to_uri(test_path), test) + html = self.HTML_TR_TEST % (self.abspath_to_uri(test_path), test) html += self.HTML_TEST_DETAIL % ' '.join(rows) _log.debug(' html for test: %s', html) @@ -867,7 +819,7 @@ def get_host_port_object(options): return port_obj -def main(): +def main(executive=Executive()): """Main function to produce new baselines.""" option_parser = optparse.OptionParser() @@ -992,7 +944,8 @@ def main(): html_generator = HtmlGenerator(target_port_obj, options, rebaseline_platforms, - rebaselining_tests) + rebaselining_tests, + executive=executive) html_generator.generate_html() if not options.quiet: html_generator.show_html() 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 9ba3d6b..ef33a47 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 @@ -30,10 +30,13 @@ """Unit tests for rebaseline_chromium_webkit_tests.py.""" import os +import sys import unittest +from webkitpy.tool import mocktool from webkitpy.layout_tests import port from webkitpy.layout_tests import rebaseline_chromium_webkit_tests +from webkitpy.common.system.executive import Executive, ScriptError class MockPort(object): @@ -44,11 +47,6 @@ class MockPort(object): return self.image_diff_exists -class MockOptions(object): - def __init__(self): - self.configuration = None - - def get_mock_get(config_expectations): def mock_get(port_name, options): return MockPort(config_expectations[options.configuration]) @@ -61,7 +59,8 @@ class TestGetHostPortObject(unittest.TestCase): # that Image diff is (or isn't) present in the two configs. port.get = get_mock_get({'Release': release_present, 'Debug': debug_present}) - options = MockOptions() + options = mocktool.MockOptions(configuration=None, + html_directory=None) port_obj = rebaseline_chromium_webkit_tests.get_host_port_object( options) if valid_port_obj: @@ -87,7 +86,8 @@ class TestGetHostPortObject(unittest.TestCase): class TestRebaseliner(unittest.TestCase): def make_rebaseliner(self): - options = MockOptions() + options = mocktool.MockOptions(configuration=None, + html_directory=None) host_port_obj = port.get('test', options) target_options = options target_port_obj = port.get('test', target_options) @@ -118,5 +118,32 @@ class TestRebaseliner(unittest.TestCase): self.assertFalse(rebaseliner._diff_baselines(image, image, is_image=True)) + +class TestHtmlGenerator(unittest.TestCase): + def make_generator(self, tests): + return rebaseline_chromium_webkit_tests.HtmlGenerator( + target_port=None, + options=mocktool.MockOptions(configuration=None, + html_directory='/tmp'), + platforms=['mac'], + rebaselining_tests=tests, + executive=Executive()) + + def test_generate_baseline_links(self): + orig_platform = sys.platform + orig_exists = os.path.exists + + try: + sys.platform = 'darwin' + os.path.exists = lambda x: True + generator = self.make_generator(["foo.txt"]) + links = generator._generate_baseline_links("foo", ".txt", "mac") + expected_links = '<td align=center><a href="file:///tmp/foo-expected-mac-old.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-new.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-diff.txt">Diff</a></td>' + self.assertEqual(links, expected_links) + finally: + sys.platform = orig_platform + os.path.exists = orig_exists + + 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 e9c6d2c..9cc7895 100755 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py @@ -1,5 +1,6 @@ #!/usr/bin/env python # Copyright (C) 2010 Google Inc. All rights reserved. +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -498,6 +499,12 @@ class TestRunner: self._options.slow_time_out_ms) return TestInfo(self._port, test_file, self._options.time_out_ms) + def _test_requires_lock(self, test_file): + """Return True if the test needs to be locked when + running multiple copies of NRWTs.""" + split_path = test_file.split(os.sep) + return 'http' in split_path or 'websocket' in split_path + def _get_test_file_queue(self, test_files): """Create the thread safe queue of lists of (test filenames, test URIs) tuples. Each TestShellThread pulls a list from this queue and runs @@ -511,46 +518,47 @@ class TestRunner: The Queue of lists of TestInfo objects. """ + test_lists = [] + tests_to_http_lock = [] if (self._options.experimental_fully_parallel or self._is_single_threaded()): - filename_queue = Queue.Queue() for test_file in test_files: - filename_queue.put( - ('.', [self._get_test_info_for_file(test_file)])) - return filename_queue - - tests_by_dir = {} - for test_file in test_files: - directory = self._get_dir_for_test_file(test_file) - tests_by_dir.setdefault(directory, []) - tests_by_dir[directory].append( - self._get_test_info_for_file(test_file)) - - # Sort by the number of tests in the dir so that the ones with the - # most tests get run first in order to maximize parallelization. - # Number of tests is a good enough, but not perfect, approximation - # of how long that set of tests will take to run. We can't just use - # a PriorityQueue until we move # to Python 2.6. - test_lists = [] - http_tests = None - for directory in tests_by_dir: - test_list = tests_by_dir[directory] - # Keep the tests in alphabetical order. - # TODO: Remove once tests are fixed so they can be run in any - # order. - test_list.reverse() - test_list_tuple = (directory, test_list) - if directory == 'LayoutTests' + os.sep + 'http': - http_tests = test_list_tuple - else: + test_info = self._get_test_info_for_file(test_file) + if self._test_requires_lock(test_file): + tests_to_http_lock.append(test_info) + else: + test_lists.append((".", [test_info])) + else: + tests_by_dir = {} + for test_file in test_files: + directory = self._get_dir_for_test_file(test_file) + test_info = self._get_test_info_for_file(test_file) + if self._test_requires_lock(test_file): + tests_to_http_lock.append(test_info) + else: + tests_by_dir.setdefault(directory, []) + tests_by_dir[directory].append(test_info) + # Sort by the number of tests in the dir so that the ones with the + # most tests get run first in order to maximize parallelization. + # Number of tests is a good enough, but not perfect, approximation + # of how long that set of tests will take to run. We can't just use + # a PriorityQueue until we move to Python 2.6. + for directory in tests_by_dir: + test_list = tests_by_dir[directory] + # Keep the tests in alphabetical order. + # FIXME: Remove once tests are fixed so they can be run in any + # order. + test_list.reverse() + test_list_tuple = (directory, test_list) test_lists.append(test_list_tuple) - test_lists.sort(lambda a, b: cmp(len(b[1]), len(a[1]))) + test_lists.sort(lambda a, b: cmp(len(b[1]), len(a[1]))) # Put the http tests first. There are only a couple hundred of them, # but each http test takes a very long time to run, so sorting by the # number of tests doesn't accurately capture how long they take to run. - if http_tests: - test_lists.insert(0, http_tests) + if tests_to_http_lock: + tests_to_http_lock.reverse() + test_lists.insert(0, ("tests_to_http_lock", tests_to_http_lock)) filename_queue = Queue.Queue() for item in test_lists: @@ -687,7 +695,7 @@ class TestRunner: thread_timings.append({'name': thread.getName(), 'num_tests': thread.get_num_tests(), 'total_time': thread.get_total_time()}) - test_timings.update(thread.get_directory_timing_stats()) + test_timings.update(thread.get_test_group_timing_stats()) individual_test_timings.extend(thread.get_test_results()) return (thread_timings, test_timings, individual_test_timings) @@ -696,6 +704,10 @@ class TestRunner: """Returns whether the test runner needs an HTTP server.""" return self._contains_tests(self.HTTP_SUBDIR) + def needs_websocket(self): + """Returns whether the test runner needs a WEBSOCKET server.""" + return self._contains_tests(self.WEBSOCKET_SUBDIR) + def set_up_run(self): """Configures the system to be ready to run tests. @@ -728,14 +740,16 @@ class TestRunner: if not result_summary: return None - if self.needs_http(): - self._printer.print_update('Starting HTTP server ...') - self._port.start_http_server() + # Do not start when http locking is enabled. + if not self._options.wait_for_httpd: + if self.needs_http(): + self._printer.print_update('Starting HTTP server ...') + self._port.start_http_server() - if self._contains_tests(self.WEBSOCKET_SUBDIR): - self._printer.print_update('Starting WebSocket server ...') - self._port.start_websocket_server() - # self._websocket_secure_server.Start() + if self.needs_websocket(): + self._printer.print_update('Starting WebSocket server ...') + self._port.start_websocket_server() + # self._websocket_secure_server.Start() return result_summary @@ -826,10 +840,11 @@ class TestRunner: sys.stdout.flush() _log.debug("flushing stderr") sys.stderr.flush() - _log.debug("stopping http server") - self._port.stop_http_server() - _log.debug("stopping websocket server") - self._port.stop_websocket_server() + if not self._options.wait_for_httpd: + _log.debug("stopping http server") + self._port.stop_http_server() + _log.debug("stopping websocket server") + self._port.stop_websocket_server() _log.debug("stopping helper") self._port.stop_helper() @@ -1432,13 +1447,10 @@ def _set_up_derived_options(port_obj, options): if not options.use_apache: options.use_apache = sys.platform in ('darwin', 'linux2') - if options.results_directory.startswith("/"): - # Assume it's an absolute path and normalize. - options.results_directory = port_obj.get_absolute_path( - options.results_directory) - else: - # If it's a relative path, make the output directory relative to - # Debug or Release. + if not os.path.isabs(options.results_directory): + # This normalizes the path to the build dir. + # FIXME: how this happens is not at all obvious; this is a dumb + # interface and should be cleaned up. options.results_directory = port_obj.results_directory() if not options.time_out_ms: @@ -1588,13 +1600,12 @@ def parse_args(args=None): optparse.make_option("--no-record-results", action="store_false", default=True, dest="record_results", help="Don't record the results."), + optparse.make_option("--wait-for-httpd", action="store_true", + default=False, dest="wait_for_httpd", + help="Wait for http locks."), # old-run-webkit-tests also has HTTP toggle options: # --[no-]http Run (or do not run) http tests # (default: run) - # --[no-]wait-for-httpd Wait for httpd if some other test - # session is using it already (same - # as WEBKIT_WAIT_FOR_HTTPD=1). - # (default: 0) ] test_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 6fe99d6..a716cec 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py @@ -1,5 +1,6 @@ #!/usr/bin/python # Copyright (C) 2010 Google Inc. All rights reserved. +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -33,6 +34,7 @@ import codecs import logging import os import Queue +import shutil import sys import tempfile import thread @@ -70,7 +72,7 @@ def passing_run(args=[], port_obj=None, record_results=False, # We use the glob to test that globbing works. new_args.extend(['passes', 'http/tests', - 'websocket/tests', + 'http/tests/websocket/tests', 'failures/expected/*']) options, parsed_args = run_webkit_tests.parse_args(new_args) if port_obj is None: @@ -88,7 +90,7 @@ def logging_run(args=[], tests_included=False): if not tests_included: new_args.extend(['passes', 'http/tests', - 'websocket/tests', + 'http/tests/websocket/tests', 'failures/expected/*']) options, parsed_args = run_webkit_tests.parse_args(new_args) user = MockUser() @@ -232,10 +234,37 @@ class MainTest(unittest.TestCase): self.assertFalse(err.empty()) self.assertEqual(user.url, '/tmp/layout-test-results/results.html') + def test_results_directory_absolute(self): + # We run a configuration that should fail, to generate output, then + # look for what the output results url was. + + tmpdir = tempfile.mkdtemp() + res, out, err, user = logging_run(['--results-directory=' + tmpdir], + tests_included=True) + self.assertEqual(user.url, os.path.join(tmpdir, 'results.html')) + shutil.rmtree(tmpdir, ignore_errors=True) + + def test_results_directory_default(self): + # We run a configuration that should fail, to generate output, then + # look for what the output results url was. + + # This is the default location. + res, out, err, user = logging_run(tests_included=True) + self.assertEqual(user.url, '/tmp/layout-test-results/results.html') + + def test_results_directory_relative(self): + # We run a configuration that should fail, to generate output, then + # look for what the output results url was. + + res, out, err, user = logging_run(['--results-directory=foo'], + tests_included=True) + self.assertEqual(user.url, '/tmp/foo/results.html') + + def _mocked_open(original_open, file_list): def _wrapper(name, mode, encoding): - if name.find("-expected.") != -1 and mode == "w": + if name.find("-expected.") != -1 and mode.find("w") != -1: # we don't want to actually write new baselines, so stub these out name.replace('\\', '/') file_list.append(name) @@ -251,7 +280,10 @@ class RebaselineTest(unittest.TestCase): baseline = file + "-expected" + ext self.assertTrue(any(f.find(baseline) != -1 for f in file_list)) - def test_reset_results(self): + # FIXME: This test is failing on the bots. Also, this test touches the + # file system. Unit tests should not read or write the file system. + # https://bugs.webkit.org/show_bug.cgi?id=47879 + def disabled_test_reset_results(self): file_list = [] original_open = codecs.open try: @@ -294,6 +326,11 @@ class RebaselineTest(unittest.TestCase): codecs.open = original_open +class TestRunnerWrapper(run_webkit_tests.TestRunner): + def _get_test_info_for_file(self, test_file): + return test_file + + class TestRunnerTest(unittest.TestCase): def test_results_html(self): mock_port = Mock() @@ -314,6 +351,52 @@ class TestRunnerTest(unittest.TestCase): html = runner._results_html(["test_path"], {}, "Title", override_time="time") self.assertEqual(html, expected_html) + def queue_to_list(self, queue): + queue_list = [] + while(True): + try: + queue_list.append(queue.get_nowait()) + except Queue.Empty: + break + return queue_list + + def test_get_test_file_queue(self): + # Test that _get_test_file_queue in run_webkit_tests.TestRunner really + # put the http tests first in the queue. + runner = TestRunnerWrapper(port=Mock(), options=Mock(), printer=Mock()) + runner._options.experimental_fully_parallel = False + + test_list = [ + "LayoutTests/websocket/tests/unicode.htm", + "LayoutTests/animations/keyframes.html", + "LayoutTests/http/tests/security/view-source-no-refresh.html", + "LayoutTests/websocket/tests/websocket-protocol-ignored.html", + "LayoutTests/fast/css/display-none-inline-style-change-crash.html", + "LayoutTests/http/tests/xmlhttprequest/supported-xml-content-types.html", + "LayoutTests/dom/html/level2/html/HTMLAnchorElement03.html", + "LayoutTests/ietestcenter/Javascript/11.1.5_4-4-c-1.html", + "LayoutTests/dom/html/level2/html/HTMLAnchorElement06.html", + ] + + expected_tests_to_http_lock = set([ + 'LayoutTests/websocket/tests/unicode.htm', + 'LayoutTests/http/tests/security/view-source-no-refresh.html', + 'LayoutTests/websocket/tests/websocket-protocol-ignored.html', + 'LayoutTests/http/tests/xmlhttprequest/supported-xml-content-types.html', + ]) + + runner._options.child_processes = 1 + test_queue_for_single_thread = runner._get_test_file_queue(test_list) + runner._options.child_processes = 2 + test_queue_for_multi_thread = runner._get_test_file_queue(test_list) + + single_thread_results = self.queue_to_list(test_queue_for_single_thread) + multi_thread_results = self.queue_to_list(test_queue_for_multi_thread) + + self.assertEqual("tests_to_http_lock", single_thread_results[0][0]) + self.assertEqual(expected_tests_to_http_lock, set(single_thread_results[0][1])) + self.assertEqual("tests_to_http_lock", multi_thread_results[0][0]) + self.assertEqual(expected_tests_to_http_lock, set(multi_thread_results[0][1])) class DryrunTest(unittest.TestCase): # FIXME: it's hard to know which platforms are safe to test; the 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 1ad0fe6..0b05802 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py @@ -104,7 +104,7 @@ class ImageDiff(test_type_base.TestTypeBase): self.FILENAME_SUFFIX_EXPECTED + '.png') expected_image = port.expected_image(filename) - with codecs.open(actual_filename, 'r', None) as file: + with codecs.open(actual_filename, 'r+b', None) as file: actual_image = file.read() result = port.diff_image(expected_image, actual_image, 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 3a6e92b..dcc64a3 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 @@ -161,7 +161,10 @@ class TestTypeBase(object): def _write_into_file_at_path(self, file_path, contents, encoding): """This method assumes that byte_array is already encoded into the right format.""" - with codecs.open(file_path, "w", encoding=encoding) as file: + open_mode = 'w' + if encoding is None: + open_mode = 'w+b' + with codecs.open(file_path, open_mode, encoding=encoding) as file: file.write(contents) def write_output_files(self, filename, file_type, diff --git a/WebKitTools/Scripts/webkitpy/style/checker.py b/WebKitTools/Scripts/webkitpy/style/checker.py index f8eefa4..e0c956f 100644 --- a/WebKitTools/Scripts/webkitpy/style/checker.py +++ b/WebKitTools/Scripts/webkitpy/style/checker.py @@ -134,6 +134,7 @@ _PATH_RULES_SPECIFIER = [ ([# The GTK+ APIs use GTK+ naming style, which includes # lower-cased, underscore-separated values. # Also, GTK+ allows the use of NULL. + "WebCore/bindings/scripts/test/GObject", "WebKit/gtk/webkit/", "WebKitTools/DumpRenderTree/gtk/"], ["-readability/naming", @@ -142,6 +143,10 @@ _PATH_RULES_SPECIFIER = [ # exceptional header guards (e.g., WebCore_FWD_Debugger_h). "/ForwardingHeaders/"], ["-build/header_guard"]), + ([# assembler has lots of opcodes that use underscores, so + # we don't check for underscores in that directory. + "/JavaScriptCore/assembler/"], + ["-readability/naming"]), # For third-party Python code, keep only the following checks-- # diff --git a/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py index f8ebeff..7c1cb3e 100644 --- a/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py @@ -2512,7 +2512,7 @@ def check_identifier_name_in_declaration(filename, line_number, line, error): modified_identifier = sub(r'(^|(?<=::))[ms]_', '', identifier) if modified_identifier.find('_') >= 0: # Various exceptions to the rule: JavaScript op codes functions, const_iterator. - if (not (filename.find('JavaScriptCore') >= 0 and modified_identifier.find('_op_') >= 0) + if (not (filename.find('JavaScriptCore') >= 0 and modified_identifier.find('op_') >= 0) and not modified_identifier.startswith('tst_') and not modified_identifier.startswith('webkit_dom_object_') and not modified_identifier.startswith('NPN_') @@ -2521,7 +2521,8 @@ def check_identifier_name_in_declaration(filename, line_number, line, error): and not modified_identifier.startswith('qt_') and not modified_identifier.startswith('cairo_') and not modified_identifier.find('::qt_') >= 0 - and not modified_identifier == "const_iterator"): + and not modified_identifier == "const_iterator" + and not modified_identifier == "vm_throw"): error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.") # Check for variables named 'l', these are too easy to confuse with '1' in some fonts diff --git a/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py index 2f54305..071ce50 100644 --- a/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py @@ -3690,6 +3690,7 @@ class WebKitStyleTest(CppStyleTestBase): # There is an exception for op code functions but only in the JavaScriptCore directory. self.assert_lint('void this_op_code(int var1, int var2)', '', 'JavaScriptCore/foo.cpp') + self.assert_lint('void op_code(int var1, int var2)', '', 'JavaScriptCore/foo.cpp') self.assert_lint('void this_op_code(int var1, int var2)', 'this_op_code' + name_underscore_error_message) # GObject requires certain magical names in class declarations. @@ -3716,6 +3717,9 @@ class WebKitStyleTest(CppStyleTestBase): # const_iterator is allowed as well. self.assert_lint('typedef VectorType::const_iterator const_iterator;', '') + # vm_throw is allowed as well. + self.assert_lint('int vm_throw;', '') + # Bitfields. self.assert_lint('unsigned _fillRule : 1;', '_fillRule' + name_underscore_error_message) diff --git a/WebKitTools/Scripts/webkitpy/style/patchreader.py b/WebKitTools/Scripts/webkitpy/style/patchreader.py index 576504a..f44839d 100644 --- a/WebKitTools/Scripts/webkitpy/style/patchreader.py +++ b/WebKitTools/Scripts/webkitpy/style/patchreader.py @@ -37,7 +37,6 @@ _log = logging.getLogger("webkitpy.style.patchreader") class PatchReader(object): - """Supports checking style in patches.""" def __init__(self, text_file_reader): @@ -53,28 +52,15 @@ class PatchReader(object): """Check style in the given patch.""" patch_files = DiffParser(patch_string.splitlines()).files - # The diff variable is a DiffFile instance. - for path, diff in patch_files.iteritems(): - line_numbers = set() - for line in diff.lines: - # When deleted line is not set, it means that - # the line is newly added (or modified). - if not line[0]: - line_numbers.add(line[1]) - - _log.debug('Found %s new or modified lines in: %s' - % (len(line_numbers), path)) + for path, diff_file in patch_files.iteritems(): + line_numbers = diff_file.added_or_modified_line_numbers() + _log.debug('Found %s new or modified lines in: %s' % (len(line_numbers), path)) - # If line_numbers is empty, the file has no new or - # modified lines. In this case, we don't check the file - # because we'll never output errors for the file. - # This optimization also prevents the program from exiting - # due to a deleted file. - if line_numbers: - self._text_file_reader.process_file(file_path=path, - line_numbers=line_numbers) - else: - # We don't check the file which contains deleted lines only - # but would like to treat it as to be processed so that - # we count up number of such files. + if not line_numbers: + # Don't check files which contain only deleted lines + # as they can never add style errors. However, mark them as + # processed so that we count up number of such files. self._text_file_reader.count_delete_only_file() + continue + + self._text_file_reader.process_file(file_path=path, line_numbers=line_numbers) diff --git a/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py b/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py index 2453c6b..b121082 100644 --- a/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py @@ -78,7 +78,7 @@ index ef65bee..e3db70e 100644 # Required for Python to search this directory for module files +# New line """) - self._assert_checked([("__init__.py", set([2]))], 0) + self._assert_checked([("__init__.py", [2])], 0) def test_check_patch_with_deletion(self): self._call_check_patch("""Index: __init__.py diff --git a/WebKitTools/Scripts/webkitpy/test/main.py b/WebKitTools/Scripts/webkitpy/test/main.py index 9351768..1038d82 100644 --- a/WebKitTools/Scripts/webkitpy/test/main.py +++ b/WebKitTools/Scripts/webkitpy/test/main.py @@ -50,12 +50,12 @@ class Tester(object): return unittest_paths - def _modules_from_paths(self, webkitpy_dir, paths): + def _modules_from_paths(self, package_root, paths): """Return a list of fully-qualified module names given paths.""" - webkitpy_dir = os.path.abspath(webkitpy_dir) - webkitpy_name = os.path.split(webkitpy_dir)[1] # Equals "webkitpy". + package_path = os.path.abspath(package_root) + root_package_name = os.path.split(package_path)[1] # Equals "webkitpy". - prefix_length = len(webkitpy_dir) + prefix_length = len(package_path) modules = [] for path in paths: @@ -72,7 +72,8 @@ class Tester(object): break parts.insert(0, tail) # We now have, for example: common.config.ports_unittest - parts.insert(0, webkitpy_name) # Put "webkitpy" at the beginning. + # FIXME: This is all a hack around the fact that we always prefix webkitpy includes with "webkitpy." + parts.insert(0, root_package_name) # Put "webkitpy" at the beginning. module = ".".join(parts) modules.append(module) @@ -91,6 +92,9 @@ class Tester(object): if external_package_paths is None: external_package_paths = [] else: + # FIXME: We should consider moving webkitpy off of using "webkitpy." to prefix + # all includes. If we did that, then this would use path instead of dirname(path). + # QueueStatusServer.__init__ has a sys.path import hack due to this code. 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("-"): @@ -101,6 +105,7 @@ class Tester(object): # Otherwise, auto-detect all unit tests. + # FIXME: This should be combined with the external_package_paths code above. webkitpy_dir = os.path.dirname(webkitpy.__file__) modules = [] diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py index a347972..02e203c 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py @@ -27,19 +27,39 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from webkitpy.common.system.executive import ScriptError +from webkitpy.common.net.layouttestresults import LayoutTestResults + + +class CommitQueueTaskDelegate(object): + def run_command(self, command): + raise NotImplementedError("subclasses must implement") + + def command_passed(self, message, patch): + raise NotImplementedError("subclasses must implement") + + def command_failed(self, message, script_error, patch): + raise NotImplementedError("subclasses must implement") + + def refetch_patch(self, patch): + raise NotImplementedError("subclasses must implement") + + def layout_test_results(self): + raise NotImplementedError("subclasses must implement") + + def report_flaky_tests(self, patch, flaky_tests): + raise NotImplementedError("subclasses must implement") class CommitQueueTask(object): - def __init__(self, tool, commit_queue, patch): - self._tool = tool - self._commit_queue = commit_queue + def __init__(self, delegate, patch): + self._delegate = delegate 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()) + self._patch = self._delegate.refetch_patch(self._patch) if self._patch.is_obsolete(): return False if self._patch.bug().is_closed(): @@ -52,12 +72,12 @@ class CommitQueueTask(object): 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) + self._delegate.run_command(command) + self._delegate.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) + self.failure_status_id = self._delegate.command_failed(failure_message, script_error=self._script_error, patch=self._patch) return False def _apply(self): @@ -76,7 +96,6 @@ class CommitQueueTask(object): "build", "--no-clean", "--no-update", - "--build", "--build-style=both", "--quiet", ], @@ -88,7 +107,6 @@ class CommitQueueTask(object): "build", "--force-clean", "--no-update", - "--build", "--build-style=both", "--quiet", ], @@ -121,6 +139,12 @@ class CommitQueueTask(object): "Able to pass tests without patch", "Unable to pass tests without patch (tree is red?)") + def _failing_tests_from_last_run(self): + results = self._delegate.layout_test_results() + if not results: + return None + return results.failing_tests() + def _land(self): return self._run_command([ "land-attachment", @@ -134,6 +158,29 @@ class CommitQueueTask(object): "Landed patch", "Unable to land patch") + def _report_flaky_tests(self, flaky_tests): + self._delegate.report_flaky_tests(self._patch, flaky_tests) + + def _test_patch(self): + if self._patch.is_rollout(): + return True + if self._test(): + return True + + first_failing_tests = self._failing_tests_from_last_run() + if self._test(): + self._report_flaky_tests(first_failing_tests) + return True + + second_failing_tests = self._failing_tests_from_last_run() + if first_failing_tests != second_failing_tests: + self._report_flaky_tests(first_failing_tests + second_failing_tests) + return False + + if self._build_and_test_without_patch(): + raise self._script_error # The error from the previous ._test() run is real, report it. + return False # Tree must be red, just retry later. + def run(self): if not self._validate(): return False @@ -143,12 +190,8 @@ class CommitQueueTask(object): 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 + if not self._test_patch(): + return False # 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(): diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py index 8b46146..6fa0667 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py @@ -36,11 +36,11 @@ from webkitpy.tool.bot.commitqueuetask import * from webkitpy.tool.mocktool import MockTool -class MockCommitQueue: +class MockCommitQueue(CommitQueueTaskDelegate): def __init__(self, error_plan): self._error_plan = error_plan - def run_webkit_patch(self, command): + def run_command(self, command): log("run_webkit_patch: %s" % command) if self._error_plan: error = self._error_plan.pop(0) @@ -56,19 +56,28 @@ class MockCommitQueue: failure_message, script_error, patch.id())) return 3947 + def refetch_patch(self, patch): + return patch + + def layout_test_results(self): + return None + + def report_flaky_tests(self, patch, flaky_tests): + log("report_flaky_tests: patch='%s' flaky_tests='%s'" % (patch.id(), flaky_tests)) + 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) + task = CommitQueueTask(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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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' @@ -93,9 +102,9 @@ command_failed: failure_message='Patch does not apply' script_error='MOCK apply ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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'] +run_webkit_patch: ['build', '--force-clean', '--no-update', '--build-style=both', '--quiet'] command_passed: success_message='Able to build without patch' patch='197' """ self._run_through_task(commit_queue, expected_stderr, ScriptError) @@ -108,9 +117,9 @@ command_passed: success_message='Able to build without patch' patch='197' ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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'] +run_webkit_patch: ['build', '--force-clean', '--no-update', '--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) @@ -123,12 +132,13 @@ command_failed: failure_message='Unable to build without patch' script_error='MO ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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' +report_flaky_tests: patch='197' flaky_tests='None' 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' """ @@ -143,7 +153,7 @@ command_passed: success_message='Landed patch' patch='197' ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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' @@ -164,7 +174,7 @@ command_passed: success_message='Able to pass tests without patch' patch='197' ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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' @@ -184,7 +194,7 @@ command_failed: failure_message='Unable to pass tests without patch (tree is red ]) 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'] +run_webkit_patch: ['build', '--no-clean', '--no-update', '--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' diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py index 15eaaf3..dc892a4 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py @@ -28,18 +28,15 @@ from webkitpy.common.system.deprecated_logging import log from webkitpy.common.net.bugzilla import CommitterValidator +from webkitpy.tool.grammar import pluralize 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)) + def feed(self): + raise NotImplementedError("subclasses must implement") class CommitQueueFeeder(AbstractFeeder): @@ -49,11 +46,17 @@ class CommitQueueFeeder(AbstractFeeder): AbstractFeeder.__init__(self, tool) self.committer_validator = CommitterValidator(self._tool.bugs) + def _update_work_items(self, item_ids): + # FIXME: This is the last use of update_work_items, the commit-queue + # should move to feeding patches one at a time like the EWS does. + self._tool.status_server.update_work_items(self.queue_name, item_ids) + log("Feeding %s items %s" % (self.queue_name, item_ids)) + 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) + 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) @@ -71,3 +74,17 @@ class CommitQueueFeeder(AbstractFeeder): if rollout_cmp != 0: return rollout_cmp return cmp(a.attach_date(), b.attach_date()) + + +class EWSFeeder(AbstractFeeder): + def __init__(self, tool): + self._ids_sent_to_server = set() + AbstractFeeder.__init__(self, tool) + + def feed(self): + ids_needing_review = set(self._tool.bugs.queries.fetch_attachment_ids_from_review_queue()) + new_ids = ids_needing_review.difference(self._ids_sent_to_server) + log("Feeding EWS (%s, %s new)" % (pluralize("r? patch", len(ids_needing_review)), len(new_ids))) + for attachment_id in new_ids: # Order doesn't really matter for the EWS. + self._tool.status_server.submit_to_ews(attachment_id) + self._ids_sent_to_server.add(attachment_id) diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/patchcollection.py b/WebKitTools/Scripts/webkitpy/tool/bot/patchcollection.py deleted file mode 100644 index 6100cf8..0000000 --- a/WebKitTools/Scripts/webkitpy/tool/bot/patchcollection.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -class PersistentPatchCollectionDelegate: - def collection_name(self): - raise NotImplementedError, "subclasses must implement" - - def fetch_potential_patch_ids(self): - raise NotImplementedError, "subclasses must implement" - - def status_server(self): - raise NotImplementedError, "subclasses must implement" - - def is_terminal_status(self, status): - raise NotImplementedError, "subclasses must implement" - - -class PersistentPatchCollection: - def __init__(self, delegate): - self._delegate = delegate - self._name = self._delegate.collection_name() - self._status = self._delegate.status_server() - self._status_cache = {} - - def _cached_status(self, patch_id): - cached = self._status_cache.get(patch_id) - if cached: - return cached - status = self._status.patch_status(self._name, patch_id) - if status and self._delegate.is_terminal_status(status): - self._status_cache[patch_id] = status - return status - - def _is_active_patch_id(self, patch_id): - """Active patches are patches waiting to be processed from this collection.""" - status = self._cached_status(patch_id) - return not status or not self._delegate.is_terminal_status(status) - - def _fetch_active_patch_ids(self): - patch_ids = self._delegate.fetch_potential_patch_ids() - return filter(lambda patch_id: self._is_active_patch_id(patch_id), patch_ids) - - def next(self): - # Note: We only fetch all the ids so we can post them back to the server. - # This will go away once we have a feeder queue and all other queues are - # just pulling their next work item from the server. - patch_ids = self._fetch_active_patch_ids() - # FIXME: We're assuming self._name is a valid queue-name. - self._status.update_work_items(self._name, patch_ids) - if not patch_ids: - return None - return patch_ids[0] diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py index 8118653..8b016e8 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py @@ -125,8 +125,8 @@ class QueueEngine: traceback.print_exc() # Don't try tell the status bot, in case telling it causes an exception. self._sleep("Exception while preparing queue") - # Never reached. - self._ensure_work_log_closed() + self._stopping("Delegate terminated queue.") + return 0 def _stopping(self, message): log("\n%s" % message) diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py index bfec401..37d8502 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py @@ -43,6 +43,7 @@ class LoggingDelegate(QueueEngineDelegate): self._test = test self._callbacks = [] self._run_before = False + self.stop_message = None expected_callbacks = [ 'queue_log_path', @@ -52,7 +53,8 @@ class LoggingDelegate(QueueEngineDelegate): 'should_proceed_with_work_item', 'work_item_log_path', 'process_work_item', - 'should_continue_work_queue' + 'should_continue_work_queue', + 'stop_work_queue', ] def record(self, method_name): @@ -95,21 +97,20 @@ class LoggingDelegate(QueueEngineDelegate): self.record("handle_unexpected_error") self._test.assertEquals(work_item, "work_item") + def stop_work_queue(self, message): + self.record("stop_work_queue") + self.stop_message = message + class RaisingDelegate(LoggingDelegate): def __init__(self, test, exception): LoggingDelegate.__init__(self, test) self._exception = exception - self.stop_message = None def process_work_item(self, work_item): self.record("process_work_item") raise self._exception - def stop_work_queue(self, message): - self.record("stop_work_queue") - self.stop_message = message - class NotSafeToProceedDelegate(LoggingDelegate): def should_proceed_with_work_item(self, work_item): @@ -132,16 +133,15 @@ class FastQueueEngine(QueueEngine): class QueueEngineTest(unittest.TestCase): def test_trivial(self): delegate = LoggingDelegate(self) - work_queue = QueueEngine("trivial-queue", delegate, threading.Event()) - work_queue.run() + self._run_engine(delegate) + self.assertEquals(delegate.stop_message, "Delegate terminated queue.") self.assertEquals(delegate._callbacks, LoggingDelegate.expected_callbacks) self.assertTrue(os.path.exists(os.path.join(self.temp_dir, "queue_log_path"))) self.assertTrue(os.path.exists(os.path.join(self.temp_dir, "work_log_path", "work_item.log"))) def test_unexpected_error(self): delegate = RaisingDelegate(self, ScriptError(exit_code=3)) - work_queue = QueueEngine("error-queue", delegate, threading.Event()) - work_queue.run() + self._run_engine(delegate) expected_callbacks = LoggingDelegate.expected_callbacks[:] work_item_index = expected_callbacks.index('process_work_item') # The unexpected error should be handled right after process_work_item starts @@ -151,11 +151,18 @@ class QueueEngineTest(unittest.TestCase): def test_handled_error(self): delegate = RaisingDelegate(self, ScriptError(exit_code=QueueEngine.handled_error_code)) - work_queue = QueueEngine("handled-error-queue", delegate, threading.Event()) - work_queue.run() + self._run_engine(delegate) self.assertEquals(delegate._callbacks, LoggingDelegate.expected_callbacks) - def _test_terminating_queue(self, exception, expected_message): + def _run_engine(self, delegate, engine=None, termination_message=None): + if not engine: + engine = QueueEngine("test-queue", delegate, threading.Event()) + if not termination_message: + termination_message = "Delegate terminated queue." + expected_stderr = "\n%s\n" % termination_message + OutputCapture().assert_outputs(self, engine.run, [], expected_stderr=expected_stderr) + + def _test_terminating_queue(self, exception, termination_message): work_item_index = LoggingDelegate.expected_callbacks.index('process_work_item') # The terminating error should be handled right after process_work_item. # There should be no other callbacks after stop_work_queue. @@ -163,14 +170,10 @@ class QueueEngineTest(unittest.TestCase): expected_callbacks.append("stop_work_queue") delegate = RaisingDelegate(self, exception) - work_queue = QueueEngine("terminating-queue", delegate, threading.Event()) - - output = OutputCapture() - expected_stderr = "\n%s\n" % expected_message - output.assert_outputs(self, work_queue.run, [], expected_stderr=expected_stderr) + self._run_engine(delegate, termination_message=termination_message) self.assertEquals(delegate._callbacks, expected_callbacks) - self.assertEquals(delegate.stop_message, expected_message) + self.assertEquals(delegate.stop_message, termination_message) def test_terminating_error(self): self._test_terminating_queue(KeyboardInterrupt(), "User terminated queue.") @@ -178,15 +181,10 @@ class QueueEngineTest(unittest.TestCase): def test_not_safe_to_proceed(self): delegate = NotSafeToProceedDelegate(self) - work_queue = FastQueueEngine(delegate) - work_queue.run() + self._run_engine(delegate, engine=FastQueueEngine(delegate)) expected_callbacks = LoggingDelegate.expected_callbacks[:] - next_work_item_index = expected_callbacks.index('next_work_item') - # We slice out the common part of the expected callbacks. - # We add 2 here to include should_proceed_with_work_item, which is - # a pain to search for directly because it occurs twice. - expected_callbacks = expected_callbacks[:next_work_item_index + 2] - expected_callbacks.append('should_continue_work_queue') + expected_callbacks.remove('work_item_log_path') + expected_callbacks.remove('process_work_item') self.assertEquals(delegate._callbacks, expected_callbacks) def test_now(self): diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py index a38c3cf..da506bc 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py @@ -77,55 +77,15 @@ class Sheriff(object): ]) return parse_bug_id(output) - def _rollout_reason(self, builders): - # FIXME: This should explain which layout tests failed - # however, that would require Build objects here, either passed - # in through failure_info, or through Builder.latest_build. - names = [builder.name() for builder in builders] - return "Caused builders %s to fail." % join_with_separators(names) - - def post_automatic_rollout_patch(self, commit_info, builders): - # For now we're only posting rollout patches for commit-queue patches. - commit_bot_email = "eseidel@chromium.org" - if commit_bot_email == commit_info.committer_email(): - try: - self.post_rollout_patch(commit_info.revision(), - self._rollout_reason(builders)) - except ScriptError, e: - log("Failed to create-rollout.") - - def post_blame_comment_on_bug(self, commit_info, builders, blame_list): + def post_blame_comment_on_bug(self, commit_info, builders, tests): if not commit_info.bug_id(): return comment = "%s might have broken %s" % ( view_source_url(commit_info.revision()), join_with_separators([builder.name() for builder in builders])) - if len(blame_list) > 1: - comment += "\nThe following changes are on the blame list:\n" - comment += "\n".join(map(view_source_url, blame_list)) + if tests: + comment += "\nThe following tests are not passing:\n" + comment += "\n".join(tests) self._tool.bugs.post_comment_to_bug(commit_info.bug_id(), comment, cc=self._sheriffbot.watchers) - - # FIXME: Should some of this logic be on BuildBot? - def provoke_flaky_builders(self, revisions_causing_failures): - # We force_build builders that are red but have not "failed" (i.e., - # been red twice). We do this to avoid a deadlock situation where a - # flaky test blocks the commit-queue and there aren't any other - # patches being landed to re-spin the builder. - failed_builders = sum([revisions_causing_failures[key] for - key in revisions_causing_failures.keys()], []) - failed_builder_names = \ - set([builder.name() for builder in failed_builders]) - idle_red_builder_names = \ - set([builder["name"] - for builder in self._tool.buildbot.idle_red_core_builders()]) - - # We only want to provoke these builders if they are idle and have not - # yet "failed" (i.e., been red twice) to avoid overloading the bots. - flaky_builder_names = idle_red_builder_names - failed_builder_names - - for name in flaky_builder_names: - flaky_builder = self._tool.buildbot.builder_with_name(name) - flaky_builder.force_build(username=self._sheriffbot.name, - comments="Probe for flakiness.") diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py index c375ff9..690af1f 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py @@ -47,15 +47,6 @@ class MockSheriffBot(object): class SheriffTest(unittest.TestCase): - def test_rollout_reason(self): - sheriff = Sheriff(MockTool(), MockSheriffBot()) - builders = [ - Builder("Foo", None), - Builder("Bar", None), - ] - reason = "Caused builders Foo and Bar to fail." - self.assertEquals(sheriff._rollout_reason(builders), reason) - def test_post_blame_comment_on_bug(self): def run(): sheriff = Sheriff(MockTool(), MockSheriffBot()) @@ -68,38 +59,32 @@ class SheriffTest(unittest.TestCase): commit_info.revision = lambda: 4321 # Should do nothing with no bug_id sheriff.post_blame_comment_on_bug(commit_info, builders, []) - sheriff.post_blame_comment_on_bug(commit_info, builders, [2468, 5646]) + sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1", "mock-test-2"]) # Should try to post a comment to the bug, but MockTool.bugs does nothing. commit_info.bug_id = lambda: 1234 sheriff.post_blame_comment_on_bug(commit_info, builders, []) - sheriff.post_blame_comment_on_bug(commit_info, builders, [3432]) - sheriff.post_blame_comment_on_bug(commit_info, builders, [841, 5646]) + sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1"]) + sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1", "mock-test-2"]) - expected_stderr = u"MOCK bug comment: bug_id=1234, cc=['watcher@example.com']\n--- Begin comment ---\\http://trac.webkit.org/changeset/4321 might have broken Foo and Bar\n--- End comment ---\n\nMOCK bug comment: bug_id=1234, cc=['watcher@example.com']\n--- Begin comment ---\\http://trac.webkit.org/changeset/4321 might have broken Foo and Bar\n--- End comment ---\n\nMOCK bug comment: bug_id=1234, cc=['watcher@example.com']\n--- Begin comment ---\\http://trac.webkit.org/changeset/4321 might have broken Foo and Bar\nThe following changes are on the blame list:\nhttp://trac.webkit.org/changeset/841\nhttp://trac.webkit.org/changeset/5646\n--- End comment ---\n\n" - OutputCapture().assert_outputs(self, run, expected_stderr=expected_stderr) + expected_stderr = u"""MOCK bug comment: bug_id=1234, cc=['watcher@example.com'] +--- Begin comment --- +http://trac.webkit.org/changeset/4321 might have broken Foo and Bar +--- End comment --- - def test_provoke_flaky_builders(self): - def run(): - tool = MockTool() - tool.buildbot.light_tree_on_fire() - sheriff = Sheriff(tool, MockSheriffBot()) - revisions_causing_failures = {} - sheriff.provoke_flaky_builders(revisions_causing_failures) - expected_stderr = "MOCK: force_build: name=Builder2, username=mock-sheriff-bot, comments=Probe for flakiness.\n" - OutputCapture().assert_outputs(self, run, expected_stderr=expected_stderr) +MOCK bug comment: bug_id=1234, cc=['watcher@example.com'] +--- Begin comment --- +http://trac.webkit.org/changeset/4321 might have broken Foo and Bar +The following tests are not passing: +mock-test-1 +--- End comment --- - def test_post_blame_comment_on_bug(self): - sheriff = Sheriff(MockTool(), MockSheriffBot()) - builders = [ - Builder("Foo", None), - Builder("Bar", None), - ] - commit_info = Mock() - commit_info.bug_id = lambda: None - commit_info.revision = lambda: 4321 - commit_info.committer = lambda: None - commit_info.committer_email = lambda: "foo@example.com" - commit_info.reviewer = lambda: None - commit_info.author = lambda: None - sheriff.post_automatic_rollout_patch(commit_info, builders) +MOCK bug comment: bug_id=1234, cc=['watcher@example.com'] +--- Begin comment --- +http://trac.webkit.org/changeset/4321 might have broken Foo and Bar +The following tests are not passing: +mock-test-1 +mock-test-2 +--- End comment --- +""" + OutputCapture().assert_outputs(self, run, expected_stderr=expected_stderr) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/commandtest.py b/WebKitTools/Scripts/webkitpy/tool/commands/commandtest.py index de92cd3..adc6d81 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/commandtest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/commandtest.py @@ -33,5 +33,16 @@ from webkitpy.tool.mocktool import MockOptions, MockTool class CommandsTest(unittest.TestCase): def assert_execute_outputs(self, command, args, expected_stdout="", expected_stderr="", options=MockOptions(), tool=MockTool()): + options.blocks = True + options.cc = 'MOCK cc' + options.component = 'MOCK component' + options.confirm = True + options.email = 'MOCK email' + options.git_commit = 'MOCK git commit' + options.obsolete_patches = True + options.open_bug = True + options.port = 'MOCK port' + options.quiet = True + options.reviewer = 'MOCK reviewer' command.bind_to_tool(tool) OutputCapture().assert_outputs(self, command.execute, [options, args, tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download.py b/WebKitTools/Scripts/webkitpy/tool/commands/download.py index 9916523..ed5c604 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/download.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/download.py @@ -43,6 +43,17 @@ from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand from webkitpy.common.system.deprecated_logging import error, log +class Clean(AbstractSequencedCommand): + name = "clean" + help_text = "Clean the working copy" + steps = [ + steps.CleanWorkingDirectory, + ] + + def _prepare_state(self, options, args, tool): + options.force_clean = True + + class Update(AbstractSequencedCommand): name = "update" help_text = "Update working copy (used internally)" @@ -61,6 +72,9 @@ class Build(AbstractSequencedCommand): steps.Build, ] + def _prepare_state(self, options, args, tool): + options.build = True + class BuildAndTest(AbstractSequencedCommand): name = "build-and-test" diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py index faddd50..6af1f64 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/download_unittest.py @@ -57,15 +57,19 @@ class AbstractRolloutPrepCommandTest(unittest.TestCase): class DownloadCommandsTest(CommandsTest): def _default_options(self): options = MockOptions() - options.force_clean = False - options.clean = True + options.build = True + options.build_style = True options.check_builders = True - options.quiet = False + options.check_style = True + options.clean = True + options.close_bug = True + options.force_clean = False + options.force_patch = True options.non_interactive = False - options.update = True - options.build = True + options.parent_command = 'MOCK parent command' + options.quiet = False options.test = True - options.close_bug = True + options.update = True return options def test_build(self): diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py index 86e2e15..5ec468e 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py @@ -48,7 +48,6 @@ class AbstractEarlyWarningSystem(AbstractReviewQueue): self.run_webkit_patch([ "build", self.port.flag(), - "--build", "--build-style=%s" % self._build_style, "--force-clean", "--no-update", @@ -149,10 +148,6 @@ class ChromiumWindowsEWS(AbstractChromiumEWS): name = "cr-win-ews" -class ChromiumMacEWS(AbstractChromiumEWS): - name = "cr-mac-ews" - - # For platforms that we can't run inside a VM (like Mac OS X), we require # patches to be uploaded by committers, who are generally trustworthy folk. :) class AbstractCommitterOnlyEWS(AbstractEarlyWarningSystem): @@ -167,6 +162,14 @@ class AbstractCommitterOnlyEWS(AbstractEarlyWarningSystem): return AbstractEarlyWarningSystem.process_work_item(self, patch) +# FIXME: Inheriting from AbstractCommitterOnlyEWS is kinda a hack, but it +# happens to work because AbstractChromiumEWS and AbstractCommitterOnlyEWS +# provide disjoint sets of functionality, and Python is otherwise smart +# enough to handle the diamond inheritance. +class ChromiumMacEWS(AbstractChromiumEWS, AbstractCommitterOnlyEWS): + name = "cr-mac-ews" + + class MacEWS(AbstractCommitterOnlyEWS): name = "mac-ews" port_name = "mac" diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py index 3b0ea47..c400f81 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py @@ -48,9 +48,9 @@ class EarlyWarningSytemTest(QueuesTest): expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr(ews.name, os.getcwd()), # FIXME: Use of os.getcwd() is wrong, should be scm.checkout_root "handle_unexpected_error": "Mock error message\n", - "next_work_item": "MOCK: update_work_items: %(name)s [103]\n" % string_replacemnts, - "process_work_item": "MOCK: update_status: %(name)s Pass\n" % string_replacemnts, - "handle_script_error": "MOCK: update_status: %(name)s ScriptError error message\nMOCK bug comment: bug_id=142, cc=%(watchers)s\n--- Begin comment ---\\Attachment 197 did not build on %(port)s:\nBuild output: http://dummy_url\n--- End comment ---\n\n" % string_replacemnts, + "next_work_item": "", + "process_work_item": "MOCK: update_status: %(name)s Pass\nMOCK: release_work_item: %(name)s 197\n" % string_replacemnts, + "handle_script_error": "MOCK: update_status: %(name)s ScriptError error message\nMOCK bug comment: bug_id=142, cc=%(watchers)s\n--- Begin comment ---\nAttachment 197 did not build on %(port)s:\nBuild output: http://dummy_url\n--- End comment ---\n\n" % string_replacemnts, } return expected_stderr @@ -85,3 +85,12 @@ class EarlyWarningSytemTest(QueuesTest): "handle_script_error": SystemExit, } self.assert_queue_outputs(ews, expected_stderr=expected_stderr, expected_exceptions=expected_exceptions) + + def test_chromium_mac_ews(self): + ews = ChromiumMacEWS() + expected_stderr = self._default_expected_stderr(ews) + expected_stderr["process_work_item"] = "MOCK: update_status: cr-mac-ews Error: cr-mac-ews cannot process patches from non-committers :(\n" + expected_exceptions = { + "handle_script_error": SystemExit, + } + self.assert_queue_outputs(ews, expected_stderr=expected_stderr, expected_exceptions=expected_exceptions) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queries.py b/WebKitTools/Scripts/webkitpy/tool/commands/queries.py index c6e45aa..16ddc2c 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queries.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queries.py @@ -30,6 +30,8 @@ from optparse import make_option +import webkitpy.tool.steps as steps + from webkitpy.common.checkout.commitinfo import CommitInfo from webkitpy.common.config.committers import CommitterList from webkitpy.common.net.buildbot import BuildBot @@ -41,6 +43,21 @@ from webkitpy.common.system.deprecated_logging import log from webkitpy.layout_tests import port +class SuggestReviewers(AbstractDeclarativeCommand): + name = "suggest-reviewers" + help_text = "Suggest reviewers for a patch based on recent changes to the modified files." + + def __init__(self): + options = [ + steps.Options.git_commit, + ] + AbstractDeclarativeCommand.__init__(self, options=options) + + def execute(self, options, args, tool): + reviewers = tool.checkout().suggested_reviewers(options.git_commit) + print "\n".join([reviewer.full_name for reviewer in reviewers]) + + class BugsToCommit(AbstractDeclarativeCommand): name = "bugs-to-commit" help_text = "List bugs in the commit-queue" @@ -162,15 +179,6 @@ class WhatBroke(AbstractDeclarativeCommand): print "All builders are passing!" -class WhoBrokeIt(AbstractDeclarativeCommand): - name = "who-broke-it" - 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.failure_map(False).revisions_causing_failures().items(): - print "r%s appears to have broken %s" % (revision, [builder.name() for builder in builders]) - - class ResultsFor(AbstractDeclarativeCommand): name = "results-for" help_text = "Print a list of failures for the passed revision from bots on %s" % BuildBot.default_host @@ -197,17 +205,21 @@ class FailureReason(AbstractDeclarativeCommand): name = "failure-reason" 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): - regression_window = RegressionWindow(green_build, red_build) - revisions = regression_window.revisions() + def _blame_line_for_revision(self, revision): + try: + commit_info = self._tool.checkout().commit_info_for_revision(revision) + except Exception, e: + return "FAILED to fetch CommitInfo for r%s, exception: %s" % (revision, e) + if not commit_info: + return "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision + return commit_info.blame_string(self._tool.bugs) + + def _print_blame_information_for_transition(self, regression_window, failing_tests): + red_build = regression_window.failing_build() 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 revisions: - commit_info = self._tool.checkout().commit_info_for_revision(revision) - if commit_info: - print commit_info.blame_string(self._tool.bugs) - else: - print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision + for revision in regression_window.revisions(): + print self._blame_line_for_revision(revision) def _explain_failures_for_builder(self, builder, start_revision): print "Examining failures for \"%s\", starting at r%s" % (builder.name(), start_revision) @@ -244,7 +256,8 @@ class FailureReason(AbstractDeclarativeCommand): print "No change in build %s (r%s), %s unexplained failures (%s in this build)" % (build._number, build.revision(), len(results_to_explain), len(failures)) last_build_with_results = build continue - self._print_blame_information_for_transition(build, last_build_with_results, fixed_results) + regression_window = RegressionWindow(build, last_build_with_results) + self._print_blame_information_for_transition(regression_window, fixed_results) last_build_with_results = build results_to_explain -= fixed_results if results_to_explain: @@ -274,6 +287,75 @@ class FailureReason(AbstractDeclarativeCommand): return self._explain_failures_for_builder(builder, start_revision=int(start_revision)) +class FindFlakyTests(AbstractDeclarativeCommand): + name = "find-flaky-tests" + help_text = "Lists tests that often fail for a single build at %s" % BuildBot.default_host + + def _find_failures(self, builder, revision): + build = builder.build_for_revision(revision, allow_failed_lookups=True) + if not build: + print "No build for %s" % revision + return (None, None) + results = build.layout_test_results() + if not results: + print "No results build %s (r%s)" % (build._number, build.revision()) + return (None, None) + failures = set(results.failing_tests()) + if len(failures) >= 20: + # FIXME: We may need to move this logic into the LayoutTestResults class. + # The buildbot stops runs after 20 failures so we don't have full results to work with here. + print "Too many failures in build %s (r%s), ignoring." % (build._number, build.revision()) + return (None, None) + return (build, failures) + + def _increment_statistics(self, flaky_tests, flaky_test_statistics): + for test in flaky_tests: + count = flaky_test_statistics.get(test, 0) + flaky_test_statistics[test] = count + 1 + + def _print_statistics(self, statistics): + print "=== Results ===" + print "Occurances Test name" + for value, key in sorted([(value, key) for key, value in statistics.items()]): + print "%10d %s" % (value, key) + + def _walk_backwards_from(self, builder, start_revision, limit): + flaky_test_statistics = {} + all_previous_failures = set([]) + one_time_previous_failures = set([]) + previous_build = None + for i in range(limit): + revision = start_revision - i + print "Analyzing %s ... " % revision, + (build, failures) = self._find_failures(builder, revision) + if failures == None: + # Notice that we don't loop on the empty set! + continue + print "has %s failures" % len(failures) + flaky_tests = one_time_previous_failures - failures + if flaky_tests: + print "Flaky tests: %s %s" % (sorted(flaky_tests), + previous_build.results_url()) + self._increment_statistics(flaky_tests, flaky_test_statistics) + one_time_previous_failures = failures - all_previous_failures + all_previous_failures = failures + previous_build = build + self._print_statistics(flaky_test_statistics) + + def _builder_to_analyze(self): + statuses = self._tool.buildbot.builder_statuses() + choices = [status["name"] for status in statuses] + chosen_name = User.prompt_with_list("Which builder to analyze:", choices) + for status in statuses: + if status["name"] == chosen_name: + return (self._tool.buildbot.builder_with_name(chosen_name), status["built_revision"]) + + def execute(self, options, args, tool): + (builder, latest_revision) = self._builder_to_analyze() + limit = self._tool.user.prompt("How many revisions to look through? [10000] ") or 10000 + return self._walk_backwards_from(builder, latest_revision, limit=int(limit)) + + class TreeStatus(AbstractDeclarativeCommand): name = "tree-status" help_text = "Print the status of the %s buildbots" % BuildBot.default_host diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queries_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queries_unittest.py index 7dddfe7..05a4a5c 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queries_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queries_unittest.py @@ -26,12 +26,15 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import unittest + from webkitpy.common.net.bugzilla import Bugzilla from webkitpy.thirdparty.mock import Mock from webkitpy.tool.commands.commandtest import CommandsTest from webkitpy.tool.commands.queries import * from webkitpy.tool.mocktool import MockTool + class QueryCommandsTest(CommandsTest): def test_bugs_to_commit(self): expected_stderr = "Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)\n" @@ -71,3 +74,17 @@ class QueryCommandsTest(CommandsTest): expected_stdout = "Test 'media' is not skipped by any port.\n" self.assert_execute_outputs(SkippedPorts(), ("media",), expected_stdout) + + +class FailureReasonTest(unittest.TestCase): + def test_blame_line_for_revision(self): + tool = MockTool() + command = FailureReason() + command.bind_to_tool(tool) + # This is an artificial example, mostly to test the CommitInfo lookup failure case. + self.assertEquals(command._blame_line_for_revision(None), "FAILED to fetch CommitInfo for rNone, likely missing ChangeLog") + + def raising_mock(self): + raise Exception("MESSAGE") + tool.checkout().commit_info_for_revision = raising_mock + self.assertEquals(command._blame_line_for_revision(None), "FAILED to fetch CommitInfo for rNone, exception: MESSAGE") diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py index 80fd2ea..7b3002a 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py @@ -27,6 +27,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import with_statement + +import codecs import time import traceback import os @@ -36,17 +39,18 @@ from optparse import make_option from StringIO import StringIO from webkitpy.common.net.bugzilla import CommitterValidator +from webkitpy.common.net.layouttestresults import path_for_layout_test, LayoutTestResults 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.commitqueuetask import CommitQueueTask, CommitQueueTaskDelegate +from webkitpy.tool.bot.feeders import CommitQueueFeeder, EWSFeeder from webkitpy.tool.bot.queueengine import QueueEngine, QueueEngineDelegate from webkitpy.tool.grammar import pluralize from webkitpy.tool.multicommandtool import Command, TryAgain + class AbstractQueue(Command, QueueEngineDelegate): watchers = [ ] @@ -78,6 +82,10 @@ class AbstractQueue(Command, QueueEngineDelegate): # 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] + if self._tool.status_server.bot_id: + webkit_patch_args += ["--bot-id=%s" % self._tool.status_server.bot_id] + if self._options.port: + webkit_patch_args += ["--port=%s" % self._options.port] webkit_patch_args.extend(args) return self._tool.executive.run_and_throw_if_fail(webkit_patch_args) @@ -94,7 +102,7 @@ class AbstractQueue(Command, QueueEngineDelegate): def begin_work_queue(self): log("CAUTION: %s will discard all local changes in \"%s\"" % (self.name, self._tool.scm().checkout_root)) - if self.options.confirm: + if self._options.confirm: response = self._tool.user.prompt("Are you sure? Type \"yes\" to continue: ") if (response != "yes"): error("User declined.") @@ -106,7 +114,7 @@ class AbstractQueue(Command, QueueEngineDelegate): def should_continue_work_queue(self): self._iteration_count += 1 - return not self.options.iterations or self._iteration_count <= self.options.iterations + return not self._options.iterations or self._iteration_count <= self._options.iterations def next_work_item(self): raise NotImplementedError, "subclasses must implement" @@ -123,7 +131,7 @@ class AbstractQueue(Command, QueueEngineDelegate): # Command methods 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._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() @@ -159,6 +167,7 @@ class FeederQueue(AbstractQueue): AbstractQueue.begin_work_queue(self) self.feeders = [ CommitQueueFeeder(self._tool), + EWSFeeder(self._tool), ] def next_work_item(self): @@ -190,6 +199,9 @@ class AbstractPatchQueue(AbstractQueue): def _fetch_next_work_item(self): return self._tool.status_server.next_work_item(self.name) + def _release_work_item(self, patch): + self._tool.status_server.release_work_item(self.name, patch) + def _did_pass(self, patch): self._update_status(self._pass_status, patch) @@ -207,7 +219,7 @@ class AbstractPatchQueue(AbstractQueue): return os.path.join(self._log_directory(), "%s.log" % patch.bug_id()) -class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): +class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler, CommitQueueTaskDelegate): name = "commit-queue" # AbstractPatchQueue methods @@ -229,7 +241,7 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): def process_work_item(self, patch): self._cc_watchers(patch.bug_id()) - task = CommitQueueTask(self._tool, self, patch) + task = CommitQueueTask(self, patch) try: if task.run(): self._did_pass(patch) @@ -239,10 +251,22 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): 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) + self._release_work_item(patch) + + def _error_message_for_bug(self, status_id, script_error): + if not script_error.output: + return script_error.message_with_output() + results_link = self._tool.status_server.results_url_for_status(status_id) + return "%s\nFull output: %s" % (script_error.message_with_output(), results_link) def handle_unexpected_error(self, patch, message): self.committer_validator.reject_patch_from_commit_queue(patch.id(), message) + # CommitQueueTaskDelegate methods + + def run_command(self, command): + self.run_webkit_patch(command) + def command_passed(self, message, patch): self._update_status(message, patch=patch) @@ -250,11 +274,36 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): 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 = self._tool.status_server.results_url_for_status(status_id) - return "%s\nFull output: %s" % (script_error.message_with_output(), results_link) + # FIXME: This exists for mocking, but should instead be mocked via + # some sort of tool.filesystem() object. + def _read_file_contents(self, path): + try: + with codecs.open(path, "r", "utf-8") as open_file: + return open_file.read() + except OSError, e: # File does not exist or can't be read. + return None + + # FIXME: This may belong on the Port object. + def layout_test_results(self): + results_path = self._tool.port().layout_tests_results_path() + results_html = self._read_file_contents(results_path) + if not results_html: + return None + return LayoutTestResults.results_from_string(results_html) + + def refetch_patch(self, patch): + return self._tool.bugs.fetch_attachment(patch.id()) + + def _author_emails_for_tests(self, flaky_tests): + test_paths = map(path_for_layout_test, flaky_tests) + commit_infos = self._tool.checkout().recent_commit_infos_for_files(test_paths) + return [commit_info.author().bugzilla_email() for commit_info in commit_infos if commit_info.author()] + + def report_flaky_tests(self, patch, flaky_tests): + authors = self._author_emails_for_tests(flaky_tests) + cc_explaination = " The author(s) of the test(s) have been CCed on this bug." if authors else "" + message = "The %s encountered the following flaky tests while processing attachment %s:\n\n%s\n\nPlease file bugs against the tests.%s The commit-queue is continuing to process your patch." % (self.name, patch.id(), "\n".join(flaky_tests), cc_explaination) + self._tool.bugs.post_comment_to_bug(patch.bug_id(), message, cc=authors) # StepSequenceErrorHandler methods @@ -278,6 +327,7 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler): raise TryAgain() +# FIXME: All the Rietveld code is no longer used and should be deleted. class RietveldUploadQueue(AbstractPatchQueue, StepSequenceErrorHandler): name = "rietveld-upload-queue" @@ -323,40 +373,27 @@ class RietveldUploadQueue(AbstractPatchQueue, StepSequenceErrorHandler): cls._reject_patch(tool, state["patch"].id()) -class AbstractReviewQueue(AbstractPatchQueue, PersistentPatchCollectionDelegate, StepSequenceErrorHandler): +class AbstractReviewQueue(AbstractPatchQueue, StepSequenceErrorHandler): + """This is the base-class for the EWS queues and the style-queue.""" def __init__(self, options=None): AbstractPatchQueue.__init__(self, options) def review_patch(self, patch): - raise NotImplementedError, "subclasses must implement" - - # PersistentPatchCollectionDelegate methods - - def collection_name(self): - return self.name - - def fetch_potential_patch_ids(self): - return self._tool.bugs.queries.fetch_attachment_ids_from_review_queue() - - def status_server(self): - return self._tool.status_server - - def is_terminal_status(self, status): - return status == "Pass" or status == "Fail" or status.startswith("Error:") + raise NotImplementedError("subclasses must implement") # AbstractPatchQueue methods def begin_work_queue(self): AbstractPatchQueue.begin_work_queue(self) - self._patches = PersistentPatchCollection(self) def next_work_item(self): - patch_id = self._patches.next() - if patch_id: - return self._tool.bugs.fetch_attachment(patch_id) + patch_id = self._fetch_next_work_item() + if not patch_id: + return None + return self._tool.bugs.fetch_attachment(patch_id) def should_proceed_with_work_item(self, patch): - raise NotImplementedError, "subclasses must implement" + raise NotImplementedError("subclasses must implement") def process_work_item(self, patch): try: @@ -368,6 +405,8 @@ class AbstractReviewQueue(AbstractPatchQueue, PersistentPatchCollectionDelegate, if e.exit_code != QueueEngine.handled_error_code: self._did_fail(patch) raise e + finally: + self._release_work_item(patch) def handle_unexpected_error(self, patch, message): log(message) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py index 029814e..b37b5dc 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py @@ -60,24 +60,31 @@ class AbstractQueueTest(CommandsTest): def test_log_directory(self): self.assertEquals(TestQueue()._log_directory(), "test-queue-logs") - def _assert_run_webkit_patch(self, run_args): + def _assert_run_webkit_patch(self, run_args, port=None): queue = TestQueue() tool = MockTool() + tool.status_server.bot_id = "gort" tool.executive = Mock() queue.bind_to_tool(tool) + queue._options = Mock() + queue._options.port = port queue.run_webkit_patch(run_args) - expected_run_args = ["echo", "--status-host=example.com"] + run_args + expected_run_args = ["echo", "--status-host=example.com", "--bot-id=gort"] + if port: + expected_run_args.append("--port=%s" % port) + expected_run_args.extend(run_args) tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args) def test_run_webkit_patch(self): self._assert_run_webkit_patch([1]) self._assert_run_webkit_patch(["one", 2]) + self._assert_run_webkit_patch([1], port="mockport") def test_iteration_count(self): queue = TestQueue() - queue.options = Mock() - queue.options.iterations = 3 + queue._options = Mock() + queue._options.iterations = 3 self.assertTrue(queue.should_continue_work_queue()) self.assertTrue(queue.should_continue_work_queue()) self.assertTrue(queue.should_continue_work_queue()) @@ -85,7 +92,7 @@ class AbstractQueueTest(CommandsTest): def test_no_iteration_count(self): queue = TestQueue() - queue.options = Mock() + queue._options = Mock() self.assertTrue(queue.should_continue_work_queue()) self.assertTrue(queue.should_continue_work_queue()) self.assertTrue(queue.should_continue_work_queue()) @@ -128,6 +135,8 @@ MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Reject - 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] +Feeding EWS (1 r? patch, 1 new) +MOCK: submit_to_ews: 103 """, "handle_unexpected_error": "Mock error message\n", } @@ -139,25 +148,13 @@ class AbstractPatchQueueTest(CommandsTest): queue = AbstractPatchQueue() tool = MockTool() queue.bind_to_tool(tool) + queue._options = Mock() + queue._options.port = None self.assertEquals(queue._fetch_next_work_item(), None) tool.status_server = MockStatusServer(work_items=[2, 1, 3]) self.assertEquals(queue._fetch_next_work_item(), 2) -class AbstractReviewQueueTest(CommandsTest): - def test_patch_collection_delegate_methods(self): - queue = TestReviewQueue() - tool = MockTool() - queue.bind_to_tool(tool) - self.assertEquals(queue.collection_name(), "test-review-queue") - self.assertEquals(queue.fetch_potential_patch_ids(), [103]) - queue.status_server() - self.assertTrue(queue.is_terminal_status("Pass")) - self.assertTrue(queue.is_terminal_status("Fail")) - self.assertTrue(queue.is_terminal_status("Error: Your patch exploded")) - self.assertFalse(queue.is_terminal_status("Foo")) - - class NeedsUpdateSequence(StepSequence): def _run(self, tool, options, state): raise CheckoutNeedsUpdate([], 1, "", None) @@ -172,7 +169,20 @@ class AlwaysCommitQueueTool(object): class SecondThoughtsCommitQueue(CommitQueue): - def _build_and_test_patch(self, patch, first_run=True): + def __init__(self): + self._reject_patch = False + CommitQueue.__init__(self) + + def run_command(self, command): + # We want to reject the patch after the first validation, + # so wait to reject it until after some other command has run. + self._reject_patch = True + return CommitQueue.run_command(self, command) + + def refetch_patch(self, patch): + if not self._reject_patch: + return self._tool.bugs.fetch_attachment(patch.id()) + attachment_dictionary = { "id": patch.id(), "bug_id": patch.bug_id(), @@ -185,9 +195,7 @@ class SecondThoughtsCommitQueue(CommitQueue): "committer_email": "foo@bar.com", "attacher_email": "Contributer1", } - patch = Attachment(attachment_dictionary, None) - self._tool.bugs.set_override_patch(patch) - return True + return Attachment(attachment_dictionary, None) class CommitQueueTest(QueuesTest): @@ -215,6 +223,7 @@ MOCK: update_status: commit-queue Pass "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 +MOCK: release_work_item: commit-queue 197 """, "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", @@ -236,7 +245,7 @@ MOCK: update_status: commit-queue Fail "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 run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build', '--no-clean', '--no-update', '--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 @@ -259,7 +268,7 @@ MOCK: update_status: commit-queue Pass "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 run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build', '--no-clean', '--no-update', '--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 @@ -290,14 +299,39 @@ MOCK: update_status: commit-queue Pass def test_manual_reject_during_processing(self): queue = SecondThoughtsCommitQueue() queue.bind_to_tool(MockTool()) + queue._options = Mock() + queue._options.port = None 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 +MOCK: update_status: commit-queue Retry +MOCK: release_work_item: commit-queue 197 """ OutputCapture().assert_outputs(self, queue.process_work_item, [MockPatch()], expected_stderr=expected_stderr) + def test_report_flaky_tests(self): + queue = CommitQueue() + queue.bind_to_tool(MockTool()) + expected_stderr = """MOCK bug comment: bug_id=142, cc=['abarth@webkit.org'] +--- Begin comment --- +The commit-queue encountered the following flaky tests while processing attachment 197: + +foo/bar.html +bar/baz.html + +Please file bugs against the tests. The author(s) of the test(s) have been CCed on this bug. The commit-queue is continuing to process your patch. +--- End comment --- + +""" + OutputCapture().assert_outputs(self, queue.report_flaky_tests, [MockPatch(), ["foo/bar.html", "bar/baz.html"]], expected_stderr=expected_stderr) + + def test_layout_test_results(self): + queue = CommitQueue() + queue.bind_to_tool(MockTool()) + queue._read_file_contents = lambda path: None + self.assertEquals(queue.layout_test_results(), None) + queue._read_file_contents = lambda path: "" + self.assertEquals(queue.layout_test_results(), None) class RietveldUploadQueueTest(QueuesTest): def test_rietveld_upload_queue(self): @@ -315,11 +349,11 @@ class StyleQueueTest(QueuesTest): def test_style_queue(self): expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr("style-queue", MockSCM.fake_checkout_root), - "next_work_item": "MOCK: update_work_items: style-queue [103]\n", + "next_work_item": "", "should_proceed_with_work_item": "MOCK: update_status: style-queue Checking style\n", - "process_work_item": "MOCK: update_status: style-queue Pass\n", + "process_work_item": "MOCK: update_status: style-queue Pass\nMOCK: release_work_item: style-queue 197\n", "handle_unexpected_error": "Mock error message\n", - "handle_script_error": "MOCK: update_status: style-queue ScriptError error message\nMOCK bug comment: bug_id=142, cc=[]\n--- Begin comment ---\\Attachment 197 did not pass style-queue:\n\nScriptError error message\n\nIf any of these errors are false positives, please file a bug against check-webkit-style.\n--- End comment ---\n\n", + "handle_script_error": "MOCK: update_status: style-queue ScriptError error message\nMOCK bug comment: bug_id=142, cc=[]\n--- Begin comment ---\nAttachment 197 did not pass style-queue:\n\nScriptError error message\n\nIf any of these errors are false positives, please file a bug against check-webkit-style.\n--- End comment ---\n\n", } expected_exceptions = { "handle_script_error": SystemExit, diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py index 9f3583d..379d380 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queuestest.py @@ -80,13 +80,18 @@ class QueuesTest(unittest.TestCase): string_replacements = {"name": name, 'checkout_dir': checkout_dir} return "CAUTION: %(name)s will discard all local changes in \"%(checkout_dir)s\"\nRunning WebKit %(name)s.\nMOCK: update_status: %(name)s Starting Queue\n" % string_replacements - def assert_queue_outputs(self, queue, args=None, work_item=None, expected_stdout=None, expected_stderr=None, expected_exceptions=None, options=Mock(), tool=MockTool()): + def assert_queue_outputs(self, queue, args=None, work_item=None, expected_stdout=None, expected_stderr=None, expected_exceptions=None, options=None, tool=None): + if not tool: + tool = MockTool() if not expected_stdout: expected_stdout = {} if not expected_stderr: expected_stderr = {} if not args: args = [] + if not options: + options = Mock() + options.port = None if not work_item: work_item = self.mock_work_item tool.user.prompt = lambda message: "yes" diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py index 23d013d..145f485 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py @@ -54,77 +54,47 @@ class SheriffBot(AbstractQueue, StepSequenceErrorHandler): 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]) - - def _new_failures(self, revisions_causing_failures, old_failing_svn_revisions): - # We ignore failures that might have been caused by svn_revisions that - # we've already complained about. This is conservative in the sense - # that we might be ignoring some new failures, but our experience has - # been that skipping this check causes a lot of spam for builders that - # take a long time to cycle. - old_failing_builder_names = [] - for svn_revision in old_failing_svn_revisions: - old_failing_builder_names.extend( - [builder.name() for builder in revisions_causing_failures[svn_revision]]) - - new_failures = {} - for svn_revision, builders in revisions_causing_failures.items(): - if svn_revision in old_failing_svn_revisions: - # FIXME: We should re-process the work item after some time delay. - # https://bugs.webkit.org/show_bug.cgi?id=36581 - continue - new_builders = [builder for builder in builders - if builder.name() not in old_failing_builder_names] - if new_builders: - new_failures[svn_revision] = new_builders - - return new_failures + def work_item_log_path(self, failure_map): + return None + + def _is_old_failure(self, revision): + return self._tool.status_server.svn_revision(revision) def next_work_item(self): self._irc_bot.process_pending_messages() self._update() - # We do one read from buildbot to ensure a consistent view. - revisions_causing_failures = self._tool.buildbot.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): - old_failing_svn_revisions.append(svn_revision) + # FIXME: We need to figure out how to provoke_flaky_builders. - new_failures = self._new_failures(revisions_causing_failures, - old_failing_svn_revisions) + failure_map = self._tool.buildbot.failure_map() + failure_map.filter_out_old_failures(self._is_old_failure) + if failure_map.is_empty(): + return None + return failure_map - self._sheriff.provoke_flaky_builders(revisions_causing_failures) - return new_failures - - def should_proceed_with_work_item(self, new_failures): + def should_proceed_with_work_item(self, failure_map): # Currently, we don't have any reasons not to proceed with work items. return True - def process_work_item(self, new_failures): - blame_list = new_failures.keys() - for svn_revision, builders in new_failures.items(): + def process_work_item(self, failure_map): + failing_revisions = failure_map.failing_revisions() + for revision in failing_revisions: + builders = failure_map.builders_failing_for(revision) + tests = failure_map.tests_failing_for(revision) try: - commit_info = self._tool.checkout().commit_info_for_revision(svn_revision) + commit_info = self._tool.checkout().commit_info_for_revision(revision) if not commit_info: print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision continue self._sheriff.post_irc_warning(commit_info, builders) - self._sheriff.post_blame_comment_on_bug(commit_info, - builders, - blame_list) - self._sheriff.post_automatic_rollout_patch(commit_info, - builders) + self._sheriff.post_blame_comment_on_bug(commit_info, builders, tests) + finally: for builder in builders: - self._tool.status_server.update_svn_revision(svn_revision, - builder.name()) + self._tool.status_server.update_svn_revision(revision, builder.name()) return True - def handle_unexpected_error(self, new_failures, message): + def handle_unexpected_error(self, failure_map, message): log(message) # StepSequenceErrorHandler methods diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py index a63ec24..32eb016 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot_unittest.py @@ -30,7 +30,7 @@ import os from webkitpy.tool.commands.queuestest import QueuesTest from webkitpy.tool.commands.sheriffbot import SheriffBot -from webkitpy.tool.mocktool import MockBuilder +from webkitpy.tool.mocktool import * class SheriffBotTest(QueuesTest): @@ -38,36 +38,19 @@ class SheriffBotTest(QueuesTest): builder2 = MockBuilder("Builder2") def test_sheriff_bot(self): - mock_work_item = { - 29837: [self.builder1], - } + mock_work_item = MockFailureMap(MockTool().buildbot) expected_stderr = { "begin_work_queue": self._default_begin_work_queue_stderr("sheriff-bot", os.getcwd()), "next_work_item": "", - "process_work_item": "MOCK: irc.post: abarth, darin, eseidel: http://trac.webkit.org/changeset/29837 might have broken Builder1\nMOCK bug comment: bug_id=42, cc=['abarth@webkit.org', 'eric@webkit.org']\n--- Begin comment ---\\http://trac.webkit.org/changeset/29837 might have broken Builder1\n--- End comment ---\n\n", + "process_work_item": """MOCK: irc.post: abarth, darin, eseidel: http://trac.webkit.org/changeset/29837 might have broken Builder1 +MOCK bug comment: bug_id=42, cc=['abarth@webkit.org', 'eric@webkit.org'] +--- Begin comment --- +http://trac.webkit.org/changeset/29837 might have broken Builder1 +The following tests are not passing: +mock-test-1 +--- End comment --- + +""", "handle_unexpected_error": "Mock error message\n" } self.assert_queue_outputs(SheriffBot(), work_item=mock_work_item, expected_stderr=expected_stderr) - - revisions_causing_failures = { - 1234: [builder1], - 1235: [builder1, builder2], - } - - def test_new_failures(self): - old_failing_svn_revisions = [] - self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures, - old_failing_svn_revisions), - self.revisions_causing_failures) - - def test_new_failures_with_old_revisions(self): - old_failing_svn_revisions = [1234] - self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures, - old_failing_svn_revisions), - {1235: [builder2]}) - - def test_new_failures_with_old_revisions(self): - old_failing_svn_revisions = [1235] - self.assertEquals(SheriffBot()._new_failures(self.revisions_causing_failures, - old_failing_svn_revisions), - {}) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py index 5f3f400..0d096b6 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py @@ -52,11 +52,12 @@ class UploadCommandsTest(CommandsTest): def test_post(self): options = MockOptions() + options.cc = None + options.check_style = True + options.comment = None options.description = "MOCK description" options.request_commit = False options.review = True - options.comment = None - options.cc = None expected_stderr = """Running check-webkit-style MOCK: user.open_url: file://... Obsoleting 2 old patches on bug 42 @@ -81,11 +82,12 @@ MOCK: user.open_url: http://example.com/42 def test_upload(self): options = MockOptions() + options.cc = None + options.check_style = True + options.comment = None options.description = "MOCK description" options.request_commit = False options.review = True - options.comment = None - options.cc = None expected_stderr = """Running check-webkit-style MOCK: user.open_url: file://... Obsoleting 2 old patches on bug 42 @@ -103,7 +105,7 @@ MOCK: user.open_url: http://example.com/42 options = Mock() options.bug_id = 42 options.comment = "MOCK comment" - expected_stderr = "Bug: <http://example.com/42> Bug with two r+'d and cq+'d patches, one of which has an invalid commit-queue setter.\nRevision: 9876\nMOCK: user.open_url: http://example.com/42\nAdding comment to Bug 42.\nMOCK bug comment: bug_id=42, cc=None\n--- Begin comment ---\\MOCK comment\n\nCommitted r9876: <http://trac.webkit.org/changeset/9876>\n--- End comment ---\n\n" + expected_stderr = "Bug: <http://example.com/42> Bug with two r+'d and cq+'d patches, one of which has an invalid commit-queue setter.\nRevision: 9876\nMOCK: user.open_url: http://example.com/42\nAdding comment to Bug 42.\nMOCK bug comment: bug_id=42, cc=None\n--- Begin comment ---\nMOCK comment\n\nCommitted r9876: <http://trac.webkit.org/changeset/9876>\n--- End comment ---\n\n" self.assert_execute_outputs(MarkBugFixed(), [], expected_stderr=expected_stderr, tool=tool, options=options) def test_edit_changelog(self): diff --git a/WebKitTools/Scripts/webkitpy/tool/main.py b/WebKitTools/Scripts/webkitpy/tool/main.py index 9531b63..ce6666e 100755 --- a/WebKitTools/Scripts/webkitpy/tool/main.py +++ b/WebKitTools/Scripts/webkitpy/tool/main.py @@ -34,6 +34,7 @@ import threading from webkitpy.common.checkout.api import Checkout from webkitpy.common.checkout.scm import default_scm +from webkitpy.common.config.ports import WebKitPort from webkitpy.common.net.bugzilla import Bugzilla from webkitpy.common.net.buildbot import BuildBot from webkitpy.common.net.rietveld import Rietveld @@ -52,15 +53,16 @@ from webkitpy.tool.commands.queues import * from webkitpy.tool.commands.sheriffbot import * from webkitpy.tool.commands.upload import * from webkitpy.tool.multicommandtool import MultiCommandTool -from webkitpy.common.system.deprecated_logging import log class WebKitPatch(MultiCommandTool): global_options = [ make_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="enable all logging"), make_option("--dry-run", action="store_true", dest="dry_run", default=False, help="do not touch remote servers"), - make_option("--status-host", action="store", dest="status_host", type="string", nargs=1, help="Hostname (e.g. localhost or commit.webkit.org) where status updates should be posted."), - make_option("--irc-password", action="store", dest="irc_password", type="string", nargs=1, help="Password to use when communicating via IRC."), + make_option("--status-host", action="store", dest="status_host", type="string", help="Hostname (e.g. localhost or commit.webkit.org) where status updates should be posted."), + make_option("--bot-id", action="store", dest="bot_id", type="string", help="Identifier for this bot (if multiple bots are running for a queue)"), + make_option("--irc-password", action="store", dest="irc_password", type="string", help="Password to use when communicating via IRC."), + make_option("--port", action="store", dest="port", default=None, help="Specify a port (e.g., mac, qt, gtk, ...)."), ] def __init__(self, path): @@ -72,6 +74,7 @@ class WebKitPatch(MultiCommandTool): self.buildbot = BuildBot() self.executive = Executive() self._irc = None + self._port = None self.user = User() self._scm = None self._checkout = None @@ -90,6 +93,9 @@ class WebKitPatch(MultiCommandTool): self._checkout = Checkout(self.scm()) return self._checkout + def port(self): + return self._port + def ensure_irc_connected(self, irc_delegate): if not self._irc: self._irc = IRCProxy(irc_delegate) @@ -123,8 +129,12 @@ class WebKitPatch(MultiCommandTool): self.codereview.dryrun = True if options.status_host: self.status_server.set_host(options.status_host) + if options.bot_id: + self.status_server.set_bot_id(options.bot_id) if options.irc_password: self.irc_password = options.irc_password + # If options.port is None, we'll get the default port for this platform. + self._port = WebKitPort.port(options.port) def should_execute_command(self, command): if command.requires_local_commits and not self.scm().supports_local_commits(): diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool.py b/WebKitTools/Scripts/webkitpy/tool/mocktool.py index 277bd08..05b30dd 100644 --- a/WebKitTools/Scripts/webkitpy/tool/mocktool.py +++ b/WebKitTools/Scripts/webkitpy/tool/mocktool.py @@ -317,7 +317,7 @@ class MockBugzilla(Mock): flag_name, flag_value, attachment_id, comment_text, additional_comment_text)) def post_comment_to_bug(self, bug_id, comment_text, cc=None): - log("MOCK bug comment: bug_id=%s, cc=%s\n--- Begin comment ---\%s\n--- End comment ---\n" % ( + log("MOCK bug comment: bug_id=%s, cc=%s\n--- Begin comment ---\n%s\n--- End comment ---\n" % ( bug_id, cc, comment_text)) def add_patch_to_bug(self, @@ -350,14 +350,24 @@ class MockBuilder(object): self._name, username, comments)) -class MockFailureMap(): +class MockFailureMap(object): def __init__(self, buildbot): self._buildbot = buildbot - def revisions_causing_failures(self): - return { - "29837": [self._buildbot.builder_with_name("Builder1")], - } + def is_empty(self): + return False + + def filter_out_old_failures(self, is_old_revision): + pass + + def failing_revisions(self): + return [29837] + + def builders_failing_for(self, revision): + return [self._buildbot.builder_with_name("Builder1")] + + def tests_failing_for(self, revision): + return ["mock-test-1"] class MockBuildBot(object): @@ -419,7 +429,7 @@ class MockSCM(Mock): # will actually be the root. Since getcwd() is wrong, use a globally fake root for now. self.checkout_root = self.fake_checkout_root - def create_patch(self, git_commit): + def create_patch(self, git_commit, changed_files=None): return "Patch1" def commit_ids_from_commitish_arguments(self, args): @@ -447,6 +457,9 @@ class MockCheckout(object): _committer_list = CommitterList() def commit_info_for_revision(self, svn_revision): + # The real Checkout would probably throw an exception, but this is the only way tests have to get None back at the moment. + if not svn_revision: + return None return CommitInfo(svn_revision, "eric@webkit.org", { "bug_id": 42, "author_name": "Adam Barth", @@ -459,7 +472,10 @@ class MockCheckout(object): def bug_id_for_revision(self, svn_revision): return 12345 - def modified_changelogs(self, git_commit): + def recent_commit_infos_for_files(self, paths): + return [self.commit_info_for_revision(32)] + + def modified_changelogs(self, git_commit, changed_files=None): # Ideally we'd return something more interesting here. The problem is # that LandDiff will try to actually read the patch from disk! return [] @@ -515,8 +531,9 @@ class MockIRC(object): class MockStatusServer(object): - def __init__(self, work_items=None): + def __init__(self, bot_id=None, work_items=None): self.host = "example.com" + self.bot_id = bot_id self._work_items = work_items or [] def patch_status(self, queue_name, patch_id): @@ -530,10 +547,16 @@ class MockStatusServer(object): return None return self._work_items[0] + def release_work_item(self, queue_name, patch): + log("MOCK: release_work_item: %s %s" % (queue_name, patch.id())) + def update_work_items(self, queue_name, work_items): self._work_items = work_items log("MOCK: update_work_items: %s %s" % (queue_name, work_items)) + def submit_to_ews(self, patch_id): + log("MOCK: submit_to_ews: %s" % (patch_id)) + def update_status(self, queue_name, status, patch=None, results_file=None): log("MOCK: update_status: %s %s" % (queue_name, status)) return 187 @@ -567,9 +590,17 @@ class MockExecute(Mock): return "MOCK output of child process" -class MockOptions(Mock): - no_squash = False - squash = False +class MockOptions(object): + """Mock implementation of optparse.Values.""" + + def __init__(self, **kwargs): + # The caller can set option values using keyword arguments. We don't + # set any values by default because we don't know how this + # object will be used. Generally speaking unit tests should + # subclass this or provider wrapper functions that set a common + # set of options. + for key, value in kwargs.items(): + self.__dict__[key] = value class MockRietveld(): @@ -630,3 +661,22 @@ class MockTool(): def path(self): return "echo" + + def port(self): + return Mock() + + +class MockBrowser(object): + params = {} + + def open(self, url): + pass + + def select_form(self, name): + pass + + def __setitem__(self, key, value): + self.params[key] = value + + def submit(self): + return Mock(file) diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool_unittest.py b/WebKitTools/Scripts/webkitpy/tool/mocktool_unittest.py new file mode 100644 index 0000000..cceaa2e --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/tool/mocktool_unittest.py @@ -0,0 +1,59 @@ +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from mocktool import MockOptions + + +class MockOptionsTest(unittest.TestCase): + # MockOptions() should implement the same semantics that + # optparse.Values does. + + def test_get__set(self): + # Test that we can still set options after we construct the + # object. + options = MockOptions() + options.foo = 'bar' + self.assertEqual(options.foo, 'bar') + + def test_get__unset(self): + # Test that unset options raise an exception (regular Mock + # objects return an object and hence are different from + # optparse.Values()). + options = MockOptions() + self.assertRaises(AttributeError, lambda: options.foo) + + def test_kwarg__set(self): + # Test that keyword arguments work in the constructor. + options = MockOptions(foo='bar') + self.assertEqual(options.foo, 'bar') + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py b/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py index 9ceb2cb..5525ea0 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py @@ -36,27 +36,23 @@ class AbstractStep(object): def __init__(self, tool, options): self._tool = tool self._options = options - self._port = None + # FIXME: This should use tool.port() def _run_script(self, script_name, args=None, quiet=False, port=WebKitPort): log("Running %s" % script_name) command = [port.script_path(script_name)] if args: command.extend(args) - # FIXME: This should use self.port() self._tool.executive.run_and_throw_if_fail(command, quiet) - # FIXME: The port should live on the tool. - def port(self): - if self._port: - return self._port - self._port = WebKitPort.port(self._options.port) - return self._port + def _changed_files(self, state): + return self.cached_lookup(state, "changed_files") _well_known_keys = { - "diff": lambda self, state: self._tool.scm().create_patch(self._options.git_commit), - "changelogs": lambda self, state: self._tool.checkout().modified_changelogs(self._options.git_commit), "bug_title": lambda self, state: self._tool.bugs.fetch_bug(state["bug_id"]).title(), + "changed_files": lambda self, state: self._tool.scm().changed_files(self._options.git_commit), + "diff": lambda self, state: self._tool.scm().create_patch(self._options.git_commit, changed_files=self._changed_files(state)), + "changelogs": lambda self, state: self._tool.checkout().modified_changelogs(self._options.git_commit, changed_files=self._changed_files(state)), } def cached_lookup(self, state, key, promise=None): @@ -67,6 +63,11 @@ class AbstractStep(object): state[key] = promise(self, state) return state[key] + def did_modify_checkout(self, state): + state["diff"] = None + state["changelogs"] = None + state["changed_files"] = None + @classmethod def options(cls): return [ diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/build.py b/WebKitTools/Scripts/webkitpy/tool/steps/build.py index 456db25..0990b8b 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/build.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/build.py @@ -41,7 +41,7 @@ class Build(AbstractStep): ] def build(self, build_style): - self._tool.executive.run_and_throw_if_fail(self.port().build_webkit_command(build_style=build_style), self._options.quiet) + self._tool.executive.run_and_throw_if_fail(self._tool.port().build_webkit_command(build_style=build_style), self._options.quiet) def run(self, state): if not self._options.build: diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/editchangelog.py b/WebKitTools/Scripts/webkitpy/tool/steps/editchangelog.py index de9b4e4..4d9646f 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/editchangelog.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/editchangelog.py @@ -35,3 +35,4 @@ class EditChangeLog(AbstractStep): def run(self, state): os.chdir(self._tool.scm().checkout_root) self._tool.user.edit_changelog(self.cached_lookup(state, "changelogs")) + self.did_modify_checkout(state) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/options.py b/WebKitTools/Scripts/webkitpy/tool/steps/options.py index 3dc1963..835fdba 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/options.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/options.py @@ -50,7 +50,6 @@ class Options(object): obsolete_patches = make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting this one.") open_bug = make_option("--open-bug", action="store_true", dest="open_bug", default=False, help="Opens the associated bug in a browser.") parent_command = make_option("--parent-command", action="store", dest="parent_command", default=None, help="(Internal) The command that spawned this instance.") - port = make_option("--port", action="store", dest="port", default=None, help="Specify a port (e.g., mac, qt, gtk, ...).") quiet = make_option("--quiet", action="store_true", dest="quiet", default=False, help="Produce less console output.") request_commit = make_option("--request-commit", action="store_true", dest="request_commit", default=False, help="Mark the patch as needing auto-commit after review.") review = make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review.") diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py index ce04024..099dfe3 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py @@ -39,7 +39,6 @@ class PrepareChangeLog(AbstractStep): @classmethod def options(cls): return AbstractStep.options() + [ - Options.port, Options.quiet, Options.email, Options.git_commit, @@ -62,7 +61,7 @@ class PrepareChangeLog(AbstractStep): self._ensure_bug_url(state) return os.chdir(self._tool.scm().checkout_root) - args = [self.port().script_path("prepare-ChangeLog")] + args = [self._tool.port().script_path("prepare-ChangeLog")] if state.get("bug_id"): args.append("--bug=%s" % state["bug_id"]) if self._options.email: @@ -75,4 +74,4 @@ class PrepareChangeLog(AbstractStep): self._tool.executive.run_and_throw_if_fail(args, self._options.quiet) except ScriptError, e: error("Unable to prepare ChangeLogs.") - state["diff"] = None # We've changed the diff + self.did_modify_checkout(state) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py index aff1fd9..dcbfc44 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py @@ -37,7 +37,6 @@ class RunTests(AbstractStep): Options.test, Options.non_interactive, Options.quiet, - Options.port, ] def run(self, state): @@ -46,14 +45,17 @@ class RunTests(AbstractStep): # Run the scripting unit tests first because they're quickest. log("Running Python unit tests") - self._tool.executive.run_and_throw_if_fail(self.port().run_python_unittests_command()) + self._tool.executive.run_and_throw_if_fail(self._tool.port().run_python_unittests_command()) log("Running Perl unit tests") - self._tool.executive.run_and_throw_if_fail(self.port().run_perl_unittests_command()) - log("Running JavaScriptCore tests") - self._tool.executive.run_and_throw_if_fail(self.port().run_javascriptcore_tests_command(), quiet=True) + self._tool.executive.run_and_throw_if_fail(self._tool.port().run_perl_unittests_command()) + + javascriptcore_tests_command = self._tool.port().run_javascriptcore_tests_command() + if javascriptcore_tests_command: + log("Running JavaScriptCore tests") + self._tool.executive.run_and_throw_if_fail(javascriptcore_tests_command, quiet=True) log("Running run-webkit-tests") - args = self.port().run_webkit_tests_command() + args = self._tool.port().run_webkit_tests_command() if self._options.non_interactive: args.append("--no-launch-safari") args.append("--exit-after-n-failures=1") @@ -61,7 +63,7 @@ class RunTests(AbstractStep): # FIXME: Hack to work around https://bugs.webkit.org/show_bug.cgi?id=38912 # when running the commit-queue on a mac leopard machine since compositing # does not work reliably on Leopard due to various graphics driver/system bugs. - if self.port().name() == "Mac" and self.port().is_leopard(): + if self._tool.port().name() == "Mac" and self._tool.port().is_leopard(): tests_to_ignore = [] tests_to_ignore.append("compositing") diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py index 15f275a..7eb8e3a 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py @@ -37,39 +37,49 @@ from webkitpy.tool.steps.promptforbugortitle import PromptForBugOrTitle class StepsTest(unittest.TestCase): + def _step_options(self): + options = MockOptions() + options.non_interactive = True + options.port = 'MOCK port' + options.quiet = True + options.test = True + return options + def _run_step(self, step, tool=None, options=None, state=None): if not tool: tool = MockTool() if not options: - options = MockOptions() + options = self._step_options() if not state: state = {} step(tool, options).run(state) def test_update_step(self): - options = MockOptions() + tool = MockTool() + options = self._step_options() options.update = True expected_stderr = "Updating working directory\n" - OutputCapture().assert_outputs(self, self._run_step, [Update, options], expected_stderr=expected_stderr) + OutputCapture().assert_outputs(self, self._run_step, [Update, tool, options], expected_stderr=expected_stderr) def test_prompt_for_bug_or_title_step(self): tool = MockTool() tool.user.prompt = lambda message: 42 self._run_step(PromptForBugOrTitle, tool=tool) - def test_runtests_leopard_commit_queue_hack(self): + def test_runtests_leopard_commit_queue_hack_step(self): expected_stderr = "Running Python unit tests\nRunning Perl unit tests\nRunning JavaScriptCore tests\nRunning run-webkit-tests\n" OutputCapture().assert_outputs(self, self._run_step, [RunTests], expected_stderr=expected_stderr) - def test_runtests_leopard_commit_queue_hack(self): - mock_options = MockOptions() - mock_options.non_interactive = True + def test_runtests_leopard_commit_queue_hack_command(self): + mock_options = self._step_options() step = RunTests(MockTool(log_executive=True), mock_options) # FIXME: We shouldn't use a real port-object here, but there is too much to mock at the moment. mock_port = WebKitPort() mock_port.name = lambda: "Mac" mock_port.is_leopard = lambda: True - step.port = lambda: mock_port + tool = MockTool(log_executive=True) + tool.port = lambda: mock_port + step = RunTests(tool, mock_options) expected_stderr = """Running Python unit tests MOCK run_and_throw_if_fail: ['WebKitTools/Scripts/test-webkitpy'] Running Perl unit tests diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/update.py b/WebKitTools/Scripts/webkitpy/tool/steps/update.py index 0f450f3..cd1d4d8 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/update.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/update.py @@ -36,11 +36,10 @@ class Update(AbstractStep): def options(cls): return AbstractStep.options() + [ Options.update, - Options.port, ] def run(self, state): if not self._options.update: return log("Updating working directory") - self._tool.executive.run_and_throw_if_fail(self.port().update_webkit_command(), quiet=True) + self._tool.executive.run_and_throw_if_fail(self._tool.port().update_webkit_command(), quiet=True) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreview_unittest.py b/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreview_unittest.py index a037422..b475378 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreview_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreview_unittest.py @@ -41,5 +41,8 @@ class UpdateChangeLogsWithReviewerTest(unittest.TestCase): def test_empty_state(self): capture = OutputCapture() - step = UpdateChangeLogsWithReviewer(MockTool(), MockOptions()) + options = MockOptions() + options.reviewer = 'MOCK reviewer' + options.git_commit = 'MOCK git commit' + step = UpdateChangeLogsWithReviewer(MockTool(), options) capture.assert_outputs(self, step.run, [{}]) diff --git a/WebKitTools/TestResultServer/handlers/dashboardhandler.py b/WebKitTools/TestResultServer/handlers/dashboardhandler.py index 587d737..c8b5ace 100644 --- a/WebKitTools/TestResultServer/handlers/dashboardhandler.py +++ b/WebKitTools/TestResultServer/handlers/dashboardhandler.py @@ -89,7 +89,9 @@ class UpdateDashboardFile(webapp.RequestHandler): if not files: files = ["flakiness_dashboard.html", "dashboard_base.js", - "aggregate_results.html"] + "aggregate_results.html", + "dygraph-combined.js", + "timeline_explorer.html"] errors = [] for file in files: diff --git a/WebKitTools/TestWebKitAPI/Configurations/Base.xcconfig b/WebKitTools/TestWebKitAPI/Configurations/Base.xcconfig new file mode 100644 index 0000000..feabe9a --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/Base.xcconfig @@ -0,0 +1,71 @@ +// 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. ``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 +// 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. + +HEADER_SEARCH_PATHS = $(WEBCORE_PRIVATE_HEADERS_DIR)/ForwardingHeaders; +FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks; +GCC_PREPROCESSOR_DEFINITIONS = ENABLE_DASHBOARD_SUPPORT WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST; +DEBUG_INFORMATION_FORMAT = dwarf +PREBINDING = NO +GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_PRECOMPILE_PREFIX_HEADER = YES +GCC_TREAT_WARNINGS_AS_ERRORS = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VARIABLE = YES +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO +WARNING_CFLAGS = -Wall -W -Wno-unused-parameter +LINKER_DISPLAYS_MANGLED_NAMES = YES; + + +TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); + + +// Use GCC 4.2 with Xcode 3.1, which includes GCC 4.2 but defaults to GCC 4.0. +// Note that Xcode versions as new as 3.1.2 use XCODE_VERSION_ACTUAL for the minor version +// number. Newer versions of Xcode use XCODE_VERSION_MINOR for the minor version, and +// XCODE_VERSION_ACTUAL for the full version number. +TARGET_GCC_VERSION = $(TARGET_GCC_VERSION_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +TARGET_GCC_VERSION_ = $(TARGET_GCC_VERSION_1040); +TARGET_GCC_VERSION_1040 = GCC_40; +TARGET_GCC_VERSION_1050 = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_MINOR)); +TARGET_GCC_VERSION_1050_ = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_ACTUAL)); +TARGET_GCC_VERSION_1050_0310 = GCC_42; +TARGET_GCC_VERSION_1050_0320 = GCC_42; +TARGET_GCC_VERSION_1060 = GCC_42; +TARGET_GCC_VERSION_1070 = LLVM_GCC_42; + +GCC_VERSION = $(GCC_VERSION_$(TARGET_GCC_VERSION)); +GCC_VERSION_GCC_40 = 4.0; +GCC_VERSION_GCC_42 = 4.2; +GCC_VERSION_LLVM_GCC_42 = com.apple.compilers.llvmgcc42; + +// If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK. +SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +SDKROOT_1050_1040 = macosx10.4; +SDKROOT_1060_1040 = macosx10.4; +SDKROOT_1060_1050 = macosx10.5; +SDKROOT_1070_1040 = macosx10.4; +SDKROOT_1070_1050 = macosx10.5; +SDKROOT_1070_1060 = macosx10.6; + +WEBKIT_UMBRELLA_FRAMEWORKS_DIR = $(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Frameworks; +WEBCORE_PRIVATE_HEADERS_DIR = $(WEBKIT_UMBRELLA_FRAMEWORKS_DIR)/WebCore.framework/PrivateHeaders; diff --git a/WebKitTools/TestWebKitAPI/Configurations/DebugRelease.xcconfig b/WebKitTools/TestWebKitAPI/Configurations/DebugRelease.xcconfig new file mode 100644 index 0000000..41600b1 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/DebugRelease.xcconfig @@ -0,0 +1,42 @@ +// 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. ``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 +// 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 "Base.xcconfig" + +ARCHS = $(ARCHS_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +ARCHS_ = $(ARCHS_1040); +ARCHS_1040 = $(NATIVE_ARCH); +ARCHS_1050 = $(NATIVE_ARCH); +ARCHS_1060 = $(ARCHS_STANDARD_32_64_BIT); +ARCHS_1070 = $(ARCHS_STANDARD_32_64_BIT); + +ONLY_ACTIVE_ARCH = YES; + +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR)) +MACOSX_DEPLOYMENT_TARGET_ = 10.4; +MACOSX_DEPLOYMENT_TARGET_1040 = 10.4; +MACOSX_DEPLOYMENT_TARGET_1050 = 10.5; +MACOSX_DEPLOYMENT_TARGET_1060 = 10.6; +MACOSX_DEPLOYMENT_TARGET_1070 = 10.7; + +WEBKIT_UMBRELLA_FRAMEWORKS_DIR = $(BUILT_PRODUCTS_DIR); diff --git a/WebKitTools/TestWebKitAPI/Configurations/InjectedBundle.xcconfig b/WebKitTools/TestWebKitAPI/Configurations/InjectedBundle.xcconfig new file mode 100644 index 0000000..4d3d1ee --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/InjectedBundle.xcconfig @@ -0,0 +1,24 @@ +// 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. ``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 +// 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. + +PRODUCT_NAME = InjectedBundle diff --git a/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig new file mode 100644 index 0000000..5e69d0e --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig @@ -0,0 +1,26 @@ +// 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. ``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 +// 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. + +PRODUCT_NAME = TestWebKitAPI +GCC_ENABLE_OBJC_EXCEPTIONS = YES +GCC_PREFIX_HEADER = TestWebKitAPIPrefix.h diff --git a/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops new file mode 100644 index 0000000..61b6614 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICFLite"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CFLite$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops new file mode 100644 index 0000000..1de3506 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\..";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include""
+ ForcedIncludeFiles="TestWebKitAPIPrefix.h"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WebKit$(WebKitDLLConfigSuffix).lib JavaScriptCore$(WebKitDLLConfigSuffix).lib"
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed""
+ />
+ <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"
"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops new file mode 100644 index 0000000..ee139c0 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICoreFoundation"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CoreFoundation$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/WebKitTools/TestWebKitAPI/InjectedBundle-Info.plist b/WebKitTools/TestWebKitAPI/InjectedBundle-Info.plist new file mode 100644 index 0000000..c285a47 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/InjectedBundle-Info.plist @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/WebKitTools/TestWebKitAPI/InjectedBundleController.cpp b/WebKitTools/TestWebKitAPI/InjectedBundleController.cpp new file mode 100644 index 0000000..dc563ac --- /dev/null +++ b/WebKitTools/TestWebKitAPI/InjectedBundleController.cpp @@ -0,0 +1,118 @@ +/* + * 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 "InjectedBundleController.h" + +#include "InjectedBundleTest.h" +#include "PlatformUtilities.h" +#include <WebKit2/WebKit2.h> +#include <algorithm> +#include <assert.h> + +namespace TestWebKitAPI { + +InjectedBundleController& InjectedBundleController::shared() +{ + static InjectedBundleController& shared = *new InjectedBundleController; + return shared; +} + +InjectedBundleController::InjectedBundleController() + : m_bundle(0) + , m_currentTest(0) +{ +} + +void InjectedBundleController::initialize(WKBundleRef bundle) +{ + m_bundle = bundle; + + WKBundleClient client = { + 0, + this, + didCreatePage, + willDestroyPage, + didReceiveMessage + }; + WKBundleSetClient(m_bundle, &client); +} + +void InjectedBundleController::didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) +{ + InjectedBundleController* self = static_cast<InjectedBundleController*>(const_cast<void*>(clientInfo)); + assert(self->m_currentTest); + self->m_currentTest->didCreatePage(bundle, page); +} + +void InjectedBundleController::willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) +{ + InjectedBundleController* self = static_cast<InjectedBundleController*>(const_cast<void*>(clientInfo)); + assert(self->m_currentTest); + self->m_currentTest->willDestroyPage(bundle, page); +} + +void InjectedBundleController::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo) +{ + InjectedBundleController* self = static_cast<InjectedBundleController*>(const_cast<void*>(clientInfo)); + + if (WKStringIsEqualToUTF8CString(messageName, "BundleTestInstantiator")) { + assert(WKGetTypeID(messageBody) == WKStringGetTypeID()); + WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody); + + self->initializeTestNamed(Util::toSTD(messageBodyString)); + + return; + } + + assert(self->m_currentTest); + self->m_currentTest->didReceiveMessage(bundle, messageName, messageBody); +} + +void InjectedBundleController::dumpTestNames() +{ + std::map<std::string, CreateInjectedBundleTestFunction>::const_iterator it = m_createInjectedBundleTestFunctions.begin(); + std::map<std::string, CreateInjectedBundleTestFunction>::const_iterator end = m_createInjectedBundleTestFunctions.end(); + for (; it != end; ++it) + printf("%s\n", (*it).first.c_str()); +} + +void InjectedBundleController::initializeTestNamed(const std::string& identifier) +{ + CreateInjectedBundleTestFunction createTestFunction = m_createInjectedBundleTestFunctions[identifier]; + if (!createTestFunction) { + printf("ERROR: InjectedBundle test not found - %s\n", identifier.c_str()); + exit(1); + } + + m_currentTest = createTestFunction(identifier); + m_currentTest->initialize(); +} + +void InjectedBundleController::registerCreateInjectedBundleTestFunction(const std::string& identifier, CreateInjectedBundleTestFunction function) +{ + m_createInjectedBundleTestFunctions[identifier] = function; +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/InjectedBundleController.h b/WebKitTools/TestWebKitAPI/InjectedBundleController.h new file mode 100644 index 0000000..89e2c5e --- /dev/null +++ b/WebKitTools/TestWebKitAPI/InjectedBundleController.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef InjectedBundleController_h +#define InjectedBundleController_h + +#include <WebKit2/WKBundle.h> +#include <map> +#include <string> + +namespace TestWebKitAPI { + +class InjectedBundleTest; + +class InjectedBundleController { +public: + static InjectedBundleController& shared(); + + void initialize(WKBundleRef); + + void dumpTestNames(); + void initializeTestNamed(const std::string&); + + typedef InjectedBundleTest* (*CreateInjectedBundleTestFunction)(const std::string&); + void registerCreateInjectedBundleTestFunction(const std::string&, CreateInjectedBundleTestFunction); + +private: + InjectedBundleController(); + ~InjectedBundleController(); + + static void didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo); + static void willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo); + static void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo); + + std::map<std::string, CreateInjectedBundleTestFunction> m_createInjectedBundleTestFunctions; + WKBundleRef m_bundle; + InjectedBundleTest* m_currentTest; +}; + +} // namespace TestWebKitAPI + +#endif // InjectedBundleController_h diff --git a/WebKitTools/TestWebKitAPI/InjectedBundleMain.cpp b/WebKitTools/TestWebKitAPI/InjectedBundleMain.cpp new file mode 100644 index 0000000..8f9e8ad --- /dev/null +++ b/WebKitTools/TestWebKitAPI/InjectedBundleMain.cpp @@ -0,0 +1,37 @@ +/* + * 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 "InjectedBundleController.h" +#include <WebKit2/WKBundleInitialize.h> + +#if defined(WIN32) || defined(_WIN32) +extern "C" __declspec(dllexport) +#else +extern "C" +#endif +void WKBundleInitialize(WKBundleRef bundle) +{ + TestWebKitAPI::InjectedBundleController::shared().initialize(bundle); +} diff --git a/WebKitTools/TestWebKitAPI/InjectedBundleTest.h b/WebKitTools/TestWebKitAPI/InjectedBundleTest.h new file mode 100644 index 0000000..f3812ef --- /dev/null +++ b/WebKitTools/TestWebKitAPI/InjectedBundleTest.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef InjectedBundleTest_h +#define InjectedBundleTest_h + +#include "InjectedBundleController.h" + +namespace TestWebKitAPI { + +class InjectedBundleTest { +public: + virtual ~InjectedBundleTest() { } + + virtual void initialize() { } + + virtual void didCreatePage(WKBundleRef, WKBundlePageRef) { } + virtual void willDestroyPage(WKBundleRef, WKBundlePageRef) { } + virtual void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody) { } + + std::string name() const { return m_identifier; } + + template<typename TestClassTy> class Register { + public: + Register(const std::string& test) + { + InjectedBundleController::shared().registerCreateInjectedBundleTestFunction(test, Register::create); + } + + private: + static InjectedBundleTest* create(const std::string& identifier) + { + return new TestClassTy(identifier); + } + }; + +protected: + InjectedBundleTest(const std::string& identifier) + : m_identifier(identifier) + { + } + + std::string m_identifier; +}; + +} // namespace TestWebKitAPI + +#endif // InjectedBundleTest_h diff --git a/WebKitTools/TestWebKitAPI/Makefile b/WebKitTools/TestWebKitAPI/Makefile new file mode 100644 index 0000000..ed01cce --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Makefile @@ -0,0 +1,21 @@ +# Build TestWebKitAPI only on Snow Leopard and later. + +OSX_VERSION ?= $(shell sw_vers -productVersion | cut -d. -f 2) +BUILD_TESTWEBKITAPI = $(shell (( $(OSX_VERSION) >= 6 )) && echo "YES" ) + +ifeq "$(BUILD_TESTWEBKITAPI)" "YES" + +SCRIPTS_PATH = ../Scripts +include ../../Makefile.shared + +else + +all: ; + +debug d development dev develop: ; + +release r deployment dep deploy: ; + +clean: ; + +endif diff --git a/WebKitTools/TestWebKitAPI/PlatformUtilities.cpp b/WebKitTools/TestWebKitAPI/PlatformUtilities.cpp new file mode 100644 index 0000000..2fadf3a --- /dev/null +++ b/WebKitTools/TestWebKitAPI/PlatformUtilities.cpp @@ -0,0 +1,59 @@ +/* + * 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 "PlatformUtilities.h" + +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WebKit2.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/PassOwnArrayPtr.h> + +namespace TestWebKitAPI { +namespace Util { + +WKContextRef createContextForInjectedBundleTest(const std::string& testName) +{ + WKRetainPtr<WKStringRef> injectedBundlePath(AdoptWK, createInjectedBundlePath()); + WKContextRef context = WKContextCreateWithInjectedBundlePath(injectedBundlePath.get()); + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BundleTestInstantiator")); + WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(testName.c_str())); + + // Enqueue message to instantiate the bundle test. + WKContextPostMessageToInjectedBundle(context, messageName.get(), messageBody.get()); + + return context; +} + +std::string toSTD(WKStringRef string) +{ + size_t bufferSize = WKStringGetMaximumUTF8CStringSize(string); + OwnArrayPtr<char> buffer = adoptArrayPtr(new char[bufferSize]); + size_t stringLength = WKStringGetUTF8CString(string, buffer.get(), bufferSize); + return std::string(buffer.get(), stringLength - 1); +} + +} // namespace Util +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/PlatformUtilities.h b/WebKitTools/TestWebKitAPI/PlatformUtilities.h new file mode 100644 index 0000000..8ae347c --- /dev/null +++ b/WebKitTools/TestWebKitAPI/PlatformUtilities.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef PlatformUtilities_h +#define PlatformUtilities_h + +#include <WebKit2/WebKit2.h> +#include <string> + +namespace TestWebKitAPI { +namespace Util { + +// Runs a platform runloop until the 'done' is true. +void run(bool* done); + +WKContextRef createContextForInjectedBundleTest(const std::string&); + +WKStringRef createInjectedBundlePath(); +WKURLRef createURLForResource(const char* resource, const char* extension); +WKURLRef URLForNonExistentResource(); + +bool isKeyDown(WKNativeEventPtr); + +std::string toSTD(WKStringRef string); + +} // namespace Util +} // namespace TestWebKitAPI + +#endif // PlatformUtilities_h diff --git a/WebKitTools/TestWebKitAPI/PlatformWebView.h b/WebKitTools/TestWebKitAPI/PlatformWebView.h new file mode 100644 index 0000000..7f4f057 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/PlatformWebView.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#ifndef PlatformWebView_h +#define PlatformWebView_h + +#include <wtf/Platform.h> + +#ifdef __APPLE__ +#ifdef __OBJC__ +@class WKView; +@class NSWindow; +#else +class WKView; +class NSWindow; +#endif +typedef WKView *PlatformWKView; +typedef NSWindow *PlatformWindow; +#elif defined(WIN32) || defined(_WIN32) +typedef WKViewRef PlatformWKView; +typedef HWND PlatformWindow; +#endif + +namespace TestWebKitAPI { + +#if PLATFORM(WIN) +class WindowMessageObserver; +#endif + +class PlatformWebView { +public: + PlatformWebView(WKPageNamespaceRef); + ~PlatformWebView(); + + WKPageRef page(); + PlatformWKView platformView() const { return m_view; } + void resizeTo(unsigned width, unsigned height); + void focus(); + + void simulateSpacebarKeyPress(); + void simulateAltKeyPress(); + +#if PLATFORM(WIN) + void setParentWindowMessageObserver(WindowMessageObserver* observer) { m_parentWindowMessageObserver = observer; } +#endif + +private: +#if PLATFORM(WIN) + static void registerWindowClass(); + static LRESULT CALLBACK wndProc(HWND, UINT message, WPARAM, LPARAM); +#endif + + PlatformWKView m_view; + PlatformWindow m_window; + +#if PLATFORM(WIN) + WindowMessageObserver* m_parentWindowMessageObserver; +#endif +}; + +} // namespace TestWebKitAPI + +#endif // PlatformWebView_h diff --git a/WebKitTools/TestWebKitAPI/Test.h b/WebKitTools/TestWebKitAPI/Test.h new file mode 100644 index 0000000..93bfd8b --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Test.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#ifndef Test_h +#define Test_h + +#include "TestsController.h" + +namespace TestWebKitAPI { + +// Abstract base class that all tests inherit from. +class Test { +public: + virtual ~Test() { } + + virtual void run() = 0; + std::string name() const { return m_identifier; } + + template<typename TestClassTy> class Register { + public: + Register(const std::string& testSuite, const std::string& testCase) + { + TestsController::shared().registerCreateTestFunction(testSuite + "/" + testCase, Register::create); + } + + private: + static Test* create(const std::string& identifier) + { + return new TestClassTy(identifier); + } + }; + +protected: + Test(const std::string& identifier) + : m_identifier(identifier) + { + } + + std::string m_identifier; +}; + +#define TEST_CLASS_NAME(testSuite, testCaseName) testSuite##testCaseName##_Test +#define TEST_REGISTRAR_NAME(testSuite, testCaseName) testSuite##testCaseName##_Registrar + +// Use this to define a new test. +#define TEST(testSuite, testCaseName) \ + class TEST_CLASS_NAME(testSuite, testCaseName) : public Test { \ + public: \ + TEST_CLASS_NAME(testSuite, testCaseName)(const std::string& identifier) \ + : Test(identifier) \ + { \ + } \ + virtual void run(); \ + }; \ + \ + static Test::Register<TEST_CLASS_NAME(testSuite, testCaseName)> TEST_REGISTRAR_NAME(testSuite, testCaseName)(#testSuite, #testCaseName); \ + \ + void TEST_CLASS_NAME(testSuite, testCaseName)::run() + +#define TEST_ASSERT(expression) do { if (!(expression)) { TestsController::shared().testFailed(__FILE__, __LINE__, #expression); return; } } while (0) + +} // namespace TestWebKitAPI + +#endif // Test_h diff --git a/WebKitTools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/WebKitTools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fa967b7 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj @@ -0,0 +1,473 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1A02C84F125D4A8400E3F4BD /* Find.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A02C84E125D4A8400E3F4BD /* Find.cpp */; }; + 1A02C870125D4CFD00E3F4BD /* find.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 1A02C84B125D4A5E00E3F4BD /* find.html */; }; + BC131885117114B600B69727 /* PlatformUtilitiesMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */; }; + BC131A9B1171316900B69727 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131A9A1171316900B69727 /* main.mm */; }; + BC131AA9117131FC00B69727 /* TestsController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC131AA8117131FC00B69727 /* TestsController.cpp */; }; + BC575A90126E74D3006F0F12 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCB9E9F011235BDE00A137E0 /* Cocoa.framework */; }; + BC575A91126E74D3006F0F12 /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA61DB411700EFD00460D1E /* WebKit2.framework */; }; + BC575A92126E74D3006F0F12 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC90964D1255620C00083756 /* JavaScriptCore.framework */; }; + BC575A97126E74F1006F0F12 /* InjectedBundleMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575946126E7351006F0F12 /* InjectedBundleMain.cpp */; }; + BC575AA2126E7660006F0F12 /* InjectedBundleController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575AA0126E7657006F0F12 /* InjectedBundleController.cpp */; }; + BC575AAD126E83B9006F0F12 /* InjectedBundleBasic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575AAC126E83B9006F0F12 /* InjectedBundleBasic.cpp */; }; + BC575AB0126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575AAF126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp */; }; + BC575BC0126F5752006F0F12 /* PlatformUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */; }; + BC575BD9126F58E2006F0F12 /* PlatformUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */; }; + BC575BE0126F590D006F0F12 /* PlatformUtilitiesMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */; }; + BC90955D125548AA00083756 /* PlatformWebViewMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC90955C125548AA00083756 /* PlatformWebViewMac.mm */; }; + BC90964C125561BF00083756 /* VectorBasic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC90964B125561BF00083756 /* VectorBasic.cpp */; }; + BC90964E1255620C00083756 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC90964D1255620C00083756 /* JavaScriptCore.framework */; }; + BC90977A125571AB00083756 /* PageLoadBasic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC909779125571AB00083756 /* PageLoadBasic.cpp */; }; + BC909784125571CF00083756 /* simple.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = BC909778125571AB00083756 /* simple.html */; }; + BC90995E12567BC100083756 /* WKString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC90995D12567BC100083756 /* WKString.cpp */; }; + BC9099941256ACF100083756 /* WKStringJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC9099931256ACF100083756 /* WKStringJSString.cpp */; }; + BCA61DB511700EFD00460D1E /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCA61DB411700EFD00460D1E /* WebKit2.framework */; }; + BCB9E9F111235BDE00A137E0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCB9E9F011235BDE00A137E0 /* Cocoa.framework */; }; + BCBD3710125AA2EB00D2C29F /* FrameMIMETypeHTML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCBD370F125AA2EB00D2C29F /* FrameMIMETypeHTML.cpp */; }; + BCBD3737125ABBEB00D2C29F /* icon.png in Copy Resources */ = {isa = PBXBuildFile; fileRef = BCBD372E125ABBE600D2C29F /* icon.png */; }; + BCBD3761125ABCFE00D2C29F /* FrameMIMETypePNG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCBD3760125ABCFE00D2C29F /* FrameMIMETypePNG.cpp */; }; + BCC8B95B12611F4700DE46A4 /* FailedLoad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCC8B95A12611F4700DE46A4 /* FailedLoad.cpp */; }; + C01A23F21266156700C9ED55 /* spacebar-scrolling.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C02B7882126615410026BF0F /* spacebar-scrolling.html */; }; + C02B77F2126612140026BF0F /* SpacebarScrolling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C02B77F1126612140026BF0F /* SpacebarScrolling.cpp */; }; + C02B7854126613AE0026BF0F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C02B7853126613AE0026BF0F /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + BC575A95126E74E7006F0F12 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = BC57597F126E74AF006F0F12 /* InjectedBundle */; + remoteInfo = InjectedBundle; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F9E0486AA7600D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + BCB9F4FB112384C000A137E0 /* Copy Resources */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 7; + files = ( + BCBD3737125ABBEB00D2C29F /* icon.png in Copy Resources */, + 1A02C870125D4CFD00E3F4BD /* find.html in Copy Resources */, + BC909784125571CF00083756 /* simple.html in Copy Resources */, + C01A23F21266156700C9ED55 /* spacebar-scrolling.html in Copy Resources */, + ); + name = "Copy Resources"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1A02C84B125D4A5E00E3F4BD /* find.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = find.html; sourceTree = "<group>"; }; + 1A02C84E125D4A8400E3F4BD /* Find.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Find.cpp; sourceTree = "<group>"; }; + 8DD76FA10486AA7600D96B5E /* TestWebKitAPI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestWebKitAPI; sourceTree = BUILT_PRODUCTS_DIR; }; + BC131883117114A800B69727 /* PlatformUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformUtilities.h; sourceTree = "<group>"; }; + BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformUtilitiesMac.mm; sourceTree = "<group>"; }; + BC131A9A1171316900B69727 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; + BC131A9E1171317C00B69727 /* TestWebKitAPIPrefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestWebKitAPIPrefix.h; sourceTree = "<group>"; }; + BC131AA8117131FC00B69727 /* TestsController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = TestsController.cpp; sourceTree = "<group>"; }; + BC575946126E7351006F0F12 /* InjectedBundleMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleMain.cpp; sourceTree = "<group>"; }; + BC575980126E74AF006F0F12 /* InjectedBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InjectedBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + BC575981126E74AF006F0F12 /* InjectedBundle-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "InjectedBundle-Info.plist"; sourceTree = "<group>"; }; + BC575A9E126E75FB006F0F12 /* InjectedBundleTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundleTest.h; sourceTree = "<group>"; }; + BC575A9F126E7657006F0F12 /* InjectedBundleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundleController.h; sourceTree = "<group>"; }; + BC575AA0126E7657006F0F12 /* InjectedBundleController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleController.cpp; sourceTree = "<group>"; }; + BC575AAC126E83B9006F0F12 /* InjectedBundleBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleBasic.cpp; sourceTree = "<group>"; }; + BC575AAF126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleBasic_Bundle.cpp; sourceTree = "<group>"; }; + BC575AE2126E88B1006F0F12 /* InjectedBundle.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = InjectedBundle.xcconfig; sourceTree = "<group>"; }; + BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformUtilities.cpp; sourceTree = "<group>"; }; + BC90951B125533D700083756 /* PlatformWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformWebView.h; sourceTree = "<group>"; }; + BC90955C125548AA00083756 /* PlatformWebViewMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformWebViewMac.mm; sourceTree = "<group>"; }; + BC90957E12554CF900083756 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; }; + BC90957F12554CF900083756 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; }; + BC90958012554CF900083756 /* TestWebKitAPI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TestWebKitAPI.xcconfig; sourceTree = "<group>"; }; + BC90964B125561BF00083756 /* VectorBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VectorBasic.cpp; path = WTF/VectorBasic.cpp; sourceTree = "<group>"; }; + BC90964D1255620C00083756 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JavaScriptCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BC909778125571AB00083756 /* simple.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = simple.html; sourceTree = "<group>"; }; + BC909779125571AB00083756 /* PageLoadBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageLoadBasic.cpp; sourceTree = "<group>"; }; + BC90995D12567BC100083756 /* WKString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKString.cpp; sourceTree = "<group>"; }; + BC9099931256ACF100083756 /* WKStringJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKStringJSString.cpp; sourceTree = "<group>"; }; + BCA61DB411700EFD00460D1E /* WebKit2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BCB9E7C711234E3A00A137E0 /* TestsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestsController.h; sourceTree = "<group>"; }; + BCB9E7FA112359A300A137E0 /* Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Test.h; sourceTree = "<group>"; }; + BCB9E9F011235BDE00A137E0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + BCBD370F125AA2EB00D2C29F /* FrameMIMETypeHTML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameMIMETypeHTML.cpp; sourceTree = "<group>"; }; + BCBD372E125ABBE600D2C29F /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; }; + BCBD3760125ABCFE00D2C29F /* FrameMIMETypePNG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameMIMETypePNG.cpp; sourceTree = "<group>"; }; + BCC8B95A12611F4700DE46A4 /* FailedLoad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FailedLoad.cpp; sourceTree = "<group>"; }; + C02B77F1126612140026BF0F /* SpacebarScrolling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpacebarScrolling.cpp; sourceTree = "<group>"; }; + C02B7853126613AE0026BF0F /* Carbon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = Carbon.framework; sourceTree = SDKROOT; }; + C02B7882126615410026BF0F /* spacebar-scrolling.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "spacebar-scrolling.html"; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F9B0486AA7600D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BCB9E9F111235BDE00A137E0 /* Cocoa.framework in Frameworks */, + BCA61DB511700EFD00460D1E /* WebKit2.framework in Frameworks */, + BC90964E1255620C00083756 /* JavaScriptCore.framework in Frameworks */, + C02B7854126613AE0026BF0F /* Carbon.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BC57597E126E74AF006F0F12 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BC575A90126E74D3006F0F12 /* Cocoa.framework in Frameworks */, + BC575A91126E74D3006F0F12 /* WebKit2.framework in Frameworks */, + BC575A92126E74D3006F0F12 /* JavaScriptCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* TestWebKitAPI */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + BCB9EB66112366D800A137E0 /* Tests */, + BC90957D12554CEA00083756 /* Configurations */, + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + BC575981126E74AF006F0F12 /* InjectedBundle-Info.plist */, + ); + name = TestWebKitAPI; + sourceTree = "<group>"; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + BCA61C3A11700B9400460D1E /* mac */, + BC575944126E733C006F0F12 /* InjectedBundle */, + BC131A9E1171317C00B69727 /* TestWebKitAPIPrefix.h */, + BC575BBF126F5752006F0F12 /* PlatformUtilities.cpp */, + BC131883117114A800B69727 /* PlatformUtilities.h */, + BC90951B125533D700083756 /* PlatformWebView.h */, + BCB9E7FA112359A300A137E0 /* Test.h */, + BC131AA8117131FC00B69727 /* TestsController.cpp */, + BCB9E7C711234E3A00A137E0 /* TestsController.h */, + ); + name = Source; + sourceTree = "<group>"; + }; + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + BCB9E9F011235BDE00A137E0 /* Cocoa.framework */, + BC90964D1255620C00083756 /* JavaScriptCore.framework */, + BCA61DB411700EFD00460D1E /* WebKit2.framework */, + C02B7853126613AE0026BF0F /* Carbon.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = "<group>"; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FA10486AA7600D96B5E /* TestWebKitAPI */, + BC575980126E74AF006F0F12 /* InjectedBundle.bundle */, + ); + name = Products; + sourceTree = "<group>"; + }; + BC575944126E733C006F0F12 /* InjectedBundle */ = { + isa = PBXGroup; + children = ( + BC575946126E7351006F0F12 /* InjectedBundleMain.cpp */, + BC575A9E126E75FB006F0F12 /* InjectedBundleTest.h */, + BC575A9F126E7657006F0F12 /* InjectedBundleController.h */, + BC575AA0126E7657006F0F12 /* InjectedBundleController.cpp */, + ); + name = InjectedBundle; + sourceTree = "<group>"; + }; + BC90957D12554CEA00083756 /* Configurations */ = { + isa = PBXGroup; + children = ( + BC90957E12554CF900083756 /* Base.xcconfig */, + BC90957F12554CF900083756 /* DebugRelease.xcconfig */, + BC575AE2126E88B1006F0F12 /* InjectedBundle.xcconfig */, + BC90958012554CF900083756 /* TestWebKitAPI.xcconfig */, + ); + path = Configurations; + sourceTree = "<group>"; + }; + BC9096411255616000083756 /* WebKit2 */ = { + isa = PBXGroup; + children = ( + BC90977B125571AE00083756 /* Resources */, + 1A02C84E125D4A8400E3F4BD /* Find.cpp */, + BCBD370F125AA2EB00D2C29F /* FrameMIMETypeHTML.cpp */, + BCBD3760125ABCFE00D2C29F /* FrameMIMETypePNG.cpp */, + BC909779125571AB00083756 /* PageLoadBasic.cpp */, + C02B77F1126612140026BF0F /* SpacebarScrolling.cpp */, + BC90995D12567BC100083756 /* WKString.cpp */, + BC9099931256ACF100083756 /* WKStringJSString.cpp */, + BCC8B95A12611F4700DE46A4 /* FailedLoad.cpp */, + BC575AAC126E83B9006F0F12 /* InjectedBundleBasic.cpp */, + BC575AAF126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp */, + ); + path = WebKit2; + sourceTree = "<group>"; + }; + BC9096461255618900083756 /* WTF */ = { + isa = PBXGroup; + children = ( + BC90964B125561BF00083756 /* VectorBasic.cpp */, + ); + name = WTF; + sourceTree = "<group>"; + }; + BC90977B125571AE00083756 /* Resources */ = { + isa = PBXGroup; + children = ( + BCBD372E125ABBE600D2C29F /* icon.png */, + 1A02C84B125D4A5E00E3F4BD /* find.html */, + BC909778125571AB00083756 /* simple.html */, + C02B7882126615410026BF0F /* spacebar-scrolling.html */, + ); + name = Resources; + sourceTree = "<group>"; + }; + BCA61C3A11700B9400460D1E /* mac */ = { + isa = PBXGroup; + children = ( + BC131A9A1171316900B69727 /* main.mm */, + BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */, + BC90955C125548AA00083756 /* PlatformWebViewMac.mm */, + ); + path = mac; + sourceTree = "<group>"; + }; + BCB9EB66112366D800A137E0 /* Tests */ = { + isa = PBXGroup; + children = ( + BC9096411255616000083756 /* WebKit2 */, + BC9096461255618900083756 /* WTF */, + ); + path = Tests; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F960486AA7600D96B5E /* TestWebKitAPI */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "TestWebKitAPI" */; + buildPhases = ( + 8DD76F990486AA7600D96B5E /* Sources */, + 8DD76F9B0486AA7600D96B5E /* Frameworks */, + 8DD76F9E0486AA7600D96B5E /* CopyFiles */, + BCB9F4FB112384C000A137E0 /* Copy Resources */, + ); + buildRules = ( + ); + dependencies = ( + BC575A96126E74E7006F0F12 /* PBXTargetDependency */, + ); + name = TestWebKitAPI; + productInstallPath = "$(HOME)/bin"; + productName = TestWebKitAPI; + productReference = 8DD76FA10486AA7600D96B5E /* TestWebKitAPI */; + productType = "com.apple.product-type.tool"; + }; + BC57597F126E74AF006F0F12 /* InjectedBundle */ = { + isa = PBXNativeTarget; + buildConfigurationList = BC575986126E74AF006F0F12 /* Build configuration list for PBXNativeTarget "InjectedBundle" */; + buildPhases = ( + BC57597C126E74AF006F0F12 /* Resources */, + BC57597D126E74AF006F0F12 /* Sources */, + BC57597E126E74AF006F0F12 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = InjectedBundle; + productName = InjectedBundle; + productReference = BC575980126E74AF006F0F12 /* InjectedBundle.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "TestWebKitAPI" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* TestWebKitAPI */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F960486AA7600D96B5E /* TestWebKitAPI */, + BC57597F126E74AF006F0F12 /* InjectedBundle */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + BC57597C126E74AF006F0F12 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F990486AA7600D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BC131885117114B600B69727 /* PlatformUtilitiesMac.mm in Sources */, + BC131A9B1171316900B69727 /* main.mm in Sources */, + BC131AA9117131FC00B69727 /* TestsController.cpp in Sources */, + BC90955D125548AA00083756 /* PlatformWebViewMac.mm in Sources */, + BC90964C125561BF00083756 /* VectorBasic.cpp in Sources */, + BC90977A125571AB00083756 /* PageLoadBasic.cpp in Sources */, + BC90995E12567BC100083756 /* WKString.cpp in Sources */, + BC9099941256ACF100083756 /* WKStringJSString.cpp in Sources */, + BCBD3710125AA2EB00D2C29F /* FrameMIMETypeHTML.cpp in Sources */, + BCBD3761125ABCFE00D2C29F /* FrameMIMETypePNG.cpp in Sources */, + 1A02C84F125D4A8400E3F4BD /* Find.cpp in Sources */, + BCC8B95B12611F4700DE46A4 /* FailedLoad.cpp in Sources */, + C02B77F2126612140026BF0F /* SpacebarScrolling.cpp in Sources */, + BC575AAD126E83B9006F0F12 /* InjectedBundleBasic.cpp in Sources */, + BC575BC0126F5752006F0F12 /* PlatformUtilities.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BC57597D126E74AF006F0F12 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BC575A97126E74F1006F0F12 /* InjectedBundleMain.cpp in Sources */, + BC575AA2126E7660006F0F12 /* InjectedBundleController.cpp in Sources */, + BC575AB0126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp in Sources */, + BC575BD9126F58E2006F0F12 /* PlatformUtilities.cpp in Sources */, + BC575BE0126F590D006F0F12 /* PlatformUtilitiesMac.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + BC575A96126E74E7006F0F12 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BC57597F126E74AF006F0F12 /* InjectedBundle */; + targetProxy = BC575A95126E74E7006F0F12 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1DEB927508733DD40010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC90958012554CF900083756 /* TestWebKitAPI.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + }; + name = Debug; + }; + 1DEB927608733DD40010E9CD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC90958012554CF900083756 /* TestWebKitAPI.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + }; + name = Release; + }; + 1DEB927908733DD40010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC90957F12554CF900083756 /* DebugRelease.xcconfig */; + buildSettings = { + GCC_OPTIMIZATION_LEVEL = 0; + }; + name = Debug; + }; + 1DEB927A08733DD40010E9CD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC90957F12554CF900083756 /* DebugRelease.xcconfig */; + buildSettings = { + }; + name = Release; + }; + BC575984126E74AF006F0F12 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC575AE2126E88B1006F0F12 /* InjectedBundle.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + BC575985126E74AF006F0F12 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC575AE2126E88B1006F0F12 /* InjectedBundle.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "TestWebKitAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB927508733DD40010E9CD /* Debug */, + 1DEB927608733DD40010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "TestWebKitAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB927908733DD40010E9CD /* Debug */, + 1DEB927A08733DD40010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BC575986126E74AF006F0F12 /* Build configuration list for PBXNativeTarget "InjectedBundle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BC575984126E74AF006F0F12 /* Debug */, + BC575985126E74AF006F0F12 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/WebKitTools/TestWebKitAPI/TestWebKitAPIPrefix.h b/WebKitTools/TestWebKitAPI/TestWebKitAPIPrefix.h new file mode 100644 index 0000000..00e14ad --- /dev/null +++ b/WebKitTools/TestWebKitAPI/TestWebKitAPIPrefix.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + + +#if __APPLE__ + +#ifdef __OBJC__ +#import <Cocoa/Cocoa.h> +#endif + +#elif defined(WIN32) || defined(_WIN32) + +#define NOMINMAX + +#endif + +#include <stdint.h> + +#include <WebKit2/WebKit2.h> diff --git a/WebKitTools/TestWebKitAPI/Tests/WTF/VectorBasic.cpp b/WebKitTools/TestWebKitAPI/Tests/WTF/VectorBasic.cpp new file mode 100644 index 0000000..012fa27 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WTF/VectorBasic.cpp @@ -0,0 +1,40 @@ +/* + * 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 "Test.h" + +#include <JavaScriptCore/Vector.h> + +namespace TestWebKitAPI { + +TEST(WTF, VectorBasic) +{ + Vector<int> intVector; + TEST_ASSERT(intVector.isEmpty()); + TEST_ASSERT(intVector.size() == 0); + TEST_ASSERT(intVector.capacity() == 0); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp new file mode 100644 index 0000000..b7db746 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp @@ -0,0 +1,72 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +// FIXME: This should also test the that the load state after didFailLoadWithErrorForFrame is kWKFrameLoadStateFinished + +static bool testDone; + +static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo) +{ + TEST_ASSERT(WKFrameGetFrameLoadState(frame) == kWKFrameLoadStateFinished); + + WKURLRef url = WKFrameCopyProvisionalURL(frame); + WKURLRef emptyURL = WKURLCreateWithUTF8CString(""); + TEST_ASSERT(WKURLIsEqual(url, emptyURL)); + WKRelease(url); + WKRelease(emptyURL); + + testDone = true; +} + +TEST(WebKit2, FailedLoad) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.clientInfo = 0; + loaderClient.didFailProvisionalLoadWithErrorForFrame = didFailProvisionalLoadWithErrorForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::URLForNonExistentResource()); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&testDone); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/Find.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/Find.cpp new file mode 100644 index 0000000..63bcea8 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/Find.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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WebKit2.h> + +namespace TestWebKitAPI { + +static bool didFinishLoad = false; +static bool didCallCountStringMatches = false; + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + didFinishLoad = true; +} + +static void didCountStringMatches(WKPageRef page, WKStringRef string, unsigned numMatches, const void* clientInfo) +{ + TEST_ASSERT(WKStringIsEqualToUTF8CString(string, "Hello")); + TEST_ASSERT(numMatches == 3); + + didCallCountStringMatches = true; +} + +TEST(WebKit2, Find) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKPageFindClient findClient; + memset(&findClient, 0, sizeof(findClient)); + + findClient.version = 0; + findClient.didCountStringMatches = didCountStringMatches; + WKPageSetPageFindClient(webView.page(), &findClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("find", "html")); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&didFinishLoad); + + WKRetainPtr<WKStringRef> findString(AdoptWK, WKStringCreateWithUTF8CString("Hello")); + WKPageCountStringMatches(webView.page(), findString.get(), true, 100); + + Util::run(&didCallCountStringMatches); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp new file mode 100644 index 0000000..a270357 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp @@ -0,0 +1,79 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +static bool testDone; + +static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEmpty(wkMIME.get())); +} + +static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEqualToUTF8CString(wkMIME.get(), "text/html")); +} + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEqualToUTF8CString(wkMIME.get(), "text/html")); + + testDone = true; +} + +TEST(WebKit2, FrameMIMETypeHTML) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.clientInfo = 0; + loaderClient.didStartProvisionalLoadForFrame = didStartProvisionalLoadForFrame; + loaderClient.didCommitLoadForFrame = didCommitLoadForFrame; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&testDone); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp new file mode 100644 index 0000000..3588940 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp @@ -0,0 +1,79 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +static bool testDone; + +static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEmpty(wkMIME.get())); +} + +static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEqualToUTF8CString(wkMIME.get(), "image/png")); +} + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + WKRetainPtr<WKStringRef> wkMIME(AdoptWK, WKFrameCopyMIMEType(frame)); + TEST_ASSERT(WKStringIsEqualToUTF8CString(wkMIME.get(), "image/png")); + + testDone = true; +} + +TEST(WebKit2, FrameMIMETypePNG) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.clientInfo = 0; + loaderClient.didStartProvisionalLoadForFrame = didStartProvisionalLoadForFrame; + loaderClient.didCommitLoadForFrame = didCommitLoadForFrame; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("icon", "png")); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&testDone); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp new file mode 100644 index 0000000..1f4cce6 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp @@ -0,0 +1,80 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +static bool done; +static bool loadDone; +static bool messageReceived; + +void didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo) +{ + messageReceived = true; + if (loadDone) + done = true; +} + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + loadDone = true; + if (messageReceived) + done = true; +} + +TEST(WebKit2, InjectedBundleBasic) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("InjectedBundleBasicTest")); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + + WKContextInjectedBundleClient injectedBundleClient; + memset(&injectedBundleClient, 0, sizeof(injectedBundleClient)); + injectedBundleClient.version = 0; + injectedBundleClient.clientInfo = 0; + injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle; + WKContextSetInjectedBundleClient(context.get(), &injectedBundleClient); + + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + loaderClient.version = 0; + loaderClient.clientInfo = 0; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&done); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp new file mode 100644 index 0000000..67c062b --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp @@ -0,0 +1,49 @@ +/* + * 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 "InjectedBundleTest.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +class InjectedBundleBasicTest : public InjectedBundleTest { +public: + InjectedBundleBasicTest(const std::string& identifier) + : InjectedBundleTest(identifier) + { + } + + virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page) + { + WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("DoneMessageName")); + WKRetainPtr<WKStringRef> doneMessageBody(AdoptWK, WKStringCreateWithUTF8CString("DoneMessageBody")); + WKBundlePostMessage(bundle, doneMessageName.get(), doneMessageBody.get()); + } +}; + +static InjectedBundleTest::Register<InjectedBundleBasicTest> registrar("InjectedBundleBasicTest"); + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp new file mode 100644 index 0000000..a0b4058 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp @@ -0,0 +1,135 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WebKit2.h> +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +static bool test1Done; + +struct State { + State() + : didDecidePolicyForNavigationAction(false) + , didStartProvisionalLoadForFrame(false) + , didCommitLoadForFrame(false) + { + } + + bool didDecidePolicyForNavigationAction; + bool didStartProvisionalLoadForFrame; + bool didCommitLoadForFrame; +}; + +static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + State* state = reinterpret_cast<State*>(const_cast<void*>(clientInfo)); + TEST_ASSERT(state->didDecidePolicyForNavigationAction); + TEST_ASSERT(!state->didCommitLoadForFrame); + TEST_ASSERT(!state->didStartProvisionalLoadForFrame); + + state->didStartProvisionalLoadForFrame = true; +} + +static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + State* state = reinterpret_cast<State*>(const_cast<void*>(clientInfo)); + TEST_ASSERT(state->didDecidePolicyForNavigationAction); + TEST_ASSERT(state->didStartProvisionalLoadForFrame); + + state->didCommitLoadForFrame = true; +} + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + State* state = reinterpret_cast<State*>(const_cast<void*>(clientInfo)); + TEST_ASSERT(state->didDecidePolicyForNavigationAction); + TEST_ASSERT(state->didStartProvisionalLoadForFrame); + TEST_ASSERT(state->didCommitLoadForFrame); + + test1Done = true; +} + +static void decidePolicyForNavigationAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void* clientInfo) +{ + State* state = reinterpret_cast<State*>(const_cast<void*>(clientInfo)); + TEST_ASSERT(!state->didStartProvisionalLoadForFrame); + TEST_ASSERT(!state->didCommitLoadForFrame); + + state->didDecidePolicyForNavigationAction = true; + + WKFramePolicyListenerUse(listener); +} + +static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void* clientInfo) +{ + WKFramePolicyListenerUse(listener); +} + +static void decidePolicyForMIMEType(WKPageRef page, WKStringRef MIMEType, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void* clientInfo) +{ + WKFramePolicyListenerUse(listener); +} + +TEST(WebKit2, PageLoadBasic) +{ + State state; + + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.clientInfo = &state; + loaderClient.didStartProvisionalLoadForFrame = didStartProvisionalLoadForFrame; + loaderClient.didCommitLoadForFrame = didCommitLoadForFrame; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKPagePolicyClient policyClient; + memset(&policyClient, 0, sizeof(policyClient)); + + policyClient.version = 0; + policyClient.clientInfo = &state; + policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction; + policyClient.decidePolicyForNewWindowAction = decidePolicyForNewWindowAction; + policyClient.decidePolicyForMIMEType = decidePolicyForMIMEType; + WKPageSetPagePolicyClient(webView.page(), &policyClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + Util::run(&test1Done); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp new file mode 100644 index 0000000..a88db9f --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp @@ -0,0 +1,134 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +struct JavaScriptCallbackContext { + JavaScriptCallbackContext(const char* expectedString) : didFinish(false), expectedString(expectedString), didMatchExpectedString(false) { } + + bool didFinish; + const char* expectedString; + bool didMatchExpectedString; +}; + +static bool didFinishLoad; +static bool didNotHandleKeyDownEvent; + +static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*) +{ + didFinishLoad = true; +} + +static void didNotHandleKeyEventCallback(WKPageRef, WKNativeEventPtr event, const void*) +{ + if (Util::isKeyDown(event)) + didNotHandleKeyDownEvent = true; +} + +static void javaScriptCallback(WKStringRef string, WKErrorRef error, void* ctx) +{ + JavaScriptCallbackContext* context = static_cast<JavaScriptCallbackContext*>(ctx); + + context->didFinish = true; + context->didMatchExpectedString = WKStringIsEqualToUTF8CString(string, context->expectedString); + + TEST_ASSERT(!error); +} + +static WKRetainPtr<WKStringRef> wk(const char* utf8String) +{ + return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(utf8String)); +} + +static bool runJSTest(WKPageRef page, const char* script, const char* expectedResult) +{ + JavaScriptCallbackContext context(expectedResult); + WKPageRunJavaScriptInMainFrame(page, wk(script).get(), &context, javaScriptCallback); + Util::run(&context.didFinish); + return context.didMatchExpectedString; +} + +TEST(WebKit2, SpacebarScrolling) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + + PlatformWebView webView(pageNamespace.get()); + + WKPageLoaderClient loaderClient; + memset(&loaderClient, 0, sizeof(loaderClient)); + + loaderClient.version = 0; + loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; + WKPageSetPageLoaderClient(webView.page(), &loaderClient); + + WKPageUIClient uiClient; + memset(&uiClient, 0, sizeof(uiClient)); + + uiClient.didNotHandleKeyEvent = didNotHandleKeyEventCallback; + WKPageSetPageUIClient(webView.page(), &uiClient); + + WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("spacebar-scrolling", "html")); + WKPageLoadURL(webView.page(), url.get()); + Util::run(&didFinishLoad); + + TEST_ASSERT(runJSTest(webView.page(), "isDocumentScrolled()", "false")); + TEST_ASSERT(runJSTest(webView.page(), "textFieldContainsSpace()", "false")); + + webView.simulateSpacebarKeyPress(); + + TEST_ASSERT(runJSTest(webView.page(), "isDocumentScrolled()", "false")); + TEST_ASSERT(runJSTest(webView.page(), "textFieldContainsSpace()", "true")); + + // On Mac, a key down event represents both a raw key down and a key press. On Windows, a key + // down event only represents a raw key down. We expect the key press to be handled (because it + // inserts text into the text field). But the raw key down should not be handled. +#if PLATFORM(MAC) + TEST_ASSERT(!didNotHandleKeyDownEvent); +#elif PLATFORM(WIN) + TEST_ASSERT(didNotHandleKeyDownEvent); +#endif + + TEST_ASSERT(runJSTest(webView.page(), "blurTextField()", "undefined")); + + didNotHandleKeyDownEvent = false; + webView.simulateSpacebarKeyPress(); + + TEST_ASSERT(runJSTest(webView.page(), "isDocumentScrolled()", "true")); + TEST_ASSERT(runJSTest(webView.page(), "textFieldContainsSpace()", "true")); +#if PLATFORM(MAC) + TEST_ASSERT(!didNotHandleKeyDownEvent); +#elif PLATFORM(WIN) + TEST_ASSERT(didNotHandleKeyDownEvent); +#endif +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKString.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKString.cpp new file mode 100644 index 0000000..b0b133d --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKString.cpp @@ -0,0 +1,52 @@ +/* + * 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 "Test.h" + +#include <WebKit2/WKString.h> + +namespace TestWebKitAPI { + +TEST(WebKit2, WKString) +{ + WKStringRef string = WKStringCreateWithUTF8CString("hello"); + TEST_ASSERT(!WKStringIsEmpty(string)); + TEST_ASSERT(WKStringIsEqual(string, string)); + TEST_ASSERT(WKStringIsEqualToUTF8CString(string, "hello")); + TEST_ASSERT(WKStringGetMaximumUTF8CStringSize(string) == 16); + + size_t maxSize = WKStringGetMaximumUTF8CStringSize(string); + char* buffer = new char[maxSize]; + + size_t actualSize = WKStringGetUTF8CString(string, buffer, maxSize); + TEST_ASSERT(actualSize == 6); + TEST_ASSERT(strcmp(buffer, "hello") == 0); + + delete[] buffer; + + WKRelease(string); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp new file mode 100644 index 0000000..0d6eca3 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp @@ -0,0 +1,52 @@ +/* + * 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 "Test.h" + +#include <WebKit2/WKString.h> +#include <WebKit2/WKStringPrivate.h> +#include <JavaScriptCore/JSStringRef.h> + +namespace TestWebKitAPI { + +TEST(WebKit2, WKStringJSString) +{ + WKStringRef wkString = WKStringCreateWithUTF8CString("hello"); + JSStringRef jsString = JSStringCreateWithUTF8CString("hello"); + + WKStringRef convertedJSString = WKStringCreateWithJSString(jsString); + TEST_ASSERT(WKStringIsEqual(wkString, convertedJSString)); + + JSStringRef convertedWKString = WKStringCopyJSString(wkString); + TEST_ASSERT(JSStringIsEqual(jsString, convertedWKString)); + + WKRelease(wkString); + WKRelease(convertedJSString); + + JSStringRelease(jsString); + JSStringRelease(convertedWKString); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/find.html b/WebKitTools/TestWebKitAPI/Tests/WebKit2/find.html new file mode 100644 index 0000000..d965911 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/find.html @@ -0,0 +1,5 @@ +<html> +<body> + Test search. Hello Hello Hello! +</body> +</html> diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/icon.png b/WebKitTools/TestWebKitAPI/Tests/WebKit2/icon.png Binary files differnew file mode 100644 index 0000000..79e4598 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/icon.png diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/simple.html b/WebKitTools/TestWebKitAPI/Tests/WebKit2/simple.html new file mode 100644 index 0000000..12cf873 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/simple.html @@ -0,0 +1,5 @@ +<html> +<body> + Simple HTML file. +</body> +</html> diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html b/WebKitTools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html new file mode 100644 index 0000000..8da08b3 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script> + function textFieldContainsSpace() + { + return document.querySelector("input").value === " "; + } + + function blurTextField() + { + document.querySelector("input").blur(); + } + + function isDocumentScrolled() + { + return scrollY !== 0; + } + + function loaded() + { + document.querySelector("input").focus(); + } + + addEventListener("load", loaded); +</script> +<input> +<div style="height: 3000px;"></div> diff --git a/WebKitTools/TestWebKitAPI/Tests/WebKit2/win/AltKeyGeneratesWMSysCommand.cpp b/WebKitTools/TestWebKitAPI/Tests/WebKit2/win/AltKeyGeneratesWMSysCommand.cpp new file mode 100644 index 0000000..c463cf0 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/Tests/WebKit2/win/AltKeyGeneratesWMSysCommand.cpp @@ -0,0 +1,88 @@ +/* + * 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 "Test.h" + +#include "PlatformUtilities.h" +#include "PlatformWebView.h" +#include "WindowMessageObserver.h" +#include <WebKit2/WKRetainPtr.h> + +namespace TestWebKitAPI { + +class WMSysCommandObserver : public WindowMessageObserver { +public: + WMSysCommandObserver() : m_windowDidReceiveWMSysCommand(false) { } + + bool windowDidReceiveWMSysCommand() const { return m_windowDidReceiveWMSysCommand; } + +private: + virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM) + { + if (message == WM_SYSCOMMAND) + m_windowDidReceiveWMSysCommand = true; + } + + bool m_windowDidReceiveWMSysCommand; +}; + +static bool didNotHandleWMSysKeyUp; + +static void didNotHandleKeyEventCallback(WKPageRef, WKNativeEventPtr event, const void*) +{ + if (event->message != WM_SYSKEYUP) + return; + + didNotHandleWMSysKeyUp = true; +} + +TEST(WebKit2, AltKeyGeneratesWMSysCommand) +{ + WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); + WKRetainPtr<WKPageNamespaceRef> pageNamespace(AdoptWK, WKPageNamespaceCreate(context.get())); + + PlatformWebView webView(pageNamespace.get()); + + WKPageUIClient uiClient; + memset(&uiClient, 0, sizeof(uiClient)); + + uiClient.didNotHandleKeyEvent = didNotHandleKeyEventCallback; + WKPageSetPageUIClient(webView.page(), &uiClient); + + WMSysCommandObserver observer; + webView.setParentWindowMessageObserver(&observer); + + webView.simulateAltKeyPress(); + + Util::run(&didNotHandleWMSysKeyUp); + + webView.setParentWindowMessageObserver(0); + + // The WM_SYSKEYUP message should have generated a WM_SYSCOMMAND message that was sent to the + // WKView's parent window. + TEST_ASSERT(observer.windowDidReceiveWMSysCommand()); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/TestsController.cpp b/WebKitTools/TestWebKitAPI/TestsController.cpp new file mode 100644 index 0000000..3499f2c --- /dev/null +++ b/WebKitTools/TestWebKitAPI/TestsController.cpp @@ -0,0 +1,82 @@ +/* + * 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 "TestsController.h" + +#include "Test.h" +#include <algorithm> +#include <assert.h> + +namespace TestWebKitAPI { + +TestsController& TestsController::shared() +{ + static TestsController& shared = *new TestsController; + return shared; +} + +TestsController::TestsController() + : m_testFailed(false) + , m_currentTest(0) +{ +} + +void TestsController::dumpTestNames() +{ + std::map<std::string, CreateTestFunction>::const_iterator it = m_createTestFunctions.begin(); + std::map<std::string, CreateTestFunction>::const_iterator end = m_createTestFunctions.end(); + for (; it != end; ++it) + printf("%s\n", (*it).first.c_str()); +} + +bool TestsController::runTestNamed(const std::string& identifier) +{ + CreateTestFunction createTestFunction = m_createTestFunctions[identifier]; + if (!createTestFunction) { + printf("ERROR: Test not found - %s\n", identifier.c_str()); + return false; + } + + m_currentTest = createTestFunction(identifier); + m_currentTest->run(); + + delete m_currentTest; + m_currentTest = 0; + + return !m_testFailed; +} + +void TestsController::testFailed(const char* file, int line, const char* message) +{ + m_testFailed = true; + printf("FAIL: %s\n\t%s (%s:%d)\n", m_currentTest->name().c_str(), message, file, line); +} + +void TestsController::registerCreateTestFunction(const std::string& identifier, CreateTestFunction createTestFunction) +{ + m_createTestFunctions[identifier] = createTestFunction; +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/TestsController.h b/WebKitTools/TestWebKitAPI/TestsController.h new file mode 100644 index 0000000..0ff1fc7 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/TestsController.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#ifndef TestsController_h +#define TestsController_h + +#include <map> +#include <string> + +namespace TestWebKitAPI { + +class Test; + +class TestsController { +public: + static TestsController& shared(); + + void dumpTestNames(); + bool runTestNamed(const std::string&); + + // Called by the tests themselves. + void testFailed(const char* file, int line, const char* message); + + typedef Test* (*CreateTestFunction)(const std::string&); + void registerCreateTestFunction(const std::string&, CreateTestFunction); + +private: + TestsController(); + ~TestsController(); + + bool m_testFailed; + Test* m_currentTest; + + std::map<std::string, CreateTestFunction> m_createTestFunctions; +}; + +} // namespace TestWebKitAPI + +#endif // TestsController_h diff --git a/WebKitTools/TestWebKitAPI/mac/PlatformUtilitiesMac.mm b/WebKitTools/TestWebKitAPI/mac/PlatformUtilitiesMac.mm new file mode 100644 index 0000000..a9552fd --- /dev/null +++ b/WebKitTools/TestWebKitAPI/mac/PlatformUtilitiesMac.mm @@ -0,0 +1,66 @@ +/* + * 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 "PlatformUtilities.h" + +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WKStringCF.h> +#include <WebKit2/WKURLCF.h> +#include <WebKit2/WebKit2.h> + +namespace TestWebKitAPI { +namespace Util { + +void run(bool* done) +{ + while (!*done) + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; +} + +WKStringRef createInjectedBundlePath() +{ + NSString *nsString = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"InjectedBundle.bundle"]; + return WKStringCreateWithCFString((CFStringRef)nsString); +} + +WKURLRef createURLForResource(const char* resource, const char* extension) +{ + NSURL *nsURL = [[NSBundle mainBundle] URLForResource:[NSString stringWithUTF8String:resource] withExtension:[NSString stringWithUTF8String:extension]]; + return WKURLCreateWithCFURL((CFURLRef)nsURL); +} + +WKURLRef URLForNonExistentResource() +{ + NSURL *nsURL = [NSURL URLWithString:@"file:///does-not-exist.html"]; + return WKURLCreateWithCFURL((CFURLRef)nsURL); +} + +bool isKeyDown(WKNativeEventPtr event) +{ + return [event type] == NSKeyDown; +} + +} // namespace Util +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/mac/PlatformWebViewMac.mm b/WebKitTools/TestWebKitAPI/mac/PlatformWebViewMac.mm new file mode 100644 index 0000000..d4c31eb --- /dev/null +++ b/WebKitTools/TestWebKitAPI/mac/PlatformWebViewMac.mm @@ -0,0 +1,97 @@ +/* + * 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 "PlatformWebView.h" + +#import <Carbon/Carbon.h> + +namespace TestWebKitAPI { + +PlatformWebView::PlatformWebView(WKPageNamespaceRef namespaceRef) +{ + NSRect rect = NSMakeRect(0, 0, 800, 600); + m_view = [[WKView alloc] initWithFrame:rect pageNamespaceRef:namespaceRef]; + + NSRect windowRect = NSOffsetRect(rect, -10000, [[[NSScreen screens] objectAtIndex:0] frame].size.height - rect.size.height + 10000); + m_window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; + [m_window setColorSpace:[[NSScreen mainScreen] colorSpace]]; + [[m_window contentView] addSubview:m_view]; + [m_window orderBack:nil]; + [m_window setAutodisplay:NO]; + [m_window setReleasedWhenClosed:NO]; +} + +void PlatformWebView::resizeTo(unsigned width, unsigned height) +{ + [m_view setFrame:NSMakeRect(0, 0, width, height)]; +} + +PlatformWebView::~PlatformWebView() +{ + [m_window close]; + [m_window release]; + [m_view release]; +} + +WKPageRef PlatformWebView::page() +{ + return [m_view pageRef]; +} + +void PlatformWebView::focus() +{ + // Implement. +} + +void PlatformWebView::simulateSpacebarKeyPress() +{ + NSEvent *event = [NSEvent keyEventWithType:NSKeyDown + location:NSMakePoint(5, 5) + modifierFlags:0 + timestamp:GetCurrentEventTime() + windowNumber:[m_window windowNumber] + context:[NSGraphicsContext currentContext] + characters:@" " + charactersIgnoringModifiers:@" " + isARepeat:NO + keyCode:0x31]; + + [m_view keyDown:event]; + + event = [NSEvent keyEventWithType:NSKeyUp + location:NSMakePoint(5, 5) + modifierFlags:0 + timestamp:GetCurrentEventTime() + windowNumber:[m_window windowNumber] + context:[NSGraphicsContext currentContext] + characters:@" " + charactersIgnoringModifiers:@" " + isARepeat:NO + keyCode:0x31]; + + [m_view keyUp:event]; +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/mac/main.mm b/WebKitTools/TestWebKitAPI/mac/main.mm new file mode 100644 index 0000000..e6dd4a6 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/mac/main.mm @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#import "TestsController.h" + +int main(int argc, const char* argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + [NSApplication sharedApplication]; + + bool passed = true; + + std::string argument(argv[1]); + if (argument == "--dump-tests") + TestWebKitAPI::TestsController::shared().dumpTestNames(); + else + passed = TestWebKitAPI::TestsController::shared().runTestNamed(argument); + + [pool drain]; + + return passed ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/WebKitTools/TestWebKitAPI/win/PlatformUtilitiesWin.cpp b/WebKitTools/TestWebKitAPI/win/PlatformUtilitiesWin.cpp new file mode 100644 index 0000000..17d8dad --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/PlatformUtilitiesWin.cpp @@ -0,0 +1,85 @@ +/* + * 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 "PlatformUtilities.h" + +#include <WebKit2/WKStringCF.h> +#include <WebKit2/WKURLCF.h> +#include <wtf/RetainPtr.h> + +namespace TestWebKitAPI { +namespace Util { + +#if !defined(NDEBUG) && (!defined(DEBUG_INTERNAL) || defined(DEBUG_ALL)) +const char* injectedBundleDLL = "\\InjectedBundle_debug.dll"; +#else +const char* injectedBundleDLL = "\\InjectedBundle.dll"; +#endif + +void run(bool* done) +{ + while (!*done) { + MSG msg; + BOOL result = ::GetMessageW(&msg, 0, 0, 0); + if (!result || result == -1) + break; + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } +} + +RetainPtr<CFStringRef> cf(const char* utf8String) +{ + return RetainPtr<CFStringRef>(AdoptCF, CFStringCreateWithCString(kCFAllocatorDefault, utf8String, kCFStringEncodingUTF8)); +} + +WKStringRef createInjectedBundlePath() +{ + RetainPtr<CFURLRef> executableURL(AdoptCF, CFBundleCopyExecutableURL(CFBundleGetMainBundle())); + RetainPtr<CFURLRef> executableContainerURL(AdoptCF, CFURLCreateCopyDeletingLastPathComponent(0, executableURL.get())); + RetainPtr<CFStringRef> dllFilename(AdoptCF, CFStringCreateWithCStringNoCopy(0, injectedBundleDLL, kCFStringEncodingWindowsLatin1, 0)); + RetainPtr<CFURLRef> bundleURL(AdoptCF, CFURLCreateCopyAppendingPathComponent(0, executableContainerURL.get(), dllFilename.get(), false)); + RetainPtr<CFStringRef> bundlePath(AdoptCF, CFURLCopyFileSystemPath(bundleURL.get(), kCFURLWindowsPathStyle)); + return WKStringCreateWithCFString(bundlePath.get()); +} + +WKURLRef createURLForResource(const char* resource, const char* extension) +{ + RetainPtr<CFURLRef> url(AdoptCF, CFBundleCopyResourceURL(CFBundleGetMainBundle(), cf(resource).get(), cf(extension).get(), 0)); + return WKURLCreateWithCFURL(url.get()); +} + +WKURLRef URLForNonExistentResource() +{ + return WKURLCreateWithUTF8CString("file:///does-not-exist.html"); +} + +bool isKeyDown(WKNativeEventPtr event) +{ + return event->message == WM_KEYDOWN; +} + +} // namespace Util +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/win/PlatformWebViewWin.cpp b/WebKitTools/TestWebKitAPI/win/PlatformWebViewWin.cpp new file mode 100644 index 0000000..65bdbc6 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/PlatformWebViewWin.cpp @@ -0,0 +1,118 @@ +/* + * 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 "PlatformWebView.h" + +#include "WindowMessageObserver.h" + +namespace TestWebKitAPI { + +static const wchar_t* hostWindowClassName = L"org.WebKit.TestWebKitAPI.PlatformWebViewHostWindow"; +static const wchar_t* webViewPointerProperty = L"org.WebKit.TestWebKitAPI.PlatformWebView.InstancePointer"; + +// These offsets come from rom <http://msdn.microsoft.com/en-us/library/ms646280(VS.85).aspx>. +static const size_t repeatCountBitOffset = 0; +static const size_t scanCodeBitOffset = 16; +static const size_t contextCodeBitOffset = 29; +static const size_t previousStateBitOffset = 30; +static const size_t transitionStateBitOffset = 31; + +void PlatformWebView::registerWindowClass() +{ + static bool initialized; + if (initialized) + return; + initialized = true; + + WNDCLASSEXW wndClass = {0}; + wndClass.cbSize = sizeof(wndClass); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = wndProc; + wndClass.hCursor = LoadCursor(0, IDC_ARROW); + wndClass.lpszClassName = hostWindowClassName; + + ::RegisterClassExW(&wndClass); +} + +PlatformWebView::PlatformWebView(WKPageNamespaceRef namespaceRef) + : m_parentWindowMessageObserver(0) +{ + registerWindowClass(); + + RECT viewRect = {0, 0, 800, 600}; + m_window = CreateWindowExW(0, hostWindowClassName, L"TestWebKitAPI", WS_OVERLAPPEDWINDOW, viewRect.left, viewRect.top, viewRect.right, viewRect.bottom, 0, 0, 0, this); + m_view = WKViewCreate(viewRect, namespaceRef, m_window); +} + +PlatformWebView::~PlatformWebView() +{ + ::DestroyWindow(m_window); + WKRelease(m_view); +} + +WKPageRef PlatformWebView::page() +{ + return WKViewGetPage(m_view); +} + +void PlatformWebView::simulateSpacebarKeyPress() +{ + HWND window = WKViewGetWindow(m_view); + + // These values match what happens when you press the spacebar in Notepad, as observed by Spy++. + ::SendMessageW(window, WM_KEYDOWN, VK_SPACE, (1 << repeatCountBitOffset) | (39 << scanCodeBitOffset)); + ::SendMessageW(window, WM_CHAR, ' ', (1 << repeatCountBitOffset) | (39 << scanCodeBitOffset)); + ::SendMessageW(window, WM_KEYUP, VK_SPACE, (1 << repeatCountBitOffset) | (39 << scanCodeBitOffset) | (1 << previousStateBitOffset) | (1 << transitionStateBitOffset)); +} + +void PlatformWebView::simulateAltKeyPress() +{ + HWND window = WKViewGetWindow(m_view); + + // These values match what happens when you press the Alt key in Notepad, as observed by Spy++. + ::SendMessageW(window, WM_SYSKEYDOWN, VK_MENU, (1 << repeatCountBitOffset) | (38 << scanCodeBitOffset) | (1 << contextCodeBitOffset)); + ::SendMessageW(window, WM_SYSKEYUP, VK_MENU, (1 << repeatCountBitOffset) | (38 << scanCodeBitOffset) | (1 << previousStateBitOffset) | (1 << transitionStateBitOffset)); +} + +LRESULT PlatformWebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PlatformWebView* webView; + if (message == WM_CREATE) { + CREATESTRUCT* createStruct = reinterpret_cast<CREATESTRUCT*>(lParam); + webView = static_cast<PlatformWebView*>(createStruct->lpCreateParams); + ::SetPropW(hWnd, webViewPointerProperty, webView); + } else + webView = reinterpret_cast<PlatformWebView*>(::GetPropW(hWnd, webViewPointerProperty)); + + if (webView && webView->m_parentWindowMessageObserver) + webView->m_parentWindowMessageObserver->windowReceivedMessage(hWnd, message, wParam, lParam); + + if (message == WM_NCDESTROY) + ::RemovePropW(hWnd, webViewPointerProperty); + + return ::DefWindowProcW(hWnd, message, wParam, lParam); +} + +} // namespace TestWebKitAPI diff --git a/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.sln b/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.sln new file mode 100644 index 0000000..e323372 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.sln @@ -0,0 +1,54 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestWebKitAPI", "TestWebKitAPI.vcproj", "{3E48AB23-D249-488F-A1C4-43CDF52FBD28}"
+ ProjectSection(ProjectDependencies) = postProject
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86} = {45C45411-7F0E-404D-919A-4EE9BB60BE86}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestWebKitAPIGenerated", "TestWebKitAPIGenerated.vcproj", "{45C45411-7F0E-404D-919A-4EE9BB60BE86}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ all|Win32 = all|Win32
+ Debug_All|Win32 = Debug_All|Win32
+ Debug_CFLite|Win32 = Debug_CFLite|Win32
+ Debug_Internal|Win32 = Debug_Internal|Win32
+ Debug|Win32 = Debug|Win32
+ Release_CFLite|Win32 = Release_CFLite|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.all|Win32.ActiveCfg = Release_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.all|Win32.Build.0 = Release_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_CFLite|Win32.ActiveCfg = Debug_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_CFLite|Win32.Build.0 = Debug_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_Internal|Win32.ActiveCfg = Debug_Internal|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug_Internal|Win32.Build.0 = Debug_Internal|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Debug|Win32.Build.0 = Debug|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Release_CFLite|Win32.ActiveCfg = Release_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Release_CFLite|Win32.Build.0 = Release_CFLite|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Release|Win32.ActiveCfg = Release|Win32
+ {3E48AB23-D249-488F-A1C4-43CDF52FBD28}.Release|Win32.Build.0 = Release|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.all|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.all|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_All|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_All|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_CFLite|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_CFLite|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_Internal|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug_Internal|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Debug|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Release_CFLite|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Release_CFLite|Win32.Build.0 = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Release|Win32.ActiveCfg = all|Win32
+ {45C45411-7F0E-404D-919A-4EE9BB60BE86}.Release|Win32.Build.0 = all|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.vcproj b/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.vcproj new file mode 100644 index 0000000..44bf963 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/TestWebKitAPI.vcproj @@ -0,0 +1,516 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPI"
+ ProjectGUID="{3E48AB23-D249-488F-A1C4-43CDF52FBD28}"
+ RootNamespace="TestWebKitAPI"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICoreFoundation.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|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICoreFoundation.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>
+ <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\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICoreFoundation.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="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\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICoreFoundation.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="Debug_CFLite|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_wincairo.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICFLite.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="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICFLite.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>
+ <Files>
+ <Filter
+ Name="win"
+ >
+ <File
+ RelativePath=".\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\PlatformUtilitiesWin.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\PlatformWebViewWin.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\WindowMessageObserver.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Tests"
+ >
+ <Filter
+ Name="WebKit2"
+ >
+ <File
+ RelativePath="..\Tests\WebKit2\FailedLoad.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\Find.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\find.html"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\FrameMIMETypeHTML.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\FrameMIMETypePNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\icon.png"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\PageLoadBasic.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\simple.html"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\spacebar-scrolling.html"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\SpacebarScrolling.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\WKString.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Tests\WebKit2\WKStringJSString.cpp"
+ >
+ </File>
+ <Filter
+ Name="win"
+ >
+ <File
+ RelativePath="..\Tests\WebKit2\win\AltKeyGeneratesWMSysCommand.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="WTF"
+ >
+ <File
+ RelativePath="..\Tests\WTF\VectorBasic.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <File
+ RelativePath="..\PlatformUtilities.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\PlatformUtilities.h"
+ >
+ </File>
+ <File
+ RelativePath="..\PlatformWebView.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Test.h"
+ >
+ </File>
+ <File
+ RelativePath="..\TestsController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\TestsController.h"
+ >
+ </File>
+ <File
+ RelativePath="..\TestWebKitAPIPrefix.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/TestWebKitAPI/win/TestWebKitAPIGenerated.vcproj b/WebKitTools/TestWebKitAPI/win/TestWebKitAPIGenerated.vcproj new file mode 100644 index 0000000..ce5afeb --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/TestWebKitAPIGenerated.vcproj @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIGenerated"
+ ProjectGUID="{45C45411-7F0E-404D-919A-4EE9BB60BE86}"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="all|Win32"
+ ConfigurationType="0"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="copy-resources.cmd"
+ ReBuildCommandLine="copy-resources.cmd rebuild"
+ CleanCommandLine="copy-resources.cmd clean"
+ Output=""
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\copy-resources.cmd"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/TestWebKitAPI/win/WindowMessageObserver.h b/WebKitTools/TestWebKitAPI/win/WindowMessageObserver.h new file mode 100644 index 0000000..3388816 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/WindowMessageObserver.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef WindowMessageObserver_h +#define WindowMessageObserver_h + +namespace TestWebKitAPI { + +class WindowMessageObserver { +public: + virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM) = 0; + +protected: + virtual ~WindowMessageObserver() { } +}; + +} // namespace TestWebKitAPI + +#endif // WindowMessageObserver_h diff --git a/WebKitTools/TestWebKitAPI/win/copy-resources.cmd b/WebKitTools/TestWebKitAPI/win/copy-resources.cmd new file mode 100755 index 0000000..a5b8406 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/copy-resources.cmd @@ -0,0 +1,24 @@ +@echo off + +set ResourcesDirectory=%WebKitOutputDir%\bin\TestWebKitAPI.resources + +if "%1" EQU "clean" goto :clean +if "%1" EQU "rebuild" call :clean + +echo Copying resources... +mkdir 2>NUL "%ResourcesDirectory%" +for %%f in ( + ..\Tests\WebKit2\find.html + ..\Tests\WebKit2\icon.png + ..\Tests\WebKit2\simple.html + ..\Tests\WebKit2\spacebar-scrolling.html +) do ( + xcopy /y /d %%f "%ResourcesDirectory%" +) + +goto :EOF + +:clean + +echo Deleting resources... +del /s /q "%ResourcesDirectory%" diff --git a/WebKitTools/TestWebKitAPI/win/main.cpp b/WebKitTools/TestWebKitAPI/win/main.cpp new file mode 100644 index 0000000..3091819 --- /dev/null +++ b/WebKitTools/TestWebKitAPI/win/main.cpp @@ -0,0 +1,39 @@ +/* + * 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 "TestsController.h" + +int main(int argc, const char* argv[]) +{ + bool passed = true; + + std::string argument(argv[1]); + if (argument == "--dump-tests") + TestWebKitAPI::TestsController::shared().dumpTestNames(); + else + passed = TestWebKitAPI::TestsController::shared().runTestNamed(argument); + + return passed ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/WebKitTools/WebKitTestRunner/Configurations/Base.xcconfig b/WebKitTools/WebKitTestRunner/Configurations/Base.xcconfig index 7ceab07..feabe9a 100644 --- a/WebKitTools/WebKitTestRunner/Configurations/Base.xcconfig +++ b/WebKitTools/WebKitTestRunner/Configurations/Base.xcconfig @@ -21,7 +21,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. -HEADER_SEARCH_PATHS = ForwardingHeaders; +HEADER_SEARCH_PATHS = $(WEBCORE_PRIVATE_HEADERS_DIR)/ForwardingHeaders; FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks; GCC_PREPROCESSOR_DEFINITIONS = ENABLE_DASHBOARD_SUPPORT WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST; DEBUG_INFORMATION_FORMAT = dwarf diff --git a/WebKitTools/WebKitTestRunner/DerivedSources.pro b/WebKitTools/WebKitTestRunner/DerivedSources.pro new file mode 100644 index 0000000..bab70cc --- /dev/null +++ b/WebKitTools/WebKitTestRunner/DerivedSources.pro @@ -0,0 +1,57 @@ +# DerivedSources - qmake build info + +CONFIG -= debug_and_release + +TEMPLATE = lib +TARGET = dummy + +QMAKE_EXTRA_TARGETS += generated_files + +GENERATED_SOURCES_DIR = generated + +IDL_BINDINGS += \ + InjectedBundle/Bindings/EventSendingController.idl \ + InjectedBundle/Bindings/GCController.idl \ + InjectedBundle/Bindings/LayoutTestController.idl \ + +defineTest(addExtraCompiler) { + eval($${1}.CONFIG = target_predeps no_link) + eval($${1}.variable_out =) + eval($${1}.dependency_type = TYPE_C) + + wkScript = $$eval($${1}.wkScript) + eval($${1}.depends += $$wkScript) + + export($${1}.CONFIG) + export($${1}.variable_out) + export($${1}.dependency_type) + export($${1}.depends) + + QMAKE_EXTRA_COMPILERS += $$1 + generated_files.depends += compiler_$${1}_make_all + export(QMAKE_EXTRA_COMPILERS) + export(generated_files.depends) + return(true) +} + +SRC_ROOT_DIR = $$replace(PWD, /WebKitTools/WebKitTestRunner, /) + +# Make sure forwarded headers needed by this project are present +fwheader_generator.commands = perl $${SRC_ROOT_DIR}/WebKitTools/Scripts/generate-forwarding-headers.pl $${SRC_ROOT_DIR}/WebKitTools/WebKitTestRunner $${OUTPUT_DIR}/include qt +fwheader_generator.depends = $${SRC_ROOT_DIR}/WebKitTools/Scripts/generate-forwarding-headers.pl +generated_files.depends += fwheader_generator +QMAKE_EXTRA_TARGETS += fwheader_generator + +# GENERATOR 1: IDL compiler +idl.output = $${GENERATED_SOURCES_DIR}/JS${QMAKE_FILE_BASE}.cpp +idl.input = IDL_BINDINGS +idl.wkScript = $$PWD/../../WebCore/bindings/scripts/generate-bindings.pl +idl.commands = perl -I$$PWD/../../WebCore/bindings/scripts -I$$PWD/InjectedBundle/Bindings $$idl.wkScript --defines \"\" --generator TestRunner --include $$PWD/InjectedBundle/Bindings --outputDir $$GENERATED_SOURCES_DIR --preprocessor \"$${QMAKE_MOC} -E\" ${QMAKE_FILE_NAME} +idl.depends = $$PWD/../../WebCore/bindings/scripts/CodeGenerator.pm \ + $$PWD/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm \ + $$PWD/../../WebCore/bindings/scripts/IDLParser.pm \ + $$PWD/../../WebCore/bindings/scripts/IDLStructure.pm \ + $$PWD/../../WebCore/bindings/scripts/InFilesParser.pm \ + $$PWD/../../WebCore/bindings/scripts/generate-bindings.pl +addExtraCompiler(idl) + diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ASCIICType.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ASCIICType.h deleted file mode 100644 index f2258d2..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ASCIICType.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/ASCIICType.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Assertions.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Assertions.h deleted file mode 100644 index 2144410..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Assertions.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Assertions.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Atomics.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Atomics.h deleted file mode 100644 index 37b1892..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Atomics.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Atomics.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/FastMalloc.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/FastMalloc.h deleted file mode 100644 index 1701231..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/FastMalloc.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/FastMalloc.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/GetPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/GetPtr.h deleted file mode 100644 index aedd784..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/GetPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/GetPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashMap.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashMap.h deleted file mode 100644 index 9f262e2..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashMap.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/HashMap.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashSet.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashSet.h deleted file mode 100644 index cfe2d80..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashSet.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/HashSet.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashTraits.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashTraits.h deleted file mode 100644 index 412fa98..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/HashTraits.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/HashTraits.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Locker.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Locker.h deleted file mode 100644 index 75b0acd..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Locker.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Locker.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MainThread.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MainThread.h deleted file mode 100644 index ff75971..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MainThread.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/MainThread.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MathExtras.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MathExtras.h deleted file mode 100644 index 2955786..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/MathExtras.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/MathExtras.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Noncopyable.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Noncopyable.h deleted file mode 100644 index f8484d2..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Noncopyable.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Noncopyable.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtr.h deleted file mode 100644 index 9211d38..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/OwnPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtrCommon.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtrCommon.h deleted file mode 100644 index 6064e88..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/OwnPtrCommon.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/PassOwnPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassOwnPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassOwnPtr.h deleted file mode 100644 index 6064e88..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassOwnPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/PassOwnPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassRefPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassRefPtr.h deleted file mode 100644 index aafd1a2..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/PassRefPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/PassRefPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Platform.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Platform.h deleted file mode 100644 index 3b22955..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Platform.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Platform.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefCounted.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefCounted.h deleted file mode 100644 index 628a63b..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefCounted.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/RefCounted.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefPtr.h deleted file mode 100644 index 0ff6213..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RefPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/RefPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RetainPtr.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RetainPtr.h deleted file mode 100644 index 65fc27b..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/RetainPtr.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/RetainPtr.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/StringExtras.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/StringExtras.h deleted file mode 100644 index 063d500..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/StringExtras.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/StringExtras.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadSafeShared.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadSafeShared.h deleted file mode 100644 index 4a7a77f..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadSafeShared.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/ThreadSafeShared.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Threading.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Threading.h deleted file mode 100644 index 17359e5..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Threading.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Threading.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadingPrimitives.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadingPrimitives.h deleted file mode 100644 index a7ee117..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/ThreadingPrimitives.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/ThreadingPrimitives.h> diff --git a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Vector.h b/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Vector.h deleted file mode 100644 index c6d15fd..0000000 --- a/WebKitTools/WebKitTestRunner/ForwardingHeaders/wtf/Vector.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/Vector.h> diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h index 9cb97af..5ec7197 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h @@ -26,7 +26,7 @@ #ifndef JSWrappable_h #define JSWrappable_h -#include <JavaScriptCore/JavaScriptCore.h> +#include <JavaScriptCore/JavaScript.h> #include <wtf/RefCounted.h> namespace WTR { diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp index ecc302f..af8bb69 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp @@ -32,10 +32,8 @@ #include <WebKit2/WKBundlePagePrivate.h> #include <WebKit2/WKBundlePrivate.h> #include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKStringCF.h> #include <WebKit2/WebKit2.h> #include <wtf/PassOwnPtr.h> -#include <wtf/RetainPtr.h> #include <wtf/Vector.h> namespace WTR { @@ -105,18 +103,19 @@ void InjectedBundle::willDestroyPage(WKBundlePageRef page) void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody) { - CFStringRef cfMessage = WKStringCopyCFString(0, messageName); - if (CFEqual(cfMessage, CFSTR("BeginTest"))) { - WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithCFString(CFSTR("Ack"))); - WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithCFString(CFSTR("BeginTest"))); + if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) { + ASSERT(!messageBody); + + WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack")); + WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest")); WKBundlePostMessage(m_bundle, ackMessageName.get(), ackMessageBody.get()); beginTesting(); return; } - WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithCFString(CFSTR("Error"))); - WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithCFString(CFSTR("Unknown"))); + WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); + WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown")); WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get()); } @@ -140,13 +139,12 @@ void InjectedBundle::beginTesting() void InjectedBundle::done() { - m_mainPage->stopLoading(); + m_state = Stopping; - WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithCFString(CFSTR("Done"))); + m_mainPage->stopLoading(); - std::string output = m_outputStream.str(); - RetainPtr<CFStringRef> outputCFString(AdoptCF, CFStringCreateWithCString(0, output.c_str(), kCFStringEncodingUTF8)); - WKRetainPtr<WKStringRef> doneMessageBody(AdoptWK, WKStringCreateWithCFString(outputCFString.get())); + WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done")); + WKRetainPtr<WKStringRef> doneMessageBody(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str())); WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get()); diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h index 520ea1f..6c5c69e 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h @@ -88,7 +88,8 @@ private: enum State { Idle, - Testing + Testing, + Stopping }; State m_state; }; diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp index 32b92cb..22af6ff 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp @@ -27,6 +27,7 @@ #include "InjectedBundle.h" #include "StringFunctions.h" +#include <cmath> #include <JavaScriptCore/JSRetainPtr.h> #include <WebKit2/WKArray.h> #include <WebKit2/WKBundleFrame.h> @@ -240,9 +241,9 @@ void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBu static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame); } -void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) +void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo) { - static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame); + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame, error); } void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) @@ -260,9 +261,9 @@ void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKB static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame); } -void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) +void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef error, WKTypeRef*, const void *clientInfo) { - static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame); + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame, error); } void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo) @@ -319,7 +320,7 @@ void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBu { } -void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame) +void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef error) { } @@ -433,7 +434,7 @@ void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame) dump(); } -void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame) +void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef) { if (!InjectedBundle::shared().isTestRunning()) return; diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h index c814c85..737ad18 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h @@ -49,11 +49,11 @@ private: // Loader Client static void didStartProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); static void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); - static void didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); + static void didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*, const void*); static void didCommitLoadForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); static void didFinishLoadForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); static void didFinishDocumentLoadForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); - static void didFailLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, WKTypeRef*, const void*); + static void didFailLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, WKErrorRef, WKTypeRef*, const void*); static void didReceiveTitleForFrame(WKBundlePageRef, WKStringRef title, WKBundleFrameRef, WKTypeRef*, const void*); static void didClearWindowForFrame(WKBundlePageRef, WKBundleFrameRef, WKBundleScriptWorldRef, const void*); static void didCancelClientRedirectForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); @@ -64,10 +64,10 @@ private: static void didRunInsecureContentForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); void didStartProvisionalLoadForFrame(WKBundleFrameRef); void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef); - void didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef); + void didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef, WKErrorRef); void didCommitLoadForFrame(WKBundleFrameRef); void didFinishLoadForFrame(WKBundleFrameRef); - void didFailLoadWithErrorForFrame(WKBundleFrameRef); + void didFailLoadWithErrorForFrame(WKBundleFrameRef, WKErrorRef); void didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef); void didClearWindowForFrame(WKBundleFrameRef, WKBundleScriptWorldRef); void didCancelClientRedirectForFrame(WKBundleFrameRef); diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h index 6ae20d8..c892ba0 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h @@ -28,9 +28,18 @@ #include "JSWrappable.h" #include <JavaScriptCore/JSRetainPtr.h> +#include <string> #include <wtf/PassRefPtr.h> + +#if PLATFORM(MAC) #include <wtf/RetainPtr.h> -#include <string> +typedef RetainPtr<CFRunLoopTimerRef> PlatformTimerRef; +#elif PLATFORM(WIN) +typedef UINT_PTR PlatformTimerRef; +#elif PLATFORM(QT) +#include <QTimer> +typedef QTimer PlatformTimerRef; +#endif namespace WTR { @@ -124,11 +133,7 @@ private: bool m_testRepaint; bool m_testRepaintSweepHorizontally; -#if PLATFORM(MAC) - RetainPtr<CFRunLoopTimerRef> m_waitToDumpWatchdogTimer; -#elif PLATFORM(WIN) - UINT_PTR m_waitToDumpWatchdogTimer; -#endif + PlatformTimerRef m_waitToDumpWatchdogTimer; }; } // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/qt/ActivateFontsQt.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/ActivateFontsQt.cpp new file mode 100644 index 0000000..ec920dc --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/ActivateFontsQt.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ActivateFonts.h" + +#include <QByteArray> +#include <QDir> + +#ifdef Q_WS_X11 +#include <fontconfig/fontconfig.h> +#endif + +#include <limits.h> + +namespace WTR { + +void activateFonts() +{ +#if defined(Q_WS_X11) + static int numFonts = -1; + + // Some test cases may add or remove application fonts (via @font-face). + // Make sure to re-initialize the font set if necessary. + FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication); + if (appFontSet && numFonts >= 0 && appFontSet->nfont == numFonts) + return; + + QByteArray fontDir = getenv("WEBKIT_TESTFONTS"); + if (fontDir.isEmpty() || !QDir(fontDir).exists()) { + fprintf(stderr, + "\n\n" + "----------------------------------------------------------------------\n" + "WEBKIT_TESTFONTS environment variable is not set correctly.\n" + "This variable has to point to the directory containing the fonts\n" + "you can clone from git://gitorious.org/qtwebkit/testfonts.git\n" + "----------------------------------------------------------------------\n" + ); + exit(1); + } + char currentPath[PATH_MAX+1]; + if (!getcwd(currentPath, PATH_MAX)) + qFatal("Couldn't get current working directory"); + QByteArray configFile = currentPath; + FcConfig* config = FcConfigCreate(); + configFile += "/WebKitTools/DumpRenderTree/qt/fonts.conf"; + if (!FcConfigParseAndLoad (config, (FcChar8*) configFile.data(), true)) + qFatal("Couldn't load font configuration file"); + if (!FcConfigAppFontAddDir (config, (FcChar8*) fontDir.data())) + qFatal("Couldn't add font dir!"); + FcConfigSetCurrent(config); + + appFontSet = FcConfigGetFonts(config, FcSetApplication); + numFonts = appFontSet->nfont; +#endif +} + +} diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro new file mode 100644 index 0000000..d596f33 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro @@ -0,0 +1,69 @@ +TEMPLATE = lib + +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. + +SOURCES += \ + ../InjectedBundle.cpp \ + ../InjectedBundle.h \ + ../InjectedBundleMain.cpp \ + ../InjectedBundlePage.cpp \ + ../InjectedBundlePage.h \ + ../EventSendingController.cpp \ + ../EventSendingController.h \ + ../GCController.cpp \ + ../GCController.h \ + ../LayoutTestController.cpp \ + ../LayoutTestController.h \ + ../Bindings/JSWrapper.cpp \ + ActivateFontsQt.cpp \ + LayoutTestControllerQt.cpp \ + $$OUTPUT_DIR/WebKitTools/WebKitTestRunner/generated/JSEventSendingController.cpp \ + $$OUTPUT_DIR/WebKitTools/WebKitTestRunner/generated/JSGCController.cpp \ + $$OUTPUT_DIR/WebKitTools/WebKitTestRunner/generated/JSLayoutTestController.cpp \ + +HEADERS += \ + ../ActivateFonts.h \ + ../EventSendingController.h \ + ../GCController.h \ + ../InjectedBundle.h \ + ../InjectedBundlePage.h \ + ../LayoutTestController.h \ + +!CONFIG(release, debug|release) { + OBJECTS_DIR = obj/debug +} else { # Release + OBJECTS_DIR = obj/release +} + +include(../../../../WebKit.pri) +include(../../../../JavaScriptCore/JavaScriptCore.pri) +addJavaScriptCoreLib(../../../../JavaScriptCore) +include(../../../../WebKit2/WebKit2.pri) +addWebKit2Lib(../../../../WebKit2) + +INCLUDEPATH += \ + $$PWD \ + $$PWD/.. \ + $$PWD/../.. \ + $$PWD/../Bindings \ + $$PWD/../../../../JavaScriptCore \ + $$PWD/../../../../JavaScriptCore/wtf \ + $$PWD/../../../../WebKit2 \ + $$PWD/../../../../WebKit2/Shared \ + $$OUTPUT_DIR/WebKitTools/WebKitTestRunner/generated + +INCLUDEPATH += \ + $$OUTPUT_DIR/include \ + $$OUTPUT_DIR/WebCore/generated + +PREFIX_HEADER = $$PWD/../../WebKitTestRunnerPrefix.h +QMAKE_CXXFLAGS += "-include $$PREFIX_HEADER" + +unix:!mac { + CONFIG += link_pkgconfig + PKGCONFIG += fontconfig +} + +TARGET = WTRInjectedBundle +DESTDIR = $$OUTPUT_DIR/lib +!CONFIG(standalone_package): CONFIG -= app_bundle diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/qt/LayoutTestControllerQt.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/LayoutTestControllerQt.cpp new file mode 100644 index 0000000..b515326 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/qt/LayoutTestControllerQt.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged. 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 "LayoutTestController.h" + +#include "InjectedBundle.h" +#include <QObject> + +namespace WTR { + +class WatchdogTimerHelper : public QObject { + Q_OBJECT + +public: + static WatchdogTimerHelper* instance() + { + static WatchdogTimerHelper* theInstance = new WatchdogTimerHelper; + return theInstance; + } + +public slots: + void timerFired() + { + InjectedBundle::shared().layoutTestController()->waitToDumpWatchdogTimerFired(); + } + +private: + WatchdogTimerHelper() {} +}; + +void LayoutTestController::platformInitialize() +{ + QObject::connect(&m_waitToDumpWatchdogTimer, SIGNAL(timeout()), WatchdogTimerHelper::instance(), SLOT(timerFired())); +} + +void LayoutTestController::invalidateWaitToDumpWatchdogTimer() +{ + m_waitToDumpWatchdogTimer.stop(); +} + +void LayoutTestController::initializeWaitToDumpWatchdogTimerIfNeeded() +{ + if (m_waitToDumpWatchdogTimer.isActive()) + return; + + m_waitToDumpWatchdogTimer.start(waitToDumpWatchdogTimerInterval * 1000); +} + +} // namespace WTR + +#include "LayoutTestControllerQt.moc" diff --git a/WebKitTools/WebKitTestRunner/PlatformWebView.h b/WebKitTools/WebKitTestRunner/PlatformWebView.h index 29c63ae..72de868 100644 --- a/WebKitTools/WebKitTestRunner/PlatformWebView.h +++ b/WebKitTools/WebKitTestRunner/PlatformWebView.h @@ -26,7 +26,14 @@ #ifndef PlatformWebView_h #define PlatformWebView_h -#if __APPLE__ +#if defined(BUILDING_QT__) +namespace WTR { +class WebView; +} +typedef WTR::WebView* PlatformWKView; +class QMainWindow; +typedef QMainWindow* PlatformWindow; +#elif defined(__APPLE__) && __APPLE__ #if __OBJC__ @class WKView; @class NSWindow; @@ -53,6 +60,9 @@ public: void resizeTo(unsigned width, unsigned height); void focus(); + WKRect windowFrame(); + void setWindowFrame(WKRect); + private: PlatformWKView m_view; PlatformWindow m_window; diff --git a/WebKitTools/WebKitTestRunner/StringFunctions.h b/WebKitTools/WebKitTestRunner/StringFunctions.h index 8195606..2d0ca72 100644 --- a/WebKitTools/WebKitTestRunner/StringFunctions.h +++ b/WebKitTools/WebKitTestRunner/StringFunctions.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,54 +28,35 @@ #define StringFunctions_h #include <JavaScriptCore/JSRetainPtr.h> -#include <JavaScriptCore/JavaScriptCore.h> +#include <JavaScriptCore/JavaScript.h> +#include <sstream> +#include <string> #include <WebKit2/WKRetainPtr.h> #include <WebKit2/WKString.h> -#include <WebKit2/WKStringCF.h> +#include <WebKit2/WKStringPrivate.h> #include <WebKit2/WKURL.h> -#include <WebKit2/WKURLCF.h> -#include <sstream> +#include <wtf/OwnArrayPtr.h> +#include <wtf/PassOwnArrayPtr.h> #include <wtf/Platform.h> -#include <wtf/RetainPtr.h> #include <wtf/Vector.h> namespace WTR { // Conversion functions -inline RetainPtr<CFStringRef> toCF(JSStringRef string) -{ - return RetainPtr<CFStringRef>(AdoptCF, JSStringCopyCFString(0, string)); -} - -inline RetainPtr<CFStringRef> toCF(WKStringRef string) -{ - return RetainPtr<CFStringRef>(AdoptCF, WKStringCopyCFString(0, string)); -} - -inline RetainPtr<CFURLRef> toCF(WKURLRef url) -{ - return RetainPtr<CFURLRef>(AdoptCF, WKURLCopyCFURL(0, url)); -} - -inline RetainPtr<CFURLRef> toCF(const WKRetainPtr<WKURLRef>& url) -{ - return toCF(url.get()); -} - inline WKRetainPtr<WKStringRef> toWK(JSStringRef string) { - return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithCFString(toCF(string).get())); + return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithJSString(string)); } inline WKRetainPtr<WKStringRef> toWK(JSRetainPtr<JSStringRef> string) { - return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithCFString(toCF(string.get()).get())); + return toWK(string.get()); } inline JSRetainPtr<JSStringRef> toJS(WKStringRef string) { - return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCFString(toCF(string).get())); + return JSRetainPtr<JSStringRef>(Adopt, WKStringCopyJSString(string)); } inline JSRetainPtr<JSStringRef> toJS(const WKRetainPtr<WKStringRef>& string) @@ -82,29 +64,27 @@ inline JSRetainPtr<JSStringRef> toJS(const WKRetainPtr<WKStringRef>& string) return toJS(string.get()); } -// Streaming functions - -inline std::ostream& operator<<(std::ostream& out, CFStringRef stringRef) +inline std::string toSTD(WKStringRef string) { - if (!stringRef) - return out; - CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef), kCFStringEncodingUTF8) + 1; - Vector<char> buffer(bufferLength); - if (!CFStringGetCString(stringRef, buffer.data(), bufferLength, kCFStringEncodingUTF8)) - return out; - return out << buffer.data(); + size_t bufferSize = WKStringGetMaximumUTF8CStringSize(string); + OwnArrayPtr<char> buffer = adoptArrayPtr(new char[bufferSize]); + size_t stringLength = WKStringGetUTF8CString(string, buffer.get(), bufferSize); + return std::string(buffer.get(), stringLength - 1); } -inline std::ostream& operator<<(std::ostream& out, const RetainPtr<CFStringRef>& stringRef) +inline std::string toSTD(const WKRetainPtr<WKStringRef>& string) { - return out << stringRef.get(); + return toSTD(string.get()); } +// Streaming functions + inline std::ostream& operator<<(std::ostream& out, WKStringRef stringRef) { if (!stringRef) return out; - return out << toCF(stringRef); + + return out << toSTD(stringRef); } inline std::ostream& operator<<(std::ostream& out, const WKRetainPtr<WKStringRef>& stringRef) @@ -112,24 +92,6 @@ inline std::ostream& operator<<(std::ostream& out, const WKRetainPtr<WKStringRef return out << stringRef.get(); } -// URL creation - -inline WKURLRef createWKURL(const char* pathOrURL) -{ - RetainPtr<CFStringRef> pathOrURLCFString(AdoptCF, CFStringCreateWithCString(0, pathOrURL, kCFStringEncodingUTF8)); - RetainPtr<CFURLRef> cfURL; - if (CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("http://")) || CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("https://"))) - cfURL.adoptCF(CFURLCreateWithString(0, pathOrURLCFString.get(), 0)); - else -#if PLATFORM(WIN) - cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLWindowsPathStyle, false)); -#else - cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLPOSIXPathStyle, false)); -#endif - return WKURLCreateWithCFURL(cfURL.get()); -} - - } // namespace WTR #endif // StringFunctions_h diff --git a/WebKitTools/WebKitTestRunner/TestController.cpp b/WebKitTools/WebKitTestRunner/TestController.cpp index fc2e28d..aff8798 100644 --- a/WebKitTools/WebKitTestRunner/TestController.cpp +++ b/WebKitTools/WebKitTestRunner/TestController.cpp @@ -28,12 +28,19 @@ #include "PlatformWebView.h" #include "StringFunctions.h" #include "TestInvocation.h" +#include <cstdio> #include <WebKit2/WKContextPrivate.h> #include <WebKit2/WKPreferencesPrivate.h> #include <wtf/PassOwnPtr.h> namespace WTR { +static WKURLRef blankURL() +{ + static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank"); + return staticBlankURL; +} + static TestController* controller; TestController& TestController::shared() @@ -60,6 +67,30 @@ TestController::~TestController() { } +static WKRect getWindowFrameMainPage(WKPageRef page, const void* clientInfo) +{ + PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView(); + return view->windowFrame(); +} + +static void setWindowFrameMainPage(WKPageRef page, WKRect frame, const void* clientInfo) +{ + PlatformWebView* view = static_cast<TestController*>(const_cast<void*>(clientInfo))->mainWebView(); + view->setWindowFrame(frame); +} + +static WKRect getWindowFrameOtherPage(WKPageRef page, const void* clientInfo) +{ + PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo)); + return view->windowFrame(); +} + +static void setWindowFrameOtherPage(WKPageRef page, WKRect frame, const void* clientInfo) +{ + PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo)); + view->setWindowFrame(frame); +} + static void closeOtherPage(WKPageRef page, const void* clientInfo) { WKPageClose(page); @@ -78,15 +109,19 @@ static WKPageRef createOtherPage(WKPageRef oldPage, const void*) 0, view, createOtherPage, - 0, + 0, // showPage closeOtherPage, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 0, // runJavaScriptAlert + 0, // runJavaScriptConfirm + 0, // runJavaScriptPrompt + 0, // setStatusText + 0, // mouseDidMoveOverElement + 0, // contentsSizeChanged + 0, // didNotHandleKeyEvent + getWindowFrameOtherPage, + setWindowFrameOtherPage, + 0, // runBeforeUnloadConfirmPanel + 0 // didDraw }; WKPageSetPageUIClient(newPage, &otherPageUIClient); @@ -159,39 +194,43 @@ void TestController::initialize(int argc, const char* argv[]) 0, this, createOtherPage, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 0, // showPage + 0, // close + 0, // runJavaScriptAlert + 0, // runJavaScriptConfirm + 0, // runJavaScriptPrompt + 0, // setStatusText + 0, // mouseDidMoveOverElement + 0, // contentsSizeChanged + 0, // didNotHandleKeyEvent + getWindowFrameMainPage, + setWindowFrameMainPage, + 0, // runBeforeUnloadConfirmPanel + 0 // didDraw }; WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient); WKPageLoaderClient pageLoaderClient = { 0, this, - 0, - 0, - 0, - 0, - 0, + 0, // didStartProvisionalLoadForFrame + 0, // didReceiveServerRedirectForProvisionalLoadForFrame + 0, // didFailProvisionalLoadWithErrorForFrame + 0, // didCommitLoadForFrame + 0, // didFinishDocumentLoadForFrame didFinishLoadForFrame, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 0, // didFailLoadWithErrorForFrame + 0, // didReceiveTitleForFrame + 0, // didFirstLayoutForFrame + 0, // didFirstVisuallyNonEmptyLayoutForFrame + 0, // didRemoveFrameFromHierarchy + 0, // didStartProgress + 0, // didChangeProgress + 0, // didFinishProgress + 0, // didBecomeUnresponsive + 0, // didBecomeResponsive + 0, // processDidExit + 0 // didChangeBackForwardList }; WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient); } @@ -208,13 +247,26 @@ void TestController::resetStateToConsistentValues() WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing); WKPreferencesSetXSSAuditorEnabled(preferences, false); + static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times"); + static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery"); + static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus"); + static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier"); + static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica"); + static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times"); + + WKPreferencesSetStandardFontFamily(preferences, standardFontFamily); + WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily); + WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily); + WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily); + WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily); + WKPreferencesSetSerifFontFamily(preferences, serifFontFamily); + m_mainWebView->focus(); // Reset main page back to about:blank m_doneResetting = false; - WKRetainPtr<WKURLRef> url(AdoptWK, createWKURL("about:blank")); - WKPageLoadURL(m_mainWebView->page(), url.get()); + WKPageLoadURL(m_mainWebView->page(), blankURL()); TestController::runUntil(m_doneResetting); } @@ -281,9 +333,7 @@ void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame) return; WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame)); - RetainPtr<CFURLRef> cfURL= toCF(wkURL); - CFStringRef cfURLString = CFURLGetString(cfURL.get()); - if (!CFEqual(cfURLString, CFSTR("about:blank"))) + if (!WKURLIsEqual(wkURL.get(), blankURL())) return; m_doneResetting = true; diff --git a/WebKitTools/WebKitTestRunner/TestInvocation.cpp b/WebKitTools/WebKitTestRunner/TestInvocation.cpp index 47df66b..c1bf894 100644 --- a/WebKitTools/WebKitTestRunner/TestInvocation.cpp +++ b/WebKitTools/WebKitTestRunner/TestInvocation.cpp @@ -28,15 +28,62 @@ #include "PlatformWebView.h" #include "StringFunctions.h" #include "TestController.h" +#include <climits> +#include <cstdio> #include <WebKit2/WKContextPrivate.h> #include <WebKit2/WKRetainPtr.h> -#include <wtf/RetainPtr.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/PassOwnArrayPtr.h> + +#if OS(WINDOWS) +#include <direct.h> // For _getcwd. +#define getcwd _getcwd // MSDN says getcwd is deprecated. +#define PATH_MAX _MAX_PATH +#endif using namespace WebKit; using namespace std; namespace WTR { +static WKURLRef createWKURL(const char* pathOrURL) +{ + if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://")) + return WKURLCreateWithUTF8CString(pathOrURL); + + // Creating from filesytem path. + size_t length = strlen(pathOrURL); + if (!length) + return 0; + + const char* filePrefix = "file://"; + static const size_t prefixLength = strlen(filePrefix); +#if OS(WINDOWS) + const char separator = '\\'; + bool isAbsolutePath = length >= 3 && pathOrURL[1] == ':' && pathOrURL[2] == separator; +#else + const char separator = '/'; + bool isAbsolutePath = pathOrURL[0] == separator; +#endif + + OwnArrayPtr<char> buffer; + if (isAbsolutePath) { + buffer = adoptArrayPtr(new char[prefixLength + length + 1]); + strcpy(buffer.get(), filePrefix); + strcpy(buffer.get() + prefixLength, pathOrURL); + } else { + buffer = adoptArrayPtr(new char[prefixLength + PATH_MAX + length + 2]); // 1 for the separator + strcpy(buffer.get(), filePrefix); + if (!getcwd(buffer.get() + prefixLength, PATH_MAX)) + return 0; + size_t numCharacters = strlen(buffer.get()); + buffer[numCharacters] = separator; + strcpy(buffer.get() + numCharacters + 1, pathOrURL); + } + + return WKURLCreateWithUTF8CString(buffer.get()); +} + TestInvocation::TestInvocation(const char* pathOrURL) : m_url(AdoptWK, createWKURL(pathOrURL)) , m_pathOrURL(fastStrDup(pathOrURL)) @@ -70,9 +117,8 @@ void TestInvocation::invoke() { sizeWebViewForCurrentTest(m_pathOrURL); - WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithCFString(CFSTR("BeginTest"))); - WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithCFString(CFSTR(""))); - WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), messageBody.get()); + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeginTest")); + WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0); TestController::runUntil(m_gotInitialResponse); if (m_error) { @@ -104,8 +150,7 @@ void TestInvocation::dump(const char* stringToDump) void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody) { - RetainPtr<CFStringRef> cfMessageName(AdoptCF, WKStringCopyCFString(0, messageName)); - if (CFEqual(cfMessageName.get(), CFSTR("Error"))) { + if (WKStringIsEqualToUTF8CString(messageName, "Error")) { // Set all states to true to stop spinning the runloop. m_gotInitialResponse = true; m_gotFinalMessage = true; @@ -113,11 +158,10 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName return; } - if (CFEqual(cfMessageName.get(), CFSTR("Ack"))) { + if (WKStringIsEqualToUTF8CString(messageName, "Ack")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); - RetainPtr<CFStringRef> cfMessageBody(AdoptCF, WKStringCopyCFString(0, static_cast<WKStringRef>(messageBody))); - - if (CFEqual(cfMessageBody.get(), CFSTR("BeginTest"))) { + WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody); + if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) { m_gotInitialResponse = true; return; } @@ -125,12 +169,11 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName ASSERT_NOT_REACHED(); } - if (CFEqual(cfMessageName.get(), CFSTR("Done"))) { + if (WKStringIsEqualToUTF8CString(messageName, "Done")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); - ostringstream out; - out << static_cast<WKStringRef>(messageBody); + WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody); - dump(out.str().c_str()); + dump(toSTD(messageBodyString).c_str()); m_gotFinalMessage = true; return; diff --git a/WebKitTools/WebKitTestRunner/WebKitTestRunner.pro b/WebKitTools/WebKitTestRunner/WebKitTestRunner.pro new file mode 100644 index 0000000..677abb3 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/WebKitTestRunner.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS = qt/WebKitTestRunner.pro \ + InjectedBundle/qt/InjectedBundle.pro \ + diff --git a/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj b/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj index 6ecbef9..599e09e 100644 --- a/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj +++ b/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj @@ -368,7 +368,14 @@ isa = PBXProject; buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "WebKitTestRunner" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 08FB7794FE84155DC02AAC07 /* WebKitTestRunner */; projectDirPath = ""; projectRoot = ""; diff --git a/WebKitTools/WebKitTestRunner/mac/PlatformWebViewMac.mm b/WebKitTools/WebKitTestRunner/mac/PlatformWebViewMac.mm index 96e6526..6080c1f 100644 --- a/WebKitTools/WebKitTestRunner/mac/PlatformWebViewMac.mm +++ b/WebKitTools/WebKitTestRunner/mac/PlatformWebViewMac.mm @@ -63,4 +63,21 @@ void PlatformWebView::focus() // Implement. } +WKRect PlatformWebView::windowFrame() +{ + NSRect frame = [m_window frame]; + + WKRect wkFrame; + wkFrame.origin.x = frame.origin.x; + wkFrame.origin.y = frame.origin.y; + wkFrame.size.width = frame.size.width; + wkFrame.size.height = frame.size.height; + return wkFrame; +} + +void PlatformWebView::setWindowFrame(WKRect frame) +{ + [m_window setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height) display:YES]; +} + } // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/qt/PlatformWebViewQt.cpp b/WebKitTools/WebKitTestRunner/qt/PlatformWebViewQt.cpp new file mode 100644 index 0000000..d405a0f --- /dev/null +++ b/WebKitTools/WebKitTestRunner/qt/PlatformWebViewQt.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PlatformWebView.h" +#include "qgraphicswkview.h" +#include <QtGui> + +namespace WTR { + +class WebView : public QGraphicsView { +public: + WebView(WKPageNamespaceRef); + + QGraphicsWKView* wkView() const { return m_item; } + + virtual ~WebView() { delete m_item; } + +private: + QGraphicsWKView* m_item; +}; + +WebView::WebView(WKPageNamespaceRef namespaceRef) + : QGraphicsView() + , m_item(new QGraphicsWKView(namespaceRef)) +{ + setScene(new QGraphicsScene(this)); + scene()->addItem(m_item); +} + +PlatformWebView::PlatformWebView(WKPageNamespaceRef namespaceRef) + : m_view(new WebView(namespaceRef)) + , m_window(new QMainWindow()) +{ + m_view->setParent(m_window); + m_window->setCentralWidget(m_view); + m_window->setGeometry(0, 0, 800, 600); +} + +PlatformWebView::~PlatformWebView() +{ + delete m_window; +} + +void PlatformWebView::resizeTo(unsigned width, unsigned height) +{ + m_window->resize(width, height); +} + +WKPageRef PlatformWebView::page() +{ + return m_view->wkView()->page()->pageRef(); +} + +void PlatformWebView::focus() +{ + m_view->setFocus(Qt::OtherFocusReason); +} + +WKRect PlatformWebView::windowFrame() +{ + // Implement. + + WKRect wkFrame; + wkFrame.origin.x = 0; + wkFrame.origin.y = 0; + wkFrame.size.width = 0; + wkFrame.size.height = 0; + return wkFrame; +} + +void PlatformWebView::setWindowFrame(WKRect) +{ + // Implement. +} + +} // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/qt/TestControllerQt.cpp b/WebKitTools/WebKitTestRunner/qt/TestControllerQt.cpp new file mode 100644 index 0000000..d3aee4a --- /dev/null +++ b/WebKitTools/WebKitTestRunner/qt/TestControllerQt.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TestController.h" + +#include "WKStringQt.h" + +#include <cstdlib> +#include <QCoreApplication> +#include <QEventLoop> +#include <QFileInfo> +#include <QLibrary> +#include <QObject> +#include <QtGlobal> +#include <wtf/Platform.h> +#include <wtf/text/WTFString.h> + +namespace WTR { + +// With a bigger interval we would waste to much time +// after the test had been finished. +static const unsigned kTimerIntervalMS = 1; + +class RunUntilConditionLoop : public QObject { + Q_OBJECT + +public: + static void start(bool& done) + { + static RunUntilConditionLoop* instance = new RunUntilConditionLoop; + instance->run(done); + } + +private: + RunUntilConditionLoop() {} + + void run(bool& done) + { + m_condition = &done; + m_timerID = startTimer(kTimerIntervalMS); + ASSERT(m_timerID); + m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + } + + virtual void timerEvent(QTimerEvent*) + { + if (!*m_condition) + return; + + killTimer(m_timerID); + m_eventLoop.exit(); + } + + QEventLoop m_eventLoop; + bool* m_condition; + int m_timerID; +}; + +void TestController::platformInitialize() +{ +} + +void TestController::runUntil(bool& done) +{ + RunUntilConditionLoop::start(done); + ASSERT(done); +} + +static bool isExistingLibrary(const QString& path) +{ +#if OS(WINDOWS) || OS(SYMBIAN) + const char* librarySuffixes[] = { ".dll" }; +#elif PLATFORM(MAC) + const char* librarySuffixes[] = { ".bundle", ".dylib", ".so" }; +#elif OS(UNIX) + const char* librarySuffixes[] = { ".so" }; +#else +#error Library path suffix should be specified for this platform +#endif + for (unsigned i = 0; i < sizeof(librarySuffixes) / sizeof(const char*); ++i) { + if (QLibrary::isLibrary(path + librarySuffixes[i])) + return true; + } + + return false; +} + +void TestController::initializeInjectedBundlePath() +{ + QString path = QLatin1String(getenv("WTR_INJECTEDBUNDLE_PATH")); + if (path.isEmpty()) + path = QFileInfo(QCoreApplication::applicationDirPath() + "/../lib/libWTRInjectedBundle").absoluteFilePath(); + if (!isExistingLibrary(path)) + qFatal("Cannot find the injected bundle at %s\n", qPrintable(path)); + + m_injectedBundlePath = WKStringCreateWithQString(path); +} + +void TestController::initializeTestPluginDirectory() +{ + // This is called after initializeInjectedBundlePath. + m_testPluginDirectory = m_injectedBundlePath; +} + +void TestController::platformInitializeContext() +{ +} + +#include "TestControllerQt.moc" + +} // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/qt/WebKitTestRunner.pro b/WebKitTools/WebKitTestRunner/qt/WebKitTestRunner.pro new file mode 100644 index 0000000..a638e65 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/qt/WebKitTestRunner.pro @@ -0,0 +1,68 @@ +TARGET = WebKitTestRunner +CONFIG -= app_bundle + +BASEDIR = $$PWD/../ +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../.. + +include(../../../WebKit.pri) + +!CONFIG(release, debug|release) { + OBJECTS_DIR = obj/debug +} else { # Release + OBJECTS_DIR = obj/release +} + +DEFINES += USE_SYSTEM_MALLOC + +INCLUDEPATH += \ + $$BASEDIR \ + $$BASEDIR/../../JavaScriptCore \ + $$BASEDIR/../../WebKit2 \ + $$BASEDIR/../../WebKit2/Shared \ + $$BASEDIR/../../WebKit2/UIProcess/API/qt \ + $$BASEDIR/../../WebKit2/UIProcess/API/cpp/qt \ + +INCLUDEPATH += \ + $$OUTPUT_DIR/include \ + + +DESTDIR = $$OUTPUT_DIR/bin + +unix:!mac { + CONFIG += link_pkgconfig + PKGCONFIG += fontconfig +} + +QT = core gui network + +HEADERS = \ + $$BASEDIR/PlatformWebView.h \ + $$BASEDIR/StringFunctions.h \ + $$BASEDIR/TestController.h \ + $$BASEDIR/TestInvocation.h + +SOURCES = \ + main.cpp \ + PlatformWebViewQt.cpp \ + TestControllerQt.cpp \ + $$BASEDIR/TestController.cpp \ + $$BASEDIR/TestInvocation.cpp \ + +PREFIX_HEADER = $$BASEDIR/WebKitTestRunnerPrefix.h +QMAKE_CXXFLAGS += "-include $$PREFIX_HEADER" + +linux-* { + # From Creator's src/rpath.pri: + # Do the rpath by hand since it's not possible to use ORIGIN in QMAKE_RPATHDIR + # this expands to $ORIGIN (after qmake and make), it does NOT read a qmake var. + QMAKE_RPATHDIR = \$\$ORIGIN/../lib $$QMAKE_RPATHDIR + MY_RPATH = $$join(QMAKE_RPATHDIR, ":") + + QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${MY_RPATH}\' + QMAKE_RPATHDIR = +} else { + QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR +} + +include(../../../JavaScriptCore/JavaScriptCore.pri) +addJavaScriptCoreLib(../../../JavaScriptCore) diff --git a/WebKitTools/WebKitTestRunner/qt/main.cpp b/WebKitTools/WebKitTestRunner/qt/main.cpp new file mode 100644 index 0000000..4312a05 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/qt/main.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY 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 "TestController.h" + +#include <QApplication> +#include <QObject> +#include <QTimer> + +class Launcher : public QObject { + Q_OBJECT + +public: + Launcher(int argc, char** argv) + : m_argc(argc) + , m_argv(argv) + { + } + + ~Launcher() + { + delete m_controller; + } + +public slots: + void launch() + { + m_controller = new WTR::TestController(m_argc, const_cast<const char**>(m_argv)); + QApplication::exit(); + } + +private: + WTR::TestController* m_controller; + int m_argc; + char** m_argv; +}; + +int main(int argc, char** argv) +{ + QApplication app(argc, argv); + Launcher launcher(argc, argv); + QTimer::singleShot(0, &launcher, SLOT(launch())); + return app.exec();; +} + +#include "main.moc" diff --git a/WebKitTools/WebKitTestRunner/win/PlatformWebViewWin.cpp b/WebKitTools/WebKitTestRunner/win/PlatformWebViewWin.cpp index b9854c4..9acd236 100644 --- a/WebKitTools/WebKitTestRunner/win/PlatformWebViewWin.cpp +++ b/WebKitTools/WebKitTestRunner/win/PlatformWebViewWin.cpp @@ -78,4 +78,21 @@ void PlatformWebView::focus() ::SetFocus(::WKViewGetWindow(m_view)); } +WKRect PlatformWebView::windowFrame() +{ + // Implement. + + WKRect wkFrame; + wkFrame.origin.x = 0; + wkFrame.origin.y = 0; + wkFrame.size.width = 0; + wkFrame.size.height = 0; + return wkFrame; +} + +void PlatformWebView::setWindowFrame(WKRect) +{ + // Implement. +} + } // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj index e4cd870..c852f64 100644 --- a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj +++ b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj @@ -23,7 +23,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -39,7 +39,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
@@ -95,7 +95,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -111,7 +111,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
@@ -166,7 +166,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -182,7 +182,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
@@ -236,7 +236,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -252,7 +252,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
@@ -308,7 +308,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -324,7 +324,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
@@ -382,7 +382,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\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"
"
+ 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"

"
/>
<Tool
Name="VCCustomBuildTool"
@@ -398,7 +398,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebKitTestRunner\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
+ AdditionalIncludeDirectories=""$(ProjectDir)\..";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include""
PreprocessorDefinitions="__WIN32__;_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="WebKitTestRunnerPrefix.h"
diff --git a/WebKitTools/gdb/webkit.py b/WebKitTools/gdb/webkit.py index 2d3b47a..95c3d9c 100644 --- a/WebKitTools/gdb/webkit.py +++ b/WebKitTools/gdb/webkit.py @@ -100,6 +100,36 @@ class WTFStringPrinter(StringPrinter): self.get_length()) +class JSCUStringPrinter(StringPrinter): + "Print a JSC::UString" + def get_length(self): + if not self.val['m_impl']['m_ptr']: + return 0 + return self.val['m_impl']['m_ptr']['m_length'] + + def to_string(self): + if self.get_length() == 0: + return '' + + return ustring_to_string(self.val['m_impl']['m_ptr']['m_data'], + self.get_length()) + + +class JSCIdentifierPrinter(StringPrinter): + "Print a JSC::Identifier" + def to_string(self): + return JSCUStringPrinter(self.val['m_string']).to_string() + + +class JSCJSStringPrinter(StringPrinter): + "Print a JSC::JSString" + def to_string(self): + if self.val['m_length'] == 0: + return '' + + return JSCUStringPrinter(self.val['m_value']).to_string() + + class WebCoreQualifiedNamePrinter(StringPrinter): "Print a WebCore::QualifiedName" @@ -198,13 +228,15 @@ class WTFVectorPrinter: def display_hint(self): return 'array' - def add_pretty_printers(): pretty_printers_dict = { re.compile("^WTF::Vector<.*>$"): WTFVectorPrinter, re.compile("^WTF::AtomicString$"): WTFAtomicStringPrinter, re.compile("^WTF::String$"): WTFStringPrinter, re.compile("^WebCore::QualifiedName$"): WebCoreQualifiedNamePrinter, + re.compile("^JSC::UString$"): JSCUStringPrinter, + re.compile("^JSC::Identifier$"): JSCIdentifierPrinter, + re.compile("^JSC::JSString$"): JSCJSStringPrinter, } def lookup_function(val): |