blob: df3344e2df346ad317d335a8ed0fc612057dabab [file] [log] [blame] [edit]
//! These tests are not run automatically right now. Please run these tests manually by copying them
//! to a separate project when modifying any related code.
use super::alloc::*;
use super::time::system_time_internal::{from_uefi, to_uefi};
use crate::io::{IoSlice, IoSliceMut};
use crate::time::Duration;
const SECS_IN_MINUTE: u64 = 60;
const MAX_UEFI_TIME: Duration = from_uefi(r_efi::efi::Time {
year: 9999,
month: 12,
day: 31,
hour: 23,
minute: 59,
second: 59,
nanosecond: 999_999_999,
timezone: 1440,
daylight: 0,
pad1: 0,
pad2: 0,
});
#[test]
fn align() {
// UEFI ABI specifies that allocation alignment minimum is always 8. So this can be
// statically verified.
assert_eq!(POOL_ALIGNMENT, 8);
// Loop over allocation-request sizes from 0-256 and alignments from 1-128, and verify
// that in case of overalignment there is at least space for one additional pointer to
// store in the allocation.
for i in 0..256 {
for j in &[1, 2, 4, 8, 16, 32, 64, 128] {
if *j <= 8 {
assert_eq!(align_size(i, *j), i);
} else {
assert!(align_size(i, *j) > i + size_of::<*mut ()>());
}
}
}
}
// UEFI Time cannot implement Eq due to uninitilaized pad1 and pad2
fn uefi_time_cmp(t1: r_efi::efi::Time, t2: r_efi::efi::Time) -> bool {
t1.year == t2.year
&& t1.month == t2.month
&& t1.day == t2.day
&& t1.hour == t2.hour
&& t1.minute == t2.minute
&& t1.second == t2.second
&& t1.nanosecond == t2.nanosecond
&& t1.timezone == t2.timezone
&& t1.daylight == t2.daylight
}
#[test]
fn systemtime_start() {
let t = r_efi::efi::Time {
year: 1900,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
pad1: 0,
nanosecond: 0,
timezone: -1440,
daylight: 0,
pad2: 0,
};
assert_eq!(from_uefi(&t), Duration::new(0, 0));
assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t), -1440, 0).unwrap()));
assert!(to_uefi(&from_uefi(&t), 0, 0).is_err());
}
#[test]
fn systemtime_utc_start() {
let t = r_efi::efi::Time {
year: 1900,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
pad1: 0,
nanosecond: 0,
timezone: 0,
daylight: 0,
pad2: 0,
};
assert_eq!(from_uefi(&t), Duration::new(1440 * SECS_IN_MINUTE, 0));
assert!(uefi_time_cmp(t, to_uefi(&from_uefi(&t), 0, 0).unwrap()));
assert!(to_uefi(&from_uefi(&t), -1440, 0).is_ok());
}
#[test]
fn systemtime_end() {
let t = r_efi::efi::Time {
year: 9999,
month: 12,
day: 31,
hour: 23,
minute: 59,
second: 59,
pad1: 0,
nanosecond: 0,
timezone: 1440,
daylight: 0,
pad2: 0,
};
assert!(to_uefi(&from_uefi(&t), 1440, 0).is_ok());
assert!(to_uefi(&from_uefi(&t), 1439, 0).is_err());
}
#[test]
fn min_time() {
let inp = Duration::from_secs(1440 * SECS_IN_MINUTE);
let new_tz = to_uefi(&inp, 1440, 0).err().unwrap();
assert_eq!(new_tz, 0);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
let inp = Duration::from_secs(1450 * SECS_IN_MINUTE);
let new_tz = to_uefi(&inp, 1440, 0).err().unwrap();
assert_eq!(new_tz, 10);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
let inp = Duration::from_secs(1450 * SECS_IN_MINUTE + 10);
let new_tz = to_uefi(&inp, 1440, 0).err().unwrap();
assert_eq!(new_tz, 10);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
let inp = Duration::from_secs(1430 * SECS_IN_MINUTE);
let new_tz = to_uefi(&inp, 1440, 0).err().unwrap();
assert_eq!(new_tz, -10);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
}
#[test]
fn max_time() {
let inp = MAX_UEFI_TIME.0;
let new_tz = to_uefi(&inp, -1440, 0).err().unwrap();
assert_eq!(new_tz, 1440);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
let inp = MAX_UEFI_TIME.0 - Duration::from_secs(1440 * SECS_IN_MINUTE);
let new_tz = to_uefi(&inp, -1440, 0).err().unwrap();
assert_eq!(new_tz, 0);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
let inp = MAX_UEFI_TIME.0 - Duration::from_secs(1440 * SECS_IN_MINUTE + 10);
let new_tz = to_uefi(&inp, -1440, 0).err().unwrap();
assert_eq!(new_tz, 0);
assert!(to_uefi(&inp, new_tz, 0).is_ok());
}
// UEFI IoSlice and IoSliceMut Tests
//
// Strictly speaking, vectored read/write types for UDP4, UDP6, TCP4, TCP6 are defined
// separately in the UEFI Spec. However, they have the same signature. These tests just ensure
// that `IoSlice` and `IoSliceMut` are compatible with the vectored types for all the
// networking protocols.
unsafe fn to_slice<T>(val: &T) -> &[u8] {
let len = size_of_val(val);
unsafe { crate::slice::from_raw_parts(crate::ptr::from_ref(val).cast(), len) }
}
#[test]
fn io_slice_single() {
let mut data = [0, 1, 2, 3, 4];
let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let tcp6_frag = r_efi::protocols::tcp6::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let udp4_frag = r_efi::protocols::udp4::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let udp6_frag = r_efi::protocols::udp6::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let io_slice = IoSlice::new(&data);
unsafe {
assert_eq!(to_slice(&io_slice), to_slice(&tcp4_frag));
assert_eq!(to_slice(&io_slice), to_slice(&tcp6_frag));
assert_eq!(to_slice(&io_slice), to_slice(&udp4_frag));
assert_eq!(to_slice(&io_slice), to_slice(&udp6_frag));
}
}
#[test]
fn io_slice_mut_single() {
let mut data = [0, 1, 2, 3, 4];
let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let tcp6_frag = r_efi::protocols::tcp6::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let udp4_frag = r_efi::protocols::udp4::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let udp6_frag = r_efi::protocols::udp6::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let io_slice_mut = IoSliceMut::new(&mut data);
unsafe {
assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp4_frag));
assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp6_frag));
assert_eq!(to_slice(&io_slice_mut), to_slice(&udp4_frag));
assert_eq!(to_slice(&io_slice_mut), to_slice(&udp6_frag));
}
}
#[test]
fn io_slice_multi() {
let mut data = [0, 1, 2, 3, 4];
let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
fragment_length: data.len().try_into().unwrap(),
fragment_buffer: data.as_mut_ptr().cast(),
};
let rhs =
[tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag];
let lhs = [
IoSlice::new(&data),
IoSlice::new(&data),
IoSlice::new(&data),
IoSlice::new(&data),
IoSlice::new(&data),
];
unsafe {
assert_eq!(to_slice(&lhs), to_slice(&rhs));
}
}
#[test]
fn io_slice_basic() {
let data = [0, 1, 2, 3, 4];
let mut io_slice = IoSlice::new(&data);
assert_eq!(data, io_slice.as_slice());
io_slice.advance(2);
assert_eq!(&data[2..], io_slice.as_slice());
}
#[test]
fn io_slice_mut_basic() {
let data = [0, 1, 2, 3, 4];
let mut data_clone = [0, 1, 2, 3, 4];
let mut io_slice_mut = IoSliceMut::new(&mut data_clone);
assert_eq!(data, io_slice_mut.as_slice());
assert_eq!(data, io_slice_mut.as_mut_slice());
io_slice_mut.advance(2);
assert_eq!(&data[2..], io_slice_mut.into_slice());
}