OLD | NEW |
| (Empty) |
1 /* | |
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 | |
14 #include "webrtc/base/random.h" | |
15 #include "webrtc/logging/rtc_event_log/ringbuffer.h" | |
16 #include "webrtc/test/gtest.h" | |
17 | |
18 namespace { | |
19 template <typename T> | |
20 class 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 | |
59 namespace webrtc { | |
60 | |
61 // Verify that the ring buffer works as a simple queue. | |
62 TEST(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. | |
81 TEST(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. | |
112 TEST(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. | |
131 TEST(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 | |
156 TEST(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 | |
OLD | NEW |