| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Runs all types of tests from one unified interface. | 7 """Runs all types of tests from one unified interface. |
| 8 | 8 |
| 9 TODO(gkanwar): | 9 TODO(gkanwar): |
| 10 * Add options to run Monkey tests. | 10 * Add options to run Monkey tests. |
| 11 """ | 11 """ |
| 12 | 12 |
| 13 import collections | 13 import collections |
| 14 import optparse | 14 import optparse |
| 15 import os | 15 import os |
| 16 import shutil | 16 import shutil |
| 17 import sys | 17 import sys |
| 18 | 18 |
| 19 from pylib import cmd_helper | |
| 20 from pylib import constants | 19 from pylib import constants |
| 21 from pylib import ports | 20 from pylib import ports |
| 22 from pylib.base import base_test_result | 21 from pylib.base import base_test_result |
| 23 from pylib.base import test_dispatcher | 22 from pylib.base import test_dispatcher |
| 24 from pylib.browsertests import setup as browsertests_setup | 23 from pylib.browsertests import setup as browsertests_setup |
| 24 from pylib.gtest import gtest_config |
| 25 from pylib.gtest import setup as gtest_setup | 25 from pylib.gtest import setup as gtest_setup |
| 26 from pylib.gtest import gtest_config | |
| 27 from pylib.host_driven import run_python_tests as python_dispatch | 26 from pylib.host_driven import run_python_tests as python_dispatch |
| 28 from pylib.instrumentation import setup as instrumentation_setup | 27 from pylib.instrumentation import setup as instrumentation_setup |
| 28 from pylib.test_options import GTestOptions |
| 29 from pylib.test_options import InstrumentationOptions |
| 30 from pylib.test_options import UIAutomatorOptions |
| 29 from pylib.uiautomator import setup as uiautomator_setup | 31 from pylib.uiautomator import setup as uiautomator_setup |
| 30 from pylib.utils import report_results | 32 from pylib.utils import report_results |
| 31 from pylib.utils import run_tests_helper | 33 from pylib.utils import run_tests_helper |
| 32 | 34 |
| 33 | 35 |
| 34 _SDK_OUT_DIR = os.path.join(constants.DIR_SOURCE_ROOT, 'out') | 36 _SDK_OUT_DIR = os.path.join(constants.DIR_SOURCE_ROOT, 'out') |
| 35 | 37 |
| 36 | 38 |
| 37 def AddBuildTypeOption(option_parser): | 39 def AddBuildTypeOption(option_parser): |
| 38 """Adds the build type option to |option_parser|.""" | 40 """Adds the build type option to |option_parser|.""" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 # TODO(gkanwar): Move these to Common Options once we have the plumbing | 143 # TODO(gkanwar): Move these to Common Options once we have the plumbing |
| 142 # in our other test types to handle these commands | 144 # in our other test types to handle these commands |
| 143 AddCommonOptions(option_parser) | 145 AddCommonOptions(option_parser) |
| 144 | 146 |
| 145 | 147 |
| 146 def ProcessGTestOptions(options): | 148 def ProcessGTestOptions(options): |
| 147 """Intercept test suite help to list test suites. | 149 """Intercept test suite help to list test suites. |
| 148 | 150 |
| 149 Args: | 151 Args: |
| 150 options: Command line options. | 152 options: Command line options. |
| 151 | |
| 152 Returns: | |
| 153 True if the command should continue. | |
| 154 """ | 153 """ |
| 155 if options.suite_name == 'help': | 154 if options.suite_name == 'help': |
| 156 print 'Available test suites are:' | 155 print 'Available test suites are:' |
| 157 for test_suite in gtest_config.STABLE_TEST_SUITES: | 156 for test_suite in gtest_config.STABLE_TEST_SUITES: |
| 158 print test_suite.name | 157 print test_suite.name |
| 159 return False | 158 sys.exit(0) |
| 160 | 159 |
| 161 # Convert to a list, assuming all test suites if nothing was specified. | 160 # Convert to a list, assuming all test suites if nothing was specified. |
| 162 # TODO(gkanwar): Require having a test suite | 161 # TODO(gkanwar): Require having a test suite |
| 163 if options.suite_name: | 162 if options.suite_name: |
| 164 options.suite_name = [options.suite_name] | 163 options.suite_name = [options.suite_name] |
| 165 else: | 164 else: |
| 166 options.suite_name = [suite.name | 165 options.suite_name = [suite.name |
| 167 for suite in gtest_config.STABLE_TEST_SUITES] | 166 for suite in gtest_config.STABLE_TEST_SUITES] |
| 168 return True | |
| 169 | 167 |
| 170 | 168 |
| 171 def AddJavaTestOptions(option_parser): | 169 def AddJavaTestOptions(option_parser): |
| 172 """Adds the Java test options to |option_parser|.""" | 170 """Adds the Java test options to |option_parser|.""" |
| 173 | 171 |
| 174 option_parser.add_option('-f', '--test_filter', dest='test_filter', | 172 option_parser.add_option('-f', '--test_filter', dest='test_filter', |
| 175 help=('Test filter (if not fully qualified, ' | 173 help=('Test filter (if not fully qualified, ' |
| 176 'will run all matches).')) | 174 'will run all matches).')) |
| 177 option_parser.add_option( | 175 option_parser.add_option( |
| 178 '-A', '--annotation', dest='annotation_str', | 176 '-A', '--annotation', dest='annotation_str', |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 option_parser.add_option('-I', dest='install_apk', action='store_true', | 266 option_parser.add_option('-I', dest='install_apk', action='store_true', |
| 269 help='Install test APK.') | 267 help='Install test APK.') |
| 270 option_parser.add_option( | 268 option_parser.add_option( |
| 271 '--test-apk', dest='test_apk', | 269 '--test-apk', dest='test_apk', |
| 272 help=('The name of the apk containing the tests ' | 270 help=('The name of the apk containing the tests ' |
| 273 '(without the .apk extension; e.g. "ContentShellTest"). ' | 271 '(without the .apk extension; e.g. "ContentShellTest"). ' |
| 274 'Alternatively, this can be a full path to the apk.')) | 272 'Alternatively, this can be a full path to the apk.')) |
| 275 | 273 |
| 276 | 274 |
| 277 def ProcessInstrumentationOptions(options, error_func): | 275 def ProcessInstrumentationOptions(options, error_func): |
| 278 """Processes options/arguments and populate |options| with defaults.""" | 276 """Processes options/arguments and populate |options| with defaults. |
| 277 |
| 278 Args: |
| 279 options: optparse.Options object. |
| 280 error_func: Function to call with the error message in case of an error. |
| 281 |
| 282 Returns: |
| 283 An InstrumentationOptions named tuple which contains all options relevant to |
| 284 instrumentation tests. |
| 285 """ |
| 279 | 286 |
| 280 ProcessJavaTestOptions(options, error_func) | 287 ProcessJavaTestOptions(options, error_func) |
| 281 | 288 |
| 282 if not options.test_apk: | 289 if not options.test_apk: |
| 283 error_func('--test-apk must be specified.') | 290 error_func('--test-apk must be specified.') |
| 284 | 291 |
| 285 if os.path.exists(options.test_apk): | 292 if os.path.exists(options.test_apk): |
| 286 # The APK is fully qualified, assume the JAR lives along side. | 293 # The APK is fully qualified, assume the JAR lives along side. |
| 287 options.test_apk_path = options.test_apk | 294 options.test_apk_path = options.test_apk |
| 288 options.test_apk_jar_path = (os.path.splitext(options.test_apk_path)[0] + | 295 options.test_apk_jar_path = (os.path.splitext(options.test_apk_path)[0] + |
| 289 '.jar') | 296 '.jar') |
| 290 else: | 297 else: |
| 291 options.test_apk_path = os.path.join(_SDK_OUT_DIR, | 298 options.test_apk_path = os.path.join(_SDK_OUT_DIR, |
| 292 options.build_type, | 299 options.build_type, |
| 293 constants.SDK_BUILD_APKS_DIR, | 300 constants.SDK_BUILD_APKS_DIR, |
| 294 '%s.apk' % options.test_apk) | 301 '%s.apk' % options.test_apk) |
| 295 options.test_apk_jar_path = os.path.join( | 302 options.test_apk_jar_path = os.path.join( |
| 296 _SDK_OUT_DIR, options.build_type, constants.SDK_BUILD_TEST_JAVALIB_DIR, | 303 _SDK_OUT_DIR, options.build_type, constants.SDK_BUILD_TEST_JAVALIB_DIR, |
| 297 '%s.jar' % options.test_apk) | 304 '%s.jar' % options.test_apk) |
| 298 | 305 |
| 306 return InstrumentationOptions(options.build_type, |
| 307 options.annotations, |
| 308 options.exclude_annotations, |
| 309 options.test_filter, |
| 310 options.test_data, |
| 311 options.save_perf_json, |
| 312 options.screenshot_failures, |
| 313 options.tool, |
| 314 options.disable_assertions, |
| 315 options.push_deps, |
| 316 options.cleanup_test_files, |
| 317 options.wait_for_debugger, |
| 318 options.install_apk, |
| 319 options.test_apk, |
| 320 options.test_apk_path, |
| 321 options.test_apk_jar_path) |
| 322 |
| 299 | 323 |
| 300 def AddUIAutomatorTestOptions(option_parser): | 324 def AddUIAutomatorTestOptions(option_parser): |
| 301 """Adds UI Automator test options to |option_parser|.""" | 325 """Adds UI Automator test options to |option_parser|.""" |
| 302 | 326 |
| 303 option_parser.usage = '%prog uiautomator [options]' | 327 option_parser.usage = '%prog uiautomator [options]' |
| 304 option_parser.command_list = [] | 328 option_parser.command_list = [] |
| 305 option_parser.example = ( | 329 option_parser.example = ( |
| 306 '%prog uiautomator --test-jar=chromium_testshell_uiautomator_tests' | 330 '%prog uiautomator --test-jar=chromium_testshell_uiautomator_tests' |
| 307 ' --package-name=org.chromium.chrome.testshell') | 331 ' --package-name=org.chromium.chrome.testshell') |
| 308 option_parser.add_option( | 332 option_parser.add_option( |
| 309 '--package-name', | 333 '--package-name', |
| 310 help='The package name used by the apk containing the application.') | 334 help='The package name used by the apk containing the application.') |
| 311 option_parser.add_option( | 335 option_parser.add_option( |
| 312 '--test-jar', dest='test_jar', | 336 '--test-jar', dest='test_jar', |
| 313 help=('The name of the dexed jar containing the tests (without the ' | 337 help=('The name of the dexed jar containing the tests (without the ' |
| 314 '.dex.jar extension). Alternatively, this can be a full path ' | 338 '.dex.jar extension). Alternatively, this can be a full path ' |
| 315 'to the jar.')) | 339 'to the jar.')) |
| 316 | 340 |
| 317 AddJavaTestOptions(option_parser) | 341 AddJavaTestOptions(option_parser) |
| 318 AddCommonOptions(option_parser) | 342 AddCommonOptions(option_parser) |
| 319 | 343 |
| 320 | 344 |
| 321 def ProcessUIAutomatorOptions(options, error_func): | 345 def ProcessUIAutomatorOptions(options, error_func): |
| 322 """Processes UIAutomator options/arguments.""" | 346 """Processes UIAutomator options/arguments. |
| 347 |
| 348 Args: |
| 349 options: optparse.Options object. |
| 350 error_func: Function to call with the error message in case of an error. |
| 351 |
| 352 Returns: |
| 353 A UIAutomatorOptions named tuple which contains all options relevant to |
| 354 instrumentation tests. |
| 355 """ |
| 323 | 356 |
| 324 ProcessJavaTestOptions(options, error_func) | 357 ProcessJavaTestOptions(options, error_func) |
| 325 | 358 |
| 326 if not options.package_name: | 359 if not options.package_name: |
| 327 error_func('--package-name must be specified.') | 360 error_func('--package-name must be specified.') |
| 328 | 361 |
| 329 if not options.test_jar: | 362 if not options.test_jar: |
| 330 error_func('--test-jar must be specified.') | 363 error_func('--test-jar must be specified.') |
| 331 | 364 |
| 332 if os.path.exists(options.test_jar): | 365 if os.path.exists(options.test_jar): |
| 333 # The dexed JAR is fully qualified, assume the info JAR lives along side. | 366 # The dexed JAR is fully qualified, assume the info JAR lives along side. |
| 334 options.uiautomator_jar = options.test_jar | 367 options.uiautomator_jar = options.test_jar |
| 335 else: | 368 else: |
| 336 options.uiautomator_jar = os.path.join( | 369 options.uiautomator_jar = os.path.join( |
| 337 _SDK_OUT_DIR, options.build_type, constants.SDK_BUILD_JAVALIB_DIR, | 370 _SDK_OUT_DIR, options.build_type, constants.SDK_BUILD_JAVALIB_DIR, |
| 338 '%s.dex.jar' % options.test_jar) | 371 '%s.dex.jar' % options.test_jar) |
| 339 options.uiautomator_info_jar = ( | 372 options.uiautomator_info_jar = ( |
| 340 options.uiautomator_jar[:options.uiautomator_jar.find('.dex.jar')] + | 373 options.uiautomator_jar[:options.uiautomator_jar.find('.dex.jar')] + |
| 341 '_java.jar') | 374 '_java.jar') |
| 342 | 375 |
| 376 return UIAutomatorOptions(options.build_type, |
| 377 options.annotations, |
| 378 options.exclude_annotations, |
| 379 options.test_filter, |
| 380 options.test_data, |
| 381 options.save_perf_json, |
| 382 options.screenshot_failures, |
| 383 options.tool, |
| 384 options.disable_assertions, |
| 385 options.push_deps, |
| 386 options.cleanup_test_files, |
| 387 options.uiautomator_jar, |
| 388 options.uiautomator_info_jar, |
| 389 options.package_name) |
| 390 |
| 343 | 391 |
| 344 def _RunGTests(options, error_func): | 392 def _RunGTests(options, error_func): |
| 345 """Subcommand of RunTestsCommands which runs gtests.""" | 393 """Subcommand of RunTestsCommands which runs gtests.""" |
| 346 if not ProcessGTestOptions(options): | 394 ProcessGTestOptions(options) |
| 347 return 0 | |
| 348 | 395 |
| 349 exit_code = 0 | 396 exit_code = 0 |
| 350 for suite_name in options.suite_name: | 397 for suite_name in options.suite_name: |
| 351 runner_factory, tests = gtest_setup.Setup( | 398 # TODO(gkanwar): Move this into ProcessGTestOptions once we require -s for |
| 352 options.exe, suite_name, options.test_arguments, | 399 # the gtest command. |
| 353 options.timeout, options.cleanup_test_files, options.tool, | 400 gtest_options = GTestOptions(options.build_type, |
| 354 options.build_type, options.push_deps, options.test_filter) | 401 options.tool, |
| 402 options.cleanup_test_files, |
| 403 options.push_deps, |
| 404 options.test_filter, |
| 405 options.test_arguments, |
| 406 options.exe, |
| 407 options.timeout, |
| 408 suite_name) |
| 409 runner_factory, tests = gtest_setup.Setup(gtest_options) |
| 355 | 410 |
| 356 results, test_exit_code = test_dispatcher.RunTests( | 411 results, test_exit_code = test_dispatcher.RunTests( |
| 357 tests, runner_factory, False, options.test_device, | 412 tests, runner_factory, False, options.test_device, |
| 358 shard=True, | 413 shard=True, |
| 359 build_type=options.build_type, | 414 build_type=options.build_type, |
| 360 test_timeout=None, | 415 test_timeout=None, |
| 361 num_retries=options.num_retries) | 416 num_retries=options.num_retries) |
| 362 | 417 |
| 363 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE: | 418 if test_exit_code and exit_code != constants.ERROR_EXIT_CODE: |
| 364 exit_code = test_exit_code | 419 exit_code = test_exit_code |
| 365 | 420 |
| 366 report_results.LogFull( | 421 report_results.LogFull( |
| 367 results=results, | 422 results=results, |
| 368 test_type='Unit test', | 423 test_type='Unit test', |
| 369 test_package=suite_name, | 424 test_package=suite_name, |
| 370 build_type=options.build_type, | 425 build_type=options.build_type, |
| 371 flakiness_server=options.flakiness_dashboard_server) | 426 flakiness_server=options.flakiness_dashboard_server) |
| 372 | 427 |
| 373 if os.path.isdir(constants.ISOLATE_DEPS_DIR): | 428 if os.path.isdir(constants.ISOLATE_DEPS_DIR): |
| 374 shutil.rmtree(constants.ISOLATE_DEPS_DIR) | 429 shutil.rmtree(constants.ISOLATE_DEPS_DIR) |
| 375 | 430 |
| 376 return exit_code | 431 return exit_code |
| 377 | 432 |
| 378 | 433 |
| 379 def _RunContentBrowserTests(options, error_func): | 434 def _RunContentBrowserTests(options, error_func): |
| 380 """Subcommand of RunTestsCommands which runs content_browsertests.""" | 435 """Subcommand of RunTestsCommands which runs content_browsertests.""" |
| 381 runner_factory, tests = browsertests_setup.Setup( | 436 gtest_options = GTestOptions(options.build_type, |
| 382 options.test_arguments, options.timeout, options.cleanup_test_files, | 437 options.tool, |
| 383 options.tool, options.build_type, options.push_deps, | 438 options.cleanup_test_files, |
| 384 options.test_filter) | 439 options.push_deps, |
| 440 options.test_filter, |
| 441 options.test_arguments, |
| 442 options.exe, |
| 443 options.timeout, |
| 444 constants.BROWSERTEST_SUITE_NAME) |
| 445 runner_factory, tests = browsertests_setup.Setup(gtest_options) |
| 385 | 446 |
| 386 # TODO(nileshagrawal): remove this abnormally long setup timeout once fewer | 447 # TODO(nileshagrawal): remove this abnormally long setup timeout once fewer |
| 387 # files are pushed to the devices for content_browsertests: crbug.com/138275 | 448 # files are pushed to the devices for content_browsertests: crbug.com/138275 |
| 388 setup_timeout = 20 * 60 # 20 minutes | 449 setup_timeout = 20 * 60 # 20 minutes |
| 389 results, exit_code = test_dispatcher.RunTests( | 450 results, exit_code = test_dispatcher.RunTests( |
| 390 tests, runner_factory, False, options.test_device, | 451 tests, runner_factory, False, options.test_device, |
| 391 shard=True, | 452 shard=True, |
| 392 build_type=options.build_type, | 453 build_type=options.build_type, |
| 393 test_timeout=None, | 454 test_timeout=None, |
| 394 setup_timeout=setup_timeout, | 455 setup_timeout=setup_timeout, |
| 395 num_retries=options.num_retries) | 456 num_retries=options.num_retries) |
| 396 | 457 |
| 397 report_results.LogFull( | 458 report_results.LogFull( |
| 398 results=results, | 459 results=results, |
| 399 test_type='Unit test', | 460 test_type='Unit test', |
| 400 test_package=constants.BROWSERTEST_SUITE_NAME, | 461 test_package=constants.BROWSERTEST_SUITE_NAME, |
| 401 build_type=options.build_type, | 462 build_type=options.build_type, |
| 402 flakiness_server=options.flakiness_dashboard_server) | 463 flakiness_server=options.flakiness_dashboard_server) |
| 403 | 464 |
| 404 if os.path.isdir(constants.ISOLATE_DEPS_DIR): | 465 if os.path.isdir(constants.ISOLATE_DEPS_DIR): |
| 405 shutil.rmtree(constants.ISOLATE_DEPS_DIR) | 466 shutil.rmtree(constants.ISOLATE_DEPS_DIR) |
| 406 | 467 |
| 407 return exit_code | 468 return exit_code |
| 408 | 469 |
| 409 | 470 |
| 410 def _RunInstrumentationTests(options, error_func): | 471 def _RunInstrumentationTests(options, error_func): |
| 411 """Subcommand of RunTestsCommands which runs instrumentation tests.""" | 472 """Subcommand of RunTestsCommands which runs instrumentation tests.""" |
| 412 ProcessInstrumentationOptions(options, error_func) | 473 instrumentation_options = ProcessInstrumentationOptions(options, error_func) |
| 413 | 474 |
| 414 results = base_test_result.TestRunResults() | 475 results = base_test_result.TestRunResults() |
| 415 exit_code = 0 | 476 exit_code = 0 |
| 416 | 477 |
| 417 if options.run_java_tests: | 478 if options.run_java_tests: |
| 418 runner_factory, tests = instrumentation_setup.Setup( | 479 runner_factory, tests = instrumentation_setup.Setup(instrumentation_options) |
| 419 options.test_apk_path, options.test_apk_jar_path, options.annotations, | |
| 420 options.exclude_annotations, options.test_filter, options.build_type, | |
| 421 options.test_data, options.install_apk, options.save_perf_json, | |
| 422 options.screenshot_failures, options.tool, options.wait_for_debugger, | |
| 423 options.disable_assertions, options.push_deps, | |
| 424 options.cleanup_test_files) | |
| 425 | 480 |
| 426 test_results, exit_code = test_dispatcher.RunTests( | 481 test_results, exit_code = test_dispatcher.RunTests( |
| 427 tests, runner_factory, options.wait_for_debugger, | 482 tests, runner_factory, options.wait_for_debugger, |
| 428 options.test_device, | 483 options.test_device, |
| 429 shard=True, | 484 shard=True, |
| 430 build_type=options.build_type, | 485 build_type=options.build_type, |
| 431 test_timeout=None, | 486 test_timeout=None, |
| 432 num_retries=options.num_retries) | 487 num_retries=options.num_retries) |
| 433 | 488 |
| 434 results.AddTestRunResults(test_results) | 489 results.AddTestRunResults(test_results) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 449 test_package=os.path.basename(options.test_apk), | 504 test_package=os.path.basename(options.test_apk), |
| 450 annotation=options.annotations, | 505 annotation=options.annotations, |
| 451 build_type=options.build_type, | 506 build_type=options.build_type, |
| 452 flakiness_server=options.flakiness_dashboard_server) | 507 flakiness_server=options.flakiness_dashboard_server) |
| 453 | 508 |
| 454 return exit_code | 509 return exit_code |
| 455 | 510 |
| 456 | 511 |
| 457 def _RunUIAutomatorTests(options, error_func): | 512 def _RunUIAutomatorTests(options, error_func): |
| 458 """Subcommand of RunTestsCommands which runs uiautomator tests.""" | 513 """Subcommand of RunTestsCommands which runs uiautomator tests.""" |
| 459 ProcessUIAutomatorOptions(options, error_func) | 514 uiautomator_options = ProcessUIAutomatorOptions(options, error_func) |
| 460 | 515 |
| 461 results = base_test_result.TestRunResults() | 516 results = base_test_result.TestRunResults() |
| 462 exit_code = 0 | 517 exit_code = 0 |
| 463 | 518 |
| 464 if options.run_java_tests: | 519 if options.run_java_tests: |
| 465 runner_factory, tests = uiautomator_setup.Setup( | 520 runner_factory, tests = uiautomator_setup.Setup(uiautomator_options) |
| 466 options.uiautomator_jar, options.uiautomator_info_jar, | |
| 467 options.annotations, options.exclude_annotations, options.test_filter, | |
| 468 options.package_name, options.build_type, options.test_data, | |
| 469 options.save_perf_json, options.screenshot_failures, options.tool, | |
| 470 options.disable_assertions, options.push_deps, | |
| 471 options.cleanup_test_files) | |
| 472 | 521 |
| 473 test_results, exit_code = test_dispatcher.RunTests( | 522 test_results, exit_code = test_dispatcher.RunTests( |
| 474 tests, runner_factory, False, options.test_device, | 523 tests, runner_factory, False, options.test_device, |
| 475 shard=True, | 524 shard=True, |
| 476 build_type=options.build_type, | 525 build_type=options.build_type, |
| 477 test_timeout=None, | 526 test_timeout=None, |
| 478 num_retries=options.num_retries) | 527 num_retries=options.num_retries) |
| 479 | 528 |
| 480 results.AddTestRunResults(test_results) | 529 results.AddTestRunResults(test_results) |
| 481 | 530 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 return 0 | 683 return 0 |
| 635 command = argv[1] | 684 command = argv[1] |
| 636 VALID_COMMANDS[command].add_options_func(option_parser) | 685 VALID_COMMANDS[command].add_options_func(option_parser) |
| 637 options, args = option_parser.parse_args(argv) | 686 options, args = option_parser.parse_args(argv) |
| 638 return VALID_COMMANDS[command].run_command_func( | 687 return VALID_COMMANDS[command].run_command_func( |
| 639 command, options, args, option_parser) | 688 command, options, args, option_parser) |
| 640 | 689 |
| 641 | 690 |
| 642 if __name__ == '__main__': | 691 if __name__ == '__main__': |
| 643 sys.exit(main(sys.argv)) | 692 sys.exit(main(sys.argv)) |
| OLD | NEW |