port_testcase.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. # Copyright (C) 2010 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. """Unit testing base class for Port implementations."""
  29. import errno
  30. import logging
  31. import os
  32. import socket
  33. import sys
  34. import time
  35. import unittest2 as unittest
  36. from webkitpy.common.system.executive_mock import MockExecutive
  37. from webkitpy.common.system.filesystem_mock import MockFileSystem
  38. from webkitpy.common.system.outputcapture import OutputCapture
  39. from webkitpy.common.system.systemhost_mock import MockSystemHost
  40. from webkitpy.port.base import Port
  41. from webkitpy.port.server_process_mock import MockServerProcess
  42. from webkitpy.layout_tests.servers import http_server_base
  43. from webkitpy.tool.mocktool import MockOptions
  44. # FIXME: get rid of this fixture
  45. class TestWebKitPort(Port):
  46. port_name = "testwebkitport"
  47. def __init__(self, port_name=None, symbols_string=None,
  48. expectations_file=None, skips_file=None, host=None, config=None,
  49. **kwargs):
  50. port_name = port_name or TestWebKitPort.port_name
  51. self.symbols_string = symbols_string # Passing "" disables all staticly-detectable features.
  52. host = host or MockSystemHost()
  53. super(TestWebKitPort, self).__init__(host, port_name=port_name, **kwargs)
  54. def all_test_configurations(self):
  55. return [self.test_configuration()]
  56. def _symbols_string(self):
  57. return self.symbols_string
  58. def _tests_for_other_platforms(self):
  59. return ["media", ]
  60. def _tests_for_disabled_features(self):
  61. return ["accessibility", ]
  62. class PortTestCase(unittest.TestCase):
  63. """Tests that all Port implementations must pass."""
  64. HTTP_PORTS = (8000, 8080, 8443)
  65. WEBSOCKET_PORTS = (8880,)
  66. # Subclasses override this to point to their Port subclass.
  67. os_name = None
  68. os_version = None
  69. port_maker = TestWebKitPort
  70. port_name = None
  71. def make_port(self, host=None, port_name=None, options=None, os_name=None, os_version=None, **kwargs):
  72. host = host or MockSystemHost(os_name=(os_name or self.os_name), os_version=(os_version or self.os_version))
  73. options = options or MockOptions(configuration='Release')
  74. port_name = port_name or self.port_name
  75. port_name = self.port_maker.determine_full_port_name(host, options, port_name)
  76. port = self.port_maker(host, port_name, options=options, **kwargs)
  77. port._config.build_directory = lambda configuration: '/mock-build'
  78. return port
  79. def test_default_max_locked_shards(self):
  80. port = self.make_port()
  81. port.default_child_processes = lambda: 16
  82. self.assertEqual(port.default_max_locked_shards(), 1)
  83. port.default_child_processes = lambda: 2
  84. self.assertEqual(port.default_max_locked_shards(), 1)
  85. def test_default_timeout_ms(self):
  86. self.assertEqual(self.make_port(options=MockOptions(configuration='Release')).default_timeout_ms(), 35000)
  87. self.assertEqual(self.make_port(options=MockOptions(configuration='Debug')).default_timeout_ms(), 35000)
  88. def test_default_pixel_tests(self):
  89. self.assertEqual(self.make_port().default_pixel_tests(), False)
  90. def test_driver_cmd_line(self):
  91. port = self.make_port()
  92. self.assertTrue(len(port.driver_cmd_line()))
  93. options = MockOptions(additional_drt_flag=['--foo=bar', '--foo=baz'])
  94. port = self.make_port(options=options)
  95. cmd_line = port.driver_cmd_line()
  96. self.assertTrue('--foo=bar' in cmd_line)
  97. self.assertTrue('--foo=baz' in cmd_line)
  98. def assert_servers_are_down(self, host, ports):
  99. for port in ports:
  100. try:
  101. test_socket = socket.socket()
  102. test_socket.connect((host, port))
  103. self.fail()
  104. except IOError, e:
  105. self.assertTrue(e.errno in (errno.ECONNREFUSED, errno.ECONNRESET))
  106. finally:
  107. test_socket.close()
  108. def assert_servers_are_up(self, host, ports):
  109. for port in ports:
  110. try:
  111. test_socket = socket.socket()
  112. test_socket.connect((host, port))
  113. except IOError, e:
  114. self.fail('failed to connect to %s:%d' % (host, port))
  115. finally:
  116. test_socket.close()
  117. def integration_test_http_lock(self):
  118. port = self.make_port()
  119. # Only checking that no exception is raised.
  120. port.acquire_http_lock()
  121. port.release_http_lock()
  122. def integration_test_check_sys_deps(self):
  123. port = self.make_port()
  124. # Only checking that no exception is raised.
  125. port.check_sys_deps(True)
  126. def integration_test_helper(self):
  127. port = self.make_port()
  128. # Only checking that no exception is raised.
  129. port.start_helper()
  130. port.stop_helper()
  131. def integration_test_http_server__normal(self):
  132. port = self.make_port()
  133. self.assert_servers_are_down('localhost', self.HTTP_PORTS)
  134. port.start_http_server()
  135. self.assert_servers_are_up('localhost', self.HTTP_PORTS)
  136. port.stop_http_server()
  137. self.assert_servers_are_down('localhost', self.HTTP_PORTS)
  138. def integration_test_http_server__fails(self):
  139. port = self.make_port()
  140. # Test that if a port isn't available, the call fails.
  141. for port_number in self.HTTP_PORTS:
  142. test_socket = socket.socket()
  143. try:
  144. try:
  145. test_socket.bind(('localhost', port_number))
  146. except socket.error, e:
  147. if e.errno in (errno.EADDRINUSE, errno.EALREADY):
  148. self.fail('could not bind to port %d' % port_number)
  149. raise
  150. try:
  151. port.start_http_server()
  152. self.fail('should not have been able to start the server while bound to %d' % port_number)
  153. except http_server_base.ServerError, e:
  154. pass
  155. finally:
  156. port.stop_http_server()
  157. test_socket.close()
  158. # Test that calling start() twice fails.
  159. try:
  160. port.start_http_server()
  161. self.assertRaises(AssertionError, port.start_http_server)
  162. finally:
  163. port.stop_http_server()
  164. def integration_test_http_server__two_servers(self):
  165. # Test that calling start() on two different ports causes the
  166. # first port to be treated as stale and killed.
  167. port = self.make_port()
  168. # Test that if a port isn't available, the call fails.
  169. port.start_http_server()
  170. new_port = self.make_port()
  171. try:
  172. new_port.start_http_server()
  173. # Check that the first server was killed.
  174. self.assertFalse(port._executive.check_running_pid(port._http_server._pid))
  175. # Check that there is something running.
  176. self.assert_servers_are_up('localhost', self.HTTP_PORTS)
  177. # Test that calling stop() on a killed server is harmless.
  178. port.stop_http_server()
  179. finally:
  180. port.stop_http_server()
  181. new_port.stop_http_server()
  182. # Test that calling stop() twice is harmless.
  183. new_port.stop_http_server()
  184. def integration_test_image_diff(self):
  185. port = self.make_port()
  186. # FIXME: This test will never run since we are using a MockFilesystem for these tests!?!?
  187. if not port.check_image_diff():
  188. # The port hasn't been built - don't run the tests.
  189. return
  190. dir = port.layout_tests_dir()
  191. file1 = port._filesystem.join(dir, 'fast', 'css', 'button_center.png')
  192. contents1 = port._filesystem.read_binary_file(file1)
  193. file2 = port._filesystem.join(dir, 'fast', 'css',
  194. 'remove-shorthand-expected.png')
  195. contents2 = port._filesystem.read_binary_file(file2)
  196. tmpfd, tmpfile = port._filesystem.open_binary_tempfile('')
  197. tmpfd.close()
  198. self.assertFalse(port.diff_image(contents1, contents1)[0])
  199. self.assertTrue(port.diff_image(contents1, contents2)[0])
  200. self.assertTrue(port.diff_image(contents1, contents2, tmpfile)[0])
  201. port._filesystem.remove(tmpfile)
  202. def test_diff_image__missing_both(self):
  203. port = self.make_port()
  204. self.assertFalse(port.diff_image(None, None)[0])
  205. self.assertFalse(port.diff_image(None, '')[0])
  206. self.assertFalse(port.diff_image('', None)[0])
  207. self.assertFalse(port.diff_image('', '')[0])
  208. def test_diff_image__missing_actual(self):
  209. port = self.make_port()
  210. self.assertTrue(port.diff_image(None, 'foo')[0])
  211. self.assertTrue(port.diff_image('', 'foo')[0])
  212. def test_diff_image__missing_expected(self):
  213. port = self.make_port()
  214. self.assertTrue(port.diff_image('foo', None)[0])
  215. self.assertTrue(port.diff_image('foo', '')[0])
  216. def test_diff_image(self):
  217. port = self.make_port()
  218. self.proc = None
  219. def make_proc(port, nm, cmd, env):
  220. self.proc = MockServerProcess(port, nm, cmd, env, lines=['diff: 100% failed\n', 'diff: 100% failed\n'])
  221. return self.proc
  222. port._server_process_constructor = make_proc
  223. port.setup_test_run()
  224. self.assertEqual(port.diff_image('foo', 'bar'), ('', 100.0, None))
  225. self.assertEqual(self.proc.cmd[1:3], ["--tolerance", "0.1"])
  226. self.assertEqual(port.diff_image('foo', 'bar', None), ('', 100.0, None))
  227. self.assertEqual(self.proc.cmd[1:3], ["--tolerance", "0.1"])
  228. self.assertEqual(port.diff_image('foo', 'bar', 0), ('', 100.0, None))
  229. self.assertEqual(self.proc.cmd[1:3], ["--tolerance", "0"])
  230. port.clean_up_test_run()
  231. self.assertTrue(self.proc.stopped)
  232. self.assertEqual(port._image_differ, None)
  233. def test_diff_image_crashed(self):
  234. port = self.make_port()
  235. self.proc = None
  236. def make_proc(port, nm, cmd, env):
  237. self.proc = MockServerProcess(port, nm, cmd, env, crashed=True)
  238. return self.proc
  239. port._server_process_constructor = make_proc
  240. port.setup_test_run()
  241. self.assertEqual(port.diff_image('foo', 'bar'), ('', 0, 'ImageDiff crashed\n'))
  242. port.clean_up_test_run()
  243. def test_check_wdiff(self):
  244. port = self.make_port()
  245. port.check_wdiff()
  246. def integration_test_websocket_server__normal(self):
  247. port = self.make_port()
  248. self.assert_servers_are_down('localhost', self.WEBSOCKET_PORTS)
  249. port.start_websocket_server()
  250. self.assert_servers_are_up('localhost', self.WEBSOCKET_PORTS)
  251. port.stop_websocket_server()
  252. self.assert_servers_are_down('localhost', self.WEBSOCKET_PORTS)
  253. def integration_test_websocket_server__fails(self):
  254. port = self.make_port()
  255. # Test that start() fails if a port isn't available.
  256. for port_number in self.WEBSOCKET_PORTS:
  257. test_socket = socket.socket()
  258. try:
  259. test_socket.bind(('localhost', port_number))
  260. try:
  261. port.start_websocket_server()
  262. self.fail('should not have been able to start the server while bound to %d' % port_number)
  263. except http_server_base.ServerError, e:
  264. pass
  265. finally:
  266. port.stop_websocket_server()
  267. test_socket.close()
  268. # Test that calling start() twice fails.
  269. try:
  270. port.start_websocket_server()
  271. self.assertRaises(AssertionError, port.start_websocket_server)
  272. finally:
  273. port.stop_websocket_server()
  274. def integration_test_websocket_server__two_servers(self):
  275. port = self.make_port()
  276. # Test that calling start() on two different ports causes the
  277. # first port to be treated as stale and killed.
  278. port.start_websocket_server()
  279. new_port = self.make_port()
  280. try:
  281. new_port.start_websocket_server()
  282. # Check that the first server was killed.
  283. self.assertFalse(port._executive.check_running_pid(port._websocket_server._pid))
  284. # Check that there is something running.
  285. self.assert_servers_are_up('localhost', self.WEBSOCKET_PORTS)
  286. # Test that calling stop() on a killed server is harmless.
  287. port.stop_websocket_server()
  288. finally:
  289. port.stop_websocket_server()
  290. new_port.stop_websocket_server()
  291. # Test that calling stop() twice is harmless.
  292. new_port.stop_websocket_server()
  293. def test_test_configuration(self):
  294. port = self.make_port()
  295. self.assertTrue(port.test_configuration())
  296. def test_all_test_configurations(self):
  297. port = self.make_port()
  298. self.assertTrue(len(port.all_test_configurations()) > 0)
  299. self.assertTrue(port.test_configuration() in port.all_test_configurations(), "%s not in %s" % (port.test_configuration(), port.all_test_configurations()))
  300. def integration_test_http_server__loop(self):
  301. port = self.make_port()
  302. i = 0
  303. while i < 10:
  304. self.assert_servers_are_down('localhost', self.HTTP_PORTS)
  305. port.start_http_server()
  306. # We sleep in between alternating runs to ensure that this
  307. # test handles both back-to-back starts and stops and
  308. # starts and stops separated by a delay.
  309. if i % 2:
  310. time.sleep(0.1)
  311. self.assert_servers_are_up('localhost', self.HTTP_PORTS)
  312. port.stop_http_server()
  313. if i % 2:
  314. time.sleep(0.1)
  315. i += 1
  316. def test_get_crash_log(self):
  317. port = self.make_port()
  318. self.assertEqual(port._get_crash_log(None, None, None, None, newer_than=None),
  319. (None,
  320. 'crash log for <unknown process name> (pid <unknown>):\n'
  321. 'STDOUT: <empty>\n'
  322. 'STDERR: <empty>\n'))
  323. self.assertEqual(port._get_crash_log('foo', 1234, 'out bar\nout baz', 'err bar\nerr baz\n', newer_than=None),
  324. ('err bar\nerr baz\n',
  325. 'crash log for foo (pid 1234):\n'
  326. 'STDOUT: out bar\n'
  327. 'STDOUT: out baz\n'
  328. 'STDERR: err bar\n'
  329. 'STDERR: err baz\n'))
  330. self.assertEqual(port._get_crash_log('foo', 1234, 'foo\xa6bar', 'foo\xa6bar', newer_than=None),
  331. ('foo\xa6bar',
  332. u'crash log for foo (pid 1234):\n'
  333. u'STDOUT: foo\ufffdbar\n'
  334. u'STDERR: foo\ufffdbar\n'))
  335. self.assertEqual(port._get_crash_log('foo', 1234, 'foo\xa6bar', 'foo\xa6bar', newer_than=1.0),
  336. ('foo\xa6bar',
  337. u'crash log for foo (pid 1234):\n'
  338. u'STDOUT: foo\ufffdbar\n'
  339. u'STDERR: foo\ufffdbar\n'))
  340. def assert_build_path(self, options, dirs, expected_path):
  341. port = self.make_port(options=options)
  342. for directory in dirs:
  343. port.host.filesystem.maybe_make_directory(directory)
  344. self.assertEqual(port._build_path(), expected_path)
  345. def test_expectations_ordering(self):
  346. port = self.make_port()
  347. for path in port.expectations_files():
  348. port._filesystem.write_text_file(path, '')
  349. ordered_dict = port.expectations_dict()
  350. self.assertEqual(port.path_to_generic_test_expectations_file(), ordered_dict.keys()[0])
  351. self.assertEqual(port.path_to_test_expectations_file(), ordered_dict.keys()[1])
  352. options = MockOptions(additional_expectations=['/tmp/foo', '/tmp/bar'])
  353. port = self.make_port(options=options)
  354. for path in port.expectations_files():
  355. port._filesystem.write_text_file(path, '')
  356. port._filesystem.write_text_file('/tmp/foo', 'foo')
  357. port._filesystem.write_text_file('/tmp/bar', 'bar')
  358. ordered_dict = port.expectations_dict()
  359. self.assertEqual(ordered_dict.keys()[-2:], options.additional_expectations) # pylint: disable=E1101
  360. self.assertEqual(ordered_dict.values()[-2:], ['foo', 'bar'])
  361. def test_path_to_test_expectations_file(self):
  362. port = TestWebKitPort()
  363. port._options = MockOptions(webkit_test_runner=False)
  364. self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations')
  365. port = TestWebKitPort()
  366. port._options = MockOptions(webkit_test_runner=True)
  367. self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations')
  368. port = TestWebKitPort()
  369. port.host.filesystem.files['/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations'] = 'some content'
  370. port._options = MockOptions(webkit_test_runner=False)
  371. self.assertEqual(port.path_to_test_expectations_file(), '/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations')
  372. def test_skipped_directories_for_features(self):
  373. supported_features = ["Accelerated Compositing", "Foo Feature"]
  374. expected_directories = set(["animations/3d", "transforms/3d"])
  375. port = TestWebKitPort(supported_features=supported_features)
  376. port._runtime_feature_list = lambda: supported_features
  377. result_directories = set(port._skipped_tests_for_unsupported_features(test_list=["animations/3d/foo.html"]))
  378. self.assertEqual(result_directories, expected_directories)
  379. def test_skipped_directories_for_features_no_matching_tests_in_test_list(self):
  380. supported_features = ["Accelerated Compositing", "Foo Feature"]
  381. expected_directories = set([])
  382. result_directories = set(TestWebKitPort(supported_features=supported_features)._skipped_tests_for_unsupported_features(test_list=['foo.html']))
  383. self.assertEqual(result_directories, expected_directories)
  384. def test_skipped_tests_for_unsupported_features_empty_test_list(self):
  385. supported_features = ["Accelerated Compositing", "Foo Feature"]
  386. expected_directories = set([])
  387. result_directories = set(TestWebKitPort(supported_features=supported_features)._skipped_tests_for_unsupported_features(test_list=None))
  388. self.assertEqual(result_directories, expected_directories)
  389. def test_skipped_layout_tests(self):
  390. self.assertEqual(TestWebKitPort().skipped_layout_tests(test_list=[]), set(['media']))
  391. def test_expectations_files(self):
  392. port = TestWebKitPort()
  393. def platform_dirs(port):
  394. return [port.host.filesystem.basename(port.host.filesystem.dirname(f)) for f in port.expectations_files()]
  395. self.assertEqual(platform_dirs(port), ['LayoutTests', 'testwebkitport'])
  396. port = TestWebKitPort(port_name="testwebkitport-version")
  397. self.assertEqual(platform_dirs(port), ['LayoutTests', 'testwebkitport', 'testwebkitport-version'])
  398. port = TestWebKitPort(port_name="testwebkitport-version-wk2")
  399. self.assertEqual(platform_dirs(port), ['LayoutTests', 'testwebkitport', 'testwebkitport-version', 'wk2', 'testwebkitport-wk2'])
  400. port = TestWebKitPort(port_name="testwebkitport-version",
  401. options=MockOptions(additional_platform_directory=["internal-testwebkitport"]))
  402. self.assertEqual(platform_dirs(port), ['LayoutTests', 'testwebkitport', 'testwebkitport-version', 'internal-testwebkitport'])
  403. def test_root_option(self):
  404. port = TestWebKitPort()
  405. port._options = MockOptions(root='/foo')
  406. self.assertEqual(port._path_to_driver(), "/foo/DumpRenderTree")
  407. def test_test_expectations(self):
  408. # Check that we read the expectations file
  409. host = MockSystemHost()
  410. host.filesystem.write_text_file('/mock-checkout/LayoutTests/platform/testwebkitport/TestExpectations',
  411. 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = FAIL\n')
  412. port = TestWebKitPort(host=host)
  413. self.assertEqual(''.join(port.expectations_dict().values()), 'BUG_TESTEXPECTATIONS SKIP : fast/html/article-element.html = FAIL\n')
  414. def test_build_driver(self):
  415. output = OutputCapture()
  416. port = TestWebKitPort()
  417. # Delay setting _executive to avoid logging during construction
  418. port._executive = MockExecutive(should_log=True)
  419. port._options = MockOptions(configuration="Release") # This should not be necessary, but I think TestWebKitPort is actually reading from disk (and thus detects the current configuration).
  420. expected_logs = "MOCK run_command: ['Tools/Scripts/build-dumprendertree', '--release'], cwd=/mock-checkout, env={'LC_ALL': 'C', 'MOCK_ENVIRON_COPY': '1'}\n"
  421. self.assertTrue(output.assert_outputs(self, port._build_driver, expected_logs=expected_logs))
  422. # Make sure when passed --webkit-test-runner we build the right tool.
  423. port._options = MockOptions(webkit_test_runner=True, configuration="Release")
  424. expected_logs = "MOCK run_command: ['Tools/Scripts/build-dumprendertree', '--release'], cwd=/mock-checkout, env={'LC_ALL': 'C', 'MOCK_ENVIRON_COPY': '1'}\nMOCK run_command: ['Tools/Scripts/build-webkittestrunner', '--release'], cwd=/mock-checkout, env={'LC_ALL': 'C', 'MOCK_ENVIRON_COPY': '1'}\n"
  425. self.assertTrue(output.assert_outputs(self, port._build_driver, expected_logs=expected_logs))
  426. # Make sure we show the build log when --verbose is passed, which we simulate by setting the logging level to DEBUG.
  427. output.set_log_level(logging.DEBUG)
  428. port._options = MockOptions(configuration="Release")
  429. expected_logs = """MOCK run_command: ['Tools/Scripts/build-dumprendertree', '--release'], cwd=/mock-checkout, env={'LC_ALL': 'C', 'MOCK_ENVIRON_COPY': '1'}
  430. Output of ['Tools/Scripts/build-dumprendertree', '--release']:
  431. MOCK output of child process
  432. """
  433. self.assertTrue(output.assert_outputs(self, port._build_driver, expected_logs=expected_logs))
  434. output.set_log_level(logging.INFO)
  435. # Make sure that failure to build returns False.
  436. port._executive = MockExecutive(should_log=True, should_throw=True)
  437. # Because WK2 currently has to build both webkittestrunner and DRT, if DRT fails, that's the only one it tries.
  438. expected_logs = """MOCK run_command: ['Tools/Scripts/build-dumprendertree', '--release'], cwd=/mock-checkout, env={'LC_ALL': 'C', 'MOCK_ENVIRON_COPY': '1'}
  439. MOCK ScriptError
  440. MOCK output of child process
  441. """
  442. self.assertFalse(output.assert_outputs(self, port._build_driver, expected_logs=expected_logs))
  443. def _assert_config_file_for_platform(self, port, platform, config_file):
  444. self.assertEqual(port._apache_config_file_name_for_platform(platform), config_file)
  445. def test_linux_distro_detection(self):
  446. port = TestWebKitPort()
  447. self.assertFalse(port._is_redhat_based())
  448. self.assertFalse(port._is_debian_based())
  449. port._filesystem = MockFileSystem({'/etc/redhat-release': ''})
  450. self.assertTrue(port._is_redhat_based())
  451. self.assertFalse(port._is_debian_based())
  452. port._filesystem = MockFileSystem({'/etc/debian_version': ''})
  453. self.assertFalse(port._is_redhat_based())
  454. self.assertTrue(port._is_debian_based())
  455. port._filesystem = MockFileSystem({'/etc/arch-release': ''})
  456. self.assertFalse(port._is_redhat_based())
  457. self.assertTrue(port._is_arch_based())
  458. def test_apache_config_file_name_for_platform(self):
  459. port = TestWebKitPort()
  460. self._assert_config_file_for_platform(port, 'cygwin', 'cygwin-httpd.conf')
  461. self._assert_config_file_for_platform(port, 'linux2', 'apache2-httpd.conf')
  462. self._assert_config_file_for_platform(port, 'linux3', 'apache2-httpd.conf')
  463. port._is_redhat_based = lambda: True
  464. port._apache_version = lambda: '2.2'
  465. self._assert_config_file_for_platform(port, 'linux2', 'fedora-httpd-2.2.conf')
  466. port = TestWebKitPort()
  467. port._is_debian_based = lambda: True
  468. self._assert_config_file_for_platform(port, 'linux2', 'apache2-debian-httpd.conf')
  469. self._assert_config_file_for_platform(port, 'mac', 'apache2-httpd.conf')
  470. self._assert_config_file_for_platform(port, 'win32', 'apache2-httpd.conf') # win32 isn't a supported sys.platform. AppleWin/WinCairo/WinCE ports all use cygwin.
  471. self._assert_config_file_for_platform(port, 'barf', 'apache2-httpd.conf')
  472. def test_path_to_apache_config_file(self):
  473. port = TestWebKitPort()
  474. saved_environ = os.environ.copy()
  475. try:
  476. os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/path/to/httpd.conf'
  477. self.assertRaises(IOError, port._path_to_apache_config_file)
  478. port._filesystem.write_text_file('/existing/httpd.conf', 'Hello, world!')
  479. os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/existing/httpd.conf'
  480. self.assertEqual(port._path_to_apache_config_file(), '/existing/httpd.conf')
  481. finally:
  482. os.environ = saved_environ.copy()
  483. # Mock out _apache_config_file_name_for_platform to ignore the passed sys.platform value.
  484. port._apache_config_file_name_for_platform = lambda platform: 'httpd.conf'
  485. self.assertEqual(port._path_to_apache_config_file(), '/mock-checkout/LayoutTests/http/conf/httpd.conf')
  486. # Check that even if we mock out _apache_config_file_name, the environment variable takes precedence.
  487. saved_environ = os.environ.copy()
  488. try:
  489. os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/existing/httpd.conf'
  490. self.assertEqual(port._path_to_apache_config_file(), '/existing/httpd.conf')
  491. finally:
  492. os.environ = saved_environ.copy()
  493. def test_check_build(self):
  494. port = self.make_port(options=MockOptions(build=True))
  495. self.build_called = False
  496. def build_driver_called():
  497. self.build_called = True
  498. return True
  499. port._build_driver = build_driver_called
  500. port.check_build(False)
  501. self.assertTrue(self.build_called)
  502. port = self.make_port(options=MockOptions(root='/tmp', build=True))
  503. self.build_called = False
  504. port._build_driver = build_driver_called
  505. port.check_build(False)
  506. self.assertFalse(self.build_called, None)
  507. port = self.make_port(options=MockOptions(build=False))
  508. self.build_called = False
  509. port._build_driver = build_driver_called
  510. port.check_build(False)
  511. self.assertFalse(self.build_called, None)
  512. def test_additional_platform_directory(self):
  513. port = self.make_port(options=MockOptions(additional_platform_directory=['/tmp/foo']))
  514. self.assertEqual(port.baseline_search_path()[0], '/tmp/foo')