128 lines
3.3 KiB
C++
128 lines
3.3 KiB
C++
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "berberis/base/arena_alloc.h"
|
|
#include "berberis/base/arena_list.h"
|
|
#include "berberis/base/arena_vector.h"
|
|
#include "berberis/base/mmap.h"
|
|
|
|
namespace berberis {
|
|
|
|
class ArenaTest : public ::testing::Test {
|
|
public:
|
|
ArenaTest() = default;
|
|
|
|
size_t ArenaMappedSize() {
|
|
size_t size = 0;
|
|
auto* block = arena_.blocks_;
|
|
while (block) {
|
|
size += block->size;
|
|
block = block->next;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
size_t BigMapSize(size_t requested_size, size_t align) {
|
|
return AlignUpPageSize(AlignUp(sizeof(arena_internal::ArenaBlock), align) + requested_size);
|
|
}
|
|
|
|
protected:
|
|
static constexpr size_t kBlockSize = arena_internal::kDefaultArenaBlockSize;
|
|
static constexpr size_t kReallyBigSize = 8 * kBlockSize;
|
|
Arena arena_;
|
|
};
|
|
|
|
namespace {
|
|
|
|
struct Node {
|
|
unsigned elem1;
|
|
unsigned elem2;
|
|
|
|
explicit Node(unsigned e) : elem1(e), elem2(e + 11) {}
|
|
};
|
|
|
|
typedef ArenaList<Node*> FastList;
|
|
typedef ArenaVector<Node*> FastVector;
|
|
|
|
TEST_F(ArenaTest, Smoke) {
|
|
char* p;
|
|
|
|
p = static_cast<char*>(arena_.Alloc(1, 1));
|
|
ASSERT_NE(p, nullptr);
|
|
p[0] = 'a';
|
|
ASSERT_EQ(ArenaMappedSize(), kBlockSize);
|
|
|
|
p = static_cast<char*>(arena_.Alloc(100, 2));
|
|
ASSERT_NE(p, nullptr);
|
|
p[99] = 'b';
|
|
ASSERT_EQ(ArenaMappedSize(), kBlockSize);
|
|
|
|
p = static_cast<char*>(arena_.Alloc(kBlockSize / 10, 4));
|
|
ASSERT_NE(p, nullptr);
|
|
p[kBlockSize / 10 - 1] = 'c';
|
|
ASSERT_EQ(ArenaMappedSize(), kBlockSize);
|
|
|
|
p = static_cast<char*>(arena_.Alloc(kReallyBigSize, 4));
|
|
ASSERT_NE(p, nullptr);
|
|
p[kReallyBigSize - 1] = 'z';
|
|
ASSERT_EQ(ArenaMappedSize(), kBlockSize + BigMapSize(kReallyBigSize, 4));
|
|
}
|
|
|
|
TEST_F(ArenaTest, Alloc) {
|
|
size_t requested_size = 0;
|
|
for (int i = 0; i < 4; ++i) {
|
|
for (size_t n = 1; n < 2 * kReallyBigSize; n *= 2) {
|
|
requested_size += n;
|
|
char* p = static_cast<char*>(arena_.Alloc(n, 1));
|
|
p[0] = 'a';
|
|
p[n - 1] = 'z';
|
|
}
|
|
}
|
|
ASSERT_GE(ArenaMappedSize(), requested_size);
|
|
}
|
|
|
|
TEST_F(ArenaTest, List) {
|
|
FastList list(&arena_);
|
|
|
|
list.push_back(NewInArena<Node>(&arena_, 1));
|
|
list.push_back(NewInArena<Node>(&arena_, 2));
|
|
|
|
ASSERT_EQ(2u, list.size());
|
|
ASSERT_EQ(1u + 11, (*list.begin())->elem2);
|
|
ASSERT_EQ(2u, (*--list.end())->elem1);
|
|
ASSERT_EQ(ArenaMappedSize(), kBlockSize);
|
|
}
|
|
|
|
TEST_F(ArenaTest, Vector) {
|
|
constexpr size_t kElems = 40000;
|
|
FastVector vector(kElems, nullptr, &arena_);
|
|
|
|
for (unsigned i = 0; i < kElems; i++) {
|
|
vector[i] = NewInArena<Node>(&arena_, i);
|
|
}
|
|
|
|
ASSERT_EQ(kElems, vector.size());
|
|
ASSERT_EQ(0u, (*vector.begin())->elem1);
|
|
ASSERT_EQ(kElems - 1, vector[kElems - 1]->elem1);
|
|
ASSERT_GE(ArenaMappedSize(), kElems * sizeof(Node));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
} // namespace berberis
|