Title: [100875] trunk/Tools
Revision
100875
Author
[email protected]
Date
2011-11-20 17:26:57 -0800 (Sun, 20 Nov 2011)

Log Message

Change the final place where we use version 3 of the results json output
https://bugs.webkit.org/show_bug.cgi?id=72838

Reviewed by Adam Barth.

This converts the json from being a flat map of test name --> results
to being hierarchical by directory. This will make the json files
considerably smaller.

Also cleaned up some functions that were returning/checking boolean values
that were always True.

* TestResultServer/model/jsonresults.py:
* TestResultServer/model/jsonresults_unittest.py:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (100874 => 100875)


--- trunk/Tools/ChangeLog	2011-11-20 23:55:31 UTC (rev 100874)
+++ trunk/Tools/ChangeLog	2011-11-21 01:26:57 UTC (rev 100875)
@@ -1,5 +1,22 @@
 2011-11-20  Ojan Vafai  <[email protected]>
 
+        Change the final place where we use version 3 of the results json output
+        https://bugs.webkit.org/show_bug.cgi?id=72838
+
+        Reviewed by Adam Barth.
+
+        This converts the json from being a flat map of test name --> results
+        to being hierarchical by directory. This will make the json files 
+        considerably smaller.
+
+        Also cleaned up some functions that were returning/checking boolean values
+        that were always True.
+
+        * TestResultServer/model/jsonresults.py:
+        * TestResultServer/model/jsonresults_unittest.py:
+
+2011-11-20  Ojan Vafai  <[email protected]>
+
         Include the master name when querying the test results server.
         This will soon be required since leaving the master name out mean
         that multiple files could match the query.

Modified: trunk/Tools/TestResultServer/model/jsonresults.py (100874 => 100875)


--- trunk/Tools/TestResultServer/model/jsonresults.py	2011-11-20 23:55:31 UTC (rev 100874)
+++ trunk/Tools/TestResultServer/model/jsonresults.py	2011-11-21 01:26:57 UTC (rev 100875)
@@ -44,12 +44,41 @@
 JSON_RESULTS_PASS = "P"
 JSON_RESULTS_NO_DATA = "N"
 JSON_RESULTS_MIN_TIME = 1
-JSON_RESULTS_VERSION = 3
 JSON_RESULTS_HIERARCHICAL_VERSION = 4
 JSON_RESULTS_MAX_BUILDS = 750
 JSON_RESULTS_MAX_BUILDS_SMALL = 200
 
 
+def _add_path_to_trie(path, value, trie):
+    if not "/" in path:
+        trie[path] = value
+        return
+
+    directory, slash, rest = path.partition("/")
+    if not directory in trie:
+        trie[directory] = {}
+    _add_path_to_trie(rest, value, trie[directory])
+
+
+def _trie_json_tests(tests):
+    """Breaks a test name into chunks by directory and puts the test time as a value in the lowest part, e.g.
+    foo/bar/baz.html: VALUE1
+    foo/bar/baz1.html: VALUE2
+
+    becomes
+    foo: {
+        bar: {
+            baz.html: VALUE1,
+            baz1.html: VALUE2
+        }
+    }
+    """
+    trie = {}
+    for test, value in tests.iteritems():
+        _add_path_to_trie(test, value, trie)
+    return trie
+
+
 class JsonResults(object):
     @classmethod
     def _strip_prefix_suffix(cls, data):
@@ -78,16 +107,12 @@
 
     @classmethod
     def _merge_json(cls, aggregated_json, incremental_json, num_runs):
-        if not cls._merge_non_test_data(aggregated_json, incremental_json, num_runs):
-            return False
-
+        cls._merge_non_test_data(aggregated_json, incremental_json, num_runs)
         incremental_tests = incremental_json[JSON_RESULTS_TESTS]
         if incremental_tests:
             aggregated_tests = aggregated_json[JSON_RESULTS_TESTS]
             cls._merge_tests(aggregated_tests, incremental_tests, num_runs)
 
-        return True
-
     @classmethod
     def _merge_non_test_data(cls, aggregated_json, incremental_json, num_runs):
         incremental_builds = incremental_json[JSON_RESULTS_BUILD_NUMBERS]
@@ -101,8 +126,6 @@
             # Merge this build into aggreagated results.
             cls._merge_one_build(aggregated_json, incremental_json, index, num_runs)
 
-        return True
-
     @classmethod
     def _merge_one_build(cls, aggregated_json, incremental_json, incremental_index, num_runs):
         for key in incremental_json.keys():
