@@ -47,8 +47,20 @@ def _have_socket_can():
4747 s .close ()
4848 return True
4949
50+ def _have_socket_rds ():
51+ """Check whether RDS sockets are supported on this host."""
52+ try :
53+ s = socket .socket (socket .PF_RDS , socket .SOCK_SEQPACKET , 0 )
54+ except (AttributeError , OSError ):
55+ return False
56+ else :
57+ s .close ()
58+ return True
59+
5060HAVE_SOCKET_CAN = _have_socket_can ()
5161
62+ HAVE_SOCKET_RDS = _have_socket_rds ()
63+
5264# Size in bytes of the int type
5365SIZEOF_INT = array .array ("i" ).itemsize
5466
@@ -113,6 +125,23 @@ def setUp(self):
113125 self .skipTest ('network interface `%s` does not exist' %
114126 self .interface )
115127
128+
129+ class SocketRDSTest (unittest .TestCase ):
130+
131+ """To be able to run this test, the `rds` kernel module must be loaded:
132+ # modprobe rds
133+ """
134+ bufsize = 8192
135+
136+ def setUp (self ):
137+ self .serv = socket .socket (socket .PF_RDS , socket .SOCK_SEQPACKET , 0 )
138+ self .addCleanup (self .serv .close )
139+ try :
140+ self .port = support .bind_port (self .serv )
141+ except OSError :
142+ self .skipTest ('unable to bind RDS socket' )
143+
144+
116145class ThreadableTest :
117146 """Threadable Test class
118147
@@ -271,6 +300,29 @@ def clientTearDown(self):
271300 self .cli = None
272301 ThreadableTest .clientTearDown (self )
273302
303+ class ThreadedRDSSocketTest (SocketRDSTest , ThreadableTest ):
304+
305+ def __init__ (self , methodName = 'runTest' ):
306+ SocketRDSTest .__init__ (self , methodName = methodName )
307+ ThreadableTest .__init__ (self )
308+ self .evt = threading .Event ()
309+
310+ def clientSetUp (self ):
311+ self .cli = socket .socket (socket .PF_RDS , socket .SOCK_SEQPACKET , 0 )
312+ try :
313+ # RDS sockets must be bound explicitly to send or receive data
314+ self .cli .bind ((HOST , 0 ))
315+ self .cli_addr = self .cli .getsockname ()
316+ except OSError :
317+ # skipTest should not be called here, and will be called in the
318+ # server instead
319+ pass
320+
321+ def clientTearDown (self ):
322+ self .cli .close ()
323+ self .cli = None
324+ ThreadableTest .clientTearDown (self )
325+
274326class SocketConnectedTest (ThreadedTCPSocketTest ):
275327 """Socket tests for client-server connection.
276328
@@ -1239,6 +1291,112 @@ def _testSendMultiFrames(self):
12391291 self .cli .send (self .cf2 )
12401292
12411293
1294+ @unittest .skipUnless (HAVE_SOCKET_RDS , 'RDS sockets required for this test.' )
1295+ class BasicRDSTest (unittest .TestCase ):
1296+
1297+ def testCrucialConstants (self ):
1298+ socket .AF_RDS
1299+ socket .PF_RDS
1300+
1301+ def testCreateSocket (self ):
1302+ with socket .socket (socket .PF_RDS , socket .SOCK_SEQPACKET , 0 ) as s :
1303+ pass
1304+
1305+ def testSocketBufferSize (self ):
1306+ bufsize = 16384
1307+ with socket .socket (socket .PF_RDS , socket .SOCK_SEQPACKET , 0 ) as s :
1308+ s .setsockopt (socket .SOL_SOCKET , socket .SO_RCVBUF , bufsize )
1309+ s .setsockopt (socket .SOL_SOCKET , socket .SO_SNDBUF , bufsize )
1310+
1311+
1312+ @unittest .skipUnless (HAVE_SOCKET_RDS , 'RDS sockets required for this test.' )
1313+ @unittest .skipUnless (thread , 'Threading required for this test.' )
1314+ class RDSTest (ThreadedRDSSocketTest ):
1315+
1316+ def __init__ (self , methodName = 'runTest' ):
1317+ ThreadedRDSSocketTest .__init__ (self , methodName = methodName )
1318+
1319+ def testSendAndRecv (self ):
1320+ data , addr = self .serv .recvfrom (self .bufsize )
1321+ self .assertEqual (self .data , data )
1322+ self .assertEqual (self .cli_addr , addr )
1323+
1324+ def _testSendAndRecv (self ):
1325+ self .data = b'spam'
1326+ self .cli .sendto (self .data , 0 , (HOST , self .port ))
1327+
1328+ def testPeek (self ):
1329+ data , addr = self .serv .recvfrom (self .bufsize , socket .MSG_PEEK )
1330+ self .assertEqual (self .data , data )
1331+ data , addr = self .serv .recvfrom (self .bufsize )
1332+ self .assertEqual (self .data , data )
1333+
1334+ def _testPeek (self ):
1335+ self .data = b'spam'
1336+ self .cli .sendto (self .data , 0 , (HOST , self .port ))
1337+
1338+ @requireAttrs (socket .socket , 'recvmsg' )
1339+ def testSendAndRecvMsg (self ):
1340+ data , ancdata , msg_flags , addr = self .serv .recvmsg (self .bufsize )
1341+ self .assertEqual (self .data , data )
1342+
1343+ @requireAttrs (socket .socket , 'sendmsg' )
1344+ def _testSendAndRecvMsg (self ):
1345+ self .data = b'hello ' * 10
1346+ self .cli .sendmsg ([self .data ], (), 0 , (HOST , self .port ))
1347+
1348+ def testSendAndRecvMulti (self ):
1349+ data , addr = self .serv .recvfrom (self .bufsize )
1350+ self .assertEqual (self .data1 , data )
1351+
1352+ data , addr = self .serv .recvfrom (self .bufsize )
1353+ self .assertEqual (self .data2 , data )
1354+
1355+ def _testSendAndRecvMulti (self ):
1356+ self .data1 = b'bacon'
1357+ self .cli .sendto (self .data1 , 0 , (HOST , self .port ))
1358+
1359+ self .data2 = b'egg'
1360+ self .cli .sendto (self .data2 , 0 , (HOST , self .port ))
1361+
1362+ def testSelect (self ):
1363+ r , w , x = select .select ([self .serv ], [], [], 3.0 )
1364+ self .assertIn (self .serv , r )
1365+ data , addr = self .serv .recvfrom (self .bufsize )
1366+ self .assertEqual (self .data , data )
1367+
1368+ def _testSelect (self ):
1369+ self .data = b'select'
1370+ self .cli .sendto (self .data , 0 , (HOST , self .port ))
1371+
1372+ def testCongestion (self ):
1373+ # wait until the sender is done
1374+ self .evt .wait ()
1375+
1376+ def _testCongestion (self ):
1377+ # test the behavior in case of congestion
1378+ self .data = b'fill'
1379+ self .cli .setblocking (False )
1380+ try :
1381+ # try to lower the receiver's socket buffer size
1382+ self .cli .setsockopt (socket .SOL_SOCKET , socket .SO_RCVBUF , 16384 )
1383+ except OSError :
1384+ pass
1385+ with self .assertRaises (OSError ) as cm :
1386+ try :
1387+ # fill the receiver's socket buffer
1388+ while True :
1389+ self .cli .sendto (self .data , 0 , (HOST , self .port ))
1390+ finally :
1391+ # signal the receiver we're done
1392+ self .evt .set ()
1393+ # sendto() should have failed with ENOBUFS
1394+ self .assertEqual (cm .exception .errno , errno .ENOBUFS )
1395+ # and we should have received a congestion notification through poll
1396+ r , w , x = select .select ([self .serv ], [], [], 3.0 )
1397+ self .assertIn (self .serv , r )
1398+
1399+
12421400@unittest .skipUnless (thread , 'Threading required for this test.' )
12431401class BasicTCPTest (SocketConnectedTest ):
12441402
@@ -4362,6 +4520,7 @@ def test_main():
43624520 tests .append (TIPCTest )
43634521 tests .append (TIPCThreadableTest )
43644522 tests .extend ([BasicCANTest , CANTest ])
4523+ tests .extend ([BasicRDSTest , RDSTest ])
43654524 tests .extend ([
43664525 CmsgMacroTests ,
43674526 SendmsgUDPTest ,
0 commit comments