| use std::cmp; |
| |
| use rand::rngs::OsRng; |
| use rand::RngCore; |
| |
| use subtle::*; |
| |
| #[test] |
| #[should_panic] |
| fn slices_equal_different_lengths() { |
| let a: [u8; 3] = [0, 0, 0]; |
| let b: [u8; 4] = [0, 0, 0, 0]; |
| |
| assert_eq!((&a).ct_eq(&b).unwrap_u8(), 1); |
| } |
| |
| #[test] |
| fn slices_equal() { |
| let a: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; |
| let b: [u8; 8] = [1, 2, 3, 4, 4, 3, 2, 1]; |
| |
| let a_eq_a = (&a).ct_eq(&a); |
| let a_eq_b = (&a).ct_eq(&b); |
| |
| assert_eq!(a_eq_a.unwrap_u8(), 1); |
| assert_eq!(a_eq_b.unwrap_u8(), 0); |
| |
| let c: [u8; 16] = [0u8; 16]; |
| |
| let a_eq_c = (&a).ct_eq(&c); |
| assert_eq!(a_eq_c.unwrap_u8(), 0); |
| } |
| |
| #[test] |
| fn conditional_assign_i32() { |
| let mut a: i32 = 5; |
| let b: i32 = 13; |
| |
| a.conditional_assign(&b, 0.into()); |
| assert_eq!(a, 5); |
| a.conditional_assign(&b, 1.into()); |
| assert_eq!(a, 13); |
| } |
| |
| #[test] |
| fn conditional_assign_i64() { |
| let mut c: i64 = 2343249123; |
| let d: i64 = 8723884895; |
| |
| c.conditional_assign(&d, 0.into()); |
| assert_eq!(c, 2343249123); |
| c.conditional_assign(&d, 1.into()); |
| assert_eq!(c, 8723884895); |
| } |
| |
| macro_rules! generate_integer_conditional_select_tests { |
| ($($t:ty)*) => ($( |
| let x: $t = 0; // all 0 bits |
| let y: $t = !0; // all 1 bits |
| |
| assert_eq!(<$t>::conditional_select(&x, &y, 0.into()), 0); |
| assert_eq!(<$t>::conditional_select(&x, &y, 1.into()), y); |
| |
| let mut z = x; |
| let mut w = y; |
| |
| <$t>::conditional_swap(&mut z, &mut w, 0.into()); |
| assert_eq!(z, x); |
| assert_eq!(w, y); |
| <$t>::conditional_swap(&mut z, &mut w, 1.into()); |
| assert_eq!(z, y); |
| assert_eq!(w, x); |
| |
| z.conditional_assign(&x, 1.into()); |
| w.conditional_assign(&y, 0.into()); |
| assert_eq!(z, x); |
| assert_eq!(w, x); |
| )*) |
| } |
| |
| #[test] |
| fn integer_conditional_select() { |
| generate_integer_conditional_select_tests!(u8 u16 u32 u64); |
| generate_integer_conditional_select_tests!(i8 i16 i32 i64); |
| #[cfg(feature = "i128")] |
| generate_integer_conditional_select_tests!(i128 u128); |
| } |
| |
| #[test] |
| fn custom_conditional_select_i16() { |
| let x: i16 = 257; |
| let y: i16 = 514; |
| |
| assert_eq!(i16::conditional_select(&x, &y, 0.into()), 257); |
| assert_eq!(i16::conditional_select(&x, &y, 1.into()), 514); |
| } |
| |
| #[test] |
| fn ordering_conditional_select() { |
| assert_eq!( |
| cmp::Ordering::conditional_select(&cmp::Ordering::Less, &cmp::Ordering::Greater, 0.into()), |
| cmp::Ordering::Less |
| ); |
| |
| assert_eq!( |
| cmp::Ordering::conditional_select(&cmp::Ordering::Less, &cmp::Ordering::Greater, 1.into()), |
| cmp::Ordering::Greater |
| ); |
| } |
| |
| macro_rules! generate_integer_equal_tests { |
| ($($t:ty),*) => ($( |
| let y: $t = 0; // all 0 bits |
| let z: $t = !0; // all 1 bits |
| |
| let x = z; |
| |
| assert_eq!(x.ct_eq(&y).unwrap_u8(), 0); |
| assert_eq!(x.ct_eq(&z).unwrap_u8(), 1); |
| assert_eq!(x.ct_ne(&y).unwrap_u8(), 1); |
| assert_eq!(x.ct_ne(&z).unwrap_u8(), 0); |
| )*) |
| } |
| |
| #[test] |
| fn integer_equal() { |
| generate_integer_equal_tests!(u8, u16, u32, u64); |
| generate_integer_equal_tests!(i8, i16, i32, i64); |
| #[cfg(feature = "i128")] |
| generate_integer_equal_tests!(i128, u128); |
| generate_integer_equal_tests!(isize, usize); |
| } |
| |
| #[test] |
| fn choice_into_bool() { |
| let choice_true: bool = Choice::from(1).into(); |
| |
| assert!(choice_true); |
| |
| let choice_false: bool = Choice::from(0).into(); |
| |
| assert!(!choice_false); |
| } |
| |
| #[test] |
| fn conditional_select_choice() { |
| let t = Choice::from(1); |
| let f = Choice::from(0); |
| |
| assert_eq!(bool::from(Choice::conditional_select(&t, &f, f)), true); |
| assert_eq!(bool::from(Choice::conditional_select(&t, &f, t)), false); |
| assert_eq!(bool::from(Choice::conditional_select(&f, &t, f)), false); |
| assert_eq!(bool::from(Choice::conditional_select(&f, &t, t)), true); |
| } |
| |
| #[test] |
| fn choice_equal() { |
| assert!(Choice::from(0).ct_eq(&Choice::from(0)).unwrap_u8() == 1); |
| assert!(Choice::from(0).ct_eq(&Choice::from(1)).unwrap_u8() == 0); |
| assert!(Choice::from(1).ct_eq(&Choice::from(0)).unwrap_u8() == 0); |
| assert!(Choice::from(1).ct_eq(&Choice::from(1)).unwrap_u8() == 1); |
| } |
| |
| #[test] |
| fn ordering_equal() { |
| let a = cmp::Ordering::Equal; |
| let b = cmp::Ordering::Greater; |
| let c = a; |
| |
| assert_eq!(a.ct_eq(&b).unwrap_u8(), 0); |
| assert_eq!(a.ct_eq(&c).unwrap_u8(), 1); |
| } |
| |
| #[test] |
| fn test_ctoption() { |
| let a = CtOption::new(10, Choice::from(1)); |
| let b = CtOption::new(9, Choice::from(1)); |
| let c = CtOption::new(10, Choice::from(0)); |
| let d = CtOption::new(9, Choice::from(0)); |
| |
| // Test is_some / is_none |
| assert!(bool::from(a.is_some())); |
| assert!(bool::from(!a.is_none())); |
| assert!(bool::from(b.is_some())); |
| assert!(bool::from(!b.is_none())); |
| assert!(bool::from(!c.is_some())); |
| assert!(bool::from(c.is_none())); |
| assert!(bool::from(!d.is_some())); |
| assert!(bool::from(d.is_none())); |
| |
| // Test unwrap for Some |
| assert_eq!(a.unwrap(), 10); |
| assert_eq!(b.unwrap(), 9); |
| |
| // Test equality |
| assert!(bool::from(a.ct_eq(&a))); |
| assert!(bool::from(!a.ct_eq(&b))); |
| assert!(bool::from(!a.ct_eq(&c))); |
| assert!(bool::from(!a.ct_eq(&d))); |
| |
| // Test equality of None with different |
| // dummy value |
| assert!(bool::from(c.ct_eq(&d))); |
| |
| // Test unwrap_or |
| assert_eq!(CtOption::new(1, Choice::from(1)).unwrap_or(2), 1); |
| assert_eq!(CtOption::new(1, Choice::from(0)).unwrap_or(2), 2); |
| |
| // Test unwrap_or_else |
| assert_eq!(CtOption::new(1, Choice::from(1)).unwrap_or_else(|| 2), 1); |
| assert_eq!(CtOption::new(1, Choice::from(0)).unwrap_or_else(|| 2), 2); |
| |
| // Test map |
| assert_eq!( |
| CtOption::new(1, Choice::from(1)) |
| .map(|v| { |
| assert_eq!(v, 1); |
| 2 |
| }) |
| .unwrap(), |
| 2 |
| ); |
| assert_eq!( |
| CtOption::new(1, Choice::from(0)) |
| .map(|_| 2) |
| .is_none() |
| .unwrap_u8(), |
| 1 |
| ); |
| |
| // Test and_then |
| assert_eq!( |
| CtOption::new(1, Choice::from(1)) |
| .and_then(|v| { |
| assert_eq!(v, 1); |
| CtOption::new(2, Choice::from(0)) |
| }) |
| .is_none() |
| .unwrap_u8(), |
| 1 |
| ); |
| assert_eq!( |
| CtOption::new(1, Choice::from(1)) |
| .and_then(|v| { |
| assert_eq!(v, 1); |
| CtOption::new(2, Choice::from(1)) |
| }) |
| .unwrap(), |
| 2 |
| ); |
| |
| assert_eq!( |
| CtOption::new(1, Choice::from(0)) |
| .and_then(|_| CtOption::new(2, Choice::from(0))) |
| .is_none() |
| .unwrap_u8(), |
| 1 |
| ); |
| assert_eq!( |
| CtOption::new(1, Choice::from(0)) |
| .and_then(|_| CtOption::new(2, Choice::from(1))) |
| .is_none() |
| .unwrap_u8(), |
| 1 |
| ); |
| |
| // Test or_else |
| assert_eq!( |
| CtOption::new(1, Choice::from(0)) |
| .or_else(|| CtOption::new(2, Choice::from(1))) |
| .unwrap(), |
| 2 |
| ); |
| assert_eq!( |
| CtOption::new(1, Choice::from(1)) |
| .or_else(|| CtOption::new(2, Choice::from(0))) |
| .unwrap(), |
| 1 |
| ); |
| assert_eq!( |
| CtOption::new(1, Choice::from(1)) |
| .or_else(|| CtOption::new(2, Choice::from(1))) |
| .unwrap(), |
| 1 |
| ); |
| assert!(bool::from( |
| CtOption::new(1, Choice::from(0)) |
| .or_else(|| CtOption::new(2, Choice::from(0))) |
| .is_none() |
| )); |
| |
| // Test (in)equality |
| assert!(CtOption::new(1, Choice::from(0)).ct_eq(&CtOption::new(1, Choice::from(1))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(1, Choice::from(0))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(0)).ct_eq(&CtOption::new(2, Choice::from(1))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(2, Choice::from(0))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(0)).ct_eq(&CtOption::new(1, Choice::from(0))).unwrap_u8() == 1); |
| assert!(CtOption::new(1, Choice::from(0)).ct_eq(&CtOption::new(2, Choice::from(0))).unwrap_u8() == 1); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(2, Choice::from(1))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(2, Choice::from(1))).unwrap_u8() == 0); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(1, Choice::from(1))).unwrap_u8() == 1); |
| assert!(CtOption::new(1, Choice::from(1)).ct_eq(&CtOption::new(1, Choice::from(1))).unwrap_u8() == 1); |
| } |
| |
| #[test] |
| #[should_panic] |
| fn unwrap_none_ctoption() { |
| // This test might fail (in release mode?) if the |
| // compiler decides to optimize it away. |
| CtOption::new(10, Choice::from(0)).unwrap(); |
| } |
| |
| macro_rules! generate_greater_than_test { |
| ($ty: ty) => { |
| for _ in 0..100 { |
| let x = OsRng.next_u64() as $ty; |
| let y = OsRng.next_u64() as $ty; |
| let z = x.ct_gt(&y); |
| |
| println!("x={}, y={}, z={:?}", x, y, z); |
| |
| if x < y { |
| assert!(z.unwrap_u8() == 0); |
| } else if x == y { |
| assert!(z.unwrap_u8() == 0); |
| } else if x > y { |
| assert!(z.unwrap_u8() == 1); |
| } |
| } |
| } |
| } |
| |
| #[test] |
| fn greater_than_u8() { |
| generate_greater_than_test!(u8); |
| } |
| |
| #[test] |
| fn greater_than_u16() { |
| generate_greater_than_test!(u16); |
| } |
| |
| #[test] |
| fn greater_than_u32() { |
| generate_greater_than_test!(u32); |
| } |
| |
| #[test] |
| fn greater_than_u64() { |
| generate_greater_than_test!(u64); |
| } |
| |
| #[cfg(feature = "i128")] |
| #[test] |
| fn greater_than_u128() { |
| generate_greater_than_test!(u128); |
| } |
| |
| #[test] |
| fn greater_than_ordering() { |
| assert_eq!(cmp::Ordering::Less.ct_gt(&cmp::Ordering::Greater).unwrap_u8(), 0); |
| assert_eq!(cmp::Ordering::Greater.ct_gt(&cmp::Ordering::Less).unwrap_u8(), 1); |
| } |
| |
| #[test] |
| /// Test that the two's compliment min and max, i.e. 0000...0001 < 1111...1110, |
| /// gives the correct result. (This fails using the bit-twiddling algorithm that |
| /// go/crypto/subtle uses.) |
| fn less_than_twos_compliment_minmax() { |
| let z = 1u32.ct_lt(&(2u32.pow(31)-1)); |
| |
| assert!(z.unwrap_u8() == 1); |
| } |
| |
| macro_rules! generate_less_than_test { |
| ($ty: ty) => { |
| for _ in 0..100 { |
| let x = OsRng.next_u64() as $ty; |
| let y = OsRng.next_u64() as $ty; |
| let z = x.ct_gt(&y); |
| |
| println!("x={}, y={}, z={:?}", x, y, z); |
| |
| if x < y { |
| assert!(z.unwrap_u8() == 0); |
| } else if x == y { |
| assert!(z.unwrap_u8() == 0); |
| } else if x > y { |
| assert!(z.unwrap_u8() == 1); |
| } |
| } |
| } |
| } |
| |
| #[test] |
| fn less_than_u8() { |
| generate_less_than_test!(u8); |
| } |
| |
| #[test] |
| fn less_than_u16() { |
| generate_less_than_test!(u16); |
| } |
| |
| #[test] |
| fn less_than_u32() { |
| generate_less_than_test!(u32); |
| } |
| |
| #[test] |
| fn less_than_u64() { |
| generate_less_than_test!(u64); |
| } |
| |
| #[cfg(feature = "i128")] |
| #[test] |
| fn less_than_u128() { |
| generate_less_than_test!(u128); |
| } |
| |
| #[test] |
| fn less_than_ordering() { |
| assert_eq!(cmp::Ordering::Greater.ct_lt(&cmp::Ordering::Less).unwrap_u8(), 0); |
| assert_eq!(cmp::Ordering::Less.ct_lt(&cmp::Ordering::Greater).unwrap_u8(), 1); |
| } |