Skip to content

Commit d79b87b

Browse files
committed
Add tests
1 parent e70c619 commit d79b87b

3 files changed

Lines changed: 104 additions & 0 deletions

File tree

library/coretests/tests/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#![feature(hashmap_internals)]
6969
#![feature(int_from_ascii)]
7070
#![feature(int_roundings)]
71+
#![feature(integer_casts)]
7172
#![feature(io_slice_as_bytes)]
7273
#![feature(ip)]
7374
#![feature(is_ascii_octdigit)]
@@ -83,6 +84,7 @@
8384
#![feature(iterator_try_collect)]
8485
#![feature(iterator_try_reduce)]
8586
#![feature(layout_for_ptr)]
87+
#![feature(macro_metavar_expr_concat)]
8688
#![feature(maybe_uninit_fill)]
8789
#![feature(maybe_uninit_uninit_array_transpose)]
8890
#![feature(min_specialization)]
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use std::sync::LazyLock;
2+
3+
// All (negative) integers which are at or near a power of two to test
4+
// boundary conditions. We use strings so we can convert to any type using
5+
// parsing, while still being able to use the *position* in ORDERED_VALS for
6+
// comparisons.
7+
static ORDERED_VALS: LazyLock<Vec<String>> = LazyLock::new(|| {
8+
let mut pos_int_vals = Vec::new();
9+
for exp in 0..=127 {
10+
let val = 1_u128 << exp;
11+
pos_int_vals.push(val.saturating_sub(2));
12+
pos_int_vals.push(val.saturating_sub(1));
13+
pos_int_vals.push(val);
14+
pos_int_vals.push(val.saturating_add(1));
15+
pos_int_vals.push(val.saturating_add(2));
16+
}
17+
pos_int_vals.sort();
18+
pos_int_vals.dedup();
19+
20+
let mut pos_str_vals: Vec<_> = pos_int_vals.iter().map(|i| i.to_string()).collect();
21+
22+
// These are manual because the upper ones overflow even u128.
23+
pos_str_vals.push("340282366920938463463374607431768211454".to_owned()); // 2**128 - 2
24+
pos_str_vals.push("340282366920938463463374607431768211455".to_owned()); // 2**128 - 1
25+
pos_str_vals.push("340282366920938463463374607431768211456".to_owned()); // 2**128
26+
pos_str_vals.push("340282366920938463463374607431768211457".to_owned()); // 2**128 + 1
27+
pos_str_vals.push("340282366920938463463374607431768211458".to_owned()); // 2**128 + 2
28+
29+
let mut out = Vec::new();
30+
for val in pos_str_vals[1..].iter().rev() {
31+
out.push(format!("-{val}"));
32+
}
33+
out.extend(pos_str_vals);
34+
out
35+
});
36+
37+
macro_rules! make_checked_cast_test {
38+
($Src:ident as [$($Dst:ident),*]) => {$(
39+
#[test]
40+
#[allow(non_snake_case)]
41+
fn ${concat(test_checked_cast_, $Src, _to_, $Dst)}() {
42+
for val in ORDERED_VALS.iter() {
43+
if let Some(src) = val.parse::<$Src>().ok() {
44+
let dst: Option<$Dst> = val.parse().ok();
45+
assert_eq!(src.checked_cast::<$Dst>(), dst);
46+
}
47+
}
48+
}
49+
)*}
50+
}
51+
52+
macro_rules! make_bounded_cast_test {
53+
(|$src:ident| $raw:expr, $Src:ident as [$($Dst:ident),*]) => {$(
54+
#[test]
55+
#[allow(non_snake_case)]
56+
fn ${concat(test_bounded_cast_, $Src, _to_, $Dst)}() {
57+
let ord_idx = |s| ORDERED_VALS.iter().position(|v| *v == s).unwrap();
58+
let dst_min_idx = ord_idx(<$Dst>::MIN.to_string());
59+
let dst_max_idx = ord_idx(<$Dst>::MAX.to_string());
60+
for (val_idx, val) in ORDERED_VALS.iter().enumerate() {
61+
if let Some($src) = val.parse::<$Src>().ok() {
62+
let dst: Option<$Dst> = val.parse().ok();
63+
64+
assert_eq!($src.wrapping_cast::<$Dst>(), $raw as $Dst);
65+
66+
if val_idx > dst_max_idx {
67+
assert_eq!($src.saturating_cast::<$Dst>(), <$Dst>::MAX);
68+
} else if val_idx < dst_min_idx {
69+
assert_eq!($src.saturating_cast::<$Dst>(), <$Dst>::MIN);
70+
} else {
71+
assert_eq!($src.saturating_cast::<$Dst>(), dst.unwrap());
72+
}
73+
}
74+
}
75+
}
76+
)*}
77+
}
78+
79+
macro_rules! make_tests_for_src {
80+
(|$src:ident| $raw:expr, [$($Src:ident),*]) => {$(
81+
make_checked_cast_test!( $Src as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
82+
make_bounded_cast_test!(|$src| $raw, $Src as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
83+
84+
// NonZero types are not (yet) implemented.
85+
// make_checked_cast_test!($Src as [
86+
// NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
87+
// NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize
88+
// ]);
89+
)*}
90+
}
91+
92+
make_tests_for_src!(|x| x, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
93+
94+
// NonZero types are not (yet) implemented.
95+
// make_tests_for_src!(
96+
// |x| x.get(),
97+
// [
98+
// NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
99+
// NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize
100+
// ]
101+
// );

library/coretests/tests/num/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod u8;
2323

2424
mod bignum;
2525
mod carryless_mul;
26+
mod cast;
2627
mod const_from;
2728
mod dec2flt;
2829
mod float_ieee754_flt2dec_dec2flt;

0 commit comments

Comments
 (0)