PageRenderTime 153ms CodeModel.GetById 27ms RepoModel.GetById 7ms app.codeStats 1ms

/test/test_rospy/test/unit/test_rospy_tcpros_pubsub.py

https://gitlab.com/F34140r/ros_comm
Python | 235 lines | 195 code | 6 blank | 34 comment | 1 complexity | 94188ac537d707a766580dfe2ef89652 MD5 | raw file
Possible License(s): LGPL-2.1
  1. #!/usr/bin/env python
  2. # Software License Agreement (BSD License)
  3. #
  4. # Copyright (c) 2008, Willow Garage, Inc.
  5. # All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. #
  11. # * Redistributions of source code must retain the above copyright
  12. # notice, this list of conditions and the following disclaimer.
  13. # * Redistributions in binary form must reproduce the above
  14. # copyright notice, this list of conditions and the following
  15. # disclaimer in the documentation and/or other materials provided
  16. # with the distribution.
  17. # * Neither the name of Willow Garage, Inc. nor the names of its
  18. # contributors may be used to endorse or promote products derived
  19. # from this software without specific prior written permission.
  20. #
  21. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. # POSSIBILITY OF SUCH DAMAGE.
  33. import os
  34. import sys
  35. import socket
  36. import struct
  37. import unittest
  38. import time
  39. class FakeSocket(object):
  40. def __init__(self):
  41. self.data = ''
  42. self.sockopt = None
  43. def fileno(self):
  44. # fool select logic by giving it stdout fileno
  45. return 1
  46. def setblocking(self, *args):
  47. pass
  48. def setsockopt(self, *args):
  49. self.sockopt = args
  50. def send(self, d):
  51. self.data = self.data+d
  52. return len(d)
  53. def sendall(self, d):
  54. self.data = self.data+d
  55. def close(self):
  56. pass
  57. # test rospy API verifies that the rospy module exports the required symbols
  58. class TestRospyTcprosPubsub(unittest.TestCase):
  59. def test_TCPROSSub(self):
  60. import rospy.impl.transport
  61. from rospy.impl.tcpros_pubsub import TCPROSSub
  62. import test_rospy.msg
  63. callerid = 'test_TCPROSSub'
  64. import rospy.names
  65. rospy.names._set_caller_id(callerid)
  66. #name, recv_data_class, queue_size=None, buff_size=DEFAULT_BUFF_SIZE
  67. name = 'name-%s'%time.time()
  68. recv_data_class = test_rospy.msg.Val
  69. s = TCPROSSub(name, recv_data_class)
  70. self.assertEquals(name, s.resolved_name)
  71. self.assertEquals(rospy.impl.transport.INBOUND, s.direction)
  72. self.assertEquals(recv_data_class, s.recv_data_class)
  73. self.assert_(s.buff_size > -1)
  74. self.failIf(s.tcp_nodelay)
  75. self.assertEquals(None, s.queue_size)
  76. fields = s.get_header_fields()
  77. self.assertEquals(name, fields['topic'])
  78. self.assertEquals(recv_data_class._md5sum, fields['md5sum'])
  79. self.assertEquals(recv_data_class._full_text, fields['message_definition'])
  80. self.assertEquals('test_rospy/Val', fields['type'])
  81. self.assert_(callerid, fields['callerid'])
  82. if 'tcp_nodelay' in fields:
  83. self.assertEquals('0', fields['tcp_nodelay'])
  84. v = int(time.time())
  85. s = TCPROSSub(name, recv_data_class, queue_size=v)
  86. self.assertEquals(v, s.queue_size)
  87. s = TCPROSSub(name, recv_data_class, buff_size=v)
  88. self.assertEquals(v, s.buff_size)
  89. s = TCPROSSub(name, recv_data_class, tcp_nodelay=True)
  90. self.assert_(s.tcp_nodelay)
  91. self.assertEquals('1', s.get_header_fields()['tcp_nodelay'])
  92. def test_TCPROSPub(self):
  93. import rospy.impl.transport
  94. from rospy.impl.tcpros_pubsub import TCPROSPub
  95. import test_rospy.msg
  96. callerid = 'test_TCPROSPub'
  97. import rospy.names
  98. rospy.names._set_caller_id(callerid)
  99. #name, pub_data_class
  100. name = 'name-%s'%time.time()
  101. pub_data_class = test_rospy.msg.Val
  102. p = TCPROSPub(name, pub_data_class)
  103. self.assertEquals(name, p.resolved_name)
  104. self.assertEquals(rospy.impl.transport.OUTBOUND, p.direction)
  105. self.assertEquals(pub_data_class, p.pub_data_class)
  106. self.assert_(p.buff_size > -1)
  107. self.failIf(p.is_latch)
  108. fields = p.get_header_fields()
  109. self.assertEquals(name, fields['topic'])
  110. self.assertEquals(pub_data_class._md5sum, fields['md5sum'])
  111. self.assertEquals(pub_data_class._full_text, fields['message_definition'])
  112. self.assertEquals('test_rospy/Val', fields['type'])
  113. self.assert_(callerid, fields['callerid'])
  114. if 'latching' in fields:
  115. self.assertEquals('0', fields['latching'])
  116. p = TCPROSPub(name, pub_data_class, is_latch=True)
  117. self.assert_(p.is_latch)
  118. self.assertEquals('1', p.get_header_fields()['latching'])
  119. # test additional header fields
  120. p = TCPROSPub(name, pub_data_class, headers={'foo': 'bar', 'hoge': 'fuga'})
  121. fields = p.get_header_fields()
  122. self.assertEquals(name, fields['topic'])
  123. self.assertEquals('fuga', fields['hoge'])
  124. self.assertEquals('bar', fields['foo'])
  125. def test_configure_pub_socket(self):
  126. # #1241 regression test to make sure that imports don't get messed up again
  127. from rospy.impl.tcpros_pubsub import _configure_pub_socket
  128. import socket
  129. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  130. _configure_pub_socket(sock, True)
  131. sock.close()
  132. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  133. _configure_pub_socket(sock, False)
  134. sock.close()
  135. def test_TCPROSHandler_topic_connection_handler(self):
  136. import rospy
  137. import rospy.core
  138. # very ugly hack to handle bad design choice in rospy and bad isolation inside of nose
  139. rospy.core._shutdown_flag = False
  140. rospy.core._in_shutdown = False
  141. from rospy.impl.registration import Registration
  142. from rospy.impl.tcpros_pubsub import TCPROSHandler
  143. import test_rospy.msg
  144. handler = TCPROSHandler()
  145. tch = handler.topic_connection_handler
  146. sock = FakeSocket()
  147. client_addr = '127.0.0.1'
  148. data_class = test_rospy.msg.Val
  149. topic_name = '/foo-tch'
  150. headers = { 'topic': topic_name, 'md5sum': data_class._md5sum, 'callerid': '/node'}
  151. # test required logic
  152. for k in headers.iterkeys():
  153. header_copy = headers.copy()
  154. del header_copy[k]
  155. err = tch(sock, client_addr, header_copy)
  156. self.assertNotEquals('', err)
  157. # '/foo-tch' is not registered, so this should error
  158. err = tch(sock, client_addr, headers)
  159. self.assert_(err)
  160. # register '/foo-tch'
  161. tm = rospy.impl.registration.get_topic_manager()
  162. impl = tm.acquire_impl(Registration.PUB, topic_name, data_class)
  163. self.assert_(impl is not None)
  164. # test with mismatched md5sum
  165. header_copy = headers.copy()
  166. header_copy['md5sum'] = 'bad'
  167. md5_err = tch(sock, client_addr, header_copy)
  168. self.assert_("md5sum" in md5_err, md5_err)
  169. # now test with correct params
  170. err = tch(sock, client_addr, headers)
  171. self.failIf(err)
  172. self.assertEquals(None, sock.sockopt)
  173. # test with mismatched type
  174. # - if md5sums match, this should not error
  175. header_copy = headers.copy()
  176. header_copy['type'] = 'bad_type/Bad'
  177. err = tch(sock, client_addr, header_copy)
  178. self.failIf(err)
  179. # - now give mismatched md5sum, this will test different error message
  180. header_copy['md5sum'] = 'bad'
  181. type_md5_err = tch(sock, client_addr, header_copy)
  182. self.assert_("types" in type_md5_err, type_md5_err)
  183. # - these error messages should be different
  184. self.assertNotEquals(md5_err, type_md5_err)
  185. # test tcp_nodelay
  186. # - should be equivalent to above
  187. headers['tcp_nodelay'] = '0'
  188. err = tch(sock, client_addr, headers)
  189. self.failIf(err)
  190. self.assertEquals(None, sock.sockopt)
  191. # - now test actual sock opt
  192. headers['tcp_nodelay'] = '1'
  193. err = tch(sock, client_addr, headers)
  194. self.failIf(err)
  195. self.assertEquals((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), sock.sockopt)
  196. # test connection headers
  197. impl.headers = {'foo': 'baz', 'hoge': 'fuga'}
  198. headers['tcp_nodelay'] = '0'
  199. err = tch(sock, client_addr, headers)
  200. self.failIf(err)
  201. connection = impl.connections[-1]
  202. fields = connection.protocol.get_header_fields()
  203. self.assertEquals(impl.resolved_name, fields['topic'])
  204. self.assertEquals('fuga', fields['hoge'])
  205. self.assertEquals('baz', fields['foo'])