A Discrete-Event Network Simulator
API
threaded-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 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: Claudio Freire <claudio-daniel.freire@inria.fr>
19  */
20 #include "ns3/test.h"
21 #include "ns3/simulator.h"
22 #include "ns3/list-scheduler.h"
23 #include "ns3/heap-scheduler.h"
24 #include "ns3/map-scheduler.h"
25 #include "ns3/calendar-scheduler.h"
26 #include "ns3/config.h"
27 #include "ns3/string.h"
28 #include "ns3/system-thread.h"
29 
30 #include <chrono> // seconds, milliseconds
31 #include <ctime>
32 #include <list>
33 #include <thread> // sleep_for
34 #include <utility>
35 
36 using namespace ns3;
37 
38 #define MAXTHREADS 64
39 
41 {
42 public:
43  ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads);
44  void EventA (int a);
45  void EventB (int b);
46  void EventC (int c);
47  void EventD (int d);
48  void DoNothing (unsigned int threadno);
49  static void SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context);
50  void End (void);
51  uint64_t m_b;
52  uint64_t m_a;
53  uint64_t m_c;
54  uint64_t m_d;
55  unsigned int m_threads;
56  bool m_threadWaiting[MAXTHREADS];
57  bool m_stop;
59  std::string m_simulatorType;
60  std::string m_error;
61  std::list<Ptr<SystemThread> > m_threadlist;
62 
63 private:
64  virtual void DoSetup (void);
65  virtual void DoRun (void);
66  virtual void DoTeardown (void);
67 };
68 
69 ThreadedSimulatorEventsTestCase::ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
70  : TestCase ("Check threaded event handling with " +
71  std::to_string (threads) + " threads, " +
72  schedulerFactory.GetTypeId ().GetName () + " scheduler, in " +
73  simulatorType),
74  m_threads (threads),
75  m_schedulerFactory (schedulerFactory),
76  m_simulatorType (simulatorType)
77 {}
78 
79 void
81 {
82  m_stop = true;
83  for (std::list<Ptr<SystemThread> >::iterator it2 = m_threadlist.begin (); it2 != m_threadlist.end (); ++it2)
84  {
85  (*it2)->Join ();
86  }
87 }
88 void
89 ThreadedSimulatorEventsTestCase::SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context)
90 {
91  ThreadedSimulatorEventsTestCase *me = context.first;
92  unsigned int threadno = context.second;
93 
94  while (!me->m_stop)
95  {
96  me->m_threadWaiting[threadno] = true;
97  Simulator::ScheduleWithContext (threadno,
98  MicroSeconds (1),
100  while (!me->m_stop && me->m_threadWaiting[threadno])
101  {
102  std::this_thread::sleep_for (std::chrono::nanoseconds (500));
103  }
104  }
105 }
106 void
108 {
109  if (!m_error.empty ())
110  {
111  m_error = "Bad threaded scheduling";
112  }
113  m_threadWaiting[threadno] = false;
114 }
115 void
117 {
118  if (m_a != m_b || m_a != m_c || m_a != m_d)
119  {
120  m_error = "Bad scheduling";
121  Simulator::Stop ();
122  }
123  ++m_a;
124  Simulator::Schedule (MicroSeconds (10),
126 }
127 
128 void
130 {
131  if (m_a != (m_b + 1) || m_a != (m_c + 1) || m_a != (m_d + 1))
132  {
133  m_error = "Bad scheduling";
134  Simulator::Stop ();
135  }
136  ++m_b;
137  Simulator::Schedule (MicroSeconds (10),
139 }
140 
141 void
143 {
144  if (m_a != m_b || m_a != (m_c + 1) || m_a != (m_d + 1))
145  {
146  m_error = "Bad scheduling";
147  Simulator::Stop ();
148  }
149  ++m_c;
150  Simulator::Schedule (MicroSeconds (10),
152 }
153 
154 void
156 {
157  if (m_a != m_b || m_a != m_c || m_a != (m_d + 1))
158  {
159  m_error = "Bad scheduling";
160  Simulator::Stop ();
161  }
162  ++m_d;
163  if (m_stop)
164  {
165  Simulator::Stop ();
166  }
167  else
168  {
169  Simulator::Schedule (MicroSeconds (10),
171  }
172 }
173 
174 void
176 {
177  if (!m_simulatorType.empty ())
178  {
179  Config::SetGlobal ("SimulatorImplementationType", StringValue (m_simulatorType));
180  }
181 
182  m_error = "";
183 
184  m_a =
185  m_b =
186  m_c =
187  m_d = 0;
188 
189  for (unsigned int i = 0; i < m_threads; ++i)
190  {
191  m_threadlist.push_back (
192  Create<SystemThread> (MakeBoundCallback (
194  std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> (this,i) )) );
195  }
196 }
197 void
199 {
200  m_threadlist.clear ();
201 
202  Config::SetGlobal ("SimulatorImplementationType", StringValue ("ns3::DefaultSimulatorImpl"));
203 }
204 void
206 {
207  m_stop = false;
208  Simulator::SetScheduler (m_schedulerFactory);
209 
210  Simulator::Schedule (MicroSeconds (10), &ThreadedSimulatorEventsTestCase::EventA, this, 1);
211  Simulator::Schedule (Seconds (1), &ThreadedSimulatorEventsTestCase::End, this);
212 
213 
214  for (std::list<Ptr<SystemThread> >::iterator it = m_threadlist.begin (); it != m_threadlist.end (); ++it)
215  {
216  (*it)->Start ();
217  }
218 
219  Simulator::Run ();
220  Simulator::Destroy ();
221 
222  NS_TEST_EXPECT_MSG_EQ (m_error.empty (), true, m_error.c_str ());
223  NS_TEST_EXPECT_MSG_EQ (m_a, m_b, "Bad scheduling");
224  NS_TEST_EXPECT_MSG_EQ (m_a, m_c, "Bad scheduling");
225  NS_TEST_EXPECT_MSG_EQ (m_a, m_d, "Bad scheduling");
226 }
227 
229 {
230 public:
232  : TestSuite ("threaded-simulator")
233  {
234  std::string simulatorTypes[] = {
235 #ifdef HAVE_RT
236  "ns3::RealtimeSimulatorImpl",
237 #endif
238  "ns3::DefaultSimulatorImpl"
239  };
240  std::string schedulerTypes[] = {
241  "ns3::ListScheduler",
242  "ns3::HeapScheduler",
243  "ns3::MapScheduler",
244  "ns3::CalendarScheduler"
245  };
246  unsigned int threadcounts[] = {
247  0,
248  2,
249  10,
250  20
251  };
252  ObjectFactory factory;
253 
254  for (unsigned int i = 0; i < (sizeof(simulatorTypes) / sizeof(simulatorTypes[0])); ++i)
255  {
256  for (unsigned int j = 0; j < (sizeof(threadcounts) / sizeof(threadcounts[0])); ++j)
257  {
258  for (unsigned int k = 0; k < (sizeof(schedulerTypes) / sizeof(schedulerTypes[0])); ++k)
259  {
260  factory.SetTypeId (schedulerTypes[k]);
261  AddTestCase (new ThreadedSimulatorEventsTestCase (factory, simulatorTypes[i], threadcounts[j]), TestCase::QUICK);
262  }
263  }
264  }
265  }
void DoNothing(unsigned int threadno)
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
Hold variables of type string.
Definition: string.h:41
ThreadedSimulatorTestSuite g_threadedSimulatorTestSuite
A suite of tests to run.
Definition: test.h:1343
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1703
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
#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:283
encapsulates test code
Definition: test.h:1153
STL namespace.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
#define MAXTHREADS
#define list
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::list< Ptr< SystemThread > > m_threadlist
Instantiate subclasses of ns3::Object.
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:889
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
ThreadedSimulatorEventsTestCase(ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1294
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
static void SchedulingThread(std::pair< ThreadedSimulatorEventsTestCase *, unsigned int > context)