ione 1.2.0.pre5 → 1.2.0.pre6
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|