diff --git a/src/test_util/mock_client.rs b/src/test_util/mock_client.rs index 4cbefc0..626833f 100644 --- a/src/test_util/mock_client.rs +++ b/src/test_util/mock_client.rs @@ -1,11 +1,105 @@ +use std::{ + cell::{RefCell, RefMut}, + collections::{HashMap, hash_map::Entry}, +}; + use crate::{ - Result, file, + Error, Result, + file::{self, FileTrait}, sharry::{AliasID, Client, FileID, ShareID, Uri, json}, }; use super::mock_ids::CheckID; -pub struct MockClient; +#[derive(Debug)] +pub struct MockClient { + shares: RefCell>, +} + +#[derive(Debug, Default)] +struct MockShare { + files: HashMap, +} + +#[derive(Debug)] +struct MockFile { + name: String, + size: u64, + offset: u64, +} + +impl MockClient { + fn insert_share(&self, share_id: &ShareID) -> Result<()> { + let mut shares = self.shares.borrow_mut(); + + let Entry::Vacant(entry) = shares.entry(share_id.to_string()) else { + return Err(Error::response(format_args!( + "Can't create share {share_id:?}!" + ))); + }; + + entry.insert(MockShare::default()); + + Ok(()) + } + + fn insert_file( + &self, + share_id: &ShareID, + file_id: &FileID, + name: String, + size: u64, + ) -> Result<()> { + let mut share = self.get_share_mut(share_id)?; + + let Entry::Vacant(entry) = share.files.entry(file_id.to_string()) else { + return Err(Error::response(format_args!( + "Can't create file {file_id:?}!" + ))); + }; + + entry.insert(MockFile { + name, + size, + offset: 0, + }); + + Ok(()) + } + + fn get_share_mut<'t>(&'t self, share_id: &ShareID) -> Result> { + let share_id = &share_id.to_string(); + let shares = self.shares.borrow_mut(); + + shares + .get(share_id) + .ok_or_else(|| Error::response(format_args!("Can't find share {share_id:?}!")))?; + + // share exists + Ok(RefMut::map(shares, |shares| { + shares.get_mut(share_id).expect("checked but None!") + })) + } + + fn get_file_mut<'t>( + &'t self, + share_id: &ShareID, + file_id: &FileID, + ) -> Result> { + let file_id = &file_id.to_string(); + let share = self.get_share_mut(share_id)?; + + share + .files + .get(file_id) + .ok_or_else(|| Error::response(format_args!("Can't find file {file_id:?}!")))?; + + // file exists + Ok(RefMut::map(share, move |share| { + share.files.get_mut(file_id).expect("checked but None!") + })) + } +} impl Client for MockClient { fn share_create( @@ -16,7 +110,10 @@ impl Client for MockClient { ) -> Result { (uri, alias_id).check()?; - Ok(true.into()) + let share_id = true.into(); + self.insert_share(&share_id)?; + + Ok(share_id) } fn share_notify(&self, uri: &Uri, alias_id: &AliasID, share_id: &ShareID) -> crate::Result<()> { @@ -31,12 +128,20 @@ impl Client for MockClient { uri: &Uri, alias_id: &AliasID, share_id: &ShareID, - _: &file::Checked, + file: &file::Checked, ) -> Result { (uri, alias_id).check()?; share_id.check()?; - Ok(true.into()) + let file_id = true.into(); + self.insert_file( + share_id, + &file_id, + file.get_name().to_string(), + file.get_size(), + )?; + + Ok(file_id) } fn file_patch( @@ -50,9 +155,10 @@ impl Client for MockClient { (share_id, chunk.get_file_id()).check()?; // TODO: `chunk` must align to a full MiB - - // Ok(()) + let file = self.get_file_mut(share_id, chunk.get_file_id())?; todo!() + + // Ok(()) } } diff --git a/src/test_util/mock_ids.rs b/src/test_util/mock_ids.rs index 9660c4e..5618fdd 100644 --- a/src/test_util/mock_ids.rs +++ b/src/test_util/mock_ids.rs @@ -8,15 +8,22 @@ const VALID_ALIAS: &str = "valid-alias"; const VALID_SHARE: &str = "valid-share"; const VALID_FILE: &str = "valid-file"; +fn make_invalid(valid: &str) -> String { + let invalid = valid.replace("valid", "invalid"); + assert_ne!(valid, invalid); + + invalid +} + pub trait CheckID { fn check(self) -> Result<()>; } impl CheckID for (&Uri, &AliasID) { fn check(self) -> Result<()> { - if self.0.to_string() != VALID_URI { + if self.0.to_string() == make_invalid(VALID_URI) { Err(self.0.into()) - } else if self.1.as_ref() != VALID_ALIAS { + } else if self.1.as_ref() == make_invalid(VALID_ALIAS) { Err(self.1.into()) } else { Ok(()) @@ -26,10 +33,10 @@ impl CheckID for (&Uri, &AliasID) { impl CheckID for &ShareID { fn check(self) -> Result<()> { - if self.to_string() == VALID_SHARE { - Ok(()) - } else { + if self.to_string() == make_invalid(VALID_SHARE) { Err(self.into()) + } else { + Ok(()) } } } @@ -38,21 +45,14 @@ impl CheckID for (&ShareID, &FileID) { fn check(self) -> Result<()> { self.0.check()?; - if self.1.to_string() == VALID_FILE { - Ok(()) - } else { + if self.1.to_string() == make_invalid(VALID_FILE) { Err(self.1.into()) + } else { + Ok(()) } } } -fn make_invalid(valid: &str) -> String { - let invalid = valid.replace("valid", "invalid"); - assert_ne!(valid, invalid); - - invalid -} - impl From for Uri { fn from(value: bool) -> Self { if value { @@ -111,6 +111,17 @@ mod tests { assert!(matches!((&share_id, &file_id).check(), Ok(()))); } + #[test] + fn default_is_valid() { + let uri = Uri::default(); + let share_id = ShareID::default(); + let file_id = FileID::default(); + + assert!(matches!((&uri, &AliasID::from(true)).check(), Ok(()))); + assert!(matches!(share_id.check(), Ok(()))); + assert!(matches!((&share_id, &file_id).check(), Ok(()))); + } + #[test] fn false_makes_invalids() { let uri = Uri::from(true);