blob: dec47a45f4e59c04b4ddc4fb4a95d54cf42f12c6 [file] [log] [blame]
/*
* Copyright (C) 2016 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 "memory_manager.h"
#include "stack.h"
#include "test_utilities.h"
#include <gtest/gtest.h>
#include <memory>
namespace gapir {
namespace test {
namespace {
const uint32_t MEMORY_SIZE = 4096;
const uint32_t STACK_CAPACITY = 128;
const uint32_t CONSTANT_SIZE = 128;
static const uint8_t CONSTANT_MEMORY[CONSTANT_SIZE] = {};
class StackTest : public ::testing::Test {
protected:
virtual void SetUp() {
std::vector<uint32_t> memorySizes = {MEMORY_SIZE};
mMemoryManager.reset(new MemoryManager(memorySizes));
mStack.reset(new Stack(STACK_CAPACITY, mMemoryManager.get()));
mMemoryManager->setConstantMemory(std::make_pair(&CONSTANT_MEMORY, CONSTANT_SIZE));
}
std::unique_ptr<MemoryManager> mMemoryManager;
std::unique_ptr<Stack> mStack;
};
void fillStack(Stack* stack, uint32_t n) {
for (unsigned i = 0; i < n; ++i) {
stack->push<uint32_t>(0);
}
}
} // anonymous namespace
TEST_F(StackTest, IsValid) {
EXPECT_TRUE(mStack->isValid());
}
TEST_F(StackTest, GetType) {
mStack->push<uint32_t>(123);
EXPECT_EQ(BaseType::Uint32, mStack->getTopType());
EXPECT_TRUE(mStack->isValid());
mStack->discard(1);
EXPECT_TRUE(mStack->isValid());
mStack->push<void*>(nullptr);
EXPECT_EQ(BaseType::AbsolutePointer, mStack->getTopType());
EXPECT_TRUE(mStack->isValid());
mStack->discard(1);
EXPECT_TRUE(mStack->isValid());
}
TEST_F(StackTest, GetTypeErrorEmptyStack) {
mStack->getTopType();
EXPECT_FALSE(mStack->isValid());
mStack->getTopType();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PushValue) {
uint32_t x = 123456789;
mStack->pushValue(BaseType::Uint32, x);
EXPECT_EQ(123456789, mStack->pop<uint32_t>());
EXPECT_TRUE(mStack->isValid());
}
TEST_F(StackTest, PushValueErrorStackOverflow) {
fillStack(mStack.get(), STACK_CAPACITY);
EXPECT_TRUE(mStack->isValid());
uint32_t x = 123456789;
mStack->pushValue(BaseType::Uint32, x);
EXPECT_FALSE(mStack->isValid());
mStack->pushValue(BaseType::Uint32, x);
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopVolatilePtrWithoutConvert) {
uint32_t offset = 0x123;
mStack->pushValue(BaseType::VolatilePointer, offset);
uint32_t pointer = mStack->popBaseValue();
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(offset, pointer);
}
TEST_F(StackTest, PopVolatilePtrWithConvert) {
uint32_t offset = 0x123;
mStack->pushValue(BaseType::VolatilePointer, offset);
const void* pointer = mStack->popVolatile<const void*>();
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(mMemoryManager->volatileToAbsolute(offset), pointer);
}
TEST_F(StackTest, PopConstantPtrWithoutConvert) {
uint32_t offset = 0x12;
mStack->pushValue(BaseType::ConstantPointer, offset);
uint32_t pointer = mStack->popBaseValue();
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(offset, pointer);
}
TEST_F(StackTest, PopConstantPtrWithConvert) {
uint32_t offset = 0x12;
mStack->pushValue(BaseType::ConstantPointer, offset);
const void* pointer = mStack->popConstant<const void*>();
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(mMemoryManager->constantToAbsolute(offset), pointer);
}
TEST_F(StackTest, PopErrorEmptyStack) {
mStack->pop<uint32_t>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopConstantErrorEmptyStack) {
mStack->popConstant<const void*>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopVolatileErrorEmptyStack) {
mStack->popVolatile<void*>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopBaseValueErrorEmptyStack) {
mStack->popBaseValue();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, Discard) {
mStack->push<uint32_t>(1234);
mStack->push<uint32_t>(2345);
mStack->push<uint32_t>(3356);
EXPECT_TRUE(mStack->isValid());
mStack->discard(2);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(1234, mStack->pop<uint32_t>());
}
TEST_F(StackTest, SequentialDiscard) {
mStack->push<uint32_t>(12);
mStack->push<uint32_t>(123);
mStack->push<uint32_t>(234);
mStack->discard(1);
mStack->push<uint32_t>(345);
mStack->discard(1);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(123, mStack->pop<uint32_t>());
}
TEST_F(StackTest, DiscardErrorStackUnderflow) {
mStack->push<uint32_t>(1234);
EXPECT_TRUE(mStack->isValid());
mStack->discard(2);
EXPECT_FALSE(mStack->isValid());
mStack->discard(1);
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, Clone) {
mStack->push<uint32_t>(1234);
mStack->push<uint32_t>(2345);
EXPECT_TRUE(mStack->isValid());
mStack->clone(1);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(1234, mStack->pop<uint32_t>());
EXPECT_EQ(2345, mStack->pop<uint32_t>());
EXPECT_EQ(1234, mStack->pop<uint32_t>());
EXPECT_TRUE(mStack->isValid());
}
TEST_F(StackTest, CloneErrorNonExistantIndex) {
mStack->clone(1);
EXPECT_FALSE(mStack->isValid());
mStack->clone(1);
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, CloneErrorOutsideOfCapacity) {
mStack->push<uint32_t>(1234);
mStack->push<uint32_t>(2345);
EXPECT_TRUE(mStack->isValid());
mStack->clone(3);
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, CloneErrorStackOverflow) {
fillStack(mStack.get(), STACK_CAPACITY);
EXPECT_TRUE(mStack->isValid());
mStack->clone(1);
EXPECT_FALSE(mStack->isValid());
mStack->clone(1);
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PushPop) {
mStack->push<uint32_t>(123);
EXPECT_TRUE(mStack->isValid());
ASSERT_EQ(123, mStack->pop<uint32_t>());
EXPECT_TRUE(mStack->isValid());
}
TEST_F(StackTest, PopVolatilePointer) {
uint32_t a = 0;
mStack->pushValue(BaseType::VolatilePointer, a);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(mMemoryManager->volatileToAbsolute(0), mStack->pop<void*>());
}
TEST_F(StackTest, PopConstantPointer) {
uint32_t a = 0;
mStack->pushValue(BaseType::ConstantPointer, a);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(mMemoryManager->constantToAbsolute(0), mStack->pop<const void*>());
}
TEST_F(StackTest, PopAbsolutePointer) {
uint32_t a = 0;
mStack->push<void*>(nullptr);
EXPECT_TRUE(mStack->isValid());
EXPECT_EQ(nullptr, mStack->pop<void*>());
}
TEST_F(StackTest, PopErrorStackUnderflow) {
mStack->pop<uint32_t>();
EXPECT_FALSE(mStack->isValid());
mStack->pop<uint32_t>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopErrorTypeMissmatch) {
mStack->push<uint16_t>(123);
EXPECT_TRUE(mStack->isValid());
mStack->pop<uint32_t>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PopErrorMismatchingPointerType) {
mStack->push<uint32_t>(123);
EXPECT_TRUE(mStack->isValid());
mStack->pop<void*>();
EXPECT_FALSE(mStack->isValid());
}
TEST_F(StackTest, PushErrorOverCapacity) {
fillStack(mStack.get(), STACK_CAPACITY);
EXPECT_TRUE(mStack->isValid());
mStack->push<uint32_t>(1);
EXPECT_FALSE(mStack->isValid());
mStack->push<uint32_t>(1);
EXPECT_FALSE(mStack->isValid());
}
} // namespace test
} // namespace gapir