em-synchrony 1.0.1 → 1.0.2

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,30 +1,413 @@
1
1
  require "spec/helper/all"
2
2
 
3
- describe EventMachine::Synchrony::TCPSocket do
4
- it 'connects to a TCP port' do
5
- EventMachine.synchrony do
6
- @socket = EventMachine::Synchrony::TCPSocket.new 'eventmachine.rubyforge.org', 80
7
- @socket.should_not be_error
8
- EM.stop
9
- end
3
+ module SendAndClose
4
+ def post_init
5
+ send_data "1234"
6
+ close_connection_after_writing
7
+ end
8
+ end
9
+
10
+ module SendAndTimedClose
11
+ def post_init
12
+ send_data "1234"
13
+ EM.add_timer(0.05) { self.close_connection_after_writing }
14
+ end
15
+ end
16
+
17
+ module SendAndKeepOpen
18
+ def post_init
19
+ send_data "1234"
10
20
  end
21
+ end
11
22
 
12
- it 'errors on connection failure' do
23
+ def tcp_test(server_type, ops={}, &block)
24
+ Proc.new do
13
25
  EventMachine.synchrony do
14
- proc {
15
- EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
16
- }.should raise_error(SocketError)
17
- EM.stop
26
+ ops = {:stop => true}.merge ops
27
+ EM::start_server('localhost', 12345, server_type)
28
+ @socket = EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
29
+ @socket.close if ops[:close]
30
+ block.call
31
+ EM.stop if ops[:stop]
18
32
  end
19
33
  end
34
+ end
20
35
 
21
- it 'should accept "send" when wrapped in a connection pool' do
22
- EventMachine.synchrony do
23
- @socket = EventMachine::Synchrony::ConnectionPool.new(size: 1) do
24
- EventMachine::Synchrony::TCPSocket.new 'eventmachine.rubyforge.org', 80
36
+ describe EventMachine::Synchrony::TCPSocket do
37
+ context '.new' do
38
+ context 'to an open TCP port on an resolvable host' do
39
+ it 'succeeds' do
40
+ EventMachine.synchrony do
41
+ EM::start_server('localhost', 12345)
42
+ @socket = EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
43
+ @socket.should_not be_error
44
+ EM.stop
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'to an unresolvable host' do
50
+ it 'raises SocketError' do
51
+ EventMachine.synchrony do
52
+ proc {
53
+ EventMachine::Synchrony::TCPSocket.new 'xxxyyyzzz', 12345
54
+ }.should raise_error(SocketError)
55
+ EM.stop
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'to a closed TCP port' do
61
+ it 'raises Errno::ECONNREFUSED' do
62
+ EventMachine.synchrony do
63
+ proc {
64
+ EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
65
+ }.should raise_error(Errno::ECONNREFUSED)
66
+ EM.stop
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context '#closed?' do
73
+ context 'after calling #close' do
74
+ it 'returns true' do
75
+ tcp_test(SendAndKeepOpen, :close => true) do
76
+ @socket.should be_closed
77
+ end
78
+ end
79
+ end
80
+ context 'after the peer has closed the connection' do
81
+ context 'when we\'ve not yet read EOF' do
82
+ it 'returns false' do
83
+ tcp_test(SendAndClose) do
84
+ @socket.read(2).size.should eq 2
85
+ @socket.should_not be_closed
86
+ end
87
+ end
88
+ end
89
+ context 'when we\'ve read EOF' do
90
+ it 'returns false' do
91
+ tcp_test(SendAndClose) do
92
+ @socket.read(10).size.should < 10
93
+ @socket.read(10).should be_nil
94
+ @socket.should_not be_closed
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ context '#read' do
102
+ context 'with a length argument' do
103
+ context 'with a possitive length argument' do
104
+ context 'when the connection is open' do
105
+ context 'with greater or equal than the requested data buffered' do
106
+ it 'returns the requested data and no more' do
107
+ tcp_test(SendAndKeepOpen) do
108
+ @socket.read(2).size.should eq 2
109
+ @socket.read(1).size.should eq 1
110
+ end
111
+ end
112
+ end
113
+ context 'with less than the requested data buffered' do
114
+ it 'blocks' do
115
+ tcp_test(SendAndKeepOpen, :stop => false) do
116
+ @blocked = true
117
+ EM.next_tick { @blocked.should eq true; EM.next_tick { EM.stop } }
118
+ @socket.read(10)
119
+ @blocked = false
120
+ end
121
+ end
122
+ end
123
+ end
124
+ context 'when the peer has closed the connection' do
125
+ context 'with no data buffered' do
126
+ it 'returns nil' do
127
+ tcp_test(SendAndClose) do
128
+ @socket.read(4).size.should eq 4
129
+ @socket.read(1).should be_nil
130
+ end
131
+ end
132
+ end
133
+ context 'with less than the requested data buffered' do
134
+ it 'returns the buffered data' do
135
+ tcp_test(SendAndClose) do
136
+ @socket.read(50).size.should eq 4
137
+ end
138
+ end
139
+ end
140
+ context 'with greater or equal than the requested data buffered' do
141
+ it 'returns the requested data and no more' do
142
+ tcp_test(SendAndClose) do
143
+ @socket = EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
144
+ @socket.read(2).size.should eq 2
145
+ end
146
+ end
147
+ end
148
+ end
149
+ context 'when we closed the connection' do
150
+ it 'raises IOError' do
151
+ tcp_test(SendAndKeepOpen, :close => true) do
152
+ proc {
153
+ @socket.read(4)
154
+ }.should raise_error(IOError)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ context 'with a negative length argument' do
160
+ it 'raises ArgumentError' do
161
+ tcp_test(SendAndKeepOpen) do
162
+ proc {
163
+ @socket.read(-10)
164
+ }.should raise_error(ArgumentError)
165
+ end
166
+ end
167
+ end
168
+ context 'with a zero length argument' do
169
+ context 'when the connection is open' do
170
+ it 'returns an empty string' do
171
+ tcp_test(SendAndKeepOpen) do
172
+ @socket.read(0).should eq ""
173
+ end
174
+ end
175
+ end
176
+ context 'when the peer has closed the connection' do
177
+ it 'returns an empty string' do
178
+ tcp_test(SendAndClose) do
179
+ @socket.read(0).should eq ""
180
+ end
181
+ end
182
+ end
183
+ context 'when we closed the connection' do
184
+ it 'raises IOError' do
185
+ tcp_test(SendAndKeepOpen, :close => true) do
186
+ proc {
187
+ @socket.read(0)
188
+ }.should raise_error(IOError)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ context 'without a length argument' do
195
+ context 'when the connection is open' do
196
+ it 'blocks until the peer closes the connection and returns all data sent' do
197
+ tcp_test(SendAndTimedClose) do
198
+ @blocked = true
199
+ EM.next_tick { @blocked.should eq true }
200
+ @socket.read(10).should eq '1234'
201
+ @blocked = false
202
+ end
203
+ end
204
+ end
205
+ context 'when the peer has closed the connection' do
206
+ context 'with no data buffered' do
207
+ it 'returns an empty string' do
208
+ tcp_test(SendAndClose) do
209
+ @socket.read()
210
+ @socket.read().should eq ""
211
+ end
212
+ end
213
+ end
214
+ context 'with data buffered' do
215
+ it 'returns the buffered data' do
216
+ tcp_test(SendAndClose) do
217
+ @socket.read().should eq "1234"
218
+ end
219
+ end
220
+ end
221
+ end
222
+ context 'when we closed the connection' do
223
+ it 'raises IOError' do
224
+ tcp_test(SendAndKeepOpen, :close => true) do
225
+ proc {
226
+ @socket.read()
227
+ }.should raise_error(IOError)
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+ context '#recv' do
235
+ context 'with a length argument' do
236
+ context 'with a possitive length argument' do
237
+ context 'when the connection is open' do
238
+ context 'with greater or equal than the requested data buffered' do
239
+ it 'returns the requested data and no more' do
240
+ tcp_test(SendAndKeepOpen) do
241
+ @socket.recv(2).size.should eq 2
242
+ @socket.recv(1).size.should eq 1
243
+ end
244
+ end
245
+ end
246
+ context 'with less than the requested data buffered' do
247
+ it 'return the buffered data' do
248
+ tcp_test(SendAndKeepOpen) do
249
+ @socket.recv(50).size.should eq 4
250
+ end
251
+ end
252
+ end
253
+ context 'with no buffered data' do
254
+ it 'blocks' do
255
+ tcp_test(SendAndKeepOpen, :stop => false) do
256
+ @socket.recv(10)
257
+ @blocked = true
258
+ EM.next_tick { @blocked.should eq true; EM.next_tick { EM.stop } }
259
+ @socket.recv(10)
260
+ @blocked = false
261
+ end
262
+ end
263
+ end
264
+ end
265
+ context 'when the peer has closed the connection' do
266
+ context 'with no data buffered' do
267
+ it 'returns an empty string' do
268
+ tcp_test(SendAndClose) do
269
+ @socket.read(4).size.should eq 4
270
+ @socket.recv(1).should eq ""
271
+ end
272
+ end
273
+ end
274
+ context 'with less than the requested data buffered' do
275
+ it 'returns the buffered data' do
276
+ tcp_test(SendAndClose) do
277
+ @socket.recv(50).size.should eq 4
278
+ end
279
+ end
280
+ end
281
+ context 'with greater or equal than the requested data buffered' do
282
+ it 'returns the requested data and no more' do
283
+ tcp_test(SendAndClose) do
284
+ @socket.recv(2).size.should eq 2
285
+ end
286
+ end
287
+ end
288
+ end
289
+ context 'when we closed the connection' do
290
+ it 'raises IOError' do
291
+ tcp_test(SendAndKeepOpen, :close => true) do
292
+ proc {
293
+ @socket.recv(4)
294
+ }.should raise_error(IOError)
295
+ end
296
+ end
297
+ end
298
+ end
299
+ context 'with a negative length argument' do
300
+ it 'raises ArgumentError' do
301
+ tcp_test(SendAndKeepOpen) do
302
+ proc {
303
+ @socket.recv(-10)
304
+ }.should raise_error(ArgumentError)
305
+ end
306
+ end
307
+ end
308
+ context 'with a zero length argument' do
309
+ context 'when the connection is open' do
310
+ it 'returns an empty string' do
311
+ tcp_test(SendAndKeepOpen) do
312
+ @socket.recv(0).should eq ""
313
+ end
314
+ end
315
+ end
316
+ context 'when the peer has closed the connection' do
317
+ it 'returns an empty string' do
318
+ tcp_test(SendAndClose) do
319
+ @socket.recv(0).should eq ""
320
+ end
321
+ end
322
+ end
323
+ context 'when we closed the connection' do
324
+ it 'raises IOError' do
325
+ tcp_test(SendAndKeepOpen, :close => true) do
326
+ proc {
327
+ @socket.recv(0)
328
+ }.should raise_error(IOError)
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
334
+ context 'without a length argument' do
335
+ it 'raises ArgumentError' do
336
+ tcp_test(SendAndKeepOpen) do
337
+ proc {
338
+ @socket.recv()
339
+ }.should raise_error(ArgumentError)
340
+ end
341
+ end
342
+ end
343
+ end
344
+
345
+ context '#write' do
346
+ context 'when the peer has closed the connection' do
347
+ it 'raises Errno::EPIPE' do
348
+ tcp_test(SendAndClose, :stop => false) do
349
+ EM.add_timer(0.01) do
350
+ proc {
351
+ @socket.write("foo")
352
+ }.should raise_error(Errno::EPIPE)
353
+ EM.stop
354
+ end
355
+ end
356
+ end
357
+ end
358
+ context 'when we closed the connection' do
359
+ it 'raises IOError' do
360
+ tcp_test(SendAndKeepOpen, :close => true) do
361
+ proc {
362
+ @socket.write("foo")
363
+ }.should raise_error(IOError)
364
+ end
365
+ end
366
+ end
367
+ end
368
+
369
+ context '#send' do
370
+ context 'when the peer has closed the connection' do
371
+ it 'raises Errno::EPIPE' do
372
+ tcp_test(SendAndClose, :stop => false) do
373
+ EM.add_timer(0.01) do
374
+ proc {
375
+ @socket.send("foo",0)
376
+ }.should raise_error(Errno::EPIPE)
377
+ EM.stop
378
+ end
379
+ end
380
+ end
381
+ end
382
+ context 'when we closed the connection' do
383
+ it 'raises IOError' do
384
+ tcp_test(SendAndKeepOpen, :close => true) do
385
+ proc {
386
+ @socket.send("foo",0)
387
+ }.should raise_error(IOError)
388
+ end
389
+ end
390
+ end
391
+ context 'without a flags argument' do
392
+ it 'raises ArgumentError' do
393
+ tcp_test(SendAndKeepOpen) do
394
+ proc {
395
+ @socket.send('foo')
396
+ }.should raise_error(ArgumentError)
397
+ end
398
+ end
399
+ end
400
+ end
401
+
402
+ context 'when wrapped in a connection pool' do
403
+ it 'accepts "send"' do
404
+ EventMachine.synchrony do
405
+ @socket = EventMachine::Synchrony::ConnectionPool.new(size: 1) do
406
+ EventMachine::Synchrony::TCPSocket.new 'eventmachine.rubyforge.org', 80
407
+ end
408
+ @socket.send("GET / HTTP1.1\r\n\r\n",0).class.should be(Fixnum)
409
+ EM.stop
25
410
  end
26
- @socket.send("GET / HTTP1.1\r\n\r\n").class.should be(Fixnum)
27
- EM.stop
28
411
  end
29
412
  end
30
413
  end
@@ -32,4 +32,11 @@ describe EventMachine::Synchrony do
32
32
  end
33
33
  end
34
34
 
35
+ it 'should return instance of EventMachine::Timer from add_timer method' do
36
+ EM.synchrony do
37
+ timer = EM::Synchrony.add_timer(0.1){}
38
+ timer.should be_instance_of(EventMachine::Timer)
39
+ EventMachine.stop
40
+ end
41
+ end
35
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-synchrony
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-19 00:00:00.000000000 Z
12
+ date: 2012-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
- requirement: &2152409200 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: 1.0.0.beta.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2152409200
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0.beta.1
25
30
  description: Fiber aware EventMachine libraries
26
31
  email:
27
32
  - ilya@igvita.com
@@ -109,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
114
  version: '0'
110
115
  requirements: []
111
116
  rubyforge_project: em-synchrony
112
- rubygems_version: 1.8.10
117
+ rubygems_version: 1.8.24
113
118
  signing_key:
114
119
  specification_version: 3
115
120
  summary: Fiber aware EventMachine libraries