1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "TCPServer.new" do
after :each do
@server.close if @server && [email protected]?
end
it "binds to a host and a port" do
@server = TCPServer.new('127.0.0.1', 0)
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Integer)
# on some platforms (Mac), MRI
# returns comma at the end.
addr[2].should =~ /^#{SocketSpecs.hostname}\b/
addr[3].should == '127.0.0.1'
end
it "binds to localhost and a port with either IPv4 or IPv6" do
@server = TCPServer.new(SocketSpecs.hostname, 0)
addr = @server.addr
addr[1].should be_kind_of(Integer)
if addr[0] == 'AF_INET'
addr[2].should =~ /^#{SocketSpecs.hostname}\b/
addr[3].should == '127.0.0.1'
else
addr[2].should =~ /^#{SocketSpecs.hostname('::1')}\b/
addr[3].should == '::1'
end
end
it "binds to INADDR_ANY if the hostname is empty" do
@server = TCPServer.new('', 0)
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Integer)
addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0'
end
it "binds to INADDR_ANY if the hostname is empty and the port is a string" do
@server = TCPServer.new('', '0')
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Integer)
addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0'
end
it "binds to a port if the port is explicitly nil" do
@server = TCPServer.new('', nil)
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Integer)
addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0'
end
it "binds to a port if the port is an empty string" do
@server = TCPServer.new('', '')
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Integer)
addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0'
end
it "coerces port to string, then determines port from that number or service name" do
-> { TCPServer.new(SocketSpecs.hostname, Object.new) }.should raise_error(TypeError)
port = Object.new
port.should_receive(:to_str).and_return("0")
@server = TCPServer.new(SocketSpecs.hostname, port)
addr = @server.addr
addr[1].should be_kind_of(Integer)
# TODO: This should also accept strings like 'https', but I don't know how to
# pick such a service port that will be able to reliably bind...
end
it "has a single argument form and treats it as a port number" do
@server = TCPServer.new(0)
addr = @server.addr
addr[1].should be_kind_of(Integer)
end
it "coerces port to a string when it is the only argument" do
-> { TCPServer.new(Object.new) }.should raise_error(TypeError)
port = Object.new
port.should_receive(:to_str).and_return("0")
@server = TCPServer.new(port)
addr = @server.addr
addr[1].should be_kind_of(Integer)
end
it "raises Errno::EADDRNOTAVAIL when the address is unknown" do
-> { TCPServer.new("1.2.3.4", 0) }.should raise_error(Errno::EADDRNOTAVAIL)
end
# There is no way to make this fail-proof on all machines, because
# DNS servers like opendns return A records for ANY host, including
# traditionally invalidly named ones.
quarantine! do
it "raises a SocketError when the host is unknown" do
-> {
TCPServer.new("--notavalidname", 0)
}.should raise_error(SocketError)
end
end
it "raises Errno::EADDRINUSE when address is already in use" do
@server = TCPServer.new('127.0.0.1', 0)
-> {
@server = TCPServer.new('127.0.0.1', @server.addr[1])
}.should raise_error(Errno::EADDRINUSE)
end
platform_is_not :windows, :aix do
# A known bug in AIX. getsockopt(2) does not properly set
# the fifth argument for SO_REUSEADDR.
it "sets SO_REUSEADDR on the resulting server" do
@server = TCPServer.new('127.0.0.1', 0)
@server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00"
@server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0
end
end
end
|