3 """Dispatch to update_*_test_checks.py scripts automatically in bulk
5 Given a list of test files, this script will invoke the correct
6 update_test_checks-style script, skipping any tests which have not previously
7 had assertions autogenerated.
10 from __future__
import print_function
17 from concurrent
.futures
import ThreadPoolExecutor
19 RE_ASSERTIONS
= re
.compile(
20 r
'NOTE: Assertions have been autogenerated by ([^\s]+)( UTC_ARGS:.*)?$')
22 def find_utc_tool(search_path
, utc_name
):
24 Return the path to the given UTC tool in the search path, or None if not
27 for path
in search_path
:
28 candidate
= os
.path
.join(path
, utc_name
)
29 if os
.path
.isfile(candidate
):
33 def run_utc_tool(utc_name
, utc_tool
, testname
):
34 result
= subprocess
.run([utc_tool
, testname
], stdout
=subprocess
.PIPE
,
35 stderr
=subprocess
.PIPE
)
36 return (result
.returncode
, result
.stdout
, result
.stderr
)
39 from argparse
import RawTextHelpFormatter
40 parser
= argparse
.ArgumentParser(description
=__doc__
,
41 formatter_class
=RawTextHelpFormatter
)
43 '--jobs', '-j', default
=1, type=int,
44 help='Run the given number of jobs in parallel')
46 '--utc-dir', nargs
='*',
47 help='Additional directories to scan for update_*_test_checks scripts')
48 parser
.add_argument('tests', nargs
='+')
49 config
= parser
.parse_args()
52 utc_search_path
= config
.utc_dir
[:]
55 script_name
= os
.path
.abspath(__file__
)
56 utc_search_path
.append(os
.path
.join(os
.path
.dirname(script_name
),
59 not_autogenerated
= []
63 with
ThreadPoolExecutor(max_workers
=config
.jobs
) as executor
:
66 for testname
in config
.tests
:
67 with
open(testname
, 'r') as f
:
68 header
= f
.readline().strip()
69 m
= RE_ASSERTIONS
.search(header
)
71 not_autogenerated
.append(testname
)
75 if utc_name
not in utc_tools
:
76 utc_tools
[utc_name
] = find_utc_tool(utc_search_path
, utc_name
)
77 if not utc_tools
[utc_name
]:
78 print(f
"{utc_name}: not found (used in {testname})",
83 future
= executor
.submit(run_utc_tool
, utc_name
, utc_tools
[utc_name
],
85 jobs
.append((testname
, future
))
87 for testname
, future
in jobs
:
88 return_code
, stdout
, stderr
= future
.result()
90 print(f
"Update {testname}")
91 stdout
= stdout
.decode(errors
='replace')
94 if not stdout
.endswith('\n'):
97 stderr
= stderr
.decode(errors
='replace')
100 if not stderr
.endswith('\n'):
103 print(f
"Return code: {return_code}")
109 if not_autogenerated
:
110 print("Tests without autogenerated assertions:")
111 for testname
in not_autogenerated
:
112 print(f
" {testname}")
114 if __name__
== '__main__':