kgio 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,240 @@
1
+ require 'test/unit'
2
+ require 'io/nonblock'
3
+ $-w = true
4
+ require 'kgio'
5
+
6
+ module LibReadWriteTest
7
+ RANDOM_BLOB = File.open("/dev/urandom") { |fp| fp.read(10 * 1024 * 1024) }
8
+
9
+ def teardown
10
+ assert_nothing_raised do
11
+ @rd.close unless @rd.closed?
12
+ @wr.close unless @wr.closed?
13
+ end
14
+ assert_nothing_raised do
15
+ Kgio.wait_readable = Kgio.wait_writable = nil
16
+ end
17
+ end
18
+
19
+ def test_read_eof
20
+ @wr.close
21
+ assert_nil @rd.kgio_read(5)
22
+ end
23
+
24
+ def test_tryread_eof
25
+ @wr.close
26
+ assert_nil @rd.kgio_tryread(5)
27
+ end
28
+
29
+ def test_write_closed
30
+ @rd.close
31
+ assert_raises(Errno::EPIPE, Errno::ECONNRESET) {
32
+ loop { @wr.kgio_write "HI" }
33
+ }
34
+ end
35
+
36
+ def test_trywrite_closed
37
+ @rd.close
38
+ assert_raises(Errno::EPIPE, Errno::ECONNRESET) {
39
+ loop { @wr.kgio_trywrite "HI" }
40
+ }
41
+ end
42
+
43
+ def test_write_conv
44
+ assert_equal nil, @wr.kgio_write(10)
45
+ assert_equal "10", @rd.kgio_read(2)
46
+ end
47
+
48
+ def test_trywrite_conv
49
+ assert_equal nil, @wr.kgio_trywrite(10)
50
+ assert_equal "10", @rd.kgio_tryread(2)
51
+ end
52
+
53
+ def test_tryread_empty
54
+ assert_equal Kgio::WaitReadable, @rd.kgio_tryread(1)
55
+ end
56
+
57
+ def test_read_too_much
58
+ assert_equal nil, @wr.kgio_write("hi")
59
+ assert_equal "hi", @rd.kgio_read(4)
60
+ end
61
+
62
+ def test_tryread_too_much
63
+ assert_equal nil, @wr.kgio_trywrite("hi")
64
+ assert_equal "hi", @rd.kgio_tryread(4)
65
+ end
66
+
67
+ def test_read_short
68
+ assert_equal nil, @wr.kgio_write("hi")
69
+ assert_equal "h", @rd.kgio_read(1)
70
+ assert_equal "i", @rd.kgio_read(1)
71
+ end
72
+
73
+ def test_tryread_short
74
+ assert_equal nil, @wr.kgio_trywrite("hi")
75
+ assert_equal "h", @rd.kgio_tryread(1)
76
+ assert_equal "i", @rd.kgio_tryread(1)
77
+ end
78
+
79
+ def test_read_extra_buf
80
+ tmp = ""
81
+ tmp_object_id = tmp.object_id
82
+ assert_equal nil, @wr.kgio_write("hi")
83
+ rv = @rd.kgio_read(2, tmp)
84
+ assert_equal "hi", rv
85
+ assert_equal rv.object_id, tmp.object_id
86
+ assert_equal tmp_object_id, rv.object_id
87
+ end
88
+
89
+ def test_trywrite_return_wait_writable
90
+ tmp = []
91
+ tmp << @wr.kgio_trywrite("HI") until tmp[-1] == Kgio::WaitWritable
92
+ assert_equal Kgio::WaitWritable, tmp.pop
93
+ assert tmp.size > 0
94
+ penultimate = tmp.pop
95
+ assert(penultimate == "I" || penultimate == nil)
96
+ assert tmp.size > 0
97
+ tmp.each { |count| assert_equal nil, count }
98
+ end
99
+
100
+ def test_tryread_extra_buf_eagain_clears_buffer
101
+ tmp = "hello world"
102
+ rv = @rd.kgio_tryread(2, tmp)
103
+ assert_equal Kgio::WaitReadable, rv
104
+ assert_equal "", tmp
105
+ end
106
+
107
+ def test_tryread_extra_buf_eof_clears_buffer
108
+ tmp = "hello world"
109
+ @wr.close
110
+ assert_nil @rd.kgio_tryread(2, tmp)
111
+ assert_equal "", tmp
112
+ end
113
+
114
+ def test_monster_trywrite
115
+ buf = RANDOM_BLOB.dup
116
+ rv = @wr.kgio_trywrite(buf)
117
+ assert_kind_of String, rv
118
+ assert rv.size < buf.size
119
+ @rd.nonblock = false
120
+ assert_equal(buf, @rd.read(buf.size - rv.size) + rv)
121
+ end
122
+
123
+ def test_monster_write
124
+ buf = RANDOM_BLOB.dup
125
+ thr = Thread.new { @wr.kgio_write(buf) }
126
+ @rd.nonblock = false
127
+ readed = @rd.read(buf.size)
128
+ thr.join
129
+ assert_nil thr.value
130
+ assert_equal buf, readed
131
+ end
132
+
133
+ def test_monster_write_wait_writable
134
+ @wr.instance_variable_set :@nr, 0
135
+ def @wr.wait_writable
136
+ @nr += 1
137
+ IO.select(nil, [self])
138
+ end
139
+ Kgio.wait_writable = :wait_writable
140
+ buf = "." * 1024 * 1024 * 10
141
+ thr = Thread.new { @wr.kgio_write(buf) }
142
+ readed = @rd.read(buf.size)
143
+ thr.join
144
+ assert_nil thr.value
145
+ assert_equal buf, readed
146
+ assert @wr.instance_variable_get(:@nr) > 0
147
+ end
148
+
149
+ def test_wait_readable_ruby_default
150
+ assert_nothing_raised { Kgio.wait_readable = nil }
151
+ elapsed = 0
152
+ foo = nil
153
+ t0 = Time.now
154
+ thr = Thread.new { sleep 1; @wr.write "HELLO" }
155
+ assert_nothing_raised do
156
+ foo = @rd.kgio_read(5)
157
+ elapsed = Time.now - t0
158
+ end
159
+ assert elapsed >= 1.0, "elapsed: #{elapsed}"
160
+ assert_equal "HELLO", foo
161
+ thr.join
162
+ assert_equal 5, thr.value
163
+ end
164
+
165
+ def test_wait_writable_ruby_default
166
+ buf = "." * 512
167
+ nr = 0
168
+ begin
169
+ nr += @wr.write_nonblock(buf)
170
+ rescue Errno::EAGAIN
171
+ break
172
+ end while true
173
+ assert_nothing_raised { Kgio.wait_writable = nil }
174
+ elapsed = 0
175
+ foo = nil
176
+ t0 = Time.now
177
+ thr = Thread.new { sleep 1; @rd.readpartial(nr) }
178
+ assert_nothing_raised do
179
+ foo = @wr.kgio_write("HELLO")
180
+ elapsed = Time.now - t0
181
+ end
182
+ assert_nil foo
183
+ if @wr.stat.pipe?
184
+ assert elapsed >= 1.0, "elapsed: #{elapsed}"
185
+ end
186
+ assert(String === foo || foo == nil)
187
+ assert_kind_of String, thr.value
188
+ end
189
+
190
+ def test_wait_readable_method
191
+ def @rd.moo
192
+ defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
193
+ end
194
+ assert_nothing_raised { Kgio.wait_readable = :moo }
195
+ foo = nil
196
+ begin
197
+ foo = @rd.kgio_read(5)
198
+ assert false
199
+ rescue RuntimeError => e
200
+ assert_equal("Hello", e.message)
201
+ end
202
+ assert_equal "HI", @rd.instance_variable_get(:@z)
203
+ assert_nil foo
204
+ end
205
+
206
+ def test_tryread_wait_readable_method
207
+ def @rd.moo
208
+ raise "Hello"
209
+ end
210
+ assert_nothing_raised { Kgio.wait_readable = :moo }
211
+ assert_equal Kgio::WaitReadable, @rd.kgio_tryread(5)
212
+ end
213
+
214
+ def test_trywrite_wait_readable_method
215
+ def @wr.moo
216
+ raise "Hello"
217
+ end
218
+ assert_nothing_raised { Kgio.wait_writable = :moo }
219
+ tmp = []
220
+ buf = "." * 1024
221
+ 10000.times { tmp << @wr.kgio_trywrite(buf) }
222
+ assert_equal Kgio::WaitWritable, tmp.pop
223
+ end
224
+
225
+ def test_wait_writable_method
226
+ def @wr.moo
227
+ defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
228
+ end
229
+ assert_nothing_raised { Kgio.wait_writable = :moo }
230
+ n = []
231
+ begin
232
+ loop { n << @wr.kgio_write("HIHIHIHIHIHI") }
233
+ assert false
234
+ rescue RuntimeError => e
235
+ assert_equal("Hello", e.message)
236
+ end
237
+ assert n.size > 0
238
+ assert_equal "HI", @wr.instance_variable_get(:@z)
239
+ end
240
+ end
@@ -0,0 +1,70 @@
1
+ require 'test/unit'
2
+ require 'io/nonblock'
3
+ $-w = true
4
+ require 'kgio'
5
+
6
+ module LibServerAccept
7
+
8
+ def teardown
9
+ @srv.close unless @srv.closed?
10
+ Kgio.accept_cloexec = true
11
+ Kgio.accept_nonblock = false
12
+ end
13
+
14
+ def test_tryaccept_success
15
+ a = client_connect
16
+ IO.select([@srv])
17
+ b = @srv.kgio_tryaccept
18
+ assert_kind_of Kgio::Socket, b
19
+ assert_equal @host, b.kgio_addr
20
+ end
21
+
22
+ def test_tryaccept_fail
23
+ assert_equal nil, @srv.kgio_tryaccept
24
+ end
25
+
26
+ def test_blocking_accept
27
+ t0 = Time.now
28
+ pid = fork { sleep 1; a = client_connect; sleep }
29
+ b = @srv.kgio_accept
30
+ elapsed = Time.now - t0
31
+ assert_kind_of Kgio::Socket, b
32
+ assert_equal @host, b.kgio_addr
33
+ Process.kill(:TERM, pid)
34
+ Process.waitpid(pid)
35
+ assert elapsed >= 1, "elapsed: #{elapsed}"
36
+ end
37
+
38
+ def test_blocking_accept_with_nonblock_socket
39
+ @srv.nonblock = true
40
+ t0 = Time.now
41
+ pid = fork { sleep 1; a = client_connect; sleep }
42
+ b = @srv.kgio_accept
43
+ elapsed = Time.now - t0
44
+ assert_kind_of Kgio::Socket, b
45
+ assert_equal @host, b.kgio_addr
46
+ Process.kill(:TERM, pid)
47
+ Process.waitpid(pid)
48
+ assert elapsed >= 1, "elapsed: #{elapsed}"
49
+
50
+ t0 = Time.now
51
+ pid = fork { sleep 6; a = client_connect; sleep }
52
+ b = @srv.kgio_accept
53
+ elapsed = Time.now - t0
54
+ assert_kind_of Kgio::Socket, b
55
+ assert_equal @host, b.kgio_addr
56
+ Process.kill(:TERM, pid)
57
+ Process.waitpid(pid)
58
+ assert elapsed >= 6, "elapsed: #{elapsed}"
59
+
60
+ t0 = Time.now
61
+ pid = fork { sleep 1; a = client_connect; sleep }
62
+ b = @srv.kgio_accept
63
+ elapsed = Time.now - t0
64
+ assert_kind_of Kgio::Socket, b
65
+ assert_equal @host, b.kgio_addr
66
+ Process.kill(:TERM, pid)
67
+ Process.waitpid(pid)
68
+ assert elapsed >= 1, "elapsed: #{elapsed}"
69
+ end
70
+ end
@@ -0,0 +1,23 @@
1
+ require 'test/unit'
2
+ require 'io/nonblock'
3
+ $-w = true
4
+ require 'kgio'
5
+
6
+ class TestConnectFDLeak < Test::Unit::TestCase
7
+
8
+ def teardown
9
+ Kgio.wait_readable = Kgio.wait_writable = nil
10
+ end
11
+
12
+ def test_unix_socket
13
+ nr = 0
14
+ path = "/non/existent/path"
15
+ assert(! File.exist?(path), "#{path} should not exist")
16
+ assert_nothing_raised do
17
+ begin
18
+ sock = Kgio::UNIXSocket.new(path)
19
+ rescue Errno::ENOENT
20
+ end while (nr += 1) < 10000
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+ require 'io/nonblock'
3
+ $-w = true
4
+ require 'kgio'
5
+
6
+ class TestPipePopen < Test::Unit::TestCase
7
+ def test_popen
8
+ io = Kgio::Pipe.popen("sleep 1 && echo HI")
9
+ assert_equal Kgio::WaitReadable, io.kgio_tryread(2)
10
+ sleep 1.5
11
+ assert_equal "HI\n", io.kgio_read(3)
12
+ assert_nil io.kgio_read(5)
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ require './test/lib_read_write.rb'
2
+
3
+ class TestKgioPipe < Test::Unit::TestCase
4
+ def setup
5
+ @rd, @wr = Kgio::Pipe.new
6
+ end
7
+
8
+ include LibReadWriteTest
9
+ end
@@ -0,0 +1,9 @@
1
+ require './test/lib_read_write.rb'
2
+
3
+ class TestKgioUNIXSocketPair < Test::Unit::TestCase
4
+ def setup
5
+ @rd, @wr = Kgio::UNIXSocket.pair
6
+ end
7
+
8
+ include LibReadWriteTest
9
+ end
@@ -0,0 +1,13 @@
1
+ require './test/lib_read_write'
2
+
3
+ class TesTcpClientReadServerWrite < Test::Unit::TestCase
4
+ def setup
5
+ @host = ENV["TEST_HOST"] || '127.0.0.1'
6
+ @srv = Kgio::TCPServer.new(@host, 0)
7
+ @port = @srv.addr[1]
8
+ @wr = Kgio::TCPSocket.new(@host, @port)
9
+ @rd = @srv.kgio_accept
10
+ end
11
+
12
+ include LibReadWriteTest
13
+ end
@@ -0,0 +1,73 @@
1
+ require 'test/unit'
2
+ require 'io/nonblock'
3
+ $-w = true
4
+ require 'kgio'
5
+
6
+ class SubSocket < Kgio::Socket
7
+ attr_accessor :foo
8
+ def wait_writable
9
+ @foo = "waited"
10
+ end
11
+ end
12
+
13
+ class TestKgioTcpConnect < Test::Unit::TestCase
14
+
15
+ def setup
16
+ @host = ENV["TEST_HOST"] || '127.0.0.1'
17
+ @srv = Kgio::TCPServer.new(@host, 0)
18
+ @port = @srv.addr[1]
19
+ @addr = Socket.pack_sockaddr_in(@port, @host)
20
+ end
21
+
22
+ def teardown
23
+ @srv.close unless @srv.closed?
24
+ Kgio.accept_cloexec = true
25
+ Kgio.accept_nonblock = false
26
+ Kgio.wait_readable = Kgio.wait_writable = nil
27
+ end
28
+
29
+ def test_new
30
+ sock = Kgio::Socket.new(@addr)
31
+ assert_kind_of Kgio::Socket, sock
32
+ ready = IO.select(nil, [ sock ])
33
+ assert_equal sock, ready[1][0]
34
+ assert_equal nil, sock.kgio_write("HELLO")
35
+ end
36
+
37
+ def test_start
38
+ sock = Kgio::Socket.start(@addr)
39
+ assert_kind_of Kgio::Socket, sock
40
+ ready = IO.select(nil, [ sock ])
41
+ assert_equal sock, ready[1][0]
42
+ assert_equal nil, sock.kgio_write("HELLO")
43
+ end
44
+
45
+ def test_tcp_socket_new_invalid
46
+ assert_raises(ArgumentError) { Kgio::TCPSocket.new('example.com', 80) }
47
+ assert_raises(ArgumentError) { Kgio::TCPSocket.new('999.999.999.999', 80) }
48
+ end
49
+
50
+ def test_tcp_socket_new
51
+ sock = Kgio::TCPSocket.new(@host, @port)
52
+ assert_instance_of Kgio::TCPSocket, sock
53
+ ready = IO.select(nil, [ sock ])
54
+ assert_equal sock, ready[1][0]
55
+ assert_equal nil, sock.kgio_write("HELLO")
56
+ end
57
+
58
+ def test_socket_start
59
+ Kgio::wait_writable = :wait_writable
60
+ sock = SubSocket.start(@addr)
61
+ assert_nil sock.foo
62
+ ready = IO.select(nil, [ sock ])
63
+ assert_equal sock, ready[1][0]
64
+ assert_equal nil, sock.kgio_write("HELLO")
65
+ end
66
+
67
+ def test_wait_writable_set
68
+ Kgio::wait_writable = :wait_writable
69
+ sock = SubSocket.new(@addr)
70
+ assert_equal "waited", sock.foo
71
+ assert_equal nil, sock.kgio_write("HELLO")
72
+ end
73
+ end