• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
alloc(&self, layout: Layout) -> *mut u817     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 
dealloc(&self, ptr: *mut u8, layout: Layout)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]
sanity_check_odd_allocator()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]
test_bytes_from_vec_drop()58 fn test_bytes_from_vec_drop() {
59     let vec = vec![33u8; 1024];
60     let _b = Bytes::from(vec);
61 }
62 
63 #[test]
test_bytes_clone_drop()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]
test_bytes_into_vec()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