1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdlib.h> 18 #include <string.h> 19 #include <sys/mman.h> 20 21 #include <gtest/gtest.h> 22 23 #include "../linker_allocator.h" 24 25 #include <unistd.h> 26 27 namespace { 28 29 /* 30 * this one has size below allocator cap which is 2*sizeof(void*) 31 */ 32 struct test_struct_small { 33 char dummy_str[5]; 34 }; 35 36 struct test_struct_large { 37 char dummy_str[1009]; 38 }; 39 40 struct test_struct_huge { 41 char dummy_str[73939]; 42 }; 43 44 struct test_struct_512 { 45 char dummy_str[503]; 46 }; 47 48 }; 49 50 static size_t kPageSize = sysconf(_SC_PAGE_SIZE); 51 52 TEST(linker_memory, test_alloc_0) { 53 LinkerMemoryAllocator allocator; 54 void* ptr = allocator.alloc(0); 55 ASSERT_TRUE(ptr != nullptr); 56 allocator.free(ptr); 57 } 58 59 TEST(linker_memory, test_free_nullptr) { 60 LinkerMemoryAllocator allocator; 61 allocator.free(nullptr); 62 } 63 64 TEST(linker_memory, test_realloc) { 65 LinkerMemoryAllocator allocator; 66 uint32_t* array = reinterpret_cast<uint32_t*>(allocator.alloc(512)); 67 const size_t array_size = 512 / sizeof(uint32_t); 68 69 uint32_t model[1000]; 70 71 model[0] = 1; 72 model[1] = 1; 73 74 for (size_t i = 2; i < 1000; ++i) { 75 model[i] = model[i - 1] + model[i - 2]; 76 } 77 78 memcpy(array, model, array_size); 79 80 uint32_t* reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 1024)); 81 82 ASSERT_TRUE(reallocated_ptr != nullptr); 83 ASSERT_TRUE(reallocated_ptr != array); 84 85 ASSERT_TRUE(memcmp(reallocated_ptr, model, array_size) == 0); 86 87 array = reallocated_ptr; 88 89 memcpy(array, model, 2*array_size); 90 91 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 62)); 92 93 ASSERT_TRUE(reallocated_ptr == array); 94 95 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 4000)); 96 97 ASSERT_TRUE(reallocated_ptr != nullptr); 98 ASSERT_TRUE(reallocated_ptr != array); 99 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(reallocated_ptr) % 16); 100 101 ASSERT_TRUE(memcmp(reallocated_ptr, model, array_size * 2) == 0); 102 103 array = reallocated_ptr; 104 105 memcpy(array, model, 4000); 106 107 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 64000)); 108 109 ASSERT_TRUE(reallocated_ptr != nullptr); 110 ASSERT_TRUE(reallocated_ptr != array); 111 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(reallocated_ptr) % 16); 112 113 ASSERT_TRUE(memcmp(reallocated_ptr, model, 4000) == 0); 114 115 ASSERT_EQ(nullptr, allocator.realloc(reallocated_ptr, 0)); 116 } 117 118 TEST(linker_memory, test_small_smoke) { 119 LinkerMemoryAllocator allocator; 120 121 uint8_t zeros[16]; 122 memset(zeros, 0, sizeof(zeros)); 123 124 test_struct_small* ptr1 = 125 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small))); 126 test_struct_small* ptr2 = 127 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small))); 128 129 ASSERT_TRUE(ptr1 != nullptr); 130 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 131 ASSERT_TRUE(ptr2 != nullptr); 132 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 133 134 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1)+16, reinterpret_cast<uintptr_t>(ptr2)); 135 ASSERT_TRUE(memcmp(ptr1, zeros, 16) == 0); 136 137 allocator.free(ptr1); 138 allocator.free(ptr2); 139 } 140 141 TEST(linker_memory, test_huge_smoke) { 142 LinkerMemoryAllocator allocator; 143 144 // this should trigger proxy-to-mmap 145 test_struct_huge* ptr1 = 146 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge))); 147 test_struct_huge* ptr2 = 148 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge))); 149 150 ASSERT_TRUE(ptr1 != nullptr); 151 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 152 ASSERT_TRUE(ptr2 != nullptr); 153 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 154 155 ASSERT_TRUE( 156 reinterpret_cast<uintptr_t>(ptr1)/kPageSize != reinterpret_cast<uintptr_t>(ptr2)/kPageSize); 157 allocator.free(ptr2); 158 allocator.free(ptr1); 159 } 160 161 TEST(linker_memory, test_large) { 162 LinkerMemoryAllocator allocator; 163 164 test_struct_large* ptr1 = 165 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 166 test_struct_large* ptr2 = 167 reinterpret_cast<test_struct_large*>(allocator.alloc(1024)); 168 169 ASSERT_TRUE(ptr1 != nullptr); 170 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr1) % 16); 171 ASSERT_TRUE(ptr2 != nullptr); 172 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr2) % 16); 173 174 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1) + 1024, reinterpret_cast<uintptr_t>(ptr2)); 175 176 // let's allocate until we reach the next page. 177 size_t n = kPageSize / sizeof(test_struct_large) + 1 - 2; 178 test_struct_large* objects[n]; 179 180 for (size_t i = 0; i < n; ++i) { 181 test_struct_large* obj_ptr = 182 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 183 ASSERT_TRUE(obj_ptr != nullptr); 184 objects[i] = obj_ptr; 185 } 186 187 test_struct_large* ptr_to_free = 188 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 189 190 ASSERT_TRUE(ptr_to_free != nullptr); 191 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr_to_free) % 16); 192 193 allocator.free(ptr1); 194 195 for (size_t i=0; i<n; ++i) { 196 allocator.free(objects[i]); 197 } 198 199 allocator.free(ptr2); 200 allocator.free(ptr_to_free); 201 } 202 203 204