summaryrefslogtreecommitdiff
path: root/Tools/Scripts/webkitpy
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy')
-rw-r--r--Tools/Scripts/webkitpy/bindings/main.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/changelog.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py85
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/git.py26
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py51
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers.py14
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers_unittest.py187
-rwxr-xr-xTools/Scripts/webkitpy/common/config/watchlist22
-rw-r--r--Tools/Scripts/webkitpy/common/system/filesystem_mock.py2
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py13
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/base.py79
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py48
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/builders.py15
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/chromium.py36
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py34
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py119
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py134
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py3
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/driver.py73
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/factory.py7
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py18
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/gtk.py9
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py5
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/test.py23
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/webkit.py19
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py2
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py8
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/servers/http_server.py8
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/views/printing.py15
-rw-r--r--Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py6
-rwxr-xr-xTools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py8
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/changelog.py8
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/changelog_unittest.py8
-rw-r--r--Tools/Scripts/webkitpy/test/main.py3
-rw-r--r--Tools/Scripts/webkitpy/thirdparty/__init__.py6
-rw-r--r--Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py1044
-rw-r--r--Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests_unittest.py387
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py5
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py1
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/rebaseline.py45
-rw-r--r--Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py84
-rw-r--r--Tools/Scripts/webkitpy/tool/servers/gardeningserver.py11
-rw-r--r--Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py8
-rw-r--r--Tools/Scripts/webkitpy/tool/steps/options.py8
46 files changed, 743 insertions, 1956 deletions
diff --git a/Tools/Scripts/webkitpy/bindings/main.py b/Tools/Scripts/webkitpy/bindings/main.py
index 5154f399b..15884bb73 100644
--- a/Tools/Scripts/webkitpy/bindings/main.py
+++ b/Tools/Scripts/webkitpy/bindings/main.py
@@ -73,7 +73,7 @@ class BindingsTests:
cmd = ['perl', '-w',
'-IWebCore/bindings/scripts',
- 'WebCore/bindings/scripts/resolve-supplemental.pl',
+ 'WebCore/bindings/scripts/preprocess-idls.pl',
'--idlFilesList', idl_files_list[1],
'--defines', '',
'--supplementalDependencyFile', supplemental_dependency_file,
diff --git a/Tools/Scripts/webkitpy/common/checkout/changelog.py b/Tools/Scripts/webkitpy/common/checkout/changelog.py
index fd41871a0..55b05982b 100644
--- a/Tools/Scripts/webkitpy/common/checkout/changelog.py
+++ b/Tools/Scripts/webkitpy/common/checkout/changelog.py
@@ -263,7 +263,7 @@ class ChangeLog(object):
entry_lines.append(line)
return None # We never found a date line!
- svn_blame_regexp = re.compile(r'^(\s*(?P<revision>\d+) [^ ]+)\s(?P<line>.*?\n)')
+ svn_blame_regexp = re.compile(r'^(\s*(?P<revision>\d+) [^ ]+)\s*(?P<line>.*?\n)')
@staticmethod
def _separate_revision_and_line(line):
diff --git a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py b/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
index db4a55b06..431c86701 100644
--- a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py
@@ -250,39 +250,40 @@ class ChangeLogTest(unittest.TestCase):
self.assertEquals(parsed_entries[8].reviewer_text(), 'Darin Adler')
def test_parse_log_entries_from_annotated_file(self):
- changelog_file = StringIO(u'''100000 ossy@webkit.org 2011-11-11 Csaba Osztrogon\u00e1c <ossy@webkit.org>
-100000 ossy@webkit.org
-100000 ossy@webkit.org 100,000 !!!
-100000 ossy@webkit.org
-100000 ossy@webkit.org Reviewed by Zoltan Herczeg.
-100000 ossy@webkit.org
-100000 ossy@webkit.org * ChangeLog: Point out revision 100,000.
-100000 ossy@webkit.org
-93798 ap@apple.com 2011-08-25 Alexey Proskuryakov <ap@apple.com>
-93798 ap@apple.com
-93798 ap@apple.com Fix build when GCC 4.2 is not installed.
-93798 ap@apple.com
-93798 ap@apple.com * gtest/xcode/Config/CompilerVersion.xcconfig: Copied from Source/WebCore/Configurations/CompilerVersion.xcconfig.
-93798 ap@apple.com * gtest/xcode/Config/General.xcconfig:
-93798 ap@apple.com Use the same compiler version as other projects do.
-93798 ap@apple.com
-99491 andreas.kling@nokia.com 2011-11-03 Andreas Kling <kling@webkit.org>
-99491 andreas.kling@nokia.com
-99190 andreas.kling@nokia.com Unreviewed build fix, sigh.
-99190 andreas.kling@nokia.com
-99190 andreas.kling@nokia.com * css/CSSFontFaceRule.h:
-99190 andreas.kling@nokia.com * css/CSSMutableStyleDeclaration.h:
-99190 andreas.kling@nokia.com
-99190 andreas.kling@nokia.com 2011-11-03 Andreas Kling <kling@webkit.org>
-99190 andreas.kling@nokia.com
-99187 andreas.kling@nokia.com Unreviewed build fix, out-of-line StyleSheet::parentStyleSheet()
-99187 andreas.kling@nokia.com again since there's a cycle in the includes between CSSRule/StyleSheet.
-99187 andreas.kling@nokia.com
-99187 andreas.kling@nokia.com * css/StyleSheet.cpp:
-99187 andreas.kling@nokia.com (WebCore::StyleSheet::parentStyleSheet):
-99187 andreas.kling@nokia.com * css/StyleSheet.h:
-99187 andreas.kling@nokia.com
-''')
+ # Note that there are trailing spaces on some of the lines intentionally.
+ changelog_file = StringIO(u"100000 ossy@webkit.org 2011-11-11 Csaba Osztrogon\u00e1c <ossy@webkit.org>\n"
+ u"100000 ossy@webkit.org\n"
+ u"100000 ossy@webkit.org 100,000 !!!\n"
+ u"100000 ossy@webkit.org \n"
+ u"100000 ossy@webkit.org Reviewed by Zoltan Herczeg.\n"
+ u"100000 ossy@webkit.org \n"
+ u"100000 ossy@webkit.org * ChangeLog: Point out revision 100,000.\n"
+ u"100000 ossy@webkit.org \n"
+ u"93798 ap@apple.com 2011-08-25 Alexey Proskuryakov <ap@apple.com>\n"
+ u"93798 ap@apple.com \n"
+ u"93798 ap@apple.com Fix build when GCC 4.2 is not installed.\n"
+ u"93798 ap@apple.com \n"
+ u"93798 ap@apple.com * gtest/xcode/Config/CompilerVersion.xcconfig: Copied from Source/WebCore/Configurations/CompilerVersion.xcconfig.\n"
+ u"93798 ap@apple.com * gtest/xcode/Config/General.xcconfig:\n"
+ u"93798 ap@apple.com Use the same compiler version as other projects do.\n"
+ u"93798 ap@apple.com\n"
+ u"99491 andreas.kling@nokia.com 2011-11-03 Andreas Kling <kling@webkit.org>\n"
+ u"99491 andreas.kling@nokia.com \n"
+ u"99190 andreas.kling@nokia.com Unreviewed build fix, sigh.\n"
+ u"99190 andreas.kling@nokia.com \n"
+ u"99190 andreas.kling@nokia.com * css/CSSFontFaceRule.h:\n"
+ u"99190 andreas.kling@nokia.com * css/CSSMutableStyleDeclaration.h:\n"
+ u"99190 andreas.kling@nokia.com\n"
+ u"99190 andreas.kling@nokia.com 2011-11-03 Andreas Kling <kling@webkit.org>\n"
+ u"99190 andreas.kling@nokia.com \n"
+ u"99187 andreas.kling@nokia.com Unreviewed build fix, out-of-line StyleSheet::parentStyleSheet()\n"
+ u"99187 andreas.kling@nokia.com again since there's a cycle in the includes between CSSRule/StyleSheet.\n"
+ u"99187 andreas.kling@nokia.com \n"
+ u"99187 andreas.kling@nokia.com * css/StyleSheet.cpp:\n"
+ u"99187 andreas.kling@nokia.com (WebCore::StyleSheet::parentStyleSheet):\n"
+ u"99187 andreas.kling@nokia.com * css/StyleSheet.h:\n"
+ u"99187 andreas.kling@nokia.com \n")
+
parsed_entries = list(ChangeLog.parse_entries_from_file(changelog_file))
self.assertEquals(parsed_entries[0].revision(), 100000)
self.assertEquals(parsed_entries[0].reviewer_text(), "Zoltan Herczeg")
@@ -390,17 +391,27 @@ class ChangeLogTest(unittest.TestCase):
self.assertEquals(reviewer_text_list, expected_text_list)
self.assertEquals(self._entry_with_reviewer(reviewer_text).reviewers(), self._contributors(expected_contributors))
- def test_fuzzy_reviewer_match(self):
- self._assert_fuzzy_reviewer_match('Reviewed by Dimitri Glazkov, build fix', ['Dimitri Glazkov', 'build fix'], ['Dimitri Glazkov'])
+ def test_fuzzy_reviewer_match__none(self):
self._assert_fuzzy_reviewer_match('Reviewed by BUILD FIX', ['BUILD FIX'], [])
self._assert_fuzzy_reviewer_match('Reviewed by Mac build fix', ['Mac build fix'], [])
+
+ def test_fuzzy_reviewer_match_adam_barth(self):
+ self._assert_fuzzy_reviewer_match('Reviewed by Adam Barth.:w', ['Adam Barth.:w'], ['Adam Barth'])
+
+ def test_fuzzy_reviewer_match_darin_adler_et_al(self):
+ self._assert_fuzzy_reviewer_match('Reviewed by Darin Adler in <https://bugs.webkit.org/show_bug.cgi?id=47736>.', ['Darin Adler in'], ['Darin Adler'])
self._assert_fuzzy_reviewer_match('Reviewed by Darin Adler, Dan Bernstein, Adele Peterson, and others.',
['Darin Adler', 'Dan Bernstein', 'Adele Peterson', 'others'], ['Darin Adler', 'Dan Bernstein', 'Adele Peterson'])
+
+ def test_fuzzy_reviewer_match_dimitri_glazkov(self):
+ self._assert_fuzzy_reviewer_match('Reviewed by Dimitri Glazkov, build fix', ['Dimitri Glazkov', 'build fix'], ['Dimitri Glazkov'])
+
+ def test_fuzzy_reviewer_match_george_staikos(self):
self._assert_fuzzy_reviewer_match('Reviewed by George Staikos (and others)', ['George Staikos', 'others'], ['George Staikos'])
+
+ def test_fuzzy_reviewer_match_mark_rowe(self):
self._assert_fuzzy_reviewer_match('Reviewed by Mark Rowe, but Dan Bernstein also reviewed and asked thoughtful questions.',
['Mark Rowe', 'but Dan Bernstein also reviewed', 'asked thoughtful questions'], ['Mark Rowe'])
- self._assert_fuzzy_reviewer_match('Reviewed by Darin Adler in <https://bugs.webkit.org/show_bug.cgi?id=47736>.', ['Darin Adler in'], ['Darin Adler'])
- self._assert_fuzzy_reviewer_match('Reviewed by Adam Barth.:w', ['Adam Barth.:w'], ['Adam Barth'])
def _assert_parse_authors(self, author_text, expected_contributors):
parsed_authors = [(author['name'], author['email']) for author in self._entry_with_author(author_text).authors()]
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
index 7c5d80cc3..c7dbd7ca1 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/git.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -170,11 +170,28 @@ class Git(SCM, SVNRepository):
return_code = self.run(["git", "show", "HEAD:%s" % path], return_exit_code=True, decode_output=False)
return return_code != self.ERROR_FILE_IS_MISSING
+ def _branch_from_ref(self, ref):
+ return ref.replace('refs/heads/', '')
+
+ def _current_branch(self):
+ return self._branch_from_ref(self.run(['git', 'symbolic-ref', '-q', 'HEAD'], cwd=self.checkout_root).strip())
+
+ def _upstream_branch(self):
+ current_branch = self._current_branch()
+ return self._branch_from_ref(self.read_git_config('branch.%s.merge' % current_branch, cwd=self.checkout_root).strip())
+
def merge_base(self, git_commit):
if git_commit:
- # Special-case HEAD.. to mean working-copy changes only.
- if git_commit.upper() == 'HEAD..':
- return 'HEAD'
+ # Rewrite UPSTREAM to the upstream branch
+ if 'UPSTREAM' in git_commit:
+ upstream = self._upstream_branch()
+ if not upstream:
+ raise ScriptError(message='No upstream/tracking branch set.')
+ git_commit = git_commit.replace('UPSTREAM', upstream)
+
+ # Special-case <refname>.. to include working copy changes, e.g., 'HEAD....' shows only the diffs from HEAD.
+ if git_commit.endswith('....'):
+ return git_commit[:-4]
if '..' not in git_commit:
git_commit = git_commit + "^.." + git_commit
@@ -350,8 +367,7 @@ class Git(SCM, SVNRepository):
return self.push_local_commits_to_server(username=username, password=password)
def _commit_on_branch(self, message, git_commit, username=None, password=None):
- branch_ref = self.run(['git', 'symbolic-ref', 'HEAD']).strip()
- branch_name = branch_ref.replace('refs/heads/', '')
+ branch_name = self._current_branch()
commit_ids = self.commit_ids_from_commitish_arguments([git_commit])
# We want to squash all this branch's commits into one commit with the proper description.
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
index 4b88c3da1..7ce714a19 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
@@ -1167,9 +1167,12 @@ class GitSVNTest(SCMTest):
write_into_file_at_path('test_file_commit2', 'still more test content')
run_command(['git', 'add', 'test_file_commit2'])
+ def _second_local_commit(self):
+ self._local_commit('test_file_commit2', 'still more test content', 'yet another test commit')
+
def _two_local_commits(self):
self._one_local_commit()
- self._local_commit('test_file_commit2', 'still more test content', 'yet another test commit')
+ self._second_local_commt()
def _three_local_commits(self):
self._local_commit('test_file_commit0', 'more test content', 'another test commit')
@@ -1213,13 +1216,6 @@ class GitSVNTest(SCMTest):
self.assertTrue(re.search(r'test_file_commit1', svn_log))
self.assertTrue(re.search(r'test_file_commit2', svn_log))
- def test_changed_files_working_copy_only(self):
- self._one_local_commit_plus_working_copy_changes()
- scm = detect_scm_system(self.git_checkout_path)
- commit_text = scm.commit_with_message("another test commit", git_commit="HEAD..")
- self.assertFalse(re.search(r'test_file_commit1', svn_log))
- self.assertTrue(re.search(r'test_file_commit2', svn_log))
-
def test_commit_with_message_only_local_commit(self):
self._one_local_commit()
scm = detect_scm_system(self.git_checkout_path)
@@ -1291,6 +1287,11 @@ class GitSVNTest(SCMTest):
# There's a conflict between trunk and the test_file2 modification.
self.assertRaises(ScriptError, scm.commit_with_message, "another test commit", force_squash=True)
+ def test_upstream_branch(self):
+ run_command(['git', 'checkout', '-t', '-b', 'my-branch'])
+ run_command(['git', 'checkout', '-t', '-b', 'my-second-branch'])
+ self.assertEquals(self.scm._upstream_branch(), 'my-branch')
+
def test_remote_branch_ref(self):
self.assertEqual(self.scm.remote_branch_ref(), 'refs/remotes/trunk')
@@ -1360,7 +1361,7 @@ class GitSVNTest(SCMTest):
def test_create_patch_working_copy_only(self):
self._one_local_commit_plus_working_copy_changes()
scm = detect_scm_system(self.git_checkout_path)
- patch = scm.create_patch(git_commit="HEAD..")
+ patch = scm.create_patch(git_commit="HEAD....")
self.assertFalse(re.search(r'test_file_commit1', patch))
self.assertTrue(re.search(r'test_file_commit2', patch))
@@ -1413,6 +1414,16 @@ class GitSVNTest(SCMTest):
self.assertTrue('test_file_commit1' in files)
self.assertTrue('test_file_commit2' in files)
+ # working copy should *not* be in the list.
+ files = scm.changed_files('trunk..')
+ self.assertTrue('test_file_commit1' in files)
+ self.assertFalse('test_file_commit2' in files)
+
+ # working copy *should* be in the list.
+ files = scm.changed_files('trunk....')
+ self.assertTrue('test_file_commit1' in files)
+ self.assertTrue('test_file_commit2' in files)
+
def test_changed_files_git_commit(self):
self._two_local_commits()
scm = detect_scm_system(self.git_checkout_path)
@@ -1431,7 +1442,7 @@ class GitSVNTest(SCMTest):
def test_changed_files_working_copy_only(self):
self._one_local_commit_plus_working_copy_changes()
scm = detect_scm_system(self.git_checkout_path)
- files = scm.changed_files(git_commit="HEAD..")
+ files = scm.changed_files(git_commit="HEAD....")
self.assertFalse('test_file_commit1' in files)
self.assertTrue('test_file_commit2' in files)
@@ -1466,6 +1477,26 @@ class GitSVNTest(SCMTest):
def test_changed_files_for_revision(self):
self._shared_test_changed_files_for_revision()
+ def test_changed_files_upstream(self):
+ run_command(['git', 'checkout', '-t', '-b', 'my-branch'])
+ self._one_local_commit()
+ run_command(['git', 'checkout', '-t', '-b', 'my-second-branch'])
+ self._second_local_commit()
+ write_into_file_at_path('test_file_commit0', 'more test content')
+ run_command(['git', 'add', 'test_file_commit0'])
+
+ # equivalent to 'git diff my-branch..HEAD, should not include working changes
+ files = self.scm.changed_files(git_commit='UPSTREAM..')
+ self.assertFalse('test_file_commit1' in files)
+ self.assertTrue('test_file_commit2' in files)
+ self.assertFalse('test_file_commit0' in files)
+
+ # equivalent to 'git diff my-branch', *should* include working changes
+ files = self.scm.changed_files(git_commit='UPSTREAM....')
+ self.assertFalse('test_file_commit1' in files)
+ self.assertTrue('test_file_commit2' in files)
+ self.assertTrue('test_file_commit0' in files)
+
def test_contents_at_revision(self):
self._shared_test_contents_at_revision()
diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py
index 54dbbed80..f646db7a9 100644
--- a/Tools/Scripts/webkitpy/common/config/committers.py
+++ b/Tools/Scripts/webkitpy/common/config/committers.py
@@ -141,7 +141,6 @@ contributors_who_are_not_committers = [
Contributor("Peter Linss", "peter.linss@hp.com", "plinss"),
Contributor("Radar WebKit Bug Importer", "webkit-bug-importer@group.apple.com"),
Contributor("Roland Takacs", "takacs.roland@stud.u-szeged.hu", "rtakacs"),
- Contributor("Stephen Chenney", "schenney@chromium.org", "schenney"),
Contributor("Szilard Ledan-Muntean", "muntean-ledan.szilard@stud.u-szeged.hu", "szledan"),
Contributor("Tab Atkins", ["tabatkins@google.com", "jackalmage@gmail.com"], "tabatkins"),
Contributor("Tamas Czene", ["tczene@inf.u-szeged.hu", "Czene.Tamas@stud.u-szeged.hu"], "tczene"),
@@ -164,8 +163,8 @@ committers_unable_to_review = [
Committer("Adam Klein", "adamk@chromium.org", "aklein"),
Committer("Adam Langley", "agl@chromium.org", "agl"),
Committer("Ademar de Souza Reis Jr", ["ademar.reis@gmail.com", "ademar@webkit.org"], "ademar"),
- Committer("Adrienne Walker", ["enne@google.com", "enne@chromium.org"], "enne"),
Committer("Albert J. Wong", "ajwong@chromium.org"),
+ Committer(u"Alexander F\u00e6r\u00f8y", ["ahf@0x90.dk", "alexander.faeroy@nokia.com"], "ahf"),
Committer("Alexander Kellett", ["lypanov@mac.com", "a-lists001@lypanov.net", "lypanov@kde.org"], "lypanov"),
Committer("Alexander Pavlov", "apavlov@chromium.org", "apavlov"),
Committer("Alexandru Chiculita", "achicu@adobe.com", "achicu"),
@@ -198,6 +197,7 @@ committers_unable_to_review = [
Committer("Carlos Garcia Campos", ["cgarcia@igalia.com", "carlosgc@gnome.org", "carlosgc@webkit.org"], "KaL"),
Committer("Carol Szabo", ["carol@webkit.org", "carol.szabo@nokia.com"], "cszabo1"),
Committer("Cary Clark", ["caryclark@google.com", "caryclark@chromium.org"], "caryclark"),
+ Committer("Charles Wei", ["charles.wei@torchmobile.com.cn"], "cswei"),
Committer("Chris Evans", ["cevans@google.com", "cevans@chromium.org"]),
Committer("Chris Guillory", ["ctguil@chromium.org", "chris.guillory@google.com"], "ctguil"),
Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"),
@@ -234,7 +234,7 @@ committers_unable_to_review = [
Committer("Hayato Ito", "hayato@chromium.org", "hayato"),
Committer("Helder Correia", "helder@sencha.com", "helder"),
Committer("Hin-Chung Lam", ["hclam@google.com", "hclam@chromium.org"]),
- Committer("Igor Trindade Oliveira", ["igor.oliveira@webkit.org", "igor.oliveira@openbossa.org"], "igoroliveira"),
+ Committer("Igor Trindade Oliveira", ["igor.oliveira@webkit.org", "igor.o@sisa.samsung.com"], "igoroliveira"),
Committer("Ilya Sherman", "isherman@chromium.org", "isherman"),
Committer("Ilya Tikhonovsky", "loislo@chromium.org", "loislo"),
Committer("Ivan Krsti\u0107", "ike@apple.com"),
@@ -251,7 +251,6 @@ committers_unable_to_review = [
Committer("Jens Alfke", ["snej@chromium.org", "jens@apple.com"]),
Committer("Jer Noble", "jer.noble@apple.com", "jernoble"),
Committer("Jeremy Moskovich", ["playmobil@google.com", "jeremy@chromium.org"], "jeremymos"),
- Committer("Jessie Berlin", ["jberlin@webkit.org", "jberlin@apple.com"]),
Committer("Jesus Sanchez-Palencia", ["jesus@webkit.org", "jesus.palencia@openbossa.org"], "jeez_"),
Committer("Jia Pu", "jpu@apple.com"),
Committer("Jocelyn Turcotte", "jocelyn.turcotte@nokia.com", "jturcotte"),
@@ -334,6 +333,7 @@ committers_unable_to_review = [
Committer("Shawn Singh", "shawnsingh@chromium.org", "shawnsingh"),
Committer("Shinya Kawanaka", "shinyak@chromium.org", "shinyak"),
Committer("Siddharth Mathur", "siddharth.mathur@nokia.com", "simathur"),
+ Committer("Stephen Chenney", "schenney@chromium.org", "schenney"),
Committer("Steve Lacey", "sjl@chromium.org", "stevela"),
Committer("Takashi Toyoshima", "toyoshim@chromium.org", "toyoshim"),
Committer("Thomas Sepez", "tsepez@chromium.org", "tsepez"),
@@ -374,10 +374,11 @@ committers_unable_to_review = [
reviewers_list = [
Reviewer("Ada Chan", "adachan@apple.com", "chanada"),
Reviewer("Adam Barth", "abarth@webkit.org", "abarth"),
- Reviewer("Adam Roben", "aroben@apple.com", "aroben"),
+ Reviewer("Adam Roben", ["aroben@webkit.org", "aroben@apple.com"], "aroben"),
Reviewer("Adam Treat", ["treat@kde.org", "treat@webkit.org", "atreat@rim.com"], "manyoso"),
- Reviewer("Alejandro G. Castro", ["alex@igalia.com", "alex@webkit.org"], "alexg__"),
Reviewer("Adele Peterson", "adele@apple.com", "adele"),
+ Reviewer("Adrienne Walker", ["enne@google.com", "enne@chromium.org"], "enne"),
+ Reviewer("Alejandro G. Castro", ["alex@igalia.com", "alex@webkit.org"], "alexg__"),
Reviewer("Alexey Proskuryakov", ["ap@webkit.org", "ap@apple.com"], "ap"),
Reviewer("Alice Liu", "alice.liu@apple.com", "aliu"),
Reviewer("Alp Toker", ["alp@nuanti.com", "alp@atoker.com", "alp@webkit.org"], "alp"),
@@ -428,6 +429,7 @@ reviewers_list = [
Reviewer("James Robinson", ["jamesr@chromium.org", "jamesr@google.com"], "jamesr"),
Reviewer("Jan Alonzo", ["jmalonzo@gmail.com", "jmalonzo@webkit.org"], "janm"),
Reviewer("Jeremy Orlow", ["jorlow@webkit.org", "jorlow@chromium.org"], "jorlow"),
+ Reviewer("Jessie Berlin", ["jberlin@webkit.org", "jberlin@apple.com"], "jessieberlin"),
Reviewer("Jian Li", "jianli@chromium.org", "jianli"),
Reviewer("John Sullivan", "sullivan@apple.com", "sullivan"),
Reviewer("Jon Honeycutt", "jhoneycutt@apple.com", "jhoneycutt"),
diff --git a/Tools/Scripts/webkitpy/common/config/committers_unittest.py b/Tools/Scripts/webkitpy/common/config/committers_unittest.py
index 53d9c4d14..1c8c86a1a 100644
--- a/Tools/Scripts/webkitpy/common/config/committers_unittest.py
+++ b/Tools/Scripts/webkitpy/common/config/committers_unittest.py
@@ -7,8 +7,7 @@
# * 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
+# 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
@@ -110,141 +109,205 @@ class CommittersTest(unittest.TestCase):
expected_names = [name_of_expected_contributor] if name_of_expected_contributor else []
self.assertEqual(([contributor.full_name for contributor in contributors], distance), (expected_names, expected_distance))
+ # Basic testing of the edit distance matching ...
def test_contributors_by_fuzzy_match(self):
self._assert_fuzz_match('Geoff Garen', 'Geoffrey Garen', 3)
self._assert_fuzz_match('Kenneth Christiansen', 'Kenneth Rohde Christiansen', 6)
- self._assert_fuzz_match('Ken Russell', 'Kenneth Russell', 4)
- self._assert_fuzz_match('Dave Hyatt', 'David Hyatt', 2)
- self._assert_fuzz_match('Dave Kilzer', 'David Kilzer', 2)
- self._assert_fuzz_match('Antti "printf" Koivisto', 'Antti Koivisto', 9)
- self._assert_fuzz_match('Sammy Weinig', 'Sam Weinig', 2)
- self._assert_fuzz_match('Andres Kling', 'Andreas Kling', 1)
- self._assert_fuzz_match('Darin Adler\'', 'Darin Adler', 1)
- self._assert_fuzz_match('Joe Pecoraro', 'Joseph Pecoraro', 3)
- self._assert_fuzz_match('Dr Dan Bernstein', 'Dan Bernstein', 3)
- self._assert_fuzz_match('Mitzpettel', 'Dan Bernstein', 0)
- self._assert_fuzz_match('rniwa@webkit.org', 'Ryosuke Niwa', 0)
- self._assert_fuzz_match('Ap', 'Alexey Proskuryakov', 0)
self._assert_fuzz_match('Sam', 'Sam Weinig', 0)
- self._assert_fuzz_match('darin', 'Darin Adler', 0)
- self._assert_fuzz_match('harrison', 'David Harrison', 0)
self._assert_fuzz_match('me', None, 2)
+
+ # The remaining tests test that certain names are resolved in a specific way.
+ # We break this up into multiple tests so that each is faster and they can
+ # be run in parallel. Unfortunately each test scans the entire committers list,
+ # so these are inherently slow (see https://bugs.webkit.org/show_bug.cgi?id=79179).
+ #
+ # Commented out lines are test cases imported from the bug 26533 yet to pass.
+
+ def integration_test_contributors__none(self):
self._assert_fuzz_match('myself', None, 6)
self._assert_fuzz_match('others', None, 6)
self._assert_fuzz_match('BUILD FIX', None, 9)
+
+ def integration_test_contributors__none_2(self):
self._assert_fuzz_match('but Dan Bernstein also reviewed', None, 31)
self._assert_fuzz_match('asked thoughtful questions', None, 26)
self._assert_fuzz_match('build fix of mac', None, 16)
+
+ def integration_test_contributors__none_3(self):
self._assert_fuzz_match('a spell checker', None, 15)
self._assert_fuzz_match('nobody, build fix', None, 17)
self._assert_fuzz_match('NOBODY (chromium build fix)', None, 27)
- def test_contributors_by_fuzzy_match_with_legacy_names(self):
- # Commented out lines are test cases imported from the bug 26533 yet to pass.
-
+ def integration_test_contributors_ada_chan(self):
self._assert_fuzz_match('Ada', 'Ada Chan', 0)
+
+ def integration_test_contributors_adele_peterson(self):
self._assert_fuzz_match('adele', 'Adele Peterson', 0)
-# self._assert_fuzz_match('Adam', 'Adam Roben', 0)
+
+ def integration_test_contributors_adele_peterson(self):
+ # self._assert_fuzz_match('Adam', 'Adam Roben', 0)
self._assert_fuzz_match('aroben', 'Adam Roben', 0)
-# self._assert_fuzz_match('Alexey', 'Alexey Proskuryakov', 0)
+
+ def integration_test_contributors_alexey_proskuryakov(self):
+ # self._assert_fuzz_match('Alexey', 'Alexey Proskuryakov', 0)
self._assert_fuzz_match('ap', 'Alexey Proskuryakov', 0)
self._assert_fuzz_match('Alexey P', 'Alexey Proskuryakov', 0)
-# self._assert_fuzz_match('Alice', 'Alice Liu', 0)
+
+ def integration_test_contributors_alice_liu(self):
+ # self._assert_fuzz_match('Alice', 'Alice Liu', 0)
self._assert_fuzz_match('aliu', 'Alice Liu', 0)
self._assert_fuzz_match('Liu', 'Alice Liu', 0)
+
+ def integration_test_contributors_alp_toker(self):
self._assert_fuzz_match('Alp', 'Alp Toker', 0)
+
+ def integration_test_contributors_anders_carlsson(self):
self._assert_fuzz_match('Anders', 'Anders Carlsson', 0)
self._assert_fuzz_match('andersca', 'Anders Carlsson', 0)
self._assert_fuzz_match('anders', 'Anders Carlsson', 0)
self._assert_fuzz_match('Andersca', 'Anders Carlsson', 0)
+
+ def integration_test_contributors_antti_koivisto(self):
+ self._assert_fuzz_match('Antti "printf" Koivisto', 'Antti Koivisto', 9)
self._assert_fuzz_match('Antti', 'Antti Koivisto', 0)
+ def integration_test_contributors_beth_dakin(self):
self._assert_fuzz_match('Beth', 'Beth Dakin', 0)
self._assert_fuzz_match('beth', 'Beth Dakin', 0)
self._assert_fuzz_match('bdakin', 'Beth Dakin', 0)
+
+ def integration_test_contributors_brady_eidson(self):
self._assert_fuzz_match('Brady', 'Brady Eidson', 0)
self._assert_fuzz_match('bradee-oh', 'Brady Eidson', 0)
+ self._assert_fuzz_match('Brady', 'Brady Eidson', 0)
+
+ def integration_test_contributors_cameron_zwarich(self):
+ pass # self._assert_fuzz_match('Cameron', 'Cameron Zwarich', 0)
+ # self._assert_fuzz_match('cpst', 'Cameron Zwarich', 1)
-# self._assert_fuzz_match('Cameron', 'Cameron Zwarich', 0)
-# self._assert_fuzz_match('cpst', 'Cameron Zwarich', 1)
-# self._assert_fuzz_match('Chris', 'Chris Blumenberg', 0)
+ def integration_test_contributors_chris_blumenberg(self):
+ # self._assert_fuzz_match('Chris', 'Chris Blumenberg', 0)
self._assert_fuzz_match('cblu', 'Chris Blumenberg', 0)
+ def integration_test_contributors_dan_bernstein(self):
self._assert_fuzz_match('Dan', ['Dan Winship', 'Dan Bernstein'], 0)
self._assert_fuzz_match('Dan B', 'Dan Bernstein', 0)
-# self._assert_fuzz_match('mitz', 'Dan Bernstein', 0)
+ # self._assert_fuzz_match('mitz', 'Dan Bernstein', 0)
self._assert_fuzz_match('Mitz Pettel', 'Dan Bernstein', 1)
self._assert_fuzz_match('Mitzpettel', 'Dan Bernstein', 0)
self._assert_fuzz_match('Mitz Pettel RTL', 'Dan Bernstein', 5)
+
+ def integration_test_contributors_dan_bernstein_2(self):
self._assert_fuzz_match('Teh Mitzpettel', 'Dan Bernstein', 4)
-# self._assert_fuzz_match('The Mitz', 'Dan Bernstein', 0)
+ # self._assert_fuzz_match('The Mitz', 'Dan Bernstein', 0)
+ self._assert_fuzz_match('Dr Dan Bernstein', 'Dan Bernstein', 3)
+ def integration_test_contributors_darin_adler(self):
+ self._assert_fuzz_match('Darin Adler\'', 'Darin Adler', 1)
self._assert_fuzz_match('Darin', 'Darin Adler', 0) # Thankfully "Fisher" is longer than "Adler"
+ self._assert_fuzz_match('darin', 'Darin Adler', 0)
+ def integration_test_contributors_david_harrison(self):
self._assert_fuzz_match('Dave Harrison', 'David Harrison', 2)
self._assert_fuzz_match('harrison', 'David Harrison', 0)
self._assert_fuzz_match('Dr. Harrison', 'David Harrison', 4)
+
+ def integration_test_contributors_david_harrison_2(self):
self._assert_fuzz_match('Dave Harrson', 'David Harrison', 3)
self._assert_fuzz_match('Dave Harrsion', 'David Harrison', 4) # Damerau-Levenshtein distance is 3
+ def integration_test_contributors_david_hyatt(self):
+ self._assert_fuzz_match('Dave Hyatt', 'David Hyatt', 2)
self._assert_fuzz_match('Daddy Hyatt', 'David Hyatt', 3)
-# self._assert_fuzz_match('Dave', 'David Hyatt', 0) # 'Dave' could mean harrison.
+ # self._assert_fuzz_match('Dave', 'David Hyatt', 0) # 'Dave' could mean harrison.
self._assert_fuzz_match('hyatt', 'David Hyatt', 0)
-# self._assert_fuzz_match('Haytt', 'David Hyatt', 0) # Works if we had implemented Damerau-Levenshtein distance!
+ # self._assert_fuzz_match('Haytt', 'David Hyatt', 0) # Works if we had implemented Damerau-Levenshtein distance!
+
+ def integration_test_contributors_david_kilzer(self):
self._assert_fuzz_match('Dave Kilzer', 'David Kilzer', 2)
self._assert_fuzz_match('David D. Kilzer', 'David Kilzer', 3)
self._assert_fuzz_match('ddkilzer', 'David Kilzer', 0)
+
+ def integration_test_contributors_don_melton(self):
self._assert_fuzz_match('Don', 'Don Melton', 0)
self._assert_fuzz_match('Gramps', 'Don Melton', 0)
-# self._assert_fuzz_match('eric', 'Eric Seidel', 0)
+ def integration_test_contributors_eric_seidel(self):
+ # self._assert_fuzz_match('eric', 'Eric Seidel', 0)
self._assert_fuzz_match('Eric S', 'Eric Seidel', 0)
-# self._assert_fuzz_match('MacDome', 'Eric Seidel', 0)
+ # self._assert_fuzz_match('MacDome', 'Eric Seidel', 0)
self._assert_fuzz_match('eseidel', 'Eric Seidel', 0)
-# self._assert_fuzz_match('Geof', 'Geoffrey Garen', 4)
-# self._assert_fuzz_match('Geoff', 'Geoffrey Garen', 3)
+ def integration_test_contributors_geoffrey_garen(self):
+ # self._assert_fuzz_match('Geof', 'Geoffrey Garen', 4)
+ # self._assert_fuzz_match('Geoff', 'Geoffrey Garen', 3)
self._assert_fuzz_match('Geoff Garen', 'Geoffrey Garen', 3)
self._assert_fuzz_match('ggaren', 'Geoffrey Garen', 0)
-# self._assert_fuzz_match('geoff', 'Geoffrey Garen', 0)
+ # self._assert_fuzz_match('geoff', 'Geoffrey Garen', 0)
self._assert_fuzz_match('Geoffrey', 'Geoffrey Garen', 0)
self._assert_fuzz_match('GGaren', 'Geoffrey Garen', 0)
-# self._assert_fuzz_match('Greg', 'Greg Bolsinga', 0)
+ def integration_test_contributors_greg_bolsinga(self):
+ pass # self._assert_fuzz_match('Greg', 'Greg Bolsinga', 0)
+
+ def integration_test_contributors_holger_freyther(self):
self._assert_fuzz_match('Holger', 'Holger Freyther', 0)
self._assert_fuzz_match('Holger Hans Peter Freyther', 'Holger Freyther', 11)
-# self._assert_fuzz_match('john', 'John Sullivan', 0)
+ def integration_test_contributors_jon_sullivan(self):
+ # self._assert_fuzz_match('john', 'John Sullivan', 0)
self._assert_fuzz_match('sullivan', 'John Sullivan', 0)
+
+ def integration_test_contributors_jon_honeycutt(self):
self._assert_fuzz_match('John Honeycutt', 'Jon Honeycutt', 1)
-# self._assert_fuzz_match('Jon', 'Jon Honeycutt', 0)
-# self._assert_fuzz_match('justin', 'Justin Garcia', 0)
+ # self._assert_fuzz_match('Jon', 'Jon Honeycutt', 0)
+
+ def integration_test_contributors_jon_honeycutt(self):
+ # self._assert_fuzz_match('justin', 'Justin Garcia', 0)
self._assert_fuzz_match('justing', 'Justin Garcia', 0)
+ def integration_test_contributors_joseph_pecoraro(self):
+ self._assert_fuzz_match('Joe Pecoraro', 'Joseph Pecoraro', 3)
+
+ def integration_test_contributors_ken_kocienda(self):
self._assert_fuzz_match('ken', 'Ken Kocienda', 0)
self._assert_fuzz_match('kocienda', 'Ken Kocienda', 0)
+
+ def integration_test_contributors_kenneth_russell(self):
+ self._assert_fuzz_match('Ken Russell', 'Kenneth Russell', 4)
+
+ def integration_test_contributors_kevin_decker(self):
self._assert_fuzz_match('kdecker', 'Kevin Decker', 0)
+
+ def integration_test_contributors_kevin_mccullough(self):
self._assert_fuzz_match('Kevin M', 'Kevin McCullough', 0)
self._assert_fuzz_match('Kevin McCulough', 'Kevin McCullough', 1)
self._assert_fuzz_match('mccullough', 'Kevin McCullough', 0)
+ def integration_test_contributors_lars_knoll(self):
self._assert_fuzz_match('lars', 'Lars Knoll', 0)
+
+ def integration_test_contributors_lars_weintraub(self):
self._assert_fuzz_match('levi', 'Levi Weintraub', 0)
+ def integration_test_contributors_maciej_stachowiak(self):
self._assert_fuzz_match('Maciej', 'Maciej Stachowiak', 0)
-# self._assert_fuzz_match('mjs', 'Maciej Stachowiak', 0)
+ # self._assert_fuzz_match('mjs', 'Maciej Stachowiak', 0)
self._assert_fuzz_match('Maciej S', 'Maciej Stachowiak', 0)
-# self._assert_fuzz_match('Mark', 'Mark Rowe', 0)
+ def integration_test_contributors_mark_rowe(self):
+ # self._assert_fuzz_match('Mark', 'Mark Rowe', 0)
self._assert_fuzz_match('bdash', 'Mark Rowe', 0)
self._assert_fuzz_match('mrowe', 'Mark Rowe', 0)
-# self._assert_fuzz_match('Brian Dash', 'Mark Rowe', 0)
+ # self._assert_fuzz_match('Brian Dash', 'Mark Rowe', 0)
-# self._assert_fuzz_match('Niko', 'Nikolas Zimmermann', 1)
+ def integration_test_contributors_nikolas_zimmermann(self):
+ # self._assert_fuzz_match('Niko', 'Nikolas Zimmermann', 1)
self._assert_fuzz_match('Niko Zimmermann', 'Nikolas Zimmermann', 3)
self._assert_fuzz_match('Nikolas', 'Nikolas Zimmermann', 0)
-# self._assert_fuzz_match('Oliver', 'Oliver Hunt', 0)
+ def integration_test_contributors_oliver_hunt(self):
+ # self._assert_fuzz_match('Oliver', 'Oliver Hunt', 0)
self._assert_fuzz_match('Ollie', 'Oliver Hunt', 1)
self._assert_fuzz_match('Olliej', 'Oliver Hunt', 0)
self._assert_fuzz_match('Olliej Hunt', 'Oliver Hunt', 3)
@@ -252,36 +315,54 @@ class CommittersTest(unittest.TestCase):
self._assert_fuzz_match('ollie', 'Oliver Hunt', 1)
self._assert_fuzz_match('ollliej', 'Oliver Hunt', 1)
+ def integration_test_contributors_oliver_hunt(self):
self._assert_fuzz_match('Richard', 'Richard Williamson', 0)
self._assert_fuzz_match('rjw', 'Richard Williamson', 0)
+
+ def integration_test_contributors_oliver_hunt(self):
self._assert_fuzz_match('Rob', 'Rob Buis', 0)
self._assert_fuzz_match('rwlbuis', 'Rob Buis', 0)
+ def integration_test_contributors_rniwa(self):
+ self._assert_fuzz_match('rniwa@webkit.org', 'Ryosuke Niwa', 0)
+
+ def disabled_integration_test_contributors_simon_fraser(self):
+ pass # self._assert_fuzz_match('Simon', 'Simon Fraser', 0)
+
+ def integration_test_contributors_steve_falkenburg(self):
+ self._assert_fuzz_match('Sfalken', 'Steve Falkenburg', 0)
+ # self._assert_fuzz_match('Steve', 'Steve Falkenburg', 0)
+
+ def integration_test_contributors_sam_weinig(self):
self._assert_fuzz_match('Sam', 'Sam Weinig', 0)
-# self._assert_fuzz_match('Weinig Sam', 'weinig', 0)
+ # self._assert_fuzz_match('Weinig Sam', 'weinig', 0)
self._assert_fuzz_match('Weinig', 'Sam Weinig', 0)
self._assert_fuzz_match('Sam W', 'Sam Weinig', 0)
self._assert_fuzz_match('Sammy Weinig', 'Sam Weinig', 2)
-# self._assert_fuzz_match('Simon', 'Simon Fraser', 0)
- self._assert_fuzz_match('Sfalken', 'Steve Falkenburg', 0)
-# self._assert_fuzz_match('Steve', 'Steve Falkenburg', 0)
-# self._assert_fuzz_match('timo', 'Tim Omernick', 0)
+ def integration_test_contributors_tim_omernick(self):
+ # self._assert_fuzz_match('timo', 'Tim Omernick', 0)
self._assert_fuzz_match('TimO', 'Tim Omernick', 0)
-# self._assert_fuzz_match('Timo O', 'Tim Omernick', 0)
-# self._assert_fuzz_match('Tim O.', 'Tim Omernick', 0)
+ # self._assert_fuzz_match('Timo O', 'Tim Omernick', 0)
+ # self._assert_fuzz_match('Tim O.', 'Tim Omernick', 0)
self._assert_fuzz_match('Tim O', 'Tim Omernick', 0)
-# self._assert_fuzz_match('Tim', 'Timothy Hatcher', 0)
-# self._assert_fuzz_match('Tim H', 'Timothy Hatcher', 0)
+ def integration_test_contributors_timothy_hatcher(self):
+ # self._assert_fuzz_match('Tim', 'Timothy Hatcher', 0)
+ # self._assert_fuzz_match('Tim H', 'Timothy Hatcher', 0)
self._assert_fuzz_match('Tim Hatcher', 'Timothy Hatcher', 4)
self._assert_fuzz_match('Tim Hatcheri', 'Timothy Hatcher', 5)
self._assert_fuzz_match('timothy', 'Timothy Hatcher', 0)
self._assert_fuzz_match('thatcher', 'Timothy Hatcher', 1)
self._assert_fuzz_match('xenon', 'Timothy Hatcher', 0)
self._assert_fuzz_match('Hatcher', 'Timothy Hatcher', 0)
-# self._assert_fuzz_match('TimH', 'Timothy Hatcher', 0)
+ # self._assert_fuzz_match('TimH', 'Timothy Hatcher', 0)
+ def integration_test_contributors_tor_arne_vestbo(self):
self._assert_fuzz_match('Tor Arne', u"Tor Arne Vestb\u00f8", 1) # Matches IRC nickname
+
+ def integration_test_contributors_vicki_murley(self):
self._assert_fuzz_match('Vicki', u"Vicki Murley", 0)
+
+ def integration_test_contributors_zack_rusin(self):
self._assert_fuzz_match('Zack', 'Zack Rusin', 0)
diff --git a/Tools/Scripts/webkitpy/common/config/watchlist b/Tools/Scripts/webkitpy/common/config/watchlist
index bf92f05da..dbdbd392d 100755
--- a/Tools/Scripts/webkitpy/common/config/watchlist
+++ b/Tools/Scripts/webkitpy/common/config/watchlist
@@ -21,14 +21,19 @@
"ChromiumPublicApi": {
"filename": r"Source/WebKit/chromium/public/"
},
+ "ChromiumPlatformApi": {
+ "filename": r"Source/Platform/chromium/public/"
+ },
"AppleMacPublicApi": {
"filename": r"Source/WebCore/bindings/objc/PublicDOMInterfaces.h"
},
"Forms": {
- "filename": r"Source/WebCore/html/HTML(FieldSet|Form|FormControl|Input|Label"
- r"|OptGroup|Option|Select|TextArea|TextFormControl)Element\."
+ "filename": r"Source/WebCore/html/HTML(DataList|FieldSet|Form|FormControl|Input|Keygen|Label"
+ r"|Legend|OptGroup|Option|Output|Select|TextArea|TextFormControl)Element\."
+ r"|Source/WebCore/html/FormAssociatedElement\."
r"|Source/WebCore/html/\w*InputType\."
- r"|Source/WebCore/rendering/Render(ListBox|MenuList|Slider|TextControl"
+ r"|Source/WebCore/html/shadow/(SliderThumbElement|TextControlInnerElements)\."
+ r"|Source/WebCore/rendering/Render(FileUploadControl|ListBox|MenuList|Slider|TextControl"
r"|TextControlMultiLine|TextControlSingleLine)\."
},
"GStreamerGraphics": {
@@ -133,6 +138,9 @@
"SoupNetwork": {
"filename": r"Source/WebCore/platform/network/soup/",
},
+ "ScrollingCoordinator": {
+ "filename": r"Source/WebCore/page/scrolling/",
+ }
},
"CC_RULES": {
# Note: All email addresses listed must be registered with bugzilla.
@@ -140,7 +148,8 @@
# two different accounts as far as bugzilla is concerned.
"ChromiumDumpRenderTree": [ "tkent@chromium.org", ],
"ChromiumGraphics": [ "jamesr@chromium.org", "cc-bugs@google.com" ],
- "ChromiumPublicApi": [ "fishd@chromium.org", ],
+ "ChromiumPublicApi": [ "abarth@webkit.org", "fishd@chromium.org" ],
+ "ChromiumPlatformApi": [ "abarth@webkit.org", "fishd@chromium.org", "jamesr@chromium.org" ],
"AppleMacPublicApi": [ "timothy@apple.com" ],
"Forms": [ "tkent@chromium.org", ],
"GStreamerGraphics": [ "alexis.menard@openbossa.org", "pnormand@igalia.com", "gns@gnome.org" ],
@@ -148,7 +157,7 @@
"StyleChecker": [ "levin@chromium.org", ],
"ThreadingFiles|ThreadingUsage": [ "levin+threading@chromium.org", ],
"WatchListScript": [ "levin+watchlist@chromium.org", ],
- "V8Bindings|BindingsScripts": [ "abarth@webkit.org", "japhet@chromium.org" ],
+ "V8Bindings|BindingsScripts": [ "abarth@webkit.org", "japhet@chromium.org", "haraken@chromium.org" ],
"FrameLoader": [ "abarth@webkit.org", "japhet@chromium.org" ],
"Loader": [ "japhet@chromium.org" ],
"SecurityCritical": [ "abarth@webkit.org" ],
@@ -162,10 +171,13 @@
"EFL": [ "kubo@profusion.mobi", ],
"CMake": [ "kubo@profusion.mobi", ],
"SoupNetwork": [ "kubo@profusion.mobi", ],
+ "ScrollingCoordinator": [ "andersca@apple.com", "jamesr@chromium.org", "tonikitoo@webkit.org" ],
},
"MESSAGE_RULES": {
"ChromiumPublicApi": [ "Please wait for approval from fishd@chromium.org before submitting "
"because this patch contains changes to the Chromium public API.", ],
+ "ChromiumPlatformApi": [ "Please wait for approval from fishd@chromium.org, abarth@webkit.org or jamesr@chromium.org before submitting "
+ "because this patch contains changes to the Chromium platform API.", ],
"AppleMacPublicApi": [ "Please wait for approval from timothy@apple.com (or another member "
"of the Apple Safari Team) before submitting "
"because this patch contains changes to the Apple Mac "
diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
index 6fb1dcaee..2ff688af7 100644
--- a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
+++ b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
@@ -110,6 +110,8 @@ class MockFileSystem(object):
raise IOError(errno.EISDIR, source, os.strerror(errno.ISDIR))
if self.isdir(destination):
raise IOError(errno.EISDIR, destination, os.strerror(errno.ISDIR))
+ if not self.exists(self.dirname(destination)):
+ raise IOError(errno.ENOENT, destination, os.strerror(errno.ENOENT))
self.files[destination] = self.files[source]
self.written_files[destination] = self.files[source]
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
index 38f75bdac..6375820cd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
@@ -198,11 +198,14 @@ class SingleTestRunner:
if driver_output.crash:
failures.append(test_failures.FailureCrash(bool(reference_filename)))
- _log.debug("%s Stacktrace for %s:\n%s" % (self._worker_name, testname,
- driver_output.error))
+ if driver_output.error:
+ _log.debug("%s %s crashed, stack trace:" % (self._worker_name, testname))
+ else:
+ _log.debug("%s %s crashed, no stack trace" % (self._worker_name, testname))
elif driver_output.error:
- _log.debug("%s %s output stderr lines:\n%s" % (self._worker_name, testname,
- driver_output.error))
+ _log.debug("%s %s output stderr lines:" % (self._worker_name, testname))
+ for line in driver_output.error.splitlines():
+ _log.debug(" %s" % line)
return failures
def _compare_output(self, driver_output, expected_driver_output):
@@ -266,7 +269,7 @@ class SingleTestRunner:
failures.append(test_failures.FailureImageHashMismatch(diff_result[1]))
else:
# See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this isn't a full failure.
- _log.warning('%s -> pixel hash failed (but pixel test still passes)' % self._test_name)
+ _log.warning(' %s -> pixel hash failed (but pixel test still passes)' % self._test_name)
return failures
def _run_reftest(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py
index 1b86bfe0d..11aa5081c 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -379,6 +379,11 @@ class Port(object):
platform_dir, baseline_filename = self.expected_baselines(test_name, suffix)[0]
if platform_dir:
return self._filesystem.join(platform_dir, baseline_filename)
+
+ actual_test_name = self.lookup_virtual_test_base(test_name)
+ if actual_test_name:
+ return self.expected_filename(actual_test_name, suffix)
+
return self._filesystem.join(self.layout_tests_dir(), baseline_filename)
def expected_checksum(self, test_name):
@@ -459,6 +464,9 @@ class Port(object):
def tests(self, paths):
"""Return the list of tests found."""
+ return self._real_tests(paths).union(self._virtual_tests(paths, self.populated_virtual_test_suites()))
+
+ def _real_tests(self, paths):
# When collecting test cases, skip these directories
skipped_directories = set(['.svn', '_svn', 'resources', 'script-tests', 'reference', 'reftest'])
files = find_files.find(self._filesystem, self.layout_tests_dir(), paths, skipped_directories, Port._is_test_file)
@@ -498,22 +506,26 @@ class Port(object):
def test_isfile(self, test_name):
"""Return True if the test name refers to a directory of tests."""
# Used by test_expectations.py to apply rules to whole directories.
- test_path = self.abspath_for_test(test_name)
- return self._filesystem.isfile(test_path)
+ if self._filesystem.isfile(self.abspath_for_test(test_name)):
+ return True
+ base = self.lookup_virtual_test_base(test_name)
+ return base and self._filesystem.isfile(self.abspath_for_test(base))
@memoized
def test_isdir(self, test_name):
"""Return True if the test name refers to a directory of tests."""
# Used by test_expectations.py to apply rules to whole directories.
- test_path = self.abspath_for_test(test_name)
- return self._filesystem.isdir(test_path)
+ if self._filesystem.isdir(self.abspath_for_test(test_name)):
+ return True
+ base = self.lookup_virtual_test_base(test_name)
+ return base and self._filesystem.isdir(self.abspath_for_test(base))
+ @memoized
def test_exists(self, test_name):
"""Return True if the test name refers to an existing test or baseline."""
# Used by test_expectations.py to determine if an entry refers to a
# valid test and by printing.py to determine if baselines exist.
- test_path = self.abspath_for_test(test_name)
- return self._filesystem.exists(test_path)
+ return self.test_isfile(test_name) or self.test_isdir(test_name)
def split_test(self, test_name):
"""Splits a test name into the 'directory' part and the 'basename' part."""
@@ -533,7 +545,7 @@ class Port(object):
def driver_cmd_line(self):
"""Prints the DRT command line that will be used."""
driver = self.create_driver(0)
- return driver.cmd_line()
+ return driver.cmd_line(self.get_option('pixel_tests'), [])
def update_baseline(self, baseline_path, data):
"""Updates the baseline for a test.
@@ -1043,3 +1055,56 @@ class Port(object):
def _driver_class(self):
"""Returns the port's driver implementation."""
raise NotImplementedError('Port._driver_class')
+
+ def virtual_test_suites(self):
+ return []
+
+ @memoized
+ def populated_virtual_test_suites(self):
+ suites = self.virtual_test_suites()
+
+ # Sanity-check the suites to make sure they don't point to other suites.
+ suite_dirs = [suite.name for suite in suites]
+ for suite in suites:
+ assert suite.base not in suite_dirs
+
+ for suite in suites:
+ base_tests = self._real_tests([suite.base])
+ suite.tests = {}
+ for test in base_tests:
+ suite.tests[test.replace(suite.base, suite.name)] = test
+ return suites
+
+ def _virtual_tests(self, paths, suites):
+ virtual_tests = set()
+ for suite in suites:
+ if paths:
+ for test in suite.tests:
+ if any(test.startswith(p) for p in paths):
+ virtual_tests.add(test)
+ else:
+ virtual_tests.update(set(suite.tests.keys()))
+ return virtual_tests
+
+ def lookup_virtual_test_base(self, test_name):
+ for suite in self.populated_virtual_test_suites():
+ if test_name.startswith(suite.name):
+ return suite.tests.get(test_name)
+ return None
+
+ def lookup_virtual_test_args(self, test_name):
+ for suite in self.populated_virtual_test_suites():
+ if test_name.startswith(suite.name):
+ return suite.args
+ return []
+
+
+class VirtualTestSuite(object):
+ def __init__(self, name, base, args, tests=None):
+ self.name = name
+ self.base = base
+ self.args = args
+ self.tests = tests or set()
+
+ def __repr__(self):
+ return "VirtualTestSuite('%s', '%s', %s)" % (self.name, self.base, self.args)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 8465f6019..fde05fda0 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -312,7 +312,7 @@ class PortTest(unittest.TestCase):
def test_find_with_skipped_directories(self):
port = self.make_port(with_tests=True)
- tests = port.tests('userscripts')
+ tests = port.tests(['userscripts'])
self.assertTrue('userscripts/resources/iframe.html' not in tests)
def test_find_with_skipped_directories_2(self):
@@ -406,6 +406,52 @@ class PortTest(unittest.TestCase):
self.assertVirtual(port._path_to_lighttpd_php)
self.assertVirtual(port._path_to_wdiff)
+ def test_test_exists(self):
+ port = self.make_port(with_tests=True)
+ self.assertTrue(port.test_exists('passes'))
+ self.assertTrue(port.test_exists('passes/text.html'))
+ self.assertFalse(port.test_exists('passes/does_not_exist.html'))
+
+ self.assertTrue(port.test_exists('virtual'))
+ self.assertFalse(port.test_exists('virtual/does_not_exist.html'))
+ self.assertTrue(port.test_exists('virtual/passes/text.html'))
+
+ def test_test_isfile(self):
+ port = self.make_port(with_tests=True)
+ self.assertFalse(port.test_isfile('passes'))
+ self.assertTrue(port.test_isfile('passes/text.html'))
+ self.assertFalse(port.test_isfile('passes/does_not_exist.html'))
+
+ self.assertFalse(port.test_isfile('virtual'))
+ self.assertTrue(port.test_isfile('virtual/passes/text.html'))
+ self.assertFalse(port.test_isfile('virtual/does_not_exist.html'))
+
+ def test_test_isdir(self):
+ port = self.make_port(with_tests=True)
+ self.assertTrue(port.test_isdir('passes'))
+ self.assertFalse(port.test_isdir('passes/text.html'))
+ self.assertFalse(port.test_isdir('passes/does_not_exist.html'))
+ self.assertFalse(port.test_isdir('passes/does_not_exist/'))
+
+ self.assertTrue(port.test_isdir('virtual'))
+ self.assertFalse(port.test_isdir('virtual/does_not_exist.html'))
+ self.assertFalse(port.test_isdir('virtual/does_not_exist/'))
+ self.assertFalse(port.test_isdir('virtual/passes/text.html'))
+
+ def test_tests(self):
+ port = self.make_port(with_tests=True)
+ tests = port.tests([])
+ self.assertTrue('passes/text.html' in tests)
+ self.assertTrue('virtual/passes/text.html' in tests)
+
+ tests = port.tests(['passes'])
+ self.assertTrue('passes/text.html' in tests)
+ self.assertFalse('virtual/passes/text.html' in tests)
+
+ tests = port.tests(['virtual/passes'])
+ self.assertFalse('passes/text.html' in tests)
+ self.assertTrue('virtual/passes/text.html' in tests)
+
if __name__ == '__main__':
unittest.main()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/builders.py b/Tools/Scripts/webkitpy/layout_tests/port/builders.py
index 3f7e413ce..ea6b468cd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/builders.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/builders.py
@@ -50,13 +50,7 @@ _exact_matches = {
"Webkit Mac10.5 (dbg)(2)": {"port_name": "chromium-mac-leopard", "specifiers": set(["leopard", "debug"])},
"Webkit Mac10.6": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard"])},
"Webkit Mac10.6 (dbg)": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard", "debug"])},
- "Webkit Win - GPU": {"port_name": "chromium-gpu-win-xp", "specifiers": set(["xp", "release", "gpu"])},
- "Webkit Win7 - GPU": {"port_name": "chromium-gpu-win-win7", "specifiers": set(["win7", "vista", "release", "gpu"])},
- # FIXME: For some reason, these port names don't work correctly.
- # "Webkit Linux - GPU": {"port_name": "chromium-gpu-linux-x86_64", "specifiers": set(["linux", "gpu"])},
- # "Webkit Linux 32 - GPU": {"port_name": "chromium-gpu-linux-x86", "specifiers": set(["linux", "x86", "gpu"])},
- "Webkit Mac10.6 (dbg) - GPU": {"port_name": "chromium-gpu-mac-snowleopard", "specifiers": set(["snowleopard", "gpu", "debug"])},
- "Webkit Mac10.6 - GPU": {"port_name": "chromium-gpu-mac-snowleopard", "specifiers": set(["snowleopard", "gpu"])},
+ "Webkit Mac10.7": {"port_name": "chromium-mac-lion", "specifiers": set(["lion"]), "move_overwritten_baselines_to": "chromium-mac-snowleopard"},
# These builders are on build.webkit.org.
"GTK Linux 32-bit Debug": {"port_name": "gtk", "specifiers": set(["gtk"])},
@@ -83,9 +77,6 @@ _fuzzy_matches = {
_ports_without_builders = [
- # FIXME: Including chromium-gpu-linux below is a workaround for
- # chromium-gpu-linux-x86_64 and chromium-gpu-linux-x86 not working properly.
- "chromium-gpu-linux",
"google-chrome-linux32",
"google-chrome-linux64",
"qt-mac",
@@ -130,3 +121,7 @@ def builder_name_for_port_name(target_port_name):
def builder_path_for_port_name(port_name):
builder_path_from_name(builder_name_for_port_name(port_name))
+
+
+def fallback_port_name_for_new_port(builder_name):
+ return _exact_matches[builder_name].get("move_overwritten_baselines_to")
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
index 83139e0fc..f80f53bb5 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -45,7 +45,7 @@ from webkitpy.common.system.path import cygpath
from webkitpy.layout_tests.controllers.manager import Manager
from webkitpy.layout_tests.models import test_expectations
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
-from webkitpy.layout_tests.port.base import Port
+from webkitpy.layout_tests.port.base import Port, VirtualTestSuite
from webkitpy.layout_tests.port.driver import Driver, DriverOutput
from webkitpy.layout_tests.port import builders
from webkitpy.layout_tests.servers import http_server
@@ -75,7 +75,6 @@ class ChromiumPort(Port):
'chromium-mac-lion', 'chromium-mac-snowleopard', 'chromium-mac-leopard',
'chromium-win-win7', 'chromium-win-vista', 'chromium-win-xp',
'chromium-linux-x86_64', 'chromium-linux-x86',
- 'chromium-gpu-mac-snowleopard', 'chromium-gpu-win-win7', 'chromium-gpu-linux-x86_64',
]
CONFIGURATION_SPECIFIER_MACROS = {
@@ -342,6 +341,15 @@ class ChromiumPort(Port):
repos.append(('chromium', self.path_from_chromium_base('build')))
return repos
+ def virtual_test_suites(self):
+ return [
+ VirtualTestSuite('platform/chromium/virtual/gpu/fast/canvas',
+ 'fast/canvas',
+ ['--enable-accelerated-2d-canvas']),
+ VirtualTestSuite('platform/chromium/virtual/gpu/canvas/philip',
+ 'canvas/philip',
+ ['--enable-accelerated-2d-canvas'])]
+
#
# PROTECTED METHODS
#
@@ -395,12 +403,12 @@ class ChromiumDriver(Driver):
Driver.__init__(self, port, worker_number, pixel_tests, no_timeout)
self._proc = None
self._image_path = None
- if self._pixel_tests:
- self._image_path = self._port._filesystem.join(self._port.results_directory(), 'png_result%s.png' % self._worker_number)
- def _wrapper_options(self):
+ def _wrapper_options(self, pixel_tests):
cmd = []
- if self._pixel_tests:
+ if pixel_tests or self._pixel_tests:
+ if not self._image_path:
+ self._image_path = self._port._filesystem.join(self._port.results_directory(), 'png_result%s.png' % self._worker_number)
# See note above in diff_image() for why we need _convert_path().
cmd.append("--pixel-tests=" + self._port._convert_path(self._image_path))
# FIXME: This is not None shouldn't be necessary, unless --js-flags="''" changes behavior somehow?
@@ -433,21 +441,23 @@ class ChromiumDriver(Driver):
cmd.extend(self._port.get_option('additional_drt_flag', []))
return cmd
- def cmd_line(self):
+ def cmd_line(self, pixel_tests, per_test_args):
cmd = self._command_wrapper(self._port.get_option('wrapper'))
cmd.append(self._port._path_to_driver())
# FIXME: Why does --test-shell exist? TestShell is dead, shouldn't this be removed?
# It seems it's still in use in Tools/DumpRenderTree/chromium/DumpRenderTree.cpp as of 8/10/11.
cmd.append('--test-shell')
- cmd.extend(self._wrapper_options())
+ cmd.extend(self._wrapper_options(pixel_tests))
+ cmd.extend(per_test_args)
+
return cmd
- def _start(self):
+ def _start(self, pixel_tests, per_test_args):
assert not self._proc
# FIXME: This should use ServerProcess like WebKitDriver does.
# FIXME: We should be reading stderr and stdout separately like how WebKitDriver does.
close_fds = sys.platform != 'win32'
- self._proc = subprocess.Popen(self.cmd_line(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=close_fds)
+ self._proc = subprocess.Popen(self.cmd_line(pixel_tests, per_test_args), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=close_fds)
def has_crashed(self):
if self._proc is None:
@@ -508,7 +518,7 @@ class ChromiumDriver(Driver):
def run_test(self, driver_input):
if not self._proc:
- self._start()
+ self._start(driver_input.is_reftest or self._pixel_tests, driver_input.args)
output = []
error = []
@@ -594,9 +604,9 @@ class ChromiumDriver(Driver):
return DriverOutput(text, output_image, actual_checksum, audio=audio_bytes,
crash=crash, crashed_process_name=crashed_process_name, test_time=run_time, timeout=timeout, error=error)
- def start(self):
+ def start(self, pixel_tests, per_test_args):
if not self._proc:
- self._start()
+ self._start(pixel_tests, per_test_args)
def stop(self):
if not self._proc:
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
index bdb2cbb31..2b6d53625 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
@@ -141,12 +141,6 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
def __init__(self, host, port_name, **kwargs):
chromium.ChromiumPort.__init__(self, host, port_name, **kwargs)
- # The chromium-android port always uses the GPU code path, so we set
- # these options here, almost as if this was the chromium-gpu-android
- # port.
- self._options.accelerated_2d_canvas = True
- self._options.accelerated_video = True
-
self._operating_system = 'android'
self._version = 'icecreamsandwich'
# FIXME: we may support other architectures in the future.
@@ -401,14 +395,13 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
class ChromiumAndroidDriver(chromium.ChromiumDriver):
def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
chromium.ChromiumDriver.__init__(self, port, worker_number, pixel_tests, no_timeout)
- if self._image_path:
- self._device_image_path = DEVICE_DRT_DIR + port.host.filesystem.basename(self._image_path)
+ self._device_image_path = None
- def _start(self):
+ def _start(self, pixel_tests, per_test_args):
# Convert the original command line into to two parts:
# - the 'adb shell' command line to start an interactive adb shell;
# - the DumpRenderTree command line to send to the adb shell.
- original_cmd = self.cmd_line()
+ original_cmd = self.cmd_line(pixel_tests, per_test_args)
shell_cmd = []
drt_args = []
path_to_driver = self._port._path_to_driver()
@@ -421,6 +414,8 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver):
shell_cmd.append(param)
else:
if param.startswith('--pixel-tests='):
+ if not self._device_image_path:
+ self._device_image_path = DEVICE_DRT_DIR + self._port.host.filesystem.basename(self._image_path)
param = '--pixel-tests=' + self._device_image_path
drt_args.append(param)
@@ -430,10 +425,10 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver):
while True:
_log.debug('Starting adb shell for DumpRenderTree: ' + ' '.join(shell_cmd))
executive = self._port.host.executive
- self._proc = executive.Popen(shell_cmd, stdin=executive.PIPE, stdout=executive.PIPE, stderr=executive.STDOUT, close_fds=True)
- # Read back the shell prompt ('# ') to ensure adb shell ready.
- prompt = self._proc.stdout.read(2)
- assert(prompt == '# ')
+ self._proc = executive.popen(shell_cmd, stdin=executive.PIPE, stdout=executive.PIPE, stderr=executive.STDOUT,
+ close_fds=True, universal_newlines=True)
+ # Read back the shell prompt to ensure adb shell ready.
+ self._read_prompt()
# Some tests rely on this to produce proper number format etc.,
# e.g. fast/speech/input-appearance-numberandspeech.html.
self._write_command_and_read_line("export LC_CTYPE='en_US'\n")
@@ -526,3 +521,14 @@ class ChromiumAndroidDriver(chromium.ChromiumDriver):
# (which causes Shell to output a message), and dumps the stack strace.
# We use the Shell output as a crash hint.
return line is not None and line.find('[1] + Stopped (signal)') >= 0
+
+ def _read_prompt(self):
+ last_char = ''
+ while True:
+ current_char = self._proc.stdout.read(1)
+ if current_char == ' ':
+ if last_char == '#':
+ return
+ if last_char == '$':
+ raise AssertionError('Adbd is not running as root')
+ last_char = current_char
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py
deleted file mode 100644
index fdc1117c9..000000000
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2010 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import sys
-
-import chromium_linux
-import chromium_mac
-import chromium_win
-
-
-# FIXME: This whole file needs to go away and we need to eliminate the GPU configuration.
-
-def _set_gpu_options(port, graphics_type='gpu'):
- port._graphics_type = graphics_type
- if port.get_option('accelerated_2d_canvas') is None:
- port._options.accelerated_2d_canvas = True
- if port.get_option('accelerated_video') is None:
- port._options.accelerated_video = True
- if port.get_option('experimental_fully_parallel') is None:
- port._options.experimental_fully_parallel = True
-
- # FIXME: Remove this after http://codereview.chromium.org/5133001/ is enabled
- # on the bots.
- if port.get_option('builder_name') is not None and not ' - GPU' in port._options.builder_name:
- port._options.builder_name += ' - GPU'
-
-
-def _default_tests_paths(port):
- paths = []
- if port.name() != 'chromium-gpu-mac-leopard':
- # Only run tests requiring accelerated compositing on platforms that
- # support it.
- # FIXME: we should add the above paths here as well but let's test
- # the waters with media first.
- paths += ['media']
-
- paths += ['fast/canvas', 'canvas/philip']
-
- if not paths:
- # FIXME: This is a hack until we can turn off the webkit_gpu
- # tests on the bots. If paths is empty, port.tests()
- # finds *everything*. However, we have to return something,
- # or NRWT thinks there's something wrong. So, we return a single
- # short directory. See https://bugs.webkit.org/show_bug.cgi?id=72498.
- paths = ['fast/html']
-
- return paths
-
-
-class ChromiumGpuLinuxPort(chromium_linux.ChromiumLinuxPort):
- port_name = 'chromium-gpu-linux'
-
- def __init__(self, host, port_name, **kwargs):
- chromium_linux.ChromiumLinuxPort.__init__(self, host, port_name, **kwargs)
- _set_gpu_options(self)
-
- def baseline_search_path(self):
- # 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 tests(self, paths):
- paths = paths or _default_tests_paths(self)
- return chromium_linux.ChromiumLinuxPort.tests(self, paths)
-
-
-class ChromiumGpuMacPort(chromium_mac.ChromiumMacPort):
- port_name = 'chromium-gpu-mac'
-
- def __init__(self, host, port_name, **kwargs):
- chromium_mac.ChromiumMacPort.__init__(self, host, port_name, **kwargs)
- _set_gpu_options(self)
-
- def baseline_search_path(self):
- return (map(self._webkit_baseline_path, ['chromium-gpu-mac', 'chromium-gpu']) +
- chromium_mac.ChromiumMacPort.baseline_search_path(self))
-
- def tests(self, paths):
- paths = paths or _default_tests_paths(self)
- return chromium_mac.ChromiumMacPort.tests(self, paths)
-
-
-class ChromiumGpuWinPort(chromium_win.ChromiumWinPort):
- port_name = 'chromium-gpu-win'
-
- def __init__(self, host, port_name, **kwargs):
- chromium_win.ChromiumWinPort.__init__(self, host, port_name, **kwargs)
- _set_gpu_options(self)
-
- def baseline_search_path(self):
- return (map(self._webkit_baseline_path, ['chromium-gpu-win', 'chromium-gpu']) +
- chromium_win.ChromiumWinPort.baseline_search_path(self))
-
- def tests(self, paths):
- paths = paths or _default_tests_paths(self)
- return chromium_win.ChromiumWinPort.tests(self, paths)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py
deleted file mode 100755
index c96b7eb18..000000000
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2010 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import sys
-import unittest
-
-from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.systemhost_mock import MockSystemHost
-from webkitpy.layout_tests.port import chromium_gpu
-from webkitpy.layout_tests.port import port_testcase
-from webkitpy.layout_tests.port.factory import PortFactory
-from webkitpy.tool.mocktool import MockOptions
-
-
-class ChromiumGpuTest(unittest.TestCase):
- def integration_test_chromium_gpu_linux(self):
- self.assert_port_works('chromium-gpu-linux')
- self.assert_port_works('chromium-gpu-linux', 'chromium-gpu', 'linux2')
- self.assert_port_works('chromium-gpu-linux', 'chromium-gpu', 'linux3')
-
- def integration_test_chromium_gpu_mac(self):
- self.assert_port_works('chromium-gpu-mac')
- self.assert_port_works('chromium-gpu-mac', 'chromium-gpu', 'darwin')
-
- def integration_test_chromium_gpu_win(self):
- self.assert_port_works('chromium-gpu-win')
- self.assert_port_works('chromium-gpu-win', 'chromium-gpu', 'win32')
- self.assert_port_works('chromium-gpu-win', 'chromium-gpu', 'cygwin')
-
- def assert_port_works(self, port_name, input_name=None, platform=None):
- host = MockSystemHost()
- host.filesystem = FileSystem() # FIXME: This test should not use a real filesystem!
-
- # test that we got the right port
- mock_options = MockOptions(accelerated_2d_canvas=None,
- accelerated_video=None,
- builder_name='foo',
- child_processes=None)
- if input_name and platform:
- port = PortFactory(host).get(host, platform=platform, port_name=input_name, options=mock_options)
- else:
- port = PortFactory(host).get(host, port_name=port_name, options=mock_options)
- self.assertTrue(port._options.accelerated_2d_canvas)
- self.assertTrue(port._options.accelerated_video)
- self.assertTrue(port._options.experimental_fully_parallel)
- self.assertEqual(port._options.builder_name, 'foo - GPU')
-
- self.assertTrue(port.name().startswith(port_name))
-
- # 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're limiting to the correct directories.
- # These two tests are picked mostly at random, but we make sure they
- # exist separately from being filtered out by the port.
-
- # Note that this is using a real filesystem.
- files = port.tests(None)
-
- path = 'fast/html/keygen.html'
- self.assertTrue(port._filesystem.exists(port.abspath_for_test(path)))
- self.assertFalse(path in files)
-
- def _assert_baseline_path(self, port_name, baseline_path):
- port = PortFactory(MockSystemHost()).get(port_name)
- self.assertEquals(port.name(), port_name)
- self.assertEquals(port.baseline_path(), port._webkit_baseline_path(baseline_path))
-
- def test_baseline_paths(self):
- self._assert_baseline_path('chromium-gpu-win-vista', 'chromium-gpu-win')
- self._assert_baseline_path('chromium-gpu-win-xp', 'chromium-gpu-win')
- self._assert_baseline_path('chromium-gpu-win-win7', 'chromium-gpu-win')
-
- def test_graphics_type(self):
- port = PortFactory(MockSystemHost()).get('chromium-gpu-mac')
- self.assertEquals('gpu', port.graphics_type())
-
- def test_default_tests_paths(self):
-
- def test_paths(port_name):
- return chromium_gpu._default_tests_paths(PortFactory(MockSystemHost()).get(port_name))
-
- self.assertEqual(test_paths('chromium-gpu-linux'), ['media', 'fast/canvas', 'canvas/philip'])
- self.assertEqual(test_paths('chromium-gpu-mac-leopard'), ['fast/canvas', 'canvas/philip'])
-
- def test_test_files(self):
- host = MockSystemHost()
- files = {
- '/mock-checkout/LayoutTests/canvas/philip/test.html': '',
- '/mock-checkout/LayoutTests/fast/canvas/test.html': '',
- '/mock-checkout/LayoutTests/fast/html/test.html': '',
- '/mock-checkout/LayoutTests/media/test.html': '',
- '/mock-checkout/LayoutTests/foo/bar.html': '',
- }
- host.filesystem = MockFileSystem(files)
-
- def test_paths(port_name):
- return PortFactory(host).get(port_name).tests([])
-
- self.assertEqual(test_paths('chromium-gpu-linux'), set(['canvas/philip/test.html', 'fast/canvas/test.html', 'media/test.html']))
- self.assertEqual(test_paths('chromium-gpu-mac-leopard'), set(['canvas/philip/test.html', 'fast/canvas/test.html']))
-
-
-if __name__ == '__main__':
- port_testcase.main()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
index ac0779574..a46cb5070 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
@@ -138,15 +138,15 @@ class ChromiumDriverTest(unittest.TestCase):
def __init__(self):
chromium.ChromiumDriver.__init__(self, mock_port, worker_number=0, pixel_tests=False)
- def cmd_line(self):
+ def cmd_line(self, pixel_test, per_test_args):
return 'python'
# get_option is used to get the timeout (ms) for a process before we kill it.
mock_port.get_option = lambda name: 60 * 1000
driver1 = MockDriver()
- driver1._start()
+ driver1._start(False, [])
driver2 = MockDriver()
- driver2._start()
+ driver2._start(False, [])
# It's possible for driver1 to timeout when stopping if it's sharing stdin with driver2.
start_time = time.time()
driver1.stop()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py
index 51a779850..08b9af16c 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/config_unittest.py
@@ -40,6 +40,9 @@ import config
class ConfigTest(unittest.TestCase):
+ def setUp(self):
+ config.clear_cached_configuration()
+
def tearDown(self):
config.clear_cached_configuration()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver.py b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
index 92e6992d7..fa6e81b2e 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/driver.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
@@ -26,6 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import copy
import re
import shlex
@@ -33,11 +34,12 @@ from webkitpy.common.system import path
class DriverInput(object):
- def __init__(self, test_name, timeout, image_hash, is_reftest):
+ def __init__(self, test_name, timeout, image_hash, is_reftest, args=None):
self.test_name = test_name
self.timeout = timeout # in ms
self.image_hash = image_hash
self.is_reftest = is_reftest
+ self.args = args or []
class DriverOutput(object):
@@ -162,7 +164,7 @@ class Driver(object):
def stop(self):
raise NotImplementedError('Driver.stop')
- def cmd_line(self):
+ def cmd_line(self, pixel_tests, per_test_args):
raise NotImplementedError('Driver.cmd_line')
@@ -172,38 +174,67 @@ class DriverProxy(object):
single driver."""
def __init__(self, port, worker_number, driver_instance_constructor, pixel_tests, no_timeout):
- self._driver = driver_instance_constructor(port, worker_number, pixel_tests, no_timeout)
- if pixel_tests:
- self._reftest_driver = self._driver
- else:
- self._reftest_driver = driver_instance_constructor(port, worker_number, True, no_timeout)
+ self._port = port
+ self._worker_number = worker_number
+ self._driver_instance_constructor = driver_instance_constructor
+ self._no_timeout = no_timeout
+ self._pixel_tests = pixel_tests
+
+ # FIXME: We shouldn't need to create a driver until we actually run a test.
+ self._driver = self._make_driver(pixel_tests)
+ self._running_drivers = {}
+ self._running_drivers[self._cmd_line_as_key(pixel_tests, [])] = self._driver
+
+ def _make_driver(self, pixel_tests):
+ return self._driver_instance_constructor(self._port, self._worker_number, pixel_tests, self._no_timeout)
+ # FIXME: this should be a @classmethod (or implemented on Port instead).
def is_http_test(self, test_name):
return self._driver.is_http_test(test_name)
+ # FIXME: this should be a @classmethod (or implemented on Port instead).
def test_to_uri(self, test_name):
return self._driver.test_to_uri(test_name)
+ # FIXME: this should be a @classmethod (or implemented on Port instead).
def uri_to_test(self, uri):
return self._driver.uri_to_test(uri)
def run_test(self, driver_input):
- if driver_input.is_reftest:
- return self._reftest_driver.run_test(driver_input)
- return self._driver.run_test(driver_input)
+ base = self._port.lookup_virtual_test_base(driver_input.test_name)
+ if base:
+ virtual_driver_input = copy.copy(driver_input)
+ virtual_driver_input.test_name = base
+ virtual_driver_input.args = self._port.lookup_virtual_test_args(driver_input.test_name)
+ return self.run_test(virtual_driver_input)
- def has_crashed(self):
- return self._driver.has_crashed() or self._reftest_driver.has_crashed()
+ pixel_tests_needed = self._pixel_tests or driver_input.is_reftest
+ cmd_line_key = self._cmd_line_as_key(pixel_tests_needed, driver_input.args)
+ if not cmd_line_key in self._running_drivers:
+ self._running_drivers[cmd_line_key] = self._make_driver(pixel_tests_needed)
+
+ return self._running_drivers[cmd_line_key].run_test(driver_input)
def start(self):
- self._driver.start()
+ # FIXME: Callers shouldn't normally call this, since this routine
+ # may not be specifying the correct combination of pixel test and
+ # per_test args.
+ #
+ # The only reason we have this routine at all is so the perftestrunner
+ # can pause before running a test; it might be better to push that
+ # into run_test() directly.
+ self._driver.start(self._pixel_tests, [])
+
+ def has_crashed(self):
+ return any(driver.has_crashed() for driver in self._running_drivers.values())
def stop(self):
- self._driver.stop()
- self._reftest_driver.stop()
-
- def cmd_line(self):
- cmd_line = self._driver.cmd_line()
- if self._driver != self._reftest_driver:
- cmd_line += ['; '] + self._reftest_driver.cmd_line()
- return cmd_line
+ for driver in self._running_drivers.values():
+ driver.stop()
+
+ # FIXME: this should be a @classmethod (or implemented on Port instead).
+ def cmd_line(self, pixel_tests=None, per_test_args=None):
+ return self._driver.cmd_line(pixel_tests or self._pixel_tests, per_test_args or [])
+
+ def _cmd_line_as_key(self, pixel_tests, per_test_args):
+ return ' '.join(self.cmd_line(pixel_tests, per_test_args))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
index d0a510f9d..08d4d9882 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
@@ -91,7 +91,7 @@ class DriverTest(unittest.TestCase):
driver = Driver(self.make_port(), None, pixel_tests=False)
self.assertVirtual(driver.run_test, None)
self.assertVirtual(driver.stop)
- self.assertVirtual(driver.cmd_line)
+ self.assertVirtual(driver.cmd_line, False, [])
def test_command_wrapper(self):
self._assert_wrapper(None, [])
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/factory.py b/Tools/Scripts/webkitpy/layout_tests/port/factory.py
index 059186eee..092106019 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/factory.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/factory.py
@@ -43,9 +43,6 @@ class BuilderOptions(object):
class PortFactory(object):
PORT_CLASSES = (
'chromium_android.ChromiumAndroidPort',
- 'chromium_gpu.ChromiumGpuLinuxPort',
- 'chromium_gpu.ChromiumGpuMacPort',
- 'chromium_gpu.ChromiumGpuWinPort',
'chromium_linux.ChromiumLinuxPort',
'chromium_mac.ChromiumMacPort',
'chromium_win.ChromiumWinPort',
@@ -87,10 +84,6 @@ class PortFactory(object):
if port_name == 'chromium':
port_name = 'chromium-' + self._host.platform.os_name
- # FIXME: Remove this when we remove the chromium-gpu ports.
- if port_name == 'chromium-gpu':
- port_name = port_name + '-' + self._host.platform.os_name
-
for port_class in self.PORT_CLASSES:
module_name, class_name = port_class.rsplit('.', 1)
module = __import__(module_name, globals(), locals(), [], -1)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
index e6478eefc..9fc20582f 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
@@ -31,7 +31,6 @@ import unittest
from webkitpy.tool.mocktool import MockOptions
from webkitpy.common.system.systemhost_mock import MockSystemHost
-from webkitpy.layout_tests.port import chromium_gpu
from webkitpy.layout_tests.port import chromium_linux
from webkitpy.layout_tests.port import chromium_mac
from webkitpy.layout_tests.port import chromium_win
@@ -96,23 +95,6 @@ class FactoryTest(unittest.TestCase):
def test_qt(self):
self.assert_port(port_name='qt', cls=qt.QtPort)
- def test_chromium_gpu(self):
- self.assert_port(port_name='chromium-gpu', os_name='mac', os_version='leopard',
- cls=chromium_gpu.ChromiumGpuMacPort)
- self.assert_port(port_name='chromium-gpu', os_name='win', os_version='xp',
- cls=chromium_gpu.ChromiumGpuWinPort)
- self.assert_port(port_name='chromium-gpu', os_name='linux', os_version='lucid',
- cls=chromium_gpu.ChromiumGpuLinuxPort)
-
- def test_chromium_gpu_linux(self):
- self.assert_port(port_name='chromium-gpu-linux', cls=chromium_gpu.ChromiumGpuLinuxPort)
-
- def test_chromium_gpu_mac(self):
- self.assert_port(port_name='chromium-gpu-mac-leopard', cls=chromium_gpu.ChromiumGpuMacPort)
-
- def test_chromium_gpu_win(self):
- self.assert_port(port_name='chromium-gpu-win-xp', cls=chromium_gpu.ChromiumGpuWinPort)
-
def test_chromium_mac(self):
self.assert_port(port_name='chromium-mac-leopard', cls=chromium_mac.ChromiumMacPort)
self.assert_port(port_name='chromium-mac', os_name='mac', os_version='leopard',
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
index c9ee1cbfe..4f8c01ff2 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
@@ -40,7 +40,7 @@ _log = logging.getLogger(__name__)
class GtkDriver(WebKitDriver):
- def _start(self):
+ def _start(self, pixel_tests, per_test_args):
# Use even displays for pixel tests and odd ones otherwise. When pixel tests are disabled,
# DriverProxy creates two drivers, one for normal and the other for ref tests. Both have
# the same worker number, so this prevents them from using the same Xvfb instance.
@@ -54,7 +54,7 @@ class GtkDriver(WebKitDriver):
environment = self._port.setup_environ_for_server(server_name)
# We must do this here because the DISPLAY number depends on _worker_number
environment['DISPLAY'] = ":%d" % (display_id)
- self._server_process = ServerProcess(self._port, server_name, self.cmd_line(), environment)
+ self._server_process = ServerProcess(self._port, server_name, self.cmd_line(pixel_tests, per_test_args), environment)
def stop(self):
WebKitDriver.stop(self)
@@ -64,9 +64,9 @@ class GtkDriver(WebKitDriver):
self._xvfb_process.wait()
self._xvfb_process = None
- def cmd_line(self):
+ def cmd_line(self, pixel_tests, per_test_args):
wrapper_path = self._port.path_from_webkit_base("Tools", "gtk", "run-with-jhbuild")
- return [wrapper_path] + WebKitDriver.cmd_line(self)
+ return [wrapper_path] + WebKitDriver.cmd_line(self, pixel_tests, per_test_args)
class GtkPort(WebKitPort):
@@ -81,6 +81,7 @@ class GtkPort(WebKitPort):
def setup_environ_for_server(self, server_name=None):
environment = WebKitPort.setup_environ_for_server(self, server_name)
environment['GTK_MODULES'] = 'gail'
+ environment['GSETTINGS_BACKEND'] = 'memory'
environment['LIBOVERLAY_SCROLLBAR'] = '0'
environment['TEST_RUNNER_INJECTED_BUNDLE_FILENAME'] = self._build_path('Libraries', 'libTestRunnerInjectedBundle.la')
environment['TEST_RUNNER_TEST_PLUGIN_PATH'] = self._build_path('TestNetscapePlugin', '.libs')
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
index cbb6bb6ce..3d41ebdde 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
@@ -93,8 +93,8 @@ class MockDRTPort(object):
@staticmethod
def _overriding_cmd_line(original_cmd_line, driver_path, python_exe, this_file, port_name):
- def new_cmd_line():
- cmd_line = original_cmd_line()
+ def new_cmd_line(pixel_tests, per_test_args):
+ cmd_line = original_cmd_line(pixel_tests, per_test_args)
index = cmd_line.index(driver_path)
cmd_line[index:index + 1] = [python_exe, this_file, '--platform', port_name]
return cmd_line
@@ -275,6 +275,7 @@ class MockChromiumDRT(MockDRT):
self._stdout.write("#URL:%s\n" % self._driver.test_to_uri(test_input.test_name))
if self._options.pixel_tests and (test_input.image_hash or test_input.is_reftest):
self._stdout.write("#MD5:%s\n" % output.image_hash)
+ self._host.filesystem.maybe_make_directory(self._host.filesystem.dirname(self._options.pixel_path))
self._host.filesystem.write_binary_file(self._options.pixel_path,
output.image)
self._stdout.write(output.text)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/test.py b/Tools/Scripts/webkitpy/layout_tests/port/test.py
index 199460d57..e1132cbaa 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -32,6 +32,7 @@ import sys
import time
from webkitpy.layout_tests.port import Port, Driver, DriverOutput
+from webkitpy.layout_tests.port.base import VirtualTestSuite
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.common.system.filesystem_mock import MockFileSystem
@@ -159,6 +160,7 @@ layer at (0,0) size 800x34
tests.add('http/tests/passes/text.html')
tests.add('http/tests/passes/image.html')
tests.add('http/tests/ssl/text.html')
+ tests.add('passes/args.html')
tests.add('passes/error.html', error='stuff going to stderr')
tests.add('passes/image.html')
tests.add('passes/audio.html',
@@ -304,6 +306,7 @@ WONTFIX SKIP : failures/expected/exception.html = CRASH
add_file(test, '-expected.txt', test.expected_text)
add_file(test, '-expected.png', test.expected_image)
+ filesystem.write_text_file(filesystem.join(LAYOUT_TEST_DIR, 'virtual', 'passes', 'args-expected.txt'), 'args-txt --virtual-arg')
# Clear the list of written files so that we can watch what happens during testing.
filesystem.clear_written_files()
@@ -352,7 +355,7 @@ class TestPort(Port):
def _path_to_driver(self):
# This routine shouldn't normally be called, but it is called by
# the mock_drt Driver. We return something, but make sure it's useless.
- return 'junk'
+ return 'MOCK _path_to_driver'
def baseline_search_path(self):
search_paths = {
@@ -489,16 +492,22 @@ class TestPort(Port):
def all_baseline_variants(self):
return self.ALL_BASELINE_VARIANTS
+ def virtual_test_suites(self):
+ return [
+ VirtualTestSuite('virtual/passes', 'passes', ['--virtual-arg']),
+ ]
class TestDriver(Driver):
"""Test/Dummy implementation of the DumpRenderTree interface."""
- def cmd_line(self):
- return [self._port._path_to_driver()] + self._port.get_option('additional_drt_flag', [])
+ def cmd_line(self, pixel_tests, per_test_args):
+ pixel_tests_flag = '-p' if pixel_tests else ''
+ return [self._port._path_to_driver()] + [pixel_tests_flag] + self._port.get_option('additional_drt_flag', []) + per_test_args
def run_test(self, test_input):
start_time = time.time()
test_name = test_input.test_name
+ test_args = test_input.args or []
test = self._port._tests[test_name]
if test.keyboard:
raise KeyboardInterrupt
@@ -508,6 +517,10 @@ class TestDriver(Driver):
time.sleep((float(test_input.timeout) * 4) / 1000.0)
audio = None
+ actual_text = test.actual_text
+ if actual_text and test_args and test_name == 'passes/args.html':
+ actual_text = actual_text + ' ' + ' '.join(test_args)
+
if test.actual_audio:
audio = base64.b64decode(test.actual_audio)
crashed_process_name = None
@@ -515,12 +528,12 @@ class TestDriver(Driver):
crashed_process_name = self._port.driver_name()
elif test.web_process_crash:
crashed_process_name = 'WebProcess'
- return DriverOutput(test.actual_text, test.actual_image,
+ return DriverOutput(actual_text, test.actual_image,
test.actual_checksum, audio, crash=test.crash or test.web_process_crash,
crashed_process_name=crashed_process_name,
test_time=time.time() - start_time, timeout=test.timeout, error=test.error)
- def start(self):
+ def start(self, pixel_tests, per_test_args):
pass
def stop(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
index aeb918ce0..cc3b0c716 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -464,13 +464,11 @@ class WebKitDriver(Driver):
def __del__(self):
self._port._filesystem.rmtree(str(self._driver_tempdir))
- def cmd_line(self):
+ def cmd_line(self, pixel_tests, per_test_args):
cmd = self._command_wrapper(self._port.get_option('wrapper'))
cmd.append(self._port._path_to_driver())
if self._port.get_option('skip_pixel_test_if_no_baseline'):
cmd.append('--skip-pixel-test-if-no-baseline')
- if self._pixel_tests:
- cmd.append('--pixel-tests')
if self._port.get_option('gc_between_tests'):
cmd.append('--gc-between-tests')
if self._port.get_option('complex_text'):
@@ -482,10 +480,15 @@ class WebKitDriver(Driver):
# FIXME: We need to pass --timeout=SECONDS to WebKitTestRunner for WebKit2.
cmd.extend(self._port.get_option('additional_drt_flag', []))
+
+ if pixel_tests or self._pixel_tests:
+ cmd.append('--pixel-tests')
+ cmd.extend(per_test_args)
+
cmd.append('-')
return cmd
- def _start(self):
+ def _start(self, pixel_tests, per_test_args):
server_name = self._port.driver_name()
environment = self._port.setup_environ_for_server(server_name)
environment['DYLD_FRAMEWORK_PATH'] = self._port._build_path()
@@ -493,7 +496,7 @@ class WebKitDriver(Driver):
environment['DUMPRENDERTREE_TEMP'] = str(self._driver_tempdir)
environment['LOCAL_RESOURCE_ROOT'] = self._port.layout_tests_dir()
self._crashed_subprocess_name = None
- self._server_process = server_process.ServerProcess(self._port, server_name, self.cmd_line(), environment)
+ self._server_process = server_process.ServerProcess(self._port, server_name, self.cmd_line(pixel_tests, per_test_args), environment)
def has_crashed(self):
if self._server_process is None:
@@ -553,7 +556,7 @@ class WebKitDriver(Driver):
def run_test(self, driver_input):
if not self._server_process:
- self._start()
+ self._start(driver_input.is_reftest or self._pixel_tests, [])
self.error_from_test = str()
self.err_seen_eof = False
@@ -645,9 +648,9 @@ class WebKitDriver(Driver):
block.decode_content()
return block
- def start(self):
+ def start(self, pixel_tests, per_test_args):
if not self._server_process:
- self._start()
+ self._start(pixel_tests, per_test_args)
def stop(self):
if self._server_process:
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
index ffaae6eb7..aadbf72fd 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
@@ -300,4 +300,4 @@ class WebKitDriverTest(unittest.TestCase):
def test_no_timeout(self):
port = TestWebKitPort()
driver = WebKitDriver(port, 0, pixel_tests=True, no_timeout=True)
- self.assertEquals(driver.cmd_line(), ['MOCK output of child process/DumpRenderTree', '--pixel-tests', '--no-timeout', '-'])
+ self.assertEquals(driver.cmd_line(True, []), ['MOCK output of child process/DumpRenderTree', '--no-timeout', '--pixel-tests', '-'])
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
index 66876cc8c..dc2e1c2b4 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
@@ -273,6 +273,10 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
self.assertTrue(passing_run(['--accelerated-2d-canvas']))
self.assertTrue(passing_run(['--no-accelerated-2d-canvas']))
+ def test_all(self):
+ res, out, err, user = logging_run([], tests_included=True)
+ self.assertEquals(res, unexpected_tests_count)
+
def test_basic(self):
self.assertTrue(passing_run())
@@ -748,6 +752,10 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
test_port = get_port_for_run(base_args)
self.assertEqual(None, test_port.tolerance_used_for_diff_image)
+ def test_virtual(self):
+ self.assertTrue(passing_run(['passes/text.html', 'passes/args.html',
+ 'virtual/passes/text.html', 'virtual/passes/args.html']))
+
def test_worker_model__inline(self):
self.assertTrue(passing_run(['--worker-model', 'inline']))
diff --git a/Tools/Scripts/webkitpy/layout_tests/servers/http_server.py b/Tools/Scripts/webkitpy/layout_tests/servers/http_server.py
index 1f14e0dad..8def09d0a 100755
--- a/Tools/Scripts/webkitpy/layout_tests/servers/http_server.py
+++ b/Tools/Scripts/webkitpy/layout_tests/servers/http_server.py
@@ -179,11 +179,11 @@ class Lighttpd(http_server_base.HttpServerBase):
# bug that mod_alias.so loads it from the hard coded path.
if sys.platform == 'darwin':
tmp_module_path = '/tmp/lighttpd/lib'
- if not os.path.exists(tmp_module_path):
- os.makedirs(tmp_module_path)
+ if not self._filesystem.exists(tmp_module_path):
+ self._filesystem.maybe_make_directory(tmp_module_path)
lib_file = 'liblightcomp.dylib'
- self._filesystem.copyfile(os.path.join(module_path, lib_file),
- os.path.join(tmp_module_path, lib_file))
+ self._filesystem.copyfile(self._filesystem.join(module_path, lib_file),
+ self._filesystem.join(tmp_module_path, lib_file))
self._start_cmd = start_cmd
self._env = self._port_obj.setup_environ_for_server('lighttpd')
diff --git a/Tools/Scripts/webkitpy/layout_tests/views/printing.py b/Tools/Scripts/webkitpy/layout_tests/views/printing.py
index bccbb1a7c..750c48df9 100644
--- a/Tools/Scripts/webkitpy/layout_tests/views/printing.py
+++ b/Tools/Scripts/webkitpy/layout_tests/views/printing.py
@@ -315,18 +315,25 @@ class Printer(object):
- actual result
- timing info
"""
- filename = self._port.abspath_for_test(result.test_name)
test_name = result.test_name
self._write('trace: %s' % test_name)
+
+ base = self._port.lookup_virtual_test_base(test_name)
+ if base:
+ args = ' '.join(self._port.lookup_virtual_test_args(test_name))
+ self._write(' base: %s' % base)
+ self._write(' args: %s' % args)
+
for extension in ('.txt', '.png', '.wav', '.webarchive'):
- self._print_baseline(filename, extension)
+ self._print_baseline(test_name, extension)
+
self._write(' exp: %s' % exp_str)
self._write(' got: %s' % got_str)
self._write(' took: %-.3f' % result.test_run_time)
self._write('')
- def _print_baseline(self, filename, extension):
- baseline = self._port.expected_filename(filename, extension)
+ def _print_baseline(self, test_name, extension):
+ baseline = self._port.expected_filename(test_name, extension)
if self._port._filesystem.exists(baseline):
relpath = self._port.relative_test_filename(baseline)
else:
diff --git a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
index 189500f6a..8cc0d745e 100644
--- a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
+++ b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
@@ -99,6 +99,8 @@ class PerfTestsRunner(object):
help="Path to a JSON file to be merged into the JSON file when --output-json-path is present"),
optparse.make_option("--test-results-server",
help="Upload the generated JSON file to the specified server when --output-json-path is present"),
+ optparse.make_option("--webkit-test-runner", "-2", action="store_true",
+ help="Use WebKitTestRunner rather than DumpRenderTree."),
]
option_list = (perf_option_list + print_options)
@@ -302,6 +304,8 @@ class PerfTestsRunner(object):
def _run_single_test(self, test, driver, is_chromium_style):
test_failed = False
+ start_time = time.time()
+
output = driver.run_test(DriverInput(test, self._options.time_out_ms, None, False))
if output.text == None:
@@ -325,4 +329,6 @@ class PerfTestsRunner(object):
if test_failed:
self._printer.write('FAILED')
+ self._printer.write("Finished: %f s" % (time.time() - start_time))
+
return not test_failed
diff --git a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
index e194072c3..1a287a7cf 100755
--- a/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
+++ b/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
@@ -174,7 +174,7 @@ max 1120
unexpected_result_count = runner._run_tests_set(tests, runner._port)
self.assertEqual(TestDriverWithStopCount.stop_count, 6)
- def test_run_test_set_kills_drt_per_run(self):
+ def test_run_test_pause_before_testing(self):
class TestDriverWithStartCount(MainTest.TestDriver):
start_count = 0
@@ -195,7 +195,7 @@ max 1120
finally:
_, stderr, logs = output.restore_output()
self.assertEqual(stderr, "Ready to run test?\n")
- self.assertEqual(logs, "Running inspector/pass.html (1 of 1)\n\n")
+ self.assertTrue("Running inspector/pass.html (1 of 1)" in logs)
def test_run_test_set_for_parser_tests(self):
buildbot_output = StringIO.StringIO()
@@ -280,6 +280,10 @@ max 1120
self.assertEqual(generated_json['builder-name'], 'builder1')
self.assertEqual(generated_json['build-number'], 123)
upload_json_returns_true = False
+
+ runner = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
+ '--test-results-server', 'some.host', '--platform', 'platform1', '--builder-name', 'builder1', '--build-number', '123'])
+ runner._upload_json = mock_upload_json
self.assertEqual(runner.run(), -3)
def test_upload_json(self):
diff --git a/Tools/Scripts/webkitpy/style/checkers/changelog.py b/Tools/Scripts/webkitpy/style/checkers/changelog.py
index d744bc87d..a096d3f46 100644
--- a/Tools/Scripts/webkitpy/style/checkers/changelog.py
+++ b/Tools/Scripts/webkitpy/style/checkers/changelog.py
@@ -68,6 +68,14 @@ class ChangeLogChecker(object):
"changelog/filechangedescriptionwhitespace", 5,
"Need whitespace between colon and description")
+ # check for a lingering "No new tests. (OOPS!)" left over from prepare-changeLog.
+ line_no = first_line_checked - 1
+ for line in entry_lines:
+ line_no = line_no + 1
+ if re.match('\s*No new tests. \(OOPS!\)$', line):
+ self.handle_style_error(line_no,
+ "changelog/nonewtests", 5,
+ "You should remove the 'No new tests' and either add and list tests, or explain why no new tests were possible.")
def check(self, lines):
self._tab_checker.check(lines)
diff --git a/Tools/Scripts/webkitpy/style/checkers/changelog_unittest.py b/Tools/Scripts/webkitpy/style/checkers/changelog_unittest.py
index 842eaa16b..9fe8a60bc 100644
--- a/Tools/Scripts/webkitpy/style/checkers/changelog_unittest.py
+++ b/Tools/Scripts/webkitpy/style/checkers/changelog_unittest.py
@@ -121,6 +121,14 @@ class ChangeLogCheckerTest(unittest.TestCase):
' * Source/Tools/random-script.py:Fixed\n'
' * Source/Tools/one-morefile:\n')
+ def test_no_new_tests(self):
+ self.assert_error(5, range(1, 20), 'changelog/nonewtests',
+ '2011-01-01 Dmitry Lomov <dslomov@google.com>\n'
+ ' ExampleBug\n'
+ ' http://bugs.webkit.org/show_bug.cgi?id=12345\n'
+ '\n'
+ ' No new tests. (OOPS!)\n'
+ ' * Source/Tools/random-script.py: Fixed')
def test_no_error(self):
self.assert_no_error([],
diff --git a/Tools/Scripts/webkitpy/test/main.py b/Tools/Scripts/webkitpy/test/main.py
index 78c39db55..76dac0e3b 100644
--- a/Tools/Scripts/webkitpy/test/main.py
+++ b/Tools/Scripts/webkitpy/test/main.py
@@ -198,7 +198,7 @@ class Tester(object):
def _run_tests(self, dirs, args):
if self._options.coverage:
try:
- import coverage
+ import webkitpy.thirdparty.autoinstalled.coverage as coverage
except ImportError, e:
_log.error("Failed to import 'coverage'; can't generate coverage numbers.")
return False
@@ -233,6 +233,7 @@ class Tester(object):
if self._options.coverage:
cov.stop()
cov.save()
+ cov.report(show_missing=False)
return result.wasSuccessful()
def _is_module(self, dirs, name):
diff --git a/Tools/Scripts/webkitpy/thirdparty/__init__.py b/Tools/Scripts/webkitpy/thirdparty/__init__.py
index e7a12e685..2c39de6cc 100644
--- a/Tools/Scripts/webkitpy/thirdparty/__init__.py
+++ b/Tools/Scripts/webkitpy/thirdparty/__init__.py
@@ -74,6 +74,8 @@ class AutoinstallImportHook(object):
self._install_mechanize()
elif '.pep8' in fullname:
self._install_pep8()
+ elif '.coverage' in fullname:
+ self._install_coverage()
elif '.eliza' in fullname:
self._install_eliza()
elif '.irc' in fullname:
@@ -108,6 +110,10 @@ class AutoinstallImportHook(object):
self._install("http://pypi.python.org/packages/source/b/buildbot/buildbot-0.8.4p2.tar.gz#md5=7597d945724c80c0ab476e833a1026cb", "buildbot-0.8.4p2/buildbot")
+ def _install_coverage(self):
+ installer = AutoInstaller(target_dir=_AUTOINSTALLED_DIR)
+ installer.install(url="http://pypi.python.org/packages/source/c/coverage/coverage-3.5.1.tar.gz#md5=410d4c8155a4dab222f2bc51212d4a24", url_subpath="coverage-3.5.1/coverage")
+
def _install_eliza(self):
installer = AutoInstaller(target_dir=_AUTOINSTALLED_DIR)
installer.install(url="http://www.adambarth.com/webkit/eliza",
diff --git a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py b/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py
deleted file mode 100644
index 27db72022..000000000
--- a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py
+++ /dev/null
@@ -1,1044 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2010 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * 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.
-
-"""Rebaselining tool that automatically produces baselines for all platforms.
-
-The script does the following for each platform specified:
- 1. Compile a list of tests that need rebaselining.
- 2. Download test result archive from buildbot for the platform.
- 3. Extract baselines from the archive file for all identified files.
- 4. Add new baselines to SVN repository.
- 5. For each test that has been rebaselined, remove this platform option from
- the test in test_expectation.txt. If no other platforms remain after
- removal, delete the rebaselined test from the file.
-
-At the end, the script generates a html that compares old and new baselines.
-"""
-
-import copy
-import logging
-import optparse
-import re
-import sys
-import time
-
-from webkitpy.common.checkout import scm
-from webkitpy.common.system import zipfileset
-from webkitpy.common.system import path
-from webkitpy.common.system import urlfetcher
-from webkitpy.common.system.executive import ScriptError
-from webkitpy.common.host import Host
-
-from webkitpy.layout_tests.port.factory import PortFactory
-from webkitpy.layout_tests import read_checksum_from_png
-from webkitpy.layout_tests.models import test_expectations
-
-
-_log = logging.getLogger(__name__)
-
-BASELINE_SUFFIXES = ('.txt', '.png', '.checksum')
-
-ARCHIVE_DIR_NAME_DICT = {
- 'chromium-win-win7': 'Webkit_Win7',
- 'chromium-win-vista': 'Webkit_Vista',
- 'chromium-win-xp': 'Webkit_Win',
- 'chromium-mac-leopard': 'Webkit_Mac10_5',
- 'chromium-mac-snowleopard': 'Webkit_Mac10_6',
- 'chromium-linux-x86': 'Webkit_Linux_32',
- 'chromium-linux-x86_64': 'Webkit_Linux',
- 'chromium-gpu-mac-snowleopard': 'Webkit_Mac10_6_-_GPU',
- 'chromium-gpu-win-xp': 'Webkit_Win_-_GPU',
- 'chromium-gpu-win-win7': 'Webkit_Win7_-_GPU',
- 'chromium-gpu-linux-x86_64': 'Webkit_Linux_-_GPU',
- 'chromium-gpu-linux-x86': 'Webkit_Linux_32_-_GPU',
-}
-
-
-def log_dashed_string(text, platform=None, logging_level=logging.DEBUG):
- """Log text message with dashes on both sides."""
- msg = text
- if platform:
- msg += ': ' + platform
- if len(msg) < 78:
- dashes = '-' * ((78 - len(msg)) / 2)
- msg = '%s %s %s' % (dashes, msg, dashes)
- _log.log(logging_level, msg)
-
-
-def setup_html_directory(filesystem, parent_directory):
- """Setup the directory to store html results.
-
- All html related files are stored in the "rebaseline_html" subdirectory of
- the parent directory. The path to the created directory is returned.
- """
-
- if not parent_directory:
- parent_directory = str(filesystem.mkdtemp())
- else:
- filesystem.maybe_make_directory(parent_directory)
-
- html_directory = filesystem.join(parent_directory, 'rebaseline_html')
- _log.debug('Html directory: "%s"', html_directory)
-
- if filesystem.exists(html_directory):
- filesystem.rmtree(html_directory)
- _log.debug('Deleted html directory: "%s"', html_directory)
-
- filesystem.maybe_make_directory(html_directory)
- return html_directory
-
-
-def get_result_file_fullpath(filesystem, html_directory, baseline_filename, platform,
- result_type):
- """Get full path of the baseline result file.
-
- Args:
- filesystem: wrapper object
- html_directory: directory that stores the html related files.
- baseline_filename: name of the baseline file.
- platform: win, linux or mac
- result_type: type of the baseline result: '.txt', '.png'.
-
- Returns:
- Full path of the baseline file for rebaselining result comparison.
- """
-
- base, ext = filesystem.splitext(baseline_filename)
- result_filename = '%s-%s-%s%s' % (base, platform, result_type, ext)
- fullpath = filesystem.join(html_directory, result_filename)
- _log.debug(' Result file full path: "%s".', fullpath)
- return fullpath
-
-
-class Rebaseliner(object):
- """Class to produce new baselines for a given platform."""
-
- REVISION_REGEX = r'<a href=\"(\d+)/\">'
-
- def __init__(self, host, running_port, target_port, platform, options, url_fetcher, zip_factory, logged_before=False):
- """
- Args:
- running_port: the Port the script is running on.
- target_port: the Port the script uses to find port-specific
- configuration information like the test_expectations.txt
- file location and the list of test platforms.
- platform: the test platform to rebaseline
- options: the command-line options object.
- url_fetcher: object that can fetch objects from URLs
- zip_factory: optional object that can fetch zip files from URLs
- scm: scm object for adding new baselines
- logged_before: whether the previous running port logged anything.
- """
- self._platform = platform
- self._options = options
- self._port = running_port
- self._filesystem = host.filesystem
- self._target_port = target_port
-
- self._rebaseline_port = host.port_factory.get(platform, options)
- self._rebaselining_tests = set()
- self._rebaselined_tests = []
- self._logged_before = logged_before
- self.did_log = False
-
- # Create tests and expectations helper which is used to:
- # -. compile list of tests that need rebaselining.
- # -. update the tests in test_expectations file after rebaseline
- # is done.
- expectations_str = self._rebaseline_port.test_expectations()
- self._test_expectations = test_expectations.TestExpectations(
- self._rebaseline_port, None, expectations_str, self._rebaseline_port.test_configuration(), False)
- self._url_fetcher = url_fetcher
- self._zip_factory = zip_factory
- self._scm = host.scm()
-
- def run(self):
- """Run rebaseline process."""
-
- log_dashed_string('Compiling rebaselining tests', self._platform, logging.DEBUG)
- if not self._compile_rebaselining_tests():
- return False
- if not self._rebaselining_tests:
- return True
-
- self.did_log = True
- log_dashed_string('Downloading archive', self._platform, logging.DEBUG)
- archive_file = self._download_buildbot_archive()
- _log.debug('')
- if not archive_file:
- _log.error('No archive found.')
- return False
-
- log_dashed_string('Extracting and adding new baselines', self._platform, logging.DEBUG)
- self._extract_and_add_new_baselines(archive_file)
- archive_file.close()
-
- log_dashed_string('Updating rebaselined tests in file', self._platform)
-
- if len(self._rebaselining_tests) != len(self._rebaselined_tests):
- _log.debug('')
- _log.debug('NOT ALL TESTS WERE REBASELINED.')
- _log.debug(' Number marked for rebaselining: %d', len(self._rebaselining_tests))
- _log.debug(' Number actually rebaselined: %d', len(self._rebaselined_tests))
- _log.info('')
- return False
-
- _log.debug(' All tests needing rebaselining were successfully rebaselined.')
- _log.info('')
- return True
-
- def remove_rebaselining_expectations(self, tests, backup):
- """if backup is True, we backup the original test expectations file."""
- new_expectations = self._test_expectations.remove_rebaselined_tests(tests)
- path = self._target_port.path_to_test_expectations_file()
- if backup:
- date_suffix = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
- backup_file = '%s.orig.%s' % (path, date_suffix)
- if self._filesystem.exists(backup_file):
- self._filesystem.remove(backup_file)
- _log.debug('Saving original file to "%s"', backup_file)
- self._filesystem.move(path, backup_file)
-
- self._filesystem.write_text_file(path, new_expectations)
- # self._scm.add(path)
-
- def get_rebaselined_tests(self):
- return self._rebaselined_tests
-
- def _compile_rebaselining_tests(self):
- """Compile list of tests that need rebaselining for the platform.
-
- Returns:
- False if reftests are wrongly marked as 'needs rebaselining' or True
- """
-
- self._rebaselining_tests = self._test_expectations.get_rebaselining_failures()
- if not self._rebaselining_tests:
- _log.info('%s: No tests to rebaseline.', self._platform)
- return True
-
- fs = self._target_port._filesystem
- for test in self._rebaselining_tests:
- if self._target_port.reference_files(test):
- _log.error('%s seems to be a reftest. We can not rebase for reftests.', test)
- self._rebaselining_tests = set()
- return False
-
- if not self._logged_before:
- _log.info('')
- _log.info('%s: Rebaselining %d tests:', self._platform, len(self._rebaselining_tests))
- test_no = 1
- for test in self._rebaselining_tests:
- _log.debug(' %d: %s', test_no, test)
- test_no += 1
-
- return True
-
- def _get_latest_revision(self, url):
- """Get the latest layout test revision number from buildbot.
-
- Args:
- url: Url to retrieve layout test revision numbers.
-
- Returns:
- latest revision or
- None on failure.
- """
-
- _log.debug('Url to retrieve revision: "%s"', url)
-
- content = self._url_fetcher.fetch(url)
-
- revisions = re.findall(self.REVISION_REGEX, content)
- if not revisions:
- _log.error('Failed to find revision, content: "%s"', content)
- return None
-
- revisions.sort(key=int)
- _log.debug(' Latest revision: %s', revisions[len(revisions) - 1])
- return revisions[len(revisions) - 1]
-
- def _get_archive_dir_name(self, platform):
- """Get name of the layout test archive directory.
-
- Returns:
- Directory name or
- None on failure
- """
-
- if platform in ARCHIVE_DIR_NAME_DICT:
- return ARCHIVE_DIR_NAME_DICT[platform]
- else:
- _log.error('Cannot find platform key %s in archive '
- 'directory name dictionary', platform)
- return None
-
- def _get_archive_url(self):
- """Generate the url to download latest layout test archive.
-
- Returns:
- Url to download archive or
- None on failure
- """
-
- if self._options.force_archive_url:
- return self._options.force_archive_url
-
- dir_name = self._get_archive_dir_name(self._platform)
- if not dir_name:
- return None
-
- _log.debug('Buildbot platform dir name: "%s"', dir_name)
-
- url_base = '%s/%s/' % (self._options.archive_url, dir_name)
- latest_revision = self._get_latest_revision(url_base)
- if latest_revision is None or latest_revision <= 0:
- return None
- archive_url = '%s%s/layout-test-results.zip' % (url_base, latest_revision)
- _log.info(' Using %s', archive_url)
- return archive_url
-
- def _download_buildbot_archive(self):
- """Download layout test archive file from buildbot and return a handle to it."""
- url = self._get_archive_url()
- if url is None:
- return None
-
- archive_file = zipfileset.ZipFileSet(url, filesystem=self._filesystem,
- zip_factory=self._zip_factory)
- _log.debug('Archive downloaded')
- return archive_file
-
- def _extract_and_add_new_baselines(self, zip_file):
- """Extract new baselines from the zip file and add them to SVN repository.
-
- Returns:
- List of tests that have been rebaselined or None on failure."""
- zip_namelist = zip_file.namelist()
-
- _log.debug('zip file namelist:')
- for name in zip_namelist:
- _log.debug(' ' + name)
-
- _log.debug('Platform dir: "%s"', self._platform)
-
- self._rebaselined_tests = []
- for test_no, test in enumerate(self._rebaselining_tests):
- _log.debug('Test %d: %s', test_no + 1, test)
- self._extract_and_add_new_baseline(test, zip_file)
-
- def _extract_and_add_new_baseline(self, test, zip_file):
- found = False
- scm_error = False
- test_basename = self._filesystem.splitext(test)[0]
- for suffix in BASELINE_SUFFIXES:
- archive_test_name = 'layout-test-results/%s-actual%s' % (test_basename, suffix)
- _log.debug(' Archive test file name: "%s"', archive_test_name)
- if not archive_test_name in zip_file.namelist():
- _log.debug(' %s file not in archive.', suffix)
- continue
-
- found = True
- _log.debug(' %s file found in archive.', suffix)
-
- temp_name = self._extract_from_zip_to_tempfile(zip_file, archive_test_name)
-
- expected_filename = '%s-expected%s' % (test_basename, suffix)
- expected_fullpath = self._filesystem.join(
- self._rebaseline_port.baseline_path(), expected_filename)
- expected_fullpath = self._filesystem.normpath(expected_fullpath)
- _log.debug(' Expected file full path: "%s"', expected_fullpath)
-
- relpath = self._filesystem.relpath(expected_fullpath, self._target_port.layout_tests_dir())
-
- # TODO(victorw): for now, the rebaselining tool checks whether
- # or not THIS baseline is duplicate and should be skipped.
- # We could improve the tool to check all baselines in upper
- # and lower levels and remove all duplicated baselines.
- if self._is_dup_baseline(temp_name, expected_fullpath, test, suffix, self._platform):
- self._filesystem.remove(temp_name)
- if self._filesystem.exists(expected_fullpath):
- _log.info(' Removing %s' % relpath)
- self._delete_baseline(expected_fullpath)
- _log.debug(' %s is a duplicate' % relpath)
-
- # FIXME: We consider a duplicate baseline a success in the normal case.
- # FIXME: This may not be what you want sometimes; should this be
- # FIXME: controllable?
- self._rebaselined_tests.append(test)
- continue
-
- if suffix == '.checksum' and self._png_has_same_checksum(temp_name, test, expected_fullpath):
- self._filesystem.remove(temp_name)
- # If an old checksum exists, delete it.
- self._delete_baseline(expected_fullpath)
- continue
-
- self._filesystem.maybe_make_directory(self._filesystem.dirname(expected_fullpath))
- self._filesystem.move(temp_name, expected_fullpath)
-
- path_from_base = self._filesystem.relpath(expected_fullpath)
- if self._scm.exists(path_from_base):
- _log.info(' Updating %s' % relpath)
- else:
- _log.info(' Adding %s' % relpath)
-
- if self._scm.add(expected_fullpath, return_exit_code=True):
- # FIXME: print detailed diagnose messages
- scm_error = True
- elif suffix != '.checksum':
- self._create_html_baseline_files(expected_fullpath)
-
- if not found:
- _log.warn('No results in archive for %s' % test)
- elif scm_error:
- _log.warn('Failed to add baselines to your repository.')
- else:
- _log.debug(' Rebaseline succeeded.')
- self._rebaselined_tests.append(test)
-
- def _extract_from_zip_to_tempfile(self, zip_file, filename):
- """Extracts |filename| from |zip_file|, a ZipFileSet. Returns the full
- path name to the extracted file."""
- data = zip_file.read(filename)
- suffix = self._filesystem.splitext(filename)[1]
- tempfile, temp_name = self._filesystem.open_binary_tempfile(suffix)
- tempfile.write(data)
- tempfile.close()
- return temp_name
-
- def _png_has_same_checksum(self, checksum_path, test, checksum_expected_fullpath):
- """Returns True if the fallback png for |checksum_expected_fullpath|
- contains the same checksum."""
- fs = self._filesystem
- png_fullpath = self._first_fallback_png_for_test(test)
-
- if not fs.exists(png_fullpath):
- _log.error(' Checksum without png file found! Expected %s to exist.' % png_fullpath)
- return False
-
- with fs.open_binary_file_for_reading(png_fullpath) as filehandle:
- checksum_in_png = read_checksum_from_png.read_checksum(filehandle)
- checksum_in_text_file = fs.read_text_file(checksum_path)
- if checksum_in_png and checksum_in_png != checksum_in_text_file:
- _log.error(" checksum in %s and %s don't match! Continuing"
- " to copy but please investigate." % (
- checksum_expected_fullpath, png_fullpath))
- return checksum_in_text_file == checksum_in_png
-
- def _first_fallback_png_for_test(self, test):
- all_baselines = self._rebaseline_port.expected_baselines(test, '.png', True)
- return self._filesystem.join(all_baselines[0][0], all_baselines[0][1])
-
- def _is_dup_baseline(self, new_baseline, baseline_path, test, suffix, platform):
- """Check whether a baseline is duplicate and can fallback to same
- baseline for another platform. For example, if a test has same
- baseline on linux and windows, then we only store windows
- baseline and linux baseline will fallback to the windows version.
-
- Args:
- new_baseline: temp filename containing the new baseline results
- baseline_path: baseline expectation file name.
- test: test name.
- suffix: file suffix of the expected results, including dot;
- e.g. '.txt' or '.png'.
- platform: baseline platform 'mac', 'win' or 'linux'.
-
- Returns:
- True if the baseline is unnecessary.
- False otherwise.
- """
- all_baselines = self._rebaseline_port.expected_baselines(test, suffix, True)
-
- for fallback_dir, fallback_file in all_baselines:
- if not fallback_dir or not fallback_file:
- continue
-
- fallback_fullpath = self._filesystem.normpath(
- self._filesystem.join(fallback_dir, fallback_file))
- if fallback_fullpath.lower() == baseline_path.lower():
- continue
- fallback_dir_relpath = self._filesystem.relpath(fallback_dir, self._target_port.layout_tests_dir())
- if fallback_dir_relpath == '':
- fallback_dir_relpath = '<generic>'
-
- new_output = self._filesystem.read_binary_file(new_baseline)
- fallback_output = self._filesystem.read_binary_file(fallback_fullpath)
- is_image = baseline_path.lower().endswith('.png')
- if not self._diff_baselines(new_output, fallback_output, is_image):
- _log.info(' Skipping %s (matches %s)', test, fallback_dir_relpath)
- return True
- return False
-
- return False
-
- def _diff_baselines(self, output1, output2, is_image):
- """Check whether two baselines are different.
-
- Args:
- output1, output2: contents of the baselines to compare.
-
- Returns:
- True if two files are different or have different extensions.
- False otherwise.
- """
-
- if is_image:
- return self._port.diff_image(output1, output2)[0]
-
- return self._port.do_text_results_differ(output1, output2)
-
- def _delete_baseline(self, filename):
- """Remove the file from repository and delete it from disk.
-
- Args:
- filename: full path of the file to delete.
- """
-
- if not filename or not self._filesystem.isfile(filename):
- return
- self._scm.delete(filename)
-
- def _create_html_baseline_files(self, baseline_fullpath):
- """Create baseline files (old, new and diff) in html directory.
-
- The files are used to compare the rebaselining results.
-
- Args:
- baseline_fullpath: full path of the expected baseline file.
- """
-
- baseline_relpath = self._filesystem.relpath(baseline_fullpath)
- _log.debug(' Html: create baselines for "%s"', baseline_relpath)
-
- if (not baseline_fullpath
- or not self._filesystem.exists(baseline_fullpath)):
- _log.debug(' Html: Does not exist: "%s"', baseline_fullpath)
- return
-
- if not self._scm.exists(baseline_relpath):
- _log.debug(' Html: Does not exist in scm: "%s"', baseline_relpath)
- return
-
- # Copy the new baseline to html directory for result comparison.
- baseline_filename = self._filesystem.basename(baseline_fullpath)
- new_file = get_result_file_fullpath(self._filesystem, self._options.html_directory,
- baseline_filename, self._platform, 'new')
- self._filesystem.copyfile(baseline_fullpath, new_file)
- _log.debug(' Html: copied new baseline file from "%s" to "%s".',
- baseline_fullpath, new_file)
-
- # Get the old baseline from the repository and save to the html directory.
- try:
- output = self._scm.show_head(baseline_relpath)
- except ScriptError, e:
- _log.warning(e)
- output = ""
-
- if (not output) or (output.upper().rstrip().endswith('NO SUCH FILE OR DIRECTORY')):
- _log.warning(' No base file: "%s"', baseline_fullpath)
- return
- base_file = get_result_file_fullpath(self._filesystem, self._options.html_directory,
- baseline_filename, self._platform, 'old')
- if base_file.upper().endswith('.PNG'):
- self._filesystem.write_binary_file(base_file, output)
- else:
- self._filesystem.write_text_file(base_file, output)
- _log.debug(' Html: created old baseline file: "%s".', base_file)
-
- # Get the diff between old and new baselines and save to the html dir.
- diff_file = get_result_file_fullpath(self._filesystem,
- self._options.html_directory,
- baseline_filename,
- self._platform, 'diff')
- has_diff = False
- if baseline_filename.upper().endswith('.TXT'):
- output = self._scm.diff_for_file(baseline_relpath, log=_log)
- if output:
- self._filesystem.write_text_file(diff_file, output)
- has_diff = True
- elif baseline_filename.upper().endswith('.PNG'):
- old_file = get_result_file_fullpath(self._filesystem,
- self._options.html_directory,
- baseline_filename,
- self._platform, 'old')
- new_file = get_result_file_fullpath(self._filesystem,
- self._options.html_directory,
- baseline_filename,
- self._platform, 'new')
- _log.debug(' Html: diffing "%s" and "%s"', old_file, new_file)
- old_output = self._filesystem.read_binary_file(old_file)
- new_output = self._filesystem.read_binary_file(new_file)
- image_diff = self._port.diff_image(old_output, new_output)[0]
- self._filesystem.write_binary_file(diff_file, image_diff)
-
- if has_diff:
- _log.debug(' Html: created baseline diff file: "%s".', diff_file)
-
-
-class HtmlGenerator(object):
- """Class to generate rebaselining result comparison html."""
-
- HTML_REBASELINE = ('<html>'
- '<head>'
- '<style>'
- 'body {font-family: sans-serif;}'
- '.mainTable {background: #666666;}'
- '.mainTable td , .mainTable th {background: white;}'
- '.detail {margin-left: 10px; margin-top: 3px;}'
- '</style>'
- '<title>Rebaselining Result Comparison (%(time)s)'
- '</title>'
- '</head>'
- '<body>'
- '<h2>Rebaselining Result Comparison (%(time)s)</h2>'
- '%(body)s'
- '</body>'
- '</html>')
- HTML_NO_REBASELINING_TESTS = (
- '<p>No tests found that need rebaselining.</p>')
- HTML_TABLE_TEST = ('<table class="mainTable" cellspacing=1 cellpadding=5>'
- '%s</table><br>')
- HTML_TR_TEST = ('<tr>'
- '<th style="background-color: #CDECDE; border-bottom: '
- '1px solid black; font-size: 18pt; font-weight: bold" '
- 'colspan="5">'
- '<a href="%s">%s</a>'
- '</th>'
- '</tr>')
- HTML_TEST_DETAIL = ('<div class="detail">'
- '<tr>'
- '<th width="100">Baseline</th>'
- '<th width="100">Platform</th>'
- '<th width="200">Old</th>'
- '<th width="200">New</th>'
- '<th width="150">Difference</th>'
- '</tr>'
- '%s'
- '</div>')
- HTML_TD_NOLINK = '<td align=center><a>%s</a></td>'
- HTML_TD_LINK = '<td align=center><a href="%(uri)s">%(name)s</a></td>'
- HTML_TD_LINK_IMG = ('<td><a href="%(uri)s">'
- '<img style="width: 200" src="%(uri)s" /></a></td>')
- HTML_TR = '<tr>%s</tr>'
-
- def __init__(self, host, port, target_port, options, platforms, rebaselining_tests):
- self._html_directory = options.html_directory
- self._host = host
- self._filesystem = host.filesystem
- self._port = port
- self._target_port = target_port
- self._options = options
- self._platforms = platforms
- self._rebaselining_tests = rebaselining_tests
- self._html_file = self._filesystem.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._port._executive)
-
- def generate_html(self):
- """Generate html file for rebaselining result comparison."""
-
- _log.debug('Generating html file')
-
- html_body = ''
- if not self._rebaselining_tests:
- html_body += self.HTML_NO_REBASELINING_TESTS
- else:
- tests = list(self._rebaselining_tests)
- tests.sort()
-
- test_no = 1
- for test in tests:
- _log.debug('Test %d: %s', test_no, test)
- html_body += self._generate_html_for_one_test(test)
-
- html = self.HTML_REBASELINE % ({'time': time.asctime(),
- 'body': html_body})
- _log.debug(html)
-
- self._filesystem.write_text_file(self._html_file, html)
- _log.debug('Baseline comparison html generated at "%s"', self._html_file)
-
- def show_html(self):
- """Launch the rebaselining html in brwoser."""
-
- _log.debug('Launching html: "%s"', self._html_file)
- self._host.user.open_url(self._html_file)
- _log.debug('Html launched.')
-
- def _generate_baseline_links(self, test_basename, suffix, platform):
- """Generate links for baseline results (old, new and diff).
-
- Args:
- test_basename: base filename of the test
- suffix: baseline file suffixes: '.txt', '.png'
- platform: win, linux or mac
-
- Returns:
- html links for showing baseline results (old, new and diff)
- """
-
- baseline_filename = '%s-expected%s' % (test_basename, suffix)
- _log.debug(' baseline filename: "%s"', baseline_filename)
-
- new_file = get_result_file_fullpath(self._filesystem, self._html_directory,
- baseline_filename, platform, 'new')
- _log.debug(' New baseline file: "%s"', new_file)
- if not self._filesystem.exists(new_file):
- _log.debug(' No new baseline file: "%s"', new_file)
- return ''
-
- old_file = get_result_file_fullpath(self._filesystem, self._html_directory,
- baseline_filename, platform, 'old')
- _log.debug(' Old baseline file: "%s"', old_file)
- if suffix == '.png':
- html_td_link = self.HTML_TD_LINK_IMG
- else:
- html_td_link = self.HTML_TD_LINK
-
- links = ''
- if self._filesystem.exists(old_file):
- links += html_td_link % {
- 'uri': self.abspath_to_uri(old_file),
- 'name': baseline_filename}
- else:
- _log.debug(' No old baseline file: "%s"', old_file)
- links += self.HTML_TD_NOLINK % ''
-
- links += html_td_link % {'uri': self.abspath_to_uri(new_file),
- 'name': baseline_filename}
-
- diff_file = get_result_file_fullpath(self._filesystem, self._html_directory,
- baseline_filename, platform, 'diff')
- _log.debug(' Baseline diff file: "%s"', diff_file)
- if self._filesystem.exists(diff_file):
- links += html_td_link % {'uri': self.abspath_to_uri(diff_file),
- 'name': 'Diff'}
- else:
- _log.debug(' No baseline diff file: "%s"', diff_file)
- links += self.HTML_TD_NOLINK % ''
-
- return links
-
- def _generate_html_for_one_test(self, test):
- """Generate html for one rebaselining test.
-
- Args:
- test: layout test name
-
- Returns:
- html that compares baseline results for the test.
- """
-
- test_basename = self._filesystem.basename(self._filesystem.splitext(test)[0])
- _log.debug(' basename: "%s"', test_basename)
- rows = []
- for suffix in BASELINE_SUFFIXES:
- if suffix == '.checksum':
- continue
-
- _log.debug(' Checking %s files', suffix)
- for platform in self._platforms:
- links = self._generate_baseline_links(test_basename, suffix, platform)
- if links:
- row = self.HTML_TD_NOLINK % self._get_baseline_result_type(suffix)
- row += self.HTML_TD_NOLINK % platform
- row += links
- _log.debug(' html row: %s', row)
-
- rows.append(self.HTML_TR % row)
-
- if rows:
- test_path = self._filesystem.join(self._target_port.layout_tests_dir(), 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)
- return self.HTML_TABLE_TEST % html
-
- return ''
-
- def _get_baseline_result_type(self, suffix):
- """Name of the baseline result type."""
-
- if suffix == '.png':
- return 'Pixel'
- elif suffix == '.txt':
- return 'Render Tree'
- else:
- return 'Other'
-
-
-def get_host_port_object(port_factory, options):
- """Return a port object for the platform we're running on."""
- # We want the ImageDiff logic to match that of the chromium bots, so we
- # force the use of a Chromium port. We will look for either Debug or
- # Release versions.
- options.configuration = "Release"
- options.chromium = True
- port_obj = port_factory.get(options=options)
- if not port_obj.check_image_diff(override_step=None, logging=False):
- _log.debug('No release version of the image diff binary was found.')
- options.configuration = "Debug"
- port_obj = port_factory.get(options=options)
- if not port_obj.check_image_diff(override_step=None, logging=False):
- _log.error('No version of image diff was found. Check your build.')
- return None
- else:
- _log.debug('Found the debug version of the image diff binary.')
- else:
- _log.debug('Found the release version of the image diff binary.')
- return port_obj
-
-
-def parse_options(args):
- """Parse options and return a pair of host options and target options."""
- option_parser = optparse.OptionParser()
- option_parser.add_option('-v', '--verbose',
- action='store_true',
- default=False,
- help='include debug-level logging.')
-
- option_parser.add_option('-q', '--quiet',
- action='store_true',
- help='Suppress result HTML viewing')
-
- option_parser.add_option('-p', '--platforms',
- default=None,
- help=('Comma delimited list of platforms '
- 'that need rebaselining.'))
-
- option_parser.add_option('-u', '--archive_url',
- default=('http://build.chromium.org/f/chromium/'
- 'layout_test_results'),
- help=('Url to find the layout test result archive'
- ' file.'))
- option_parser.add_option('-U', '--force_archive_url',
- help=('Url of result zip file. This option is for debugging '
- 'purposes'))
-
- option_parser.add_option('-b', '--backup',
- action='store_true',
- default=False,
- help=('Whether or not to backup the original test'
- ' expectations file after rebaseline.'))
-
- option_parser.add_option('-d', '--html_directory',
- default='',
- help=('The directory that stores the results for '
- 'rebaselining comparison.'))
-
- option_parser.add_option('', '--use_drt',
- action='store_true',
- default=False,
- help=('Use ImageDiff from DumpRenderTree instead '
- 'of image_diff for pixel tests.'))
-
- option_parser.add_option('-w', '--webkit_canary',
- action='store_true',
- default=False,
- help=('DEPRECATED. This flag no longer has any effect.'
- ' The canaries are always used.'))
-
- option_parser.add_option('', '--target-platform',
- default='chromium',
- help=('The target platform to rebaseline '
- '("mac", "chromium", "qt", etc.). Defaults '
- 'to "chromium".'))
-
- options = option_parser.parse_args(args)[0]
- if options.webkit_canary:
- print "-w/--webkit-canary is no longer necessary, ignoring."
-
- target_options = copy.copy(options)
- if options.target_platform == 'chromium':
- target_options.chromium = True
- options.tolerance = 0
-
- return (options, target_options)
-
-
-class DebugLogHandler(logging.Handler):
- num_failures = 0
-
- def __init__(self):
- logging.Handler.__init__(self)
- self.formatter = logging.Formatter(fmt=('%(asctime)s %(filename)s:%(lineno)-3d '
- '%(levelname)s %(message)s'))
- self.setFormatter(self.formatter)
-
- def emit(self, record):
- if record.levelno > logging.INFO:
- self.num_failures += 1
- print self.format(record)
-
-
-class NormalLogHandler(logging.Handler):
- last_levelno = None
- num_failures = 0
-
- def emit(self, record):
- if record.levelno > logging.INFO:
- self.num_failures += 1
- if self.last_levelno != record.levelno:
- print
- self.last_levelno = record.levelno
- prefix = ''
- msg = record.getMessage()
- if record.levelno > logging.INFO and msg:
- prefix = '%s: ' % record.levelname
- print '%s%s' % (prefix, msg)
-
-
-def main(args):
- """Bootstrap function that sets up the object references we need and calls real_main()."""
- options, target_options = parse_options(args)
-
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
- if options.verbose:
- log_level = logging.DEBUG
- log_handler = DebugLogHandler()
- else:
- log_level = logging.INFO
- log_handler = NormalLogHandler()
-
- logger = logging.getLogger()
- logger.setLevel(log_level)
- logger.addHandler(log_handler)
-
- host = Host()
- host._initialize_scm()
- target_port_obj = host.port_factory.get(None, target_options)
- host_port_obj = get_host_port_object(host.port_factory, options)
- if not host_port_obj or not target_port_obj:
- return 1
-
- url_fetcher = urlfetcher.UrlFetcher(host.filesystem)
-
- # We use the default zip factory method.
- zip_factory = None
-
- # FIXME: SCM module doesn't handle paths that aren't relative to the checkout_root consistently.
- host_port_obj._filesystem.chdir(host.scm().checkout_root)
-
- ret_code = real_main(host, options, target_options, host_port_obj, target_port_obj, url_fetcher, zip_factory)
- if not ret_code and log_handler.num_failures:
- ret_code = 1
- print ''
- if ret_code:
- print 'Rebaselining failed.'
- else:
- print 'Rebaselining succeeded.'
- return ret_code
-
-
-def real_main(host, options, target_options, host_port_obj, target_port_obj, url_fetcher, zip_factory):
- """Main function to produce new baselines. The Rebaseliner object uses two
- different Port objects - one to represent the machine the object is running
- on, and one to represent the port whose expectations are being updated.
- E.g., you can run the script on a mac and rebaseline the 'win' port.
-
- Args:
- host: Host object
- options: command-line argument used for the host_port_obj (see below)
- target_options: command_line argument used for the target_port_obj.
- This object may have slightly different values than |options|.
- host_port_obj: a Port object for the platform the script is running
- on. This is used to produce image and text diffs, mostly, and
- is usually acquired from get_host_port_obj().
- target_port_obj: a Port obj representing the port getting rebaselined.
- This is used to find the expectations file, the baseline paths,
- etc.
- url_fetcher: object used to download the build archives from the bots
- zip_factory: factory function used to create zip file objects for
- the archives.
- """
- options.html_directory = setup_html_directory(host_port_obj._filesystem, options.html_directory)
- all_platforms = target_port_obj.all_baseline_variants()
- if options.platforms:
- bail = False
- for platform in options.platforms:
- if not platform in all_platforms:
- _log.error('Invalid platform: "%s"' % (platform))
- bail = True
- if bail:
- return 1
- rebaseline_platforms = options.platforms
- else:
- rebaseline_platforms = all_platforms
-
- # FIXME: These log messages will be wrong if ports store baselines outside
- # of layout_tests_dir(), but the code should work correctly.
- layout_tests_dir = target_port_obj.layout_tests_dir()
- expectations_path = target_port_obj.path_to_test_expectations_file()
- _log.info('Using %s' % layout_tests_dir)
- _log.info(' and %s' % expectations_path)
-
- rebaselined_tests = set()
- logged_before = False
- for platform in rebaseline_platforms:
- rebaseliner = Rebaseliner(host, host_port_obj, target_port_obj,
- platform, options, url_fetcher, zip_factory,
- logged_before)
-
- _log.debug('')
- log_dashed_string('Rebaseline started', platform)
- if rebaseliner.run():
- log_dashed_string('Rebaseline done', platform)
- else:
- log_dashed_string('Rebaseline failed', platform)
-
- rebaselined_tests |= set(rebaseliner.get_rebaselined_tests())
- logged_before = rebaseliner.did_log
-
- if rebaselined_tests:
- rebaseliner.remove_rebaselining_expectations(rebaselined_tests,
- options.backup)
-
- _log.debug('')
- log_dashed_string('Rebaselining result comparison started')
- html_generator = HtmlGenerator(host, host_port_obj,
- target_port_obj,
- options,
- rebaseline_platforms,
- rebaselined_tests)
- html_generator.generate_html()
- if not options.quiet:
- html_generator.show_html()
- log_dashed_string('Rebaselining result comparison done')
-
- return 0
-
-
-if '__main__' == __name__:
- sys.exit(main(sys.argv[1:]))
diff --git a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests_unittest.py b/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests_unittest.py
deleted file mode 100644
index c44dcdf2f..000000000
--- a/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests_unittest.py
+++ /dev/null
@@ -1,387 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2010 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * 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.
-
-"""Unit tests for rebaseline_chromium_webkit_tests.py."""
-
-import unittest
-
-from webkitpy.tool.mocktool import MockOptions
-from webkitpy.common.system import urlfetcher_mock
-from webkitpy.common.host_mock import MockHost
-
-from webkitpy.common.system import zipfileset_mock
-from webkitpy.common.system import outputcapture
-from webkitpy.common.system.executive import Executive, ScriptError
-
-from webkitpy.layout_tests import port
-from webkitpy.to_be_moved import rebaseline_chromium_webkit_tests
-
-
-class MockPort(object):
- def __init__(self, image_diff_exists):
- self.image_diff_exists = image_diff_exists
-
- def check_image_diff(self, override_step, logging):
- return self.image_diff_exists
-
-
-class MockPortFactory(object):
- def __init__(self, config_expectations):
- self.config_expectations = config_expectations
-
- def get(self, port_name=None, options=None):
- return MockPort(self.config_expectations[options.configuration])
-
-
-ARCHIVE_URL = 'http://localhost/layout_test_results'
-
-
-def test_options():
- return MockOptions(configuration=None,
- backup=False,
- html_directory='/tmp',
- archive_url=ARCHIVE_URL,
- force_archive_url=None,
- verbose=False,
- quiet=False,
- platforms=None)
-
-
-def test_host_port_and_filesystem(options, expectations):
- host = MockHost()
- host_port_obj = host.port_factory.get('test', options)
- expectations_path = host_port_obj.path_to_test_expectations_file()
- host.filesystem.write_text_file(expectations_path, expectations)
- return (host, host_port_obj, host.filesystem)
-
-
-def test_url_fetcher(filesystem):
- urls = {
- ARCHIVE_URL + '/Webkit_Mac10_6/': '<a href="4/">',
- ARCHIVE_URL + '/Webkit_Mac10_5/': '<a href="1/"><a href="2/">',
- ARCHIVE_URL + '/Webkit_Win7/': '<a href="1/">',
- ARCHIVE_URL + '/Webkit_Vista/': '<a href="1/">',
- ARCHIVE_URL + '/Webkit_Win/': '<a href="1/">',
- ARCHIVE_URL + '/Webkit_Linux/': '<a href="1/">',
- }
- return urlfetcher_mock.make_fetcher_cls(urls)(filesystem)
-
-
-def test_zip_factory():
- ziphashes = {
- ARCHIVE_URL + '/Webkit_Mac10_5/2/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'new-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'new-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'new-image-png',
- 'layout-test-results/failures/expected/image_checksum-actual.txt': 'png-comment-txt',
- 'layout-test-results/failures/expected/image_checksum-actual.checksum': '0123456789',
- 'layout-test-results/failures/expected/image_checksum-actual.png': 'tEXtchecksum\x000123456789',
- },
- ARCHIVE_URL + '/Webkit_Mac10_6/4/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'new-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'new-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'new-image-png',
- },
- ARCHIVE_URL + '/Webkit_Vista/1/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
- },
- ARCHIVE_URL + '/Webkit_Win7/1/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
- },
- ARCHIVE_URL + '/Webkit_Win/1/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
- },
- ARCHIVE_URL + '/Webkit_Linux/1/layout-test-results.zip': {
- 'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
- 'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
- 'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
- },
- }
- return zipfileset_mock.make_factory(ziphashes)
-
-
-def test_archive(orig_archive_dict):
- new_archive_dict = {}
- for platform, dirname in orig_archive_dict.iteritems():
- # This is a giant hack. :(
- platform = platform.replace('chromium', 'test')
- new_archive_dict[platform] = dirname
- return new_archive_dict
-
-
-class TestGetHostPortObject(unittest.TestCase):
- def assert_result(self, release_present, debug_present, valid_port_obj):
- # Tests whether we get a valid port object returned when we claim
- # that Image diff is (or isn't) present in the two configs.
- port_factory = MockPortFactory({'Release': release_present, 'Debug': debug_present})
- options = MockOptions(configuration=None, html_directory='/tmp')
- port_obj = rebaseline_chromium_webkit_tests.get_host_port_object(port_factory, options)
- if valid_port_obj:
- self.assertNotEqual(port_obj, None)
- else:
- self.assertEqual(port_obj, None)
-
- def test_get_host_port_object(self):
- # Test whether we get a valid port object back for the four
- # possible cases of having ImageDiffs built. It should work when
- # there is at least one binary present.
- self.assert_result(False, False, False)
- self.assert_result(True, False, True)
- self.assert_result(False, True, True)
- self.assert_result(True, True, True)
-
-
-class TestOptions(unittest.TestCase):
- def test_parse_options(self):
- (options, target_options) = rebaseline_chromium_webkit_tests.parse_options([])
- self.assertTrue(target_options.chromium)
- self.assertEqual(options.tolerance, 0)
-
- (options, target_options) = rebaseline_chromium_webkit_tests.parse_options(['--target-platform', 'qt'])
- self.assertFalse(hasattr(target_options, 'chromium'))
- self.assertEqual(options.tolerance, 0)
-
-
-class TestRebaseliner(unittest.TestCase):
- def setUp(self):
- if not hasattr(self, '_orig_archive'):
- self._orig_archive = rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT
- rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = test_archive(self._orig_archive)
-
- def tearDown(self):
- rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = self._orig_archive
-
- def make_rebaseliner(self, expectations):
- options = test_options()
- host, host_port_obj, filesystem = test_host_port_and_filesystem(options, expectations)
-
- target_options = options
- target_port_obj = host.port_factory.get('test', target_options)
- platform = target_port_obj.name()
-
- url_fetcher = test_url_fetcher(filesystem)
- zip_factory = test_zip_factory()
-
- # FIXME: SCM module doesn't handle paths that aren't relative to the checkout_root consistently.
- filesystem.chdir(filesystem.dirname(host_port_obj.layout_tests_dir()))
-
- rebaseliner = rebaseline_chromium_webkit_tests.Rebaseliner(host, host_port_obj,
- target_port_obj, platform, options, url_fetcher, zip_factory)
- return rebaseliner, filesystem
-
- def test_noop(self):
- # this method tests that was can at least instantiate an object, even
- # if there is nothing to do.
- rebaseliner, filesystem = self.make_rebaseliner("")
- rebaseliner.run()
- self.assertEqual(len(filesystem.written_files), 1)
-
- def test_rebaselining_tests(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE MAC : failures/expected/image.html = IMAGE")
- compile_success = rebaseliner._compile_rebaselining_tests()
- self.assertTrue(compile_success)
- self.assertEqual(set(['failures/expected/image.html']), rebaseliner._rebaselining_tests)
-
- def test_rebaselining_tests_should_ignore_reftests(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE : failures/expected/reftest.html = IMAGE")
- compile_success = rebaseliner._compile_rebaselining_tests()
- self.assertFalse(compile_success)
- self.assertFalse(rebaseliner._rebaselining_tests)
-
- def test_one_platform(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE MAC : failures/expected/image.html = IMAGE")
-
- rebaseliner.run()
- layout_test_dir = rebaseliner._port.layout_tests_dir()
- # We expect to have written 13 files over the course of this rebaseline:
- # *) 3 files in /__im_tmp for the extracted archive members
- # *) 3 new baselines under layout_test_dir
- # *) 4 files in /tmp for the new and old baselines in the result file
- # (-{old,new}.{txt,png}
- # *) 1 text diff in /tmp for the result file (-diff.txt).
- # *) 1 image diff in /tmp for the result file (-diff.png).
- # *) 1 updated test_expectations file
- self.assertEqual(len(filesystem.written_files), 13)
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.checksum'], 'new-image-checksum')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.png'], 'new-image-png')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.txt'], 'new-image-txt')
-
- def test_all_platforms(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE : failures/expected/image.html = IMAGE")
- layout_test_dir = rebaseliner._port.layout_tests_dir()
- rebaseliner.run()
- # See comment in test_one_platform for an explanation of the 13 written tests.
- # Note that even though the rebaseline is marked for all platforms, each
- # rebaseliner only ever does one.
- self.assertEqual(len(filesystem.written_files), 13)
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.checksum'], 'new-image-checksum')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.png'], 'new-image-png')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image-expected.txt'], 'new-image-txt')
-
- def test_png_file_with_comment(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
- layout_test_dir = rebaseliner._port.layout_tests_dir()
- compile_success = rebaseliner._compile_rebaselining_tests()
- self.assertTrue(compile_success)
- self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
- rebaseliner.run()
- # There is one less file written than |test_one_platform| because we only
- # write 2 expectations (the png and the txt file).
- self.assertEqual(len(filesystem.written_files), 12)
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'], 'tEXtchecksum\x000123456789')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'], 'png-comment-txt')
- self.assertFalse(filesystem.files.get(layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None))
-
- def test_png_file_with_comment_remove_old_checksum(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
- layout_test_dir = rebaseliner._port.layout_tests_dir()
- filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'] = 'old'
- filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum'] = 'old'
- filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'] = 'old'
-
- compile_success = rebaseliner._compile_rebaselining_tests()
- self.assertTrue(compile_success)
- self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
- rebaseliner.run()
- # There is one more file written than |test_png_file_with_comment_remove_old_checksum|
- # because we also delete the old checksum.
- self.assertEqual(len(filesystem.written_files), 13)
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'], 'tEXtchecksum\x000123456789')
- self.assertEqual(filesystem.files[layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'], 'png-comment-txt')
- self.assertEqual(filesystem.files.get(layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None), None)
-
- def test_png_file_with_comment_as_duplicate(self):
- rebaseliner, filesystem = self.make_rebaseliner(
- "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
- layout_test_dir = rebaseliner._port.layout_tests_dir()
- filesystem.files[layout_test_dir + '/platform/test-mac-snowleopard/failures/expected/image_checksum-expected.png'] = 'tEXtchecksum\x000123456789'
- filesystem.files[layout_test_dir + '/platform/test-mac-snowleopard/failures/expected/image_checksum-expected.txt'] = 'png-comment-txt'
-
- compile_success = rebaseliner._compile_rebaselining_tests()
- self.assertTrue(compile_success)
- self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
- rebaseliner.run()
- self.assertEqual(filesystem.files.get(layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.png', None), None)
- self.assertEqual(filesystem.files.get(layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt', None), None)
- self.assertEqual(filesystem.files.get(layout_test_dir + '/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None), None)
-
- def test_diff_baselines_txt(self):
- rebaseliner, filesystem = self.make_rebaseliner("")
- port = rebaseliner._port
- output = port.expected_text('passes/text.html')
- self.assertFalse(rebaseliner._diff_baselines(output, output,
- is_image=False))
-
- def test_diff_baselines_png(self):
- rebaseliner, filesystem = self.make_rebaseliner('')
- port = rebaseliner._port
- image = port.expected_image('passes/image.html')
- self.assertFalse(rebaseliner._diff_baselines(image, image,
- is_image=True))
-
-
-class TestRealMain(unittest.TestCase):
- def setUp(self):
- if not hasattr(self, '_orig_archive'):
- self._orig_archive = rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT
- rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = test_archive(self._orig_archive)
-
- def tearDown(self):
- rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = self._orig_archive
-
- def test_all_platforms(self):
- expectations = "BUGX REBASELINE : failures/expected/image.html = IMAGE"
-
- options = test_options()
- host, host_port_obj, filesystem = test_host_port_and_filesystem(options, expectations)
- url_fetcher = test_url_fetcher(filesystem)
- zip_factory = test_zip_factory()
-
- # FIXME: SCM module doesn't handle paths that aren't relative to the checkout_root consistently.
- filesystem.chdir(filesystem.dirname(host_port_obj.layout_tests_dir()))
-
- oc = outputcapture.OutputCapture()
- oc.capture_output()
- res = rebaseline_chromium_webkit_tests.real_main(host, options, options,
- host_port_obj, host_port_obj, url_fetcher, zip_factory)
- oc.restore_output()
-
- # We expect to have written 38 files over the course of this rebaseline:
- # *) 6*3 files in /__im_tmp/ for the archived members of the 6 ports
- # *) 2*3 files in /test.checkout for actually differing baselines
- # *) 1 file in /test.checkout for the updated test_expectations file
- # *) 2*4 files in /tmp for the old/new baselines for the two actual ports
- # *) 2 files in /tmp for the text diffs for the two ports
- # *) 2 files in /tmp for the image diffs for the two ports
- # *) 1 file in /tmp for the rebaseline results html file
- # FIXME: These numbers depend on MockSCM.exists() returning True for all files.
- self.assertEqual(res, 0)
- self.assertEqual(len(filesystem.written_files), 38)
-
-
-class TestHtmlGenerator(unittest.TestCase):
- def make_generator(self, files, tests):
- options = MockOptions(configuration=None, html_directory='/tmp')
- host = MockHost()
- fs = host.filesystem
- for filename, contents in files.iteritems():
- fs.maybe_make_directory(fs.dirname(filename))
- fs.write_binary_file(filename, contents)
- host_port = host.port_factory.get('test', options)
- generator = rebaseline_chromium_webkit_tests.HtmlGenerator(host, host_port,
- target_port=None, options=options, platforms=['test-mac-leopard'], rebaselining_tests=tests)
- return generator, host_port
-
- def test_generate_baseline_links(self):
- files = {
- "/tmp/foo-expected-mac-old.txt": "",
- "/tmp/foo-expected-mac-new.txt": "",
- "/tmp/foo-expected-mac-diff.txt": "",
- }
- tests = ["foo.txt"]
- generator, host_port = self.make_generator(files, tests)
- 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)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py b/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py
index 4085e366a..37bc4b72e 100644
--- a/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py
+++ b/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem.py
@@ -160,6 +160,11 @@ class QtEWS(AbstractEarlyWarningSystem):
port_name = "qt"
+class QtWK2EWS(AbstractEarlyWarningSystem):
+ name = "qt-wk2-ews"
+ port_name = "qt"
+
+
class WinEWS(AbstractEarlyWarningSystem):
name = "win-ews"
port_name = "win"
diff --git a/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py b/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
index cb349412c..3adad4c58 100644
--- a/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py
@@ -83,6 +83,7 @@ class EarlyWarningSytemTest(QueuesTest):
self._test_builder_ews(MacEWS())
self._test_builder_ews(ChromiumWindowsEWS())
self._test_builder_ews(QtEWS())
+ self._test_builder_ews(QtWK2EWS())
self._test_builder_ews(GtkEWS())
self._test_builder_ews(EflEWS())
diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
index 515ff7dfa..f47494acd 100644
--- a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
+++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py
@@ -26,6 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import optparse
import os.path
import re
import shutil
@@ -56,7 +57,7 @@ def _baseline_name(fs, test_name, suffix):
class RebaselineTest(AbstractDeclarativeCommand):
name = "rebaseline-test"
help_text = "Rebaseline a single test from a buildbot. (Currently works only with build.chromium.org buildbots.)"
- argument_names = "BUILDER_NAME TEST_NAME"
+ argument_names = "BUILDER_NAME TEST_NAME [PLATFORM_TO_MOVE_EXISTING_BASELINES_TO]"
def _results_url(self, builder_name):
# FIXME: Generalize this command to work with non-build.chromium.org builders.
@@ -67,6 +68,23 @@ class RebaselineTest(AbstractDeclarativeCommand):
port = self._tool.port_factory.get_from_builder_name(builder_name)
return port.baseline_path()
+ def _copy_existing_baseline(self, platform_to_move_existing_baselines_to, test_name, suffix):
+ port = self._tool.port_factory.get(platform_to_move_existing_baselines_to)
+ old_baseline = port.expected_filename(test_name, "." + suffix)
+ if not self._tool.filesystem.exists(old_baseline):
+ print("No existing baseline for %s." % test_name)
+ return
+
+ new_baseline = self._tool.filesystem.join(port.baseline_path(), self._file_name_for_expected_result(test_name, suffix))
+ if self._tool.filesystem.exists(new_baseline):
+ print("Existing baseline at %s, not copying over it." % new_baseline)
+ else:
+ print("Copying baseline from %s to %s." % (old_baseline, new_baseline))
+ self._tool.filesystem.maybe_make_directory(self._tool.filesystem.dirname(new_baseline))
+ self._tool.filesystem.copyfile(old_baseline, new_baseline)
+ if not self._tool.scm().exists(new_baseline):
+ self._tool.scm().add(new_baseline)
+
def _save_baseline(self, data, target_baseline):
if not data:
return
@@ -85,19 +103,27 @@ class RebaselineTest(AbstractDeclarativeCommand):
def _file_name_for_expected_result(self, test_name, suffix):
return "%s-expected.%s" % (self._test_root(test_name), suffix)
- def _rebaseline_test(self, builder_name, test_name, suffix):
+ def _rebaseline_test(self, builder_name, test_name, platform_to_move_existing_baselines_to, suffix):
results_url = self._results_url(builder_name)
baseline_directory = self._baseline_directory(builder_name)
source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_result(test_name, suffix))
- target_baseline = os.path.join(baseline_directory, self._file_name_for_expected_result(test_name, suffix))
+ target_baseline = self._tool.filesystem.join(baseline_directory, self._file_name_for_expected_result(test_name, suffix))
+
+ if platform_to_move_existing_baselines_to:
+ self._copy_existing_baseline(platform_to_move_existing_baselines_to, test_name, suffix)
print "Retrieving %s." % source_baseline
self._save_baseline(self._tool.web.get_binary(source_baseline, convert_404_to_None=True), target_baseline)
def execute(self, options, args, tool):
for suffix in _baseline_suffix_list:
- self._rebaseline_test(args[0], args[1], suffix)
+ if len(args) > 2:
+ platform_to_move_existing_baselines_to = args[2]
+ else:
+ platform_to_move_existing_baselines_to = None
+
+ self._rebaseline_test(args[0], args[1], platform_to_move_existing_baselines_to, suffix)
class OptimizeBaselines(AbstractDeclarativeCommand):
@@ -150,6 +176,15 @@ class RebaselineExpectations(AbstractDeclarativeCommand):
name = "rebaseline-expectations"
help_text = "Rebaselines the tests indicated in test_expectations.txt."
+ def __init__(self):
+ options = [
+ optparse.make_option('--no-optimize', dest='optimize', action='store_false', default=True,
+ help=('Do not optimize/de-dup the expectations after rebaselining '
+ '(default is to de-dup automatically). '
+ 'You can use "webkit-patch optimize-baselines" to optimize separately.')),
+ ]
+ AbstractDeclarativeCommand.__init__(self, options=options)
+
def _run_webkit_patch(self, args):
try:
self._tool.executive.run_command([self._tool.path()] + args, cwd=self._tool.scm().checkout_root)
@@ -192,6 +227,8 @@ class RebaselineExpectations(AbstractDeclarativeCommand):
self._rebaseline_port(port_name)
for port_name in tool.port_factory.all_port_names():
self._update_expectations_file(port_name)
+ if not options.optimize:
+ return
for test_name in self._touched_test_names:
print "Optimizing baselines for %s." % test_name
self._run_webkit_patch(['optimize-baselines', test_name])
diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
index 52724308d..37e8a391b 100644
--- a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -31,7 +31,7 @@ import unittest
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.commands.rebaseline import *
-from webkitpy.tool.mocktool import MockTool
+from webkitpy.tool.mocktool import MockTool, MockOptions
from webkitpy.common.system.executive_mock import MockExecutive
@@ -46,7 +46,59 @@ class TestRebaseline(unittest.TestCase):
command = RebaselineTest()
command.bind_to_tool(MockTool())
expected_stdout = "Retrieving http://example.com/f/builders/Webkit Linux/results/layout-test-results/userscripts/another-test-actual.txt.\n"
- OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Linux", "userscripts/another-test.html", "txt"], expected_stdout=expected_stdout)
+ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Linux", "userscripts/another-test.html", None, "txt"], expected_stdout=expected_stdout)
+
+ def test_rebaseline_and_copy_test(self):
+ command = RebaselineTest()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7")
+ tool.filesystem.write_text_file(os.path.join(lion_port.layout_tests_dir(), "userscripts/another-test-expected.txt"), "Dummy expected result")
+
+ expected_stdout = """Copying baseline from /mock-checkout/LayoutTests/userscripts/another-test-expected.txt to /mock-checkout/LayoutTests/platform/chromium-mac-snowleopard/userscripts/another-test-expected.txt.
+Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.txt.
+"""
+ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Mac10.7", "userscripts/another-test.html", "chromium-mac-snowleopard", "txt"], expected_stdout=expected_stdout)
+
+ def test_rebaseline_and_copy_test_no_existing_result(self):
+ command = RebaselineTest()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ expected_stdout = """No existing baseline for userscripts/another-test.html.
+Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.txt.
+"""
+ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Mac10.7", "userscripts/another-test.html", "chromium-mac-snowleopard", "txt"], expected_stdout=expected_stdout)
+
+ def test_rebaseline_and_copy_test_with_lion_result(self):
+ command = RebaselineTest()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7")
+ tool.filesystem.write_text_file(os.path.join(lion_port.baseline_path(), "userscripts/another-test-expected.txt"), "Dummy expected result")
+
+ expected_stdout = """Copying baseline from /mock-checkout/LayoutTests/platform/chromium-mac/userscripts/another-test-expected.txt to /mock-checkout/LayoutTests/platform/chromium-mac-snowleopard/userscripts/another-test-expected.txt.
+Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.txt.
+"""
+ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Mac10.7", "userscripts/another-test.html", "chromium-mac-snowleopard", "txt"], expected_stdout=expected_stdout)
+
+ def test_rebaseline_and_copy_no_overwrite_test(self):
+ command = RebaselineTest()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ lion_port = tool.port_factory.get_from_builder_name("Webkit Mac10.7")
+ tool.filesystem.write_text_file(os.path.join(lion_port.baseline_path(), "userscripts/another-test-expected.txt"), "Dummy expected result")
+
+ snowleopard_port = tool.port_factory.get_from_builder_name("Webkit Mac10.6")
+ tool.filesystem.write_text_file(os.path.join(snowleopard_port.baseline_path(), "userscripts/another-test-expected.txt"), "Dummy expected result")
+
+ expected_stdout = """Existing baseline at /mock-checkout/LayoutTests/platform/chromium-mac-snowleopard/userscripts/another-test-expected.txt, not copying over it.
+Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-results/userscripts/another-test-actual.txt.
+"""
+ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Mac10.7", "userscripts/another-test.html", "chromium-mac-snowleopard", "txt"], expected_stdout=expected_stdout)
def test_rebaseline_expectations(self):
command = RebaselineExpectations()
@@ -60,10 +112,7 @@ class TestRebaseline(unittest.TestCase):
# Don't enable logging until after we create the mock expectation files as some Port.__init__'s run subcommands.
tool.executive = MockExecutive(should_log=True)
- expected_stdout = """Retrieving results for chromium-gpu-mac-snowleopard from Webkit Mac10.6 - GPU.
-Retrieving results for chromium-gpu-win-win7 from Webkit Win7 - GPU.
-Retrieving results for chromium-gpu-win-xp from Webkit Win - GPU.
-Retrieving results for chromium-linux-x86 from Webkit Linux 32.
+ expected_stdout = """Retrieving results for chromium-linux-x86 from Webkit Linux 32.
userscripts/another-test.html
userscripts/images.svg
Retrieving results for chromium-linux-x86_64 from Webkit Linux.
@@ -72,6 +121,9 @@ Retrieving results for chromium-linux-x86_64 from Webkit Linux.
Retrieving results for chromium-mac-leopard from Webkit Mac10.5.
userscripts/another-test.html
userscripts/images.svg
+Retrieving results for chromium-mac-lion from Webkit Mac10.7.
+ userscripts/another-test.html
+ userscripts/images.svg
Retrieving results for chromium-mac-snowleopard from Webkit Mac10.6.
userscripts/another-test.html
userscripts/images.svg
@@ -84,15 +136,16 @@ Retrieving results for chromium-win-win7 from Webkit Win7.
Retrieving results for chromium-win-xp from Webkit Win.
userscripts/another-test.html
userscripts/images.svg
-Optimizing baselines for userscripts/another-test.html.
-Optimizing baselines for userscripts/images.svg.
"""
+
expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux 32', 'userscripts/another-test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux 32', 'userscripts/images.svg'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux', 'userscripts/another-test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Linux', 'userscripts/images.svg'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.5', 'userscripts/another-test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.5', 'userscripts/images.svg'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.7', 'userscripts/another-test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.7', 'userscripts/images.svg'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.6', 'userscripts/another-test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Mac10.6', 'userscripts/images.svg'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Vista', 'userscripts/another-test.html'], cwd=/mock-checkout
@@ -101,8 +154,17 @@ MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win7', 'userscripts/anothe
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win7', 'userscripts/images.svg'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win', 'userscripts/another-test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'rebaseline-test', 'Webkit Win', 'userscripts/images.svg'], cwd=/mock-checkout
-MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/another-test.html'], cwd=/mock-checkout
-MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/images.svg'], cwd=/mock-checkout
"""
+
+ command._tests_to_rebaseline = lambda port: ['userscripts/another-test.html', 'userscripts/images.svg']
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=False), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
+
+ expected_stdout_with_optimize = expected_stdout + (
+ "Optimizing baselines for userscripts/another-test.html.\n"
+ "Optimizing baselines for userscripts/images.svg.\n")
+ expected_stderr_with_optimize = expected_stderr + (
+ "MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/another-test.html'], cwd=/mock-checkout\n"
+ "MOCK run_command: ['echo', 'optimize-baselines', 'userscripts/images.svg'], cwd=/mock-checkout\n")
+
command._tests_to_rebaseline = lambda port: [] if not port.name().find('-gpu-') == -1 else ['userscripts/another-test.html', 'userscripts/images.svg']
- OutputCapture().assert_outputs(self, command.execute, [None, [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True), [], tool], expected_stdout=expected_stdout_with_optimize, expected_stderr=expected_stderr_with_optimize)
diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py
index b090af912..17e543780 100644
--- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py
+++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py
@@ -137,12 +137,15 @@ class GardeningHTTPRequestHandler(ReflectionHandler):
def rebaseline(self):
builder = self.query['builder'][0]
- test = self.query['test'][0]
- self._run_webkit_patch([
+ command = [
'rebaseline-test',
builder,
- test,
- ])
+ self.query['test'][0],
+ ]
+ fallback_port = builders.fallback_port_name_for_new_port(builder)
+ if fallback_port:
+ command.append(fallback_port)
+ self._run_webkit_patch(command)
self._serve_text('success')
def optimizebaselines(self):
diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
index 9d99835f1..f41a38a78 100644
--- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py
@@ -31,6 +31,7 @@ import unittest
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.layout_tests.models.test_configuration import *
+from webkitpy.layout_tests.port import builders
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.mocktool import MockTool
from webkitpy.common.system.executive_mock import MockExecutive
@@ -182,10 +183,17 @@ class GardeningServerTest(unittest.TestCase):
self._post_to_path("/rollout?revision=2314&reason=MOCK+rollout+reason", expected_stderr=expected_stderr, expected_stdout=expected_stdout)
def test_rebaseline(self):
+ builders._exact_matches = {"MOCK builder": {"port_name": "mock-port-name", "specifiers": set(["mock-specifier"])}}
expected_stderr = "MOCK run_command: ['echo', 'rebaseline-test', 'MOCK builder', 'user-scripts/another-test.html'], cwd=/mock-checkout\n"
expected_stdout = "== Begin Response ==\nsuccess\n== End Response ==\n"
self._post_to_path("/rebaseline?builder=MOCK+builder&test=user-scripts/another-test.html", expected_stderr=expected_stderr, expected_stdout=expected_stdout)
+ def test_rebaseline_new_port(self):
+ builders._exact_matches = {"MOCK builder": {"port_name": "mock-port-name", "specifiers": set(["mock-specifier"]), "move_overwritten_baselines_to": "mock-port-fallback"}}
+ expected_stderr = "MOCK run_command: ['echo', 'rebaseline-test', 'MOCK builder', 'user-scripts/another-test.html', 'mock-port-fallback'], cwd=/mock-checkout\n"
+ expected_stdout = "== Begin Response ==\nsuccess\n== End Response ==\n"
+ self._post_to_path("/rebaseline?builder=MOCK+builder&test=user-scripts/another-test.html", expected_stderr=expected_stderr, expected_stdout=expected_stdout)
+
def test_optimizebaselines(self):
expected_stderr = "MOCK run_command: ['echo', 'optimize-baselines', 'user-scripts/another-test.html'], cwd=/mock-checkout\n"
expected_stdout = "== Begin Response ==\nsuccess\n== End Response ==\n"
diff --git a/Tools/Scripts/webkitpy/tool/steps/options.py b/Tools/Scripts/webkitpy/tool/steps/options.py
index 1141df7e4..c29e59d9c 100644
--- a/Tools/Scripts/webkitpy/tool/steps/options.py
+++ b/Tools/Scripts/webkitpy/tool/steps/options.py
@@ -1,9 +1,9 @@
# 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
@@ -44,7 +44,7 @@ class Options(object):
description = make_option("-m", "--description", action="store", type="string", dest="description", help="Description string for the attachment")
email = make_option("--email", action="store", type="string", dest="email", help="Email address to use in ChangeLogs.")
force_clean = make_option("--force-clean", action="store_true", dest="force_clean", default=False, help="Clean working directory before applying patches (removes local changes and commits)")
- git_commit = make_option("-g", "--git-commit", action="store", dest="git_commit", help="Operate on a local commit. If a range, the commits are squashed into one. HEAD.. operates on working copy changes only.")
+ git_commit = make_option("-g", "--git-commit", action="store", dest="git_commit", help="Operate on a local commit. If a range, the commits are squashed into one. <ref>.... includes the working copy changes. UPSTREAM can be used for the upstream/tracking branch.")
local_commit = make_option("--local-commit", action="store_true", dest="local_commit", default=False, help="Make a local commit for each applied patch")
non_interactive = make_option("--non-interactive", action="store_true", dest="non_interactive", default=False, help="Never prompt the user, fail as fast as possible.")
obsolete_patches = make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting this one.")