diff --git a/ci/commit_pragma_mapping.yaml b/ci/commit_pragma_mapping.yaml index f76b90da094..816593c909f 100644 --- a/ci/commit_pragma_mapping.yaml +++ b/ci/commit_pragma_mapping.yaml @@ -5,24 +5,179 @@ # # Each key is a regex path to match. # Under each path is optionally each key: +# stop_on_match: Whether to stop processing other entries if when a match is found. +# For example, if "src/tests/ftest*" matches, we don't want to also process ".*" # test-tag : Either direct test tags for this path or: # handler: either "direct" or "FtestTagMap" for special handling. Default is "direct" -# stop_on_match: Whether to stop processing other entries if when a match is found. -# For example, if "src/tests/ftest*" matches, we don't want to also process ".*" # tags: the tags to use for a match # need-unit-test : Either a direct boolean value or: # stop_on_match: Whether to stop processing other entries for this path when a match is found. # val: Whether this path needs unit tests. Default is True. +ftest-only: &ftest-only + stop_on_match: True + need-unit-test: False + # Special handling for ftest, defaulting to pr src/tests/ftest*: + <<: *ftest-only test-tag: handler: FtestTagMap - stop_on_match: True tags: pr - need-unit-test: - stop_on_match: True - val: False + +src/tests/suite/daos_aggregate_ec.c: + test-tag: test_daos_aggregate_ec + <<: *ftest-only + +src/tests/suite/daos_array.c: + test-tag: test_daos_array + <<: *ftest-only + +src/tests/suite/daos_base_tx.c: + test-tag: test_daos_single_rdg_tx + <<: *ftest-only + +src/tests/suite/daos_capa.c: + test-tag: test_daos_capability + <<: *ftest-only + +src/tests/suite/daos_checksum.c: + test-tag: test_daos_checksum + <<: *ftest-only + +src/tests/suite/daos_container.c: + test-tag: test_daos_container + <<: *ftest-only + +src/tests/suite/daos_cr.c: + test-tag: test_daos_cat_recov_core + <<: *ftest-only + +src/tests/suite/daos_dedup.c: + test-tag: test_daos_dedup + <<: *ftest-only + +src/tests/suite/daos_degraded.c: + test-tag: test_daos_degraded_mode + <<: *ftest-only + +src/tests/suite/daos_degrade_ec.c: + test-tag: test_daos_degraded_ec + <<: *ftest-only + +src/tests/suite/daos_dist_tx.c: + test-tag: test_daos_distributed_tx + <<: *ftest-only + +src/tests/suite/daos_drain_simple.c: + test-tag: test_daos_drain_simple + <<: *ftest-only + +src/tests/suite/daos_epoch.c: + test-tag: test_daos_epoch + <<: *ftest-only + +src/tests/suite/daos_epoch_recovery.c: + test-tag: test_daos_epoch_recovery + <<: *ftest-only + +src/tests/suite/daos_extend_simple.c: + test-tag: test_daos_extend_simple + <<: *ftest-only + +src/tests/suite/daos_inc_reint.c: + test-tag: test_daos_inc_reint_cont_recov + <<: *ftest-only + +src/tests/suite/daos_kv.c: + test-tag: test_daos_kv + <<: *ftest-only + +src/tests/suite/daos_md_replication.c: + test-tag: test_daos_md_replication + <<: *ftest-only + +src/tests/suite/daos_mgmt.c: + test-tag: test_daos_management + <<: *ftest-only + +src/tests/suite/daos_nvme_recovery.c: + test-tag: DaosCoreTestNvme + <<: *ftest-only + +src/tests/suite/daos_obj_array.c: + test-tag: test_daos_object_array + <<: *ftest-only + +src/tests/suite/daos_obj.c: + test-tag: test_daos_io test_daos_ec_io + <<: *ftest-only + +src/tests/suite/daos_obj_ec.c: + test-tag: test_daos_ec_obj + <<: *ftest-only + +src/tests/suite/daos_oid_alloc.c: + test-tag: test_daos_oid_allocator + <<: *ftest-only + +src/tests/suite/daos_pipeline.c: + test-tag: test_daos_pipeline + <<: *ftest-only + +src/tests/suite/daos_pool.c: + test-tag: test_daos_pool + <<: *ftest-only + +src/tests/suite/daos_rebuild.c: + test-tag: DaosCoreTestRebuild + <<: *ftest-only + +src/tests/suite/daos_rebuild_ec.c: + test-tag: test_daos_rebuild_ec + <<: *ftest-only + +src/tests/suite/daos_rebuild_interactive.c: + test-tag: test_daos_rebuild_interactive + <<: *ftest-only + +src/tests/suite/daos_rebuild_simple.c: + test-tag: test_daos_rebuild_simple + <<: *ftest-only + +src/tests/suite/daos_upgrade.c: + test-tag: test_daos_upgrade + <<: *ftest-only + +src/tests/suite/daos_verify_consistency.c: + test-tag: test_daos_verify_consistency + <<: *ftest-only + +src/tests/suite/dfs_par_test.c: + test-tag: test_daos_dfs_parallel + <<: *ftest-only + +src/tests/suite/dfs_sys_unit_test.c: + test-tag: test_daos_dfs_sys + <<: *ftest-only + +src/tests/suite/dfs_test.c: + test-tag: dfs_test + <<: *ftest-only + +src/tests/suite/dfs_unit_test.c: + test-tag: test_daos_dfs_unit + <<: *ftest-only + +src/tests/suite/dfuse_test.c: + test-tag: DaosCoreTestDfuse + <<: *ftest-only + +# Run all daos_test for common daos_test files +src/tests/suite/: + test-tag: daos_test + <<: *ftest-only + # Individual code areas src/client/dfs/: diff --git a/ci/gen_commit_pragmas.py b/ci/gen_commit_pragmas.py index 3c22dbf81c0..1dbdba0cb6b 100755 --- a/ci/gen_commit_pragmas.py +++ b/ci/gen_commit_pragmas.py @@ -108,13 +108,6 @@ def read_commit_pragma_mapping(): raise ValueError( f'Invalid handler: {config[path_match][pragma_key]["handler"]}') - # Set default stop_on_match and check for invalid values - if 'stop_on_match' not in config[path_match][pragma_key]: - config[path_match][pragma_key]['stop_on_match'] = False - elif not isinstance(config[path_match][pragma_key]['stop_on_match'], bool): - raise ValueError( - f'Invalid stop_on_match: {config[path_match][pragma_key]["stop_on_match"]}') - # Check for missing or invalid tags if 'tags' not in config[path_match][pragma_key]: raise ValueError(f'Missing tags for {path_match}') @@ -136,13 +129,6 @@ def read_commit_pragma_mapping(): if extra_keys: raise ValueError(f'Unsupported keys in config: {", ".join(extra_keys)}') - # Set default stop_on_match and check for invalid values - if 'stop_on_match' not in config[path_match][pragma_key]: - config[path_match][pragma_key]['stop_on_match'] = False - elif not isinstance(config[path_match][pragma_key]['stop_on_match'], bool): - raise ValueError( - f'Invalid stop_on_match: {config[path_match][pragma_key]["stop_on_match"]}') - # Check for missing or invalid val if 'val' not in config[path_match][pragma_key]: raise ValueError(f'Missing val for {path_match}') @@ -150,18 +136,22 @@ def read_commit_pragma_mapping(): raise TypeError( f'Expected {bool} for val, not ' f'{type(config[path_match][pragma_key]["val"])}') + elif pragma_key == 'stop_on_match': + if not isinstance(pragma_config, bool): + raise TypeError(f'Expected {bool} for stop_on_match, not {type(pragma_config)}') else: raise ValueError(f'Invalid pragma key: {pragma_key}') return config -def __get_test_tag(test_tag_config, paths): +def __get_test_tag(commit_pragma_mapping, paths, default='pr'): """Get the Test-tag pragma. Args: - test_tag_config (dict): test-tag config. E.g. {path1: foo, path2: {tags: pr}} + commit_pragma_mapping (dict): full commit pragma mapping config paths (list): paths to get tags for + default (str): default tag to use if a path does not have a test-tag config Returns: str: Test-tag pragma for these paths @@ -172,58 +162,65 @@ def __get_test_tag(test_tag_config, paths): all_tags = set() for path in paths: - for _pattern, _config in test_tag_config.items(): + for _pattern, config in commit_pragma_mapping.items(): if re.search(rf'{_pattern}', path): - if isinstance(_config, str): - _config = { - 'tags': _config, - 'handler': 'direct', - 'stop_on_match': False + test_tag_config = config.get('test-tag', default) + if isinstance(test_tag_config, str): + test_tag_config = { + 'tags': test_tag_config, + 'handler': 'direct' } - _handler = _config['handler'] + _handler = test_tag_config['handler'] if _handler == 'FtestTagMap': # Special ftest handling try: all_tags.update(ftest_tag_map.minimal_tags(path)) except KeyError: # Use default from config - all_tags.update(_config['tags'].split(' ')) + all_tags.update(test_tag_config['tags'].split(' ')) elif _handler == 'direct': # Use direct tags from config - all_tags.update(_config['tags'].split(' ')) + all_tags.update(test_tag_config['tags'].split(' ')) else: - raise ValueError(f'Invalid handler: {_config["handler"]}') + raise ValueError(f'Invalid handler: {test_tag_config["handler"]}') - if _config['stop_on_match']: + if test_tag_config.get('stop_on_match', config.get('stop_on_match', False)): # Don't process further entries for this path break + # Make sure the test-tag we get from the config are valid tags in ftest + ftest_unique_tags = ftest_tag_map.unique_tags() + invalid_tags = all_tags - ftest_unique_tags + if invalid_tags: + raise ValueError(f'test-tag does not match any tests: {", ".join(invalid_tags)}') + return ' '.join(sorted(all_tags)) -def __get_need_unit_test(need_unit_test_config, paths): +def __get_need_unit_test(commit_pragma_mapping, paths, default=True): """Determine whether we need to run unit tests for these paths. Args: - need_unit_test_config (dict): need-unit-test config. E.g. {path1: True, path2: False} + commit_pragma_mapping (dict): full commit pragma mapping config paths (list): paths to match on + default (bool): default value to use if a path does not have a need-unit-test config Returns: bool: whether we need to run unit tests for these paths """ for path in paths: - for _pattern, _config in need_unit_test_config.items(): + for _pattern, config in commit_pragma_mapping.items(): if re.search(rf'{_pattern}', path): - if isinstance(_config, bool): - _config = { - 'val': _config, - 'stop_on_match': False + unit_test_config = config.get('need-unit-test', default) + if isinstance(unit_test_config, bool): + unit_test_config = { + 'val': unit_test_config } - if _config['val']: + if unit_test_config['val']: # If any path matches with a True value, we need to run unit tests return True - if _config['stop_on_match']: + if unit_test_config.get('stop_on_match', config.get('stop_on_match', False)): # Don't process further entries for this path break @@ -254,30 +251,11 @@ def gen_commit_pragmas(target): commit_pragma_mapping = read_commit_pragma_mapping() - def __pragma_config(pragma_key, default): - """Return the configs for a single pragma key. - - Args: - pragma_key (str): key to get for each path. E.g. 'test-tag' - default (obj): default value if a path does not have the key - - Returns: - dict: each path mapping to its pragma_key value - - For example: - config = {path: {test-tag: tag_config}} - __pragma_config('test-tag', default) -> {path: tag_config} - """ - return { - path_match: path_config.get(pragma_key, default) - for path_match, path_config in commit_pragma_mapping.items() - } - - test_tag = __get_test_tag(__pragma_config('test-tag', 'pr'), modified_files) + test_tag = __get_test_tag(commit_pragma_mapping, modified_files) if test_tag: pragmas['Test-tag'] = test_tag - need_unit_test = __get_need_unit_test(__pragma_config('need-unit-test', True), modified_files) + need_unit_test = __get_need_unit_test(commit_pragma_mapping, modified_files) if modified_files and not need_unit_test: pragmas['Skip-unit-tests'] = True pragmas['Skip-fault-injection-test'] = True