aboutsummaryrefslogtreecommitdiff
path: root/test/lint
diff options
context:
space:
mode:
Diffstat (limited to 'test/lint')
-rwxr-xr-xtest/lint/extended-lint-all.sh26
-rwxr-xr-xtest/lint/extended-lint-cppcheck.sh88
-rwxr-xr-xtest/lint/lint-assertions.py12
-rwxr-xr-xtest/lint/lint-circular-dependencies.py16
-rwxr-xr-xtest/lint/lint-format-strings.py2
-rwxr-xr-xtest/lint/lint-includes.py5
-rwxr-xr-xtest/lint/lint-locale-dependence.py8
-rwxr-xr-xtest/lint/lint-shell.py93
-rwxr-xr-xtest/lint/lint-shell.sh33
9 files changed, 112 insertions, 171 deletions
diff --git a/test/lint/extended-lint-all.sh b/test/lint/extended-lint-all.sh
deleted file mode 100755
index be5d9db4a9..0000000000
--- a/test/lint/extended-lint-all.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2019-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.
-#
-# This script runs all contrib/devtools/extended-lint-*.sh files, and fails if
-# any exit with a non-zero status code.
-
-# This script is intentionally locale dependent by not setting "export LC_ALL=C"
-# in order to allow for the executed lint scripts to opt in or opt out of locale
-# dependence themselves.
-
-set -u
-
-SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
-LINTALL=$(basename "${BASH_SOURCE[0]}")
-
-for f in "${SCRIPTDIR}"/extended-lint-*.sh; do
- if [ "$(basename "$f")" != "$LINTALL" ]; then
- if ! "$f"; then
- echo "^---- failure generated from $f"
- exit 1
- fi
- fi
-done
diff --git a/test/lint/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh
deleted file mode 100755
index 2af39ed60a..0000000000
--- a/test/lint/extended-lint-cppcheck.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2019-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-
-export LC_ALL=C
-
-ENABLED_CHECKS=(
- "Class '.*' has a constructor with 1 argument that is not explicit."
- "Struct '.*' has a constructor with 1 argument that is not explicit."
-)
-
-IGNORED_WARNINGS=(
- "src/arith_uint256.h:.* Class 'arith_uint256' has a constructor with 1 argument that is not explicit."
- "src/arith_uint256.h:.* Class 'base_uint < 256 >' has a constructor with 1 argument that is not explicit."
- "src/arith_uint256.h:.* Class 'base_uint' has a constructor with 1 argument that is not explicit."
- "src/coins.h:.* Class 'CCoinsViewBacked' has a constructor with 1 argument that is not explicit."
- "src/coins.h:.* Class 'CCoinsViewCache' has a constructor with 1 argument that is not explicit."
- "src/coins.h:.* Class 'CCoinsViewCursor' has a constructor with 1 argument that is not explicit."
- "src/net.h:.* Class 'CNetMessage' has a constructor with 1 argument that is not explicit."
- "src/policy/feerate.h:.* Class 'CFeeRate' has a constructor with 1 argument that is not explicit."
- "src/prevector.h:.* Class 'const_iterator' has a constructor with 1 argument that is not explicit."
- "src/prevector.h:.* Class 'const_reverse_iterator' has a constructor with 1 argument that is not explicit."
- "src/prevector.h:.* Class 'iterator' has a constructor with 1 argument that is not explicit."
- "src/prevector.h:.* Class 'reverse_iterator' has a constructor with 1 argument that is not explicit."
- "src/primitives/block.h:.* Class 'CBlock' has a constructor with 1 argument that is not explicit."
- "src/primitives/transaction.h:.* Class 'CTransaction' has a constructor with 1 argument that is not explicit."
- "src/protocol.h:.* Class 'CMessageHeader' has a constructor with 1 argument that is not explicit."
- "src/qt/guiutil.h:.* Class 'ItemDelegate' has a constructor with 1 argument that is not explicit."
- "src/rpc/util.h:.* Struct 'RPCResults' has a constructor with 1 argument that is not explicit."
- "src/rpc/util.h:.* Struct 'UniValueType' has a constructor with 1 argument that is not explicit."
- "src/rpc/util.h:.* style: Struct 'UniValueType' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'AddressDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'ComboDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'ConstPubkeyProvider' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'PKDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'PKHDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'RawDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'SHDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'WPKHDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/descriptor.cpp:.* Class 'WSHDescriptor' has a constructor with 1 argument that is not explicit."
- "src/script/script.h:.* Class 'CScript' has a constructor with 1 argument that is not explicit."
- "src/script/standard.h:.* Class 'CScriptID' has a constructor with 1 argument that is not explicit."
- "src/span.h:.* Class 'Span < const CRPCCommand >' has a constructor with 1 argument that is not explicit."
- "src/span.h:.* Class 'Span < const char >' has a constructor with 1 argument that is not explicit."
- "src/span.h:.* Class 'Span < const std :: vector <unsigned char > >' has a constructor with 1 argument that is not explicit."
- "src/span.h:.* Class 'Span < const uint8_t >' has a constructor with 1 argument that is not explicit."
- "src/span.h:.* Class 'Span' has a constructor with 1 argument that is not explicit."
- "src/support/allocators/secure.h:.* Struct 'secure_allocator < char >' has a constructor with 1 argument that is not explicit."
- "src/support/allocators/secure.h:.* Struct 'secure_allocator < RNGState >' has a constructor with 1 argument that is not explicit."
- "src/support/allocators/secure.h:.* Struct 'secure_allocator < unsigned char >' has a constructor with 1 argument that is not explicit."
- "src/support/allocators/zeroafterfree.h:.* Struct 'zero_after_free_allocator < char >' has a constructor with 1 argument that is not explicit."
- "src/test/checkqueue_tests.cpp:.* Struct 'FailingCheck' has a constructor with 1 argument that is not explicit."
- "src/test/checkqueue_tests.cpp:.* Struct 'MemoryCheck' has a constructor with 1 argument that is not explicit."
- "src/test/checkqueue_tests.cpp:.* Struct 'UniqueCheck' has a constructor with 1 argument that is not explicit."
- "src/test/fuzz/util.h:.* Class 'FuzzedFileProvider' has a constructor with 1 argument that is not explicit."
- "src/test/fuzz/util.h:.* Class 'FuzzedAutoFileProvider' has a constructor with 1 argument that is not explicit."
- "src/wallet/db.h:.* Class 'BerkeleyEnvironment' has a constructor with 1 argument that is not explicit."
-)
-
-if ! command -v cppcheck > /dev/null; then
- echo "Skipping cppcheck linting since cppcheck is not installed. Install by running \"apt install cppcheck\""
- exit 0
-fi
-
-function join_array {
- local IFS="$1"
- shift
- echo "$*"
-}
-
-ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}")
-IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}")
-WARNINGS=$(git ls-files -- "*.cpp" "*.h" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/minisketch/" ":(exclude)src/univalue/" | \
- xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \
- grep -E "${ENABLED_CHECKS_REGEXP}" | \
- grep -vE "${IGNORED_WARNINGS_REGEXP}")
-if [[ ${WARNINGS} != "" ]]; then
- echo "${WARNINGS}"
- echo
- echo "Advice not applicable in this specific case? Add an exception by updating"
- echo "IGNORED_WARNINGS in $0"
- # Uncomment to enforce the developer note policy "By default, declare single-argument constructors `explicit`"
- # exit 1
-fi
-exit 0
diff --git a/test/lint/lint-assertions.py b/test/lint/lint-assertions.py
index a8d2b3927c..195ff33d11 100755
--- a/test/lint/lint-assertions.py
+++ b/test/lint/lint-assertions.py
@@ -30,20 +30,20 @@ def main():
r"[^_]assert\(.*(\+\+|\-\-|[^=!<>]=[^=!<>]).*\);",
"--",
"*.cpp",
- "*.h"
+ "*.h",
], "Assertions should not have side effects:")
- # Macro CHECK_NONFATAL(condition) should be used instead of assert for RPC code, where it
- # is undesirable to crash the whole program. See: src/util/check.h
+ # Aborting the whole process is undesirable for RPC code. So nonfatal
+ # checks should be used over assert. See: src/util/check.h
# src/rpc/server.cpp is excluded from this check since it's mostly meta-code.
exit_code |= git_grep([
"-nE",
- r"\<(A|a)ssert *\(.*\);",
+ r"\<(A|a)ss(ume|ert) *\(.*\);",
"--",
"src/rpc/",
"src/wallet/rpc*",
- ":(exclude)src/rpc/server.cpp"
- ], "CHECK_NONFATAL(condition) should be used instead of assert for RPC code.")
+ ":(exclude)src/rpc/server.cpp",
+ ], "CHECK_NONFATAL(condition) or NONFATAL_UNREACHABLE should be used instead of assert for RPC code.")
sys.exit(exit_code)
diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py
index e04909c0a5..7ca2ec994b 100755
--- a/test/lint/lint-circular-dependencies.py
+++ b/test/lint/lint-circular-dependencies.py
@@ -6,7 +6,6 @@
#
# Check for circular dependencies
-import glob
import os
import re
import subprocess
@@ -32,17 +31,14 @@ CODE_DIR = "src"
def main():
circular_dependencies = []
exit_code = 0
- os.chdir(
- CODE_DIR
- ) # We change dir before globbing since glob.glob's root_dir option is only available in Python 3.10
- # Using glob.glob since subprocess.run's globbing won't work without shell=True
- files = []
- for path in ["*", "*/*", "*/*/*"]:
- for extension in ["h", "cpp"]:
- files.extend(glob.glob(f"{path}.{extension}"))
+ os.chdir(CODE_DIR)
+ files = subprocess.check_output(
+ ['git', 'ls-files', '--', '*.h', '*.cpp'],
+ universal_newlines=True,
+ ).splitlines()
- command = ["python3", "../contrib/devtools/circular-dependencies.py", *files]
+ command = [sys.executable, "../contrib/devtools/circular-dependencies.py", *files]
dependencies_output = subprocess.run(
command,
stdout=subprocess.PIPE,
diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py
index 5a36da11fd..28e7b1e4ff 100755
--- a/test/lint/lint-format-strings.py
+++ b/test/lint/lint-format-strings.py
@@ -36,7 +36,7 @@ RUN_LINT_FILE = 'test/lint/run-lint-format-strings.py'
def check_doctest():
command = [
- 'python3',
+ sys.executable,
'-m',
'doctest',
RUN_LINT_FILE,
diff --git a/test/lint/lint-includes.py b/test/lint/lint-includes.py
index b29c7f8b4d..ae62994642 100755
--- a/test/lint/lint-includes.py
+++ b/test/lint/lint-includes.py
@@ -21,10 +21,7 @@ EXCLUDED_DIRS = ["src/leveldb/",
"src/minisketch/",
"src/univalue/"]
-EXPECTED_BOOST_INCLUDES = ["boost/algorithm/string.hpp",
- "boost/algorithm/string/classification.hpp",
- "boost/algorithm/string/replace.hpp",
- "boost/algorithm/string/split.hpp",
+EXPECTED_BOOST_INCLUDES = ["boost/algorithm/string/replace.hpp",
"boost/date_time/posix_time/posix_time.hpp",
"boost/multi_index/hashed_index.hpp",
"boost/multi_index/ordered_index.hpp",
diff --git a/test/lint/lint-locale-dependence.py b/test/lint/lint-locale-dependence.py
index 2abf1be6b3..9b2cf4587a 100755
--- a/test/lint/lint-locale-dependence.py
+++ b/test/lint/lint-locale-dependence.py
@@ -49,7 +49,9 @@ KNOWN_VIOLATIONS = [
"src/test/fuzz/locale.cpp:.*setlocale",
"src/test/fuzz/string.cpp:.*strtol",
"src/test/fuzz/string.cpp:.*strtoul",
- "src/test/util_tests.cpp:.*strtoll"
+ "src/test/util_tests.cpp:.*strtoll",
+ "src/wallet/bdb.cpp:.*DbEnv::strerror", # False positive
+ "src/util/syserror.cpp:.*strerror", # Outside this function use `SysErrorString`
]
REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS = [
@@ -144,7 +146,7 @@ LOCALE_DEPENDENT_FUNCTIONS = [
"strcasecmp",
"strcasestr",
"strcoll", # LC_COLLATE
- #"strerror",
+ "strerror",
"strfmon",
"strftime", # LC_TIME
"strncasecmp",
@@ -218,7 +220,7 @@ LOCALE_DEPENDENT_FUNCTIONS = [
def find_locale_dependent_function_uses():
regexp_locale_dependent_functions = "|".join(LOCALE_DEPENDENT_FUNCTIONS)
exclude_args = [":(exclude)" + excl for excl in REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS]
- git_grep_command = ["git", "grep", "-E", "[^a-zA-Z0-9_\\`'\"<>](" + regexp_locale_dependent_functions + "(_r|_s)?)[^a-zA-Z0-9_\\`'\"<>]", "--", "*.cpp", "*.h"] + exclude_args
+ git_grep_command = ["git", "grep", "-E", "[^a-zA-Z0-9_\\`'\"<>](" + regexp_locale_dependent_functions + ")(_r|_s)?[^a-zA-Z0-9_\\`'\"<>]", "--", "*.cpp", "*.h"] + exclude_args
git_grep_output = list()
try:
diff --git a/test/lint/lint-shell.py b/test/lint/lint-shell.py
new file mode 100755
index 0000000000..f1e4494350
--- /dev/null
+++ b/test/lint/lint-shell.py
@@ -0,0 +1,93 @@
+#!/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.
+
+"""
+Check for shellcheck warnings in shell scripts.
+"""
+
+import subprocess
+import re
+import sys
+
+# Disabled warnings:
+DISABLED = [
+ 'SC2162', # read without -r will mangle backslashes.
+]
+
+def check_shellcheck_install():
+ try:
+ subprocess.run(['shellcheck', '--version'], stdout=subprocess.DEVNULL, check=True)
+ except FileNotFoundError:
+ print('Skipping shell linting since shellcheck is not installed.')
+ sys.exit(0)
+
+def get_files(command):
+ output = subprocess.run(command, stdout=subprocess.PIPE, universal_newlines=True)
+ files = output.stdout.split('\n')
+
+ # remove whitespace element
+ files = list(filter(None, files))
+ return files
+
+def main():
+ check_shellcheck_install()
+
+ # build the `exclude` flag
+ exclude = '--exclude=' + ','.join(DISABLED)
+
+ # build the `sourced files` list
+ sourced_files_cmd = [
+ 'git',
+ 'grep',
+ '-El',
+ r'^# shellcheck shell=',
+ ]
+ sourced_files = get_files(sourced_files_cmd)
+
+ # build the `guix files` list
+ guix_files_cmd = [
+ 'git',
+ 'grep',
+ '-El',
+ r'^#!\/usr\/bin\/env bash',
+ '--',
+ 'contrib/guix',
+ 'contrib/shell',
+ ]
+ guix_files = get_files(guix_files_cmd)
+
+ # build the other script files list
+ files_cmd = [
+ 'git',
+ 'ls-files',
+ '--',
+ '*.sh',
+ ]
+ files = get_files(files_cmd)
+ # remove everything that doesn't match this regex
+ reg = re.compile(r'src/[leveldb,secp256k1,minisketch,univalue]')
+ files[:] = [file for file in files if not reg.match(file)]
+
+ # build the `shellcheck` command
+ shellcheck_cmd = [
+ 'shellcheck',
+ '--external-sources',
+ '--check-sourced',
+ '--source-path=SCRIPTDIR',
+ ]
+ shellcheck_cmd.append(exclude)
+ shellcheck_cmd.extend(sourced_files)
+ shellcheck_cmd.extend(guix_files)
+ shellcheck_cmd.extend(files)
+
+ # run the `shellcheck` command
+ try:
+ subprocess.check_call(shellcheck_cmd)
+ except subprocess.CalledProcessError:
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh
deleted file mode 100755
index 5fa104fce6..0000000000
--- a/test/lint/lint-shell.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2018-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check for shellcheck warnings in shell scripts.
-
-export LC_ALL=C
-
-# Disabled warnings:
-disabled=(
- SC2162 # read without -r will mangle backslashes.
-)
-
-EXIT_CODE=0
-
-if ! command -v shellcheck > /dev/null; then
- echo "Skipping shell linting since shellcheck is not installed."
- exit $EXIT_CODE
-fi
-
-SHELLCHECK_CMD=(shellcheck --external-sources --check-sourced --source-path=SCRIPTDIR)
-EXCLUDE="--exclude=$(IFS=','; echo "${disabled[*]}")"
-# Check shellcheck directive used for sourced files
-mapfile -t SOURCED_FILES < <(git ls-files | xargs gawk '/^# shellcheck shell=/ {print FILENAME} {nextfile}')
-mapfile -t GUIX_FILES < <(git ls-files contrib/guix contrib/shell | xargs gawk '/^#!\/usr\/bin\/env bash/ {print FILENAME} {nextfile}')
-mapfile -t FILES < <(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|minisketch|univalue)/')
-if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" "${SOURCED_FILES[@]}" "${GUIX_FILES[@]}" "${FILES[@]}"; then
- EXIT_CODE=1
-fi
-
-exit $EXIT_CODE