Home | History | Annotate | Download | only in tests
      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