1 # Copyright (C) 2010 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
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
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.
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.
34 from webkitpy.common.system import logtesting
35 from webkitpy.common.system.executive_mock import MockExecutive, MockExecutive2
36 from webkitpy.common.system.filesystem_mock import MockFileSystem
37 from webkitpy.common.host_mock import MockHost
38 from webkitpy.thirdparty.mock import Mock
39 from webkitpy.tool.mocktool import MockOptions
46 from webkitpy.layout_tests.models.test_configuration import TestConfiguration
47 from webkitpy.layout_tests.port import port_testcase
48 from webkitpy.layout_tests.port.driver import DriverInput
51 class ChromiumDriverTest(unittest.TestCase):
53 mock_port = Mock() # FIXME: This should use a tighter mock.
54 self.driver = chromium.ChromiumDriver(mock_port, worker_number=0, pixel_tests=True)
56 def test_test_shell_command(self):
57 expected_command = "test.html 2 checksum\n"
58 self.assertEqual(self.driver._test_shell_command("test.html", 2, "checksum"), expected_command)
60 def _assert_write_command_and_read_line(self, input=None, expected_line=None, expected_stdin=None, expected_crash=False):
61 if not expected_stdin:
63 expected_stdin = input
65 # We reset stdin, so we should expect stdin.getValue = ""
67 self.driver._proc.stdin = StringIO.StringIO()
68 line, did_crash = self.driver._write_command_and_read_line(input)
69 self.assertEqual(self.driver._proc.stdin.getvalue(), expected_stdin)
70 self.assertEqual(line, expected_line)
71 self.assertEqual(did_crash, expected_crash)
73 def test_write_command_and_read_line(self):
74 self.driver._proc = Mock() # FIXME: This should use a tighter mock.
75 # Set up to read 3 lines before we get an IOError
76 self.driver._proc.stdout = StringIO.StringIO("first\nsecond\nthird\n")
78 unicode_input = u"I \u2661 Unicode"
79 utf8_input = unicode_input.encode("utf-8")
80 # Test unicode input conversion to utf-8
81 self._assert_write_command_and_read_line(input=unicode_input, expected_stdin=utf8_input, expected_line="first\n")
83 self._assert_write_command_and_read_line(input="foo", expected_line="second\n")
85 self._assert_write_command_and_read_line(expected_line="third\n")
86 # Test reading from a closed/empty stream.
87 # reading from a StringIO does not raise IOError like a real file would, so raise IOError manually.
90 self.driver._proc.stdout.readline = mock_readline
91 self._assert_write_command_and_read_line(expected_crash=True)
93 def test_crashed_process_name(self):
94 self.driver._proc = Mock()
96 # Simulate a crash by having stdout close unexpectedly.
99 self.driver._proc.stdout.readline = mock_readline
101 self.driver._port.test_to_uri = lambda test: 'mocktesturi'
102 driver_output = self.driver.run_test(DriverInput(test_name='some/test.html', timeout=1, image_hash=None, is_reftest=False))
103 self.assertEqual(self.driver._port.driver_name(), driver_output.crashed_process_name)
107 self.wait_called = False
108 self.driver._proc = Mock() # FIXME: This should use a tighter mock.
109 self.driver._proc.pid = 1
110 self.driver._proc.stdin = StringIO.StringIO()
111 self.driver._proc.stdout = StringIO.StringIO()
112 self.driver._proc.stderr = StringIO.StringIO()
113 self.driver._proc.poll = lambda: None
116 self.assertTrue(self.pid is not None)
117 self.wait_called = True
119 self.driver._proc.wait = fake_wait
121 class FakeExecutive(object):
122 def kill_process(other, pid):
124 self.driver._proc.poll = lambda: 2
126 self.driver._port._executive = FakeExecutive()
127 # Override the kill timeout (ms) so the test runs faster.
128 self.driver._port.get_option = lambda name: 1
130 self.assertTrue(self.wait_called)
131 self.assertEquals(self.pid, 1)
133 def test_two_drivers(self):
136 class MockDriver(chromium.ChromiumDriver):
138 chromium.ChromiumDriver.__init__(self, mock_port, worker_number=0, pixel_tests=False)
143 # get_option is used to get the timeout (ms) for a process before we kill it.
144 mock_port.get_option = lambda name: 60 * 1000
145 driver1 = MockDriver()
147 driver2 = MockDriver()
149 # It's possible for driver1 to timeout when stopping if it's sharing stdin with driver2.
150 start_time = time.time()
153 self.assertTrue(time.time() - start_time < 20)
156 class ChromiumPortTest(port_testcase.PortTestCase):
157 port_maker = chromium.ChromiumPort
159 def test_all_test_configurations(self):
160 """Validate the complete set of configurations this port knows about."""
161 port = chromium.ChromiumPort(MockHost())
162 self.assertEquals(set(port.all_test_configurations()), set([
163 TestConfiguration('leopard', 'x86', 'debug', 'cpu'),
164 TestConfiguration('leopard', 'x86', 'debug', 'gpu'),
165 TestConfiguration('leopard', 'x86', 'debug', 'cpu-cg'),
166 TestConfiguration('leopard', 'x86', 'debug', 'gpu-cg'),
167 TestConfiguration('leopard', 'x86', 'release', 'cpu'),
168 TestConfiguration('leopard', 'x86', 'release', 'gpu'),
169 TestConfiguration('leopard', 'x86', 'release', 'cpu-cg'),
170 TestConfiguration('leopard', 'x86', 'release', 'gpu-cg'),
171 TestConfiguration('snowleopard', 'x86', 'debug', 'cpu'),
172 TestConfiguration('snowleopard', 'x86', 'debug', 'gpu'),
173 TestConfiguration('snowleopard', 'x86', 'debug', 'cpu-cg'),
174 TestConfiguration('snowleopard', 'x86', 'debug', 'gpu-cg'),
175 TestConfiguration('snowleopard', 'x86', 'release', 'cpu'),
176 TestConfiguration('snowleopard', 'x86', 'release', 'gpu'),
177 TestConfiguration('snowleopard', 'x86', 'release', 'cpu-cg'),
178 TestConfiguration('snowleopard', 'x86', 'release', 'gpu-cg'),
179 TestConfiguration('lion', 'x86', 'debug', 'cpu'),
180 TestConfiguration('lion', 'x86', 'debug', 'gpu'),
181 TestConfiguration('lion', 'x86', 'debug', 'cpu-cg'),
182 TestConfiguration('lion', 'x86', 'debug', 'gpu-cg'),
183 TestConfiguration('lion', 'x86', 'release', 'cpu'),
184 TestConfiguration('lion', 'x86', 'release', 'gpu'),
185 TestConfiguration('lion', 'x86', 'release', 'cpu-cg'),
186 TestConfiguration('lion', 'x86', 'release', 'gpu-cg'),
187 TestConfiguration('xp', 'x86', 'debug', 'cpu'),
188 TestConfiguration('xp', 'x86', 'debug', 'gpu'),
189 TestConfiguration('xp', 'x86', 'release', 'cpu'),
190 TestConfiguration('xp', 'x86', 'release', 'gpu'),
191 TestConfiguration('vista', 'x86', 'debug', 'cpu'),
192 TestConfiguration('vista', 'x86', 'debug', 'gpu'),
193 TestConfiguration('vista', 'x86', 'release', 'cpu'),
194 TestConfiguration('vista', 'x86', 'release', 'gpu'),
195 TestConfiguration('win7', 'x86', 'debug', 'cpu'),
196 TestConfiguration('win7', 'x86', 'debug', 'gpu'),
197 TestConfiguration('win7', 'x86', 'release', 'cpu'),
198 TestConfiguration('win7', 'x86', 'release', 'gpu'),
199 TestConfiguration('lucid', 'x86', 'debug', 'cpu'),
200 TestConfiguration('lucid', 'x86', 'debug', 'gpu'),
201 TestConfiguration('lucid', 'x86', 'release', 'cpu'),
202 TestConfiguration('lucid', 'x86', 'release', 'gpu'),
203 TestConfiguration('lucid', 'x86_64', 'debug', 'cpu'),
204 TestConfiguration('lucid', 'x86_64', 'debug', 'gpu'),
205 TestConfiguration('lucid', 'x86_64', 'release', 'cpu'),
206 TestConfiguration('lucid', 'x86_64', 'release', 'gpu'),
209 def test_driver_cmd_line(self):
210 # Override this test since ChromiumPort doesn't implement driver_cmd_line().
213 def test_check_build(self):
214 # Override this test since ChromiumPort doesn't implement _path_to_driver().
217 def test_check_wdiff(self):
218 # Override this test since ChromiumPort doesn't implement _path_to_driver().
221 class TestMacPort(chromium_mac.ChromiumMacPort):
222 def __init__(self, options=None):
223 options = options or MockOptions()
224 chromium_mac.ChromiumMacPort.__init__(self, MockHost(), options=options)
226 def default_configuration(self):
227 self.default_configuration_called = True
230 class TestLinuxPort(chromium_linux.ChromiumLinuxPort):
231 def __init__(self, options=None):
232 options = options or MockOptions()
233 chromium_linux.ChromiumLinuxPort.__init__(self, MockHost(), options=options)
235 def default_configuration(self):
236 self.default_configuration_called = True
239 class TestWinPort(chromium_win.ChromiumWinPort):
240 def __init__(self, options=None):
241 options = options or MockOptions()
242 chromium_win.ChromiumWinPort.__init__(self, MockHost(), options=options)
244 def default_configuration(self):
245 self.default_configuration_called = True
248 def test_path_to_image_diff(self):
249 # FIXME: These don't need to use endswith now that the port uses a MockFileSystem.
250 self.assertTrue(ChromiumPortTest.TestLinuxPort()._path_to_image_diff().endswith('/out/default/ImageDiff'))
251 self.assertTrue(ChromiumPortTest.TestMacPort()._path_to_image_diff().endswith('/xcodebuild/default/ImageDiff'))
252 self.assertTrue(ChromiumPortTest.TestWinPort()._path_to_image_diff().endswith('/default/ImageDiff.exe'))
254 def test_skipped_layout_tests(self):
255 mock_options = MockOptions()
256 mock_options.configuration = 'release'
257 port = ChromiumPortTest.TestLinuxPort(options=mock_options)
259 fake_test = 'fast/js/not-good.js'
261 port.test_expectations = lambda: """BUG_TEST SKIP : fast/js/not-good.js = TEXT
262 LINUX WIN : fast/js/very-good.js = TIMEOUT PASS"""
263 port.test_expectations_overrides = lambda: ''
264 port.tests = lambda paths: set()
265 port.test_exists = lambda test: True
267 skipped_tests = port.skipped_layout_tests(extra_test_files=[fake_test, ])
268 self.assertTrue("fast/js/not-good.js" in skipped_tests)
270 def test_default_configuration(self):
271 mock_options = MockOptions()
272 port = ChromiumPortTest.TestLinuxPort(options=mock_options)
273 self.assertEquals(mock_options.configuration, 'default')
274 self.assertTrue(port.default_configuration_called)
276 mock_options = MockOptions(configuration=None)
277 port = ChromiumPortTest.TestLinuxPort(mock_options)
278 self.assertEquals(mock_options.configuration, 'default')
279 self.assertTrue(port.default_configuration_called)
281 def test_diff_image(self):
282 class TestPort(ChromiumPortTest.TestLinuxPort):
283 def _path_to_image_diff(self):
284 return "/path/to/image_diff"
286 port = ChromiumPortTest.TestLinuxPort()
287 mock_image_diff = "MOCK Image Diff"
289 def mock_run_command(args):
290 port._filesystem.write_binary_file(args[4], mock_image_diff)
293 # Images are different.
294 port._executive = MockExecutive2(run_command_fn=mock_run_command)
295 self.assertEquals(mock_image_diff, port.diff_image("EXPECTED", "ACTUAL")[0])
297 # Images are the same.
298 port._executive = MockExecutive2(exit_code=0)
299 self.assertEquals(None, port.diff_image("EXPECTED", "ACTUAL")[0])
301 # There was some error running image_diff.
302 port._executive = MockExecutive2(exit_code=2)
303 exception_raised = False
305 port.diff_image("EXPECTED", "ACTUAL")
306 except ValueError, e:
307 exception_raised = True
308 self.assertFalse(exception_raised)
310 def test_overrides_and_builder_names(self):
311 port = self.make_port()
313 filesystem = MockFileSystem()
314 port._filesystem = filesystem
315 port.path_from_chromium_base = lambda *comps: '/' + '/'.join(comps)
317 overrides_path = port.path_from_chromium_base('webkit', 'tools', 'layout_tests', 'test_expectations.txt')
319 filesystem.files[overrides_path] = OVERRIDES
321 port._options.builder_name = 'DUMMY_BUILDER_NAME'
322 self.assertEquals(port.test_expectations_overrides(), OVERRIDES)
324 port._options.builder_name = 'builder (deps)'
325 self.assertEquals(port.test_expectations_overrides(), OVERRIDES)
327 port._options.builder_name = 'builder'
328 self.assertEquals(port.test_expectations_overrides(), None)
331 class ChromiumPortLoggingTest(logtesting.LoggingTestCase):
332 def test_check_sys_deps(self):
333 port = ChromiumPortTest.TestLinuxPort()
336 port._executive = MockExecutive2(exit_code=0)
337 self.assertTrue(port.check_sys_deps(needs_http=False))
340 port._executive = MockExecutive2(exit_code=1,
341 output='testing output failure')
342 self.assertFalse(port.check_sys_deps(needs_http=False))
344 'ERROR: System dependencies check failed.\n',
345 'ERROR: To override, invoke with --nocheck-sys-deps\n',
347 'ERROR: testing output failure\n'])
350 if __name__ == '__main__':