A Discrete-Event Network Simulator
API
time-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005,2006 INRIA
3  * Copyright (c) 2007 Emmanuelle Laprise
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@sophia.inria.fr>
19  * TimeStep support by Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
20  */
21 
22 #include "ns3/int64x64.h"
23 #include "ns3/nstime.h"
24 #include "ns3/test.h"
25 
26 #include <array>
27 #include <iomanip>
28 #include <iostream>
29 #include <sstream>
30 #include <string>
31 #include <tuple>
32 
33 using namespace ns3;
34 
40 {
41  public:
46 
47  private:
51  void DoSetup() override;
52 
56  void DoRun() override;
57 
61  virtual void DoTimeOperations();
62 
66  void DoTeardown() override;
67 
78  template <typename T>
79  void TestMultiplication(Time t, Time expected, T val, const std::string& msg);
80 
84  void TestMultiplicationByIntegerTypes();
85 
89  void TestMultiplicationByDecimalTypes();
90 
101  template <typename T>
102  void TestDivision(Time t, Time expected, T val, const std::string& msg);
103 
107  void TestDivisionByIntegerTypes();
108 
112  void TestDivisionByDecimalTypes();
113 };
114 
116  : TestCase("Sanity check of common time operations")
117 {
118 }
119 
120 void
122 {
123 }
124 
125 void
127 {
128  // Test Multiplication
129  constexpr long long oneSec = 1000000000; // conversion to default nanoseconds
130 
131  // Time in seconds
132  ns3::Time t1 = Time(125LL * oneSec);
133  ns3::Time t2 = Time(2000LL * oneSec);
134 
135  std::cout << "Testing Time Subtraction \n";
136 
137  NS_TEST_ASSERT_MSG_EQ((t2 - t1).GetSeconds(), 1875, "Time Subtraction");
138 
139  // Test Multiplication Operations:
140  std::cout << "Testing Time Multiplication \n";
141 
144 
145  // Test Division Operations:
146  std::cout << "Testing Time Division \n";
147 
150 
151  std::cout << "Testing modulo division \n";
152 
153  t1 = Time(101LL * oneSec);
154  NS_TEST_ASSERT_MSG_EQ((t2 % t1).GetSeconds(), 81, "Remainder Operation (2000 % 101 = 81)");
155  NS_TEST_ASSERT_MSG_EQ(Div(t2, t1), 19, "Modular Division");
156  NS_TEST_ASSERT_MSG_EQ(Rem(t2, t1).GetSeconds(), 81, "Remainder Operation (2000 % 101 = 81)");
157 }
158 
159 void
161 {
162  NS_TEST_ASSERT_MSG_EQ_TOL(Years(1.0).GetYears(), 1.0, Years(1).GetYears(), "is 1 really 1 ?");
163  NS_TEST_ASSERT_MSG_EQ_TOL(Years(10.0).GetYears(),
164  10.0,
165  Years(1).GetYears(),
166  "is 10 really 10 ?");
167  NS_TEST_ASSERT_MSG_EQ_TOL(Days(1.0).GetDays(), 1.0, Days(1).GetDays(), "is 1 really 1 ?");
168  NS_TEST_ASSERT_MSG_EQ_TOL(Days(10.0).GetDays(), 10.0, Days(1).GetDays(), "is 10 really 10 ?");
169  NS_TEST_ASSERT_MSG_EQ_TOL(Hours(1.0).GetHours(), 1.0, Hours(1).GetHours(), "is 1 really 1 ?");
170  NS_TEST_ASSERT_MSG_EQ_TOL(Hours(10.0).GetHours(),
171  10.0,
172  Hours(1).GetHours(),
173  "is 10 really 10 ?");
174  NS_TEST_ASSERT_MSG_EQ_TOL(Minutes(1.0).GetMinutes(),
175  1.0,
176  Minutes(1).GetMinutes(),
177  "is 1 really 1 ?");
178  NS_TEST_ASSERT_MSG_EQ_TOL(Minutes(10.0).GetMinutes(),
179  10.0,
180  Minutes(1).GetMinutes(),
181  "is 10 really 10 ?");
182  NS_TEST_ASSERT_MSG_EQ_TOL(Seconds(1.0).GetSeconds(),
183  1.0,
184  TimeStep(1).GetSeconds(),
185  "is 1 really 1 ?");
186  NS_TEST_ASSERT_MSG_EQ_TOL(Seconds(10.0).GetSeconds(),
187  10.0,
188  TimeStep(1).GetSeconds(),
189  "is 10 really 10 ?");
190  NS_TEST_ASSERT_MSG_EQ(MilliSeconds(1).GetMilliSeconds(), 1, "is 1ms really 1ms ?");
191  NS_TEST_ASSERT_MSG_EQ(MicroSeconds(1).GetMicroSeconds(), 1, "is 1us really 1us ?");
192 
194 
195 #if 0
196  Time ns = NanoSeconds (1);
197  ns.GetNanoSeconds ();
198  NS_TEST_ASSERT_MSG_EQ (NanoSeconds (1).GetNanoSeconds (), 1,
199  "is 1ns really 1ns ?");
200  NS_TEST_ASSERT_MSG_EQ (PicoSeconds (1).GetPicoSeconds (), 1,
201  "is 1ps really 1ps ?");
202  NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1,
203  "is 1fs really 1fs ?");
204 #endif
205 
206  Time ten = NanoSeconds(10);
207  int64_t tenValue = ten.GetInteger();
208  Time::SetResolution(Time::PS);
209  int64_t tenKValue = ten.GetInteger();
210  NS_TEST_ASSERT_MSG_EQ(tenValue * 1000, tenKValue, "change resolution to PS");
211 }
212 
213 void
215 {
216 }
217 
218 template <typename T>
219 void
220 TimeSimpleTestCase::TestMultiplication(Time t, Time expected, T val, const std::string& msg)
221 
222 {
223  using TestEntry = std::tuple<Time, std::string>;
224  std::array<TestEntry, 2> TESTS{std::make_tuple(t * val, "Test Time * value: "),
225  std::make_tuple(val * t, "Test Time * value: ")};
226 
227  for (auto test : TESTS)
228  {
229  std::string errMsg = std::get<1>(test) + msg;
230 
231  NS_TEST_ASSERT_MSG_EQ(std::get<0>(test), expected, errMsg);
232  }
233 }
234 
235 void
237 {
238  int sec = 125;
239  int scale = 100;
240 
241  Time t = Seconds(sec);
242  Time expected = Time(t.GetTimeStep() * scale);
243 
244  TestMultiplication(t, expected, static_cast<char>(scale), "Multiplication by char");
246  expected,
247  static_cast<unsigned char>(scale),
248  "Multiplication by unsigned char");
249  TestMultiplication(t, expected, static_cast<short>(scale), "Multiplication by short");
251  expected,
252  static_cast<unsigned short>(scale),
253  "Multiplication by unsigned short");
254  TestMultiplication(t, expected, static_cast<int>(scale), "Multiplication by int");
256  expected,
257  static_cast<unsigned int>(scale),
258  "Multiplication by unsigned int");
259  TestMultiplication(t, expected, static_cast<long>(scale), "Multiplication by long");
261  expected,
262  static_cast<unsigned long>(scale),
263  "Multiplication by unsigned long");
264  TestMultiplication(t, expected, static_cast<long long>(scale), "Multiplication by long long");
266  expected,
267  static_cast<unsigned long long>(scale),
268  "Multiplication by unsigned long long");
269  TestMultiplication(t, expected, static_cast<std::size_t>(scale), "Multiplication by size_t");
270 
271  int64x64_t scale64 = 100;
272  TestMultiplication(t, expected, scale64, "Multiplication by int64x64_t");
273 }
274 
275 void
277 {
278  float sec = 150.0;
279  float scale = 100.2;
280 
281  Time t = Seconds(sec);
282  Time expected = Time(t.GetDouble() * scale);
283 
284  TestMultiplication(t, expected, scale, "Multiplication by float");
285  TestMultiplication(t, expected, static_cast<double>(scale), "Multiplication by double");
286 }
287 
288 template <typename T>
289 void
290 TimeSimpleTestCase::TestDivision(Time t, Time expected, T val, const std::string& msg)
291 {
292  Time result = t / val;
293 
294  NS_TEST_ASSERT_MSG_EQ(result, expected, msg);
295 }
296 
297 void
299 {
300  int sec = 2000;
301  int scale = 100;
302 
303  Time t = Seconds(sec);
304  Time expected = Time(t.GetTimeStep() / scale);
305 
306  TestDivision(t, expected, static_cast<char>(scale), "Division by char");
307  TestDivision(t, expected, static_cast<unsigned char>(scale), "Division by unsigned char");
308  TestDivision(t, expected, static_cast<short>(scale), "Division by short");
309  TestDivision(t, expected, static_cast<unsigned short>(scale), "Division by unsigned short");
310  TestDivision(t, expected, static_cast<int>(scale), "Division by int");
311  TestDivision(t, expected, static_cast<unsigned int>(scale), "Division by unsigned int");
312  TestDivision(t, expected, static_cast<long>(scale), "Division by long");
313  TestDivision(t, expected, static_cast<unsigned long>(scale), "Division by unsigned long");
314  TestDivision(t, expected, static_cast<long long>(scale), "Division by long long");
315  TestDivision(t,
316  expected,
317  static_cast<unsigned long long>(scale),
318  "Division by unsigned long long");
319  TestDivision(t, expected, static_cast<std::size_t>(scale), "Division by size_t");
320 
321  int64x64_t scale64 = 100;
322  TestDivision(t, expected, scale64, "Division by int64x64_t");
323 }
324 
325 void
327 {
328  float sec = 200.0;
329  float scale = 0.2;
330 
331  Time t = Seconds(sec);
332  Time expected = t / int64x64_t(scale);
333 
334  TestDivision(t, expected, scale, "Division by float");
335  TestDivision(t, expected, static_cast<double>(scale), "Division by double");
336 }
337 
343 {
344  public:
349 
350  private:
354  void DoSetup() override;
355 
359  void DoRun() override;
360 
364  void DoTeardown() override;
365 };
366 
368  : TestCase("Checks times that have plus or minus signs")
369 {
370 }
371 
372 void
374 {
375 }
376 
377 void
379 {
380  Time timePositive("+1000.0");
381  Time timePositiveWithUnits("+1000.0ms");
382 
383  Time timeNegative("-1000.0");
384  Time timeNegativeWithUnits("-1000.0ms");
385 
386  NS_TEST_ASSERT_MSG_EQ_TOL(timePositive.GetSeconds(),
387  +1000.0,
388  1.0e-8,
389  "Positive time not parsed correctly.");
390 
391  NS_TEST_ASSERT_MSG_EQ_TOL(timePositiveWithUnits.GetSeconds(),
392  +1.0,
393  1.0e-8,
394  "Positive time with units not parsed correctly.");
395 
396  NS_TEST_ASSERT_MSG_EQ_TOL(timeNegative.GetSeconds(),
397  -1000.0,
398  1.0e-8,
399  "Negative time not parsed correctly.");
400 
401  NS_TEST_ASSERT_MSG_EQ_TOL(timeNegativeWithUnits.GetSeconds(),
402  -1.0,
403  1.0e-8,
404  "Negative time with units not parsed correctly.");
405 }
406 
407 void
409 {
410 }
411 
417 {
418  public:
423 
424  private:
428  void DoRun() override;
433  void Check(const std::string& str);
434 
440  void CheckAs(const Time t, const std::string expect);
441 };
442 
444  : TestCase("Input,output from,to strings")
445 {
446 }
447 
448 void
449 TimeInputOutputTestCase::Check(const std::string& str)
450 {
451  std::stringstream ss(str);
452  Time time;
453  ss >> time;
454  ss << time;
455  bool pass = (str == ss.str());
456 
457  std::cout << GetParent()->GetName() << " InputOutput: " << (pass ? "pass " : "FAIL ") << "\""
458  << str << "\"";
459  if (!pass)
460  {
461  std::cout << ", got " << ss.str();
462  }
463  std::cout << std::endl;
464  NS_TEST_EXPECT_MSG_EQ(ss.str(), str, "round trip conversion from/to string");
465 }
466 
467 void
468 TimeInputOutputTestCase::CheckAs(const Time t, const std::string expect)
469 {
470  std::stringstream ss;
471  ss << std::fixed << std::setprecision(6) << t.As();
472  std::string str;
473  ss >> str;
474  bool pass = (str == expect);
475 
476  std::cout << GetParent()->GetName() << " InputOutput:As: " << (pass ? "pass " : "FAIL ") << "\""
477  << expect << "\"";
478  if (!pass)
479  {
480  std::cout << ", got " << str;
481  }
482  std::cout << std::endl;
483  NS_TEST_EXPECT_MSG_EQ(str, expect, "Time::As() autoscaling");
484 }
485 
486 void
488 {
489  std::cout << std::endl;
490  std::cout << GetParent()->GetName() << " InputOutput: " << GetName() << std::endl;
491 
492  Check("2ns");
493  Check("+3.1us");
494  Check("-4.2ms");
495  Check("5.3s");
496  Check("6.4min");
497  Check("7.5h");
498  Check("8.6d");
499  Check("10.8y");
500 
501  Time t(3.141592654e9); // Pi seconds
502 
503  std::cout << GetParent()->GetName() << " InputOutput: "
504  << "example: raw: " << t << std::endl;
505 
506  std::cout << GetParent()->GetName() << " InputOutput: " << std::fixed << std::setprecision(9)
507  << "example: in s: " << t.As(Time::S) << std::endl;
508 
509  std::cout << GetParent()->GetName() << " InputOutput: " << std::setprecision(6)
510  << "example: in ms: " << t.As(Time::MS) << std::endl;
511 
512  std::cout << GetParent()->GetName() << " InputOutput: "
513  << "example: Get ns: " << t.GetNanoSeconds() << std::endl;
514 
515  std::cout << GetParent()->GetName() << " InputOutput: "
516  << "example: auto scale: \n";
517  CheckAs(t * 1e-9, "+3.000000ns");
518  CheckAs(t * 1e-8, "+31.000000ns");
519  CheckAs(t * 1e-7, "+314.000000ns");
520  CheckAs(t * 1e-6, "+3.142000us");
521  CheckAs(t * 1e-5, "+31.416000us");
522  CheckAs(t * 1e-4, "+314.159000us");
523  CheckAs(t * 1e-3, "+3.141593ms");
524  CheckAs(t * 1e-2, "+31.415927ms");
525  CheckAs(t * 1e-1, "+314.159265ms");
526  CheckAs(t * 1e-0, "+3.141593s");
527  CheckAs(t * 1e+1, "+31.415927s");
528  CheckAs(t * 1e+2, "+5.235988min");
529  CheckAs(t * 1e+3, "+52.359878min");
530  CheckAs(t * 1e+4, "+8.726646h");
531  CheckAs(t * 1e+5, "+3.636103d");
532  CheckAs(t * 1e+6, "+36.361026d");
533  CheckAs(t * 1e+7, "+363.610261d");
534  CheckAs(t * 1e+8, "+9.961925y");
535 }
536 
541 static class TimeTestSuite : public TestSuite
542 {
543  public:
545  : TestSuite("time", UNIT)
546  {
547  AddTestCase(new TimeWithSignTestCase(), TestCase::QUICK);
548  AddTestCase(new TimeInputOutputTestCase(), TestCase::QUICK);
549  // This should be last, since it changes the resolution
550  AddTestCase(new TimeSimpleTestCase(), TestCase::QUICK);
551  }
552 }
Input output Test Case for Time.
TimeInputOutputTestCase()
Constructor for TimeInputOutputTestCase.
void DoRun() override
DoRun for TimeInputOutputTestCase.
void CheckAs(const Time t, const std::string expect)
Check autoscaling output using Time::As()
void Check(const std::string &str)
Check roundtrip from/to string.
time simple test case, Checks the basic operations on time
void DoTeardown() override
Does the tear down for TimeSimpleTestCase.
virtual void DoTimeOperations()
Tests the Time Operations.
void DoSetup() override
setup function for TimeSimpleTestCase.
void TestMultiplicationByDecimalTypes()
Test multiplying a Time instance by various decimal types.
void TestMultiplicationByIntegerTypes()
Test multiplying a Time instance by various integer types.
TimeSimpleTestCase()
constructor for TimeSimpleTestCase.
void DoRun() override
Runs the Simple Time test case.
void TestDivisionByIntegerTypes()
Test dividing a Time instance by various integer types.
void TestDivision(Time t, Time expected, T val, const std::string &msg)
Helper function to handle boilerplate code for division tests.
void TestDivisionByDecimalTypes()
Test dividing a Time instance by various decimal types.
void TestMultiplication(Time t, Time expected, T val, const std::string &msg)
Helper function to handle boilerplate code for multiplication tests.
Time test Suite.
time-tests Time with Sign test case
void DoTeardown() override
DoTeardown for TimeWithSignTestCase.
void DoSetup() override
DoSetup for TimeWithSignTestCase.
void DoRun() override
DoRun for TimeWithSignTestCase.
TimeWithSignTestCase()
constructor for TimeWithSignTestCase.
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
TestCase * GetParent() const
Get the parent of this TestCase.
Definition: test.cc:380
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:418
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
int64_t GetInteger() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:455
double GetDouble() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:450
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:445
High precision numerical type, implementing Q64.64 fixed precision.
TimeTestSuite g_timeTestSuite
Member variable for time test suite.
int64_t Div(const Length &numerator, const Length &denominator, Length *remainder)
Calculate how many times numerator can be split into denominator sized pieces.
Definition: length.cc:482
#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_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:337
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time Days(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1290
Time Hours(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1302
Time PicoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1374
Time FemtoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1386
Time Minutes(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1314
Time Years(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time Rem(const Time &lhs, const Time &rhs)
Remainder (modulus) from the quotient of two Times.
Definition: nstime.h:1133