diff --git a/Cargo.toml b/Cargo.toml index 083d16d..2fc555a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["password", "credential", "keychain", "keyring", "cross-platform"] license = "MIT OR Apache-2.0" name = "keyring" repository = "https://github.com/hwchen/keyring-rs.git" -version = "2.3.1" +version = "2.3.2" rust-version = "1.68" edition = "2021" exclude = [".github/"] diff --git a/README.md b/README.md index fa96226..d5a7c49 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ whether through contributing code, discussion, or bug reports! - @MaikKlein - @Phrohdoh - @phlip9 +- @ReactorScram - @Rukenshia - @russellbanks - @ryanavella diff --git a/tests/threading.rs b/tests/threading.rs index d0f4c96..1061c91 100644 --- a/tests/threading.rs +++ b/tests/threading.rs @@ -149,3 +149,65 @@ fn test_simultaneous_independent_create_set() { handle.join().expect("Couldn't execute on thread") } } + +#[test] +#[cfg(not(all(feature = "linux-keyutils", not(feature = "secret-service"))))] +fn test_multiple_create_delete_single_thread() { + let name = generate_random_string(); + let entry = Entry::new(&name, &name).expect("Can't create entry"); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + let repeats = 10; + #[cfg(any(target_os = "macos", target_os = "windows"))] + let repeats = 10_000; + for _i in 0..repeats { + entry.set_password(&name).expect("Can't set ascii password"); + let stored_password = entry.get_password().expect("Can't get ascii password"); + assert_eq!( + stored_password, name, + "Retrieved and set ascii passwords don't match" + ); + entry + .delete_password() + .expect("Can't delete ascii password"); + assert!( + matches!(entry.get_password(), Err(Error::NoEntry)), + "Able to read a deleted ascii password" + ); + } +} + +#[test] +#[cfg(not(all(feature = "linux-keyutils", not(feature = "secret-service"))))] +fn test_simultaneous_multiple_create_delete_single_thread() { + let mut handles = vec![]; + for t in 0..10 { + let root = generate_random_string(); + let test = move || { + let name = format!("{root}-{t}"); + let entry = Entry::new(&name, &name).expect("Can't create entry"); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + let repeats = 10; + #[cfg(any(target_os = "macos", target_os = "windows"))] + let repeats = 10_000; + for _i in 0..repeats { + entry.set_password(&name).expect("Can't set ascii password"); + let stored_password = entry.get_password().expect("Can't get ascii password"); + assert_eq!( + stored_password, name, + "Retrieved and set ascii passwords don't match" + ); + entry + .delete_password() + .expect("Can't delete ascii password"); + assert!( + matches!(entry.get_password(), Err(Error::NoEntry)), + "Able to read a deleted ascii password" + ); + } + }; + handles.push(std::thread::spawn(test)) + } + for handle in handles { + handle.join().expect("Couldn't execute on thread") + } +}