pub trait V1 {
fn make(&self) -> String;
fn is_valid(&self, value: String) -> bool;
}
#[cfg(test)]
mod tests {
use super::V1;
use crate::id::v1::id::ID;
use crate::id::v1::mock::Mock;
use rand::distributions::Alphanumeric;
use rand::thread_rng;
use rand::Rng;
use std::panic;
use std::sync::Arc;
use std::thread;
#[test]
fn make_success() {
let total_interactions = 100;
let mock_module = Mock::new();
for _ in 1..total_interactions {
let random_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(26)
.map(char::from)
.collect();
mock_module.expected_make(random_id);
}
let modules: Vec<Arc<dyn V1 + Sync + Send>> =
vec![Arc::new(ID::new()), Arc::new(mock_module)];
for module in modules {
let threads: Vec<_> = (1..total_interactions)
.map(|_| {
let module_internal = module.clone();
thread::spawn(move || {
let value = module_internal.make();
assert!(value.len() == 26, "value '{}' must have 26 chars", value);
for char in value.chars() {
assert!(
!char.is_whitespace(),
"value '{}' can't have blank spaces",
value
);
assert!(
char.is_lowercase() || char.is_numeric(),
"value '{}' must be lower case or numeric",
value
);
assert!(
char.is_ascii_alphanumeric(),
"value '{}' must be a alphabet letter",
value
);
}
})
})
.collect();
for handle in threads {
handle.join().unwrap();
}
}
}
#[test]
fn is_valid_true() {
let total_interactions = 100;
let mock_module = Mock::new();
for _ in 1..total_interactions {
let random_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(26)
.map(char::from)
.collect();
mock_module.expected_make(random_id);
}
let modules: Vec<Arc<dyn V1 + Sync + Send>> =
vec![Arc::new(ID::new()), Arc::new(mock_module)];
for module in modules {
let threads: Vec<_> = (1..total_interactions)
.map(|_| {
let module_internal = module.clone();
thread::spawn(move || {
let value = module_internal.make();
assert!(module_internal.is_valid(value));
})
})
.collect();
for handle in threads {
handle.join().unwrap();
}
}
}
#[test]
fn is_valid_false() {
let mut values: Vec<String> = vec![];
for count in 0..100 {
if count == 26 {
continue;
}
let random_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(count)
.map(char::from)
.collect();
values.push(random_id.to_lowercase());
}
let modules: Vec<Arc<dyn V1 + Sync + Send>> =
vec![Arc::new(ID::new()), Arc::new(Mock::new())];
for module in modules {
let threads: Vec<_> = values
.to_vec()
.into_iter()
.map(|value| {
let module_internal = module.clone();
thread::spawn(move || {
assert!(module_internal.is_valid(value.to_string()) == false);
})
})
.collect();
for handle in threads {
handle.join().unwrap();
}
}
}
#[test]
fn make_mock_panic_initialize() {
let random_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(26)
.map(char::from)
.collect();
let random_id = random_id.to_lowercase();
assert_eq!(
panic::catch_unwind(|| {
let mock_module = Mock::new_options(random_id.clone());
mock_module.make();
}).err().and_then(move |a| a.downcast_ref::<String>().map(|s| {
s == &format!("no values were found for this mock instance ({}), you did'nt initialize the mock correctly, to do so use the 'new' function as shown below: Mock::new()", random_id.clone())
})),
Some(true));
}
#[test]
fn make_mock_panic_no_values() {
let random_id: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(26)
.map(char::from)
.collect();
let random_id = random_id.to_lowercase();
assert_eq!(
panic::catch_unwind(|| {
let mock_module = Mock::new_options(random_id.clone());
mock_module.expected_make("value_a".to_string());
mock_module.make();
mock_module.make();
}).err().and_then(move |a| a.downcast_ref::<String>().map(|s| {
s == &format!("no value found for the requested mock instance ({}), you must set the value expected by the mock using the 'expected_make' function as shown below: mock_instance.expected_make(\"my_value\".to_string())", random_id.clone())
})),
Some(true));
}
}