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 | |