• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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