use rand::Rng;
use data::{Flow, Hybrid, LinkReference};
use doublets::{Doublets, Link};
#[allow(dead_code)]
pub fn test_crud<T: LinkReference>(store: &mut impl Doublets<T>) {
let constants = store.constants().clone();
assert_eq!(store.count(), T::from_byte(0));
let address = store.create().unwrap();
let mut link: Link<T> = store.get_link(address).unwrap();
assert_eq!(link.index, address);
assert_eq!(link.source, constants.null);
assert_eq!(link.target, constants.null);
assert_eq!(store.count(), T::from_byte(0));
store.update(address, address, address).unwrap();
link = store.get_link(address).unwrap();
assert_eq!(link.source, address);
assert_eq!(link.target, address);
let updated = store
.update(address, constants.null, constants.null)
.unwrap();
assert_eq!(updated, address);
link = store.get_link(address).unwrap();
assert_eq!(link.source, constants.null);
assert_eq!(link.target, constants.null);
store.delete(address).unwrap();
assert_eq!(store.count(), T::from_byte(0));
}
#[allow(dead_code)]
pub fn test_raw_numbers_crud<T: LinkReference>(store: &mut impl Doublets<T>) {
let links = store;
let constants = links.constants().clone();
let n106 = T::try_from(106_usize).unwrap();
let n107 = T::try_from(char::from_u32(107).unwrap() as usize).unwrap();
#[allow(clippy::cast_sign_loss)]
let n108 = T::try_from((-108_i32) as usize).unwrap();
let h106 = Hybrid::external(n106);
let h107 = Hybrid::new(n107);
let h108 = Hybrid::new(n108);
assert_eq!(h106.abs().as_(), 106);
assert_eq!(h107.abs().as_(), 107);
assert_eq!(h108.abs().as_(), 108);
let address1 = links.create().unwrap();
links
.update(address1, h106.as_inner(), h108.as_inner())
.unwrap();
let link = links.get_link(address1).unwrap();
assert_eq!(link.source, h106.as_inner());
assert_eq!(link.target, h108.as_inner());
let address2 = links.create().unwrap();
links.update(address2, address1, h108.as_inner()).unwrap();
let link = links.get_link(address2).unwrap();
assert_eq!(link.source, address1);
assert_eq!(link.target, h108.as_inner());
let address3 = links.create().unwrap();
links.update(address3, address1, address2).unwrap();
let link = links.get_link(address3).unwrap();
assert_eq!(link.source, address1);
assert_eq!(link.target, address2);
let any = constants.any;
let mut result = None;
links.each_by([any, h106.as_inner(), h108.as_inner()], |link| {
result = Some(link.index);
Flow::Break
});
assert_eq!(result, Some(address1));
let mut result = None;
links.each_by([any, h106.abs(), h107.abs()], |link| {
result = Some(link.index);
Flow::Break
}); assert_eq!(result, None);
let updated = links
.update(address3, T::from_byte(0), T::from_byte(0))
.unwrap();
assert_eq!(updated, address3);
let link = links.get_link(updated).unwrap();
assert_eq!(link.source, T::from_byte(0));
assert_eq!(link.target, T::from_byte(0));
links.delete(updated).unwrap();
assert_eq!(links.count(), T::try_from(2).unwrap());
let _continue = links.constants().r#continue;
let mut result = None;
links.each(|link| {
result = Some(link.index);
Flow::Continue
});
assert_eq!(result, Some(address2));
}
pub fn test_random_creations_and_deletions<T: LinkReference>(
store: &mut impl Doublets<T>,
per_cycle: usize,
) {
for n in 1..per_cycle {
let mut created = 0;
for _ in 0..n {
let count = store.count().as_();
let create_point: bool = rand::random();
if count >= 2 && create_point {
let address = 1..=count;
let source = rand::thread_rng().gen_range(address.clone());
let target = rand::thread_rng().gen_range(address);
let result = store
.get_or_create(T::try_from(source).unwrap(), T::try_from(target).unwrap())
.unwrap()
.as_();
if result > count {
created += 1;
}
} else {
store.create().unwrap();
created += 1;
}
assert_eq!(created, store.count().as_());
}
store.delete_all().unwrap();
assert_eq!(store.count(), T::from_byte(0));
}
}