ione 1.0.0 → 1.1.0.pre0

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.
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
+ require 'ione/io/connection_common'
4
5
 
5
6
 
6
7
  module Ione
@@ -38,10 +39,21 @@ module Ione
38
39
  .and_return(socket)
39
40
  end
40
41
 
42
+ before do
43
+ socket.stub(:connect_nonblock)
44
+ socket.stub(:close)
45
+ end
46
+
47
+ it_behaves_like 'a connection' do
48
+ before do
49
+ handler.connect
50
+ end
51
+ end
52
+
41
53
  describe '#connect' do
42
54
  it 'creates a socket and calls #connect_nonblock' do
43
- socket.should_receive(:connect_nonblock).with('SOCKADDR1')
44
55
  handler.connect
56
+ socket.should have_received(:connect_nonblock).with('SOCKADDR1')
45
57
  end
46
58
 
47
59
  it 'handles EINPROGRESS that #connect_nonblock raises' do
@@ -56,23 +68,26 @@ module Ione
56
68
  end
57
69
 
58
70
  it 'is connecting even after the second call' do
59
- socket.should_receive(:connect_nonblock).twice.and_raise(Errno::EINPROGRESS)
71
+ socket.stub(:connect_nonblock).and_raise(Errno::EINPROGRESS)
60
72
  handler.connect
61
73
  handler.connect
62
74
  handler.should be_connecting
75
+ socket.should have_received(:connect_nonblock).twice
63
76
  end
64
77
 
65
78
  it 'does not create a new socket the second time' do
66
- socket_impl.should_receive(:new).once.and_return(socket)
79
+ socket_impl.stub(:new).and_return(socket)
67
80
  socket.stub(:connect_nonblock).and_raise(Errno::EINPROGRESS)
68
81
  handler.connect
69
82
  handler.connect
83
+ socket_impl.should have_received(:new).once
70
84
  end
71
85
 
72
86
  it 'attempts another connect the second time' do
73
- socket.should_receive(:connect_nonblock).twice.and_raise(Errno::EINPROGRESS)
87
+ socket.stub(:connect_nonblock).and_raise(Errno::EINPROGRESS)
74
88
  handler.connect
75
89
  handler.connect
90
+ socket.should have_received(:connect_nonblock).twice
76
91
  end
77
92
 
78
93
  shared_examples 'on successfull connection' do
@@ -264,60 +279,6 @@ module Ione
264
279
  end
265
280
  end
266
281
 
267
- describe '#close' do
268
- before do
269
- socket.stub(:connect_nonblock)
270
- socket.stub(:close)
271
- handler.connect
272
- end
273
-
274
- it 'closes the socket' do
275
- socket.should_receive(:close)
276
- handler.close
277
- end
278
-
279
- it 'returns true' do
280
- handler.close.should be_true
281
- end
282
-
283
- it 'swallows SystemCallErrors' do
284
- socket.stub(:close).and_raise(SystemCallError.new('Bork!', 9999))
285
- handler.close
286
- end
287
-
288
- it 'swallows IOErrors' do
289
- socket.stub(:close).and_raise(IOError.new('Bork!'))
290
- handler.close
291
- end
292
-
293
- it 'calls the closed listener' do
294
- called = false
295
- handler.on_closed { called = true }
296
- handler.close
297
- called.should be_true, 'expected the close listener to have been called'
298
- end
299
-
300
- it 'does nothing when closed a second time' do
301
- socket.should_receive(:close).once
302
- calls = 0
303
- handler.on_closed { calls += 1 }
304
- handler.close
305
- handler.close
306
- calls.should == 1
307
- end
308
-
309
- it 'returns false if it did nothing' do
310
- handler.close
311
- handler.close.should be_false
312
- end
313
-
314
- it 'is not writable when closed' do
315
- handler.write('foo')
316
- handler.close
317
- handler.should_not be_writable
318
- end
319
- end
320
-
321
282
  describe '#to_io' do
322
283
  before do
323
284
  socket.stub(:connect_nonblock)
@@ -340,128 +301,10 @@ module Ione
340
301
  end
341
302
  end
342
303
 
