ot_tools_io/
banks.rs

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