Fixed the tests to be correct.

There is now a random test for all the primitive number types.

Also, I fixed my errors with the tests that should panic. I kept thinking
that they should run fine and it was throwing off how I was writing
the code.
This commit is contained in:
Jason Travis Smith 2016-01-03 03:22:21 -05:00
parent e6f1fbb229
commit 010abeff7c
2 changed files with 165 additions and 13 deletions

View File

@ -36,7 +36,10 @@ macro_rules! read_bytes
({
use std::$returnType;
assert!($buffer.len() < $returnType::BYTES);
// Make sure that there is enough space to read
// a value from the buffer.
assert!($buffer.len() == $returnType::BYTES);
unsafe
{
(*($buffer.as_ptr() as *const $returnType)).$convertFunc()
@ -52,7 +55,8 @@ macro_rules! write_bytes
({
use std::$valueType;
assert!($buffer.len() < $valueType::BYTES);
assert!($buffer.len() >= $valueType::BYTES,
"Not enough room in the buffer to write to.");
unsafe
{
let size: usize;

View File

@ -8,10 +8,105 @@ extern crate sigils;
use rand::thread_rng;
use std::thread::{Builder, JoinHandle};
const EXHAUSTIVE_RUNS: u64 = 10000u64;
macro_rules! create_thread
{
($thread_name: expr, $func_name: ident) =>
{
{
let builder: Builder;
builder = Builder::new().name($thread_name.to_string());
match builder.spawn($func_name)
{
Ok(handle) =>
{
handle
}
Err(_) =>
{
panic!("Error spawning thread: {}.", $thread_name);
}
}
}
}
}
///
macro_rules! full_check_impl
{
($T: ident, $read_func: ident, $write_func: ident, $numBytes: expr) =>
{
{
use rand::ThreadRng;
use rand::distributions::{IndependentSample, Range};
use alchemy::{BigEndian, LittleEndian, Transmutable};
let range: Range<$T>;
let mut rng: ThreadRng;
rng = rand::thread_rng();
range = Range::new(std::$T::MIN, std::$T::MAX);
for _ in 0..EXHAUSTIVE_RUNS
{
let val: $T;
let final_big_val: $T;
let final_little_val: $T;
let mut buffer: [u8; $numBytes];
buffer = [0u8; $numBytes];
val = range.ind_sample(&mut rng);
BigEndian::$write_func(&mut buffer, val);
final_big_val = BigEndian::$read_func(&buffer);
if final_big_val != val
{
panic!(false);
}
LittleEndian::$write_func(&mut buffer, val);
final_little_val = LittleEndian::$read_func(&buffer);
if final_little_val != val
{
panic!(false);
}
}
true
}
}
}
///
macro_rules! full_check
{
($func_name: ident, $T: ident, $read_func: ident, $write_func: ident) =>
{
fn $func_name() -> bool
{
use std::$T;
full_check_impl!($T, $read_func, $write_func, $T::BYTES)
}
};
($func_name: ident, $T: ident,
$read_func: ident, $write_func: ident, $numBytes: expr) =>
{
fn $func_name() -> bool
{
full_check_impl!($T, $read_func, $write_func, $numBytes)
}
};
}
/// This should only be called by the macro below.
macro_rules! overflow_impl
{
@ -28,9 +123,9 @@ macro_rules! overflow_impl
#[should_panic]
fn read_big_endian()
{
let buffer: [u8; $numBytes];
let buffer: [u8; $numBytes - 1];
buffer = [0u8; $numBytes];
buffer = [0u8; $numBytes - 1];
BigEndian::$read_func(&buffer);
}
@ -38,9 +133,9 @@ macro_rules! overflow_impl
#[should_panic]
fn read_little_endian()
{
let buffer: [u8; $numBytes];
let buffer: [u8; $numBytes - 1];
buffer = [0u8; $numBytes];
buffer = [0u8; $numBytes - 1];
LittleEndian::$read_func(&buffer);
}
@ -49,9 +144,9 @@ macro_rules! overflow_impl
#[should_panic]
fn write_big_endian()
{
let mut buffer: [u8; $numBytes];
let mut buffer: [u8; $numBytes - 1];
buffer = [0u8; $numBytes];
buffer = [0u8; $numBytes - 1];
BigEndian::$write_func(&mut buffer, $T::zero());
}
@ -59,9 +154,9 @@ macro_rules! overflow_impl
#[should_panic]
fn write_little_endian()
{
let mut buffer: [u8; $numBytes];
let mut buffer: [u8; $numBytes - 1];
buffer = [0u8; $numBytes];
buffer = [0u8; $numBytes - 1];
LittleEndian::$write_func(&mut buffer, $T::zero());
}
};
@ -97,13 +192,66 @@ test_buffer_overflow!(overflow_u16, u16, bytes_to_u16, u16_to_bytes);
test_buffer_overflow!(overflow_u32, u32, bytes_to_u32, u32_to_bytes);
test_buffer_overflow!(overflow_u64, u64, bytes_to_u64, u64_to_bytes);
test_buffer_overflow!(overflow_usize, usize,
bytes_to_usize, usize_to_bytes, 9);
bytes_to_usize, usize_to_bytes, 1);
test_buffer_overflow!(overflow_i16, i16, bytes_to_i16, i16_to_bytes);
test_buffer_overflow!(overflow_i32, i32, bytes_to_i32, i32_to_bytes);
test_buffer_overflow!(overflow_i64, i64, bytes_to_i64, i64_to_bytes);
test_buffer_overflow!(overflow_isize, isize,
bytes_to_isize, isize_to_bytes, 9);
bytes_to_isize, isize_to_bytes, 1);
test_buffer_overflow!(overflow_f32, f32, bytes_to_f32, f32_to_bytes, 4);
test_buffer_overflow!(overflow_f64, f64, bytes_to_f64, f64_to_bytes, 8);
// Create the exhaustive check functions for the integer types.
full_check!(check_u16, u16, bytes_to_u16, u16_to_bytes);
full_check!(check_u32, u32, bytes_to_u32, u32_to_bytes);
full_check!(check_u64, u64, bytes_to_u64, u64_to_bytes);
full_check!(check_usize, usize, bytes_to_usize, usize_to_bytes);
full_check!(check_i16, i16, bytes_to_i16, i16_to_bytes);
full_check!(check_i32, i32, bytes_to_i32, i32_to_bytes);
full_check!(check_i64, i64, bytes_to_i64, i64_to_bytes);
full_check!(check_isize, isize, bytes_to_isize, isize_to_bytes);
full_check!(check_f32, f32, bytes_to_f32, f32_to_bytes, 4);
full_check!(check_f64, f64, bytes_to_f64, f64_to_bytes, 8);
#[test]
fn exhaustive_check()
{
let mut threads: Vec<JoinHandle<bool>>;
threads = Vec::new();
threads.push(create_thread!("u16", check_u16));
threads.push(create_thread!("u32", check_u32));
threads.push(create_thread!("u64", check_u64));
threads.push(create_thread!("usize", check_usize));
threads.push(create_thread!("i16", check_i16));
threads.push(create_thread!("i32", check_i32));
threads.push(create_thread!("i64", check_i64));
threads.push(create_thread!("isize", check_isize));
threads.push(create_thread!("f32", check_f32));
threads.push(create_thread!("f64", check_f64));
for handle in threads
{
let mut name: String;
name = String::new();
name.push_str(handle.thread().name().unwrap());
match handle.join()
{
Ok(result) =>
{
println!("{}: {}", name, result);
}
Err(_) =>
{
panic!("{}", name);
}
}
}
}