blob: fb04b45ffdd718fbf0ddd0dbb470a59461f6aa97 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/escher/util/stack_allocator.h"
#include "gtest/gtest.h"
namespace {
using namespace escher;
TEST(StackAllocator, Integers) {
StackAllocator<int64_t, 1000> alloc;
int64_t* pair = alloc.Allocate(2);
pair[0] = 32;
pair[1] = 24;
int64_t* the_rest = alloc.Allocate(998);
int64_t* no_more = alloc.Allocate(1);
EXPECT_NE(pair, nullptr);
EXPECT_NE(the_rest, nullptr);
EXPECT_EQ(no_more, nullptr);
// Memory is left in its previous state after the allocator is reset. This
// isn't guaranteed by the API, but this checks that the implementation isn't
// slowing things down by unnecessarily overwriting the memory.
alloc.Reset();
pair = alloc.Allocate(2);
EXPECT_EQ(pair[0], 32);
EXPECT_EQ(pair[1], 24);
pair[0] = 33;
pair[1] = 25;
alloc.Reset();
pair = alloc.Allocate(2);
EXPECT_EQ(pair[0], 33);
EXPECT_EQ(pair[1], 25);
// Memory can be pre-initialized to a default value via AllocateFilled().
alloc.Reset();
pair = alloc.AllocateFilled(2);
EXPECT_EQ(pair[0], 0);
EXPECT_EQ(pair[1], 0);
alloc.Reset();
pair = alloc.Allocate(2);
EXPECT_EQ(pair[0], 0);
EXPECT_EQ(pair[1], 0);
// Memory can be pre-initialized to a specific value via AllocateFilled().
alloc.Reset();
pair = alloc.AllocateFilled(2, 19);
EXPECT_EQ(pair[0], 19);
EXPECT_EQ(pair[1], 19);
alloc.Reset();
pair = alloc.Allocate(2);
EXPECT_EQ(pair[0], 19);
EXPECT_EQ(pair[1], 19);
}
TEST(StackAllocator, ConstructableObjects) {
// Foo is default-constructible, and also has a 2-arg constructor.
class Foo {
public:
Foo() : Foo(16, 32) {}
Foo(int a, int b) : a_(a), b_(b) { c_ = a_ + b_; }
// Uncommenting this results in a compilation error, due to the requirement
// that StackAllocator can only be used with trivially-destructible types.
// ~Foo() { a = 0; b = 0; c = 0; }
int a() const { return a_; }
int b() const { return b_; }
int c() const { return c_; }
private:
int a_, b_, c_;
};
StackAllocator<Foo, 1000> alloc;
// Allocate half of the allocator's capacity, initializing each Foo with a
// default value.
Foo* foo = alloc.AllocateFilled(500);
for (size_t i = 0; i < 500; ++i) {
EXPECT_EQ(foo[i].a(), 16);
EXPECT_EQ(foo[i].b(), 32);
EXPECT_EQ(foo[i].c(), 48);
}
// Allocate the other half of the allocator's capacity, initializing each Foo
// with a specified value.
foo = alloc.AllocateFilled(500, Foo(11, 22));
for (size_t i = 0; i < 500; ++i) {
EXPECT_EQ(foo[i].a(), 11);
EXPECT_EQ(foo[i].b(), 22);
EXPECT_EQ(foo[i].c(), 33);
}
// No more space.
foo = alloc.AllocateFilled(1);
EXPECT_EQ(foo, nullptr);
// Memory is left in its previous state after the allocator is reset. This
// isn't guaranteed by the API, but this checks that the implementation isn't
// slowing things down by unnecessarily overwriting the memory.
alloc.Reset();
foo = alloc.Allocate(1000);
for (size_t i = 0; i < 500; ++i) {
EXPECT_EQ(foo[i].a(), 16);
EXPECT_EQ(foo[i].b(), 32);
EXPECT_EQ(foo[i].c(), 48);
}
for (size_t i = 500; i < 1000; ++i) {
EXPECT_EQ(foo[i].a(), 11);
EXPECT_EQ(foo[i].b(), 22);
EXPECT_EQ(foo[i].c(), 33);
}
// No more space.
foo = alloc.AllocateFilled(1);
EXPECT_EQ(foo, nullptr);
}
} // namespace