#[cfg(test)]
mod anonymous_test{
use crate::anonymous::{self, Anonymous};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct ComplexStruct{
one: i32,
two: ContainsPrimitiveValue
}
impl anonymous::Anonymous for ComplexStruct{ fn id() -> u16 { 0 } }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Empty{
One,
Two
}
impl anonymous::Anonymous for Empty{ fn id() -> u16 { 0 } }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum ContainsPrimitiveValue{
One(i32),
Two(i32)
}
impl anonymous::Anonymous for ContainsPrimitiveValue{ fn id() -> u16{ 0 } }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum ContainsComplex{
One(ComplexStruct),
Two(ComplexStruct)
}
impl anonymous::Anonymous for ContainsComplex{ fn id() -> u16 { 0 } }
#[test]
fn assign_primitive() {
let data = 120;
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(data, *unsafe{ cell.get_ref()} );
}
#[test]
fn assign_complex() {
let data = ComplexStruct{
one: 1,
two: ContainsPrimitiveValue::Two(2)
};
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(data, *unsafe{ cell.get_ref()} );
}
#[test]
fn assign_none_primitive() {
let data: Option<i32> = None;
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(None, *unsafe{ cell.get_ref::<Option<i32>>()} );
}
#[test]
fn assign_some_primitive() {
let data: Option<i32> = Some(1);
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(Some(1), *unsafe{ cell.get_ref::<Option<i32>>()} );
}
#[test]
fn assign_empty_enum() {
let data = Empty::One;
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(Empty::One, *unsafe{ cell.get_ref::<Empty>()} );
assert_ne!(Empty::Two, *unsafe{ cell.get_ref::<Empty>()} );
}
#[test]
fn assign_primitive_enum() {
let data = ContainsPrimitiveValue::One(1);
let cell = anonymous::AnonymousCell::new(data);
assert_eq!(ContainsPrimitiveValue::One(1), *unsafe{ cell.get_ref::<ContainsPrimitiveValue>()} );
assert_ne!(ContainsPrimitiveValue::One(2), *unsafe{ cell.get_ref::<ContainsPrimitiveValue>()} );
assert_ne!(ContainsPrimitiveValue::Two(1), *unsafe{ cell.get_ref::<ContainsPrimitiveValue>()} );
assert_ne!(ContainsPrimitiveValue::Two(2), *unsafe{ cell.get_ref::<ContainsPrimitiveValue>()} );
}
#[test]
fn assign_complex_enum() {
let data = ComplexStruct{ one: 1, two: ContainsPrimitiveValue::Two(2) };
let alternative = ComplexStruct{ one: 2, two: ContainsPrimitiveValue::One(1) };
let cell = anonymous::AnonymousCell::new(ContainsComplex::One(data));
assert_eq!(ContainsComplex::One(data), *unsafe{ cell.get_ref() });
assert_ne!(ContainsComplex::One(alternative), *unsafe{ cell.get_ref() });
assert_ne!(ContainsComplex::Two(data), *unsafe { cell.get_ref() });
assert_ne!(ContainsComplex::Two(alternative), *unsafe{ cell.get_ref() });
}
#[test]
fn reassign() {
let data = 10;
let mut cell = anonymous::AnonymousCell::new(data);
unsafe{
let old = cell.exchange_value(2);
assert_eq!(10, old);
}
assert_eq!(2, *unsafe{ cell.get_ref() });
}
#[test]
fn update_inplace() {
let data = ComplexStruct{ one: 1, two: ContainsPrimitiveValue::Two(2) };
let expected = ComplexStruct{ one: 2, two: ContainsPrimitiveValue::Two(2) };
let mut cell = anonymous::AnonymousCell::new(data);
unsafe{
let ptr = cell.get_mut::<ComplexStruct>();
ptr.one = 2;
assert_eq!(*cell.get_ref::<ComplexStruct>(), expected);
assert_ne!(*cell.get_ref::<ComplexStruct>(), data);
}
}
#[test]
fn multiple_updates() {
let initial = ComplexStruct{ one: 1, two: ContainsPrimitiveValue::Two(2) };
let second = ComplexStruct{ one: 2, two: ContainsPrimitiveValue::Two(2) };
let third = ComplexStruct{ one: 2, two: ContainsPrimitiveValue::One(1) };
let mut cell = anonymous::AnonymousCell::new(initial);
unsafe{
let ptr = cell.get_mut::<ComplexStruct>();
assert_eq!(*ptr, initial);
ptr.one = 2;
assert_eq!(*ptr, second);
assert_ne!(*ptr, initial);
ptr.two = ContainsPrimitiveValue::One(1);
assert_eq!(*ptr, third);
assert_ne!(*ptr, second);
}
}
#[test]
fn evil_things() {
#[repr(C)]
#[derive(Copy, Clone, Debug)]
struct Breakable{ one: i32, two: i32 }
impl anonymous::Anonymous for Breakable{ fn id() -> u16 { 0 } }
let data = Breakable{ one: 1, two: 2};
let cell = anonymous::AnonymousCell::new(data);
unsafe{
let ptr = cell.get_ref::<i64>();
let nums: [i32; 2] = std::mem::transmute(*ptr);
assert_eq!(nums, [1, 2]);
}
}
#[test]
fn evil_bad_things() {
#[repr(C)]
#[derive(Copy, Clone, Debug)]
struct Larger([i32; 10]);
impl Anonymous for Larger{ fn id() -> u16 { 0 }}
let data = 1;
let cell = anonymous::AnonymousCell::new(data);
unsafe{
let ptr = cell.get_ref::<Larger>();
println!("{:?}", *ptr);
}
}
#[test]
fn edit_under_scope() {
let data = 1;
let mut cell = anonymous::AnonymousCell::new(data);
unsafe {
cell.exchange_value(2);
}
assert_eq!(*unsafe{ cell.get_ref::<i32>() }, 2);
}
#[test]
fn edit_with_move() {
let data = 1;
let mut cell = anonymous::AnonymousCell::new(data);
let mut change = || {
unsafe{ cell.exchange_value(2); }
};
change();
assert_eq!(*unsafe{ cell.get_ref::<i32>() }, 2)
}
}
#[cfg(test)]
mod row_test{
use crate::table::AnonymousRow;
use crate::anonymous::Anonymous;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct ComplexStruct{
one: i32,
two: u32
}
impl Anonymous for ComplexStruct{ fn id() -> u16 { 0 } }
#[test]
fn push() {
let mut row = AnonymousRow::new();
assert_eq!(row.len(), 0);
row.push(1);
assert_eq!(row.len(), 1);
row.push(2.0);
assert_eq!(row.len(), 2);
row.push(3u32);
assert_eq!(row.len(), 3);
}
#[test]
fn get() {
let mut row = AnonymousRow::new();
row.push(1);
row.push(2.0);
row.push(3u32);
assert_eq!(1, *unsafe{ row.get_at(0).unwrap_unchecked() });
assert_eq!(2.0, *unsafe{ row.get_at(1).unwrap_unchecked() });
assert_eq!(3u32, *unsafe{ row.get_at(2).unwrap_unchecked() });
}
#[test]
fn change() {
let mut row = AnonymousRow::new();
row.push(1);
row.push(2.0);
row.exchange_at(3, 0).unwrap();
assert_eq!(3, *unsafe{ row.get_at(0).unwrap_unchecked() } );
assert_eq!(2.0, *unsafe{ row.get_at(1).unwrap_unchecked() });
}
#[test]
fn update() {
let mut row = AnonymousRow::new();
row.push(ComplexStruct{ one: 1, two: 2 });
row.push(2.0);
unsafe{
let ptr: &mut ComplexStruct = row.get_mut_at(0).unwrap_unchecked();
ptr.one = 2;
assert_eq!(*row.get_at::<ComplexStruct>(0).unwrap_unchecked(), ComplexStruct{ one: 2, two: 2});
}
}
}
#[cfg(test)]
mod tag_test{
use std::str::FromStr;
use anonymous_table::{AnonymousRow, AnonymousTable, RowName, Tag};
#[test]
fn tag_row() {
let mut table = AnonymousTable::new();
let mut row = AnonymousRow::new();
let tag = Tag::new(1020);
row.push(1.0f32);
row.push(99 as u64);
row.push(String::from_str("words").unwrap());
table.push_row(AnonymousRow::new().chain_push(2.0).chain_push(30));
table.register_tagged_row(row, tag);
table.push_row(AnonymousRow::new().chain_push('a'));
assert_eq!(table.len(), 3);
let row = table.get_row(1);
let row = row.unwrap();
assert_eq!(row.len(), 3);
let first_cell: &f32 = row.get_at(0).unwrap();
let second_cell: &u64 = row.get_at(1).unwrap();
let third_cell: &String = row.get_at(2).unwrap();
assert_eq!(*first_cell, 1.0f32);
assert_eq!(*second_cell, 99u64);
assert_eq!(*third_cell, String::from_str("words").unwrap());
}
#[test]
fn tag_multiple_rows(){
let tag = Tag::new(19023);
let row1 = AnonymousRow::new()
.chain_push(1.0)
.chain_push(99u32);
let row2 = AnonymousRow::new()
.chain_push('a');
let mut table = AnonymousTable::new();
table.register_tagged_row(row1, tag);
table.register_tagged_row(row2, tag);
assert_eq!(table.len(), 2);
table.push_row(AnonymousRow::new());
assert_eq!(table.len(), 3);
table.register_tagged_row(AnonymousRow::new(), tag);
assert_eq!(table.len(), 4);
let rows = table.get_tagged_rows(tag).expect("Tag went unregistered for tag_multiple_rows test");
assert_eq!(rows.len(), 3);
for (i, row) in rows.iter().enumerate(){
assert_eq!(row.len(), 3 - (i+1));
}
}
#[test]
fn tag_and_name_row(){
let tag = Tag::new(12034);
let name = RowName(284735);
let row = AnonymousRow::new()
.chain_push(Some(1))
.chain_push('a');
let mut table = AnonymousTable::new()
.chain_push_row(AnonymousRow::new())
.chain_push_row(AnonymousRow::new());
table.register_named_tagged_row(row, tag, name);
let name_ref = table.get_named_row_mut(name).unwrap();
name_ref.exchange_at::<Option<i32>>(None, 0).expect("Failure to exchange value in tag_and_name_row tesst");
let tagged_rows = table.get_tagged_rows(tag)
.expect("missing tagged row in tag_and_name_row test");
let row_ref = tagged_rows.get(0)
.expect("Tag value never stored in tag_and_row_test");
let name_ref = table.get_named_row(name)
.expect("Name lost in tag_and_row_test");
let row_as_raw: *const AnonymousRow = *row_ref;
let name_as_raw: *const AnonymousRow = name_ref;
assert_eq!(row_as_raw, name_as_raw);
assert!(name_ref.get_at::<Option<i32>>(0).unwrap().is_none());
}
#[test]
fn get_from_tagged(){
let tag = Tag::new(12034);
let row = AnonymousRow::new()
.chain_push(Some(12));
let mut table = AnonymousTable::new();
table.register_tagged_row(row, tag);
table.register_tagged_row(AnonymousRow::new().chain_push(1.0), tag);
let tagged_with_wanted = table.get_from_tagged::<Option<i32>>(tag);
assert!(tagged_with_wanted.is_some());
assert_eq!(tagged_with_wanted.unwrap().len(), 1);
}
}