extern crate rand; extern crate rdxsort; use std::collections; use std::hash; use std::hash::Hash; use std::hash::Hasher; use std::iter; use std::mem; use std::ops; use rand::{Rand, Rng, XorShiftRng}; use rdxsort::*; pub static CFG_N: usize = 10_000; fn is_sorted(data: &Vec) -> bool where T: Clone, T: PartialOrd { let mut last_entry: Option = None; for x in data.iter().cloned() { match last_entry { Some(l) => { if !(l.le(&x)) { return false; } } None => {} } last_entry = Some(x); } return true; } pub trait MyHash { fn hash_it(&self, state: &mut H) where H: Hasher; } macro_rules! trivial_myhash { ($t:ty) => { impl MyHash for $t { fn hash_it(&self, state: &mut H) where H: Hasher { self.hash(state); } } } } trivial_myhash!([u8; 0]); trivial_myhash!([u8; 4]); trivial_myhash!((u8,)); trivial_myhash!((u8, i32)); trivial_myhash!((u8, i32, char)); trivial_myhash!(bool); trivial_myhash!(char); trivial_myhash!(i8); trivial_myhash!(i16); trivial_myhash!(i32); trivial_myhash!(i64); trivial_myhash!(isize); trivial_myhash!(u8); trivial_myhash!(u16); trivial_myhash!(u32); trivial_myhash!(u64); trivial_myhash!(usize); impl MyHash for f32 { fn hash_it(&self, state: &mut H) where H: Hasher { let alias = unsafe {mem::transmute_copy::(self)}; alias.hash(state); } } impl MyHash for f64 { fn hash_it(&self, state: &mut H) where H: Hasher { let alias = unsafe {mem::transmute_copy::(self)}; alias.hash(state); } } fn guess_entropy(data: &Vec) -> f64 where T: MyHash { let mut counter = collections::HashMap::::new(); for x in data { let mut hasher = hash::SipHasher::new(); x.hash_it(&mut hasher); let key = hasher.finish(); let state = counter.entry(key).or_insert(0); *state += 1; } counter.values().map(|&x| x as f64 / data.len() as f64).map(|x| -x * x.log2()).fold(0f64, |a, b| a + b) } pub fn test_generic(data: Vec) where T: Clone + PartialOrd, Vec: RdxSort { let mut data = data; let n = data.len(); let mut data_sorted_ref = data.clone(); data_sorted_ref.sort_by(|a, b| a.partial_cmp(b).unwrap()); data.rdxsort(); assert!(data.len() == n, "sorted data has wrong lenght!"); assert!(is_sorted(&data), "data is not sorted!"); for (x, y) in data.iter().zip(data_sorted_ref.iter()) { assert!(x == y, "sortd data does not match the reference!"); } } pub fn test_empty_generic() where T: Clone + PartialOrd, Vec: RdxSort { let data: Vec = vec![]; test_generic(data); } pub fn test_rnd_generic(vspecial: Vec) where T: Clone + PartialOrd + Rand + MyHash, Vec: RdxSort { // config let entropy_threshold = 0.5f64; // generate data let mut rng = XorShiftRng::new_unseeded(); let mut data: Vec = rng.gen_iter::().take(CFG_N).collect(); let mut positions: Vec = (0..(CFG_N + 1)).collect(); rng.shuffle(&mut positions[..]); assert!(vspecial.len() < CFG_N, "to many special values to test!"); for (i, x) in positions.into_iter().zip(vspecial.into_iter()) { data[i] = x; } assert!(data.len() == CFG_N, "generated data has wrong length!"); assert!(guess_entropy(&data) >= entropy_threshold, "generated data does not contain enough entropy!"); test_generic(data); } pub fn test_single_generic(x: T) where T: Clone + PartialOrd, Vec: RdxSort { let data: Vec = vec![x]; test_generic(data); } pub fn test_full_generic(vmin: T, vmax: T) where T: Clone+ PartialOrd + ops::Add, ops::Range: iter::Iterator, Vec: iter::FromIterator< as iter::Iterator>::Item>, Vec: RdxSort { // TODO: use inclusive range once it's stable let mut data: Vec = (vmin.clone()..vmax.clone()).collect(); data.push(vmax); let mut rng = XorShiftRng::new_unseeded(); rng.shuffle(&mut data[..]); test_generic(data); } mod sub_array { use super::*; #[test] fn test_empty_array0() { test_empty_generic::<[u8; 0]>(); } #[test] fn test_single_array0() { test_single_generic::<[u8; 0]>([]); } #[test] fn test_rnd_array4() { test_rnd_generic::<[u8; 4]>(vec![]); } #[test] fn test_empty_array4() { test_empty_generic::<[u8; 4]>(); } #[test] fn test_single_array4() { test_single_generic::<[u8; 4]>([1, 2, 3, 4]); } } mod sub_bool { use super::*; #[test] fn test_rnd_bool() { test_rnd_generic::(vec![false, true]); } #[test] fn test_empty_bool() { test_empty_generic::(); } #[test] fn test_single_bool() { test_single_generic::(true); } } mod sub_char { use super::*; use std::char; #[test] fn test_rnd_char() { test_rnd_generic::(vec!['\0', char::MAX]); } #[test] fn test_empty_char() { test_empty_generic::(); } #[test] fn test_single_char() { test_single_generic::('x'); } } mod sub_i8 { use super::*; #[test] fn test_rnd_i8() { test_rnd_generic::(vec![i8::min_value(), i8::min_value() + 1, -1i8, 0i8, 1i8, i8::max_value() - 1, i8::max_value()]); } #[test] fn test_full_i8() { test_full_generic::(i8::min_value(), i8::max_value()); } #[test] fn test_empty_i8() { test_empty_generic::(); } #[test] fn test_single_i8() { test_single_generic::(3i8); } } mod sub_i16 { use super::*; #[test] fn test_rnd_i16() { test_rnd_generic::(vec![i16::min_value(), i16::min_value() + 1, -1i16, 0i16, 1i16, i16::max_value() - 1, i16::max_value()]); } #[test] fn test_full_i16() { test_full_generic::(i16::min_value(), i16::max_value()); } #[test] fn test_empty_i16() { test_empty_generic::(); } #[test] fn test_single_i16() { test_single_generic::(3i16); } } mod sub_i32 { use super::*; #[test] fn test_rnd_i32() { test_rnd_generic::(vec![i32::min_value(), i32::min_value() + 1, -1i32, 0i32, 1i32, i32::max_value() - 1, i32::max_value()]); } #[test] fn test_empty_i32() { test_empty_generic::(); } #[test] fn test_single_i32() { test_single_generic::(3i32); } } mod sub_i64 { use super::*; #[test] fn test_rnd_i64() { test_rnd_generic::(vec![i64::min_value(), i64::min_value() + 1, -1i64, 0i64, 1i64, i64::max_value() - 1, i64::max_value()]); } #[test] fn test_empty_i64() { test_empty_generic::(); } #[test] fn test_single_i64() { test_single_generic::(3i64); } } mod sub_isize { use super::*; #[test] fn test_rnd_isize() { test_rnd_generic::(vec![isize::min_value(), isize::min_value() + 1, -1, 0, 1, isize::max_value() - 1, isize::max_value()]); } #[test] fn test_empty_isize() { test_empty_generic::(); } #[test] fn test_single_isize() { test_single_generic::(3); } } mod sub_u8 { use super::*; #[test] fn test_rnd_u8() { test_rnd_generic::(vec![0u8, 1u8, u8::max_value() - 1, u8::max_value()]); } #[test] fn test_full_u8() { test_full_generic::(u8::min_value(), u8::max_value()); } #[test] fn test_empty_u8() { test_empty_generic::(); } #[test] fn test_single_u8() { test_single_generic::(3u8); } } mod sub_u16 { use super::*; #[test] fn test_rnd_u16() { test_rnd_generic::(vec![0u16, 1u16, u16::max_value() - 1, u16::max_value()]); } #[test] fn test_full_u16() { test_full_generic::(u16::min_value(), u16::max_value()); } #[test] fn test_empty_u16() { test_empty_generic::(); } #[test] fn test_single_u16() { test_single_generic::(3u16); } } mod sub_u32 { use super::*; #[test] fn test_rnd_u32() { test_rnd_generic::(vec![0u32, 1u32, u32::max_value() - 1, u32::max_value()]); } #[test] fn test_empty_u32() { test_empty_generic::(); } #[test] fn test_single_u32() { test_single_generic::(3u32); } } mod sub_u64 { use super::*; #[test] fn test_rnd_u64() { test_rnd_generic::(vec![0u64, 1u64, u64::max_value() - 1, u64::max_value()]); } #[test] fn test_empty_u64() { test_empty_generic::(); } #[test] fn test_single_u64() { test_single_generic::(3u64); } } mod sub_usize { use super::*; #[test] fn test_rnd_usize() { test_rnd_generic::(vec![0, 1, usize::max_value() - 1, usize::max_value()]); } #[test] fn test_empty_usize() { test_empty_generic::(); } #[test] fn test_single_usize() { test_single_generic::(3); } } mod sub_f32 { use super::*; use std::f32; #[test] fn test_rnd_f32() { test_rnd_generic::(vec![-f32::INFINITY, -0f32, 0f32, f32::INFINITY]); } #[test] fn test_empty_f32() { test_empty_generic::(); } #[test] fn test_single_f32() { test_single_generic::(3f32); } } mod sub_f64 { use super::*; use std::f64; #[test] fn test_rnd_f64() { test_rnd_generic::(vec![-f64::INFINITY, -0f64, 0f64, f64::INFINITY]); } #[test] fn test_empty_f64() { test_empty_generic::(); } #[test] fn test_single_f64() { test_single_generic::(3f64); } } mod sub_tuple { use super::*; #[test] fn test_empty_tuple0() { test_empty_generic::<()>(); } #[test] fn test_single_tuple0() { test_single_generic::<()>(()); } #[test] fn test_rnd_tuple1() { test_rnd_generic::<(u8,)>(vec![]); } #[test] fn test_empty_tuple1() { test_empty_generic::<(u8,)>(); } #[test] fn test_single_tuple1() { test_single_generic::<(u8,)>((1u8,)); } #[test] fn test_rnd_tuple2() { test_rnd_generic::<(u8, i32)>(vec![]); } #[test] fn test_empty_tuple2() { test_empty_generic::<(u8, i32)>(); } #[test] fn test_single_tuple2() { test_single_generic::<(u8, i32)>((1u8, 1337i32)); } #[test] fn test_rnd_tuple3() { test_rnd_generic::<(u8, i32, char)>(vec![]); } #[test] fn test_empty_tuple3() { test_empty_generic::<(u8, i32, char)>(); } #[test] fn test_single_tuple3() { test_single_generic::<(u8, i32, char)>((1u8, 1337i32, 'x')); } }