ione 1.2.5 → 1.3.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,7 +7,11 @@ module Ione
7
7
  module Io
8
8
  describe IoReactor do
9
9
  let :reactor do
10
- described_class.new(selector: selector, clock: clock)
10
+ described_class.new(options)
11
+ end
12
+
13
+ let :options do
14
+ {selector: selector, clock: clock, drain_timeout: 3}
11
15
  end
12
16
 
13
17
  let! :selector do
@@ -37,7 +41,7 @@ module Ione
37
41
  end
38
42
 
39
43
  after do
40
- reactor.stop if reactor.running?
44
+ reactor.stop.value if reactor.running?
41
45
  end
42
46
  end
43
47
 
@@ -77,15 +81,16 @@ module Ione
77
81
  end
78
82
  reactor.start.value
79
83
  stopped_future = reactor.stop
80
- restarted_future = reactor.start
81
84
  sequence = []
82
85
  stopped_future.on_complete { sequence << :stopped }
86
+ restarted_future = reactor.start
83
87
  restarted_future.on_complete { sequence << :restarted }
84
88
  barrier.push(nil)
85
89
  stopped_future.value
86
90
  restarted_future.value
91
+ await { sequence.size >= 2 }
87
92
  begin
88
- sequence.should eq([:stopped, :restarted])
93
+ sequence.should == [:stopped, :restarted]
89
94
  ensure
90
95
  reactor.stop
91
96
  barrier.push(nil) while reactor.running?
@@ -93,7 +98,6 @@ module Ione
93
98
  end
94
99
 
95
100
  it 'restarts the reactor even when restarted before a failed stop' do
96
- pending 'This test is broken in JRuby' if RUBY_ENGINE == 'jruby'
97
101
  barrier = Queue.new
98
102
  selector.handler do
99
103
  if barrier.pop == :fail
@@ -112,6 +116,7 @@ module Ione
112
116
  barrier.push(:fail)
113
117
  stopped_future.value rescue nil
114
118
  restarted_future.value
119
+ await { crashed && restarted }
115
120
  begin
116
121
  crashed.should be_true
117
122
  restarted.should be_true
@@ -136,6 +141,8 @@ module Ione
136
141
 
137
142
  context 'when already started' do
138
143
  it 'is not started again' do
144
+ calls = 0
145
+ lock = Mutex.new
139
146
  ticks = Queue.new
140
147
  barrier = Queue.new
141
148
  selector.handler do
@@ -176,7 +183,7 @@ module Ione
176
183
  reactor.should_not be_running
177
184
  end
178
185
 
179
- it 'keeps running until stop completed' do
186
+ it 'keeps running until stop completes' do
180
187
  running_barrier = Queue.new
181
188
  stop_barrier = Queue.new
182
189
  selector.handler do
@@ -191,11 +198,125 @@ module Ione
191
198
  stop_barrier.push(nil) until future.completed?
192
199
  end
193
200
 
194
- it 'closes all sockets' do
201
+ it 'unblocks the reactor' do
202
+ running_barrier = Queue.new
203
+ selector.handler do |readables, writables, _, _|
204
+ running_barrier.push(nil)
205
+ IO.select(readables, writables, nil, 5)
206
+ end
195
207
  reactor.start.value
