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