Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """A tool used to run a Chrome test executable and process the output. | 6 """A tool used to run a Chrome test executable and process the output. |
| 7 | 7 |
| 8 This script is used by the buildbot slaves. It must be run from the outer | 8 This script is used by the buildbot slaves. It must be run from the outer |
| 9 build directory, e.g. chrome-release/build/. | 9 build directory, e.g. chrome-release/build/. |
| 10 | 10 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 # TODO(crbug.com/403564). We almost certainly shouldn't be importing this. | 47 # TODO(crbug.com/403564). We almost certainly shouldn't be importing this. |
| 48 import config | 48 import config |
| 49 | 49 |
| 50 from slave import annotation_utils | 50 from slave import annotation_utils |
| 51 from slave import build_directory | 51 from slave import build_directory |
| 52 from slave import crash_utils | 52 from slave import crash_utils |
| 53 from slave import gtest_slave_utils | 53 from slave import gtest_slave_utils |
| 54 from slave import process_log_utils | 54 from slave import process_log_utils |
| 55 from slave import results_dashboard | 55 from slave import results_dashboard |
| 56 from slave import slave_utils | 56 from slave import slave_utils |
| 57 from slave import telemetry_utils | |
| 57 from slave import xvfb | 58 from slave import xvfb |
| 58 | 59 |
| 59 USAGE = '%s [options] test.exe [test args]' % os.path.basename(sys.argv[0]) | 60 USAGE = '%s [options] test.exe [test args]' % os.path.basename(sys.argv[0]) |
| 60 | 61 |
| 61 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox' | 62 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox' |
| 62 | 63 |
| 63 # Directory to write JSON for test results into. | 64 # Directory to write JSON for test results into. |
| 64 DEST_DIR = 'gtest_results' | 65 DEST_DIR = 'gtest_results' |
| 65 | 66 |
| 66 # Names of httpd configuration file under different platforms. | 67 # Names of httpd configuration file under different platforms. |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 shouldlist = selection and selection == 'list' | 547 shouldlist = selection and selection == 'list' |
| 547 if shouldlist: | 548 if shouldlist: |
| 548 print | 549 print |
| 549 print 'Available log parsers:' | 550 print 'Available log parsers:' |
| 550 for p in parsers: | 551 for p in parsers: |
| 551 print ' ', p, parsers[p].__name__ | 552 print ' ', p, parsers[p].__name__ |
| 552 | 553 |
| 553 return shouldlist | 554 return shouldlist |
| 554 | 555 |
| 555 | 556 |
| 556 def _SelectResultsTracker(options): | 557 def _SelectResultsTracker(options, test_exe): |
| 557 """Returns a log parser class (aka results tracker class). | 558 """Returns a log parser class (aka results tracker class). |
| 558 | 559 |
| 559 Args: | 560 Args: |
| 560 options: Command-line options (from OptionParser). | 561 options: Command-line options (from OptionParser). |
| 562 test_exe: Name of the test to execute | |
| 561 | 563 |
| 562 Returns: | 564 Returns: |
| 563 A log parser class (aka results tracker class), or None. | 565 A log parser class (aka results tracker class), or None. |
| 564 """ | 566 """ |
| 565 if _UsingGtestJson(options): | 567 if _UsingGtestJson(options): |
| 566 return gtest_utils.GTestJSONParser | 568 return gtest_utils.GTestJSONParser |
| 567 | 569 |
| 570 if test_exe and test_exe.endswith('telemetry.py'): | |
| 571 return telemetry_utils.TelemetryLogParser | |
|
sullivan
2014/09/05 04:30:00
Is this the best way to tell if it's a telemetry t
ghost stip (do not use)
2014/09/05 21:39:06
Unfortunately yeah, if you want skip a master rest
| |
| 572 | |
| 568 parsers = _GetParsers() | 573 parsers = _GetParsers() |
| 569 if options.annotate: | 574 if options.annotate: |
| 570 if options.annotate in parsers: | 575 if options.annotate in parsers: |
| 571 if options.generate_json_file and options.annotate != 'gtest': | 576 if options.generate_json_file and options.annotate != 'gtest': |
| 572 raise NotImplementedError('"%s" doesn\'t make sense with ' | 577 raise NotImplementedError('"%s" doesn\'t make sense with ' |
| 573 'options.generate_json_file.') | 578 'options.generate_json_file.') |
| 574 else: | 579 else: |
| 575 return parsers[options.annotate] | 580 return parsers[options.annotate] |
| 576 else: | 581 else: |
| 577 raise KeyError('"%s" is not a valid GTest parser!' % options.annotate) | 582 raise KeyError('"%s" is not a valid GTest parser!' % options.annotate) |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 595 Args: | 600 Args: |
| 596 tracker_class: A log parser class. | 601 tracker_class: A log parser class. |
| 597 options: Command-line options (from OptionParser). | 602 options: Command-line options (from OptionParser). |
| 598 | 603 |
| 599 Returns: | 604 Returns: |
| 600 An instance of a log parser class, or None. | 605 An instance of a log parser class, or None. |
| 601 """ | 606 """ |
| 602 if not tracker_class: | 607 if not tracker_class: |
| 603 return None | 608 return None |
| 604 | 609 |
| 605 if tracker_class.__name__ in ('GTestLogParser',): | 610 if tracker_class.__name__ in ('GTestLogParser', 'TelemetryLogParser'): |
| 606 tracker_obj = tracker_class() | 611 tracker_obj = tracker_class() |
| 607 elif tracker_class.__name__ in ('GTestJSONParser',): | 612 elif tracker_class.__name__ in ('GTestJSONParser',): |
| 608 tracker_obj = tracker_class(options.build_properties.get('mastername')) | 613 tracker_obj = tracker_class(options.build_properties.get('mastername')) |
| 609 else: | 614 else: |
| 610 build_dir = os.path.abspath(options.build_dir) | 615 build_dir = os.path.abspath(options.build_dir) |
| 611 | 616 |
| 612 if options.webkit_revision: | 617 if options.webkit_revision: |
| 613 webkit_revision = options.webkit_revision | 618 webkit_revision = options.webkit_revision |
| 614 else: | 619 else: |
| 615 try: | 620 try: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 683 """ | 688 """ |
| 684 if system is None: | 689 if system is None: |
| 685 # perf_id not specified in factory properties. | 690 # perf_id not specified in factory properties. |
| 686 print 'Error: No system name (perf_id) specified when sending to dashboard.' | 691 print 'Error: No system name (perf_id) specified when sending to dashboard.' |
| 687 return | 692 return |
| 688 supplemental_columns = _GetSupplementalColumns( | 693 supplemental_columns = _GetSupplementalColumns( |
| 689 build_dir, supplemental_columns_file) | 694 build_dir, supplemental_columns_file) |
| 690 if extra_columns: | 695 if extra_columns: |
| 691 supplemental_columns.update(extra_columns) | 696 supplemental_columns.update(extra_columns) |
| 692 | 697 |
| 693 charts = _GetDataFromLogProcessor(results_tracker) | 698 if results_tracker.IsChartJson(): |
| 694 points = results_dashboard.MakeListOfPoints( | 699 results_dashboard.SendChartJsonResults( |
|
sullivan
2014/09/05 04:30:00
Still working on implementing this.
sullivan
2014/09/05 21:32:16
This is implemented now.
| |
| 695 charts, system, test, mastername, buildername, buildnumber, | 700 results_tracker.Chart(), results_tracker.RefChart(), |
| 696 supplemental_columns) | 701 system, test, mastername, buildername, buildnumber, supplemental_columns |
| 697 results_dashboard.SendResults(points, url, build_dir) | 702 ) |
| 703 else: | |
| 704 charts = _GetDataFromLogProcessor(results_tracker) | |
| 705 points = results_dashboard.MakeListOfPoints( | |
| 706 charts, system, test, mastername, buildername, buildnumber, | |
| 707 supplemental_columns) | |
| 708 results_dashboard.SendResults(points, url, build_dir) | |
| 698 | 709 |
| 699 | 710 |
| 700 def _GetDataFromLogProcessor(log_processor): | 711 def _GetDataFromLogProcessor(log_processor): |
| 701 """Returns a mapping of chart names to chart data. | 712 """Returns a mapping of chart names to chart data. |
| 702 | 713 |
| 703 Args: | 714 Args: |
| 704 log_processor: A log processor (aka results tracker) object. | 715 log_processor: A log processor (aka results tracker) object. |
| 705 | 716 |
| 706 Returns: | 717 Returns: |
| 707 A dictionary mapping chart name to lists of chart data. | 718 A dictionary mapping chart name to lists of chart data. |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 955 through the specified annotation parser. | 966 through the specified annotation parser. |
| 956 """ | 967 """ |
| 957 if not options.annotate: | 968 if not options.annotate: |
| 958 raise chromium_utils.MissingArgument('--parse-input doesn\'t make sense ' | 969 raise chromium_utils.MissingArgument('--parse-input doesn\'t make sense ' |
| 959 'without --annotate.') | 970 'without --annotate.') |
| 960 | 971 |
| 961 # If --annotate=list was passed, list the log parser classes and exit. | 972 # If --annotate=list was passed, list the log parser classes and exit. |
| 962 if _ListParsers(options.annotate): | 973 if _ListParsers(options.annotate): |
| 963 return 0 | 974 return 0 |
| 964 | 975 |
| 965 tracker_class = _SelectResultsTracker(options) | 976 tracker_class = _SelectResultsTracker(options, None) |
|
sullivan
2014/09/05 04:30:00
This should never get called for Telemetry tests,
ghost stip (do not use)
2014/09/05 21:39:06
Right, there is no binary here
| |
| 966 results_tracker = _CreateResultsTracker(tracker_class, options) | 977 results_tracker = _CreateResultsTracker(tracker_class, options) |
| 967 | 978 |
| 968 if options.generate_json_file: | 979 if options.generate_json_file: |
| 969 if os.path.exists(options.test_output_xml): | 980 if os.path.exists(options.test_output_xml): |
| 970 # remove the old XML output file. | 981 # remove the old XML output file. |
| 971 os.remove(options.test_output_xml) | 982 os.remove(options.test_output_xml) |
| 972 | 983 |
| 973 if options.parse_input == '-': | 984 if options.parse_input == '-': |
| 974 f = sys.stdin | 985 f = sys.stdin |
| 975 else: | 986 else: |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1022 command = [sys.executable, test_exe] | 1033 command = [sys.executable, test_exe] |
| 1023 else: | 1034 else: |
| 1024 command = [test_exe_path] | 1035 command = [test_exe_path] |
| 1025 if options.annotate == 'gtest': | 1036 if options.annotate == 'gtest': |
| 1026 command.extend(['--brave-new-test-launcher', '--test-launcher-bot-mode']) | 1037 command.extend(['--brave-new-test-launcher', '--test-launcher-bot-mode']) |
| 1027 command.extend(args[1:]) | 1038 command.extend(args[1:]) |
| 1028 | 1039 |
| 1029 # If --annotate=list was passed, list the log parser classes and exit. | 1040 # If --annotate=list was passed, list the log parser classes and exit. |
| 1030 if _ListParsers(options.annotate): | 1041 if _ListParsers(options.annotate): |
| 1031 return 0 | 1042 return 0 |
| 1032 tracker_class = _SelectResultsTracker(options) | 1043 tracker_class = _SelectResultsTracker(options, test_exe) |
| 1033 results_tracker = _CreateResultsTracker(tracker_class, options) | 1044 results_tracker = _CreateResultsTracker(tracker_class, options) |
| 1034 | 1045 |
| 1035 if options.generate_json_file: | 1046 if options.generate_json_file: |
| 1036 if os.path.exists(options.test_output_xml): | 1047 if os.path.exists(options.test_output_xml): |
| 1037 # remove the old XML output file. | 1048 # remove the old XML output file. |
| 1038 os.remove(options.test_output_xml) | 1049 os.remove(options.test_output_xml) |
| 1039 | 1050 |
| 1040 try: | 1051 try: |
| 1041 http_server = None | 1052 http_server = None |
| 1042 if options.document_root: | 1053 if options.document_root: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1084 options.test_type, options.results_url, options.build_dir, | 1095 options.test_type, options.results_url, options.build_dir, |
| 1085 options.build_properties.get('mastername'), | 1096 options.build_properties.get('mastername'), |
| 1086 options.build_properties.get('buildername'), | 1097 options.build_properties.get('buildername'), |
| 1087 options.build_properties.get('buildnumber'), | 1098 options.build_properties.get('buildnumber'), |
| 1088 options.supplemental_columns_file, | 1099 options.supplemental_columns_file, |
| 1089 options.perf_config) | 1100 options.perf_config) |
| 1090 | 1101 |
| 1091 return result | 1102 return result |
| 1092 | 1103 |
| 1093 | 1104 |
| 1094 def _MainIOS(options, args, extra_env): | 1105 def _MainIOS(options, args, extra_env): |
|
sullivan
2014/09/05 04:30:00
Is telemetry available on iOS? Not sure how perf t
ghost stip (do not use)
2014/09/05 21:39:06
I'm not sure. smut@?
smut
2014/09/05 21:59:09
Perf tests only run downstream on iOS, and downstr
| |
| 1095 """Runs the test on iOS.""" | 1106 """Runs the test on iOS.""" |
| 1096 if len(args) < 1: | 1107 if len(args) < 1: |
| 1097 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) | 1108 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) |
| 1098 | 1109 |
| 1099 def kill_simulator(): | 1110 def kill_simulator(): |
| 1100 chromium_utils.RunCommand(['/usr/bin/killall', 'iPhone Simulator']) | 1111 chromium_utils.RunCommand(['/usr/bin/killall', 'iPhone Simulator']) |
| 1101 | 1112 |
| 1102 # For iOS tests, the args come in in the following order: | 1113 # For iOS tests, the args come in in the following order: |
| 1103 # [0] test display name formatted as 'test_name (device[ ios_version])' | 1114 # [0] test display name formatted as 'test_name (device[ ios_version])' |
| 1104 # [1:] gtest args (e.g. --gtest_print_time) | 1115 # [1:] gtest args (e.g. --gtest_print_time) |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1275 command = [sys.executable, test_exe] | 1286 command = [sys.executable, test_exe] |
| 1276 else: | 1287 else: |
| 1277 command = [test_exe_path] | 1288 command = [test_exe_path] |
| 1278 if options.annotate == 'gtest': | 1289 if options.annotate == 'gtest': |
| 1279 command.extend(['--brave-new-test-launcher', '--test-launcher-bot-mode']) | 1290 command.extend(['--brave-new-test-launcher', '--test-launcher-bot-mode']) |
| 1280 command.extend(args[1:]) | 1291 command.extend(args[1:]) |
| 1281 | 1292 |
| 1282 # If --annotate=list was passed, list the log parser classes and exit. | 1293 # If --annotate=list was passed, list the log parser classes and exit. |
| 1283 if _ListParsers(options.annotate): | 1294 if _ListParsers(options.annotate): |
| 1284 return 0 | 1295 return 0 |
| 1285 tracker_class = _SelectResultsTracker(options) | 1296 tracker_class = _SelectResultsTracker(options, test_exe) |
| 1286 results_tracker = _CreateResultsTracker(tracker_class, options) | 1297 results_tracker = _CreateResultsTracker(tracker_class, options) |
| 1287 | 1298 |
| 1288 if options.generate_json_file: | 1299 if options.generate_json_file: |
| 1289 if os.path.exists(options.test_output_xml): | 1300 if os.path.exists(options.test_output_xml): |
| 1290 # remove the old XML output file. | 1301 # remove the old XML output file. |
| 1291 os.remove(options.test_output_xml) | 1302 os.remove(options.test_output_xml) |
| 1292 | 1303 |
| 1293 try: | 1304 try: |
| 1294 start_xvfb = False | 1305 start_xvfb = False |
| 1295 http_server = None | 1306 http_server = None |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1424 '--'] + command | 1435 '--'] + command |
| 1425 command.extend(args[1:]) | 1436 command.extend(args[1:]) |
| 1426 | 1437 |
| 1427 # Nuke anything that appears to be stale chrome items in the temporary | 1438 # Nuke anything that appears to be stale chrome items in the temporary |
| 1428 # directory from previous test runs (i.e.- from crashes or unittest leaks). | 1439 # directory from previous test runs (i.e.- from crashes or unittest leaks). |
| 1429 slave_utils.RemoveChromeTemporaryFiles() | 1440 slave_utils.RemoveChromeTemporaryFiles() |
| 1430 | 1441 |
| 1431 # If --annotate=list was passed, list the log parser classes and exit. | 1442 # If --annotate=list was passed, list the log parser classes and exit. |
| 1432 if _ListParsers(options.annotate): | 1443 if _ListParsers(options.annotate): |
| 1433 return 0 | 1444 return 0 |
| 1434 tracker_class = _SelectResultsTracker(options) | 1445 tracker_class = _SelectResultsTracker(options, test_exe) |
| 1435 results_tracker = _CreateResultsTracker(tracker_class, options) | 1446 results_tracker = _CreateResultsTracker(tracker_class, options) |
| 1436 | 1447 |
| 1437 if options.generate_json_file: | 1448 if options.generate_json_file: |
| 1438 if os.path.exists(options.test_output_xml): | 1449 if os.path.exists(options.test_output_xml): |
| 1439 # remove the old XML output file. | 1450 # remove the old XML output file. |
| 1440 os.remove(options.test_output_xml) | 1451 os.remove(options.test_output_xml) |
| 1441 | 1452 |
| 1442 try: | 1453 try: |
| 1443 http_server = None | 1454 http_server = None |
| 1444 if options.document_root: | 1455 if options.document_root: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1482 options.test_type, options.results_url, options.build_dir, | 1493 options.test_type, options.results_url, options.build_dir, |
| 1483 options.build_properties.get('mastername'), | 1494 options.build_properties.get('mastername'), |
| 1484 options.build_properties.get('buildername'), | 1495 options.build_properties.get('buildername'), |
| 1485 options.build_properties.get('buildnumber'), | 1496 options.build_properties.get('buildnumber'), |
| 1486 options.supplemental_columns_file, | 1497 options.supplemental_columns_file, |
| 1487 options.perf_config) | 1498 options.perf_config) |
| 1488 | 1499 |
| 1489 return result | 1500 return result |
| 1490 | 1501 |
| 1491 | 1502 |
| 1492 def _MainAndroid(options, args, extra_env): | 1503 def _MainAndroid(options, args, extra_env): |
|
sullivan
2014/09/05 04:30:00
The command line looks different for Android, I th
ghost stip (do not use)
2014/09/05 21:39:06
Android uses a far different way of invoking tests
| |
| 1493 """Runs tests on android. | 1504 """Runs tests on android. |
| 1494 | 1505 |
| 1495 Running GTest-based tests on android is different than on Linux as it requires | 1506 Running GTest-based tests on android is different than on Linux as it requires |
| 1496 src/build/android/test_runner.py to deploy and communicate with the device. | 1507 src/build/android/test_runner.py to deploy and communicate with the device. |
| 1497 Python scripts are the same as with Linux. | 1508 Python scripts are the same as with Linux. |
| 1498 | 1509 |
| 1499 Args: | 1510 Args: |
| 1500 options: Command-line options for this invocation of runtest.py. | 1511 options: Command-line options for this invocation of runtest.py. |
| 1501 args: Command and arguments for the test. | 1512 args: Command and arguments for the test. |
| 1502 extra_env: A dictionary of extra environment variables to set. | 1513 extra_env: A dictionary of extra environment variables to set. |
| 1503 | 1514 |
| 1504 Returns: | 1515 Returns: |
| 1505 Exit status code. | 1516 Exit status code. |
| 1506 """ | 1517 """ |
| 1507 if options.run_python_script: | 1518 if options.run_python_script: |
| 1508 return _MainLinux(options, args, extra_env) | 1519 return _MainLinux(options, args, extra_env) |
| 1509 | 1520 |
| 1510 if len(args) < 1: | 1521 if len(args) < 1: |
| 1511 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) | 1522 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) |
| 1512 | 1523 |
| 1513 if _ListParsers(options.annotate): | 1524 if _ListParsers(options.annotate): |
| 1514 return 0 | 1525 return 0 |
| 1515 tracker_class = _SelectResultsTracker(options) | 1526 tracker_class = _SelectResultsTracker(options, None) |
| 1516 results_tracker = _CreateResultsTracker(tracker_class, options) | 1527 results_tracker = _CreateResultsTracker(tracker_class, options) |
| 1517 | 1528 |
| 1518 if options.generate_json_file: | 1529 if options.generate_json_file: |
| 1519 if os.path.exists(options.test_output_xml): | 1530 if os.path.exists(options.test_output_xml): |
| 1520 # remove the old XML output file. | 1531 # remove the old XML output file. |
| 1521 os.remove(options.test_output_xml) | 1532 os.remove(options.test_output_xml) |
| 1522 | 1533 |
| 1523 # Assume it's a gtest apk, so use the android harness. | 1534 # Assume it's a gtest apk, so use the android harness. |
| 1524 test_suite = args[0] | 1535 test_suite = args[0] |
| 1525 run_test_target_option = '--release' | 1536 run_test_target_option = '--release' |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1949 finally: | 1960 finally: |
| 1950 if did_launch_dbus: | 1961 if did_launch_dbus: |
| 1951 # It looks like the command line argument --exit-with-session | 1962 # It looks like the command line argument --exit-with-session |
| 1952 # isn't working to clean up the spawned dbus-daemon. Kill it | 1963 # isn't working to clean up the spawned dbus-daemon. Kill it |
| 1953 # manually. | 1964 # manually. |
| 1954 _ShutdownDBus() | 1965 _ShutdownDBus() |
| 1955 | 1966 |
| 1956 | 1967 |
| 1957 if '__main__' == __name__: | 1968 if '__main__' == __name__: |
| 1958 sys.exit(main()) | 1969 sys.exit(main()) |
| OLD | NEW |