1#!/usr/bin/env 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 6# are met: 7# 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 25"""Unit tests for deduplicate_tests.py.""" 26 27import deduplicate_tests 28import os 29import unittest 30import webkitpy.common.checkout.scm as scm 31 32 33class MockExecutive(object): 34 last_run_command = [] 35 response = '' 36 37 class Executive(object): 38 def run_command(self, 39 args, 40 cwd=None, 41 input=None, 42 error_handler=None, 43 return_exit_code=False, 44 return_stderr=True, 45 decode_output=True): 46 MockExecutive.last_run_command += [args] 47 return MockExecutive.response 48 49 50class ListDuplicatesTest(unittest.TestCase): 51 def setUp(self): 52 MockExecutive.last_run_command = [] 53 MockExecutive.response = '' 54 deduplicate_tests.executive = MockExecutive 55 self._original_cwd = os.getcwd() 56 checkout_root = scm.find_checkout_root() 57 self.assertNotEqual(checkout_root, None) 58 os.chdir(checkout_root) 59 60 def tearDown(self): 61 os.chdir(self._original_cwd) 62 63 def test_parse_git_output(self): 64 git_output = ( 65 '100644 blob 5053240b3353f6eb39f7cb00259785f16d121df2\tLayoutTests/mac/foo-expected.txt\n' 66 '100644 blob a004548d107ecc4e1ea08019daf0a14e8634a1ff\tLayoutTests/platform/chromium/foo-expected.txt\n' 67 '100644 blob d6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-linux/foo-expected.txt\n' 68 '100644 blob abcdebc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-linux/animage.png\n' 69 '100644 blob d6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-win/foo-expected.txt\n' 70 '100644 blob abcdebc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-win/animage.png\n' 71 '100644 blob 4303df5389ca87cae83dd3236b8dd84e16606517\tLayoutTests/platform/mac/foo-expected.txt\n') 72 hashes = deduplicate_tests.parse_git_output(git_output, '*') 73 expected = {('mac/foo-expected.txt', '5053240b3353f6eb39f7cb00259785f16d121df2'): set(['mac/foo-expected.txt']), 74 ('animage.png', 'abcdebc762e3aec5df03b5c04485b2cb3b65ffb1'): set(['platform/chromium-linux/animage.png', 'platform/chromium-win/animage.png']), 75 ('foo-expected.txt', '4303df5389ca87cae83dd3236b8dd84e16606517'): set(['platform/mac/foo-expected.txt']), 76 ('foo-expected.txt', 'd6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1'): set(['platform/chromium-linux/foo-expected.txt', 'platform/chromium-win/foo-expected.txt']), 77 ('foo-expected.txt', 'a004548d107ecc4e1ea08019daf0a14e8634a1ff'): set(['platform/chromium/foo-expected.txt'])} 78 self.assertEquals(expected, hashes) 79 80 hashes = deduplicate_tests.parse_git_output(git_output, '*.png') 81 expected = {('animage.png', 'abcdebc762e3aec5df03b5c04485b2cb3b65ffb1'): set(['platform/chromium-linux/animage.png', 'platform/chromium-win/animage.png'])} 82 self.assertEquals(expected, hashes) 83 84 def test_extract_platforms(self): 85 self.assertEquals({'foo': 'platform/foo/bar', 86 'zoo': 'platform/zoo/com'}, 87 deduplicate_tests.extract_platforms(['platform/foo/bar', 'platform/zoo/com'])) 88 self.assertEquals({'foo': 'platform/foo/bar', 89 deduplicate_tests._BASE_PLATFORM: 'what/'}, 90 deduplicate_tests.extract_platforms(['platform/foo/bar', 'what/'])) 91 92 def test_has_intermediate_results(self): 93 test_cases = ( 94 # If we found a duplicate in our first fallback, we have no 95 # intermediate results. 96 (False, ('fast/foo-expected.txt', 97 ['chromium-win', 'chromium', 'base'], 98 'chromium-win-win7', 99 lambda path: True)), 100 # Since chromium-win has a result, we have an intermediate result. 101 (True, ('fast/foo-expected.txt', 102 ['chromium-win', 'chromium', 'base'], 103 'chromium', 104 lambda path: True)), 105 # There are no intermediate results. 106 (False, ('fast/foo-expected.txt', 107 ['chromium-win', 'chromium', 'base'], 108 'chromium', 109 lambda path: False)), 110 # There are no intermediate results since a result for chromium is 111 # our duplicate file. 112 (False, ('fast/foo-expected.txt', 113 ['chromium-win', 'chromium', 'base'], 114 'chromium', 115 lambda path: path == 'LayoutTests/platform/chromium/fast/foo-expected.txt')), 116 # We have an intermediate result in 'chromium' even though our 117 # duplicate is with the file in 'base'. 118 (True, ('fast/foo-expected.txt', 119 ['chromium-win', 'chromium', 'base'], 120 'base', 121 lambda path: path == 'LayoutTests/platform/chromium/fast/foo-expected.txt')), 122 # We have an intermediate result in 'chromium-win' even though our 123 # duplicate is in 'base'. 124 (True, ('fast/foo-expected.txt', 125 ['chromium-win', 'chromium', 'base'], 126 'base', 127 lambda path: path == 'LayoutTests/platform/chromium-win/fast/foo-expected.txt')), 128 ) 129 for expected, inputs in test_cases: 130 self.assertEquals(expected, 131 deduplicate_tests.has_intermediate_results(*inputs)) 132 133 def test_unique(self): 134 MockExecutive.response = ( 135 '100644 blob 5053240b3353f6eb39f7cb00259785f16d121df2\tLayoutTests/mac/foo-expected.txt\n' 136 '100644 blob a004548d107ecc4e1ea08019daf0a14e8634a1ff\tLayoutTests/platform/chromium/foo-expected.txt\n' 137 '100644 blob abcd0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-linux/foo-expected.txt\n' 138 '100644 blob d6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-win/foo-expected.txt\n' 139 '100644 blob 4303df5389ca87cae83dd3236b8dd84e16606517\tLayoutTests/platform/mac/foo-expected.txt\n') 140 result = deduplicate_tests.deduplicate('*') 141 self.assertEquals(1, len(MockExecutive.last_run_command)) 142 self.assertEquals(('git', 'ls-tree', '-r', 'HEAD', 'LayoutTests'), MockExecutive.last_run_command[-1]) 143 self.assertEquals(0, len(result)) 144 145 def test_duplicates(self): 146 MockExecutive.response = ( 147 '100644 blob 5053240b3353f6eb39f7cb00259785f16d121df2\tLayoutTests/mac/foo-expected.txt\n' 148 '100644 blob a004548d107ecc4e1ea08019daf0a14e8634a1ff\tLayoutTests/platform/chromium/foo-expected.txt\n' 149 '100644 blob d6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-linux/foo-expected.txt\n' 150 '100644 blob abcdebc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-linux/animage.png\n' 151 '100644 blob d6bb0bc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-win/foo-expected.txt\n' 152 '100644 blob abcdebc762e3aec5df03b5c04485b2cb3b65ffb1\tLayoutTests/platform/chromium-win/animage.png\n' 153 '100644 blob 4303df5389ca87cae83dd3236b8dd84e16606517\tLayoutTests/platform/mac/foo-expected.txt\n') 154 155 result = deduplicate_tests.deduplicate('*') 156 self.assertEquals(1, len(MockExecutive.last_run_command)) 157 self.assertEquals(('git', 'ls-tree', '-r', 'HEAD', 'LayoutTests'), MockExecutive.last_run_command[-1]) 158 self.assertEquals(2, len(result)) 159 self.assertEquals({'test': 'animage.png', 160 'path': 'LayoutTests/platform/chromium-linux/animage.png', 161 'fallback': 'chromium-win', 162 'platform': 'chromium-linux-x86'}, 163 result[0]) 164 self.assertEquals({'test': 'foo-expected.txt', 165 'path': 'LayoutTests/platform/chromium-linux/foo-expected.txt', 166 'fallback': 'chromium-win', 167 'platform': 'chromium-linux-x86'}, 168 result[1]) 169 170 result = deduplicate_tests.deduplicate('*.txt') 171 self.assertEquals(2, len(MockExecutive.last_run_command)) 172 self.assertEquals(('git', 'ls-tree', '-r', 'HEAD', 'LayoutTests'), MockExecutive.last_run_command[-1]) 173 self.assertEquals(1, len(result)) 174 self.assertEquals({'test': 'foo-expected.txt', 175 'path': 'LayoutTests/platform/chromium-linux/foo-expected.txt', 176 'fallback': 'chromium-win', 177 'platform': 'chromium-linux-x86'}, 178 result[0]) 179 180 result = deduplicate_tests.deduplicate('*.png') 181 self.assertEquals(3, len(MockExecutive.last_run_command)) 182 self.assertEquals(('git', 'ls-tree', '-r', 'HEAD', 'LayoutTests'), MockExecutive.last_run_command[-1]) 183 self.assertEquals(1, len(result)) 184 self.assertEquals({'test': 'animage.png', 185 'path': 'LayoutTests/platform/chromium-linux/animage.png', 186 'fallback': 'chromium-win', 187 'platform': 'chromium-linux-x86'}, 188 result[0]) 189 190 def test_get_relative_test_path(self): 191 checkout_root = scm.find_checkout_root() 192 layout_test_dir = os.path.join(checkout_root, 'LayoutTests') 193 test_cases = ( 194 ('platform/mac/test.html', 195 ('platform/mac/test.html', layout_test_dir)), 196 ('LayoutTests/platform/mac/test.html', 197 ('platform/mac/test.html', checkout_root)), 198 (None, 199 ('platform/mac/test.html', os.path.join(checkout_root, 'Source', 'WebCore'))), 200 ('test.html', 201 ('platform/mac/test.html', os.path.join(layout_test_dir, 'platform/mac'))), 202 (None, 203 ('platform/mac/test.html', os.path.join(layout_test_dir, 'platform/win'))), 204 ) 205 for expected, inputs in test_cases: 206 self.assertEquals(expected, 207 deduplicate_tests.get_relative_test_path(*inputs)) 208 209if __name__ == '__main__': 210 unittest.main() 211