reinstate the original (and dangerous) autopush in C
[kgio.git] / test / test_autopush.rb
blob38b7c520c712a36022d3fbe49b21390fa9e6c87c
1 require 'tempfile'
2 require 'test/unit'
3 begin
4   $-w = false
5   RUBY_PLATFORM =~ /linux/ and require 'strace'
6 rescue LoadError
7 end
8 $-w = true
9 require 'kgio'
11 class TestAutopush < Test::Unit::TestCase
12   TCP_CORK = 3
13   TCP_NOPUSH = 4
15   def setup
16     Kgio.autopush = false
17     assert_equal false, Kgio.autopush?
19     @host = ENV["TEST_HOST"] || '127.0.0.1'
20     @srv = Kgio::TCPServer.new(@host, 0)
21     RUBY_PLATFORM =~ /linux/ and
22       @srv.setsockopt(Socket::IPPROTO_TCP, TCP_CORK, 1)
23     RUBY_PLATFORM =~ /freebsd/ and
24       @srv.setsockopt(Socket::IPPROTO_TCP, TCP_NOPUSH, 1)
25     @port = @srv.addr[1]
26   end
28   def test_autopush_accessors
29     Kgio.autopush = true
30     opt = RUBY_PLATFORM =~ /freebsd/ ? TCP_NOPUSH : TCP_CORK
31     s = Kgio::TCPSocket.new(@host, @port)
32     assert_equal 0, s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
33     assert ! s.kgio_autopush?
34     s.kgio_autopush = true
35     assert s.kgio_autopush?
36     s.kgio_write 'asdf'
37     assert_equal :wait_readable, s.kgio_tryread(1)
38     assert s.kgio_autopush?
39     val = s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
40     assert_operator val, :>, 0, "#{opt}=#{val} (#{RUBY_PLATFORM})"
41   end
43   def test_autopush_true_unix
44     Kgio.autopush = true
45     tmp = Tempfile.new('kgio_unix')
46     @path = tmp.path
47     tmp.close!
48     @srv = Kgio::UNIXServer.new(@path)
49     @rd = Kgio::UNIXSocket.new(@path)
50     t0 = nil
51     if defined?(Strace)
52       io, err = Strace.me { @wr = @srv.kgio_accept }
53       assert_nil err
54       rc = nil
55       io, err = Strace.me {
56         t0 = Time.now
57         @wr.kgio_write "HI\n"
58         rc = @wr.kgio_tryread 666
59       }
60       assert_nil err
61       lines = io.readlines
62       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
63     else
64       @wr = @srv.kgio_accept
65       t0 = Time.now
66       @wr.kgio_write "HI\n"
67       rc = @wr.kgio_tryread 666
68     end
69     assert_equal "HI\n", @rd.kgio_read(3)
70     diff = Time.now - t0
71     assert(diff < 0.200, "nopush on UNIX sockets? diff=#{diff} > 200ms")
72     assert_equal :wait_readable, rc
73   ensure
74     File.unlink(@path) rescue nil
75   end
77   def test_autopush_false
78     Kgio.autopush = nil
79     assert_equal false, Kgio.autopush?
81     @wr = Kgio::TCPSocket.new(@host, @port)
82     if defined?(Strace)
83       io, err = Strace.me { @rd = @srv.kgio_accept }
84       assert_nil err
85       lines = io.readlines
86       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
87       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
88     else
89       @rd = @srv.kgio_accept
90     end
92     rbuf = "..."
93     t0 = Time.now
94     @rd.kgio_write "HI\n"
95     @wr.kgio_read(3, rbuf)
96     diff = Time.now - t0
97     assert(diff >= 0.190, "nopush broken? diff=#{diff} > 200ms")
98     assert_equal "HI\n", rbuf
99   end
101   def test_autopush_true
102     Kgio.autopush = true
103     assert_equal true, Kgio.autopush?
104     @wr = Kgio::TCPSocket.new(@host, @port)
106     if defined?(Strace)
107       io, err = Strace.me { @rd = @srv.kgio_accept }
108       assert_nil err
109       lines = io.readlines
110       assert_equal 1, lines.grep(/TCP_CORK/).size, lines.inspect
111       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
112     else
113       @rd = @srv.kgio_accept
114     end
116     @wr.write "HI\n"
117     rbuf = ""
118     if defined?(Strace)
119       io, err = Strace.me { @rd.kgio_read(3, rbuf) }
120       assert_nil err
121       lines = io.readlines
122       assert lines.grep(/TCP_CORK/).empty?, lines.inspect
123       assert_equal "HI\n", rbuf
124     else
125       assert_equal "HI\n", @rd.kgio_read(3, rbuf)
126     end
128     t0 = Time.now
129     @rd.kgio_write "HI2U2\n"
130     @rd.kgio_write "HOW\n"
131     rc = false
133     if defined?(Strace)
134       io, err = Strace.me { rc = @rd.kgio_tryread(666) }
135     else
136       rc = @rd.kgio_tryread(666)
137     end
139     @wr.readpartial(666, rbuf)
140     rbuf == "HI2U2\nHOW\n" or warn "rbuf=#{rbuf.inspect} looking bad?"
141     diff = Time.now - t0
142     assert(diff < 0.200, "time diff=#{diff} >= 200ms")
143     assert_equal :wait_readable, rc
144     if defined?(Strace)
145       assert_nil err
146       lines = io.readlines
147       assert_equal 2, lines.grep(/TCP_CORK/).size, lines.inspect
148     end
149     @wr.close
150     @rd.close
152     @wr = Kgio::TCPSocket.new(@host, @port)
153     if defined?(Strace)
154       io, err = Strace.me { @rd = @srv.kgio_accept }
155       assert_nil err
156       lines = io.readlines
157       assert lines.grep(/TCP_CORK/).empty?,"optimization fail: #{lines.inspect}"
158       assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
159     end
160   end
162   def teardown
163     Kgio.autopush = false
164   end
165 end if RUBY_PLATFORM =~ /linux|freebsd/