kgio.git  about / heads / tags
kinder, gentler I/O for Ruby
blob 38b7c520c712a36022d3fbe49b21390fa9e6c87c 4545 bytes (raw)
$ git show HEAD:test/test_autopush.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
 
require 'tempfile'
require 'test/unit'
begin
  $-w = false
  RUBY_PLATFORM =~ /linux/ and require 'strace'
rescue LoadError
end
$-w = true
require 'kgio'

class TestAutopush < Test::Unit::TestCase
  TCP_CORK = 3
  TCP_NOPUSH = 4

  def setup
    Kgio.autopush = false
    assert_equal false, Kgio.autopush?

    @host = ENV["TEST_HOST"] || '127.0.0.1'
    @srv = Kgio::TCPServer.new(@host, 0)
    RUBY_PLATFORM =~ /linux/ and
      @srv.setsockopt(Socket::IPPROTO_TCP, TCP_CORK, 1)
    RUBY_PLATFORM =~ /freebsd/ and
      @srv.setsockopt(Socket::IPPROTO_TCP, TCP_NOPUSH, 1)
    @port = @srv.addr[1]
  end

  def test_autopush_accessors
    Kgio.autopush = true
    opt = RUBY_PLATFORM =~ /freebsd/ ? TCP_NOPUSH : TCP_CORK
    s = Kgio::TCPSocket.new(@host, @port)
    assert_equal 0, s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
    assert ! s.kgio_autopush?
    s.kgio_autopush = true
    assert s.kgio_autopush?
    s.kgio_write 'asdf'
    assert_equal :wait_readable, s.kgio_tryread(1)
    assert s.kgio_autopush?
    val = s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
    assert_operator val, :>, 0, "#{opt}=#{val} (#{RUBY_PLATFORM})"
  end

  def test_autopush_true_unix
    Kgio.autopush = true
    tmp = Tempfile.new('kgio_unix')
    @path = tmp.path
    tmp.close!
    @srv = Kgio::UNIXServer.new(@path)
    @rd = Kgio::UNIXSocket.new(@path)
    t0 = nil
    if defined?(Strace)
      io, err = Strace.me { @wr = @srv.kgio_accept }
      assert_nil err
      rc = nil
      io, err = Strace.me {
        t0 = Time.now
        @wr.kgio_write "HI\n"
        rc = @wr.kgio_tryread 666
      }
      assert_nil err
      lines = io.readlines
      assert lines.grep(/TCP_CORK/).empty?, lines.inspect
    else
      @wr = @srv.kgio_accept
      t0 = Time.now
      @wr.kgio_write "HI\n"
      rc = @wr.kgio_tryread 666
    end
    assert_equal "HI\n", @rd.kgio_read(3)
    diff = Time.now - t0
    assert(diff < 0.200, "nopush on UNIX sockets? diff=#{diff} > 200ms")
    assert_equal :wait_readable, rc
  ensure
    File.unlink(@path) rescue nil
  end

  def test_autopush_false
    Kgio.autopush = nil
    assert_equal false, Kgio.autopush?

    @wr = Kgio::TCPSocket.new(@host, @port)
    if defined?(Strace)
      io, err = Strace.me { @rd = @srv.kgio_accept }
      assert_nil err
      lines = io.readlines
      assert lines.grep(/TCP_CORK/).empty?, lines.inspect
      assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
    else
      @rd = @srv.kgio_accept
    end

    rbuf = "..."
    t0 = Time.now
    @rd.kgio_write "HI\n"
    @wr.kgio_read(3, rbuf)
    diff = Time.now - t0
    assert(diff >= 0.190, "nopush broken? diff=#{diff} > 200ms")
    assert_equal "HI\n", rbuf
  end

  def test_autopush_true
    Kgio.autopush = true
    assert_equal true, Kgio.autopush?
    @wr = Kgio::TCPSocket.new(@host, @port)

    if defined?(Strace)
      io, err = Strace.me { @rd = @srv.kgio_accept }
      assert_nil err
      lines = io.readlines
      assert_equal 1, lines.grep(/TCP_CORK/).size, lines.inspect
      assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
    else
      @rd = @srv.kgio_accept
    end

    @wr.write "HI\n"
    rbuf = ""
    if defined?(Strace)
      io, err = Strace.me { @rd.kgio_read(3, rbuf) }
      assert_nil err
      lines = io.readlines
      assert lines.grep(/TCP_CORK/).empty?, lines.inspect
      assert_equal "HI\n", rbuf
    else
      assert_equal "HI\n", @rd.kgio_read(3, rbuf)
    end

    t0 = Time.now
    @rd.kgio_write "HI2U2\n"
    @rd.kgio_write "HOW\n"
    rc = false

    if defined?(Strace)
      io, err = Strace.me { rc = @rd.kgio_tryread(666) }
    else
      rc = @rd.kgio_tryread(666)
    end

    @wr.readpartial(666, rbuf)
    rbuf == "HI2U2\nHOW\n" or warn "rbuf=#{rbuf.inspect} looking bad?"
    diff = Time.now - t0
    assert(diff < 0.200, "time diff=#{diff} >= 200ms")
    assert_equal :wait_readable, rc
    if defined?(Strace)
      assert_nil err
      lines = io.readlines
      assert_equal 2, lines.grep(/TCP_CORK/).size, lines.inspect
    end
    @wr.close
    @rd.close

    @wr = Kgio::TCPSocket.new(@host, @port)
    if defined?(Strace)
      io, err = Strace.me { @rd = @srv.kgio_accept }
      assert_nil err
      lines = io.readlines
      assert lines.grep(/TCP_CORK/).empty?,"optimization fail: #{lines.inspect}"
      assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
    end
  end

  def teardown
    Kgio.autopush = false
  end
end if RUBY_PLATFORM =~ /linux|freebsd/

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