nit: Could use @dataclass for slightly less stringly typed code, and tuple for immutability:
<details><summary>Expand for diff</summary>
diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py
index 6ee075f906..1913002962 100755
--- a/test/functional/feature_init.py
+++ b/test/functional/feature_init.py
@@ -9,6 +9,7 @@ import platform
import shutil
import signal
import subprocess
+from dataclasses import dataclass, field
from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import (
@@ -107,74 +108,55 @@ class InitTest(BitcoinTestFramework):
self.log.info("Test startup errors after removing certain essential files")
- deletion_rounds = [
- {
- 'filepath_glob': 'blocks/index/*.ldb',
- 'error_message': 'Error opening block database.',
- 'startup_args': [],
- },
- {
- 'filepath_glob': 'chainstate/*.ldb',
- 'error_message': 'Error opening coins database.',
- 'startup_args': ['-checklevel=4'],
- },
- {
- 'filepath_glob': 'blocks/blk*.dat',
- 'error_message': 'Error loading block database.',
- 'startup_args': ['-checkblocks=200', '-checklevel=4'],
- },
- {
- 'filepath_glob': 'indexes/txindex/MANIFEST*',
- 'error_message': 'LevelDB error: Corruption: CURRENT points to a non-existent file',
- 'startup_args': ['-txindex=1'],
- },
+ [@dataclass](/bitcoin-bitcoin/contributor/dataclass/)
+ class RoundInfo:
+ filepath_glob: str
+ error_message: str
+ startup_args: list[str] = field(default_factory=list)
+
+ deletion_rounds: tuple[RoundInfo, ...] = (
+ RoundInfo(filepath_glob='blocks/index/*.ldb',
+ error_message='Error opening block database.'),
+ RoundInfo(filepath_glob='chainstate/*.ldb',
+ error_message='Error opening coins database.',
+ startup_args=['-checklevel=4']),
+ RoundInfo(filepath_glob='blocks/blk*.dat',
+ error_message='Error loading block database.',
+ startup_args=['-checkblocks=200', '-checklevel=4']),
+ RoundInfo(filepath_glob='indexes/txindex/MANIFEST*',
+ error_message='LevelDB error: Corruption: CURRENT points to a non-existent file.',
+ startup_args=['-txindex=1']),
# Removing these files does not result in a startup error:
# 'indexes/blockfilter/basic/*.dat', 'indexes/blockfilter/basic/db/*.*', 'indexes/coinstats/db/*.*',
# 'indexes/txindex/*.log', 'indexes/txindex/CURRENT', 'indexes/txindex/LOCK'
- ]
-
- perturbation_rounds = [
- {
- 'filepath_glob': 'blocks/index/*.ldb',
- 'error_message': 'Error loading block database.',
- 'startup_args': [],
- },
- {
- 'filepath_glob': 'chainstate/*.ldb',
- 'error_message': 'Error opening coins database.',
- 'startup_args': [],
- },
- {
- 'filepath_glob': 'blocks/blk*.dat',
- 'error_message': 'Corrupted block database detected.',
- 'startup_args': ['-checkblocks=200', '-checklevel=4'],
- },
- {
- 'filepath_glob': 'indexes/blockfilter/basic/db/*.*',
- 'error_message': 'LevelDB error: Corruption',
- 'startup_args': ['-blockfilterindex=1'],
- },
- {
- 'filepath_glob': 'indexes/coinstats/db/*.*',
- 'error_message': 'LevelDB error: Corruption',
- 'startup_args': ['-coinstatsindex=1'],
- },
- {
- 'filepath_glob': 'indexes/txindex/*.log',
- 'error_message': 'LevelDB error: Corruption',
- 'startup_args': ['-txindex=1'],
- },
- {
- 'filepath_glob': 'indexes/txindex/CURRENT',
- 'error_message': 'LevelDB error: Corruption',
- 'startup_args': ['-txindex=1'],
- },
- ]
+ )
+
+ perturbation_rounds: tuple[RoundInfo, ...] = (
+ RoundInfo(filepath_glob='blocks/index/*.ldb',
+ error_message='Error loading block database.'),
+ RoundInfo(filepath_glob='chainstate/*.ldb',
+ error_message='Error opening coins database.'),
+ RoundInfo(filepath_glob='blocks/blk*.dat',
+ error_message='Corrupted block database detected.',
+ startup_args=['-checkblocks=200', '-checklevel=4']),
+ RoundInfo(filepath_glob='indexes/blockfilter/basic/db/*.*',
+ error_message='LevelDB error: Corruption',
+ startup_args=['-blockfilterindex=1']),
+ RoundInfo(filepath_glob='indexes/coinstats/db/*.*',
+ error_message='LevelDB error: Corruption',
+ startup_args=['-coinstatsindex=1']),
+ RoundInfo(filepath_glob='indexes/txindex/*.log',
+ error_message='LevelDB error: Corruption',
+ startup_args=['-txindex=1']),
+ RoundInfo(filepath_glob='indexes/txindex/CURRENT',
+ error_message='LevelDB error: Corruption',
+ startup_args=['-txindex=1']),
+ )
for round_info in deletion_rounds:
- file_patt = round_info['filepath_glob']
- err_fragment = round_info['error_message']
- startup_args = round_info['startup_args']
+ file_patt = round_info.filepath_glob
+ err_fragment = round_info.error_message
+ startup_args = round_info.startup_args
target_files = list(node.chain_path.glob(file_patt))
for target_file in target_files:
@@ -195,9 +177,9 @@ class InitTest(BitcoinTestFramework):
self.log.info("Test startup errors after perturbing certain essential files")
dirs = ["blocks", "chainstate", "indexes"]
for round_info in perturbation_rounds:
- file_patt = round_info['filepath_glob']
- err_fragment = round_info['error_message']
- startup_args = round_info['startup_args']
+ file_patt = round_info.filepath_glob
+ err_fragment = round_info.error_message
+ startup_args = round_info.startup_args
for dir in dirs:
shutil.copytree(node.chain_path / dir, node.chain_path / f"{dir}_bak")
</details>