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 
25 using namespace ns3;
26 
38 class 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 
59 void
60 BufferTest::EnsureWrittenBytes(Buffer b, uint32_t n, uint8_t array[])
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 
106 void
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 
405 {
406  public:
407  BufferTestSuite();
408 };
409 
411  : TestSuite("buffer", UNIT)
412 {
413  AddTestCase(new BufferTest, TestCase::QUICK);
414 }
415 
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
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
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:301
A suite of tests to run.
Definition: test.h:1256
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#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.