blob: 21cb27eaf0ef2b117f79244a3bd90fff14040bb8 [file] [log] [blame]
Andrew Kaylorbbf628b2012-09-19 20:46:12 +00001//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/Memory.h"
11#include "llvm/Support/Process.h"
12
13#include "gtest/gtest.h"
14#include <cstdlib>
15
16using namespace llvm;
17using namespace sys;
18
19namespace {
20
21class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
22public:
23 MappedMemoryTest() {
24 Flags = GetParam();
25 PageSize = sys::Process::GetPageSize();
26 }
27
28protected:
29 // Adds RW flags to permit testing of the resulting memory
30 unsigned getTestableEquivalent(unsigned RequestedFlags) {
31 switch (RequestedFlags) {
32 case Memory::MF_READ:
33 case Memory::MF_WRITE:
34 case Memory::MF_READ|Memory::MF_WRITE:
35 return Memory::MF_READ|Memory::MF_WRITE;
36 case Memory::MF_READ|Memory::MF_EXEC:
37 case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
38 case Memory::MF_EXEC:
39 return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
40 }
41 // Default in case values are added to the enum, as required by some compilers
42 return Memory::MF_READ|Memory::MF_WRITE;
43 }
44
45 // Returns true if the memory blocks overlap
46 bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
47 if (M1.base() == M2.base())
48 return true;
49
50 if (M1.base() > M2.base())
51 return (unsigned char *)M2.base() + M2.size() > M1.base();
52
53 return (unsigned char *)M1.base() + M1.size() > M2.base();
54 }
55
56 unsigned Flags;
57 size_t PageSize;
58};
59
60TEST_P(MappedMemoryTest, AllocAndRelease) {
61 error_code EC;
62 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
63 EXPECT_EQ(error_code::success(), EC);
64
65 EXPECT_NE((void*)0, M1.base());
66 EXPECT_LE(sizeof(int), M1.size());
67
68 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
69}
70
71TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
72 error_code EC;
73 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
74 EXPECT_EQ(error_code::success(), EC);
75 MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC);
76 EXPECT_EQ(error_code::success(), EC);
77 MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC);
78 EXPECT_EQ(error_code::success(), EC);
79
80 EXPECT_NE((void*)0, M1.base());
81 EXPECT_LE(16U, M1.size());
82 EXPECT_NE((void*)0, M2.base());
83 EXPECT_LE(64U, M2.size());
84 EXPECT_NE((void*)0, M3.base());
85 EXPECT_LE(32U, M3.size());
86
87 EXPECT_FALSE(doesOverlap(M1, M2));
88 EXPECT_FALSE(doesOverlap(M2, M3));
89 EXPECT_FALSE(doesOverlap(M1, M3));
90
91 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
92 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
93 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
94 EXPECT_EQ(error_code::success(), EC);
95 EXPECT_NE((void*)0, M4.base());
96 EXPECT_LE(16U, M4.size());
97 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
98 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
99}
100
101TEST_P(MappedMemoryTest, BasicWrite) {
102 // This test applies only to writeable combinations
103 if (Flags && !(Flags & Memory::MF_WRITE))
104 return;
105
106 error_code EC;
107 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
108 EXPECT_EQ(error_code::success(), EC);
109
110 EXPECT_NE((void*)0, M1.base());
111 EXPECT_LE(sizeof(int), M1.size());
112
113 int *a = (int*)M1.base();
114 *a = 1;
115 EXPECT_EQ(1, *a);
116
117 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
118}
119
120TEST_P(MappedMemoryTest, MultipleWrite) {
121 // This test applies only to writeable combinations
122 if (Flags && !(Flags & Memory::MF_WRITE))
123 return;
124 error_code EC;
125 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
126 EXPECT_EQ(error_code::success(), EC);
127 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
128 EXPECT_EQ(error_code::success(), EC);
129 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
130 EXPECT_EQ(error_code::success(), EC);
131
132 EXPECT_FALSE(doesOverlap(M1, M2));
133 EXPECT_FALSE(doesOverlap(M2, M3));
134 EXPECT_FALSE(doesOverlap(M1, M3));
135
136 EXPECT_NE((void*)0, M1.base());
137 EXPECT_LE(1U * sizeof(int), M1.size());
138 EXPECT_NE((void*)0, M2.base());
139 EXPECT_LE(8U * sizeof(int), M2.size());
140 EXPECT_NE((void*)0, M3.base());
141 EXPECT_LE(4U * sizeof(int), M3.size());
142
143 int *x = (int*)M1.base();
144 *x = 1;
145
146 int *y = (int*)M2.base();
147 for (int i = 0; i < 8; i++) {
148 y[i] = i;
149 }
150
151 int *z = (int*)M3.base();
152 *z = 42;
153
154 EXPECT_EQ(1, *x);
155 EXPECT_EQ(7, y[7]);
156 EXPECT_EQ(42, *z);
157
158 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
159 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
160
161 MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC);
162 EXPECT_EQ(error_code::success(), EC);
163 EXPECT_NE((void*)0, M4.base());
164 EXPECT_LE(64U * sizeof(int), M4.size());
165 x = (int*)M4.base();
166 *x = 4;
167 EXPECT_EQ(4, *x);
168 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
169
170 // Verify that M2 remains unaffected by other activity
171 for (int i = 0; i < 8; i++) {
172 EXPECT_EQ(i, y[i]);
173 }
174 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
175}
176
177TEST_P(MappedMemoryTest, EnabledWrite) {
178 error_code EC;
179 MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC);
180 EXPECT_EQ(error_code::success(), EC);
181 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
182 EXPECT_EQ(error_code::success(), EC);
183 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
184 EXPECT_EQ(error_code::success(), EC);
185
186 EXPECT_NE((void*)0, M1.base());
187 EXPECT_LE(2U * sizeof(int), M1.size());
188 EXPECT_NE((void*)0, M2.base());
189 EXPECT_LE(8U * sizeof(int), M2.size());
190 EXPECT_NE((void*)0, M3.base());
191 EXPECT_LE(4U * sizeof(int), M3.size());
192
193 EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
194 EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
195 EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
196
197 EXPECT_FALSE(doesOverlap(M1, M2));
198 EXPECT_FALSE(doesOverlap(M2, M3));
199 EXPECT_FALSE(doesOverlap(M1, M3));
200
201 int *x = (int*)M1.base();
202 *x = 1;
203 int *y = (int*)M2.base();
204 for (unsigned int i = 0; i < 8; i++) {
205 y[i] = i;
206 }
207 int *z = (int*)M3.base();
208 *z = 42;
209
210 EXPECT_EQ(1, *x);
211 EXPECT_EQ(7, y[7]);
212 EXPECT_EQ(42, *z);
213
214 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
215 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
216 EXPECT_EQ(6, y[6]);
217
218 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
219 EXPECT_EQ(error_code::success(), EC);
220 EXPECT_NE((void*)0, M4.base());
221 EXPECT_LE(16U, M4.size());
222 EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
223 x = (int*)M4.base();
224 *x = 4;
225 EXPECT_EQ(4, *x);
226 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
227 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
228}
229
230TEST_P(MappedMemoryTest, SuccessiveNear) {
231 error_code EC;
232 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
233 EXPECT_EQ(error_code::success(), EC);
234 MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
235 EXPECT_EQ(error_code::success(), EC);
236 MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
237 EXPECT_EQ(error_code::success(), EC);
238
239 EXPECT_NE((void*)0, M1.base());
240 EXPECT_LE(16U, M1.size());
241 EXPECT_NE((void*)0, M2.base());
242 EXPECT_LE(64U, M2.size());
243 EXPECT_NE((void*)0, M3.base());
244 EXPECT_LE(32U, M3.size());
245
246 EXPECT_FALSE(doesOverlap(M1, M2));
247 EXPECT_FALSE(doesOverlap(M2, M3));
248 EXPECT_FALSE(doesOverlap(M1, M3));
249
250 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
251 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
252 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
253}
254
255TEST_P(MappedMemoryTest, DuplicateNear) {
256 error_code EC;
257 MemoryBlock Near((void*)(3*PageSize), 16);
258 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
259 EXPECT_EQ(error_code::success(), EC);
260 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
261 EXPECT_EQ(error_code::success(), EC);
262 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
263 EXPECT_EQ(error_code::success(), EC);
264
265 EXPECT_NE((void*)0, M1.base());
266 EXPECT_LE(16U, M1.size());
267 EXPECT_NE((void*)0, M2.base());
268 EXPECT_LE(64U, M2.size());
269 EXPECT_NE((void*)0, M3.base());
270 EXPECT_LE(32U, M3.size());
271
272 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
273 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
274 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
275}
276
277TEST_P(MappedMemoryTest, ZeroNear) {
278 error_code EC;
279 MemoryBlock Near(0, 0);
280 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
281 EXPECT_EQ(error_code::success(), EC);
282 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
283 EXPECT_EQ(error_code::success(), EC);
284 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
285 EXPECT_EQ(error_code::success(), EC);
286
287 EXPECT_NE((void*)0, M1.base());
288 EXPECT_LE(16U, M1.size());
289 EXPECT_NE((void*)0, M2.base());
290 EXPECT_LE(64U, M2.size());
291 EXPECT_NE((void*)0, M3.base());
292 EXPECT_LE(32U, M3.size());
293
294 EXPECT_FALSE(doesOverlap(M1, M2));
295 EXPECT_FALSE(doesOverlap(M2, M3));
296 EXPECT_FALSE(doesOverlap(M1, M3));
297
298 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
299 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
300 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
301}
302
303TEST_P(MappedMemoryTest, ZeroSizeNear) {
304 error_code EC;
305 MemoryBlock Near((void*)(4*PageSize), 0);
306 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
307 EXPECT_EQ(error_code::success(), EC);
308 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
309 EXPECT_EQ(error_code::success(), EC);
310 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
311 EXPECT_EQ(error_code::success(), EC);
312
313 EXPECT_NE((void*)0, M1.base());
314 EXPECT_LE(16U, M1.size());
315 EXPECT_NE((void*)0, M2.base());
316 EXPECT_LE(64U, M2.size());
317 EXPECT_NE((void*)0, M3.base());
318 EXPECT_LE(32U, M3.size());
319
320 EXPECT_FALSE(doesOverlap(M1, M2));
321 EXPECT_FALSE(doesOverlap(M2, M3));
322 EXPECT_FALSE(doesOverlap(M1, M3));
323
324 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
325 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
326 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
327}
328
329TEST_P(MappedMemoryTest, UnalignedNear) {
330 error_code EC;
331 MemoryBlock Near((void*)(2*PageSize+5), 0);
332 MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
333 EXPECT_EQ(error_code::success(), EC);
334
335 EXPECT_NE((void*)0, M1.base());
336 EXPECT_LE(sizeof(int), M1.size());
337
338 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
339}
340
341// Note that Memory::MF_WRITE is not supported exclusively across
342// operating systems and architectures and can imply MF_READ|MF_WRITE
343unsigned MemoryFlags[] = {
344 Memory::MF_READ,
345 Memory::MF_WRITE,
346 Memory::MF_READ|Memory::MF_WRITE,
347 Memory::MF_EXEC,
348 Memory::MF_READ|Memory::MF_EXEC,
349 Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
350 };
351
352INSTANTIATE_TEST_CASE_P(AllocationTests,
353 MappedMemoryTest,
354 ::testing::ValuesIn(MemoryFlags));
355
356} // anonymous namespace