about summary refs log tree commit homepage
path: root/test/test_autopush.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_autopush.rb')
-rw-r--r--test/test_autopush.rb162
1 files changed, 160 insertions, 2 deletions
diff --git a/test/test_autopush.rb b/test/test_autopush.rb
index 4e5af92..22fd7ad 100644
--- a/test/test_autopush.rb
+++ b/test/test_autopush.rb
@@ -1,11 +1,169 @@
+# Copyright (C) 2015 all contributors <kgio-public@bogomips.org>
+# License: LGPLv2.1 or later (https://www.gnu.org/licenses/lgpl-2.1.txt)
+# using this code is not recommended, for backwards compatibility only
+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
-  def test_compatibility
+  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
     assert_equal false, Kgio.autopush?
   end
-end
+end if RUBY_PLATFORM =~ /linux|freebsd/