Source code

Revision control

Copy as Markdown

Other Tools

/*
* Copyright 2017 WebAssembly Community Group participants
*
* 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
*
*
* 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 <memory>
#include "wabt/circular-array.h"
using namespace wabt;
namespace {
struct TestObject {
static int construct_count;
static int destruct_count;
TestObject(int data = 0, int data2 = 0) : data(data), data2(data2) {
construct_count++;
}
TestObject(const TestObject& other) {
*this = other;
construct_count++;
}
TestObject& operator=(const TestObject& other) {
data = other.data;
data2 = other.data2;
return *this;
}
TestObject(TestObject&& other) { *this = std::move(other); }
TestObject& operator=(TestObject&& other) {
data = other.data;
data2 = other.data2;
other.moved = true;
return *this;
}
~TestObject() {
if (!moved) {
destruct_count++;
}
}
int data = 0;
int data2 = 0;
bool moved = false;
};
// static
int TestObject::construct_count = 0;
// static
int TestObject::destruct_count = 0;
class CircularArrayTest : public ::testing::Test {
protected:
virtual void SetUp() {
// Reset to 0 even if the previous test leaked objects to keep the tests
// independent.
TestObject::construct_count = 0;
TestObject::destruct_count = 0;
}
virtual void TearDown() {
ASSERT_EQ(0, TestObject::construct_count - TestObject::destruct_count)
<< "construct count: " << TestObject::construct_count
<< ", destruct_count: " << TestObject::destruct_count;
}
template <size_t N>
void AssertCircularArrayEq(const CircularArray<TestObject, N>& ca,
const std::vector<int>& expected) {
if (expected.empty()) {
ASSERT_EQ(0U, ca.size());
ASSERT_TRUE(ca.empty());
} else {
ASSERT_EQ(expected.size(), ca.size());
ASSERT_FALSE(ca.empty());
ASSERT_EQ(expected.front(), ca.front().data);
ASSERT_EQ(expected.back(), ca.back().data);
for (size_t i = 0; i < ca.size(); ++i) {
ASSERT_EQ(expected[i], ca.at(i).data);
ASSERT_EQ(expected[i], ca[i].data);
}
}
}
};
} // end anonymous namespace
// Basic API tests
TEST_F(CircularArrayTest, default_constructor) {
CircularArray<TestObject, 2> ca;
}
TEST_F(CircularArrayTest, at) {
CircularArray<TestObject, 2> ca;
ca.push_back(TestObject(1));
ca.push_back(TestObject(2));
ASSERT_EQ(1, ca.at(0).data);
ASSERT_EQ(2, ca.at(1).data);
}
TEST_F(CircularArrayTest, const_at) {
CircularArray<TestObject, 2> ca;
const auto& cca = ca;
ca.push_back(TestObject(1));
ca.push_back(TestObject(2));
ASSERT_EQ(1, cca.at(0).data);
ASSERT_EQ(2, cca.at(1).data);
}
TEST_F(CircularArrayTest, operator_brackets) {
CircularArray<TestObject, 2> ca;
ca.push_back(TestObject(1));
ca.push_back(TestObject(2));
ASSERT_EQ(1, ca[0].data);
ASSERT_EQ(2, ca[1].data);
}
TEST_F(CircularArrayTest, const_operator_brackets) {
CircularArray<TestObject, 2> ca;
const auto& cca = ca;
ca.push_back(TestObject(1));
ca.push_back(TestObject(2));
ASSERT_EQ(1, cca[0].data);
ASSERT_EQ(2, cca[1].data);
}
TEST_F(CircularArrayTest, back) {
CircularArray<TestObject, 2> ca;
ca.push_back(TestObject(1));
ASSERT_EQ(1, ca.back().data);
ca.push_back(TestObject(2));
ASSERT_EQ(2, ca.back().data);
}
TEST_F(CircularArrayTest, const_back) {
CircularArray<TestObject, 2> ca;
const auto& cca = ca;
ca.push_back(TestObject(1));
ASSERT_EQ(1, cca.back().data);
ca.push_back(TestObject(2));
ASSERT_EQ(2, cca.back().data);
}
TEST_F(CircularArrayTest, empty) {
CircularArray<TestObject, 2> ca;
ASSERT_TRUE(ca.empty());
ca.push_back(TestObject(1));
ASSERT_FALSE(ca.empty());
ca.push_back(TestObject(2));
ASSERT_FALSE(ca.empty());
ca.pop_back();
ASSERT_FALSE(ca.empty());
ca.pop_back();
ASSERT_TRUE(ca.empty());
}
TEST_F(CircularArrayTest, front) {
CircularArray<TestObject, 2> ca;
ca.push_back(TestObject(1));
ASSERT_EQ(1, ca.front().data);
ca.push_back(TestObject(2));
ASSERT_EQ(1, ca.front().data);
}
TEST_F(CircularArrayTest, const_front) {
CircularArray<TestObject, 2> ca;
const auto& cca = ca;
ca.push_back(TestObject(1));
ASSERT_EQ(1, cca.front().data);
ca.push_back(TestObject(2));
ASSERT_EQ(1, cca.front().data);
}
TEST_F(CircularArrayTest, size) {
CircularArray<TestObject, 2> ca;
ASSERT_EQ(0U, ca.size());
ca.push_back(TestObject(1));
ASSERT_EQ(1U, ca.size());
ca.push_back(TestObject(2));
ASSERT_EQ(2U, ca.size());
ca.pop_back();
ASSERT_EQ(1U, ca.size());
ca.pop_back();
ASSERT_EQ(0U, ca.size());
}
TEST_F(CircularArrayTest, clear) {
CircularArray<TestObject, 2> ca;
ca.push_back(TestObject(1));
ca.push_back(TestObject(2));
ASSERT_EQ(2U, ca.size());
ca.clear();
ASSERT_EQ(0U, ca.size());
}
// More involved tests
TEST_F(CircularArrayTest, circular) {
CircularArray<TestObject, 4> ca;
ca.push_back(TestObject(1));
AssertCircularArrayEq(ca, {1});
ca.push_back(TestObject(2));
AssertCircularArrayEq(ca, {1, 2});
ca.push_back(TestObject(3));
AssertCircularArrayEq(ca, {1, 2, 3});
ca.pop_front();
AssertCircularArrayEq(ca, {2, 3});
ca.push_back(TestObject(4));
AssertCircularArrayEq(ca, {2, 3, 4});
ca.pop_front();
AssertCircularArrayEq(ca, {3, 4});
ca.pop_front();
AssertCircularArrayEq(ca, {4});
ca.push_back(TestObject(5));
AssertCircularArrayEq(ca, {4, 5});
ca.push_back(TestObject(6));
AssertCircularArrayEq(ca, {4, 5, 6});
ca.pop_back();
AssertCircularArrayEq(ca, {4, 5});
ca.pop_back();
AssertCircularArrayEq(ca, {4});
ca.pop_front();
AssertCircularArrayEq(ca, {});
}