diff options
author | vrachev <vlad.rachev@mongodb.com> | 2020-05-06 09:46:35 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-12 17:55:40 +0000 |
commit | bc8faeeeefe9e6663598b161ced59d41be71f2b8 (patch) | |
tree | 17ffff0cb33252e5087d94af2710503edf277f8b /buildscripts | |
parent | 9c1ce38d7c87f625be1c2d5d7f5a6b709ebfb72e (diff) | |
download | mongo-bc8faeeeefe9e6663598b161ced59d41be71f2b8.tar.gz |
SERVER-47611 Re-work to_local_args function using argparse
(cherry picked from commit ece056a4cd1eba70a47f88d6d5fd2ba38e7d4df0)
Diffstat (limited to 'buildscripts')
-rw-r--r-- | buildscripts/resmokelib/commands/run.py | 12 | ||||
-rw-r--r-- | buildscripts/resmokelib/parser.py | 304 | ||||
-rw-r--r-- | buildscripts/tests/resmokelib/test_parser.py | 76 |
3 files changed, 231 insertions, 161 deletions
diff --git a/buildscripts/resmokelib/commands/run.py b/buildscripts/resmokelib/commands/run.py index 4d876a0047a..0d8fe334597 100644 --- a/buildscripts/resmokelib/commands/run.py +++ b/buildscripts/resmokelib/commands/run.py @@ -22,6 +22,7 @@ except ImportError: from buildscripts.resmokelib import config from buildscripts.resmokelib import errors from buildscripts.resmokelib import logging +from buildscripts.resmokelib import parser from buildscripts.resmokelib import reportfile from buildscripts.resmokelib import sighandler from buildscripts.resmokelib import suitesconfig @@ -158,12 +159,11 @@ class TestRunner(interface.Subcommand): # pylint: disable=too-many-instance-att """Run the suite and tests specified.""" self._resmoke_logger.info("verbatim resmoke.py invocation: %s", " ".join(sys.argv)) - # TODO: SERVER-47611 - # if config.EVERGREEN_TASK_ID: - # local_args = parser.to_local_args() - # self._resmoke_logger.info("resmoke.py invocation for local usage: %s %s", - # os.path.join("buildscripts", "resmoke.py"), - # " ".join(local_args)) + if config.EVERGREEN_TASK_ID: + local_args = parser.to_local_args() + self._resmoke_logger.info("resmoke.py invocation for local usage: %s %s", + os.path.join("buildscripts", "resmoke.py"), + " ".join(local_args)) suites = None try: diff --git a/buildscripts/resmokelib/parser.py b/buildscripts/resmokelib/parser.py index 4e155e851da..b3e8dcc285a 100644 --- a/buildscripts/resmokelib/parser.py +++ b/buildscripts/resmokelib/parser.py @@ -10,6 +10,8 @@ from . import config as _config from . import configure_resmoke from . import commands +_INTERNAL_OPTIONS_TITLE = "Internal Options" +_BENCHMARK_ARGUMENT_TITLE = "Benchmark/Benchrun test options" _EVERGREEN_ARGUMENT_TITLE = "Evergreen options" @@ -59,32 +61,11 @@ def _add_run(subparsers): # pylint: disable=too-many-statements " passed in from test files may cause an error.")) parser.add_argument( - "--archiveFile", dest="archive_file", metavar="ARCHIVE_FILE", - help=("Sets the archive file name for the Evergreen task running the tests." - " The archive file is JSON format containing a list of tests that were" - " successfully archived to S3. If unspecified, no data files from tests" - " will be archived in S3. Tests can be designated for archival in the" - " task suite configuration file.")) - - parser.add_argument( - "--archiveLimitMb", type=int, dest="archive_limit_mb", metavar="ARCHIVE_LIMIT_MB", - help=("Sets the limit (in MB) for archived files to S3. A value of 0" - " indicates there is no limit.")) - - parser.add_argument( - "--archiveLimitTests", type=int, dest="archive_limit_tests", metavar="ARCHIVE_LIMIT_TESTS", - help=("Sets the maximum number of tests to archive to S3. A value" - " of 0 indicates there is no limit.")) - - parser.add_argument( "--basePort", dest="base_port", metavar="PORT", help=("The starting port number to use for mongod and mongos processes" " spawned by resmoke.py or the tests themselves. Each fixture and Job" " allocates a contiguous range of ports.")) - parser.add_argument("--buildloggerUrl", action="store", dest="buildlogger_url", metavar="URL", - help="The root url of the buildlogger server.") - parser.add_argument("--continueOnFailure", action="store_true", dest="continue_on_failure", help="Executes all tests in all suites, even if some of them fail.") @@ -130,11 +111,6 @@ def _add_run(subparsers): # pylint: disable=too-many-statements help=("The number of Job instances to use. Each instance will receive its" " own MongoDB deployment to dispatch tests to.")) - parser.add_argument( - "--log", dest="logger_file", metavar="LOGGER", - help=("A YAML file that specifies the logging configuration. If the file is" - " located in the resmokeconfig/suites/ directory, then the basename" - " without the .yml extension can be specified, e.g. 'console'.")) parser.set_defaults(logger_file="console") parser.add_argument("--mongo", dest="mongo_executable", metavar="PATH", @@ -166,9 +142,6 @@ def _add_run(subparsers): # pylint: disable=too-many-statements parser.add_argument("--numClientsPerFixture", type=int, dest="num_clients_per_fixture", help="Number of clients running tests per fixture.") - parser.add_argument("--perfReportFile", dest="perf_report_file", metavar="PERF_REPORT", - help="Writes a JSON file with performance test results.") - parser.add_argument( "--shellConnString", dest="shell_conn_string", metavar="CONN_STRING", help="Overrides the default fixture and connects with a mongodb:// connection" @@ -211,16 +184,6 @@ def _add_run(subparsers): # pylint: disable=too-many-statements " command line.") parser.add_argument( - "--reportFailureStatus", action="store", dest="report_failure_status", - choices=("fail", "silentfail"), metavar="STATUS", - help="Controls if the test failure status should be reported as failed" - " or be silently ignored (STATUS=silentfail). Dynamic test failures will" - " never be silently ignored. Defaults to STATUS=%%default.") - - parser.add_argument("--reportFile", dest="report_file", metavar="REPORT", - help="Writes a JSON file with test status and timing information.") - - parser.add_argument( "--seed", type=int, dest="seed", metavar="SEED", help=("Seed for the random number generator. Useful in combination with the" " --shuffle option for producing a consistent test execution order.")) @@ -252,11 +215,6 @@ def _add_run(subparsers): # pylint: disable=too-many-statements " all cases except when the number of jobs requested is 1.")) parser.add_argument( - "--staggerJobs", action="store", dest="stagger_jobs", choices=("on", "off"), - metavar="ON|OFF", help=("Enables or disables the stagger of launching resmoke jobs." - " Defaults to %%default.")) - - parser.add_argument( "--majorityReadConcern", action="store", dest="majority_read_concern", choices=("on", "off"), metavar="ON|OFF", help=("Enable or disable majority read concern support." @@ -286,9 +244,6 @@ def _add_run(subparsers): # pylint: disable=too-many-statements parser.add_argument("--numShards", type=int, dest="num_shards", metavar="N", help="The number of shards to use in a ShardedClusterFixture.") - parser.add_argument("--tagFile", dest="tag_file", metavar="OPTIONS", - help="A YAML file that associates tests and tags.") - parser.add_argument( "--wiredTigerCollectionConfigString", dest="wt_coll_config", metavar="CONFIG", help="Sets the WiredTiger collection configuration setting for all mongod's.") @@ -316,14 +271,70 @@ def _add_run(subparsers): # pylint: disable=too-many-statements metavar="ON|OFF", help="Enable or disable linear chaining for tests using " "ReplicaSetFixture.") + internal_options = parser.add_argument_group( + title=_INTERNAL_OPTIONS_TITLE, + description=("Internal options for advanced users and resmoke developers." + " These are not meant to be invoked when running resmoke locally.")) + + internal_options.add_argument( + "--log", dest="logger_file", metavar="LOGGER", + help=("A YAML file that specifies the logging configuration. If the file is" + " located in the resmokeconfig/suites/ directory, then the basename" + " without the .yml extension can be specified, e.g. 'console'.")) + + # Used for testing resmoke. Do not set this. + internal_options.add_argument("--internalParam", action="append", dest="internal_params", + help=argparse.SUPPRESS) + + internal_options.add_argument("--perfReportFile", dest="perf_report_file", + metavar="PERF_REPORT", + help="Writes a JSON file with performance test results.") + + internal_options.add_argument( + "--reportFailureStatus", action="store", dest="report_failure_status", + choices=("fail", "silentfail"), metavar="STATUS", + help="Controls if the test failure status should be reported as failed" + " or be silently ignored (STATUS=silentfail). Dynamic test failures will" + " never be silently ignored. Defaults to STATUS=%%default.") + + internal_options.add_argument( + "--reportFile", dest="report_file", metavar="REPORT", + help="Writes a JSON file with test status and timing information.") + + internal_options.add_argument( + "--staggerJobs", action="store", dest="stagger_jobs", choices=("on", "off"), + metavar="ON|OFF", help=("Enables or disables the stagger of launching resmoke jobs." + " Defaults to %%default.")) + evergreen_options = parser.add_argument_group( title=_EVERGREEN_ARGUMENT_TITLE, description=("Options used to propagate information about the Evergreen task running this" " script.")) + evergreen_options.add_argument( + "--archiveFile", dest="archive_file", metavar="ARCHIVE_FILE", + help=("Sets the archive file name for the Evergreen task running the tests." + " The archive file is JSON format containing a list of tests that were" + " successfully archived to S3. If unspecified, no data files from tests" + " will be archived in S3. Tests can be designated for archival in the" + " task suite configuration file.")) + + evergreen_options.add_argument( + "--archiveLimitMb", type=int, dest="archive_limit_mb", metavar="ARCHIVE_LIMIT_MB", + help=("Sets the limit (in MB) for archived files to S3. A value of 0" + " indicates there is no limit.")) + + evergreen_options.add_argument( + "--archiveLimitTests", type=int, dest="archive_limit_tests", metavar="ARCHIVE_LIMIT_TESTS", + help=("Sets the maximum number of tests to archive to S3. A value" + " of 0 indicates there is no limit.")) + evergreen_options.add_argument("--buildId", dest="build_id", metavar="BUILD_ID", help="Sets the build ID of the task.") + evergreen_options.add_argument("--buildloggerUrl", action="store", dest="buildlogger_url", + metavar="URL", help="The root url of the buildlogger server.") + evergreen_options.add_argument( "--distroId", dest="distro_id", metavar="DISTRO_ID", help=("Sets the identifier for the Evergreen distro running the" @@ -360,6 +371,9 @@ def _add_run(subparsers): # pylint: disable=too-many-statements metavar="REVISION_ORDER_ID", help="Sets the chronological order number of this commit.") + evergreen_options.add_argument("--tagFile", dest="tag_file", metavar="OPTIONS", + help="A YAML file that associates tests and tags.") + evergreen_options.add_argument("--taskName", dest="task_name", metavar="TASK_NAME", help="Sets the name of the Evergreen task running the tests.") @@ -375,8 +389,7 @@ def _add_run(subparsers): # pylint: disable=too-many-statements help="Sets the version ID of the task.") benchmark_options = parser.add_argument_group( - title="Benchmark/Benchrun test options", - description="Options for running Benchmark/Benchrun tests") + title=_BENCHMARK_ARGUMENT_TITLE, description="Options for running Benchmark/Benchrun tests") benchmark_options.add_argument("--benchmarkFilter", type=str, dest="benchmark_filter", metavar="BENCHMARK_FILTER", @@ -424,17 +437,13 @@ def _add_find_suites(subparsers): parser = subparsers.add_parser( "find-suites", help="Lists the names of the suites that will execute the specified tests.") + # find-suites shares a lot of code with 'run' (for now), and this option needs be specified, + # though it is not used. parser.set_defaults(logger_file="console") parser.add_argument("test_files", metavar="TEST_FILES", nargs="*", help="Explicit test files to run") - parser.add_argument( - "--log", dest="logger_file", metavar="LOGGER", - help=("A YAML file that specifies the logging configuration. If the file is" - " located in the resmokeconfig/suites/ directory, then the basename" - " without the .yml extension can be specified, e.g. 'console'.")) - def _add_hang_analyzer(subparsers): """Create and add the parser for the hang analyzer subcommand.""" @@ -471,94 +480,103 @@ def _add_hang_analyzer(subparsers): " Python process's stdout.") -# def to_local_args(args=None): # pylint: disable=too-many-branches,too-many-locals -# """ -# Return a command line invocation for resmoke.py suitable for being run outside of Evergreen. -# This function parses the 'args' list of command line arguments, removes any Evergreen-centric -# options, and returns a new list of command line arguments. -# """ - -# if args is None: -# args = sys.argv[1:] - -# parser = _make_parser() - -# # We call optparse.OptionParser.parse_args() with a new instance of optparse.Values to avoid -# # having the default values filled in. This makes it so 'options' only contains command line -# # options that were explicitly specified. -# options, extra_args = parser.parse_args(args=args, values=optparse.Values()) - -# # If --originSuite was specified, then we replace the value of --suites with it. This is done to -# # avoid needing to have engineers learn about the test suites generated by the -# # evergreen_generate_resmoke_tasks.py script. -# origin_suite = getattr(options, "origin_suite", None) -# if origin_suite is not None: -# setattr(options, "suite_files", origin_suite) - -# # optparse.OptionParser doesn't offer a public and/or documented method for getting all of the -# # options. Given that the optparse module is deprecated, it is unlikely for the -# # _get_all_options() method to ever be removed or renamed. -# all_options = parser._get_all_options() # pylint: disable=protected-access - -# options_by_dest = {} -# for option in all_options: -# options_by_dest[option.dest] = option - -# suites_arg = None -# storage_engine_arg = None -# other_local_args = [] - -# options_to_ignore = { -# "--archiveLimitMb", -# "--archiveLimitTests", -# "--buildloggerUrl", -# "--log", -# "--perfReportFile", -# "--reportFailureStatus", -# "--reportFile", -# "--staggerJobs", -# "--tagFile", -# } - -# def format_option(option_name, option_value): -# """ -# Return <option_name>=<option_value>. -# This function assumes that 'option_name' is always "--" prefix and isn't "-" prefixed. -# """ -# return "%s=%s" % (option_name, option_value) - -# for option_dest in sorted(vars(options)): -# option_value = getattr(options, option_dest) -# option = options_by_dest[option_dest] -# option_name = option.get_opt_string() - -# if option_name in options_to_ignore: -# continue - -# option_group = parser.get_option_group(option_name) -# if option_group is not None and option_group.title == _EVERGREEN_OPTIONS_TITLE: -# continue - -# if option.takes_value(): -# if option.action == "append": -# args = [format_option(option_name, elem) for elem in option_value] -# other_local_args.extend(args) -# else: -# arg = format_option(option_name, option_value) - -# # We track the value for the --suites and --storageEngine command line options -# # separately in order to more easily sort them to the front. -# if option_dest == "suite_files": -# suites_arg = arg -# elif option_dest == "storage_engine": -# storage_engine_arg = arg -# else: -# other_local_args.append(arg) -# else: -# other_local_args.append(option_name) - -# return [arg for arg in (suites_arg, storage_engine_arg) if arg is not None -# ] + other_local_args + extra_args +def to_local_args(input_args=None): # pylint: disable=too-many-branches,too-many-locals + """ + Return a command line invocation for resmoke.py suitable for being run outside of Evergreen. + + This function parses the 'args' list of command line arguments, removes any Evergreen-centric + options, and returns a new list of command line arguments. + """ + + if input_args is None: + input_args = sys.argv[1:] + + if input_args[0] != 'run': + raise TypeError( + f"to_local_args can only be called for the 'run' subcommand. Instead was called on '{input_args[0]}'" + ) + + (parser, parsed_args) = _parse(input_args) + + # If --originSuite was specified, then we replace the value of --suites with it. This is done to + # avoid needing to have engineers learn about the test suites generated by the + # evergreen_generate_resmoke_tasks.py script. + origin_suite = getattr(parsed_args, "origin_suite", None) + if origin_suite is not None: + setattr(parsed_args, "suite_files", origin_suite) + + # The top-level parser has one subparser that contains all subcommand parsers. + command_subparser = [ + action for action in parser._actions # pylint: disable=protected-access + if action.dest == "command" + ][0] + + run_parser = command_subparser.choices.get("run") + + suites_arg = None + storage_engine_arg = None + other_local_args = [] + positional_args = [] + + def format_option(option_name, option_value): + """ + Return <option_name>=<option_value>. + + This function assumes that 'option_name' is always "--" prefix and isn't "-" prefixed. + """ + return f"{option_name}={option_value}" + + # Trim the argument namespace of any args we don't want to return. + for group in run_parser._action_groups: # pylint: disable=protected-access + arg_dests_visited = set() + for action in group._group_actions: # pylint: disable=protected-access + arg_dest = action.dest + arg_value = getattr(parsed_args, arg_dest, None) + + # Some arguments, such as --shuffle and --shuffleMode, update the same dest variable. + # To not print out multiple arguments that will update the same dest, we will skip once + # one such argument has been visited. + if arg_dest in arg_dests_visited: + continue + else: + arg_dests_visited.add(arg_dest) + + # If the arg doesn't exist in the parsed namespace, skip. + # This is mainly for "--help". + if not hasattr(parsed_args, arg_dest): + continue + # Skip any evergreen centric args. + elif group.title in [_INTERNAL_OPTIONS_TITLE, _EVERGREEN_ARGUMENT_TITLE]: + continue + # Keep these args. + elif group.title == 'optional arguments': + arg_name = action.option_strings[-1] + + # If an option has the same value as the default, we don't need to specify it. + if getattr(parsed_args, arg_dest, None) == action.default: + continue + # These are arguments that take no value. + elif action.nargs == 0: + other_local_args.append(arg_name) + elif isinstance(action, argparse._AppendAction): # pylint: disable=protected-access + args = [format_option(arg_name, elem) for elem in arg_value] + other_local_args.extend(args) + else: + arg = format_option(arg_name, arg_value) + + # We track the value for the --suites and --storageEngine command line options + # separately in order to more easily sort them to the front. + if arg_dest == "suite_files": + suites_arg = arg + elif arg_dest == "storage_engine": + storage_engine_arg = arg + else: + other_local_args.append(arg) + elif group.title == 'positional arguments': + positional_args.extend(arg_value) + + return ["run"] + [arg for arg in (suites_arg, storage_engine_arg) if arg is not None + ] + other_local_args + positional_args def _parse(sys_args): diff --git a/buildscripts/tests/resmokelib/test_parser.py b/buildscripts/tests/resmokelib/test_parser.py index faf2826edbf..281053f17df 100644 --- a/buildscripts/tests/resmokelib/test_parser.py +++ b/buildscripts/tests/resmokelib/test_parser.py @@ -7,21 +7,22 @@ from buildscripts.resmokelib import parser as _parser # pylint: disable=missing-docstring -@unittest.skip("TODO: SERVER-47611") class TestLocalCommandLine(unittest.TestCase): """Unit tests for the to_local_args() function.""" def test_keeps_any_positional_arguments(self): cmdline = _parser.to_local_args([ + "run", "test_file1.js", - "--suites=my_suite", "test_file2.js", - "--storageEngine=my_storage_engine", "test_file3.js", "test_file4.js", + "--suites=my_suite", + "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "test_file1.js", @@ -32,12 +33,14 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_continue_on_failure_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--continueOnFailure", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--continueOnFailure", @@ -45,6 +48,7 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_exclude_with_any_tags_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--excludeWithAnyTags=tag1,tag2,tag4", "--excludeWithAnyTags=tag3,tag5", @@ -52,6 +56,7 @@ class TestLocalCommandLine(unittest.TestCase): ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--excludeWithAnyTags=tag1,tag2,tag4", @@ -60,6 +65,7 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_include_with_any_tags_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--includeWithAnyTags=tag1,tag2,tag4", "--includeWithAnyTags=tag3,tag5", @@ -67,6 +73,7 @@ class TestLocalCommandLine(unittest.TestCase): ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--includeWithAnyTags=tag1,tag2,tag4", @@ -75,12 +82,14 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_no_journal_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--nojournal", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--nojournal", @@ -88,12 +97,14 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_num_clients_per_fixture_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--numClientsPerFixture=10", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--numClientsPerFixture=10", @@ -101,30 +112,35 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_repeat_options(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--repeatSuites=1000", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", - "--repeat=1000", + "--repeatSuites=1000", ]) cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--repeatTests=1000", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--repeatTests=1000", ]) cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--repeatTestsMax=1000", "--repeatTestsMin=20", @@ -133,6 +149,7 @@ class TestLocalCommandLine(unittest.TestCase): ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--repeatTestsMax=1000", @@ -142,25 +159,29 @@ class TestLocalCommandLine(unittest.TestCase): def test_keeps_shuffle_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--shuffle", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", - "--shuffleMode=on", + "--shuffle", ]) def test_keeps_storage_engine_cache_size_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--storageEngineCacheSizeGB=1", "--storageEngine=my_storage_engine", ]) self.assertEqual(cmdline, [ + "run", "--suites=my_suite", "--storageEngine=my_storage_engine", "--storageEngineCacheSizeGB=1", @@ -171,15 +192,18 @@ class TestLocalCommandLine(unittest.TestCase): # We intentionally say --suite rather than --suites here to protect against this command # line option from becoming ambiguous if more similarly named command line options are # added in the future. + "run", "--suite=part_of_my_suite", "--originSuite=my_entire_suite", "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_entire_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, + ["run", "--suites=my_entire_suite", "--storageEngine=my_storage_engine"]) def test_removes_archival_options(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--archiveFile=archive.json", "--archiveLimitMb=100", @@ -187,11 +211,13 @@ class TestLocalCommandLine(unittest.TestCase): "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) def test_removes_evergreen_options(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", + "--archiveFile=archive.json", "--buildId=some_build_id", "--distroId=some_distro_id", "--executionNumber=1", @@ -206,20 +232,22 @@ class TestLocalCommandLine(unittest.TestCase): "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) def test_removes_log_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--log=buildlogger", "--buildloggerUrl=some_url", "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) def test_removes_report_file_options(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--reportFailureStatus=fail", "--reportFile=report.json", @@ -227,25 +255,49 @@ class TestLocalCommandLine(unittest.TestCase): "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) def test_removes_stagger_jobs_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--staggerJobs=on", "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) def test_removes_tag_file_option(self): cmdline = _parser.to_local_args([ + "run", "--suites=my_suite", "--tagFile=etc/test_retrial.yml", "--storageEngine=my_storage_engine", ]) - self.assertEqual(cmdline, ["--suites=my_suite", "--storageEngine=my_storage_engine"]) + self.assertEqual(cmdline, ["run", "--suites=my_suite", "--storageEngine=my_storage_engine"]) + + def test_accepts_space_delimited_args(self): + cmdline = _parser.to_local_args([ + "run", + "--suites", + "my_suite", + "--tagFile=etc/test_retrial.yml", + "--storageEngine", + "my_storage_engine", + "--includeWithAnyTags", + "tag1,tag2,tag4", + "--includeWithAnyTags", + "tag3,tag5", + ]) + + self.assertEqual(cmdline, [ + "run", + "--suites=my_suite", + "--storageEngine=my_storage_engine", + "--includeWithAnyTags=tag1,tag2,tag4", + "--includeWithAnyTags=tag3,tag5", + ]) class TestParseArgs(unittest.TestCase): |