Skip to content
This repository has been archived by the owner on Feb 9, 2024. It is now read-only.

Commit

Permalink
moar tests
Browse files Browse the repository at this point in the history
  • Loading branch information
CyonAlexRDX committed Jan 18, 2024
1 parent ffbc3d7 commit e1766bd
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 10 deletions.
15 changes: 14 additions & 1 deletion profile/src/v100/factors/factor_source.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
use crate::prelude::*;

#[derive(Serialize, Deserialize, Clone, EnumAsInner, Debug, PartialEq, Eq, Hash, uniffi::Enum)]
#[derive(
Serialize,
Deserialize,
Clone,
EnumAsInner,
Debug,
PartialEq,
Eq,
Hash,
derive_more::Display,
uniffi::Enum,
)]
#[serde(untagged, remote = "Self")]
pub enum FactorSource {
Device {
#[serde(rename = "device")]
#[display("DeviceFS({value})")]
value: DeviceFactorSource,
},

Ledger {
#[serde(rename = "ledgerHQHardwareWallet")]
#[display("LedgerHWFS({value})")]
value: LedgerHardwareWalletFactorSource,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use crate::prelude::*;
/// all new Accounts and Personas an users authenticate signing by authorizing
/// the client (Wallet App) to access a mnemonic stored in secure storage on
/// the device.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, uniffi::Record)]
#[derive(
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, derive_more::Display, uniffi::Record,
)]
#[serde(rename_all = "camelCase")]
#[display("{hint} {id}")]
pub struct DeviceFactorSource {
/// Unique and stable identifier of this factor source, stemming from the
/// hash of a special child key of the HD root of the mnemonic.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use crate::prelude::*;

/// Properties describing a DeviceFactorSource to help user disambiguate between
/// it and another one.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, uniffi::Record)]
#[derive(
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, derive_more::Display, uniffi::Record,
)]
#[serde(rename_all = "camelCase")]
#[display("{name} {model}")]
pub struct DeviceFactorSourceHint {
/// "iPhone RED"
pub name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::prelude::*;

#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Debug, uniffi::Record)]
#[derive(
Serialize, Deserialize, Clone, PartialEq, Eq, Hash, Debug, derive_more::Display, uniffi::Record,
)]
#[serde(rename_all = "camelCase")]
#[display("{hint} : {id}")]
pub struct LedgerHardwareWalletFactorSource {
/// Unique and stable identifier of this factor source, stemming from the
/// hash of a special child key of the HD root of the mnemonic,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::prelude::*;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, uniffi::Record)]
#[derive(
Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, derive_more::Display, uniffi::Record,
)]
#[display("{name} {model}")]
pub struct LedgerHardwareWalletHint {
/// "Orange, scratched"
pub name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@ use crate::prelude::*;
/// The model of a Ledger HQ hardware wallet NanoS, e.g.
/// *Ledger Nano S+*.
#[derive(
Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, uniffi::Enum,
Serialize,
Deserialize,
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
derive_more::Display,
uniffi::Enum,
)]
#[serde(rename_all = "camelCase")]
pub enum LedgerHardwareWalletModel {
Expand Down
3 changes: 2 additions & 1 deletion profile/src/wallet/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ impl Identifiable for Header {

#[derive(Debug, uniffi::Object)]
pub struct Wallet {
profile: RwLock<Profile>,
// This is pub(crate) for testing purposes only, i.e. causing the RwLock to be poisoned.
pub(crate) profile: RwLock<Profile>,
pub(crate) wallet_client_storage: WalletClientStorage,
}

Expand Down
115 changes: 112 additions & 3 deletions profile/src/wallet/wallet_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Wallet {
self.add_factor_source(private_device_factor_source.factor_source.into())
.map_err(|e| {
error!(
"Failed to Private DeviceFactorSource to SecureStorage, factor source id: {}",
"Failed to add Private DeviceFactorSource to SecureStorage, factor source id: {}",
id
);
_ = self.wallet_client_storage.delete_mnemonic(&id);
Expand All @@ -52,10 +52,20 @@ impl Wallet {
/// edited.
pub fn add_factor_source(&self, factor_source: FactorSource) -> Result<()> {
self.try_write(|mut p| {
trace!(
"About to add FactorSource: {}, to list of factor sources: {}",
&factor_source,
&p.factor_sources

Check warning on line 58 in profile/src/wallet/wallet_accounts.rs

View check run for this annotation

Codecov / codecov/patch

profile/src/wallet/wallet_accounts.rs#L57-L58

Added lines #L57 - L58 were not covered by tests
);
if p.factor_sources.append(factor_source.to_owned()).0 {
Err(CommonError::Unknown)
} else {
debug!("Added FactorSource: {}", &factor_source);
Ok(())
} else {
error!(

Check warning on line 64 in profile/src/wallet/wallet_accounts.rs

View check run for this annotation

Codecov / codecov/patch

profile/src/wallet/wallet_accounts.rs#L64

Added line #L64 was not covered by tests
"FactorSource not added, already present: {}",
&factor_source

Check warning on line 66 in profile/src/wallet/wallet_accounts.rs

View check run for this annotation

Codecov / codecov/patch

profile/src/wallet/wallet_accounts.rs#L66

Added line #L66 was not covered by tests
);
Err(CommonError::Unknown)

Check warning on line 68 in profile/src/wallet/wallet_accounts.rs

View check run for this annotation

Codecov / codecov/patch

profile/src/wallet/wallet_accounts.rs#L68

Added line #L68 was not covered by tests
}
})
.map_err(
Expand Down Expand Up @@ -188,6 +198,14 @@ impl Wallet {
#[cfg(test)]
mod tests {

use std::{
borrow::{Borrow, BorrowMut},
ops::Deref,
sync::atomic::AtomicBool,
};

use __private__::{Mutex, RwLock};

use crate::prelude::*;

#[test]
Expand Down Expand Up @@ -229,4 +247,95 @@ mod tests {
MnemonicWithPassphrase::placeholder()
);
}

#[test]
pub fn add_private_device_factor_source_successful() {
let profile = Profile::placeholder();
let new =
PrivateHierarchicalDeterministicFactorSource::generate_new(WalletClientModel::Unknown);
let (wallet, storage) = Wallet::ephemeral(profile.clone());
assert_eq!(
profile
.factor_sources
.contains_id(&new.clone().factor_source.factor_source_id()),
false
);
assert!(wallet.add_private_device_factor_source(new.clone()).is_ok());
assert!(storage.storage.read().unwrap().contains_key(
&SecureStorageKey::DeviceFactorSourceMnemonic {
factor_source_id: new.clone().factor_source.id,
},
));
assert_eq!(
wallet
.profile()
.factor_sources
.contains_id(&new.clone().factor_source.factor_source_id()),
true
);
}

#[test]
pub fn add_private_device_factor_source_ok_storage_when_save_to_profile_fails_then_deleted_from_storage(
) {
let profile = Profile::placeholder();
let new =
PrivateHierarchicalDeterministicFactorSource::generate_new(WalletClientModel::Unknown);

assert_eq!(
profile
.factor_sources
.contains_id(&new.clone().factor_source.factor_source_id()),
false
);
let delete_data_was_called = Arc::new(RwLock::new(Option::<SecureStorageKey>::None));
#[derive(Debug)]
struct TestStorage {
delete_data_was_called: Arc<RwLock<Option<SecureStorageKey>>>,
}
impl SecureStorage for TestStorage {
fn load_data(&self, _key: SecureStorageKey) -> Result<Option<Vec<u8>>> {
todo!()
}

fn save_data(&self, _key: SecureStorageKey, _data: Vec<u8>) -> Result<()> {
Ok(()) // mnemonic gets saved
}

fn delete_data_for_key(&self, key: SecureStorageKey) -> Result<()> {
let mut delete_data_was_called = self.delete_data_was_called.write().unwrap();
*delete_data_was_called = Some(key);
Ok(())
}
}
let storage = Arc::new(TestStorage {
delete_data_was_called: delete_data_was_called.clone(),
});
let wallet = Wallet::by_importing_profile(profile, storage.clone());

// Acquire write lock, in order to make `wallet.add_private_device_factor_source` fail (because cant have multiple writers).
let lock = wallet.profile.write().unwrap();

assert_eq!(
wallet.add_private_device_factor_source(new.clone()),
Err(CommonError::UnableToSaveFactorSourceToProfile(
new.factor_source.factor_source_id()
))
);
drop(lock);

assert_eq!(
wallet
.profile()
.factor_sources
.contains_id(&new.clone().factor_source.factor_source_id()),
false // should not have been saved.
);
assert_eq!(
delete_data_was_called.read().unwrap().clone().unwrap(),
SecureStorageKey::DeviceFactorSourceMnemonic {
factor_source_id: new.clone().factor_source.id
}
);
}
}

0 comments on commit e1766bd

Please sign in to comment.