A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
threaded-test-suite.cc
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 A (int a);
43  void B (int b);
44  void C (int c);
45  void D (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;
56  ObjectFactory m_schedulerFactory;
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
77 ThreadedSimulatorEventsTestCase::End (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),
96  &ThreadedSimulatorEventsTestCase::DoNothing, me, threadno);
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
107 ThreadedSimulatorEventsTestCase::DoNothing (unsigned int threadno)
108 {
109  if (!m_error.empty())
110  {
111  m_error = "Bad threaded scheduling";
112  }
113  m_threadWaiting[threadno] = false;
114 }
115 void
116 ThreadedSimulatorEventsTestCase::A (int a)
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),
125  &ThreadedSimulatorEventsTestCase::B, this, a+1);
126 }
127 
128 void
129 ThreadedSimulatorEventsTestCase::B (int b)
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),
138  &ThreadedSimulatorEventsTestCase::C, this, b+1);
139 }
140 
141 void
142 ThreadedSimulatorEventsTestCase::C (int c)
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),
151  &ThreadedSimulatorEventsTestCase::D, this, c+1);
152 }
153 
154 void
155 ThreadedSimulatorEventsTestCase::D (int d)
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),
170  &ThreadedSimulatorEventsTestCase::A, this, d+1);
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 (
193  &ThreadedSimulatorEventsTestCase::SchedulingThread,
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::A, 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  }
266 } g_threadedSimulatorTestSuite;
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
hold variables of type string
Definition: string.h:19
A suite of tests to run.
Definition: test.h:962
void SetTypeId(TypeId tid)
encapsulates test code
Definition: test.h:834
TestSuite(std::string name, Type type=UNIT)
Constuct a new test suite.
Definition: test.cc:354
virtual void DoRun(void)
Implementation to actually run this test case.
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual test case to this test suite.
Definition: test.cc:172
instantiate subclasses of ns3::Object.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
virtual void DoTeardown(void)
Implementation to do any local setup required for this test case.
virtual void DoSetup(void)
Implementation to do any local setup required for this test case.
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
Definition: nstime.h:615