blob: d8892cd5f061d3104142017b36e300bf8500868b (
plain)
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
132
|
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "TCPServer#accept" do
before :each do
@server = TCPServer.new("127.0.0.1", 0)
@port = @server.addr[1]
end
after :each do
@server.close unless @server.closed?
end
it "accepts a connection and returns a TCPSocket" do
data = nil
t = Thread.new do
client = @server.accept
client.should be_kind_of(TCPSocket)
data = client.read(5)
client << "goodbye"
client.close
end
Thread.pass while t.status and t.status != "sleep"
socket = TCPSocket.new('127.0.0.1', @port)
socket.write('hello')
socket.shutdown(1) # we are done with sending
socket.read.should == 'goodbye'
t.join
data.should == 'hello'
socket.close
end
it "can be interrupted by Thread#kill" do
t = Thread.new { @server.accept }
Thread.pass while t.status and t.status != "sleep"
# kill thread, ensure it dies in a reasonable amount of time
t.kill
a = 0
while t.alive? and a < 5000
sleep 0.001
a += 1
end
a.should < 5000
end
it "can be interrupted by Thread#raise" do
t = Thread.new {
-> {
@server.accept
}.should raise_error(Exception, "interrupted")
}
Thread.pass while t.status and t.status != "sleep"
t.raise Exception, "interrupted"
t.join
end
it "is automatically retried when interrupted by SIGVTALRM" do
t = Thread.new do
client = @server.accept
value = client.read(2)
client.close
value
end
Thread.pass while t.status and t.status != "sleep"
# Thread#backtrace uses SIGVTALRM on TruffleRuby and potentially other implementations.
# Sending a signal to a thread is not possible with Ruby APIs.
t.backtrace.join("\n").should =~ /in [`'](?:TCPServer#)?accept'/
socket = TCPSocket.new('127.0.0.1', @port)
socket.write("OK")
socket.close
t.value.should == "OK"
end
it "raises an IOError if the socket is closed" do
@server.close
-> { @server.accept }.should raise_error(IOError)
end
end
describe 'TCPServer#accept' do
SocketSpecs.each_ip_protocol do |family, ip_address|
before do
@server = TCPServer.new(ip_address, 0)
end
after do
@server.close
end
describe 'without a connected client' do
it 'blocks the caller' do
-> { @server.accept }.should block_caller
end
end
describe 'with a connected client' do
before do
@client = TCPSocket.new(ip_address, @server.connect_address.ip_port)
end
after do
@socket.close if @socket
@client.close
end
it 'returns a TCPSocket' do
@socket = @server.accept
@socket.should be_an_instance_of(TCPSocket)
end
platform_is_not :windows do
it "returns a TCPSocket which is set to nonblocking" do
require 'io/nonblock'
@socket = @server.accept
@socket.should.nonblock?
end
end
it "returns a TCPSocket which is set to close on exec" do
@socket = @server.accept
@socket.should.close_on_exec?
end
end
end
end
|