em-synchrony 1.0.1 → 1.0.2

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