diff --git a/test/code-correctness/src/run.py b/test/code-correctness/src/run.py index d9578f2c93..0cc041d43a 100644 --- a/test/code-correctness/src/run.py +++ b/test/code-correctness/src/run.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse import os import glob import yaml @@ -36,12 +37,14 @@ def get_func_name(msg): return msg def run_tidy(files): + if len(files) == 0: + return [] files_str = ' '.join(files) hid = hashlib.md5(files_str.encode('utf-8')).hexdigest() _, _ = execute(f'clang-tidy --export-fixes=/tmp/{hid}.yaml --quiet --checks=-*,bugprone-exception-escape {files_str}') results = [] - with open(f'/tmp/{hid}.yaml', 'r') as file: - data = yaml.safe_load(file) + with open(f'/tmp/{hid}.yaml', 'r') as f: + data = yaml.safe_load(f) for d in data['Diagnostics']: if d['DiagnosticName'] != 'bugprone-exception-escape': continue @@ -52,12 +55,20 @@ def run_tidy(files): results.append((msg['FilePath'].replace(f'{os.getcwd()}/', ''), line_num, get_func_name(msg['Message']))) return results -def exception_escape_test(): - files = glob.glob('filament/**/*.mm', recursive=True) + \ - glob.glob('filament/**/*.cpp', recursive=True) + \ - glob.glob('filament/**/*.h', recursive=True) +DEFAULT_SRC_GLOBS=[ + 'filament/**/*.mm', + 'filament/**/*.cpp', + 'filament/**/*.h', +] - num_workers = 5 # Number of threads to spawn +def exception_escape_test(src_globs=DEFAULT_SRC_GLOBS): + files = [] + if not isinstance(src_globs, list): + src_globs = [src_globs] + for i in src_globs: + files += glob.glob(i, recursive=True) + + num_workers = min(len(files), 5) # Number of threads to spawn part_len = len(files) // num_workers workloads = [] for i in range(num_workers): @@ -78,21 +89,46 @@ def exception_escape_test(): test_name = 'code-correctness::exception-escape' failure_str_lines = [] if len(all_results) > 0: + all_results.sort(key=lambda x: x[0]) failure_str_lines.append(f'Number of failures: {len(all_results)}') for fname, line_num, msg in all_results: failure_str_lines.append(f'{fname}({line_num}): {msg}()') return (len(all_results) == 0, failure_str_lines) TESTS = [ - (exception_escape_test, - 'exception-escape', - '\'an exception may be thrown in a function which should not throw exceptions\'') + ( + exception_escape_test, + # Test name + 'exception-escape', + + # Test description + 'An exception may be thrown in a function which should not throw exceptions. ' + 'Consider adding \'NOLINT(bugprone-exception-escape)\' for valid suppression this check.', + + # Maps a command line argument to a function argument + [('exception_escape_globs', 'src_globs')], + ) ] if __name__ == "__main__": + parser = argparse.ArgumentParser() + + for f, name, desc, args in TESTS: + for cmd_arg_name, _ in args: + parser.add_argument(f'--{cmd_arg_name}', required=False) + + args = parser.parse_args() + has_failures = False - for test_func, test_name, test_desc in TESTS: - result, res_strs = test_func() + for test_func, test_name, test_desc, arguments in TESTS: + func_args = {} + for cmdline_arg, func_arg in arguments: + arg_val = getattr(args, cmdline_arg, None) + if arg_val is not None: + func_args[func_arg] = arg_val.split(',') if ',' in arg_val else arg_val + + result, res_strs = test_func(**func_args) + ss = ' ' * 4 if result: print(f'[{test_name}] PASSED') @@ -104,6 +140,5 @@ if __name__ == "__main__": print(f'{ss}{s}') if has_failures: # TODO: Enable this when we've fixed all the exception-escape errors - #exit(1) + #exit(1) pass - diff --git a/test/code-correctness/test.sh b/test/code-correctness/test.sh index a2427e4165..63ea390ea4 100644 --- a/test/code-correctness/test.sh +++ b/test/code-correctness/test.sh @@ -25,4 +25,4 @@ if ! command -v clang-tidy > /dev/null 2>&1; then fi set -e && set -x && \ - python3 ${CODE_CORRECTNESS_TEST_DIR}/src/run.py + python3 ${CODE_CORRECTNESS_TEST_DIR}/src/run.py "$@"