resurrect Kgio.autopush support in pure Ruby
[kgio.git] / test / test_autopush.rb
blob22fd7adadcd96eee397b100b21c4e0651dc66d30
1 # Copyright (C) 2015 all contributors <kgio-public@bogomips.org>
2 # License: LGPLv2.1 or later (https://www.gnu.org/licenses/lgpl-2.1.txt)
3 # using this code is not recommended, for backwards compatibility only
4 require 'tempfile'
5 require 'test/unit'
6 begin
7   $-w = false
8   RUBY_PLATFORM =~ /linux/ and require 'strace'
9 rescue LoadError
10 end
11 $-w = true
12 require 'kgio'
14 class TestAutopush < Test::Unit::TestCase
15   TCP_CORK = 3
16   TCP_NOPUSH = 4
18   def setup
19     Kgio.autopush = false
20     assert_equal false, Kgio.autopush?
22     @host = ENV["TEST_HOST"] || '127.0.0.1'
23     @srv = Kgio::TCPServer.new(@host, 0)
24     RUBY_PLATFORM =~ /linux/ and
25       @srv.setsockopt(Socket::IPPROTO_TCP, TCP_CORK, 1)
26     RUBY_PLATFORM =~ /freebsd/ and
27       @srv.setsockopt(Socket::IPPROTO_TCP, TCP_NOPUSH, 1)
28     @port = @srv.addr[1]
29   end
31   def test_autopush_accessors
32     Kgio.autopush = true
33     opt = RUBY_PLATFORM =~ /freebsd/ ? TCP_NOPUSH : TCP_CORK
34     s = Kgio::TCPSocket.new(@host, @port)
35     assert_equal 0, s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
36     assert ! s.kgio_autopush?
37     s.kgio_autopush = true
38     assert s.kgio_autopush?
39     s.kgio_write 'asdf'
40     assert_equal :wait_readable, s.kgio_tryread(1)
41     assert s.kgio_autopush?
42     val = s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
43     assert_operator val, :>, 0, "#{opt}=#{val} (#{RUBY_PLATFORM})"
44   end
46   def test_autopush_true_unix
47     Kgio.autopush = true
48     tmp = Tempfile.new('kgio_unix')
49     @path = tmp.path
50     tmp.close!
51     @srv = Kgio::UNIXServer.new(@path)
52     @rd = Kgio::UNIXSocket.new(@path)
53     t0 = nil
54     if defined?(Strace)
55       io, err = Strace.me { @wr = @srv.kgio_accept }
56       assert_nil err
57       rc = nil
58       io, err = Strace.me {
59         t0 = Time.now
60         @wr.kgio_write "HI\n"
61         rc = @wr.kgio_tryread 666
62       }
63       assert_nil err
64       lines = io.readlines
65       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
66     else
67       @wr = @srv.kgio_accept
68       t0 = Time.now
69       @wr.kgio_write "HI\n"
70       rc = @wr.kgio_tryread 666
71     end
72     assert_equal "HI\n", @rd.kgio_read(3)
73     diff = Time.now - t0
74     assert(diff < 0.200, "nopush on UNIX sockets? diff=#{diff} > 200ms")
75     assert_equal :wait_readable, rc
76   ensure
77     File.unlink(@path) rescue nil
78   end
80   def test_autopush_false
81     Kgio.autopush = nil
82     assert_equal false, Kgio.autopush?
84     @wr = Kgio::TCPSocket.new(@host, @port)
85     if defined?(Strace)
86       io, err = Strace.me { @rd = @srv.kgio_accept }
87       assert_nil err
88       lines = io.readlines
89       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
90       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
91     else
92       @rd = @srv.kgio_accept
93     end
95     rbuf = "..."
96     t0 = Time.now
97     @rd.kgio_write "HI\n"
98     @wr.kgio_read(3, rbuf)
99     diff = Time.now - t0
100     assert(diff >= 0.190, "nopush broken? diff=#{diff} > 200ms")
101     assert_equal "HI\n", rbuf
102   end
104   def test_autopush_true
105     Kgio.autopush = true
106     assert_equal true, Kgio.autopush?
107     @wr = Kgio::TCPSocket.new(@host, @port)
109     if defined?(Strace)
110       io, err = Strace.me { @rd = @srv.kgio_accept }
111       assert_nil err
112       lines = io.readlines
113       assert_equal 1, lines.grep(/TCP_CORK/).size, lines.inspect
114       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
115     else
116       @rd = @srv.kgio_accept
117     end
119     @wr.write "HI\n"
120     rbuf = ""
121     if defined?(Strace)
122       io, err = Strace.me { @rd.kgio_read(3, rbuf) }
123       assert_nil err
124       lines = io.readlines
125       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
126       assert_equal "HI\n", rbuf
127     else
128       assert_equal "HI\n", @rd.kgio_read(3, rbuf)
129     end
131     t0 = Time.now
132     @rd.kgio_write "HI2U2\n"
133     @rd.kgio_write "HOW\n"
134     rc = false
136     if defined?(Strace)
137       io, err = Strace.me { rc = @rd.kgio_tryread(666) }
138     else
139       rc = @rd.kgio_tryread(666)
140     end
142     @wr.readpartial(666, rbuf)
143     rbuf == "HI2U2\nHOW\n" or warn "rbuf=#{rbuf.inspect} looking bad?"
144     diff = Time.now - t0
145     assert(diff < 0.200, "time diff=#{diff} >= 200ms")
146     assert_equal :wait_readable, rc
147     if defined?(Strace)
148       assert_nil err
149       lines = io.readlines
150       assert_equal 2, lines.grep(/TCP_CORK/).size, lines.inspect
151     end
152     @wr.close
153     @rd.close
155     @wr = Kgio::TCPSocket.new(@host, @port)
156     if defined?(Strace)
157       io, err = Strace.me { @rd = @srv.kgio_accept }
158       assert_nil err
159       lines = io.readlines
160       assert lines.grep(/TCP_CORK/).empty?,"optimization fail: #{lines.inspect}"
161       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
162     end
163   end
165   def teardown
166     Kgio.autopush = false
167     assert_equal false, Kgio.autopush?
168   end
169 end if RUBY_PLATFORM =~ /linux|freebsd/