Chromium Code Reviews| Index: gm/rebaseline_server/results.py |
| =================================================================== |
| --- gm/rebaseline_server/results.py (revision 11507) |
| +++ gm/rebaseline_server/results.py (working copy) |
| @@ -31,6 +31,9 @@ |
| import gm_json |
| IMAGE_FILENAME_RE = re.compile(gm_json.IMAGE_FILENAME_PATTERN) |
| +CATEGORIES_TO_SUMMARIZE = [ |
| + 'builder', 'test', 'config', 'resultType', |
| +] |
| class Results(object): |
| """ Loads actual and expected results from all builders, supplying combined |
| @@ -44,24 +47,47 @@ |
| """ |
| self._actual_builder_dicts = Results._GetDictsFromRoot(actuals_root) |
| self._expected_builder_dicts = Results._GetDictsFromRoot(expected_root) |
| - self._all_results = self._Combine() |
| + self._all_results = Results._Combine( |
| + actual_builder_dicts=self._actual_builder_dicts, |
| + expected_builder_dicts=self._expected_builder_dicts) |
| def GetAll(self): |
| - """Return results of all tests, as a list in this form: |
| + """Return results of all tests, as a dictionary in this form: |
| - [ |
| + { |
| + "categories": # dictionary of category totals, keyed by category name |
|
epoger
2013/09/27 18:12:39
This "categories" dict is the new part. By includ
borenet
2013/09/27 19:22:01
I'm confused - "resultType" and "builder" are the
epoger
2013/09/27 21:38:13
I updated the docstring to (hopefully) make it cle
borenet
2013/09/30 13:06:02
Thanks Elliot. This is much clearer.
|
| + # and value |
| { |
| - "builder": "Test-Mac10.6-MacMini4.1-GeForce320M-x86-Debug", |
| - "test": "bigmatrix", |
| - "config": "8888", |
| - "resultType": "failed", |
| - "expectedHashType": "bitmap-64bitMD5", |
| - "expectedHashDigest": "10894408024079689926", |
| - "actualHashType": "bitmap-64bitMD5", |
| - "actualHashDigest": "2409857384569", |
| - }, |
| - ... |
| - ] |
| + "resultType": # category name, one of CATEGORIES_TO_SUMMARIZE |
| + { |
| + "failed": 3, # category value and total number found of that value |
| + "failure-ignored": 19, |
| + "no-comparison": 120, |
| + "succeeded": 1932, |
| + }, |
| + "builder": |
| + { |
| + "Test-Mac10.6-MacMini4.1-GeForce320M-x86-Debug": 180, |
| + "Test-Mac10.6-MacMini4.1-GeForce320M-x86-Release": 180, |
|
borenet
2013/09/27 19:22:01
What does 180 mean? Is that the total number of r
epoger
2013/09/27 21:38:13
That's what the number at that position represents
|
| + ... |
| + }, |
| + }, # end of "categories" dictionary |
| + |
| + "testData": # list of test results, with a dictionary for each |
| + [ |
| + { |
| + "builder": "Test-Mac10.6-MacMini4.1-GeForce320M-x86-Debug", |
| + "test": "bigmatrix", |
| + "config": "8888", |
| + "resultType": "failed", |
| + "expectedHashType": "bitmap-64bitMD5", |
| + "expectedHashDigest": "10894408024079689926", |
| + "actualHashType": "bitmap-64bitMD5", |
| + "actualHashDigest": "2409857384569", |
| + }, |
| + ... |
| + ], # end of "testData" list |
| + } |
| """ |
| return self._all_results |
| @@ -84,15 +110,21 @@ |
| meta_dict[builder] = gm_json.LoadFromFile(fullpath) |
| return meta_dict |
| - def _Combine(self): |
| - """Returns a list of all tests, across all builders, based on the |
| - contents of self._actual_builder_dicts and self._expected_builder_dicts . |
| - Returns the list in the same form needed for GetAllResults(). |
| + @staticmethod |
| + def _Combine(actual_builder_dicts, expected_builder_dicts): |
| + """Gathers the results of all tests, across all builders (based on the |
| + contents of actual_builder_dicts and expected_builder_dicts) |
| + and returns it in a list in the same form needed for self.GetAll(). |
| + |
| + This is a static method, because once we start refreshing results |
| + asynchronously, we need to make sure we are not corrupting the object's |
| + member variables. |
| """ |
| - all_tests = [] |
| - for builder in sorted(self._actual_builder_dicts.keys()): |
| + test_data = [] |
| + category_dict = {} |
| + for builder in sorted(actual_builder_dicts.keys()): |
| actual_results_for_this_builder = ( |
| - self._actual_builder_dicts[builder][gm_json.JSONKEY_ACTUALRESULTS]) |
| + actual_builder_dicts[builder][gm_json.JSONKEY_ACTUALRESULTS]) |
| for result_type in sorted(actual_results_for_this_builder.keys()): |
| results_of_this_type = actual_results_for_this_builder[result_type] |
| if not results_of_this_type: |
| @@ -102,7 +134,7 @@ |
| try: |
| # TODO(epoger): assumes a single allowed digest per test |
| expected_image = ( |
| - self._expected_builder_dicts |
| + expected_builder_dicts |
| [builder][gm_json.JSONKEY_EXPECTEDRESULTS] |
| [image_name][gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS] |
| [0]) |
| @@ -159,13 +191,8 @@ |
| else: |
| updated_result_type = result_type |
| - # TODO(epoger): For now, don't include succeeded results. |
| - # There are so many of them that they make the client too slow. |
| - if updated_result_type == gm_json.JSONKEY_ACTUALRESULTS_SUCCEEDED: |
| - continue |
| - |
| (test, config) = IMAGE_FILENAME_RE.match(image_name).groups() |
| - all_tests.append({ |
| + results_for_this_test = { |
| "builder": builder, |
| "test": test, |
| "config": config, |
| @@ -174,5 +201,35 @@ |
| "actualHashDigest": str(actual_image[1]), |
| "expectedHashType": expected_image[0], |
| "expectedHashDigest": str(expected_image[1]), |
| - }) |
| - return all_tests |
| + } |
| + Results._AddToCategoryDict(category_dict, results_for_this_test) |
| + |
| + # TODO(epoger): For now, don't include succeeded results in the raw |
| + # data. There are so many of them that they make the client too slow. |
| + if updated_result_type != gm_json.JSONKEY_ACTUALRESULTS_SUCCEEDED: |
| + test_data.append(results_for_this_test) |
| + return {"categories": category_dict, "testData": test_data} |
| + |
| + @staticmethod |
| + def _AddToCategoryDict(category_dict, test_results): |
| + """Add test_results to the category dictionary we are building |
| + (see documentation of self.GetAll() for the format of this dictionary). |
| + |
| + params: |
| + category_dict: category dict-of-dicts to add to; modify this in-place |
| + test_results: test data with which to update category_list, in a dict: |
| + { |
| + "category_name": "category_value", |
| + "category_name": "category_value", |
| + ... |
| + } |
| + """ |
| + for category in CATEGORIES_TO_SUMMARIZE: |
| + category_value = test_results.get(category) |
| + if not category_value: |
| + continue # test_results did not include this category, keep going |
| + if not category_dict.get(category): |
| + category_dict[category] = {} |
| + if not category_dict[category].get(category_value): |
| + category_dict[category][category_value] = 0 |
| + category_dict[category][category_value] += 1 |