blob: 2475dd52987ef430bfa2a3b1a0fbc25eee17ec2e [file] [log] [blame]
/*
* 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