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