196
- connection = reactor.connect('example.com', 9999, 5).value
197
- reactor.stop.value
198
- connection.should be_closed
208
+ running_barrier.pop
209
+ stopped_future = reactor.stop
210
+ await { stopped_future.completed? }
211
+ stopped_future.should be_completed
212
+ stopped_future.value
213
+ end
214
+
215
+ it 'drains all sockets' do
216
+ reactor.start.value
217
+ TCPServer.open(0) do |server|
218
+ lazy_socket = Thread.start { server.accept }
219
+ connection = reactor.connect(server.addr[3], server.addr[1], 5).value
220
+ writable = false
221
+ connection.stub(:stub_writable?) { writable }
222
+ class <<connection; alias_method :writable?, :stub_writable?; end
223
+ connection.write('12345678')
224
+ release_barrier = barrier = Queue.new
225
+ selector.handler do |readables, writables, _, _|
226
+ barrier.pop
227
+ [[], writables, []]
228
+ end
229
+ await { barrier.num_waiting > 0 }
230
+ barrier = []
231
+ release_barrier.push(nil)
232
+ connection.stub(:flush) do
233
+ writable = false
234
+ end
235
+ writable = true
236
+ reactor.stop.value
237
+ connection.should have_received(:flush)
238
+ end
239
+ end
240
+
241
+ it 'waits on drain to complete upto the specified drain timeout' do
242
+ time = time_increment = next_increment = 0
243
+ mutex = Mutex.new
244
+ clock.stub(:now) { mutex.synchronize { time } }
245
+ selector.handler do |_, writables, _, _|
246
+ mutex.synchronize do
247
+ time += time_increment
248
+ time_increment = next_increment
249
+ end
250
+ [[], writables, []]
251
+ end
252
+ reactor.start.value
253
+ TCPServer.open(0) do |server|
254
+ lazy_socket = Thread.start { server.accept }
255
+ connection = reactor.connect(server.addr[3], server.addr[1], 5).value
256
+ stopped_future = nil
257
+ mutex.synchronize do
258
+ connection.stub(:writable?).and_return(true)
259
+ connection.stub(:flush)
260
+ next_increment = 1
261
+ stopped_future = reactor.stop
262
+ end
263
+ expect { stopped_future.value }.to raise_error(ReactorError, /timeout/)
264
+ (time).should eq(3)
265
+ end
266
+ end
267
+
268
+ it 'waits on drain to complete upto five seconds by default' do
269
+ with_server do |host, port|
270
+ options.delete(:drain_timeout)
271
+ time = time_increment = next_increment = 0
272
+ mutex = Mutex.new
273
+ clock.stub(:now) { mutex.synchronize { time } }
274
+ selector.handler do |_, writables, _, _|
275
+ mutex.synchronize do
276
+ time += time_increment
277
+ time_increment = next_increment
278
+ end
279
+ [[], writables, []]
280
+ end
281
+ reactor.start.value
282
+ connection = reactor.connect(host, port, 5).value
283
+ stopped_future = nil
284
+ mutex.synchronize do
285
+ connection.stub(:writable?).and_return(true)
286
+ connection.stub(:flush)
287
+ next_increment = 1
288
+ stopped_future = reactor.stop
289
+ end
290
+ expect { stopped_future.value }.to raise_error(ReactorError, /timeout/)
291
+ time.should eq(5)
292
+ end
293
+ end
294
+
295
+ it 'closes all sockets' do
296
+ with_server do |host, port|
297
+ reactor.start.value
298
+ connection = reactor.connect(host, port, 5).value
299
+ reactor.stop.value
300
+ connection.should be_closed
301
+ end
302
+ end
303
+
304
+ it 'closes all sockets even if drain fails' do
305
+ with_server do |host, port|
306
+ reactor.start.value
307
+ connection = reactor.connect(host, port, 5).value
308
+ Thread.pass
309
+ writable = false
310
+ connection.stub(:stub_writable?) { writable }
311
+ class <<connection; alias_method :writable?, :stub_writable?; end
312
+ connection.write('12345678')
313
+ Thread.pass
314
+ connection.stub(:flush).and_raise(StandardError, 'Boork')
315
+ writable = true
316
+ f = reactor.stop
317
+ expect { f.value }.to raise_error(StandardError, 'Boork')
318
+ connection.should be_closed
319
+ end
199
320
  end
200
321
 
201
322
  it 'cancels all active timers' do
@@ -237,7 +358,7 @@ module Ione
237
358
  reactor.on_error { |e| error = e }
238
359
  reactor.start
239
360
  await { error }
240
- error.message.should eq('Blurgh')
361
+ error.message.should == 'Blurgh'
241
362
  end
242
363
 
243
364
  it 'calls the listener immediately when the reactor has already crashed' do
@@ -266,17 +387,18 @@ module Ione
266
387
  reactor.on_error { calls << :post_started }
267
388
  barrier.push(nil)
268
389
  await { !reactor.running? }
390
+ await { calls.size >= 2 }
269
391
  reactor.on_error { calls << :pre_restarted }
270
- calls.should eq([
392
+ calls.should == [
271
393
  :pre_started,
272
394
  :post_started,
273
395
  :pre_restarted,
274
- ])
396
+ ]
275
397
  reactor.start
276
398
  reactor.on_error { calls << :post_restarted }
