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 
80 void
82 {
83  m_stop = true;
84  for (std::list<Ptr<SystemThread> >::iterator it2 = m_threadlist.begin(); it2 != m_threadlist.end(); ++it2)
85  {
86  (*it2)->Join();
87  }
88 }
89 void
90 ThreadedSimulatorEventsTestCase::SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context)
91 {
92  ThreadedSimulatorEventsTestCase *me = context.first;
93  unsigned int threadno = context.second;
94 
95  while (!me->m_stop)
96  {
97  me->m_threadWaiting[threadno] = true;
98  Simulator::ScheduleWithContext (threadno,
99  MicroSeconds (1),
101  while (!me->m_stop && me->m_threadWaiting[threadno])
102  {
103  std::this_thread::sleep_for(std::chrono::nanoseconds(500));
104  }
105  }
106 }
107 void
109 {
110  if (!m_error.empty())
111  {
112  m_error = "Bad threaded scheduling";
113  }
114  m_threadWaiting[threadno] = false;
115 }
116 void
118 {
119  if (m_a != m_b || m_a != m_c || m_a != m_d)
120  {
121  m_error = "Bad scheduling";
122  Simulator::Stop();
123  };
124  ++m_a;
125  Simulator::Schedule (MicroSeconds (10),
127 }
128 
129 void
131 {
132  if (m_a != (m_b+1) || m_a != (m_c+1) || m_a != (m_d+1))
133  {
134  m_error = "Bad scheduling";
135  Simulator::Stop();
136  };
137  ++m_b;
138  Simulator::Schedule (MicroSeconds (10),
140 }
141 
142 void
144 {
145  if (m_a != m_b || m_a != (m_c+1) || m_a != (m_d+1))
146  {
147  m_error = "Bad scheduling";
148  Simulator::Stop();
149  };
150  ++m_c;
151  Simulator::Schedule (MicroSeconds (10),
153 }
154 
155 void
157 {
158  if (m_a != m_b || m_a != m_c || m_a != (m_d+1))
159  {
160  m_error = "Bad scheduling";
161  Simulator::Stop();
162  };
163  ++m_d;
164  if (m_stop)
165  {
166  Simulator::Stop();
167  }
168  else
169  {
170  Simulator::Schedule (MicroSeconds (10),
172  }
173 }
174 
175 void
177 {
178  if (!m_simulatorType.empty())
179  {
180  Config::SetGlobal ("SimulatorImplementationType", StringValue (m_simulatorType));
181  }
182 
183  m_error = "";
184 
185  m_a =
186  m_b =
187  m_c =
188  m_d = 0;
189 
190  for (unsigned int i=0; i < m_threads; ++i)
191  {
192  m_threadlist.push_back(
193  Create<SystemThread> (MakeBoundCallback (
195  std::pair<ThreadedSimulatorEventsTestCase *, unsigned int>(this,i) )) );
196  }
197 }
198 void
200 {
201  m_threadlist.clear();
202 
203  Config::SetGlobal ("SimulatorImplementationType", StringValue ("ns3::DefaultSimulatorImpl"));
204 }
205 void
207 {
208  m_stop = false;
209  Simulator::SetScheduler (m_schedulerFactory);
210 
211  Simulator::Schedule (MicroSeconds (10), &ThreadedSimulatorEventsTestCase::EventA, this, 1);
212  Simulator::Schedule (Seconds (1), &ThreadedSimulatorEventsTestCase::End, this);
213 
214 
215  for (std::list<Ptr<SystemThread> >::iterator it = m_threadlist.begin(); it != m_threadlist.end(); ++it)
216  {
217  (*it)->Start();
218  }
219 
220  Simulator::Run ();
221  Simulator::Destroy ();
222 
223  NS_TEST_EXPECT_MSG_EQ (m_error.empty(), true, m_error.c_str());
224  NS_TEST_EXPECT_MSG_EQ (m_a, m_b, "Bad scheduling");
225  NS_TEST_EXPECT_MSG_EQ (m_a, m_c, "Bad scheduling");
226  NS_TEST_EXPECT_MSG_EQ (m_a, m_d, "Bad scheduling");
227 }
228 
230 {
231 public:
233  : TestSuite ("threaded-simulator")
234  {
235  std::string simulatorTypes[] = {
236 #ifdef HAVE_RT
237  "ns3::RealtimeSimulatorImpl",
238 #endif
239  "ns3::DefaultSimulatorImpl"
240  };
241  std::string schedulerTypes[] = {
242  "ns3::ListScheduler",
243  "ns3::HeapScheduler",
244  "ns3::MapScheduler",
245  "ns3::CalendarScheduler"
246  };
247  unsigned int threadcounts[] = {
248  0,
249  2,
250  10,
251  20
252  };
253  ObjectFactory factory;
254 
255  for (unsigned int i=0; i < (sizeof(simulatorTypes) / sizeof(simulatorTypes[0])); ++i)
256  {
257  for (unsigned int j=0; j < (sizeof(threadcounts) / sizeof(threadcounts[0])); ++j)
258  {
259  for (unsigned int k=0; k < (sizeof(schedulerTypes) / sizeof(schedulerTypes[0])); ++k)
260  {
261  factory.SetTypeId(schedulerTypes[k]);
262  AddTestCase (new ThreadedSimulatorEventsTestCase (factory, simulatorTypes[i], threadcounts[j]), TestCase::QUICK);
263  }
264  }
265  }
266  }
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:1342
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1686
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:285
encapsulates test code
Definition: test.h:1155
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:822
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:1014
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:1030
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
static void SchedulingThread(std::pair< ThreadedSimulatorEventsTestCase *, unsigned int > context)