1require 'test/unit'
2require 'timeout'
3require 'fcntl'
4
5class TestReadPartial < Test::Unit::TestCase
6  def make_pipe
7    r, w = IO.pipe
8    r.binmode
9    w.binmode
10    begin
11      yield r, w
12    ensure
13      r.close unless r.closed?
14      w.close unless w.closed?
15    end
16  end
17
18  def pipe
19    make_pipe {|r, w|
20      yield r, w
21    }
22    return unless defined?(Fcntl::F_SETFL)
23    return unless defined?(Fcntl::F_GETFL)
24    return unless defined?(Fcntl::O_NONBLOCK)
25    make_pipe {|r, w|
26      r.fcntl(Fcntl::F_SETFL, r.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
27      yield r, w
28    }
29  end
30
31  def test_length_zero
32    pipe {|r, w|
33      assert_equal('', r.readpartial(0))
34    }
35  end
36
37  def test_closed_pipe
38    pipe {|r, w|
39      w << 'abc'
40      w.close
41      assert_equal('ab', r.readpartial(2))
42      assert_equal('c', r.readpartial(2))
43      assert_raise(EOFError) { r.readpartial(2) }
44      assert_raise(EOFError) { r.readpartial(2) }
45    }
46  end
47
48  def test_open_pipe
49    pipe {|r, w|
50      w << 'abc'
51      assert_equal('ab', r.readpartial(2))
52      assert_equal('c', r.readpartial(2))
53      assert_raise(TimeoutError) {
54        timeout(0.1) { r.readpartial(2) }
55      }
56    }
57  end
58
59  def test_with_stdio
60    pipe {|r, w|
61      w << "abc\ndef\n"
62      assert_equal("abc\n", r.gets)
63      w << "ghi\n"
64      assert_equal("de", r.readpartial(2))
65      assert_equal("f\n", r.readpartial(4096))
66      assert_equal("ghi\n", r.readpartial(4096))
67      assert_raise(TimeoutError) {
68        timeout(0.1) { r.readpartial(2) }
69      }
70    }
71  end
72end
73