Skip to main content

ot_tools_io/
banks.rs

1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2026 Mike Robeson [dijksterhuis]
4*/
5
6//! Types for `bank??.*` binary data files.
7
8use crate::parts::Part;
9use crate::patterns::Pattern;
10
11use crate::generics::{Parts, Patterns};
12use crate::identifiers::SavedState;
13use crate::{
14    Defaults, HasChecksumField, HasFileVersionField, HasHeaderField, OctatrackFileIO,
15    OtToolsIoError,
16};
17use itertools::Itertools;
18use ot_tools_io_derive::{
19    ArrayDefaults, AsMutDerive, AsRefDerive, BoxedArrayDefaults, IntegrityChecks, IsDefaultCheck,
20};
21use serde::{Deserialize, Serialize};
22use serde_big_array::BigArray;
23use std::array::from_fn;
24
25/// Bank header data.
26/// ```text
27/// FORM....DPS1BANK.....
28/// 46 4f 52 4d 00 00 00 00 44 50 53 31 42 41 4e 4b 00 00 00 00 00
29/// [70 79 82 77 0 0 0 0 68 80 83 49 66 65 78 75 0 0 0 0 0]
30/// ```
31pub const BANK_HEADER: [u8; 21] = [
32    70, 79, 82, 77, 0, 0, 0, 0, 68, 80, 83, 49, 66, 65, 78, 75, 0, 0, 0, 0, 0,
33];
34
35/// Current/supported version of bank files.
36pub const BANK_FILE_VERSION: u8 = 23;
37
38const BANK_DEFAULT_CHECKSUM: u16 = 48022;
39
40/// An Octatrack Bank. Contains data related to Parts and Patterns.
41#[derive(
42    Clone,
43    Debug,
44    Eq,
45    Hash,
46    Ord,
47    PartialEq,
48    PartialOrd,
49    Serialize,
50    Deserialize,
51    AsMutDerive,
52    AsRefDerive,
53    ArrayDefaults,
54    BoxedArrayDefaults,
55    IsDefaultCheck,
56    IntegrityChecks,
57)]
58pub struct BankFile {
59    /// Misc header data for Banks.
60    /// Always follows the same format.
61    #[serde(with = "BigArray")]
62    pub header: [u8; 21],
63
64    pub datatype_version: u8,
65
66    pub patterns: Patterns<Pattern>,
67
68    /// Unsaved/currently editing part data for this bank
69    pub parts_unsaved: Parts<Part>,
70
71    /// Saved part data for this bank
72    pub parts_saved: Parts<Part>,
73
74    /// Indicates which parts have previously saved state available for reloading.
75    #[serde(with = "BigArray")]
76    pub parts_saved_state: [u8; 4],
77
78    /// Bit mask indicating which parts are currently in an edited state.
79    /// ```text
80    /// parts
81    /// 1 2 3 4 | mask
82    /// --------|------
83    /// - - - - | 0
84    /// x - - - | 1
85    /// - x - - | 2
86    /// - - x - | 4
87    /// - - - x | 8
88    /// --------|------
89    /// x x - - | 3
90    /// x - x - | 5
91    /// - x x - | 6
92    /// x x x - | 7
93    /// x - - x | 9
94    /// - x - x | 10
95    /// x x - x | 11
96    /// - - x x | 12
97    /// - x x x | 14
98    /// x x x x | 15
99    /// ```
100    pub parts_edited_bitmask: u8,
101
102    /// Names for each Part within the Bank.
103    /// Maximum 7 character length.
104    #[serde(with = "BigArray")]
105    pub part_names: [[u8; 7]; 4],
106
107    /// checksum bytes
108    pub checksum: u16,
109}
110
111impl BankFile {
112    /// Returns an reference to [`Patterns`] data
113    ///
114    /// ```
115    /// # use ot_tools_io::types::{BankFile, Patterns};
116    ///
117    /// assert_eq!(
118    ///     BankFile::default().patterns_ref(),
119    ///     &Patterns::default(),
120    /// )
121    /// ```
122    pub fn patterns_ref(&self) -> &Patterns<Pattern> {
123        &self.patterns
124    }
125
126    /// Returns a mutable reference to [`Patterns`] data
127    ///
128    /// ```
129    /// # use ot_tools_io::types::{BankFile, Patterns};
130    ///
131    /// assert_eq!(
132    ///     BankFile::default().patterns_mut(),
133    ///     &mut Patterns::default(),
134    /// )
135    /// ```
136    pub fn patterns_mut(&mut self) -> &mut Patterns<Pattern> {
137        &mut self.patterns
138    }
139
140    /// Returns an owned [`Parts`] for the given [`SavedState`]
141    ///
142    /// ```
143    /// use ot_tools_io::types::{BankFile, Parts};
144    /// use ot_tools_io::identifiers::{SavedState, PartId};
145    ///
146    /// assert_eq!(
147    ///     BankFile::default().parts(&SavedState::Working),
148    ///     Parts::default(),
149    /// );
150    ///
151    /// // can be used to chain lookups like so
152    /// BankFile::default().parts(&SavedState::Working).id(&PartId::One);
153    /// ```
154    pub fn parts(self, saved_state: &SavedState) -> Parts<Part> {
155        match saved_state {
156            SavedState::Working => self.parts_unsaved,
157            SavedState::Stored => self.parts_saved,
158        }
159    }
160
161    /// Returns a reference to [`Parts`] for the given [`SavedState`]
162    ///
163    /// ```
164    /// use ot_tools_io::types::{BankFile, Parts};
165    /// use ot_tools_io::identifiers::{SavedState, PartId};
166    ///
167    /// assert_eq!(
168    ///     BankFile::default().parts_ref(&SavedState::Working),
169    ///     &Parts::default(),
170    /// );
171    ///
172    /// // can be used to chain lookups like so
173    /// BankFile::default().parts_ref(&SavedState::Working).id_ref(&PartId::One);
174    /// ```
175    pub fn parts_ref(&self, saved_state: &SavedState) -> &Parts<Part> {
176        match saved_state {
177            SavedState::Working => &self.parts_unsaved,
178            SavedState::Stored => &self.parts_saved,
179        }
180    }
181
182    /// Returns a mutable reference to the [`Parts`] for the given [`SavedState`]
183    ///
184    /// ```
185    /// use ot_tools_io::types::{BankFile, Parts};
186    /// use ot_tools_io::identifiers::{SavedState, PartId};
187    ///
188    /// assert_eq!(
189    ///     BankFile::default().parts_mut(&SavedState::Working),
190    ///     &mut Parts::default(),
191    /// );
192    ///
193    /// // can be used to chain lookups like so
194    /// BankFile::default().parts_mut(&SavedState::Working).id_mut(&PartId::One);
195    /// ```
196    pub fn parts_mut(&mut self, saved_state: &SavedState) -> &mut Parts<Part> {
197        match saved_state {
198            SavedState::Working => &mut self.parts_unsaved,
199            SavedState::Stored => &mut self.parts_saved,
200        }
201    }
202
203    const PART_BITMASK_BASE: [u8; 4] = [1, 2, 4, 8];
204
205    /// Get the "edited" state for each part as a `[bool; 4]` set of flags.
206    ///
207    /// ```
208    /// use ot_tools_io::types::BankFile;
209    ///
210    /// assert_eq!(
211    ///     BankFile::default().parts_edit_states(),
212    ///     [false, false, false, false]
213    /// );
214    /// ```
215    pub fn parts_edit_states(&self) -> [bool; 4] {
216        Self::PART_BITMASK_BASE
217            .iter()
218            .map(|x| (self.parts_edited_bitmask & x) > 0)
219            .collect_array()
220            .unwrap()
221    }
222
223    /// Get the "saved" state for each part as a `[bool; 4]` set of flags.
224    ///
225    /// ```
226    /// use ot_tools_io::types::BankFile;
227    ///
228    /// assert_eq!(
229    ///     BankFile::default().part_save_states(),
230    ///     [false, false, false, false]
231    /// );
232    /// ```
233    pub fn part_save_states(&self) -> [bool; 4] {
234        self.parts_saved_state
235            .iter()
236            .map(|x| x > &0)
237            .collect_array()
238            .unwrap()
239    }
240
241    fn part_name_to_string(arr: &[u8; 7]) -> String {
242        String::from_utf8(arr.to_vec())
243            .unwrap_or("ERR".to_string())
244            .replace("\0", "")
245    }
246
247    /// Get names of parts as a `[String; 4]`
248    ///
249    /// ```
250    /// use ot_tools_io::types::BankFile;
251    ///
252    /// assert_eq!(
253    ///     BankFile::default().part_name_strings(),
254    ///     [
255    ///         String::from("ONE"),
256    ///         String::from("TWO"),
257    ///         String::from("THREE"),
258    ///         String::from("FOUR"),
259    ///     ]
260    /// );
261    /// ```
262    pub fn part_name_strings(&self) -> [String; 4] {
263        self.part_names
264            .iter()
265            .map(Self::part_name_to_string)
266            .collect_array()
267            .unwrap()
268    }
269}
270
271/// Default Part names (ONE, TWO, THREE, FOUR) converted to u8 for ease of use.
272const DEFAULT_PART_NAMES: [[u8; 7]; 4] = [
273    [0x4f, 0x4e, 0x45, 0x00, 0x00, 0x00, 0x00], // "ONE",
274    [0x54, 0x57, 0x4f, 0x00, 0x00, 0x00, 0x00], // "TWO",
275    [0x54, 0x48, 0x52, 0x45, 0x45, 0x00, 0x00], // "THREE",
276    [0x46, 0x4f, 0x55, 0x52, 0x00, 0x00, 0x00], // "FOUR",
277];
278
279impl OctatrackFileIO for BankFile {
280    fn to_bytes(&self) -> Result<Vec<u8>, OtToolsIoError>
281    where
282        Self: Serialize,
283    {
284        let mut chkd = self.clone();
285        chkd.checksum = self.calculate_checksum()?;
286        let bytes = bincode::serialize(&chkd)?;
287        Ok(bytes)
288    }
289}
290
291impl Default for BankFile {
292    fn default() -> Self {
293        Self {
294            header: BANK_HEADER,
295            datatype_version: BANK_FILE_VERSION,
296            patterns: Patterns::<Pattern>::default(),
297            parts_unsaved: Parts::<Part>::default(),
298            parts_saved: Parts::<Part>::default(),
299            parts_saved_state: from_fn(|_| 0),
300            parts_edited_bitmask: 0,
301            part_names: DEFAULT_PART_NAMES,
302            // WARN: mutated during encode! do not calculate checksum in this
303            // method until i've refactored `get_checksum` to not use Bank::default()
304            // (end up with a never ending recursive loop of calling default)
305            // TODO: Hardcoded
306            checksum: BANK_DEFAULT_CHECKSUM,
307        }
308    }
309}
310
311#[cfg(test)]
312mod from_bytes {
313    use crate::{
314        read_bin_file, test_utils::get_blank_proj_dirpath, BankFile, OctatrackFileIO,
315        OtToolsIoError,
316    };
317    #[test]
318    fn valid() -> Result<(), OtToolsIoError> {
319        let path = get_blank_proj_dirpath().join("bank01.work");
320        let bytes = read_bin_file(&path)?;
321        let s = BankFile::from_bytes(&bytes)?;
322        assert_eq!(s, BankFile::default());
323        Ok(())
324    }
325}
326
327#[cfg(test)]
328mod to_bytes {
329    use crate::{
330        read_bin_file, test_utils::get_blank_proj_dirpath, BankFile, OctatrackFileIO,
331        OtToolsIoError,
332    };
333    #[test]
334    fn valid() -> Result<(), OtToolsIoError> {
335        let path = get_blank_proj_dirpath().join("bank01.work");
336        let bytes = read_bin_file(&path)?;
337        let b = BankFile::default().to_bytes()?;
338        assert_eq!(b, bytes);
339        Ok(())
340    }
341}
342
343impl HasChecksumField for BankFile {
344    fn calculate_checksum(&self) -> Result<u16, OtToolsIoError> {
345        let bytes = bincode::serialize(self)?;
346        // Note: the header field is 21 bytes, but only the first 20 are skipped
347        let payload = &bytes[20..bytes.len() - 2];
348        let mut checksum: u16 = 0;
349        for b in payload {
350            checksum = checksum.wrapping_add(*b as u16);
351        }
352        if cfg!(target_endian = "little") {
353            Ok(checksum.swap_bytes())
354        } else {
355            Ok(checksum)
356        }
357    }
358
359    fn update_checksum(&mut self) -> Result<(), OtToolsIoError> {
360        self.checksum = self.calculate_checksum()?;
361        Ok(())
362    }
363
364    fn check_checksum(&self) -> Result<bool, OtToolsIoError> {
365        Ok(self.checksum == self.calculate_checksum()?)
366    }
367}
368
369#[cfg(test)]
370mod checksum_field {
371    use crate::{BankFile, HasChecksumField, OtToolsIoError};
372    #[test]
373    fn valid() -> Result<(), OtToolsIoError> {
374        let mut x = BankFile::default();
375        x.checksum = x.calculate_checksum()?;
376        assert!(x.check_checksum()?);
377        Ok(())
378    }
379
380    #[test]
381    fn invalid() -> Result<(), OtToolsIoError> {
382        let x = BankFile {
383            checksum: u16::MAX,
384            ..Default::default()
385        };
386        assert!(!x.check_checksum()?);
387        Ok(())
388    }
389
390    mod files {
391        use crate::test_utils::{get_bank_dirpath, get_blank_proj_dirpath};
392        use crate::{BankFile, HasChecksumField, OctatrackFileIO, OtToolsIoError};
393        use std::path::Path;
394
395        fn helper_test_chksum(fp: &Path) -> Result<(u16, u16), OtToolsIoError> {
396            let valid = BankFile::from_data_file(fp)?;
397            let mut test = valid.clone();
398            test.checksum = 0;
399            let chk = test.calculate_checksum()?;
400            Ok((chk, valid.checksum))
401        }
402
403        #[allow(clippy::field_reassign_with_default)]
404        #[test]
405        fn default_method() -> Result<(), OtToolsIoError> {
406            let (_, valid) = helper_test_chksum(&get_blank_proj_dirpath().join("bank01.work"))?;
407            let mut x = BankFile::default();
408            x.checksum = 0;
409            let test = x.calculate_checksum()?;
410            assert_eq!(test, valid);
411            Ok(())
412        }
413
414        #[test]
415        fn default_bank1_file() -> Result<(), OtToolsIoError> {
416            let (test, valid) = helper_test_chksum(&get_blank_proj_dirpath().join("bank01.work"))?;
417            assert_eq!(test, valid);
418            Ok(())
419        }
420
421        #[test]
422        fn default_bank2_file() -> Result<(), OtToolsIoError> {
423            let (test, valid) = helper_test_chksum(&get_blank_proj_dirpath().join("bank02.work"))?;
424            assert_eq!(test, valid);
425            Ok(())
426        }
427
428        #[test]
429        fn one_scene_zero_val() -> Result<(), OtToolsIoError> {
430            // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
431            let (test, valid) = helper_test_chksum(
432                &get_bank_dirpath()
433                    .join("checksum")
434                    .join("scene1-atrack1-lfo-dep1-zero.work"),
435            )?;
436            assert_eq!(test, valid);
437            Ok(())
438        }
439
440        #[test]
441        fn one_scene_127_val() -> Result<(), OtToolsIoError> {
442            // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
443            let (test, valid) = helper_test_chksum(
444                &get_bank_dirpath()
445                    .join("checksum")
446                    .join("scene1-atrack1-lfo-dep1-127.work"),
447            )?;
448            assert_eq!(test, valid);
449            Ok(())
450        }
451
452        #[test]
453        fn scene_params_decr_lots() -> Result<(), OtToolsIoError> {
454            // all scenes have assignments on the LFO parameters for track 1 - sets everything tp 0
455            let (test, valid) = helper_test_chksum(
456                &get_bank_dirpath()
457                    .join("checksum")
458                    .join("all-scenes-lfo-params-zeroed.work"),
459            )?;
460            assert_eq!(test, valid);
461            Ok(())
462        }
463
464        mod static_strt_only {
465            use super::helper_test_chksum;
466            use crate::test_utils::get_bank_dirpath;
467            use crate::OtToolsIoError;
468
469            #[test]
470            fn static_strt_1() -> Result<(), OtToolsIoError> {
471                // start value incremented by one on the machine
472                let (test, valid) = helper_test_chksum(
473                    &get_bank_dirpath()
474                        .join("checksum")
475                        .join("static-strt-1.work"),
476                )?;
477                assert_eq!(test, valid);
478                Ok(())
479            }
480
481            #[test]
482            fn static_strt_2() -> Result<(), OtToolsIoError> {
483                // start value incremented by two on the machine
484                let (test, valid) = helper_test_chksum(
485                    &get_bank_dirpath()
486                        .join("checksum")
487                        .join("static-strt-2.work"),
488                )?;
489                assert_eq!(test, valid);
490                Ok(())
491            }
492
493            #[test]
494            fn static_strt_10() -> Result<(), OtToolsIoError> {
495                // start value incremented by ten on the machine
496                let (test, valid) = helper_test_chksum(
497                    &get_bank_dirpath()
498                        .join("checksum")
499                        .join("static-strt-10.work"),
500                )?;
501                assert_eq!(test, valid);
502                Ok(())
503            }
504
505            // off by one -- this is why we have so many of these test examples
506            #[test]
507            fn static_strt_127() -> Result<(), OtToolsIoError> {
508                // start value incremented by 127 (max) on the machine
509                let (test, valid) = helper_test_chksum(
510                    &get_bank_dirpath()
511                        .join("checksum")
512                        .join("static-strt-127.work"),
513                )?;
514                assert_eq!(test, valid);
515                Ok(())
516            }
517
518            #[test]
519            fn static_strt_126() -> Result<(), OtToolsIoError> {
520                let (test, valid) = helper_test_chksum(
521                    &get_bank_dirpath()
522                        .join("checksum")
523                        .join("static-strt-126.work"),
524                )?;
525                assert_eq!(test, valid);
526                Ok(())
527            }
528
529            #[test]
530            fn static_strt_125() -> Result<(), OtToolsIoError> {
531                let (test, valid) = helper_test_chksum(
532                    &get_bank_dirpath()
533                        .join("checksum")
534                        .join("static-strt-125.work"),
535                )?;
536                assert_eq!(test, valid);
537                Ok(())
538            }
539
540            #[test]
541            fn static_strt_124() -> Result<(), OtToolsIoError> {
542                let (test, valid) = helper_test_chksum(
543                    &get_bank_dirpath()
544                        .join("checksum")
545                        .join("static-strt-124.work"),
546                )?;
547                assert_eq!(test, valid);
548                Ok(())
549            }
550
551            #[test]
552            fn static_strt_123() -> Result<(), OtToolsIoError> {
553                let (test, valid) = helper_test_chksum(
554                    &get_bank_dirpath()
555                        .join("checksum")
556                        .join("static-strt-123.work"),
557                )?;
558                assert_eq!(test, valid);
559                Ok(())
560            }
561
562            #[test]
563            fn static_strt_122() -> Result<(), OtToolsIoError> {
564                let (test, valid) = helper_test_chksum(
565                    &get_bank_dirpath()
566                        .join("checksum")
567                        .join("static-strt-122.work"),
568                )?;
569                assert_eq!(test, valid);
570                Ok(())
571            }
572
573            #[test]
574            fn static_strt_121() -> Result<(), OtToolsIoError> {
575                let (test, valid) = helper_test_chksum(
576                    &get_bank_dirpath()
577                        .join("checksum")
578                        .join("static-strt-121.work"),
579                )?;
580                assert_eq!(test, valid);
581                Ok(())
582            }
583
584            #[test]
585            fn static_strt_120() -> Result<(), OtToolsIoError> {
586                let (test, valid) = helper_test_chksum(
587                    &get_bank_dirpath()
588                        .join("checksum")
589                        .join("static-strt-120.work"),
590                )?;
591                assert_eq!(test, valid);
592                Ok(())
593            }
594
595            #[test]
596            fn static_strt_119() -> Result<(), OtToolsIoError> {
597                let (test, valid) = helper_test_chksum(
598                    &get_bank_dirpath()
599                        .join("checksum")
600                        .join("static-strt-119.work"),
601                )?;
602                assert_eq!(test, valid);
603                Ok(())
604            }
605
606            #[test]
607            fn static_strt_118() -> Result<(), OtToolsIoError> {
608                let (test, valid) = helper_test_chksum(
609                    &get_bank_dirpath()
610                        .join("checksum")
611                        .join("static-strt-118.work"),
612                )?;
613                assert_eq!(test, valid);
614                Ok(())
615            }
616
617            #[test]
618            fn static_strt_117() -> Result<(), OtToolsIoError> {
619                let (test, valid) = helper_test_chksum(
620                    &get_bank_dirpath()
621                        .join("checksum")
622                        .join("static-strt-117.work"),
623                )?;
624                assert_eq!(test, valid);
625                Ok(())
626            }
627
628            #[test]
629            fn static_strt_116() -> Result<(), OtToolsIoError> {
630                let (test, valid) = helper_test_chksum(
631                    &get_bank_dirpath()
632                        .join("checksum")
633                        .join("static-strt-116.work"),
634                )?;
635                assert_eq!(test, valid);
636                Ok(())
637            }
638
639            #[test]
640            fn static_strt_115() -> Result<(), OtToolsIoError> {
641                let (test, valid) = helper_test_chksum(
642                    &get_bank_dirpath()
643                        .join("checksum")
644                        .join("static-strt-115.work"),
645                )?;
646                assert_eq!(test, valid);
647                Ok(())
648            }
649
650            #[test]
651            fn static_strt_114() -> Result<(), OtToolsIoError> {
652                let (test, valid) = helper_test_chksum(
653                    &get_bank_dirpath()
654                        .join("checksum")
655                        .join("static-strt-114.work"),
656                )?;
657                assert_eq!(test, valid);
658                Ok(())
659            }
660
661            #[test]
662            fn static_strt_113() -> Result<(), OtToolsIoError> {
663                let (test, valid) = helper_test_chksum(
664                    &get_bank_dirpath()
665                        .join("checksum")
666                        .join("static-strt-113.work"),
667                )?;
668                assert_eq!(test, valid);
669                Ok(())
670            }
671
672            #[test]
673            fn static_strt_112() -> Result<(), OtToolsIoError> {
674                let (test, valid) = helper_test_chksum(
675                    &get_bank_dirpath()
676                        .join("checksum")
677                        .join("static-strt-112.work"),
678                )?;
679                assert_eq!(test, valid);
680                Ok(())
681            }
682
683            #[test]
684            fn static_strt_111() -> Result<(), OtToolsIoError> {
685                let (test, valid) = helper_test_chksum(
686                    &get_bank_dirpath()
687                        .join("checksum")
688                        .join("static-strt-111.work"),
689                )?;
690                assert_eq!(test, valid);
691                Ok(())
692            }
693
694            #[test]
695            fn static_strt_71() -> Result<(), OtToolsIoError> {
696                let (test, valid) = helper_test_chksum(
697                    &get_bank_dirpath()
698                        .join("checksum")
699                        .join("static-strt-71.work"),
700                )?;
701                assert_eq!(test, valid);
702                Ok(())
703            }
704
705            #[test]
706            fn static_strt_70() -> Result<(), OtToolsIoError> {
707                let (test, valid) = helper_test_chksum(
708                    &get_bank_dirpath()
709                        .join("checksum")
710                        .join("static-strt-70.work"),
711                )?;
712                assert_eq!(test, valid);
713                Ok(())
714            }
715
716            #[test]
717            fn static_strt_69() -> Result<(), OtToolsIoError> {
718                let (test, valid) = helper_test_chksum(
719                    &get_bank_dirpath()
720                        .join("checksum")
721                        .join("static-strt-69.work"),
722                )?;
723                assert_eq!(test, valid);
724                Ok(())
725            }
726
727            #[test]
728            fn static_strt_68() -> Result<(), OtToolsIoError> {
729                let (test, valid) = helper_test_chksum(
730                    &get_bank_dirpath()
731                        .join("checksum")
732                        .join("static-strt-68.work"),
733                )?;
734                assert_eq!(test, valid);
735                Ok(())
736            }
737
738            #[test]
739            fn static_strt_67() -> Result<(), OtToolsIoError> {
740                let (test, valid) = helper_test_chksum(
741                    &get_bank_dirpath()
742                        .join("checksum")
743                        .join("static-strt-67.work"),
744                )?;
745                assert_eq!(test, valid);
746                Ok(())
747            }
748
749            #[test]
750            fn static_strt_66() -> Result<(), OtToolsIoError> {
751                let (test, valid) = helper_test_chksum(
752                    &get_bank_dirpath()
753                        .join("checksum")
754                        .join("static-strt-66.work"),
755                )?;
756                assert_eq!(test, valid);
757                Ok(())
758            }
759
760            #[test]
761            fn static_strt_65() -> Result<(), OtToolsIoError> {
762                let (test, valid) = helper_test_chksum(
763                    &get_bank_dirpath()
764                        .join("checksum")
765                        .join("static-strt-65.work"),
766                )?;
767                assert_eq!(test, valid);
768                Ok(())
769            }
770
771            #[test]
772            fn static_strt_64() -> Result<(), OtToolsIoError> {
773                let (test, valid) = helper_test_chksum(
774                    &get_bank_dirpath()
775                        .join("checksum")
776                        .join("static-strt-64.work"),
777                )?;
778                assert_eq!(test, valid);
779                Ok(())
780            }
781
782            #[test]
783            fn static_strt_63() -> Result<(), OtToolsIoError> {
784                let (test, valid) = helper_test_chksum(
785                    &get_bank_dirpath()
786                        .join("checksum")
787                        .join("static-strt-63.work"),
788                )?;
789                assert_eq!(test, valid);
790                Ok(())
791            }
792
793            #[test]
794            fn static_strt_62() -> Result<(), OtToolsIoError> {
795                let (test, valid) = helper_test_chksum(
796                    &get_bank_dirpath()
797                        .join("checksum")
798                        .join("static-strt-62.work"),
799                )?;
800                assert_eq!(test, valid);
801                Ok(())
802            }
803
804            #[test]
805            fn static_strt_61() -> Result<(), OtToolsIoError> {
806                let (test, valid) = helper_test_chksum(
807                    &get_bank_dirpath()
808                        .join("checksum")
809                        .join("static-strt-61.work"),
810                )?;
811                assert_eq!(test, valid);
812                Ok(())
813            }
814
815            #[test]
816            fn static_strt_60() -> Result<(), OtToolsIoError> {
817                let (test, valid) = helper_test_chksum(
818                    &get_bank_dirpath()
819                        .join("checksum")
820                        .join("static-strt-60.work"),
821                )?;
822                assert_eq!(test, valid);
823                Ok(())
824            }
825
826            #[test]
827            fn static_strt_59() -> Result<(), OtToolsIoError> {
828                let (test, valid) = helper_test_chksum(
829                    &get_bank_dirpath()
830                        .join("checksum")
831                        .join("static-strt-59.work"),
832                )?;
833                assert_eq!(test, valid);
834                Ok(())
835            }
836
837            #[test]
838            fn static_strt_58() -> Result<(), OtToolsIoError> {
839                let (test, valid) = helper_test_chksum(
840                    &get_bank_dirpath()
841                        .join("checksum")
842                        .join("static-strt-58.work"),
843                )?;
844                assert_eq!(test, valid);
845                Ok(())
846            }
847
848            #[test]
849            fn static_strt_57() -> Result<(), OtToolsIoError> {
850                let (test, valid) = helper_test_chksum(
851                    &get_bank_dirpath()
852                        .join("checksum")
853                        .join("static-strt-57.work"),
854                )?;
855                assert_eq!(test, valid);
856                Ok(())
857            }
858
859            #[test]
860            fn static_strt_56() -> Result<(), OtToolsIoError> {
861                let (test, valid) = helper_test_chksum(
862                    &get_bank_dirpath()
863                        .join("checksum")
864                        .join("static-strt-56.work"),
865                )?;
866                assert_eq!(test, valid);
867                Ok(())
868            }
869        }
870
871        mod static_strt_mult {
872            use super::helper_test_chksum;
873            use crate::test_utils::get_bank_dirpath;
874            use crate::OtToolsIoError;
875
876            #[test]
877            fn static_strt_127_len_128() -> Result<(), OtToolsIoError> {
878                // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
879                let (test, valid) = helper_test_chksum(
880                    &get_bank_dirpath()
881                        .join("checksum")
882                        .join("static-strt-127-len-128.work"),
883                )?;
884                assert_eq!(test, valid);
885                Ok(())
886            }
887
888            #[test]
889            fn static_strt_67_len_67() -> Result<(), OtToolsIoError> {
890                let (test, valid) = helper_test_chksum(
891                    &get_bank_dirpath()
892                        .join("checksum")
893                        .join("static-strt-67-len-67.work"),
894                )?;
895                assert_eq!(test, valid);
896                Ok(())
897            }
898
899            #[test]
900            fn static_strt_67_len_68() -> Result<(), OtToolsIoError> {
901                let (test, valid) = helper_test_chksum(
902                    &get_bank_dirpath()
903                        .join("checksum")
904                        .join("static-strt-67-len-68.work"),
905                )?;
906                assert_eq!(test, valid);
907                Ok(())
908            }
909
910            #[test]
911            fn static_strt_68_len_68() -> Result<(), OtToolsIoError> {
912                let (test, valid) = helper_test_chksum(
913                    &get_bank_dirpath()
914                        .join("checksum")
915                        .join("static-strt-68-len-68.work"),
916                )?;
917                assert_eq!(test, valid);
918                Ok(())
919            }
920
921            #[test]
922            fn static_strt_67_len_66() -> Result<(), OtToolsIoError> {
923                let (test, valid) = helper_test_chksum(
924                    &get_bank_dirpath()
925                        .join("checksum")
926                        .join("static-strt-67-len-66.work"),
927                )?;
928                assert_eq!(test, valid);
929                Ok(())
930            }
931
932            #[test]
933            fn static_strt_66_len_66() -> Result<(), OtToolsIoError> {
934                let (test, valid) = helper_test_chksum(
935                    &get_bank_dirpath()
936                        .join("checksum")
937                        .join("static-strt-66-len-66.work"),
938                )?;
939                assert_eq!(test, valid);
940                Ok(())
941            }
942
943            #[test]
944            fn static_strt_32_len_32() -> Result<(), OtToolsIoError> {
945                let (test, valid) = helper_test_chksum(
946                    &get_bank_dirpath()
947                        .join("checksum")
948                        .join("static-strt-32-len-32.work"),
949                )?;
950                assert_eq!(test, valid);
951                Ok(())
952            }
953
954            #[test]
955            fn static_strt_32_len_33() -> Result<(), OtToolsIoError> {
956                let (test, valid) = helper_test_chksum(
957                    &get_bank_dirpath()
958                        .join("checksum")
959                        .join("static-strt-32-len-33.work"),
960                )?;
961                assert_eq!(test, valid);
962                Ok(())
963            }
964
965            #[test]
966            fn static_strt_33_len_33() -> Result<(), OtToolsIoError> {
967                let (test, valid) = helper_test_chksum(
968                    &get_bank_dirpath()
969                        .join("checksum")
970                        .join("static-strt-33-len-33.work"),
971                )?;
972                assert_eq!(test, valid);
973                Ok(())
974            }
975
976            #[test]
977            fn static_strt_32_len_31() -> Result<(), OtToolsIoError> {
978                let (test, valid) = helper_test_chksum(
979                    &get_bank_dirpath()
980                        .join("checksum")
981                        .join("static-strt-32-len-31.work"),
982                )?;
983                assert_eq!(test, valid);
984                Ok(())
985            }
986
987            #[test]
988            fn static_strt_31_len_31() -> Result<(), OtToolsIoError> {
989                let (test, valid) = helper_test_chksum(
990                    &get_bank_dirpath()
991                        .join("checksum")
992                        .join("static-strt-31-len-31.work"),
993                )?;
994                assert_eq!(test, valid);
995                Ok(())
996            }
997
998            #[test]
999            fn static_strt_67_len_67_rtrg_68() -> Result<(), OtToolsIoError> {
1000                let (test, valid) = helper_test_chksum(
1001                    &get_bank_dirpath()
1002                        .join("checksum")
1003                        .join("static-strt-67-len-67-rtrg-68.work"),
1004                )?;
1005                assert_eq!(test, valid);
1006                Ok(())
1007            }
1008
1009            #[test]
1010            fn static_strt_67_len_68_rtrg_68() -> Result<(), OtToolsIoError> {
1011                let (test, valid) = helper_test_chksum(
1012                    &get_bank_dirpath()
1013                        .join("checksum")
1014                        .join("static-strt-67-len-68-rtrg-68.work"),
1015                )?;
1016                assert_eq!(test, valid);
1017                Ok(())
1018            }
1019
1020            #[test]
1021            fn static_strt_67_len_69_rtrg_68() -> Result<(), OtToolsIoError> {
1022                let (test, valid) = helper_test_chksum(
1023                    &get_bank_dirpath()
1024                        .join("checksum")
1025                        .join("static-strt-67-len-69-rtrg-68.work"),
1026                )?;
1027                assert_eq!(test, valid);
1028                Ok(())
1029            }
1030
1031            #[test]
1032            fn static_strt_67_len_69_rtrg_69() -> Result<(), OtToolsIoError> {
1033                let (test, valid) = helper_test_chksum(
1034                    &get_bank_dirpath()
1035                        .join("checksum")
1036                        .join("static-strt-67-len-69-rtrg-69.work"),
1037                )?;
1038                assert_eq!(test, valid);
1039                Ok(())
1040            }
1041
1042            #[test]
1043            fn static_strt_67_len_69_rtrg_67() -> Result<(), OtToolsIoError> {
1044                let (test, valid) = helper_test_chksum(
1045                    &get_bank_dirpath()
1046                        .join("checksum")
1047                        .join("static-strt-67-len-69-rtrg-67.work"),
1048                )?;
1049                assert_eq!(test, valid);
1050                Ok(())
1051            }
1052
1053            #[test]
1054            fn static_strt_67_len_67_rtrg_67() -> Result<(), OtToolsIoError> {
1055                let (test, valid) = helper_test_chksum(
1056                    &get_bank_dirpath()
1057                        .join("checksum")
1058                        .join("static-strt-67-len-67-rtrg-67.work"),
1059                )?;
1060                assert_eq!(test, valid);
1061                Ok(())
1062            }
1063        }
1064
1065        mod flex_strt {
1066            use super::helper_test_chksum;
1067            use crate::test_utils::get_bank_dirpath;
1068            use crate::OtToolsIoError;
1069
1070            #[test]
1071            fn flex_strt_126() -> Result<(), OtToolsIoError> {
1072                let (test, valid) = helper_test_chksum(
1073                    &get_bank_dirpath()
1074                        .join("checksum")
1075                        .join("flex-strt-126.work"),
1076                )?;
1077                assert_eq!(test, valid);
1078                Ok(())
1079            }
1080
1081            #[test]
1082            fn flex_strt_125() -> Result<(), OtToolsIoError> {
1083                let (test, valid) = helper_test_chksum(
1084                    &get_bank_dirpath()
1085                        .join("checksum")
1086                        .join("flex-strt-125.work"),
1087                )?;
1088                assert_eq!(test, valid);
1089                Ok(())
1090            }
1091
1092            #[test]
1093            fn flex_strt_124() -> Result<(), OtToolsIoError> {
1094                let (test, valid) = helper_test_chksum(
1095                    &get_bank_dirpath()
1096                        .join("checksum")
1097                        .join("flex-strt-124.work"),
1098                )?;
1099                assert_eq!(test, valid);
1100                Ok(())
1101            }
1102
1103            #[test]
1104            fn flex_strt_123() -> Result<(), OtToolsIoError> {
1105                let (test, valid) = helper_test_chksum(
1106                    &get_bank_dirpath()
1107                        .join("checksum")
1108                        .join("flex-strt-123.work"),
1109                )?;
1110                assert_eq!(test, valid);
1111                Ok(())
1112            }
1113
1114            #[test]
1115            fn flex_strt_122() -> Result<(), OtToolsIoError> {
1116                let (test, valid) = helper_test_chksum(
1117                    &get_bank_dirpath()
1118                        .join("checksum")
1119                        .join("flex-strt-122.work"),
1120                )?;
1121                assert_eq!(test, valid);
1122                Ok(())
1123            }
1124
1125            #[test]
1126            fn flex_strt_121() -> Result<(), OtToolsIoError> {
1127                let (test, valid) = helper_test_chksum(
1128                    &get_bank_dirpath()
1129                        .join("checksum")
1130                        .join("flex-strt-121.work"),
1131                )?;
1132                assert_eq!(test, valid);
1133                Ok(())
1134            }
1135
1136            #[test]
1137            fn flex_strt_120() -> Result<(), OtToolsIoError> {
1138                let (test, valid) = helper_test_chksum(
1139                    &get_bank_dirpath()
1140                        .join("checksum")
1141                        .join("flex-strt-120.work"),
1142                )?;
1143                assert_eq!(test, valid);
1144                Ok(())
1145            }
1146
1147            #[test]
1148            fn flex_strt_119() -> Result<(), OtToolsIoError> {
1149                let (test, valid) = helper_test_chksum(
1150                    &get_bank_dirpath()
1151                        .join("checksum")
1152                        .join("flex-strt-119.work"),
1153                )?;
1154                assert_eq!(test, valid);
1155                Ok(())
1156            }
1157
1158            #[test]
1159            fn flex_strt_118() -> Result<(), OtToolsIoError> {
1160                let (test, valid) = helper_test_chksum(
1161                    &get_bank_dirpath()
1162                        .join("checksum")
1163                        .join("flex-strt-118.work"),
1164                )?;
1165                assert_eq!(test, valid);
1166                Ok(())
1167            }
1168
1169            #[test]
1170            fn flex_strt_117() -> Result<(), OtToolsIoError> {
1171                let (test, valid) = helper_test_chksum(
1172                    &get_bank_dirpath()
1173                        .join("checksum")
1174                        .join("flex-strt-117.work"),
1175                )?;
1176                assert_eq!(test, valid);
1177                Ok(())
1178            }
1179
1180            #[test]
1181            fn flex_strt_116() -> Result<(), OtToolsIoError> {
1182                let (test, valid) = helper_test_chksum(
1183                    &get_bank_dirpath()
1184                        .join("checksum")
1185                        .join("flex-strt-116.work"),
1186                )?;
1187                assert_eq!(test, valid);
1188                Ok(())
1189            }
1190
1191            #[test]
1192            fn flex_strt_115() -> Result<(), OtToolsIoError> {
1193                let (test, valid) = helper_test_chksum(
1194                    &get_bank_dirpath()
1195                        .join("checksum")
1196                        .join("flex-strt-115.work"),
1197                )?;
1198                assert_eq!(test, valid);
1199                Ok(())
1200            }
1201
1202            #[test]
1203            fn flex_strt_114() -> Result<(), OtToolsIoError> {
1204                let (test, valid) = helper_test_chksum(
1205                    &get_bank_dirpath()
1206                        .join("checksum")
1207                        .join("flex-strt-114.work"),
1208                )?;
1209                assert_eq!(test, valid);
1210                Ok(())
1211            }
1212
1213            #[test]
1214            fn flex_strt_113() -> Result<(), OtToolsIoError> {
1215                let (test, valid) = helper_test_chksum(
1216                    &get_bank_dirpath()
1217                        .join("checksum")
1218                        .join("flex-strt-113.work"),
1219                )?;
1220                assert_eq!(test, valid);
1221                Ok(())
1222            }
1223
1224            #[test]
1225            fn flex_strt_112() -> Result<(), OtToolsIoError> {
1226                let (test, valid) = helper_test_chksum(
1227                    &get_bank_dirpath()
1228                        .join("checksum")
1229                        .join("flex-strt-112.work"),
1230                )?;
1231                assert_eq!(test, valid);
1232                Ok(())
1233            }
1234
1235            #[test]
1236            fn flex_strt_111() -> Result<(), OtToolsIoError> {
1237                let (test, valid) = helper_test_chksum(
1238                    &get_bank_dirpath()
1239                        .join("checksum")
1240                        .join("flex-strt-111.work"),
1241                )?;
1242                assert_eq!(test, valid);
1243                Ok(())
1244            }
1245        }
1246
1247        mod track_parameters {
1248            use super::helper_test_chksum;
1249            use crate::test_utils::get_bank_dirpath;
1250            use crate::OtToolsIoError;
1251
1252            #[test]
1253            fn track_params_attack_127() -> Result<(), OtToolsIoError> {
1254                let (test, valid) = helper_test_chksum(
1255                    &get_bank_dirpath()
1256                        .join("checksum")
1257                        .join("tparams-attack-127.work"),
1258                )?;
1259                assert_eq!(test, valid);
1260                Ok(())
1261            }
1262
1263            #[test]
1264            fn track_params_hold_0() -> Result<(), OtToolsIoError> {
1265                let (test, valid) = helper_test_chksum(
1266                    &get_bank_dirpath()
1267                        .join("checksum")
1268                        .join("tparams-hold-0.work"),
1269                )?;
1270                assert_eq!(test, valid);
1271                Ok(())
1272            }
1273
1274            #[test]
1275            fn track_params_release_0() -> Result<(), OtToolsIoError> {
1276                let (test, valid) = helper_test_chksum(
1277                    &get_bank_dirpath()
1278                        .join("checksum")
1279                        .join("tparams-rel-0.work"),
1280                )?;
1281                assert_eq!(test, valid);
1282                Ok(())
1283            }
1284            #[test]
1285            fn track_params_vol_neg64() -> Result<(), OtToolsIoError> {
1286                let (test, valid) = helper_test_chksum(
1287                    &get_bank_dirpath()
1288                        .join("checksum")
1289                        .join("tparams-vol-neg64.work"),
1290                )?;
1291                assert_eq!(test, valid);
1292                Ok(())
1293            }
1294
1295            #[test]
1296            fn track_params_vol_pos63() -> Result<(), OtToolsIoError> {
1297                let (test, valid) = helper_test_chksum(
1298                    &get_bank_dirpath()
1299                        .join("checksum")
1300                        .join("tparams-vol-pos63.work"),
1301                )?;
1302                assert_eq!(test, valid);
1303                Ok(())
1304            }
1305
1306            #[test]
1307            fn track_params_balance_neg64() -> Result<(), OtToolsIoError> {
1308                let (test, valid) = helper_test_chksum(
1309                    &get_bank_dirpath()
1310                        .join("checksum")
1311                        .join("tparams-bal-neg64.work"),
1312                )?;
1313                assert_eq!(test, valid);
1314                Ok(())
1315            }
1316
1317            #[test]
1318            fn track_params_balance_pos63() -> Result<(), OtToolsIoError> {
1319                let (test, valid) = helper_test_chksum(
1320                    &get_bank_dirpath()
1321                        .join("checksum")
1322                        .join("tparams-bal-pos63.work"),
1323                )?;
1324                assert_eq!(test, valid);
1325                Ok(())
1326            }
1327
1328            #[test]
1329            fn track_params_lfo1_spd_0() -> Result<(), OtToolsIoError> {
1330                let (test, valid) = helper_test_chksum(
1331                    &get_bank_dirpath()
1332                        .join("checksum")
1333                        .join("tparams-lfo1-spd-0.work"),
1334                )?;
1335                assert_eq!(test, valid);
1336                Ok(())
1337            }
1338
1339            #[test]
1340            fn track_params_lfo1_spd_127() -> Result<(), OtToolsIoError> {
1341                let (test, valid) = helper_test_chksum(
1342                    &get_bank_dirpath()
1343                        .join("checksum")
1344                        .join("tparams-lfo1-spd-127.work"),
1345                )?;
1346                assert_eq!(test, valid);
1347                Ok(())
1348            }
1349
1350            #[test]
1351            fn track_params_lfo1_amt_64() -> Result<(), OtToolsIoError> {
1352                let (test, valid) = helper_test_chksum(
1353                    &get_bank_dirpath()
1354                        .join("checksum")
1355                        .join("tparams-lfo1-amt-64.work"),
1356                )?;
1357                assert_eq!(test, valid);
1358                Ok(())
1359            }
1360
1361            #[test]
1362            fn track_params_lfo1_amt_127() -> Result<(), OtToolsIoError> {
1363                let (test, valid) = helper_test_chksum(
1364                    &get_bank_dirpath()
1365                        .join("checksum")
1366                        .join("tparams-lfo1-amt-127.work"),
1367                )?;
1368                assert_eq!(test, valid);
1369                Ok(())
1370            }
1371
1372            #[test]
1373            fn track_params_fx1_filter_base_127() -> Result<(), OtToolsIoError> {
1374                let (test, valid) = helper_test_chksum(
1375                    &get_bank_dirpath()
1376                        .join("checksum")
1377                        .join("tparams-fx1-filt-base-127.work"),
1378                )?;
1379                assert_eq!(test, valid);
1380                Ok(())
1381            }
1382
1383            #[test]
1384            fn track_params_fx1_filter_width_0() -> Result<(), OtToolsIoError> {
1385                let (test, valid) = helper_test_chksum(
1386                    &get_bank_dirpath()
1387                        .join("checksum")
1388                        .join("tparams-fx1-filt-wid-0.work"),
1389                )?;
1390                assert_eq!(test, valid);
1391                Ok(())
1392            }
1393
1394            #[test]
1395            fn track_params_fx1_filter_q_127() -> Result<(), OtToolsIoError> {
1396                let (test, valid) = helper_test_chksum(
1397                    &get_bank_dirpath()
1398                        .join("checksum")
1399                        .join("tparams-fx1-filt-q-127.work"),
1400                )?;
1401                assert_eq!(test, valid);
1402                Ok(())
1403            }
1404
1405            #[test]
1406            fn track_params_fx1_filter_depth_neg64() -> Result<(), OtToolsIoError> {
1407                let (test, valid) = helper_test_chksum(
1408                    &get_bank_dirpath()
1409                        .join("checksum")
1410                        .join("tparams-fx1-filt-dep-neg64.work"),
1411                )?;
1412                assert_eq!(test, valid);
1413                Ok(())
1414            }
1415
1416            #[test]
1417            fn track_params_fx1_filter_depth_pos63() -> Result<(), OtToolsIoError> {
1418                let (test, valid) = helper_test_chksum(
1419                    &get_bank_dirpath()
1420                        .join("checksum")
1421                        .join("tparams-fx1-filt-dep-pos63.work"),
1422                )?;
1423                assert_eq!(test, valid);
1424                Ok(())
1425            }
1426
1427            #[test]
1428            fn track_params_fx2_delay_snd_127() -> Result<(), OtToolsIoError> {
1429                // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
1430                let (test, valid) = helper_test_chksum(
1431                    &get_bank_dirpath()
1432                        .join("checksum")
1433                        .join("atrack1-delay-snd-127.work"),
1434                )?;
1435                assert_eq!(test, valid);
1436                Ok(())
1437            }
1438        }
1439
1440        mod lfo_designer {
1441            use super::helper_test_chksum;
1442            use crate::test_utils::get_bank_dirpath;
1443            use crate::OtToolsIoError;
1444
1445            #[test]
1446            fn lfo_design_atr1_step1_pos64() -> Result<(), OtToolsIoError> {
1447                let (test, valid) = helper_test_chksum(
1448                    &get_bank_dirpath()
1449                        .join("checksum")
1450                        .join("lfo-design-step1-64.work"),
1451                )?;
1452                assert_eq!(test, valid);
1453                Ok(())
1454            }
1455
1456            #[test]
1457            fn lfo_design_atr1_step1_pos127() -> Result<(), OtToolsIoError> {
1458                let (test, valid) = helper_test_chksum(
1459                    &get_bank_dirpath()
1460                        .join("checksum")
1461                        .join("lfo-design-step1-127.work"),
1462                )?;
1463                assert_eq!(test, valid);
1464                Ok(())
1465            }
1466
1467            #[test]
1468            fn lfo_design_atr1_step1_neg64() -> Result<(), OtToolsIoError> {
1469                let (test, valid) = helper_test_chksum(
1470                    &get_bank_dirpath()
1471                        .join("checksum")
1472                        .join("lfo-design-step1-neg64.work"),
1473                )?;
1474                assert_eq!(test, valid);
1475                Ok(())
1476            }
1477
1478            #[test]
1479            fn lfo_design_atr1_step1_neg128() -> Result<(), OtToolsIoError> {
1480                let (test, valid) = helper_test_chksum(
1481                    &get_bank_dirpath()
1482                        .join("checksum")
1483                        .join("lfo-design-step1-neg128.work"),
1484                )?;
1485                assert_eq!(test, valid);
1486                Ok(())
1487            }
1488
1489            #[test]
1490            fn lfo_design_atr1_randomised() -> Result<(), OtToolsIoError> {
1491                let (test, valid) = helper_test_chksum(
1492                    &get_bank_dirpath()
1493                        .join("checksum")
1494                        .join("lfo-design-randomised.work"),
1495                )?;
1496                assert_eq!(test, valid);
1497                Ok(())
1498            }
1499        }
1500        mod real_bank_files {
1501            use super::helper_test_chksum;
1502            use crate::test_utils::get_bank_dirpath;
1503            use crate::OtToolsIoError;
1504
1505            mod romant_delete {
1506                use super::*;
1507                #[test]
1508                fn b01() -> Result<(), OtToolsIoError> {
1509                    let (test, valid) = helper_test_chksum(
1510                        &get_bank_dirpath()
1511                            .join("checksum")
1512                            .join("romant-delete-b01.work"),
1513                    )?;
1514                    assert_eq!(test, valid);
1515                    Ok(())
1516                }
1517                #[test]
1518                fn b02() -> Result<(), OtToolsIoError> {
1519                    let (test, valid) = helper_test_chksum(
1520                        &get_bank_dirpath()
1521                            .join("checksum")
1522                            .join("romant-delete-b02.work"),
1523                    )?;
1524                    assert_eq!(test, valid);
1525                    Ok(())
1526                }
1527                #[test]
1528                fn b03() -> Result<(), OtToolsIoError> {
1529                    let (test, valid) = helper_test_chksum(
1530                        &get_bank_dirpath()
1531                            .join("checksum")
1532                            .join("romant-delete-b03.work"),
1533                    )?;
1534                    assert_eq!(test, valid);
1535                    Ok(())
1536                }
1537                #[test]
1538                fn b04() -> Result<(), OtToolsIoError> {
1539                    let (test, valid) = helper_test_chksum(
1540                        &get_bank_dirpath()
1541                            .join("checksum")
1542                            .join("romant-delete-b04.work"),
1543                    )?;
1544                    assert_eq!(test, valid);
1545                    Ok(())
1546                }
1547                #[test]
1548                fn b05() -> Result<(), OtToolsIoError> {
1549                    let (test, valid) = helper_test_chksum(
1550                        &get_bank_dirpath()
1551                            .join("checksum")
1552                            .join("romant-delete-b05.work"),
1553                    )?;
1554                    assert_eq!(test, valid);
1555                    Ok(())
1556                }
1557                #[test]
1558                fn b06() -> Result<(), OtToolsIoError> {
1559                    let (test, valid) = helper_test_chksum(
1560                        &get_bank_dirpath()
1561                            .join("checksum")
1562                            .join("romant-delete-b06.work"),
1563                    )?;
1564                    assert_eq!(test, valid);
1565                    Ok(())
1566                }
1567                #[test]
1568                fn b07() -> Result<(), OtToolsIoError> {
1569                    let (test, valid) = helper_test_chksum(
1570                        &get_bank_dirpath()
1571                            .join("checksum")
1572                            .join("romant-delete-b07.work"),
1573                    )?;
1574                    assert_eq!(test, valid);
1575                    Ok(())
1576                }
1577                #[test]
1578                fn b08() -> Result<(), OtToolsIoError> {
1579                    let (test, valid) = helper_test_chksum(
1580                        &get_bank_dirpath()
1581                            .join("checksum")
1582                            .join("romant-delete-b08.work"),
1583                    )?;
1584                    assert_eq!(test, valid);
1585                    Ok(())
1586                }
1587                #[test]
1588                fn b09() -> Result<(), OtToolsIoError> {
1589                    let (test, valid) = helper_test_chksum(
1590                        &get_bank_dirpath()
1591                            .join("checksum")
1592                            .join("romant-delete-b09.work"),
1593                    )?;
1594                    assert_eq!(test, valid);
1595                    Ok(())
1596                }
1597                #[test]
1598                fn b10() -> Result<(), OtToolsIoError> {
1599                    let (test, valid) = helper_test_chksum(
1600                        &get_bank_dirpath()
1601                            .join("checksum")
1602                            .join("romant-delete-b10.work"),
1603                    )?;
1604                    assert_eq!(test, valid);
1605                    Ok(())
1606                }
1607                #[test]
1608                fn b11() -> Result<(), OtToolsIoError> {
1609                    let (test, valid) = helper_test_chksum(
1610                        &get_bank_dirpath()
1611                            .join("checksum")
1612                            .join("romant-delete-b11.work"),
1613                    )?;
1614                    assert_eq!(test, valid);
1615                    Ok(())
1616                }
1617                #[test]
1618                fn b12() -> Result<(), OtToolsIoError> {
1619                    let (test, valid) = helper_test_chksum(
1620                        &get_bank_dirpath()
1621                            .join("checksum")
1622                            .join("romant-delete-b12.work"),
1623                    )?;
1624                    assert_eq!(test, valid);
1625                    Ok(())
1626                }
1627                #[test]
1628                fn b13() -> Result<(), OtToolsIoError> {
1629                    let (test, valid) = helper_test_chksum(
1630                        &get_bank_dirpath()
1631                            .join("checksum")
1632                            .join("romant-delete-b13.work"),
1633                    )?;
1634                    assert_eq!(test, valid);
1635                    Ok(())
1636                }
1637                #[test]
1638                fn b14() -> Result<(), OtToolsIoError> {
1639                    let (test, valid) = helper_test_chksum(
1640                        &get_bank_dirpath()
1641                            .join("checksum")
1642                            .join("romant-delete-b14.work"),
1643                    )?;
1644                    assert_eq!(test, valid);
1645                    Ok(())
1646                }
1647                #[test]
1648                fn b15() -> Result<(), OtToolsIoError> {
1649                    let (test, valid) = helper_test_chksum(
1650                        &get_bank_dirpath()
1651                            .join("checksum")
1652                            .join("romant-delete-b15.work"),
1653                    )?;
1654                    assert_eq!(test, valid);
1655                    Ok(())
1656                }
1657                #[test]
1658                fn b16() -> Result<(), OtToolsIoError> {
1659                    let (test, valid) = helper_test_chksum(
1660                        &get_bank_dirpath()
1661                            .join("checksum")
1662                            .join("romant-delete-b16.work"),
1663                    )?;
1664                    assert_eq!(test, valid);
1665                    Ok(())
1666                }
1667            }
1668        }
1669
1670        // tests for projects from my main compact flash card
1671        mod main_cfcard {
1672            use super::helper_test_chksum;
1673            use crate::test_utils::get_bank_dirpath;
1674            use crate::OtToolsIoError;
1675            use std::path::{Path, PathBuf};
1676
1677            fn bank_fpaths_from_dirpath(dirpath: &Path) -> Result<Vec<PathBuf>, OtToolsIoError> {
1678                let mut v: Vec<PathBuf> = Vec::new();
1679                for i in 1..=16 {
1680                    let fname = format!["bank{i:0>2}.work"].to_string();
1681                    v.push(dirpath.join(fname).to_path_buf());
1682                }
1683                Ok(v)
1684            }
1685
1686            fn tests_helper(dirname: &str) -> Result<(), OtToolsIoError> {
1687                let fpaths = bank_fpaths_from_dirpath(
1688                    &get_bank_dirpath()
1689                        .join("checksum")
1690                        .join("live")
1691                        .join(dirname),
1692                )?;
1693
1694                let mut results: Vec<bool> = Vec::new();
1695
1696                for test_fpath in fpaths {
1697                    let (test, valid) = helper_test_chksum(&test_fpath)?;
1698
1699                    if test != valid {
1700                        println!("Bad file: {test_fpath:?}");
1701                    }
1702                    results.push(test == valid);
1703                }
1704                println!(
1705                    "\n----------------\n{:?} incorrect file checksums",
1706                    results.iter().filter(|x| !*(*x)).count()
1707                );
1708                assert!(results.iter().all(|x| *x));
1709                Ok(())
1710            }
1711
1712            #[test]
1713            fn romant_delete() -> Result<(), OtToolsIoError> {
1714                tests_helper("ROMANT_DELETING")
1715            }
1716
1717            #[test]
1718            fn iamacameratheworldis() -> Result<(), OtToolsIoError> {
1719                tests_helper("1704Iamacameratheworldis")
1720            }
1721
1722            #[test]
1723            fn a2() -> Result<(), OtToolsIoError> {
1724                tests_helper("A2")
1725            }
1726
1727            #[test]
1728            fn aaaadrafts0() -> Result<(), OtToolsIoError> {
1729                tests_helper("AAAADRAFTS0")
1730            }
1731
1732            #[test]
1733            fn aaaaplay() -> Result<(), OtToolsIoError> {
1734                tests_helper("AAAAplay")
1735            }
1736
1737            #[test]
1738            fn aaambient() -> Result<(), OtToolsIoError> {
1739                tests_helper("AAAMBIENT")
1740            }
1741
1742            #[test]
1743            fn aaasafespaces() -> Result<(), OtToolsIoError> {
1744                tests_helper("AAAsafespaces")
1745            }
1746
1747            #[test]
1748            fn aacrackhead() -> Result<(), OtToolsIoError> {
1749                tests_helper("AACRACKHEAD")
1750            }
1751
1752            #[test]
1753            fn aadrums() -> Result<(), OtToolsIoError> {
1754                tests_helper("AADRUMS")
1755            }
1756
1757            #[test]
1758            fn album5() -> Result<(), OtToolsIoError> {
1759                tests_helper("ALBUM5")
1760            }
1761
1762            #[test]
1763            fn ammbbb() -> Result<(), OtToolsIoError> {
1764                tests_helper("AMMBBB")
1765            }
1766
1767            #[test]
1768            fn empty() -> Result<(), OtToolsIoError> {
1769                tests_helper("EMPTY")
1770            }
1771
1772            #[test]
1773            fn filmsoundings() -> Result<(), OtToolsIoError> {
1774                tests_helper("FILMSOUNDINGS")
1775            }
1776
1777            #[test]
1778            fn gorgieflat() -> Result<(), OtToolsIoError> {
1779                tests_helper("GORGIEFLAT1")
1780            }
1781
1782            #[test]
1783            fn gorgiehow2lose() -> Result<(), OtToolsIoError> {
1784                tests_helper("gorgiehow2lose")
1785            }
1786
1787            #[test]
1788            fn gorgierecordsin() -> Result<(), OtToolsIoError> {
1789                tests_helper("gorgierecordsin")
1790            }
1791
1792            #[test]
1793            fn gorgiettl() -> Result<(), OtToolsIoError> {
1794                tests_helper("gorgiettl")
1795            }
1796
1797            // # cringe
1798            #[test]
1799            fn iwishyouwouldletmeloveyou() -> Result<(), OtToolsIoError> {
1800                tests_helper("IWishYouWouldLetMeLoveYou")
1801            }
1802
1803            #[test]
1804            fn jigg() -> Result<(), OtToolsIoError> {
1805                tests_helper("jigg")
1806            }
1807
1808            #[test]
1809            fn livetechno60days() -> Result<(), OtToolsIoError> {
1810                tests_helper("LIVETECHNO60DAYS")
1811            }
1812
1813            #[test]
1814            fn nawwww() -> Result<(), OtToolsIoError> {
1815                tests_helper("NAWWWWW")
1816            }
1817
1818            #[test]
1819            fn nones() -> Result<(), OtToolsIoError> {
1820                tests_helper("NINES")
1821            }
1822
1823            #[test]
1824            fn no_recording() -> Result<(), OtToolsIoError> {
1825                tests_helper("NO_RECORDING")
1826            }
1827
1828            #[test]
1829            fn other() -> Result<(), OtToolsIoError> {
1830                tests_helper("OTHER")
1831            }
1832
1833            #[test]
1834            fn recovery() -> Result<(), OtToolsIoError> {
1835                tests_helper("recovery")
1836            }
1837
1838            #[test]
1839            fn singleintricatepieces() -> Result<(), OtToolsIoError> {
1840                tests_helper("singleintricatepieces")
1841            }
1842
1843            #[test]
1844            fn songs_back() -> Result<(), OtToolsIoError> {
1845                tests_helper("SONGS_BAck")
1846            }
1847
1848            #[test]
1849            fn songs() -> Result<(), OtToolsIoError> {
1850                tests_helper("SONGS")
1851            }
1852
1853            #[test]
1854            fn stop_talkingnlet_me_dance() -> Result<(), OtToolsIoError> {
1855                tests_helper("stop_talkingnlet_me_dance")
1856            }
1857
1858            #[test]
1859            fn syshalt() -> Result<(), OtToolsIoError> {
1860                tests_helper("sys-halt")
1861            }
1862
1863            #[test]
1864            fn systems() -> Result<(), OtToolsIoError> {
1865                tests_helper("SYSTEMS")
1866            }
1867
1868            #[test]
1869            fn teka() -> Result<(), OtToolsIoError> {
1870                tests_helper("TEkA")
1871            }
1872        }
1873    }
1874}
1875
1876impl HasHeaderField for BankFile {
1877    fn check_header(&self) -> Result<bool, OtToolsIoError> {
1878        Ok(self.header == BANK_HEADER)
1879    }
1880}
1881
1882#[cfg(test)]
1883mod header_field {
1884    use crate::{BankFile, HasHeaderField, OtToolsIoError};
1885    #[test]
1886    fn valid() -> Result<(), OtToolsIoError> {
1887        assert!(BankFile::default().check_header()?);
1888        Ok(())
1889    }
1890
1891    #[test]
1892    fn invalid() -> Result<(), OtToolsIoError> {
1893        let mut mutated = BankFile::default();
1894        mutated.header[0] = 0x00;
1895        mutated.header[20] = 111;
1896        assert!(!mutated.check_header()?);
1897        Ok(())
1898    }
1899}
1900
1901impl HasFileVersionField for BankFile {
1902    fn check_file_version(&self) -> Result<bool, OtToolsIoError> {
1903        Ok(BANK_FILE_VERSION == self.datatype_version)
1904    }
1905}
1906
1907#[cfg(test)]
1908mod file_version_field {
1909    use crate::{BankFile, HasFileVersionField, OtToolsIoError};
1910    #[test]
1911    fn valid() -> Result<(), OtToolsIoError> {
1912        assert!(BankFile::default().check_file_version()?);
1913        Ok(())
1914    }
1915
1916    #[test]
1917    fn invalid() -> Result<(), OtToolsIoError> {
1918        let x = BankFile {
1919            datatype_version: 0,
1920            ..BankFile::default()
1921        };
1922        assert!(!x.check_file_version()?);
1923        Ok(())
1924    }
1925}