A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
threaded-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Claudio Freire <claudio-daniel.freire@inria.fr>
7 */
8#include "ns3/calendar-scheduler.h"
9#include "ns3/config.h"
10#include "ns3/heap-scheduler.h"
11#include "ns3/list-scheduler.h"
12#include "ns3/map-scheduler.h"
13#include "ns3/simulator.h"
14#include "ns3/string.h"
15#include "ns3/test.h"
16
17#include <chrono> // seconds, milliseconds
18#include <ctime>
19#include <list>
20#include <thread> // sleep_for
21#include <utility>
22
23using namespace ns3;
24
25/// Maximum number of threads.
26constexpr int MAXTHREADS = 64;
27
28/**
29 * \file
30 * \ingroup threaded-tests
31 * Threaded events test suite
32 */
33
34/**
35 * \ingroup core-tests
36 * \defgroup threaded-tests Threaded events tests
37 */
38
39/**
40 * \ingroup threaded-tests
41 *
42 * \brief Check threaded event handling with various thread number, schedulers, and simulator
43 * types.
44 */
46{
47 public:
48 /**
49 * Constructor.
50 *
51 * \param schedulerFactory The scheduler factory.
52 * \param simulatorType The simulator type.
53 * \param threads The number of threads.
54 */
56 const std::string& simulatorType,
57 unsigned int threads);
58 /**
59 * Event A
60 * \param a The Event parameter.
61 */
62 void EventA(int a);
63 /**
64 * Event B
65 * \param b The Event parameter.
66 */
67 void EventB(int b);
68 /**
69 * Event C
70 * \param c The Event parameter.
71 */
72 void EventC(int c);
73 /**
74 * Event D
75 * \param d The Event parameter.
76 */
77 void EventD(int d);
78 /**
79 * No-op function, records the thread that called it.
80 * \param threadno The thread number.
81 */
82 void DoNothing(unsigned int threadno);
83 /**
84 * Schedule a thread.
85 * \param context The context.
86 */
87 static void SchedulingThread(std::pair<ThreadedSimulatorEventsTestCase*, unsigned int> context);
88 /**
89 * End the thread execution.
90 */
91 void End();
92 uint64_t m_a; //!< The value incremented when EventA is called.
93 uint64_t m_b; //!< The value incremented when EventB is called.
94 uint64_t m_c; //!< The value incremented when EventC is called.
95 uint64_t m_d; //!< The value incremented when EventD is called.
96 unsigned int m_threads; //!< The number of threads.
97 bool m_threadWaiting[MAXTHREADS]; //!< Threads waiting to be scheduled.
98 bool m_stop; //!< Stop variable.
99 ObjectFactory m_schedulerFactory; //!< Scheduler factory.
100 std::string m_simulatorType; //!< Simulator type.
101 std::string m_error; //!< Error condition.
102 std::list<std::thread> m_threadlist; //!< Thread list.
103
104 private:
105 void DoSetup() override;
106 void DoRun() override;
107 void DoTeardown() override;
108};
109
111 const std::string& simulatorType,
112 unsigned int threads)
113 : TestCase("Check threaded event handling with " + std::to_string(threads) + " threads, " +
114 schedulerFactory.GetTypeId().GetName() + " scheduler, in " + simulatorType),
115 m_threads(threads),
116 m_schedulerFactory(schedulerFactory),
117 m_simulatorType(simulatorType)
118{
119}
120
121void
123{
124 m_stop = true;
125 for (auto& thread : m_threadlist)
126 {
127 if (thread.joinable())
128 {
129 thread.join();
130 }
131 }
132}
133
134void
136 std::pair<ThreadedSimulatorEventsTestCase*, unsigned int> context)
137{
138 ThreadedSimulatorEventsTestCase* me = context.first;
139 unsigned int threadno = context.second;
140
141 while (!me->m_stop)
142 {
143 me->m_threadWaiting[threadno] = true;
145 MicroSeconds(1),
147 me,
148 threadno);
149 while (!me->m_stop && me->m_threadWaiting[threadno])
150 {
151 std::this_thread::sleep_for(std::chrono::nanoseconds(500));
152 }
153 }
154}
155
156void
158{
159 if (!m_error.empty())
160 {
161 m_error = "Bad threaded scheduling";
162 }
163 m_threadWaiting[threadno] = false;
164}
165
166void
168{
169 if (m_a != m_b || m_a != m_c || m_a != m_d)
170 {
171 m_error = "Bad scheduling";
173 }
174 ++m_a;
176}
177
178void
180{
181 if (m_a != (m_b + 1) || m_a != (m_c + 1) || m_a != (m_d + 1))
182 {
183 m_error = "Bad scheduling";
185 }
186 ++m_b;
188}
189
190void
192{
193 if (m_a != m_b || m_a != (m_c + 1) || m_a != (m_d + 1))
194 {
195 m_error = "Bad scheduling";
197 }
198 ++m_c;
200}
201
202void
204{
205 if (m_a != m_b || m_a != m_c || m_a != (m_d + 1))
206 {
207 m_error = "Bad scheduling";
209 }
210 ++m_d;
211 if (m_stop)
212 {
214 }
215 else
216 {
219 this,
220 d + 1);
221 }
222}
223
224void
226{
227 if (!m_simulatorType.empty())
228 {
229 Config::SetGlobal("SimulatorImplementationType", StringValue(m_simulatorType));
230 }
231
232 m_error = "";
233
234 m_a = m_b = m_c = m_d = 0;
235}
236
237void
239{
240 m_threadlist.clear();
241
242 Config::SetGlobal("SimulatorImplementationType", StringValue("ns3::DefaultSimulatorImpl"));
243}
244
245void
247{
248 m_stop = false;
250
253
254 for (unsigned int i = 0; i < m_threads; ++i)
255 {
256 m_threadlist.emplace_back(
258 std::pair<ThreadedSimulatorEventsTestCase*, unsigned int>(this, i));
259 }
260
263
264 NS_TEST_EXPECT_MSG_EQ(m_error.empty(), true, m_error);
265 NS_TEST_EXPECT_MSG_EQ(m_a, m_b, "Bad scheduling");
266 NS_TEST_EXPECT_MSG_EQ(m_a, m_c, "Bad scheduling");
267 NS_TEST_EXPECT_MSG_EQ(m_a, m_d, "Bad scheduling");
268}
269
270/**
271 * \ingroup threaded-tests
272 *
273 * \brief The threaded simulator Test Suite.
274 */
276{
277 public:
279 : TestSuite("threaded-simulator")
280 {
281 std::string simulatorTypes[] = {
282 "ns3::RealtimeSimulatorImpl",
283 "ns3::DefaultSimulatorImpl",
284 };
285 std::string schedulerTypes[] = {
286 "ns3::ListScheduler",
287 "ns3::HeapScheduler",
288 "ns3::MapScheduler",
289 "ns3::CalendarScheduler",
290 };
291 unsigned int threadCounts[] = {0, 2, 10, 20};
292 ObjectFactory factory;
293
294 for (auto& simulatorType : simulatorTypes)
295 {
296 for (auto& schedulerType : schedulerTypes)
297 {
298 for (auto& threadCount : threadCounts)
299 {
300 factory.SetTypeId(schedulerType);
302 new ThreadedSimulatorEventsTestCase(factory, simulatorType, threadCount),
303 TestCase::Duration::QUICK);
304 }
305 }
306 }
307 }
308};
309
310/// Static variable for test initialization.
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.
ThreadedSimulatorEventsTestCase(ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
Constructor.
ObjectFactory m_schedulerFactory
Scheduler factory.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
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.
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.
void End()
End the thread execution.
void DoRun() override
Implementation to actually run this TestCase.
unsigned int m_threads
The number of threads.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint64_t m_a
The value incremented when EventA is called.
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.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition simulator.h:577
static void Run()
Run the simulation.
Definition simulator.cc:167
static void SetScheduler(ObjectFactory schedulerFactory)
Set the scheduler type with an ObjectFactory.
Definition simulator.cc:153
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
void SetGlobal(std::string name, const AttributeValue &value)
Definition config.cc:929
#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:241
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
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.