about summary refs log tree commit diff
path: root/src/liballoc/raw_vec/tests.rs
blob: 860058debe1fda3588b6eb92e9fe141e7d9eafce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use super::*;

#[test]
fn allocator_param() {
    use crate::alloc::AllocErr;

    // Writing a test of integration between third-party
    // allocators and `RawVec` is a little tricky because the `RawVec`
    // API does not expose fallible allocation methods, so we
    // cannot check what happens when allocator is exhausted
    // (beyond detecting a panic).
    //
    // Instead, this just checks that the `RawVec` methods do at
    // least go through the Allocator API when it reserves
    // storage.

    // A dumb allocator that consumes a fixed amount of fuel
    // before allocation attempts start failing.
    struct BoundedAlloc {
        fuel: usize,
    }
    unsafe impl AllocRef for BoundedAlloc {
        unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
            let size = layout.size();
            if size > self.fuel {
                return Err(AllocErr);
            }
            match Global.alloc(layout) {
                ok @ Ok(_) => {
                    self.fuel -= size;
                    ok
                }
                err @ Err(_) => err,
            }
        }
        unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
            Global.dealloc(ptr, layout)
        }
    }

    let a = BoundedAlloc { fuel: 500 };
    let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
    assert_eq!(v.a.fuel, 450);
    v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
    assert_eq!(v.a.fuel, 250);
}

#[test]
fn reserve_does_not_overallocate() {
    {
        let mut v: RawVec<u32> = RawVec::new();
        // First, `reserve` allocates like `reserve_exact`.
        v.reserve(0, 9);
        assert_eq!(9, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 7);
        assert_eq!(7, v.capacity());
        // 97 if more than double of 7, so `reserve` should work
        // like `reserve_exact`.
        v.reserve(7, 90);
        assert_eq!(97, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 12);
        assert_eq!(12, v.capacity());
        v.reserve(12, 3);
        // 3 is less than half of 12, so `reserve` must grow
        // exponentially. At the time of writing this test grow
        // factor is 2, so new capacity is 24, however, grow factor
        // of 1.5 is OK too. Hence `>= 18` in assert.
        assert!(v.capacity() >= 12 + 12 / 2);
    }
}