Skip to content

Commit de8f912

Browse files
pinheadmzachow101
andcommitted
test: cover read-only blockstore
Co-authored-by: Andrew Chow <[email protected]>
1 parent 5c2185b commit de8f912

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2023-present The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""Test running bitcoind with -reindex from a read-only blockstore
6+
- Start a node, generate blocks, then restart with -reindex after setting blk files to read-only
7+
"""
8+
9+
import platform
10+
import stat
11+
import subprocess
12+
from test_framework.test_framework import BitcoinTestFramework
13+
14+
15+
class BlockstoreReindexTest(BitcoinTestFramework):
16+
def set_test_params(self):
17+
self.setup_clean_chain = True
18+
self.num_nodes = 1
19+
self.extra_args = [["-fastprune"]]
20+
21+
def reindex_readonly(self):
22+
self.log.debug("Generate block big enough to start second block file")
23+
fastprune_blockfile_size = 0x10000
24+
opreturn = "6a"
25+
nulldata = fastprune_blockfile_size * "ff"
26+
self.generateblock(self.nodes[0], output=f"raw({opreturn}{nulldata})", transactions=[])
27+
self.stop_node(0)
28+
29+
assert (self.nodes[0].chain_path / "blocks" / "blk00000.dat").exists()
30+
assert (self.nodes[0].chain_path / "blocks" / "blk00001.dat").exists()
31+
32+
self.log.debug("Make the first block file read-only")
33+
filename = self.nodes[0].chain_path / "blocks" / "blk00000.dat"
34+
filename.chmod(stat.S_IREAD)
35+
36+
used_chattr = False
37+
if platform.system() == "Linux":
38+
try:
39+
subprocess.run(['chattr', '+i', filename], capture_output=True, check=True)
40+
used_chattr = True
41+
self.log.info("Made file immutable with chattr")
42+
except subprocess.CalledProcessError as e:
43+
self.log.warning(str(e))
44+
if e.stdout:
45+
self.log.warning(f"stdout: {e.stdout}")
46+
if e.stderr:
47+
self.log.warning(f"stderr: {e.stderr}")
48+
49+
self.log.debug("Attempt to restart and reindex the node with the unwritable block file")
50+
with self.nodes[0].assert_debug_log(expected_msgs=['FlushStateToDisk', 'failed to open file'], unexpected_msgs=[]):
51+
self.nodes[0].assert_start_raises_init_error(extra_args=['-reindex', '-fastprune'],
52+
expected_msg="Error: A fatal internal error occurred, see debug.log for details")
53+
54+
if used_chattr:
55+
subprocess.check_call(['chattr', '-i', filename])
56+
57+
filename.chmod(0o777)
58+
59+
def run_test(self):
60+
self.reindex_readonly()
61+
62+
63+
if __name__ == '__main__':
64+
BlockstoreReindexTest().main()

test/functional/test_runner.py

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
'wallet_abandonconflict.py --legacy-wallet',
163163
'wallet_abandonconflict.py --descriptors',
164164
'feature_reindex.py',
165+
'feature_reindex_readonly.py',
165166
'wallet_labels.py --legacy-wallet',
166167
'wallet_labels.py --descriptors',
167168
'p2p_compactblocks.py',

0 commit comments

Comments
 (0)