A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tcp-header-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
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  */
19 
20 #define __STDC_LIMIT_MACROS
21 #include <stdint.h>
22 #include "ns3/test.h"
23 #include "ns3/core-module.h"
24 #include "ns3/tcp-header.h"
25 #include "ns3/buffer.h"
26 #include "../model/tcp-option-rfc793.h"
27 
28 namespace ns3 {
29 
30 #define GET_RANDOM_UINT32(RandomVariable) \
31  static_cast<uint32_t> (RandomVariable->GetInteger (0, UINT32_MAX))
32 
33 #define GET_RANDOM_UINT16(RandomVariable) \
34  static_cast<uint16_t> (RandomVariable->GetInteger (0, UINT16_MAX))
35 
36 #define GET_RANDOM_UINT8(RandomVariable) \
37  static_cast<uint8_t> (RandomVariable->GetInteger (0, UINT8_MAX))
38 
39 #define GET_RANDOM_UINT6(RandomVariable) \
40  static_cast<uint8_t> (RandomVariable->GetInteger (0, UINT8_MAX >> 2))
41 
43 {
44 public:
45  TcpHeaderGetSetTestCase (std::string name);
46 protected:
47 private:
48  virtual void DoRun (void);
49  virtual void DoTeardown (void);
50 
51 };
52 
54 {
55 }
57 {
58  uint16_t sourcePort;
59  uint16_t destinationPort;
60  SequenceNumber32 sequenceNumber;
61  SequenceNumber32 ackNumber;
62  uint8_t flags;
63  uint16_t windowSize;
64  uint16_t urgentPointer;
65  TcpHeader header;
66  Buffer buffer;
67 
68  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
69  for (uint32_t i = 0; i < 1000; ++i)
70  {
71  sourcePort = GET_RANDOM_UINT16 (x);
72  destinationPort = GET_RANDOM_UINT16 (x);
73  sequenceNumber = SequenceNumber32 (GET_RANDOM_UINT32 (x));
74  ackNumber = SequenceNumber32 (GET_RANDOM_UINT32 (x));
75  flags = GET_RANDOM_UINT6 (x);
76  windowSize = GET_RANDOM_UINT16 (x);
77  urgentPointer = GET_RANDOM_UINT16 (x);
78 
79  header.SetSourcePort (sourcePort);
80  header.SetDestinationPort (destinationPort);
81  header.SetSequenceNumber (sequenceNumber);
82  header.SetAckNumber (ackNumber);
83  header.SetFlags (flags);
84  header.SetWindowSize (windowSize);
85  header.SetUrgentPointer (urgentPointer);
86 
87  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
88  " not 5 word");
89 
90  buffer.AddAtStart (header.GetSerializedSize ());
91  header.Serialize (buffer.Begin ());
92 
93  NS_TEST_ASSERT_MSG_EQ (sourcePort, header.GetSourcePort (),
94  "Different source port found");
95  NS_TEST_ASSERT_MSG_EQ (destinationPort, header.GetDestinationPort (),
96  "Different destination port found");
97  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, header.GetSequenceNumber (),
98  "Different sequence number found");
99  NS_TEST_ASSERT_MSG_EQ (ackNumber, header.GetAckNumber (),
100  "Different ack number found");
101  NS_TEST_ASSERT_MSG_EQ (flags, header.GetFlags (),
102  "Different flags found");
103  NS_TEST_ASSERT_MSG_EQ (windowSize, header.GetWindowSize (),
104  "Different window size found");
105  NS_TEST_ASSERT_MSG_EQ (urgentPointer, header.GetUrgentPointer (),
106  "Different urgent pointer found");
107 
108  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
109  " not 5 word");
110 
111  TcpHeader copyHeader;
112 
113  copyHeader.Deserialize (buffer.Begin ());
114 
115  NS_TEST_ASSERT_MSG_EQ (sourcePort, copyHeader.GetSourcePort (),
116  "Different source port found in deserialized header");
117  NS_TEST_ASSERT_MSG_EQ (destinationPort, copyHeader.GetDestinationPort (),
118  "Different destination port found in deserialized header");
119  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, copyHeader.GetSequenceNumber (),
120  "Different sequence number found in deserialized header");
121  NS_TEST_ASSERT_MSG_EQ (ackNumber, copyHeader.GetAckNumber (),
122  "Different ack number found in deserialized header");
123  NS_TEST_ASSERT_MSG_EQ (flags, copyHeader.GetFlags (),
124  "Different flags found in deserialized header");
125  NS_TEST_ASSERT_MSG_EQ (windowSize, copyHeader.GetWindowSize (),
126  "Different window size found in deserialized header");
127  NS_TEST_ASSERT_MSG_EQ (urgentPointer, copyHeader.GetUrgentPointer (),
128  "Different urgent pointer found in deserialized header");
129  }
130 }
131 
133 {
134 
135 }
136 
138 {
139 public:
140  TcpHeaderWithRFC793OptionTestCase (std::string name);
141 
142 private:
143  virtual void DoRun (void);
144  virtual void DoTeardown (void);
145 
150  void OneOptionAtTime ();
151  void CheckNoPadding ();
152  void CheckCorrectDeserialize ();
153 };
154 
155 
157  : TestCase (name)
158 {
159 
160 }
161 
162 void
164 {
165  OneOptionAtTime ();
166  CheckNoPadding ();
168 }
169 
170 void
172 {
173  TcpHeader source, destination;
174  TcpOptionNOP temp;
175  Buffer buffer;
176  buffer.AddAtStart (40);
177 
178  Buffer::Iterator i = buffer.Begin ();
179  source.AppendOption (&temp);
180 
181  source.Serialize (i);
182 
183  i.ReadU8 ();
184  i.WriteU8 (59);
185 
186  i = buffer.Begin ();
187  destination.Deserialize (i);
188 
189  NS_TEST_ASSERT_MSG_EQ (destination.HasOption (59), false, "Kind 59 registered");
190 }
191 
192 void
194 {
195  {
196  TcpOptionNOP oNop1, oNop2, oNop3, oNop4;
197  TcpHeader header;
198  Buffer buffer;
199 
200  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
201  " not 5 word");
202  header.AppendOption (&oNop1);
203  header.AppendOption (&oNop2);
204  header.AppendOption (&oNop3);
205  header.AppendOption (&oNop4);
206 
207  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "Four byte added as option "
208  "are not a word");
209  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Four byte added as option "
210  "are not a word");
211 
212  buffer.AddAtStart (header.GetSerializedSize ());
213  header.Serialize (buffer.Begin ());
214 
216  buffer.GetSize (), "Header not correctly serialized");
217 
218  // Inserted 4 byte NOP, no padding should be present
219  Buffer::Iterator i = buffer.Begin ();
220  i.Next (20);
221 
222  for (uint32_t j = 0; j < 4; ++j)
223  {
224  std::stringstream ss;
225  ss << j;
226  uint8_t value = i.ReadU8 ();
228  "NOP not present at position " + ss.str ());
229  }
230  }
231 }
232 
233 void
235 {
236  {
237  TcpOptionEnd oEnd;
238  TcpHeader header;
239  Buffer buffer;
240 
241  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
242  " not 5 word");
243  header.AppendOption (&oEnd);
244  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "Length has changed also for"
245  " END option");
246  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 20, "Length has changed also for"
247  " END option");
248 
249 
250  buffer.AddAtStart (header.GetSerializedSize ());
251  header.Serialize (buffer.Begin ());
252 
254  buffer.GetSize (), "Header not correctly serialized");
255  }
256 
257  {
258  TcpOptionNOP oNop;
259  TcpHeader header;
260  Buffer buffer;
261 
262  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
263  " not 5 word");
264  header.AppendOption (&oNop);
265  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "NOP option not handled correctly");
266  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
267  "NOP option");
268 
269  buffer.AddAtStart (header.GetSerializedSize ());
270  header.Serialize (buffer.Begin ());
271 
273  buffer.GetSize (), "Header not correctly serialized");
274 
275  // Inserted only 1 byte NOP, and so implementation should pad; so
276  // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
277  Buffer::Iterator i = buffer.Begin ();
278  i.Next (20);
279 
280  uint8_t value = i.ReadU8 ();
281  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::NOP, "NOP not present at byte 1");
282  value = i.ReadU8 ();
283  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "END not present at byte 2");
284  value = i.ReadU8 ();
285  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 3");
286  value = i.ReadU8 ();
287  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 4");
288  }
289 
290  {
291  TcpOptionMSS oMSS;
292  oMSS.SetMSS (50);
293  TcpHeader header, dest;
294  Buffer buffer;
295 
296  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
297  " not 5 word");
298  header.AppendOption (&oMSS);
299  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "MSS option not handled correctly");
300  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
301  "MSS option");
302 
303  buffer.AddAtStart (header.GetSerializedSize ());
304  header.Serialize (buffer.Begin ());
305 
307  buffer.GetSize (), "Header not correctly serialized");
308 
309  dest.Deserialize (buffer.Begin ());
311  true, "MSS option not correctly serialized");
312  }
313 }
314 
315 
316 void
318 {
319  uint32_t foo;
320  foo = UINT32_MAX;
321  foo--;
322 
323 }
324 
326 {
327 public:
328  TcpHeaderFlagsToString (std::string name);
329 
330 private:
331  virtual void DoRun (void);
332 };
333 
335  : TestCase (name)
336 {
337 }
338 
339 void
341 {
342  std::string str, target;
343  str = TcpHeader::FlagsToString (0x0);
344  target = "";
345  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
346  str = TcpHeader::FlagsToString (0x1);
347  target = "FIN";
348  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
349  str = TcpHeader::FlagsToString (0x2);
350  target = "SYN";
351  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
352  str = TcpHeader::FlagsToString (0x4);
353  target = "RST";
354  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
355  str = TcpHeader::FlagsToString (0x8);
356  target = "PSH";
357  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
358  str = TcpHeader::FlagsToString (0x10);
359  target = "ACK";
360  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
361  str = TcpHeader::FlagsToString (0x20);
362  target = "URG";
363  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
364  str = TcpHeader::FlagsToString (0x40);
365  target = "ECE";
366  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
367  str = TcpHeader::FlagsToString (0x80);
368  target = "CWR";
369  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
370  str = TcpHeader::FlagsToString (0x3);
371  target = "FIN|SYN";
372  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
373  str = TcpHeader::FlagsToString (0x5);
374  target = "FIN|RST";
375  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
376  str = TcpHeader::FlagsToString (0xff);
377  target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
378  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
379  str = TcpHeader::FlagsToString (0xff, ":");
380  target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
381  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
382 }
383 
384 static class TcpHeaderTestSuite : public TestSuite
385 {
386 public:
388  : TestSuite ("tcp-header", UNIT)
389  {
390  AddTestCase (new TcpHeaderGetSetTestCase ("GetSet test cases"), TestCase::QUICK);
391  AddTestCase (new TcpHeaderWithRFC793OptionTestCase ("Test for options in RFC 793"), TestCase::QUICK);
392  AddTestCase (new TcpHeaderFlagsToString ("Test flags to string function"), TestCase::QUICK);
393  }
394 
396 
397 } // namespace ns3
static std::string FlagsToString(uint8_t flags, const std::string &delimiter="|")
Converts an integer into a human readable list of Tcp flags.
Definition: tcp-header.cc:55
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
void SetMSS(uint16_t mss)
Set the Maximum Segment Size stored in the Option.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
Defines the TCP option of kind 1 (no operation) as in RFC 793
A suite of tests to run.
Definition: test.h:1333
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
automatically resized byte buffer
Definition: buffer.h:92
#define GET_RANDOM_UINT6(RandomVariable)
encapsulates test code
Definition: test.h:1147
iterator in a Buffer instance
Definition: buffer.h:98
TcpHeaderGetSetTestCase(std::string name)
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:460
ns3::TcpHeaderTestSuite g_TcpHeaderTestSuite
TcpHeaderFlagsToString(std::string name)
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:297
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
#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:161
virtual void DoRun(void)
Implementation to actually run this TestCase.
Defines the TCP option of kind 0 (end of option list) as in RFC 793
void Next(void)
go forward by one byte
Definition: buffer.h:839
Buffer::Iterator Begin(void) const
Definition: buffer.h:1063
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
void OneOptionAtTime()
Check an header with only one kind of option.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
uint32_t GetSize(void) const
Definition: buffer.h:1057
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:309
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
Fast test.
Definition: test.h:1152
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:360
#define GET_RANDOM_UINT16(RandomVariable)
void WriteU8(uint8_t data)
Definition: buffer.h:863
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
#define GET_RANDOM_UINT32(RandomVariable)
Defines the TCP option of kind 2 (maximum segment size) as in RFC 793
uint8_t ReadU8(void)
Definition: buffer.h:1015
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
This test suite implements a Unit Test.
Definition: test.h:1343
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:502
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
virtual void DoRun(void)
Implementation to actually run this TestCase.
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:185
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:315
virtual void DoRun(void)
Implementation to actually run this TestCase.