mithril_common/digesters/
dummy_cardano_db.rs1use crate::test_utils::TempDir;
2use crate::{
3 digesters::{ImmutableFile, IMMUTABLE_DIR, LEDGER_DIR, VOLATILE_DIR},
4 entities::ImmutableFileNumber,
5};
6use std::{
7 fs::File,
8 io::prelude::Write,
9 path::{Path, PathBuf},
10};
11
12struct DummyImmutableDb {
14 dir: PathBuf,
16 immutables_files: Vec<ImmutableFile>,
18 non_immutables_files: Vec<PathBuf>,
20}
21
22impl DummyImmutableDb {
23 pub fn add_immutable_file(&mut self) -> ImmutableFileNumber {
25 let new_file_number = self.last_immutable_number().unwrap_or(0) + 1;
26 let mut new_files = write_immutable_trio(None, &self.dir, new_file_number);
27
28 self.immutables_files.append(&mut new_files);
29
30 new_file_number
31 }
32
33 pub fn last_immutable_number(&self) -> Option<ImmutableFileNumber> {
35 self.immutables_files.last().map(|f| f.number)
36 }
37}
38
39pub struct DummyCardanoDb {
41 dir: PathBuf,
43
44 immutable_db: DummyImmutableDb,
46
47 ledger_files: Vec<PathBuf>,
49}
50
51impl DummyCardanoDb {
52 pub fn get_dir(&self) -> &PathBuf {
54 &self.dir
55 }
56
57 pub fn get_immutable_dir(&self) -> &PathBuf {
59 &self.immutable_db.dir
60 }
61
62 pub fn get_ledger_dir(&self) -> PathBuf {
64 self.dir.join(LEDGER_DIR)
65 }
66
67 pub fn get_volatile_dir(&self) -> PathBuf {
69 self.dir.join(VOLATILE_DIR)
70 }
71
72 pub fn get_immutable_files(&self) -> &Vec<ImmutableFile> {
74 &self.immutable_db.immutables_files
75 }
76
77 pub fn get_ledger_files(&self) -> &Vec<PathBuf> {
79 &self.ledger_files
80 }
81
82 pub fn add_immutable_file(&mut self) -> ImmutableFileNumber {
84 self.immutable_db.add_immutable_file()
85 }
86
87 pub fn last_immutable_number(&self) -> Option<ImmutableFileNumber> {
89 self.immutable_db.last_immutable_number()
90 }
91
92 pub fn get_non_immutables_files(&self) -> &Vec<PathBuf> {
94 &self.immutable_db.non_immutables_files
95 }
96}
97
98pub struct DummyCardanoDbBuilder {
100 sub_dir: String,
101 immutables_to_write: Vec<ImmutableFileNumber>,
102 non_immutables_to_write: Vec<String>,
103 append_uncompleted_trio: bool,
104 immutable_file_size: Option<u64>,
105 ledger_files_to_write: Vec<String>,
106 ledger_file_size: Option<u64>,
107 volatile_files_to_write: Vec<String>,
108 volatile_file_size: Option<u64>,
109}
110
111impl DummyCardanoDbBuilder {
112 pub fn new(dir_name: &str) -> Self {
115 Self {
116 sub_dir: dir_name.to_string(),
117 immutables_to_write: vec![],
118 non_immutables_to_write: vec![],
119 append_uncompleted_trio: false,
120 immutable_file_size: None,
121 ledger_files_to_write: vec![],
122 ledger_file_size: None,
123 volatile_files_to_write: vec![],
124 volatile_file_size: None,
125 }
126 }
127
128 pub fn with_immutables(&mut self, immutables: &[ImmutableFileNumber]) -> &mut Self {
131 self.immutables_to_write = immutables.to_vec();
132 self
133 }
134
135 pub fn with_non_immutables(&mut self, non_immutables: &[&str]) -> &mut Self {
137 self.non_immutables_to_write = non_immutables.iter().map(|f| f.to_string()).collect();
138 self
139 }
140
141 pub fn with_ledger_files(&mut self, files: &[&str]) -> &mut Self {
143 self.ledger_files_to_write = files.iter().map(|name| name.to_string()).collect();
144 self
145 }
146
147 pub fn set_ledger_file_size(&mut self, file_size: u64) -> &mut Self {
149 self.ledger_file_size = Some(file_size);
150 self
151 }
152
153 pub fn with_volatile_files(&mut self, files: &[&str]) -> &mut Self {
155 self.volatile_files_to_write = files.iter().map(|f| f.to_string()).collect();
156 self
157 }
158
159 pub fn set_volatile_file_size(&mut self, file_size: u64) -> &mut Self {
161 self.volatile_file_size = Some(file_size);
162 self
163 }
164
165 pub fn append_immutable_trio(&mut self) -> &mut Self {
169 self.append_uncompleted_trio = true;
170 self
171 }
172
173 pub fn set_immutable_trio_file_size(&mut self, trio_file_size: u64) -> &mut Self {
177 assert!(
178 trio_file_size % 3 == 0,
179 "'trio_file_size' must be a multiple of 3"
180 );
181
182 self.immutable_file_size = Some(trio_file_size / 3);
183 self
184 }
185
186 pub fn build(&self) -> DummyCardanoDb {
188 let dir = get_test_dir(&self.sub_dir);
189
190 let mut ledger_files = vec![];
191 let mut non_immutables_files = vec![];
192 let mut immutable_numbers = self.immutables_to_write.clone();
193 immutable_numbers.sort();
194
195 if self.append_uncompleted_trio {
196 write_immutable_trio(
197 self.immutable_file_size,
198 &dir.join(IMMUTABLE_DIR),
199 match immutable_numbers.last() {
200 None => 0,
201 Some(last) => last + 1,
202 },
203 );
204 }
205
206 for non_immutable in &self.non_immutables_to_write {
207 non_immutables_files.push(write_dummy_file(
208 self.immutable_file_size,
209 &dir.join(IMMUTABLE_DIR),
210 non_immutable,
211 ));
212 }
213
214 for filename in &self.ledger_files_to_write {
215 let ledger_file_path =
216 write_dummy_file(self.ledger_file_size, &dir.join(LEDGER_DIR), filename);
217 ledger_files.push(ledger_file_path);
218 }
219
220 for filename in &self.volatile_files_to_write {
221 write_dummy_file(self.volatile_file_size, &dir.join(VOLATILE_DIR), filename);
222 }
223
224 let immutable_db = DummyImmutableDb {
225 dir: dir.join(IMMUTABLE_DIR),
226 immutables_files: immutable_numbers
227 .into_iter()
228 .flat_map(|ifn| {
229 write_immutable_trio(self.immutable_file_size, &dir.join(IMMUTABLE_DIR), ifn)
230 })
231 .collect::<Vec<_>>(),
232 non_immutables_files,
233 };
234
235 DummyCardanoDb {
236 dir,
237 immutable_db,
238 ledger_files,
239 }
240 }
241}
242
243fn write_immutable_trio(
244 optional_size: Option<u64>,
245 dir: &Path,
246 immutable: ImmutableFileNumber,
247) -> Vec<ImmutableFile> {
248 let mut result = vec![];
249 for filename in [
250 format!("{immutable:05}.chunk"),
251 format!("{immutable:05}.primary"),
252 format!("{immutable:05}.secondary"),
253 ] {
254 let file = write_dummy_file(optional_size, dir, &filename);
255 result.push(ImmutableFile {
256 number: immutable.to_owned(),
257 path: file,
258 filename: filename.to_string(),
259 });
260 }
261 result
262}
263
264fn write_dummy_file(optional_size: Option<u64>, dir: &Path, filename: &str) -> PathBuf {
267 let file = dir.join(Path::new(filename));
268 let mut source_file = File::create(&file).unwrap();
269
270 write!(source_file, "This is a test file named '{filename}'").unwrap();
271
272 if let Some(file_size) = optional_size {
273 writeln!(source_file).unwrap();
274 source_file.set_len(file_size).unwrap();
275 }
276
277 file
278}
279
280fn get_test_dir(subdir_name: &str) -> PathBuf {
281 let db_dir = TempDir::create("test_cardano_db", subdir_name);
282 for subdir_name in [LEDGER_DIR, IMMUTABLE_DIR, VOLATILE_DIR] {
283 std::fs::create_dir(db_dir.join(subdir_name)).unwrap();
284 }
285
286 db_dir
287}