1begin
2  require "socket"
3rescue LoadError
4end
5
6require "test/unit"
7require "tempfile"
8require "timeout"
9
10class TestSocketNonblock < Test::Unit::TestCase
11  def test_accept_nonblock
12    serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
13    serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
14    serv.listen(5)
15    assert_raise(IO::WaitReadable) { serv.accept_nonblock }
16    c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
17    c.connect(serv.getsockname)
18    begin
19      s, sockaddr = serv.accept_nonblock
20    rescue IO::WaitReadable
21      IO.select [serv]
22      s, sockaddr = serv.accept_nonblock
23    end
24    assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr))
25  ensure
26    serv.close if serv
27    c.close if c
28    s.close if s
29  end
30
31  def test_connect_nonblock
32    serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
33    serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
34    serv.listen(5)
35    c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
36    servaddr = serv.getsockname
37    begin
38      c.connect_nonblock(servaddr)
39    rescue IO::WaitWritable
40      IO.select nil, [c]
41      assert_nothing_raised {
42        begin
43          c.connect_nonblock(servaddr)
44        rescue Errno::EISCONN
45        end
46      }
47    end
48    s, sockaddr = serv.accept
49    assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr))
50  ensure
51    serv.close if serv
52    c.close if c
53    s.close if s
54  end
55
56  def test_udp_recvfrom_nonblock
57    u1 = UDPSocket.new
58    u2 = UDPSocket.new
59    u1.bind("127.0.0.1", 0)
60    assert_raise(IO::WaitReadable) { u1.recvfrom_nonblock(100) }
61    assert_raise(IO::WaitReadable, Errno::EINVAL) { u2.recvfrom_nonblock(100) }
62    u2.send("aaa", 0, u1.getsockname)
63    IO.select [u1]
64    mesg, inet_addr = u1.recvfrom_nonblock(100)
65    assert_equal(4, inet_addr.length)
66    assert_equal("aaa", mesg)
67    af, port, host, addr = inet_addr
68    u2_port, u2_addr = Socket.unpack_sockaddr_in(u2.getsockname)
69    assert_equal(u2_port, port)
70    assert_raise(IO::WaitReadable) { u1.recvfrom_nonblock(100) }
71    u2.send("", 0, u1.getsockname)
72    assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
73      timeout(1) { IO.select [u1] }
74    }
75    mesg, inet_addr = u1.recvfrom_nonblock(100)
76    assert_equal("", mesg)
77  ensure
78    u1.close if u1
79    u2.close if u2
80  end
81
82  def test_udp_recv_nonblock
83    u1 = UDPSocket.new
84    u2 = UDPSocket.new
85    u1.bind("127.0.0.1", 0)
86    assert_raise(IO::WaitReadable) { u1.recv_nonblock(100) }
87    assert_raise(IO::WaitReadable, Errno::EINVAL) { u2.recv_nonblock(100) }
88    u2.send("aaa", 0, u1.getsockname)
89    IO.select [u1]
90    mesg = u1.recv_nonblock(100)
91    assert_equal("aaa", mesg)
92    assert_raise(IO::WaitReadable) { u1.recv_nonblock(100) }
93    u2.send("", 0, u1.getsockname)
94    assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
95      timeout(1) { IO.select [u1] }
96    }
97    mesg = u1.recv_nonblock(100)
98    assert_equal("", mesg)
99  ensure
100    u1.close if u1
101    u2.close if u2
102  end
103
104  def test_socket_recvfrom_nonblock
105    s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
106    s1.bind(Socket.sockaddr_in(0, "127.0.0.1"))
107    s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
108    assert_raise(IO::WaitReadable) { s1.recvfrom_nonblock(100) }
109    assert_raise(IO::WaitReadable, Errno::EINVAL) { s2.recvfrom_nonblock(100) }
110    s2.send("aaa", 0, s1.getsockname)
111    IO.select [s1]
112    mesg, sockaddr = s1.recvfrom_nonblock(100)
113    assert_equal("aaa", mesg)
114    port, addr = Socket.unpack_sockaddr_in(sockaddr)
115    s2_port, s2_addr = Socket.unpack_sockaddr_in(s2.getsockname)
116    assert_equal(s2_port, port)
117  ensure
118    s1.close if s1
119    s2.close if s2
120  end
121
122  def tcp_pair
123    serv = TCPServer.new("127.0.0.1", 0)
124    af, port, host, addr = serv.addr
125    c = TCPSocket.new(addr, port)
126    s = serv.accept
127    if block_given?
128      begin
129        yield c, s
130      ensure
131        c.close if !c.closed?
132        s.close if !s.closed?
133      end
134    else
135      return c, s
136    end
137  ensure
138    serv.close if serv && !serv.closed?
139  end
140
141  def udp_pair
142    s1 = UDPSocket.new
143    s1.bind('127.0.0.1', 0)
144    af, port1, host, addr1 = s1.addr
145
146    s2 = UDPSocket.new
147    s2.bind('127.0.0.1', 0)
148    af, port2, host, addr2 = s2.addr
149
150    s1.connect(addr2, port2)
151    s2.connect(addr1, port1)
152
153    if block_given?
154      begin
155        yield s1, s2
156      ensure
157        s1.close if !s1.closed?
158        s2.close if !s2.closed?
159      end
160    else
161      return s1, s2
162    end
163  end
164
165  def test_tcp_recv_nonblock
166    c, s = tcp_pair
167    assert_raise(IO::WaitReadable) { c.recv_nonblock(100) }
168    assert_raise(IO::WaitReadable) { s.recv_nonblock(100) }
169    c.write("abc")
170    IO.select [s]
171    assert_equal("a", s.recv_nonblock(1))
172    assert_equal("bc", s.recv_nonblock(100))
173    assert_raise(IO::WaitReadable) { s.recv_nonblock(100) }
174  ensure
175    c.close if c
176    s.close if s
177  end
178
179  def test_read_nonblock
180    c, s = tcp_pair
181    assert_raise(IO::WaitReadable) { c.read_nonblock(100) }
182    assert_raise(IO::WaitReadable) { s.read_nonblock(100) }
183    c.write("abc")
184    IO.select [s]
185    assert_equal("a", s.read_nonblock(1))
186    assert_equal("bc", s.read_nonblock(100))
187    assert_raise(IO::WaitReadable) { s.read_nonblock(100) }
188  ensure
189    c.close if c
190    s.close if s
191  end
192
193=begin
194  def test_write_nonblock
195    c, s = tcp_pair
196    str = "a" * 10000
197    _, ws, _ = IO.select(nil, [c], nil)
198    assert_equal([c], ws)
199    ret = c.write_nonblock(str)
200    assert_operator(ret, :>, 0)
201    loop {
202      assert_raise(IO::WaitWritable) {
203        loop {
204          ret = c.write_nonblock(str)
205          assert_operator(ret, :>, 0)
206        }
207      }
208      _, ws, _ = IO.select(nil, [c], nil, 0)
209      break if !ws
210    }
211  ensure
212    c.close if c
213    s.close if s
214  end
215=end
216
217  def test_sendmsg_nonblock_error
218    udp_pair {|s1, s2|
219      begin
220        loop {
221          s1.sendmsg_nonblock("a" * 100000)
222        }
223      rescue NotImplementedError, Errno::ENOSYS
224        skip "sendmsg not implemented on this platform."
225      rescue Errno::EMSGSIZE
226        # UDP has 64K limit (if no Jumbograms).  No problem.
227      rescue Errno::EWOULDBLOCK
228        assert_kind_of(IO::WaitWritable, $!)
229      end
230    }
231  end
232
233  def test_recvmsg_nonblock_error
234    udp_pair {|s1, s2|
235      begin
236        s1.recvmsg_nonblock(4096)
237      rescue NotImplementedError
238        skip "recvmsg not implemented on this platform."
239      rescue Errno::EWOULDBLOCK
240        assert_kind_of(IO::WaitReadable, $!)
241      end
242    }
243  end
244
245  def test_recv_nonblock_error
246    tcp_pair {|c, s|
247      begin
248        c.recv_nonblock(4096)
249      rescue Errno::EWOULDBLOCK
250        assert_kind_of(IO::WaitReadable, $!)
251      end
252    }
253  end
254
255  def test_connect_nonblock_error
256    serv = TCPServer.new("127.0.0.1", 0)
257    af, port, host, addr = serv.addr
258    c = Socket.new(:INET, :STREAM)
259    begin
260      c.connect_nonblock(Socket.sockaddr_in(port, "127.0.0.1"))
261    rescue Errno::EINPROGRESS
262      assert_kind_of(IO::WaitWritable, $!)
263    end
264  ensure
265    serv.close if serv && !serv.closed?
266    c.close if c && !c.closed?
267  end
268
269  def test_accept_nonblock_error
270    serv = Socket.new(:INET, :STREAM)
271    serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
272    serv.listen(5)
273    port = serv.local_address.ip_port
274    begin
275      s, _ = serv.accept_nonblock
276    rescue Errno::EWOULDBLOCK
277      assert_kind_of(IO::WaitReadable, $!)
278    end
279  ensure
280    serv.close if serv && !serv.closed?
281    s.close if s && !s.closed?
282  end
283
284end if defined?(Socket)
285