From 010abeff7cffc5db09b3feab168247c16609a165 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Sun, 3 Jan 2016 03:22:21 -0500 Subject: [PATCH] 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. --- src/endian.rs | 8 ++- tests/lib.rs | 170 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 165 insertions(+), 13 deletions(-) diff --git a/src/endian.rs b/src/endian.rs index dcc49ff..5bc292e 100644 --- a/src/endian.rs +++ b/src/endian.rs @@ -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; diff --git a/tests/lib.rs b/tests/lib.rs index 2304237..931262d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -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>; + + 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); + } + } + } +}