PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/test/socket/test_socket.rb

http://github.com/ruby/ruby
Ruby | 754 lines | 684 code | 52 blank | 18 comment | 63 complexity | 9d855931b0db5c2f7f974044415aacd2 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 "tmpdir"
  5. require "fcntl"
  6. require "etc"
  7. require "test/unit"
  8. rescue LoadError
  9. end
  10. class TestSocket < Test::Unit::TestCase
  11. def test_socket_new
  12. begin
  13. s = Socket.new(:INET, :STREAM)
  14. assert_kind_of(Socket, s)
  15. ensure
  16. s.close
  17. end
  18. end
  19. def test_socket_new_cloexec
  20. return unless defined? Fcntl::FD_CLOEXEC
  21. begin
  22. s = Socket.new(:INET, :STREAM)
  23. assert(s.close_on_exec?)
  24. ensure
  25. s.close
  26. end
  27. end
  28. def test_unpack_sockaddr
  29. sockaddr_in = Socket.sockaddr_in(80, "")
  30. assert_raise(ArgumentError) { Socket.unpack_sockaddr_un(sockaddr_in) }
  31. sockaddr_un = Socket.sockaddr_un("/testdir/s")
  32. assert_raise(ArgumentError) { Socket.unpack_sockaddr_in(sockaddr_un) }
  33. assert_raise(ArgumentError) { Socket.unpack_sockaddr_in("") }
  34. assert_raise(ArgumentError) { Socket.unpack_sockaddr_un("") }
  35. end if Socket.respond_to?(:sockaddr_un)
  36. def test_sysaccept
  37. serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
  38. serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
  39. serv.listen 5
  40. c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
  41. c.connect(serv.getsockname)
  42. fd, peeraddr = serv.sysaccept
  43. assert_equal(c.getsockname, peeraddr.to_sockaddr)
  44. ensure
  45. serv.close if serv
  46. c.close if c
  47. IO.for_fd(fd).close if fd
  48. end
  49. def test_initialize
  50. Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|s|
  51. s.bind(Socket.sockaddr_in(0, "127.0.0.1"))
  52. addr = s.getsockname
  53. assert_nothing_raised { Socket.unpack_sockaddr_in(addr) }
  54. assert_raise(ArgumentError, NoMethodError) { Socket.unpack_sockaddr_un(addr) }
  55. }
  56. Socket.open("AF_INET", "SOCK_STREAM", 0) {|s|
  57. s.bind(Socket.sockaddr_in(0, "127.0.0.1"))
  58. addr = s.getsockname
  59. assert_nothing_raised { Socket.unpack_sockaddr_in(addr) }
  60. assert_raise(ArgumentError, NoMethodError) { Socket.unpack_sockaddr_un(addr) }
  61. }
  62. Socket.open(:AF_INET, :SOCK_STREAM, 0) {|s|
  63. s.bind(Socket.sockaddr_in(0, "127.0.0.1"))
  64. addr = s.getsockname
  65. assert_nothing_raised { Socket.unpack_sockaddr_in(addr) }
  66. assert_raise(ArgumentError, NoMethodError) { Socket.unpack_sockaddr_un(addr) }
  67. }
  68. end
  69. def test_bind
  70. Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|bound|
  71. bound.bind(Socket.sockaddr_in(0, "127.0.0.1"))
  72. addr = bound.getsockname
  73. port, = Socket.unpack_sockaddr_in(addr)
  74. Socket.open(Socket::AF_INET, Socket::SOCK_STREAM, 0) {|s|
  75. e = assert_raise(Errno::EADDRINUSE) do
  76. s.bind(Socket.sockaddr_in(port, "127.0.0.1"))
  77. end
  78. assert_match "bind(2) for 127.0.0.1:#{port}", e.message
  79. }
  80. }
  81. end
  82. def test_getaddrinfo
  83. # This should not send a DNS query because AF_UNIX.
  84. assert_raise(SocketError) { Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") }
  85. end
  86. def test_getaddrinfo_raises_no_errors_on_port_argument_of_0 # [ruby-core:29427]
  87. assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', 0, Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
  88. assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', '0', Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
  89. assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', '00', Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
  90. assert_raise(SocketError, '[ruby-core:29427]'){ Socket.getaddrinfo(nil, nil, Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
  91. assert_nothing_raised('[ruby-core:29427]'){ TCPServer.open('localhost', 0) {} }
  92. end
  93. def test_getnameinfo
  94. assert_raise(SocketError) { Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"]) }
  95. assert_raise(ArgumentError) {Socket.getnameinfo(["AF_INET", "http\0", "example.net"])}
  96. assert_raise(ArgumentError) {Socket.getnameinfo(["AF_INET", "http", "example.net\0"])}
  97. end
  98. def test_ip_address_list
  99. begin
  100. list = Socket.ip_address_list
  101. rescue NotImplementedError
  102. return
  103. end
  104. list.each {|ai|
  105. assert_instance_of(Addrinfo, ai)
  106. assert(ai.ip?)
  107. }
  108. end
  109. def test_ip_address_list_include_localhost
  110. begin
  111. list = Socket.ip_address_list
  112. rescue NotImplementedError
  113. return
  114. end
  115. assert_includes list.map(&:ip_address), Addrinfo.tcp("localhost", 0).ip_address
  116. end
  117. def test_tcp
  118. TCPServer.open(0) {|serv|
  119. addr = serv.connect_address
  120. addr.connect {|s1|
  121. s2 = serv.accept
  122. begin
  123. assert_equal(s2.remote_address.ip_unpack, s1.local_address.ip_unpack)
  124. ensure
  125. s2.close
  126. end
  127. }
  128. }
  129. end
  130. def test_tcp_cloexec
  131. return unless defined? Fcntl::FD_CLOEXEC
  132. TCPServer.open(0) {|serv|
  133. addr = serv.connect_address
  134. addr.connect {|s1|
  135. s2 = serv.accept
  136. begin
  137. assert(s2.close_on_exec?)
  138. ensure
  139. s2.close
  140. end
  141. }
  142. }
  143. end
  144. def random_port
  145. # IANA suggests dynamic port for 49152 to 65535
  146. # http://www.iana.org/assignments/port-numbers
  147. 49152 + rand(65535-49152+1)
  148. end
  149. def errors_addrinuse
  150. [Errno::EADDRINUSE]
  151. end
  152. def test_tcp_server_sockets
  153. port = random_port
  154. begin
  155. sockets = Socket.tcp_server_sockets(port)
  156. rescue *errors_addrinuse
  157. return # not test failure
  158. end
  159. begin
  160. sockets.each {|s|
  161. assert_equal(port, s.local_address.ip_port)
  162. }
  163. ensure
  164. sockets.each {|s|
  165. s.close
  166. }
  167. end
  168. end
  169. def test_tcp_server_sockets_port0
  170. sockets = Socket.tcp_server_sockets(0)
  171. ports = sockets.map {|s| s.local_address.ip_port }
  172. the_port = ports.first
  173. ports.each {|port|
  174. assert_equal(the_port, port)
  175. }
  176. ensure
  177. if sockets
  178. sockets.each {|s|
  179. s.close
  180. }
  181. end
  182. end
  183. if defined? UNIXSocket
  184. def test_unix
  185. Dir.mktmpdir {|tmpdir|
  186. path = "#{tmpdir}/sock"
  187. UNIXServer.open(path) {|serv|
  188. Socket.unix(path) {|s1|
  189. s2 = serv.accept
  190. begin
  191. s2raddr = s2.remote_address
  192. s1laddr = s1.local_address
  193. assert(s2raddr.to_sockaddr.empty? ||
  194. s1laddr.to_sockaddr.empty? ||
  195. s2raddr.unix_path == s1laddr.unix_path)
  196. assert(s2.close_on_exec?)
  197. ensure
  198. s2.close
  199. end
  200. }
  201. }
  202. }
  203. end
  204. def test_unix_server_socket
  205. Dir.mktmpdir {|tmpdir|
  206. path = "#{tmpdir}/sock"
  207. 2.times {
  208. serv = Socket.unix_server_socket(path)
  209. begin
  210. assert_kind_of(Socket, serv)
  211. assert(File.socket?(path))
  212. assert_equal(path, serv.local_address.unix_path)
  213. ensure
  214. serv.close
  215. end
  216. }
  217. }
  218. end
  219. def test_accept_loop_with_unix
  220. Dir.mktmpdir {|tmpdir|
  221. tcp_servers = []
  222. clients = []
  223. accepted = []
  224. begin
  225. tcp_servers = Socket.tcp_server_sockets(0)
  226. unix_server = Socket.unix_server_socket("#{tmpdir}/sock")
  227. tcp_servers.each {|s|
  228. addr = s.connect_address
  229. begin
  230. clients << addr.connect
  231. rescue
  232. # allow failure if the address is IPv6
  233. raise unless addr.ipv6?
  234. end
  235. }
  236. addr = unix_server.connect_address
  237. assert_nothing_raised("connect to #{addr.inspect}") {
  238. clients << addr.connect
  239. }
  240. Socket.accept_loop(tcp_servers, unix_server) {|s|
  241. accepted << s
  242. break if clients.length == accepted.length
  243. }
  244. assert_equal(clients.length, accepted.length)
  245. ensure
  246. tcp_servers.each {|s| s.close if !s.closed? }
  247. unix_server.close if unix_server && !unix_server.closed?
  248. clients.each {|s| s.close if !s.closed? }
  249. accepted.each {|s| s.close if !s.closed? }
  250. end
  251. }
  252. end
  253. end
  254. def test_accept_loop
  255. servers = []
  256. begin
  257. servers = Socket.tcp_server_sockets(0)
  258. port = servers[0].local_address.ip_port
  259. Socket.tcp("localhost", port) {|s1|
  260. Socket.accept_loop(servers) {|s2, client_ai|
  261. begin
  262. assert_equal(s1.local_address.ip_unpack, client_ai.ip_unpack)
  263. ensure
  264. s2.close
  265. end
  266. break
  267. }
  268. }
  269. ensure
  270. servers.each {|s| s.close if !s.closed? }
  271. end
  272. end
  273. def test_accept_loop_multi_port
  274. servers = []
  275. begin
  276. servers = Socket.tcp_server_sockets(0)
  277. port = servers[0].local_address.ip_port
  278. servers2 = Socket.tcp_server_sockets(0)
  279. servers.concat servers2
  280. port2 = servers2[0].local_address.ip_port
  281. Socket.tcp("localhost", port) {|s1|
  282. Socket.accept_loop(servers) {|s2, client_ai|
  283. begin
  284. assert_equal(s1.local_address.ip_unpack, client_ai.ip_unpack)
  285. ensure
  286. s2.close
  287. end
  288. break
  289. }
  290. }
  291. Socket.tcp("localhost", port2) {|s1|
  292. Socket.accept_loop(servers) {|s2, client_ai|
  293. begin
  294. assert_equal(s1.local_address.ip_unpack, client_ai.ip_unpack)
  295. ensure
  296. s2.close
  297. end
  298. break
  299. }
  300. }
  301. ensure
  302. servers.each {|s| s.close if !s.closed? }
  303. end
  304. end
  305. def test_udp_server
  306. begin
  307. ifaddrs = Socket.getifaddrs
  308. rescue NotImplementedError
  309. skip "Socket.getifaddrs not implemented"
  310. end
  311. ifconfig = nil
  312. Socket.udp_server_sockets(0) {|sockets|
  313. famlies = {}
  314. sockets.each {|s| famlies[s.local_address.afamily] = s }
  315. nd6 = {}
  316. ifaddrs.reject! {|ifa|
  317. ai = ifa.addr
  318. next true unless ai
  319. s = famlies[ai.afamily]
  320. next true unless s
  321. next true if ai.ipv6_linklocal? # IPv6 link-local address is too troublesome in this test.
  322. case RUBY_PLATFORM
  323. when /linux/
  324. if ai.ip_address.include?('%') and
  325. (Etc.uname[:release][/[0-9.]+/].split('.').map(&:to_i) <=> [2,6,18]) <= 0
  326. # Cent OS 5.6 (2.6.18-238.19.1.el5xen) doesn't correctly work
  327. # sendmsg with pktinfo for link-local ipv6 addresses
  328. next true
  329. end
  330. when /freebsd/
  331. if ifa.addr.ipv6_linklocal?
  332. # FreeBSD 9.0 with default setting (ipv6_activate_all_interfaces
  333. # is not YES) sets IFDISABLED to interfaces which don't have
  334. # global IPv6 address.
  335. # Link-local IPv6 addresses on those interfaces don't work.
  336. ulSIOCGIFINFO_IN6 = 3225971052
  337. ulND6_IFF_IFDISABLED = 8
  338. in6_ondireq = ifa.name
  339. s.ioctl(ulSIOCGIFINFO_IN6, in6_ondireq)
  340. flag = in6_ondireq.unpack('A16L6').last
  341. next true if flag & ulND6_IFF_IFDISABLED != 0
  342. nd6[ai] = flag
  343. end
  344. when /darwin/
  345. if !ai.ipv6?
  346. elsif ai.ipv6_unique_local? && /darwin1[01]\./ =~ RUBY_PLATFORM
  347. next true # iCloud addresses do not work, see Bug #6692
  348. elsif ifr_name = ai.ip_address[/%(.*)/, 1]
  349. # Mac OS X may sets IFDISABLED as FreeBSD does
  350. ulSIOCGIFFLAGS = 3223349521
  351. ulSIOCGIFINFO_IN6 = 3224398156
  352. ulIFF_POINTOPOINT = 0x10
  353. ulND6_IFF_IFDISABLED = 8
  354. in6_ondireq = ifr_name
  355. s.ioctl(ulSIOCGIFINFO_IN6, in6_ondireq)
  356. flag = in6_ondireq.unpack('A16L6').last
  357. next true if (flag & ulND6_IFF_IFDISABLED) != 0
  358. nd6[ai] = flag
  359. in6_ifreq = [ifr_name,ai.to_sockaddr].pack('a16A*')
  360. s.ioctl(ulSIOCGIFFLAGS, in6_ifreq)
  361. next true if in6_ifreq.unpack('A16L1').last & ulIFF_POINTOPOINT != 0
  362. end
  363. ifconfig ||= `/sbin/ifconfig`
  364. next true if ifconfig.scan(/^(\w+):(.*(?:\n\t.*)*)/).find do |_ifname, value|
  365. value.include?(ai.ip_address) && value.include?('POINTOPOINT')
  366. end
  367. end
  368. false
  369. }
  370. skipped = false
  371. begin
  372. port = sockets.first.local_address.ip_port
  373. ping_p = false
  374. th = Thread.new {
  375. Socket.udp_server_loop_on(sockets) {|msg, msg_src|
  376. break if msg == "exit"
  377. rmsg = Marshal.dump([msg, msg_src.remote_address, msg_src.local_address])
  378. ping_p = true
  379. msg_src.reply rmsg
  380. }
  381. }
  382. ifaddrs.each {|ifa|
  383. ai = ifa.addr
  384. Addrinfo.udp(ai.ip_address, port).connect {|s|
  385. ping_p = false
  386. msg1 = "<<<#{ai.inspect}>>>"
  387. s.sendmsg msg1
  388. unless IO.select([s], nil, nil, 10)
  389. nd6options = nd6.key?(ai) ? "nd6=%x " % nd6[ai] : ''
  390. raise "no response from #{ifa.inspect} #{nd6options}ping=#{ping_p}"
  391. end
  392. msg2, addr = s.recvmsg
  393. msg2, _, _ = Marshal.load(msg2)
  394. assert_equal(msg1, msg2)
  395. assert_equal(ai.ip_address, addr.ip_address)
  396. }
  397. }
  398. rescue NotImplementedError, Errno::ENOSYS
  399. skipped = true
  400. skip "need sendmsg and recvmsg: #{$!}"
  401. ensure
  402. if th
  403. if skipped
  404. Thread.kill th unless th.join(10)
  405. else
  406. Addrinfo.udp("127.0.0.1", port).connect {|s| s.sendmsg "exit" }
  407. unless th.join(10)
  408. Thread.kill th
  409. th.join(10)
  410. raise "thread killed"
  411. end
  412. end
  413. end
  414. end
  415. }
  416. end
  417. def test_linger
  418. opt = Socket::Option.linger(true, 0)
  419. assert_equal([true, 0], opt.linger)
  420. Addrinfo.tcp("127.0.0.1", 0).listen {|serv|
  421. serv.local_address.connect {|s1|
  422. s2, _ = serv.accept
  423. begin
  424. s1.setsockopt(opt)
  425. s1.close
  426. assert_raise(Errno::ECONNRESET) { s2.read }
  427. ensure
  428. s2.close
  429. end
  430. }
  431. }
  432. end
  433. def timestamp_retry_rw(s1, s2, t1, type)
  434. IO.pipe do |r,w|
  435. # UDP may not be reliable, keep sending until recvmsg returns:
  436. th = Thread.new do
  437. n = 0
  438. begin
  439. s2.send("a", 0, s1.local_address)
  440. n += 1
  441. end while IO.select([r], nil, nil, 0.1).nil?
  442. n
  443. end
  444. timeout = (RubyVM::MJIT.enabled? ? 120 : 30) # for --jit-wait
  445. assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout))
  446. msg, _, _, stamp = s1.recvmsg
  447. assert_equal("a", msg)
  448. assert(stamp.cmsg_is?(:SOCKET, type))
  449. w.close # stop th
  450. n = th.value
  451. n > 1 and
  452. warn "UDP packet loss for #{type} over loopback, #{n} tries needed"
  453. t2 = Time.now.strftime("%Y-%m-%d")
  454. pat = Regexp.union([t1, t2].uniq)
  455. assert_match(pat, stamp.inspect)
  456. t = stamp.timestamp
  457. assert_match(pat, t.strftime("%Y-%m-%d"))
  458. stamp
  459. end
  460. end
  461. def test_timestamp
  462. return if /linux|freebsd|netbsd|openbsd|solaris|darwin/ !~ RUBY_PLATFORM
  463. return if !defined?(Socket::AncillaryData) || !defined?(Socket::SO_TIMESTAMP)
  464. t1 = Time.now.strftime("%Y-%m-%d")
  465. stamp = nil
  466. Addrinfo.udp("127.0.0.1", 0).bind {|s1|
  467. Addrinfo.udp("127.0.0.1", 0).bind {|s2|
  468. s1.setsockopt(:SOCKET, :TIMESTAMP, true)
  469. stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMP)
  470. }
  471. }
  472. t = stamp.timestamp
  473. pat = /\.#{"%06d" % t.usec}/
  474. assert_match(pat, stamp.inspect)
  475. end
  476. def test_timestampns
  477. return if /linux/ !~ RUBY_PLATFORM || !defined?(Socket::SO_TIMESTAMPNS)
  478. t1 = Time.now.strftime("%Y-%m-%d")
  479. stamp = nil
  480. Addrinfo.udp("127.0.0.1", 0).bind {|s1|
  481. Addrinfo.udp("127.0.0.1", 0).bind {|s2|
  482. begin
  483. s1.setsockopt(:SOCKET, :TIMESTAMPNS, true)
  484. rescue Errno::ENOPROTOOPT
  485. # SO_TIMESTAMPNS is available since Linux 2.6.22
  486. return
  487. end
  488. stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMPNS)
  489. }
  490. }
  491. t = stamp.timestamp
  492. pat = /\.#{"%09d" % t.nsec}/
  493. assert_match(pat, stamp.inspect)
  494. end
  495. def test_bintime
  496. return if /freebsd/ !~ RUBY_PLATFORM
  497. t1 = Time.now.strftime("%Y-%m-%d")
  498. stamp = nil
  499. Addrinfo.udp("127.0.0.1", 0).bind {|s1|
  500. Addrinfo.udp("127.0.0.1", 0).bind {|s2|
  501. s1.setsockopt(:SOCKET, :BINTIME, true)
  502. s2.send "a", 0, s1.local_address
  503. msg, _, _, stamp = s1.recvmsg
  504. assert_equal("a", msg)
  505. assert(stamp.cmsg_is?(:SOCKET, :BINTIME))
  506. }
  507. }
  508. t2 = Time.now.strftime("%Y-%m-%d")
  509. pat = Regexp.union([t1, t2].uniq)
  510. assert_match(pat, stamp.inspect)
  511. t = stamp.timestamp
  512. assert_match(pat, t.strftime("%Y-%m-%d"))
  513. assert_equal(stamp.data[-8,8].unpack("Q")[0], t.subsec * 2**64)
  514. end
  515. def test_closed_read
  516. require 'timeout'
  517. require 'socket'
  518. bug4390 = '[ruby-core:35203]'
  519. server = TCPServer.new("localhost", 0)
  520. serv_thread = Thread.new {server.accept}
  521. begin sleep(0.1) end until serv_thread.stop?
  522. sock = TCPSocket.new("localhost", server.addr[1])
  523. client_thread = Thread.new do
  524. assert_raise(IOError, bug4390) {
  525. sock.readline
  526. }
  527. end
  528. begin sleep(0.1) end until client_thread.stop?
  529. Timeout.timeout(1) do
  530. sock.close
  531. sock = nil
  532. client_thread.join
  533. end
  534. ensure
  535. serv_thread.value.close
  536. server.close
  537. end
  538. def test_connect_timeout
  539. host = "127.0.0.1"
  540. server = TCPServer.new(host, 0)
  541. port = server.addr[1]
  542. serv_thread = Thread.new {server.accept}
  543. sock = Socket.tcp(host, port, :connect_timeout => 30)
  544. accepted = serv_thread.value
  545. assert_kind_of TCPSocket, accepted
  546. assert_equal sock, IO.select(nil, [ sock ])[1][0], "not writable"
  547. sock.close
  548. # some platforms may not timeout when the listener queue overflows,
  549. # but we know Linux does with the default listen backlog of SOMAXCONN for
  550. # TCPServer.
  551. assert_raise(Errno::ETIMEDOUT) do
  552. (Socket::SOMAXCONN*2).times do |i|
  553. sock = Socket.tcp(host, port, :connect_timeout => 0)
  554. assert_equal sock, IO.select(nil, [ sock ])[1][0],
  555. "not writable (#{i})"
  556. sock.close
  557. end
  558. end if RUBY_PLATFORM =~ /linux/
  559. ensure
  560. server.close
  561. accepted.close if accepted
  562. sock.close if sock && ! sock.closed?
  563. end
  564. def test_getifaddrs
  565. begin
  566. list = Socket.getifaddrs
  567. rescue NotImplementedError
  568. return
  569. end
  570. list.each {|ifaddr|
  571. assert_instance_of(Socket::Ifaddr, ifaddr)
  572. }
  573. end
  574. def test_connect_in_rescue
  575. serv = Addrinfo.tcp(nil, 0).listen
  576. addr = serv.connect_address
  577. begin
  578. raise "dummy error"
  579. rescue
  580. s = addr.connect
  581. assert(!s.closed?)
  582. end
  583. ensure
  584. serv.close if serv && !serv.closed?
  585. s.close if s && !s.closed?
  586. end
  587. def test_bind_in_rescue
  588. begin
  589. raise "dummy error"
  590. rescue
  591. s = Addrinfo.tcp(nil, 0).bind
  592. assert(!s.closed?)
  593. end
  594. ensure
  595. s.close if s && !s.closed?
  596. end
  597. def test_listen_in_rescue
  598. begin
  599. raise "dummy error"
  600. rescue
  601. s = Addrinfo.tcp(nil, 0).listen
  602. assert(!s.closed?)
  603. end
  604. ensure
  605. s.close if s && !s.closed?
  606. end
  607. def test_udp_server_sockets_in_rescue
  608. begin
  609. raise "dummy error"
  610. rescue
  611. ss = Socket.udp_server_sockets(0)
  612. ss.each {|s|
  613. assert(!s.closed?)
  614. }
  615. end
  616. ensure
  617. if ss
  618. ss.each {|s|
  619. s.close if !s.closed?
  620. }
  621. end
  622. end
  623. def test_tcp_server_sockets_in_rescue
  624. begin
  625. raise "dummy error"
  626. rescue
  627. ss = Socket.tcp_server_sockets(0)
  628. ss.each {|s|
  629. assert(!s.closed?)
  630. }
  631. end
  632. ensure
  633. if ss
  634. ss.each {|s|
  635. s.close if !s.closed?
  636. }
  637. end
  638. end
  639. def test_recvmsg_udp_no_arg
  640. n = 4097
  641. s1 = Addrinfo.udp("127.0.0.1", 0).bind
  642. s2 = s1.connect_address.connect
  643. s2.send("a" * n, 0)
  644. ret = s1.recvmsg
  645. assert_equal n, ret[0].bytesize, '[ruby-core:71517] [Bug #11701]'
  646. s2.send("a" * n, 0)
  647. IO.select([s1])
  648. ret = s1.recvmsg_nonblock
  649. assert_equal n, ret[0].bytesize, 'non-blocking should also grow'
  650. ensure
  651. s1.close
  652. s2.close
  653. end
  654. def test_udp_read_truncation
  655. s1 = Addrinfo.udp("127.0.0.1", 0).bind
  656. s2 = s1.connect_address.connect
  657. s2.send("a" * 100, 0)
  658. ret = s1.read(10)
  659. assert_equal "a" * 10, ret
  660. s2.send("b" * 100, 0)
  661. ret = s1.read(10)
  662. assert_equal "b" * 10, ret
  663. ensure
  664. s1.close
  665. s2.close
  666. end
  667. def test_udp_recv_truncation
  668. s1 = Addrinfo.udp("127.0.0.1", 0).bind
  669. s2 = s1.connect_address.connect
  670. s2.send("a" * 100, 0)
  671. ret = s1.recv(10, Socket::MSG_PEEK)
  672. assert_equal "a" * 10, ret
  673. ret = s1.recv(10, 0)
  674. assert_equal "a" * 10, ret
  675. s2.send("b" * 100, 0)
  676. ret = s1.recv(10, 0)
  677. assert_equal "b" * 10, ret
  678. ensure
  679. s1.close
  680. s2.close
  681. end
  682. def test_udp_recvmsg_truncation
  683. s1 = Addrinfo.udp("127.0.0.1", 0).bind
  684. s2 = s1.connect_address.connect
  685. s2.send("a" * 100, 0)
  686. ret, addr, rflags = s1.recvmsg(10, Socket::MSG_PEEK)
  687. assert_equal "a" * 10, ret
  688. # AIX does not set MSG_TRUNC for a message partially read with MSG_PEEK.
  689. assert_equal Socket::MSG_TRUNC, rflags & Socket::MSG_TRUNC if !rflags.nil? && /aix/ !~ RUBY_PLATFORM
  690. ret, addr, rflags = s1.recvmsg(10, 0)
  691. assert_equal "a" * 10, ret
  692. assert_equal Socket::MSG_TRUNC, rflags & Socket::MSG_TRUNC if !rflags.nil?
  693. s2.send("b" * 100, 0)
  694. ret, addr, rflags = s1.recvmsg(10, 0)
  695. assert_equal "b" * 10, ret
  696. assert_equal Socket::MSG_TRUNC, rflags & Socket::MSG_TRUNC if !rflags.nil?
  697. addr
  698. ensure
  699. s1.close
  700. s2.close
  701. end
  702. end if defined?(Socket)