Compare commits

..

3 commits

Author SHA1 Message Date
a5ecf19f70 [wip] unit tests for file module
- testing for `Uploading`
2025-07-15 15:00:11 +00:00
aa76c7efda clippy fix 2025-07-15 14:55:29 +00:00
147c78377a better error assertions 2025-07-15 14:54:27 +00:00
5 changed files with 132 additions and 45 deletions

View file

@ -40,7 +40,27 @@ impl_param_from! {
impl Parameter { impl Parameter {
fn is_fatal(&self) -> bool { fn is_fatal(&self) -> bool {
matches!(self, Self::Uri(_) | Self::AliasID(_)) self.is_uri() || self.is_alias_id()
}
#[must_use]
pub fn is_uri(&self) -> bool {
matches!(self, Self::Uri(_))
}
#[must_use]
pub fn is_alias_id(&self) -> bool {
matches!(self, Self::AliasID(_))
}
#[must_use]
pub fn is_share_id(&self) -> bool {
matches!(self, Self::ShareID(_))
}
#[must_use]
pub fn is_file_id(&self) -> bool {
matches!(self, Self::FileID(_))
} }
} }
@ -123,17 +143,34 @@ impl Error {
}) })
} }
#[must_use]
pub fn is_stdio_kind(&self, kind: std::io::ErrorKind) -> bool {
if let Self::StdIo(e) = self {
e.kind() == kind
} else {
false
}
}
pub fn is_mismatch<E, A>(&self, want_expected: E, want_actual: A) -> bool pub fn is_mismatch<E, A>(&self, want_expected: E, want_actual: A) -> bool
where where
E: AsRef<str>, E: AsRef<str>,
A: AsRef<str>, A: AsRef<str>,
{ {
matches!( if let Self::Mismatch { expected, actual } = self {
self, expected == want_expected.as_ref() && actual == want_actual.as_ref()
Self::Mismatch { expected, actual } } else {
if expected == want_expected.as_ref() false
&& actual == want_actual.as_ref() }
) }
#[must_use]
pub fn response_contains(&self, pat: &str) -> bool {
if let Self::Response(r) = self {
r.contains(pat)
} else {
false
}
} }
#[must_use] #[must_use]

View file

@ -158,7 +158,7 @@ mod tests {
}; };
let err = compute_hash(&nex_path, 0, drop).unwrap_err(); let err = compute_hash(&nex_path, 0, drop).unwrap_err();
assert!(matches!(err, crate::Error::StdIo(e) if e.kind() == std::io::ErrorKind::NotFound)); assert!(err.is_stdio_kind(std::io::ErrorKind::NotFound));
} }
#[test] #[test]
@ -166,9 +166,7 @@ mod tests {
let dir = TempDir::new().unwrap(); let dir = TempDir::new().unwrap();
let err = compute_hash(dir.path(), 0, drop).unwrap_err(); let err = compute_hash(dir.path(), 0, drop).unwrap_err();
assert!( assert!(err.is_stdio_kind(std::io::ErrorKind::IsADirectory));
matches!(err, crate::Error::StdIo(e) if e.kind() == std::io::ErrorKind::IsADirectory)
);
} }
#[test] #[test]

View file

@ -145,7 +145,7 @@ mod tests {
sharry::{Client, json::NewShareRequest}, sharry::{Client, json::NewShareRequest},
test_util::{ test_util::{
MockClient, create_file, MockClient, create_file,
data::{DATA_LENGTHS_BAD, cases, cases_with}, data::{DATA_LENGTHS_BAD, cases, cases_with, data},
}, },
}; };
@ -248,13 +248,13 @@ mod tests {
#[test] #[test]
fn check_rewind_works() { fn check_rewind_works() {
let cases = cases() let data = cases()
// ignore "empty" testcase // ignore "empty" testcase
.filter(|&(_, size)| size > 0) .filter(|&(_, size)| size > 0)
// remove "size" // remove "size"
.map(|(content, _)| content); .map(|(content, _)| content);
for content in cases { for content in data {
let (mut upl, _share_id, _file) = create_uploading(content); let (mut upl, _share_id, _file) = create_uploading(content);
// read 1 byte and rewind // read 1 byte and rewind
@ -269,4 +269,72 @@ mod tests {
assert!(upl.rewind().is_none()); assert!(upl.rewind().is_none());
} }
} }
#[test]
fn upload_works() {
let client = MockClient::default();
let uri = sharry::Uri::from(true);
let alias_id = sharry::AliasID::from(true);
let share_id = client
.share_create(&uri, &alias_id, NewShareRequest::new("share", 0))
.unwrap();
let mut buf = vec![0; 1024 * 1024];
for content in data() {
let file = create_file(content);
let mut upl = Checked::new(file.path())
.unwrap()
.start_upload(&client, &uri, &alias_id, &share_id)
.unwrap();
while let Ok(chunk) = upl.read(&mut buf) {
assert!(
client
.file_patch(&uri, &alias_id, &share_id, &chunk)
.is_ok()
);
}
assert_eq!(upl.offset, upl.size);
}
}
#[test]
fn check_upload_bad_align() {
let data = cases()
// ignore "empty" testcase
.filter(|&(_, size)| size >= 2)
// remove "size"
.map(|(content, _)| content);
let client = MockClient::default();
let uri = sharry::Uri::from(true);
let alias_id = sharry::AliasID::from(true);
let share_id = client
.share_create(&uri, &alias_id, NewShareRequest::new("share", 0))
.unwrap();
// single-byte buffer to force bad chunk alignment
let mut buf = [0];
for content in data {
let file = create_file(content);
let mut upl = Checked::new(file.path())
.unwrap()
.start_upload(&client, &uri, &alias_id, &share_id)
.unwrap();
// first chunk works
client
.file_patch(&uri, &alias_id, &share_id, &upl.read(&mut buf).unwrap())
.unwrap();
// second chunk misaligned
let res = client.file_patch(&uri, &alias_id, &share_id, &upl.read(&mut buf).unwrap());
assert!(res.is_err());
assert!(res.unwrap_err().response_contains("not aligned to a MiB"));
}
}
} }

