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:
47  void EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[]);
48 public:
49  virtual void DoRun (void);
50  BufferTest ();
51 };
52 
53 
55  : TestCase ("Buffer") {
56 }
57 
58 void
59 BufferTest::EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[])
60 {
61  bool success = true;
62  uint8_t *expected = array;
63  uint8_t const*got;
64  got = b.PeekData ();
65  for (uint32_t j = 0; j < n; j++)
66  {
67  if (got[j] != expected[j])
68  {
69  success = false;
70  }
71  }
72  if (!success)
73  {
74  std::ostringstream failure;
75  failure << "Buffer -- ";
76  failure << "expected: n=";
77  failure << n << ", ";
78  failure.setf (std::ios::hex, std::ios::basefield);
79  for (uint32_t j = 0; j < n; j++)
80  {
81  failure << (uint16_t)expected[j] << " ";
82  }
83  failure.setf (std::ios::dec, std::ios::basefield);
84  failure << "got: ";
85  failure.setf (std::ios::hex, std::ios::basefield);
86  for (uint32_t j = 0; j < n; j++)
87  {
88  failure << (uint16_t)got[j] << " ";
89  }
90  failure << std::endl;
91  NS_TEST_ASSERT_MSG_EQ (true, false, failure.str ());
92  }
93 }
94 
95 /*
96  * Works only when variadic macros are
97  * available which is the case for gcc.
98  */
99 #define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
100  { \
101  uint8_t bytes[] = { __VA_ARGS__}; \
102  EnsureWrittenBytes (buffer, n, bytes); \
103  }
104 
105 void
107 {
108  Buffer buffer;
110  buffer.AddAtStart (6);
111  i = buffer.Begin ();
112  i.WriteU8 (0x66);
113  ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
114  i = buffer.Begin ();
115  i.WriteU8 (0x67);
116  ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
117  i.WriteHtonU16 (0x6568);
118  i = buffer.Begin ();
119  ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
120  i.WriteHtonU16 (0x6369);
121  ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
122  i.WriteHtonU32 (0xdeadbeaf);
123  ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
124  buffer.AddAtStart (2);
125  i = buffer.Begin ();
126  i.WriteU16 (0);
127  ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
128  buffer.AddAtEnd (2);
129  i = buffer.Begin ();
130  i.Next (8);
131  i.WriteU16 (0);
132  ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
133  buffer.RemoveAtStart (3);
134  i = buffer.Begin ();
135  ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
136  buffer.RemoveAtEnd (4);
137  i = buffer.Begin ();
138  ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
139  buffer.AddAtStart (1);
140  i = buffer.Begin ();
141  i.WriteU8 (0xff);
142  ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
143  buffer.AddAtEnd (1);
144  i = buffer.Begin ();
145  i.Next (4);
146  i.WriteU8 (0xff);
147  i.Prev (2);
148  uint16_t saved = i.ReadU16 ();
149  i.Prev (2);
150  i.WriteHtonU16 (0xff00);
151  i.Prev (2);
152  NS_TEST_ASSERT_MSG_EQ (i.ReadNtohU16 (), 0xff00, "Could not read expected value");
153  i.Prev (2);
154  i.WriteU16 (saved);
155  ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
156  Buffer o = buffer;
157  ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
158  o.AddAtStart (1);
159  i = o.Begin ();
160  i.WriteU8 (0xfe);
161  ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
162  buffer.AddAtStart (2);
163  i = buffer.Begin ();
164  i.WriteU8 (0xfd);
165  i.WriteU8 (0xfd);
166  ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
167  ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
168 
169  // test 64-bit read/write
170  Buffer buff64;
171  buff64.AddAtStart (8);
172  i = buff64.Begin ();
173  i.WriteU64 (0x0123456789ABCDEFllu);
174  i = buff64.Begin ();
175  NS_TEST_ASSERT_MSG_EQ (i.ReadU64 (), 0x0123456789abcdefllu, "Could not read expected value");
176  i = buff64.Begin ();
177  i.WriteHtolsbU64 (0x0123456789ABCDEFllu);
178  ENSURE_WRITTEN_BYTES (buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
179  i = buff64.Begin ();
180  NS_TEST_ASSERT_MSG_EQ (i.ReadLsbtohU64 (), 0x0123456789abcdefllu, "Could not read expected value");
181  i = buff64.Begin ();
182  i.WriteHtonU64 (0x0123456789ABCDEFllu);
183  ENSURE_WRITTEN_BYTES (buff64, 8, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
184  i = buff64.Begin ();
185  NS_TEST_ASSERT_MSG_EQ (i.ReadNtohU64 (), 0x0123456789abcdefllu, "could not read expected value");
186 
187  // test self-assignment
188  {
189  Buffer a = o;
190 #if defined(__clang__)
191  #if __has_warning("-Wself-assign-overloaded")
192  #pragma clang diagnostic push
193  #pragma clang diagnostic ignored "-Wself-assign-overloaded"
194  #endif
195 #endif
196  a = a;
197 #if defined(__clang__)
198  #if __has_warning("-Wself-assign-overloaded")
199  #pragma clang diagnostic pop
200  #endif
201 #endif
202  }
203 
204  // test Remove start.
205  buffer = Buffer (5);
206  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
207  buffer.RemoveAtStart (1);
208  ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
209  buffer.AddAtStart (1);
210  buffer.Begin ().WriteU8 (0xff);
211  ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
212  buffer.RemoveAtStart (3);
213  ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
214  buffer.AddAtStart (4);
215  buffer.Begin ().WriteHtonU32 (0xdeadbeaf);
216  ENSURE_WRITTEN_BYTES (buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
217  buffer.RemoveAtStart (2);
218  ENSURE_WRITTEN_BYTES (buffer, 4, 0xbe, 0xaf, 0, 0);
219  buffer.AddAtEnd (4);
220  i = buffer.Begin ();
221  i.Next (4);
222  i.WriteHtonU32 (0xdeadbeaf);
223  ENSURE_WRITTEN_BYTES (buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
224  buffer.RemoveAtStart (5);
225  ENSURE_WRITTEN_BYTES (buffer, 3, 0xad, 0xbe, 0xaf);
226  // test Remove end
227  buffer = Buffer (5);
228  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
229  buffer.RemoveAtEnd (1);
230  ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
231  buffer.AddAtEnd (2);
232  i = buffer.Begin ();
233  i.Next (4);
234  i.WriteU8 (0xab);
235  i.WriteU8 (0xac);
236  ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
237  buffer.RemoveAtEnd (1);
238  ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
239  buffer.RemoveAtEnd (3);
240  ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
241  buffer.AddAtEnd (6);
242  i = buffer.Begin ();
243  i.Next (2);
244  i.WriteU8 (0xac);
245  i.WriteU8 (0xad);
246  i.WriteU8 (0xae);
247  i.WriteU8 (0xaf);
248  i.WriteU8 (0xba);
249  i.WriteU8 (0xbb);
250  ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
251  buffer.AddAtStart (3);
252  i = buffer.Begin ();
253  i.WriteU8 (0x30);
254  i.WriteU8 (0x31);
255  i.WriteU8 (0x32);
256  ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
257  buffer.RemoveAtEnd (9);
258  ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
259  buffer = Buffer (3);
260  buffer.AddAtEnd (2);
261  i = buffer.Begin ();
262  i.Next (3);
263  i.WriteHtonU16 (0xabcd);
264  buffer.AddAtStart (1);
265  buffer.Begin ().WriteU8 (0x21);
266  ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
267  buffer.RemoveAtEnd (8);
268  NS_TEST_ASSERT_MSG_EQ (buffer.GetSize (), 0, "Buffer size not zero");
269 
270  buffer = Buffer (6);
271  buffer.AddAtStart (9);
272  buffer.AddAtEnd (3);
273  i = buffer.End ();
274  i.Prev (1);
275  i.WriteU8 (1, 1);
276 
277  buffer = Buffer (6);
278  buffer.AddAtStart (3);
279  buffer.RemoveAtEnd (8);
280  buffer.AddAtEnd (4);
281  i = buffer.End ();
282  i.Prev (4);
283  i.WriteU8 (1, 4);
284 
285  buffer = Buffer (1);
286  buffer.AddAtEnd (100);
287  i = buffer.End ();
288  i.Prev (100);
289  i.WriteU8 (1, 100);
290 
293  {
294  const uint32_t actualSize = 72602;
295  const uint32_t chunkSize = 67624;
296  Ptr<UniformRandomVariable> bytesRng = CreateObject<UniformRandomVariable> ();
297  bytesRng->SetAttribute ("Min", DoubleValue (0));
298  bytesRng->SetAttribute ("Max", DoubleValue (256));
299 
300  Buffer inputBuffer;
301  Buffer outputBuffer;
302 
303  inputBuffer.AddAtEnd (actualSize);
304  {
305  Buffer::Iterator iter = inputBuffer.Begin ();
306  for (uint32_t i = 0; i < actualSize; i++)
307  iter.WriteU8 (static_cast<uint8_t> (bytesRng->GetValue ()));
308  }
309 
310  outputBuffer.AddAtEnd (chunkSize);
311  Buffer::Iterator iter = outputBuffer.End ();
312  iter.Prev (chunkSize);
313  iter.Write (inputBuffer.PeekData (), chunkSize);
314 
315  NS_TEST_EXPECT_MSG_EQ (memcmp (inputBuffer.PeekData (), outputBuffer.PeekData (), chunkSize), 0, "memcp works");
316  }
317 
318  buffer = Buffer (5);
319  buffer.AddAtEnd (2);
320  i = buffer.End ();
321  i.Prev (2);
322  i.WriteU8 (0);
323  i.WriteU8 (0x66);
324  ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
325  Buffer frag0 = buffer.CreateFragment (0, 2);
326  ENSURE_WRITTEN_BYTES (frag0, 2, 0x00, 0x00);
327  Buffer frag1 = buffer.CreateFragment (2, 5);
328  ENSURE_WRITTEN_BYTES (frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
329  frag0.AddAtEnd (frag1);
330  ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
331  ENSURE_WRITTEN_BYTES (frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
332 
333  buffer = Buffer (5);
334  buffer.AddAtStart (2);
335  i = buffer.Begin ();
336  i.WriteU8 (0x1);
337  i.WriteU8 (0x2);
338  buffer.AddAtEnd (2);
339  i = buffer.End ();
340  i.Prev (2);
341  i.WriteU8 (0x3);
342  i.WriteU8 (0x4);
343  ENSURE_WRITTEN_BYTES (buffer, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
344  Buffer other;
345  other.AddAtStart (9);
346  i = other.Begin ();
347  i.Write (buffer.Begin (), buffer.End ());
348  ENSURE_WRITTEN_BYTES (other, 9, 0x1, 0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3, 0x4);
349 
351  std::string ct ("This is the next content of the buffer.");
352  buffer = Buffer ();
353  buffer.AddAtStart (ct.size ());
354  i = buffer.Begin ();
355  i.Write ((const uint8_t*)ct.c_str (), ct.size ());
356  uint32_t sizeBuffer = buffer.GetSize ();
357  NS_TEST_ASSERT_MSG_EQ (sizeBuffer, ct.size(), "Buffer bad size");
358  uint8_t const* evilBuffer = buffer.PeekData ();
359  NS_TEST_ASSERT_MSG_NE( evilBuffer, 0, "Buffer PeekData failed");
360  uint8_t *cBuf = (uint8_t*) malloc ( sizeBuffer );
361  uint32_t copyLen = buffer.CopyData (cBuf, sizeBuffer);
362  NS_TEST_ASSERT_MSG_EQ (copyLen, sizeBuffer, "CopyData return bad size");
363  for (uint8_t i=0; i < sizeBuffer ; i++ )
364  {
365  NS_TEST_ASSERT_MSG_EQ ( cBuf [i], *(((const uint8_t*)ct.c_str ()) + i), "Bad buffer copied data");
366  NS_TEST_ASSERT_MSG_EQ ( evilBuffer [i], cBuf [i] , "Bad buffer peeked");
367  }
368  free (cBuf);
369 
371  buffer = Buffer (1);
372  buffer.AddAtEnd (2);
373  i = buffer.Begin ();
374  i.Next (1);
375  i.WriteU8 (0x77);
376  i.WriteU8 (0x66);
377  ENSURE_WRITTEN_BYTES (buffer, 3, 0x00, 0x77, 0x66);
378  i = buffer.Begin ();
379  i.ReadU8 ();
380  uint16_t val1 = i.ReadNtohU16 ();
381  i = buffer.Begin ();
382  i.ReadU8 ();
383  uint16_t val2 = 0;
384  val2 |= i.ReadU8 ();
385  val2 <<= 8;
386  val2 |= i.ReadU8 ();
387  NS_TEST_ASSERT_MSG_EQ (val1, val2, "Bad ReadNtohU16()");
388 }
389 
397 {
398 public:
399  BufferTestSuite ();
400 };
401 
403  : TestSuite ("buffer", UNIT)
404 {
405  AddTestCase (new BufferTest, TestCase::QUICK);
406 }
407 
static BufferTestSuite g_bufferTestSuite
Static variable for test initialization.
Definition: buffer-test.cc:408
#define ENSURE_WRITTEN_BYTES(buffer, n,...)
Definition: buffer-test.cc:99
Buffer unit tests.
Definition: buffer-test.cc:39
virtual void DoRun(void)
Implementation to actually run this TestCase.
Definition: buffer-test.cc:106
void EnsureWrittenBytes(Buffer b, uint32_t n, uint8_t array[])
Checks the buffer content.
Definition: buffer-test.cc:59
Buffer TestSuite.
Definition: buffer-test.cc:397
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU64(uint64_t data)
Definition: buffer.cc:891
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:954
uint16_t ReadNtohU16(void)
Definition: buffer.h:946
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:941
uint64_t ReadNtohU64(void)
Definition: buffer.cc:1044
void WriteU8(uint8_t data)
Definition: buffer.h:869
void Next(void)
go forward by one byte
Definition: buffer.h:845
void WriteU16(uint16_t data)
Definition: buffer.cc:871
uint16_t ReadU16(void)
Definition: buffer.h:1029
uint8_t ReadU8(void)
Definition: buffer.h:1021
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:927
void WriteHtonU16(uint16_t data)
Definition: buffer.h:905
void Prev(void)
go backward by one byte
Definition: buffer.h:851
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1094
uint64_t ReadU64(void)
Definition: buffer.cc:990
void WriteHtonU32(uint32_t data)
Definition: buffer.h:924
automatically resized byte buffer
Definition: buffer.h:93
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:524
uint32_t GetSize(void) const
Definition: buffer.h:1063
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:720
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:488
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
void AddAtEnd(uint32_t end)
Definition: buffer.cc:354
Buffer::Iterator End(void) const
Definition: buffer.h:1075
uint8_t const * PeekData(void) const
Definition: buffer.cc:710
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:443
This class can be used to hold variables of floating point type such as 'double' or 'float'.
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:256
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
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:141
#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:542
Every class exported by the ns3 library is enclosed in the ns3 namespace.