• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::*;
2 use std::cell::Cell;
3 
4 #[test]
allocator_param()5 fn allocator_param() {
6     use crate::alloc::AllocError;
7 
8     // Writing a test of integration between third-party
9     // allocators and `RawVec` is a little tricky because the `RawVec`
10     // API does not expose fallible allocation methods, so we
11     // cannot check what happens when allocator is exhausted
12     // (beyond detecting a panic).
13     //
14     // Instead, this just checks that the `RawVec` methods do at
15     // least go through the Allocator API when it reserves
16     // storage.
17 
18     // A dumb allocator that consumes a fixed amount of fuel
19     // before allocation attempts start failing.
20     struct BoundedAlloc {
21         fuel: Cell<usize>,
22     }
23     unsafe impl Allocator for BoundedAlloc {
24         fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
25             let size = layout.size();
26             if size > self.fuel.get() {
27                 return Err(AllocError);
28             }
29             match Global.allocate(layout) {
30                 ok @ Ok(_) => {
31                     self.fuel.set(self.fuel.get() - size);
32                     ok
33                 }
34                 err @ Err(_) => err,
35             }
36         }
37         unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
38             unsafe { Global.deallocate(ptr, layout) }
39         }
40     }
41 
42     let a = BoundedAlloc { fuel: Cell::new(500) };
43     let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
44     assert_eq!(v.alloc.fuel.get(), 450);
45     v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
46     assert_eq!(v.alloc.fuel.get(), 250);
47 }
48 
49 #[test]
reserve_does_not_overallocate()50 fn reserve_does_not_overallocate() {
51     {
52         let mut v: RawVec<u32> = RawVec::new();
53         // First, `reserve` allocates like `reserve_exact`.
54         v.reserve(0, 9);
55         assert_eq!(9, v.capacity());
56     }
57 
58     {
59         let mut v: RawVec<u32> = RawVec::new();
60         v.reserve(0, 7);
61         assert_eq!(7, v.capacity());
62         // 97 is more than double of 7, so `reserve` should work
63         // like `reserve_exact`.
64         v.reserve(7, 90);
65         assert_eq!(97, v.capacity());
66     }
67 
68     {
69         let mut v: RawVec<u32> = RawVec::new();
70         v.reserve(0, 12);
71         assert_eq!(12, v.capacity());
72         v.reserve(12, 3);
73         // 3 is less than half of 12, so `reserve` must grow
74         // exponentially. At the time of writing this test grow
75         // factor is 2, so new capacity is 24, however, grow factor
76         // of 1.5 is OK too. Hence `>= 18` in assert.
77         assert!(v.capacity() >= 12 + 12 / 2);
78     }
79 }
80 
81 struct ZST;
82 
83 // A `RawVec` holding zero-sized elements should always look like this.
zst_sanity<T>(v: &RawVec<T>)84 fn zst_sanity<T>(v: &RawVec<T>) {
85     assert_eq!(v.capacity(), usize::MAX);
86     assert_eq!(v.ptr(), core::ptr::Unique::<T>::dangling().as_ptr());
87     assert_eq!(v.current_memory(), None);
88 }
89 
90 #[test]
zst()91 fn zst() {
92     let cap_err = Err(crate::collections::TryReserveErrorKind::CapacityOverflow.into());
93 
94     assert_eq!(std::mem::size_of::<ZST>(), 0);
95 
96     // All these different ways of creating the RawVec produce the same thing.
97 
98     let v: RawVec<ZST> = RawVec::new();
99     zst_sanity(&v);
100 
101     let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
102     zst_sanity(&v);
103 
104     let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
105     zst_sanity(&v);
106 
107     let v: RawVec<ZST> = RawVec::allocate_in(0, AllocInit::Uninitialized, Global);
108     zst_sanity(&v);
109 
110     let v: RawVec<ZST> = RawVec::allocate_in(100, AllocInit::Uninitialized, Global);
111     zst_sanity(&v);
112 
113     let mut v: RawVec<ZST> = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global);
114     zst_sanity(&v);
115 
116     // Check all these operations work as expected with zero-sized elements.
117 
118     assert!(!v.needs_to_grow(100, usize::MAX - 100));
119     assert!(v.needs_to_grow(101, usize::MAX - 100));
120     zst_sanity(&v);
121 
122     v.reserve(100, usize::MAX - 100);
123     //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below
124     zst_sanity(&v);
125 
126     v.reserve_exact(100, usize::MAX - 100);
127     //v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below
128     zst_sanity(&v);
129 
130     assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(()));
131     assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err);
132     zst_sanity(&v);
133 
134     assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(()));
135     assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err);
136     zst_sanity(&v);
137 
138     assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err);
139     assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err);
140     zst_sanity(&v);
141 
142     assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err);
143     assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err);
144     zst_sanity(&v);
145 }
146 
147 #[test]
148 #[should_panic(expected = "capacity overflow")]
zst_reserve_panic()149 fn zst_reserve_panic() {
150     let mut v: RawVec<ZST> = RawVec::new();
151     zst_sanity(&v);
152 
153     v.reserve(101, usize::MAX - 100);
154 }
155 
156 #[test]
157 #[should_panic(expected = "capacity overflow")]
zst_reserve_exact_panic()158 fn zst_reserve_exact_panic() {
159     let mut v: RawVec<ZST> = RawVec::new();
160     zst_sanity(&v);
161 
162     v.reserve_exact(101, usize::MAX - 100);
163 }
164