Home | History | Annotate | Download | only in layout_tests
      1 #!/usr/bin/python
      2 # Copyright (C) 2010 Google Inc. All rights reserved.
      3 #
      4 # Redistribution and use in source and binary forms, with or without
      5 # modification, are permitted provided that the following conditions are
      6 # met:
      7 #
      8 #     * Redistributions of source code must retain the above copyright
      9 # notice, this list of conditions and the following disclaimer.
     10 #     * Redistributions in binary form must reproduce the above
     11 # copyright notice, this list of conditions and the following disclaimer
     12 # in the documentation and/or other materials provided with the
     13 # distribution.
     14 #     * Neither the name of Google Inc. nor the names of its
     15 # contributors may be used to endorse or promote products derived from
     16 # this software without specific prior written permission.
     17 #
     18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 """Unit tests for rebaseline_chromium_webkit_tests.py."""
     31 
     32 import unittest
     33 
     34 from webkitpy.tool import mocktool
     35 from webkitpy.common.system import urlfetcher_mock
     36 from webkitpy.common.system import filesystem_mock
     37 from webkitpy.common.system import zipfileset_mock
     38 from webkitpy.common.system import outputcapture
     39 from webkitpy.common.system.executive import Executive, ScriptError
     40 
     41 from webkitpy.layout_tests import port
     42 from webkitpy.layout_tests import rebaseline_chromium_webkit_tests
     43 
     44 
     45 class MockPort(object):
     46     def __init__(self, image_diff_exists):
     47         self.image_diff_exists = image_diff_exists
     48 
     49     def check_image_diff(self, override_step, logging):
     50         return self.image_diff_exists
     51 
     52 
     53 def get_mock_get(config_expectations):
     54     def mock_get(port_name, options):
     55         return MockPort(config_expectations[options.configuration])
     56     return mock_get
     57 
     58 
     59 ARCHIVE_URL = 'http://localhost/layout_test_results'
     60 
     61 
     62 def test_options():
     63     return mocktool.MockOptions(configuration=None,
     64                                 backup=False,
     65                                 html_directory='/tmp',
     66                                 archive_url=ARCHIVE_URL,
     67                                 force_archive_url=None,
     68                                 verbose=False,
     69                                 quiet=False,
     70                                 platforms=None)
     71 
     72 
     73 def test_host_port_and_filesystem(options, expectations):
     74     filesystem = port.unit_test_filesystem()
     75     host_port_obj = port.get('test', options, filesystem=filesystem,
     76                              user=mocktool.MockUser())
     77 
     78     expectations_path = host_port_obj.path_to_test_expectations_file()
     79     filesystem.write_text_file(expectations_path, expectations)
     80     return (host_port_obj, filesystem)
     81 
     82 
     83 def test_url_fetcher(filesystem):
     84     urls = {
     85         ARCHIVE_URL + '/Webkit_Mac10_6/': '<a href="4/">',
     86         ARCHIVE_URL + '/Webkit_Mac10_5/': '<a href="1/"><a href="2/">',
     87         ARCHIVE_URL + '/Webkit_Win7/': '<a href="1/">',
     88         ARCHIVE_URL + '/Webkit_Vista/': '<a href="1/">',
     89         ARCHIVE_URL + '/Webkit_Win/': '<a href="1/">',
     90         ARCHIVE_URL + '/Webkit_Linux/': '<a href="1/">',
     91     }
     92     return urlfetcher_mock.make_fetcher_cls(urls)(filesystem)
     93 
     94 
     95 def test_zip_factory():
     96     ziphashes = {
     97         ARCHIVE_URL + '/Webkit_Mac10_5/2/layout-test-results.zip': {
     98             'layout-test-results/failures/expected/image-actual.txt': 'new-image-txt',
     99             'layout-test-results/failures/expected/image-actual.checksum': 'new-image-checksum',
    100             'layout-test-results/failures/expected/image-actual.png': 'new-image-png',
    101             'layout-test-results/failures/expected/image_checksum-actual.txt': 'png-comment-txt',
    102             'layout-test-results/failures/expected/image_checksum-actual.checksum': '0123456789',
    103             'layout-test-results/failures/expected/image_checksum-actual.png': 'tEXtchecksum\x000123456789',
    104         },
    105         ARCHIVE_URL + '/Webkit_Mac10_6/4/layout-test-results.zip': {
    106             'layout-test-results/failures/expected/image-actual.txt': 'new-image-txt',
    107             'layout-test-results/failures/expected/image-actual.checksum': 'new-image-checksum',
    108             'layout-test-results/failures/expected/image-actual.png': 'new-image-png',
    109         },
    110          ARCHIVE_URL + '/Webkit_Vista/1/layout-test-results.zip': {
    111             'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
    112             'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
    113             'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
    114         },
    115           ARCHIVE_URL + '/Webkit_Win7/1/layout-test-results.zip': {
    116             'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
    117             'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
    118             'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
    119         },
    120           ARCHIVE_URL + '/Webkit_Win/1/layout-test-results.zip': {
    121             'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
    122             'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
    123             'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
    124         },
    125           ARCHIVE_URL + '/Webkit_Linux/1/layout-test-results.zip': {
    126             'layout-test-results/failures/expected/image-actual.txt': 'win-image-txt',
    127             'layout-test-results/failures/expected/image-actual.checksum': 'win-image-checksum',
    128             'layout-test-results/failures/expected/image-actual.png': 'win-image-png',
    129         },
    130     }
    131     return zipfileset_mock.make_factory(ziphashes)
    132 
    133 
    134 def test_archive(orig_archive_dict):
    135     new_archive_dict = {}
    136     for platform, dirname in orig_archive_dict.iteritems():
    137         platform = platform.replace('chromium', 'test')
    138         new_archive_dict[platform] = dirname
    139     return new_archive_dict
    140 
    141 
    142 class TestGetHostPortObject(unittest.TestCase):
    143     def assert_result(self, release_present, debug_present, valid_port_obj):
    144         # Tests whether we get a valid port object returned when we claim
    145         # that Image diff is (or isn't) present in the two configs.
    146         port.get = get_mock_get({'Release': release_present,
    147                                  'Debug': debug_present})
    148         options = mocktool.MockOptions(configuration=None,
    149                                        html_directory='/tmp')
    150         port_obj = rebaseline_chromium_webkit_tests.get_host_port_object(options)
    151         if valid_port_obj:
    152             self.assertNotEqual(port_obj, None)
    153         else:
    154             self.assertEqual(port_obj, None)
    155 
    156     def test_get_host_port_object(self):
    157         # Save the normal port.get() function for future testing.
    158         old_get = port.get
    159 
    160         # Test whether we get a valid port object back for the four
    161         # possible cases of having ImageDiffs built. It should work when
    162         # there is at least one binary present.
    163         self.assert_result(False, False, False)
    164         self.assert_result(True, False, True)
    165         self.assert_result(False, True, True)
    166         self.assert_result(True, True, True)
    167 
    168         # Restore the normal port.get() function.
    169         port.get = old_get
    170 
    171 
    172 class TestOptions(unittest.TestCase):
    173     def test_parse_options(self):
    174         (options, target_options) = rebaseline_chromium_webkit_tests.parse_options([])
    175         self.assertTrue(target_options.chromium)
    176         self.assertEqual(options.tolerance, 0)
    177 
    178         (options, target_options) = rebaseline_chromium_webkit_tests.parse_options(['--target-platform', 'qt'])
    179         self.assertFalse(hasattr(target_options, 'chromium'))
    180         self.assertEqual(options.tolerance, 0)
    181 
    182 
    183 class TestRebaseliner(unittest.TestCase):
    184     def setUp(self):
    185         if not hasattr(self, '_orig_archive'):
    186             self._orig_archive = rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT
    187             rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = test_archive(self._orig_archive)
    188 
    189     def tearDown(self):
    190         rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = self._orig_archive
    191 
    192     def make_rebaseliner(self, expectations):
    193         options = test_options()
    194         host_port_obj, filesystem = test_host_port_and_filesystem(options, expectations)
    195 
    196         target_options = options
    197         target_port_obj = port.get('test', target_options,
    198                                    filesystem=filesystem)
    199         target_port_obj._expectations = expectations
    200         platform = target_port_obj.name()
    201 
    202         url_fetcher = test_url_fetcher(filesystem)
    203         zip_factory = test_zip_factory()
    204         mock_scm = mocktool.MockSCM(filesystem)
    205         rebaseliner = rebaseline_chromium_webkit_tests.Rebaseliner(host_port_obj,
    206             target_port_obj, platform, options, url_fetcher, zip_factory, mock_scm)
    207         return rebaseliner, filesystem
    208 
    209     def test_noop(self):
    210         # this method tests that was can at least instantiate an object, even
    211         # if there is nothing to do.
    212         rebaseliner, filesystem = self.make_rebaseliner("")
    213         rebaseliner.run()
    214         self.assertEqual(len(filesystem.written_files), 1)
    215 
    216     def test_rebaselining_tests(self):
    217         rebaseliner, filesystem = self.make_rebaseliner(
    218             "BUGX REBASELINE MAC : failures/expected/image.html = IMAGE")
    219         compile_success = rebaseliner._compile_rebaselining_tests()
    220         self.assertTrue(compile_success)
    221         self.assertEqual(set(['failures/expected/image.html']), rebaseliner._rebaselining_tests)
    222 
    223     def test_rebaselining_tests_should_ignore_reftests(self):
    224         rebaseliner, filesystem = self.make_rebaseliner(
    225             "BUGX REBASELINE : failures/expected/reftest.html = IMAGE")
    226         compile_success = rebaseliner._compile_rebaselining_tests()
    227         self.assertFalse(compile_success)
    228         self.assertFalse(rebaseliner._rebaselining_tests)
    229 
    230     def test_one_platform(self):
    231         rebaseliner, filesystem = self.make_rebaseliner(
    232             "BUGX REBASELINE MAC : failures/expected/image.html = IMAGE")
    233         rebaseliner.run()
    234         # We expect to have written 12 files over the course of this rebaseline:
    235         # *) 3 files in /__im_tmp for the extracted archive members
    236         # *) 3 new baselines under '/test.checkout/LayoutTests'
    237         # *) 4 files in /tmp for the new and old baselines in the result file
    238         #    (-{old,new}.{txt,png}
    239         # *) 1 text diff in /tmp for the result file (-diff.txt). We don't
    240         #    create image diffs (FIXME?) and don't display the checksums.
    241         # *) 1 updated test_expectations file
    242         self.assertEqual(len(filesystem.written_files), 12)
    243         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.checksum'], 'new-image-checksum')
    244         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.png'], 'new-image-png')
    245         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.txt'], 'new-image-txt')
    246 
    247     def test_all_platforms(self):
    248         rebaseliner, filesystem = self.make_rebaseliner(
    249             "BUGX REBASELINE : failures/expected/image.html = IMAGE")
    250         rebaseliner.run()
    251         # See comment in test_one_platform for an explanation of the 12 written tests.
    252         # Note that even though the rebaseline is marked for all platforms, each
    253         # rebaseliner only ever does one.
    254         self.assertEqual(len(filesystem.written_files), 12)
    255         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.checksum'], 'new-image-checksum')
    256         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.png'], 'new-image-png')
    257         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image-expected.txt'], 'new-image-txt')
    258 
    259     def test_png_file_with_comment(self):
    260         rebaseliner, filesystem = self.make_rebaseliner(
    261             "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
    262         compile_success = rebaseliner._compile_rebaselining_tests()
    263         self.assertTrue(compile_success)
    264         self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
    265         rebaseliner.run()
    266         # There is one less file written than |test_one_platform| because we only
    267         # write 2 expectations (the png and the txt file).
    268         self.assertEqual(len(filesystem.written_files), 11)
    269         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'], 'tEXtchecksum\x000123456789')
    270         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'], 'png-comment-txt')
    271         self.assertFalse(filesystem.files.get('/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None))
    272 
    273     def test_png_file_with_comment_remove_old_checksum(self):
    274         rebaseliner, filesystem = self.make_rebaseliner(
    275             "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
    276         filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'] = 'old'
    277         filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum'] = 'old'
    278         filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'] = 'old'
    279 
    280         compile_success = rebaseliner._compile_rebaselining_tests()
    281         self.assertTrue(compile_success)
    282         self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
    283         rebaseliner.run()
    284         # There is one more file written than |test_png_file_with_comment_remove_old_checksum|
    285         # because we also delete the old checksum.
    286         self.assertEqual(len(filesystem.written_files), 12)
    287         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.png'], 'tEXtchecksum\x000123456789')
    288         self.assertEqual(filesystem.files['/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt'], 'png-comment-txt')
    289         self.assertEqual(filesystem.files.get('/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None), None)
    290 
    291     def test_png_file_with_comment_as_duplicate(self):
    292         rebaseliner, filesystem = self.make_rebaseliner(
    293             "BUGX REBASELINE MAC : failures/expected/image_checksum.html = IMAGE")
    294         filesystem.files['/test.checkout/LayoutTests/platform/test-mac-snowleopard/failures/expected/image_checksum-expected.png'] = 'tEXtchecksum\x000123456789'
    295         filesystem.files['/test.checkout/LayoutTests/platform/test-mac-snowleopard/failures/expected/image_checksum-expected.txt'] = 'png-comment-txt'
    296 
    297         compile_success = rebaseliner._compile_rebaselining_tests()
    298         self.assertTrue(compile_success)
    299         self.assertEqual(set(['failures/expected/image_checksum.html']), rebaseliner._rebaselining_tests)
    300         rebaseliner.run()
    301         self.assertEqual(filesystem.files.get('/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.png', None), None)
    302         self.assertEqual(filesystem.files.get('/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.txt', None), None)
    303         self.assertEqual(filesystem.files.get('/test.checkout/LayoutTests/platform/test-mac-leopard/failures/expected/image_checksum-expected.checksum', None), None)
    304 
    305     def test_diff_baselines_txt(self):
    306         rebaseliner, filesystem = self.make_rebaseliner("")
    307         port = rebaseliner._port
    308         output = port.expected_text(
    309             port._filesystem.join(port.layout_tests_dir(), 'passes/text.html'))
    310         self.assertFalse(rebaseliner._diff_baselines(output, output,
    311                                                      is_image=False))
    312 
    313     def test_diff_baselines_png(self):
    314         rebaseliner, filesystem = self.make_rebaseliner('')
    315         port = rebaseliner._port
    316         image = port.expected_image(
    317             port._filesystem.join(port.layout_tests_dir(), 'passes/image.html'))
    318         self.assertFalse(rebaseliner._diff_baselines(image, image,
    319                                                      is_image=True))
    320 
    321 
    322 class TestRealMain(unittest.TestCase):
    323     def setUp(self):
    324         if not hasattr(self, '_orig_archive'):
    325             self._orig_archive = rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT
    326             rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = test_archive(self._orig_archive)
    327 
    328     def tearDown(self):
    329         rebaseline_chromium_webkit_tests.ARCHIVE_DIR_NAME_DICT = self._orig_archive
    330 
    331     def test_all_platforms(self):
    332         expectations = "BUGX REBASELINE : failures/expected/image.html = IMAGE"
    333 
    334         options = test_options()
    335         host_port_obj, filesystem = test_host_port_and_filesystem(options, expectations)
    336         url_fetcher = test_url_fetcher(filesystem)
    337         zip_factory = test_zip_factory()
    338         mock_scm = mocktool.MockSCM()
    339         oc = outputcapture.OutputCapture()
    340         oc.capture_output()
    341         res = rebaseline_chromium_webkit_tests.real_main(options, options,
    342             host_port_obj, host_port_obj, url_fetcher, zip_factory, mock_scm)
    343         oc.restore_output()
    344 
    345         # We expect to have written 36 files over the course of this rebaseline:
    346         # *) 6*3 files in /__im_tmp/ for the archived members of the 6 ports
    347         # *) 2*3 files in /test.checkout for actually differing baselines
    348         # *) 1 file in /test.checkout for the updated test_expectations file
    349         # *) 2*4 files in /tmp for the old/new baselines for the two actual ports
    350         # *) 2 files in /tmp for the text diffs for the two ports
    351         # *) 1 file in /tmp for the rebaseline results html file
    352         self.assertEqual(res, 0)
    353         self.assertEqual(len(filesystem.written_files), 36)
    354 
    355 
    356 class TestHtmlGenerator(unittest.TestCase):
    357     def make_generator(self, files, tests):
    358         options = mocktool.MockOptions(configuration=None, html_directory='/tmp')
    359         host_port = port.get('test', options, filesystem=port.unit_test_filesystem(files))
    360         generator = rebaseline_chromium_webkit_tests.HtmlGenerator(host_port,
    361             target_port=None, options=options, platforms=['test-mac-leopard'], rebaselining_tests=tests)
    362         return generator, host_port
    363 
    364     def test_generate_baseline_links(self):
    365         files = {
    366             "/tmp/foo-expected-mac-old.txt": "",
    367             "/tmp/foo-expected-mac-new.txt": "",
    368             "/tmp/foo-expected-mac-diff.txt": "",
    369         }
    370         tests = ["foo.txt"]
    371         generator, host_port = self.make_generator(files, tests)
    372         links = generator._generate_baseline_links("foo", ".txt", "mac")
    373         expected_links = '<td align=center><a href="file:///tmp/foo-expected-mac-old.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-new.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-diff.txt">Diff</a></td>'
    374         self.assertEqual(links, expected_links)
    375 
    376 
    377 if __name__ == '__main__':
    378     unittest.main()
    379