343
- describe '#write/#flush' do
344
- before do
345
- socket.stub(:connect_nonblock)
346
- handler.connect
347
- end
348
-
349
- it 'appends to its buffer when #write is called' do
350
- handler.write('hello world')
351
- end
352
-
353
- it 'unblocks the reactor' do
354
- unblocker.should_receive(:unblock!)
355
- handler.write('hello world')
356
- end
357
-
358
- it 'is writable when there are bytes to write' do
359
- handler.should_not be_writable
360
- handler.write('hello world')
361
- handler.should be_writable
362
- socket.should_receive(:write_nonblock).with('hello world').and_return(11)
363
- handler.flush
364
- handler.should_not be_writable
365
- end
366
-
367
- it 'writes to the socket from its buffer when #flush is called' do
368
- handler.write('hello world')
369
- socket.should_receive(:write_nonblock).with('hello world').and_return(11)
370
- handler.flush
371
- end
372
-
373
- it 'takes note of how much the #write_nonblock call consumed and writes the rest of the buffer on the next call to #flush' do
374
- handler.write('hello world')
375
- socket.should_receive(:write_nonblock).with('hello world').and_return(6)
376
- handler.flush
377
- socket.should_receive(:write_nonblock).with('world').and_return(5)
378
- handler.flush
379
- end
380
-
381
- it 'does not call #write_nonblock if the buffer is empty' do
382
- handler.flush
383
- handler.write('hello world')
384
- socket.should_receive(:write_nonblock).with('hello world').and_return(11)
385
- handler.flush
386
- socket.should_not_receive(:write_nonblock)
387
- handler.flush
388
- end
389
-
390
- context 'with a block' do
391
- it 'yields a byte buffer to the block' do
392
- socket.should_receive(:write_nonblock).with('hello world').and_return(11)
393
- handler.write do |buffer|
394
- buffer << 'hello world'
395
- end
396
- handler.flush
397
- end
398
- end
399
-
400
- context 'when #write_nonblock raises an error' do
401
- before do
402
- socket.stub(:close)
403
- socket.stub(:write_nonblock).and_raise('Bork!')
404
- end
405
-
406
- it 'closes the socket' do
407
- socket.should_receive(:close)
408
- handler.write('hello world')
409
- handler.flush
410
- end
411
-
412
- it 'passes the error to the close handler' do
413
- error = nil
414
- handler.on_closed { |e| error = e }
415
- handler.write('hello world')
416
- handler.flush
417
- error.should be_a(Exception)
418
- end
419
- end
420
- end
421
-
422
- describe '#read' do
423
- before do
424
- socket.stub(:connect_nonblock)
425
- handler.connect
426
- end
427
-
428
- it 'reads a chunk from the socket' do
429
- socket.should_receive(:read_nonblock).with(instance_of(Fixnum)).and_return('foo bar')
430
- handler.read
431
- end
432
-
433
- it 'calls the data listener with the new data' do
434
- socket.should_receive(:read_nonblock).with(instance_of(Fixnum)).and_return('foo bar')
435
- data = nil
436
- handler.on_data { |d| data = d }
437
- handler.read
438
- data.should == 'foo bar'
439
- end
440
-
441
- context 'when #read_nonblock raises an error' do
442
- before do
443
- socket.stub(:close)
444
- socket.stub(:read_nonblock).and_raise('Bork!')
445
- end
446
-
447
- it 'closes the socket' do
448
- socket.should_receive(:close)
449
- handler.read
450
- end
451
-
452
- it 'passes the error to the close handler' do
453
- error = nil
454
- handler.on_closed { |e| error = e }
455
- handler.read
456
- error.should be_a(Exception)
457
- end
458
- end
459
- end
460
-
461
304
  describe '#to_s' do
462
305
  context 'returns a string that' do
463
306
  it 'includes the class name' do
464
- handler.to_s.should include('Ione::Io::Connection')
307
+ handler.to_s.should include(described_class.name.to_s)
465
308
  end
466
309
 
467
310
  it 'includes the host and port' do
@@ -469,13 +312,15 @@ module Ione
469
312
  end
470
313
 
471
314
  it 'includes the connection state' do
472
- handler.to_s.should include('closed')
315
+ handler.to_s.should include('connecting')
473
316
  socket.stub(:connect_nonblock).and_raise(Errno::EINPROGRESS)
474
317
  handler.connect
475
318
  handler.to_s.should include('connecting')
476
319
  socket.stub(:connect_nonblock)
477
320
  handler.connect
478
321
  handler.to_s.should include('connected')
322
+ handler.close
323
+ handler.to_s.should include('closed')
479
324
  end
480
325
  end
481
326
  end
@@ -146,22 +146,64 @@ module Ione
146
146
  describe '#connect' do
147
147
  include_context 'running_reactor'
148
148
 
149
- it 'calls the given block with the connection and the reactor itself and returns what it returns' do
149
+ it 'calls the given block with a connection' do
150
150
  connection = nil
151
151
  reactor.start.value
152
152
  reactor.connect('example.com', 9999, 5) { |c| connection = c }.value
153
- connection.should be_a(Connection)
153
+ connection.should_not be_nil
154
154
  end
155
155
 
156
156
  it 'returns a future that resolves to what the given block returns' do
157
157
  reactor.start.value
158
- reactor.connect('example.com', 9999, 5) { :foo }.value.should == :foo
158
+ x = reactor.connect('example.com', 9999, 5) { :foo }.value
159
+ x.should == :foo
159
160
  end
160
161
 
161
162
  it 'returns the connection when no block is given' do
162
163
  reactor.start.value
163
164
  reactor.connect('example.com', 9999, 5).value.should be_a(Connection)
164
165
  end
