A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
buffer-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@cutebugs.net>
7 */
8
9#include "ns3/buffer.h"
10#include "ns3/double.h"
11#include "ns3/random-variable-stream.h"
12#include "ns3/test.h"
13
14using namespace ns3;
15
16/**
17 * \ingroup network
18 * \defgroup network-test Network module unit tests
19 */
20
21/**
22 * \ingroup network-test
23 * \ingroup tests
24 *
25 * Buffer unit tests.
26 */
27class BufferTest : public TestCase
28{
29 private:
30 /**
31 * Checks the buffer content
32 * \param b The buffer to check
33 * \param n The number of bytes to check
34 * \param array The array of bytes that should be in the buffer
35 */
36 void EnsureWrittenBytes(Buffer b, uint32_t n, uint8_t array[]);
37
38 public:
39 void DoRun() override;
40 BufferTest();
41};
42
44 : TestCase("Buffer")
45{
46}
47
48void
50{
51 bool success = true;
52 uint8_t* expected = array;
53 const uint8_t* got;
54 got = b.PeekData();
55 for (uint32_t j = 0; j < n; j++)
56 {
57 if (got[j] != expected[j])
58 {
59 success = false;
60 }
61 }
62 if (!success)
63 {
64 std::ostringstream failure;
65 failure << "Buffer -- ";
66 failure << "expected: n=";
67 failure << n << ", ";
68 failure.setf(std::ios::hex, std::ios::basefield);
69 for (uint32_t j = 0; j < n; j++)
70 {
71 failure << (uint16_t)expected[j] << " ";
72 }
73 failure.setf(std::ios::dec, std::ios::basefield);
74 failure << "got: ";
75 failure.setf(std::ios::hex, std::ios::basefield);
76 for (uint32_t j = 0; j < n; j++)
77 {
78 failure << (uint16_t)got[j] << " ";
79 }
80 failure << std::endl;
81 NS_TEST_ASSERT_MSG_EQ(true, false, failure.str());
82 }
83}
84
85/*
86 * Works only when variadic macros are
87 * available which is the case for gcc.
88 */
89#define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
90 { \
91 uint8_t bytes[] = {__VA_ARGS__}; \
92 EnsureWrittenBytes(buffer, n, bytes); \
93 }
94
95void
97{
98 Buffer buffer;
100 buffer.AddAtStart(6);
101 i = buffer.Begin();
102 i.WriteU8(0x66);
103 ENSURE_WRITTEN_BYTES(buffer, 1, 0x66);
104 i = buffer.Begin();
105 i.WriteU8(0x67);
106 ENSURE_WRITTEN_BYTES(buffer, 1, 0x67);
107 i.WriteHtonU16(0x6568);
108 i = buffer.Begin();
109 ENSURE_WRITTEN_BYTES(buffer, 3, 0x67, 0x65, 0x68);
110 i.WriteHtonU16(0x6369);
111 ENSURE_WRITTEN_BYTES(buffer, 3, 0x63, 0x69, 0x68);
112 i.WriteHtonU32(0xdeadbeaf);
113 ENSURE_WRITTEN_BYTES(buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
114 buffer.AddAtStart(2);
115 i = buffer.Begin();
116 i.WriteU16(0);
117 ENSURE_WRITTEN_BYTES(buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
118 buffer.AddAtEnd(2);
119 i = buffer.Begin();
120 i.Next(8);
121 i.WriteU16(0);
122 ENSURE_WRITTEN_BYTES(buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
123 buffer.RemoveAtStart(3);
124 i = buffer.Begin();
125 ENSURE_WRITTEN_BYTES(buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
126 buffer.RemoveAtEnd(4);
127 i = buffer.Begin();
128 ENSURE_WRITTEN_BYTES(buffer, 3, 0x69, 0xde, 0xad);
129 buffer.AddAtStart(1);
130 i = buffer.Begin();
131 i.WriteU8(0xff);
132 ENSURE_WRITTEN_BYTES(buffer, 4, 0xff, 0x69, 0xde, 0xad);
133 buffer.AddAtEnd(1);
134 i = buffer.Begin();
135 i.Next(4);
136 i.WriteU8(0xff);
137 i.Prev(2);
138 uint16_t saved = i.ReadU16();
139 i.Prev(2);
140 i.WriteHtonU16(0xff00);
141 i.Prev(2);
142 NS_TEST_ASSERT_MSG_EQ(i.ReadNtohU16(), 0xff00, "Could not read expected value");
143 i.Prev(2);
144 i.WriteU16(saved);
145 ENSURE_WRITTEN_BYTES(buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
146 Buffer o = buffer;
147 ENSURE_WRITTEN_BYTES(o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
148 o.AddAtStart(1);
149 i = o.Begin();
150 i.WriteU8(0xfe);
151 ENSURE_WRITTEN_BYTES(o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
152 buffer.AddAtStart(2);
153 i = buffer.Begin();
154 i.WriteU8(0xfd);
155 i.WriteU8(0xfd);
156 ENSURE_WRITTEN_BYTES(o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
157 ENSURE_WRITTEN_BYTES(buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
158
159 // test 64-bit read/write
160 Buffer buff64;
161 buff64.AddAtStart(8);
162 i = buff64.Begin();
163 i.WriteU64(0x0123456789ABCDEFLLU);
164 i = buff64.Begin();
165 NS_TEST_ASSERT_MSG_EQ(i.ReadU64(), 0x0123456789abcdefLLU, "Could not read expected value");
166 i = buff64.Begin();
167 i.WriteHtolsbU64(0x0123456789ABCDEFLLU);
168 ENSURE_WRITTEN_BYTES(buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
169 i = buff64.Begin();
171 0x0123456789abcdefLLU,
172 "Could not read expected value");
173 i = buff64.Begin();
174 i.WriteHtonU64(0x0123456789ABCDEFLLU);
175 ENSURE_WRITTEN_BYTES(buff64, 8, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
176 i = buff64.Begin();
177 NS_TEST_ASSERT_MSG_EQ(i.ReadNtohU64(), 0x0123456789abcdefLLU, "could not read expected value");
178
179 // test self-assignment
180 {
181 Buffer a = o;
182#if defined(__clang__)
183#if __has_warning("-Wself-assign-overloaded")
184#pragma clang diagnostic push
185#pragma clang diagnostic ignored "-Wself-assign-overloaded"
186#endif
187#endif
188 a = a;
189#if defined(__clang__)
190#if __has_warning("-Wself-assign-overloaded")
191#pragma clang diagnostic pop
192#endif
193#endif
194 }
195
196 // test Remove start.
197 buffer = Buffer(5);
198 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0);
199 buffer.RemoveAtStart(1);
200 ENSURE_WRITTEN_BYTES(buffer, 4, 0, 0, 0, 0);
201 buffer.AddAtStart(1);
202 buffer.Begin().WriteU8(0xff);
203 ENSURE_WRITTEN_BYTES(buffer, 5, 0xff, 0, 0, 0, 0);
204 buffer.RemoveAtStart(3);
205 ENSURE_WRITTEN_BYTES(buffer, 2, 0, 0);
206 buffer.AddAtStart(4);
207 buffer.Begin().WriteHtonU32(0xdeadbeaf);
208 ENSURE_WRITTEN_BYTES(buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
209 buffer.RemoveAtStart(2);
210 ENSURE_WRITTEN_BYTES(buffer, 4, 0xbe, 0xaf, 0, 0);
211 buffer.AddAtEnd(4);
212 i = buffer.Begin();
213 i.Next(4);
214 i.WriteHtonU32(0xdeadbeaf);
215 ENSURE_WRITTEN_BYTES(buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
216 buffer.RemoveAtStart(5);
217 ENSURE_WRITTEN_BYTES(buffer, 3, 0xad, 0xbe, 0xaf);
218 // test Remove end
219 buffer = Buffer(5);
220 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0);
221 buffer.RemoveAtEnd(1);
222 ENSURE_WRITTEN_BYTES(buffer, 4, 0, 0, 0, 0);
223 buffer.AddAtEnd(2);
224 i = buffer.Begin();
225 i.Next(4);
226 i.WriteU8(0xab);
227 i.WriteU8(0xac);
228 ENSURE_WRITTEN_BYTES(buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
229 buffer.RemoveAtEnd(1);
230 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0xab);
231 buffer.RemoveAtEnd(3);
232 ENSURE_WRITTEN_BYTES(buffer, 2, 0, 0);
233 buffer.AddAtEnd(6);
234 i = buffer.Begin();
235 i.Next(2);
236 i.WriteU8(0xac);
237 i.WriteU8(0xad);
238 i.WriteU8(0xae);
239 i.WriteU8(0xaf);
240 i.WriteU8(0xba);
241 i.WriteU8(0xbb);
242 ENSURE_WRITTEN_BYTES(buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
243 buffer.AddAtStart(3);
244 i = buffer.Begin();
245 i.WriteU8(0x30);
246 i.WriteU8(0x31);
247 i.WriteU8(0x32);
248 ENSURE_WRITTEN_BYTES(buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
249 buffer.RemoveAtEnd(9);
250 ENSURE_WRITTEN_BYTES(buffer, 2, 0x30, 0x31);
251 buffer = Buffer(3);
252 buffer.AddAtEnd(2);
253 i = buffer.Begin();
254 i.Next(3);
255 i.WriteHtonU16(0xabcd);
256 buffer.AddAtStart(1);
257 buffer.Begin().WriteU8(0x21);
258 ENSURE_WRITTEN_BYTES(buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
259 buffer.RemoveAtEnd(8);
260 NS_TEST_ASSERT_MSG_EQ(buffer.GetSize(), 0, "Buffer size not zero");
261
262 buffer = Buffer(6);
263 buffer.AddAtStart(9);
264 buffer.AddAtEnd(3);
265 i = buffer.End();
266 i.Prev(1);
267 i.WriteU8(1, 1);
268
269 buffer = Buffer(6);
270 buffer.AddAtStart(3);
271 buffer.RemoveAtEnd(8);
272 buffer.AddAtEnd(4);
273 i = buffer.End();
274 i.Prev(4);
275 i.WriteU8(1, 4);
276
277 buffer = Buffer(1);
278 buffer.AddAtEnd(100);
279 i = buffer.End();
280 i.Prev(100);
281 i.WriteU8(1, 100);
282
283 // See \bugid{54}
284 {
285 const uint32_t actualSize = 72602;
286 const uint32_t chunkSize = 67624;
288 bytesRng->SetAttribute("Min", DoubleValue(0));
289 bytesRng->SetAttribute("Max", DoubleValue(256));
290
291 Buffer inputBuffer;
292 Buffer outputBuffer;
293
294 inputBuffer.AddAtEnd(actualSize);
295 {
296 Buffer::Iterator iter = inputBuffer.Begin();
297 for (uint32_t i = 0; i < actualSize; i++)
298 {
299 iter.WriteU8(static_cast<uint8_t>(bytesRng->GetValue()));
300 }
301 }
302
303 outputBuffer.AddAtEnd(chunkSize);
304 Buffer::Iterator iter = outputBuffer.End();
305 iter.Prev(chunkSize);
306 iter.Write(inputBuffer.PeekData(), chunkSize);
307
308 NS_TEST_EXPECT_MSG_EQ(memcmp(inputBuffer.PeekData(), outputBuffer.PeekData(), chunkSize),
309 0,
310 "memcp works");
311 }
312
313 buffer = Buffer(5);
314 buffer.AddAtEnd(2);
315 i = buffer.End();
316 i.Prev(2);
317 i.WriteU8(0);
318 i.WriteU8(0x66);
319 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
320 Buffer frag0 = buffer.CreateFragment(0, 2);
321 ENSURE_WRITTEN_BYTES(frag0, 2, 0x00, 0x00);
322 Buffer frag1 = buffer.CreateFragment(2, 5);
323 ENSURE_WRITTEN_BYTES(frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
324 frag0.AddAtEnd(frag1);
325 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
326 ENSURE_WRITTEN_BYTES(frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
327
328 buffer = Buffer(5);
329 buffer.AddAtStart(2);
330 i = buffer.Begin();
331 i.WriteU8(0x1);
332 i.WriteU8(0x2);
333 buffer.AddAtEnd(2);
334 i = buffer.End();
335 i.Prev(2);
336 i.WriteU8(0x3);
337 i.WriteU8(0x4);
338 ENSURE_WRITTEN_BYTES(buffer, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
339 Buffer other;
340 other.AddAtStart(9);
341 i = other.Begin();
342 i.Write(buffer.Begin(), buffer.End());
343 ENSURE_WRITTEN_BYTES(other, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
344
345 // See \bugid{1001}
346 std::string ct("This is the next content of the buffer.");
347 buffer = Buffer();
348 buffer.AddAtStart(ct.size());
349 i = buffer.Begin();
350 i.Write((const uint8_t*)ct.c_str(), ct.size());
351 uint32_t sizeBuffer = buffer.GetSize();
352 NS_TEST_ASSERT_MSG_EQ(sizeBuffer, ct.size(), "Buffer bad size");
353 const uint8_t* evilBuffer = buffer.PeekData();
354 NS_TEST_ASSERT_MSG_NE(evilBuffer, 0, "Buffer PeekData failed");
355 auto cBuf = (uint8_t*)malloc(sizeBuffer);
356 uint32_t copyLen = buffer.CopyData(cBuf, sizeBuffer);
357 NS_TEST_ASSERT_MSG_EQ(copyLen, sizeBuffer, "CopyData return bad size");
358 for (uint32_t i = 0; i < sizeBuffer; i++)
359 {
360 NS_TEST_ASSERT_MSG_EQ(cBuf[i],
361 *(((const uint8_t*)ct.c_str()) + i),
362 "Bad buffer copied data");
363 NS_TEST_ASSERT_MSG_EQ(evilBuffer[i], cBuf[i], "Bad buffer peeked");
364 }
365 free(cBuf);
366
367 // See \bugid{2044} Will not pass without bug2044 fix.
368 buffer = Buffer(1);
369 buffer.AddAtEnd(2);
370 i = buffer.Begin();
371 i.Next(1);
372 i.WriteU8(0x77);
373 i.WriteU8(0x66);
374 ENSURE_WRITTEN_BYTES(buffer, 3, 0x00, 0x77, 0x66);
375 i = buffer.Begin();
376 i.ReadU8();
377 uint16_t val1 = i.ReadNtohU16();
378 i = buffer.Begin();
379 i.ReadU8();
380 uint16_t val2 = 0;
381 val2 |= i.ReadU8();
382 val2 <<= 8;
383 val2 |= i.ReadU8();
384 NS_TEST_ASSERT_MSG_EQ(val1, val2, "Bad ReadNtohU16()");
385}
386
387/**
388 * \ingroup network-test
389 * \ingroup tests
390 *
391 * \brief Buffer TestSuite
392 */
394{
395 public:
397};
398
400 : TestSuite("buffer", Type::UNIT)
401{
402 AddTestCase(new BufferTest, TestCase::Duration::QUICK);
403}
404
405static BufferTestSuite g_bufferTestSuite; //!< Static variable for test initialization
static BufferTestSuite g_bufferTestSuite
Static variable for test initialization.
#define ENSURE_WRITTEN_BYTES(buffer, n,...)
Buffer unit tests.
void DoRun() override
Implementation to actually run this TestCase.
void EnsureWrittenBytes(Buffer b, uint32_t n, uint8_t array[])
Checks the buffer content.
Buffer TestSuite.
iterator in a Buffer instance
Definition buffer.h:89
void WriteU64(uint64_t data)
Definition buffer.cc:870
uint64_t ReadU64()
Definition buffer.cc:973
void WriteHtonU64(uint64_t data)
Definition buffer.cc:923
uint64_t ReadNtohU64()
Definition buffer.cc:1030
void WriteU8(uint8_t data)
Definition buffer.h:870
void Write(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:937
void WriteU16(uint16_t data)
Definition buffer.cc:848
uint64_t ReadLsbtohU64()
Definition buffer.cc:1083
void WriteHtolsbU64(uint64_t data)
Definition buffer.cc:909
void WriteHtonU16(uint16_t data)
Definition buffer.h:904
void WriteHtonU32(uint32_t data)
Definition buffer.h:922
uint16_t ReadNtohU16()
Definition buffer.h:943
void Prev()
go backward by one byte
Definition buffer.h:849
uint16_t ReadU16()
Definition buffer.h:1024
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition buffer.cc:518
void CopyData(std::ostream *os, uint32_t size) const
Copy the specified amount of data from the buffer to the given output stream.
Definition buffer.cc:702
void RemoveAtEnd(uint32_t end)
Definition buffer.cc:482
uint32_t GetSize() const
Definition buffer.h:1057
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1063
void AddAtEnd(uint32_t end)
Definition buffer.cc:349
Buffer::Iterator End() const
Definition buffer.h:1070
void RemoveAtStart(uint32_t start)
Definition buffer.cc:436
const uint8_t * PeekData() const
Definition buffer.cc:692
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Smart pointer class similar to boost::intrusive_ptr.
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:554
Every class exported by the ns3 library is enclosed in the ns3 namespace.