blob: d0ca8ec5f9a31bf8e1ed2551f68dbfa965c0ee85 [file] [log] [blame]
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08003 * All rights reserved.
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -07004 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070014 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -080015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070027 */
28
29#include <stdlib.h>
30#include <string.h>
31#include <sys/mman.h>
32
33#include <gtest/gtest.h>
34
Ryan Prichard083d8502019-01-24 13:47:13 -080035#include "private/bionic_allocator.h"
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070036
37#include <unistd.h>
38
39namespace {
40
41/*
42 * this one has size below allocator cap which is 2*sizeof(void*)
43 */
44struct test_struct_small {
45 char dummy_str[5];
46};
47
48struct test_struct_large {
49 char dummy_str[1009];
50};
51
52struct test_struct_huge {
53 char dummy_str[73939];
54};
55
56struct test_struct_512 {
57 char dummy_str[503];
58};
59
60};
61
62static size_t kPageSize = sysconf(_SC_PAGE_SIZE);
63
Ryan Prichard083d8502019-01-24 13:47:13 -080064TEST(bionic_allocator, test_alloc_0) {
65 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070066 void* ptr = allocator.alloc(0);
67 ASSERT_TRUE(ptr != nullptr);
Dmitriy Ivanova0f187b2015-10-05 12:06:40 -070068 allocator.free(ptr);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070069}
70
Ryan Prichard083d8502019-01-24 13:47:13 -080071TEST(bionic_allocator, test_free_nullptr) {
72 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070073 allocator.free(nullptr);
74}
75
Ryan Prichard083d8502019-01-24 13:47:13 -080076TEST(bionic_allocator, test_realloc) {
77 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -070078 uint32_t* array = reinterpret_cast<uint32_t*>(allocator.alloc(512));
79 const size_t array_size = 512 / sizeof(uint32_t);
80
81 uint32_t model[1000];
82
83 model[0] = 1;
84 model[1] = 1;
85
86 for (size_t i = 2; i < 1000; ++i) {
87 model[i] = model[i - 1] + model[i - 2];
88 }
89
90 memcpy(array, model, array_size);
91
92 uint32_t* reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 1024));
93
94 ASSERT_TRUE(reallocated_ptr != nullptr);
95 ASSERT_TRUE(reallocated_ptr != array);
96
97 ASSERT_TRUE(memcmp(reallocated_ptr, model, array_size) == 0);
98
99 array = reallocated_ptr;
100
101 memcpy(array, model, 2*array_size);
102
103 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 62));
104
105 ASSERT_TRUE(reallocated_ptr == array);
106
107 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 4000));
108
109 ASSERT_TRUE(reallocated_ptr != nullptr);
110 ASSERT_TRUE(reallocated_ptr != array);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800111 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(reallocated_ptr) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700112
113 ASSERT_TRUE(memcmp(reallocated_ptr, model, array_size * 2) == 0);
114
115 array = reallocated_ptr;
116
117 memcpy(array, model, 4000);
118
119 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 64000));
120
121 ASSERT_TRUE(reallocated_ptr != nullptr);
122 ASSERT_TRUE(reallocated_ptr != array);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800123 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(reallocated_ptr) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700124
125 ASSERT_TRUE(memcmp(reallocated_ptr, model, 4000) == 0);
126
Dmitriy Ivanova0f187b2015-10-05 12:06:40 -0700127 ASSERT_EQ(nullptr, allocator.realloc(reallocated_ptr, 0));
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700128}
129
Ryan Prichard083d8502019-01-24 13:47:13 -0800130TEST(bionic_allocator, test_small_smoke) {
131 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700132
133 uint8_t zeros[16];
134 memset(zeros, 0, sizeof(zeros));
135
136 test_struct_small* ptr1 =
137 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small)));
138 test_struct_small* ptr2 =
139 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small)));
140
141 ASSERT_TRUE(ptr1 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800142 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700143 ASSERT_TRUE(ptr2 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800144 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
145
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700146 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1)+16, reinterpret_cast<uintptr_t>(ptr2));
147 ASSERT_TRUE(memcmp(ptr1, zeros, 16) == 0);
148
149 allocator.free(ptr1);
150 allocator.free(ptr2);
151}
152
Ryan Prichard083d8502019-01-24 13:47:13 -0800153TEST(bionic_allocator, test_huge_smoke) {
154 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700155
156 // this should trigger proxy-to-mmap
157 test_struct_huge* ptr1 =
158 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge)));
159 test_struct_huge* ptr2 =
160 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge)));
161
162 ASSERT_TRUE(ptr1 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800163 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700164 ASSERT_TRUE(ptr2 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800165 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700166
167 ASSERT_TRUE(
168 reinterpret_cast<uintptr_t>(ptr1)/kPageSize != reinterpret_cast<uintptr_t>(ptr2)/kPageSize);
169 allocator.free(ptr2);
170 allocator.free(ptr1);
171}
172
Ryan Prichard083d8502019-01-24 13:47:13 -0800173TEST(bionic_allocator, test_large) {
174 BionicAllocator allocator;
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700175
176 test_struct_large* ptr1 =
177 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large)));
178 test_struct_large* ptr2 =
179 reinterpret_cast<test_struct_large*>(allocator.alloc(1024));
180
181 ASSERT_TRUE(ptr1 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800182 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700183 ASSERT_TRUE(ptr2 != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800184 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700185
186 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1) + 1024, reinterpret_cast<uintptr_t>(ptr2));
187
188 // let's allocate until we reach the next page.
189 size_t n = kPageSize / sizeof(test_struct_large) + 1 - 2;
190 test_struct_large* objects[n];
191
192 for (size_t i = 0; i < n; ++i) {
193 test_struct_large* obj_ptr =
194 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large)));
195 ASSERT_TRUE(obj_ptr != nullptr);
196 objects[i] = obj_ptr;
197 }
198
199 test_struct_large* ptr_to_free =
200 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large)));
201
202 ASSERT_TRUE(ptr_to_free != nullptr);
Dimitry Ivanov3edc5c42016-01-21 10:55:40 -0800203 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr_to_free) % 16);
Dmitriy Ivanov19656ce2015-03-10 17:48:27 -0700204
205 allocator.free(ptr1);
206
207 for (size_t i=0; i<n; ++i) {
208 allocator.free(objects[i]);
209 }
210
211 allocator.free(ptr2);
212 allocator.free(ptr_to_free);
213}
214
215