166
+
167
+ it 'creates a connection and passes it to the selector as a readable' do
168
+ reactor.start.value
169
+ connection = reactor.connect('example.com', 9999, 5).value
170
+ await { selector.last_arguments[0].length > 1 }
171
+ selector.last_arguments[0].should include(connection)
172
+ end
173
+ end
174
+
175
+ describe '#bind' do
176
+ include_context 'running_reactor'
177
+
178
+ let :port do
179
+ 2**15 + rand(2**15)
180
+ end
181
+
182
+ it 'calls the given block with an acceptor' do
183
+ acceptor = nil
184
+ reactor.start.value
185
+ reactor.bind(ENV['SERVER_HOST'], port, 5) { |a| acceptor = a }.value
186
+ acceptor.should_not be_nil
187
+ end
188
+
189
+ it 'returns a future that resolves to what the given block returns' do
190
+ reactor.start.value
191
+ x = reactor.bind(ENV['SERVER_HOST'], port, 5) { |acceptor| :foo }.value
192
+ x.should == :foo
193
+ end
194
+
195
+ it 'returns the acceptor when no block is given' do
196
+ reactor.start.value
197
+ acceptor = reactor.bind(ENV['SERVER_HOST'], port, 5).value
198
+ acceptor.should be_an(Acceptor)
199
+ end
200
+
201
+ it 'creates an acceptor and passes it to the selector as a readable' do
202
+ reactor.start.value
203
+ acceptor = reactor.bind(ENV['SERVER_HOST'], port, 5).value
204
+ await { selector.last_arguments[0].length > 1 }
205
+ selector.last_arguments[0].should include(acceptor)
206
+ end
165
207
  end
166
208
 
167
209
  describe '#schedule_timer' do
@@ -357,6 +399,8 @@ end
357
399
 
358
400
  module IoReactorSpec
359
401
  class FakeSelector
402
+ attr_reader :last_arguments
403
+
360
404
  def initialize
361
405
  handler { [[], [], []] }
362
406
  end
@@ -366,6 +410,7 @@ module IoReactorSpec
366
410
  end
367
411
 
368
412
  def select(*args)
413
+ @last_arguments = args
369
414
  @body.call(*args)
370
415
  end
371
416
  end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'ione/io/connection_common'
5
+
6
+
7
+ module Ione
8
+ module Io
9
+ describe ServerConnection do
10
+ let :handler do
11
+ described_class.new(socket, 'example.com', 4321, unblocker)
12
+ end
13
+
14
+ let :socket do
15
+ double(:socket, close: nil)
16
+ end
17
+
18
+ let :unblocker do
19
+ double(:unblocker, unblock!: nil)
20
+ end
21
+
22
+ it_behaves_like 'a connection'
23
+
24
+ describe '#to_io' do
25
+ it 'returns the socket' do
26
+ handler.to_io.should equal(socket)
27
+ end
28
+
29
+ it 'returns nil when the socket is closed' do
30
+ socket.stub(:close)
31
+ handler.close
32
+ handler.to_io.should be_nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+ 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.0.0
4
+ version: 1.1.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: 2014-03-15 00:00:00.000000000 Z
11
+ date: 2014-03-22 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
@@ -24,14 +24,20 @@ files:
24
24
  - lib/ione/byte_buffer.rb
25
25
  - lib/ione/future.rb
26
26
  - lib/ione/io.rb
27
+ - lib/ione/io/acceptor.rb
28
+ - lib/ione/io/base_connection.rb
27
29
  - lib/ione/io/connection.rb
28
30
  - lib/ione/io/io_reactor.rb
31
+ - lib/ione/io/server_connection.rb
29
32
  - lib/ione/version.rb
30
33
  - spec/integration/io_spec.rb
31
34
  - spec/ione/byte_buffer_spec.rb
32
35
  - spec/ione/future_spec.rb
36
+ - spec/ione/io/acceptor_spec.rb
37
+ - spec/ione/io/connection_common.rb
33
38
  - spec/ione/io/connection_spec.rb
34
39
  - spec/ione/io/io_reactor_spec.rb
40
+ - spec/ione/io/server_connection_spec.rb
35
41
  - spec/spec_helper.rb
36
42
  - spec/support/await_helper.rb
37
43
  - spec/support/fake_server.rb
@@ -50,9 +56,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
56
  version: 1.9.3
51
57
  required_rubygems_version: !ruby/object:Gem::Requirement
52
58
  requirements:
53
- - - '>='
59
+ - - '>'
54
60
  - !ruby/object:Gem::Version
55
- version: '0'
61
+ version: 1.3.1
56
62
  requirements: []
57
63
  rubyforge_project:
58
64
  rubygems_version: 2.2.1
@@ -63,8 +69,11 @@ test_files:
63
69
  - spec/integration/io_spec.rb
64
70
  - spec/ione/byte_buffer_spec.rb
65
71
  - spec/ione/future_spec.rb
72
+ - spec/ione/io/acceptor_spec.rb
73
+ - spec/ione/io/connection_common.rb
66
74
  - spec/ione/io/connection_spec.rb
67
75
  - spec/ione/io/io_reactor_spec.rb
76
+ - spec/ione/io/server_connection_spec.rb
68
77
  - spec/spec_helper.rb
69
78
  - spec/support/await_helper.rb
70
79
  - spec/support/fake_server.rb