rubysl-socket 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/lib/rubysl/socket.rb +2 -0
  7. data/lib/rubysl/socket/socket.rb +1210 -0
  8. data/lib/{rubysl-socket → rubysl/socket}/version.rb +1 -1
  9. data/lib/socket.rb +1 -0
  10. data/rubysl-socket.gemspec +17 -18
  11. data/spec/addrinfo/afamily_spec.rb +5 -0
  12. data/spec/addrinfo/bind_spec.rb +5 -0
  13. data/spec/addrinfo/canonname_spec.rb +5 -0
  14. data/spec/addrinfo/connect_from_spec.rb +5 -0
  15. data/spec/addrinfo/connect_spec.rb +5 -0
  16. data/spec/addrinfo/connect_to_spec.rb +5 -0
  17. data/spec/addrinfo/family_addrinfo_spec.rb +5 -0
  18. data/spec/addrinfo/foreach_spec.rb +5 -0
  19. data/spec/addrinfo/getaddrinfo_spec.rb +5 -0
  20. data/spec/addrinfo/getnameinfo_spec.rb +5 -0
  21. data/spec/addrinfo/inspect_sockaddr_spec.rb +5 -0
  22. data/spec/addrinfo/inspect_spec.rb +5 -0
  23. data/spec/addrinfo/ip_address_spec.rb +5 -0
  24. data/spec/addrinfo/ip_port_spec.rb +5 -0
  25. data/spec/addrinfo/ip_spec.rb +9 -0
  26. data/spec/addrinfo/ip_unpack_spec.rb +5 -0
  27. data/spec/addrinfo/ipv4_loopback_spec.rb +5 -0
  28. data/spec/addrinfo/ipv4_multicast_spec.rb +5 -0
  29. data/spec/addrinfo/ipv4_private_spec.rb +5 -0
  30. data/spec/addrinfo/ipv4_spec.rb +5 -0
  31. data/spec/addrinfo/ipv6_linklocal_spec.rb +5 -0
  32. data/spec/addrinfo/ipv6_loopback_spec.rb +5 -0
  33. data/spec/addrinfo/ipv6_mc_global_spec.rb +5 -0
  34. data/spec/addrinfo/ipv6_mc_linklocal_spec.rb +5 -0
  35. data/spec/addrinfo/ipv6_mc_nodelocal_spec.rb +5 -0
  36. data/spec/addrinfo/ipv6_mc_orglocal_spec.rb +5 -0
  37. data/spec/addrinfo/ipv6_mc_sitelocal_spec.rb +5 -0
  38. data/spec/addrinfo/ipv6_multicast_spec.rb +5 -0
  39. data/spec/addrinfo/ipv6_sitelocal_spec.rb +5 -0
  40. data/spec/addrinfo/ipv6_spec.rb +5 -0
  41. data/spec/addrinfo/ipv6_to_ipv4_spec.rb +5 -0
  42. data/spec/addrinfo/ipv6_unspecified_spec.rb +5 -0
  43. data/spec/addrinfo/ipv6_v4compat_spec.rb +5 -0
  44. data/spec/addrinfo/ipv6_v4mapped_spec.rb +5 -0
  45. data/spec/addrinfo/listen_spec.rb +5 -0
  46. data/spec/addrinfo/marshal_dump_spec.rb +5 -0
  47. data/spec/addrinfo/marshal_load_spec.rb +5 -0
  48. data/spec/addrinfo/pfamily_spec.rb +5 -0
  49. data/spec/addrinfo/protocol_spec.rb +5 -0
  50. data/spec/addrinfo/socktype_spec.rb +5 -0
  51. data/spec/addrinfo/tcp_spec.rb +5 -0
  52. data/spec/addrinfo/to_s_spec.rb +5 -0
  53. data/spec/addrinfo/to_sockaddr_spec.rb +5 -0
  54. data/spec/addrinfo/udp_spec.rb +5 -0
  55. data/spec/addrinfo/unix_path_spec.rb +5 -0
  56. data/spec/addrinfo/unix_spec.rb +9 -0
  57. data/spec/basicsocket/close_read_spec.rb +42 -0
  58. data/spec/basicsocket/close_write_spec.rb +42 -0
  59. data/spec/basicsocket/do_not_reverse_lookup_spec.rb +78 -0
  60. data/spec/basicsocket/for_fd_spec.rb +37 -0
  61. data/spec/basicsocket/getpeername_spec.rb +24 -0
  62. data/spec/basicsocket/getsockname_spec.rb +27 -0
  63. data/spec/basicsocket/getsockopt_spec.rb +54 -0
  64. data/spec/basicsocket/ioctl_spec.rb +22 -0
  65. data/spec/basicsocket/recv_nonblock_spec.rb +6 -0
  66. data/spec/basicsocket/recv_spec.rb +76 -0
  67. data/spec/basicsocket/send_spec.rb +81 -0
  68. data/spec/basicsocket/setsockopt_spec.rb +333 -0
  69. data/spec/basicsocket/shutdown_spec.rb +5 -0
  70. data/spec/constants/constants_spec.rb +63 -0
  71. data/spec/fixtures/classes.rb +174 -0
  72. data/spec/fixtures/send_io.txt +1 -0
  73. data/spec/ipsocket/addr_spec.rb +72 -0
  74. data/spec/ipsocket/getaddress_spec.rb +26 -0
  75. data/spec/ipsocket/peeraddr_spec.rb +79 -0
  76. data/spec/ipsocket/recvfrom_spec.rb +64 -0
  77. data/spec/option/int_spec.rb +27 -0
  78. data/spec/option/linger_spec.rb +52 -0
  79. data/spec/option/new_spec.rb +32 -0
  80. data/spec/shared/pack_sockaddr.rb +26 -0
  81. data/spec/shared/partially_closable_sockets.rb +13 -0
  82. data/spec/shared/recv_nonblock.rb +33 -0
  83. data/spec/shared/socketpair.rb +35 -0
  84. data/spec/socket/accept_nonblock_spec.rb +27 -0
  85. data/spec/socket/accept_spec.rb +1 -0
  86. data/spec/socket/bind_spec.rb +80 -0
  87. data/spec/socket/connect_nonblock_spec.rb +62 -0
  88. data/spec/socket/connect_spec.rb +1 -0
  89. data/spec/socket/for_fd_spec.rb +29 -0
  90. data/spec/socket/getaddrinfo_spec.rb +120 -0
  91. data/spec/socket/gethostbyaddr_spec.rb +1 -0
  92. data/spec/socket/gethostbyname_spec.rb +26 -0
  93. data/spec/socket/gethostname_spec.rb +9 -0
  94. data/spec/socket/getnameinfo_spec.rb +57 -0
  95. data/spec/socket/getservbyname_spec.rb +24 -0
  96. data/spec/socket/listen_spec.rb +21 -0
  97. data/spec/socket/new_spec.rb +109 -0
  98. data/spec/socket/pack_sockaddr_in_spec.rb +6 -0
  99. data/spec/socket/pack_sockaddr_un_spec.rb +6 -0
  100. data/spec/socket/pair_spec.rb +6 -0
  101. data/spec/socket/recvfrom_nonblock_spec.rb +1 -0
  102. data/spec/socket/recvfrom_spec.rb +1 -0
  103. data/spec/socket/sockaddr_in_spec.rb +6 -0
  104. data/spec/socket/sockaddr_un_spec.rb +6 -0
  105. data/spec/socket/socket_spec.rb +37 -0
  106. data/spec/socket/socketpair_spec.rb +6 -0
  107. data/spec/socket/sysaccept_spec.rb +1 -0
  108. data/spec/socket/unpack_sockaddr_in_spec.rb +16 -0
  109. data/spec/socket/unpack_sockaddr_un_spec.rb +2 -0
  110. data/spec/tcpserver/accept_nonblock_spec.rb +30 -0
  111. data/spec/tcpserver/accept_spec.rb +60 -0
  112. data/spec/tcpserver/gets_spec.rb +17 -0
  113. data/spec/tcpserver/listen_spec.rb +1 -0
  114. data/spec/tcpserver/new_spec.rb +88 -0
  115. data/spec/tcpserver/output_spec.rb +8 -0
  116. data/spec/tcpserver/readpartial_spec.rb +8 -0
  117. data/spec/tcpserver/sysaccept_spec.rb +1 -0
  118. data/spec/tcpsocket/gethostbyname_spec.rb +62 -0
  119. data/spec/tcpsocket/new_spec.rb +5 -0
  120. data/spec/tcpsocket/open_spec.rb +5 -0
  121. data/spec/tcpsocket/partially_closable_spec.rb +20 -0
  122. data/spec/tcpsocket/recv_nonblock_spec.rb +31 -0
  123. data/spec/tcpsocket/setsockopt_spec.rb +49 -0
  124. data/spec/tcpsocket/shared/new.rb +85 -0
  125. data/spec/udpsocket/bind_spec.rb +33 -0
  126. data/spec/udpsocket/connect_spec.rb +1 -0
  127. data/spec/udpsocket/new_spec.rb +1 -0
  128. data/spec/udpsocket/open_spec.rb +12 -0
  129. data/spec/udpsocket/recvfrom_nonblock_spec.rb +1 -0
  130. data/spec/udpsocket/send_spec.rb +57 -0
  131. data/spec/unixserver/accept_nonblock_spec.rb +33 -0
  132. data/spec/unixserver/accept_spec.rb +64 -0
  133. data/spec/unixserver/for_fd_spec.rb +32 -0
  134. data/spec/unixserver/new_spec.rb +5 -0
  135. data/spec/unixserver/open_spec.rb +25 -0
  136. data/spec/unixserver/shared/new.rb +23 -0
  137. data/spec/unixsocket/addr_spec.rb +37 -0
  138. data/spec/unixsocket/new_spec.rb +5 -0
  139. data/spec/unixsocket/open_spec.rb +26 -0
  140. data/spec/unixsocket/pair_spec.rb +38 -0
  141. data/spec/unixsocket/partially_closable_spec.rb +25 -0
  142. data/spec/unixsocket/path_spec.rb +29 -0
  143. data/spec/unixsocket/peeraddr_spec.rb +29 -0
  144. data/spec/unixsocket/recv_io_spec.rb +40 -0
  145. data/spec/unixsocket/recvfrom_spec.rb +48 -0
  146. data/spec/unixsocket/send_io_spec.rb +30 -0
  147. data/spec/unixsocket/shared/new.rb +25 -0
  148. metadata +328 -89
  149. data/lib/rubysl-socket.rb +0 -7
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ ruby_version_is "1.9.2" do
4
+ describe "Socket::Option.int" do
5
+ it "creates a new Socket::Option for SO_LINGER" do
6
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 5)
7
+ so.family.should == Socket::Constants::AF_INET
8
+ so.level.should == Socket::Constants::SOL_SOCKET
9
+ so.optname.should == Socket::Constants::SO_KEEPALIVE
10
+ so.data.should == [5].pack('i')
11
+ end
12
+ end
13
+
14
+ describe "Socket::Option#int" do
15
+ it "returns int option" do
16
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 17)
17
+ so.int.should == 17
18
+
19
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 32765)
20
+ so.int.should == 32765
21
+ end
22
+ it "raises TypeError if option has not good size" do
23
+ so = Socket::Option.new(:UNSPEC, :SOCKET, :KEEPALIVE, [0, 0].pack('i*'))
24
+ lambda { so.int }.should raise_error(TypeError)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ ruby_version_is "1.9.2" do
4
+ describe "Socket::Option.linger" do
5
+ it "creates a new Socket::Option for SO_LINGER" do
6
+ so = Socket::Option.linger(1, 10)
7
+ so.family.should == Socket::Constants::AF_UNSPEC
8
+ so.level.should == Socket::Constants::SOL_SOCKET
9
+ so.optname.should == Socket::Constants::SO_LINGER
10
+ so.data.should == [1, 10].pack('i*')
11
+ end
12
+ it "accepts boolean as onoff argument" do
13
+ so = Socket::Option.linger(false, 0)
14
+ so.data.should == [0, 0].pack('i*')
15
+
16
+ so = Socket::Option.linger(true, 1)
17
+ so.data.should == [1, 1].pack('i*')
18
+ end
19
+ end
20
+
21
+ describe "Socket::Option#linger" do
22
+ it "returns linger option" do
23
+ so = Socket::Option.linger(0, 5)
24
+ ary = so.linger
25
+ ary[0].should be_false
26
+ ary[1].should == 5
27
+
28
+ so = Socket::Option.linger(false, 4)
29
+ ary = so.linger
30
+ ary[0].should be_false
31
+ ary[1].should == 4
32
+
33
+ so = Socket::Option.linger(1, 10)
34
+ ary = so.linger
35
+ ary[0].should be_true
36
+ ary[1].should == 10
37
+
38
+ so = Socket::Option.linger(true, 9)
39
+ ary = so.linger
40
+ ary[0].should be_true
41
+ ary[1].should == 9
42
+ end
43
+ it "raises TypeError if not a SO_LINGER" do
44
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :KEEPALIVE, 1)
45
+ lambda { so.linger }.should raise_error(TypeError)
46
+ end
47
+ it "raises TypeError if option has not good size" do
48
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :LINGER, 1)
49
+ lambda { so.linger }.should raise_error(TypeError)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ ruby_version_is "1.9.2" do
4
+ describe "Socket::Option.new" do
5
+ it "should accept integers" do
6
+ so = Socket::Option.new(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, [0].pack('i'))
7
+ so.family.should == Socket::AF_INET
8
+ so.level.should == Socket::SOL_SOCKET
9
+ so.optname.should == Socket::SO_KEEPALIVE
10
+ end
11
+ it "should accept symbols" do
12
+ so = Socket::Option.new(:AF_INET, :SOL_SOCKET, :SO_KEEPALIVE, [0].pack('i'))
13
+ so.family.should == Socket::AF_INET
14
+ so.level.should == Socket::SOL_SOCKET
15
+ so.optname.should == Socket::SO_KEEPALIVE
16
+
17
+ so = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [0].pack('i'))
18
+ so.family.should == Socket::AF_INET
19
+ so.level.should == Socket::SOL_SOCKET
20
+ so.optname.should == Socket::SO_KEEPALIVE
21
+ end
22
+ it "should raise error on unknown family" do
23
+ lambda { Socket::Option.new(:INET4, :SOCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
24
+ end
25
+ it "should raise error on unknown level" do
26
+ lambda { Socket::Option.new(:INET, :ROCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
27
+ end
28
+ it "should raise error on unknown option name" do
29
+ lambda { Socket::Option.new(:INET, :SOCKET, :ALIVE, [0].pack('i')) }.should raise_error(SocketError)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ describe :socket_pack_sockaddr_in, :shared => true do
2
+ it "packs and unpacks" do
3
+ sockaddr_in = Socket.pack_sockaddr_in 0, nil
4
+ port, addr = Socket.unpack_sockaddr_in(sockaddr_in)
5
+ ["127.0.0.1", "::1"].include?(addr).should == true
6
+ port.should == 0
7
+
8
+ sockaddr_in = Socket.pack_sockaddr_in 0, ''
9
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '0.0.0.0']
10
+
11
+ sockaddr_in = Socket.pack_sockaddr_in 80, '127.0.0.1'
12
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
13
+
14
+ sockaddr_in = Socket.pack_sockaddr_in '80', '127.0.0.1'
15
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
16
+ end
17
+ end
18
+
19
+ describe :socket_pack_sockaddr_un, :shared => true do
20
+ not_supported_on :jruby, :windows do
21
+ it "packs and unpacks" do
22
+ sockaddr_un = Socket.pack_sockaddr_un '/tmp/s'
23
+ Socket.unpack_sockaddr_un(sockaddr_un).should == '/tmp/s'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ describe "partially closable sockets", :shared => true do
2
+ specify "if the write end is closed then the other side can read past EOF without blocking" do
3
+ @s1.write("foo")
4
+ @s1.close_write
5
+ @s2.read("foo".size + 1).should == "foo"
6
+ end
7
+
8
+ specify "closing the write end ensures that the other side can read until EOF" do
9
+ @s1.write("hello world")
10
+ @s1.close_write
11
+ @s2.read.should == "hello world"
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ describe :socket_recv_nonblock, :shared => true do
2
+ not_supported_on :jruby do
3
+ before :each do
4
+ @s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
5
+ @s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
6
+ end
7
+
8
+ after :each do
9
+ @s1.close unless @s1.closed?
10
+ @s2.close unless @s2.closed?
11
+ end
12
+
13
+ it "raises EAGAIN if there's no data available" do
14
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
15
+ lambda { @s1.recv_nonblock(5)}.should raise_error(Errno::EAGAIN)
16
+ end
17
+
18
+ it "receives data after it's ready" do
19
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
20
+ @s2.send("aaa", 0, @s1.getsockname)
21
+ IO.select([@s1], nil, nil, 2)
22
+ @s1.recv_nonblock(5).should == "aaa"
23
+ end
24
+
25
+ it "does not block if there's no data available" do
26
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
27
+ @s2.send("a", 0, @s1.getsockname)
28
+ IO.select([@s1], nil, nil, 2)
29
+ @s1.recv_nonblock(1).should == "a"
30
+ lambda { @s1.recv_nonblock(5)}.should raise_error(Errno::EAGAIN)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ describe :socket_socketpair, :shared => true do
2
+ not_supported_on :jruby, :windows do
3
+ it "ensures the returned sockets are connected" do
4
+ s1, s2 = Socket.socketpair(Socket::AF_UNIX, 1, 0)
5
+ s1.puts("test")
6
+ s2.gets.should == "test\n"
7
+ s1.close
8
+ s2.close
9
+ end
10
+ end
11
+
12
+ it "only allows Socket constants as strings" do
13
+ [ :DGRAM, :RAW, :RDM, :SEQPACKET, :STREAM ].each do |socket_type|
14
+ lambda { Socket.socketpair(Socket::AF_UNIX, "SOCK_#{socket_type}", 0) }.should_not raise_error(SocketError)
15
+ end
16
+ end
17
+
18
+ ruby_version_is "1.9" do
19
+ it "raises SocketError if given symbol is not a Socket constants reference" do
20
+ lambda { Socket.socketpair(Socket::AF_UNIX, :NO_EXIST, 0) }.should raise_error(SocketError)
21
+ end
22
+
23
+ it "only allows Socket constants as symbols" do
24
+ [ :DGRAM, :RAW, :RDM, :SEQPACKET, :STREAM ].each do |socket_type|
25
+ lambda { Socket.socketpair(Socket::AF_UNIX, socket_type, 0) }.should_not raise_error(SocketError)
26
+ end
27
+ end
28
+ end
29
+
30
+ ruby_version_is ""..."1.9" do
31
+ it "raises Errno::EPROTONOSUPPORT if socket type is not a String or Integer" do
32
+ lambda { Socket.socketpair(Socket::AF_UNIX, :DGRAM, 0) }.should raise_error(Errno::EPROTONOSUPPORT)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ require 'socket'
4
+
5
+ describe "Socket#accept_nonblock" do
6
+ before :each do
7
+ @hostname = "127.0.0.1"
8
+ @addr = Socket.sockaddr_in(0, @hostname)
9
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
10
+ @socket.bind(@addr)
11
+ @socket.listen(1)
12
+ end
13
+
14
+ after :each do
15
+ @socket.close
16
+ end
17
+
18
+ it "raises Errno::EAGAIN if the connection is not accepted yet" do
19
+ lambda { @socket.accept_nonblock }.should raise_error(Errno::EAGAIN)
20
+ end
21
+
22
+ ruby_version_is "1.9.2" do
23
+ it "raises IO::WaitReadable if the connection is not accepted yet" do
24
+ lambda { @socket.accept_nonblock }.should raise_error(IO::WaitReadable)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
@@ -0,0 +1,80 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ include Socket::Constants
4
+
5
+ describe "Socket#bind on SOCK_DGRAM socket" do
6
+ before :each do
7
+ @sock = Socket.new(AF_INET, SOCK_DGRAM, 0);
8
+ @sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1");
9
+ end
10
+
11
+ after :each do
12
+ @sock.closed?.should be_false
13
+ @sock.close
14
+ end
15
+
16
+ it "binds to a port" do
17
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
18
+ end
19
+
20
+ it "returns 0 if successful" do
21
+ @sock.bind(@sockaddr).should == 0
22
+ end
23
+
24
+ it "raises Errno::EINVAL when binding to an already bound port" do
25
+ @sock.bind(@sockaddr);
26
+
27
+ lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL);
28
+ end
29
+
30
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
31
+ sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1");
32
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL)
33
+ end
34
+
35
+ platform_is_not :os => [:windows, :cygwin] do
36
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
37
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1");
38
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "Socket#bind on SOCK_STREAM socket" do
44
+ before :each do
45
+ @sock = Socket.new(AF_INET, SOCK_STREAM, 0);
46
+ @sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
47
+ @sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1");
48
+ end
49
+
50
+ after :each do
51
+ @sock.closed?.should be_false
52
+ @sock.close
53
+ end
54
+
55
+ it "binds to a port" do
56
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
57
+ end
58
+
59
+ it "returns 0 if successful" do
60
+ @sock.bind(@sockaddr).should == 0
61
+ end
62
+
63
+ it "raises Errno::EINVAL when binding to an already bound port" do
64
+ @sock.bind(@sockaddr);
65
+
66
+ lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL);
67
+ end
68
+
69
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
70
+ sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1");
71
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL)
72
+ end
73
+
74
+ platform_is_not :os => [:windows, :cygwin] do
75
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
76
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1");
77
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ require 'socket'
4
+
5
+ describe "Socket#connect_nonblock" do
6
+ before :each do
7
+ @hostname = "127.0.0.1"
8
+ @addr = Socket.sockaddr_in(SocketSpecs.port, @hostname)
9
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
10
+ @thread = nil
11
+ end
12
+
13
+ after :each do
14
+ @socket.close
15
+ @thread.join if @thread
16
+ end
17
+
18
+ it "connects the socket to the remote side" do
19
+ ready = false
20
+ @thread = Thread.new do
21
+ server = TCPServer.new(@hostname, SocketSpecs.port)
22
+ ready = true
23
+ conn = server.accept
24
+ conn << "hello!"
25
+ conn.close
26
+ server.close
27
+ end
28
+
29
+ Thread.pass while (@thread.status and @thread.status != 'sleep') or !ready
30
+
31
+ begin
32
+ @socket.connect_nonblock(@addr)
33
+ rescue Errno::EINPROGRESS
34
+ end
35
+
36
+ IO.select nil, [@socket]
37
+
38
+ begin
39
+ @socket.connect_nonblock(@addr)
40
+ rescue Errno::EISCONN
41
+ # Not all OS's use this errno, so we trap and ignore it
42
+ end
43
+
44
+ @socket.read(6).should == "hello!"
45
+ end
46
+
47
+ platform_is_not :freebsd do
48
+ it "raises Errno::EINPROGRESS when the connect would block" do
49
+ lambda do
50
+ @socket.connect_nonblock(@addr)
51
+ end.should raise_error(Errno::EINPROGRESS)
52
+ end
53
+
54
+ ruby_version_is "1.9.2" do
55
+ it "raises Errno::EINPROGRESS with IO::WaitWritable mixed in when the connect would block" do
56
+ lambda do
57
+ @socket.connect_nonblock(@addr)
58
+ end.should raise_error(IO::WaitWritable)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+ require 'socket'
3
+
4
+ describe "Socket.for_fd" do
5
+ before :each do
6
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
7
+ @client = TCPSocket.open("127.0.0.1", SocketSpecs.port)
8
+ end
9
+
10
+ after :each do
11
+ @socket.shutdown Socket::SHUT_RD if @socket
12
+ @client.shutdown Socket::SHUT_WR
13
+
14
+ @host.close if @host
15
+ @server.close
16
+ end
17
+
18
+ it "creates a new Socket that aliases the existing Socket's file descriptor" do
19
+ @socket = Socket.for_fd(@client.fileno)
20
+ @socket.fileno.should == @client.fileno
21
+
22
+ @socket.send("foo", 0)
23
+ @client.send("bar", 0)
24
+
25
+ @host = @server.accept
26
+ @host.read(3).should == "foo"
27
+ @host.read(3).should == "bar"
28
+ end
29
+ end
@@ -0,0 +1,120 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ require 'socket'
4
+
5
+ describe "Socket#getaddrinfo" do
6
+ before :all do
7
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
8
+ end
9
+
10
+ before :each do
11
+ BasicSocket.do_not_reverse_lookup = true
12
+ end
13
+
14
+ after :each do
15
+ BasicSocket.do_not_reverse_lookup = false
16
+ end
17
+
18
+ after :all do
19
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
20
+ end
21
+
22
+ it "gets the address information" do
23
+ expected = []
24
+ # The check for AP_INET6's class is needed because ipaddr.rb adds
25
+ # fake AP_INET6 even in case when IPv6 is not really supported.
26
+ # Without such check, this test might fail when ipaddr was required
27
+ # by some other specs.
28
+ if (Socket.constants.include? 'AF_INET6') &&
29
+ (Socket::AF_INET6.class != Object) then
30
+ expected.concat [
31
+ ['AF_INET6', 80, SocketSpecs.hostname, '::1', Socket::AF_INET6,
32
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
33
+ ['AF_INET6', 80, SocketSpecs.hostname, '::1', Socket::AF_INET6,
34
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
35
+ ['AF_INET6', 80, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
36
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
37
+ ['AF_INET6', 80, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
38
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
39
+ ]
40
+ end
41
+
42
+ expected.concat [
43
+ ['AF_INET', 80, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
44
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
45
+ ['AF_INET', 80, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
46
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
47
+ ]
48
+
49
+ addrinfo = Socket.getaddrinfo SocketSpecs.hostname, 'http'
50
+ addrinfo.each do |a|
51
+ case a.last
52
+ when Socket::IPPROTO_UDP, Socket::IPPROTO_TCP
53
+ expected.should include(a)
54
+ else
55
+ # don't check this. It's some weird protocol we don't know about
56
+ # so we can't spec it.
57
+ end
58
+ end
59
+ end
60
+
61
+ # #getaddrinfo will return a INADDR_ANY address (0.0.0.0
62
+ # or "::") if it's a passive socket. In the case of non-passive
63
+ # sockets (AI_PASSIVE not set) it should return the loopback
64
+ # address (127.0.0.1 or "::1".
65
+
66
+ it "accepts empty addresses for IPv4 passive sockets" do
67
+ res = Socket::getaddrinfo(nil, "http",
68
+ Socket::AF_INET,
69
+ Socket::SOCK_STREAM,
70
+ Socket::IPPROTO_TCP,
71
+ Socket::AI_PASSIVE)
72
+
73
+ expected = [["AF_INET", 80, "0.0.0.0", "0.0.0.0", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
74
+ ["AF_INET", 80, "", "0.0.0.0", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
75
+ res.each do |a|
76
+ expected.should include(a)
77
+ end
78
+ end
79
+
80
+ it "accepts empty addresses for IPv4 non-passive sockets" do
81
+ res = Socket::getaddrinfo(nil, "http",
82
+ Socket::AF_INET,
83
+ Socket::SOCK_STREAM,
84
+ Socket::IPPROTO_TCP,
85
+ 0)
86
+
87
+ expected = [["AF_INET", 80, "127.0.0.1", "127.0.0.1", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
88
+ res.should == expected
89
+ end
90
+
91
+
92
+ it "accepts empty addresses for IPv6 passive sockets" do
93
+ res = Socket::getaddrinfo(nil, "http",
94
+ Socket::AF_INET6,
95
+ Socket::SOCK_STREAM,
96
+ Socket::IPPROTO_TCP,
97
+ Socket::AI_PASSIVE)
98
+
99
+ expected = [
100
+ ["AF_INET6", 80, "::", "::", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
101
+ ["AF_INET6", 80, "0:0:0:0:0:0:0:0", "0:0:0:0:0:0:0:0", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
102
+ ]
103
+ res.each { |a| expected.should include (a) }
104
+ end
105
+
106
+ it "accepts empty addresses for IPv6 non-passive sockets" do
107
+ res = Socket::getaddrinfo(nil, "http",
108
+ Socket::AF_INET6,
109
+ Socket::SOCK_STREAM,
110
+ Socket::IPPROTO_TCP,
111
+ 0)
112
+
113
+ expected = [
114
+ ["AF_INET6", 80, "::1", "::1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
115
+ ["AF_INET6", 80, "0:0:0:0:0:0:0:1", "0:0:0:0:0:0:0:1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
116
+ ]
117
+ res.each { |a| expected.should include (a) }
118
+ end
119
+ end
120
+