Title: [92624] trunk/Tools
Revision
92624
Author
[email protected]
Date
2011-08-08 12:59:31 -0700 (Mon, 08 Aug 2011)

Log Message

Wire up updating expectations in garden-o-matic.
https://bugs.webkit.org/show_bug.cgi?id=65794

Reviewed by Adam Barth.

* Scripts/webkitpy/layout_tests/port/factory.py: Moved _port_for_builder from rebaseline.py to here, rename to get_from_builder_name.
* Scripts/webkitpy/tool/commands/rebaseline.py: Adapted callsites to new location.
* Scripts/webkitpy/tool/servers/gardeningserver.py: Added GardeningExpectationsUpdater, which knows how to update expectations.
* Scripts/webkitpy/tool/servers/gardeningserver_unittest.py: Added loads of tests.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (92623 => 92624)


--- trunk/Tools/ChangeLog	2011-08-08 19:54:46 UTC (rev 92623)
+++ trunk/Tools/ChangeLog	2011-08-08 19:59:31 UTC (rev 92624)
@@ -1,3 +1,15 @@
+2011-08-05  Dimitri Glazkov  <[email protected]>
+
+        Wire up updating expectations in garden-o-matic.
+        https://bugs.webkit.org/show_bug.cgi?id=65794
+
+        Reviewed by Adam Barth.
+
+        * Scripts/webkitpy/layout_tests/port/factory.py: Moved _port_for_builder from rebaseline.py to here, rename to get_from_builder_name.
+        * Scripts/webkitpy/tool/commands/rebaseline.py: Adapted callsites to new location.
+        * Scripts/webkitpy/tool/servers/gardeningserver.py: Added GardeningExpectationsUpdater, which knows how to update expectations.
+        * Scripts/webkitpy/tool/servers/gardeningserver_unittest.py: Added loads of tests.
+
 2011-08-08  Jochen Eisinger  <[email protected]>
 
         webkit-patch doesn't get along with renamed files

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py (92623 => 92624)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py	2011-08-08 19:54:46 UTC (rev 92623)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py	2011-08-08 19:59:31 UTC (rev 92624)
@@ -29,12 +29,19 @@
 
 """Factory method to retrieve the appropriate port implementation."""
 
-
+import re
 import sys
 
 from webkitpy.layout_tests.port import builders
 
 
