| OLD | NEW |
| 1 # Copyright (C) 2010 Google Inc. All rights reserved. | 1 # Copyright (C) 2010 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 from webkitpy.common.system.path import cygpath | 55 from webkitpy.common.system.path import cygpath |
| 56 from webkitpy.common.system.systemhost import SystemHost | 56 from webkitpy.common.system.systemhost import SystemHost |
| 57 from webkitpy.common.webkit_finder import WebKitFinder | 57 from webkitpy.common.webkit_finder import WebKitFinder |
| 58 from webkitpy.layout_tests.layout_package.bot_test_expectations import BotTestEx
pectationsFactory | 58 from webkitpy.layout_tests.layout_package.bot_test_expectations import BotTestEx
pectationsFactory |
| 59 from webkitpy.layout_tests.models import test_run_results | 59 from webkitpy.layout_tests.models import test_run_results |
| 60 from webkitpy.layout_tests.models.test_configuration import TestConfiguration | 60 from webkitpy.layout_tests.models.test_configuration import TestConfiguration |
| 61 from webkitpy.layout_tests.port import config as port_config | 61 from webkitpy.layout_tests.port import config as port_config |
| 62 from webkitpy.layout_tests.port import driver | 62 from webkitpy.layout_tests.port import driver |
| 63 from webkitpy.layout_tests.port import server_process | 63 from webkitpy.layout_tests.port import server_process |
| 64 from webkitpy.layout_tests.port.factory import PortFactory | 64 from webkitpy.layout_tests.port.factory import PortFactory |
| 65 from webkitpy.layout_tests.servers import apache_http_server | 65 from webkitpy.layout_tests.servers import apache_http |
| 66 from webkitpy.layout_tests.servers import http_server | 66 from webkitpy.layout_tests.servers import lighttpd |
| 67 from webkitpy.layout_tests.servers import websocket_server | 67 from webkitpy.layout_tests.servers import pywebsocket |
| 68 | 68 |
| 69 _log = logging.getLogger(__name__) | 69 _log = logging.getLogger(__name__) |
| 70 | 70 |
| 71 | 71 |
| 72 # FIXME: This class should merge with WebKitPort now that Chromium behaves mostl
y like other webkit ports. | 72 # FIXME: This class should merge with WebKitPort now that Chromium behaves mostl
y like other webkit ports. |
| 73 class Port(object): | 73 class Port(object): |
| 74 """Abstract class for Port-specific hooks for the layout_test package.""" | 74 """Abstract class for Port-specific hooks for the layout_test package.""" |
| 75 | 75 |
| 76 # Subclasses override this. This should indicate the basic implementation | 76 # Subclasses override this. This should indicate the basic implementation |
| 77 # part of the port name, e.g., 'mac', 'win', 'gtk'; there is probably (?) | 77 # part of the port name, e.g., 'mac', 'win', 'gtk'; there is probably (?) |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 result = self.check_image_diff( | 341 result = self.check_image_diff( |
| 342 'To override, invoke with --no-pixel-tests') and result | 342 'To override, invoke with --no-pixel-tests') and result |
| 343 | 343 |
| 344 # It's okay if pretty patch and wdiff aren't available, but we will at l
east log messages. | 344 # It's okay if pretty patch and wdiff aren't available, but we will at l
east log messages. |
| 345 self._pretty_patch_available = self.check_pretty_patch() | 345 self._pretty_patch_available = self.check_pretty_patch() |
| 346 self._wdiff_available = self.check_wdiff() | 346 self._wdiff_available = self.check_wdiff() |
| 347 | 347 |
| 348 if self._dump_reader: | 348 if self._dump_reader: |
| 349 result = self._dump_reader.check_is_functional() and result | 349 result = self._dump_reader.check_is_functional() and result |
| 350 | 350 |
| 351 if needs_http: |
| 352 result = self.check_httpd() and result |
| 353 |
| 351 return test_run_results.OK_EXIT_STATUS if result else test_run_results.U
NEXPECTED_ERROR_EXIT_STATUS | 354 return test_run_results.OK_EXIT_STATUS if result else test_run_results.U
NEXPECTED_ERROR_EXIT_STATUS |
| 352 | 355 |
| 353 def _check_driver(self): | 356 def _check_driver(self): |
| 354 driver_path = self._path_to_driver() | 357 driver_path = self._path_to_driver() |
| 355 if not self._filesystem.exists(driver_path): | 358 if not self._filesystem.exists(driver_path): |
| 356 _log.error("%s was not found at %s" % (self.driver_name(), driver_pa
th)) | 359 _log.error("%s was not found at %s" % (self.driver_name(), driver_pa
th)) |
| 357 return False | 360 return False |
| 358 return True | 361 return True |
| 359 | 362 |
| 360 def _check_port_build(self): | 363 def _check_port_build(self): |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 _log.warning(' ' + line) | 428 _log.warning(' ' + line) |
| 426 _log.warning('') | 429 _log.warning('') |
| 427 return False | 430 return False |
| 428 | 431 |
| 429 return True | 432 return True |
| 430 | 433 |
| 431 def _wdiff_missing_message(self): | 434 def _wdiff_missing_message(self): |
| 432 return 'wdiff is not installed; please install it to generate word-by-wo
rd diffs.' | 435 return 'wdiff is not installed; please install it to generate word-by-wo
rd diffs.' |
| 433 | 436 |
| 434 def check_httpd(self): | 437 def check_httpd(self): |
| 435 if self._uses_apache(): | 438 if self.uses_apache(): |
| 436 httpd_path = self._path_to_apache() | 439 httpd_path = self.path_to_apache() |
| 437 else: | 440 else: |
| 438 httpd_path = self._path_to_lighttpd() | 441 httpd_path = self.path_to_lighttpd() |
| 439 | 442 |
| 440 try: | 443 try: |
| 441 server_name = self._filesystem.basename(httpd_path) | 444 server_name = self._filesystem.basename(httpd_path) |
| 442 env = self.setup_environ_for_server(server_name) | 445 env = self.setup_environ_for_server(server_name) |
| 443 if self._executive.run_command([httpd_path, "-v"], env=env, return_e
xit_code=True) != 0: | 446 if self._executive.run_command([httpd_path, "-v"], env=env, return_e
xit_code=True) != 0: |
| 444 _log.error("httpd seems broken. Cannot run http tests.") | 447 _log.error("httpd seems broken. Cannot run http tests.") |
| 445 return False | 448 return False |
| 446 return True | 449 return True |
| 447 except OSError: | 450 except OSError: |
| 448 _log.error("No httpd found. Cannot run http tests.") | 451 _log.error("No httpd found. Cannot run http tests.") |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 stdin=self._executive.PIPE, stdout=self._executive.PIPE, stderr=
None) | 1087 stdin=self._executive.PIPE, stdout=self._executive.PIPE, stderr=
None) |
| 1085 is_ready = self._helper.stdout.readline() | 1088 is_ready = self._helper.stdout.readline() |
| 1086 if not is_ready.startswith('ready'): | 1089 if not is_ready.startswith('ready'): |
| 1087 _log.error("layout_test_helper failed to be ready") | 1090 _log.error("layout_test_helper failed to be ready") |
| 1088 | 1091 |
| 1089 def requires_http_server(self): | 1092 def requires_http_server(self): |
| 1090 """Does the port require an HTTP server for running tests? This could | 1093 """Does the port require an HTTP server for running tests? This could |
| 1091 be the case when the tests aren't run on the host platform.""" | 1094 be the case when the tests aren't run on the host platform.""" |
| 1092 return False | 1095 return False |
| 1093 | 1096 |
| 1094 def start_http_server(self, additional_dirs=None, number_of_servers=None): | 1097 def start_http_server(self, number_of_drivers): |
| 1095 """Start a web server. Raise an error if it can't start or is already ru
nning. | 1098 """Start a web server. Raise an error if it can't start or is already ru
nning. |
| 1096 | 1099 |
| 1097 Ports can stub this out if they don't need a web server to be running.""
" | 1100 Ports can stub this out if they don't need a web server to be running.""
" |
| 1098 assert not self._http_server, 'Already running an http server.' | 1101 assert not self._http_server, 'Already running an http server.' |
| 1099 | 1102 |
| 1100 if self._uses_apache(): | 1103 if self.uses_apache(): |
| 1101 server = apache_http_server.LayoutTestApacheHttpd(self, self.results
_directory(), additional_dirs=additional_dirs, number_of_servers=number_of_serve
rs) | 1104 server = apache_http.ApacheHttpd(self, self.results_directory(), num
ber_of_drivers * 4) |
| 1102 else: | 1105 else: |
| 1103 server = http_server.Lighttpd(self, self.results_directory(), additi
onal_dirs=additional_dirs, number_of_servers=number_of_servers) | 1106 server = lighttpd.Lighttpd(self, self.results_directory()) |
| 1104 | 1107 |
| 1105 server.start() | 1108 server.start() |
| 1106 self._http_server = server | 1109 self._http_server = server |
| 1107 | 1110 |
| 1108 def start_websocket_server(self): | 1111 def start_websocket_server(self): |
| 1109 """Start a web server. Raise an error if it can't start or is already ru
nning. | 1112 """Start a web server. Raise an error if it can't start or is already ru
nning. |
| 1110 | 1113 |
| 1111 Ports can stub this out if they don't need a websocket server to be runn
ing.""" | 1114 Ports can stub this out if they don't need a websocket server to be runn
ing.""" |
| 1112 assert not self._websocket_server, 'Already running a websocket server.' | 1115 assert not self._websocket_server, 'Already running a websocket server.' |
| 1113 | 1116 |
| 1114 server = websocket_server.PyWebSocket(self, self.results_directory()) | 1117 server = pywebsocket.PyWebSocket(self, self.results_directory()) |
| 1115 server.start() | 1118 server.start() |
| 1116 self._websocket_server = server | 1119 self._websocket_server = server |
| 1117 | 1120 |
| 1118 def http_server_supports_ipv6(self): | 1121 def http_server_supports_ipv6(self): |
| 1119 # Cygwin is the only platform to still use Apache 1.3, which only suppor
ts IPV4. | 1122 # Apache < 2.4 on win32 does not support IPv6. |
| 1120 # Once it moves to Apache 2, we can drop this method altogether. | 1123 if self.host.platform.is_cygwin() or self.get_option('use_apache') and s
elf.host.platform.is_win(): |
| 1121 if self.host.platform.is_cygwin(): | |
| 1122 return False | 1124 return False |
| 1123 return True | 1125 return True |
| 1124 | 1126 |
| 1125 def stop_helper(self): | 1127 def stop_helper(self): |
| 1126 """Shut down the test helper if it is running. Do nothing if | 1128 """Shut down the test helper if it is running. Do nothing if |
| 1127 it isn't, or it isn't available. If a port overrides start_helper() | 1129 it isn't, or it isn't available. If a port overrides start_helper() |
| 1128 it must override this routine as well.""" | 1130 it must override this routine as well.""" |
| 1129 if self._helper: | 1131 if self._helper: |
| 1130 _log.debug("Stopping layout test helper") | 1132 _log.debug("Stopping layout test helper") |
| 1131 try: | 1133 try: |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 self._pretty_patch_available = False | 1362 self._pretty_patch_available = False |
| 1361 _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, e.messa
ge_with_output())) | 1363 _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, e.messa
ge_with_output())) |
| 1362 return self._pretty_patch_error_html | 1364 return self._pretty_patch_error_html |
| 1363 | 1365 |
| 1364 def default_configuration(self): | 1366 def default_configuration(self): |
| 1365 return self._config.default_configuration() | 1367 return self._config.default_configuration() |
| 1366 | 1368 |
| 1367 def clobber_old_port_specific_results(self): | 1369 def clobber_old_port_specific_results(self): |
| 1368 pass | 1370 pass |
| 1369 | 1371 |
| 1372 def uses_apache(self): |
| 1373 return True |
| 1374 |
| 1375 # FIXME: This does not belong on the port object. |
| 1376 @memoized |
| 1377 def path_to_apache(self): |
| 1378 """Returns the full path to the apache binary. |
| 1379 |
| 1380 This is needed only by ports that use the apache_http_server module.""" |
| 1381 raise NotImplementedError('Port.path_to_apache') |
| 1382 |
| 1383 def path_to_apache_config_file(self): |
| 1384 """Returns the full path to the apache configuration file. |
| 1385 |
| 1386 If the WEBKIT_HTTP_SERVER_CONF_PATH environment variable is set, its |
| 1387 contents will be used instead. |
| 1388 |
| 1389 This is needed only by ports that use the apache_http_server module.""" |
| 1390 config_file_from_env = os.environ.get('WEBKIT_HTTP_SERVER_CONF_PATH') |
| 1391 if config_file_from_env: |
| 1392 if not self._filesystem.exists(config_file_from_env): |
| 1393 raise IOError('%s was not found on the system' % config_file_fro
m_env) |
| 1394 return config_file_from_env |
| 1395 |
| 1396 config_file_name = self._apache_config_file_name_for_platform(sys.platfo
rm) |
| 1397 return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', co
nfig_file_name) |
| 1398 |
| 1399 def path_to_lighttpd(self): |
| 1400 """Returns the path to the LigHTTPd binary. |
| 1401 |
| 1402 This is needed only by ports that use the http_server.py module.""" |
| 1403 raise NotImplementedError('Port._path_to_lighttpd') |
| 1404 |
| 1405 def path_to_lighttpd_modules(self): |
| 1406 """Returns the path to the LigHTTPd modules directory. |
| 1407 |
| 1408 This is needed only by ports that use the http_server.py module.""" |
| 1409 raise NotImplementedError('Port._path_to_lighttpd_modules') |
| 1410 |
| 1411 def path_to_lighttpd_php(self): |
| 1412 """Returns the path to the LigHTTPd PHP executable. |
| 1413 |
| 1414 This is needed only by ports that use the http_server.py module.""" |
| 1415 raise NotImplementedError('Port._path_to_lighttpd_php') |
| 1416 |
| 1417 |
| 1370 # | 1418 # |
| 1371 # PROTECTED ROUTINES | 1419 # PROTECTED ROUTINES |
| 1372 # | 1420 # |
| 1373 # The routines below should only be called by routines in this class | 1421 # The routines below should only be called by routines in this class |
| 1374 # or any of its subclasses. | 1422 # or any of its subclasses. |
| 1375 # | 1423 # |
| 1376 | 1424 |
| 1377 def _uses_apache(self): | |
| 1378 return True | |
| 1379 | |
| 1380 # FIXME: This does not belong on the port object. | |
| 1381 @memoized | |
| 1382 def _path_to_apache(self): | |
| 1383 """Returns the full path to the apache binary. | |
| 1384 | |
| 1385 This is needed only by ports that use the apache_http_server module.""" | |
| 1386 raise NotImplementedError('Port._path_to_apache') | |
| 1387 | |
| 1388 # FIXME: This belongs on some platform abstraction instead of Port. | 1425 # FIXME: This belongs on some platform abstraction instead of Port. |
| 1389 def _is_redhat_based(self): | 1426 def _is_redhat_based(self): |
| 1390 return self._filesystem.exists('/etc/redhat-release') | 1427 return self._filesystem.exists('/etc/redhat-release') |
| 1391 | 1428 |
| 1392 def _is_debian_based(self): | 1429 def _is_debian_based(self): |
| 1393 return self._filesystem.exists('/etc/debian_version') | 1430 return self._filesystem.exists('/etc/debian_version') |
| 1394 | 1431 |
| 1395 def _apache_version(self): | 1432 def _apache_version(self): |
| 1396 config = self._executive.run_command([self._path_to_apache(), '-v']) | 1433 config = self._executive.run_command([self.path_to_apache(), '-v']) |
| 1397 return re.sub(r'(?:.|\n)*Server version: Apache/(\d+\.\d+)(?:.|\n)*', r'
\1', config) | 1434 return re.sub(r'(?:.|\n)*Server version: Apache/(\d+\.\d+)(?:.|\n)*', r'
\1', config) |
| 1398 | 1435 |
| 1399 # We pass sys_platform into this method to make it easy to unit test. | 1436 # We pass sys_platform into this method to make it easy to unit test. |
| 1400 def _apache_config_file_name_for_platform(self, sys_platform): | 1437 def _apache_config_file_name_for_platform(self, sys_platform): |
| 1401 if sys_platform == 'cygwin': | 1438 if sys_platform == 'cygwin': |
| 1402 return 'cygwin-httpd.conf' # CYGWIN is the only platform to still u
se Apache 1.3. | 1439 return 'cygwin-httpd.conf' # CYGWIN is the only platform to still u
se Apache 1.3. |
| 1403 if sys_platform.startswith('linux'): | 1440 if sys_platform.startswith('linux'): |
| 1404 if self._is_redhat_based(): | 1441 if self._is_redhat_based(): |
| 1405 return 'fedora-httpd-' + self._apache_version() + '.conf' | 1442 return 'fedora-httpd-' + self._apache_version() + '.conf' |
| 1406 if self._is_debian_based(): | 1443 if self._is_debian_based(): |
| 1407 return 'debian-httpd-' + self._apache_version() + '.conf' | 1444 return 'debian-httpd-' + self._apache_version() + '.conf' |
| 1408 # All platforms use apache2 except for CYGWIN (and Mac OS X Tiger and pr
ior, which we no longer support). | 1445 # All platforms use apache2 except for CYGWIN (and Mac OS X Tiger and pr
ior, which we no longer support). |
| 1409 return "apache2-httpd.conf" | 1446 return "apache2-httpd.conf" |
| 1410 | 1447 |
| 1411 def _path_to_apache_config_file(self): | |
| 1412 """Returns the full path to the apache configuration file. | |
| 1413 | |
| 1414 If the WEBKIT_HTTP_SERVER_CONF_PATH environment variable is set, its | |
| 1415 contents will be used instead. | |
| 1416 | |
| 1417 This is needed only by ports that use the apache_http_server module.""" | |
| 1418 config_file_from_env = os.environ.get('WEBKIT_HTTP_SERVER_CONF_PATH') | |
| 1419 if config_file_from_env: | |
| 1420 if not self._filesystem.exists(config_file_from_env): | |
| 1421 raise IOError('%s was not found on the system' % config_file_fro
m_env) | |
| 1422 return config_file_from_env | |
| 1423 | |
| 1424 config_file_name = self._apache_config_file_name_for_platform(sys.platfo
rm) | |
| 1425 return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', co
nfig_file_name) | |
| 1426 | |
| 1427 def _path_to_driver(self, configuration=None): | 1448 def _path_to_driver(self, configuration=None): |
| 1428 """Returns the full path to the test driver.""" | 1449 """Returns the full path to the test driver.""" |
| 1429 return self._build_path(self.driver_name()) | 1450 return self._build_path(self.driver_name()) |
| 1430 | 1451 |
| 1431 def _path_to_webcore_library(self): | 1452 def _path_to_webcore_library(self): |
| 1432 """Returns the full path to a built copy of WebCore.""" | 1453 """Returns the full path to a built copy of WebCore.""" |
| 1433 return None | 1454 return None |
| 1434 | 1455 |
| 1435 def _path_to_helper(self): | 1456 def _path_to_helper(self): |
| 1436 """Returns the full path to the layout_test_helper binary, which | 1457 """Returns the full path to the layout_test_helper binary, which |
| 1437 is used to help configure the system for the test run, or None | 1458 is used to help configure the system for the test run, or None |
| 1438 if no helper is needed. | 1459 if no helper is needed. |
| 1439 | 1460 |
| 1440 This is likely only used by start/stop_helper().""" | 1461 This is likely only used by start/stop_helper().""" |
| 1441 return None | 1462 return None |
| 1442 | 1463 |
| 1443 def _path_to_image_diff(self): | 1464 def _path_to_image_diff(self): |
| 1444 """Returns the full path to the image_diff binary, or None if it is not
available. | 1465 """Returns the full path to the image_diff binary, or None if it is not
available. |
| 1445 | 1466 |
| 1446 This is likely used only by diff_image()""" | 1467 This is likely used only by diff_image()""" |
| 1447 return self._build_path('image_diff') | 1468 return self._build_path('image_diff') |
| 1448 | 1469 |
| 1449 def _path_to_lighttpd(self): | |
| 1450 """Returns the path to the LigHTTPd binary. | |
| 1451 | |
| 1452 This is needed only by ports that use the http_server.py module.""" | |
| 1453 raise NotImplementedError('Port._path_to_lighttpd') | |
| 1454 | |
| 1455 def _path_to_lighttpd_modules(self): | |
| 1456 """Returns the path to the LigHTTPd modules directory. | |
| 1457 | |
| 1458 This is needed only by ports that use the http_server.py module.""" | |
| 1459 raise NotImplementedError('Port._path_to_lighttpd_modules') | |
| 1460 | |
| 1461 def _path_to_lighttpd_php(self): | |
| 1462 """Returns the path to the LigHTTPd PHP executable. | |
| 1463 | |
| 1464 This is needed only by ports that use the http_server.py module.""" | |
| 1465 raise NotImplementedError('Port._path_to_lighttpd_php') | |
| 1466 | |
| 1467 @memoized | 1470 @memoized |
| 1468 def _path_to_wdiff(self): | 1471 def _path_to_wdiff(self): |
| 1469 """Returns the full path to the wdiff binary, or None if it is not avail
able. | 1472 """Returns the full path to the wdiff binary, or None if it is not avail
able. |
| 1470 | 1473 |
| 1471 This is likely used only by wdiff_text()""" | 1474 This is likely used only by wdiff_text()""" |
| 1472 for path in ("/usr/bin/wdiff", "/usr/bin/dwdiff"): | 1475 for path in ("/usr/bin/wdiff", "/usr/bin/dwdiff"): |
| 1473 if self._filesystem.exists(path): | 1476 if self._filesystem.exists(path): |
| 1474 return path | 1477 return path |
| 1475 return None | 1478 return None |
| 1476 | 1479 |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 if name.find('/') != -1: | 1750 if name.find('/') != -1: |
| 1748 _log.error("Virtual test suites names cannot contain /'s: %s" %
name) | 1751 _log.error("Virtual test suites names cannot contain /'s: %s" %
name) |
| 1749 return | 1752 return |
| 1750 self.name = 'virtual/' + name + '/' + base | 1753 self.name = 'virtual/' + name + '/' + base |
| 1751 self.base = base | 1754 self.base = base |
| 1752 self.args = args | 1755 self.args = args |
| 1753 self.tests = tests or set() | 1756 self.tests = tests or set() |
| 1754 | 1757 |
| 1755 def __repr__(self): | 1758 def __repr__(self): |
| 1756 return "VirtualTestSuite('%s', '%s', %s)" % (self.name, self.base, self.
args) | 1759 return "VirtualTestSuite('%s', '%s', %s)" % (self.name, self.base, self.
args) |
| OLD | NEW |