cool.io 1.2.3-x86-mingw32 → 1.4.1-x86-mingw32
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/.gitignore +3 -0
- data/.travis.yml +3 -3
- data/CHANGES.md +35 -0
- data/README.md +1 -3
- data/Rakefile +11 -13
- data/cool.io.gemspec +3 -2
- data/examples/callbacked_echo_server.rb +24 -0
- data/ext/cool.io/extconf.rb +8 -24
- data/ext/cool.io/loop.c +1 -1
- data/ext/iobuffer/iobuffer.c +2 -0
- data/ext/libev/Changes +123 -4
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +8 -8
- data/ext/libev/ev.c +313 -144
- data/ext/libev/ev.h +18 -10
- data/ext/libev/ev_epoll.c +4 -1
- data/ext/libev/ev_kqueue.c +1 -1
- data/ext/libev/ev_select.c +3 -4
- data/ext/libev/ev_vars.h +3 -2
- data/ext/libev/ev_win32.c +1 -1
- data/ext/libev/win_select.patch +115 -0
- data/lib/cool.io.rb +6 -4
- data/lib/cool.io/dns_resolver.rb +4 -10
- data/lib/cool.io/dsl.rb +6 -2
- data/lib/cool.io/io.rb +36 -16
- data/lib/cool.io/loop.rb +3 -11
- data/lib/cool.io/meta.rb +2 -2
- data/lib/cool.io/version.rb +4 -2
- data/spec/async_watcher_spec.rb +5 -5
- data/spec/dns_spec.rb +11 -7
- data/spec/iobuffer_spec.rb +147 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/stat_watcher_spec.rb +3 -3
- data/spec/tcp_server_spec.rb +98 -5
- 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 +7 -7
- data/spec/unix_server_spec.rb +7 -7
- metadata +83 -103
- 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 -427
data/lib/cool.io/loop.rb
CHANGED
@@ -15,17 +15,9 @@ end
|
|
15
15
|
|
16
16
|
module Coolio
|
17
17
|
class Loop
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
def self.default
|
22
|
-
Thread.current._coolio_loop
|
23
|
-
end
|
24
|
-
else
|
25
|
-
# Retrieve the default event loop
|
26
|
-
def self.default
|
27
|
-
@@_coolio_loop ||= Coolio::Loop.new
|
28
|
-
end
|
18
|
+
# Retrieve the default event loop for the current thread
|
19
|
+
def self.default
|
20
|
+
Thread.current._coolio_loop
|
29
21
|
end
|
30
22
|
|
31
23
|
# Create a new Coolio::Loop
|
data/lib/cool.io/meta.rb
CHANGED
@@ -11,7 +11,7 @@ module Coolio
|
|
11
11
|
# an event to occur before the current watcher can be used in earnest,
|
12
12
|
# such as making an outgoing TCP connection.
|
13
13
|
def watcher_delegate(proxy_var)
|
14
|
-
%w{attach detach enable disable}.each do |method|
|
14
|
+
%w{attach attached? detach enable disable}.each do |method|
|
15
15
|
module_eval <<-EOD
|
16
16
|
def #{method}(*args)
|
17
17
|
if defined? #{proxy_var} and #{proxy_var}
|
@@ -39,7 +39,7 @@ module Coolio
|
|
39
39
|
end
|
40
40
|
|
41
41
|
if defined? @#{method}_callback and @#{method}_callback
|
42
|
-
|
42
|
+
@#{method}_callback.call(*args)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
EOD
|
data/lib/cool.io/version.rb
CHANGED
data/spec/async_watcher_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require File.expand_path('../spec_helper', __FILE__)
|
|
2
2
|
require 'tempfile'
|
3
3
|
require 'fcntl'
|
4
4
|
|
5
|
-
describe Cool.io::AsyncWatcher, :env => :
|
5
|
+
describe Cool.io::AsyncWatcher, :env => :exclude_win do
|
6
6
|
|
7
7
|
it "does not signal on spurious wakeups" do
|
8
8
|
aw = Cool.io::AsyncWatcher.new
|
@@ -30,7 +30,7 @@ describe Cool.io::AsyncWatcher, :env => :win do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# ensure children are ready
|
33
|
-
nr_fork.times { rd.sysread(1).
|
33
|
+
nr_fork.times { expect(rd.sysread(1)).to eq('.') }
|
34
34
|
|
35
35
|
# send our signals
|
36
36
|
nr_signal.times { aw.signal }
|
@@ -41,15 +41,15 @@ describe Cool.io::AsyncWatcher, :env => :win do
|
|
41
41
|
children.each do |pid|
|
42
42
|
Process.kill(:TERM, pid)
|
43
43
|
_, status = Process.waitpid2(pid)
|
44
|
-
status.exitstatus.
|
44
|
+
expect(status.exitstatus).to eq(0)
|
45
45
|
end
|
46
46
|
|
47
47
|
# we should've written a line for every signal we sent
|
48
48
|
lines = tmp.readlines
|
49
|
-
lines.size.
|
49
|
+
expect(lines.size).to eq(nr_signal)
|
50
50
|
|
51
51
|
# theoretically a bad kernel scheduler could give us fewer...
|
52
|
-
lines.sort.uniq.size.
|
52
|
+
expect(lines.sort.uniq.size).to eq(nr_fork)
|
53
53
|
|
54
54
|
tmp.close!
|
55
55
|
end
|
data/spec/dns_spec.rb
CHANGED
@@ -22,18 +22,22 @@ describe "DNS" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "connects to valid domains" do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
begin
|
26
|
+
c = ConnectorThingy.connect(VALID_DOMAIN, 80).attach(@loop)
|
27
|
+
|
28
|
+
expect do
|
29
|
+
@loop.run
|
30
|
+
end.to raise_error(ItWorked)
|
31
|
+
ensure
|
32
|
+
c.close
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
it "fires on_resolve_failed for invalid domains" do
|
33
37
|
ConnectorThingy.connect(INVALID_DOMAIN, 80).attach(@loop)
|
34
38
|
|
35
|
-
|
39
|
+
expect do
|
36
40
|
@loop.run
|
37
|
-
end.
|
41
|
+
end.to raise_error(WontResolve)
|
38
42
|
end
|
39
43
|
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
|
4
|
+
describe IO::Buffer do
|
5
|
+
|
6
|
+
let :buffer do
|
7
|
+
IO::Buffer.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "provides a subset of the methods available in Strings" do
|
11
|
+
expect(buffer << "foo").to eq "foo"
|
12
|
+
expect(buffer << "bar").to eq "bar"
|
13
|
+
expect(buffer.to_str).to eq "foobar"
|
14
|
+
expect(buffer.to_str).to eq "foobar"
|
15
|
+
expect(buffer.size).to eq 6
|
16
|
+
end
|
17
|
+
|
18
|
+
it "provides append and prepend" do
|
19
|
+
expect(buffer.append "bar").to eq "bar"
|
20
|
+
expect(buffer.prepend "foo").to eq "foo"
|
21
|
+
expect(buffer.append "baz").to eq "baz"
|
22
|
+
expect(buffer.to_str).to eq "foobarbaz"
|
23
|
+
end
|
24
|
+
|
25
|
+
context "#read" do
|
26
|
+
it "can be used to retrieve the contents of a buffer" do
|
27
|
+
expect(buffer << "foo").to eq "foo"
|
28
|
+
expect(buffer.read 2).to eq "fo"
|
29
|
+
expect(buffer << "bar").to eq "bar"
|
30
|
+
expect(buffer.read 2).to eq "ob"
|
31
|
+
expect(buffer << "baz").to eq "baz"
|
32
|
+
expect(buffer.read 3).to eq "arb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "provides methods for performing non-blocking I/O" do
|
37
|
+
require "tempfile"
|
38
|
+
|
39
|
+
context "#read_from" do
|
40
|
+
context "using local file", :env => :exclude_win do
|
41
|
+
let :tmp do
|
42
|
+
t = Tempfile.open "read_from"
|
43
|
+
t << "foobar"
|
44
|
+
t.rewind
|
45
|
+
t
|
46
|
+
end
|
47
|
+
|
48
|
+
it "will read as much data as possible" do
|
49
|
+
expect(buffer.read_from tmp).to eq 6
|
50
|
+
expect(buffer.to_str).to eq "foobar"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "using udp socket" do
|
55
|
+
before :each do
|
56
|
+
@receiver = UDPSocket.open
|
57
|
+
@receiver.bind nil, 0
|
58
|
+
|
59
|
+
@sender = UDPSocket.open
|
60
|
+
@sender.connect "localhost", @receiver.addr[1]
|
61
|
+
end
|
62
|
+
after :each do
|
63
|
+
@receiver.close
|
64
|
+
@sender.close
|
65
|
+
end
|
66
|
+
|
67
|
+
it "will read as much data as possible" do
|
68
|
+
select [], [@sender]
|
69
|
+
@sender.send "foo", 0
|
70
|
+
select [@receiver]
|
71
|
+
expect(buffer.read_from @receiver).to eq 3
|
72
|
+
expect(buffer.to_str).to eq "foo"
|
73
|
+
|
74
|
+
select [], [@sender]
|
75
|
+
@sender.send "barbaz", 0
|
76
|
+
select [@receiver]
|
77
|
+
expect(buffer.read_from @receiver).to eq 6
|
78
|
+
expect(buffer.to_str).to eq "foobarbaz"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "#write_to" do
|
84
|
+
context "using local file", :env => :exclude_win do
|
85
|
+
let :tmp do
|
86
|
+
Tempfile.open "write_to"
|
87
|
+
end
|
88
|
+
it "writes the contents of the buffer" do
|
89
|
+
buffer << "foo"
|
90
|
+
expect(buffer.write_to tmp).to eq 3
|
91
|
+
tmp.rewind
|
92
|
+
expect(tmp.read 3).to eq "foo"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "using udp socket" do
|
97
|
+
before :each do
|
98
|
+
@receiver = UDPSocket.open
|
99
|
+
@receiver.bind nil, 0
|
100
|
+
|
101
|
+
@sender = UDPSocket.open
|
102
|
+
@sender.connect "localhost", @receiver.addr[1]
|
103
|
+
end
|
104
|
+
after :each do
|
105
|
+
@receiver.close
|
106
|
+
@sender.close
|
107
|
+
end
|
108
|
+
|
109
|
+
it "will read as much data as possible" do
|
110
|
+
buffer << "foo"
|
111
|
+
select [], [@sender]
|
112
|
+
expect(buffer.write_to @sender).to eq 3
|
113
|
+
select [@receiver]
|
114
|
+
expect(@receiver.recvfrom_nonblock(3)[0]).to eq "foo"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "#clear" do
|
121
|
+
it "clear all data" do
|
122
|
+
buffer << "foo"
|
123
|
+
expect(buffer.size).to eq 3
|
124
|
+
expect(buffer.empty?).to eq false
|
125
|
+
buffer.clear
|
126
|
+
expect(buffer.size).to eq 0
|
127
|
+
expect(buffer.empty?).to eq true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "#read_frame" do
|
132
|
+
it "Read up to and including the given frame marker" do
|
133
|
+
buffer << "foo\nbarbaz"
|
134
|
+
data = ""
|
135
|
+
expect(buffer.read_frame data, "\n".ord).to eq true
|
136
|
+
expect(buffer.empty?).to eq false
|
137
|
+
expect(data).to eq "foo\n"
|
138
|
+
expect(buffer.to_str).to eq "barbaz"
|
139
|
+
|
140
|
+
expect(buffer.read_frame data, "\n".ord).to eq false
|
141
|
+
expect(buffer.empty?).to eq true
|
142
|
+
expect(data).to eq "foo\nbarbaz"
|
143
|
+
expect(buffer.to_str).to eq ""
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,8 +12,8 @@ def unused_port
|
|
12
12
|
end
|
13
13
|
|
14
14
|
RSpec.configure do |c|
|
15
|
-
if RUBY_PLATFORM =~ /mingw|
|
15
|
+
if RUBY_PLATFORM =~ /mingw|mswin/
|
16
16
|
$stderr.puts "Skip some specs on Windows"
|
17
|
-
c.filter_run_excluding :env => :
|
17
|
+
c.filter_run_excluding :env => :exclude_win
|
18
18
|
end
|
19
19
|
end
|
data/spec/stat_watcher_spec.rb
CHANGED
@@ -62,16 +62,16 @@ describe Cool.io::StatWatcher do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
it "fire on_change when the file it is watching is modified" do
|
65
|
-
watcher.accessed.
|
65
|
+
expect(watcher.accessed).to eq(true)
|
66
66
|
end
|
67
67
|
|
68
68
|
it "should pass previous and current file stat info given a stat watcher" do
|
69
|
-
watcher.previous.ino.
|
69
|
+
expect(watcher.previous.ino).to eq(watcher.current.ino)
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should raise when the handler does not take 2 parameters" do
|
73
73
|
class MyStatWatcher < Cool.io::StatWatcher; def on_change; end; end
|
74
|
-
|
74
|
+
expect { watcher.accessed }.to raise_error(ArgumentError)
|
75
75
|
end
|
76
76
|
|
77
77
|
end
|
data/spec/tcp_server_spec.rb
CHANGED
@@ -106,14 +106,14 @@ ensure
|
|
106
106
|
end
|
107
107
|
|
108
108
|
# This test should work on Windows
|
109
|
-
describe Coolio::TCPServer
|
109
|
+
describe Coolio::TCPServer do
|
110
110
|
|
111
111
|
it '#run' do
|
112
|
-
test_run("hello").
|
112
|
+
expect(test_run("hello")).to eq("hello")
|
113
113
|
end
|
114
114
|
|
115
115
|
it '#run_once' do
|
116
|
-
test_run_once("hello").
|
116
|
+
expect(test_run_once("hello")).to eq("hello")
|
117
117
|
end
|
118
118
|
|
119
119
|
it '#run_once(timeout)' do
|
@@ -125,8 +125,101 @@ describe Coolio::TCPServer, :env => :win do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it '#run(timeout)' do
|
128
|
-
test_run_timeout("hello").
|
128
|
+
expect(test_run_timeout("hello")).to eq("hello")
|
129
129
|
end
|
130
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
|
131
225
|
end
|
132
|
-
|
@@ -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
|