aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
authorMatthew Zipkin <pinheadmz@gmail.com>2023-06-21 10:41:09 -0400
committerMatthew Zipkin <pinheadmz@gmail.com>2023-09-14 12:02:01 -0400
commitde8f9123afbecc3b4f59fa80af8148bc865d0588 (patch)
tree249466a9f9d2e424126ca1aa86d707856b459912 /test/functional
parent5c2185b3b624ce87320ec16412f98ab591a5860c (diff)
test: cover read-only blockstore
Co-authored-by: Andrew Chow <github@achow101.com>
Diffstat (limited to 'test/functional')
-rwxr-xr-xtest/functional/feature_reindex_readonly.py64
-rwxr-xr-xtest/functional/test_runner.py1
2 files changed, 65 insertions, 0 deletions
diff --git a/test/functional/feature_reindex_readonly.py b/test/functional/feature_reindex_readonly.py
new file mode 100755
index 0000000000..9f1bb30023
--- /dev/null
+++ b/test/functional/feature_reindex_readonly.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test running bitcoind with -reindex from a read-only blockstore
+- Start a node, generate blocks, then restart with -reindex after setting blk files to read-only
+"""
+
+import platform
+import stat
+import subprocess
+from test_framework.test_framework import BitcoinTestFramework
+
+
+class BlockstoreReindexTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [["-fastprune"]]
+
+ def reindex_readonly(self):
+ self.log.debug("Generate block big enough to start second block file")
+ fastprune_blockfile_size = 0x10000
+ opreturn = "6a"
+ nulldata = fastprune_blockfile_size * "ff"
+ self.generateblock(self.nodes[0], output=f"raw({opreturn}{nulldata})", transactions=[])
+ self.stop_node(0)
+
+ assert (self.nodes[0].chain_path / "blocks" / "blk00000.dat").exists()
+ assert (self.nodes[0].chain_path / "blocks" / "blk00001.dat").exists()
+
+ self.log.debug("Make the first block file read-only")
+ filename = self.nodes[0].chain_path / "blocks" / "blk00000.dat"
+ filename.chmod(stat.S_IREAD)
+
+ used_chattr = False
+ if platform.system() == "Linux":
+ try:
+ subprocess.run(['chattr', '+i', filename], capture_output=True, check=True)
+ used_chattr = True
+ self.log.info("Made file immutable with chattr")
+ except subprocess.CalledProcessError as e:
+ self.log.warning(str(e))
+ if e.stdout:
+ self.log.warning(f"stdout: {e.stdout}")
+ if e.stderr:
+ self.log.warning(f"stderr: {e.stderr}")
+
+ 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=[]):
+ 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])
+
+ filename.chmod(0o777)
+
+ def run_test(self):
+ self.reindex_readonly()
+
+
+if __name__ == '__main__':
+ BlockstoreReindexTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index db04bb8bdb..f44a5be19f 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -162,6 +162,7 @@ BASE_SCRIPTS = [
'wallet_abandonconflict.py --legacy-wallet',
'wallet_abandonconflict.py --descriptors',
'feature_reindex.py',
+ 'feature_reindex_readonly.py',
'wallet_labels.py --legacy-wallet',
'wallet_labels.py --descriptors',
'p2p_compactblocks.py',