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 "mem/arena.h"
17#include "mem/pool_manager.h"
18#include "mem/mem.h"
19#include "mem/mem_config.h"
20#include "mem/mmap_mem_pool-inl.h"
21
22#include "gtest/gtest.h"
23#include "utils/logger.h"
24
25namespace panda {
26
27class ArenaTest : public testing::Test {
28public:
29    ArenaTest()
30    {
31        panda::mem::MemConfig::Initialize(0, 16_MB, 0, 0);
32        PoolManager::Initialize();
33    }
34
35    ~ArenaTest()
36    {
37        PoolManager::Finalize();
38        panda::mem::MemConfig::Finalize();
39    }
40
41protected:
42    static constexpr size_t ARENA_SIZE = 1_MB;
43
44    template <class ArenaT>
45    ArenaT *CreateArena(size_t size)
46    {
47        return PoolManager::GetMmapMemPool()->AllocArena<ArenaT>(size, SpaceType::SPACE_TYPE_INTERNAL,
48                                                                 AllocatorType::ARENA_ALLOCATOR);
49    }
50
51    template <class ArenaT>
52    void GetOccupiedAndFreeSizeTestImplementation(size_t arena_size, size_t alloc_size)
53    {
54        ASSERT_TRUE(arena_size != 0);
55        ASSERT_TRUE(alloc_size != 0);
56        ArenaT *arena = CreateArena<ArenaT>(arena_size);
57        size_t old_free_size = arena->GetFreeSize();
58        ASSERT_TRUE(arena->Alloc(alloc_size) != nullptr);
59        ASSERT_TRUE(arena->GetOccupiedSize() == alloc_size);
60        ASSERT_TRUE(old_free_size - alloc_size == arena->GetFreeSize());
61    }
62
63    template <class ArenaT>
64    void ResizeAndResetTestImplementation(size_t arena_size, size_t alloc_size)
65    {
66        constexpr const int64_t immTwo = 2;
67        ASSERT_TRUE(arena_size != 0);
68        ASSERT_TRUE(alloc_size != 0);
69        ArenaT *arena = CreateArena<ArenaT>(arena_size);
70        ASSERT_TRUE(alloc_size * immTwo <= arena->GetFreeSize());
71        void *first_allocation = arena->Alloc(alloc_size);
72        void *second_allocation = arena->Alloc(alloc_size);
73        ASSERT_TRUE(first_allocation != nullptr);
74        ASSERT_TRUE(first_allocation != nullptr);
75        ASSERT_TRUE(arena->GetOccupiedSize() == immTwo * alloc_size);
76        arena->Resize(alloc_size);
77        ASSERT_TRUE(arena->GetOccupiedSize() == alloc_size);
78        void *third_allocation = arena->Alloc(alloc_size);
79        // we expect that we get the same address
80        ASSERT_TRUE(ToUintPtr(second_allocation) == ToUintPtr(third_allocation));
81        ASSERT_TRUE(arena->GetOccupiedSize() == immTwo * alloc_size);
82        arena->Reset();
83        ASSERT_TRUE(arena->GetOccupiedSize() == 0);
84    }
85};
86
87TEST_F(ArenaTest, GetOccupiedAndFreeSizeTest)
88{
89    static constexpr size_t ALLOC_SIZE = AlignUp(ARENA_SIZE / 2, GetAlignmentInBytes(ARENA_DEFAULT_ALIGNMENT));
90    static constexpr Alignment ARENA_ALIGNMENT = LOG_ALIGN_4;
91    static constexpr size_t ALIGNED_ALLOC_SIZE = AlignUp(ALLOC_SIZE, GetAlignmentInBytes(ARENA_ALIGNMENT));
92    GetOccupiedAndFreeSizeTestImplementation<Arena>(ARENA_SIZE, ALLOC_SIZE);
93    GetOccupiedAndFreeSizeTestImplementation<AlignedArena<ARENA_ALIGNMENT>>(ARENA_SIZE, ALIGNED_ALLOC_SIZE);
94    GetOccupiedAndFreeSizeTestImplementation<DoubleLinkedAlignedArena<ARENA_ALIGNMENT>>(ARENA_SIZE, ALIGNED_ALLOC_SIZE);
95}
96
97TEST_F(ArenaTest, ResizeAndResetTest)
98{
99    static constexpr size_t ALLOC_SIZE = AlignUp(ARENA_SIZE / 3, GetAlignmentInBytes(ARENA_DEFAULT_ALIGNMENT));
100    static constexpr Alignment ARENA_ALIGNMENT = LOG_ALIGN_4;
101    static constexpr size_t ALIGNED_ALLOC_SIZE = AlignUp(ALLOC_SIZE, GetAlignmentInBytes(ARENA_ALIGNMENT));
102    ResizeAndResetTestImplementation<Arena>(ARENA_SIZE, ALLOC_SIZE);
103    ResizeAndResetTestImplementation<AlignedArena<ARENA_ALIGNMENT>>(ARENA_SIZE, ALIGNED_ALLOC_SIZE);
104    ResizeAndResetTestImplementation<DoubleLinkedAlignedArena<ARENA_ALIGNMENT>>(ARENA_SIZE, ALIGNED_ALLOC_SIZE);
105}
106
107}  // namespace panda
108