PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/test/socket/test_basicsocket.rb

http://github.com/ruby/ruby
Ruby | 230 lines | 190 code | 32 blank | 8 comment | 7 complexity | d0fde741b95b45225c8ca09686c8c1d8 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: true
  2. begin
  3. require "socket"
  4. require "test/unit"
  5. require "io/nonblock"
  6. rescue LoadError
  7. end
  8. class TestSocket_BasicSocket < Test::Unit::TestCase
  9. def inet_stream
  10. sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
  11. yield sock
  12. ensure
  13. assert(sock.closed?)
  14. end
  15. def test_getsockopt
  16. inet_stream do |s|
  17. begin
  18. n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
  19. assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)
  20. n = s.getsockopt("SOL_SOCKET", "SO_TYPE")
  21. assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)
  22. n = s.getsockopt(:SOL_SOCKET, :SO_TYPE)
  23. assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)
  24. n = s.getsockopt(:SOCKET, :TYPE)
  25. assert_equal([Socket::SOCK_STREAM].pack("i"), n.data)
  26. n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
  27. assert_equal([0].pack("i"), n.data)
  28. rescue Minitest::Assertion
  29. s.close
  30. if /aix/ =~ RUBY_PLATFORM
  31. skip "Known bug in getsockopt(2) on AIX"
  32. end
  33. raise $!
  34. end
  35. val = Object.new
  36. class << val; self end.send(:define_method, :to_int) {
  37. s.close
  38. Socket::SO_TYPE
  39. }
  40. assert_raise(IOError) {
  41. n = s.getsockopt(Socket::SOL_SOCKET, val)
  42. }
  43. end
  44. end
  45. def test_setsockopt
  46. s = nil
  47. linger = [0, 0].pack("ii")
  48. val = Object.new
  49. class << val; self end.send(:define_method, :to_str) {
  50. s.close
  51. linger
  52. }
  53. inet_stream do |sock|
  54. s = sock
  55. assert_equal(0, s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger))
  56. assert_raise(IOError, "[ruby-dev:25039]") {
  57. s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, val)
  58. }
  59. end
  60. val = Object.new
  61. class << val; self end.send(:define_method, :to_int) {
  62. s.close
  63. Socket::SO_LINGER
  64. }
  65. inet_stream do |sock|
  66. s = sock
  67. assert_raise(IOError) {
  68. s.setsockopt(Socket::SOL_SOCKET, val, linger)
  69. }
  70. end
  71. end
  72. def test_listen
  73. s = nil
  74. log = Object.new
  75. class << log; self end.send(:define_method, :to_int) {
  76. s.close
  77. 2
  78. }
  79. inet_stream do |sock|
  80. s = sock
  81. assert_raise(IOError) {
  82. s.listen(log)
  83. }
  84. end
  85. end
  86. def socks
  87. sserv = TCPServer.new('localhost', 0)
  88. ssock = nil
  89. t = Thread.new { ssock = sserv.accept }
  90. csock = TCPSocket.new('localhost', sserv.addr[1])
  91. t.join
  92. yield sserv, ssock, csock
  93. ensure
  94. ssock.close rescue nil
  95. csock.close rescue nil
  96. sserv.close rescue nil
  97. end
  98. def test_close_read
  99. socks do |sserv, ssock, csock|
  100. # close_read makes subsequent reads raise IOError
  101. csock.close_read
  102. assert_raise(IOError) { csock.read(5) }
  103. # close_read ignores any error from shutting down half of still-open socket
  104. assert_nothing_raised { csock.close_read }
  105. # close_read raises if socket is not open
  106. assert_nothing_raised { csock.close }
  107. assert_raise(IOError) { csock.close_read }
  108. end
  109. end
  110. def test_close_write
  111. socks do |sserv, ssock, csock|
  112. # close_write makes subsequent writes raise IOError
  113. csock.close_write
  114. assert_raise(IOError) { csock.write(5) }
  115. # close_write ignores any error from shutting down half of still-open socket
  116. assert_nothing_raised { csock.close_write }
  117. # close_write raises if socket is not open
  118. assert_nothing_raised { csock.close }
  119. assert_raise(IOError) { csock.close_write }
  120. end
  121. end
  122. def test_for_fd
  123. assert_raise(Errno::EBADF, '[ruby-core:72418] [Bug #11854]') do
  124. BasicSocket.for_fd(-1)
  125. end
  126. inet_stream do |sock|
  127. s = BasicSocket.for_fd(sock.fileno)
  128. assert_instance_of BasicSocket, s
  129. s.autoclose = false
  130. sock.close
  131. end
  132. end
  133. def test_read_write_nonblock
  134. socks do |sserv, ssock, csock|
  135. set_nb = true
  136. buf = String.new
  137. if ssock.respond_to?(:nonblock?)
  138. assert_not_predicate(ssock, :nonblock?)
  139. assert_not_predicate(csock, :nonblock?)
  140. csock.nonblock = ssock.nonblock = false
  141. # Linux may use MSG_DONTWAIT to avoid setting O_NONBLOCK
  142. if RUBY_PLATFORM.match?(/linux/) && Socket.const_defined?(:MSG_DONTWAIT)
  143. set_nb = false
  144. end
  145. end
  146. assert_equal :wait_readable, ssock.read_nonblock(1, buf, exception: false)
  147. assert_equal 5, csock.write_nonblock('hello')
  148. IO.select([ssock])
  149. assert_same buf, ssock.read_nonblock(5, buf, exception: false)
  150. assert_equal 'hello', buf
  151. buf = '*' * 16384
  152. n = 0
  153. case w = csock.write_nonblock(buf, exception: false)
  154. when Integer
  155. n += w
  156. when :wait_writable
  157. break
  158. end while true
  159. assert_equal :wait_writable, w
  160. assert_raise(IO::WaitWritable) { loop { csock.write_nonblock(buf) } }
  161. assert_operator n, :>, 0
  162. assert_not_predicate(csock, :nonblock?, '[Feature #13362]') unless set_nb
  163. csock.close
  164. case r = ssock.read_nonblock(16384, buf, exception: false)
  165. when String
  166. next
  167. when nil
  168. break
  169. when :wait_readable
  170. IO.select([ssock], nil, nil, 10) or
  171. flunk 'socket did not become readable'
  172. else
  173. flunk "unexpected read_nonblock return: #{r.inspect}"
  174. end while true
  175. assert_raise(EOFError) { ssock.read_nonblock(1) }
  176. assert_not_predicate(ssock, :nonblock?) unless set_nb
  177. end
  178. end
  179. def test_read_nonblock_mix_buffered
  180. socks do |sserv, ssock, csock|
  181. ssock.write("hello\nworld\n")
  182. assert_equal "hello\n", csock.gets
  183. IO.select([csock], nil, nil, 10) or
  184. flunk 'socket did not become readable'
  185. assert_equal "world\n", csock.read_nonblock(8)
  186. end
  187. end
  188. def test_write_nonblock_buffered
  189. socks do |sserv, ssock, csock|
  190. ssock.sync = false
  191. ssock.write("h")
  192. assert_equal :wait_readable, csock.read_nonblock(1, exception: false)
  193. assert_equal 4, ssock.write_nonblock("ello")
  194. ssock.close
  195. assert_equal "hello", csock.read(5)
  196. end
  197. end
  198. end if defined?(BasicSocket)