A Discrete-Event Network Simulator
API
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
38class BufferTest : public TestCase
39{
40 private:
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
296 {
297 const uint32_t actualSize = 72602;
298 const uint32_t chunkSize = 67624;
299 Ptr<UniformRandomVariable> bytesRng = CreateObject<UniformRandomVariable>();
300 bytesRng->SetAttribute("Min", DoubleValue(0));
301 bytesRng->SetAttribute("Max", DoubleValue(256));
302
303 Buffer inputBuffer;
304 Buffer outputBuffer;
305
306 inputBuffer.AddAtEnd(actualSize);
307 {
308 Buffer::Iterator iter = inputBuffer.Begin();
309 for (uint32_t i = 0; i < actualSize; i++)
310 {
311 iter.WriteU8(static_cast<uint8_t>(bytesRng->GetValue()));
312 }
313 }
314
315 outputBuffer.AddAtEnd(chunkSize);
316 Buffer::Iterator iter = outputBuffer.End();
317 iter.Prev(chunkSize);
318 iter.Write(inputBuffer.PeekData(), chunkSize);
319
320 NS_TEST_EXPECT_MSG_EQ(memcmp(inputBuffer.PeekData(), outputBuffer.PeekData(), chunkSize),
321 0,
322 "memcp works");
323 }
324
325 buffer = Buffer(5);
326 buffer.AddAtEnd(2);
327 i = buffer.End();
328 i.Prev(2);
329 i.WriteU8(0);
330 i.WriteU8(0x66);
331 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
332 Buffer frag0 = buffer.CreateFragment(0, 2);
333 ENSURE_WRITTEN_BYTES(frag0, 2, 0x00, 0x00);
334 Buffer frag1 = buffer.CreateFragment(2, 5);
335 ENSURE_WRITTEN_BYTES(frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
336 frag0.AddAtEnd(frag1);
337 ENSURE_WRITTEN_BYTES(buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
338 ENSURE_WRITTEN_BYTES(frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
339
340 buffer = Buffer(5);
341 buffer.AddAtStart(2);
342 i = buffer.Begin();
343 i.WriteU8(0x1);
344 i.WriteU8(0x2);
345 buffer.AddAtEnd(2);
346 i = buffer.End();
347 i.Prev(2);
348 i.WriteU8(0x3);
349 i.WriteU8(0x4);
350 ENSURE_WRITTEN_BYTES(buffer, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
351 Buffer other;
352 other.AddAtStart(9);
353 i = other.Begin();
354 i.Write(buffer.Begin(), buffer.End());
355 ENSURE_WRITTEN_BYTES(other, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
356
358 std::string ct("This is the next content of the buffer.");
359 buffer = Buffer();
360 buffer.AddAtStart(ct.size());
361 i = buffer.Begin();
362 i.Write((const uint8_t*)ct.c_str(), ct.size());
363 uint32_t sizeBuffer = buffer.GetSize();
364 NS_TEST_ASSERT_MSG_EQ(sizeBuffer, ct.size(), "Buffer bad size");
365 const uint8_t* evilBuffer = buffer.PeekData();
366 NS_TEST_ASSERT_MSG_NE(evilBuffer, 0, "Buffer PeekData failed");
367 uint8_t* cBuf = (uint8_t*)malloc(sizeBuffer);
368 uint32_t copyLen = buffer.CopyData(cBuf, sizeBuffer);
369 NS_TEST_ASSERT_MSG_EQ(copyLen, sizeBuffer, "CopyData return bad size");
370 for (uint32_t i = 0; i < sizeBuffer; i++)
371 {
372 NS_TEST_ASSERT_MSG_EQ(cBuf[i],
373 *(((const uint8_t*)ct.c_str()) + i),
374 "Bad buffer copied data");
375 NS_TEST_ASSERT_MSG_EQ(evilBuffer[i], cBuf[i], "Bad buffer peeked");
376 }
377 free(cBuf);
378
380 buffer = Buffer(1);
381 buffer.AddAtEnd(2);
382 i = buffer.Begin();
383 i.Next(1);
384 i.WriteU8(0x77);
385 i.WriteU8(0x66);
386 ENSURE_WRITTEN_BYTES(buffer, 3, 0x00, 0x77, 0x66);
387 i = buffer.Begin();
388 i.ReadU8();
389 uint16_t val1 = i.ReadNtohU16();
390 i = buffer.Begin();
391 i.ReadU8();
392 uint16_t val2 = 0;
393 val2 |= i.ReadU8();
394 val2 <<= 8;
395 val2 |= i.ReadU8();
396 NS_TEST_ASSERT_MSG_EQ(val1, val2, "Bad ReadNtohU16()");
397}
398
406{
407 public:
409};
410
412 : TestSuite("buffer", UNIT)
413{
414 AddTestCase(new BufferTest, TestCase::QUICK);
415}
416
static BufferTestSuite g_bufferTestSuite
Static variable for test initialization.
Definition: buffer-test.cc:417
#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:406
iterator in a Buffer instance
Definition: buffer.h:100
void WriteU64(uint64_t data)
Definition: buffer.cc:884
uint64_t ReadU64()
Definition: buffer.cc:987
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:937
uint64_t ReadNtohU64()
Definition: buffer.cc:1044
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:951
void WriteU16(uint16_t data)
Definition: buffer.cc:862
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1097
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:923
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:526
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:716
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:490
uint32_t GetSize() const
Definition: buffer.h:1068
void AddAtStart(uint32_t start)
Definition: buffer.cc:311
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void AddAtEnd(uint32_t end)
Definition: buffer.cc:357
Buffer::Iterator End() const
Definition: buffer.h:1081
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:444
const uint8_t * PeekData() const
Definition: buffer.cc:706
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:258
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
#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:144
#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:251
#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:564
Every class exported by the ns3 library is enclosed in the ns3 namespace.