1 # Copyright (C) 2011 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 import unittest 30 31 from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer 32 from webkitpy.common.checkout.scm.scm_mock import MockSCM 33 from webkitpy.common.host_mock import MockHost 34 from webkitpy.common.webkit_finder import WebKitFinder 35 36 37 class ExcludingMockSCM(MockSCM): 38 def __init__(self, exclusion_list, filesystem=None, executive=None): 39 MockSCM.__init__(self, filesystem, executive) 40 self._exclusion_list = exclusion_list 41 42 def exists(self, path): 43 if path in self._exclusion_list: 44 return False 45 return MockSCM.exists(self, path) 46 47 def delete(self, path): 48 return self.delete_list([path]) 49 50 def delete_list(self, paths): 51 for path in paths: 52 if path in self._exclusion_list: 53 raise Exception("File is not SCM managed: " + path) 54 return MockSCM.delete_list(self, paths) 55 56 def move(self, origin, destination): 57 if origin in self._exclusion_list: 58 raise Exception("File is not SCM managed: " + origin) 59 return MockSCM.move(self, origin, destination) 60 61 62 class BaselineOptimizerTest(unittest.TestCase): 63 def test_move_baselines(self): 64 host = MockHost(scm=ExcludingMockSCM(['/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt'])) 65 host.filesystem.write_text_file('/mock-checkout/third_party/WebKit/LayoutTests/VirtualTestSuites', '[]') 66 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 'result A') 67 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt', 'result A') 68 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 'result B') 69 baseline_optimizer = BaselineOptimizer(host, host.port_factory.get(), host.port_factory.all_port_names(), skip_scm_commands=False) 70 baseline_optimizer._move_baselines('another/test-expected.txt', { 71 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win': 'aaa', 72 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac': 'aaa', 73 '/mock-checkout/third_party/WebKit/LayoutTests': 'bbb', 74 }, { 75 '/mock-checkout/third_party/WebKit/LayoutTests': 'aaa', 76 }) 77 self.assertEqual(host.filesystem.read_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt'), 'result A') 78 79 def test_move_baselines_skip_scm_commands(self): 80 host = MockHost(scm=ExcludingMockSCM(['/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt'])) 81 host.filesystem.write_text_file('/mock-checkout/third_party/WebKit/LayoutTests/VirtualTestSuites', '[]') 82 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 'result A') 83 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt', 'result A') 84 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 'result B') 85 baseline_optimizer = BaselineOptimizer(host, host.port_factory.get(), host.port_factory.all_port_names(), skip_scm_commands=True) 86 baseline_optimizer._move_baselines('another/test-expected.txt', { 87 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win': 'aaa', 88 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac': 'aaa', 89 '/mock-checkout/third_party/WebKit/LayoutTests': 'bbb', 90 }, { 91 '/mock-checkout/third_party/WebKit/LayoutTests/platform/linux': 'bbb', 92 '/mock-checkout/third_party/WebKit/LayoutTests': 'aaa', 93 }) 94 self.assertEqual(host.filesystem.read_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt'), 'result A') 95 96 self.assertEqual(baseline_optimizer._files_to_delete, [ 97 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 98 ]) 99 100 self.assertEqual(baseline_optimizer._files_to_add, [ 101 '/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 102 '/mock-checkout/third_party/WebKit/LayoutTests/platform/linux/another/test-expected.txt', 103 ]) 104 105 def _assertOptimization(self, results_by_directory, expected_new_results_by_directory, baseline_dirname='', expected_files_to_delete=None, host=None): 106 if not host: 107 host = MockHost() 108 fs = host.filesystem 109 webkit_base = WebKitFinder(fs).webkit_base() 110 baseline_name = 'mock-baseline-expected.txt' 111 fs.write_text_file(fs.join(webkit_base, 'LayoutTests', 'VirtualTestSuites'), 112 '[{"prefix": "gpu", "base": "fast/canvas", "args": ["--foo"]}]') 113 114 for dirname, contents in results_by_directory.items(): 115 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 116 fs.write_binary_file(path, contents) 117 118 baseline_optimizer = BaselineOptimizer(host, host.port_factory.get(), host.port_factory.all_port_names(), skip_scm_commands=expected_files_to_delete is not None) 119 self.assertTrue(baseline_optimizer.optimize(fs.join(baseline_dirname, baseline_name))) 120 121 for dirname, contents in expected_new_results_by_directory.items(): 122 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 123 if contents is None: 124 self.assertTrue(not fs.exists(path) or path in baseline_optimizer._files_to_delete) 125 else: 126 self.assertEqual(fs.read_binary_file(path), contents) 127 128 # Check that the files that were in the original set have been deleted where necessary. 129 for dirname in results_by_directory: 130 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 131 if not dirname in expected_new_results_by_directory: 132 self.assertTrue(not fs.exists(path) or path in baseline_optimizer._files_to_delete) 133 134 if expected_files_to_delete: 135 self.assertEqual(sorted(baseline_optimizer._files_to_delete), sorted(expected_files_to_delete)) 136 137 def test_linux_redundant_with_win(self): 138 self._assertOptimization({ 139 'platform/win': '1', 140 'platform/linux': '1', 141 }, { 142 'platform/win': '1', 143 }) 144 145 def test_covers_mac_win_linux(self): 146 self._assertOptimization({ 147 'platform/mac': '1', 148 'platform/win': '1', 149 'platform/linux': '1', 150 '': None, 151 }, { 152 '': '1', 153 }) 154 155 def test_overwrites_root(self): 156 self._assertOptimization({ 157 'platform/mac': '1', 158 'platform/win': '1', 159 'platform/linux': '1', 160 '': '2', 161 }, { 162 '': '1', 163 }) 164 165 def test_no_new_common_directory(self): 166 self._assertOptimization({ 167 'platform/mac': '1', 168 'platform/linux': '1', 169 '': '2', 170 }, { 171 'platform/mac': '1', 172 'platform/linux': '1', 173 '': '2', 174 }) 175 176 177 def test_local_optimization(self): 178 self._assertOptimization({ 179 'platform/mac': '1', 180 'platform/linux': '1', 181 'platform/linux-x86': '1', 182 }, { 183 'platform/mac': '1', 184 'platform/linux': '1', 185 }) 186 187 def test_local_optimization_skipping_a_port_in_the_middle(self): 188 self._assertOptimization({ 189 'platform/mac-snowleopard': '1', 190 'platform/win': '1', 191 'platform/linux-x86': '1', 192 }, { 193 'platform/mac-snowleopard': '1', 194 'platform/win': '1', 195 }) 196 197 def test_baseline_redundant_with_root(self): 198 self._assertOptimization({ 199 'platform/mac': '1', 200 'platform/win': '2', 201 '': '2', 202 }, { 203 'platform/mac': '1', 204 '': '2', 205 }) 206 207 def test_root_baseline_unused(self): 208 self._assertOptimization({ 209 'platform/mac': '1', 210 'platform/win': '2', 211 '': '3', 212 }, { 213 'platform/mac': '1', 214 'platform/win': '2', 215 }) 216 217 def test_root_baseline_unused_and_non_existant(self): 218 self._assertOptimization({ 219 'platform/mac': '1', 220 'platform/win': '2', 221 }, { 222 'platform/mac': '1', 223 'platform/win': '2', 224 }) 225 226 def test_virtual_root_redundant_with_actual_root(self): 227 self._assertOptimization({ 228 'virtual/gpu/fast/canvas': '2', 229 'fast/canvas': '2', 230 }, { 231 'virtual/gpu/fast/canvas': None, 232 'fast/canvas': '2', 233 }, baseline_dirname='virtual/gpu/fast/canvas') 234 235 def test_virtual_root_redundant_with_ancestors(self): 236 self._assertOptimization({ 237 'virtual/gpu/fast/canvas': '2', 238 'platform/mac/fast/canvas': '2', 239 'platform/win/fast/canvas': '2', 240 }, { 241 'virtual/gpu/fast/canvas': None, 242 'fast/canvas': '2', 243 }, baseline_dirname='virtual/gpu/fast/canvas') 244 245 def test_virtual_root_redundant_with_ancestors_skip_scm_commands(self): 246 self._assertOptimization({ 247 'virtual/gpu/fast/canvas': '2', 248 'platform/mac/fast/canvas': '2', 249 'platform/win/fast/canvas': '2', 250 }, { 251 'virtual/gpu/fast/canvas': None, 252 'fast/canvas': '2', 253 }, 254 baseline_dirname='virtual/gpu/fast/canvas', 255 expected_files_to_delete=[ 256 '/mock-checkout/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/mock-baseline-expected.txt', 257 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/mock-baseline-expected.txt', 258 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win/fast/canvas/mock-baseline-expected.txt', 259 ]) 260 261 def test_virtual_root_redundant_with_ancestors_skip_scm_commands_with_file_not_in_scm(self): 262 self._assertOptimization({ 263 'virtual/gpu/fast/canvas': '2', 264 'platform/mac/fast/canvas': '2', 265 'platform/win/fast/canvas': '2', 266 }, { 267 'virtual/gpu/fast/canvas': None, 268 'fast/canvas': '2', 269 }, 270 baseline_dirname='virtual/gpu/fast/canvas', 271 expected_files_to_delete=[ 272 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/mock-baseline-expected.txt', 273 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win/fast/canvas/mock-baseline-expected.txt', 274 ], 275 host=MockHost(scm=ExcludingMockSCM(['/mock-checkout/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/mock-baseline-expected.txt']))) 276 277 def test_virtual_root_not_redundant_with_ancestors(self): 278 self._assertOptimization({ 279 'virtual/gpu/fast/canvas': '2', 280 'platform/mac/fast/canvas': '1', 281 }, { 282 'virtual/gpu/fast/canvas': '2', 283 'platform/mac/fast/canvas': '1', 284 }, baseline_dirname='virtual/gpu/fast/canvas') 285