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 webkitpy.thirdparty.unittest2 as 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_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 'result A') 66 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt', 'result A') 67 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 'result B') 68 baseline_optimizer = BaselineOptimizer(host, host.port_factory.all_port_names(), skip_scm_commands=False) 69 baseline_optimizer._move_baselines('another/test-expected.txt', { 70 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win': 'aaa', 71 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac': 'aaa', 72 '/mock-checkout/third_party/WebKit/LayoutTests': 'bbb', 73 }, { 74 '/mock-checkout/third_party/WebKit/LayoutTests': 'aaa', 75 }) 76 self.assertEqual(host.filesystem.read_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt'), 'result A') 77 78 def test_move_baselines_skip_scm_commands(self): 79 host = MockHost(scm=ExcludingMockSCM(['/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt'])) 80 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 'result A') 81 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/another/test-expected.txt', 'result A') 82 host.filesystem.write_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 'result B') 83 baseline_optimizer = BaselineOptimizer(host, host.port_factory.all_port_names(), skip_scm_commands=True) 84 baseline_optimizer._move_baselines('another/test-expected.txt', { 85 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win': 'aaa', 86 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac': 'aaa', 87 '/mock-checkout/third_party/WebKit/LayoutTests': 'bbb', 88 }, { 89 '/mock-checkout/third_party/WebKit/LayoutTests/platform/linux': 'bbb', 90 '/mock-checkout/third_party/WebKit/LayoutTests': 'aaa', 91 }) 92 self.assertEqual(host.filesystem.read_binary_file('/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt'), 'result A') 93 94 self.assertEqual(baseline_optimizer._files_to_delete, [ 95 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win/another/test-expected.txt', 96 ]) 97 98 self.assertEqual(baseline_optimizer._files_to_add, [ 99 '/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt', 100 '/mock-checkout/third_party/WebKit/LayoutTests/platform/linux/another/test-expected.txt', 101 ]) 102 103 def _assertOptimization(self, results_by_directory, expected_new_results_by_directory, baseline_dirname='', expected_files_to_delete=None): 104 host = MockHost() 105 fs = host.filesystem 106 webkit_base = WebKitFinder(fs).webkit_base() 107 baseline_name = 'mock-baseline-expected.txt' 108 109 for dirname, contents in results_by_directory.items(): 110 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 111 fs.write_binary_file(path, contents) 112 113 baseline_optimizer = BaselineOptimizer(host, host.port_factory.all_port_names(), skip_scm_commands=expected_files_to_delete is not None) 114 self.assertTrue(baseline_optimizer.optimize(fs.join(baseline_dirname, baseline_name))) 115 116 for dirname, contents in expected_new_results_by_directory.items(): 117 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 118 if contents is None: 119 self.assertTrue(not fs.exists(path) or path in baseline_optimizer._files_to_delete) 120 else: 121 self.assertEqual(fs.read_binary_file(path), contents) 122 123 # Check that the files that were in the original set have been deleted where necessary. 124 for dirname in results_by_directory: 125 path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name) 126 if not dirname in expected_new_results_by_directory: 127 self.assertTrue(not fs.exists(path) or path in baseline_optimizer._files_to_delete) 128 129 if expected_files_to_delete: 130 self.assertEqual(baseline_optimizer._files_to_delete, expected_files_to_delete) 131 132 def test_linux_redundant_with_win(self): 133 self._assertOptimization({ 134 'platform/win': '1', 135 'platform/linux': '1', 136 }, { 137 'platform/win': '1', 138 }) 139 140 def test_covers_mac_win_linux(self): 141 self._assertOptimization({ 142 'platform/mac': '1', 143 'platform/win': '1', 144 'platform/linux': '1', 145 '': None, 146 }, { 147 '': '1', 148 }) 149 150 def test_overwrites_root(self): 151 self._assertOptimization({ 152 'platform/mac': '1', 153 'platform/win': '1', 154 'platform/linux': '1', 155 '': '2', 156 }, { 157 '': '1', 158 }) 159 160 def test_no_new_common_directory(self): 161 self._assertOptimization({ 162 'platform/mac': '1', 163 'platform/linux': '1', 164 '': '2', 165 }, { 166 'platform/mac': '1', 167 'platform/linux': '1', 168 '': '2', 169 }) 170 171 172 def test_local_optimization(self): 173 self._assertOptimization({ 174 'platform/mac': '1', 175 'platform/linux': '1', 176 'platform/linux-x86': '1', 177 }, { 178 'platform/mac': '1', 179 'platform/linux': '1', 180 }) 181 182 def test_local_optimization_skipping_a_port_in_the_middle(self): 183 self._assertOptimization({ 184 'platform/mac-snowleopard': '1', 185 'platform/win': '1', 186 'platform/linux-x86': '1', 187 }, { 188 'platform/mac-snowleopard': '1', 189 'platform/win': '1', 190 }) 191 192 def test_baseline_redundant_with_root(self): 193 self._assertOptimization({ 194 'platform/mac': '1', 195 'platform/win': '2', 196 '': '2', 197 }, { 198 'platform/mac': '1', 199 '': '2', 200 }) 201 202 def test_root_baseline_unused(self): 203 self._assertOptimization({ 204 'platform/mac': '1', 205 'platform/win': '2', 206 '': '3', 207 }, { 208 'platform/mac': '1', 209 'platform/win': '2', 210 }) 211 212 def test_root_baseline_unused_and_non_existant(self): 213 self._assertOptimization({ 214 'platform/mac': '1', 215 'platform/win': '2', 216 }, { 217 'platform/mac': '1', 218 'platform/win': '2', 219 }) 220 221 def test_virtual_root_redundant_with_actual_root(self): 222 self._assertOptimization({ 223 'virtual/softwarecompositing': '2', 224 'compositing': '2', 225 }, { 226 'virtual/softwarecompositing': None, 227 'compositing': '2', 228 }, baseline_dirname='virtual/softwarecompositing') 229 230 def test_virtual_root_redundant_with_ancestors(self): 231 self._assertOptimization({ 232 'virtual/softwarecompositing': '2', 233 'platform/mac/compositing': '2', 234 'platform/win/compositing': '2', 235 }, { 236 'virtual/softwarecompositing': None, 237 'compositing': '2', 238 }, baseline_dirname='virtual/softwarecompositing') 239 240 def test_virtual_root_redundant_with_ancestors_skip_scm_commands(self): 241 self._assertOptimization({ 242 'virtual/softwarecompositing': '2', 243 'platform/mac/compositing': '2', 244 'platform/win/compositing': '2', 245 }, { 246 'virtual/softwarecompositing': None, 247 'compositing': '2', 248 }, 249 baseline_dirname='virtual/softwarecompositing', 250 expected_files_to_delete=[ 251 '/mock-checkout/third_party/WebKit/LayoutTests/virtual/softwarecompositing/mock-baseline-expected.txt', 252 '/mock-checkout/third_party/WebKit/LayoutTests/platform/mac/compositing/mock-baseline-expected.txt', 253 '/mock-checkout/third_party/WebKit/LayoutTests/platform/win/compositing/mock-baseline-expected.txt', 254 ]) 255 256 def test_virtual_root_not_redundant_with_ancestors(self): 257 self._assertOptimization({ 258 'virtual/softwarecompositing': '2', 259 'platform/mac/compositing': '1', 260 }, { 261 'virtual/softwarecompositing': '2', 262 'platform/mac/compositing': '1', 263 }, baseline_dirname='virtual/softwarecompositing') 264