mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-11 01:26:10 +01:00
Merge bitcoin/bitcoin#24802: lint: convert format strings linter test to python
267684ee34
lint: convert format strings linter test to python (Eunoia) Pull request description: Refs #24783 Attempted to keep the style and flow of implementation as it is. ### Additional Notes(Optional): 1. There is scope of improvement on how the related files are fetched. In this `git grep` with `subprocess` is still used as I found it to be the simplest. Any pointers on this are appreciated. 2. Removed sort operation on the matching files as I couldn't think of any strong arguments to have it. Any pointers on this are appreciated. 3. Not important, but one small detail is that the previous implementation was storing matched files for all the `function_names` iterated so far. Fixed that in this PR. ACKs for top commit: laanwj: Code review ACK267684ee34
Tree-SHA512: 54ceae0c3501e561fdd9c5167b2dd8dd06da1b3697a077a042210970ce7004bda8c4e19abb1905ee64cbdce635f0a078508da645846ae7e81c016091f3f02458
This commit is contained in:
commit
0342ae1d39
2 changed files with 98 additions and 44 deletions
98
test/lint/lint-format-strings.py
Executable file
98
test/lint/lint-format-strings.py
Executable file
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2018-2022 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
"""
|
||||
Lint format strings: This program checks that the number of arguments passed
|
||||
to a variadic format string function matches the number of format specifiers
|
||||
in the format string.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
|
||||
FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS = [
|
||||
'FatalError,0',
|
||||
'fprintf,1',
|
||||
'tfm::format,1', # Assuming tfm::::format(std::ostream&, ...
|
||||
'LogConnectFailure,1',
|
||||
'LogPrint,1',
|
||||
'LogPrintf,0',
|
||||
'printf,0',
|
||||
'snprintf,2',
|
||||
'sprintf,1',
|
||||
'strprintf,0',
|
||||
'vfprintf,1',
|
||||
'vprintf,1',
|
||||
'vsnprintf,1',
|
||||
'vsprintf,1',
|
||||
'WalletLogPrintf,0',
|
||||
]
|
||||
RUN_LINT_FILE = 'test/lint/run-lint-format-strings.py'
|
||||
|
||||
def check_doctest():
|
||||
command = [
|
||||
'python3',
|
||||
'-m',
|
||||
'doctest',
|
||||
RUN_LINT_FILE,
|
||||
]
|
||||
try:
|
||||
subprocess.run(command, check = True)
|
||||
except subprocess.CalledProcessError:
|
||||
sys.exit(1)
|
||||
|
||||
def get_matching_files(function_name):
|
||||
command = [
|
||||
'git',
|
||||
'grep',
|
||||
'--full-name',
|
||||
'-l',
|
||||
function_name,
|
||||
'--',
|
||||
'*.c',
|
||||
'*.cpp',
|
||||
'*.h',
|
||||
]
|
||||
try:
|
||||
return subprocess.check_output(command, stderr = subprocess.STDOUT).decode('utf-8').splitlines()
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode > 1: # return code is 1 when match is empty
|
||||
print(e.output.decode('utf-8'), end='')
|
||||
sys.exit(1)
|
||||
return []
|
||||
|
||||
def main():
|
||||
exit_code = 0
|
||||
check_doctest()
|
||||
for s in FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS:
|
||||
function_name, skip_arguments = s.split(',')
|
||||
matching_files = get_matching_files(function_name)
|
||||
|
||||
matching_files_filtered = []
|
||||
for matching_file in matching_files:
|
||||
if not re.search('^src/(leveldb|secp256k1|minisketch|tinyformat|univalue|test/fuzz/strprintf.cpp)', matching_file):
|
||||
matching_files_filtered.append(matching_file)
|
||||
matching_files_filtered.sort()
|
||||
|
||||
run_lint_args = [
|
||||
RUN_LINT_FILE,
|
||||
'--skip-arguments',
|
||||
skip_arguments,
|
||||
function_name,
|
||||
]
|
||||
run_lint_args.extend(matching_files_filtered)
|
||||
|
||||
try:
|
||||
subprocess.run(run_lint_args, check = True)
|
||||
except subprocess.CalledProcessError:
|
||||
exit_code = 1
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018-2020 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
# Lint format strings: This program checks that the number of arguments passed
|
||||
# to a variadic format string function matches the number of format specifiers
|
||||
# in the format string.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS=(
|
||||
"FatalError,0"
|
||||
"fprintf,1"
|
||||
"tfm::format,1" # Assuming tfm::::format(std::ostream&, ...
|
||||
"LogConnectFailure,1"
|
||||
"LogPrint,1"
|
||||
"LogPrintf,0"
|
||||
"printf,0"
|
||||
"snprintf,2"
|
||||
"sprintf,1"
|
||||
"strprintf,0"
|
||||
"vfprintf,1"
|
||||
"vprintf,1"
|
||||
"vsnprintf,1"
|
||||
"vsprintf,1"
|
||||
"WalletLogPrintf,0"
|
||||
)
|
||||
|
||||
EXIT_CODE=0
|
||||
if ! python3 -m doctest "test/lint/run-lint-format-strings.py"; then
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
for S in "${FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS[@]}"; do
|
||||
IFS="," read -r FUNCTION_NAME SKIP_ARGUMENTS <<< "${S}"
|
||||
for MATCHING_FILE in $(git grep --full-name -l "${FUNCTION_NAME}" -- "*.c" "*.cpp" "*.h" | sort | grep -vE "^src/(leveldb|secp256k1|minisketch|tinyformat|univalue|test/fuzz/strprintf.cpp)"); do
|
||||
MATCHING_FILES+=("${MATCHING_FILE}")
|
||||
done
|
||||
if ! "test/lint/run-lint-format-strings.py" --skip-arguments "${SKIP_ARGUMENTS}" "${FUNCTION_NAME}" "${MATCHING_FILES[@]}"; then
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
done
|
||||
exit ${EXIT_CODE}
|
Loading…
Add table
Reference in a new issue