| 1 | //! Test using `Bytes` with an allocator that hands out "odd" pointers for |
| 2 | //! vectors (pointers where the LSB is set). |
| 3 | |
| 4 | #![cfg (not(miri))] // Miri does not support custom allocators (also, Miri is "odd" by default with 50% chance) |
| 5 | |
| 6 | use std::alloc::{GlobalAlloc, Layout, System}; |
| 7 | use std::ptr; |
| 8 | |
| 9 | use bytes::Bytes; |
| 10 | |
| 11 | #[global_allocator] |
| 12 | static ODD: Odd = Odd; |
| 13 | |
| 14 | struct Odd; |
| 15 | |
| 16 | unsafe impl GlobalAlloc for Odd { |
| 17 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { |
| 18 | if layout.align() == 1 && layout.size() > 0 { |
| 19 | // Allocate slightly bigger so that we can offset the pointer by 1 |
| 20 | let size = layout.size() + 1; |
| 21 | let new_layout = match Layout::from_size_align(size, 1) { |
| 22 | Ok(layout) => layout, |
| 23 | Err(_err) => return ptr::null_mut(), |
| 24 | }; |
| 25 | let ptr = System.alloc(new_layout); |
| 26 | if !ptr.is_null() { |
| 27 | ptr.offset(1) |
| 28 | } else { |
| 29 | ptr |
| 30 | } |
| 31 | } else { |
| 32 | System.alloc(layout) |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { |
| 37 | if layout.align() == 1 && layout.size() > 0 { |
| 38 | let size = layout.size() + 1; |
| 39 | let new_layout = match Layout::from_size_align(size, 1) { |
| 40 | Ok(layout) => layout, |
| 41 | Err(_err) => std::process::abort(), |
| 42 | }; |
| 43 | System.dealloc(ptr.offset(-1), new_layout); |
| 44 | } else { |
| 45 | System.dealloc(ptr, layout); |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | #[test] |
| 51 | fn sanity_check_odd_allocator() { |
| 52 | let vec = vec![33u8; 1024]; |
| 53 | let p = vec.as_ptr() as usize; |
| 54 | assert!(p & 0x1 == 0x1, "{:#b}" , p); |
| 55 | } |
| 56 | |
| 57 | #[test] |
| 58 | fn test_bytes_from_vec_drop() { |
| 59 | let vec = vec![33u8; 1024]; |
| 60 | let _b = Bytes::from(vec); |
| 61 | } |
| 62 | |
| 63 | #[test] |
| 64 | fn test_bytes_clone_drop() { |
| 65 | let vec = vec![33u8; 1024]; |
| 66 | let b1 = Bytes::from(vec); |
| 67 | let _b2 = b1.clone(); |
| 68 | } |
| 69 | |
| 70 | #[test] |
| 71 | fn test_bytes_into_vec() { |
| 72 | let vec = vec![33u8; 1024]; |
| 73 | |
| 74 | // Test cases where kind == KIND_VEC |
| 75 | let b1 = Bytes::from(vec.clone()); |
| 76 | assert_eq!(Vec::from(b1), vec); |
| 77 | |
| 78 | // Test cases where kind == KIND_ARC, ref_cnt == 1 |
| 79 | let b1 = Bytes::from(vec.clone()); |
| 80 | drop(b1.clone()); |
| 81 | assert_eq!(Vec::from(b1), vec); |
| 82 | |
| 83 | // Test cases where kind == KIND_ARC, ref_cnt == 2 |
| 84 | let b1 = Bytes::from(vec.clone()); |
| 85 | let b2 = b1.clone(); |
| 86 | assert_eq!(Vec::from(b1), vec); |
| 87 | |
| 88 | // Test cases where vtable = SHARED_VTABLE, kind == KIND_ARC, ref_cnt == 1 |
| 89 | assert_eq!(Vec::from(b2), vec); |
| 90 | |
| 91 | // Test cases where offset != 0 |
| 92 | let mut b1 = Bytes::from(vec.clone()); |
| 93 | let b2 = b1.split_off(20); |
| 94 | |
| 95 | assert_eq!(Vec::from(b2), vec[20..]); |
| 96 | assert_eq!(Vec::from(b1), vec[..20]); |
| 97 | } |
| 98 | |