aboutsummaryrefslogtreecommitdiff
path: root/tests/test_bytes_odd_alloc.rs
diff options
context:
space:
mode:
authorGravatar Sean McArthur <sean@seanmonstar.com> 2019-12-17 13:23:15 -0800
committerGravatar GitHub <noreply@github.com> 2019-12-17 13:23:15 -0800
commitc7cf71618071933eac2c18471427d30e6a630af5 (patch)
treeeb467f28b5bc5b60c427cea7675d08d487301969 /tests/test_bytes_odd_alloc.rs
parent8ae3bb2104fda9a02d55ac5635974ca1b5a49ebb (diff)
downloadbytes-c7cf71618071933eac2c18471427d30e6a630af5.tar.gz
bytes-c7cf71618071933eac2c18471427d30e6a630af5.tar.zst
bytes-c7cf71618071933eac2c18471427d30e6a630af5.zip
Fix Bytes when Vec pointer's LSB is set (#346)
This separates the `SharedVtable` into 3: - `PromotableEvenVtable`: The original `SharedVtable`, which will promote the `Vec` to `Shared` on the first clone, and is selected when the `Vec`'s pointer has the LSB unset. - `PromotableOddVtable`: Similar to the `PromotableEvenVtable`, but selected when the `Vec`'s pointer has the LSB set. This vtable differs in the masking used when reconstructing the `Vec`. - `SharedVtable`: This no longer checks if its current kind is `VEC` or `ARC`, and is only created by the "promotable" vtables. This also adds a test using an "odd" global allocator that purposefully bumps all pointers with alignment of 1. Closes #343
Diffstat (limited to 'tests/test_bytes_odd_alloc.rs')
-rw-r--r--tests/test_bytes_odd_alloc.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/tests/test_bytes_odd_alloc.rs b/tests/test_bytes_odd_alloc.rs
new file mode 100644
index 0000000..01e51ea
--- /dev/null
+++ b/tests/test_bytes_odd_alloc.rs
@@ -0,0 +1,67 @@
+//! Test using `Bytes` with an allocator that hands out "odd" pointers for
+//! vectors (pointers where the LSB is set).
+
+use std::alloc::{GlobalAlloc, Layout, System};
+use std::ptr;
+
+use bytes::Bytes;
+
+#[global_allocator]
+static ODD: Odd = Odd;
+
+struct Odd;
+
+unsafe impl GlobalAlloc for Odd {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ if layout.align() == 1 && layout.size() > 0 {
+ // Allocate slightly bigger so that we can offset the pointer by 1
+ let size = layout.size() + 1;
+ let new_layout = match Layout::from_size_align(size, 1) {
+ Ok(layout) => layout,
+ Err(_err) => return ptr::null_mut(),
+ };
+ let ptr = System.alloc(new_layout);
+ if !ptr.is_null() {
+ let ptr = ptr.offset(1);
+ ptr
+ } else {
+ ptr
+ }
+ } else {
+ System.alloc(layout)
+ }
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ if layout.align() == 1 && layout.size() > 0 {
+ let size = layout.size() + 1;
+ let new_layout = match Layout::from_size_align(size, 1) {
+ Ok(layout) => layout,
+ Err(_err) => std::process::abort(),
+ };
+ System.dealloc(ptr.offset(-1), new_layout);
+ } else {
+ System.alloc(layout);
+ }
+ }
+}
+
+#[test]
+fn sanity_check_odd_allocator() {
+ let vec = vec![33u8; 1024];
+ let p = vec.as_ptr() as usize;
+ assert!(p & 0x1 == 0x1, "{:#b}", p);
+}
+
+#[test]
+fn test_bytes_from_vec_drop() {
+ let vec = vec![33u8; 1024];
+ let _b = Bytes::from(vec);
+}
+
+#[test]
+fn test_bytes_clone_drop() {
+ let vec = vec![33u8; 1024];
+ let b1 = Bytes::from(vec);
+ let _b2 = b1.clone();
+}