1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "gtest/gtest.h" 17 #include "mem/pool_map.h" 18 #include "mem/mem_pool.h" 19 #include "mem/mem.h" 20 21 #include <ctime> 22 #include <algorithm> 23 24 namespace panda { 25 26 class PoolMapTest : public testing::Test { 27 public: PoolMapTest()28 PoolMapTest() 29 { 30 #ifdef PANDA_NIGHTLY_TEST_ON 31 seed_ = std::time(NULL); 32 #else 33 seed_ = 0xDEADBEEF; 34 #endif 35 srand(seed_); 36 } 37 ~PoolMapTest()38 ~PoolMapTest() 39 { 40 ResetPoolMap(); 41 } 42 43 protected: 44 static constexpr size_t MINIMAL_POOL_SIZE = PANDA_POOL_ALIGNMENT_IN_BYTES; 45 AddToPoolMap(Pool pool,SpaceType space_type,AllocatorType allocator_type,void * allocator_addr=nullptr)46 void AddToPoolMap(Pool pool, SpaceType space_type, AllocatorType allocator_type, void *allocator_addr = nullptr) 47 { 48 if (allocator_addr == nullptr) { 49 allocator_addr = pool.GetMem(); 50 } 51 pools_.push_back(pool); 52 pool_map_.AddPoolToMap(pool.GetMem(), pool.GetSize(), space_type, allocator_type, allocator_addr); 53 } 54 RemovePoolFromMap(Pool pool)55 void RemovePoolFromMap(Pool pool) 56 { 57 auto items = std::remove(pools_.begin(), pools_.end(), pool); 58 ASSERT(items != pools_.end()); 59 pools_.erase(items, pools_.end()); 60 pool_map_.RemovePoolFromMap(pool.GetMem(), pool.GetSize()); 61 } 62 ResetPoolMap()63 void ResetPoolMap() 64 { 65 for (auto i : pools_) { 66 pool_map_.RemovePoolFromMap(i.GetMem(), i.GetSize()); 67 } 68 pools_.clear(); 69 } 70 IsEmptyPoolMap() const71 bool IsEmptyPoolMap() const 72 { 73 return pool_map_.IsEmpty(); 74 } 75 GetRandSpaceType() const76 SpaceType GetRandSpaceType() const 77 { 78 int rand_index = rand() % ALL_SPACE_TYPES.size(); 79 return ALL_SPACE_TYPES[rand_index]; 80 } 81 GetRandAllocatorType() const82 AllocatorType GetRandAllocatorType() const 83 { 84 int rand_index = rand() % ALL_ALLOCATOR_TYPES.size(); 85 return ALL_ALLOCATOR_TYPES[rand_index]; 86 } 87 RandHeapAddr() const88 size_t RandHeapAddr() const 89 { 90 return AlignUp(rand() % PANDA_MAX_HEAP_SIZE, DEFAULT_ALIGNMENT_IN_BYTES); 91 } 92 CheckRandomPoolAddress(Pool pool,SpaceType space_type,AllocatorType allocator_type,uintptr_t allocator_addr)93 void CheckRandomPoolAddress(Pool pool, SpaceType space_type, AllocatorType allocator_type, uintptr_t allocator_addr) 94 { 95 void *pool_addr = RandAddrFromPool(pool); 96 ASSERT_EQ(GetSpaceTypeForAddr(pool_addr), space_type); 97 ASSERT_EQ(GetAllocatorInfoForAddr(pool_addr).GetType(), allocator_type); 98 ASSERT_EQ(ToUintPtr(GetAllocatorInfoForAddr(pool_addr).GetAllocatorHeaderAddr()), allocator_addr); 99 } 100 101 private: RandAddrFromPool(Pool pool) const102 void *RandAddrFromPool(Pool pool) const 103 { 104 return ToVoidPtr(ToUintPtr(pool.GetMem()) + rand() % pool.GetSize()); 105 } 106 GetAllocatorInfoForAddr(const void * addr) const107 AllocatorInfo GetAllocatorInfoForAddr(const void *addr) const 108 { 109 return pool_map_.GetAllocatorInfo(addr); 110 } 111 GetSpaceTypeForAddr(const void * addr) const112 SpaceType GetSpaceTypeForAddr(const void *addr) const 113 { 114 return pool_map_.GetSpaceType(addr); 115 } 116 117 static constexpr std::array<SpaceType, 6> ALL_SPACE_TYPES = {SpaceType::SPACE_TYPE_OBJECT, 118 SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT, 119 SpaceType::SPACE_TYPE_NON_MOVABLE_OBJECT, 120 SpaceType::SPACE_TYPE_INTERNAL, 121 SpaceType::SPACE_TYPE_CODE, 122 SpaceType::SPACE_TYPE_COMPILER}; 123 124 static constexpr std::array<AllocatorType, 8> ALL_ALLOCATOR_TYPES = { 125 AllocatorType::RUNSLOTS_ALLOCATOR, AllocatorType::FREELIST_ALLOCATOR, AllocatorType::HUMONGOUS_ALLOCATOR, 126 AllocatorType::ARENA_ALLOCATOR, AllocatorType::BUMP_ALLOCATOR, AllocatorType::TLAB_ALLOCATOR, 127 AllocatorType::REGION_ALLOCATOR, AllocatorType::FRAME_ALLOCATOR}; 128 129 unsigned int seed_; 130 std::vector<Pool> pools_; 131 PoolMap pool_map_; 132 }; 133 134 HWTEST_F(PoolMapTest, TwoConsistentPoolsTest, testing::ext::TestSize.Level0) 135 { 136 static constexpr size_t FIRST_POOL_SIZE = 4 * MINIMAL_POOL_SIZE; 137 static constexpr size_t SECOND_POOL_SIZE = 10 * MINIMAL_POOL_SIZE; 138 static constexpr uintptr_t FIRST_POOL_ADDR = 0; 139 static constexpr uintptr_t SECOND_POOL_ADDR = FIRST_POOL_ADDR + FIRST_POOL_SIZE; 140 static constexpr SpaceType FIRST_SPACE_TYPE = SpaceType::SPACE_TYPE_INTERNAL; 141 static constexpr SpaceType SECOND_SPACE_TYPE = SpaceType::SPACE_TYPE_OBJECT; 142 static constexpr AllocatorType FIRST_ALLOCATOR_TYPE = AllocatorType::RUNSLOTS_ALLOCATOR; 143 static constexpr AllocatorType SECOND_ALLOCATOR_TYPE = AllocatorType::FREELIST_ALLOCATOR; 144 145 uintptr_t first_pool_allocator_header_addr = RandHeapAddr(); 146 147 Pool first_pool(FIRST_POOL_SIZE, ToVoidPtr(FIRST_POOL_ADDR)); 148 Pool second_pool(SECOND_POOL_SIZE, ToVoidPtr(SECOND_POOL_ADDR)); 149 150 AddToPoolMap(first_pool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, ToVoidPtr(first_pool_allocator_header_addr)); 151 AddToPoolMap(second_pool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE); 152 153 CheckRandomPoolAddress(first_pool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, first_pool_allocator_header_addr); 154 // We haven't initialized second allocator header address. 155 // Therefore it must return a pointer to the first pool byte. 156 CheckRandomPoolAddress(second_pool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE, SECOND_POOL_ADDR); 157 158 ASSERT_FALSE(IsEmptyPoolMap()); 159 160 // Check that we remove elements from pool map correctly 161 RemovePoolFromMap(first_pool); 162 RemovePoolFromMap(second_pool); 163 164 ASSERT_TRUE(IsEmptyPoolMap()); 165 ResetPoolMap(); 166 } 167 168 HWTEST_F(PoolMapTest, AddRemoveDifferentPoolsTest, testing::ext::TestSize.Level0) 169 { 170 static constexpr size_t MAX_POOL_SIZE = 256 * MINIMAL_POOL_SIZE; 171 static constexpr size_t ITERATIONS = 200; 172 static constexpr uintptr_t POOL_START_ADDR = PANDA_POOL_ALIGNMENT_IN_BYTES; 173 for (size_t i = 0; i < ITERATIONS; i++) { 174 size_t pool_size = AlignUp(rand() % MAX_POOL_SIZE, PANDA_POOL_ALIGNMENT_IN_BYTES); 175 SpaceType space = GetRandSpaceType(); 176 AllocatorType allocator = GetRandAllocatorType(); 177 Pool pool(pool_size, ToVoidPtr(POOL_START_ADDR)); 178 179 AddToPoolMap(pool, space, allocator); 180 CheckRandomPoolAddress(pool, space, allocator, POOL_START_ADDR); 181 RemovePoolFromMap(pool); 182 } 183 184 ASSERT_TRUE(IsEmptyPoolMap()); 185 ResetPoolMap(); 186 } 187 188 } // namespace panda 189