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 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 100 ASSERT_TRUE(memcmp(reallocated_ptr, model, array_size * 2) == 0); 101 102 array = reallocated_ptr; 103 104 memcpy(array, model, 4000); 105 106 reallocated_ptr = reinterpret_cast<uint32_t*>(allocator.realloc(array, 64000)); 107 108 ASSERT_TRUE(reallocated_ptr != nullptr); 109 ASSERT_TRUE(reallocated_ptr != array); 110 111 ASSERT_TRUE(memcmp(reallocated_ptr, model, 4000) == 0); 112 113 ASSERT_EQ(nullptr, realloc(reallocated_ptr, 0)); 114 } 115 116 TEST(linker_memory, test_small_smoke) { 117 LinkerMemoryAllocator allocator; 118 119 uint8_t zeros[16]; 120 memset(zeros, 0, sizeof(zeros)); 121 122 test_struct_small* ptr1 = 123 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small))); 124 test_struct_small* ptr2 = 125 reinterpret_cast<test_struct_small*>(allocator.alloc(sizeof(test_struct_small))); 126 127 ASSERT_TRUE(ptr1 != nullptr); 128 ASSERT_TRUE(ptr2 != nullptr); 129 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1)+16, reinterpret_cast<uintptr_t>(ptr2)); 130 ASSERT_TRUE(memcmp(ptr1, zeros, 16) == 0); 131 132 allocator.free(ptr1); 133 allocator.free(ptr2); 134 } 135 136 TEST(linker_memory, test_huge_smoke) { 137 LinkerMemoryAllocator allocator; 138 139 // this should trigger proxy-to-mmap 140 test_struct_huge* ptr1 = 141 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge))); 142 test_struct_huge* ptr2 = 143 reinterpret_cast<test_struct_huge*>(allocator.alloc(sizeof(test_struct_huge))); 144 145 ASSERT_TRUE(ptr1 != nullptr); 146 ASSERT_TRUE(ptr2 != nullptr); 147 148 ASSERT_TRUE( 149 reinterpret_cast<uintptr_t>(ptr1)/kPageSize != reinterpret_cast<uintptr_t>(ptr2)/kPageSize); 150 allocator.free(ptr2); 151 allocator.free(ptr1); 152 } 153 154 TEST(linker_memory, test_large) { 155 LinkerMemoryAllocator allocator; 156 157 test_struct_large* ptr1 = 158 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 159 test_struct_large* ptr2 = 160 reinterpret_cast<test_struct_large*>(allocator.alloc(1024)); 161 162 ASSERT_TRUE(ptr1 != nullptr); 163 ASSERT_TRUE(ptr2 != nullptr); 164 165 ASSERT_EQ(reinterpret_cast<uintptr_t>(ptr1) + 1024, reinterpret_cast<uintptr_t>(ptr2)); 166 167 // let's allocate until we reach the next page. 168 size_t n = kPageSize / sizeof(test_struct_large) + 1 - 2; 169 test_struct_large* objects[n]; 170 171 for (size_t i = 0; i < n; ++i) { 172 test_struct_large* obj_ptr = 173 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 174 ASSERT_TRUE(obj_ptr != nullptr); 175 objects[i] = obj_ptr; 176 } 177 178 test_struct_large* ptr_to_free = 179 reinterpret_cast<test_struct_large*>(allocator.alloc(sizeof(test_struct_large))); 180 181 ASSERT_TRUE(ptr_to_free != nullptr); 182 183 allocator.free(ptr1); 184 185 for (size_t i=0; i<n; ++i) { 186 allocator.free(objects[i]); 187 } 188 189 allocator.free(ptr2); 190 allocator.free(ptr_to_free); 191 } 192 193 194