0diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py
1index 6ee075f906..1913002962 100755
2--- a/test/functional/feature_init.py
3+++ b/test/functional/feature_init.py
4@@ -9,6 +9,7 @@ import platform
5 import shutil
6 import signal
7 import subprocess
8+from dataclasses import dataclass, field
9
10 from test_framework.test_framework import BitcoinTestFramework
11 from test_framework.test_node import (
12@@ -107,74 +108,55 @@ class InitTest(BitcoinTestFramework):
13
14 self.log.info("Test startup errors after removing certain essential files")
15
16- deletion_rounds = [
17- {
18- 'filepath_glob': 'blocks/index/*.ldb',
19- 'error_message': 'Error opening block database.',
20- 'startup_args': [],
21- },
22- {
23- 'filepath_glob': 'chainstate/*.ldb',
24- 'error_message': 'Error opening coins database.',
25- 'startup_args': ['-checklevel=4'],
26- },
27- {
28- 'filepath_glob': 'blocks/blk*.dat',
29- 'error_message': 'Error loading block database.',
30- 'startup_args': ['-checkblocks=200', '-checklevel=4'],
31- },
32- {
33- 'filepath_glob': 'indexes/txindex/MANIFEST*',
34- 'error_message': 'LevelDB error: Corruption: CURRENT points to a non-existent file',
35- 'startup_args': ['-txindex=1'],
36- },
37+ [@dataclass](/bitcoin-bitcoin/contributor/dataclass/)
38+ class RoundInfo:
39+ filepath_glob: str
40+ error_message: str
41+ startup_args: list[str] = field(default_factory=list)
42+
43+ deletion_rounds: tuple[RoundInfo, ...] = (
44+ RoundInfo(filepath_glob='blocks/index/*.ldb',
45+ error_message='Error opening block database.'),
46+ RoundInfo(filepath_glob='chainstate/*.ldb',
47+ error_message='Error opening coins database.',
48+ startup_args=['-checklevel=4']),
49+ RoundInfo(filepath_glob='blocks/blk*.dat',
50+ error_message='Error loading block database.',
51+ startup_args=['-checkblocks=200', '-checklevel=4']),
52+ RoundInfo(filepath_glob='indexes/txindex/MANIFEST*',
53+ error_message='LevelDB error: Corruption: CURRENT points to a non-existent file.',
54+ startup_args=['-txindex=1']),
55 # Removing these files does not result in a startup error:
56 # 'indexes/blockfilter/basic/*.dat', 'indexes/blockfilter/basic/db/*.*', 'indexes/coinstats/db/*.*',
57 # 'indexes/txindex/*.log', 'indexes/txindex/CURRENT', 'indexes/txindex/LOCK'
58- ]
59-
60- perturbation_rounds = [
61- {
62- 'filepath_glob': 'blocks/index/*.ldb',
63- 'error_message': 'Error loading block database.',
64- 'startup_args': [],
65- },
66- {
67- 'filepath_glob': 'chainstate/*.ldb',
68- 'error_message': 'Error opening coins database.',
69- 'startup_args': [],
70- },
71- {
72- 'filepath_glob': 'blocks/blk*.dat',
73- 'error_message': 'Corrupted block database detected.',
74- 'startup_args': ['-checkblocks=200', '-checklevel=4'],
75- },
76- {
77- 'filepath_glob': 'indexes/blockfilter/basic/db/*.*',
78- 'error_message': 'LevelDB error: Corruption',
79- 'startup_args': ['-blockfilterindex=1'],
80- },
81- {
82- 'filepath_glob': 'indexes/coinstats/db/*.*',
83- 'error_message': 'LevelDB error: Corruption',
84- 'startup_args': ['-coinstatsindex=1'],
85- },
86- {
87- 'filepath_glob': 'indexes/txindex/*.log',
88- 'error_message': 'LevelDB error: Corruption',
89- 'startup_args': ['-txindex=1'],
90- },
91- {
92- 'filepath_glob': 'indexes/txindex/CURRENT',
93- 'error_message': 'LevelDB error: Corruption',
94- 'startup_args': ['-txindex=1'],
95- },
96- ]
97+ )
98+
99+ perturbation_rounds: tuple[RoundInfo, ...] = (
100+ RoundInfo(filepath_glob='blocks/index/*.ldb',
101+ error_message='Error loading block database.'),
102+ RoundInfo(filepath_glob='chainstate/*.ldb',
103+ error_message='Error opening coins database.'),
104+ RoundInfo(filepath_glob='blocks/blk*.dat',
105+ error_message='Corrupted block database detected.',
106+ startup_args=['-checkblocks=200', '-checklevel=4']),
107+ RoundInfo(filepath_glob='indexes/blockfilter/basic/db/*.*',
108+ error_message='LevelDB error: Corruption',
109+ startup_args=['-blockfilterindex=1']),
110+ RoundInfo(filepath_glob='indexes/coinstats/db/*.*',
111+ error_message='LevelDB error: Corruption',
112+ startup_args=['-coinstatsindex=1']),
113+ RoundInfo(filepath_glob='indexes/txindex/*.log',
114+ error_message='LevelDB error: Corruption',
115+ startup_args=['-txindex=1']),
116+ RoundInfo(filepath_glob='indexes/txindex/CURRENT',
117+ error_message='LevelDB error: Corruption',
118+ startup_args=['-txindex=1']),
119+ )
120
121 for round_info in deletion_rounds:
122- file_patt = round_info['filepath_glob']
123- err_fragment = round_info['error_message']
124- startup_args = round_info['startup_args']
125+ file_patt = round_info.filepath_glob
126+ err_fragment = round_info.error_message
127+ startup_args = round_info.startup_args
128 target_files = list(node.chain_path.glob(file_patt))
129
130 for target_file in target_files:
131@@ -195,9 +177,9 @@ class InitTest(BitcoinTestFramework):
132 self.log.info("Test startup errors after perturbing certain essential files")
133 dirs = ["blocks", "chainstate", "indexes"]
134 for round_info in perturbation_rounds:
135- file_patt = round_info['filepath_glob']
136- err_fragment = round_info['error_message']
137- startup_args = round_info['startup_args']
138+ file_patt = round_info.filepath_glob
139+ err_fragment = round_info.error_message
140+ startup_args = round_info.startup_args
141
142 for dir in dirs:
143 shutil.copytree(node.chain_path / dir, node.chain_path / f"{dir}_bak")