View file

@ -222,11 +222,9 @@ mod tests {
let share_ids: [_; 10] = std::array::from_fn(|_| add_share(&client)); let share_ids: [_; 10] = std::array::from_fn(|_| add_share(&client));
for share_id in share_ids.as_ref() { for share_id in share_ids.as_ref() {
let res = client.insert_share(&share_id, MockShare::default()); let res = client.insert_share(share_id, MockShare::default());
assert!(res.is_err()); assert!(res.is_err());
assert!( assert!(res.unwrap_err().response_contains("can't insert share"));
matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't insert share"))
);
} }
} }
@ -250,9 +248,7 @@ mod tests {
let res = client.get_share(share_id_nex); let res = client.get_share(share_id_nex);
assert!(res.is_err()); assert!(res.is_err());
assert!( assert!(res.unwrap_err().response_contains("can't find share"));
matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't find share"))
);
} }
} }
@ -284,7 +280,7 @@ mod tests {
let share_id_nex = ShareID::default(); let share_id_nex = ShareID::default();
let res = client.insert_file(&share_id_nex, &FileID::from(true), MockFile::default()); let res = client.insert_file(&share_id_nex, &FileID::from(true), MockFile::default());
assert!(res.is_err()); assert!(res.is_err());
assert!(matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't find share"))); assert!(res.unwrap_err().response_contains("can't find share"));
} }
#[test] #[test]
@ -294,11 +290,9 @@ mod tests {
let file_ids: [_; 10] = std::array::from_fn(|_| add_file(&client, &share_id)); let file_ids: [_; 10] = std::array::from_fn(|_| add_file(&client, &share_id));
for file_id in file_ids.as_ref() { for file_id in file_ids.as_ref() {
let res = client.insert_file(&share_id, &file_id, MockFile::default()); let res = client.insert_file(&share_id, file_id, MockFile::default());
assert!(res.is_err()); assert!(res.is_err());
assert!( assert!(res.unwrap_err().response_contains("can't insert file"));
matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't insert file"))
);
} }
} }
@ -325,16 +319,12 @@ mod tests {
let res = client.get_file(&share_id_nex, file_id_nex); let res = client.get_file(&share_id_nex, file_id_nex);
assert!(res.is_err()); assert!(res.is_err());
assert!( assert!(res.unwrap_err().response_contains("can't find share"));
matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't find share"))
);
let res = client.get_file(&share_id, file_id_nex); let res = client.get_file(&share_id, file_id_nex);
assert!(res.is_err()); assert!(res.is_err());
assert!( assert!(res.unwrap_err().response_contains("can't find file"));
matches!(res.unwrap_err(), Error::Response(s) if s.contains("can't find file"))
);
} }
} }
} }

View file

@ -160,23 +160,17 @@ mod tests {
let share_id_i = ShareID::from(false); let share_id_i = ShareID::from(false);
let file_id_i = FileID::from(false); let file_id_i = FileID::from(false);
// param checks
let is_uri_i = |p: &Parameter| matches!(p, Parameter::Uri(_));
let is_alias_id_i = |p: &Parameter| matches!(p, Parameter::AliasID(_));
let is_share_id_i = |p: &Parameter| matches!(p, Parameter::ShareID(_));
let is_file_id_i = |p: &Parameter| matches!(p, Parameter::FileID(_));
// uri + alias // uri + alias
test_check((&uri_i, &alias_id_i), is_uri_i); test_check((&uri_i, &alias_id_i), Parameter::is_uri);
test_check((&uri_i, &alias_id), is_uri_i); test_check((&uri_i, &alias_id), Parameter::is_uri);
test_check((&uri, &alias_id_i), is_alias_id_i); test_check((&uri, &alias_id_i), Parameter::is_alias_id);
// share // share
test_check(&share_id_i, is_share_id_i); test_check(&share_id_i, Parameter::is_share_id);
// share + file // share + file
test_check((&share_id_i, &file_id_i), is_share_id_i); test_check((&share_id_i, &file_id_i), Parameter::is_share_id);
test_check((&share_id_i, &file_id), is_share_id_i); test_check((&share_id_i, &file_id), Parameter::is_share_id);
test_check((&share_id, &file_id_i), is_file_id_i); test_check((&share_id, &file_id_i), Parameter::is_file_id);
} }
} }