cool.io 1.0.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/test.yaml +54 -0
- data/.gitignore +30 -0
- data/.rspec +3 -0
- data/{CHANGES → CHANGES.md} +175 -79
- data/{README.markdown → README.md} +43 -49
- data/Rakefile +44 -69
- data/appveyor.yml +18 -0
- data/cool.io.gemspec +18 -131
- data/examples/callbacked_echo_server.rb +24 -0
- data/ext/cool.io/buffer.c +781 -0
- data/ext/cool.io/cool.io.h +13 -0
- data/ext/cool.io/cool.io_ext.c +1 -0
- data/ext/cool.io/ev_wrap.h +4 -2
- data/ext/cool.io/extconf.rb +27 -16
- data/ext/cool.io/iowatcher.c +17 -8
- data/ext/cool.io/loop.c +36 -84
- data/ext/cool.io/stat_watcher.c +103 -25
- data/ext/cool.io/timer_watcher.c +3 -3
- data/ext/cool.io/utils.c +5 -0
- data/ext/cool.io/watcher.h +1 -1
- data/ext/libev/Changes +152 -3
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +8 -8
- data/ext/libev/ev.c +1719 -348
- data/ext/libev/ev.h +146 -118
- data/ext/libev/ev_epoll.c +71 -20
- data/ext/libev/ev_kqueue.c +36 -16
- data/ext/libev/ev_poll.c +14 -11
- data/ext/libev/ev_port.c +43 -18
- data/ext/libev/ev_select.c +82 -25
- data/ext/libev/ev_vars.h +28 -21
- data/ext/libev/ev_win32.c +19 -10
- data/ext/libev/ev_wrap.h +166 -152
- data/ext/libev/test_libev_win32.c +1 -1
- data/gems.rb +9 -0
- data/lib/cool.io/async_watcher.rb +1 -1
- data/lib/cool.io/custom_require.rb +9 -0
- data/lib/cool.io/dns_resolver.rb +30 -22
- data/lib/cool.io/dsl.rb +32 -28
- data/lib/cool.io/io.rb +55 -35
- data/lib/cool.io/iowatcher.rb +1 -1
- data/lib/cool.io/listener.rb +35 -17
- data/lib/cool.io/loop.rb +17 -25
- data/lib/cool.io/meta.rb +6 -5
- data/lib/cool.io/server.rb +5 -4
- data/lib/cool.io/socket.rb +41 -30
- data/lib/cool.io/timer_watcher.rb +1 -1
- data/lib/cool.io/version.rb +7 -0
- data/lib/cool.io.rb +11 -10
- data/lib/coolio.rb +1 -1
- data/libev_ruby_gil.diff +175 -0
- data/libev_win_select.diff +130 -0
- data/spec/async_watcher_spec.rb +5 -5
- data/spec/dns_spec.rb +27 -8
- data/spec/iobuffer_spec.rb +147 -0
- data/spec/spec_helper.rb +15 -1
- data/spec/stat_watcher_spec.rb +81 -0
- data/spec/tcp_server_spec.rb +225 -0
- data/spec/tcp_socket_spec.rb +185 -0
- data/spec/timer_watcher_spec.rb +23 -19
- data/spec/udp_socket_spec.rb +58 -0
- data/spec/unix_listener_spec.rb +8 -8
- data/spec/unix_server_spec.rb +10 -8
- metadata +109 -112
- data/VERSION +0 -1
- data/examples/httpclient.rb +0 -38
- data/ext/http11_client/.gitignore +0 -5
- data/ext/http11_client/LICENSE +0 -31
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -300
- data/ext/http11_client/http11_parser.c +0 -403
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -173
- data/lib/cool.io/eventmachine.rb +0 -234
- data/lib/cool.io/http_client.rb +0 -419
- data/lib/rev.rb +0 -4
- data/spec/possible_tests/schedules_other_threads.rb +0 -48
- data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
- data/spec/possible_tests/test_resolves.rb +0 -27
- data/spec/possible_tests/test_write_during_resolve.rb +0 -27
- data/spec/possible_tests/works_straight.rb +0 -71
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
TIMEOUT = 0.010
|
|
4
|
+
HOST = '127.0.0.1'
|
|
5
|
+
PORT = unused_port
|
|
6
|
+
|
|
7
|
+
def send_data(data)
|
|
8
|
+
io = TCPSocket.new('127.0.0.1', PORT)
|
|
9
|
+
begin
|
|
10
|
+
io.write data
|
|
11
|
+
ensure
|
|
12
|
+
io.close
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class MyConnection < Coolio::Socket
|
|
17
|
+
attr_accessor :data, :connected, :closed
|
|
18
|
+
|
|
19
|
+
def initialize(io, on_message)
|
|
20
|
+
super(io)
|
|
21
|
+
@on_message = on_message
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def on_connect
|
|
25
|
+
@connected = true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def on_close
|
|
29
|
+
@closed = true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def on_read(data)
|
|
33
|
+
@on_message.call(data)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@data = ""
|
|
38
|
+
def on_message(data)
|
|
39
|
+
@data = data
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_run(data = nil)
|
|
43
|
+
reactor = Coolio::Loop.new
|
|
44
|
+
server = Cool.io::TCPServer.new(HOST, PORT, MyConnection, method(:on_message))
|
|
45
|
+
reactor.attach(server)
|
|
46
|
+
thread = Thread.new { reactor.run }
|
|
47
|
+
send_data(data) if data
|
|
48
|
+
sleep TIMEOUT
|
|
49
|
+
reactor.stop
|
|
50
|
+
server.detach
|
|
51
|
+
send_data('') # to leave from blocking loop
|
|
52
|
+
thread.join
|
|
53
|
+
@data
|
|
54
|
+
ensure
|
|
55
|
+
server.close
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_run_once(data = nil)
|
|
59
|
+
reactor = Coolio::Loop.new
|
|
60
|
+
server = Cool.io::TCPServer.new(HOST, PORT, MyConnection, method(:on_message))
|
|
61
|
+
reactor.attach(server)
|
|
62
|
+
thread = Thread.new do
|
|
63
|
+
reactor.run_once # on_connect
|
|
64
|
+
reactor.run_once # on_read
|
|
65
|
+
end
|
|
66
|
+
send_data(data) if data
|
|
67
|
+
thread.join
|
|
68
|
+
server.detach
|
|
69
|
+
@data
|
|
70
|
+
ensure
|
|
71
|
+
server.close
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_run_once_timeout(timeout = TIMEOUT)
|
|
75
|
+
@data = ""
|
|
76
|
+
reactor = Coolio::Loop.new
|
|
77
|
+
server = Cool.io::TCPServer.new(HOST, PORT, MyConnection, method(:on_message))
|
|
78
|
+
reactor.attach(server)
|
|
79
|
+
thread = Thread.new { reactor.run_once(timeout) }
|
|
80
|
+
sleep timeout
|
|
81
|
+
server.detach
|
|
82
|
+
thread.join
|
|
83
|
+
@data
|
|
84
|
+
ensure
|
|
85
|
+
server.close
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_run_timeout(data = nil, timeout = TIMEOUT)
|
|
89
|
+
reactor = Coolio::Loop.new
|
|
90
|
+
server = Cool.io::TCPServer.new(HOST, PORT, MyConnection, method(:on_message))
|
|
91
|
+
reactor.attach(server)
|
|
92
|
+
running = true
|
|
93
|
+
thread = Thread.new do
|
|
94
|
+
while running and reactor.has_active_watchers?
|
|
95
|
+
reactor.run_once(timeout)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
send_data(data) if data
|
|
99
|
+
sleep timeout
|
|
100
|
+
server.detach
|
|
101
|
+
running = false # another send is not required
|
|
102
|
+
thread.join
|
|
103
|
+
@data
|
|
104
|
+
ensure
|
|
105
|
+
server.close
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# This test should work on Windows
|
|
109
|
+
describe Coolio::TCPServer do
|
|
110
|
+
|
|
111
|
+
it '#run' do
|
|
112
|
+
expect(test_run("hello")).to eq("hello")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it '#run_once' do
|
|
116
|
+
expect(test_run_once("hello")).to eq("hello")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it '#run_once(timeout)' do
|
|
120
|
+
test_run_once_timeout # should not block
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it '#run_once(-timeout)' do
|
|
124
|
+
expect { test_run_once_timeout(-0.1) }.to raise_error(ArgumentError)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it '#run(timeout)' do
|
|
128
|
+
expect(test_run_timeout("hello")).to eq("hello")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
describe "functionaltest" do
|
|
132
|
+
let :loop do
|
|
133
|
+
Coolio::Loop.new
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
let :port do
|
|
137
|
+
unused_port
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "#on_connect" do
|
|
141
|
+
class ServerOnConnect < Coolio::Socket
|
|
142
|
+
def initialize(io, cb)
|
|
143
|
+
super(io)
|
|
144
|
+
@cb = cb
|
|
145
|
+
end
|
|
146
|
+
def on_connect
|
|
147
|
+
@cb.call
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "connected socket called on_connect" do
|
|
152
|
+
begin
|
|
153
|
+
connected = false
|
|
154
|
+
server = Cool.io::TCPServer.new("localhost", port, ServerOnConnect, proc { connected = true })
|
|
155
|
+
loop.attach server
|
|
156
|
+
s = TCPSocket.open("localhost", port)
|
|
157
|
+
loop.run_once
|
|
158
|
+
s.close
|
|
159
|
+
expect(connected).to eq true
|
|
160
|
+
ensure
|
|
161
|
+
server.detach
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "#on_close" do
|
|
167
|
+
class ServerOnClose < Coolio::Socket
|
|
168
|
+
def initialize(io, cb)
|
|
169
|
+
super(io)
|
|
170
|
+
@cb = cb
|
|
171
|
+
end
|
|
172
|
+
def on_close
|
|
173
|
+
@cb.call
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "closed socket called on_close" do
|
|
178
|
+
begin
|
|
179
|
+
closed = false
|
|
180
|
+
server = Cool.io::TCPServer.new("localhost", port, ServerOnConnect, proc { closed = true })
|
|
181
|
+
loop.attach server
|
|
182
|
+
s = TCPSocket.open("localhost", port)
|
|
183
|
+
loop.run_once
|
|
184
|
+
s.close
|
|
185
|
+
loop.run_once
|
|
186
|
+
expect(closed).to eq true
|
|
187
|
+
ensure
|
|
188
|
+
server.detach
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context "#on_read" do
|
|
194
|
+
class Echo < Coolio::Socket
|
|
195
|
+
def initialize(io, cb)
|
|
196
|
+
super(io)
|
|
197
|
+
@cb = cb
|
|
198
|
+
end
|
|
199
|
+
def on_read(data)
|
|
200
|
+
@cb.call data
|
|
201
|
+
_size = write(data + "fff")
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "server socket received data" do
|
|
206
|
+
begin
|
|
207
|
+
data = "aaa"
|
|
208
|
+
server = Cool.io::TCPServer.new("localhost", port, Echo, proc { |d| data = d })
|
|
209
|
+
loop.attach server
|
|
210
|
+
thread = Thread.new { loop.run }
|
|
211
|
+
s = TCPSocket.open("localhost", port)
|
|
212
|
+
s.write "zzz"
|
|
213
|
+
sleep 0.1
|
|
214
|
+
expect(data).to eq "zzz"
|
|
215
|
+
expect(s.read 6).to eq "zzzfff"
|
|
216
|
+
ensure
|
|
217
|
+
s.close
|
|
218
|
+
loop.stop
|
|
219
|
+
server.detach
|
|
220
|
+
thread.join
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
describe Coolio::TCPSocket do
|
|
4
|
+
let :loop do
|
|
5
|
+
Coolio::Loop.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
before :each do
|
|
9
|
+
@echo = TCPServer.new("127.0.0.1", 0)
|
|
10
|
+
@host = @echo.addr[3]
|
|
11
|
+
@port = @echo.addr[1]
|
|
12
|
+
@running = true
|
|
13
|
+
@echo_thread = Thread.new do
|
|
14
|
+
socks = [@echo]
|
|
15
|
+
begin
|
|
16
|
+
serv socks
|
|
17
|
+
ensure
|
|
18
|
+
socks.each do |s|
|
|
19
|
+
s.close
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
Thread.pass
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def serv(socks)
|
|
27
|
+
while @running
|
|
28
|
+
selected = select(socks, [], [], 0.1)
|
|
29
|
+
next if selected.nil?
|
|
30
|
+
selected[0].each do |s|
|
|
31
|
+
if s == @echo
|
|
32
|
+
socks.push s.accept
|
|
33
|
+
next
|
|
34
|
+
end
|
|
35
|
+
begin
|
|
36
|
+
unless s.eof?
|
|
37
|
+
s.write(s.read_nonblock 1)
|
|
38
|
+
end
|
|
39
|
+
rescue SystemCallError, EOFError, IOError, SocketError
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def shutdown
|
|
46
|
+
if @running
|
|
47
|
+
@running = false
|
|
48
|
+
@echo_thread.join
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
after :each do
|
|
53
|
+
shutdown
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "#close" do
|
|
57
|
+
it "detaches all watchers on #close before loop#run" do
|
|
58
|
+
client = Coolio::TCPSocket.connect(@host, @port)
|
|
59
|
+
loop.attach client
|
|
60
|
+
client.close
|
|
61
|
+
expect(loop.watchers.size).to eq 0
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "#on_connect" do
|
|
66
|
+
class OnConnect < Cool.io::TCPSocket
|
|
67
|
+
attr :connected
|
|
68
|
+
def on_connect
|
|
69
|
+
@connected = true
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "connected client called on_connect" do
|
|
74
|
+
begin
|
|
75
|
+
c = OnConnect.connect(@host, @port)
|
|
76
|
+
loop.attach c
|
|
77
|
+
loop.run_once
|
|
78
|
+
expect(c.connected).to eq true
|
|
79
|
+
ensure
|
|
80
|
+
c.close
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "#on_connect_failed" do
|
|
86
|
+
class OnConnectFailed < Cool.io::TCPSocket
|
|
87
|
+
attr :connect_failed
|
|
88
|
+
def on_connect_failed
|
|
89
|
+
@connect_failed = true
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "try to connect dead host" do
|
|
94
|
+
serv = TCPServer.new(0)
|
|
95
|
+
dead_host = serv.addr[3]
|
|
96
|
+
dead_port = serv.addr[1]
|
|
97
|
+
serv.close
|
|
98
|
+
|
|
99
|
+
c = OnConnectFailed.connect(dead_host, dead_port)
|
|
100
|
+
loop.attach c
|
|
101
|
+
loop.run_once # on_connect_failed
|
|
102
|
+
expect(c.connect_failed).to eq true
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "#on_close" do
|
|
107
|
+
class Closed < StandardError; end
|
|
108
|
+
class OnClose < Cool.io::TCPSocket
|
|
109
|
+
def on_close
|
|
110
|
+
raise Closed
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
let :client do
|
|
115
|
+
OnClose.connect(@host, @port)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
before :each do
|
|
119
|
+
loop.attach client
|
|
120
|
+
loop.run_once # on_connect
|
|
121
|
+
client.write "0"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "disconnect from client" do
|
|
125
|
+
expect { client.close }.to raise_error(Closed)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "disconnect from server" do
|
|
129
|
+
shutdown
|
|
130
|
+
expect { loop.run }.to raise_error(Closed)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "#on_read" do
|
|
135
|
+
class Finished < StandardError; end
|
|
136
|
+
class OnRead < Cool.io::TCPSocket
|
|
137
|
+
attr :read_data, :times
|
|
138
|
+
def on_connect
|
|
139
|
+
@read_data = ""
|
|
140
|
+
@times = 0
|
|
141
|
+
end
|
|
142
|
+
def on_read(data)
|
|
143
|
+
@read_data += data
|
|
144
|
+
@times += 1
|
|
145
|
+
if @times < 5
|
|
146
|
+
write "#{@times}"
|
|
147
|
+
else
|
|
148
|
+
close
|
|
149
|
+
raise Finished
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "receive 5 times" do
|
|
155
|
+
c = OnRead.connect(@host, @port)
|
|
156
|
+
loop.attach c
|
|
157
|
+
loop.run_once # on_connect
|
|
158
|
+
c.write "0"
|
|
159
|
+
expect { loop.run }.to raise_error(Finished)
|
|
160
|
+
|
|
161
|
+
expect(c.times).to eq 5
|
|
162
|
+
expect(c.read_data).to eq "01234"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "#on_write_complete" do
|
|
167
|
+
class WriteComplete < StandardError; end
|
|
168
|
+
class OnWriteComplete < Cool.io::TCPSocket
|
|
169
|
+
attr :called
|
|
170
|
+
def on_write_complete
|
|
171
|
+
@called = true
|
|
172
|
+
close
|
|
173
|
+
raise WriteComplete
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "on_write_complete is called" do
|
|
178
|
+
c = OnWriteComplete.connect(@host, @port)
|
|
179
|
+
loop.attach c
|
|
180
|
+
loop.run_once # on_connect
|
|
181
|
+
c.write "aaa"
|
|
182
|
+
expect { loop.run }.to raise_error(WriteComplete)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
data/spec/timer_watcher_spec.rb
CHANGED
|
@@ -4,15 +4,19 @@ describe Cool.io::TimerWatcher do
|
|
|
4
4
|
|
|
5
5
|
interval = 0.010
|
|
6
6
|
|
|
7
|
+
let :loop do
|
|
8
|
+
Cool.io::Loop.new
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
it "can have the on_timer callback defined after creation" do
|
|
8
12
|
@watcher = Cool.io::TimerWatcher.new(interval, true)
|
|
9
13
|
nr = '0'
|
|
10
|
-
@watcher.on_timer { nr.succ! }.
|
|
11
|
-
@watcher.attach(
|
|
12
|
-
nr.
|
|
14
|
+
expect(@watcher.on_timer { nr.succ! }).to be_nil
|
|
15
|
+
expect(@watcher.attach(loop)).to eq(@watcher)
|
|
16
|
+
expect(nr).to eq('0')
|
|
13
17
|
sleep interval
|
|
14
|
-
|
|
15
|
-
nr.
|
|
18
|
+
loop.run_once
|
|
19
|
+
expect(nr).to eq('1')
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
it "can be subclassed" do
|
|
@@ -24,29 +28,29 @@ describe Cool.io::TimerWatcher do
|
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
@watcher = MyTimerWatcher.new(interval, true)
|
|
27
|
-
@watcher.attach(
|
|
28
|
-
MyTimerWatcher::TMP.
|
|
31
|
+
expect(@watcher.attach(loop)).to eq(@watcher)
|
|
32
|
+
expect(MyTimerWatcher::TMP).to eq('0')
|
|
29
33
|
sleep interval
|
|
30
|
-
|
|
31
|
-
MyTimerWatcher::TMP.
|
|
34
|
+
loop.run_once
|
|
35
|
+
expect(MyTimerWatcher::TMP).to eq('1')
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
it "can have the on_timer callback redefined between runs" do
|
|
35
39
|
@watcher = Cool.io::TimerWatcher.new(interval, true)
|
|
36
40
|
nr = '0'
|
|
37
|
-
@watcher.on_timer { nr.succ! }.
|
|
38
|
-
@watcher.attach(
|
|
39
|
-
nr.
|
|
41
|
+
expect(@watcher.on_timer { nr.succ! }).to be_nil
|
|
42
|
+
expect(@watcher.attach(loop)).to eq(@watcher)
|
|
43
|
+
expect(nr).to eq('0')
|
|
40
44
|
sleep interval
|
|
41
|
-
|
|
42
|
-
nr.
|
|
45
|
+
loop.run_once
|
|
46
|
+
expect(nr).to eq('1')
|
|
43
47
|
@watcher.detach
|
|
44
|
-
@watcher.on_timer { nr = :foo }.
|
|
45
|
-
@watcher.attach(
|
|
46
|
-
nr.
|
|
48
|
+
expect(@watcher.on_timer { nr = :foo }).to be_nil
|
|
49
|
+
expect(@watcher.attach(loop)).to eq(@watcher)
|
|
50
|
+
expect(nr).to eq('1')
|
|
47
51
|
sleep interval
|
|
48
|
-
|
|
49
|
-
nr.
|
|
52
|
+
loop.run_once
|
|
53
|
+
expect(nr).to eq(:foo)
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
after :each do
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Coolio::UDPSocket" do
|
|
4
|
+
let :loop do
|
|
5
|
+
Coolio::Loop.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
before :each do
|
|
9
|
+
@echo = UDPSocket.open
|
|
10
|
+
@echo.bind nil, 0
|
|
11
|
+
@port = @echo.addr[1]
|
|
12
|
+
|
|
13
|
+
@running = true
|
|
14
|
+
@echo_thread = Thread.new do
|
|
15
|
+
while @running
|
|
16
|
+
begin
|
|
17
|
+
msg, sender = @echo.recvfrom_nonblock(3)
|
|
18
|
+
@echo.send(msg + "bbb", 0, sender[3], sender[1])
|
|
19
|
+
rescue IO::WaitReadable
|
|
20
|
+
end
|
|
21
|
+
Thread.pass
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
after :each do
|
|
27
|
+
@running = false
|
|
28
|
+
@echo_thread.join
|
|
29
|
+
@echo.close
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Readable < Cool.io::IOWatcher
|
|
33
|
+
attr :socket, :received
|
|
34
|
+
def initialize
|
|
35
|
+
@socket = UDPSocket.new
|
|
36
|
+
super(@socket)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def on_readable
|
|
40
|
+
@received = @socket.recvfrom_nonblock(6).first
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "receive message #on_readable 5 times" do
|
|
45
|
+
5.times do
|
|
46
|
+
begin
|
|
47
|
+
r = Readable.new
|
|
48
|
+
r.socket.send "aaa", 0, "localhost", @port
|
|
49
|
+
|
|
50
|
+
loop.attach r
|
|
51
|
+
loop.run_once
|
|
52
|
+
expect(r.received).to eq "aaabbb"
|
|
53
|
+
ensure
|
|
54
|
+
r.detach
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/spec/unix_listener_spec.rb
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
|
2
2
|
require 'tempfile'
|
|
3
3
|
|
|
4
|
-
describe Cool.io::UNIXListener do
|
|
4
|
+
describe Cool.io::UNIXListener, :env => :exclude_win do
|
|
5
5
|
|
|
6
6
|
before :each do
|
|
7
7
|
@tmp = Tempfile.new('coolio_unix_listener_spec')
|
|
8
|
-
File.unlink(@tmp.path).
|
|
9
|
-
File.exist?(@tmp.path).
|
|
8
|
+
expect(File.unlink(@tmp.path)).to eq(1)
|
|
9
|
+
expect(File.exist?(@tmp.path)).to eq(false)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "creates a new UNIXListener" do
|
|
13
|
-
|
|
14
|
-
File.socket?(@tmp.path).
|
|
13
|
+
_listener = Cool.io::UNIXListener.new(@tmp.path)
|
|
14
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it "builds off an existing UNIXServer" do
|
|
18
18
|
unix_server = UNIXServer.new(@tmp.path)
|
|
19
|
-
File.socket?(@tmp.path).
|
|
19
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
20
20
|
listener = Cool.io::UNIXListener.new(unix_server)
|
|
21
|
-
File.socket?(@tmp.path).
|
|
22
|
-
listener.fileno.
|
|
21
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
22
|
+
expect(listener.fileno).to eq(unix_server.fileno)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
end
|
data/spec/unix_server_spec.rb
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
|
2
2
|
require 'tempfile'
|
|
3
3
|
|
|
4
|
-
describe Cool.io::UNIXServer do
|
|
4
|
+
describe Cool.io::UNIXServer, :env => :exclude_win do
|
|
5
5
|
|
|
6
6
|
before :each do
|
|
7
7
|
@tmp = Tempfile.new('coolio_unix_server_spec')
|
|
8
|
-
File.unlink(@tmp.path).
|
|
9
|
-
File.exist?(@tmp.path).
|
|
8
|
+
expect(File.unlink(@tmp.path)).to eq(1)
|
|
9
|
+
expect(File.exist?(@tmp.path)).to eq(false)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "creates a new Cool.io::UNIXServer" do
|
|
13
13
|
listener = Cool.io::UNIXListener.new(@tmp.path)
|
|
14
|
-
|
|
14
|
+
listener.listen(24)
|
|
15
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
it "builds off an existing ::UNIXServer" do
|
|
18
19
|
unix_server = ::UNIXServer.new(@tmp.path)
|
|
19
|
-
File.socket?(@tmp.path).
|
|
20
|
-
listener = Cool.io::UNIXServer.new(unix_server)
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
21
|
+
listener = Cool.io::UNIXServer.new(unix_server, Coolio::UNIXSocket)
|
|
22
|
+
listener.listen(24)
|
|
23
|
+
expect(File.socket?(@tmp.path)).to eq(true)
|
|
24
|
+
expect(listener.fileno).to eq(unix_server.fileno)
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
end
|