#![cfg(test)]
use ic_cdk::export::candid::Principal;
use lazy_static::lazy_static;
use proptest::test_runner::TestRunner;
use proptest::{prelude::*, strategy::ValueTree};
use std::{collections::HashMap, sync::RwLock};
use crate::data::account::{UserAccountArgs, UserAccountData};
use crate::data::chain::UserChainData;
use crate::data::transaction::UserTransactionData;
use crate::data::user::{UserData, UserDataArgs, UserDataSettingValue, UserProfileArgs};
const DEFAULT_BYTES: [u8; 29] = [0; 29];
const OWNER_BYTES: [u8; 29] = [1; 29];
const WALLET_CANISTER_BYTES: [u8; 29] = [2; 29];
lazy_static! {
static ref GENERATED_BYTES: RwLock<[u8; 29]> = RwLock::new(DEFAULT_BYTES);
}
pub fn random_caller() {
let byte_strategy = any::<[u8; 29]>();
let bytes_tree = byte_strategy.new_tree(&mut TestRunner::default()).unwrap();
let bytes = bytes_tree.current();
*GENERATED_BYTES.write().unwrap() = bytes;
}
pub fn owner_caller() {
*GENERATED_BYTES.write().unwrap() = OWNER_BYTES;
}
pub fn wallet_canister_caller() {
*GENERATED_BYTES.write().unwrap() = WALLET_CANISTER_BYTES;
}
pub fn reset_bytes() {
*GENERATED_BYTES.write().unwrap() = DEFAULT_BYTES;
}
pub fn owner_principal() -> Principal {
Principal::from_slice(&OWNER_BYTES)
}
pub fn wallet_canister_principal() -> Principal {
Principal::from_slice(&WALLET_CANISTER_BYTES)
}
pub fn set_caller(principal: Principal) {
*GENERATED_BYTES.write().unwrap() = principal.as_slice().to_vec().try_into().unwrap();
}
pub fn ic_caller() -> Principal {
let bytes = GENERATED_BYTES.read().unwrap().clone();
Principal::from_slice(&bytes)
}
pub fn ic_timestamp() -> u64 {
u64::from(1667817318 as u64)
}
pub fn random_principal() -> Principal {
let strategy = principal_strategy();
strategy
.new_tree(&mut TestRunner::default())
.unwrap()
.current()
}
pub fn principal_strategy() -> impl Strategy<Value = Principal> {
any::<[u8; 29]>().prop_map(move |bytes| Principal::from_slice(&bytes))
}
impl Arbitrary for UserDataSettingValue {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
prop_oneof![
any::<String>().prop_map(|value| UserDataSettingValue::StringValue(value)),
any::<u128>().prop_map(|value| UserDataSettingValue::NumberValue(value)),
any::<f64>().prop_map(|value| UserDataSettingValue::FloatValue(value)),
any::<bool>().prop_map(|value| UserDataSettingValue::BoolValue(value))
]
.boxed()
}
}
impl Arbitrary for UserData {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<String>(),
any::<String>(),
any::<String>(),
any::<u128>(),
any::<UserAccountData>(),
any::<UserProfileArgs>(),
any::<HashMap<String, UserDataSettingValue>>(),
)
.prop_map(
|(name, email, password, balance, accounts, profile, settings)| {
UserData::new(
UserDataArgs {
password: Some(password),
balance: Some(balance),
settings: Some(settings),
email: Some(email),
name: Some(name),
profile: Some(profile),
},
UserAccountArgs {
public_key: accounts.public_key,
name: Some(accounts.name),
hidden: Some(accounts.hidden),
disabled: Some(accounts.disabled),
},
)
},
)
.boxed()
}
}
impl Arbitrary for UserProfileArgs {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<String>(),
any::<String>(),
any::<String>(),
any::<HashMap<String, String>>(),
)
.prop_map(|(full_name, address, phone_number, attributes)| Self {
full_name: Some(full_name),
address: Some(address),
phone_number: Some(phone_number),
attributes: Some(attributes),
})
.boxed()
}
}
impl Arbitrary for UserDataArgs {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<Option<String>>(),
any::<Option<String>>(),
any::<Option<u128>>(),
any::<Option<String>>(),
any::<Option<UserProfileArgs>>(),
any::<Option<HashMap<String, UserDataSettingValue>>>(),
)
.prop_map(
|(name, email, balance, password, profile, settings)| UserDataArgs {
name,
email,
balance,
password,
profile,
settings,
},
)
.boxed()
}
}
impl Arbitrary for UserAccountArgs {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<Vec<u8>>(),
any::<Option<String>>(),
any::<Option<bool>>(),
any::<Option<bool>>(),
)
.prop_map(|(public_key, name, hidden, disabled)| Self {
public_key,
name,
hidden,
disabled,
})
.boxed()
}
}
impl Arbitrary for UserAccountData {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(
any::<Vec<u8>>(),
any::<String>(),
any::<bool>(),
any::<bool>(),
any::<HashMap<u64, UserChainData>>(),
)
.prop_map(|(public_key, name, hidden, disabled, chain_data)| Self {
public_key,
name,
hidden,
disabled,
chain_data,
})
.boxed()
}
}
impl Arbitrary for UserChainData {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(any::<UserTransactionData>())
.prop_map(|transaction| UserChainData::new(transaction))
.boxed()
}
}
impl Arbitrary for UserTransactionData {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
(any::<Vec<u8>>(), any::<u64>(), any::<u64>())
.prop_map(|(data, cycle, timestamp)| UserTransactionData::new(data, cycle, timestamp))
.boxed()
}
}