-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
test: enable reindex readonly test on *BSD #28660
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
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. I'm extracting this to a test utility in #28116, if by any chance you prefer to build on that and I'll pull in the commit there.
Concept ACK, will test on OpenBSD 7.4 in a bit. |
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.
lgtm ACK
@@ -35,6 +35,7 @@ def reindex_readonly(self): | |||
filename.chmod(stat.S_IREAD) | |||
|
|||
used_chattr = False | |||
used_chflags = False |
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.
Nit: Could replace the two boolean with a single undo_immutable
, which holds an optional lambda to run. (a no-op by default, and set to None if the test should terminate early, and the respective undo command if an util helper was used?)
This should reduce the number of symbols, and reduce the mix of if-else
vs early-return
. The diff below would look like:
diff --git a/test/functional/feature_reindex_readonly.py b/test/functional/feature_reindex_readonly.py
index 26531f472b..77716b371e 100755
--- a/test/functional/feature_reindex_readonly.py
+++ b/test/functional/feature_reindex_readonly.py
@@ -53,12 +53,11 @@ class BlockstoreReindexTest(BitcoinTestFramework):
return
self.log.debug("Attempt to restart and reindex the node with the unwritable block file")
- with self.nodes[0].assert_debug_log(expected_msgs=['FlushStateToDisk', 'failed to open file'], unexpected_msgs=[]):
+ if undo_immutable:
+ with self.nodes[0].assert_debug_log(expected_msgs=['FlushStateToDisk', 'failed to open file'], unexpected_msgs=[]):
self.nodes[0].assert_start_raises_init_error(extra_args=['-reindex', '-fastprune'],
expected_msg="Error: A fatal internal error occurred, see debug.log for details")
-
- if used_chattr:
- subprocess.check_call(['chattr', '-i', filename])
+ undo_immutable()
filename.chmod(0o777)
expected_msg="Error: A fatal internal error occurred, see debug.log for details") | ||
undo_immutable() | ||
else: | ||
return |
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.
nit: I think you can now remove the early return, because it should be fine and clearer to run the next line unconditionally.
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.
heh thanks. Having an issue on macos now...
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.
heh thanks. Having an issue on macos now...
The last push (5797225) seems to run fine on arm64 macOS for me.
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.
macOS should be unaffected by this and execute lambda: None
, no?
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.
@jonatack as root?
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.
if platform.system() in ["FreeBSD", "OpenBSD", "Darwin"]:
there we go ;-)
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.
This is very confusing. The last commit should be a refactor. And the first commit shouldn't affect macOS. This is a bug on master already, right?
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.
Latest push e7db19f works for me as root.
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.
@maflcko the first commit does not affect macos. the second commit is a refactor that also fixes a macos/root bug on master. Want me to separate the macos out to commit 3?
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.
@maflcko yes, running this test as root blocks for me on master as well.
5797225
to
e7db19f
Compare
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.
lgtm ACK
Please squash your commits according to https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#squashing-commits
self.nodes[0].assert_start_raises_init_error(extra_args=['-reindex', '-fastprune'], | ||
expected_msg="Error: A fatal internal error occurred, see debug.log for details") | ||
undo_immutable = False | ||
if platform.system() in ["FreeBSD", "OpenBSD", "Darwin"]: |
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.
What about netbsd? I think you can just run if chflags --version
or similar here?
693349c
to
98f108b
Compare
squashed and replaced all the |
98f108b
to
db03177
Compare
db03177
to
cbd5bf0
Compare
lgtm code ACK cbd5bf0 |
Is there any good reason to abuse try/catch for regular logic control flow, in this case the OS detection (previously done with |
@theStack the issue was hard-coding all the OSs. Every flavor of *BSD plus macOS has |
Not sure. This would force us to maintain a list of all operating systems in this test. FreeBSD, NetBSD, OpenBSD, macOS, ... |
If this package can be installed on all BSD and macOS, I think we can also remove the BSD branch, and just require this package? |
I don't think chattr is available for macOS |
But, we could make this a utility function that returns an "undo" lambda? And then get the weird code out of the test itself? |
Yeah, fair enough, I agree that maintaining this list is also not ideal, and just checking for the programs we need is fine. What I particularly don't like about catching the generic |
with self.nodes[0].assert_debug_log(expected_msgs=['FlushStateToDisk', 'failed to open file'], unexpected_msgs=[]): | ||
self.nodes[0].assert_start_raises_init_error(extra_args=['-reindex', '-fastprune'], | ||
expected_msg="Error: A fatal internal error occurred, see debug.log for details") | ||
undo_immutable = False |
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.
nit, might be good not to mix data types (probably a leftover from an earlier version of the PR?) :
undo_immutable = False | |
undo_immutable = lambda: None |
(also in the macOS/BSD branch below)
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 don't think this works. This will break running the test in a Linux container without --cap-add LINUX_IMMUTABLE
, no?
See also the log line immediately above this line.
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.
Oops, indeed. In my mind lambda: None
was falsy and thought the if condition below wouldn't be executed, my bad.
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.
It may be possible to type lambda: pass
, which should be equal to lambda: None
?
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.
It may be possible to type
lambda: pass
, which should be equal tolambda: None
?
Unfortunately not:
$ python3
Python 3.10.11 (main, Apr 13 2023, 01:52:20) [Clang 13.0.0 ] on openbsd7
Type "help", "copyright", "credits" or "license" for more information.
>>> x = lambda: pass
File "<stdin>", line 1
x = lambda: pass
^^^^
SyntaxError: invalid syntax
I wonder what type checkers like mypy would consider as the correct falsy value for a lambda. Maybe None
would be slightly better than False
? (or maybe both would be rejected, idk). Anyways, False
seems to do its job.
Here's some more practical example why catching the generic diff --git a/test/functional/feature_reindex_readonly.py b/test/functional/feature_reindex_readonly.py
index b276be9c03..9f3b642338 100755
--- a/test/functional/feature_reindex_readonly.py
+++ b/test/functional/feature_reindex_readonly.py
@@ -36,7 +36,7 @@ class BlockstoreReindexTest(BitcoinTestFramework):
undo_immutable = lambda: None
# Linux
try:
- subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ subprocess.run_thismethoddoesnotevenexist(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
try:
subprocess.run(['chattr', '+i', filename], capture_output=True, check=True)
undo_immutable = lambda: subprocess.check_call(['chattr', '-i', filename])
This should throw an |
This should be rfm, except for https://github.com/bitcoin/bitcoin/pull/28660/files#r1366893829, which can either be done here, or I'd do in a follow-up? |
cbd5bf0
to
5a0688a
Compare
re-cr-lgtm-ACK 5a0688a |
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 5a0688a
Tested in OpenBSD 7.4, once with and once without the e2fsprogs
package installed, to trigger both code paths:
$ which chattr && which chflags
/usr/local/bin/chattr
/usr/bin/chflags
$ ./test/functional/feature_reindex_readonly.py
2023-10-23T15:41:09.438000Z TestFramework (INFO): PRNG seed is: 435157676393106655
2023-10-23T15:41:09.493000Z TestFramework (INFO): Initializing test directory /tmp/bitcoin_func_test_2uz_nii5
2023-10-23T15:41:10.354000Z TestFramework (INFO): Made file immutable with chattr
2023-10-23T15:41:10.363000Z TestFramework (INFO): Attempt to restart and reindex the node with the unwritable block file
2023-10-23T15:41:10.966000Z TestFramework (INFO): Stopping nodes
2023-10-23T15:41:10.970000Z TestFramework (INFO): Cleaning up /tmp/bitcoin_func_test_2uz_nii5 on exit
2023-10-23T15:41:10.971000Z TestFramework (INFO): Tests successful
$ doas pkg_delete e2fsprogs
...
$ which chattr && which chflags
which: chattr: Command not found.
$ ./test/functional/feature_reindex_readonly.py
2023-10-23T15:43:04.599000Z TestFramework (INFO): PRNG seed is: 8556685811226418814
2023-10-23T15:43:04.653000Z TestFramework (INFO): Initializing test directory /tmp/bitcoin_func_test_h4lvamww
2023-10-23T15:43:05.565000Z TestFramework (INFO): Made file immutable with chflags
2023-10-23T15:43:05.622000Z TestFramework (INFO): Attempt to restart and reindex the node with the unwritable block file
2023-10-23T15:43:06.231000Z TestFramework (INFO): Stopping nodes
2023-10-23T15:43:06.295000Z TestFramework (INFO): Cleaning up /tmp/bitcoin_func_test_h4lvamww on exit
2023-10-23T15:43:06.362000Z TestFramework (INFO): Tests successful
I agree with @theStack's concerns about catching the generic exception for control flow and would be happy to re-review if this is reverted to ACK 5a0688a tested on macOS only |
undo_immutable = lambda: None | ||
# Linux | ||
try: | ||
subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | ||
try: | ||
subprocess.run(['chattr', '+i', filename], capture_output=True, check=True) |
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.
On Ubuntu 22.04.3 LTS, this line throws an exception for me
2023-10-25T19:35:49.783000Z TestFramework (DEBUG): Make the first block file read-only
2023-10-25T19:35:49.785000Z TestFramework (WARNING): Command '['chattr', '+i', PosixPath('/tmp/bitcoin_func_test_i3g4dkjv/node0/regtest/blocks/blk00000.dat')]' returned non-zero exit status 1.
2023-10-25T19:35:49.785000Z TestFramework (WARNING): stderr: b'chattr: Operation not permitted while setting flags on /tmp/bitcoin_func_test_i3g4dkjv/node0/regtest/blocks/blk00000.dat\n'
In spite of this, the file is still changed to readonly, so the test still works as intended (it just doesn't set undo_immutable
in the next line because of the exception).
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.
Yes, but this seems unrelated to the changes here, and the warning can be ignored. I guess it should just be a debug
or info
level?
used_chattr = False | ||
if platform.system() == "Linux": | ||
undo_immutable = lambda: None | ||
# Linux |
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.
nit: I guess the comment isn't applicable, given that chattr can be installed on FreeBSD
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.
Yes, the comment is already removed in #28116 (which I'll be updating).
undo_immutable = lambda: None | ||
# Linux | ||
try: | ||
subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | ||
try: | ||
subprocess.run(['chattr', '+i', filename], capture_output=True, check=True) |
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.
Yes, but this seems unrelated to the changes here, and the warning can be ignored. I guess it should just be a debug
or info
level?
5a0688a test: enable reindex readonly test on *BSD and macOS as root (Matthew Zipkin) Pull request description: see bitcoin#27850 (comment) OpenBSD and FreeBSD don't have `chattr` but they do have `chflags`, use that method to make the block file immutable for the reindex_readonly test. Written and tested on a VPS running FreeBSD: ``` FreeBSD freebsd-13-1 13.2-RELEASE-p4 FreeBSD 13.2-RELEASE-p4 GENERIC amd64 ``` ACKs for top commit: maflcko: re-cr-lgtm-ACK 5a0688a jonatack: ACK 5a0688a tested on macOS only theStack: ACK 5a0688a Tree-SHA512: 8c88d282d09c00355d22c4c504b779f60e420327a5e07bcf80fa77b97fefcb04952af9ceaf439d9033a0a2448cb26a02663fe6bddcd4a74792857cfbaf1c5162
see #27850 (comment)
OpenBSD and FreeBSD don't have
chattr
but they do havechflags
, use that method to make the block file immutable for the reindex_readonly test.Written and tested on a VPS running FreeBSD: