1use spacepackets::ByteConversionError;
2use spacepackets::cfdp::ChecksumType;
3#[cfg(feature = "std")]
4pub use std_mod::*;
5
6#[derive(Debug, thiserror::Error)]
7#[cfg_attr(all(feature = "defmt", not(feature = "std")), derive(defmt::Format))]
8#[non_exhaustive]
9pub enum FilestoreError {
10 #[error("file does not exist")]
11 FileDoesNotExist,
12 #[error("file already exists")]
13 FileAlreadyExists,
14 #[error("directory does not exist")]
15 DirDoesNotExist,
16 #[error("permission error")]
17 Permission,
18 #[error("is not a file")]
19 IsNotFile,
20 #[error("is not a directory")]
21 IsNotDirectory,
22 #[error("byte conversion: {0}")]
23 ByteConversion(#[from] ByteConversionError),
24 #[error("IO error: {0})")]
25 #[cfg(feature = "std")]
26 Io(#[from] std::io::Error),
27 #[error("checksum type not implemented: {0:?}")]
28 ChecksumTypeNotImplemented(ChecksumType),
29 #[error("utf8 error")]
30 Utf8Error,
31 #[error("other error")]
32 Other,
33}
34
35pub trait VirtualFilestore {
36 fn create_file(&self, file_path: &str) -> Result<(), FilestoreError>;
37
38 fn remove_file(&self, file_path: &str) -> Result<(), FilestoreError>;
39
40 fn truncate_file(&self, file_path: &str) -> Result<(), FilestoreError>;
43
44 fn remove_dir(&self, dir_path: &str, all: bool) -> Result<(), FilestoreError>;
45 fn create_dir(&self, dir_path: &str) -> Result<(), FilestoreError>;
46
47 fn read_data(
48 &self,
49 file_path: &str,
50 offset: u64,
51 read_len: u64,
52 buf: &mut [u8],
53 ) -> Result<(), FilestoreError>;
54
55 fn write_data(&self, file: &str, offset: u64, buf: &[u8]) -> Result<(), FilestoreError>;
56
57 fn filename_from_full_path(path: &str) -> Option<&str>
58 where
59 Self: Sized;
60
61 fn is_file(&self, path: &str) -> Result<bool, FilestoreError>;
62
63 fn is_dir(&self, path: &str) -> Result<bool, FilestoreError> {
64 Ok(!self.is_file(path)?)
65 }
66
67 fn exists(&self, path: &str) -> Result<bool, FilestoreError>;
68
69 fn file_name<'a>(&self, full_path: &'a str) -> Result<Option<&'a str>, FilestoreError>;
73
74 fn file_size(&self, path: &str) -> Result<u64, FilestoreError>;
75
76 fn calculate_checksum(
84 &self,
85 file_path: &str,
86 checksum_type: ChecksumType,
87 size_to_verify: u64,
88 verification_buf: &mut [u8],
89 ) -> Result<u32, FilestoreError>;
90
91 fn checksum_verify(
99 &self,
100 expected_checksum: u32,
101 file_path: &str,
102 checksum_type: ChecksumType,
103 size_to_verify: u64,
104 verification_buf: &mut [u8],
105 ) -> Result<bool, FilestoreError> {
106 Ok(
107 self.calculate_checksum(file_path, checksum_type, size_to_verify, verification_buf)?
108 == expected_checksum,
109 )
110 }
111}
112
113#[cfg(feature = "std")]
114pub mod std_mod {
115
116 use crc::Crc;
117
118 use crate::{CRC_32, CRC_32C};
119
120 use super::*;
121 use std::{
122 fs::{self, File, OpenOptions},
123 io::{BufReader, Read, Seek, SeekFrom, Write},
124 path::Path,
125 };
126
127 #[derive(Default)]
128 pub struct NativeFilestore {}
129
130 impl VirtualFilestore for NativeFilestore {
131 fn create_file(&self, file_path: &str) -> Result<(), FilestoreError> {
132 if self.exists(file_path)? {
133 return Err(FilestoreError::FileAlreadyExists);
134 }
135 File::create(file_path)?;
136 Ok(())
137 }
138
139 fn remove_file(&self, file_path: &str) -> Result<(), FilestoreError> {
140 if !self.exists(file_path)? {
141 return Err(FilestoreError::FileDoesNotExist);
142 }
143 if !self.is_file(file_path)? {
144 return Err(FilestoreError::IsNotFile);
145 }
146 fs::remove_file(file_path)?;
147 Ok(())
148 }
149
150 fn file_name<'a>(&self, full_path: &'a str) -> Result<Option<&'a str>, FilestoreError> {
151 let path = Path::new(full_path);
152 path.file_name()
153 .map(|s| s.to_str())
154 .ok_or(FilestoreError::Utf8Error)
155 }
156
157 fn truncate_file(&self, file_path: &str) -> Result<(), FilestoreError> {
158 if !self.exists(file_path)? {
159 return Err(FilestoreError::FileDoesNotExist);
160 }
161 if !self.is_file(file_path)? {
162 return Err(FilestoreError::IsNotFile);
163 }
164 OpenOptions::new()
165 .write(true)
166 .truncate(true)
167 .open(file_path)?;
168 Ok(())
169 }
170
171 fn create_dir(&self, dir_path: &str) -> Result<(), FilestoreError> {
172 fs::create_dir(dir_path)?;
173 Ok(())
174 }
175
176 fn remove_dir(&self, dir_path: &str, all: bool) -> Result<(), FilestoreError> {
177 if !self.exists(dir_path)? {
178 return Err(FilestoreError::DirDoesNotExist);
179 }
180 if !self.is_dir(dir_path)? {
181 return Err(FilestoreError::IsNotDirectory);
182 }
183 if !all {
184 fs::remove_dir(dir_path)?;
185 return Ok(());
186 }
187 fs::remove_dir_all(dir_path)?;
188 Ok(())
189 }
190
191 fn read_data(
192 &self,
193 file_name: &str,
194 offset: u64,
195 read_len: u64,
196 buf: &mut [u8],
197 ) -> Result<(), FilestoreError> {
198 if buf.len() < read_len as usize {
199 return Err(ByteConversionError::ToSliceTooSmall {
200 found: buf.len(),
201 expected: read_len as usize,
202 }
203 .into());
204 }
205 if !self.exists(file_name)? {
206 return Err(FilestoreError::FileDoesNotExist);
207 }
208 if !self.is_file(file_name)? {
209 return Err(FilestoreError::IsNotFile);
210 }
211 let mut file = File::open(file_name)?;
212 file.seek(SeekFrom::Start(offset))?;
213 file.read_exact(&mut buf[0..read_len as usize])?;
214 Ok(())
215 }
216
217 fn write_data(&self, file: &str, offset: u64, buf: &[u8]) -> Result<(), FilestoreError> {
218 if !self.exists(file)? {
219 return Err(FilestoreError::FileDoesNotExist);
220 }
221 if !self.is_file(file)? {
222 return Err(FilestoreError::IsNotFile);
223 }
224 let mut file = OpenOptions::new().write(true).open(file)?;
225 file.seek(SeekFrom::Start(offset))?;
226 file.write_all(buf)?;
227 Ok(())
228 }
229
230 fn is_file(&self, str_path: &str) -> Result<bool, FilestoreError> {
231 let path = Path::new(str_path);
232 if !self.exists(str_path)? {
233 return Err(FilestoreError::FileDoesNotExist);
234 }
235 Ok(path.is_file())
236 }
237
238 fn exists(&self, path: &str) -> Result<bool, FilestoreError> {
239 let path = Path::new(path);
240 Ok(self.exists_internal(path))
241 }
242
243 fn file_size(&self, str_path: &str) -> Result<u64, FilestoreError> {
244 let path = Path::new(str_path);
245 if !self.exists_internal(path) {
246 return Err(FilestoreError::FileDoesNotExist);
247 }
248 if !path.is_file() {
249 return Err(FilestoreError::IsNotFile);
250 }
251 Ok(path.metadata()?.len())
252 }
253
254 fn calculate_checksum(
255 &self,
256 file_path: &str,
257 checksum_type: ChecksumType,
258 size_to_verify: u64,
259 verification_buf: &mut [u8],
260 ) -> Result<u32, FilestoreError> {
261 let mut calc_with_crc_lib = |crc: Crc<u32>| -> Result<u32, FilestoreError> {
262 let mut digest = crc.digest();
263 let mut buf_reader = BufReader::new(File::open(file_path)?);
264 let mut remaining_bytes = size_to_verify;
265 while remaining_bytes > 0 {
266 let bytes_to_read = remaining_bytes.min(verification_buf.len() as u64) as usize;
268 let bytes_read = buf_reader.read(&mut verification_buf[0..bytes_to_read])?;
269
270 if bytes_read == 0 {
271 break; }
273 digest.update(&verification_buf[0..bytes_read]);
274 remaining_bytes -= bytes_read as u64;
275 }
276 Ok(digest.finalize())
277 };
278 match checksum_type {
279 ChecksumType::Modular => self.calc_modular_checksum(file_path),
280 ChecksumType::Crc32 => calc_with_crc_lib(CRC_32),
281 ChecksumType::Crc32C => calc_with_crc_lib(CRC_32C),
282 ChecksumType::NullChecksum => Ok(0),
283 _ => Err(FilestoreError::ChecksumTypeNotImplemented(checksum_type)),
284 }
285 }
286
287 fn filename_from_full_path(path: &str) -> Option<&str>
288 where
289 Self: Sized,
290 {
291 let path = Path::new(path);
293
294 path.file_name().and_then(|name| name.to_str())
296 }
297 }
298
299 impl NativeFilestore {
300 pub fn calc_modular_checksum(&self, file_path: &str) -> Result<u32, FilestoreError> {
301 let mut checksum: u32 = 0;
302 let file = File::open(file_path)?;
303 let mut buf_reader = BufReader::new(file);
304 let mut buffer = [0; 4];
305
306 loop {
307 let bytes_read = buf_reader.read(&mut buffer)?;
308 if bytes_read == 0 {
309 break;
310 }
311 (bytes_read..4).for_each(|i| {
313 buffer[i] = 0;
314 });
315
316 checksum = checksum.wrapping_add(u32::from_be_bytes(buffer));
317 }
318 Ok(checksum)
319 }
320
321 fn exists_internal(&self, path: &Path) -> bool {
322 if !path.exists() {
323 return false;
324 }
325 true
326 }
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use std::{fs, path::Path, println, string::ToString};
333
334 use super::*;
335 use alloc::format;
336 use tempfile::tempdir;
337
338 const EXAMPLE_DATA_CFDP: [u8; 15] = [
339 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
340 ];
341
342 const NATIVE_FS: NativeFilestore = NativeFilestore {};
343
344 #[test]
345 fn test_basic_native_filestore_create() {
346 let tmpdir = tempdir().expect("creating tmpdir failed");
347 let file_path = tmpdir.path().join("test.txt");
348 let result =
349 NATIVE_FS.create_file(file_path.to_str().expect("getting str for file failed"));
350 assert!(result.is_ok());
351 let path = Path::new(&file_path);
352 assert!(path.exists());
353 assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
354 assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
355 }
356
357 #[test]
358 fn test_basic_native_fs_file_exists() {
359 let tmpdir = tempdir().expect("creating tmpdir failed");
360 let file_path = tmpdir.path().join("test.txt");
361 assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
362 NATIVE_FS
363 .create_file(file_path.to_str().expect("getting str for file failed"))
364 .unwrap();
365 assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
366 assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
367 }
368
369 #[test]
370 fn test_basic_native_fs_dir_exists() {
371 let tmpdir = tempdir().expect("creating tmpdir failed");
372 let dir_path = tmpdir.path().join("testdir");
373 assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
374 NATIVE_FS
375 .create_dir(dir_path.to_str().expect("getting str for file failed"))
376 .unwrap();
377 assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
378 assert!(
379 NATIVE_FS
380 .is_dir(dir_path.as_path().to_str().unwrap())
381 .unwrap()
382 );
383 }
384
385 #[test]
386 fn test_basic_native_fs_remove_file() {
387 let tmpdir = tempdir().expect("creating tmpdir failed");
388 let file_path = tmpdir.path().join("test.txt");
389 NATIVE_FS
390 .create_file(file_path.to_str().expect("getting str for file failed"))
391 .expect("creating file failed");
392 assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
393 NATIVE_FS
394 .remove_file(file_path.to_str().unwrap())
395 .expect("removing file failed");
396 assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
397 }
398
399 #[test]
400 fn test_basic_native_fs_write() {
401 let tmpdir = tempdir().expect("creating tmpdir failed");
402 let file_path = tmpdir.path().join("test.txt");
403 assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
404 NATIVE_FS
405 .create_file(file_path.to_str().expect("getting str for file failed"))
406 .unwrap();
407 assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
408 assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
409 println!("{}", file_path.to_str().unwrap());
410 let write_data = "hello world\n";
411 NATIVE_FS
412 .write_data(file_path.to_str().unwrap(), 0, write_data.as_bytes())
413 .expect("writing to file failed");
414 let read_back = fs::read_to_string(file_path).expect("reading back data failed");
415 assert_eq!(read_back, write_data);
416 }
417
418 #[test]
419 fn test_basic_native_fs_read() {
420 let tmpdir = tempdir().expect("creating tmpdir failed");
421 let file_path = tmpdir.path().join("test.txt");
422 assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
423 NATIVE_FS
424 .create_file(file_path.to_str().expect("getting str for file failed"))
425 .unwrap();
426 assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
427 assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
428 println!("{}", file_path.to_str().unwrap());
429 let write_data = "hello world\n";
430 NATIVE_FS
431 .write_data(file_path.to_str().unwrap(), 0, write_data.as_bytes())
432 .expect("writing to file failed");
433 let read_back = fs::read_to_string(file_path).expect("reading back data failed");
434 assert_eq!(read_back, write_data);
435 }
436
437 #[test]
438 fn test_truncate_file() {
439 let tmpdir = tempdir().expect("creating tmpdir failed");
440 let file_path = tmpdir.path().join("test.txt");
441 NATIVE_FS
442 .create_file(file_path.to_str().expect("getting str for file failed"))
443 .expect("creating file failed");
444 fs::write(file_path.clone(), [1, 2, 3, 4]).unwrap();
445 assert_eq!(fs::read(file_path.clone()).unwrap(), [1, 2, 3, 4]);
446 NATIVE_FS
447 .truncate_file(file_path.to_str().unwrap())
448 .unwrap();
449 assert_eq!(fs::read(file_path.clone()).unwrap(), []);
450 }
451
452 #[test]
453 fn test_remove_dir() {
454 let tmpdir = tempdir().expect("creating tmpdir failed");
455 let dir_path = tmpdir.path().join("testdir");
456 assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
457 NATIVE_FS
458 .create_dir(dir_path.to_str().expect("getting str for file failed"))
459 .unwrap();
460 assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
461 NATIVE_FS
462 .remove_dir(dir_path.to_str().unwrap(), false)
463 .unwrap();
464 assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
465 }
466
467 #[test]
468 fn test_read_file() {
469 let tmpdir = tempdir().expect("creating tmpdir failed");
470 let file_path = tmpdir.path().join("test.txt");
471 NATIVE_FS
472 .create_file(file_path.to_str().expect("getting str for file failed"))
473 .expect("creating file failed");
474 fs::write(file_path.clone(), [1, 2, 3, 4]).unwrap();
475 let read_buf: &mut [u8] = &mut [0; 4];
476 NATIVE_FS
477 .read_data(file_path.to_str().unwrap(), 0, 4, read_buf)
478 .unwrap();
479 assert_eq!([1, 2, 3, 4], read_buf);
480 NATIVE_FS
481 .write_data(file_path.to_str().unwrap(), 4, &[5, 6, 7, 8])
482 .expect("writing to file failed");
483 NATIVE_FS
484 .read_data(file_path.to_str().unwrap(), 2, 4, read_buf)
485 .unwrap();
486 assert_eq!([3, 4, 5, 6], read_buf);
487 }
488
489 #[test]
490 fn test_remove_which_does_not_exist() {
491 let tmpdir = tempdir().expect("creating tmpdir failed");
492 let file_path = tmpdir.path().join("test.txt");
493 let result = NATIVE_FS.read_data(file_path.to_str().unwrap(), 0, 4, &mut [0; 4]);
494 assert!(result.is_err());
495 let error = result.unwrap_err();
496 if let FilestoreError::FileDoesNotExist = error {
497 assert_eq!(error.to_string(), "file does not exist");
498 } else {
499 panic!("unexpected error");
500 }
501 }
502
503 #[test]
504 fn test_file_already_exists() {
505 let tmpdir = tempdir().expect("creating tmpdir failed");
506 let file_path = tmpdir.path().join("test.txt");
507 let result =
508 NATIVE_FS.create_file(file_path.to_str().expect("getting str for file failed"));
509 assert!(result.is_ok());
510 let result =
511 NATIVE_FS.create_file(file_path.to_str().expect("getting str for file failed"));
512 assert!(result.is_err());
513 let error = result.unwrap_err();
514 if let FilestoreError::FileAlreadyExists = error {
515 assert_eq!(error.to_string(), "file already exists");
516 } else {
517 panic!("unexpected error");
518 }
519 }
520
521 #[test]
522 fn test_remove_file_with_dir_api() {
523 let tmpdir = tempdir().expect("creating tmpdir failed");
524 let file_path = tmpdir.path().join("test.txt");
525 NATIVE_FS
526 .create_file(file_path.to_str().expect("getting str for file failed"))
527 .unwrap();
528 let result = NATIVE_FS.remove_dir(file_path.to_str().unwrap(), true);
529 assert!(result.is_err());
530 let error = result.unwrap_err();
531 if let FilestoreError::IsNotDirectory = error {
532 assert_eq!(error.to_string(), "is not a directory");
533 } else {
534 panic!("unexpected error");
535 }
536 }
537
538 #[test]
539 fn test_remove_dir_remove_all() {
540 let tmpdir = tempdir().expect("creating tmpdir failed");
541 let dir_path = tmpdir.path().join("test");
542 NATIVE_FS
543 .create_dir(dir_path.to_str().expect("getting str for file failed"))
544 .unwrap();
545 let file_path = dir_path.as_path().join("test.txt");
546 NATIVE_FS
547 .create_file(file_path.to_str().expect("getting str for file failed"))
548 .unwrap();
549 let result = NATIVE_FS.remove_dir(dir_path.to_str().unwrap(), true);
550 assert!(result.is_ok());
551 assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
552 }
553
554 #[test]
555 fn test_remove_dir_with_file_api() {
556 let tmpdir = tempdir().expect("creating tmpdir failed");
557 let file_path = tmpdir.path().join("test");
558 NATIVE_FS
559 .create_dir(file_path.to_str().expect("getting str for file failed"))
560 .unwrap();
561 let result = NATIVE_FS.remove_file(file_path.to_str().unwrap());
562 assert!(result.is_err());
563 let error = result.unwrap_err();
564 if let FilestoreError::IsNotFile = error {
565 assert_eq!(error.to_string(), "is not a file");
566 } else {
567 panic!("unexpected error");
568 }
569 }
570
571 #[test]
572 fn test_remove_dir_which_does_not_exist() {
573 let tmpdir = tempdir().expect("creating tmpdir failed");
574 let file_path = tmpdir.path().join("test");
575 let result = NATIVE_FS.remove_dir(file_path.to_str().unwrap(), true);
576 assert!(result.is_err());
577 let error = result.unwrap_err();
578 if let FilestoreError::DirDoesNotExist = error {
579 assert_eq!(error.to_string(), "directory does not exist");
580 } else {
581 panic!("unexpected error");
582 }
583 }
584
585 #[test]
586 fn test_remove_file_which_does_not_exist() {
587 let tmpdir = tempdir().expect("creating tmpdir failed");
588 let file_path = tmpdir.path().join("test.txt");
589 let result = NATIVE_FS.remove_file(file_path.to_str().unwrap());
590 assert!(result.is_err());
591 let error = result.unwrap_err();
592 if let FilestoreError::FileDoesNotExist = error {
593 assert_eq!(error.to_string(), "file does not exist");
594 } else {
595 panic!("unexpected error");
596 }
597 }
598
599 #[test]
600 fn test_truncate_file_which_does_not_exist() {
601 let tmpdir = tempdir().expect("creating tmpdir failed");
602 let file_path = tmpdir.path().join("test.txt");
603 let result = NATIVE_FS.truncate_file(file_path.to_str().unwrap());
604 assert!(result.is_err());
605 let error = result.unwrap_err();
606 if let FilestoreError::FileDoesNotExist = error {
607 assert_eq!(error.to_string(), "file does not exist");
608 } else {
609 panic!("unexpected error");
610 }
611 }
612
613 #[test]
614 fn test_truncate_file_on_directory() {
615 let tmpdir = tempdir().expect("creating tmpdir failed");
616 let file_path = tmpdir.path().join("test");
617 NATIVE_FS.create_dir(file_path.to_str().unwrap()).unwrap();
618 let result = NATIVE_FS.truncate_file(file_path.to_str().unwrap());
619 assert!(result.is_err());
620 let error = result.unwrap_err();
621 if let FilestoreError::IsNotFile = error {
622 assert_eq!(error.to_string(), "is not a file");
623 } else {
624 panic!("unexpected error");
625 }
626 }
627
628 #[test]
629 fn test_byte_conversion_error_when_reading() {
630 let tmpdir = tempdir().expect("creating tmpdir failed");
631 let file_path = tmpdir.path().join("test.txt");
632 NATIVE_FS
633 .create_file(file_path.to_str().expect("getting str for file failed"))
634 .unwrap();
635 let result = NATIVE_FS.read_data(file_path.to_str().unwrap(), 0, 2, &mut []);
636 assert!(result.is_err());
637 let error = result.unwrap_err();
638 if let FilestoreError::ByteConversion(byte_conv_error) = error {
639 if let ByteConversionError::ToSliceTooSmall { found, expected } = byte_conv_error {
640 assert_eq!(found, 0);
641 assert_eq!(expected, 2);
642 } else {
643 panic!("unexpected error");
644 }
645 assert_eq!(
646 error.to_string(),
647 format!("byte conversion: {}", byte_conv_error)
648 );
649 } else {
650 panic!("unexpected error");
651 }
652 }
653
654 #[test]
655 fn test_read_file_on_dir() {
656 let tmpdir = tempdir().expect("creating tmpdir failed");
657 let dir_path = tmpdir.path().join("test");
658 NATIVE_FS
659 .create_dir(dir_path.to_str().expect("getting str for file failed"))
660 .unwrap();
661 let result = NATIVE_FS.read_data(dir_path.to_str().unwrap(), 0, 4, &mut [0; 4]);
662 assert!(result.is_err());
663 let error = result.unwrap_err();
664 if let FilestoreError::IsNotFile = error {
665 assert_eq!(error.to_string(), "is not a file");
666 } else {
667 panic!("unexpected error");
668 }
669 }
670
671 #[test]
672 fn test_write_file_non_existing() {
673 let tmpdir = tempdir().expect("creating tmpdir failed");
674 let file_path = tmpdir.path().join("test.txt");
675 let result = NATIVE_FS.write_data(file_path.to_str().unwrap(), 0, &[]);
676 assert!(result.is_err());
677 let error = result.unwrap_err();
678 if let FilestoreError::FileDoesNotExist = error {
679 } else {
680 panic!("unexpected error");
681 }
682 }
683
684 #[test]
685 fn test_write_file_on_dir() {
686 let tmpdir = tempdir().expect("creating tmpdir failed");
687 let file_path = tmpdir.path().join("test");
688 NATIVE_FS.create_dir(file_path.to_str().unwrap()).unwrap();
689 let result = NATIVE_FS.write_data(file_path.to_str().unwrap(), 0, &[]);
690 assert!(result.is_err());
691 let error = result.unwrap_err();
692 if let FilestoreError::IsNotFile = error {
693 } else {
694 panic!("unexpected error");
695 }
696 }
697
698 #[test]
699 fn test_filename_extraction() {
700 let tmpdir = tempdir().expect("creating tmpdir failed");
701 let file_path = tmpdir.path().join("test.txt");
702 NATIVE_FS
703 .create_file(file_path.to_str().expect("getting str for file failed"))
704 .unwrap();
705 NativeFilestore::filename_from_full_path(file_path.to_str().unwrap());
706 }
707
708 #[test]
709 fn test_modular_checksum() {
710 let tmpdir = tempdir().expect("creating tmpdir failed");
711 let file_path = tmpdir.path().join("mod-crc.bin");
712 fs::write(file_path.as_path(), EXAMPLE_DATA_CFDP).expect("writing test file failed");
713 let mut checksum: u32 = 0;
716 let mut buffer: [u8; 4] = [0; 4];
717 for i in 0..3 {
718 buffer = EXAMPLE_DATA_CFDP[i * 4..(i + 1) * 4].try_into().unwrap();
719 checksum = checksum.wrapping_add(u32::from_be_bytes(buffer));
720 }
721 buffer[0..3].copy_from_slice(&EXAMPLE_DATA_CFDP[12..15]);
722 buffer[3] = 0;
723 checksum = checksum.wrapping_add(u32::from_be_bytes(buffer));
724 let mut verif_buf: [u8; 32] = [0; 32];
725 let result = NATIVE_FS.checksum_verify(
726 checksum,
727 file_path.to_str().unwrap(),
728 ChecksumType::Modular,
729 EXAMPLE_DATA_CFDP.len() as u64,
730 &mut verif_buf,
731 );
732 assert!(result.is_ok());
733 }
734
735 #[test]
736 fn test_null_checksum_impl() {
737 let tmpdir = tempdir().expect("creating tmpdir failed");
738 let file_path = tmpdir.path().join("mod-crc.bin");
739 let result = NATIVE_FS.checksum_verify(
742 0,
743 file_path.to_str().unwrap(),
744 ChecksumType::NullChecksum,
745 0,
746 &mut [],
747 );
748 assert!(result.is_ok());
749 assert!(result.unwrap());
750 }
751
752 #[test]
753 fn test_checksum_not_implemented() {
754 let tmpdir = tempdir().expect("creating tmpdir failed");
755 let file_path = tmpdir.path().join("mod-crc.bin");
756 let result = NATIVE_FS.checksum_verify(
759 0,
760 file_path.to_str().unwrap(),
761 ChecksumType::Crc32Proximity1,
762 0,
763 &mut [],
764 );
765 assert!(result.is_err());
766 let error = result.unwrap_err();
767 if let FilestoreError::ChecksumTypeNotImplemented(cksum_type) = error {
768 assert_eq!(
769 error.to_string(),
770 format!("checksum type not implemented: {:?}", cksum_type)
771 );
772 } else {
773 panic!("unexpected error");
774 }
775 }
776}