1 | // Copyright 2019 The Marl Authors. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "marl/memory.h" |
16 | |
17 | #include "marl_test.h" |
18 | |
19 | class AllocatorTest : public testing::Test { |
20 | public: |
21 | marl::Allocator* allocator = marl::Allocator::Default; |
22 | }; |
23 | |
24 | TEST_F(AllocatorTest, AlignedAllocate) { |
25 | for (auto useGuards : {false, true}) { |
26 | for (auto alignment : {1, 2, 4, 8, 16, 32, 64, 128}) { |
27 | for (auto size : {1, 2, 3, 4, 5, 7, 8, 14, 16, 17, |
28 | 31, 34, 50, 63, 64, 65, 100, 127, 128, 129, |
29 | 200, 255, 256, 257, 500, 511, 512, 513}) { |
30 | marl::Allocation::Request request; |
31 | request.alignment = alignment; |
32 | request.size = size; |
33 | request.useGuards = useGuards; |
34 | |
35 | auto allocation = allocator->allocate(request); |
36 | auto ptr = allocation.ptr; |
37 | ASSERT_EQ(allocation.request.size, request.size); |
38 | ASSERT_EQ(allocation.request.alignment, request.alignment); |
39 | ASSERT_EQ(allocation.request.useGuards, request.useGuards); |
40 | ASSERT_EQ(allocation.request.usage, request.usage); |
41 | ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U); |
42 | memset(ptr, 0, |
43 | size); // Check the memory was actually allocated. |
44 | allocator->free(allocation); |
45 | } |
46 | } |
47 | } |
48 | } |
49 | |
50 | struct alignas(16) StructWith16ByteAlignment { |
51 | uint8_t i; |
52 | uint8_t padding[15]; |
53 | }; |
54 | struct alignas(32) StructWith32ByteAlignment { |
55 | uint8_t i; |
56 | uint8_t padding[31]; |
57 | }; |
58 | struct alignas(64) StructWith64ByteAlignment { |
59 | uint8_t i; |
60 | uint8_t padding[63]; |
61 | }; |
62 | |
63 | TEST_F(AllocatorTest, Create) { |
64 | auto s16 = allocator->create<StructWith16ByteAlignment>(); |
65 | auto s32 = allocator->create<StructWith32ByteAlignment>(); |
66 | auto s64 = allocator->create<StructWith64ByteAlignment>(); |
67 | ASSERT_EQ(alignof(StructWith16ByteAlignment), 16U); |
68 | ASSERT_EQ(alignof(StructWith32ByteAlignment), 32U); |
69 | ASSERT_EQ(alignof(StructWith64ByteAlignment), 64U); |
70 | ASSERT_EQ(reinterpret_cast<uintptr_t>(s16) & 15U, 0U); |
71 | ASSERT_EQ(reinterpret_cast<uintptr_t>(s32) & 31U, 0U); |
72 | ASSERT_EQ(reinterpret_cast<uintptr_t>(s64) & 63U, 0U); |
73 | allocator->destroy(s64); |
74 | allocator->destroy(s32); |
75 | allocator->destroy(s16); |
76 | } |
77 | |
78 | #if GTEST_HAS_DEATH_TEST |
79 | TEST_F(AllocatorTest, Guards) { |
80 | marl::Allocation::Request request; |
81 | request.alignment = 16; |
82 | request.size = 16; |
83 | request.useGuards = true; |
84 | auto alloc = allocator->allocate(request); |
85 | auto ptr = reinterpret_cast<uint8_t*>(alloc.ptr); |
86 | EXPECT_DEATH(ptr[-1] = 1, "" ); |
87 | EXPECT_DEATH(ptr[marl::pageSize()] = 1, "" ); |
88 | } |
89 | #endif |
90 | |