blob: 62ace60c5e554ba57fe442f039ce910bea3df8e9 [file] [log] [blame]
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CircularBuffer_unittest:
// Tests of the CircularBuffer class
//
#include <gtest/gtest.h>
#include "common/CircularBuffer.h"
namespace angle
{
// Make sure the various constructors compile and do basic checks
TEST(CircularBuffer, Constructors)
{
CircularBuffer<int, 5> defaultContructor;
EXPECT_EQ(5u, defaultContructor.size());
CircularBuffer<int, 5> valueConstructor(3);
EXPECT_EQ(5u, valueConstructor.size());
EXPECT_EQ(3, valueConstructor.front());
CircularBuffer<int, 5> copy(valueConstructor);
EXPECT_EQ(5u, copy.size());
CircularBuffer<int, 5> copyRValue(std::move(valueConstructor));
EXPECT_EQ(5u, copyRValue.size());
}
// Make sure the destructor destroys all elements.
TEST(CircularBuffer, Destructor)
{
struct s
{
s() {}
s(int *c) : counter(c) {}
~s()
{
if (counter)
{
++*counter;
}
}
s(const s &) = default;
s &operator=(const s &) = default;
int *counter;
};
int destructorCount = 0;
{
CircularBuffer<s, 11> buf((s(&destructorCount)));
// Destructor called once for the temporary above.
EXPECT_EQ(destructorCount, 1);
// Change front index to be non-zero.
buf.next();
buf.next();
buf.next();
}
// Destructor should be called 11 more times, once for each element.
EXPECT_EQ(destructorCount, 12);
}
// Test circulating behavior.
TEST(CircularBuffer, Circulate)
{
CircularBuffer<int, 7> buf(128);
for (int i = 0; i < 7; ++i)
{
int &value = buf.front();
EXPECT_EQ(value, 128);
value = i + 10;
buf.next();
}
for (int i = 0; i < 93; ++i)
{
EXPECT_EQ(buf.front(), i % 7 + 10);
buf.next();
}
}
// Test iteration.
TEST(CircularBuffer, Iterate)
{
CircularBuffer<int, 3> buf(12);
for (int i = 0; i < 3; ++i)
{
int &value = buf.front();
buf.next();
EXPECT_EQ(value, 12);
value = i;
}
// Check that iteration returns all the values (with unknown order) regardless of where the
// front is pointing.
for (int i = 0; i < 10; ++i)
{
uint32_t valuesSeen = 0;
for (int value : buf)
{
valuesSeen |= 1 << value;
}
EXPECT_EQ(valuesSeen, 0x7u);
// Make sure iteration hasn't affected the front index.
EXPECT_EQ(buf.front(), i % 3);
buf.next();
}
}
// Tests buffer operations with a non copyable type.
TEST(CircularBuffer, NonCopyable)
{
struct s : angle::NonCopyable
{
s() : x(0) {}
s(s &&other) : x(other.x) {}
s &operator=(s &&other)
{
x = other.x;
return *this;
}
int x;
};
CircularBuffer<s, 4> buf;
for (int i = 0; i < 4; ++i)
{
s &value = buf.front();
value.x = i;
buf.next();
}
// Make the front index non-zero.
buf.next();
EXPECT_EQ(buf.front().x, 1);
CircularBuffer<s, 4> copy = std::move(buf);
for (int i = 0; i < 4; ++i)
{
EXPECT_EQ(copy.front().x, (i + 1) % 4);
copy.next();
}
}
} // namespace angle