From f4e0bc5be4e0a8017cc1785bb8f8c9e8784e06e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Thu, 3 Jul 2025 11:07:22 +0000 Subject: [PATCH] [wip] unit tests for `sharry` module - doc + testing for `uri` module --- src/sharry/ids.rs | 6 +-- src/sharry/uri.rs | 99 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/sharry/ids.rs b/src/sharry/ids.rs index 8f2324c..b95ef20 100644 --- a/src/sharry/ids.rs +++ b/src/sharry/ids.rs @@ -30,7 +30,7 @@ impl From for AliasID { /// - impl `serde` for cachefile handling /// - impl `Display` for formatting compatibility #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ShareID(String); +pub struct ShareID(pub(super) String); impl fmt::Display for ShareID { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -51,7 +51,7 @@ impl From for ShareID { /// - impl `Display` for formatting compatibility /// - impl `TryFrom` for extracting from matching a "PATCH" uri #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FileID(String); +pub struct FileID(pub(super) String); impl fmt::Display for FileID { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -102,7 +102,7 @@ impl TryFrom for FileID { #[cfg(test)] mod tests { use super::*; -use crate::check_trait; + use crate::check_trait; #[test] fn basic_traits_working() { diff --git a/src/sharry/uri.rs b/src/sharry/uri.rs index bda02d9..65ba6b0 100644 --- a/src/sharry/uri.rs +++ b/src/sharry/uri.rs @@ -25,28 +25,34 @@ impl AsRef<[u8]> for Uri { } impl Uri { - pub fn new(protocol: impl fmt::Display, base_url: impl fmt::Display) -> Self { - Self(format!("{protocol}://{base_url}")) +/// create a new Sharry URI + pub fn new(scheme: impl fmt::Display, host: impl fmt::Display) -> Self { + Self(format!("{scheme}://{host}")) } +/// arbitrary endpoint in the Sharry API v2 fn endpoint(&self, path: fmt::Arguments) -> String { let uri = format!("{}/api/v2/{path}", self.0); trace!("endpoint: {uri:?}"); uri } +/// Sharry API endpoint to create a new share pub fn share_create(&self) -> String { self.endpoint(format_args!("alias/upload/new")) } +/// Sharry API endpoint to ping a share's notification hook pub fn share_notify(&self, share_id: &super::ShareID) -> String { self.endpoint(format_args!("alias/mail/notify/{share_id}")) } +/// Sharry API endpoint to create a new file inside a share pub fn file_create(&self, share_id: &super::ShareID) -> String { self.endpoint(format_args!("alias/upload/{share_id}/files/tus")) } +/// Sharry API endpoint to push data into a file inside a share pub fn file_patch(&self, share_id: &super::ShareID, file_id: &super::FileID) -> String { self.endpoint(format_args!("alias/upload/{share_id}/files/tus/{file_id}")) } @@ -55,31 +61,86 @@ impl Uri { #[cfg(test)] mod tests { use super::*; + use crate::{ + check_trait, + sharry::{FileID, ShareID}, + }; #[test] - fn basic_tests() { + fn basic_traits_working() { let cases = vec![ +// simple http host + "http://example.com", +// https host with port + "https://my-host:8080", +// custom scheme + "custom+scheme://host", + ]; + + for uri_data in cases { + let uri = Uri(uri_data.to_owned()); + check_trait(&uri_data, &uri.to_string(), "Display", "Uri"); + check_trait(&uri_data.as_bytes(), &uri.as_ref(), "AsRef<[u8]>", "Uri"); + } + } + + #[test] + fn test_new() { + let cases = vec![ + // simple http host ("http", "example.com", "http://example.com"), + // https host with port ("https", "my-host:8080", "https://my-host:8080"), + // custom scheme ("custom+scheme", "host", "custom+scheme://host"), ]; - for (protocol, base_url, display) in cases { - let uri = Uri::new(protocol, base_url); - assert_eq!( - uri.to_string(), - display, - "`impl Display for Uri` expected: {:?}, got {:?}", - display, - uri.to_string(), - ); - assert_eq!( - uri.as_ref(), - display.as_bytes(), - "`impl AsRef<[u8]> for Uri` expected: {:?}, got {:?}", - display.as_bytes(), - uri.as_ref(), - ); + for (scheme, host, expected) in cases { + let uri = Uri::new(scheme, host); + assert_eq!(&expected, &uri.to_string()); } } + + #[test] + fn test_endpoint() { + let cases = vec![ + // simple path + ("path/to/something", "/api/v2/path/to/something"), + // underscores, hyphens, dots + ("bob_smith-son.eve", "/api/v2/bob_smith-son.eve"), + // unicode + ("漢字ユーザー", "/api/v2/漢字ユーザー"), + // empty path + ("", "/api/v2/"), + // leading/trailing spaces + (" frank ", "/api/v2/ frank "), + // uppercase + ("GUEST", "/api/v2/GUEST"), + // numeric + ("12345", "/api/v2/12345"), + ]; + + let uri = Uri("".to_owned()); + for (path, expected) in cases { + assert_eq!(&expected, &uri.endpoint(format_args!("{path}"))); + } + } + + #[test] + fn test_pub_endpoints() { + let uri = Uri("".to_owned()); + let share_id = ShareID("sid".to_owned()); + let file_id = FileID("fid".to_owned()); + + assert_eq!("/api/v2/alias/upload/new", uri.share_create()); + assert_eq!("/api/v2/alias/mail/notify/sid", uri.share_notify(&share_id)); + assert_eq!( + "/api/v2/alias/upload/sid/files/tus", + uri.file_create(&share_id) + ); + assert_eq!( + "/api/v2/alias/upload/sid/files/tus/fid", + uri.file_patch(&share_id, &file_id) + ); + } }