diff options
Diffstat (limited to 'vendor/bytes/tests/test_buf.rs')
| -rw-r--r-- | vendor/bytes/tests/test_buf.rs | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/vendor/bytes/tests/test_buf.rs b/vendor/bytes/tests/test_buf.rs new file mode 100644 index 00000000..099016e2 --- /dev/null +++ b/vendor/bytes/tests/test_buf.rs @@ -0,0 +1,439 @@ +#![warn(rust_2018_idioms)] + +use ::bytes::{Buf, Bytes, BytesMut}; +use core::{cmp, mem}; +use std::collections::VecDeque; +#[cfg(feature = "std")] +use std::io::IoSlice; + +// A random 64-byte ascii string, with the first 8 bytes altered to +// give valid representations of f32 and f64 (making them easier to compare) +// and negative signed numbers when interpreting as big endian +// (testing Sign Extension for `Buf::get_int' and `Buf::get_int_ne`). +const INPUT: &[u8] = b"\xffFqrjrDqPhvTc45vvq33f6bJrUtyHESuTeklWKgYd64xgzxJwvAkpYYnpNJyZSRn"; + +macro_rules! e { + ($big_endian_val:expr, $little_endian_val:expr) => { + if cfg!(target_endian = "big") { + $big_endian_val + } else { + $little_endian_val + } + }; +} + +macro_rules! buf_tests { + ($make_input:ident) => { + buf_tests!($make_input, true); + }; + ($make_input:ident, $checks_vectored_is_complete:expr) => { + use super::*; + + #[test] + fn empty_state() { + let buf = $make_input(&[]); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert!(buf.chunk().is_empty()); + } + + #[test] + fn fresh_state() { + let buf = $make_input(INPUT); + assert_eq!(buf.remaining(), 64); + assert!(buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64); + assert!(INPUT.starts_with(chunk)); + } + + #[test] + fn advance() { + let mut buf = $make_input(INPUT); + buf.advance(8); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } + + #[test] + fn advance_to_end() { + let mut buf = $make_input(INPUT); + buf.advance(64); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + + let chunk = buf.chunk(); + assert!(chunk.is_empty()); + } + + #[test] + #[should_panic] + fn advance_past_end() { + let mut buf = $make_input(INPUT); + buf.advance(65); + } + + #[test] + #[cfg(feature = "std")] + fn chunks_vectored_empty() { + let buf = $make_input(&[]); + let mut bufs = [IoSlice::new(&[]); 16]; + + let n = buf.chunks_vectored(&mut bufs); + assert_eq!(n, 0); + assert!(bufs.iter().all(|buf| buf.is_empty())); + } + + #[test] + #[cfg(feature = "std")] + fn chunks_vectored_is_complete() { + let buf = $make_input(INPUT); + let mut bufs = [IoSlice::new(&[]); 16]; + + let n = buf.chunks_vectored(&mut bufs); + assert!(n > 0); + assert!(n <= 16); + + let bufs_concat = bufs[..n] + .iter() + .flat_map(|b| b.iter().copied()) + .collect::<Vec<u8>>(); + if $checks_vectored_is_complete { + assert_eq!(bufs_concat, INPUT); + } else { + // If this panics then `buf` implements `chunks_vectored`. + // Remove the `false` argument from `buf_tests!` for that type. + assert!(bufs_concat.len() < INPUT.len()); + assert!(INPUT.starts_with(&bufs_concat)); + } + + for i in n..16 { + assert!(bufs[i].is_empty()); + } + } + + #[test] + fn copy_to_slice() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 8]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..8]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } + + #[test] + fn copy_to_slice_big() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 56]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 64 - 56); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..56]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 56); + assert!(INPUT[56..].starts_with(chunk)); + } + + #[test] + fn copy_to_slice_to_end() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 64]; + buf.copy_to_slice(&mut chunk); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert_eq!(chunk, INPUT); + + assert!(buf.chunk().is_empty()); + } + + #[test] + #[should_panic] + fn copy_to_slice_overflow() { + let mut buf = $make_input(INPUT); + + let mut chunk = [0u8; 65]; + buf.copy_to_slice(&mut chunk); + } + + #[test] + fn copy_to_bytes() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(8); + assert_eq!(buf.remaining(), 64 - 8); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..8]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 8); + assert!(INPUT[8..].starts_with(chunk)); + } + + #[test] + fn copy_to_bytes_big() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(56); + assert_eq!(buf.remaining(), 64 - 56); + assert!(buf.has_remaining()); + assert_eq!(chunk, INPUT[..56]); + + let chunk = buf.chunk(); + assert!(chunk.len() <= 64 - 56); + assert!(INPUT[56..].starts_with(chunk)); + } + + #[test] + fn copy_to_bytes_to_end() { + let mut buf = $make_input(INPUT); + + let chunk = buf.copy_to_bytes(64); + assert_eq!(buf.remaining(), 0); + assert!(!buf.has_remaining()); + assert_eq!(chunk, INPUT); + + assert!(buf.chunk().is_empty()); + } + + #[test] + #[should_panic] + fn copy_to_bytes_overflow() { + let mut buf = $make_input(INPUT); + + let _ = buf.copy_to_bytes(65); + } + + buf_tests!(number $make_input, get_u8, get_u8_overflow, u8, get_u8, 0xff); + buf_tests!(number $make_input, get_i8, get_i8_overflow, i8, get_i8, 0xffu8 as i8); + buf_tests!(number $make_input, get_u16_be, get_u16_be_overflow, u16, get_u16, 0xff46); + buf_tests!(number $make_input, get_u16_le, get_u16_le_overflow, u16, get_u16_le, 0x46ff); + buf_tests!(number $make_input, get_u16_ne, get_u16_ne_overflow, u16, get_u16_ne, e!(0xff46, 0x46ff)); + buf_tests!(number $make_input, get_i16_be, get_i16_be_overflow, i16, get_i16, 0xff46u16 as i16); + buf_tests!(number $make_input, get_i16_le, get_i16_le_overflow, i16, get_i16_le, 0x46ff); + buf_tests!(number $make_input, get_i16_ne, get_i16_ne_overflow, i16, get_i16_ne, e!(0xff46u16 as i16, 0x46ff)); + buf_tests!(number $make_input, get_u32_be, get_u32_be_overflow, u32, get_u32, 0xff467172); + buf_tests!(number $make_input, get_u32_le, get_u32_le_overflow, u32, get_u32_le, 0x727146ff); + buf_tests!(number $make_input, get_u32_ne, get_u32_ne_overflow, u32, get_u32_ne, e!(0xff467172, 0x727146ff)); + buf_tests!(number $make_input, get_i32_be, get_i32_be_overflow, i32, get_i32, 0xff467172u32 as i32); + buf_tests!(number $make_input, get_i32_le, get_i32_le_overflow, i32, get_i32_le, 0x727146ff); + buf_tests!(number $make_input, get_i32_ne, get_i32_ne_overflow, i32, get_i32_ne, e!(0xff467172u32 as i32, 0x727146ff)); + buf_tests!(number $make_input, get_u64_be, get_u64_be_overflow, u64, get_u64, 0xff4671726a724471); + buf_tests!(number $make_input, get_u64_le, get_u64_le_overflow, u64, get_u64_le, 0x7144726a727146ff); + buf_tests!(number $make_input, get_u64_ne, get_u64_ne_overflow, u64, get_u64_ne, e!(0xff4671726a724471, 0x7144726a727146ff)); + buf_tests!(number $make_input, get_i64_be, get_i64_be_overflow, i64, get_i64, 0xff4671726a724471u64 as i64); + buf_tests!(number $make_input, get_i64_le, get_i64_le_overflow, i64, get_i64_le, 0x7144726a727146ff); + buf_tests!(number $make_input, get_i64_ne, get_i64_ne_overflow, i64, get_i64_ne, e!(0xff4671726a724471u64 as i64, 0x7144726a727146ff)); + buf_tests!(number $make_input, get_u128_be, get_u128_be_overflow, u128, get_u128, 0xff4671726a7244715068765463343576); + buf_tests!(number $make_input, get_u128_le, get_u128_le_overflow, u128, get_u128_le, 0x76353463547668507144726a727146ff); + buf_tests!(number $make_input, get_u128_ne, get_u128_ne_overflow, u128, get_u128_ne, e!(0xff4671726a7244715068765463343576, 0x76353463547668507144726a727146ff)); + buf_tests!(number $make_input, get_i128_be, get_i128_be_overflow, i128, get_i128, 0xff4671726a7244715068765463343576u128 as i128); + buf_tests!(number $make_input, get_i128_le, get_i128_le_overflow, i128, get_i128_le, 0x76353463547668507144726a727146ff); + buf_tests!(number $make_input, get_i128_ne, get_i128_ne_overflow, i128, get_i128_ne, e!(0xff4671726a7244715068765463343576u128 as i128, 0x76353463547668507144726a727146ff)); + buf_tests!(number $make_input, get_f32_be, get_f32_be_overflow, f32, get_f32, f32::from_bits(0xff467172)); + buf_tests!(number $make_input, get_f32_le, get_f32_le_overflow, f32, get_f32_le, f32::from_bits(0x727146ff)); + buf_tests!(number $make_input, get_f32_ne, get_f32_ne_overflow, f32, get_f32_ne, f32::from_bits(e!(0xff467172, 0x727146ff))); + buf_tests!(number $make_input, get_f64_be, get_f64_be_overflow, f64, get_f64, f64::from_bits(0xff4671726a724471)); + buf_tests!(number $make_input, get_f64_le, get_f64_le_overflow, f64, get_f64_le, f64::from_bits(0x7144726a727146ff)); + buf_tests!(number $make_input, get_f64_ne, get_f64_ne_overflow, f64, get_f64_ne, f64::from_bits(e!(0xff4671726a724471, 0x7144726a727146ff))); + + buf_tests!(var_number $make_input, get_uint_be, get_uint_be_overflow, u64, get_uint, 3, 0xff4671); + buf_tests!(var_number $make_input, get_uint_le, get_uint_le_overflow, u64, get_uint_le, 3, 0x7146ff); + buf_tests!(var_number $make_input, get_uint_ne, get_uint_ne_overflow, u64, get_uint_ne, 3, e!(0xff4671, 0x7146ff)); + buf_tests!(var_number $make_input, get_int_be, get_int_be_overflow, i64, get_int, 3, 0xffffffffffff4671u64 as i64); + buf_tests!(var_number $make_input, get_int_le, get_int_le_overflow, i64, get_int_le, 3, 0x7146ff); + buf_tests!(var_number $make_input, get_int_ne, get_int_ne_overflow, i64, get_int_ne, 3, e!(0xffffffffffff4671u64 as i64, 0x7146ff)); + }; + (number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $value:expr) => { + #[test] + fn $ok_name() { + let mut buf = $make_input(INPUT); + + let value = buf.$method(); + assert_eq!(buf.remaining(), 64 - mem::size_of::<$number>()); + assert!(buf.has_remaining()); + assert_eq!(value, $value); + } + + #[test] + #[should_panic] + fn $panic_name() { + let mut buf = $make_input(&[]); + + let _ = buf.$method(); + } + }; + (var_number $make_input:ident, $ok_name:ident, $panic_name:ident, $number:ty, $method:ident, $len:expr, $value:expr) => { + #[test] + fn $ok_name() { + let mut buf = $make_input(INPUT); + + let value = buf.$method($len); + assert_eq!(buf.remaining(), 64 - $len); + assert!(buf.has_remaining()); + assert_eq!(value, $value); + } + + #[test] + #[should_panic] + fn $panic_name() { + let mut buf = $make_input(&[]); + + let _ = buf.$method($len); + } + }; +} + +mod u8_slice { + fn make_input(buf: &'static [u8]) -> &'static [u8] { + buf + } + + buf_tests!(make_input); +} + +mod bytes { + fn make_input(buf: &'static [u8]) -> impl Buf { + Bytes::from_static(buf) + } + + buf_tests!(make_input); +} + +mod bytes_mut { + fn make_input(buf: &'static [u8]) -> impl Buf { + BytesMut::from(buf) + } + + buf_tests!(make_input); +} + +mod vec_deque { + fn make_input(buf: &'static [u8]) -> impl Buf { + let mut deque = VecDeque::new(); + + if !buf.is_empty() { + // Construct |b|some bytes|a| `VecDeque` + let mid = buf.len() / 2; + let (a, b) = buf.split_at(mid); + + deque.reserve_exact(buf.len() + 1); + + let extra_space = deque.capacity() - b.len() - 1; + deque.resize(extra_space, 0); + + deque.extend(a); + deque.drain(..extra_space); + deque.extend(b); + + let (a, b) = deque.as_slices(); + assert!( + !a.is_empty(), + "could not setup test - attempt to create discontiguous VecDeque failed" + ); + assert!( + !b.is_empty(), + "could not setup test - attempt to create discontiguous VecDeque failed" + ); + } + + deque + } + + buf_tests!(make_input, true); +} + +#[cfg(feature = "std")] +mod cursor { + use std::io::Cursor; + + fn make_input(buf: &'static [u8]) -> impl Buf { + Cursor::new(buf) + } + + buf_tests!(make_input); +} + +mod box_bytes { + fn make_input(buf: &'static [u8]) -> impl Buf { + Box::new(Bytes::from_static(buf)) + } + + buf_tests!(make_input); +} + +mod chain_u8_slice { + fn make_input(buf: &'static [u8]) -> impl Buf { + let (a, b) = buf.split_at(buf.len() / 2); + Buf::chain(a, b) + } + + buf_tests!(make_input); +} + +mod chain_small_big_u8_slice { + fn make_input(buf: &'static [u8]) -> impl Buf { + let mid = cmp::min(1, buf.len()); + let (a, b) = buf.split_at(mid); + Buf::chain(a, b) + } + + buf_tests!(make_input); +} + +mod chain_limited_slices { + fn make_input(buf: &'static [u8]) -> impl Buf { + let buf3 = &buf[cmp::min(buf.len(), 3)..]; + let a = Buf::take(buf3, 0); + let b = Buf::take(buf, 3); + let c = Buf::take(buf3, usize::MAX); + let d = buf; + Buf::take(Buf::chain(Buf::chain(a, b), Buf::chain(c, d)), buf.len()) + } + + buf_tests!(make_input, true); +} + +#[allow(unused_allocation)] // This is intentional. +#[test] +fn test_deref_buf_forwards() { + struct Special; + + impl Buf for Special { + fn remaining(&self) -> usize { + unreachable!("remaining"); + } + + fn chunk(&self) -> &[u8] { + unreachable!("chunk"); + } + + fn advance(&mut self, _: usize) { + unreachable!("advance"); + } + + fn get_u8(&mut self) -> u8 { + // specialized! + b'x' + } + } + + // these should all use the specialized method + assert_eq!(Special.get_u8(), b'x'); + assert_eq!((&mut Special as &mut dyn Buf).get_u8(), b'x'); + assert_eq!((Box::new(Special) as Box<dyn Buf>).get_u8(), b'x'); + assert_eq!(Box::new(Special).get_u8(), b'x'); +} |
