1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
pub mod error; pub mod trait_; use crate::thread_safe_cache::{ThreadSafeCacheImpl, ThreadSafeCacheTrait}; use reqwest::blocking::Client; use trait_::{GetCache, GetClient}; use url::Url; lazy_static::lazy_static! { pub(in crate) static ref DEFAULT_CLIENT: Client = Client::new(); } #[derive(Debug)] pub struct Loader<T> { cache: ThreadSafeCacheImpl<Url, T>, } impl<T> Default for Loader<T> { fn default() -> Self { Self { cache: ThreadSafeCacheImpl::default(), } } } impl<T> GetCache<T> for Loader<T> { fn get_cache(&self) -> &dyn ThreadSafeCacheTrait<Url, T> { &self.cache } } impl<T> GetClient<T> for Loader<T> { fn get_client(&self) -> &Client { &*DEFAULT_CLIENT } } #[cfg(test)] pub(in crate) mod testing { use super::{ error::LoaderError, trait_::{GetCache, GetClient, LoaderTrait}, Loader, }; use crate::thread_safe_cache::ThreadSafeCacheTrait; use reqwest::blocking::Client; use url::Url; #[derive(Debug, Default)] pub(in crate) struct TestStringLoader(Loader<String>); impl GetClient<String> for TestStringLoader { fn get_client(&self) -> &Client { self.0.get_client() } } impl GetCache<String> for TestStringLoader { fn get_cache(&self) -> &dyn ThreadSafeCacheTrait<Url, String> { self.0.get_cache() } } impl LoaderTrait<String> for TestStringLoader { fn load_from_bytes(&self, content: &[u8]) -> Result<String, LoaderError> { match std::str::from_utf8(content) { Ok(str_ref) => Ok(str_ref.to_string()), Err(utf8_error) => Err(LoaderError::FormatError(utf8_error.to_string())), } } } } #[cfg(test)] mod tests { use super::{error::LoaderError, testing::TestStringLoader, trait_::LoaderTrait}; use crate::{ testing_helpers::{test_data_file_path, MockLoaderRequestBuilder}, url_helpers::UrlError, }; use std::sync::Arc; use url::Url; #[test] fn test_load_wrong_url_parse_error() { match TestStringLoader::default().load("this-is-a-wrong-url").unwrap_err() { LoaderError::InvalidURL(UrlError::ParseError(url::ParseError::RelativeUrlWithoutBase)) => (), loader_error => panic!( "Expected LoaderError::InvalidURL(UrlError::ParseError(url::ParseError::RelativeUrlWithoutBase)), received {:?}", loader_error, ), } } #[test] fn test_load_wrong_url_syntax_error() { match TestStringLoader::default().load("http:/this-is-syntactically-invalid-url").unwrap_err() { LoaderError::InvalidURL(UrlError::SyntaxViolation(url::SyntaxViolation::ExpectedDoubleSlash)) => (), loader_error => panic!( "Expected LoaderError::InvalidURL(UrlError::ParseError(url::ParseError::RelativeUrlWithoutBase)), received {:?}", loader_error, ), } } #[test] fn test_load_from_not_existing_file() { let mut non_exiting_file_url = Url::from_file_path(test_data_file_path(&["empty"]).unwrap().as_path()).unwrap().to_string(); non_exiting_file_url.push_str("_not_existing"); assert!(matches!( TestStringLoader::default().load(&non_exiting_file_url).unwrap_err(), LoaderError::IOError(value) if value.kind() == std::io::ErrorKind::NotFound )); } #[test] fn test_load_from_not_existing_url() { assert!(matches!( MockLoaderRequestBuilder::default() .resp_status_code(404) .build() .unwrap() .send_request(&TestStringLoader::default()) .unwrap_err(), LoaderError::FetchURLFailed(value) if value.status().map(|value| value.as_u16()) == Some(404) )); } #[test] fn test_load_valid_url() { assert_eq!( MockLoaderRequestBuilder::default() .resp_body("") .build() .unwrap() .send_request(&TestStringLoader::default()) .unwrap(), Arc::new("".to_string()) ); } #[test] fn test_load_valid_url_on_different_fragments() { assert_eq!( MockLoaderRequestBuilder::default().resp_body("").build().unwrap().run_in_mock_context(&|url| { let loader = TestStringLoader::default(); let resp = loader.get_or_fetch_with_result(url).unwrap(); assert_eq!(resp, loader.get_or_fetch_with_result(&url.join("#/a_fragment").unwrap()).unwrap()); resp }), Arc::new("".to_string()) ); } }