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
29#include <chrono> // seconds, milliseconds
30#include <ctime>
31#include <list>
32#include <thread> // sleep_for
33#include <utility>
34
35using namespace ns3;
36
38constexpr int MAXTHREADS = 64;
39
57{
58public:
66 ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads);
71 void EventA (int a);
76 void EventB (int b);
81 void EventC (int c);
86 void EventD (int d);
91 void DoNothing (unsigned int threadno);
96 static void SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context);
100 void End (void);
101 uint64_t m_a;
102 uint64_t m_b;
103 uint64_t m_c;
104 uint64_t m_d;
105 unsigned int m_threads;
107 bool m_stop;
109 std::string m_simulatorType;
110 std::string m_error;
111 std::list<std::thread> m_threadlist;
112
113private:
114 virtual void DoSetup (void);
115 virtual void DoRun (void);
116 virtual void DoTeardown (void);
117};
118
119ThreadedSimulatorEventsTestCase::ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
120 : TestCase ("Check threaded event handling with " +
121 std::to_string (threads) + " threads, " +
122 schedulerFactory.GetTypeId ().GetName () + " scheduler, in " +
123 simulatorType),
124 m_threads (threads),
125 m_schedulerFactory (schedulerFactory),
126 m_simulatorType (simulatorType)
127{}
128
129void
131{
132 m_stop = true;
133 for (auto& thread : m_threadlist)
134 {
135 if (thread.joinable ())
136 {
137 thread.join ();
138 }
139 }
140}
141void
142ThreadedSimulatorEventsTestCase::SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context)
143{
144 ThreadedSimulatorEventsTestCase *me = context.first;
145 unsigned int threadno = context.second;
146
147 while (!me->m_stop)
148 {
149 me->m_threadWaiting[threadno] = true;
150 Simulator::ScheduleWithContext (threadno,
151 MicroSeconds (1),
153 while (!me->m_stop && me->m_threadWaiting[threadno])
154 {
155 std::this_thread::sleep_for (std::chrono::nanoseconds (500));
156 }
157 }
158}
159void
161{
162 if (!m_error.empty ())
163 {
164 m_error = "Bad threaded scheduling";
165 }
166 m_threadWaiting[threadno] = false;
167}
168void
170{
171 if (m_a != m_b || m_a != m_c || m_a != m_d)
172 {
173 m_error = "Bad scheduling";
174 Simulator::Stop ();
175 }
176 ++m_a;
177 Simulator::Schedule (MicroSeconds (10),
179}
180
181void
183{
184 if (m_a != (m_b + 1) || m_a != (m_c + 1) || m_a != (m_d + 1))
185 {
186 m_error = "Bad scheduling";
187 Simulator::Stop ();
188 }
189 ++m_b;
190 Simulator::Schedule (MicroSeconds (10),
192}
193
194void
196{
197 if (m_a != m_b || m_a != (m_c + 1) || m_a != (m_d + 1))
198 {
199 m_error = "Bad scheduling";
200 Simulator::Stop ();
201 }
202 ++m_c;
203 Simulator::Schedule (MicroSeconds (10),
205}
206
207void
209{
210 if (m_a != m_b || m_a != m_c || m_a != (m_d + 1))
211 {
212 m_error = "Bad scheduling";
213 Simulator::Stop ();
214 }
215 ++m_d;
216 if (m_stop)
217 {
218 Simulator::Stop ();
219 }
220 else
221 {
222 Simulator::Schedule (MicroSeconds (10),
224 }
225}
226
227void
229{
230 if (!m_simulatorType.empty ())
231 {
232 Config::SetGlobal ("SimulatorImplementationType", StringValue (m_simulatorType));
233 }
234
235 m_error = "";
236
237 m_a =
238 m_b =
239 m_c =
240 m_d = 0;
241}
242void
244{
245 m_threadlist.clear ();
246
247 Config::SetGlobal ("SimulatorImplementationType", StringValue ("ns3::DefaultSimulatorImpl"));
248}
249void
251{
252 m_stop = false;
253 Simulator::SetScheduler (m_schedulerFactory);
254
255 Simulator::Schedule (MicroSeconds (10), &ThreadedSimulatorEventsTestCase::EventA, this, 1);
256 Simulator::Schedule (Seconds (1), &ThreadedSimulatorEventsTestCase::End, this);
257
258 for (unsigned int i = 0; i < m_threads; ++i)
259 {
260 m_threadlist.push_back (
262 std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> (this,i) ));
263 }
264
265 Simulator::Run ();
266 Simulator::Destroy ();
267
268 NS_TEST_EXPECT_MSG_EQ (m_error.empty (), true, m_error.c_str ());
269 NS_TEST_EXPECT_MSG_EQ (m_a, m_b, "Bad scheduling");
270 NS_TEST_EXPECT_MSG_EQ (m_a, m_c, "Bad scheduling");
271 NS_TEST_EXPECT_MSG_EQ (m_a, m_d, "Bad scheduling");
272}
273
280{
281public:
283 : TestSuite ("threaded-simulator")
284 {
285 std::string simulatorTypes[] = {
286#ifdef HAVE_RT
287 "ns3::RealtimeSimulatorImpl",
288#endif
289 "ns3::DefaultSimulatorImpl"
290 };
291 std::string schedulerTypes[] = {
292 "ns3::ListScheduler",
293 "ns3::HeapScheduler",
294 "ns3::MapScheduler",
295 "ns3::CalendarScheduler"
296 };
297 unsigned int threadcounts[] = {
298 0,
299 2,
300 10,
301 20
302 };
303 ObjectFactory factory;
304
305 for (unsigned int i = 0; i < (sizeof(simulatorTypes) / sizeof(simulatorTypes[0])); ++i)
306 {
307 for (unsigned int j = 0; j < (sizeof(threadcounts) / sizeof(threadcounts[0])); ++j)
308 {
309 for (unsigned int k = 0; k < (sizeof(schedulerTypes) / sizeof(schedulerTypes[0])); ++k)
310 {
311 factory.SetTypeId (schedulerTypes[k]);
312 AddTestCase (new ThreadedSimulatorEventsTestCase (factory, simulatorTypes[i], threadcounts[j]), TestCase::QUICK);
313 }
314 }
315 }
316 }
317};
318
Check threaded event handling with various thread number, schedulers, and simulator types.
std::list< std::thread > m_threadlist
Thread list.
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.
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.
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
#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.
constexpr int MAXTHREADS
Maximum number of threads.
static ThreadedSimulatorTestSuite g_threadedSimulatorTestSuite
Static variable for test initialization.