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.
- data/README.md +173 -173
- data/em-synchrony.gemspec +1 -1
- data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +47 -47
- data/lib/em-synchrony.rb +1 -1
- data/lib/em-synchrony/activerecord.rb +102 -102
- data/lib/em-synchrony/amqp.rb +180 -180
- data/lib/em-synchrony/em-hiredis.rb +103 -103
- data/lib/em-synchrony/tcpsocket.rb +157 -28
- data/spec/activerecord_spec.rb +108 -108
- data/spec/amqp_spec.rb +146 -146
- data/spec/tcpsocket_spec.rb +401 -18
- data/spec/timer_spec.rb +7 -0
- metadata +10 -5
data/spec/tcpsocket_spec.rb
CHANGED
@@ -1,30 +1,413 @@
|
|
1
1
|
require "spec/helper/all"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
23
|
+
def tcp_test(server_type, ops={}, &block)
|
24
|
+
Proc.new do
|
13
25
|
EventMachine.synchrony do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
data/spec/timer_spec.rb
CHANGED
@@ -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.
|
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-
|
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:
|
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:
|
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.
|
117
|
+
rubygems_version: 1.8.24
|
113
118
|
signing_key:
|
114
119
|
specification_version: 3
|
115
120
|
summary: Fiber aware EventMachine libraries
|