PageRenderTime 28ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/socket/test_unix.rb

http://github.com/ruby/ruby
Ruby | 715 lines | 667 code | 44 blank | 4 comment | 55 complexity | 374a58c8a67af417f308f3875513b615 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. rescue LoadError
  5. end
  6. require "test/unit"
  7. require "tempfile"
  8. require "timeout"
  9. require "tmpdir"
  10. require "io/nonblock"
  11. class TestSocket_UNIXSocket < Test::Unit::TestCase
  12. def test_fd_passing
  13. r1, w = IO.pipe
  14. s1, s2 = UNIXSocket.pair
  15. begin
  16. s1.send_io(nil)
  17. rescue NotImplementedError
  18. assert_raise(NotImplementedError) { s2.recv_io }
  19. rescue TypeError
  20. s1.send_io(r1)
  21. r2 = s2.recv_io
  22. assert_equal(r1.stat.ino, r2.stat.ino)
  23. assert_not_equal(r1.fileno, r2.fileno)
  24. assert(r2.close_on_exec?)
  25. w.syswrite "a"
  26. assert_equal("a", r2.sysread(10))
  27. ensure
  28. s1.close
  29. s2.close
  30. w.close
  31. r1.close
  32. r2.close if r2 && !r2.closed?
  33. end
  34. end
  35. def test_fd_passing_class_mode
  36. UNIXSocket.pair do |s1, s2|
  37. s1.send_io(s1.fileno)
  38. r = s2.recv_io(nil)
  39. assert_kind_of Integer, r, 'recv_io with klass=nil returns integer FD'
  40. assert_not_equal s1.fileno, r
  41. r = IO.for_fd(r)
  42. assert_equal s1.stat.ino, r.stat.ino
  43. r.close
  44. s1.send_io(s1)
  45. # klass = UNIXSocket FIXME: [ruby-core:71860] [Bug #11778]
  46. klass = IO
  47. r = s2.recv_io(klass, 'r+')
  48. assert_instance_of klass, r, 'recv_io with proper klass'
  49. assert_not_equal s1.fileno, r.fileno
  50. r.close
  51. end
  52. end
  53. def test_fd_passing_n
  54. io_ary = []
  55. return if !defined?(Socket::SCM_RIGHTS)
  56. io_ary.concat IO.pipe
  57. io_ary.concat IO.pipe
  58. io_ary.concat IO.pipe
  59. send_io_ary = []
  60. io_ary.each {|io|
  61. send_io_ary << io
  62. UNIXSocket.pair {|s1, s2|
  63. begin
  64. ret = s1.sendmsg("\0", 0, nil, [Socket::SOL_SOCKET, Socket::SCM_RIGHTS,
  65. send_io_ary.map {|io2| io2.fileno }.pack("i!*")])
  66. rescue NotImplementedError
  67. return
  68. end
  69. assert_equal(1, ret)
  70. ret = s2.recvmsg(:scm_rights=>true)
  71. _, _, _, *ctls = ret
  72. recv_io_ary = []
  73. begin
  74. ctls.each {|ctl|
  75. next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
  76. recv_io_ary.concat ctl.unix_rights
  77. }
  78. assert_equal(send_io_ary.length, recv_io_ary.length)
  79. send_io_ary.length.times {|i|
  80. assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
  81. assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
  82. assert(recv_io_ary[i].close_on_exec?)
  83. }
  84. ensure
  85. recv_io_ary.each {|io2| io2.close if !io2.closed? }
  86. end
  87. }
  88. }
  89. ensure
  90. io_ary.each {|io| io.close if !io.closed? }
  91. end
  92. def test_fd_passing_n2
  93. io_ary = []
  94. return if !defined?(Socket::SCM_RIGHTS)
  95. return if !defined?(Socket::AncillaryData)
  96. io_ary.concat IO.pipe
  97. io_ary.concat IO.pipe
  98. io_ary.concat IO.pipe
  99. send_io_ary = []
  100. io_ary.each {|io|
  101. send_io_ary << io
  102. UNIXSocket.pair {|s1, s2|
  103. begin
  104. ancdata = Socket::AncillaryData.unix_rights(*send_io_ary)
  105. ret = s1.sendmsg("\0", 0, nil, ancdata)
  106. rescue NotImplementedError
  107. return
  108. end
  109. assert_equal(1, ret)
  110. ret = s2.recvmsg(:scm_rights=>true)
  111. _, _, _, *ctls = ret
  112. recv_io_ary = []
  113. begin
  114. ctls.each {|ctl|
  115. next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
  116. recv_io_ary.concat ctl.unix_rights
  117. }
  118. assert_equal(send_io_ary.length, recv_io_ary.length)
  119. send_io_ary.length.times {|i|
  120. assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
  121. assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
  122. assert(recv_io_ary[i].close_on_exec?)
  123. }
  124. ensure
  125. recv_io_ary.each {|io2| io2.close if !io2.closed? }
  126. end
  127. }
  128. }
  129. ensure
  130. io_ary.each {|io| io.close if !io.closed? }
  131. end
  132. def test_fd_passing_race_condition
  133. r1, w = IO.pipe
  134. s1, s2 = UNIXSocket.pair
  135. s1.nonblock = s2.nonblock = true
  136. lock = Thread::Mutex.new
  137. nr = 0
  138. x = 2
  139. y = 1000
  140. begin
  141. s1.send_io(nil)
  142. rescue NotImplementedError
  143. assert_raise(NotImplementedError) { s2.recv_io }
  144. rescue TypeError
  145. thrs = x.times.map do
  146. Thread.new do
  147. y.times do
  148. s2.recv_io.close
  149. lock.synchronize { nr += 1 }
  150. end
  151. true
  152. end
  153. end
  154. (x * y).times { s1.send_io r1 }
  155. assert_equal([true]*x, thrs.map { |t| t.value })
  156. assert_equal x * y, nr
  157. ensure
  158. s1.close
  159. s2.close
  160. w.close
  161. r1.close
  162. end
  163. end
  164. def test_sendmsg
  165. return if !defined?(Socket::SCM_RIGHTS)
  166. IO.pipe {|r1, w|
  167. UNIXSocket.pair {|s1, s2|
  168. begin
  169. ret = s1.sendmsg("\0", 0, nil, [Socket::SOL_SOCKET, Socket::SCM_RIGHTS, [r1.fileno].pack("i!")])
  170. rescue NotImplementedError
  171. return
  172. end
  173. assert_equal(1, ret)
  174. r2 = s2.recv_io
  175. begin
  176. assert(File.identical?(r1, r2))
  177. assert(r2.close_on_exec?)
  178. ensure
  179. r2.close
  180. end
  181. }
  182. }
  183. end
  184. def test_sendmsg_ancillarydata_int
  185. return if !defined?(Socket::SCM_RIGHTS)
  186. return if !defined?(Socket::AncillaryData)
  187. IO.pipe {|r1, w|
  188. UNIXSocket.pair {|s1, s2|
  189. begin
  190. ad = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, r1.fileno)
  191. ret = s1.sendmsg("\0", 0, nil, ad)
  192. rescue NotImplementedError
  193. return
  194. end
  195. assert_equal(1, ret)
  196. r2 = s2.recv_io
  197. begin
  198. assert(File.identical?(r1, r2))
  199. ensure
  200. r2.close
  201. end
  202. }
  203. }
  204. end
  205. def test_sendmsg_ancillarydata_unix_rights
  206. return if !defined?(Socket::SCM_RIGHTS)
  207. return if !defined?(Socket::AncillaryData)
  208. IO.pipe {|r1, w|
  209. UNIXSocket.pair {|s1, s2|
  210. begin
  211. ad = Socket::AncillaryData.unix_rights(r1)
  212. ret = s1.sendmsg("\0", 0, nil, ad)
  213. rescue NotImplementedError
  214. return
  215. end
  216. assert_equal(1, ret)
  217. r2 = s2.recv_io
  218. begin
  219. assert(File.identical?(r1, r2))
  220. ensure
  221. r2.close
  222. end
  223. }
  224. }
  225. end
  226. def test_recvmsg
  227. return if !defined?(Socket::SCM_RIGHTS)
  228. return if !defined?(Socket::AncillaryData)
  229. IO.pipe {|r1, w|
  230. UNIXSocket.pair {|s1, s2|
  231. s1.send_io(r1)
  232. ret = s2.recvmsg(:scm_rights=>true)
  233. data, srcaddr, flags, *ctls = ret
  234. assert_equal("\0", data)
  235. if flags == nil
  236. # struct msghdr is 4.3BSD style (msg_accrights field).
  237. assert_instance_of(Array, ctls)
  238. assert_equal(0, ctls.length)
  239. else
  240. # struct msghdr is POSIX/4.4BSD style (msg_control field).
  241. assert_equal(0, flags & (Socket::MSG_TRUNC|Socket::MSG_CTRUNC))
  242. assert_instance_of(Addrinfo, srcaddr)
  243. assert_instance_of(Array, ctls)
  244. assert_equal(1, ctls.length)
  245. ctl = ctls[0]
  246. assert_instance_of(Socket::AncillaryData, ctl)
  247. assert_equal(Socket::SOL_SOCKET, ctl.level)
  248. assert_equal(Socket::SCM_RIGHTS, ctl.type)
  249. assert_instance_of(String, ctl.data)
  250. ios = ctl.unix_rights
  251. assert_equal(1, ios.length)
  252. r2 = ios[0]
  253. begin
  254. assert(File.identical?(r1, r2))
  255. assert(r2.close_on_exec?)
  256. ensure
  257. r2.close
  258. end
  259. end
  260. }
  261. }
  262. end
  263. def bound_unix_socket(klass)
  264. tmpfile = Tempfile.new("s")
  265. path = tmpfile.path
  266. tmpfile.close(true)
  267. io = klass.new(path)
  268. yield io, path
  269. ensure
  270. io.close
  271. File.unlink path if path && File.socket?(path)
  272. end
  273. def test_open_nul_byte
  274. tmpfile = Tempfile.new("s")
  275. path = tmpfile.path
  276. tmpfile.close(true)
  277. assert_raise(ArgumentError) {UNIXServer.open(path+"\0")}
  278. assert_raise(ArgumentError) {UNIXSocket.open(path+"\0")}
  279. ensure
  280. File.unlink path if path && File.socket?(path)
  281. end
  282. def test_addr
  283. bound_unix_socket(UNIXServer) {|serv, path|
  284. UNIXSocket.open(path) {|c|
  285. s = serv.accept
  286. begin
  287. assert_equal(["AF_UNIX", path], c.peeraddr)
  288. assert_equal(["AF_UNIX", ""], c.addr)
  289. assert_equal(["AF_UNIX", ""], s.peeraddr)
  290. assert_equal(["AF_UNIX", path], s.addr)
  291. assert_equal(path, s.path)
  292. assert_equal("", c.path)
  293. ensure
  294. s.close
  295. end
  296. }
  297. }
  298. end
  299. def test_cloexec
  300. bound_unix_socket(UNIXServer) {|serv, path|
  301. UNIXSocket.open(path) {|c|
  302. s = serv.accept
  303. begin
  304. assert(serv.close_on_exec?)
  305. assert(c.close_on_exec?)
  306. assert(s.close_on_exec?)
  307. ensure
  308. s.close
  309. end
  310. }
  311. }
  312. end
  313. def test_noname_path
  314. s1, s2 = UNIXSocket.pair
  315. assert_equal("", s1.path)
  316. assert_equal("", s2.path)
  317. ensure
  318. s1.close
  319. s2.close
  320. end
  321. def test_noname_addr
  322. s1, s2 = UNIXSocket.pair
  323. assert_equal(["AF_UNIX", ""], s1.addr)
  324. assert_equal(["AF_UNIX", ""], s2.addr)
  325. ensure
  326. s1.close
  327. s2.close
  328. end
  329. def test_noname_peeraddr
  330. s1, s2 = UNIXSocket.pair
  331. assert_equal(["AF_UNIX", ""], s1.peeraddr)
  332. assert_equal(["AF_UNIX", ""], s2.peeraddr)
  333. ensure
  334. s1.close
  335. s2.close
  336. end
  337. def test_noname_unpack_sockaddr_un
  338. s1, s2 = UNIXSocket.pair
  339. n = nil
  340. assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != ""
  341. assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != ""
  342. assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getsockname) != ""
  343. assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getpeername) != ""
  344. assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getpeername) != ""
  345. ensure
  346. s1.close
  347. s2.close
  348. end
  349. def test_noname_recvfrom
  350. s1, s2 = UNIXSocket.pair
  351. s2.write("a")
  352. assert_equal(["a", ["AF_UNIX", ""]], s1.recvfrom(10))
  353. ensure
  354. s1.close
  355. s2.close
  356. end
  357. def test_noname_recv_nonblock
  358. s1, s2 = UNIXSocket.pair
  359. s2.write("a")
  360. IO.select [s1]
  361. assert_equal("a", s1.recv_nonblock(10))
  362. ensure
  363. s1.close
  364. s2.close
  365. end
  366. def test_too_long_path
  367. assert_raise(ArgumentError) { Socket.sockaddr_un("a" * 3000) }
  368. assert_raise(ArgumentError) { UNIXServer.new("a" * 3000) }
  369. end
  370. def test_abstract_namespace
  371. return if /linux/ !~ RUBY_PLATFORM
  372. addr = Socket.pack_sockaddr_un("\0foo")
  373. assert_match(/\0foo\z/, addr)
  374. assert_equal("\0foo", Socket.unpack_sockaddr_un(addr))
  375. end
  376. def test_dgram_pair
  377. s1, s2 = UNIXSocket.pair(Socket::SOCK_DGRAM)
  378. begin
  379. s1.recv_nonblock(10)
  380. fail
  381. rescue => e
  382. assert(IO::EAGAINWaitReadable === e)
  383. assert(IO::WaitReadable === e)
  384. end
  385. s2.send("", 0)
  386. s2.send("haha", 0)
  387. s2.send("", 0)
  388. s2.send("", 0)
  389. assert_equal("", s1.recv(10))
  390. assert_equal("haha", s1.recv(10))
  391. assert_equal("", s1.recv(10))
  392. assert_equal("", s1.recv(10))
  393. assert_raise(IO::EAGAINWaitReadable) { s1.recv_nonblock(10) }
  394. buf = "".dup
  395. s2.send("BBBBBB", 0)
  396. IO.select([s1])
  397. rv = s1.recv(100, 0, buf)
  398. assert_equal buf.object_id, rv.object_id
  399. assert_equal "BBBBBB", rv
  400. ensure
  401. s1.close if s1
  402. s2.close if s2
  403. end
  404. def test_dgram_pair_sendrecvmsg_errno_set
  405. s1, s2 = to_close = UNIXSocket.pair(Socket::SOCK_DGRAM)
  406. pipe = IO.pipe
  407. to_close.concat(pipe)
  408. set_errno = lambda do
  409. begin
  410. pipe[0].read_nonblock(1)
  411. fail
  412. rescue => e
  413. assert(IO::EAGAINWaitReadable === e)
  414. end
  415. end
  416. Timeout.timeout(10) do
  417. set_errno.call
  418. assert_equal(2, s1.sendmsg("HI"))
  419. set_errno.call
  420. assert_equal("HI", s2.recvmsg[0])
  421. end
  422. ensure
  423. to_close.each(&:close) if to_close
  424. end
  425. def test_epipe # [ruby-dev:34619]
  426. UNIXSocket.pair {|s1, s2|
  427. s1.shutdown(Socket::SHUT_WR)
  428. assert_raise(Errno::EPIPE) { s1.write "a" }
  429. assert_equal(nil, s2.read(1))
  430. s2.write "a"
  431. assert_equal("a", s1.read(1))
  432. }
  433. end
  434. def test_socket_pair_with_block
  435. pair = nil
  436. ret = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0) {|s1, s2|
  437. pair = [s1, s2]
  438. :return_value
  439. }
  440. assert_equal(:return_value, ret)
  441. assert_kind_of(Socket, pair[0])
  442. assert_kind_of(Socket, pair[1])
  443. end
  444. def test_unix_socket_pair_with_block
  445. pair = nil
  446. UNIXSocket.pair {|s1, s2|
  447. pair = [s1, s2]
  448. }
  449. assert_kind_of(UNIXSocket, pair[0])
  450. assert_kind_of(UNIXSocket, pair[1])
  451. end
  452. def test_unix_socket_pair_close_on_exec
  453. UNIXSocket.pair {|s1, s2|
  454. assert(s1.close_on_exec?)
  455. assert(s2.close_on_exec?)
  456. }
  457. end
  458. def test_initialize
  459. Dir.mktmpdir {|d|
  460. Socket.open(Socket::AF_UNIX, Socket::SOCK_STREAM, 0) {|s|
  461. s.bind(Socket.pack_sockaddr_un("#{d}/s1"))
  462. addr = s.getsockname
  463. assert_nothing_raised { Socket.unpack_sockaddr_un(addr) }
  464. assert_raise(ArgumentError) { Socket.unpack_sockaddr_in(addr) }
  465. }
  466. Socket.open("AF_UNIX", "SOCK_STREAM", 0) {|s|
  467. s.bind(Socket.pack_sockaddr_un("#{d}/s2"))
  468. addr = s.getsockname
  469. assert_nothing_raised { Socket.unpack_sockaddr_un(addr) }
  470. assert_raise(ArgumentError) { Socket.unpack_sockaddr_in(addr) }
  471. }
  472. }
  473. end
  474. def test_unix_server_socket
  475. Dir.mktmpdir {|d|
  476. path = "#{d}/sock"
  477. s0 = nil
  478. Socket.unix_server_socket(path) {|s|
  479. assert_equal(path, s.local_address.unix_path)
  480. assert(File.socket?(path))
  481. s0 = s
  482. }
  483. assert(s0.closed?)
  484. assert_raise(Errno::ENOENT) { File.stat path }
  485. }
  486. end
  487. def test_getcred_ucred
  488. return if /linux/ !~ RUBY_PLATFORM
  489. Dir.mktmpdir {|d|
  490. sockpath = "#{d}/sock"
  491. Socket.unix_server_socket(sockpath) {|serv|
  492. Socket.unix(sockpath) {|c|
  493. s, = serv.accept
  494. begin
  495. cred = s.getsockopt(:SOCKET, :PEERCRED)
  496. inspect = cred.inspect
  497. assert_match(/ pid=#{$$} /, inspect)
  498. assert_match(/ euid=#{Process.euid} /, inspect)
  499. assert_match(/ egid=#{Process.egid} /, inspect)
  500. assert_match(/ \(ucred\)/, inspect)
  501. ensure
  502. s.close
  503. end
  504. }
  505. }
  506. }
  507. end
  508. def test_getcred_xucred
  509. return if /freebsd|darwin/ !~ RUBY_PLATFORM
  510. Dir.mktmpdir do |d|
  511. sockpath = "#{d}/sock"
  512. serv = Socket.unix_server_socket(sockpath)
  513. u = Socket.unix(sockpath)
  514. s, = serv.accept
  515. cred = s.getsockopt(0, Socket::LOCAL_PEERCRED)
  516. inspect = cred.inspect
  517. assert_match(/ euid=#{Process.euid} /, inspect)
  518. assert_match(/ \(xucred\)/, inspect)
  519. ensure
  520. s&.close
  521. u&.close
  522. serv&.close
  523. end
  524. end
  525. def test_sendcred_ucred
  526. return if /linux/ !~ RUBY_PLATFORM
  527. Dir.mktmpdir {|d|
  528. sockpath = "#{d}/sock"
  529. Socket.unix_server_socket(sockpath) {|serv|
  530. Socket.unix(sockpath) {|c|
  531. s, = serv.accept
  532. begin
  533. s.setsockopt(:SOCKET, :PASSCRED, 1)
  534. c.print "a"
  535. msg, _, _, cred = s.recvmsg
  536. inspect = cred.inspect
  537. assert_equal("a", msg)
  538. assert_match(/ pid=#{$$} /, inspect)
  539. assert_match(/ uid=#{Process.uid} /, inspect)
  540. assert_match(/ gid=#{Process.gid} /, inspect)
  541. assert_match(/ \(ucred\)/, inspect)
  542. ensure
  543. s.close
  544. end
  545. }
  546. }
  547. }
  548. end
  549. def test_sendcred_sockcred
  550. return if /netbsd|freebsd/ !~ RUBY_PLATFORM
  551. Dir.mktmpdir {|d|
  552. sockpath = "#{d}/sock"
  553. serv = Socket.unix_server_socket(sockpath)
  554. c = Socket.unix(sockpath)
  555. s, = serv.accept
  556. s.setsockopt(0, Socket::LOCAL_CREDS, 1)
  557. c.print "a"
  558. msg, _, _, cred = s.recvmsg
  559. assert_equal("a", msg)
  560. inspect = cred.inspect
  561. assert_match(/ uid=#{Process.uid} /, inspect)
  562. assert_match(/ euid=#{Process.euid} /, inspect)
  563. assert_match(/ gid=#{Process.gid} /, inspect)
  564. assert_match(/ egid=#{Process.egid} /, inspect)
  565. assert_match(/ \(sockcred\)/, inspect)
  566. }
  567. end
  568. def test_sendcred_cmsgcred
  569. return if /freebsd/ !~ RUBY_PLATFORM
  570. Dir.mktmpdir {|d|
  571. sockpath = "#{d}/sock"
  572. serv = Socket.unix_server_socket(sockpath)
  573. c = Socket.unix(sockpath)
  574. s, = serv.accept
  575. c.sendmsg("a", 0, nil, [:SOCKET, Socket::SCM_CREDS, ""])
  576. msg, _, _, cred = s.recvmsg
  577. assert_equal("a", msg)
  578. inspect = cred.inspect
  579. assert_match(/ pid=#{$$} /, inspect)
  580. assert_match(/ uid=#{Process.uid} /, inspect)
  581. assert_match(/ euid=#{Process.euid} /, inspect)
  582. assert_match(/ gid=#{Process.gid} /, inspect)
  583. assert_match(/ \(cmsgcred\)/, inspect)
  584. }
  585. end
  586. def test_getpeereid
  587. Dir.mktmpdir {|d|
  588. path = "#{d}/sock"
  589. Socket.unix_server_socket(path) {|serv|
  590. Socket.unix(path) {|c|
  591. s, = serv.accept
  592. begin
  593. assert_equal([Process.euid, Process.egid], c.getpeereid)
  594. assert_equal([Process.euid, Process.egid], s.getpeereid)
  595. rescue NotImplementedError
  596. ensure
  597. s.close
  598. end
  599. }
  600. }
  601. }
  602. end
  603. def test_abstract_unix_server
  604. return if /linux/ !~ RUBY_PLATFORM
  605. name = "\0ruby-test_unix"
  606. s0 = nil
  607. UNIXServer.open(name) {|s|
  608. assert_equal(name, s.local_address.unix_path)
  609. s0 = s
  610. UNIXSocket.open(name) {|c|
  611. sock = s.accept
  612. begin
  613. assert_equal(name, c.remote_address.unix_path)
  614. ensure
  615. sock.close
  616. end
  617. }
  618. }
  619. assert(s0.closed?)
  620. end
  621. def test_abstract_unix_socket_econnrefused
  622. return if /linux/ !~ RUBY_PLATFORM
  623. name = "\0ruby-test_unix"
  624. assert_raise(Errno::ECONNREFUSED) do
  625. UNIXSocket.open(name) {}
  626. end
  627. end
  628. def test_abstract_unix_server_socket
  629. return if /linux/ !~ RUBY_PLATFORM
  630. name = "\0ruby-test_unix"
  631. s0 = nil
  632. Socket.unix_server_socket(name) {|s|
  633. assert_equal(name, s.local_address.unix_path)
  634. s0 = s
  635. Socket.unix(name) {|c|
  636. sock, = s.accept
  637. begin
  638. assert_equal(name, c.remote_address.unix_path)
  639. ensure
  640. sock.close
  641. end
  642. }
  643. }
  644. assert(s0.closed?)
  645. end
  646. def test_autobind
  647. return if /linux/ !~ RUBY_PLATFORM
  648. s0 = nil
  649. Socket.unix_server_socket("") {|s|
  650. name = s.local_address.unix_path
  651. assert_match(/\A\0[0-9a-f]{5}\z/, name)
  652. s0 = s
  653. Socket.unix(name) {|c|
  654. sock, = s.accept
  655. begin
  656. assert_equal(name, c.remote_address.unix_path)
  657. ensure
  658. sock.close
  659. end
  660. }
  661. }
  662. assert(s0.closed?)
  663. end
  664. def test_accept_nonblock
  665. bound_unix_socket(UNIXServer) {|serv, path|
  666. assert_raise(IO::WaitReadable) { serv.accept_nonblock }
  667. assert_raise(IO::WaitReadable) { serv.accept_nonblock(exception: true) }
  668. assert_equal :wait_readable, serv.accept_nonblock(exception: false)
  669. }
  670. end
  671. end if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM