[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-10851-g50815da
mihaip at chromium.org
mihaip at chromium.org
Wed Dec 22 17:56:14 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit a60ba6901081825237f32743403f9ea0aef4d3fd
Author: mihaip at chromium.org <mihaip at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Dec 2 22:53:47 2010 +0000
2010-11-30 Mihai Parparita <mihaip at chromium.org>
Reviewed by Tony Chang.
Rebaseline server: add updating of baselines
https://bugs.webkit.org/show_bug.cgi?id=50305
Implements updating of baselines, where we copy -actual.* files over
the current -expected.* files. To do this, we need a
_get_actual_result_files method to get test results files and a
_rebaseline_test method to actually do the file copy and SCM operation.
_rebaseline_test logs output into a buffer, this is useful for both
showing result in the UI and for unit tests.
To make passing around of the various test environment properties
(results directory, filesystem, SCM, etc) easier, add a TestConfig
class for them.
Moving of existing baselines is not implemented yet, this patch is big
enough as it is.
* Scripts/webkitpy/common/system/filesystem.py:
* Scripts/webkitpy/common/system/filesystem_mock.py:
* Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js:
* Scripts/webkitpy/tool/commands/rebaselineserver.py:
* Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py:
* Scripts/webkitpy/tool/mocktool.py:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73204 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 6c00378..56cde5c 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,31 @@
+2010-11-30 Mihai Parparita <mihaip at chromium.org>
+
+ Reviewed by Tony Chang.
+
+ Rebaseline server: add updating of baselines
+ https://bugs.webkit.org/show_bug.cgi?id=50305
+
+ Implements updating of baselines, where we copy -actual.* files over
+ the current -expected.* files. To do this, we need a
+ _get_actual_result_files method to get test results files and a
+ _rebaseline_test method to actually do the file copy and SCM operation.
+ _rebaseline_test logs output into a buffer, this is useful for both
+ showing result in the UI and for unit tests.
+
+ To make passing around of the various test environment properties
+ (results directory, filesystem, SCM, etc) easier, add a TestConfig
+ class for them.
+
+ Moving of existing baselines is not implemented yet, this patch is big
+ enough as it is.
+
+ * Scripts/webkitpy/common/system/filesystem.py:
+ * Scripts/webkitpy/common/system/filesystem_mock.py:
+ * Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js:
+ * Scripts/webkitpy/tool/commands/rebaselineserver.py:
+ * Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py:
+ * Scripts/webkitpy/tool/mocktool.py:
+
2010-12-02 Brent Fulgham <bfulgham at webkit.org>
Unreviewed build fix after vcproj updates.
diff --git a/WebKitTools/Scripts/webkitpy/common/system/filesystem.py b/WebKitTools/Scripts/webkitpy/common/system/filesystem.py
index c7efde3..8f396c4 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/filesystem.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/filesystem.py
@@ -33,6 +33,7 @@ from __future__ import with_statement
import codecs
import errno
import os
+import shutil
import tempfile
@@ -46,6 +47,10 @@ class FileSystem(object):
"""Return whether the path exists in the filesystem."""
return os.path.exists(path)
+ def isfile(self, path):
+ """Return whether the path refers to a file."""
+ return os.path.isfile(path)
+
def isdir(self, path):
"""Return whether the path refers to a directory."""
return os.path.isdir(path)
@@ -115,3 +120,8 @@ class FileSystem(object):
The file is written encoded as UTF-8 with no BOM."""
with codecs.open(path, 'w', 'utf8') as f:
f.write(contents)
+
+ def copyfile(self, source, destination):
+ """Copies the contents of the file at the given path to the destination
+ path."""
+ shutil.copyfile(source, destination)
diff --git a/WebKitTools/Scripts/webkitpy/common/system/filesystem_mock.py b/WebKitTools/Scripts/webkitpy/common/system/filesystem_mock.py
index 2dbc1e8..ea0f3f9 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/filesystem_mock.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/filesystem_mock.py
@@ -32,7 +32,7 @@ import path
class MockFileSystem(object):
- def __init__(self, files={}):
+ def __init__(self, files=None):
"""Initializes a "mock" filesystem that can be used to completely
stub out a filesystem.
@@ -41,16 +41,44 @@ class MockFileSystem(object):
value of None is used to indicate that the file should
not exist.
"""
- self.files = files
+ self.files = files or {}
def exists(self, path):
+ return self.isfile(path) or self.isdir(path)
+
+ def isfile(self, path):
+ return path in self.files and self.files[path] is not None
+
+ def isdir(self, path):
if path in self.files:
- return self.files[path] is not None
- return False
+ return False
+ if not path.endswith('/'):
+ path += '/'
+ return any(f.startswith(path) for f in self.files)
def join(self, *comps):
return '/'.join(comps)
+ def listdir(self, path):
+ if not self.isdir(path):
+ raise OSError("%s is not a directory" % path)
+
+ if not path.endswith('/'):
+ path += '/'
+
+ dirs = []
+ files = []
+ for f in self.files:
+ if self.exists(f) and f.startswith(path):
+ remaining = f[len(path):]
+ if '/' in remaining:
+ dir = remaining[:remaining.index('/')]
+ if not dir in dirs:
+ dirs.append(dir)
+ else:
+ files.append(remaining)
+ return dirs + files
+
def maybe_make_directory(self, *path):
# FIXME: Implement such that subsequent calls to isdir() work?
pass
@@ -69,3 +97,13 @@ class MockFileSystem(object):
def write_binary_file(self, path, contents):
self.files[path] = contents
+
+ def copyfile(self, source, destination):
+ if not self.exists(source):
+ raise IOError(errno.ENOENT, source, os.strerror(errno.ENOENT))
+ if self.isdir(source):
+ raise IOError(errno.EISDIR, source, os.strerror(errno.ISDIR))
+ if self.isdir(destination):
+ raise IOError(errno.EISDIR, destination, os.strerror(errno.ISDIR))
+
+ self.files[destination] = self.files[source]
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js b/WebKitTools/Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js
index f57c919..4c094fc 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/data/rebaselineserver/queue.js
@@ -146,13 +146,36 @@ RebaselineQueue.prototype._rebaselineTest = function(testName)
var baselineTarget = getSelectValue('baseline-target');
var baselineMoveTo = getSelectValue('baseline-move-to');
- // FIXME: actually rebaseline
- log('Rebaselining ' + testName + ' for platform ' + baselineTarget + '...');
- var test = results.tests[testName];
- this._removeTest(testName);
- this._inProgressRebaselineCount--;
- test.state = STATE_REBASELINE_SUCCEEDED;
- updateState();
- log('Rebaselined add test with state ' + test.state + ' to queue',
- log.SUCCESS);
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST',
+ '/rebaseline?test=' + encodeURIComponent(testName) +
+ '&baseline-target=' + encodeURIComponent(baselineTarget) +
+ '&baseline-move-to=' + encodeURIComponent(baselineMoveTo));
+
+ var self = this;
+ function handleResponse(logType, newState) {
+ log(xhr.responseText, logType);
+ self._removeTest(testName);
+ self._inProgressRebaselineCount--;
+ results.tests[testName].state = newState;
+ updateState();
+ }
+
+ function handleSuccess() {
+ handleResponse(log.SUCCESS, STATE_REBASELINE_SUCCEEDED);
+ }
+ function handleFailure() {
+ handleResponse(log.ERROR, STATE_REBASELINE_FAILED);
+ }
+
+ xhr.addEventListener('load', function() {
+ if (xhr.status < 400) {
+ handleSuccess();
+ } else {
+ handleFailure();
+ }
+ });
+ xhr.addEventListener('error', handleFailure);
+
+ xhr.send();
};
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver.py b/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver.py
index 2dcc566..d0db9bc 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver.py
@@ -33,6 +33,7 @@ from __future__ import with_statement
import codecs
import datetime
+import fnmatch
import mimetypes
import os
import os.path
@@ -56,9 +57,9 @@ STATE_REBASELINE_FAILED = 'rebaseline_failed'
STATE_REBASELINE_SUCCEEDED = 'rebaseline_succeeded'
class RebaselineHTTPServer(BaseHTTPServer.HTTPServer):
- def __init__(self, httpd_port, results_directory, results_json, platforms_json):
+ def __init__(self, httpd_port, test_config, results_json, platforms_json):
BaseHTTPServer.HTTPServer.__init__(self, ("", httpd_port), RebaselineHTTPRequestHandler)
- self.results_directory = results_directory
+ self.test_config = test_config
self.results_json = results_json
self.platforms_json = platforms_json
@@ -113,6 +114,36 @@ class RebaselineHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self._serve_file(os.path.join(
RebaselineHTTPRequestHandler.STATIC_FILE_DIRECTORY, static_path))
+ def rebaseline(self):
+ test = self.query['test'][0]
+ baseline_target = self.query['baseline-target'][0]
+ baseline_move_to = self.query['baseline-move-to'][0]
+ test_json = self.server.results_json['tests'][test]
+
+ if test_json['state'] != STATE_NEEDS_REBASELINE:
+ self.send_error(400, "Test %s is in unexpected state: %s" %
+ (test, test_json["state"]))
+ return
+
+ log = []
+ success = _rebaseline_test(
+ test,
+ baseline_target,
+ baseline_move_to,
+ self.server.test_config,
+ log=lambda l: log.append(l))
+
+ if success:
+ test_json['state'] = STATE_REBASELINE_SUCCEEDED
+ self.send_response(200)
+ else:
+ test_json['state'] = STATE_REBASELINE_FAILED
+ self.send_response(500)
+
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write('\n'.join(log))
+
def quitquitquit(self):
self.send_response(200)
self.send_header("Content-type", "text/plain")
@@ -143,7 +174,7 @@ class RebaselineHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
elif mode == 'diff-text':
file_name = test_name + '-diff.txt'
- file_path = os.path.join(self.server.results_directory, file_name)
+ file_path = os.path.join(self.server.test_config.results_directory, file_name)
# Let results be cached for 60 seconds, so that they can be pre-fetched
# by the UI
@@ -183,12 +214,79 @@ class RebaselineHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
shutil.copyfileobj(static_file, self.wfile)
-def _get_test_baselines(test_file, test_port, layout_tests_directory, platforms, filesystem):
+class TestConfig(object):
+ def __init__(self, test_port, layout_tests_directory, results_directory, platforms, filesystem, scm):
+ self.test_port = test_port
+ self.layout_tests_directory = layout_tests_directory
+ self.results_directory = results_directory
+ self.platforms = platforms
+ self.filesystem = filesystem
+ self.scm = scm
+
+
+def _get_actual_result_files(test_file, test_config):
+ test_name, _ = os.path.splitext(test_file)
+ test_directory = os.path.dirname(test_file)
+
+ test_results_directory = test_config.filesystem.join(
+ test_config.results_directory, test_directory)
+ actual_pattern = os.path.basename(test_name) + '-actual.*'
+ actual_files = []
+ for filename in test_config.filesystem.listdir(test_results_directory):
+ if fnmatch.fnmatch(filename, actual_pattern):
+ actual_files.append(filename)
+ actual_files.sort()
+ return tuple(actual_files)
+
+
+def _rebaseline_test(test_file, baseline_target, baseline_move_to, test_config, log):
+ test_name, _ = os.path.splitext(test_file)
+ test_directory = os.path.dirname(test_name)
+
+ log('Rebaselining %s...' % test_name)
+
+ actual_result_files = _get_actual_result_files(test_file, test_config)
+ filesystem = test_config.filesystem
+ scm = test_config.scm
+ layout_tests_directory = test_config.layout_tests_directory
+ results_directory = test_config.results_directory
+ target_expectations_directory = filesystem.join(
+ layout_tests_directory, 'platform', baseline_target, test_directory)
+ test_results_directory = test_config.filesystem.join(
+ test_config.results_directory, test_directory)
+
+ # If requested, move current baselines out
+ current_baselines = _get_test_baselines(test_file, test_config)
+ if baseline_target in current_baselines and baseline_move_to != 'none':
+ log(' Moving current %s baselines to %s' %
+ (baseline_target, baseline_move_to))
+ log(' FIXME: Add support for moving existing baselines')
+ return False
+
+ log(' Updating baselines for %s' % baseline_target)
+ for source_file in actual_result_files:
+ source_path = filesystem.join(test_results_directory, source_file)
+ destination_file = source_file.replace('-actual', '-expected')
+ destination_path = filesystem.join(
+ target_expectations_directory, destination_file)
+ filesystem.copyfile(source_path, destination_path)
+ exit_code = scm.add(destination_path, return_exit_code=True)
+ if exit_code:
+ log(' Could not update %s in SCM, exit code %d' %
+ (destination_file, exit_code))
+ return False
+ else:
+ log(' Updated %s' % destination_file)
+
+ return True
+
+
+def _get_test_baselines(test_file, test_config):
class AllPlatformsPort(WebKitPort):
def __init__(self):
- WebKitPort.__init__(self, filesystem=filesystem)
+ WebKitPort.__init__(self, filesystem=test_config.filesystem)
self._platforms_by_directory = dict(
- [(self._webkit_baseline_path(p), p) for p in platforms])
+ [(self._webkit_baseline_path(p), p) for p in test_config.platforms])
def baseline_search_path(self):
return self._platforms_by_directory.keys()
@@ -196,20 +294,21 @@ def _get_test_baselines(test_file, test_port, layout_tests_directory, platforms,
def platform_from_directory(self, directory):
return self._platforms_by_directory[directory]
- test_path = filesystem.join(layout_tests_directory, test_file)
+ test_path = test_config.filesystem.join(
+ test_config.layout_tests_directory, test_file)
all_platforms_port = AllPlatformsPort()
all_test_baselines = {}
for baseline_extension in ('.txt', '.checksum', '.png'):
- test_baselines = test_port.expected_baselines(
+ test_baselines = test_config.test_port.expected_baselines(
test_path, baseline_extension)
baselines = all_platforms_port.expected_baselines(
test_path, baseline_extension, all_baselines=True)
for platform_directory, expected_filename in baselines:
if not platform_directory:
continue
- if platform_directory == layout_tests_directory:
+ if platform_directory == test_config.layout_tests_directory:
platform = 'base'
else:
platform = all_platforms_port.platform_from_directory(
@@ -218,7 +317,7 @@ def _get_test_baselines(test_file, test_port, layout_tests_directory, platforms,
was_used_for_test = (
platform_directory, expected_filename) in test_baselines
platform_baselines[baseline_extension] = was_used_for_test
-
+
return all_test_baselines
class RebaselineServer(AbstractDeclarativeCommand):
@@ -247,13 +346,19 @@ class RebaselineServer(AbstractDeclarativeCommand):
layout_tests_directory = port.layout_tests_dir()
platforms = filesystem.listdir(
filesystem.join(layout_tests_directory, 'platform'))
+ test_config = TestConfig(
+ port,
+ layout_tests_directory,
+ results_directory,
+ platforms,
+ filesystem,
+ self._tool.scm())
print 'Gathering current baselines...'
for test_file, test_json in results_json['tests'].items():
test_json['state'] = STATE_NEEDS_REBASELINE
test_path = filesystem.join(layout_tests_directory, test_file)
- test_json['baselines'] = _get_test_baselines(
- test_file, port, layout_tests_directory, platforms, filesystem)
+ test_json['baselines'] = _get_test_baselines(test_file, test_config)
server_url = "http://localhost:%d/" % options.httpd_port
print "Starting server at %s" % server_url
@@ -265,7 +370,7 @@ class RebaselineServer(AbstractDeclarativeCommand):
httpd = RebaselineHTTPServer(
httpd_port=options.httpd_port,
- results_directory=results_directory,
+ test_config=test_config,
results_json=results_json,
platforms_json={
'platforms': platforms,
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py
index b37da3d..5cfb629 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/rebaselineserver_unittest.py
@@ -32,6 +32,114 @@ from webkitpy.common.system import filesystem_mock
from webkitpy.layout_tests.port import base
from webkitpy.layout_tests.port.webkit import WebKitPort
from webkitpy.tool.commands import rebaselineserver
+from webkitpy.tool.mocktool import MockSCM
+
+
+class RebaselineTestTest(unittest.TestCase):
+ def test_text_rebaseline(self):
+ self._assertRebaseline(
+ test_files=(
+ 'fast/text-expected.txt',
+ 'platform/mac/fast/text-expected.txt',
+ ),
+ results_files=(
+ 'fast/text-actual.txt',
+ ),
+ test_name='fast/text.html',
+ baseline_target='mac',
+ baseline_move_to='none',
+ expected_success=True,
+ expected_log=[
+ 'Rebaselining fast/text...',
+ ' Updating baselines for mac',
+ ' Updated text-expected.txt',
+ ])
+
+ def test_text_rebaseline_move_no_op(self):
+ self._assertRebaseline(
+ test_files=(
+ 'fast/text-expected.txt',
+ 'platform/win/fast/text-expected.txt',
+ ),
+ results_files=(
+ 'fast/text-actual.txt',
+ ),
+ test_name='fast/text.html',
+ baseline_target='mac',
+ baseline_move_to='mac-leopard',
+ expected_success=True,
+ expected_log=[
+ 'Rebaselining fast/text...',
+ ' Updating baselines for mac',
+ ' Updated text-expected.txt',
+ ])
+
+ def test_text_rebaseline_move(self):
+ self._assertRebaseline(
+ test_files=(
+ 'fast/text-expected.txt',
+ 'platform/mac/fast/text-expected.txt',
+ ),
+ results_files=(
+ 'fast/text-actual.txt',
+ ),
+ test_name='fast/text.html',
+ baseline_target='mac',
+ baseline_move_to='mac-leopard',
+ expected_success=False,
+ expected_log=[
+ 'Rebaselining fast/text...',
+ ' Moving current mac baselines to mac-leopard',
+ ' FIXME: Add support for moving existing baselines',
+ ])
+
+ def test_image_rebaseline(self):
+ self._assertRebaseline(
+ test_files=(
+ 'fast/image-expected.txt',
+ 'platform/mac/fast/image-expected.png',
+ 'platform/mac/fast/image-expected.checksum',
+ ),
+ results_files=(
+ 'fast/image-actual.png',
+ 'fast/image-actual.checksum',
+ ),
+ test_name='fast/image.html',
+ baseline_target='mac',
+ baseline_move_to='none',
+ expected_success=True,
+ expected_log=[
+ 'Rebaselining fast/image...',
+ ' Updating baselines for mac',
+ ' Updated image-expected.checksum',
+ ' Updated image-expected.png',
+ ])
+
+ def _assertRebaseline(self, test_files, results_files, test_name, baseline_target, baseline_move_to, expected_success, expected_log):
+ log = []
+ test_config = get_test_config(test_files, results_files)
+ success = rebaselineserver._rebaseline_test(
+ test_name,
+ baseline_target,
+ baseline_move_to,
+ test_config,
+ log=lambda l: log.append(l))
+ self.assertEqual(expected_log, log)
+ self.assertEqual(expected_success, success)
+
+
+class GetActualResultFilesTest(unittest.TestCase):
+ def test(self):
+ test_config = get_test_config(result_files=(
+ 'fast/text-actual.txt',
+ 'fast2/text-actual.txt',
+ 'fast/text2-actual.txt',
+ 'fast/text-notactual.txt',
+ ))
+ self.assertEqual(
+ ('text-actual.txt',),
+ rebaselineserver._get_actual_result_files(
+ 'fast/text.html', test_config))
class GetBaselinesTest(unittest.TestCase):
@@ -79,21 +187,31 @@ class GetBaselinesTest(unittest.TestCase):
expected_baselines={'base': {'.txt': True}})
def _assertBaselines(self, test_files, test_name, expected_baselines):
- layout_tests_directory = base.Port().layout_tests_dir()
- mock_filesystem = filesystem_mock.MockFileSystem()
- for file in test_files + (test_name,):
- file_path = mock_filesystem.join(layout_tests_directory, file)
- mock_filesystem.files[file_path] = ''
-
- class TestMacPort(WebKitPort):
- def __init__(self):
- WebKitPort.__init__(self, filesystem=mock_filesystem)
- self._name = 'mac'
-
actual_baselines = rebaselineserver._get_test_baselines(
- test_name,
- TestMacPort(),
- layout_tests_directory,
- ('mac', 'win', 'linux'),
- mock_filesystem)
+ test_name, get_test_config(test_files))
self.assertEqual(expected_baselines, actual_baselines)
+
+
+def get_test_config(test_files=[], result_files=[]):
+ layout_tests_directory = base.Port().layout_tests_dir()
+ results_directory = '/WebKitBuild/Debug/layout-test-results'
+ mock_filesystem = filesystem_mock.MockFileSystem()
+ for file in test_files:
+ file_path = mock_filesystem.join(layout_tests_directory, file)
+ mock_filesystem.files[file_path] = ''
+ for file in result_files:
+ file_path = mock_filesystem.join(results_directory, file)
+ mock_filesystem.files[file_path] = ''
+
+ class TestMacPort(WebKitPort):
+ def __init__(self):
+ WebKitPort.__init__(self, filesystem=mock_filesystem)
+ self._name = 'mac'
+
+ return rebaselineserver.TestConfig(
+ TestMacPort(),
+ layout_tests_directory,
+ results_directory,
+ ('mac', 'win', 'linux'),
+ mock_filesystem,
+ MockSCM())
diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool.py b/WebKitTools/Scripts/webkitpy/tool/mocktool.py
index 719f9b1..0040b1f 100644
--- a/WebKitTools/Scripts/webkitpy/tool/mocktool.py
+++ b/WebKitTools/Scripts/webkitpy/tool/mocktool.py
@@ -449,6 +449,10 @@ class MockSCM(Mock):
def svn_revision_from_commit_text(self, commit_text):
return "49824"
+ def add(self, destination_path, return_exit_code=False):
+ if return_exit_code:
+ return 0
+
class MockCheckout(object):
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list