ione 1.2.0.pre5 → 1.2.0.pre6
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 +4 -4
- data/lib/ione/io/acceptor.rb +16 -8
- data/lib/ione/io/base_connection.rb +9 -11
- data/lib/ione/io/io_reactor.rb +67 -52
- data/lib/ione/version.rb +1 -1
- data/spec/integration/io_spec.rb +7 -7
- data/spec/ione/io/acceptor_spec.rb +2 -2
- data/spec/ione/io/connection_common.rb +4 -4
- data/spec/ione/io/connection_spec.rb +1 -1
- data/spec/ione/io/io_reactor_spec.rb +42 -38
- data/spec/ione/io/server_connection_spec.rb +1 -1
- data/spec/ione/io/ssl_acceptor_spec.rb +3 -3
- data/spec/ione/io/ssl_connection_spec.rb +1 -1
- data/spec/support/fake_server.rb +5 -5
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 580012a6e7c6d917610532fc3fbd917ab9cd7a50
|
4
|
+
data.tar.gz: e5deb87d0deebb5d4cc9d3a1b516b672ef6848a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5760948be8fe0975500e3f673ffc0b4b4be1ed04aaccbfc44bc4535c668c1d7fec678a2fd498e608fd642a9e6e7354df4e01863f632afff471c4e70b57b6d895
|
7
|
+
data.tar.gz: e912eadf89022cb82d6f65726d1f48ccd8f17c1b434eb0a70dc783adef9407941331830ddc3898fb206e84b34aa300f0ed1b86115e98b684bc20544d38caa36b
|
data/lib/ione/io/acceptor.rb
CHANGED
@@ -17,6 +17,7 @@ module Ione
|
|
17
17
|
@socket_impl = socket_impl || ServerSocket
|
18
18
|
@accept_listeners = []
|
19
19
|
@lock = Mutex.new
|
20
|
+
@state = :binding
|
20
21
|
end
|
21
22
|
|
22
23
|
def on_accept(&listener)
|
@@ -38,6 +39,7 @@ module Ione
|
|
38
39
|
retry
|
39
40
|
end
|
40
41
|
end
|
42
|
+
@state = :connected
|
41
43
|
Future.resolved(self)
|
42
44
|
rescue => e
|
43
45
|
close
|
@@ -45,13 +47,19 @@ module Ione
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def close
|
48
|
-
|
49
|
-
|
50
|
-
@
|
51
|
-
|
52
|
-
|
50
|
+
@lock.synchronize do
|
51
|
+
return false if @state == :closed
|
52
|
+
@state = :closed
|
53
|
+
end
|
54
|
+
if @io
|
55
|
+
begin
|
56
|
+
@io.close
|
57
|
+
rescue SystemCallError, IOError
|
58
|
+
# nothing to do, the socket was most likely already closed
|
59
|
+
ensure
|
60
|
+
@io = nil
|
61
|
+
end
|
53
62
|
end
|
54
|
-
@io = nil
|
55
63
|
true
|
56
64
|
end
|
57
65
|
|
@@ -60,11 +68,11 @@ module Ione
|
|
60
68
|
end
|
61
69
|
|
62
70
|
def closed?
|
63
|
-
@
|
71
|
+
@state == :closed
|
64
72
|
end
|
65
73
|
|
66
74
|
def connected?
|
67
|
-
|
75
|
+
@state != :closed
|
68
76
|
end
|
69
77
|
|
70
78
|
def connecting?
|
@@ -10,6 +10,7 @@ module Ione
|
|
10
10
|
@port = port
|
11
11
|
@unblocker = unblocker
|
12
12
|
@state = :connecting
|
13
|
+
@writable = false
|
13
14
|
@lock = Mutex.new
|
14
15
|
@write_buffer = ByteBuffer.new
|
15
16
|
@closed_promise = Promise.new
|
@@ -22,6 +23,7 @@ module Ione
|
|
22
23
|
@lock.synchronize do
|
23
24
|
return false if @state == :closed
|
24
25
|
@state = :closed
|
26
|
+
@writable = false
|
25
27
|
end
|
26
28
|
if @io
|
27
29
|
begin
|
@@ -50,7 +52,7 @@ module Ione
|
|
50
52
|
# has closed
|
51
53
|
def drain
|
52
54
|
@state = :draining
|
53
|
-
close
|
55
|
+
close unless @writable
|
54
56
|
@closed_promise.future
|
55
57
|
end
|
56
58
|
|
@@ -71,13 +73,7 @@ module Ione
|
|
71
73
|
|
72
74
|
# @private
|
73
75
|
def writable?
|
74
|
-
@
|
75
|
-
begin
|
76
|
-
empty_buffer = @write_buffer.empty?
|
77
|
-
ensure
|
78
|
-
@lock.unlock
|
79
|
-
end
|
80
|
-
!(closed? || empty_buffer)
|
76
|
+
@writable && @state != :closed
|
81
77
|
end
|
82
78
|
|
83
79
|
# Register to receive notifications when new data is read from the socket.
|
@@ -131,10 +127,11 @@ module Ione
|
|
131
127
|
elsif bytes
|
132
128
|
@write_buffer.append(bytes)
|
133
129
|
end
|
130
|
+
@writable = !@write_buffer.empty?
|
134
131
|
ensure
|
135
132
|
@lock.unlock
|
136
133
|
end
|
137
|
-
@unblocker.unblock
|
134
|
+
@unblocker.unblock
|
138
135
|
end
|
139
136
|
end
|
140
137
|
|
@@ -143,11 +140,12 @@ module Ione
|
|
143
140
|
if @state == :connected || @state == :draining
|
144
141
|
@lock.lock
|
145
142
|
begin
|
146
|
-
|
143
|
+
if @writable
|
147
144
|
bytes_written = @io.write_nonblock(@write_buffer.cheap_peek)
|
148
145
|
@write_buffer.discard(bytes_written)
|
149
146
|
end
|
150
|
-
|
147
|
+
@writable = !@write_buffer.empty?
|
148
|
+
if @state == :draining && !@writable
|
151
149
|
close
|
152
150
|
end
|
153
151
|
ensure
|
data/lib/ione/io/io_reactor.rb
CHANGED
@@ -87,6 +87,7 @@ module Ione
|
|
87
87
|
@unblocker = Unblocker.new
|
88
88
|
@io_loop = IoLoopBody.new(options)
|
89
89
|
@io_loop.add_socket(@unblocker)
|
90
|
+
@scheduler = Scheduler.new
|
90
91
|
@running = false
|
91
92
|
@stopped = false
|
92
93
|
@started_promise = Promise.new
|
@@ -128,10 +129,13 @@ module Ione
|
|
128
129
|
Thread.start do
|
129
130
|
@started_promise.fulfill(self)
|
130
131
|
begin
|
131
|
-
|
132
|
+
until @stopped
|
133
|
+
@io_loop.tick
|
134
|
+
@scheduler.tick
|
135
|
+
end
|
132
136
|
ensure
|
133
137
|
@io_loop.close_sockets
|
134
|
-
@
|
138
|
+
@scheduler.cancel_timers
|
135
139
|
@running = false
|
136
140
|
if $!
|
137
141
|
@stopped_promise.fail($!)
|
@@ -181,7 +185,7 @@ module Ione
|
|
181
185
|
connection = Connection.new(host, port, timeout, @unblocker, @clock)
|
182
186
|
f = connection.connect
|
183
187
|
@io_loop.add_socket(connection)
|
184
|
-
@unblocker.unblock
|
188
|
+
@unblocker.unblock
|
185
189
|
if ssl
|
186
190
|
f = f.flat_map do
|
187
191
|
ssl_context = ssl == true ? nil : ssl
|
@@ -189,7 +193,7 @@ module Ione
|
|
189
193
|
ff = upgraded_connection.connect
|
190
194
|
@io_loop.remove_socket(connection)
|
191
195
|
@io_loop.add_socket(upgraded_connection)
|
192
|
-
@unblocker.unblock
|
196
|
+
@unblocker.unblock
|
193
197
|
ff
|
194
198
|
end
|
195
199
|
end
|
@@ -212,7 +216,7 @@ module Ione
|
|
212
216
|
end
|
213
217
|
f = server.bind
|
214
218
|
@io_loop.add_socket(server)
|
215
|
-
@unblocker.unblock
|
219
|
+
@unblocker.unblock
|
216
220
|
f = f.map(&block) if block_given?
|
217
221
|
f
|
218
222
|
end
|
@@ -220,7 +224,7 @@ module Ione
|
|
220
224
|
# @private
|
221
225
|
def accept(socket)
|
222
226
|
@io_loop.add_socket(socket)
|
223
|
-
@unblocker.unblock
|
227
|
+
@unblocker.unblock
|
224
228
|
end
|
225
229
|
|
226
230
|
# Returns a future that completes after the specified number of seconds.
|
@@ -229,7 +233,7 @@ module Ione
|
|
229
233
|
# future is completed
|
230
234
|
# @return [Ione::Future] a future that completes when the timer expires
|
231
235
|
def schedule_timer(timeout)
|
232
|
-
@
|
236
|
+
@scheduler.schedule_timer(timeout)
|
233
237
|
end
|
234
238
|
|
235
239
|
# Cancels a previously scheduled timer.
|
@@ -238,7 +242,7 @@ module Ione
|
|
238
242
|
#
|
239
243
|
# @param timer_future [Ione::Future] the future returned by {#schedule_timer}
|
240
244
|
def cancel_timer(timer_future)
|
241
|
-
@
|
245
|
+
@scheduler.cancel_timer(timer_future)
|
242
246
|
end
|
243
247
|
|
244
248
|
def to_s
|
@@ -269,7 +273,7 @@ module Ione
|
|
269
273
|
@in.nil?
|
270
274
|
end
|
271
275
|
|
272
|
-
def unblock
|
276
|
+
def unblock
|
273
277
|
@lock.lock
|
274
278
|
@in.write(PING_BYTE)
|
275
279
|
ensure
|
@@ -322,7 +326,7 @@ module Ione
|
|
322
326
|
end
|
323
327
|
|
324
328
|
def to_s
|
325
|
-
"#<Timer
|
329
|
+
"#<Timer @time=#{@time}>"
|
326
330
|
end
|
327
331
|
alias_method :inspect, :to_s
|
328
332
|
end
|
@@ -332,10 +336,9 @@ module Ione
|
|
332
336
|
def initialize(options={})
|
333
337
|
@selector = options[:selector] || IO
|
334
338
|
@clock = options[:clock] || Time
|
339
|
+
@timeout = options[:tick_resolution] || 1
|
335
340
|
@lock = Mutex.new
|
336
341
|
@sockets = []
|
337
|
-
@timer_queue = Heap.new
|
338
|
-
@pending_timers = {}
|
339
342
|
end
|
340
343
|
|
341
344
|
def add_socket(socket)
|
@@ -353,6 +356,53 @@ module Ione
|
|
353
356
|
end
|
354
357
|
end
|
355
358
|
|
359
|
+
def close_sockets
|
360
|
+
@sockets.each do |s|
|
361
|
+
begin
|
362
|
+
s.close
|
363
|
+
rescue
|
364
|
+
# the socket had most likely already closed due to an error
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def tick
|
370
|
+
readables = []
|
371
|
+
writables = []
|
372
|
+
connecting = []
|
373
|
+
@sockets.each do |s|
|
374
|
+
if s.connected?
|
375
|
+
readables << s
|
376
|
+
elsif s.connecting?
|
377
|
+
connecting << s
|
378
|
+
end
|
379
|
+
if s.connecting? || s.writable?
|
380
|
+
writables << s
|
381
|
+
end
|
382
|
+
end
|
383
|
+
begin
|
384
|
+
r, w, _ = @selector.select(readables, writables, nil, @timeout)
|
385
|
+
connecting.each { |s| s.connect }
|
386
|
+
r && r.each { |s| s.read }
|
387
|
+
w && w.each { |s| s.flush }
|
388
|
+
rescue IOError, Errno::EBADF
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def to_s
|
393
|
+
%(#<#{IoReactor.name} @connections=[#{@sockets.map(&:to_s).join(', ')}]>)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# @private
|
398
|
+
class Scheduler
|
399
|
+
def initialize(options={})
|
400
|
+
@clock = options[:clock] || Time
|
401
|
+
@lock = Mutex.new
|
402
|
+
@timer_queue = Heap.new
|
403
|
+
@pending_timers = {}
|
404
|
+
end
|
405
|
+
|
356
406
|
def schedule_timer(timeout)
|
357
407
|
@lock.lock
|
358
408
|
timer = Timer.new(@clock.now + timeout)
|
@@ -378,16 +428,6 @@ module Ione
|
|
378
428
|
end
|
379
429
|
end
|
380
430
|
|
381
|
-
def close_sockets
|
382
|
-
@sockets.each do |s|
|
383
|
-
begin
|
384
|
-
s.close unless s.closed?
|
385
|
-
rescue
|
386
|
-
# the socket had most likely already closed due to an error
|
387
|
-
end
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
431
|
def cancel_timers
|
392
432
|
while (timer = @timer_queue.pop)
|
393
433
|
@pending_timers.delete(timer.future)
|
@@ -395,36 +435,7 @@ module Ione
|
|
395
435
|
end
|
396
436
|
end
|
397
437
|
|
398
|
-
def tick
|
399
|
-
check_sockets!(timeout)
|
400
|
-
check_timers!
|
401
|
-
end
|
402
|
-
|
403
|
-
def to_s
|
404
|
-
%(#<#{IoReactor.name} @connections=[#{@sockets.map(&:to_s).join(', ')}]>)
|
405
|
-
end
|
406
|
-
|
407
|
-
private
|
408
|
-
|
409
|
-
def check_sockets!(timeout)
|
410
|
-
readables, writables, connecting = [], [], []
|
411
|
-
sockets = @sockets
|
412
|
-
sockets.each do |s|
|
413
|
-
next if s.closed?
|
414
|
-
readables << s if s.connected?
|
415
|
-
writables << s if s.connecting? || s.writable?
|
416
|
-
connecting << s if s.connecting?
|
417
|
-
end
|
418
|
-
begin
|
419
|
-
r, w, _ = @selector.select(readables, writables, nil, timeout)
|
420
|
-
connecting.each(&:connect)
|
421
|
-
r && r.each(&:read)
|
422
|
-
w && w.each(&:flush)
|
423
|
-
rescue IOError, Errno::EBADF
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
def check_timers!
|
438
|
+
def tick
|
428
439
|
now = @clock.now
|
429
440
|
first_timer = @timer_queue.peek
|
430
441
|
if first_timer && first_timer.time <= now
|
@@ -444,6 +455,10 @@ module Ione
|
|
444
455
|
end
|
445
456
|
end
|
446
457
|
end
|
458
|
+
|
459
|
+
def to_s
|
460
|
+
%(#<#{self.class.name} @timers=[#{@pending_timers.values.map(&:to_s).join(', ')}]>)
|
461
|
+
end
|
447
462
|
end
|
448
463
|
end
|
449
464
|
end
|
data/lib/ione/version.rb
CHANGED
data/spec/integration/io_spec.rb
CHANGED
@@ -18,32 +18,32 @@ describe 'An IO reactor' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
before do
|
21
|
-
fake_server.start
|
21
|
+
fake_server.start
|
22
22
|
io_reactor.start
|
23
23
|
end
|
24
24
|
|
25
25
|
after do
|
26
26
|
io_reactor.stop
|
27
|
-
fake_server.stop
|
27
|
+
fake_server.stop
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'connects to the server' do
|
31
31
|
io_reactor.connect(ENV['SERVER_HOST'], fake_server.port, 1, &protocol_handler_factory)
|
32
|
-
fake_server.await_connects
|
32
|
+
fake_server.await_connects(1)
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'receives data' do
|
36
36
|
protocol_handler = io_reactor.connect(ENV['SERVER_HOST'], fake_server.port, 1, &protocol_handler_factory).value
|
37
|
-
fake_server.await_connects
|
38
|
-
fake_server.broadcast
|
37
|
+
fake_server.await_connects(1)
|
38
|
+
fake_server.broadcast('hello world')
|
39
39
|
await { protocol_handler.data.bytesize > 0 }
|
40
40
|
protocol_handler.data.should == 'hello world'
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'receives data on multiple connections' do
|
44
44
|
protocol_handlers = Array.new(10) { io_reactor.connect(ENV['SERVER_HOST'], fake_server.port, 1, &protocol_handler_factory).value }
|
45
|
-
fake_server.await_connects
|
46
|
-
fake_server.broadcast
|
45
|
+
fake_server.await_connects(10)
|
46
|
+
fake_server.broadcast('hello world')
|
47
47
|
await { protocol_handlers.all? { |c| c.data.bytesize > 0 } }
|
48
48
|
protocol_handlers.sample.data.should == 'hello world'
|
49
49
|
end
|
@@ -179,11 +179,11 @@ module Ione
|
|
179
179
|
end
|
180
180
|
|
181
181
|
it 'passes the unblocker along to the connection handler' do
|
182
|
-
unblocker.stub(:unblock
|
182
|
+
unblocker.stub(:unblock)
|
183
183
|
acceptor.bind
|
184
184
|
acceptor.read
|
185
185
|
accepted_handlers.first.write('foo')
|
186
|
-
unblocker.should have_received(:unblock
|
186
|
+
unblocker.should have_received(:unblock)
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -95,7 +95,7 @@ shared_examples_for 'a connection' do |options|
|
|
95
95
|
describe '#write/#flush' do
|
96
96
|
before do
|
97
97
|
socket.stub(:write_nonblock)
|
98
|
-
unblocker.stub(:unblock
|
98
|
+
unblocker.stub(:unblock)
|
99
99
|
end
|
100
100
|
|
101
101
|
it 'appends to its buffer when #write is called' do
|
@@ -103,7 +103,7 @@ shared_examples_for 'a connection' do |options|
|
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'unblocks the reactor' do
|
106
|
-
unblocker.should_receive(:unblock
|
106
|
+
unblocker.should_receive(:unblock)
|
107
107
|
handler.write('hello world')
|
108
108
|
end
|
109
109
|
|
@@ -190,7 +190,7 @@ shared_examples_for 'a connection' do |options|
|
|
190
190
|
handler.close
|
191
191
|
handler.write('hello world')
|
192
192
|
handler.flush
|
193
|
-
unblocker.should_not have_received(:unblock
|
193
|
+
unblocker.should_not have_received(:unblock)
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
@@ -214,7 +214,7 @@ shared_examples_for 'a connection' do |options|
|
|
214
214
|
handler.drain
|
215
215
|
handler.write('hello world')
|
216
216
|
handler.flush
|
217
|
-
unblocker.should_not have_received(:unblock
|
217
|
+
unblocker.should_not have_received(:unblock)
|
218
218
|
end
|
219
219
|
end
|
220
220
|
end
|
@@ -372,6 +372,13 @@ module Ione
|
|
372
372
|
loop_body.tick
|
373
373
|
end
|
374
374
|
|
375
|
+
it 'passes writable sockets as both readable and writable to the selector' do
|
376
|
+
socket.stub(:connected?).and_return(true)
|
377
|
+
socket.stub(:writable?).and_return(true)
|
378
|
+
selector.should_receive(:select).with([socket], [socket], anything, anything).and_return([nil, nil, nil])
|
379
|
+
loop_body.tick
|
380
|
+
end
|
381
|
+
|
375
382
|
it 'passes connecting sockets as writable to the selector' do
|
376
383
|
socket.stub(:connecting?).and_return(true)
|
377
384
|
socket.stub(:connect)
|
@@ -383,9 +390,6 @@ module Ione
|
|
383
390
|
socket.stub(:closed?).and_return(true)
|
384
391
|
selector.should_receive(:select).with([], [], anything, anything).and_return([nil, nil, nil])
|
385
392
|
loop_body.tick
|
386
|
-
socket.stub(:connected?).and_return(true)
|
387
|
-
selector.should_receive(:select).with([], [], anything, anything).and_return([nil, nil, nil])
|
388
|
-
loop_body.tick
|
389
393
|
end
|
390
394
|
|
391
395
|
it 'does nothing when IO.select raises Errno::EBADF' do
|
@@ -428,29 +432,9 @@ module Ione
|
|
428
432
|
end
|
429
433
|
|
430
434
|
it 'allows the caller to specify a custom timeout' do
|
435
|
+
loop_body = described_class.new(selector: selector, clock: clock, tick_resolution: 99)
|
431
436
|
selector.should_receive(:select).with(anything, anything, anything, 99).and_return([[], [], []])
|
432
|
-
loop_body.tick(99)
|
433
|
-
end
|
434
|
-
|
435
|
-
it 'completes timers that have expired' do
|
436
|
-
selector.stub(:select).and_return([nil, nil, nil])
|
437
|
-
clock.stub(:now).and_return(1)
|
438
|
-
future = loop_body.schedule_timer(1)
|
439
437
|
loop_body.tick
|
440
|
-
future.should_not be_completed
|
441
|
-
clock.stub(:now).and_return(2)
|
442
|
-
loop_body.tick
|
443
|
-
future.should be_completed
|
444
|
-
end
|
445
|
-
|
446
|
-
it 'clears out timers that have expired' do
|
447
|
-
selector.stub(:select).and_return([nil, nil, nil])
|
448
|
-
clock.stub(:now).and_return(1)
|
449
|
-
future = loop_body.schedule_timer(1)
|
450
|
-
clock.stub(:now).and_return(2)
|
451
|
-
loop_body.tick
|
452
|
-
future.should be_completed
|
453
|
-
expect { loop_body.tick }.to_not raise_error
|
454
438
|
end
|
455
439
|
end
|
456
440
|
|
@@ -474,28 +458,48 @@ module Ione
|
|
474
458
|
loop_body.add_socket(socket2)
|
475
459
|
loop_body.close_sockets
|
476
460
|
end
|
461
|
+
end
|
462
|
+
end
|
477
463
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
loop_body.add_socket(socket)
|
482
|
-
loop_body.close_sockets
|
483
|
-
end
|
464
|
+
describe Scheduler do
|
465
|
+
let :scheduler do
|
466
|
+
described_class.new(clock: clock)
|
484
467
|
end
|
485
468
|
|
486
|
-
|
487
|
-
|
488
|
-
|
469
|
+
let :clock do
|
470
|
+
double(:clock, now: 0)
|
471
|
+
end
|
472
|
+
|
473
|
+
describe '#tick' do
|
474
|
+
it 'completes timers that have expired' do
|
475
|
+
clock.stub(:now).and_return(1)
|
476
|
+
future = scheduler.schedule_timer(1)
|
477
|
+
scheduler.tick
|
478
|
+
future.should_not be_completed
|
479
|
+
clock.stub(:now).and_return(2)
|
480
|
+
scheduler.tick
|
481
|
+
future.should be_completed
|
489
482
|
end
|
490
483
|
|
484
|
+
it 'clears out timers that have expired' do
|
485
|
+
clock.stub(:now).and_return(1)
|
486
|
+
future = scheduler.schedule_timer(1)
|
487
|
+
clock.stub(:now).and_return(2)
|
488
|
+
scheduler.tick
|
489
|
+
future.should be_completed
|
490
|
+
expect { scheduler.tick }.to_not raise_error
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
describe '#cancel_timers' do
|
491
495
|
it 'fails all active timers with a CancelledError' do
|
492
496
|
clock.stub(:now).and_return(1)
|
493
|
-
f1 =
|
494
|
-
f2 =
|
495
|
-
f3 =
|
497
|
+
f1 = scheduler.schedule_timer(1)
|
498
|
+
f2 = scheduler.schedule_timer(3)
|
499
|
+
f3 = scheduler.schedule_timer(3)
|
496
500
|
clock.stub(:now).and_return(2)
|
497
|
-
|
498
|
-
|
501
|
+
scheduler.tick
|
502
|
+
scheduler.cancel_timers
|
499
503
|
f1.should be_completed
|
500
504
|
f2.should be_failed
|
501
505
|
f3.should be_failed
|
@@ -92,15 +92,15 @@ module Ione
|
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'has a reference to the unblocker' do
|
95
|
-
unblocker.stub(:unblock
|
95
|
+
unblocker.stub(:unblock)
|
96
96
|
acceptor.bind
|
97
97
|
acceptor.read
|
98
98
|
accepted_handlers.first.write('foo')
|
99
|
-
unblocker.should have_received(:unblock
|
99
|
+
unblocker.should have_received(:unblock)
|
100
100
|
end
|
101
101
|
|
102
102
|
it 'writes to the SSL socket' do
|
103
|
-
unblocker.stub(:unblock
|
103
|
+
unblocker.stub(:unblock)
|
104
104
|
ssl_socket.stub(:write_nonblock) { |b| b.bytesize }
|
105
105
|
acceptor.bind
|
106
106
|
acceptor.read
|
data/spec/support/fake_server.rb
CHANGED
@@ -13,7 +13,7 @@ class FakeServer
|
|
13
13
|
@received_bytes = ''
|
14
14
|
end
|
15
15
|
|
16
|
-
def start
|
16
|
+
def start(options={})
|
17
17
|
@lock.synchronize do
|
18
18
|
return if @running
|
19
19
|
@running = true
|
@@ -30,7 +30,7 @@ class FakeServer
|
|
30
30
|
self
|
31
31
|
end
|
32
32
|
|
33
|
-
def stop
|
33
|
+
def stop
|
34
34
|
@lock.synchronize do
|
35
35
|
return unless @running
|
36
36
|
@running = false
|
@@ -41,13 +41,13 @@ class FakeServer
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def broadcast
|
44
|
+
def broadcast(bytes)
|
45
45
|
@lock.synchronize do
|
46
46
|
@connections.each { |c| c.write_nonblock(bytes) }
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def await_connects
|
50
|
+
def await_connects(n=1)
|
51
51
|
started_at = Time.now
|
52
52
|
until @connects >= n
|
53
53
|
sleep(0.01)
|
@@ -55,7 +55,7 @@ class FakeServer
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def await_disconnects
|
58
|
+
def await_disconnects(n=1)
|
59
59
|
started_at = Time.now
|
60
60
|
until @disconnects >= n
|
61
61
|
sleep(0.01)
|