ione 1.0.0 → 1.1.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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