From 40fc37091e125c1bf71595ae484dff0740f763ed Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 28 Jun 2023 22:38:53 -0700 Subject: [PATCH 01/22] Initial commit (framed up function signature) --- resources/persist/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index e93b44088..9716afd01 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -41,6 +41,10 @@ impl PersistInstance { Ok(serialize_into(&mut writer, &struc).map_err(PersistError::Serialize))? } + pub fn list(&self) -> Result, PersistError> { + todo!() + } + pub fn load(&self, key: &str) -> Result where T: DeserializeOwned, From 5357cb46156a7ed24ad8dd8372f7586731f7b41f Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sun, 2 Jul 2023 13:06:45 -0700 Subject: [PATCH 02/22] improvement: add list feature to shuttle persist --- .../persist/shuttle_persist/test/test.bin | Bin 0 -> 12 bytes resources/persist/src/lib.rs | 33 ++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 resources/persist/shuttle_persist/test/test.bin diff --git a/resources/persist/shuttle_persist/test/test.bin b/resources/persist/shuttle_persist/test/test.bin new file mode 100644 index 0000000000000000000000000000000000000000..33b31dd610b71d307ebf3a72d9839cd850073981 GIT binary patch literal 12 OcmZQ!fPj+J;t~J^l>x;7 literal 0 HcmV?d00001 diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 9716afd01..fb4b942c7 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -41,8 +41,26 @@ impl PersistInstance { Ok(serialize_into(&mut writer, &struc).map_err(PersistError::Serialize))? } - pub fn list(&self) -> Result, PersistError> { - todo!() + // list method returns a vector of strings containing all the keys associated with a PersistInstance + pub fn list(&self) -> Result, String> { + // call the storage folder function, bind it to a variable called folder_to_list + let folder_to_list = self.get_storage_folder(); + + // create an empty, mutable vector to store the list of strings we want to return + let mut list = Vec::new(); + + // iterate over the entries in folder_to_list, convert each entry into a string, and store it in the list vector + for item in folder_to_list.iter() { + let os_string = item.to_os_string(); + let converted_string = match os_string.into_string() { + Ok(converted_string) => converted_string, + Err(_) => "Unable to obtain a path string.".to_string(), + }; + list.push(converted_string); + } + + // return the list of strings + Ok(list) } pub fn load(&self, key: &str) -> Result @@ -115,6 +133,17 @@ mod tests { assert_eq!(result, "test"); } + // new unit test for the list method + #[test] + fn test_list() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test").unwrap(), + }; + + let result = vec!["shuttle_persist", "test"]; + assert_eq!(result, persist.list().unwrap()); + } + #[test] fn test_load_error() { let persist = PersistInstance { From 96f11a63e3f2c2a2f49ed5818162738ad66bd28c Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 3 Jul 2023 11:23:45 -0700 Subject: [PATCH 03/22] Rewrite list, add remove and associated tests --- .../persist/shuttle_persist/test/test.bin | Bin 12 -> 0 bytes resources/persist/src/lib.rs | 57 ++++++++++++------ 2 files changed, 38 insertions(+), 19 deletions(-) delete mode 100644 resources/persist/shuttle_persist/test/test.bin diff --git a/resources/persist/shuttle_persist/test/test.bin b/resources/persist/shuttle_persist/test/test.bin deleted file mode 100644 index 33b31dd610b71d307ebf3a72d9839cd850073981..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 OcmZQ!fPj+J;t~J^l>x;7 diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index fb4b942c7..1d94a1e2a 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -16,6 +16,10 @@ pub enum PersistError { Open(std::io::Error), #[error("failed to create folder: {0}")] CreateFolder(std::io::Error), + #[error("failed to list contents of folder: {0}")] + ListFolder(std::io::Error), + #[error("failed to remove file: {0}")] + RemoveFile(std::io::Error), #[error("failed to serialize data: {0}")] Serialize(BincodeError), #[error("failed to deserialize data: {0}")] @@ -41,28 +45,32 @@ impl PersistInstance { Ok(serialize_into(&mut writer, &struc).map_err(PersistError::Serialize))? } - // list method returns a vector of strings containing all the keys associated with a PersistInstance - pub fn list(&self) -> Result, String> { - // call the storage folder function, bind it to a variable called folder_to_list - let folder_to_list = self.get_storage_folder(); + /// list method returns a vector of strings containing all the keys associated with a PersistInstance + pub fn list(&self) -> Result, PersistError> { + let storage_folder = self.get_storage_folder(); - // create an empty, mutable vector to store the list of strings we want to return let mut list = Vec::new(); - // iterate over the entries in folder_to_list, convert each entry into a string, and store it in the list vector - for item in folder_to_list.iter() { - let os_string = item.to_os_string(); - let converted_string = match os_string.into_string() { - Ok(converted_string) => converted_string, - Err(_) => "Unable to obtain a path string.".to_string(), - }; - list.push(converted_string); + let entries = fs::read_dir(storage_folder).map_err(PersistError::ListFolder)?; + for entry in entries { + let dir = entry.map_err(PersistError::ListFolder)?; + list.push( + dir.path() + .into_os_string() + .into_string() + .unwrap_or_else(|_| "path contains non-UTF-8 characters".to_string()), + ); } - - // return the list of strings Ok(list) } + /// remove method deletes a key from the PersistInstance + pub fn remove(&self, key: &str) -> Result<(), PersistError> { + let file_path = self.get_storage_file(key); + fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; + Ok(()) + } + pub fn load(&self, key: &str) -> Result where T: DeserializeOwned, @@ -133,24 +141,35 @@ mod tests { assert_eq!(result, "test"); } - // new unit test for the list method #[test] fn test_list() { let persist = PersistInstance { service_name: ServiceName::from_str("test").unwrap(), }; - - let result = vec!["shuttle_persist", "test"]; + + let result = vec!["shuttle_persist/test/test.bin"]; assert_eq!(result, persist.list().unwrap()); } + #[test] + fn test_remove() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test").unwrap(), + }; + + persist.save("test", "test").unwrap(); + persist.remove("test").unwrap(); + let result: Vec = Vec::new(); + assert_eq!(result, persist.list().unwrap()); + } + #[test] fn test_load_error() { let persist = PersistInstance { service_name: ServiceName::from_str("test").unwrap(), }; - // unwrapp error + // unwrap error let result = persist.load::("error").unwrap_err(); assert_eq!( result.to_string(), From 9e3eea10db70c9c18d377701d25a89af08f0f3d7 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 3 Jul 2023 11:35:41 -0700 Subject: [PATCH 04/22] Run cargo fmt to fix failing CircleCI persist --- resources/persist/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 1d94a1e2a..3ac154c4e 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -162,7 +162,7 @@ mod tests { let result: Vec = Vec::new(); assert_eq!(result, persist.list().unwrap()); } - + #[test] fn test_load_error() { let persist = PersistInstance { From 9ea36f719ddf94a5184c5250b55715cf2ca9179d Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 3 Jul 2023 14:05:41 -0700 Subject: [PATCH 05/22] Resolve failing unit tests for list and remove --- resources/persist/shuttle_persist/test/test.bin | Bin 0 -> 12 bytes resources/persist/shuttle_persist/test/test1.bin | Bin 0 -> 13 bytes .../persist/shuttle_persist/test1/test1.bin | Bin 0 -> 13 bytes .../shuttle_persist/test_list/test_list.bin | Bin 0 -> 17 bytes resources/persist/src/lib.rs | 15 ++++++++------- 5 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 resources/persist/shuttle_persist/test/test.bin create mode 100644 resources/persist/shuttle_persist/test/test1.bin create mode 100644 resources/persist/shuttle_persist/test1/test1.bin create mode 100644 resources/persist/shuttle_persist/test_list/test_list.bin diff --git a/resources/persist/shuttle_persist/test/test.bin b/resources/persist/shuttle_persist/test/test.bin new file mode 100644 index 0000000000000000000000000000000000000000..33b31dd610b71d307ebf3a72d9839cd850073981 GIT binary patch literal 12 OcmZQ!fPj+J;t~J^l>x;7 literal 0 HcmV?d00001 diff --git a/resources/persist/shuttle_persist/test/test1.bin b/resources/persist/shuttle_persist/test/test1.bin new file mode 100644 index 0000000000000000000000000000000000000000..3809ab55adf98bd14e3b2d82605de3335e2f0466 GIT binary patch literal 13 PcmZQ&fPj+J;u1pu2ABc& literal 0 HcmV?d00001 diff --git a/resources/persist/shuttle_persist/test1/test1.bin b/resources/persist/shuttle_persist/test1/test1.bin new file mode 100644 index 0000000000000000000000000000000000000000..3809ab55adf98bd14e3b2d82605de3335e2f0466 GIT binary patch literal 13 PcmZQ&fPj+J;u1pu2ABc& literal 0 HcmV?d00001 diff --git a/resources/persist/shuttle_persist/test_list/test_list.bin b/resources/persist/shuttle_persist/test_list/test_list.bin new file mode 100644 index 0000000000000000000000000000000000000000..ca518820579fc242ee9b252295c5b05ae0cd9158 GIT binary patch literal 17 Tcmd;NfPj+J;*$8B%;FLN6XOHr literal 0 HcmV?d00001 diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 3ac154c4e..6413a5d2e 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -144,23 +144,24 @@ mod tests { #[test] fn test_list() { let persist = PersistInstance { - service_name: ServiceName::from_str("test").unwrap(), + service_name: ServiceName::from_str("test_list").unwrap(), }; - let result = vec!["shuttle_persist/test/test.bin"]; + persist.save("test_list", "test_list").unwrap(); + + let result = vec!["shuttle_persist/test_list/test_list.bin"]; assert_eq!(result, persist.list().unwrap()); } #[test] fn test_remove() { let persist = PersistInstance { - service_name: ServiceName::from_str("test").unwrap(), + service_name: ServiceName::from_str("test_remove").unwrap(), }; - persist.save("test", "test").unwrap(); - persist.remove("test").unwrap(); - let result: Vec = Vec::new(); - assert_eq!(result, persist.list().unwrap()); + persist.save("test_remove", "test_remove").unwrap(); + persist.remove("test_remove").unwrap(); + assert!(persist.list().unwrap().is_empty()); } #[test] From f866b7332f578459502aa12a32e5b8f113ade642 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 3 Jul 2023 21:07:56 -0700 Subject: [PATCH 06/22] Add clear method & remove by passing indexed item --- resources/persist/src/lib.rs | 40 +++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 6413a5d2e..1ddfb37f6 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -18,6 +18,8 @@ pub enum PersistError { CreateFolder(std::io::Error), #[error("failed to list contents of folder: {0}")] ListFolder(std::io::Error), + #[error("failed to clear the folder: {0}")] + ClearFolder(std::io::Error), #[error("failed to remove file: {0}")] RemoveFile(std::io::Error), #[error("failed to serialize data: {0}")] @@ -64,9 +66,20 @@ impl PersistInstance { Ok(list) } + /// clear method removes the storage folder from the PersistInstance + pub fn clear(&self) -> Result<(), PersistError> { + let folder_path = self.get_storage_folder(); + fs::remove_dir_all(folder_path).map_err(PersistError::ClearFolder)?; + Ok(()) + } + /// remove method deletes a key from the PersistInstance - pub fn remove(&self, key: &str) -> Result<(), PersistError> { - let file_path = self.get_storage_file(key); + pub fn remove(&self, list_item: Vec) -> Result<(), PersistError> { + let mut item_index: usize = 0; + for (index, _items) in list_item.iter().enumerate() { + item_index = index; + } + let file_path = self.get_storage_file(&list_item[item_index]); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; Ok(()) } @@ -149,8 +162,24 @@ mod tests { persist.save("test_list", "test_list").unwrap(); - let result = vec!["shuttle_persist/test_list/test_list.bin"]; - assert_eq!(result, persist.list().unwrap()); + let result = vec!["shuttle_persist/test_list/test_list.bin".to_string()]; + let list_result = persist.list().unwrap(); + assert_eq!(result, list_result); + } + + #[test] + fn test_clear() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test_clear").unwrap(), + }; + + persist.save("test_clear", "test_clear").unwrap(); + persist.clear().unwrap(); + let clear_result = persist.list().unwrap_err(); + assert_eq!( + clear_result.to_string(), + "failed to list contents of folder: No such file or directory (os error 2)" + ); } #[test] @@ -160,7 +189,8 @@ mod tests { }; persist.save("test_remove", "test_remove").unwrap(); - persist.remove("test_remove").unwrap(); + let item_to_remove = vec!["test_remove".to_string()]; + persist.remove(item_to_remove).unwrap(); assert!(persist.list().unwrap().is_empty()); } From ece68b70f6ece3c9b407e8427149e57468ad3880 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 3 Jul 2023 21:27:53 -0700 Subject: [PATCH 07/22] Adjustment to list_item parameter in remove method --- resources/persist/src/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 1ddfb37f6..7b4885b9e 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -74,12 +74,8 @@ impl PersistInstance { } /// remove method deletes a key from the PersistInstance - pub fn remove(&self, list_item: Vec) -> Result<(), PersistError> { - let mut item_index: usize = 0; - for (index, _items) in list_item.iter().enumerate() { - item_index = index; - } - let file_path = self.get_storage_file(&list_item[item_index]); + pub fn remove(&self, list_item: String) -> Result<(), PersistError> { + let file_path = self.get_storage_file(&list_item); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; Ok(()) } @@ -189,7 +185,7 @@ mod tests { }; persist.save("test_remove", "test_remove").unwrap(); - let item_to_remove = vec!["test_remove".to_string()]; + let item_to_remove = "test_remove".to_string(); persist.remove(item_to_remove).unwrap(); assert!(persist.list().unwrap().is_empty()); } From 407c95a597e3b7c3d2263cc5511ed085817dddbb Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 4 Jul 2023 17:54:55 -0700 Subject: [PATCH 08/22] list method strips .bin, updated remove unit test --- .../shuttle_persist/test_remove/test_remove.bin | Bin 0 -> 19 bytes resources/persist/src/lib.rs | 16 +++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 resources/persist/shuttle_persist/test_remove/test_remove.bin diff --git a/resources/persist/shuttle_persist/test_remove/test_remove.bin b/resources/persist/shuttle_persist/test_remove/test_remove.bin new file mode 100644 index 0000000000000000000000000000000000000000..c6938596a1360bd6bc357e8c34d31ee9fd22f720 GIT binary patch literal 19 Vcmd;PfPj+J;*$8H)ZF~CQ~(_f1i1hJ literal 0 HcmV?d00001 diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 7b4885b9e..f91f476a3 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -60,7 +60,9 @@ impl PersistInstance { dir.path() .into_os_string() .into_string() - .unwrap_or_else(|_| "path contains non-UTF-8 characters".to_string()), + .unwrap_or_else(|_| "path contains non-UTF-8 characters".to_string()) + .split(".bin") + .collect::(), ); } Ok(list) @@ -74,8 +76,8 @@ impl PersistInstance { } /// remove method deletes a key from the PersistInstance - pub fn remove(&self, list_item: String) -> Result<(), PersistError> { - let file_path = self.get_storage_file(&list_item); + pub fn remove(&self, key: String) -> Result<(), PersistError> { + let file_path = self.get_storage_file(&key); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; Ok(()) } @@ -158,7 +160,7 @@ mod tests { persist.save("test_list", "test_list").unwrap(); - let result = vec!["shuttle_persist/test_list/test_list.bin".to_string()]; + let result = vec!["shuttle_persist/test_list/test_list".to_string()]; let list_result = persist.list().unwrap(); assert_eq!(result, list_result); } @@ -185,9 +187,9 @@ mod tests { }; persist.save("test_remove", "test_remove").unwrap(); - let item_to_remove = "test_remove".to_string(); - persist.remove(item_to_remove).unwrap(); - assert!(persist.list().unwrap().is_empty()); + let list = persist.list().unwrap(); + let _ = persist.remove(list[0].clone()); + assert!(!list.contains(&"test_remove".to_string())); } #[test] From f7186e1965aed2b8ce9acc32f18e0641ce87d3c4 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 7 Jul 2023 21:44:37 -0700 Subject: [PATCH 09/22] list, remove, and clear, with tests, updated --- .../shuttle_persist/test_list/test_list.bin | Bin 17 -> 16 bytes .../test_remove/test_remove.bin | Bin 19 -> 0 bytes resources/persist/src/lib.rs | 54 +++++++++++------- 3 files changed, 32 insertions(+), 22 deletions(-) delete mode 100644 resources/persist/shuttle_persist/test_remove/test_remove.bin diff --git a/resources/persist/shuttle_persist/test_list/test_list.bin b/resources/persist/shuttle_persist/test_list/test_list.bin index ca518820579fc242ee9b252295c5b05ae0cd9158..264c4fc1ee29434841bcd6f6dea82738981a1caa 100644 GIT binary patch literal 16 Scmd;JfPj+J;*$96)Jgyk=>u^9 literal 17 Tcmd;NfPj+J;*$8B%;FLN6XOHr diff --git a/resources/persist/shuttle_persist/test_remove/test_remove.bin b/resources/persist/shuttle_persist/test_remove/test_remove.bin deleted file mode 100644 index c6938596a1360bd6bc357e8c34d31ee9fd22f720..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19 Vcmd;PfPj+J;*$8H)ZF~CQ~(_f1i1hJ diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index f91f476a3..402611579 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -16,6 +16,10 @@ pub enum PersistError { Open(std::io::Error), #[error("failed to create folder: {0}")] CreateFolder(std::io::Error), + #[error("failed to read folder contents: {0}")] + ReadFolder(std::io::Error), + #[error("failed to read the entry in the folder: {0}")] + ReadEntry(std::io::Error), #[error("failed to list contents of folder: {0}")] ListFolder(std::io::Error), #[error("failed to clear the folder: {0}")] @@ -55,14 +59,14 @@ impl PersistInstance { let entries = fs::read_dir(storage_folder).map_err(PersistError::ListFolder)?; for entry in entries { - let dir = entry.map_err(PersistError::ListFolder)?; + let file = entry.map_err(PersistError::ListFolder)?; list.push( - dir.path() - .into_os_string() - .into_string() - .unwrap_or_else(|_| "path contains non-UTF-8 characters".to_string()) - .split(".bin") - .collect::(), + file.path() + .file_stem() + .unwrap_or_default() + .to_str() + .unwrap_or_else(|| "file name contains non-UTF-8 characters") + .to_string(), ); } Ok(list) @@ -70,13 +74,22 @@ impl PersistInstance { /// clear method removes the storage folder from the PersistInstance pub fn clear(&self) -> Result<(), PersistError> { - let folder_path = self.get_storage_folder(); - fs::remove_dir_all(folder_path).map_err(PersistError::ClearFolder)?; + let storage_folder = self.get_storage_folder(); + let entries = fs::read_dir(storage_folder).map_err(PersistError::ReadFolder)?; + + for entry in entries { + let entry = entry.map_err(PersistError::ReadEntry)?; + let path = entry.path(); + + if path.is_file() { + fs::remove_file(path).map_err(PersistError::RemoveFile)?; + } + } Ok(()) } /// remove method deletes a key from the PersistInstance - pub fn remove(&self, key: String) -> Result<(), PersistError> { + pub fn remove(&self, key: &str) -> Result<(), PersistError> { let file_path = self.get_storage_file(&key); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; Ok(()) @@ -158,9 +171,9 @@ mod tests { service_name: ServiceName::from_str("test_list").unwrap(), }; - persist.save("test_list", "test_list").unwrap(); + persist.save("test_list", "test_key").unwrap(); - let result = vec!["shuttle_persist/test_list/test_list".to_string()]; + let result = vec!["test_list".to_string()]; let list_result = persist.list().unwrap(); assert_eq!(result, list_result); } @@ -171,13 +184,10 @@ mod tests { service_name: ServiceName::from_str("test_clear").unwrap(), }; - persist.save("test_clear", "test_clear").unwrap(); + persist.save("test_clear", "test_key_clear").unwrap(); + assert!(persist.list().unwrap().len() == 1); persist.clear().unwrap(); - let clear_result = persist.list().unwrap_err(); - assert_eq!( - clear_result.to_string(), - "failed to list contents of folder: No such file or directory (os error 2)" - ); + assert!(persist.list().unwrap().is_empty()); } #[test] @@ -186,10 +196,10 @@ mod tests { service_name: ServiceName::from_str("test_remove").unwrap(), }; - persist.save("test_remove", "test_remove").unwrap(); - let list = persist.list().unwrap(); - let _ = persist.remove(list[0].clone()); - assert!(!list.contains(&"test_remove".to_string())); + persist.save("test_remove", "test_key_remove").unwrap(); + assert!(persist.list().unwrap().len() == 1); + persist.remove(persist.list().unwrap()[0].as_str()).unwrap(); + assert!(persist.list().unwrap().len() == 0); } #[test] From abc170463184426dfd0ad5e42e1f2e3b733bc22d Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 7 Jul 2023 21:57:33 -0700 Subject: [PATCH 10/22] Address clippy warnings in CI check --- resources/persist/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 402611579..12b0e2dfd 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -65,7 +65,7 @@ impl PersistInstance { .file_stem() .unwrap_or_default() .to_str() - .unwrap_or_else(|| "file name contains non-UTF-8 characters") + .unwrap("file name contains non-UTF-8 characters") .to_string(), ); } @@ -90,7 +90,7 @@ impl PersistInstance { /// remove method deletes a key from the PersistInstance pub fn remove(&self, key: &str) -> Result<(), PersistError> { - let file_path = self.get_storage_file(&key); + let file_path = self.get_storage_file(key); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?; Ok(()) } @@ -199,7 +199,7 @@ mod tests { persist.save("test_remove", "test_key_remove").unwrap(); assert!(persist.list().unwrap().len() == 1); persist.remove(persist.list().unwrap()[0].as_str()).unwrap(); - assert!(persist.list().unwrap().len() == 0); + assert!(persist.list().unwrap().len().is_empty()); } #[test] From 5ff0e37778dfa6273a151e35e974ebee588031ad Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 7 Jul 2023 21:59:45 -0700 Subject: [PATCH 11/22] Address sloppy typo and clippy warning --- resources/persist/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 12b0e2dfd..04cf34241 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -65,7 +65,7 @@ impl PersistInstance { .file_stem() .unwrap_or_default() .to_str() - .unwrap("file name contains non-UTF-8 characters") + .unwrap_or("file name contains non-UTF-8 characters") .to_string(), ); } From 5a8a88361cfc6afc8dce92eadbca946b71a91c0e Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 7 Jul 2023 22:01:47 -0700 Subject: [PATCH 12/22] Fix another clippy warning in CI --- resources/persist/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 04cf34241..03364aac6 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -199,7 +199,7 @@ mod tests { persist.save("test_remove", "test_key_remove").unwrap(); assert!(persist.list().unwrap().len() == 1); persist.remove(persist.list().unwrap()[0].as_str()).unwrap(); - assert!(persist.list().unwrap().len().is_empty()); + assert!(persist.list().unwrap().is_empty()); } #[test] From bda6a719b7306400ff8b9d6d9183c6bd15d27775 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 14 Jul 2023 19:36:33 -0700 Subject: [PATCH 13/22] improvement: add size method and associated test --- resources/persist/.gitignore | 2 + resources/persist/Cargo.toml | 3 + .../persist/shuttle_persist/test/test.bin | Bin 12 -> 0 bytes .../persist/shuttle_persist/test/test1.bin | Bin 13 -> 0 bytes .../persist/shuttle_persist/test1/test1.bin | Bin 13 -> 0 bytes .../shuttle_persist/test_list/test_list.bin | Bin 16 -> 0 bytes resources/persist/src/lib.rs | 105 ++++++++++++++---- 7 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 resources/persist/.gitignore delete mode 100644 resources/persist/shuttle_persist/test/test.bin delete mode 100644 resources/persist/shuttle_persist/test/test1.bin delete mode 100644 resources/persist/shuttle_persist/test1/test1.bin delete mode 100644 resources/persist/shuttle_persist/test_list/test_list.bin diff --git a/resources/persist/.gitignore b/resources/persist/.gitignore new file mode 100644 index 000000000..dca3bd6cb --- /dev/null +++ b/resources/persist/.gitignore @@ -0,0 +1,2 @@ +# output files from tests +shuttle_persist/**/*.bin \ No newline at end of file diff --git a/resources/persist/Cargo.toml b/resources/persist/Cargo.toml index 4f2be294b..bfcbadffc 100644 --- a/resources/persist/Cargo.toml +++ b/resources/persist/Cargo.toml @@ -12,3 +12,6 @@ bincode = "1.2.1" serde = { version = "1.0.0", features = ["derive"] } shuttle-service = { path = "../../service", version = "0.21.0" } thiserror = "1.0.32" + +[dev-dependencies] +rand = "0.8.5" diff --git a/resources/persist/shuttle_persist/test/test.bin b/resources/persist/shuttle_persist/test/test.bin deleted file mode 100644 index 33b31dd610b71d307ebf3a72d9839cd850073981..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 OcmZQ!fPj+J;t~J^l>x;7 diff --git a/resources/persist/shuttle_persist/test/test1.bin b/resources/persist/shuttle_persist/test/test1.bin deleted file mode 100644 index 3809ab55adf98bd14e3b2d82605de3335e2f0466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13 PcmZQ&fPj+J;u1pu2ABc& diff --git a/resources/persist/shuttle_persist/test1/test1.bin b/resources/persist/shuttle_persist/test1/test1.bin deleted file mode 100644 index 3809ab55adf98bd14e3b2d82605de3335e2f0466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13 PcmZQ&fPj+J;u1pu2ABc& diff --git a/resources/persist/shuttle_persist/test_list/test_list.bin b/resources/persist/shuttle_persist/test_list/test_list.bin deleted file mode 100644 index 264c4fc1ee29434841bcd6f6dea82738981a1caa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16 Scmd;JfPj+J;*$96)Jgyk=>u^9 diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 03364aac6..1d9d7fb1a 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -59,15 +59,15 @@ impl PersistInstance { let entries = fs::read_dir(storage_folder).map_err(PersistError::ListFolder)?; for entry in entries { - let file = entry.map_err(PersistError::ListFolder)?; - list.push( - file.path() - .file_stem() - .unwrap_or_default() - .to_str() - .unwrap_or("file name contains non-UTF-8 characters") - .to_string(), - ); + let key = entry.map_err(PersistError::ListFolder)?; + let key_name = key + .path() + .file_stem() + .unwrap_or_default() + .to_str() + .unwrap_or("file name contains non-UTF-8 characters") + .to_string(); + list.push(key_name); } Ok(list) } @@ -95,6 +95,24 @@ impl PersistInstance { Ok(()) } + /// size method determines the size of all keys stored within a folder, within the PersistInstance + pub fn size(&self) -> Result { + let storage_folder = self.get_storage_folder(); + let mut size = 0; + + let entries = fs::read_dir(storage_folder).map_err(PersistError::ReadFolder)?; + + for entry in entries { + let entry = entry.map_err(PersistError::ReadEntry)?; + let path = entry.path(); + + if path.is_file() { + size += fs::metadata(&path).map_err(PersistError::ReadEntry)?.len(); + } + } + Ok(size) + } + pub fn load(&self, key: &str) -> Result where T: DeserializeOwned, @@ -152,8 +170,15 @@ impl ResourceBuilder for Persist { #[cfg(test)] mod tests { use super::*; + use rand::Rng; use std::str::FromStr; + fn get_range() -> usize { + let mut rng = rand::thread_rng(); + let num_keys = rng.gen_range(1..=20); + num_keys + } + #[test] fn test_save_and_load() { let persist = PersistInstance { @@ -170,12 +195,16 @@ mod tests { let persist = PersistInstance { service_name: ServiceName::from_str("test_list").unwrap(), }; + let list_length = get_range(); + for list_key in 1..=list_length { + let key_name = format!("list_key_{}", list_key); + let key_value = format!("list_key_value_{}", list_key); + persist.save(&key_name, &key_value).unwrap(); + } - persist.save("test_list", "test_key").unwrap(); - - let result = vec!["test_list".to_string()]; - let list_result = persist.list().unwrap(); - assert_eq!(result, list_result); + let length = persist.list().unwrap().len(); + assert_eq!(length, list_length); + persist.clear().unwrap(); } #[test] @@ -184,10 +213,15 @@ mod tests { service_name: ServiceName::from_str("test_clear").unwrap(), }; - persist.save("test_clear", "test_key_clear").unwrap(); - assert!(persist.list().unwrap().len() == 1); + let list_length = get_range(); + for clear_key in 1..=list_length { + let key_name = format!("clear_key_{}", clear_key); + let key_value = format!("clear_key_value_{}", clear_key); + persist.save(&key_name, &key_value).unwrap(); + } persist.clear().unwrap(); - assert!(persist.list().unwrap().is_empty()); + let actual_length = persist.list().unwrap().len(); + assert_eq!(actual_length, 0); } #[test] @@ -196,10 +230,39 @@ mod tests { service_name: ServiceName::from_str("test_remove").unwrap(), }; - persist.save("test_remove", "test_key_remove").unwrap(); - assert!(persist.list().unwrap().len() == 1); - persist.remove(persist.list().unwrap()[0].as_str()).unwrap(); - assert!(persist.list().unwrap().is_empty()); + let list_length = get_range(); + for remove_key in 1..=list_length { + let key_name = format!("remove_key_{}", remove_key); + let key_value = format!("remove_key_value_{}", remove_key); + persist.save(&key_name, &key_value).unwrap(); + } + persist + .remove(persist.list().unwrap()[list_length - 1].as_str()) + .unwrap(); + let actual_length = persist.list().unwrap().len(); + assert_eq!(actual_length, list_length - 1); + persist.clear().unwrap(); + } + + #[test] + fn test_size() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test_size").unwrap(), + }; + + let mut expected_size = 0; + let list_length = get_range(); + for size_key in 1..=list_length { + let key_name = format!("size_key_{}", size_key); + let key_value = format!("size_key_value_{}", size_key); + persist.save(&key_name, &key_value).unwrap(); + expected_size += fs::metadata(persist.get_storage_file(&key_name)) + .unwrap() + .len(); + } + let actual_size = persist.size().unwrap(); + assert_eq!(expected_size, actual_size); + persist.clear().unwrap(); } #[test] From fb9cea58d3c1f33b7e56a5d0a09e34aaa6668f48 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 14 Jul 2023 19:50:17 -0700 Subject: [PATCH 14/22] improvement: correct clippy linting error in tests --- resources/persist/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 1d9d7fb1a..2b0cd8857 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -175,8 +175,7 @@ mod tests { fn get_range() -> usize { let mut rng = rand::thread_rng(); - let num_keys = rng.gen_range(1..=20); - num_keys + rng.gen_range(1..=20) as usize } #[test] From 568e1c203f9a68fa20704c232a2c4662425ea430 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sun, 23 Jul 2023 19:36:11 -0700 Subject: [PATCH 15/22] Add tests for all list, size, remove and clear --- resources/persist/src/lib.rs | 156 +++++++++++++++-------------------- 1 file changed, 66 insertions(+), 90 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 2b0cd8857..2b9f97d8b 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -16,14 +16,10 @@ pub enum PersistError { Open(std::io::Error), #[error("failed to create folder: {0}")] CreateFolder(std::io::Error), - #[error("failed to read folder contents: {0}")] - ReadFolder(std::io::Error), - #[error("failed to read the entry in the folder: {0}")] - ReadEntry(std::io::Error), #[error("failed to list contents of folder: {0}")] ListFolder(std::io::Error), - #[error("failed to clear the folder: {0}")] - ClearFolder(std::io::Error), + #[error("failed to clear folder: {0}")] + RemoveFolder(std::io::Error), #[error("failed to remove file: {0}")] RemoveFile(std::io::Error), #[error("failed to serialize data: {0}")] @@ -72,22 +68,19 @@ impl PersistInstance { Ok(list) } - /// clear method removes the storage folder from the PersistInstance + /// clear method removes the keys within the PersistInstance pub fn clear(&self) -> Result<(), PersistError> { let storage_folder = self.get_storage_folder(); - let entries = fs::read_dir(storage_folder).map_err(PersistError::ReadFolder)?; - - for entry in entries { - let entry = entry.map_err(PersistError::ReadEntry)?; - let path = entry.path(); - - if path.is_file() { - fs::remove_file(path).map_err(PersistError::RemoveFile)?; - } - } + fs::remove_dir_all(&storage_folder).map_err(PersistError::RemoveFolder)?; + fs::create_dir_all(&storage_folder).map_err(PersistError::CreateFolder)?; Ok(()) } + /// size method returns the number of keys in a folder within a PersistInstance + pub fn size(&self) -> Result { + Ok(self.list()?.len()) + } + /// remove method deletes a key from the PersistInstance pub fn remove(&self, key: &str) -> Result<(), PersistError> { let file_path = self.get_storage_file(key); @@ -95,24 +88,6 @@ impl PersistInstance { Ok(()) } - /// size method determines the size of all keys stored within a folder, within the PersistInstance - pub fn size(&self) -> Result { - let storage_folder = self.get_storage_folder(); - let mut size = 0; - - let entries = fs::read_dir(storage_folder).map_err(PersistError::ReadFolder)?; - - for entry in entries { - let entry = entry.map_err(PersistError::ReadEntry)?; - let path = entry.path(); - - if path.is_file() { - size += fs::metadata(&path).map_err(PersistError::ReadEntry)?.len(); - } - } - Ok(size) - } - pub fn load(&self, key: &str) -> Result where T: DeserializeOwned, @@ -170,14 +145,8 @@ impl ResourceBuilder for Persist { #[cfg(test)] mod tests { use super::*; - use rand::Rng; use std::str::FromStr; - fn get_range() -> usize { - let mut rng = rand::thread_rng(); - rng.gen_range(1..=20) as usize - } - #[test] fn test_save_and_load() { let persist = PersistInstance { @@ -190,78 +159,85 @@ mod tests { } #[test] - fn test_list() { + fn test_list_and_size() { let persist = PersistInstance { - service_name: ServiceName::from_str("test_list").unwrap(), + service_name: ServiceName::from_str("test1").unwrap(), }; - let list_length = get_range(); - for list_key in 1..=list_length { - let key_name = format!("list_key_{}", list_key); - let key_value = format!("list_key_value_{}", list_key); - persist.save(&key_name, &key_value).unwrap(); - } - let length = persist.list().unwrap().len(); - assert_eq!(length, list_length); - persist.clear().unwrap(); + persist.save("test", "test").unwrap(); + let list_result = persist.list().unwrap().len(); + let size_result = persist.size().unwrap(); + assert_eq!(list_result, 1); + assert_eq!(size_result, 1); } #[test] - fn test_clear() { + fn test_list_error() { let persist = PersistInstance { - service_name: ServiceName::from_str("test_clear").unwrap(), + service_name: ServiceName::from_str("test2").unwrap(), }; - let list_length = get_range(); - for clear_key in 1..=list_length { - let key_name = format!("clear_key_{}", clear_key); - let key_value = format!("clear_key_value_{}", clear_key); - persist.save(&key_name, &key_value).unwrap(); - } - persist.clear().unwrap(); - let actual_length = persist.list().unwrap().len(); - assert_eq!(actual_length, 0); + // unwrap error + let result = persist.list().unwrap_err(); + assert_eq!( + result.to_string(), + "failed to list contents of folder: No such file or directory (os error 2)" + ); } #[test] fn test_remove() { let persist = PersistInstance { - service_name: ServiceName::from_str("test_remove").unwrap(), + service_name: ServiceName::from_str("test3").unwrap(), }; - let list_length = get_range(); - for remove_key in 1..=list_length { - let key_name = format!("remove_key_{}", remove_key); - let key_value = format!("remove_key_value_{}", remove_key); - persist.save(&key_name, &key_value).unwrap(); - } - persist - .remove(persist.list().unwrap()[list_length - 1].as_str()) - .unwrap(); - let actual_length = persist.list().unwrap().len(); - assert_eq!(actual_length, list_length - 1); - persist.clear().unwrap(); + persist.save("test", "test").unwrap(); + persist.save("test2", "test2").unwrap(); + let list = persist.list().unwrap(); + let key = list[0].as_str(); + persist.remove(key).unwrap(); + let result = persist.list().unwrap(); + assert_eq!(result.len(), 1); } #[test] - fn test_size() { + fn test_remove_error() { let persist = PersistInstance { - service_name: ServiceName::from_str("test_size").unwrap(), + service_name: ServiceName::from_str("test4").unwrap(), }; - let mut expected_size = 0; - let list_length = get_range(); - for size_key in 1..=list_length { - let key_name = format!("size_key_{}", size_key); - let key_value = format!("size_key_value_{}", size_key); - persist.save(&key_name, &key_value).unwrap(); - expected_size += fs::metadata(persist.get_storage_file(&key_name)) - .unwrap() - .len(); - } - let actual_size = persist.size().unwrap(); - assert_eq!(expected_size, actual_size); + // unwrap error + let result = persist.remove("test4").unwrap_err(); + assert_eq!( + result.to_string(), + "failed to remove file: No such file or directory (os error 2)" + ); + } + + #[test] + fn test_clear() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test5").unwrap(), + }; + + persist.save("test5", "test5").unwrap(); persist.clear().unwrap(); + let result = persist.list().unwrap(); + assert_eq!(result.len(), 0); + } + + #[test] + fn test_clear_error() { + let persist = PersistInstance { + service_name: ServiceName::from_str("test6").unwrap(), + }; + + // unwrap error + let result = persist.clear().unwrap_err(); + assert_eq!( + result.to_string(), + "failed to clear folder: No such file or directory (os error 2)" + ); } #[test] From 9c84868363be0961ff22feb630937ec3483f3d08 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 24 Jul 2023 21:45:54 -0700 Subject: [PATCH 16/22] Clean deps, fix error propagation in list, add new --- resources/persist/Cargo.toml | 3 --- resources/persist/src/lib.rs | 46 +++++++++++++++--------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/resources/persist/Cargo.toml b/resources/persist/Cargo.toml index bfcbadffc..4f2be294b 100644 --- a/resources/persist/Cargo.toml +++ b/resources/persist/Cargo.toml @@ -12,6 +12,3 @@ bincode = "1.2.1" serde = { version = "1.0.0", features = ["derive"] } shuttle-service = { path = "../../service", version = "0.21.0" } thiserror = "1.0.32" - -[dev-dependencies] -rand = "0.8.5" diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 2b9f97d8b..1ec5bfb32 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -11,13 +11,15 @@ use std::path::PathBuf; use thiserror::Error; #[derive(Error, Debug)] -pub enum PersistError { +pub enum PersistError<'a> { #[error("failed to open file: {0}")] Open(std::io::Error), #[error("failed to create folder: {0}")] CreateFolder(std::io::Error), #[error("failed to list contents of folder: {0}")] ListFolder(std::io::Error), + #[error("failed to list the file name: {0}")] + ListName(&'a str), #[error("failed to clear folder: {0}")] RemoveFolder(std::io::Error), #[error("failed to remove file: {0}")] @@ -37,10 +39,15 @@ pub struct PersistInstance { } impl PersistInstance { + pub fn new(service_name: ServiceName) -> Self { + Self { + service_name, + } + } + pub fn save(&self, key: &str, struc: T) -> Result<(), PersistError> { let storage_folder = self.get_storage_folder(); fs::create_dir_all(storage_folder).map_err(PersistError::CreateFolder)?; - let file_path = self.get_storage_file(key); let file = File::create(file_path).map_err(PersistError::Open)?; let mut writer = BufWriter::new(file); @@ -61,7 +68,8 @@ impl PersistInstance { .file_stem() .unwrap_or_default() .to_str() - .unwrap_or("file name contains non-UTF-8 characters") + .ok_or("the file name contains invalid characters") + .map_err(PersistError::ListName)? .to_string(); list.push(key_name); } @@ -149,9 +157,7 @@ mod tests { #[test] fn test_save_and_load() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()); persist.save("test", "test").unwrap(); let result: String = persist.load("test").unwrap(); @@ -160,9 +166,7 @@ mod tests { #[test] fn test_list_and_size() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test1").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test1").unwrap()); persist.save("test", "test").unwrap(); let list_result = persist.list().unwrap().len(); @@ -173,9 +177,7 @@ mod tests { #[test] fn test_list_error() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test2").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test2").unwrap()); // unwrap error let result = persist.list().unwrap_err(); @@ -187,9 +189,7 @@ mod tests { #[test] fn test_remove() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test3").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test3").unwrap()); persist.save("test", "test").unwrap(); persist.save("test2", "test2").unwrap(); @@ -202,9 +202,7 @@ mod tests { #[test] fn test_remove_error() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test4").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test4").unwrap()); // unwrap error let result = persist.remove("test4").unwrap_err(); @@ -216,9 +214,7 @@ mod tests { #[test] fn test_clear() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test5").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test5").unwrap()); persist.save("test5", "test5").unwrap(); persist.clear().unwrap(); @@ -228,9 +224,7 @@ mod tests { #[test] fn test_clear_error() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test6").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test6").unwrap()); // unwrap error let result = persist.clear().unwrap_err(); @@ -242,9 +236,7 @@ mod tests { #[test] fn test_load_error() { - let persist = PersistInstance { - service_name: ServiceName::from_str("test").unwrap(), - }; + let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()); // unwrap error let result = persist.load::("error").unwrap_err(); From eced7cd3c23f46ef6d765597d9e914d67a0790a7 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 24 Jul 2023 22:23:56 -0700 Subject: [PATCH 17/22] Resolve issue in circleci check --- resources/persist/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 1ec5bfb32..5ca480c1b 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -40,9 +40,7 @@ pub struct PersistInstance { impl PersistInstance { pub fn new(service_name: ServiceName) -> Self { - Self { - service_name, - } + Self { service_name } } pub fn save(&self, key: &str, struc: T) -> Result<(), PersistError> { From 1912a9299e0338dce1f9aee6bd363c5ca7ed0182 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 25 Jul 2023 06:59:29 -0700 Subject: [PATCH 18/22] New method creates the storage folder --- resources/persist/src/lib.rs | 46 ++++++++++-------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 5ca480c1b..a3ccda4b5 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -39,13 +39,15 @@ pub struct PersistInstance { } impl PersistInstance { - pub fn new(service_name: ServiceName) -> Self { - Self { service_name } + pub fn new(service_name: ServiceName) -> Result> { + let instance = Self { service_name }; + let storage_folder = instance.get_storage_folder(); + fs::create_dir_all(storage_folder).map_err(PersistError::CreateFolder)?; + + Ok(instance) } pub fn save(&self, key: &str, struc: T) -> Result<(), PersistError> { - let storage_folder = self.get_storage_folder(); - fs::create_dir_all(storage_folder).map_err(PersistError::CreateFolder)?; let file_path = self.get_storage_file(key); let file = File::create(file_path).map_err(PersistError::Open)?; let mut writer = BufWriter::new(file); @@ -155,7 +157,7 @@ mod tests { #[test] fn test_save_and_load() { - let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()).unwrap(); persist.save("test", "test").unwrap(); let result: String = persist.load("test").unwrap(); @@ -164,7 +166,7 @@ mod tests { #[test] fn test_list_and_size() { - let persist = PersistInstance::new(ServiceName::from_str("test1").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test1").unwrap()).unwrap(); persist.save("test", "test").unwrap(); let list_result = persist.list().unwrap().len(); @@ -173,21 +175,9 @@ mod tests { assert_eq!(size_result, 1); } - #[test] - fn test_list_error() { - let persist = PersistInstance::new(ServiceName::from_str("test2").unwrap()); - - // unwrap error - let result = persist.list().unwrap_err(); - assert_eq!( - result.to_string(), - "failed to list contents of folder: No such file or directory (os error 2)" - ); - } - #[test] fn test_remove() { - let persist = PersistInstance::new(ServiceName::from_str("test3").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test3").unwrap()).unwrap(); persist.save("test", "test").unwrap(); persist.save("test2", "test2").unwrap(); @@ -200,7 +190,7 @@ mod tests { #[test] fn test_remove_error() { - let persist = PersistInstance::new(ServiceName::from_str("test4").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test4").unwrap()).unwrap(); // unwrap error let result = persist.remove("test4").unwrap_err(); @@ -212,7 +202,7 @@ mod tests { #[test] fn test_clear() { - let persist = PersistInstance::new(ServiceName::from_str("test5").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test5").unwrap()).unwrap(); persist.save("test5", "test5").unwrap(); persist.clear().unwrap(); @@ -220,21 +210,9 @@ mod tests { assert_eq!(result.len(), 0); } - #[test] - fn test_clear_error() { - let persist = PersistInstance::new(ServiceName::from_str("test6").unwrap()); - - // unwrap error - let result = persist.clear().unwrap_err(); - assert_eq!( - result.to_string(), - "failed to clear folder: No such file or directory (os error 2)" - ); - } - #[test] fn test_load_error() { - let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()); + let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()).unwrap(); // unwrap error let result = persist.load::("error").unwrap_err(); From 107c4618587643b564bcc607ae521b7b42fb2dd8 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 27 Jul 2023 21:21:20 -0700 Subject: [PATCH 19/22] New method returns shuttle_service::Error --- resources/persist/src/lib.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index a3ccda4b5..249f08ec1 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -33,16 +33,21 @@ pub enum PersistError<'a> { #[derive(Serialize)] pub struct Persist; -#[derive(Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct PersistInstance { service_name: ServiceName, } impl PersistInstance { - pub fn new(service_name: ServiceName) -> Result> { + + /// new method constructs a new PersistInstance along with its associated storage folder + pub fn new(service_name: ServiceName) -> Result { let instance = Self { service_name }; let storage_folder = instance.get_storage_folder(); - fs::create_dir_all(storage_folder).map_err(PersistError::CreateFolder)?; + match fs::create_dir_all(storage_folder) { + Ok(_) => &instance, + Err(e) => return Err(shuttle_service::Error::Custom(PersistError::CreateFolder(e).into())), + }; Ok(instance) } @@ -154,7 +159,7 @@ impl ResourceBuilder for Persist { mod tests { use super::*; use std::str::FromStr; - + #[test] fn test_save_and_load() { let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()).unwrap(); From c51f298de8ba78d7d2df8bd51f04716d56eace08 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 27 Jul 2023 21:36:21 -0700 Subject: [PATCH 20/22] Fix issue causing circleci/persist to fail --- resources/persist/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 249f08ec1..f0715b9a1 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -39,14 +39,17 @@ pub struct PersistInstance { } impl PersistInstance { - /// new method constructs a new PersistInstance along with its associated storage folder pub fn new(service_name: ServiceName) -> Result { let instance = Self { service_name }; let storage_folder = instance.get_storage_folder(); match fs::create_dir_all(storage_folder) { Ok(_) => &instance, - Err(e) => return Err(shuttle_service::Error::Custom(PersistError::CreateFolder(e).into())), + Err(e) => { + return Err(shuttle_service::Error::Custom( + PersistError::CreateFolder(e).into(), + )) + } }; Ok(instance) @@ -159,7 +162,7 @@ impl ResourceBuilder for Persist { mod tests { use super::*; use std::str::FromStr; - + #[test] fn test_save_and_load() { let persist = PersistInstance::new(ServiceName::from_str("test").unwrap()).unwrap(); From d02dcc17b2cb28de1000c016ce1bdb49142c7a29 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sat, 29 Jul 2023 13:49:57 -0700 Subject: [PATCH 21/22] Update resource builder to use new method --- resources/persist/src/lib.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index f0715b9a1..34d1ed35a 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -40,17 +40,10 @@ pub struct PersistInstance { impl PersistInstance { /// new method constructs a new PersistInstance along with its associated storage folder - pub fn new(service_name: ServiceName) -> Result { + pub fn new(service_name: ServiceName) -> Result> { let instance = Self { service_name }; let storage_folder = instance.get_storage_folder(); - match fs::create_dir_all(storage_folder) { - Ok(_) => &instance, - Err(e) => { - return Err(shuttle_service::Error::Custom( - PersistError::CreateFolder(e).into(), - )) - } - }; + fs::create_dir_all(storage_folder).map_err(PersistError::CreateFolder)?; Ok(instance) } @@ -148,9 +141,11 @@ impl ResourceBuilder for Persist { self, factory: &mut dyn Factory, ) -> Result { - Ok(PersistInstance { - service_name: factory.get_service_name(), - }) + let persist_instance = match PersistInstance::new(factory.get_service_name()) { + Ok(persist_instance) => persist_instance, + Err(e) => return Err(shuttle_service::Error::Custom(e.into())), + }; + Ok(persist_instance) } async fn build(build_data: &Self::Output) -> Result { From 047244471b6d4d9cc68dad52462a706d752a994d Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 17 Aug 2023 06:31:25 -0700 Subject: [PATCH 22/22] chore: update document comments per review --- resources/persist/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index 34d1ed35a..c674a83e7 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -39,7 +39,7 @@ pub struct PersistInstance { } impl PersistInstance { - /// new method constructs a new PersistInstance along with its associated storage folder + /// Constructs a new PersistInstance along with its associated storage folder pub fn new(service_name: ServiceName) -> Result> { let instance = Self { service_name }; let storage_folder = instance.get_storage_folder(); @@ -55,7 +55,7 @@ impl PersistInstance { Ok(serialize_into(&mut writer, &struc).map_err(PersistError::Serialize))? } - /// list method returns a vector of strings containing all the keys associated with a PersistInstance + /// Returns a vector of strings containing all the keys associated with a PersistInstance pub fn list(&self) -> Result, PersistError> { let storage_folder = self.get_storage_folder(); @@ -77,7 +77,7 @@ impl PersistInstance { Ok(list) } - /// clear method removes the keys within the PersistInstance + /// Removes the keys within the PersistInstance pub fn clear(&self) -> Result<(), PersistError> { let storage_folder = self.get_storage_folder(); fs::remove_dir_all(&storage_folder).map_err(PersistError::RemoveFolder)?; @@ -85,12 +85,12 @@ impl PersistInstance { Ok(()) } - /// size method returns the number of keys in a folder within a PersistInstance + /// Returns the number of keys in a folder within a PersistInstance pub fn size(&self) -> Result { Ok(self.list()?.len()) } - /// remove method deletes a key from the PersistInstance + /// Deletes a key from the PersistInstance pub fn remove(&self, key: &str) -> Result<(), PersistError> { let file_path = self.get_storage_file(key); fs::remove_file(file_path).map_err(PersistError::RemoveFile)?;