+class BuilderOptions(object):
+
+    def __init__(self, builder_name):
+        self.configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release"
+        self.builder_name = builder_name
+
+
 def all_port_names():
     """Return a list of all valid, fully-specified, "real" port names.
 
@@ -57,6 +64,14 @@
     return _get_kwargs(**kwargs)
 
 
+def get_from_builder_name(builder_name):
+    port_name = builders.port_name_for_builder_name(builder_name)
+    assert(port_name)  # Need to update port_name_for_builder_name
+    port = get(port_name, BuilderOptions(builder_name))
+    assert(port)  # Need to update port_name_for_builder_name
+    return port
+
+
 def _get_kwargs(**kwargs):
     port_to_use = kwargs.get('port_name', None)
     options = kwargs.get('options', None)

Modified: trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py (92623 => 92624)


--- trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py	2011-08-08 19:54:46 UTC (rev 92623)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py	2011-08-08 19:59:31 UTC (rev 92624)
@@ -49,28 +49,11 @@
 _baseline_suffix_list = ['png', 'txt']
 
 
-def _port_for_builder(builder_name):
-    port_name = builders.port_name_for_builder_name(builder_name)
-    assert(port_name)  # Need to update port_name_for_builder_name
-    port = factory.get(port_name, RebaseliningOptions(builder_name))
-    assert(port)  # Need to update port_name_for_builder_name
-    return port
-
-
 # FIXME: Should TestResultWriter know how to compute this string?
 def _baseline_name(fs, test_name, suffix):
     return fs.splitext(test_name)[0] + TestResultWriter.FILENAME_SUFFIX_EXPECTED + "." + suffix
 
 
-class RebaseliningOptions(object):
-
-    DEBUG_CONFIGURATION_REGEX = r"[d|D](ebu|b)g"
-
-    def __init__(self, builder_name):
-        self.configuration = "Debug" if re.search(self.DEBUG_CONFIGURATION_REGEX, builder_name) else "Release"
-        self.builder_name = builder_name
-
-
 class RebaselineTest(AbstractDeclarativeCommand):
     name = "rebaseline-test"
     help_text = "Rebaseline a single test from a buildbot.  (Currently works only with build.chromium.org buildbots.)"
@@ -83,7 +66,7 @@
         return builder.accumulated_results_url()
 
     def _baseline_directory(self, builder_name):
-        port = _port_for_builder(builder_name)
+        port = factory.get_from_builder_name(builder_name)
         return port.baseline_path()
 
     def _save_baseline(self, data, target_baseline):

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py (92623 => 92624)


--- trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py	2011-08-08 19:54:46 UTC (rev 92623)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py	2011-08-08 19:59:31 UTC (rev 92624)
@@ -25,9 +25,45 @@
 import BaseHTTPServer
 import os
 
+from webkitpy.common.memoized import memoized
 from webkitpy.tool.servers.reflectionhandler import ReflectionHandler
+from webkitpy.layout_tests.models.test_expectations import BugManager, TestExpectationParser, TestExpectations, TestExpectationsEditor, TestExpectationSerializer
+from webkitpy.layout_tests.models.test_configuration import TestConfigurationConverter
+from webkitpy.layout_tests.port import factory
 
 
+class GardeningExpectationsUpdater(BugManager):
+    def __init__(self, tool, port):
+        self._converter = TestConfigurationConverter(port.all_test_configurations(), port.configuration_specifier_macros())
+        self._parser = TestExpectationParser(port, [], allow_rebaseline_modifier=False)
+        self._path_to_test_expectations_file = port.path_to_test_expectations_file()
+        self._tool = tool
+
+    @memoized
+    def _builder_to_test_config(self, builder_name):
+        return factory.get_from_builder_name(builder_name).test_configuration()
+
+    def close_bug(self, bug_id, reference_bug_id=None):
+        # FIXME: Implement this properly.
+        pass
+
+    def create_bug(self):
+        return "BUG_NEW"
+
+    def update_expectations(self, failure_info_list):
+        expectation_lines = TestExpectationParser.tokenize_list(self._tool.filesystem.read_text_file(self._path_to_test_expectations_file))
+        for expectation_line in expectation_lines:
+            self._parser.parse(expectation_line)
+        editor = TestExpectationsEditor(expectation_lines, self)
+        for failure_info in failure_info_list:
+            expectation_set = set(filter(None, map(TestExpectations.expectation_from_string, failure_info['failureTypeList'])))
+            assert(expectation_set)
+            test_name = failure_info['testName']
+            assert(test_name)
+            editor.update_expectation(test_name, set([self._builder_to_test_config(failure_info['builderName'])]), expectation_set)
+        self._tool.filesystem.write_text_file(self._path_to_test_expectations_file, TestExpectationSerializer.list_to_string(expectation_lines, self._converter))
+
+
 class GardeningHTTPServer(BaseHTTPServer.HTTPServer):
     def __init__(self, httpd_port, config):
         server_name = ''
@@ -69,6 +105,13 @@
     def _run_webkit_patch(self, args):
         return self.server.tool.executive.run_command([self.server.tool.path()] + args, cwd=self.server.tool.scm().checkout_root)
 
+    @memoized
+    def _expectations_updater(self):
+        # FIXME: Should split failure_info_list into lists per port, then edit each expectations file separately.
+        # For now, assume Chromium port.
+        port = factory.get("chromium-win-win7")
+        return GardeningExpectationsUpdater(self.server.tool, port)
+
     def rollout(self):
         revision = self.query['revision'][0]
         reason = self.query['reason'][0]
@@ -82,8 +125,7 @@
         self._serve_text('success')
 
     def updateexpectations(self):
-        failure_info_list = self._read_entity_body_as_json()
-        print 'FailureInfoList:', failure_info_list
+        self._expectations_updater().update_expectations(self._read_entity_body_as_json())
         self._serve_text('success')
 
     def rebaseline(self):

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py (92623 => 92624)


--- trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py	2011-08-08 19:54:46 UTC (rev 92623)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py	2011-08-08 19:59:31 UTC (rev 92624)
@@ -35,15 +35,27 @@
 import unittest
 
 from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.layout_tests.port import factory
 from webkitpy.thirdparty.mock import Mock
 from webkitpy.tool.mocktool import MockTool, MockExecutive
 from webkitpy.tool.servers.gardeningserver import *
 
 
+class TestPortFactory(object):
+    @classmethod
+    def create(cls):
+        return factory.get("test-win-xp")
+
+    @classmethod
+    def path_to_test_expectations_file(cls):
+        return cls.create().path_to_test_expectations_file()
+
+
 class MockServer(object):
     def __init__(self):
         self.tool = MockTool()
         self.tool.executive = MockExecutive(should_log=True)
+        self.tool.filesystem.files[TestPortFactory.path_to_test_expectations_file()] = ""
 
 
 # The real GardeningHTTPRequestHandler has a constructor that's too hard to
@@ -53,6 +65,9 @@
         self.server = server
         self.body = None
 
+    def _expectations_updater(self):
+        return GardeningExpectationsUpdater(self.server.tool, TestPortFactory.create())
+
     def _read_entity_body(self):
         return self.body if self.body else ''
 
@@ -67,6 +82,66 @@
         print "== End JSON Response =="
 
 
+class GardeningExpectationsUpdaterTest(unittest.TestCase):
+    def __init__(self, testFunc):
+        self.tool = MockTool()
+        self.tool.executive = MockExecutive(should_log=True)
+        self.tool.filesystem.files[TestPortFactory.path_to_test_expectations_file()] = ""
+        unittest.TestCase.__init__(self, testFunc)
+
+    def assert_update(self, failure_info_list, expectations_before=None, expectations_after=None, expected_exception=None):
+        updater = GardeningExpectationsUpdater(self.tool, TestPortFactory.create())
+        path_to_test_expectations_file = TestPortFactory.path_to_test_expectations_file()
+        self.tool.filesystem.files[path_to_test_expectations_file] = expectations_before or ""
+        if expected_exception:
+            self.assertRaises(expected_exception, updater.update_expectations, (failure_info_list))
+        else:
+            updater.update_expectations(failure_info_list)
+            self.assertEquals(self.tool.filesystem.files[path_to_test_expectations_file], expectations_after)
+
+    def test_empty_expectations(self):
+        failure_info_list = []
+        expectations_before = ""
+        expectations_after = ""
+        self.assert_update(failure_info_list, expectations_before=expectations_before, expectations_after=expectations_after)
+
+    def test_unknown_builder(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Bob", "failureTypeList": ["IMAGE"]}]
+        self.assert_update(failure_info_list, expected_exception=AssertionError)
+
+    def test_empty_failure_type_list(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Webkit Win", "failureTypeList": []}]
+        self.assert_update(failure_info_list, expected_exception=AssertionError)
+
+    def test_empty_test_name(self):
+        failure_info_list = [{"testName": "", "builderName": "Webkit Win", "failureTypeList": ["TEXT"]}]
+        self.assert_update(failure_info_list, expected_exception=AssertionError)
+
+    def test_unknown_failure_type(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Webkit Win", "failureTypeList": ["IMAGE", "EXPLODE"]}]
+        expectations_before = ""
+        expectations_after = "\nBUG_NEW XP RELEASE CPU : failures/expected/image.html = IMAGE"
+        self.assert_update(failure_info_list, expectations_before=expectations_before, expectations_after=expectations_after)
+
+    def test_add_new_expectation(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Webkit Win", "failureTypeList": ["IMAGE"]}]
+        expectations_before = ""
+        expectations_after = "\nBUG_NEW XP RELEASE CPU : failures/expected/image.html = IMAGE"
+        self.assert_update(failure_info_list, expectations_before=expectations_before, expectations_after=expectations_after)
+
+    def test_replace_old_expectation(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Webkit Win", "failureTypeList": ["IMAGE"]}]
+        expectations_before = "BUG_OLD XP RELEASE CPU : failures/expected/image.html = TEXT"
+        expectations_after = "BUG_NEW XP RELEASE CPU : failures/expected/image.html = IMAGE"
+        self.assert_update(failure_info_list, expectations_before=expectations_before, expectations_after=expectations_after)
+
+    def test_supplement_old_expectation(self):
+        failure_info_list = [{"testName": "failures/expected/image.html", "builderName": "Webkit Win", "failureTypeList": ["IMAGE"]}]
+        expectations_before = "BUG_OLD XP RELEASE :  failures/expected/image.html = TEXT"
+        expectations_after = "BUG_OLD XP RELEASE GPU : failures/expected/image.html = TEXT\nBUG_NEW XP RELEASE CPU : failures/expected/image.html = IMAGE"
+        self.assert_update(failure_info_list, expectations_before=expectations_before, expectations_after=expectations_after)
+
+
 class GardeningServerTest(unittest.TestCase):
     def _post_to_path(self, path, body=None, expected_stderr=None, expected_stdout=None):
         handler = TestGardeningHTTPRequestHandler(MockServer())
@@ -91,5 +166,5 @@
 
     def test_updateexpectations(self):
         expected_stderr = ""
-        expected_stdout = "FailureInfoList: []\n== Begin Response ==\nsuccess\n== End Response ==\n"
+        expected_stdout = "== Begin Response ==\nsuccess\n== End Response ==\n"
         self._post_to_path("/updateexpectations", body="[]", expected_stderr=expected_stderr, expected_stdout=expected_stdout)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to