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
6use std::alloc::{GlobalAlloc, Layout, System};
7use std::ptr;
8
9use bytes::Bytes;
10
11#[global_allocator]
12static ODD: Odd = Odd;
13
14struct Odd;
15
16unsafe 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]
51fn 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]
58fn test_bytes_from_vec_drop() {
59 let vec = vec![33u8; 1024];
60 let _b = Bytes::from(vec);
61}
62
63#[test]
64fn 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]
71fn 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