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 ] = [0 u8; 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 = 1 u32.ct_lt(&(2 u32.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 );
}
Messung V0.5 in Prozent C=81 H=97 G=89
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland