aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorlaanwj <126646+laanwj@users.noreply.github.com>2022-04-25 18:25:34 +0200
committerlaanwj <126646+laanwj@users.noreply.github.com>2022-04-25 18:32:40 +0200
commit0342ae1d395ca82614f6d3b8fabb6a44403baf2a (patch)
treef87d7702daaa2b6aa821d0f282f028a59b13cf0a /test
parent777b89b3008e53374eb13fdee70db315cd61a703 (diff)
parent267684ee34d795e4f762c4949fa45d99fe74dde3 (diff)
downloadbitcoin-0342ae1d395ca82614f6d3b8fabb6a44403baf2a.tar.xz
Merge bitcoin/bitcoin#24802: lint: convert format strings linter test to python
267684ee34d795e4f762c4949fa45d99fe74dde3 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 ACK 267684ee34d795e4f762c4949fa45d99fe74dde3 Tree-SHA512: 54ceae0c3501e561fdd9c5167b2dd8dd06da1b3697a077a042210970ce7004bda8c4e19abb1905ee64cbdce635f0a078508da645846ae7e81c016091f3f02458
Diffstat (limited to 'test')
-rwxr-xr-xtest/lint/lint-format-strings.py98
-rwxr-xr-xtest/lint/lint-format-strings.sh44
2 files changed, 98 insertions, 44 deletions
diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py
new file mode 100755
index 0000000000..5a36da11fd
--- /dev/null
+++ b/test/lint/lint-format-strings.py
@@ -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()
diff --git a/test/lint/lint-format-strings.sh b/test/lint/lint-format-strings.sh
deleted file mode 100755
index 73730f16b3..0000000000
--- a/test/lint/lint-format-strings.sh
+++ /dev/null
@@ -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}