1
1
#include <array>
2
2
#include "gtest/gtest.h"
3
3
#include "buffer.h"
4
+
#include <array>
4
5
5
6
using namespace srt;
7
+
using namespace std;
6
8
7
-
9
+
// Check the available size of the receiver buffer.
8
10
TEST(CRcvBuffer, Create)
9
11
{
10
12
const int buffer_size_pkts = 128;
11
13
CUnitQueue unit_queue;
12
14
CRcvBuffer rcv_buffer(&unit_queue, buffer_size_pkts);
13
-
14
-
EXPECT_EQ(rcv_buffer.getAvailBufSize(), buffer_size_pkts - 1); // logic
15
+
// One buffer cell is always unavailable as it is use to distinguish
16
+
// two buffer states: empty and full.
17
+
EXPECT_EQ(rcv_buffer.getAvailBufSize(), buffer_size_pkts - 1);
15
18
}
16
19
17
-
20
+
// Fill the buffer full, and check adding more data results in an error.
18
21
TEST(CRcvBuffer, FullBuffer)
19
22
{
20
23
const int buffer_size_pkts = 16;
@@ -51,10 +54,10 @@ TEST(CRcvBuffer, FullBuffer)
51
54
}
52
55
}
53
56
54
-
57
+
// BUG!!!
55
58
// In this test case a packet is added to receiver buffer with offset 1,
56
59
// thus leaving offset 0 with an empty pointer.
57
-
// The buffer sais it is not empty, and the data is available
60
+
// The buffer says it is not empty, and the data is available
58
61
// to be read, but reading should cause error.
59
62
TEST(CRcvBuffer, ReadDataIPE)
60
63
{
@@ -73,18 +76,19 @@ TEST(CRcvBuffer, ReadDataIPE)
73
76
EXPECT_EQ(rcv_buffer.getAvailBufSize(), buffer_size_pkts - 1);
74
77
75
78
EXPECT_FALSE(rcv_buffer.isRcvDataAvailable());
79
+
80
+
// BUG. Acknowledging an empty position must not result in a read-readiness.
76
81
rcv_buffer.ackData(1);
77
82
EXPECT_TRUE(rcv_buffer.isRcvDataAvailable());
83
+
EXPECT_TRUE(rcv_buffer.isRcvDataReady());
78
84
79
85
EXPECT_EQ(rcv_buffer.getAvailBufSize(), buffer_size_pkts - 2);
80
-
81
-
std::cerr << "Expecting IPE message: \n";
82
-
std::array<char, payload_size> buff;
86
+
cerr << "Expecting IPE message: \n";
87
+
array<char, payload_size> buff;
83
88
const int res = rcv_buffer.readBuffer(buff.data(), buff.size());
84
89
EXPECT_EQ(res, -1);
85
90
}
86
91
87
-
88
92
TEST(CRcvBuffer, ReadData)
89
93
{
90
94
const int buffer_size_pkts = 16;
@@ -112,7 +116,6 @@ TEST(CRcvBuffer, ReadData)
112
116
EXPECT_EQ(size_t(res), payload_size);
113
117
}
114
118
115
-
116
119
TEST(CRcvBuffer, AddData)
117
120
{
118
121
const int buffer_size_pkts = 16;
@@ -159,4 +162,232 @@ TEST(CRcvBuffer, AddData)
159
162
EXPECT_EQ(rcv_buffer.addData(unit, 1), -1);
160
163
}
161
164
165
+
TEST(CRcvBuffer, OneMessageInSeveralPackets)
166
+
{
167
+
const int buffer_size_pkts = 16;
168
+
CUnitQueue unit_queue;
169
+
unit_queue.init(buffer_size_pkts, 1500, AF_INET);
170
+
CRcvBuffer rcv_buffer(&unit_queue, buffer_size_pkts);
171
+
172
+
const int initial_seqno = 1000;
173
+
const int message_len_in_pkts = 4;
174
+
const size_t payload_size = 1456;
175
+
// Add a number of units (packets) to the buffer
176
+
// equal to the buffer size in packets
177
+
for (int i = 0; i < message_len_in_pkts; ++i)
178
+
{
179
+
CUnit* unit = unit_queue.getNextAvailUnit();
180
+
EXPECT_NE(unit, nullptr);
181
+
182
+
CPacket& packet = unit->m_Packet;
183
+
packet.setLength(payload_size);
184
+
packet.m_iSeqNo = initial_seqno + i;
185
+
packet.m_iMsgNo = PacketBoundaryBits(PB_SUBSEQUENT);
186
+
if (i == 0)
187
+
packet.m_iMsgNo |= PacketBoundaryBits(PB_FIRST);
188
+
const bool is_last_packet = (i == message_len_in_pkts - 1);
189
+
if (is_last_packet)
190
+
packet.m_iMsgNo |= PacketBoundaryBits(PB_LAST);
191
+
192
+
EXPECT_EQ(rcv_buffer.addData(unit, i), 0);
193
+
}
194
+
195
+
rcv_buffer.ackData(message_len_in_pkts);
196
+
197
+
cout << "Buffer size before reading: " << rcv_buffer.getAvailBufSize() << endl;
198
+
std::array<char, payload_size> buff;
199
+
cout << "Reading one packet of the 4-packet message" << endl;
200
+
const int res = rcv_buffer.readMsg(buff.data(), buff.size());
201
+
EXPECT_EQ(res, payload_size);
202
+
cout << "Buffer size after reading: " << rcv_buffer.getAvailBufSize() << endl;
203
+
}
204
+
205
+
class TestRcvBufferRead
206
+
: public ::testing::Test
207
+
{
208
+
protected:
209
+
TestRcvBufferRead()
210
+
{
211
+
// initialization code here
212
+
}
213
+
214
+
~TestRcvBufferRead()
215
+
{
216
+
// cleanup any pending stuff, but no exceptions allowed
217
+
}
162
218
219
+
protected:
220
+
// SetUp() is run immediately before a test starts.
221
+
void SetUp() override
222
+
{
223
+
// make_unique is unfortunatelly C++14
224
+
m_unit_queue = unique_ptr<CUnitQueue>(new CUnitQueue);
225
+
m_unit_queue->init(m_buff_size_pkts, 1500, AF_INET);
226
+
m_rcv_buffer = unique_ptr<CRcvBuffer>(new CRcvBuffer(m_unit_queue.get(), m_buff_size_pkts));
227
+
}
228
+
229
+
void TearDown() override
230
+
{
231
+
// Code here will be called just after the test completes.
232
+
// OK to throw exceptions from here if needed.
233
+
m_unit_queue.reset();
234
+
m_rcv_buffer.reset();
235
+
}
236
+
237
+
public:
238
+
void addMessage(size_t msg_len_pkts, int start_seqno, bool out_of_order = false)
239
+
{
240
+
const int msg_offset = start_seqno - m_init_seqno;
241
+
242
+
for (size_t i = 0; i < msg_len_pkts; ++i)
243
+
{
244
+
CUnit* unit = m_unit_queue->getNextAvailUnit();
245
+
EXPECT_NE(unit, nullptr);
246
+
247
+
CPacket& packet = unit->m_Packet;
248
+
packet.setLength(m_payload_sz);
249
+
packet.m_iSeqNo = start_seqno + i;
250
+
packet.m_iMsgNo = PacketBoundaryBits(PB_SUBSEQUENT);
251
+
if (i == 0)
252
+
packet.m_iMsgNo |= PacketBoundaryBits(PB_FIRST);
253
+
const bool is_last_packet = (i == (msg_len_pkts - 1));
254
+
if (is_last_packet)
255
+
packet.m_iMsgNo |= PacketBoundaryBits(PB_LAST);
256
+
257
+
if (!out_of_order)
258
+
{
259
+
packet.m_iMsgNo |= MSGNO_PACKET_INORDER::wrap(1);
260
+
EXPECT_TRUE(packet.getMsgOrderFlag());
261
+
}
262
+
263
+
EXPECT_EQ(m_rcv_buffer->addData(unit, msg_offset + i), 0);
264
+
}
265
+
}
266
+
267
+
protected:
268
+
unique_ptr<CUnitQueue> m_unit_queue;
269
+
unique_ptr<CRcvBuffer> m_rcv_buffer;
270
+
const int m_buff_size_pkts = 16;
271
+
const int m_init_seqno = 1000;
272
+
static const size_t m_payload_sz = 1456;
273
+
};
274
+
275
+
TEST_F(TestRcvBufferRead, OnePacket)
276
+
{
277
+
const size_t msg_pkts = 1;
278
+
// Adding one message without acknowledging
279
+
addMessage(msg_pkts, m_init_seqno, false);
280
+
281
+
const size_t msg_bytelen = msg_pkts * m_payload_sz;
282
+
array<char, 2 * msg_bytelen> buff;
283
+
284
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataAvailable());
285
+
286
+
int res = m_rcv_buffer->readMsg(buff.data(), buff.size());
287
+
EXPECT_EQ(res, 0);
288
+
289
+
// Full ACK
290
+
m_rcv_buffer->ackData(msg_pkts);
291
+
292
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataAvailable());
293
+
294
+
res = m_rcv_buffer->readMsg(buff.data(), buff.size());
295
+
EXPECT_EQ(res, msg_bytelen);
296
+
}
297
+
298
+
TEST_F(TestRcvBufferRead, OnePacketWithGap)
299
+
{
300
+
const size_t msg_pkts = 1;
301
+
// Adding one message without acknowledging
302
+
addMessage(msg_pkts, m_init_seqno + 1, false);
303
+
304
+
const size_t msg_bytelen = msg_pkts * m_payload_sz;
305
+
array<char, 2 * msg_bytelen> buff;
306
+
307
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataAvailable());
308
+
309
+
int res = m_rcv_buffer->readMsg(buff.data(), buff.size());
310
+
EXPECT_EQ(res, 0);
311
+
312
+
// ACK first missing packet
313
+
m_rcv_buffer->ackData(msg_pkts);
314
+
315
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataAvailable());
316
+
317
+
res = m_rcv_buffer->readMsg(buff.data(), buff.size());
318
+
EXPECT_EQ(res, 0);
319
+
320
+
m_rcv_buffer->ackData(msg_pkts);
321
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataAvailable());
322
+
323
+
res = m_rcv_buffer->readMsg(buff.data(), buff.size());
324
+
EXPECT_EQ(res, msg_bytelen);
325
+
}
326
+
327
+
// Check reading the whole message (consisting of several packets) from the buffer.
328
+
TEST_F(TestRcvBufferRead, MsgAcked)
329
+
{
330
+
const size_t msg_pkts = 4;
331
+
// Adding one message without acknowledging
332
+
addMessage(msg_pkts, m_init_seqno, false);
333
+
334
+
const size_t msg_bytelen = msg_pkts * m_payload_sz;
335
+
array<char, 2 * msg_bytelen> buff;
336
+
337
+
// Acknowledge all packets of the message.
338
+
m_rcv_buffer->ackData(4);
339
+
// Now the whole message can be read.
340
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataReady());
341
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataAvailable());
342
+
const int res = m_rcv_buffer->readMsg(buff.data(), buff.size());
343
+
EXPECT_EQ(res, msg_bytelen);
344
+
}
345
+
346
+
// BUG!!!
347
+
// Checks signalling of read-readiness of a half-acknowledged message.
348
+
// The RCV buffer implementation has an issue here: when only half of the message is
349
+
// acknowledged, the RCV buffer signals read-readiness, even though
350
+
// the message can't be read, and reading returns 0.
351
+
TEST_F(TestRcvBufferRead, MsgHalfAck)
352
+
{
353
+
const size_t msg_pkts = 4;
354
+
// Adding one message without acknowledging
355
+
addMessage(msg_pkts, m_init_seqno, false);
356
+
357
+
// Nothing to read (0 for zero bytes read).
358
+
const size_t msg_bytelen = msg_pkts * m_payload_sz;
359
+
array<char, 2 * msg_bytelen> buff;
360
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataReady());
361
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataAvailable());
362
+
int res = m_rcv_buffer->readMsg(buff.data(), buff.size());
363
+
EXPECT_EQ(res, 0);
364
+
365
+
// ACK half of the message and check read-readiness.
366
+
m_rcv_buffer->ackData(2);
367
+
// FIXME: Sadly RCV buffer says the data is ready to be read.
368
+
// EXPECT_FALSE(m_rcv_buffer->isRcvDataReady());
369
+
// EXPECT_FALSE(m_rcv_buffer->isRcvDataAvailable());
370
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataReady());
371
+
EXPECT_TRUE(m_rcv_buffer->isRcvDataAvailable());
372
+
373
+
// Actually must be nothing to read (can't read half a message).
374
+
res = m_rcv_buffer->readMsg(buff.data(), buff.size());
375
+
EXPECT_EQ(res, 0);
376
+
}
377
+
378
+
// BUG!!!
379
+
// Adding a message with the out-of-order flag set.
380
+
// RCV buffer does not signal read-readiness, but actually the packet can be read.
381
+
TEST_F(TestRcvBufferRead, OutOfOrderMsgNoACK)
382
+
{
383
+
const size_t msg_pkts = 4;
384
+
// Adding one message with the Out-Of-Order flag set, but without acknowledging.
385
+
addMessage(msg_pkts, m_init_seqno, true);
386
+
387
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataReady());
388
+
EXPECT_FALSE(m_rcv_buffer->isRcvDataAvailable());
389
+
const size_t msg_bytelen = msg_pkts * m_payload_sz;
390
+
array<char, 2 * msg_bytelen> buff;
391
+
const int res = m_rcv_buffer->readMsg(buff.data(), buff.size());
392
+
EXPECT_EQ(res, msg_bytelen);
393
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4