• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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,const void * allocator_addr=nullptr)46     void AddToPoolMap(Pool pool, SpaceType space_type, AllocatorType allocator_type,
47                       const void *allocator_addr = nullptr)
48     {
49         if (allocator_addr == nullptr) {
50             allocator_addr = pool.GetMem();
51         }
52         pools_.push_back(pool);
53         pool_map_.AddPoolToMap(pool.GetMem(), pool.GetSize(), space_type, allocator_type, allocator_addr);
54     }
55 
RemovePoolFromMap(Pool pool)56     void RemovePoolFromMap(Pool pool)
57     {
58         auto items = std::remove(pools_.begin(), pools_.end(), pool);
59         ASSERT(items != pools_.end());
60         pools_.erase(items, pools_.end());
61         pool_map_.RemovePoolFromMap(pool.GetMem(), pool.GetSize());
62     }
63 
ResetPoolMap()64     void ResetPoolMap()
65     {
66         for (auto i : pools_) {
67             pool_map_.RemovePoolFromMap(i.GetMem(), i.GetSize());
68         }
69         pools_.clear();
70     }
71 
IsEmptyPoolMap() const72     bool IsEmptyPoolMap() const
73     {
74         return pool_map_.IsEmpty();
75     }
76 
GetRandSpaceType() const77     SpaceType GetRandSpaceType() const
78     {
79         int rand_index = rand() % ALL_SPACE_TYPES.size();
80         return ALL_SPACE_TYPES[rand_index];
81     }
82 
GetRandAllocatorType() const83     AllocatorType GetRandAllocatorType() const
84     {
85         int rand_index = rand() % ALL_ALLOCATOR_TYPES.size();
86         return ALL_ALLOCATOR_TYPES[rand_index];
87     }
88 
RandHeapAddr() const89     size_t RandHeapAddr() const
90     {
91         return AlignUp(rand() % PANDA_MAX_HEAP_SIZE, DEFAULT_ALIGNMENT_IN_BYTES);
92     }
93 
CheckRandomPoolAddress(Pool pool,SpaceType space_type,AllocatorType allocator_type,uintptr_t allocator_addr) const94     void CheckRandomPoolAddress(Pool pool, SpaceType space_type, AllocatorType allocator_type,
95                                 uintptr_t allocator_addr) const
96     {
97         void *pool_addr = RandAddrFromPool(pool);
98         ASSERT_EQ(GetSpaceTypeForAddr(pool_addr), space_type);
99         ASSERT_EQ(GetAllocatorInfoForAddr(pool_addr).GetType(), allocator_type);
100         ASSERT_EQ(ToUintPtr(GetAllocatorInfoForAddr(pool_addr).GetAllocatorHeaderAddr()), allocator_addr);
101     }
102 
103 private:
RandAddrFromPool(Pool pool) const104     void *RandAddrFromPool(Pool pool) const
105     {
106         return ToVoidPtr(ToUintPtr(pool.GetMem()) + rand() % pool.GetSize());
107     }
108 
GetAllocatorInfoForAddr(void * addr) const109     AllocatorInfo GetAllocatorInfoForAddr(void *addr) const
110     {
111         return pool_map_.GetAllocatorInfo(addr);
112     }
113 
GetSpaceTypeForAddr(void * addr) const114     SpaceType GetSpaceTypeForAddr(void *addr) const
115     {
116         return pool_map_.GetSpaceType(addr);
117     }
118 
119     static constexpr std::array<SpaceType, 6> ALL_SPACE_TYPES = {SpaceType::SPACE_TYPE_OBJECT,
120                                                                  SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT,
121                                                                  SpaceType::SPACE_TYPE_NON_MOVABLE_OBJECT,
122                                                                  SpaceType::SPACE_TYPE_INTERNAL,
123                                                                  SpaceType::SPACE_TYPE_CODE,
124                                                                  SpaceType::SPACE_TYPE_COMPILER};
125 
126     static constexpr std::array<AllocatorType, 8> ALL_ALLOCATOR_TYPES = {
127         AllocatorType::RUNSLOTS_ALLOCATOR, AllocatorType::FREELIST_ALLOCATOR, AllocatorType::HUMONGOUS_ALLOCATOR,
128         AllocatorType::ARENA_ALLOCATOR,    AllocatorType::BUMP_ALLOCATOR,     AllocatorType::TLAB_ALLOCATOR,
129         AllocatorType::REGION_ALLOCATOR,   AllocatorType::FRAME_ALLOCATOR};
130 
131     unsigned int seed_;
132     std::vector<Pool> pools_;
133     PoolMap pool_map_;
134 };
135 
TEST_F(PoolMapTest,TwoConsistentPoolsTest)136 TEST_F(PoolMapTest, TwoConsistentPoolsTest)
137 {
138     static constexpr size_t FIRST_POOL_SIZE = 4 * MINIMAL_POOL_SIZE;
139     static constexpr size_t SECOND_POOL_SIZE = 10 * MINIMAL_POOL_SIZE;
140     static constexpr uintptr_t FIRST_POOL_ADDR = 0;
141     static constexpr uintptr_t SECOND_POOL_ADDR = FIRST_POOL_ADDR + FIRST_POOL_SIZE;
142     static constexpr SpaceType FIRST_SPACE_TYPE = SpaceType::SPACE_TYPE_INTERNAL;
143     static constexpr SpaceType SECOND_SPACE_TYPE = SpaceType::SPACE_TYPE_OBJECT;
144     static constexpr AllocatorType FIRST_ALLOCATOR_TYPE = AllocatorType::RUNSLOTS_ALLOCATOR;
145     static constexpr AllocatorType SECOND_ALLOCATOR_TYPE = AllocatorType::FREELIST_ALLOCATOR;
146 
147     uintptr_t first_pool_allocator_header_addr = RandHeapAddr();
148 
149     Pool first_pool(FIRST_POOL_SIZE, ToVoidPtr(FIRST_POOL_ADDR));
150     Pool second_pool(SECOND_POOL_SIZE, ToVoidPtr(SECOND_POOL_ADDR));
151 
152     AddToPoolMap(first_pool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, ToVoidPtr(first_pool_allocator_header_addr));
153     AddToPoolMap(second_pool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE);
154 
155     CheckRandomPoolAddress(first_pool, FIRST_SPACE_TYPE, FIRST_ALLOCATOR_TYPE, first_pool_allocator_header_addr);
156     // We haven't initialized second allocator header address.
157     // Therefore it must return a pointer to the first pool byte.
158     CheckRandomPoolAddress(second_pool, SECOND_SPACE_TYPE, SECOND_ALLOCATOR_TYPE, SECOND_POOL_ADDR);
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 
TEST_F(PoolMapTest,AddRemoveDifferentPoolsTest)168 TEST_F(PoolMapTest, AddRemoveDifferentPoolsTest)
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