277
399
  barrier.push(nil)
278
400
  await { !reactor.running? }
279
- calls.should eq([
401
+ calls.should == [
280
402
  :pre_started,
281
403
  :post_started,
282
404
  :pre_restarted,
@@ -284,7 +406,7 @@ module Ione
284
406
  :post_started,
285
407
  :pre_restarted,
286
408
  :post_restarted,
287
- ])
409
+ ]
288
410
  end
289
411
  end
290
412
 
@@ -292,70 +414,90 @@ module Ione
292
414
  include_context 'running_reactor'
293
415
 
294
416
  it 'calls the given block with a connection' do
295
- connection = nil
296
- reactor.start.value
297
- reactor.connect('example.com', 9999, 5) { |c| connection = c }.value
298
- connection.should_not be_nil
417
+ with_server do |host, port|
418
+ connection = nil
419
+ reactor.start.value
420
+ reactor.connect(host, port, 5) { |c| connection = c }.value
421
+ connection.should_not be_nil
422
+ end
299
423
  end
300
424
 
301
425
  it 'returns a future that resolves to what the given block returns' do
302
- reactor.start.value
303
- x = reactor.connect('example.com', 9999, 5) { :foo }.value
304
- x.should eq(:foo)
426
+ with_server do |host, port|
427
+ reactor.start.value
428
+ x = reactor.connect(host, port, 5) { :foo }.value
429
+ x.should == :foo
430
+ end
305
431
  end
306
432
 
307
433
  it 'defaults to 5 as the connection timeout' do
308
- reactor.start.value
309
- connection = reactor.connect('example.com', 9999).value
310
- connection.connection_timeout.should eq(5)
434
+ with_server do |host, port|
435
+ reactor.start.value
436
+ connection = reactor.connect(host, port).value
437
+ connection.connection_timeout.should == 5
438
+ end
311
439
  end
312
440
 
313
441
  it 'takes the connection timeout from the :timeout option' do
314
- reactor.start.value
315
- connection = reactor.connect('example.com', 9999, timeout: 9).value
316
- connection.connection_timeout.should eq(9)
442
+ with_server do |host, port|
443
+ reactor.start.value
444
+ connection = reactor.connect(host, port, timeout: 9).value
445
+ connection.connection_timeout.should == 9
446
+ end
317
447
  end
318
448
 
319
449
  it 'returns the connection when no block is given' do
320
- reactor.start.value
321
- reactor.connect('example.com', 9999, 5).value.should be_a(Connection)
450
+ with_server do |host, port|
451
+ reactor.start.value
452
+ reactor.connect(host, port, 5).value.should be_a(Connection)
453
+ end
322
454
  end
323
455
 
324
456
  it 'creates a connection and passes it to the selector as a readable' do
325
- reactor.start.value
326
- connection = reactor.connect('example.com', 9999, 5).value
327
- await { selector.last_arguments[0].length > 1 }
328
- selector.last_arguments[0].should include(connection)
457
+ with_server do |host, port|
458
+ reactor.start.value
459
+ connection = reactor.connect(host, port, 5).value
460
+ await { selector.last_arguments[0].length > 1 }
461
+ selector.last_arguments[0].should include(connection)
462
+ end
329
463
  end
330
464
 
331
465
  it 'upgrades the connection to SSL' do
332
- reactor.start.value
333
- connection = reactor.connect('example.com', 9999, ssl: true).value
334
- connection.should be_a(SslConnection)
466
+ with_server do |host, port|
467
+ reactor.start.value
468
+ connection = reactor.connect(host, port, ssl: true).value
469
+ connection.should be_a(SslConnection)
470
+ end
335
471
  end
336
472
 
337
473
  it 'passes an SSL context to the SSL connection' do
338
- ssl_context = double(:ssl_context)
339
- reactor.start.value
340
- f = reactor.connect('example.com', 9999, ssl: ssl_context)
341
- expect { f.value }.to raise_error
474
+ with_server do |host, port|
475
+ ssl_context = double(:ssl_context)
476
+ reactor.start.value
477
+ f = reactor.connect(host, port, ssl: ssl_context)
478
+ expect { f.value }.to raise_error
479
+ end
342
480
  end
343
481
 
344
482
  context 'when called before the reactor is started' do
345
483
  it 'waits for the reactor to start' do
