blob: 7e672feb224f6d57c4759a5d4606284a501cda93 [file] [log] [blame]
terelius4311ba52016-04-22 12:40:37 -07001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 *
10 */
11
12#include <list>
13
terelius4311ba52016-04-22 12:40:37 -070014#include "webrtc/base/random.h"
skvladcc91d282016-10-03 18:31:22 -070015#include "webrtc/logging/rtc_event_log/ringbuffer.h"
kwibergac9f8762016-09-30 22:29:43 -070016#include "webrtc/test/gtest.h"
terelius4311ba52016-04-22 12:40:37 -070017
18namespace {
19template <typename T>
20class MovableType {
21 public:
22 MovableType() : value_(), moved_from_(false), moved_to_(false) {}
23 explicit MovableType(T value)
24 : value_(value), moved_from_(false), moved_to_(false) {}
25 MovableType(const MovableType<T>& other)
26 : value_(other.value_), moved_from_(false), moved_to_(false) {}
27 MovableType(MovableType<T>&& other)
28 : value_(other.value_), moved_from_(false), moved_to_(true) {
29 other.moved_from_ = true;
30 }
31
32 MovableType& operator=(const MovableType<T>& other) {
33 value_ = other.value_;
34 moved_from_ = false;
35 moved_to_ = false;
36 return *this;
37 }
38
39 MovableType& operator=(MovableType<T>&& other) {
40 value_ = other.value_;
41 moved_from_ = false;
42 moved_to_ = true;
43 other.moved_from_ = true;
44 return *this;
45 }
46
47 T Value() { return value_; }
48 bool IsMovedFrom() { return moved_from_; }
49 bool IsMovedTo() { return moved_to_; }
50
51 private:
52 T value_;
53 bool moved_from_;
54 bool moved_to_;
55};
56
57} // namespace
58
59namespace webrtc {
60
61// Verify that the ring buffer works as a simple queue.
62TEST(RingBufferTest, SimpleQueue) {
63 size_t capacity = 100;
64 RingBuffer<size_t> q(capacity);
65 EXPECT_TRUE(q.empty());
66 for (size_t i = 0; i < capacity; i++) {
67 q.push_back(i);
68 EXPECT_FALSE(q.empty());
69 }
70
71 for (size_t i = 0; i < capacity; i++) {
72 EXPECT_FALSE(q.empty());
73 EXPECT_EQ(i, q.front());
74 q.pop_front();
75 }
76 EXPECT_TRUE(q.empty());
77}
78
79// Do a "random" sequence of queue operations and verify that the
80// result is consistent with the same operation performed on a std::list.
81TEST(RingBufferTest, ConsistentWithStdList) {
82 Random prng(987654321ull);
83 size_t capacity = 10;
84 RingBuffer<int> q(capacity);
85 std::list<int> l;
86 EXPECT_TRUE(q.empty());
87 for (size_t i = 0; i < 100 * capacity; i++) {
88 bool insert = prng.Rand<bool>();
89 if ((insert && l.size() < capacity) || l.size() == 0) {
90 int x = prng.Rand<int>();
91 l.push_back(x);
92 q.push_back(x);
93 EXPECT_FALSE(q.empty());
94 } else {
95 EXPECT_FALSE(q.empty());
96 EXPECT_EQ(l.front(), q.front());
97 l.pop_front();
98 q.pop_front();
99 }
100 }
101 while (!l.empty()) {
102 EXPECT_FALSE(q.empty());
103 EXPECT_EQ(l.front(), q.front());
104 l.pop_front();
105 q.pop_front();
106 }
107 EXPECT_TRUE(q.empty());
108}
109
110// Test that the ringbuffer starts reusing elements from the front
111// when the queue becomes full.
112TEST(RingBufferTest, OverwriteOldElements) {
113 size_t capacity = 100;
114 size_t insertions = 3 * capacity + 25;
115 RingBuffer<size_t> q(capacity);
116 EXPECT_TRUE(q.empty());
117 for (size_t i = 0; i < insertions; i++) {
118 q.push_back(i);
119 EXPECT_FALSE(q.empty());
120 }
121
122 for (size_t i = insertions - capacity; i < insertions; i++) {
123 EXPECT_FALSE(q.empty());
124 EXPECT_EQ(i, q.front());
125 q.pop_front();
126 }
127 EXPECT_TRUE(q.empty());
128}
129
130// Test that the ringbuffer uses std::move when pushing an rvalue reference.
131TEST(RingBufferTest, MoveSemanticsForPushBack) {
132 size_t capacity = 100;
133 size_t insertions = 3 * capacity + 25;
134 RingBuffer<MovableType<size_t>> q(capacity);
135 EXPECT_TRUE(q.empty());
136 for (size_t i = 0; i < insertions; i++) {
137 MovableType<size_t> tmp(i);
138 EXPECT_FALSE(tmp.IsMovedFrom());
139 EXPECT_FALSE(tmp.IsMovedTo());
140 q.push_back(std::move(tmp));
141 EXPECT_TRUE(tmp.IsMovedFrom());
142 EXPECT_FALSE(tmp.IsMovedTo());
143 EXPECT_FALSE(q.empty());
144 }
145
146 for (size_t i = insertions - capacity; i < insertions; i++) {
147 EXPECT_FALSE(q.empty());
148 EXPECT_EQ(i, q.front().Value());
149 EXPECT_FALSE(q.front().IsMovedFrom());
150 EXPECT_TRUE(q.front().IsMovedTo());
151 q.pop_front();
152 }
153 EXPECT_TRUE(q.empty());
154}
155
156TEST(RingBufferTest, SmallCapacity) {
157 size_t capacity = 1;
158 RingBuffer<int> q(capacity);
159 EXPECT_TRUE(q.empty());
160 q.push_back(4711);
161 EXPECT_FALSE(q.empty());
162 EXPECT_EQ(4711, q.front());
163 q.push_back(1024);
164 EXPECT_FALSE(q.empty());
165 EXPECT_EQ(1024, q.front());
166 q.pop_front();
167 EXPECT_TRUE(q.empty());
168}
169
170} // namespace webrtc