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 ENSURE_WRITTEN_BYTES(buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
165 i = buff64.Begin();
166 NS_TEST_ASSERT_MSG_EQ(i.ReadU64(), 0x0123456789abcdefLLU, "Could not read expected value");
167 i = buff64.Begin();
168 i.WriteHtonU64(0x0123456789ABCDEFLLU);
169 ENSURE_WRITTEN_BYTES(buff64, 8, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
170 i = buff64.Begin();
171 NS_TEST_ASSERT_MSG_EQ(i.ReadNtohU64(), 0x0123456789abcdefLLU, "could not read expected value");
172
173 // test self-assignment
174 {
175 Buffer a = o;
176#if defined(__clang__)
177#if __has_warning("-Wself-assign-overloaded")
178#pragma clang diagnostic push
179#pragma clang diagnostic ignored "-Wself-assign-overloaded"
180#endif
181#endif
182 a = a;
183#if defined(__clang__)
184#if __has_warning("-Wself-assign-overloaded")
185#pragma clang diagnostic pop
186#endif
187#endif
188 }
189
190 // test Remove start.
191 buffer = Buffer(5);
192 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0);
193 buffer.RemoveAtStart(1);
194 ENSURE_WRITTEN_BYTES(buffer, 4, 0, 0, 0, 0);
195 buffer.AddAtStart(1);
196 buffer.Begin().WriteU8(0xff);
197 ENSURE_WRITTEN_BYTES(buffer, 5, 0xff, 0, 0, 0, 0);
198 buffer.RemoveAtStart(3);
199 ENSURE_WRITTEN_BYTES(buffer, 2, 0, 0);
200 buffer.AddAtStart(4);
201 buffer.Begin().WriteHtonU32(0xdeadbeaf);
202 ENSURE_WRITTEN_BYTES(buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
203 buffer.RemoveAtStart(2);
204 ENSURE_WRITTEN_BYTES(buffer, 4, 0xbe, 0xaf, 0, 0);
205 buffer.AddAtEnd(4);
206 i = buffer.Begin();
207 i.Next(4);
208 i.WriteHtonU32(0xdeadbeaf);
209 ENSURE_WRITTEN_BYTES(buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
210 buffer.RemoveAtStart(5);
211 ENSURE_WRITTEN_BYTES(buffer, 3, 0xad, 0xbe, 0xaf);
212 // test Remove end
213 buffer = Buffer(5);
214 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0);
215 buffer.RemoveAtEnd(1);
216 ENSURE_WRITTEN_BYTES(buffer, 4, 0, 0, 0, 0);
217 buffer.AddAtEnd(2);
218 i = buffer.Begin();
219 i.Next(4);
220 i.WriteU8(0xab);
221 i.WriteU8(0xac);
222 ENSURE_WRITTEN_BYTES(buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
223 buffer.RemoveAtEnd(1);
224 ENSURE_WRITTEN_BYTES(buffer, 5, 0, 0, 0, 0, 0xab);
225 buffer.RemoveAtEnd(3);
226 ENSURE_WRITTEN_BYTES(buffer, 2, 0, 0);
227 buffer.AddAtEnd(6);
228 i = buffer.Begin();
229 i.Next(2);
230 i.WriteU8(0xac);
231 i.WriteU8(0xad);
232 i.WriteU8(0xae);
233 i.WriteU8(0xaf);
234 i.WriteU8(0xba);
235 i.WriteU8(0xbb);
236 ENSURE_WRITTEN_BYTES(buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
237 buffer.AddAtStart(3);
238 i = buffer.Begin();
239 i.WriteU8(0x30);
240 i.WriteU8(0x31);
241 i.WriteU8(0x32);
242 ENSURE_WRITTEN_BYTES(buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
243 buffer.RemoveAtEnd(9);
244 ENSURE_WRITTEN_BYTES(buffer, 2, 0x30, 0x31);
245 buffer = Buffer(3);
246 buffer.AddAtEnd(2);
247 i = buffer.Begin();
248 i.Next(3);
249 i.WriteHtonU16(0xabcd);
250 buffer.AddAtStart(1);
251 buffer.Begin().WriteU8(0x21);
252 ENSURE_WRITTEN_BYTES(buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
253 buffer.RemoveAtEnd(8);
254 NS_TEST_ASSERT_MSG_EQ(buffer.GetSize(), 0, "Buffer size not zero");
255
256 buffer = Buffer(6);
257 buffer.AddAtStart(9);
258 buffer.AddAtEnd(3);
259 i = buffer.End();
260 i.Prev(1);
261 i.WriteU8(1, 1);
262
263 buffer = Buffer(6);
264 buffer.AddAtStart(3);
265 buffer.RemoveAtEnd(8);
266 buffer.AddAtEnd(4);
267 i = buffer.End();
268 i.Prev(4);
269 i.WriteU8(1, 4);
270
271 buffer = Buffer(1);
272 buffer.AddAtEnd(100);
273 i = buffer.End();
274 i.Prev(100);
275 i.WriteU8(1, 100);
276
277 // See \bugid{54}
278 {
279 const uint32_t actualSize = 72602;
280 const uint32_t chunkSize = 67624;
282 bytesRng->SetAttribute("Min", DoubleValue(0));
283 bytesRng->SetAttribute("Max", DoubleValue(256));
284
285 Buffer inputBuffer;
286 Buffer outputBuffer;
287
288 inputBuffer.AddAtEnd(actualSize);
289 {
290 Buffer::Iterator iter = inputBuffer.Begin();
291 for (uint32_t i = 0; i < actualSize; i++)
292 {
293 iter.WriteU8(static_cast<uint8_t>(bytesRng->GetValue()));
294 }
295 }
296
297 outputBuffer.AddAtEnd(chunkSize);
298 Buffer::Iterator iter = outputBuffer.End();
299 iter.Prev(chunkSize);
300 iter.Write(inputBuffer.PeekData(), chunkSize);
301
302 NS_TEST_EXPECT_MSG_EQ(memcmp(inputBuffer.PeekData(), outputBuffer.PeekData(), chunkSize),
303 0,
304 "memcp works");
305 }
306
307 buffer = Buffer(5);
308 buffer.AddAtEnd(2);
309 i = buffer.End();
310 i.Prev(2);
311 i.WriteU8(0);
312 i.WriteU8(0x66);
313 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
314 Buffer frag0 = buffer.CreateFragment(0, 2);
315 ENSURE_WRITTEN_BYTES(frag0, 2, 0x00, 0x00);
316 Buffer frag1 = buffer.CreateFragment(2, 5);
317 ENSURE_WRITTEN_BYTES(frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
318 frag0.AddAtEnd(frag1);
319 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
320 ENSURE_WRITTEN_BYTES(frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
321
322 buffer = Buffer(5);
323 buffer.AddAtStart(2);
324 i = buffer.Begin();
325 i.WriteU8(0x1);
326 i.WriteU8(0x2);
327 buffer.AddAtEnd(2);
328 i = buffer.End();
329 i.Prev(2);
330 i.WriteU8(0x3);
331 i.WriteU8(0x4);
332 ENSURE_WRITTEN_BYTES(buffer, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
333 Buffer other;
334 other.AddAtStart(9);
335 i = other.Begin();
336 i.Write(buffer.Begin(), buffer.End());
337 ENSURE_WRITTEN_BYTES(other, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
338
339 // See \bugid{1001}
340 std::string ct("This is the next content of the buffer.");
341 buffer = Buffer();
342 buffer.AddAtStart(ct.size());
343 i = buffer.Begin();
344 i.Write((const uint8_t*)ct.c_str(), ct.size());
345 uint32_t sizeBuffer = buffer.GetSize();
346 NS_TEST_ASSERT_MSG_EQ(sizeBuffer, ct.size(), "Buffer bad size");
347 const uint8_t* evilBuffer = buffer.PeekData();
348 NS_TEST_ASSERT_MSG_NE(evilBuffer, 0, "Buffer PeekData failed");
349 auto cBuf = (uint8_t*)malloc(sizeBuffer);
350 uint32_t copyLen = buffer.CopyData(cBuf, sizeBuffer);
351 NS_TEST_ASSERT_MSG_EQ(copyLen, sizeBuffer, "CopyData return bad size");
352 for (uint32_t i = 0; i < sizeBuffer; i++)
353 {
354 NS_TEST_ASSERT_MSG_EQ(cBuf[i],
355 *(((const uint8_t*)ct.c_str()) + i),
356 "Bad buffer copied data");
357 NS_TEST_ASSERT_MSG_EQ(evilBuffer[i], cBuf[i], "Bad buffer peeked");
358 }
359 free(cBuf);
360
361 // See \bugid{2044} Will not pass without bug2044 fix.
362 buffer = Buffer(1);
363 buffer.AddAtEnd(2);
364 i = buffer.Begin();
365 i.Next(1);
366 i.WriteU8(0x77);
367 i.WriteU8(0x66);
368 ENSURE_WRITTEN_BYTES(buffer, 3, 0x00, 0x77, 0x66);
369 i = buffer.Begin();
370 i.ReadU8();
371 uint16_t val1 = i.ReadNtohU16();
372 i = buffer.Begin();
373 i.ReadU8();
374 uint16_t val2 = 0;
375 val2 |= i.ReadU8();
376 val2 <<= 8;
377 val2 |= i.ReadU8();
378 NS_TEST_ASSERT_MSG_EQ(val1, val2, "Bad ReadNtohU16()");
379}
380
381/**
382 * @ingroup network-test
383 * @ingroup tests
384 *
385 * @brief Buffer TestSuite
386 */
388{
389 public:
391};
392
398
399static 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:98
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:897
void Write(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:937
void WriteU16(uint16_t data)
Definition buffer.cc:848
void WriteHtonU16(uint16_t data)
Definition buffer.h:931
void WriteHtonU32(uint32_t data)
Definition buffer.h:949
uint16_t ReadNtohU16()
Definition buffer.h:970
void Prev()
go backward by one byte
Definition buffer.h:876
uint16_t ReadU16()
Definition buffer.h:1051
void Next()
go forward by one byte
Definition buffer.h:869
automatically resized byte buffer
Definition buffer.h:92
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:1084
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1090
void AddAtEnd(uint32_t end)
Definition buffer.cc:349
Buffer::Iterator End() const
Definition buffer.h:1097
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.
Definition ptr.h:70
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:133
#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:240
#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:553
Every class exported by the ns3 library is enclosed in the ns3 namespace.