@@ -119,24 +142,33 @@
 
     @classmethod
     def _merge_tests(cls, aggregated_json, incremental_json, num_runs):
-        all_tests = set(aggregated_json.iterkeys()) | set(incremental_json.iterkeys())
+        all_tests = set(aggregated_json.iterkeys())
+        if incremental_json:
+            all_tests |= set(incremental_json.iterkeys())
+
         for test_name in all_tests:
-            if test_name in aggregated_json:
-                aggregated_test = aggregated_json[test_name]
-                if test_name in incremental_json:
-                    incremental_test = incremental_json[test_name]
-                    results = incremental_test[JSON_RESULTS_RESULTS]
-                    times = incremental_test[JSON_RESULTS_TIMES]
-                else:
-                    results = [[1, JSON_RESULTS_NO_DATA]]
-                    times = [[1, 0]]
+            if test_name not in aggregated_json:
+                aggregated_json[test_name] = incremental_json[test_name]
+                continue
 
-                cls._insert_item_run_length_encoded(results, aggregated_test[JSON_RESULTS_RESULTS], num_runs)
-                cls._insert_item_run_length_encoded(times, aggregated_test[JSON_RESULTS_TIMES], num_runs)
-                cls._normalize_results_json(test_name, aggregated_json, num_runs)
+            if JSON_RESULTS_RESULTS not in aggregated_json[test_name]:
+                incremental_sub_result = incremental_json[test_name] if test_name in incremental_json else None
+                cls._merge_tests(aggregated_json[test_name], incremental_sub_result, num_runs)
+                continue
+
+            if incremental_json and test_name in incremental_json:
+                incremental_test = incremental_json[test_name]
+                results = incremental_test[JSON_RESULTS_RESULTS]
+                times = incremental_test[JSON_RESULTS_TIMES]
             else:
-                aggregated_json[test_name] = incremental_json[test_name]
+                results = [[1, JSON_RESULTS_NO_DATA]]
+                times = [[1, 0]]
 
+            aggregated_test = aggregated_json[test_name]
+            cls._insert_item_run_length_encoded(results, aggregated_test[JSON_RESULTS_RESULTS], num_runs)
+            cls._insert_item_run_length_encoded(times, aggregated_test[JSON_RESULTS_TIMES], num_runs)
+            cls._normalize_results_json(test_name, aggregated_json, num_runs)
+
     @classmethod
     def _insert_item_run_length_encoded(cls, incremental_item, aggregated_item, num_runs):
         for item in incremental_item:
@@ -175,27 +207,13 @@
         return len(results) == 1 and results[0][1] == type
 
     @classmethod
-    def _flatten_json_tests(cls, json, prefix=None):
-        """Flattens a trie directory structure of tests into a flat structure.
-        """
-        result = {}
-        for name, test in json.iteritems():
-            if prefix:
-                fullname = prefix + "/" + name
-            else:
-                fullname = name
-
-            if "results" in test:
-                result[fullname] = test
-            else:
-                result.update(cls._flatten_json_tests(test, fullname))
-
-        return result
-
-    @classmethod
     def _remove_gtest_modifiers(cls, builder, json):
         tests = json[builder][JSON_RESULTS_TESTS]
         new_tests = {}
+        # FIXME: This is wrong. If the test exists in the incremental results as both values, then one will overwrite the other.
+        # We should instead pick the one that doesn't have NO_DATA as its value.
+        # Alternately we could fix this by having the JSON generation code on the buildbot only include the test
+        # that was actually run.
         for name, test in tests.iteritems():
             new_name = name.replace('.FLAKY_', '.', 1)
             new_name = new_name.replace('.FAILS_', '.', 1)
@@ -221,13 +239,10 @@
             logging.error("Missing build number in json results.")
             return False
 
-        # FIXME(aboxhall): Once the dashboard can read hierarchical JSON, both
-        # incremental and aggregated JSON can be hierarchical, with no need to
-        # flatten here.
-        if version == JSON_RESULTS_HIERARCHICAL_VERSION:
-            flattened_tests = cls._flatten_json_tests(results_for_builder[JSON_RESULTS_TESTS])
-            json[builder][JSON_RESULTS_TESTS] = flattened_tests
-            json[JSON_RESULTS_VERSION_KEY] = JSON_RESULTS_VERSION
+        # FIXME: Once all the bots have cycled, we can remove this code since all the results will be heirarchical.
+        if version < JSON_RESULTS_HIERARCHICAL_VERSION:
+            json[builder][JSON_RESULTS_TESTS] = _trie_json_tests(results_for_builder[JSON_RESULTS_TESTS])
+            json[JSON_RESULTS_VERSION_KEY] = JSON_RESULTS_HIERARCHICAL_VERSION
 
         return True
 
