From 8edd1125d0311b4136f86d8809201336e39da698 Mon Sep 17 00:00:00 2001 From: Trevor Guidry Date: Wed, 16 Nov 2022 17:24:50 +0000 Subject: SERVER-63104 add resmoke argument for generating all_feature_flags.txt locally (cherry picked from commit 22f38cf147eeedca45943ababe818213184eb754) --- buildscripts/idl/gen_all_feature_flag_list.py | 39 +++++++++++++++-------- buildscripts/idl/idl/parser.py | 6 ++-- buildscripts/resmokelib/config.py | 8 +++++ buildscripts/resmokelib/configure_resmoke.py | 45 ++++++++++++++++++--------- buildscripts/resmokelib/run/__init__.py | 20 +++++++----- etc/perf.yml | 2 +- etc/system_perf.yml | 2 +- evergreen/gen_feature_flags.sh | 2 +- 8 files changed, 83 insertions(+), 41 deletions(-) diff --git a/buildscripts/idl/gen_all_feature_flag_list.py b/buildscripts/idl/gen_all_feature_flag_list.py index 7b431fd2dab..c7496803b3b 100644 --- a/buildscripts/idl/gen_all_feature_flag_list.py +++ b/buildscripts/idl/gen_all_feature_flag_list.py @@ -30,7 +30,6 @@ Generate a file containing a list of disabled feature flags. Used by resmoke.py to run only feature flag tests. """ -import argparse import os import sys @@ -43,13 +42,28 @@ sys.path.append(os.path.normpath(os.path.join(os.path.abspath(__file__), '../../ # pylint: disable=wrong-import-position import buildscripts.idl.lib as lib +from buildscripts.idl.idl import parser -def gen_all_feature_flags(idl_dir: str, import_dirs: List[str]): +def is_third_party_idl(idl_path: str) -> bool: + """Check if an IDL file is under a third party directory.""" + third_party_idl_subpaths = [os.path.join("third_party", "mozjs"), "win32com"] + + for file_name in third_party_idl_subpaths: + if file_name in idl_path: + return True + + return False + + +def gen_all_feature_flags(idl_dir: str = os.getcwd()): """Generate a list of all feature flags.""" all_flags = [] for idl_path in sorted(lib.list_idls(idl_dir)): - for feature_flag in lib.parse_idl(idl_path, import_dirs).spec.feature_flags: + if is_third_party_idl(idl_path): + continue + doc = parser.parse_file(open(idl_path), idl_path) + for feature_flag in doc.spec.feature_flags: if feature_flag.default.literal != "true": all_flags.append(feature_flag.name) @@ -59,18 +73,17 @@ def gen_all_feature_flags(idl_dir: str, import_dirs: List[str]): return list(set(all_flags) - set(force_disabled_flags)) -def main(): - """Run the main function.""" - arg_parser = argparse.ArgumentParser(description=__doc__) - arg_parser.add_argument("--import-dir", dest="import_dirs", type=str, action="append", - help="Directory to search for IDL import files") +def gen_all_feature_flags_file(filename: str = lib.ALL_FEATURE_FLAG_FILE): + """Output generated list of feature flags to specified file.""" + flags = gen_all_feature_flags() + with open(filename, "w") as output_file: + output_file.write("\n".join(flags)) + print("Generated: ", os.path.realpath(output_file.name)) - args = arg_parser.parse_args() - flags = gen_all_feature_flags(os.getcwd(), args.import_dirs) - with open(lib.ALL_FEATURE_FLAG_FILE, "w") as output_file: - for flag in flags: - output_file.write("%s\n" % flag) +def main(): + """Run the main function.""" + gen_all_feature_flags_file() if __name__ == '__main__': diff --git a/buildscripts/idl/idl/parser.py b/buildscripts/idl/idl/parser.py index 16f71aed244..fcf77b22c61 100644 --- a/buildscripts/idl/idl/parser.py +++ b/buildscripts/idl/idl/parser.py @@ -976,7 +976,7 @@ def _propagate_globals(spec): idltype.cpp_type = _prefix_with_namespace(cpp_namespace, idltype.cpp_type) -def _parse(stream, error_file_name): +def parse_file(stream, error_file_name): # type: (Any, str) -> syntax.IDLParsedSpec """ Parse a YAML document into an idl.syntax tree. @@ -1080,7 +1080,7 @@ def parse(stream, input_file_name, resolver): """ # pylint: disable=too-many-locals - root_doc = _parse(stream, input_file_name) + root_doc = parse_file(stream, input_file_name) if root_doc.errors: return root_doc @@ -1117,7 +1117,7 @@ def parse(stream, input_file_name, resolver): # Parse imported file with resolver.open(resolved_file_name) as file_stream: - parsed_doc = _parse(file_stream, resolved_file_name) + parsed_doc = parse_file(file_stream, resolved_file_name) # Check for errors if parsed_doc.errors: diff --git a/buildscripts/resmokelib/config.py b/buildscripts/resmokelib/config.py index da73341025c..1caf58074bc 100644 --- a/buildscripts/resmokelib/config.py +++ b/buildscripts/resmokelib/config.py @@ -84,7 +84,9 @@ DEFAULTS = { "report_failure_status": "fail", "report_file": None, "run_all_feature_flag_tests": False, + "run_no_feature_flag_tests": False, "additional_feature_flags": None, + "additional_feature_flags_file": None, "seed": int(time.time() * 256), # Taken from random.py code in Python 2.7. "service_executor": None, "shell_conn_string": None, @@ -356,6 +358,12 @@ INSTALL_DIR = None # Whether to run tests for feature flags. RUN_ALL_FEATURE_FLAG_TESTS = None +# Whether to run the tests with enabled feature flags +RUN_NO_FEATURE_FLAG_TESTS = None + +# the path to a file containing feature flags +ADDITIONAL_FEATURE_FLAGS_FILE = None + # List of enabled feature flags. ENABLED_FEATURE_FLAGS = [] diff --git a/buildscripts/resmokelib/configure_resmoke.py b/buildscripts/resmokelib/configure_resmoke.py index 789ff9f2ceb..e5a21722ada 100644 --- a/buildscripts/resmokelib/configure_resmoke.py +++ b/buildscripts/resmokelib/configure_resmoke.py @@ -15,6 +15,7 @@ import shlex import pymongo.uri_parser +from buildscripts.idl import gen_all_feature_flag_list from buildscripts.idl.lib import ALL_FEATURE_FLAG_FILE from buildscripts.resmokelib import config as _config @@ -50,14 +51,9 @@ def _validate_options(parser, args): "Cannot use --replayFile with additional test files listed on the command line invocation." ) - if args.run_all_feature_flag_tests: - if not os.path.isfile(ALL_FEATURE_FLAG_FILE): - parser.error( - "To run tests with all feature flags, the %s file must exist and be placed in" - " your working directory. The file can be downloaded from the artifacts tarball" - " in Evergreen. Alternatively, if you know which feature flags you want to enable," - " you can use the --additionalFeatureFlags command line argument" % - ALL_FEATURE_FLAG_FILE) + if args.additional_feature_flags_file and not os.path.isfile( + args.additional_feature_flags_file): + parser.error("The specified additional feature flags file does not exist.") def get_set_param_errors(process_params): agg_set_params = collections.defaultdict(list) @@ -183,20 +179,35 @@ be invoked as either: - buildscripts/resmoke.py --installDir {shlex.quote(user_config['install_dir'])}""") raise RuntimeError(err) + def process_feature_flag_file(path): + with open(path) as fd: + return fd.read().split() + def setup_feature_flags(): _config.RUN_ALL_FEATURE_FLAG_TESTS = config.pop("run_all_feature_flag_tests") - all_feature_flags = [] + _config.RUN_NO_FEATURE_FLAG_TESTS = config.pop("run_no_feature_flag_tests") + _config.ADDITIONAL_FEATURE_FLAGS_FILE = config.pop("additional_feature_flags_file") + + if _config.RUN_ALL_FEATURE_FLAG_TESTS: + print("Generating: ", ALL_FEATURE_FLAG_FILE) + gen_all_feature_flag_list.gen_all_feature_flags_file() + + all_ff = [] enabled_feature_flags = [] try: - all_feature_flags = open(ALL_FEATURE_FLAG_FILE).read().split() + all_ff = process_feature_flag_file(ALL_FEATURE_FLAG_FILE) except FileNotFoundError: # If we ask resmoke to run with all feature flags, the feature flags file # needs to exist. - if _config.RUN_ALL_FEATURE_FLAG_TESTS: + if _config.RUN_ALL_FEATURE_FLAG_TESTS or _config.RUN_NO_FEATURE_FLAG_TESTS: raise if _config.RUN_ALL_FEATURE_FLAG_TESTS: - enabled_feature_flags = all_feature_flags[:] + enabled_feature_flags = all_ff[:] + + if _config.ADDITIONAL_FEATURE_FLAGS_FILE: + enabled_feature_flags.extend( + process_feature_flag_file(_config.ADDITIONAL_FEATURE_FLAGS_FILE)) # Specify additional feature flags from the command line. # Set running all feature flag tests to True if this options is specified. @@ -204,7 +215,7 @@ be invoked as either: if additional_feature_flags is not None: enabled_feature_flags.extend(additional_feature_flags) - return enabled_feature_flags, all_feature_flags + return enabled_feature_flags, all_ff _config.ENABLED_FEATURE_FLAGS, all_feature_flags = setup_feature_flags() not_enabled_feature_flags = list(set(all_feature_flags) - set(_config.ENABLED_FEATURE_FLAGS)) @@ -221,8 +232,12 @@ be invoked as either: _config.EXCLUDE_WITH_ANY_TAGS.extend( utils.default_if_none(_tags_from_list(config.pop("exclude_with_any_tags")), [])) - # Don't run tests with feature flags that are not enabled. - _config.EXCLUDE_WITH_ANY_TAGS.extend(not_enabled_feature_flags) + if _config.RUN_NO_FEATURE_FLAG_TESTS: + # Don't run any feature flag tests. + _config.EXCLUDE_WITH_ANY_TAGS.extend(all_feature_flags) + else: + # Don't run tests with feature flags that are not enabled. + _config.EXCLUDE_WITH_ANY_TAGS.extend(not_enabled_feature_flags) _config.FAIL_FAST = not config.pop("continue_on_failure") _config.FLOW_CONTROL = config.pop("flow_control") diff --git a/buildscripts/resmokelib/run/__init__.py b/buildscripts/resmokelib/run/__init__.py index 7453aa6a4cd..1596cef2f4a 100644 --- a/buildscripts/resmokelib/run/__init__.py +++ b/buildscripts/resmokelib/run/__init__.py @@ -797,10 +797,23 @@ class RunPlugin(PluginInterface): "Run MongoDB servers with all feature flags enabled and only run tests tags with these feature flags" ) + parser.add_argument( + "--runNoFeatureFlagTests", dest="run_no_feature_flag_tests", action="store_true", + help=("Do not run any tests tagged with enabled feature flags." + " This argument has precedence over --runAllFeatureFlagTests" + "; used for multiversion suites")) + parser.add_argument("--additionalFeatureFlags", dest="additional_feature_flags", action="append", metavar="featureFlag1, featureFlag2, ...", help="Additional feature flags") + parser.add_argument("--additionalFeatureFlagsFile", dest="additional_feature_flags_file", + action="store", metavar="FILE", + help="The path to a file with feature flags, delimited by newlines.") + + parser.add_argument("--maxTestQueueSize", type=int, dest="max_test_queue_size", + help=argparse.SUPPRESS) + mongodb_server_options = parser.add_argument_group( title=_MONGODB_SERVER_OPTIONS_TITLE, description=("Options related to starting a MongoDB cluster that are forwarded from" @@ -1123,13 +1136,6 @@ def to_local_args(input_args=None): # pylint: disable=too-many-branches,too-man if origin_suite is not None: setattr(parsed_args, "suite_files", origin_suite) - # Replace --runAllFeatureFlagTests with an explicit list of feature flags. The former relies on - # all_feature_flags.txt which may not exist in the local dev environment. - run_all_feature_flag_tests = getattr(parsed_args, "run_all_feature_flag_tests", None) - if run_all_feature_flag_tests is not None: - setattr(parsed_args, "additional_feature_flags", config.ENABLED_FEATURE_FLAGS) - del parsed_args.run_all_feature_flag_tests - # The top-level parser has one subparser that contains all subcommand parsers. command_subparser = [ action for action in parser._actions # pylint: disable=protected-access diff --git a/etc/perf.yml b/etc/perf.yml index dc952c5e6d5..f2e4a289905 100644 --- a/etc/perf.yml +++ b/etc/perf.yml @@ -304,7 +304,7 @@ functions: set -o errexit set -o verbose source "${workdir}/compile_venv/bin/activate" - python ./buildscripts/idl/gen_all_feature_flag_list.py --import-dir src --import-dir src/mongo/db/modules/enterprise/src + python ./buildscripts/idl/gen_all_feature_flag_list.py mkdir -p mongodb/feature_flags cp ./all_feature_flags.txt mongodb/feature_flags - command: shell.exec diff --git a/etc/system_perf.yml b/etc/system_perf.yml index 5cbdd274d90..c76f7507982 100755 --- a/etc/system_perf.yml +++ b/etc/system_perf.yml @@ -320,7 +320,7 @@ functions: set -o errexit set -o verbose source "${workdir}/compile_venv/bin/activate" - python ./buildscripts/idl/gen_all_feature_flag_list.py --import-dir src --import-dir src/mongo/db/modules/enterprise/src + python ./buildscripts/idl/gen_all_feature_flag_list.py mkdir -p mongodb/feature_flags cp ./all_feature_flags.txt mongodb/feature_flags - command: shell.exec diff --git a/evergreen/gen_feature_flags.sh b/evergreen/gen_feature_flags.sh index 4e6dc0e9b4c..b06f614c243 100755 --- a/evergreen/gen_feature_flags.sh +++ b/evergreen/gen_feature_flags.sh @@ -6,4 +6,4 @@ cd src set -o errexit set -o verbose activate_venv -$python buildscripts/idl/gen_all_feature_flag_list.py --import-dir src --import-dir src/mongo/db/modules/enterprise/src +$python buildscripts/idl/gen_all_feature_flag_list.py -- cgit v1.2.1