A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 <ctime>
31 #include <list>
32 #include <utility>
33 
34 using namespace ns3;
35 
36 #define MAXTHREADS 64
37 
39 {
40 public:
41  ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads);
42  void EventA (int a);
43  void EventB (int b);
44  void EventC (int c);
45  void EventD (int d);
46  void DoNothing (unsigned int threadno);
47  static void SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context);
48  void End (void);
49  uint64_t m_b;
50  uint64_t m_a;
51  uint64_t m_c;
52  uint64_t m_d;
53  unsigned int m_threads;
54  bool m_threadWaiting[MAXTHREADS];
55  bool m_stop;
57  std::string m_simulatorType;
58  std::string m_error;
59  std::list<Ptr<SystemThread> > m_threadlist;
60 
61 private:
62  virtual void DoSetup (void);
63  virtual void DoRun (void);
64  virtual void DoTeardown (void);
65 };
66 
67 ThreadedSimulatorEventsTestCase::ThreadedSimulatorEventsTestCase (ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
68  : TestCase ("Check that threaded event handling is working with " +
69  schedulerFactory.GetTypeId ().GetName () + " in " + simulatorType),
70  m_threads (threads),
71  m_schedulerFactory (schedulerFactory),
72  m_simulatorType (simulatorType)
73 {
74 }
75 
76 void
78 {
79  m_stop = true;
80  for (std::list<Ptr<SystemThread> >::iterator it2 = m_threadlist.begin(); it2 != m_threadlist.end(); ++it2)
81  {
82  (*it2)->Join();
83  }
84 }
85 void
86 ThreadedSimulatorEventsTestCase::SchedulingThread (std::pair<ThreadedSimulatorEventsTestCase *, unsigned int> context)
87 {
88  ThreadedSimulatorEventsTestCase *me = context.first;
89  unsigned int threadno = context.second;
90 
91  while (!me->m_stop)
92  {
93  me->m_threadWaiting[threadno] = true;
94  Simulator::ScheduleWithContext (uint32_t (-1),
95  MicroSeconds (1),
97  while (!me->m_stop && me->m_threadWaiting[threadno])
98  {
99  struct timespec ts;
100  ts.tv_sec = 0;
101  ts.tv_nsec = 500;
102  nanosleep (&ts, NULL);
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:60
hold variables of type string
Definition: string.h:18
ThreadedSimulatorTestSuite g_threadedSimulatorTestSuite
A suite of tests to run.
Definition: test.h:1105
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Build bound Callbacks which take varying numbers of arguments, and potentially returning a value...
Definition: callback.h:1467
void SetTypeId(TypeId tid)
#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:265
encapsulates test code
Definition: test.h:929
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define MAXTHREADS
#define list
std::list< Ptr< SystemThread > > m_threadlist
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:184
instantiate subclasses of ns3::Object.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
ThreadedSimulatorEventsTestCase(ObjectFactory schedulerFactory, const std::string &simulatorType, unsigned int threads)
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:707
static void SchedulingThread(std::pair< ThreadedSimulatorEventsTestCase *, unsigned int > context)