346
- f = reactor.connect('example.com', 9999)
347
- reactor.start.value
348
- f.value
484
+ with_server do |host, port|
485
+ f = reactor.connect(host, port)
486
+ reactor.start.value
487
+ f.value
488
+ end
349
489
  end
350
490
  end
351
491
 
352
492
  context 'when called after the reactor has stopped' do
353
493
  it 'waits for the reactor to be restarted' do
354
- reactor.start.value
355
- reactor.stop.value
356
- f = reactor.connect('example.com', 9999)
357
- reactor.start.value
358
- f.value
494
+ with_server do |host, port|
495
+ reactor.start.value
496
+ reactor.stop.value
497
+ f = reactor.connect(host, port)
498
+ reactor.start.value
499
+ f.value
500
+ end
359
501
  end
360
502
  end
361
503
  end
@@ -377,19 +519,19 @@ module Ione
377
519
  it 'returns a future that resolves to what the given block returns' do
378
520
  reactor.start.value
379
521
  x = reactor.bind(ENV['SERVER_HOST'], port, 5) { |acceptor| :foo }.value
380
- x.should eq(:foo)
522
+ x.should == :foo
381
523
  end
382
524
 
383
525
  it 'defaults to a backlog of 5' do
384
526
  reactor.start.value
385
527
  acceptor = reactor.bind(ENV['SERVER_HOST'], port).value
386
- acceptor.backlog.should eq(5)
528
+ acceptor.backlog.should == 5
387
529
  end
388
530
 
389
531
  it 'takes the backlog from the :backlog option' do
390
532
  reactor.start.value
391
533
  acceptor = reactor.bind(ENV['SERVER_HOST'], port, backlog: 9).value
392
- acceptor.backlog.should eq(9)
534
+ acceptor.backlog.should == 9
393
535
  end
394
536
 
395
537
  it 'returns the acceptor when no block is given' do
@@ -442,12 +584,10 @@ module Ione
442
584
  end
443
585
 
444
586
  it 'returns a future that is resolved after the specified duration' do
445
- start = Time.now
446
587
  clock.stub(:now).and_return(1)
447
- f = reactor.schedule_timer(8)
448
- clock.stub(:now).and_return(10.1)
588
+ f = reactor.schedule_timer(0.1)
589
+ clock.stub(:now).and_return(1.1)
449
590
  await { f.resolved? }
450
- expect(Time.now - start).to be < 1
451
591
  end
452
592
  end
453
593
 
@@ -760,4 +900,4 @@ module IoReactorSpec
760
900
  @body.call(*args)
761
901
  end
762
902
  end
763
- end
903
+ end
@@ -7,7 +7,7 @@ module Ione
7
7
  module Io
8
8
  describe SslAcceptor do
9
9
  let :acceptor do
10
- described_class.new('example.com', 4321, 3, unblocker, reactor, ssl_context, socket_impl, ssl_socket_impl)
10
+ described_class.new('example.com', 4321, backlog = 3, unblocker, reactor, ssl_context, socket_impl, ssl_socket_impl)
11
11
  end
12
12
 
13
13
  let :unblocker do
@@ -80,8 +80,8 @@ module Ione
80
80
  acceptor.bind
81
81
  acceptor.read
82
82
  accepted_handlers.should have(1).item
83
- accepted_handlers.first.host.should eq('example.com')
84
- accepted_handlers.first.port.should eq(3333)
83
+ accepted_handlers.first.host.should == 'example.com'
84
+ accepted_handlers.first.port.should == 3333
85
85
  end
86
86
 
87
87
  it 'returns the raw socket from #to_io' do
@@ -124,7 +124,7 @@ module Ione
124
124
  end
125
125
  handler.connect
126
126
  handler.read
127
- read_sizes.drop(1).should eq([read_sizes.first] * 3)
127
+ read_sizes.drop(1).should == [read_sizes.first] * 3
128
128
  end
129
129
  else
130
130
  it 'reads and initial chunk of data' do
@@ -134,7 +134,7 @@ module Ione
134
134
  ssl_socket.stub(:read_nonblock).and_return('fooo')
135
135
  handler.connect
136
136
  handler.read
137
- data.should eq(['fooo'])
137
+ data.should == ['fooo']
138
138
  end
139
139
 
