• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 ark {
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         // NOLINTNEXTLINE(readability-magic-numbers)
34         seed_ = 0xDEADBEEF;
35 #endif
36         srand(seed_);
37     }
38 
~PoolMapTest()39     ~PoolMapTest() override
40     {
41         ResetPoolMap();
42     }
43 
44     NO_COPY_SEMANTIC(PoolMapTest);
45     NO_MOVE_SEMANTIC(PoolMapTest);
46 
47 protected:
48     static constexpr size_t MINIMAL_POOL_SIZE = PANDA_POOL_ALIGNMENT_IN_BYTES;
49 
AddToPoolMap(Pool pool,SpaceType spaceType,AllocatorType allocatorType,void * allocatorAddr=nullptr)50     void AddToPoolMap(Pool pool, SpaceType spaceType, AllocatorType allocatorType, void *allocatorAddr = nullptr)
51     {
52         if (allocatorAddr == nullptr) {
53             allocatorAddr = pool.GetMem();
54         }
55         pools_.push_back(pool);
56         poolMap_.AddPoolToMap(pool.GetMem(), pool.GetSize(), spaceType, allocatorType, allocatorAddr);
57     }
58 
RemovePoolFromMap(Pool pool)59     void RemovePoolFromMap(Pool pool)
60     {
61         auto items = std::remove(pools_.begin(), pools_.end(), pool);
62         ASSERT(items != pools_.end());
63         pools_.erase(items, pools_.end());
64         poolMap_.RemovePoolFromMap(pool.GetMem(), pool.GetSize());
65     }
66 
ResetPoolMap()67     void ResetPoolMap()
68     {
69         for (auto i : pools_) {
70             poolMap_.RemovePoolFromMap(i.GetMem(), i.GetSize());
71         }
72         pools_.clear();
73     }
74 
IsEmptyPoolMap() const75     bool IsEmptyPoolMap() const
76     {
77         return poolMap_.IsEmpty();
78     }
79 
GetRandSpaceType() const80     SpaceType GetRandSpaceType() const
81     {
82         // NOLINTNEXTLINE(cert-msc50-cpp)
83         int randIndex = rand() % ALL_SPACE_TYPES.size();
84         return ALL_SPACE_TYPES[randIndex];
85     }
86 
GetRandAllocatorType() const87     AllocatorType GetRandAllocatorType() const
88     {
89         // NOLINTNEXTLINE(cert-msc50-cpp)
90         int randIndex = rand() % ALL_ALLOCATOR_TYPES.size();
91         return ALL_ALLOCATOR_TYPES[randIndex];
92     }
93 
RandHeapAddr() const94     size_t RandHeapAddr() const
95     {
96         // NOLINTNEXTLINE(cert-msc50-cpp)
97         return AlignUp(rand() % PANDA_MAX_HEAP_SIZE, DEFAULT_ALIGNMENT_IN_BYTES);
98     }
99 
CheckRandomPoolAddress(Pool pool,SpaceType spaceType,AllocatorType allocatorType,uintptr_t allocatorAddr)100     void CheckRandomPoolAddress(Pool pool, SpaceType spaceType, AllocatorType allocatorType, uintptr_t allocatorAddr)
101     {
102         void *poolAddr = RandAddrFromPool(pool);
103         ASSERT_EQ(GetSpaceTypeForAddr(poolAddr), spaceType);
104         ASSERT_EQ(GetAllocatorInfoForAddr(poolAddr).GetType(), allocatorType);
105         ASSERT_EQ(ToUintPtr(GetAllocatorInfoForAddr(poolAddr).GetAllocatorHeaderAddr()), allocatorAddr);
106     }
107 
108 private:
RandAddrFromPool(Pool pool) const109     void *RandAddrFromPool(Pool pool) const
110     {
111         // NOLINTNEXTLINE(cert-msc50-cpp)
112         return ToVoidPtr(ToUintPtr(pool.GetMem()) + rand() % pool.GetSize());
113     }
114 
GetAllocatorInfoForAddr(const void * addr) const115     AllocatorInfo GetAllocatorInfoForAddr(const void *addr) const
116     {
117         return poolMap_.GetAllocatorInfo(addr);
118     }
119 
GetSpaceTypeForAddr(const void * addr) const120     SpaceType GetSpaceTypeForAddr(const void *addr) const
121     {
122         return poolMap_.GetSpaceType(addr);
123     }
124 
125     static constexpr std::array<SpaceType, 6U> ALL_SPACE_TYPES = {SpaceType::SPACE_TYPE_OBJECT,
126                                                                   SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT,
127                                                                   SpaceType::SPACE_TYPE_NON_MOVABLE_OBJECT,
128                                                                   SpaceType::SPACE_TYPE_INTERNAL,
129                                                                   SpaceType::SPACE_TYPE_CODE,
130                                                                   SpaceType::SPACE_TYPE_COMPILER};
131 
132     static constexpr std::array<AllocatorType, 8U> ALL_ALLOCATOR_TYPES = {
133         AllocatorType::RUNSLOTS_ALLOCATOR, AllocatorType::FREELIST_ALLOCATOR, AllocatorType::HUMONGOUS_ALLOCATOR,
134         AllocatorType::ARENA_ALLOCATOR,    AllocatorType::BUMP_ALLOCATOR,     AllocatorType::TLAB_ALLOCATOR,
135         AllocatorType::REGION_ALLOCATOR,   AllocatorType::FRAME_ALLOCATOR};
136 
137     unsigned int seed_;
138     std::vector<Pool> pools_;
139     PoolMap poolMap_;
140 };
141 
TEST_F(PoolMapTest,TwoConsistentPoolsTest)142 TEST_F(PoolMapTest, TwoConsistentPoolsTest)
143 {
144     static constexpr size_t FIRST_POOL_SIZE = 4U * MINIMAL_POOL_SIZE;
145     static constexpr size_t SECOND_POOL_SIZE = 10U * MINIMAL_POOL_SIZE;
146     static constexpr uintptr_t FIRST_POOL_ADDR = 0;
147     static constexpr uintptr_t SECOND_POOL_ADDR = FIRST_POOL_ADDR + FIRST_POOL_SIZE;
148     static constexpr SpaceType FIRST_SPACE_TYPE = SpaceType::SPACE_TYPE_INTERNAL;
149     static constexpr SpaceType SECOND_SPACE_TYPE = SpaceType::SPACE_TYPE_OBJECT;
150     static constexpr AllocatorType FIRST_ALLOCATOR_TYPE = AllocatorType::RUNSLOTS_ALLOCATOR;
151     static constexpr AllocatorType SECOND_ALLOCATOR_TYPE = AllocatorType::FREELIST_ALLOCATOR;
152 
153     uintptr_t firstPoolAllocatorHeaderAddr = RandHeapAddr();
154 
155     Pool firstPool(FIRST_POOL_SIZE, ToVoidPtr(FIRST_POOL_ADDR));
156     Pool secondPool(SECOND_POOL_SIZE, ToVoidPtr(SECOND_POOL_ADDR));
157 
158     AddToPoolMap(firstPool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, ToVoidPtr(firstPoolAllocatorHeaderAddr));
159     AddToPoolMap(secondPool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE);
160 
161     CheckRandomPoolAddress(firstPool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, firstPoolAllocatorHeaderAddr);
162     // We haven't initialized second allocator header address.
163     // Therefore it must return a pointer to the first pool byte.
164     CheckRandomPoolAddress(secondPool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE, SECOND_POOL_ADDR);
165 
166     // Check that we remove elements from pool map correctly
167     RemovePoolFromMap(firstPool);
168     RemovePoolFromMap(secondPool);
169 
170     ASSERT_TRUE(IsEmptyPoolMap());
171     ResetPoolMap();
172 }
173 
TEST_F(PoolMapTest,AddRemoveDifferentPoolsTest)174 TEST_F(PoolMapTest, AddRemoveDifferentPoolsTest)
175 {
176     static constexpr size_t MAX_POOL_SIZE = 256U * MINIMAL_POOL_SIZE;
177     static constexpr size_t ITERATIONS = 200;
178     static constexpr uintptr_t POOL_START_ADDR = PANDA_POOL_ALIGNMENT_IN_BYTES;
179     for (size_t i = 0; i < ITERATIONS; i++) {
180         // NOLINTNEXTLINE(cert-msc50-cpp)
181         size_t poolSize = AlignUp(rand() % MAX_POOL_SIZE, PANDA_POOL_ALIGNMENT_IN_BYTES);
182         SpaceType space = GetRandSpaceType();
183         AllocatorType allocator = GetRandAllocatorType();
184         Pool pool(poolSize, ToVoidPtr(POOL_START_ADDR));
185 
186         AddToPoolMap(pool, space, allocator);
187         CheckRandomPoolAddress(pool, space, allocator, POOL_START_ADDR);
188         RemovePoolFromMap(pool);
189     }
190 
191     ASSERT_TRUE(IsEmptyPoolMap());
192     ResetPoolMap();
193 }
194 
195 }  // namespace ark
196