Introduce SpecifierSorter, a thing that knows how specifiers should be ordered.
authordglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2011 19:55:45 +0000 (19:55 +0000)
committerdglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2011 19:55:45 +0000 (19:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65413

Reviewed by Adam Barth.

* Scripts/webkitpy/layout_tests/models/test_configuration.py: Added SpecifierSorter and converted
    existing code to use it.
* Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py: Added unit tests and cleaned up a bit.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@92136 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py
Tools/Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py

index ef86173..91678cb 100644 (file)
@@ -1,3 +1,14 @@
+2011-08-01  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Introduce SpecifierSorter, a thing that knows how specifiers should be ordered.
+        https://bugs.webkit.org/show_bug.cgi?id=65413
+
+        Reviewed by Adam Barth.
+
+        * Scripts/webkitpy/layout_tests/models/test_configuration.py: Added SpecifierSorter and converted
+            existing code to use it.
+        * Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py: Added unit tests and cleaned up a bit.
+
 2011-08-01  Adam Barth  <abarth@webkit.org>
 
         Refactor bugzilla.js for use by garden-o-matic
index 4793bcf..b074f0d 100644 (file)
@@ -64,12 +64,53 @@ class TestConfiguration(object):
         return self.__dict__.values()
 
 
+class SpecifierSorter:
+    def __init__(self, all_test_configurations=None, macros=None):
+        self._specifier_to_category = {}
+
+        if not all_test_configurations:
+            return
+        for test_configuration in all_test_configurations:
+            for category, specifier in test_configuration.items():
+                self.add_specifier(category, specifier)
+
+        if not macros:
+            return
+        # Assume well-formed macros.
+        for macro, specifier_list in macros.items():
+            self.add_specifier(self.category_for_specifier(specifier_list[0]), macro)
+
+    def add_specifier(self, category, specifier):
+        self._specifier_to_category[specifier] = category
+
+    @classmethod
+    def category_priority(cls, category):
+        return TestConfiguration.category_order().index(category)
+
+    def specifier_priority(self, specifier):
+        return self.category_priority(self._specifier_to_category[specifier])
+
+    def category_for_specifier(self, specifier):
+        return self._specifier_to_category.get(specifier)
+
+    def sort_specifiers(self, specifiers):
+        category_slots = map(lambda x: [], TestConfiguration.category_order())
+        for specifier in specifiers:
+            category_slots[self.specifier_priority(specifier)].append(specifier)
+
+        def sort_and_return(result, specifier_list):
+            specifier_list.sort()
+            return result + specifier_list
+
+        return reduce(sort_and_return, category_slots, [])
+
+
 class TestConfigurationConverter:
     def __init__(self, all_test_configurations, configuration_macros=None):
         self._all_test_configurations = all_test_configurations
         self._configuration_macros = configuration_macros or {}
         self._specifier_to_configuration_set = {}
-        self._specifier_to_category = {}
+        self._specifier_sorter = SpecifierSorter()
         self._collapsing_sets_by_size = {}
         self._junk_specifier_combinations = {}
         collapsing_sets_by_category = {}
@@ -77,7 +118,7 @@ class TestConfigurationConverter:
         for configuration in all_test_configurations:
             for category, specifier in configuration.items():
                 self._specifier_to_configuration_set.setdefault(specifier, set()).add(configuration)
-                self._specifier_to_category[specifier] = category
+                self._specifier_sorter.add_specifier(category, specifier)
                 collapsing_sets_by_category.setdefault(category, set()).add(specifier)
                 # FIXME: This seems extra-awful.
                 for cat2, spec2 in configuration.items():
@@ -87,15 +128,9 @@ class TestConfigurationConverter:
         for collapsing_set in collapsing_sets_by_category.values():
             self._collapsing_sets_by_size.setdefault(len(collapsing_set), set()).add(frozenset(collapsing_set))
 
-        def category_priority(category):
-            return TestConfiguration.category_order().index(category)
-
-        def specifier_priority(specifier):
-            return category_priority(self._specifier_to_category[specifier])
-
         for specifier, sets_by_category in matching_sets_by_category.items():
             for category, set_by_category in sets_by_category.items():
-                if len(set_by_category) == 1 and category_priority(category) > specifier_priority(specifier):
+                if len(set_by_category) == 1 and self._specifier_sorter.category_priority(category) > self._specifier_sorter.specifier_priority(specifier):
                     self._junk_specifier_combinations[specifier] = set_by_category
 
     def _expand_macros(self, specifier):
@@ -116,7 +151,7 @@ class TestConfigurationConverter:
                     if error_list is not None:
                         error_list.append("Unrecognized modifier '" + expanded_specifier + "'")
                     return set()
-                category = self._specifier_to_category[expanded_specifier]
+                category = self._specifier_sorter.category_for_specifier(expanded_specifier)
                 matching_sets.setdefault(category, set()).update(configurations)
 
         return reduce(set.intersection, matching_sets.values())
index 365a585..010de82 100644 (file)
@@ -32,6 +32,21 @@ from webkitpy.layout_tests import port
 from webkitpy.layout_tests.models.test_configuration import *
 
 
+def make_mock_all_test_configurations_set():
+    all_test_configurations = set()
+    for version, architecture in (('snowleopard', 'x86'), ('xp', 'x86'), ('win7', 'x86'), ('lucid', 'x86'), ('lucid', 'x86_64')):
+        for build_type in ('debug', 'release'):
+            for graphics_type in ('cpu', 'gpu'):
+                all_test_configurations.add(TestConfiguration(None, version, architecture, build_type, graphics_type))
+    return all_test_configurations
+
+MOCK_MACROS = {
+    'mac': ['snowleopard'],
+    'win': ['xp', 'win7'],
+    'linux': ['lucid'],
+}
+
+
 class TestConfigurationTest(unittest.TestCase):
     def test_items(self):
         config = TestConfiguration(None, 'xp', 'x86', 'release', 'cpu')
@@ -91,18 +106,54 @@ class TestConfigurationTest(unittest.TestCase):
         self.assertEquals('<xp, x86, release, cpu>', str(config))
 
 
+class SpecifierSorterTest(unittest.TestCase):
+    def __init__(self, testFunc):
+        self._all_test_configurations = make_mock_all_test_configurations_set()
+        unittest.TestCase.__init__(self, testFunc)
+
+    def test_init(self):
+        sorter = SpecifierSorter()
+        self.assertEquals(sorter.category_for_specifier('control'), None)
+        sorter = SpecifierSorter(self._all_test_configurations)
+        self.assertEquals(sorter.category_for_specifier('xp'), 'version')
+        sorter = SpecifierSorter(self._all_test_configurations, MOCK_MACROS)
+        self.assertEquals(sorter.category_for_specifier('mac'), 'version')
+
+    def test_add_specifier(self):
+        sorter = SpecifierSorter()
+        self.assertEquals(sorter.category_for_specifier('control'), None)
+        sorter.add_specifier('version', 'control')
+        self.assertEquals(sorter.category_for_specifier('control'), 'version')
+        sorter.add_specifier('version', 'one')
+        self.assertEquals(sorter.category_for_specifier('one'), 'version')
+        sorter.add_specifier('architecture', 'renaissance')
+        self.assertEquals(sorter.category_for_specifier('one'), 'version')
+        self.assertEquals(sorter.category_for_specifier('renaissance'), 'architecture')
+
+    def test_category_priority(self):
+        sorter = SpecifierSorter(self._all_test_configurations)
+        self.assertEquals(sorter.category_priority('version'), 0)
+        self.assertEquals(sorter.category_priority('build_type'), 2)
+
+    def test_specifier_priority(self):
+        sorter = SpecifierSorter(self._all_test_configurations)
+        self.assertEquals(sorter.specifier_priority('x86'), 1)
+        self.assertEquals(sorter.specifier_priority('gpu'), 3)
+        self.assertEquals(sorter.specifier_priority('snowleopard'), 0)
+
+    def test_sort_specifiers(self):
+        sorter = SpecifierSorter(self._all_test_configurations, MOCK_MACROS)
+        self.assertEquals(sorter.sort_specifiers(set()), [])
+        self.assertEquals(sorter.sort_specifiers(set(['x86'])), ['x86'])
+        self.assertEquals(sorter.sort_specifiers(set(['x86', 'win7'])), ['win7', 'x86'])
+        self.assertEquals(sorter.sort_specifiers(set(['gpu', 'x86', 'debug', 'win7'])), ['win7', 'x86', 'debug', 'gpu'])
+        self.assertEquals(sorter.sort_specifiers(set(['gpu', 'snowleopard', 'x86', 'debug', 'win7'])), ['snowleopard', 'win7', 'x86', 'debug', 'gpu'])
+        self.assertEquals(sorter.sort_specifiers(set(['gpu', 'x86', 'mac', 'debug', 'win7'])), ['mac', 'win7', 'x86', 'debug', 'gpu'])
+
+
 class TestConfigurationConverterTest(unittest.TestCase):
     def __init__(self, testFunc):
-        self._all_test_configurations = set()
-        for version, architecture in (('snowleopard', 'x86'), ('xp', 'x86'), ('win7', 'x86'), ('lucid', 'x86'), ('lucid', 'x86_64')):
-            for build_type in ('debug', 'release'):
-                for graphics_type in ('cpu', 'gpu'):
-                    self._all_test_configurations.add(TestConfiguration(None, version, architecture, build_type, graphics_type))
-        self._macros = {
-            'mac': ['snowleopard'],
-            'win': ['xp', 'win7'],
-            'linux': ['lucid'],
-        }
+        self._all_test_configurations = make_mock_all_test_configurations_set()
         unittest.TestCase.__init__(self, testFunc)
 
     def test_to_config_set(self):
@@ -179,7 +230,7 @@ class TestConfigurationConverterTest(unittest.TestCase):
         self.assertEquals(converter.to_config_set(set(['lucid', 'snowleopard', 'release', 'cpu'])), configs_to_match)
 
     def test_macro_expansion(self):
-        converter = TestConfigurationConverter(self._all_test_configurations, self._macros)
+        converter = TestConfigurationConverter(self._all_test_configurations, MOCK_MACROS)
 
         configs_to_match = set([
             TestConfiguration(None, 'xp', 'x86', 'release', 'gpu'),
@@ -283,7 +334,7 @@ class TestConfigurationConverterTest(unittest.TestCase):
         self.assertEquals(specifiers_list, [set(['bob', 'foo', 'godzilla']), set(['foo']), set(['people'])])
 
     def test_converter_macro_collapsing(self):
-        converter = TestConfigurationConverter(self._all_test_configurations, self._macros)
+        converter = TestConfigurationConverter(self._all_test_configurations, MOCK_MACROS)
 
         configs_to_match = set([
             TestConfiguration(None, 'xp', 'x86', 'release', 'gpu'),