• 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 <array>
17 #include <cstdint>
18 #include <limits>
19 #include <string>
20 
21 #include "libpandabase/mem/mem.h"
22 #include "libpandabase/mem/mem_config.h"
23 #include "libpandabase/mem/pool_manager.h"
24 #include "libpandabase/utils/logger.h"
25 #include "libpandabase/mem/stack_like_allocator-inl.h"
26 #include "runtime/tests/allocator_test_base.h"
27 
28 namespace ark::mem {
29 class StackLikeAllocatorTest : public AllocatorTest<StackLikeAllocator<>> {
30 public:
31     NO_COPY_SEMANTIC(StackLikeAllocatorTest);
32     NO_MOVE_SEMANTIC(StackLikeAllocatorTest);
StackLikeAllocatorTest()33     StackLikeAllocatorTest()
34     {
35         static constexpr size_t INTERNAL_MEMORY_SIZE = 256_MB;
36         ark::mem::MemConfig::Initialize(0, INTERNAL_MEMORY_SIZE, 0, 0, INTERNAL_MEMORY_SIZE, 0);
37         // Logger::InitializeStdLogging(Logger::Level::DEBUG, Logger::Component::ALL);
38     }
39 
~StackLikeAllocatorTest()40     ~StackLikeAllocatorTest() override
41     {
42         // Logger::Destroy();
43         ark::mem::MemConfig::Finalize();
44     }
45 
46 protected:
AddMemoryPoolToAllocator(StackLikeAllocator<> & allocator)47     void AddMemoryPoolToAllocator([[maybe_unused]] StackLikeAllocator<> &allocator) override {}
AddMemoryPoolToAllocatorProtected(StackLikeAllocator<> & allocator)48     void AddMemoryPoolToAllocatorProtected([[maybe_unused]] StackLikeAllocator<> &allocator) override {}
AllocatedByThisAllocator(StackLikeAllocator<> & allocator,void * mem)49     bool AllocatedByThisAllocator([[maybe_unused]] StackLikeAllocator<> &allocator, [[maybe_unused]] void *mem) override
50     {
51         return false;
52     }
53 
PrintMemory(void * dst,size_t size)54     void PrintMemory(void *dst, size_t size)
55     {
56         std::cout << "Print at memory: ";
57         auto mem = static_cast<uint8_t *>(dst);
58         for (size_t i = 0; i < size; i++) {
59             std::cout << *mem++;  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
60         }
61         std::cout << std::endl;
62     }
63 
PrintAtIndex(size_t idx,size_t size)64     void PrintAtIndex(size_t idx, size_t size)
65     {
66         std::cout << "Print at index:  ";
67         ASSERT(idx + size < BYTE_ARRAY_SIZE);
68         auto mem = static_cast<uint8_t *>(&byteArray_[idx]);
69         for (size_t i = 0; i < size; i++) {
70             std::cout << *mem++;  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
71         }
72         std::cout << std::endl;
73     }
74 
SetUp()75     void SetUp() override
76     {
77         PoolManager::Initialize();
78     }
79 
TearDown()80     void TearDown() override
81     {
82         PoolManager::Finalize();
83     }
84 };
85 
TEST_F(StackLikeAllocatorTest,SmallAllocateTest)86 TEST_F(StackLikeAllocatorTest, SmallAllocateTest)
87 {
88     constexpr size_t ITERATIONS = 32;
89     constexpr size_t FRAME_SIZE = 256;
90     StackLikeAllocator<> alloc;
91     std::array<void *, ITERATIONS + 1> array {nullptr};
92     for (size_t i = 1; i <= ITERATIONS; i++) {
93         array[i] = alloc.Alloc(FRAME_SIZE);
94         ASSERT_NE(array[i], nullptr);
95         *(static_cast<uint64_t *>(array[i])) = i;
96     }
97     for (size_t i = ITERATIONS; i != 0; i--) {
98         ASSERT_EQ(*(static_cast<uint64_t *>(array[i])), i);
99         alloc.Free(array[i]);
100     }
101 }
102 
103 template <Alignment ALIGNMENT>
AlignmentTest(StackLikeAllocator<ALIGNMENT> & alloc)104 void AlignmentTest(StackLikeAllocator<ALIGNMENT> &alloc)
105 {
106     constexpr size_t MAX_SIZE = 256;
107     std::array<void *, MAX_SIZE + 1> array {nullptr};
108     for (size_t i = 1; i <= MAX_SIZE; i++) {
109         array[i] = alloc.Alloc(i * GetAlignmentInBytes(ALIGNMENT));
110         if (array[i] == nullptr) {
111             break;
112         }
113         ASSERT_NE(array[i], nullptr);
114         ASSERT_EQ(ToUintPtr(array[i]), AlignUp(ToUintPtr(array[i]), GetAlignmentInBytes(ALIGNMENT)));
115         *(static_cast<uint64_t *>(array[i])) = i;
116     }
117     for (size_t i = MAX_SIZE; i != 0; i--) {
118         if (array[i] == nullptr) {
119             break;
120         }
121         ASSERT_EQ(*(static_cast<uint64_t *>(array[i])), i);
122         alloc.Free(array[i]);
123     }
124 }
125 
TEST_F(StackLikeAllocatorTest,DefaultAlignmentTest)126 TEST_F(StackLikeAllocatorTest, DefaultAlignmentTest)
127 {
128     StackLikeAllocator<> alloc;
129     AlignmentTest(alloc);
130 }
131 
TEST_F(StackLikeAllocatorTest,NonDefaultAlignmentTest)132 TEST_F(StackLikeAllocatorTest, NonDefaultAlignmentTest)
133 {
134     StackLikeAllocator<Alignment::LOG_ALIGN_4> alloc4;
135     AlignmentTest(alloc4);
136     StackLikeAllocator<Alignment::LOG_ALIGN_5> alloc5;
137     AlignmentTest(alloc5);
138 }
139 
TEST_F(StackLikeAllocatorTest,CycledAllocateFreeForHugeFramesTest)140 TEST_F(StackLikeAllocatorTest, CycledAllocateFreeForHugeFramesTest)
141 {
142     constexpr size_t ITERATIONS = 1024;
143     constexpr size_t FRAME_SIZE = 512;
144     constexpr int CYCLE_COUNT = 16;
145 
146     StackLikeAllocator<> alloc;
147     std::vector<std::pair<void *, size_t>> vec;
148 
149     for (int j = 0; j < CYCLE_COUNT; j++) {
150         for (size_t i = 1; i <= ITERATIONS; i++) {
151             void *mem = alloc.Alloc(FRAME_SIZE);
152             ASSERT_TRUE(mem != nullptr) << "Didn't allocate " << FRAME_SIZE << " bytes in " << j
153                                         << " cycle, seed: " << seed_;
154             vec.emplace_back(mem, SetBytesFromByteArray(mem, FRAME_SIZE));
155         }
156         for (size_t i = 1; i <= ITERATIONS / 2U; i++) {
157             std::pair<void *, size_t> lastPair = vec.back();
158             ASSERT_TRUE(CompareBytesWithByteArray(lastPair.first, FRAME_SIZE, lastPair.second))
159                 << "iteration: " << i << ", size: " << FRAME_SIZE << ", address: " << std::hex << lastPair.first
160                 << ", index in byte array: " << lastPair.second << ", seed: " << seed_;
161             alloc.Free(lastPair.first);
162             vec.pop_back();
163         }
164     }
165     while (!vec.empty()) {
166         std::pair<void *, size_t> lastPair = vec.back();
167         ASSERT_TRUE(CompareBytesWithByteArray(lastPair.first, FRAME_SIZE, lastPair.second))
168             << "vector size: " << vec.size() << ", size: " << FRAME_SIZE << ", address: " << std::hex << lastPair.first
169             << ", index in byte array: " << lastPair.second << ", seed: " << seed_;
170         alloc.Free(lastPair.first);
171         vec.pop_back();
172     }
173 }
174 
TEST_F(StackLikeAllocatorTest,CheckAddrInsideAllocator)175 TEST_F(StackLikeAllocatorTest, CheckAddrInsideAllocator)
176 {
177     static constexpr size_t FRAME_SIZE = 256;
178     static constexpr size_t ALLOCATION_SIZE = 10;
179     void *invalidAddr = std::malloc(ALLOCATION_SIZE);  // NOLINT(cppcoreguidelines-no-malloc)
180 
181     StackLikeAllocator<> alloc;
182     ASSERT_FALSE(alloc.Contains(invalidAddr));  // NOLINT(clang-analyzer-unix.Malloc)
183 
184     void *addr1Inside = alloc.Alloc(FRAME_SIZE);
185     ASSERT_TRUE(alloc.Contains(addr1Inside));
186     ASSERT_FALSE(alloc.Contains(invalidAddr));  // NOLINT(clang-analyzer-unix.Malloc)
187 
188     alloc.Free(addr1Inside);
189     ASSERT_FALSE(alloc.Contains(addr1Inside));
190     ASSERT_FALSE(alloc.Contains(invalidAddr));
191 
192     addr1Inside = alloc.Alloc(FRAME_SIZE);
193 
194     auto *addr2Inside = alloc.Alloc(FRAME_SIZE * 2);
195     ASSERT_TRUE(alloc.Contains(addr1Inside));
196     ASSERT_TRUE(alloc.Contains(addr2Inside));
197     ASSERT_FALSE(alloc.Contains(invalidAddr));
198     free(invalidAddr);  // NOLINT(cppcoreguidelines-no-malloc)
199 }
200 }  // namespace ark::mem
201