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
36using namespace ns3;
37
39#define MAXTHREADS 64
40
58{
59public:
67 ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads);
72 void EventA (int a);
77 void EventB (int b);
82 void EventC (int c);
87 void EventD (int d);
92 void DoNothing (unsigned int threadno);
97 static void SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context);
101 void End (void);
102 uint64_t m_a;
103 uint64_t m_b;
104 uint64_t m_c;
105 uint64_t m_d;
106 unsigned int m_threads;
108 bool m_stop;
110 std::string m_simulatorType;
111 std::string m_error;
112 std::list<Ptr<SystemThread> > m_threadlist;
113
114private:
115 virtual void DoSetup (void);
116 virtual void DoRun (void);
117 virtual void DoTeardown (void);
118};
119
120ThreadedSimulatorEventsTestCase::ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
121 : TestCase ("Check threaded event handling with " +
122 std::to_string (threads) + " threads, " +
123 schedulerFactory.GetTypeId ().GetName () + " scheduler, in " +
124 simulatorType),
125 m_threads (threads),
126 m_schedulerFactory (schedulerFactory),
127 m_simulatorType (simulatorType)
128{}
129
130void
132{
133 m_stop = true;
134 for (std::list<Ptr<SystemThread> >::iterator it2 = m_threadlist.begin (); it2 != m_threadlist.end (); ++it2)
135 {
136 (*it2)->Join ();
137 }
138}
139void
140ThreadedSimulatorEventsTestCase::SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context)
141{
142 ThreadedSimulatorEventsTestCase *me = context.first;
143 unsigned int threadno = context.second;
144
145 while (!me->m_stop)
146 {
147 me->m_threadWaiting[threadno] = true;
148 Simulator::ScheduleWithContext (threadno,
149 MicroSeconds (1),
151 while (!me->m_stop && me->m_threadWaiting[threadno])
152 {
153 std::this_thread::sleep_for (std::chrono::nanoseconds (500));
154 }
155 }
156}
157void
159{
160 if (!m_error.empty ())
161 {
162 m_error = "Bad threaded scheduling";
163 }
164 m_threadWaiting[threadno] = false;
165}
166void
168{
169 if (m_a != m_b || m_a != m_c || m_a != m_d)
170 {
171 m_error = "Bad scheduling";
172 Simulator::Stop ();
173 }
174 ++m_a;
175 Simulator::Schedule (MicroSeconds (10),
177}
178
179void
181{
182 if (m_a != (m_b + 1) || m_a != (m_c + 1) || m_a != (m_d + 1))
183 {
184 m_error = "Bad scheduling";
185 Simulator::Stop ();
186 }
187 ++m_b;
188 Simulator::Schedule (MicroSeconds (10),
190}
191
192void
194{
195 if (m_a != m_b || m_a != (m_c + 1) || m_a != (m_d + 1))
196 {
197 m_error = "Bad scheduling";
198 Simulator::Stop ();
199 }
200 ++m_c;
201 Simulator::Schedule (MicroSeconds (10),
203}
204
205void
207{
208 if (m_a != m_b || m_a != m_c || m_a != (m_d + 1))
209 {
210 m_error = "Bad scheduling";
211 Simulator::Stop ();
212 }
213 ++m_d;
214 if (m_stop)
215 {
216 Simulator::Stop ();
217 }
218 else
219 {
220 Simulator::Schedule (MicroSeconds (10),
222 }
223}
224
225void
227{
228 if (!m_simulatorType.empty ())
229 {
230 Config::SetGlobal ("SimulatorImplementationType", StringValue (m_simulatorType));
231 }
232
233 m_error = "";
234
235 m_a =
236 m_b =
237 m_c =
238 m_d = 0;
239
240 for (unsigned int i = 0; i < m_threads; ++i)
241 {
242 m_threadlist.push_back (
243 Create<SystemThread> (MakeBoundCallback (
245 std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> (this,i) )) );
246 }
247}
248void
250{
251 m_threadlist.clear ();
252
253 Config::SetGlobal ("SimulatorImplementationType", StringValue ("ns3::DefaultSimulatorImpl"));
254}
255void
257{
258 m_stop = false;
259 Simulator::SetScheduler (m_schedulerFactory);
260
261 Simulator::Schedule (MicroSeconds (10), &ThreadedSimulatorEventsTestCase::EventA, this, 1);
262 Simulator::Schedule (Seconds (1), &ThreadedSimulatorEventsTestCase::End, this);
263
264
265 for (std::list<Ptr<SystemThread> >::iterator it = m_threadlist.begin (); it != m_threadlist.end (); ++it)
266 {
267 (*it)->Start ();
268 }
269
270 Simulator::Run ();
271 Simulator::Destroy ();
272
273 NS_TEST_EXPECT_MSG_EQ (m_error.empty (), true, m_error.c_str ());
274 NS_TEST_EXPECT_MSG_EQ (m_a, m_b, "Bad scheduling");
275 NS_TEST_EXPECT_MSG_EQ (m_a, m_c, "Bad scheduling");
276 NS_TEST_EXPECT_MSG_EQ (m_a, m_d, "Bad scheduling");
277}
278
285{
286public:
288 : TestSuite ("threaded-simulator")
289 {
290 std::string simulatorTypes[] = {
291#ifdef HAVE_RT
292 "ns3::RealtimeSimulatorImpl",
293#endif
294 "ns3::DefaultSimulatorImpl"
295 };
296 std::string schedulerTypes[] = {
297 "ns3::ListScheduler",
298 "ns3::HeapScheduler",
299 "ns3::MapScheduler",
300 "ns3::CalendarScheduler"
301 };
302 unsigned int threadcounts[] = {
303 0,
304 2,
305 10,
306 20
307 };
308 ObjectFactory factory;
309
310 for (unsigned int i = 0; i < (sizeof(simulatorTypes) / sizeof(simulatorTypes[0])); ++i)
311 {
312 for (unsigned int j = 0; j < (sizeof(threadcounts) / sizeof(threadcounts[0])); ++j)
313 {
314 for (unsigned int k = 0; k < (sizeof(schedulerTypes) / sizeof(schedulerTypes[0])); ++k)
315 {
316 factory.SetTypeId (schedulerTypes[k]);
317 AddTestCase (new ThreadedSimulatorEventsTestCase (factory, simulatorTypes[i], threadcounts[j]), TestCase::QUICK);
318 }
319 }
320 }
321 }
322};
323
Check threaded event handling with various thread number, schedulers, and simulator types.
static void SchedulingThread(std::pair< ThreadedSimulatorEventsTestCase *, unsigned int > context)
Schedule a thread.
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
ThreadedSimulatorEventsTestCase(ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
Constructor.
ObjectFactory m_schedulerFactory
Scheduler factory.
void End(void)
End the thread execution.
bool m_threadWaiting[MAXTHREADS]
Threads waiting to be scheduled.
std::string m_error
Error condition.
uint64_t m_c
The value incremented when EventC is called.
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint64_t m_b
The value incremented when EventB is called.
std::string m_simulatorType
Simulator type.
uint64_t m_d
The value incremented when EventD is called.
std::list< Ptr< SystemThread > > m_threadlist
Thread list.
unsigned int m_threads
The number of threads.
uint64_t m_a
The value incremented when EventA is called.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void DoNothing(unsigned int threadno)
No-op function, records the thread that called it.
The threaded simulator Test Suite.
Instantiate subclasses of ns3::Object.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Hold variables of type string.
Definition: string.h:41
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
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:891
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
#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
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Every class exported by the ns3 library is enclosed in the ns3 namespace.
STL namespace.
#define list
#define MAXTHREADS
Maximum number of threads.
static ThreadedSimulatorTestSuite g_threadedSimulatorTestSuite
Static variable for test initialization.