-
Notifications
You must be signed in to change notification settings - Fork 38.7k
qa: Require --exclude for each excluded test
#34168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/34168. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsNo conflicts as of last run. |
rkrux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK c9698f6
Personally I don't have much use for it but I guess others can find this useful.
test/functional/test_runner.py
Outdated
| test_list.remove(exclude_item) | ||
|
|
||
| exclude_tests = [test.strip() for test in args.exclude.split(",")] | ||
| exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A set can be used here instead of a list to avoid unnecessary warning in case a test name is duplicated across different occurrences of the exclude argument.
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 58b331ee20..6f6dc442f9 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -503,7 +503,7 @@ def main():
for exclude_item in exclude_list:
test_list.remove(exclude_item)
- exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")]
+ exclude_tests = set([test.strip() for test in ",".join(args.exclude).split(",")])
for exclude_test in exclude_tests:
# A space in the name indicates it has arguments such as "rpc_bind.py --ipv4"
if ' ' in exclude_test:
(END)➜ bitcoin git:(251229-ft-exclude-append) ✗ ./build/test/functional/test_runner.py --exclude=rpc_signer,rpc_setban --exclude=rpc_users,rpc_net,rpc_signer
Temporary test directory at /var/folders/6v/mpspb4bx4zzf3xr2z96hgq9h0000gn/T/test_runner_₿_🏃_20251229_193516
exclude_tests: ['rpc_signer', 'rpc_setban', 'rpc_users', 'rpc_net', 'rpc_signer']
WARNING! Test 'rpc_signer' not found in current test list. Check the --exclude list.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍, and we could even avoid the temporary string concat hack to flatten the list, a nested comprehension would be more direct:
| exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")] | |
| exclude_tests = {test.strip() for tests in args.exclude for test in tests.split(",")} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current patch seems fine, but I wonder if this could be made a breaking change to drop the comma-separated feature and require --exclude for each excluded test. But just an idea and the current patch seems perfectly fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried it, but wouldn't we get a failure for duplicates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting a failure for duplicates seems fine and maybe even desirable, no?
The risk in removing the failure may be that someone removes an --exclude for a test, assuming it will then run in the future, but it is silently not run, because a duplicate is still present in another --exclude.
So to me it seems beneficial to sanitize the user input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removes an --exclude for a test, assuming it will then run in the future, but it is silently not run,
Hmmm, that's a good point actually...
(edit: moved rest of the comment to main thread to be registered)
|
ACK c9698f6 Verified the argument parsing logic works as expected - multiple |
test/functional/test_runner.py
Outdated
| test_list.remove(exclude_item) | ||
|
|
||
| exclude_tests = [test.strip() for test in args.exclude.split(",")] | ||
| exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍, and we could even avoid the temporary string concat hack to flatten the list, a nested comprehension would be more direct:
| exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")] | |
| exclude_tests = {test.strip() for tests in args.exclude for test in tests.split(",")} |
|
lgtm ACK c9698f6 |
In this context I would vote for that, let's have a single way to specify these to avoid confusion: approach NACK It seems simpler to migrate to separate ones completely instead of having this mixed strategy, something like: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5e5b0c48e8..e287841e6e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -503,7 +503,7 @@ jobs:
env:
# TODO: Fix the excluded test and re-enable it.
# feature_unsupported_utxo_db.py fails on windows because of emojis in the test data directory
- EXCLUDE: '--exclude wallet_multiwallet.py,feature_unsupported_utxo_db.py'
+ EXCLUDE: '--exclude wallet_multiwallet.py --exclude feature_unsupported_utxo_db.py'
TEST_RUNNER_EXTRA: ${{ github.event_name != 'pull_request' && '--extended' || '' }}
run: py -3 test/functional/test_runner.py --jobs $NUMBER_OF_PROCESSORS --ci --quiet --tmpdirprefix="$RUNNER_TEMP" --combinedlogslen=99999999 --timeout-factor=$TEST_RUNNER_TIMEOUT_FACTOR $EXCLUDE $TEST_RUNNER_EXTRA
diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh
index 884bc3955c..3e23a580da 100755
--- a/ci/test/00_setup_env_native_valgrind.sh
+++ b/ci/test/00_setup_env_native_valgrind.sh
@@ -13,7 +13,7 @@ export PIP_PACKAGES="--break-system-packages pycapnp"
export USE_VALGRIND=1
export NO_DEPENDS=1
# bind tests excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
-export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra"
+export TEST_RUNNER_EXTRA="--exclude rpc_bind --exclude feature_bind_extra"
export GOAL="install"
# TODO enable GUI
export BITCOIN_CONFIG="\
diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh
index b7d23fbf5e..b6f924cf5d 100755
--- a/ci/test/00_setup_env_s390x.sh
+++ b/ci/test/00_setup_env_s390x.sh
@@ -11,7 +11,7 @@ export PACKAGES="python3-zmq"
export CONTAINER_NAME=ci_s390x
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:24.04"
export CI_IMAGE_PLATFORM="linux/s390x"
-export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
+export TEST_RUNNER_EXTRA="--exclude rpc_bind --exclude feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
export RUN_FUNCTIONAL_TESTS=true
export GOAL="install"
export BITCOIN_CONFIG="\
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 58b331ee20..dae672e7da 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -400,7 +400,7 @@ def main():
parser.add_argument('--combinedlogslen', '-c', type=int, default=0, metavar='n', help='On failure, print a log (of length n lines) to the console, combined from the test framework and all test nodes.')
parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface')
parser.add_argument('--ci', action='store_true', help='Run checks and code that are usually only enabled in a continuous integration environment')
- parser.add_argument('--exclude', '-x', action='append', help='specify a comma-separated-list of scripts to exclude.')
+ parser.add_argument('--exclude', '-x', action='append', help='specify a script to exclude (can be specified multiple times).')
parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests')
parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit')
parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.')
@@ -503,8 +503,18 @@ def main():
for exclude_item in exclude_list:
test_list.remove(exclude_item)
- exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")]
- for exclude_test in exclude_tests:
+ for exclude_test in args.exclude:
+ if ',' in exclude_test:
+ print("{}WARNING!{} --exclude '{}' contains a comma. Use --exclude for each test.".format(BOLD[1], BOLD[0], exclude_test))
+ if fail_on_warn:
+ sys.exit(1)
+
+ if len(args.exclude) != len(set(args.exclude)):
+ print("{}WARNING!{} Duplicate --exclude detected.".format(BOLD[1], BOLD[0]))
+ if fail_on_warn:
+ sys.exit(1)
+
+ for exclude_test in args.exclude:
# A space in the name indicates it has arguments such as "rpc_bind.py --ipv4"
if ' ' in exclude_test:
remove_tests([test for test in test_list if test.replace('.py', '') == exclude_test.replace('.py', '')])Q: should we log the name of each excluded test to be safe? diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 58b331ee20..fc204b858b 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -501,6 +501,7 @@ def main():
if not exclude_list:
print_warning_missing_test(exclude_test)
for exclude_item in exclude_list:
+ print("Excluding %s" % exclude_item)
test_list.remove(exclude_item)
exclude_tests = [test.strip() for test in ",".join(args.exclude).split(",")] |
Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
c9698f6 to
c5825d4
Compare
|
Reworked per feedback. The updated branch is mostly based on @l0rinc's suggestion. |
--exclude to be specified multiple times--exclude for each excluded test
l0rinc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
|
Checked that all of my comments were applied correctly (even better than what I suggested), except for failure for duplicates, but that just behaves the same way as if we provided an invalid name for an excursion - a warning will appear: cmake -B build -DCMAKE_BUILD_TYPE=Debug && cmake --build build -j$(nproc) && \
./build/test/functional/test_runner.py feature_includeconf.py feature_loadblock.py --exclude=feature_includeconf.py --exclude=feature_includeconf.py
May not be the best UX, but I actually prefer this over more complicated code. tested ACK c5825d4 |
rkrux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK c5825d4
I preferred the comma separated list but the current way is fine as well if found beneficial by others.
|
review ACK c5825d4 🛄 Show signatureSignature: |
|
rfm? |
|
ACK c5825d4 |
This PR allows a long
--exclude ...argument in thetest/functional/test_runner.pyinvocation to be split across multiple lines, with optional per-line explanatory comments. I found this useful for the CI scripts in https://github.com/hebasto/bitcoin-core-nightly.