Home | History | Annotate | Download | only in layout_package
      1 # Copyright (C) 2010 Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #     * Redistributions of source code must retain the above copyright
      8 # notice, this list of conditions and the following disclaimer.
      9 #     * Redistributions in binary form must reproduce the above
     10 # copyright notice, this list of conditions and the following disclaimer
     11 # in the documentation and/or other materials provided with the
     12 # distribution.
     13 #     * Neither the name of Google Inc. nor the names of its
     14 # contributors may be used to endorse or promote products derived from
     15 # this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 """Unit tests for json_results_generator.py."""
     30 
     31 import unittest
     32 import optparse
     33 import random
     34 
     35 from webkitpy.common.system import filesystem_mock
     36 from webkitpy.layout_tests.layout_package import json_results_generator
     37 from webkitpy.layout_tests.layout_package import test_expectations
     38 from webkitpy.thirdparty.mock import Mock
     39 
     40 
     41 class JSONGeneratorTest(unittest.TestCase):
     42     def setUp(self):
     43         self.builder_name = 'DUMMY_BUILDER_NAME'
     44         self.build_name = 'DUMMY_BUILD_NAME'
     45         self.build_number = 'DUMMY_BUILDER_NUMBER'
     46 
     47         # For archived results.
     48         self._json = None
     49         self._num_runs = 0
     50         self._tests_set = set([])
     51         self._test_timings = {}
     52         self._failed_count_map = {}
     53 
     54         self._PASS_count = 0
     55         self._DISABLED_count = 0
     56         self._FLAKY_count = 0
     57         self._FAILS_count = 0
     58         self._fixable_count = 0
     59 
     60     def _test_json_generation(self, passed_tests_list, failed_tests_list):
     61         tests_set = set(passed_tests_list) | set(failed_tests_list)
     62 
     63         DISABLED_tests = set([t for t in tests_set
     64                              if t.startswith('DISABLED_')])
     65         FLAKY_tests = set([t for t in tests_set
     66                            if t.startswith('FLAKY_')])
     67         FAILS_tests = set([t for t in tests_set
     68                            if t.startswith('FAILS_')])
     69         PASS_tests = tests_set - (DISABLED_tests | FLAKY_tests | FAILS_tests)
     70 
     71         failed_tests = set(failed_tests_list) - DISABLED_tests
     72         failed_count_map = dict([(t, 1) for t in failed_tests])
     73 
     74         test_timings = {}
     75         i = 0
     76         for test in tests_set:
     77             test_timings[test] = float(self._num_runs * 100 + i)
     78             i += 1
     79 
     80         test_results_map = dict()
     81         for test in tests_set:
     82             test_results_map[test] = json_results_generator.TestResult(test,
     83                 failed=(test in failed_tests),
     84                 elapsed_time=test_timings[test])
     85 
     86         port = Mock()
     87         port._filesystem = filesystem_mock.MockFileSystem()
     88         generator = json_results_generator.JSONResultsGeneratorBase(port,
     89             self.builder_name, self.build_name, self.build_number,
     90             '',
     91             None,   # don't fetch past json results archive
     92             test_results_map)
     93 
     94         failed_count_map = dict([(t, 1) for t in failed_tests])
     95 
     96         # Test incremental json results
     97         incremental_json = generator.get_json()
     98         self._verify_json_results(
     99             tests_set,
    100             test_timings,
    101             failed_count_map,
    102             len(PASS_tests),
    103             len(DISABLED_tests),
    104             len(FLAKY_tests),
    105             len(DISABLED_tests | failed_tests),
    106             incremental_json,
    107             1)
    108 
    109         # We don't verify the results here, but at least we make sure the code runs without errors.
    110         generator.generate_json_output()
    111         generator.generate_full_results_file()
    112 
    113     def _verify_json_results(self, tests_set, test_timings, failed_count_map,
    114                              PASS_count, DISABLED_count, FLAKY_count,
    115                              fixable_count,
    116                              json, num_runs):
    117         # Aliasing to a short name for better access to its constants.
    118         JRG = json_results_generator.JSONResultsGeneratorBase
    119 
    120         self.assertTrue(JRG.VERSION_KEY in json)
    121         self.assertTrue(self.builder_name in json)
    122 
    123         buildinfo = json[self.builder_name]
    124         self.assertTrue(JRG.FIXABLE in buildinfo)
    125         self.assertTrue(JRG.TESTS in buildinfo)
    126         self.assertEqual(len(buildinfo[JRG.BUILD_NUMBERS]), num_runs)
    127         self.assertEqual(buildinfo[JRG.BUILD_NUMBERS][0], self.build_number)
    128 
    129         if tests_set or DISABLED_count:
    130             fixable = {}
    131             for fixable_items in buildinfo[JRG.FIXABLE]:
    132                 for (type, count) in fixable_items.iteritems():
    133                     if type in fixable:
    134                         fixable[type] = fixable[type] + count
    135                     else:
    136                         fixable[type] = count
    137 
    138             if PASS_count:
    139                 self.assertEqual(fixable[JRG.PASS_RESULT], PASS_count)
    140             else:
    141                 self.assertTrue(JRG.PASS_RESULT not in fixable or
    142                                 fixable[JRG.PASS_RESULT] == 0)
    143             if DISABLED_count:
    144                 self.assertEqual(fixable[JRG.SKIP_RESULT], DISABLED_count)
    145             else:
    146                 self.assertTrue(JRG.SKIP_RESULT not in fixable or
    147                                 fixable[JRG.SKIP_RESULT] == 0)
    148             if FLAKY_count:
    149                 self.assertEqual(fixable[JRG.FLAKY_RESULT], FLAKY_count)
    150             else:
    151                 self.assertTrue(JRG.FLAKY_RESULT not in fixable or
    152                                 fixable[JRG.FLAKY_RESULT] == 0)
    153 
    154         if failed_count_map:
    155             tests = buildinfo[JRG.TESTS]
    156             for test_name in failed_count_map.iterkeys():
    157                 self.assertTrue(test_name in tests)
    158                 test = tests[test_name]
    159 
    160                 failed = 0
    161                 for result in test[JRG.RESULTS]:
    162                     if result[1] == JRG.FAIL_RESULT:
    163                         failed += result[0]
    164                 self.assertEqual(failed_count_map[test_name], failed)
    165 
    166                 timing_count = 0
    167                 for timings in test[JRG.TIMES]:
    168                     if timings[1] == test_timings[test_name]:
    169                         timing_count = timings[0]
    170                 self.assertEqual(1, timing_count)
    171 
    172         if fixable_count:
    173             self.assertEqual(sum(buildinfo[JRG.FIXABLE_COUNT]), fixable_count)
    174 
    175     def test_json_generation(self):
    176         self._test_json_generation([], [])
    177         self._test_json_generation(['A1', 'B1'], [])
    178         self._test_json_generation([], ['FAILS_A2', 'FAILS_B2'])
    179         self._test_json_generation(['DISABLED_A3', 'DISABLED_B3'], [])
    180         self._test_json_generation(['A4'], ['B4', 'FAILS_C4'])
    181         self._test_json_generation(['DISABLED_C5', 'DISABLED_D5'], ['A5', 'B5'])
    182         self._test_json_generation(
    183             ['A6', 'B6', 'FAILS_C6', 'DISABLED_E6', 'DISABLED_F6'],
    184             ['FAILS_D6'])
    185 
    186         # Generate JSON with the same test sets. (Both incremental results and
    187         # archived results must be updated appropriately.)
    188         self._test_json_generation(
    189             ['A', 'FLAKY_B', 'DISABLED_C'],
    190             ['FAILS_D', 'FLAKY_E'])
    191         self._test_json_generation(
    192             ['A', 'DISABLED_C', 'FLAKY_E'],
    193             ['FLAKY_B', 'FAILS_D'])
    194         self._test_json_generation(
    195             ['FLAKY_B', 'DISABLED_C', 'FAILS_D'],
    196             ['A', 'FLAKY_E'])
    197 
    198 if __name__ == '__main__':
    199     unittest.main()
    200