kgio.git  about / heads / tags
kinder, gentler I/O for Ruby
blob 146c222f201d3da7bc08ba2e6103920c3e3ba76e 6329 bytes (raw)
$ git show v1.2.0:test/lib_read_write.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
 
require 'test/unit'
require 'io/nonblock'
$-w = true
require 'kgio'

module LibReadWriteTest
  RANDOM_BLOB = File.open("/dev/urandom") { |fp| fp.read(10 * 1024 * 1024) }

  def teardown
    assert_nothing_raised do
      @rd.close unless @rd.closed?
      @wr.close unless @wr.closed?
    end
    assert_nothing_raised do
      Kgio.wait_readable = Kgio.wait_writable = nil
    end
  end

  def test_read_eof
    @wr.close
    assert_nil @rd.kgio_read(5)
  end

  def test_read_bang_eof
    @wr.close
    begin
      @rd.kgio_read!(5)
      assert false, "should never get here (line:#{__LINE__})"
    rescue EOFError => e
      assert_equal [], e.backtrace
    end
  end

  def test_tryread_eof
    @wr.close
    assert_nil @rd.kgio_tryread(5)
  end

  def test_write_closed
    @rd.close
    begin
      loop { @wr.kgio_write "HI" }
    rescue Errno::EPIPE, Errno::ECONNRESET => e
      assert_equal [], e.backtrace
      return
    end
    assert false, "should never get here (line:#{__LINE__})"
  end

  def test_trywrite_closed
    @rd.close
    begin
      loop { @wr.kgio_trywrite "HI" }
    rescue Errno::EPIPE, Errno::ECONNRESET => e
      assert_equal [], e.backtrace
      return
    end
    assert false, "should never get here (line:#{__LINE__})"
  end

  def test_write_conv
    assert_equal nil, @wr.kgio_write(10)
    assert_equal "10", @rd.kgio_read(2)
  end

  def test_trywrite_conv
    assert_equal nil, @wr.kgio_trywrite(10)
    assert_equal "10", @rd.kgio_tryread(2)
  end

  def test_tryread_empty
    assert_equal Kgio::WaitReadable, @rd.kgio_tryread(1)
  end

  def test_read_too_much
    assert_equal nil, @wr.kgio_write("hi")
    assert_equal "hi", @rd.kgio_read(4)
  end

  def test_tryread_too_much
    assert_equal nil, @wr.kgio_trywrite("hi")
    assert_equal "hi", @rd.kgio_tryread(4)
  end

  def test_read_short
    assert_equal nil, @wr.kgio_write("hi")
    assert_equal "h", @rd.kgio_read(1)
    assert_equal "i", @rd.kgio_read(1)
  end

  def test_tryread_short
    assert_equal nil, @wr.kgio_trywrite("hi")
    assert_equal "h", @rd.kgio_tryread(1)
    assert_equal "i", @rd.kgio_tryread(1)
  end

  def test_read_extra_buf
    tmp = ""
    tmp_object_id = tmp.object_id
    assert_equal nil, @wr.kgio_write("hi")
    rv = @rd.kgio_read(2, tmp)
    assert_equal "hi", rv
    assert_equal rv.object_id, tmp.object_id
    assert_equal tmp_object_id, rv.object_id
  end

  def test_trywrite_return_wait_writable
    tmp = []
    tmp << @wr.kgio_trywrite("HI") until tmp[-1] == Kgio::WaitWritable
    assert_equal Kgio::WaitWritable, tmp.pop
    assert tmp.size > 0
    penultimate = tmp.pop
    assert(penultimate == "I" || penultimate == nil)
    assert tmp.size > 0
    tmp.each { |count| assert_equal nil, count }
  end

  def test_tryread_extra_buf_eagain_clears_buffer
    tmp = "hello world"
    rv = @rd.kgio_tryread(2, tmp)
    assert_equal Kgio::WaitReadable, rv
    assert_equal "", tmp
  end

  def test_tryread_extra_buf_eof_clears_buffer
    tmp = "hello world"
    @wr.close
    assert_nil @rd.kgio_tryread(2, tmp)
    assert_equal "", tmp
  end

  def test_monster_trywrite
    buf = RANDOM_BLOB.dup
    rv = @wr.kgio_trywrite(buf)
    assert_kind_of String, rv
    assert rv.size < buf.size
    @rd.nonblock = false
    assert_equal(buf, @rd.read(buf.size - rv.size) + rv)
  end

  def test_monster_write
    buf = RANDOM_BLOB.dup
    thr = Thread.new { @wr.kgio_write(buf) }
    @rd.nonblock = false
    readed = @rd.read(buf.size)
    thr.join
    assert_nil thr.value
    assert_equal buf, readed
  end

  def test_monster_write_wait_writable
    @wr.instance_variable_set :@nr, 0
    def @wr.wait_writable
      @nr += 1
      IO.select(nil, [self])
    end
    Kgio.wait_writable = :wait_writable
    buf = "." * 1024 * 1024 * 10
    thr = Thread.new { @wr.kgio_write(buf) }
    readed = @rd.read(buf.size)
    thr.join
    assert_nil thr.value
    assert_equal buf, readed
    assert @wr.instance_variable_get(:@nr) > 0
  end

  def test_wait_readable_ruby_default
    assert_nothing_raised { Kgio.wait_readable = nil }
    elapsed = 0
    foo = nil
    t0 = Time.now
    thr = Thread.new { sleep 1; @wr.write "HELLO" }
    assert_nothing_raised do
      foo = @rd.kgio_read(5)
      elapsed = Time.now - t0
    end
    assert elapsed >= 1.0, "elapsed: #{elapsed}"
    assert_equal "HELLO", foo
    thr.join
    assert_equal 5, thr.value
  end

  def test_wait_writable_ruby_default
    buf = "." * 512
    nr = 0
    begin
      nr += @wr.write_nonblock(buf)
    rescue Errno::EAGAIN
      break
    end while true
    assert_nothing_raised { Kgio.wait_writable = nil }
    elapsed = 0
    foo = nil
    t0 = Time.now
    thr = Thread.new { sleep 1; @rd.readpartial(nr) }
    assert_nothing_raised do
      foo = @wr.kgio_write("HELLO")
      elapsed = Time.now - t0
    end
    assert_nil foo
    if @wr.stat.pipe?
      assert elapsed >= 1.0, "elapsed: #{elapsed}"
    end
    assert(String === foo || foo == nil)
    assert_kind_of String, thr.value
  end

  def test_wait_readable_method
    def @rd.moo
      defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
    end
    assert_nothing_raised { Kgio.wait_readable = :moo }
    foo = nil
    begin
      foo = @rd.kgio_read(5)
      assert false
    rescue RuntimeError => e
      assert_equal("Hello", e.message)
    end
    assert_equal "HI", @rd.instance_variable_get(:@z)
    assert_nil foo
  end

  def test_tryread_wait_readable_method
    def @rd.moo
      raise "Hello"
    end
    assert_nothing_raised { Kgio.wait_readable = :moo }
    assert_equal Kgio::WaitReadable, @rd.kgio_tryread(5)
  end

  def test_trywrite_wait_readable_method
    def @wr.moo
      raise "Hello"
    end
    assert_nothing_raised { Kgio.wait_writable = :moo }
    tmp = []
    buf = "." * 1024
    10000.times { tmp << @wr.kgio_trywrite(buf) }
    assert_equal Kgio::WaitWritable, tmp.pop
  end

  def test_wait_writable_method
    def @wr.moo
      defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
    end
    assert_nothing_raised { Kgio.wait_writable = :moo }
    n = []
    begin
      loop { n << @wr.kgio_write("HIHIHIHIHIHI") }
      assert false
    rescue RuntimeError => e
      assert_equal("Hello", e.message)
    end
    assert n.size > 0
    assert_equal "HI", @wr.instance_variable_get(:@z)
  end
end

git clone git://yhbt.net/kgio.git
git clone https://yhbt.net/kgio.git