PageRenderTime 35ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/jruby-1.7.3/test/externals/ruby1.9/ruby/test_io.rb

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Ruby | 2099 lines | 1868 code | 219 blank | 12 comment | 44 complexity | 2362d94917969276c2cc24f74ffe1d72 MD5 | raw file
  1. require 'test/unit'
  2. require 'tmpdir'
  3. require "fcntl"
  4. require 'io/nonblock'
  5. require 'socket'
  6. require 'stringio'
  7. require 'timeout'
  8. require 'tempfile'
  9. require 'weakref'
  10. require_relative 'envutil'
  11. class TestIO < Test::Unit::TestCase
  12. def have_close_on_exec?
  13. begin
  14. $stdin.close_on_exec?
  15. true
  16. rescue NotImplementedError
  17. false
  18. end
  19. end
  20. def have_nonblock?
  21. IO.method_defined?("nonblock=")
  22. end
  23. def pipe(wp, rp)
  24. re, we = nil, nil
  25. r, w = IO.pipe
  26. rt = Thread.new do
  27. begin
  28. rp.call(r)
  29. rescue Exception
  30. r.close
  31. re = $!
  32. end
  33. end
  34. wt = Thread.new do
  35. begin
  36. wp.call(w)
  37. rescue Exception
  38. w.close
  39. we = $!
  40. end
  41. end
  42. flunk("timeout") unless wt.join(10) && rt.join(10)
  43. ensure
  44. w.close unless !w || w.closed?
  45. r.close unless !r || r.closed?
  46. (wt.kill; wt.join) if wt
  47. (rt.kill; rt.join) if rt
  48. raise we if we
  49. raise re if re
  50. end
  51. def with_pipe
  52. r, w = IO.pipe
  53. begin
  54. yield r, w
  55. ensure
  56. r.close unless r.closed?
  57. w.close unless w.closed?
  58. end
  59. end
  60. def with_read_pipe(content)
  61. pipe(proc do |w|
  62. w << content
  63. w.close
  64. end, proc do |r|
  65. yield r
  66. end)
  67. end
  68. def mkcdtmpdir
  69. Dir.mktmpdir {|d|
  70. Dir.chdir(d) {
  71. yield
  72. }
  73. }
  74. end
  75. def trapping_usr1
  76. @usr1_rcvd = 0
  77. trap(:USR1) { @usr1_rcvd += 1 }
  78. yield
  79. ensure
  80. trap(:USR1, "DEFAULT")
  81. end
  82. def test_pipe
  83. r, w = IO.pipe
  84. assert_instance_of(IO, r)
  85. assert_instance_of(IO, w)
  86. [
  87. Thread.start{
  88. w.print "abc"
  89. w.close
  90. },
  91. Thread.start{
  92. assert_equal("abc", r.read)
  93. r.close
  94. }
  95. ].each{|thr| thr.join}
  96. end
  97. def test_pipe_block
  98. x = nil
  99. ret = IO.pipe {|r, w|
  100. x = [r,w]
  101. assert_instance_of(IO, r)
  102. assert_instance_of(IO, w)
  103. [
  104. Thread.start do
  105. w.print "abc"
  106. w.close
  107. end,
  108. Thread.start do
  109. assert_equal("abc", r.read)
  110. end
  111. ].each{|thr| thr.join}
  112. assert(!r.closed?)
  113. assert(w.closed?)
  114. :foooo
  115. }
  116. assert_equal(:foooo, ret)
  117. assert(x[0].closed?)
  118. assert(x[1].closed?)
  119. end
  120. def test_pipe_block_close
  121. 4.times {|i|
  122. x = nil
  123. IO.pipe {|r, w|
  124. x = [r,w]
  125. r.close if (i&1) == 0
  126. w.close if (i&2) == 0
  127. }
  128. assert(x[0].closed?)
  129. assert(x[1].closed?)
  130. }
  131. end
  132. def test_gets_rs
  133. # default_rs
  134. pipe(proc do |w|
  135. w.print "aaa\nbbb\n"
  136. w.close
  137. end, proc do |r|
  138. assert_equal "aaa\n", r.gets
  139. assert_equal "bbb\n", r.gets
  140. assert_nil r.gets
  141. r.close
  142. end)
  143. # nil
  144. pipe(proc do |w|
  145. w.print "a\n\nb\n\n"
  146. w.close
  147. end, proc do |r|
  148. assert_equal "a\n\nb\n\n", r.gets(nil)
  149. assert_nil r.gets("")
  150. r.close
  151. end)
  152. # "\377"
  153. pipe(proc do |w|
  154. w.print "\377xyz"
  155. w.close
  156. end, proc do |r|
  157. r.binmode
  158. assert_equal("\377", r.gets("\377"), "[ruby-dev:24460]")
  159. r.close
  160. end)
  161. # ""
  162. pipe(proc do |w|
  163. w.print "a\n\nb\n\n"
  164. w.close
  165. end, proc do |r|
  166. assert_equal "a\n\n", r.gets(""), "[ruby-core:03771]"
  167. assert_equal "b\n\n", r.gets("")
  168. assert_nil r.gets("")
  169. r.close
  170. end)
  171. end
  172. def test_gets_limit_extra_arg
  173. pipe(proc do |w|
  174. w << "0123456789\n0123456789"
  175. w.close
  176. end, proc do |r|
  177. assert_equal("0123456789\n0", r.gets(nil, 12))
  178. assert_raise(TypeError) { r.gets(3,nil) }
  179. end)
  180. end
  181. # This test cause SEGV.
  182. def test_ungetc
  183. pipe(proc do |w|
  184. w.close
  185. end, proc do |r|
  186. s = "a" * 1000
  187. assert_raise(IOError, "[ruby-dev:31650]") { 200.times { r.ungetc s } }
  188. end)
  189. end
  190. def test_ungetbyte
  191. t = make_tempfile
  192. t.open
  193. t.binmode
  194. t.ungetbyte(0x41)
  195. assert_equal(-1, t.pos)
  196. assert_equal(0x41, t.getbyte)
  197. t.rewind
  198. assert_equal(0, t.pos)
  199. t.ungetbyte("qux")
  200. assert_equal(-3, t.pos)
  201. assert_equal("quxfoo\n", t.gets)
  202. assert_equal(4, t.pos)
  203. t.set_encoding("utf-8")
  204. t.ungetbyte(0x89)
  205. t.ungetbyte(0x8e)
  206. t.ungetbyte("\xe7")
  207. t.ungetbyte("\xe7\xb4\x85")
  208. assert_equal(-2, t.pos)
  209. assert_equal("\u7d05\u7389bar\n", t.gets)
  210. end
  211. def test_each_byte
  212. pipe(proc do |w|
  213. w << "abc def"
  214. w.close
  215. end, proc do |r|
  216. r.each_byte {|byte| break if byte == 32 }
  217. assert_equal("def", r.read, "[ruby-dev:31659]")
  218. end)
  219. end
  220. def test_each_byte_with_seek
  221. t = make_tempfile
  222. bug5119 = '[ruby-core:38609]'
  223. i = 0
  224. open(t.path) do |f|
  225. f.each_byte {i = f.pos}
  226. end
  227. assert_equal(12, i, bug5119)
  228. end
  229. def test_each_codepoint
  230. t = make_tempfile
  231. bug2959 = '[ruby-core:28650]'
  232. a = ""
  233. File.open(t, 'rt') {|f|
  234. f.each_codepoint {|c| a << c}
  235. }
  236. assert_equal("foo\nbar\nbaz\n", a, bug2959)
  237. end
  238. def test_rubydev33072
  239. t = make_tempfile
  240. path = t.path
  241. t.close!
  242. assert_raise(Errno::ENOENT, "[ruby-dev:33072]") do
  243. File.read(path, nil, nil, {})
  244. end
  245. end
  246. def test_copy_stream
  247. mkcdtmpdir {
  248. content = "foobar"
  249. File.open("src", "w") {|f| f << content }
  250. ret = IO.copy_stream("src", "dst")
  251. assert_equal(content.bytesize, ret)
  252. assert_equal(content, File.read("dst"))
  253. # overwrite by smaller file.
  254. content = "baz"
  255. File.open("src", "w") {|f| f << content }
  256. ret = IO.copy_stream("src", "dst")
  257. assert_equal(content.bytesize, ret)
  258. assert_equal(content, File.read("dst"))
  259. ret = IO.copy_stream("src", "dst", 2)
  260. assert_equal(2, ret)
  261. assert_equal(content[0,2], File.read("dst"))
  262. ret = IO.copy_stream("src", "dst", 0)
  263. assert_equal(0, ret)
  264. assert_equal("", File.read("dst"))
  265. ret = IO.copy_stream("src", "dst", nil, 1)
  266. assert_equal(content.bytesize-1, ret)
  267. assert_equal(content[1..-1], File.read("dst"))
  268. assert_raise(Errno::ENOENT) {
  269. IO.copy_stream("nodir/foo", "dst")
  270. }
  271. assert_raise(Errno::ENOENT) {
  272. IO.copy_stream("src", "nodir/bar")
  273. }
  274. pipe(proc do |w|
  275. ret = IO.copy_stream("src", w)
  276. assert_equal(content.bytesize, ret)
  277. w.close
  278. end, proc do |r|
  279. assert_equal(content, r.read)
  280. end)
  281. with_pipe {|r, w|
  282. w.close
  283. assert_raise(IOError) { IO.copy_stream("src", w) }
  284. }
  285. pipe_content = "abc"
  286. with_read_pipe(pipe_content) {|r|
  287. ret = IO.copy_stream(r, "dst")
  288. assert_equal(pipe_content.bytesize, ret)
  289. assert_equal(pipe_content, File.read("dst"))
  290. }
  291. with_read_pipe("abc") {|r1|
  292. assert_equal("a", r1.getc)
  293. pipe(proc do |w2|
  294. w2.sync = false
  295. w2 << "def"
  296. ret = IO.copy_stream(r1, w2)
  297. assert_equal(2, ret)
  298. w2.close
  299. end, proc do |r2|
  300. assert_equal("defbc", r2.read)
  301. end)
  302. }
  303. with_read_pipe("abc") {|r1|
  304. assert_equal("a", r1.getc)
  305. pipe(proc do |w2|
  306. w2.sync = false
  307. w2 << "def"
  308. ret = IO.copy_stream(r1, w2, 1)
  309. assert_equal(1, ret)
  310. w2.close
  311. end, proc do |r2|
  312. assert_equal("defb", r2.read)
  313. end)
  314. }
  315. with_read_pipe("abc") {|r1|
  316. assert_equal("a", r1.getc)
  317. pipe(proc do |w2|
  318. ret = IO.copy_stream(r1, w2)
  319. assert_equal(2, ret)
  320. w2.close
  321. end, proc do |r2|
  322. assert_equal("bc", r2.read)
  323. end)
  324. }
  325. with_read_pipe("abc") {|r1|
  326. assert_equal("a", r1.getc)
  327. pipe(proc do |w2|
  328. ret = IO.copy_stream(r1, w2, 1)
  329. assert_equal(1, ret)
  330. w2.close
  331. end, proc do |r2|
  332. assert_equal("b", r2.read)
  333. end)
  334. }
  335. with_read_pipe("abc") {|r1|
  336. assert_equal("a", r1.getc)
  337. pipe(proc do |w2|
  338. ret = IO.copy_stream(r1, w2, 0)
  339. assert_equal(0, ret)
  340. w2.close
  341. end, proc do |r2|
  342. assert_equal("", r2.read)
  343. end)
  344. }
  345. pipe(proc do |w1|
  346. w1 << "abc"
  347. w1 << "def"
  348. w1.close
  349. end, proc do |r1|
  350. assert_equal("a", r1.getc)
  351. pipe(proc do |w2|
  352. ret = IO.copy_stream(r1, w2)
  353. assert_equal(5, ret)
  354. w2.close
  355. end, proc do |r2|
  356. assert_equal("bcdef", r2.read)
  357. end)
  358. end)
  359. pipe(proc do |w|
  360. ret = IO.copy_stream("src", w, 1, 1)
  361. assert_equal(1, ret)
  362. w.close
  363. end, proc do |r|
  364. assert_equal(content[1,1], r.read)
  365. end)
  366. if have_nonblock?
  367. with_read_pipe("abc") {|r1|
  368. assert_equal("a", r1.getc)
  369. with_pipe {|r2, w2|
  370. begin
  371. w2.nonblock = true
  372. rescue Errno::EBADF
  373. skip "nonblocking IO for pipe is not implemented"
  374. break
  375. end
  376. s = w2.syswrite("a" * 100000)
  377. t = Thread.new { sleep 0.1; r2.read }
  378. ret = IO.copy_stream(r1, w2)
  379. w2.close
  380. assert_equal(2, ret)
  381. assert_equal("a" * s + "bc", t.value)
  382. }
  383. }
  384. end
  385. bigcontent = "abc" * 123456
  386. File.open("bigsrc", "w") {|f| f << bigcontent }
  387. ret = IO.copy_stream("bigsrc", "bigdst")
  388. assert_equal(bigcontent.bytesize, ret)
  389. assert_equal(bigcontent, File.read("bigdst"))
  390. File.unlink("bigdst")
  391. ret = IO.copy_stream("bigsrc", "bigdst", nil, 100)
  392. assert_equal(bigcontent.bytesize-100, ret)
  393. assert_equal(bigcontent[100..-1], File.read("bigdst"))
  394. File.unlink("bigdst")
  395. ret = IO.copy_stream("bigsrc", "bigdst", 30000, 100)
  396. assert_equal(30000, ret)
  397. assert_equal(bigcontent[100, 30000], File.read("bigdst"))
  398. File.open("bigsrc") {|f|
  399. begin
  400. assert_equal(0, f.pos)
  401. ret = IO.copy_stream(f, "bigdst", nil, 10)
  402. assert_equal(bigcontent.bytesize-10, ret)
  403. assert_equal(bigcontent[10..-1], File.read("bigdst"))
  404. assert_equal(0, f.pos)
  405. ret = IO.copy_stream(f, "bigdst", 40, 30)
  406. assert_equal(40, ret)
  407. assert_equal(bigcontent[30, 40], File.read("bigdst"))
  408. assert_equal(0, f.pos)
  409. rescue NotImplementedError
  410. #skip "pread(2) is not implemtented."
  411. end
  412. }
  413. with_pipe {|r, w|
  414. w.close
  415. assert_raise(IOError) { IO.copy_stream("src", w) }
  416. }
  417. megacontent = "abc" * 1234567
  418. File.open("megasrc", "w") {|f| f << megacontent }
  419. if have_nonblock?
  420. with_pipe {|r1, w1|
  421. with_pipe {|r2, w2|
  422. begin
  423. r1.nonblock = true
  424. w2.nonblock = true
  425. rescue Errno::EBADF
  426. skip "nonblocking IO for pipe is not implemented"
  427. end
  428. t1 = Thread.new { w1 << megacontent; w1.close }
  429. t2 = Thread.new { r2.read }
  430. ret = IO.copy_stream(r1, w2)
  431. assert_equal(megacontent.bytesize, ret)
  432. w2.close
  433. t1.join
  434. assert_equal(megacontent, t2.value)
  435. }
  436. }
  437. end
  438. with_pipe {|r1, w1|
  439. with_pipe {|r2, w2|
  440. t1 = Thread.new { w1 << megacontent; w1.close }
  441. t2 = Thread.new { r2.read }
  442. ret = IO.copy_stream(r1, w2)
  443. assert_equal(megacontent.bytesize, ret)
  444. w2.close
  445. t1.join
  446. assert_equal(megacontent, t2.value)
  447. }
  448. }
  449. with_pipe {|r, w|
  450. t = Thread.new { r.read }
  451. ret = IO.copy_stream("megasrc", w)
  452. assert_equal(megacontent.bytesize, ret)
  453. w.close
  454. assert_equal(megacontent, t.value)
  455. }
  456. }
  457. end
  458. def test_copy_stream_rbuf
  459. mkcdtmpdir {
  460. begin
  461. pipe(proc do |w|
  462. File.open("foo", "w") {|f| f << "abcd" }
  463. File.open("foo") {|f|
  464. f.read(1)
  465. assert_equal(3, IO.copy_stream(f, w, 10, 1))
  466. }
  467. w.close
  468. end, proc do |r|
  469. assert_equal("bcd", r.read)
  470. end)
  471. rescue NotImplementedError
  472. skip "pread(2) is not implemtented."
  473. end
  474. }
  475. end
  476. def with_socketpair
  477. s1, s2 = UNIXSocket.pair
  478. begin
  479. yield s1, s2
  480. ensure
  481. s1.close unless s1.closed?
  482. s2.close unless s2.closed?
  483. end
  484. end
  485. def test_copy_stream_socket
  486. return unless defined? UNIXSocket
  487. mkcdtmpdir {
  488. content = "foobar"
  489. File.open("src", "w") {|f| f << content }
  490. with_socketpair {|s1, s2|
  491. ret = IO.copy_stream("src", s1)
  492. assert_equal(content.bytesize, ret)
  493. s1.close
  494. assert_equal(content, s2.read)
  495. }
  496. bigcontent = "abc" * 123456
  497. File.open("bigsrc", "w") {|f| f << bigcontent }
  498. with_socketpair {|s1, s2|
  499. t = Thread.new { s2.read }
  500. ret = IO.copy_stream("bigsrc", s1)
  501. assert_equal(bigcontent.bytesize, ret)
  502. s1.close
  503. result = t.value
  504. assert_equal(bigcontent, result)
  505. }
  506. with_socketpair {|s1, s2|
  507. t = Thread.new { s2.read }
  508. ret = IO.copy_stream("bigsrc", s1, 10000)
  509. assert_equal(10000, ret)
  510. s1.close
  511. result = t.value
  512. assert_equal(bigcontent[0,10000], result)
  513. }
  514. File.open("bigsrc") {|f|
  515. assert_equal(0, f.pos)
  516. with_socketpair {|s1, s2|
  517. t = Thread.new { s2.read }
  518. ret = IO.copy_stream(f, s1, nil, 100)
  519. assert_equal(bigcontent.bytesize-100, ret)
  520. assert_equal(0, f.pos)
  521. s1.close
  522. result = t.value
  523. assert_equal(bigcontent[100..-1], result)
  524. }
  525. }
  526. File.open("bigsrc") {|f|
  527. assert_equal(bigcontent[0,100], f.read(100))
  528. assert_equal(100, f.pos)
  529. with_socketpair {|s1, s2|
  530. t = Thread.new { s2.read }
  531. ret = IO.copy_stream(f, s1)
  532. assert_equal(bigcontent.bytesize-100, ret)
  533. assert_equal(bigcontent.length, f.pos)
  534. s1.close
  535. result = t.value
  536. assert_equal(bigcontent[100..-1], result)
  537. }
  538. }
  539. megacontent = "abc" * 1234567
  540. File.open("megasrc", "w") {|f| f << megacontent }
  541. if have_nonblock?
  542. with_socketpair {|s1, s2|
  543. begin
  544. s1.nonblock = true
  545. rescue Errno::EBADF
  546. skip "nonblocking IO for pipe is not implemented"
  547. end
  548. t = Thread.new { s2.read }
  549. ret = IO.copy_stream("megasrc", s1)
  550. assert_equal(megacontent.bytesize, ret)
  551. s1.close
  552. result = t.value
  553. assert_equal(megacontent, result)
  554. }
  555. with_socketpair {|s1, s2|
  556. begin
  557. s1.nonblock = true
  558. rescue Errno::EBADF
  559. skip "nonblocking IO for pipe is not implemented"
  560. end
  561. trapping_usr1 do
  562. nr = 30
  563. begin
  564. pid = fork do
  565. s1.close
  566. IO.select([s2])
  567. Process.kill(:USR1, Process.ppid)
  568. s2.read
  569. end
  570. s2.close
  571. nr.times do
  572. assert_equal megacontent.bytesize, IO.copy_stream("megasrc", s1)
  573. end
  574. assert_equal(1, @usr1_rcvd)
  575. ensure
  576. s1.close
  577. _, status = Process.waitpid2(pid) if pid
  578. end
  579. assert status.success?, status.inspect
  580. end
  581. }
  582. end
  583. }
  584. end
  585. def test_copy_stream_strio
  586. src = StringIO.new("abcd")
  587. dst = StringIO.new
  588. ret = IO.copy_stream(src, dst)
  589. assert_equal(4, ret)
  590. assert_equal("abcd", dst.string)
  591. assert_equal(4, src.pos)
  592. end
  593. def test_copy_stream_strio_len
  594. src = StringIO.new("abcd")
  595. dst = StringIO.new
  596. ret = IO.copy_stream(src, dst, 3)
  597. assert_equal(3, ret)
  598. assert_equal("abc", dst.string)
  599. assert_equal(3, src.pos)
  600. end
  601. def test_copy_stream_strio_off
  602. src = StringIO.new("abcd")
  603. with_pipe {|r, w|
  604. assert_raise(ArgumentError) {
  605. IO.copy_stream(src, w, 3, 1)
  606. }
  607. }
  608. end
  609. def test_copy_stream_fname_to_strio
  610. mkcdtmpdir {
  611. File.open("foo", "w") {|f| f << "abcd" }
  612. src = "foo"
  613. dst = StringIO.new
  614. ret = IO.copy_stream(src, dst, 3)
  615. assert_equal(3, ret)
  616. assert_equal("abc", dst.string)
  617. }
  618. end
  619. def test_copy_stream_strio_to_fname
  620. mkcdtmpdir {
  621. # StringIO to filename
  622. src = StringIO.new("abcd")
  623. ret = IO.copy_stream(src, "fooo", 3)
  624. assert_equal(3, ret)
  625. assert_equal("abc", File.read("fooo"))
  626. assert_equal(3, src.pos)
  627. }
  628. end
  629. def test_copy_stream_io_to_strio
  630. mkcdtmpdir {
  631. # IO to StringIO
  632. File.open("bar", "w") {|f| f << "abcd" }
  633. File.open("bar") {|src|
  634. dst = StringIO.new
  635. ret = IO.copy_stream(src, dst, 3)
  636. assert_equal(3, ret)
  637. assert_equal("abc", dst.string)
  638. assert_equal(3, src.pos)
  639. }
  640. }
  641. end
  642. def test_copy_stream_strio_to_io
  643. mkcdtmpdir {
  644. # StringIO to IO
  645. src = StringIO.new("abcd")
  646. ret = File.open("baz", "w") {|dst|
  647. IO.copy_stream(src, dst, 3)
  648. }
  649. assert_equal(3, ret)
  650. assert_equal("abc", File.read("baz"))
  651. assert_equal(3, src.pos)
  652. }
  653. end
  654. class Rot13IO
  655. def initialize(io)
  656. @io = io
  657. end
  658. def readpartial(*args)
  659. ret = @io.readpartial(*args)
  660. ret.tr!('a-zA-Z', 'n-za-mN-ZA-M')
  661. ret
  662. end
  663. def write(str)
  664. @io.write(str.tr('a-zA-Z', 'n-za-mN-ZA-M'))
  665. end
  666. def to_io
  667. @io
  668. end
  669. end
  670. def test_copy_stream_io_to_rot13
  671. mkcdtmpdir {
  672. File.open("bar", "w") {|f| f << "vex" }
  673. File.open("bar") {|src|
  674. File.open("baz", "w") {|dst0|
  675. dst = Rot13IO.new(dst0)
  676. ret = IO.copy_stream(src, dst, 3)
  677. assert_equal(3, ret)
  678. }
  679. assert_equal("irk", File.read("baz"))
  680. }
  681. }
  682. end
  683. def test_copy_stream_rot13_to_io
  684. mkcdtmpdir {
  685. File.open("bar", "w") {|f| f << "flap" }
  686. File.open("bar") {|src0|
  687. src = Rot13IO.new(src0)
  688. File.open("baz", "w") {|dst|
  689. ret = IO.copy_stream(src, dst, 4)
  690. assert_equal(4, ret)
  691. }
  692. }
  693. assert_equal("sync", File.read("baz"))
  694. }
  695. end
  696. def test_copy_stream_rot13_to_rot13
  697. mkcdtmpdir {
  698. File.open("bar", "w") {|f| f << "bin" }
  699. File.open("bar") {|src0|
  700. src = Rot13IO.new(src0)
  701. File.open("baz", "w") {|dst0|
  702. dst = Rot13IO.new(dst0)
  703. ret = IO.copy_stream(src, dst, 3)
  704. assert_equal(3, ret)
  705. }
  706. }
  707. assert_equal("bin", File.read("baz"))
  708. }
  709. end
  710. def test_copy_stream_strio_flush
  711. with_pipe {|r, w|
  712. w.sync = false
  713. w.write "zz"
  714. src = StringIO.new("abcd")
  715. IO.copy_stream(src, w)
  716. t = Thread.new {
  717. w.close
  718. }
  719. assert_equal("zzabcd", r.read)
  720. t.join
  721. }
  722. end
  723. def test_copy_stream_strio_rbuf
  724. pipe(proc do |w|
  725. w << "abcd"
  726. w.close
  727. end, proc do |r|
  728. assert_equal("a", r.read(1))
  729. sio = StringIO.new
  730. IO.copy_stream(r, sio)
  731. assert_equal("bcd", sio.string)
  732. end)
  733. end
  734. def test_copy_stream_src_wbuf
  735. mkcdtmpdir {
  736. pipe(proc do |w|
  737. File.open("foe", "w+") {|f|
  738. f.write "abcd\n"
  739. f.rewind
  740. f.write "xy"
  741. IO.copy_stream(f, w)
  742. }
  743. assert_equal("xycd\n", File.read("foe"))
  744. w.close
  745. end, proc do |r|
  746. assert_equal("cd\n", r.read)
  747. r.close
  748. end)
  749. }
  750. end
  751. def test_copy_stream_dst_rbuf
  752. mkcdtmpdir {
  753. pipe(proc do |w|
  754. w << "xyz"
  755. w.close
  756. end, proc do |r|
  757. File.open("fom", "w+b") {|f|
  758. f.write "abcd\n"
  759. f.rewind
  760. assert_equal("abc", f.read(3))
  761. f.ungetc "c"
  762. IO.copy_stream(r, f)
  763. }
  764. assert_equal("abxyz", File.read("fom"))
  765. end)
  766. }
  767. end
  768. def safe_4
  769. t = Thread.new do
  770. $SAFE = 4
  771. yield
  772. end
  773. unless t.join(10)
  774. t.kill
  775. flunk("timeout in safe_4")
  776. end
  777. end
  778. def ruby(*args)
  779. args = ['-e', '$>.write($<.read)'] if args.empty?
  780. ruby = EnvUtil.rubybin
  781. f = IO.popen([ruby] + args, 'r+')
  782. yield(f)
  783. ensure
  784. f.close unless !f || f.closed?
  785. end
  786. def test_try_convert
  787. assert_equal(STDOUT, IO.try_convert(STDOUT))
  788. assert_equal(nil, IO.try_convert("STDOUT"))
  789. end
  790. def test_ungetc2
  791. f = false
  792. pipe(proc do |w|
  793. Thread.pass until f
  794. w.write("1" * 10000)
  795. w.close
  796. end, proc do |r|
  797. r.ungetc("0" * 10000)
  798. f = true
  799. assert_equal("0" * 10000 + "1" * 10000, r.read)
  800. end)
  801. end
  802. def test_write_non_writable
  803. with_pipe do |r, w|
  804. assert_raise(IOError) do
  805. r.write "foobarbaz"
  806. end
  807. end
  808. end
  809. def test_dup
  810. ruby do |f|
  811. f2 = f.dup
  812. f.puts "foo"
  813. f2.puts "bar"
  814. f.close_write
  815. f2.close_write
  816. assert_equal("foo\nbar\n", f.read)
  817. assert_equal("", f2.read)
  818. end
  819. end
  820. def test_dup_many
  821. ruby('-e', <<-'End') {|f|
  822. ok = 0
  823. a = []
  824. begin
  825. loop {a << IO.pipe}
  826. rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
  827. ok += 1
  828. end
  829. print "no" if ok != 1
  830. begin
  831. loop {a << [a[-1][0].dup, a[-1][1].dup]}
  832. rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
  833. ok += 1
  834. end
  835. print "no" if ok != 2
  836. print "ok"
  837. End
  838. assert_equal("ok", f.read)
  839. }
  840. end
  841. def test_inspect
  842. with_pipe do |r, w|
  843. assert_match(/^#<IO:fd \d+>$/, r.inspect)
  844. assert_raise(SecurityError) do
  845. safe_4 { r.inspect }
  846. end
  847. end
  848. end
  849. def test_readpartial
  850. pipe(proc do |w|
  851. w.write "foobarbaz"
  852. w.close
  853. end, proc do |r|
  854. assert_raise(ArgumentError) { r.readpartial(-1) }
  855. assert_equal("fooba", r.readpartial(5))
  856. r.readpartial(5, s = "")
  857. assert_equal("rbaz", s)
  858. end)
  859. end
  860. def test_readpartial_lock
  861. with_pipe do |r, w|
  862. s = ""
  863. t = Thread.new { r.readpartial(5, s) }
  864. Thread.pass until s.size == 5
  865. assert_raise(RuntimeError) { s.clear }
  866. w.write "foobarbaz"
  867. w.close
  868. assert_equal("fooba", t.value)
  869. end
  870. end
  871. def test_readpartial_pos
  872. mkcdtmpdir {
  873. open("foo", "w") {|f| f << "abc" }
  874. open("foo") {|f|
  875. f.seek(0)
  876. assert_equal("ab", f.readpartial(2))
  877. assert_equal(2, f.pos)
  878. }
  879. }
  880. end
  881. def test_read
  882. pipe(proc do |w|
  883. w.write "foobarbaz"
  884. w.close
  885. end, proc do |r|
  886. assert_raise(ArgumentError) { r.read(-1) }
  887. assert_equal("fooba", r.read(5))
  888. r.read(nil, s = "")
  889. assert_equal("rbaz", s)
  890. end)
  891. end
  892. def test_read_lock
  893. with_pipe do |r, w|
  894. s = ""
  895. t = Thread.new { r.read(5, s) }
  896. Thread.pass until s.size == 5
  897. assert_raise(RuntimeError) { s.clear }
  898. w.write "foobarbaz"
  899. w.close
  900. assert_equal("fooba", t.value)
  901. end
  902. end
  903. def test_write_nonblock
  904. skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
  905. pipe(proc do |w|
  906. w.write_nonblock(1)
  907. w.close
  908. end, proc do |r|
  909. assert_equal("1", r.read)
  910. end)
  911. end
  912. def test_read_nonblock_error
  913. return if !have_nonblock?
  914. skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
  915. with_pipe {|r, w|
  916. begin
  917. r.read_nonblock 4096
  918. rescue Errno::EWOULDBLOCK
  919. assert_kind_of(IO::WaitReadable, $!)
  920. end
  921. }
  922. end
  923. def test_write_nonblock_error
  924. return if !have_nonblock?
  925. skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
  926. with_pipe {|r, w|
  927. begin
  928. loop {
  929. w.write_nonblock "a"*100000
  930. }
  931. rescue Errno::EWOULDBLOCK
  932. assert_kind_of(IO::WaitWritable, $!)
  933. end
  934. }
  935. end
  936. def test_gets
  937. pipe(proc do |w|
  938. w.write "foobarbaz"
  939. w.close
  940. end, proc do |r|
  941. assert_equal("", r.gets(0))
  942. assert_equal("foobarbaz", s = r.gets(9))
  943. end)
  944. end
  945. def test_close_read
  946. ruby do |f|
  947. f.close_read
  948. f.write "foobarbaz"
  949. assert_raise(IOError) { f.read }
  950. end
  951. end
  952. def test_close_read_pipe
  953. with_pipe do |r, w|
  954. r.close_read
  955. assert_raise(Errno::EPIPE) { w.write "foobarbaz" }
  956. end
  957. end
  958. def test_close_read_security_error
  959. with_pipe do |r, w|
  960. assert_raise(SecurityError) do
  961. safe_4 { r.close_read }
  962. end
  963. end
  964. end
  965. def test_close_read_non_readable
  966. with_pipe do |r, w|
  967. assert_raise(IOError) do
  968. w.close_read
  969. end
  970. end
  971. end
  972. def test_close_write
  973. ruby do |f|
  974. f.write "foobarbaz"
  975. f.close_write
  976. assert_equal("foobarbaz", f.read)
  977. end
  978. end
  979. def test_close_write_security_error
  980. with_pipe do |r, w|
  981. assert_raise(SecurityError) do
  982. safe_4 { r.close_write }
  983. end
  984. end
  985. end
  986. def test_close_write_non_readable
  987. with_pipe do |r, w|
  988. assert_raise(IOError) do
  989. r.close_write
  990. end
  991. end
  992. end
  993. def test_pid
  994. r, w = IO.pipe
  995. assert_equal(nil, r.pid)
  996. assert_equal(nil, w.pid)
  997. pipe = IO.popen(EnvUtil.rubybin, "r+")
  998. pid1 = pipe.pid
  999. pipe.puts "p $$"
  1000. pipe.close_write
  1001. pid2 = pipe.read.chomp.to_i
  1002. assert_equal(pid2, pid1)
  1003. assert_equal(pid2, pipe.pid)
  1004. pipe.close
  1005. assert_raise(IOError) { pipe.pid }
  1006. end
  1007. def make_tempfile
  1008. t = Tempfile.new("test_io")
  1009. t.binmode
  1010. t.puts "foo"
  1011. t.puts "bar"
  1012. t.puts "baz"
  1013. t.close
  1014. t
  1015. end
  1016. def test_set_lineno
  1017. t = make_tempfile
  1018. ruby("-e", <<-SRC, t.path) do |f|
  1019. open(ARGV[0]) do |f|
  1020. p $.
  1021. f.gets; p $.
  1022. f.gets; p $.
  1023. f.lineno = 1000; p $.
  1024. f.gets; p $.
  1025. f.gets; p $.
  1026. f.rewind; p $.
  1027. f.gets; p $.
  1028. f.gets; p $.
  1029. f.gets; p $.
  1030. f.gets; p $.
  1031. end
  1032. SRC
  1033. assert_equal("0,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
  1034. end
  1035. pipe(proc do |w|
  1036. w.puts "foo"
  1037. w.puts "bar"
  1038. w.puts "baz"
  1039. w.close
  1040. end, proc do |r|
  1041. r.gets; assert_equal(1, $.)
  1042. r.gets; assert_equal(2, $.)
  1043. r.lineno = 1000; assert_equal(2, $.)
  1044. r.gets; assert_equal(1001, $.)
  1045. r.gets; assert_equal(1001, $.)
  1046. end)
  1047. end
  1048. def test_readline
  1049. pipe(proc do |w|
  1050. w.puts "foo"
  1051. w.puts "bar"
  1052. w.puts "baz"
  1053. w.close
  1054. end, proc do |r|
  1055. r.readline; assert_equal(1, $.)
  1056. r.readline; assert_equal(2, $.)
  1057. r.lineno = 1000; assert_equal(2, $.)
  1058. r.readline; assert_equal(1001, $.)
  1059. assert_raise(EOFError) { r.readline }
  1060. end)
  1061. end
  1062. def test_each_char
  1063. pipe(proc do |w|
  1064. w.puts "foo"
  1065. w.puts "bar"
  1066. w.puts "baz"
  1067. w.close
  1068. end, proc do |r|
  1069. a = []
  1070. r.each_char {|c| a << c }
  1071. assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a)
  1072. end)
  1073. end
  1074. def test_lines
  1075. pipe(proc do |w|
  1076. w.puts "foo"
  1077. w.puts "bar"
  1078. w.puts "baz"
  1079. w.close
  1080. end, proc do |r|
  1081. e = r.lines
  1082. assert_equal("foo\n", e.next)
  1083. assert_equal("bar\n", e.next)
  1084. assert_equal("baz\n", e.next)
  1085. assert_raise(StopIteration) { e.next }
  1086. end)
  1087. end
  1088. def test_bytes
  1089. pipe(proc do |w|
  1090. w.binmode
  1091. w.puts "foo"
  1092. w.puts "bar"
  1093. w.puts "baz"
  1094. w.close
  1095. end, proc do |r|
  1096. e = r.bytes
  1097. (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
  1098. assert_equal(c.ord, e.next)
  1099. end
  1100. assert_raise(StopIteration) { e.next }
  1101. end)
  1102. end
  1103. def test_chars
  1104. pipe(proc do |w|
  1105. w.puts "foo"
  1106. w.puts "bar"
  1107. w.puts "baz"
  1108. w.close
  1109. end, proc do |r|
  1110. e = r.chars
  1111. (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
  1112. assert_equal(c, e.next)
  1113. end
  1114. assert_raise(StopIteration) { e.next }
  1115. end)
  1116. end
  1117. def test_readbyte
  1118. pipe(proc do |w|
  1119. w.binmode
  1120. w.puts "foo"
  1121. w.puts "bar"
  1122. w.puts "baz"
  1123. w.close
  1124. end, proc do |r|
  1125. r.binmode
  1126. (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
  1127. assert_equal(c.ord, r.readbyte)
  1128. end
  1129. assert_raise(EOFError) { r.readbyte }
  1130. end)
  1131. end
  1132. def test_readchar
  1133. pipe(proc do |w|
  1134. w.puts "foo"
  1135. w.puts "bar"
  1136. w.puts "baz"
  1137. w.close
  1138. end, proc do |r|
  1139. (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
  1140. assert_equal(c, r.readchar)
  1141. end
  1142. assert_raise(EOFError) { r.readchar }
  1143. end)
  1144. end
  1145. def test_close_on_exec
  1146. skip "IO\#close_on_exec is not implemented." unless have_close_on_exec?
  1147. ruby do |f|
  1148. assert_equal(false, f.close_on_exec?)
  1149. f.close_on_exec = true
  1150. assert_equal(true, f.close_on_exec?)
  1151. f.close_on_exec = false
  1152. assert_equal(false, f.close_on_exec?)
  1153. end
  1154. with_pipe do |r, w|
  1155. assert_equal(false, r.close_on_exec?)
  1156. r.close_on_exec = true
  1157. assert_equal(true, r.close_on_exec?)
  1158. r.close_on_exec = false
  1159. assert_equal(false, r.close_on_exec?)
  1160. assert_equal(false, w.close_on_exec?)
  1161. w.close_on_exec = true
  1162. assert_equal(true, w.close_on_exec?)
  1163. w.close_on_exec = false
  1164. assert_equal(false, w.close_on_exec?)
  1165. end
  1166. end
  1167. def test_close_security_error
  1168. with_pipe do |r, w|
  1169. assert_raise(SecurityError) do
  1170. safe_4 { r.close }
  1171. end
  1172. end
  1173. end
  1174. def test_pos
  1175. t = make_tempfile
  1176. open(t.path, IO::RDWR|IO::CREAT|IO::TRUNC, 0600) do |f|
  1177. f.write "Hello"
  1178. assert_equal(5, f.pos)
  1179. end
  1180. open(t.path, IO::RDWR|IO::CREAT|IO::TRUNC, 0600) do |f|
  1181. f.sync = true
  1182. f.read
  1183. f.write "Hello"
  1184. assert_equal(5, f.pos)
  1185. end
  1186. end
  1187. def test_pos_with_getc
  1188. bug6179 = '[ruby-core:43497]'
  1189. t = make_tempfile
  1190. ["", "t", "b"].each do |mode|
  1191. open(t.path, "w#{mode}") do |f|
  1192. f.write "0123456789\n"
  1193. end
  1194. open(t.path, "r#{mode}") do |f|
  1195. assert_equal 0, f.pos, "mode=r#{mode}"
  1196. assert_equal '0', f.getc, "mode=r#{mode}"
  1197. assert_equal 1, f.pos, "mode=r#{mode}"
  1198. assert_equal '1', f.getc, "mode=r#{mode}"
  1199. assert_equal 2, f.pos, "mode=r#{mode}"
  1200. assert_equal '2', f.getc, "mode=r#{mode}"
  1201. assert_equal 3, f.pos, "mode=r#{mode}"
  1202. assert_equal '3', f.getc, "mode=r#{mode}"
  1203. assert_equal 4, f.pos, "mode=r#{mode}"
  1204. assert_equal '4', f.getc, "mode=r#{mode}"
  1205. end
  1206. end
  1207. end
  1208. def test_sysseek
  1209. t = make_tempfile
  1210. open(t.path) do |f|
  1211. f.sysseek(-4, IO::SEEK_END)
  1212. assert_equal("baz\n", f.read)
  1213. end
  1214. open(t.path) do |f|
  1215. a = [f.getc, f.getc, f.getc]
  1216. a.reverse_each {|c| f.ungetc c }
  1217. assert_raise(IOError) { f.sysseek(1) }
  1218. end
  1219. end
  1220. def test_syswrite
  1221. t = make_tempfile
  1222. open(t.path, "w") do |f|
  1223. o = Object.new
  1224. def o.to_s; "FOO\n"; end
  1225. f.syswrite(o)
  1226. end
  1227. assert_equal("FOO\n", File.read(t.path))
  1228. end
  1229. def test_sysread
  1230. t = make_tempfile
  1231. open(t.path) do |f|
  1232. a = [f.getc, f.getc, f.getc]
  1233. a.reverse_each {|c| f.ungetc c }
  1234. assert_raise(IOError) { f.sysread(1) }
  1235. end
  1236. end
  1237. def test_flag
  1238. t = make_tempfile
  1239. assert_raise(ArgumentError) do
  1240. open(t.path, "z") { }
  1241. end
  1242. assert_raise(ArgumentError) do
  1243. open(t.path, "rr") { }
  1244. end
  1245. end
  1246. def test_sysopen
  1247. t = make_tempfile
  1248. fd = IO.sysopen(t.path)
  1249. assert_kind_of(Integer, fd)
  1250. f = IO.for_fd(fd)
  1251. assert_equal("foo\nbar\nbaz\n", f.read)
  1252. f.close
  1253. fd = IO.sysopen(t.path, "w", 0666)
  1254. assert_kind_of(Integer, fd)
  1255. if defined?(Fcntl::F_GETFL)
  1256. f = IO.for_fd(fd)
  1257. else
  1258. f = IO.for_fd(fd, 0666)
  1259. end
  1260. f.write("FOO\n")
  1261. f.close
  1262. fd = IO.sysopen(t.path, "r")
  1263. assert_kind_of(Integer, fd)
  1264. f = IO.for_fd(fd)
  1265. assert_equal("FOO\n", f.read)
  1266. f.close
  1267. end
  1268. def try_fdopen(fd, autoclose = true, level = 100)
  1269. if level > 0
  1270. f = try_fdopen(fd, autoclose, level - 1)
  1271. GC.start
  1272. f
  1273. else
  1274. WeakRef.new(IO.for_fd(fd, autoclose: autoclose))
  1275. end
  1276. end
  1277. def test_autoclose
  1278. feature2250 = '[ruby-core:26222]'
  1279. pre = 'ft2250'
  1280. t = Tempfile.new(pre)
  1281. f = IO.for_fd(t.fileno)
  1282. assert_equal(true, f.autoclose?)
  1283. f.autoclose = false
  1284. assert_equal(false, f.autoclose?)
  1285. f.close
  1286. assert_nothing_raised(Errno::EBADF, feature2250) {t.close}
  1287. t.open
  1288. f = IO.for_fd(t.fileno, autoclose: false)
  1289. assert_equal(false, f.autoclose?)
  1290. f.autoclose = true
  1291. assert_equal(true, f.autoclose?)
  1292. f.close
  1293. assert_raise(Errno::EBADF, feature2250) {t.close}
  1294. end
  1295. def test_autoclose_true_closed_by_finalizer
  1296. feature2250 = '[ruby-core:26222]'
  1297. pre = 'ft2250'
  1298. t = Tempfile.new(pre)
  1299. w = try_fdopen(t.fileno)
  1300. begin
  1301. w.close
  1302. begin
  1303. t.close
  1304. rescue Errno::EBADF
  1305. end
  1306. skip "expect IO object was GC'ed but not recycled yet"
  1307. rescue WeakRef::RefError
  1308. assert_raise(Errno::EBADF, feature2250) {t.close}
  1309. end
  1310. end
  1311. def test_autoclose_false_closed_by_finalizer
  1312. feature2250 = '[ruby-core:26222]'
  1313. pre = 'ft2250'
  1314. t = Tempfile.new(pre)
  1315. w = try_fdopen(t.fileno, false)
  1316. begin
  1317. w.close
  1318. t.close
  1319. skip "expect IO object was GC'ed but not recycled yet"
  1320. rescue WeakRef::RefError
  1321. assert_nothing_raised(Errno::EBADF, feature2250) {t.close}
  1322. end
  1323. end
  1324. def test_open_redirect
  1325. o = Object.new
  1326. def o.to_open; self; end
  1327. assert_equal(o, open(o))
  1328. o2 = nil
  1329. open(o) do |f|
  1330. o2 = f
  1331. end
  1332. assert_equal(o, o2)
  1333. end
  1334. def test_open_pipe
  1335. open("|" + EnvUtil.rubybin, "r+") do |f|
  1336. f.puts "puts 'foo'"
  1337. f.close_write
  1338. assert_equal("foo\n", f.read)
  1339. end
  1340. end
  1341. def test_reopen
  1342. t = make_tempfile
  1343. with_pipe do |r, w|
  1344. assert_raise(SecurityError) do
  1345. safe_4 { r.reopen(t.path) }
  1346. end
  1347. end
  1348. open(__FILE__) do |f|
  1349. f.gets
  1350. assert_nothing_raised {
  1351. f.reopen(t.path)
  1352. assert_equal("foo\n", f.gets)
  1353. }
  1354. end
  1355. open(__FILE__) do |f|
  1356. f.gets
  1357. f2 = open(t.path)
  1358. begin
  1359. f2.gets
  1360. assert_nothing_raised {
  1361. f.reopen(f2)
  1362. assert_equal("bar\n", f.gets, '[ruby-core:24240]')
  1363. }
  1364. ensure
  1365. f2.close
  1366. end
  1367. end
  1368. open(__FILE__) do |f|
  1369. f2 = open(t.path)
  1370. begin
  1371. f.reopen(f2)
  1372. assert_equal("foo\n", f.gets)
  1373. assert_equal("bar\n", f.gets)
  1374. f.reopen(f2)
  1375. assert_equal("baz\n", f.gets, '[ruby-dev:39479]')
  1376. ensure
  1377. f2.close
  1378. end
  1379. end
  1380. end
  1381. def test_reopen_inherit
  1382. mkcdtmpdir {
  1383. system(EnvUtil.rubybin, '-e', <<"End")
  1384. f = open("out", "w")
  1385. STDOUT.reopen(f)
  1386. STDERR.reopen(f)
  1387. system(#{EnvUtil.rubybin.dump}, '-e', 'STDOUT.print "out"')
  1388. system(#{EnvUtil.rubybin.dump}, '-e', 'STDERR.print "err"')
  1389. End
  1390. assert_equal("outerr", File.read("out"))
  1391. }
  1392. end
  1393. def test_foreach
  1394. a = []
  1395. IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
  1396. assert_equal(["foo\n", "bar\n", "baz\n"], a)
  1397. t = make_tempfile
  1398. a = []
  1399. IO.foreach(t.path) {|x| a << x }
  1400. assert_equal(["foo\n", "bar\n", "baz\n"], a)
  1401. a = []
  1402. IO.foreach(t.path, {:mode => "r" }) {|x| a << x }
  1403. assert_equal(["foo\n", "bar\n", "baz\n"], a)
  1404. a = []
  1405. IO.foreach(t.path, {:open_args => [] }) {|x| a << x }
  1406. assert_equal(["foo\n", "bar\n", "baz\n"], a)
  1407. a = []
  1408. IO.foreach(t.path, {:open_args => ["r"] }) {|x| a << x }
  1409. assert_equal(["foo\n", "bar\n", "baz\n"], a)
  1410. a = []
  1411. IO.foreach(t.path, "b") {|x| a << x }
  1412. assert_equal(["foo\nb", "ar\nb", "az\n"], a)
  1413. a = []
  1414. IO.foreach(t.path, 3) {|x| a << x }
  1415. assert_equal(["foo", "\n", "bar", "\n", "baz", "\n"], a)
  1416. a = []
  1417. IO.foreach(t.path, "b", 3) {|x| a << x }
  1418. assert_equal(["foo", "\nb", "ar\n", "b", "az\n"], a)
  1419. bug = '[ruby-dev:31525]'
  1420. assert_raise(ArgumentError, bug) {IO.foreach}
  1421. a = nil
  1422. assert_nothing_raised(ArgumentError, bug) {a = IO.foreach(t.path).to_a}
  1423. assert_equal(["foo\n", "bar\n", "baz\n"], a, bug)
  1424. bug6054 = '[ruby-dev:45267]'
  1425. e = assert_raise(IOError, bug6054) {IO.foreach(t.path, mode:"w").next}
  1426. assert_match(/not opened for reading/, e.message, bug6054)
  1427. end
  1428. def test_s_readlines
  1429. t = make_tempfile
  1430. assert_equal(["foo\n", "bar\n", "baz\n"], IO.readlines(t.path))
  1431. assert_equal(["foo\nb", "ar\nb", "az\n"], IO.readlines(t.path, "b"))
  1432. assert_equal(["fo", "o\n", "ba", "r\n", "ba", "z\n"], IO.readlines(t.path, 2))
  1433. assert_equal(["fo", "o\n", "b", "ar", "\nb", "az", "\n"], IO.readlines(t.path, "b", 2))
  1434. end
  1435. def test_printf
  1436. pipe(proc do |w|
  1437. printf(w, "foo %s baz\n", "bar")
  1438. w.close_write
  1439. end, proc do |r|
  1440. assert_equal("foo bar baz\n", r.read)
  1441. end)
  1442. end
  1443. def test_print
  1444. t = make_tempfile
  1445. assert_in_out_err(["-", t.path], "print while $<.gets", %w(foo bar baz), [])
  1446. end
  1447. def test_print_separators
  1448. $, = ':'
  1449. $\ = "\n"
  1450. pipe(proc do |w|
  1451. w.print('a')
  1452. w.print('a','b','c')
  1453. w.close
  1454. end, proc do |r|
  1455. assert_equal("a\n", r.gets)
  1456. assert_equal("a:b:c\n", r.gets)
  1457. assert_nil r.gets
  1458. r.close
  1459. end)
  1460. ensure
  1461. $, = nil
  1462. $\ = nil
  1463. end
  1464. def test_putc
  1465. pipe(proc do |w|
  1466. w.putc "A"
  1467. w.putc "BC"
  1468. w.putc 68
  1469. w.close_write
  1470. end, proc do |r|
  1471. assert_equal("ABD", r.read)
  1472. end)
  1473. assert_in_out_err([], "putc 65", %w(A), [])
  1474. end
  1475. def test_puts_recursive_array
  1476. a = ["foo"]
  1477. a << a
  1478. pipe(proc do |w|
  1479. w.puts a
  1480. w.close
  1481. end, proc do |r|
  1482. assert_equal("foo\n[...]\n", r.read)
  1483. end)
  1484. end
  1485. def test_display
  1486. pipe(proc do |w|
  1487. "foo".display(w)
  1488. w.close
  1489. end, proc do |r|
  1490. assert_equal("foo", r.read)
  1491. end)
  1492. assert_in_out_err([], "'foo'.display", %w(foo), [])
  1493. end
  1494. def test_set_stdout
  1495. assert_raise(TypeError) { $> = Object.new }
  1496. assert_in_out_err([], "$> = $stderr\nputs 'foo'", [], %w(foo))
  1497. end
  1498. def test_initialize
  1499. return unless defined?(Fcntl::F_GETFL)
  1500. t = make_tempfile
  1501. fd = IO.sysopen(t.path, "w")
  1502. assert_kind_of(Integer, fd)
  1503. %w[r r+ w+ a+].each do |mode|
  1504. assert_raise(Errno::EINVAL, "#{mode} [ruby-dev:38571]") {IO.new(fd, mode)}
  1505. end
  1506. f = IO.new(fd, "w")
  1507. f.write("FOO\n")
  1508. f.close
  1509. assert_equal("FOO\n", File.read(t.path))
  1510. end
  1511. def test_reinitialize
  1512. t = make_tempfile
  1513. f = open(t.path)
  1514. begin
  1515. assert_raise(RuntimeError) do
  1516. f.instance_eval { initialize }
  1517. end
  1518. ensure
  1519. f.close
  1520. end
  1521. end
  1522. def test_new_with_block
  1523. assert_in_out_err([], "r, w = IO.pipe; IO.new(r) {}", [], /^.+$/)
  1524. end
  1525. def test_readline2
  1526. assert_in_out_err(["-e", <<-SRC], "foo\nbar\nbaz\n", %w(foo bar baz end), [])
  1527. puts readline
  1528. puts readline
  1529. puts readline
  1530. begin
  1531. puts readline
  1532. rescue EOFError
  1533. puts "end"
  1534. end
  1535. SRC
  1536. end
  1537. def test_readlines
  1538. assert_in_out_err(["-e", "p readlines"], "foo\nbar\nbaz\n",
  1539. ["[\"foo\\n\", \"bar\\n\", \"baz\\n\"]"], [])
  1540. end
  1541. def test_s_read
  1542. t = make_tempfile
  1543. assert_equal("foo\nbar\nbaz\n", File.read(t.path))
  1544. assert_equal("foo\nba", File.read(t.path, 6))
  1545. assert_equal("bar\n", File.read(t.path, 4, 4))
  1546. end
  1547. def test_uninitialized
  1548. assert_raise(IOError) { IO.allocate.print "" }
  1549. end
  1550. def test_nofollow
  1551. # O_NOFOLLOW is not standard.
  1552. return if /freebsd|linux/ !~ RUBY_PLATFORM
  1553. return unless defined? File::NOFOLLOW
  1554. mkcdtmpdir {
  1555. open("file", "w") {|f| f << "content" }
  1556. begin
  1557. File.symlink("file", "slnk")
  1558. rescue NotImplementedError
  1559. return
  1560. end
  1561. assert_raise(Errno::EMLINK, Errno::ELOOP) {
  1562. open("slnk", File::RDONLY|File::NOFOLLOW) {}
  1563. }
  1564. assert_raise(Errno::EMLINK, Errno::ELOOP) {
  1565. File.foreach("slnk", :open_args=>[File::RDONLY|File::NOFOLLOW]) {}
  1566. }
  1567. }
  1568. end
  1569. def test_tainted
  1570. t = make_tempfile
  1571. assert(File.read(t.path, 4).tainted?, '[ruby-dev:38826]')
  1572. assert(File.open(t.path) {|f| f.read(4)}.tainted?, '[ruby-dev:38826]')
  1573. end
  1574. def test_binmode_after_closed
  1575. t = make_tempfile
  1576. assert_raise(IOError) {t.binmode}
  1577. end
  1578. def test_threaded_flush
  1579. bug3585 = '[ruby-core:31348]'
  1580. src = %q{\
  1581. t = Thread.new { sleep 3 }
  1582. Thread.new {sleep 1; t.kill; p 'hi!'}
  1583. t.join
  1584. }.gsub(/^\s+/, '')
  1585. 10.times.map do
  1586. Thread.start do
  1587. assert_in_out_err([], src) {|stdout, stderr|
  1588. assert_no_match(/hi.*hi/, stderr.join)
  1589. }
  1590. end
  1591. end.each {|th| th.join}
  1592. end
  1593. def test_flush_in_finalizer1
  1594. require 'tempfile'
  1595. bug3910 = '[ruby-dev:42341]'
  1596. t = Tempfile.new("bug3910")
  1597. path = t.path
  1598. t.close
  1599. fds = []
  1600. assert_nothing_raised(TypeError, bug3910) do
  1601. 500.times {
  1602. f = File.open(path, "w")
  1603. fds << f.fileno
  1604. f.print "hoge"
  1605. }
  1606. end
  1607. ensure
  1608. GC.start
  1609. end
  1610. def test_flush_in_finalizer2
  1611. require 'tempfile'
  1612. bug3910 = '[ruby-dev:42341]'
  1613. t = Tempfile.new("bug3910")
  1614. path = t.path
  1615. t.close
  1616. 1.times do
  1617. io = open(path,"w")
  1618. io.print "hoge"
  1619. end
  1620. assert_nothing_raised(TypeError, bug3910) do
  1621. GC.start
  1622. end
  1623. end
  1624. def test_readlines_limit_0
  1625. bug4024 = '[ruby-dev:42538]'
  1626. t = make_tempfile
  1627. open(t.path, "r") do |io|
  1628. assert_raise(ArgumentError, bug4024) do
  1629. io.readlines(0)
  1630. end
  1631. end
  1632. end
  1633. def test_each_line_limit_0
  1634. bug4024 = '[ruby-dev:42538]'
  1635. t = make_tempfile
  1636. open(t.path, "r") do |io|
  1637. assert_raise(ArgumentError, bug4024) do
  1638. io.each_line(0).next
  1639. end
  1640. end
  1641. end
  1642. def test_advise
  1643. t = make_tempfile
  1644. assert_raise(ArgumentError, "no arguments") { t.advise }
  1645. %w{normal random sequential willneed dontneed noreuse}.map(&:to_sym).each do |adv|
  1646. [[0,0], [0, 20], [400, 2]].each do |offset, len|
  1647. open(make_tempfile.path) do |t|
  1648. assert_equal(t.advise(adv, offset, len), nil)
  1649. assert_raise(ArgumentError, "superfluous arguments") do
  1650. t.advise(adv, offset, len, offset)
  1651. end
  1652. assert_raise(TypeError, "wrong type for first argument") do
  1653. t.advise(adv.to_s, offset, len)
  1654. end
  1655. assert_raise(TypeError, "wrong type for last argument") do
  1656. t.advise(adv, offset, Array(len))
  1657. end
  1658. assert_raise(RangeError, "last argument too big") do
  1659. t.advise(adv, offset, 9999e99)
  1660. end
  1661. end
  1662. assert_raise(IOError, "closed file") do
  1663. make_tempfile.advise(adv.to_sym, offset, len)
  1664. end
  1665. end
  1666. end
  1667. end
  1668. def test_invalid_advise
  1669. feature4204 = '[ruby-dev:42887]'
  1670. t = make_tempfile
  1671. %w{Normal rand glark will_need zzzzzzzzzzzz \u2609}.map(&:to_sym).each do |adv|
  1672. [[0,0], [0, 20], [400, 2]].each do |offset, len|
  1673. open(make_tempfile.path) do |t|
  1674. assert_raise(NotImplementedError, feature4204) { t.advise(adv, offset, len) }
  1675. end
  1676. end
  1677. end
  1678. end
  1679. def test_fcntl_lock
  1680. return if /x86_64-linux/ !~ RUBY_PLATFORM # A binary form of struct flock depend on platform
  1681. pad=0
  1682. Tempfile.open(self.class.name) do |f|
  1683. r, w = IO.pipe
  1684. pid = fork do
  1685. r.close
  1686. lock = [Fcntl::F_WRLCK, IO::SEEK_SET, pad, 12, 34, 0].pack("s!s!i!L!L!i!")
  1687. f.fcntl Fcntl::F_SETLKW, lock
  1688. w.syswrite "."
  1689. sleep
  1690. end
  1691. w.close
  1692. assert_equal ".", r.read(1)
  1693. r.close
  1694. pad = 0
  1695. getlock = [Fcntl::F_WRLCK, 0, pad, 0, 0, 0].pack("s!s!i!L!L!i!")
  1696. f.fcntl Fcntl::F_GETLK, getlock
  1697. ptype, whence, pad, start, len, lockpid = getlock.unpack("s!s!i!L!L!i!")
  1698. assert_equal(ptype, Fcntl::F_WRLCK)
  1699. assert_equal(whence, IO::SEEK_SET)
  1700. assert_equal(start, 12)
  1701. assert_equal(len, 34)
  1702. assert_equal(pid, lockpid)
  1703. Process.kill :TERM, pid
  1704. Process.waitpid2(pid)
  1705. end
  1706. end
  1707. def test_cross_thread_close_fd
  1708. skip "cross thread close causes hung-up if pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
  1709. with_pipe do |r,w|
  1710. read_thread = Thread.new do
  1711. begin
  1712. r.read(1)
  1713. rescue => e
  1714. e
  1715. end
  1716. end
  1717. sleep(0.1) until read_thread.stop?
  1718. r.close
  1719. read_thread.join
  1720. assert_kind_of(IOError, read_thread.value)
  1721. end
  1722. end
  1723. def test_cross_thread_close_stdio
  1724. with_pipe do |r,w|
  1725. pid = fork do
  1726. $stdin.reopen(r)
  1727. r.close
  1728. read_thread = Thread.new do
  1729. begin
  1730. $stdin.read(1)
  1731. rescue => e
  1732. e
  1733. end
  1734. end
  1735. sleep(0.1) until read_thread.stop?
  1736. $stdin.close
  1737. read_thread.join
  1738. exit(IOError === read_thread.value)
  1739. end
  1740. assert Process.waitpid2(pid)[1].success?
  1741. end
  1742. rescue NotImplementedError
  1743. end
  1744. def test_open_mode
  1745. feature4742 = "[ruby-core:36338]"
  1746. bug6055 = '[ruby-dev:45268]'
  1747. mkcdtmpdir do
  1748. assert_not_nil(f = File.open('symbolic', 'w'))
  1749. f.close
  1750. assert_not_nil(f = File.open('numeric', File::WRONLY|File::TRUNC|File::CREAT))
  1751. f.close
  1752. assert_not_nil(f = File.open('hash-symbolic', :mode => 'w'))
  1753. f.close
  1754. assert_not_nil(f = File.open('hash-numeric', :mode => File::WRONLY|File::TRUNC|File::CREAT), feature4742)
  1755. f.close
  1756. assert_nothing_raised(bug6055) {f = File.open('hash-symbolic', binmode: true)}
  1757. f.close
  1758. end
  1759. end
  1760. def test_s_write
  1761. mkcdtmpdir do
  1762. path = "test_s_write"
  1763. File.write(path, "foo\nbar\nbaz")
  1764. assert_equal("foo\nbar\nbaz", File.read(path))
  1765. File.write(path, "FOO", 0)
  1766. assert_equal("FOO\nbar\nbaz", File.read(path))
  1767. File.write(path, "BAR")
  1768. assert_equal("BAR", File.read(path))
  1769. File.write(path, "\u{3042}", mode: "w", encoding: "EUC-JP")
  1770. assert_equal("\u{3042}".encode("EUC-JP"), File.read(path, encoding: "EUC-JP"))
  1771. File.delete path
  1772. assert_equal(6, File.write(path, 'string', 2))
  1773. File.delete path
  1774. assert_raise(Errno::EINVAL) { File.write('nonexisting','string', -2) }
  1775. assert_equal(6, File.write(path, 'string'))
  1776. assert_equal(3, File.write(path, 'sub', 1))
  1777. assert_equal("ssubng", File.read(path))
  1778. File.delete path
  1779. assert_equal(3, File.write(path, "foo", encoding: "UTF-8"))
  1780. File.delete path
  1781. assert_equal(3, File.write(path, "foo", 0, encoding: "UTF-8"))
  1782. assert_equal("foo", File.read(path))
  1783. assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
  1784. assert_equal("ffo", File.read(path))
  1785. File.delete path
  1786. assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
  1787. assert_equal("\00f", File.read(path))
  1788. assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8"))
  1789. assert_equal("ff", File.read(path))
  1790. end
  1791. end
  1792. def test_s_binwrite
  1793. mkcdtmpdir do
  1794. path = "test_s_binwrite"
  1795. File.binwrite(path, "foo\nbar\nbaz")
  1796. assert_equal("foo\nbar\nbaz", File.read(path))
  1797. File.binwrite(path, "FOO", 0)
  1798. assert_equal("FOO\nbar\nbaz", File.read(path))
  1799. File.binwrite(path, "BAR")
  1800. assert_equal("BAR", File.read(path))
  1801. File.binwrite(path, "\u{3042}")
  1802. assert_equal("\u{3042}".force_encoding("ASCII-8BIT"), File.binread(path))
  1803. File.delete path
  1804. assert_equal(6, File.binwrite(path, 'string', 2))
  1805. File.delete path
  1806. assert_equal(6, File.binwrite(path, 'string'))
  1807. assert_equal(3, File.binwrite(path, 'sub', 1))
  1808. assert_equal("ssubng", File.binread(path))
  1809. assert_equal(6, File.size(path))
  1810. assert_raise(Errno::EINVAL) { File.binwrite('nonexisting', 'string', -2) }
  1811. assert_nothing_raised(TypeError) { File.binwrite(path, "string", mode: "w", encoding: "EUC-JP") }
  1812. end
  1813. end
  1814. def test_race_between_read
  1815. file = Tempfile.new("test")
  1816. path = file.path
  1817. file.close
  1818. write_file = File.open(path, "wt")
  1819. read_file = File.open(path, "rt")
  1820. threads = []
  1821. 10.times do |i|
  1822. threads << Thread.new {write_file.print(i)}
  1823. threads << Thread.new {read_file.read}
  1824. end
  1825. threads.each {|t| t.join}
  1826. assert(true, "[ruby-core:37197]")
  1827. ensure
  1828. read_file.close
  1829. write_file.close
  1830. file.close!
  1831. end
  1832. def test_ioctl_linux
  1833. return if /linux/ !~ RUBY_PLATFORM
  1834. assert_nothing_raised do
  1835. File.open('/dev/urandom'){|f1|
  1836. entropy_count = ""
  1837. # get entropy count
  1838. f1.ioctl(0x80045200, entropy_count)
  1839. }
  1840. end
  1841. buf = ''
  1842. assert_nothing_raised do
  1843. fionread = 0x541B
  1844. File.open(__FILE__){|f1|
  1845. f1.ioctl(fionread, buf)
  1846. }
  1847. end
  1848. assert_equal(File.size(__FILE__), buf.unpack('i!')[0])
  1849. end
  1850. def test_ioctl_linux2
  1851. return if /linux/ !~ RUBY_PLATFORM
  1852. return if /^i.?86|^x86_64/ !~ RUBY_PLATFORM
  1853. return unless File.exist?('/dev/tty')
  1854. File.open('/dev/tty') { |f|
  1855. tiocgwinsz=0x5413
  1856. winsize=""
  1857. assert_nothing_raised {
  1858. f.ioctl(tiocgwinsz, winsize)
  1859. }
  1860. }
  1861. end
  1862. def test_setpos
  1863. mkcdtmpdir {
  1864. File.open("tmp.txt", "w") {|f|
  1865. f.puts "a"
  1866. f.puts "bc"
  1867. f.puts "def"
  1868. }
  1869. pos1 = pos2 = pos3 = nil
  1870. File.open("tmp.txt") {|f|
  1871. assert_equal("a\n", f.gets)
  1872. pos1 = f.pos
  1873. assert_equal("bc\n", f.gets)
  1874. pos2 = f.pos
  1875. assert_equal("def\n", f.gets)
  1876. pos3 = f.pos
  1877. assert_equal(nil, f.gets)
  1878. }
  1879. File.open("tmp.txt") {|f|