| // |
| // 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 |