@@ -260,13 +275,12 @@
 
         logging.info("Merging json results...")
         try:
-            if not cls._merge_json(aggregated_json[builder], incremental_json[builder], num_runs):
-                return None
+            cls._merge_json(aggregated_json[builder], incremental_json[builder], num_runs)
         except Exception, err:
             logging.error("Failed to merge json results: %s", str(err))
             return None
 
-        aggregated_json[JSON_RESULTS_VERSION_KEY] = JSON_RESULTS_VERSION
+        aggregated_json[JSON_RESULTS_VERSION_KEY] = JSON_RESULTS_HIERARCHICAL_VERSION
 
         return cls._generate_file_data(aggregated_json, sort_keys)
 

Modified: trunk/Tools/TestResultServer/model/jsonresults_unittest.py (100874 => 100875)


--- trunk/Tools/TestResultServer/model/jsonresults_unittest.py	2011-11-20 23:55:31 UTC (rev 100874)
+++ trunk/Tools/TestResultServer/model/jsonresults_unittest.py	2011-11-21 01:26:57 UTC (rev 100875)
@@ -113,10 +113,8 @@
         json = json.replace("[TESTDATA_CHROMEREVISION]", ",".join(chrome_revision))
         json = json.replace("[TESTDATA_TIMES]", ",".join(times))
 
-        if "version" in test_data:
-            json = json.replace("[VERSION]", str(test_data["version"]))
-        else:
-            json = json.replace("[VERSION]", "3")
+        version = str(test_data["version"]) if "version" in test_data else "4"
+        json = json.replace("[VERSION]", version)
 
         json_tests = []
         for (name, test) in sorted(tests.iteritems()):
@@ -556,15 +554,23 @@
         self._test_merge(
             # Aggregated results
             {"builds": ["2", "1"],
-             "tests": {"foo/001.html": {
+             "tests": {"bar/003.html": {
+                           "results": "[25,\"F\"]",
+                           "times": "[25,0]"},
+                       "foo/001.html": {
                            "results": "[50,\"F\"]",
                            "times": "[50,0]"},
                        "foo/002.html": {
                            "results": "[100,\"I\"]",
-                           "times": "[100,0]"}}},
+                           "times": "[100,0]"}},
+             "version": 3},
             # Incremental results
             {"builds": ["3"],
-             "tests": {"foo": {
+             "tests": {"baz": {
+                           "004.html": {
+                               "results": "[1,\"I\"]",
+                               "times": "[1,0]"}},
+                       "foo": {
                            "001.html": {
                                "results": "[1,\"F\"]",
                                "times": "[1,0]"},
@@ -574,13 +580,22 @@
              "version": 4},
             # Expected results
             {"builds": ["3", "2", "1"],
-             "tests": {"foo/001.html": {
-                           "results": "[51,\"F\"]",
-                           "times": "[51,0]"},
-                       "foo/002.html": {
-                           "results": "[101,\"I\"]",
-                           "times": "[101,0]"}},
-             "version": 3})
+             "tests": {"bar": {
+                           "003.html": {
+                               "results": "[1,\"N\"],[25,\"F\"]",
+                               "times": "[26,0]"}},
+                       "baz": {
+                           "004.html": {
+                               "results": "[1,\"I\"]",
+                               "times": "[1,0]"}},
+                       "foo": {
+                           "001.html": {
+                               "results": "[51,\"F\"]",
+                               "times": "[51,0]"},
+                           "002.html": {
+                               "results": "[101,\"I\"]",
+                               "times": "[101,0]"}}},
+             "version": 4})
 
     # FIXME(aboxhall): Add some tests for xhtml/svg test results.
 
@@ -612,7 +627,8 @@
                        "foo.FAILS_bar3": {
                            "results": "[100,\"I\"]",
                            "times": "[100,0]"},
-                       }},
+                       },
+             "version": 3},
             # Incremental results
             {"builds": ["3"],
              "tests": {"foo.FLAKY_bar": {
@@ -648,7 +664,7 @@
                        "foo.bar4": {
                            "results": "[1,\"I\"]",
                            "times": "[1,0]"}},
-             "version": 3})
+             "version": 4})
 
 if __name__ == '__main__':
     unittest.main()
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to