| # 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. |
| |
| import json |
| import logging |
| |
| from webkitpy.common.memoized import memoized |
| from webkitpy.layout_tests.layout_package import json_results_generator |
| from webkitpy.layout_tests.models import test_expectations |
| from webkitpy.layout_tests.models.test_expectations import TestExpectations |
| |
| _log = logging.getLogger(__name__) |
| |
| |
| # These are helper functions for navigating the results json structure. |
| def for_each_test(tree, handler, prefix=''): |
| for key in tree: |
| new_prefix = (prefix + '/' + key) if prefix else key |
| if 'actual' not in tree[key]: |
| for_each_test(tree[key], handler, new_prefix) |
| else: |
| handler(new_prefix, tree[key]) |
| |
| |
| def result_for_test(tree, test): |
| parts = test.split('/') |
| for part in parts: |
| if part not in tree: |
| return None |
| tree = tree[part] |
| return tree |
| |
| |
| class JSONTestResult(object): |
| def __init__(self, test_name, result_dict): |
| self._test_name = test_name |
| self._result_dict = result_dict |
| |
| def did_pass_or_run_as_expected(self): |
| return self.did_pass() or self.did_run_as_expected() |
| |
| def did_pass(self): |
| return test_expectations.PASS in self._actual_as_tokens() |
| |
| def did_run_as_expected(self): |
| return 'is_unexpected' not in self._result_dict |
| |
| def _tokenize(self, results_string): |
| tokens = map(TestExpectations.expectation_from_string, results_string.split(' ')) |
| if None in tokens: |
| _log.warning("Unrecognized result in %s" % results_string) |
| return set(tokens) |
| |
| @memoized |
| def _actual_as_tokens(self): |
| actual_results = self._result_dict['actual'] |
| return self._tokenize(actual_results) |
| |
| |
| # FIXME: This should be unified with ResultsSummary or other NRWT layout tests code |
| # in the layout_tests package. |
| # This doesn't belong in common.net, but we don't have a better place for it yet. |
| class LayoutTestResults(object): |
| @classmethod |
| def results_from_string(cls, string): |
| if not string: |
| return None |
| |
| content_string = json_results_generator.strip_json_wrapper(string) |
| json_dict = json.loads(content_string) |
| if not json_dict: |
| return None |
| return cls(json_dict) |
| |
| def __init__(self, parsed_json): |
| self._results = parsed_json |
| |
| def run_was_interrupted(self): |
| return self._results["interrupted"] |
| |
| def builder_name(self): |
| return self._results["builder_name"] |
| |
| def blink_revision(self): |
| return int(self._results["blink_revision"]) |
| |
| def actual_results(self, test): |
| result = result_for_test(self._results["tests"], test) |
| if result: |
| return result["actual"] |
| return "" |