1 #include <iostream>
2 #include <chrono>
3 #include <future>
4 #include <thread>
5 #include <condition_variable>
6 #include "gtest/gtest.h"
7 #define SRT_TEST_CIRCULAR_BUFFER
8 #include "api.h"
9 #include "common.h"
10
11 using namespace std;
12
13
14 // To test CircularBuffer
15 struct Double
16 {
17 double d;
18 size_t instance;
19 static size_t sourceid;
20
DoubleDouble21 Double(): d(0.0)
22 {
23 instance = ++sourceid;
24 IF_HEAVY_LOGGING(cerr << "(Double/" << instance << ": empty costruction)\n");
25 }
26
DoubleDouble27 Double(double dd): d(dd)
28 {
29 instance = ++sourceid;
30 IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " init construction:" << dd << ")\n");
31 }
32
DoubleDouble33 Double(const Double& dd): d(dd.d)
34 {
35 instance = ++sourceid;
36 IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy construction:" << dd.d << " object/" << dd.instance << ")\n");
37 }
38
operator doubleDouble39 operator double() { return d; }
40
~DoubleDouble41 ~Double()
42 {
43 IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " destruction:" << d << ")\n");
44 }
45
operator =Double46 void operator=(double dd)
47 {
48 IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy assignment:" << d << " -> " << dd << " value)\n");
49 d = dd;
50 }
51
operator =Double52 void operator=(const Double& dd)
53 {
54 IF_HEAVY_LOGGING(cerr << "(Double:/" << instance << " copy assignment:" << d << " -> " << dd.d << " object/" << dd.instance << ")\n");
55 d = dd.d;
56 }
57
58 // Required for template-based gtest :(
operator ==(const Double & l,double r)59 friend bool operator==(const Double& l, double r) { return l.d == r; }
operator ==(double l,const Double r)60 friend bool operator==(double l, const Double r) { return l == r.d; }
operator ==Double61 bool operator == (const Double& r) { return d == r; }
62 };
63
64 size_t Double::sourceid = 0;
65
66
67 template <class Val> inline
ShowCircularBuffer(const CircularBuffer<Val> & buf)68 void ShowCircularBuffer(const CircularBuffer<Val>& buf)
69 {
70 cerr << "SIZE: " << buf.size() << " FREE:" << buf.spaceleft() << " BEGIN:" << buf.m_xBegin << " END: " << buf.m_xEnd << endl;
71 for (int i = 0; i < buf.size(); ++i)
72 {
73 Double v;
74 if (buf.get(i, (v)))
75 cerr << "[" << i << "] = " << v << endl;
76 else
77 cerr << "[" << i << "] EMPTY!\n";
78 }
79 }
80
81 struct Add
82 {
83 Double v;
AddAdd84 Add(const Double& vv): v(vv) {}
operator ()Add85 void operator()(Double& accessed, bool isnew)
86 {
87 if (isnew)
88 accessed = v;
89 else
90 accessed = Double(accessed.d + v.d);
91 }
92 };
93
94
TEST(CircularBuffer,Overall)95 TEST(CircularBuffer, Overall)
96 {
97 using namespace std;
98
99 // Create some odd number of elements in a circular buffer.
100
101 CircularBuffer<Double> buf(7);
102
103 cerr << dec;
104
105 // Now, add 3 elements to it and check if succeeded.
106 buf.push(11.2);
107 buf.push(12.3);
108 buf.push(13.4);
109
110 IF_HEAVY_LOGGING(cerr << "After adding 3 elements: size=" << buf.size() << " capacity=" << buf.capacity() << ":\n");
111 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
112 ASSERT_EQ(buf.size(), 3);
113
114 IF_HEAVY_LOGGING(cerr << "Adding element at position 5:\n");
115 EXPECT_TRUE(buf.set(5, 15.5));
116 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
117 ASSERT_EQ(buf.size(), 6);
118
119 IF_HEAVY_LOGGING(cerr << "Adding element at position 7 (should fail):\n");
120 EXPECT_FALSE(buf.set(7, 10.0));
121 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
122 ASSERT_EQ(buf.size(), 6);
123
124 IF_HEAVY_LOGGING(cerr << "Dropping first 2 elements:\n");
125 buf.drop(2);
126 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
127 ASSERT_EQ(buf.size(), 4);
128
129 IF_HEAVY_LOGGING(cerr << "Adding again element at position 6 (should roll):\n");
130 buf.set(6, 22.1);
131 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
132
133 IF_HEAVY_LOGGING(cerr << "Adding element at existing position 2 (overwrite):\n");
134 buf.set(2, 33.1);
135 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
136
137 IF_HEAVY_LOGGING(cerr << "Adding element at existing position 3 (no overwrite):\n");
138 buf.set(3, 44.4, false);
139 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
140
141 Double output;
142 // [0] = 13.4 (after dropping first 2 elements)
143 EXPECT_TRUE(buf.get(0, (output)));
144 ASSERT_EQ(output, 13.4);
145 // [2] = 33.1 overwriting
146 EXPECT_TRUE(buf.get(2, (output)));
147 ASSERT_EQ(output, 33.1);
148 // [3] = was 15.5, requested to set 44.4, but not overwriting
149 EXPECT_TRUE(buf.get(3, (output)));
150 ASSERT_EQ(output, 15.5);
151 // [6] = 22.1 (as set with rolling)
152 EXPECT_TRUE(buf.get(6, (output)));
153 ASSERT_EQ(output, 22.1);
154
155 IF_HEAVY_LOGGING(cerr << "Dropping first 4 positions:\n");
156 buf.drop(4);
157 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
158 EXPECT_TRUE(buf.get(2, (output))); // Was 6 before dropping
159 ASSERT_EQ(output.d, 22.1);
160
161 IF_HEAVY_LOGGING(cerr << "Pushing 1 aslong there is capacity:\n");
162 int i = 0;
163 while (buf.push(1) != -1)
164 {
165 IF_HEAVY_LOGGING(cerr << "Pushed, begin=" << buf.m_xBegin << " end=" << buf.m_xEnd << endl);
166 ++i;
167 }
168 IF_HEAVY_LOGGING(cerr << "Done " << i << " operations, buffer:\n");
169 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
170
171 IF_HEAVY_LOGGING(cerr << "Updating value at position 5:\n");
172 EXPECT_TRUE(buf.update(5, Add(3.33)));
173 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
174 EXPECT_TRUE(buf.get(5, (output)));
175 ASSERT_EQ(output, 4.33);
176
177 int offset = 9;
178 IF_HEAVY_LOGGING(cerr << "Forced adding at position 9 with dropping (capacity: " << buf.capacity() << "):\n");
179 // State we already know it has failed. Calculate drop size.
180 int dropshift = offset - (buf.capacity() - 1); // buf.capacity()-1 is the latest position
181 offset -= dropshift;
182 IF_HEAVY_LOGGING(cerr << "Need to drop: " << dropshift << " New offset:" << offset << endl);
183 ASSERT_GE(dropshift, 0);
184 if (dropshift > 0)
185 {
186 buf.drop(dropshift);
187 IF_HEAVY_LOGGING(cerr << "AFTER DROPPING:\n");
188 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
189 EXPECT_TRUE(buf.set(offset, 99.1, true));
190
191 // size() - 1 is the latest possible offset
192 ASSERT_EQ(buf.size() - 1 + dropshift, 9);
193 }
194 else
195 {
196 IF_HEAVY_LOGGING(cerr << "NEGATIVE DROP!\n");
197 }
198 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
199 int size = buf.size();
200
201 IF_HEAVY_LOGGING(cerr << "Dropping rest of the items (passing " << (size) << "):\n");
202
203 // NOTE: 'drop' gets the POSITION as argument, but this position
204 // is allowed to be past the last addressable position. When passing
205 // the current size, it should make the container empty.
206 buf.drop(size);
207 EXPECT_TRUE(buf.empty());
208
209 IF_HEAVY_LOGGING(ShowCircularBuffer(buf));
210
211 IF_HEAVY_LOGGING(cerr << "DONE.\n");
212 }
213
TEST(ConfigString,Setting)214 TEST(ConfigString, Setting)
215 {
216 using namespace std;
217
218 static const auto STRSIZE = 20;
219 StringStorage<STRSIZE> s;
220
221 EXPECT_TRUE(s.empty());
222 EXPECT_EQ(s.size(), 0U);
223 EXPECT_EQ(s.str(), std::string());
224
225 char example_ac1[] = "example_long";
226 char example_ac2[] = "short";
227 char example_ac3[] = "example_longer";
228 char example_acx[] = "example_long_excessively";
229 char example_ace[] = "";
230
231 // According to the standard, this array gets automatically
232 // the number of characters + 1 for terminating 0. Get sizeof()-1
233 // to get the number of characters.
234
235 EXPECT_TRUE(s.set(example_ac1, sizeof (example_ac1)-1));
236 EXPECT_EQ(s.size(), sizeof (example_ac1)-1);
237 EXPECT_FALSE(s.empty());
238
239 EXPECT_TRUE(s.set(example_ac2, sizeof (example_ac2)-1));
240 EXPECT_EQ(s.size(), sizeof (example_ac2)-1);
241
242 EXPECT_TRUE(s.set(example_ac3, sizeof (example_ac3)-1));
243 EXPECT_EQ(s.size(), sizeof (example_ac3)-1);
244
245 EXPECT_FALSE(s.set(example_acx, sizeof (example_acx)-1));
246 EXPECT_EQ(s.size(), sizeof (example_ac3)-1);
247
248 EXPECT_TRUE(s.set(example_ace, sizeof (example_ace)-1));
249 EXPECT_EQ(s.size(), 0U);
250
251 string example_s1 = "example_long";
252 string example_s2 = "short";
253 string example_s3 = "example_longer";
254 string example_sx = "example_long_excessively";
255 string example_se = "";
256
257 EXPECT_TRUE(s.set(example_s1));
258 EXPECT_EQ(s.size(), example_s1.size());
259 EXPECT_FALSE(s.empty());
260
261 EXPECT_TRUE(s.set(example_s2));
262 EXPECT_EQ(s.size(), example_s2.size());
263
264 EXPECT_TRUE(s.set(example_s3));
265 EXPECT_EQ(s.size(), example_s3.size());
266
267 EXPECT_FALSE(s.set(example_sx));
268 EXPECT_EQ(s.size(), example_s3.size());
269
270 EXPECT_TRUE(s.set(example_se));
271 EXPECT_EQ(s.size(), 0U);
272 EXPECT_TRUE(s.empty());
273 }
274