A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
python-unit-tests.py
Go to the documentation of this file.
1#! /usr/bin/env python3
2
3# Copyright (C) 2008-2011 INESC Porto
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 as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19# Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
20
21import unittest
22from ns import ns
23import sys
24
25UINT32_MAX = 0xFFFFFFFF
26
27
28
29class TestSimulator(unittest.TestCase):
30
38
39 def testScheduleNow(self):
40 """! Test schedule now
41 @param self this object
42 @return None
43 """
44
45 def callback(args: ns.cppyy.gbl.std.vector) -> None:
46 """! Callback function
47 @param args arguments
48 @return None
49 """
50 self._args_received = list(map(lambda x: x.decode("utf-8"), args))
51 self._cb_time = ns.Simulator.Now()
52
53 ns.Simulator.Destroy()
54 self._args_received = None
55 self._cb_time = None
56 ns.cppyy.cppdef("""
57 EventImpl* pythonMakeEvent(void (*f)(std::vector<std::string>), std::vector<std::string> l)
58 {
59 return MakeEvent(f, l);
60 }
61 """)
62 event = ns.cppyy.gbl.pythonMakeEvent(callback, sys.argv)
63 ns.Simulator.ScheduleNow(event)
64 ns.Simulator.Run()
65 self.assertListEqual(self._args_received, sys.argv)
66 self.assertEqual(self._cb_time.GetSeconds(), 0.0)
67
68 def testSchedule(self):
69 """! Test schedule
70 @param self this object
71 @return None
72 """
73
74 def callback(args: ns.cppyy.gbl.std.vector):
75 """! Callback function
76 @param args arguments
77 @return None
78 """
79 self._args_received = list(map(lambda x: x.decode("utf-8"), args))
80 self._cb_time = ns.Simulator.Now()
81
82 ns.Simulator.Destroy()
83 self._args_received = None
84 self._cb_time = None
85 ns.cppyy.cppdef("""
86 EventImpl* pythonMakeEvent2(void (*f)(std::vector<std::string>), std::vector<std::string> l)
87 {
88 return MakeEvent(f, l);
89 }
90 """)
91 event = ns.cppyy.gbl.pythonMakeEvent2(callback, sys.argv)
92 ns.Simulator.Schedule(ns.Seconds(123), event)
93 ns.Simulator.Run()
94 self.assertListEqual(self._args_received, sys.argv)
95 self.assertEqual(self._cb_time.GetSeconds(), 123.0)
96
98 """! Test schedule destroy
99 @param self this object
100 @return None
101 """
102
103 def callback(args: ns.cppyy.gbl.std.vector):
104 """! Callback function
105 @param args
106 @return None
107 """
108 self._args_received = list(map(lambda x: x.decode("utf-8"), args))
109 self._cb_time = ns.Simulator.Now()
110
111 ns.Simulator.Destroy()
112 self._args_received = None
113 self._cb_time = None
114 ns.cppyy.cppdef("void null(){ return; }")
115 ns.Simulator.Schedule(ns.Seconds(123), ns.cppyy.gbl.null)
116 ns.cppyy.cppdef("""
117 EventImpl* pythonMakeEvent3(void (*f)(std::vector<std::string>), std::vector<std::string> l)
118 {
119 return MakeEvent(f, l);
120 }
121 """)
122 event = ns.cppyy.gbl.pythonMakeEvent3(callback, sys.argv)
123 ns.Simulator.ScheduleDestroy(event)
124 ns.Simulator.Run()
125 ns.Simulator.Destroy()
126 self.assertListEqual(self._args_received, sys.argv)
127 self.assertEqual(self._cb_time.GetSeconds(), 123.0)
128
130 """! Test schedule with context
131 @param self this object
132 @return None
133 """
134
135 def callback(context, args: ns.cppyy.gbl.std.vector):
136 """! Callback
137 @param context the context
138 @param args the arguments
139 @return None
140 """
141 self._context_received = context
142 self._args_received = list(map(lambda x: x.decode("utf-8"), args))
143 self._cb_time = ns.Simulator.Now()
144
145 ns.Simulator.Destroy()
146 self._args_received = None
147 self._cb_time = None
148 self._context_received = None
149 ns.cppyy.cppdef("""
150 EventImpl* pythonMakeEvent4(void (*f)(uint32_t, std::vector<std::string>), uint32_t context, std::vector<std::string> l)
151 {
152 return MakeEvent(f, context, l);
153 }
154 """)
155 event = ns.cppyy.gbl.pythonMakeEvent4(callback, 54321, sys.argv)
156 ns.Simulator.ScheduleWithContext(54321, ns.Seconds(123), event)
157 ns.Simulator.Run()
158 self.assertEqual(self._context_received, 54321)
159 self.assertListEqual(self._args_received, sys.argv)
160 self.assertEqual(self._cb_time.GetSeconds(), 123.0)
161
163 """! Test time comparison
164 @param self this object
165 @return None
166 """
167 self.assertTrue(ns.Seconds(123) == ns.Seconds(123))
168 self.assertTrue(ns.Seconds(123) >= ns.Seconds(123))
169 self.assertTrue(ns.Seconds(123) <= ns.Seconds(123))
170 self.assertTrue(ns.Seconds(124) > ns.Seconds(123))
171 self.assertTrue(ns.Seconds(123) < ns.Seconds(124))
172
174 """! Test numeric operations
175 @param self this object
176 @return None
177 """
178 self.assertEqual(ns.Seconds(10) + ns.Seconds(5), ns.Seconds(15))
179 self.assertEqual(ns.Seconds(10) - ns.Seconds(5), ns.Seconds(5))
180
181 v1 = ns.int64x64_t(5.0) * ns.int64x64_t(10)
182 self.assertEqual(v1, ns.int64x64_t(50))
183
184 def testConfig(self):
185 """! Test configuration
186 @param self this object
187 @return None
188 """
189 ns.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.core.UintegerValue(123))
190 # hm.. no Config.Get?
191
192 def testSocket(self):
193 """! Test socket
194 @param self
195 @return None
196 """
197 nc = ns.NodeContainer(1)
198 node = nc.Get(0)
199 internet = ns.CreateObject("InternetStackHelper")
200 internet.Install(node)
202
203 def python_rx_callback(socket) -> None:
204 self._received_packet = socket.Recv(maxSize=UINT32_MAX, flags=0)
205
206 ns.cppyy.cppdef("""
207 Callback<void,ns3::Ptr<ns3::Socket> > make_rx_callback_test_socket(void(*func)(Ptr<Socket>))
208 {
209 return MakeCallback(func);
210 }
211 """)
212
213 sink = ns.network.Socket.CreateSocket(node, ns.core.TypeId.LookupByName("ns3::UdpSocketFactory"))
214 sink.Bind(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), 80).ConvertTo())
215 sink.SetRecvCallback(ns.cppyy.gbl.make_rx_callback_test_socket(python_rx_callback))
216
217 source = ns.network.Socket.CreateSocket(node, ns.core.TypeId.LookupByName("ns3::UdpSocketFactory"))
218 source.SendTo(ns.network.Packet(19), 0,
219 ns.network.InetSocketAddress(ns.network.Ipv4Address("127.0.0.1"), 80).ConvertTo())
220
221 ns.Simulator.Run()
222 self.assertTrue(self._received_packet is not None)
223 self.assertEqual(self._received_packet.GetSize(), 19)
224
225 # Delete Ptr<>'s on the python side to let C++ clean them
226 del internet
227
228 def testAttributes(self):
229 """! Test attributes function
230 @param self this object
231 @return None
232 """
233 # Templated class DropTailQueue<Packet> in C++
234 queue = ns.CreateObject("DropTailQueue<Packet>")
235 queueSizeValue = ns.network.QueueSizeValue(ns.network.QueueSize("500p"))
236 queue.SetAttribute("MaxSize", queueSizeValue)
237
238 limit = ns.network.QueueSizeValue()
239 queue.GetAttribute("MaxSize", limit)
240 self.assertEqual(limit.Get(), ns.network.QueueSize("500p"))
241
242
243 mobility = ns.CreateObject("RandomWaypointMobilityModel")
244 ptr = ns.CreateObject("PointerValue")
245 mobility.GetAttribute("PositionAllocator", ptr)
246 self.assertEqual(ptr.GetObject(), ns.core.Ptr["Object"](ns.cppyy.nullptr))
247
248 pos = ns.mobility.ListPositionAllocator()
249 ptr.SetObject(pos)
250 mobility.SetAttribute("PositionAllocator", ptr)
251
252 ptr2 = ns.CreateObject("PointerValue")
253 mobility.GetAttribute("PositionAllocator", ptr2)
254 self.assertNotEqual(ptr.GetObject(), ns.core.Ptr["Object"](ns.cppyy.nullptr))
255
256 # Delete Ptr<>'s on the python side to let C++ clean them
257 del queue, mobility, ptr, ptr2
258
259 def testIdentity(self):
260 """! Test identify
261 @param self this object
262 @return None
263 """
264 csma = ns.CreateObject("CsmaNetDevice")
265 channel = ns.CreateObject("CsmaChannel")
266 csma.Attach(channel)
267
268 c1 = csma.GetChannel()
269 c2 = csma.GetChannel()
270
271 self.assertEqual(c1, c2)
272
273 # Delete Ptr<>'s on the python side to let C++ clean them
274 del csma, channel
275
276 def testTypeId(self):
277 """! Test type ID
278 @param self this object
279 @return None
280 """
281 ok, typeId1 = ns.LookupByNameFailSafe("ns3::UdpSocketFactory")
282 self.assertTrue(ok)
283 self.assertEqual(typeId1.GetName(), "ns3::UdpSocketFactory")
284
285 ok, typeId1 = ns.LookupByNameFailSafe("ns3::__InvalidTypeName__")
286 self.assertFalse(ok)
287
289 """! Test command line
290 @param self this object
291 @return None
292 """
293 from ctypes import c_bool, c_int, c_double, c_char_p, create_string_buffer
294
295 test1 = c_bool(True)
296 test2 = c_int(42)
297 test3 = c_double(3.1415)
298 BUFFLEN = 40 # noqa
299 test4Buffer = create_string_buffer(b"this is a test option", BUFFLEN)
300 test4 = c_char_p(test4Buffer.raw)
301
302 cmd = ns.core.CommandLine(__file__)
303 cmd.AddValue("Test1", "this is a test option", test1)
304 cmd.AddValue("Test2", "this is a test option", test2)
305 cmd.AddValue["double"]("Test3", "this is a test option", test3)
306 cmd.AddValue("Test4", "this is a test option", test4, BUFFLEN)
307
308 cmd.Parse(["python"])
309 self.assertEqual(test1.value, True)
310 self.assertEqual(test2.value, 42)
311 self.assertEqual(test3.value, 3.1415)
312 self.assertEqual(test4.value, b"this is a test option")
313
314 cmd.Parse(["python", "--Test1=false", "--Test2=0", "--Test3=0.0"])
315 self.assertEqual(test1.value, False)
316 self.assertEqual(test2.value, 0)
317 self.assertEqual(test3.value, 0.0)
318
319 cmd.Parse(["python", "--Test4=new_string"])
320 self.assertEqual(test4.value, b"new_string")
321
322 def testSubclass(self):
323 """! Test subclass
324 @param self this object
325 @return None
326 """
327
328
329 class MyNode(ns.network.Node):
330 def GetLocalTime(self) -> ns.Time:
331 return ns.Seconds(10)
332
333 node = MyNode()
334 forced_local_time = node.GetLocalTime()
335 self.assertEqual(forced_local_time, ns.Seconds(10))
336 del node
337
339 """! Test python-based application
340 @param self this object
341 @return None
342 """
343 ns.Simulator.Destroy()
344
345 nodes = ns.network.NodeContainer()
346 nodes.Create(2)
347
348 pointToPoint = ns.point_to_point.PointToPointHelper()
349 pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps"))
350 pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms"))
351
352 devices = pointToPoint.Install(nodes)
353
354 stack = ns.internet.InternetStackHelper()
355 stack.Install(nodes)
356
357 address = ns.internet.Ipv4AddressHelper()
358 address.SetBase(ns.network.Ipv4Address("10.1.1.0"),
359 ns.network.Ipv4Mask("255.255.255.0"))
360
361 interfaces = address.Assign(devices)
362
363 ns.cppyy.cppdef("""
364 namespace ns3
365 {
366 Callback<void,Ptr<Socket> > make_rx_callback(void(*func)(Ptr<Socket>))
367 {
368 return MakeCallback(func);
369 }
370 EventImpl* pythonMakeEventSend(void (*f)(Ptr<Socket>, Ptr<Packet>, Address&), Ptr<Socket> socket, Ptr<Packet> packet, Address address)
371 {
372 return MakeEvent(f, socket, packet, address);
373 }
374 }
375 """)
376
377
378 class EchoServer(ns.applications.Application):
379 LOGGING = False
380 ECHO_PORT = 1234
381 socketToInstanceDict = {}
382
383 def __init__(self, node: ns.Node, port=ECHO_PORT):
384 """! Constructor needs to call first the constructor to Application (super class)
385 @param self this object
386 @param node node where this application will be executed
387 @param port port to listen
388 return None
389 """
390 super().__init__()
391 self.__python_owns__ = False # Let C++ destroy this on Simulator::Destroy
392
393 self.port = port
394
395 self.m_socket = ns.network.Socket.CreateSocket(node,
396 ns.core.TypeId.LookupByName("ns3::UdpSocketFactory"))
397 self.m_socket.Bind(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), self.port).ConvertTo())
398 self.m_socket.SetRecvCallback(ns.make_rx_callback(EchoServer._Receive))
399 EchoServer.socketToInstanceDict[self.m_socket] = self
400
401 def __del__(self):
402 """! Destructor
403 @param self this object
404 return None
405 """
406 del EchoServer.socketToInstanceDict[self.m_socket]
407
408 def Send(self, packet: ns.Packet, address: ns.Address) -> None:
409 """! Function to send a packet to an address
410 @param self this object
411 @param packet packet to send
412 @param address destination address
413 return None
414 """
415 self.m_socket.SendTo(packet, 0, address)
416 if EchoServer.LOGGING:
417 inetAddress = ns.InetSocketAddress.ConvertFrom(address)
418 print("At time +{s}s server sent {b} bytes from {ip} port {port}"
419 .format(s=ns.Simulator.Now().GetSeconds(),
420 b=packet.__deref__().GetSize(),
421 ip=inetAddress.GetIpv4(),
422 port=inetAddress.GetPort()),
423 file=sys.stderr,
424 flush=True)
425
426 def Receive(self):
427 """! Function to receive a packet from an address
428 @param self this object
429 @return None
430 """
431 address = ns.Address()
432 packet = self.m_socket.RecvFrom(address)
433 if EchoServer.LOGGING:
434 inetAddress = ns.InetSocketAddress.ConvertFrom(address)
435 print("At time +{s}s server received {b} bytes from {ip} port {port}"
436 .format(s=ns.Simulator.Now().GetSeconds(),
437 b=packet.__deref__().GetSize(),
438 ip=inetAddress.GetIpv4(),
439 port=inetAddress.GetPort()),
440 file=sys.stderr,
441 flush=True)
442 event = ns.pythonMakeEventSend(EchoServer._Send, self.m_socket, packet, address)
443 ns.Simulator.Schedule(ns.Seconds(1), event)
444
445 @staticmethod
446 def _Send(socket: ns.Socket, packet: ns.Packet, address: ns.Address):
447 """! Static send function, which matches the output socket
448 to the EchoServer instance to call the instance Send function
449 @param socket socket from the instance that should send the packet
450 @param packet packet to send
451 @param address destination address
452 return None
453 """
454 instance = EchoServer.socketToInstanceDict[socket]
455 instance.Send(packet, address)
456
457 @staticmethod
458 def _Receive(socket: ns.Socket) -> None:
459 """! Static receive function, which matches the input socket
460 to the EchoServer instance to call the instance Receive function
461 @param socket socket from the instance that should receive the packet
462 return None
463 """
464 instance = EchoServer.socketToInstanceDict[socket]
465 instance.Receive()
466
467 echoServer = EchoServer(nodes.Get(1))
468 nodes.Get(1).AddApplication(echoServer)
469
470 serverApps = ns.ApplicationContainer()
471 serverApps.Add(echoServer)
472 serverApps.Start(ns.core.Seconds(1.0))
473 serverApps.Stop(ns.core.Seconds(10.0))
474
475 address = interfaces.GetAddress(1).ConvertTo()
476 echoClient = ns.applications.UdpEchoClientHelper(address, EchoServer.ECHO_PORT)
477 echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(10))
478 echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0)))
479 echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(101))
480
481 clientApps = echoClient.Install(nodes.Get(0))
482 clientApps.Start(ns.core.Seconds(2.0))
483 clientApps.Stop(ns.core.Seconds(10.0))
484
485 ns.Simulator.Run()
486 ns.Simulator.Destroy()
487
488
489if __name__ == '__main__':
490 unittest.main(verbosity=1, failfast=True)
def testScheduleDestroy(self)
Test schedule destroy.
port
Listen port for the server.
def testCommandLine(self)
Test command line.
def testTimeNumericOperations(self)
Test numeric operations.
def testEchoServerApplication(self)
Test python-based application.
__python_owns__
EchoServer application class.
def testScheduleNow(self)
Test schedule now.
def testTypeId(self)
Test type ID.
def testSubclass(self)
Test subclass.
def testSchedule(self)
Test schedule.
def testScheduleWithContext(self)
Test schedule with context.
def testAttributes(self)
Test attributes function.
def testSocket(self)
Test socket.
def testTimeComparison(self)
Test time comparison.
def testConfig(self)
Test configuration.
m_socket
Socket used by the server to listen to port.
def testIdentity(self)
Test identify.
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define list