140
140
  it 'reads once, and then again with the value of #pending, until #pending returns zero' do
@@ -149,7 +149,7 @@ module Ione
149
149
  end
150
150
  handler.connect
151
151
  handler.read
152
- read_sizes.drop(1).should eq([3, 2, 1])
152
+ read_sizes.drop(1).should == [3, 2, 1]
153
153
  end
154
154
  end
155
155
 
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ require 'bundler/setup'
6
6
 
7
7
  require 'support/fake_server'
8
8
  require 'support/await_helper'
9
+ require 'support/server_helper'
9
10
 
10
11
  unless ENV['COVERAGE'] == 'no' || RUBY_ENGINE == 'rbx'
11
12
  require 'coveralls'
@@ -23,8 +24,4 @@ unless ENV['COVERAGE'] == 'no' || RUBY_ENGINE == 'rbx'
23
24
  end
24
25
  end
25
26
 
26
- RSpec.configure do |config|
27
- config.warnings = true
28
- end
29
-
30
27
  require 'ione'
@@ -11,7 +11,6 @@ class FakeServer
11
11
  @disconnects = 0
12
12
  @connections = []
13
13
  @received_bytes = ''
14
- @running = false
15
14
  end
16
15
 
17
16
  def start(options={})
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module ServerHelper
4
+ def with_server
5
+ TCPServer.open(0) do |server|
6
+ thread = Thread.start { server.accept }
7
+ yield server.addr[3], server.addr[1]
8
+ thread.value
9
+ end
10
+ end
11
+ end
12
+
13
+ RSpec.configure do |c|
14
+ c.include(ServerHelper)
15
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ione
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0.pre0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theo Hultberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-22 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Reactive programming framework for Ruby, painless evented IO, futures
14
14
  and an efficient byte buffer
@@ -50,6 +50,7 @@ files:
50
50
  - spec/spec_helper.rb
51
51
  - spec/support/await_helper.rb
52
52
  - spec/support/fake_server.rb
53
+ - spec/support/server_helper.rb
53
54
  homepage: http://github.com/iconara/ione
54
55
  licenses:
55
56
  - Apache License 2.0
@@ -65,28 +66,31 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
66
  version: 1.9.3
66
67
  required_rubygems_version: !ruby/object:Gem::Requirement
67
68
  requirements:
68
- - - ">="
69
+ - - ">"
69
70
  - !ruby/object:Gem::Version
70
- version: '0'
71
+ version: 1.3.1
71
72
  requirements: []
72
- rubygems_version: 3.0.3
73
+ rubyforge_project:
74
+ rubygems_version: 2.2.2
73
75
  signing_key:
74
76
  specification_version: 4
75
77
  summary: Reactive programming framework for Ruby
76
78
  test_files:
77
- - spec/spec_helper.rb
78
- - spec/ione/io/ssl_acceptor_spec.rb
79
- - spec/ione/io/server_connection_spec.rb
80
- - spec/ione/io/ssl_server_connection_spec.rb
79
+ - spec/integration/io_spec.rb
80
+ - spec/integration/ssl_spec.rb
81
+ - spec/ione/byte_buffer_spec.rb
82
+ - spec/ione/future_spec.rb
83
+ - spec/ione/heap_spec.rb
81
84
  - spec/ione/io/acceptor_spec.rb
85
+ - spec/ione/io/connection_common.rb
82
86
  - spec/ione/io/connection_spec.rb
83
- - spec/ione/io/ssl_connection_spec.rb
84
87
  - spec/ione/io/io_reactor_spec.rb
85
- - spec/ione/io/connection_common.rb
86
- - spec/ione/heap_spec.rb
87
- - spec/ione/byte_buffer_spec.rb
88
- - spec/ione/future_spec.rb
89
- - spec/integration/ssl_spec.rb
90
- - spec/integration/io_spec.rb
88
+ - spec/ione/io/server_connection_spec.rb
89
+ - spec/ione/io/ssl_acceptor_spec.rb
90
+ - spec/ione/io/ssl_connection_spec.rb
91
+ - spec/ione/io/ssl_server_connection_spec.rb
92
+ - spec/spec_helper.rb
91
93
  - spec/support/await_helper.rb
92
94
  - spec/support/fake_server.rb
95
+ - spec/support/server_helper.rb
96
+ has_rdoc: