A Discrete-Event Network Simulator
API
buffer-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@cutebugs.net>
19  */
20 
21 #include "ns3/buffer.h"
22 #include "ns3/random-variable-stream.h"
23 #include "ns3/double.h"
24 #include "ns3/test.h"
25 
26 using namespace ns3;
27 
39 class BufferTest : public TestCase {
40 private:
49  void EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[], const char *file, int line);
50 public:
51  virtual void DoRun (void);
52  BufferTest ();
53 };
54 
55 
57  : TestCase ("Buffer") {
58 }
59 
60 void
61 BufferTest::EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[], const char *file, int line)
62 {
63  bool success = true;
64  uint8_t *expected = array;
65  uint8_t const*got;
66  got = b.PeekData ();
67  for (uint32_t j = 0; j < n; j++)
68  {
69  if (got[j] != expected[j])
70  {
71  success = false;
72  }
73  }
74  if (!success)
75  {
76  std::ostringstream failure;
77  failure << "Buffer -- ";
78  failure << "expected: n=";
79  failure << n << ", ";
80  failure.setf (std::ios::hex, std::ios::basefield);
81  for (uint32_t j = 0; j < n; j++)
82  {
83  failure << (uint16_t)expected[j] << " ";
84  }
85  failure.setf (std::ios::dec, std::ios::basefield);
86  failure << "got: ";
87  failure.setf (std::ios::hex, std::ios::basefield);
88  for (uint32_t j = 0; j < n; j++)
89  {
90  failure << (uint16_t)got[j] << " ";
91  }
92  failure << std::endl;
93  NS_TEST_ASSERT_MSG_EQ_INTERNAL (true, false, failure.str (), file, line);
94  }
95 }
96 
97 /*
98  * Works only when variadic macros are
99  * available which is the case for gcc.
100  */
101 #define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
102  { \
103  uint8_t bytes[] = { __VA_ARGS__}; \
104  EnsureWrittenBytes (buffer, n, bytes, __FILE__, __LINE__); \
105  }
106 
107 void
109 {
110  Buffer buffer;
112  buffer.AddAtStart (6);
113  i = buffer.Begin ();
114  i.WriteU8 (0x66);
115  ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
116  i = buffer.Begin ();
117  i.WriteU8 (0x67);
118  ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
119  i.WriteHtonU16 (0x6568);
120  i = buffer.Begin ();
121  ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
122  i.WriteHtonU16 (0x6369);
123  ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
124  i.WriteHtonU32 (0xdeadbeaf);
125  ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
126  buffer.AddAtStart (2);
127  i = buffer.Begin ();
128  i.WriteU16 (0);
129  ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
130  buffer.AddAtEnd (2);
131  i = buffer.Begin ();
132  i.Next (8);
133  i.WriteU16 (0);
134  ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
135  buffer.RemoveAtStart (3);
136  i = buffer.Begin ();
137  ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
138  buffer.RemoveAtEnd (4);
139  i = buffer.Begin ();
140  ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
141  buffer.AddAtStart (1);
142  i = buffer.Begin ();
143  i.WriteU8 (0xff);
144  ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
145  buffer.AddAtEnd (1);
146  i = buffer.Begin ();
147  i.Next (4);
148  i.WriteU8 (0xff);
149  i.Prev (2);
150  uint16_t saved = i.ReadU16 ();
151  i.Prev (2);
152  i.WriteHtonU16 (0xff00);
153  i.Prev (2);
154  NS_TEST_ASSERT_MSG_EQ (i.ReadNtohU16 (), 0xff00, "Could not read expected value");
155  i.Prev (2);
156  i.WriteU16 (saved);
157  ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
158  Buffer o = buffer;
159  ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
160  o.AddAtStart (1);
161  i = o.Begin ();
162  i.WriteU8 (0xfe);
163  ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
164  buffer.AddAtStart (2);
165  i = buffer.Begin ();
166  i.WriteU8 (0xfd);
167  i.WriteU8 (0xfd);
168  ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
169  ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
170 
171  // test 64-bit read/write
172  Buffer buff64;
173  buff64.AddAtStart (8);
174  i = buff64.Begin ();
175  i.WriteU64 (0x0123456789ABCDEFllu);
176  i = buff64.Begin ();
177  NS_TEST_ASSERT_MSG_EQ (i.ReadU64 (), 0x0123456789abcdefllu, "Could not read expected value");
178  i = buff64.Begin ();
179  i.WriteHtolsbU64 (0x0123456789ABCDEFllu);
180  ENSURE_WRITTEN_BYTES (buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
181  i = buff64.Begin ();
182  NS_TEST_ASSERT_MSG_EQ (i.ReadLsbtohU64 (), 0x0123456789abcdefllu, "Could not read expected value");
183  i = buff64.Begin ();
184  i.WriteHtonU64 (0x0123456789ABCDEFllu);
185  ENSURE_WRITTEN_BYTES (buff64, 8, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
186  i = buff64.Begin ();
187  NS_TEST_ASSERT_MSG_EQ (i.ReadNtohU64 (), 0x0123456789abcdefllu, "could not read expected value");
188 
189  // test self-assignment
190  {
191  Buffer a = o;
192 #if defined(__clang__)
193  #if __has_warning("-Wself-assign-overloaded")
194  #pragma clang diagnostic push
195  #pragma clang diagnostic ignored "-Wself-assign-overloaded"
196  #endif
197 #endif
198  a = a;
199 #if defined(__clang__)
200  #if __has_warning("-Wself-assign-overloaded")
201  #pragma clang diagnostic pop
202  #endif
203 #endif
204  }
205 
206  // test Remove start.
207  buffer = Buffer (5);
208  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
209  buffer.RemoveAtStart (1);
210  ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
211  buffer.AddAtStart (1);
212  buffer.Begin ().WriteU8 (0xff);
213  ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
214  buffer.RemoveAtStart (3);
215  ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
216  buffer.AddAtStart (4);
217  buffer.Begin ().WriteHtonU32 (0xdeadbeaf);
218  ENSURE_WRITTEN_BYTES (buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
219  buffer.RemoveAtStart (2);
220  ENSURE_WRITTEN_BYTES (buffer, 4, 0xbe, 0xaf, 0, 0);
221  buffer.AddAtEnd (4);
222  i = buffer.Begin ();
223  i.Next (4);
224  i.WriteHtonU32 (0xdeadbeaf);
225  ENSURE_WRITTEN_BYTES (buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
226  buffer.RemoveAtStart (5);
227  ENSURE_WRITTEN_BYTES (buffer, 3, 0xad, 0xbe, 0xaf);
228  // test Remove end
229  buffer = Buffer (5);
230  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
231  buffer.RemoveAtEnd (1);
232  ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
233  buffer.AddAtEnd (2);
234  i = buffer.Begin ();
235  i.Next (4);
236  i.WriteU8 (0xab);
237  i.WriteU8 (0xac);
238  ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
239  buffer.RemoveAtEnd (1);
240  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
241  buffer.RemoveAtEnd (3);
242  ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
243  buffer.AddAtEnd (6);
244  i = buffer.Begin ();
245  i.Next (2);
246  i.WriteU8 (0xac);
247  i.WriteU8 (0xad);
248  i.WriteU8 (0xae);
249  i.WriteU8 (0xaf);
250  i.WriteU8 (0xba);
251  i.WriteU8 (0xbb);
252  ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
253  buffer.AddAtStart (3);
254  i = buffer.Begin ();
255  i.WriteU8 (0x30);
256  i.WriteU8 (0x31);
257  i.WriteU8 (0x32);
258  ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
259  buffer.RemoveAtEnd (9);
260  ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
261  buffer = Buffer (3);
262  buffer.AddAtEnd (2);
263  i = buffer.Begin ();
264  i.Next (3);
265  i.WriteHtonU16 (0xabcd);
266  buffer.AddAtStart (1);
267  buffer.Begin ().WriteU8 (0x21);
268  ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
269  buffer.RemoveAtEnd (8);
270  NS_TEST_ASSERT_MSG_EQ (buffer.GetSize (), 0, "Buffer size not zero");
271 
272  buffer = Buffer (6);
273  buffer.AddAtStart (9);
274  buffer.AddAtEnd (3);
275  i = buffer.End ();
276  i.Prev (1);
277  i.WriteU8 (1, 1);
278 
279  buffer = Buffer (6);
280  buffer.AddAtStart (3);
281  buffer.RemoveAtEnd (8);
282  buffer.AddAtEnd (4);
283  i = buffer.End ();
284  i.Prev (4);
285  i.WriteU8 (1, 4);
286 
287  buffer = Buffer (1);
288  buffer.AddAtEnd (100);
289  i = buffer.End ();
290  i.Prev (100);
291  i.WriteU8 (1, 100);
292 
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  iter.WriteU8 (static_cast<uint8_t> (bytesRng->GetValue ()));
310  }
311 
312  outputBuffer.AddAtEnd (chunkSize);
313  Buffer::Iterator iter = outputBuffer.End ();
314  iter.Prev (chunkSize);
315  iter.Write (inputBuffer.PeekData (), chunkSize);
316 
317  NS_TEST_EXPECT_MSG_EQ (memcmp (inputBuffer.PeekData (), outputBuffer.PeekData (), chunkSize), 0, "memcp works");
318  }
319 
320  buffer = Buffer (5);
321  buffer.AddAtEnd (2);
322  i = buffer.End ();
323  i.Prev (2);
324  i.WriteU8 (0);
325  i.WriteU8 (0x66);
326  ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
327  Buffer frag0 = buffer.CreateFragment (0, 2);
328  ENSURE_WRITTEN_BYTES (frag0, 2, 0x00, 0x00);
329  Buffer frag1 = buffer.CreateFragment (2, 5);
330  ENSURE_WRITTEN_BYTES (frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
331  frag0.AddAtEnd (frag1);
332  ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
333  ENSURE_WRITTEN_BYTES (frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
334 
335  buffer = Buffer (5);
336  buffer.AddAtStart (2);
337  i = buffer.Begin ();
338  i.WriteU8 (0x1);
339  i.WriteU8 (0x2);
340  buffer.AddAtEnd (2);
341  i = buffer.End ();
342  i.Prev (2);
343  i.WriteU8 (0x3);
344  i.WriteU8 (0x4);
345  ENSURE_WRITTEN_BYTES (buffer, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
346  Buffer other;
347  other.AddAtStart (9);
348  i = other.Begin ();
349  i.Write (buffer.Begin (), buffer.End ());
350  ENSURE_WRITTEN_BYTES (other, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
351 
353  std::string ct ("This is the next content of the buffer.");
354  buffer = Buffer ();
355  buffer.AddAtStart (ct.size ());
356  i = buffer.Begin ();
357  i.Write ((const uint8_t*)ct.c_str (), ct.size ());
358  uint32_t sizeBuffer = buffer.GetSize ();
359  NS_TEST_ASSERT_MSG_EQ (sizeBuffer, ct.size(), "Buffer bad size");
360  uint8_t const* evilBuffer = buffer.PeekData ();
361  NS_TEST_ASSERT_MSG_NE( evilBuffer, 0, "Buffer PeekData failed");
362  uint8_t *cBuf = (uint8_t*) malloc ( sizeBuffer );
363  uint32_t copyLen = buffer.CopyData (cBuf, sizeBuffer);
364  NS_TEST_ASSERT_MSG_EQ (copyLen, sizeBuffer, "CopyData return bad size");
365  for (uint8_t i=0; i < sizeBuffer ; i++ )
366  {
367  NS_TEST_ASSERT_MSG_EQ ( cBuf [i], *(((const uint8_t*)ct.c_str ()) + i), "Bad buffer copied data");
368  NS_TEST_ASSERT_MSG_EQ ( evilBuffer [i], cBuf [i] , "Bad buffer peeked");
369  }
370  free (cBuf);
371 
373  buffer = Buffer (1);
374  buffer.AddAtEnd (2);
375  i = buffer.Begin ();
376  i.Next (1);
377  i.WriteU8 (0x77);
378  i.WriteU8 (0x66);
379  ENSURE_WRITTEN_BYTES (buffer, 3, 0x00, 0x77, 0x66);
380  i = buffer.Begin ();
381  i.ReadU8 ();
382  uint16_t val1 = i.ReadNtohU16 ();
383  i = buffer.Begin ();
384  i.ReadU8 ();
385  uint16_t val2 = 0;
386  val2 |= i.ReadU8 ();
387  val2 <<= 8;
388  val2 |= i.ReadU8 ();
389  NS_TEST_ASSERT_MSG_EQ (val1, val2, "Bad ReadNtohU16()");
390 }
391 
399 {
400 public:
401  BufferTestSuite ();
402 };
403 
405  : TestSuite ("buffer", UNIT)
406 {
407  AddTestCase (new BufferTest, TestCase::QUICK);
408 }
409 
uint16_t ReadU16(void)
Definition: buffer.h:1029
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:940
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
#define ENSURE_WRITTEN_BYTES(buffer, n,...)
Definition: buffer-test.cc:101
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:483
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:438
A suite of tests to run.
Definition: test.h:1342
automatically resized byte buffer
Definition: buffer.h:92
Buffer unit tests.
Definition: buffer-test.cc:39
#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:285
encapsulates test code
Definition: test.h:1155
uint8_t const * PeekData(void) const
Definition: buffer.cc:705
void EnsureWrittenBytes(Buffer b, uint32_t n, uint8_t array[], const char *file, int line)
Checks the buffer content.
Definition: buffer-test.cc:61
#define NS_TEST_ASSERT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:120
iterator in a Buffer instance
Definition: buffer.h:98
void Prev(void)
go backward by one byte
Definition: buffer.h:851
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
#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:168
void WriteU16(uint16_t data)
Definition: buffer.cc:870
void WriteHtonU16(uint16_t data)
Definition: buffer.h:905
void Next(void)
go forward by one byte
Definition: buffer.h:845
void WriteU64(uint64_t data)
Definition: buffer.cc:890
void AddAtEnd(uint32_t end)
Definition: buffer.cc:354
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
virtual void DoRun(void)
Implementation to actually run this TestCase.
Definition: buffer-test.cc:108
uint64_t ReadU64(void)
Definition: buffer.cc:989
void WriteHtonU32(uint32_t data)
Definition: buffer.h:924
Buffer::Iterator End(void) const
Definition: buffer.h:1075
void WriteU8(uint8_t data)
Definition: buffer.h:869
#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:624
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:926
uint32_t GetSize(void) const
Definition: buffer.h:1063
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:519
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:953
uint16_t ReadNtohU16(void)
Definition: buffer.h:946
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
static BufferTestSuite g_bufferTestSuite
Static variable for test initialization.
Definition: buffer-test.cc:410
Buffer TestSuite.
Definition: buffer-test.cc:398