1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include "berberis/base/arena_alloc.h"
20 #include "berberis/base/arena_list.h"
21 #include "berberis/base/arena_vector.h"
22 #include "berberis/base/mmap.h"
23
24 namespace berberis {
25
26 class ArenaTest : public ::testing::Test {
27 public:
28 ArenaTest() = default;
29
ArenaMappedSize()30 size_t ArenaMappedSize() {
31 size_t size = 0;
32 auto* block = arena_.blocks_;
33 while (block) {
34 size += block->size;
35 block = block->next;
36 }
37 return size;
38 }
39
BigMapSize(size_t requested_size,size_t align)40 size_t BigMapSize(size_t requested_size, size_t align) {
41 return AlignUpPageSize(AlignUp(sizeof(arena_internal::ArenaBlock), align) + requested_size);
42 }
43
44 protected:
45 static constexpr size_t kBlockSize = arena_internal::kDefaultArenaBlockSize;
46 static constexpr size_t kReallyBigSize = 8 * kBlockSize;
47 Arena arena_;
48 };
49
50 namespace {
51
52 struct Node {
53 unsigned elem1;
54 unsigned elem2;
55
Nodeberberis::__anonad649b4e0111::Node56 explicit Node(unsigned e) : elem1(e), elem2(e + 11) {}
57 };
58
59 using FastList = ArenaList<Node*>;
60 using FastVector = ArenaVector<Node*>;
61
TEST_F(ArenaTest,Smoke)62 TEST_F(ArenaTest, Smoke) {
63 char* p;
64
65 p = static_cast<char*>(arena_.Alloc(1, 1));
66 ASSERT_NE(p, nullptr);
67 p[0] = 'a';
68 ASSERT_EQ(ArenaMappedSize(), kBlockSize);
69
70 p = static_cast<char*>(arena_.Alloc(100, 2));
71 ASSERT_NE(p, nullptr);
72 p[99] = 'b';
73 ASSERT_EQ(ArenaMappedSize(), kBlockSize);
74
75 p = static_cast<char*>(arena_.Alloc(kBlockSize / 10, 4));
76 ASSERT_NE(p, nullptr);
77 p[kBlockSize / 10 - 1] = 'c';
78 ASSERT_EQ(ArenaMappedSize(), kBlockSize);
79
80 p = static_cast<char*>(arena_.Alloc(kReallyBigSize, 4));
81 ASSERT_NE(p, nullptr);
82 p[kReallyBigSize - 1] = 'z';
83 ASSERT_EQ(ArenaMappedSize(), kBlockSize + BigMapSize(kReallyBigSize, 4));
84 }
85
TEST_F(ArenaTest,Alloc)86 TEST_F(ArenaTest, Alloc) {
87 size_t requested_size = 0;
88 for (int i = 0; i < 4; ++i) {
89 for (size_t n = 1; n < 2 * kReallyBigSize; n *= 2) {
90 requested_size += n;
91 char* p = static_cast<char*>(arena_.Alloc(n, 1));
92 p[0] = 'a';
93 p[n - 1] = 'z';
94 }
95 }
96 ASSERT_GE(ArenaMappedSize(), requested_size);
97 }
98
TEST_F(ArenaTest,List)99 TEST_F(ArenaTest, List) {
100 FastList list(&arena_);
101
102 list.push_back(NewInArena<Node>(&arena_, 1));
103 list.push_back(NewInArena<Node>(&arena_, 2));
104
105 ASSERT_EQ(2u, list.size());
106 ASSERT_EQ(1u + 11, (*list.begin())->elem2);
107 ASSERT_EQ(2u, (*--list.end())->elem1);
108 ASSERT_EQ(ArenaMappedSize(), kBlockSize);
109 }
110
TEST_F(ArenaTest,Vector)111 TEST_F(ArenaTest, Vector) {
112 constexpr size_t kElems = 40000;
113 FastVector vector(kElems, nullptr, &arena_);
114
115 for (size_t i = 0; i < kElems; i++) {
116 vector[i] = NewInArena<Node>(&arena_, i);
117 }
118
119 ASSERT_EQ(kElems, vector.size());
120 ASSERT_EQ(0u, (*vector.begin())->elem1);
121 ASSERT_EQ(kElems - 1, vector[kElems - 1]->elem1);
122 ASSERT_GE(ArenaMappedSize(), kElems * sizeof(Node));
123 }
124
125 } // namespace
126
127 } // namespace berberis
128