Files
another-boids-in-rust/vendor/radsort/tests/integration_tests.rs

223 lines
6.1 KiB
Rust

#[test]
fn sort_bool() {
let mut actual = [
true, false, true, true, true, false, true, true, false, false, false,
];
let mut expected = actual;
radsort::sort(&mut actual);
expected.sort();
assert_eq!(actual, expected);
}
#[test]
fn sort_char() {
#[rustfmt::skip]
let mut actual = [
'\u{0}', '\u{1}', '\u{F}', '\u{7F}', // 1-byte sequence
'\u{80}', '\u{81}', '\u{FF}', '\u{7FF}', // 2-byte sequence
'\u{800}', '\u{801}', '\u{FFF}', '\u{FFFF}', // 3-byte sequence
'\u{10000}', '\u{10001}', '\u{FFFFF}', '\u{10FFFF}' // 4-byte sequence
];
actual.reverse();
let mut expected = actual;
radsort::sort(&mut actual);
expected.sort();
assert_eq!(actual, expected);
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn sort_integer() {
macro_rules! implement {
($($t:ident)*) => ($(
let mut actual = [
$t::MIN, $t::MIN+1, $t::MIN / 2,
$t::MAX, $t::MAX-1, $t::MAX / 2,
-1i8 as $t, 0, 1,
];
let mut expected = actual.clone();
expected.sort();
radsort::sort(&mut actual);
assert_eq!(actual, expected);
)*)
}
implement! {
u8 u16 u32 u64 u128 usize
i8 i16 i32 i64 i128 isize
}
}
#[test]
fn sort_float() {
macro_rules! implement {
($($t:ident)*) => ($(
let mut actual = [
0.0, -0.0, 1.0, -1.0,
$t::MIN, $t::MAX,
$t::MIN_POSITIVE, -$t::MIN_POSITIVE,
$t::EPSILON, -$t::EPSILON,
$t::INFINITY, $t::NEG_INFINITY,
];
let mut expected = actual.clone();
expected.sort_by(|a, b| a.partial_cmp(b).unwrap());
radsort::sort(&mut actual);
assert_eq!(actual, expected);
)*)
}
implement! { f32 f64 }
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn sort_cached() {
macro_rules! implement {
($($t:ident)*) => ($(
let mut actual = [
$t::MIN, $t::MIN+1, $t::MIN / 2,
$t::MAX, $t::MAX-1, $t::MAX / 2,
-1i8 as $t, 0, 1,
];
let mut expected = actual.clone();
expected.sort();
radsort::sort_by_cached_key(&mut actual, |t| *t);
assert_eq!(actual, expected);
)*)
}
implement! {
u8 u16 u32 u64 u128 usize
i8 i16 i32 i64 i128 isize
}
}
#[test]
fn sort_struct() {
#[derive(PartialEq, Debug, Clone)]
struct Data(u32);
let source: Vec<_> = (0..512).map(Data).collect();
{
// Sorting references
let mut actual: Vec<&Data> = source.iter().collect();
let mut expected = actual.clone();
radsort::sort_by_key(&mut actual, |d| d.0);
expected.sort_by_key(|d| d.0);
assert_eq!(actual, expected);
}
{
// Sorting actual values
let mut actual = source.clone();
let mut expected = source;
radsort::sort_by_key(&mut actual, |d| d.0);
expected.sort_by_key(|d| d.0);
assert_eq!(actual, expected);
}
}
/// Test sorting by multiple keys in a tuple.
#[test]
fn sort_compound() {
let mut actual = Vec::new();
for a in 0..10 {
for b in 0..10 {
for c in 0..10 {
for d in 0..10 {
actual.push([a, b, c, d]);
}
}
}
}
actual.reverse();
let mut expected = actual.clone();
radsort::sort_by_key(&mut expected, |a| a[0]);
radsort::sort_by_key(&mut actual, |a| (a[0],));
assert_eq!(actual, expected);
radsort::sort_by_key(&mut expected, |a| a[1]);
radsort::sort_by_key(&mut expected, |a| a[0]);
radsort::sort_by_key(&mut actual, |a| (a[0], a[1]));
assert_eq!(actual, expected);
radsort::sort_by_key(&mut expected, |a| a[2]);
radsort::sort_by_key(&mut expected, |a| a[1]);
radsort::sort_by_key(&mut expected, |a| a[0]);
radsort::sort_by_key(&mut actual, |a| (a[0], a[1], a[2]));
assert_eq!(actual, expected);
radsort::sort_by_key(&mut expected, |a| a[3]);
radsort::sort_by_key(&mut expected, |a| a[2]);
radsort::sort_by_key(&mut expected, |a| a[1]);
radsort::sort_by_key(&mut expected, |a| a[0]);
radsort::sort_by_key(&mut actual, |a| (a[0], a[1], a[2], a[3]));
assert_eq!(actual, expected);
}
#[test]
fn sort_zst() {
let mut actual = [(); 10];
let mut expected = actual;
expected.sort();
radsort::sort_by_key(&mut actual, |_| 0);
assert_eq!(actual, expected);
}
/// Tests that unreliable key function gets detected
#[test]
#[should_panic(
expected = "The key function is not reliable: when called repeatedly, \
it returned different keys for the same element."
)]
fn unreliable_key_function() {
let mut key_fn_call_count = 0;
let mut data: Vec<u16> = (200..300).collect();
radsort::sort_by_key(&mut data, |v| {
key_fn_call_count += 1;
if key_fn_call_count == 250 {
!v // flip all the bits, changing the element bucket
} else {
*v
}
});
}
/// Tests that the slice is left in a consistent state after a panic.
#[test]
fn exception_safety() {
// Crossing u8::MAX boundary to make sure that values differ in both bytes
// and a digit won't be skipped.
let mut actual: Vec<u16> = (200..300).collect();
let expected = actual.clone();
actual.reverse();
let mut wrapper = std::panic::AssertUnwindSafe(actual.as_mut_slice());
let e = std::panic::catch_unwind(move || {
let mut key_fn_call_count = 0;
radsort::sort_by_key(*wrapper, |v| {
key_fn_call_count += 1;
if key_fn_call_count == 250 {
// Second sorting pass, the slice is being written to
panic!("panic in the key function");
} else {
*v
}
});
})
.expect_err("panic was not thrown");
assert_eq!(
*e.downcast::<&'static str>().expect("unexpected error"),
"panic in the key function"
);
actual.sort();
assert_eq!(expected, actual);
}