amqp 0.7.0.pre → 0.7.0
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/.gitignore +4 -0
- data/.rspec +2 -0
- data/CHANGELOG +8 -2
- data/CONTRIBUTORS +22 -0
- data/Gemfile +3 -3
- data/README.md +20 -11
- data/Rakefile +30 -6
- data/amqp.gemspec +1 -1
- data/bin/cleanify.rb +50 -0
- data/examples/amqp/simple.rb +6 -4
- data/examples/mq/ack.rb +8 -6
- data/examples/mq/automatic_binding_for_default_direct_exchange.rb +65 -0
- data/examples/mq/callbacks.rb +9 -1
- data/examples/mq/clock.rb +17 -17
- data/examples/mq/hashtable.rb +19 -10
- data/examples/mq/internal.rb +13 -11
- data/examples/mq/logger.rb +38 -36
- data/examples/mq/multiclock.rb +16 -7
- data/examples/mq/pingpong.rb +16 -7
- data/examples/mq/pop.rb +8 -6
- data/examples/mq/primes-simple.rb +2 -0
- data/examples/mq/primes.rb +7 -5
- data/examples/mq/stocks.rb +14 -5
- data/lib/amqp.rb +12 -8
- data/lib/amqp/buffer.rb +35 -158
- data/lib/amqp/client.rb +34 -22
- data/lib/amqp/frame.rb +8 -64
- data/lib/amqp/protocol.rb +21 -70
- data/lib/amqp/server.rb +11 -9
- data/lib/amqp/spec.rb +8 -6
- data/lib/amqp/version.rb +2 -0
- data/lib/ext/blankslate.rb +3 -1
- data/lib/ext/em.rb +2 -0
- data/lib/ext/emfork.rb +13 -11
- data/lib/mq.rb +253 -156
- data/lib/mq/collection.rb +6 -88
- data/lib/mq/exchange.rb +70 -13
- data/lib/mq/header.rb +12 -6
- data/lib/mq/logger.rb +9 -7
- data/lib/mq/queue.rb +42 -30
- data/lib/mq/rpc.rb +6 -4
- data/protocol/codegen.rb +20 -18
- data/research/api.rb +10 -46
- data/research/primes-forked.rb +9 -7
- data/research/primes-processes.rb +74 -72
- data/research/primes-threaded.rb +9 -7
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +61 -0
- data/spec/mq_helper.rb +70 -0
- data/spec/spec_helper.rb +84 -29
- data/spec/unit/amqp/buffer_spec.rb +178 -0
- data/spec/unit/amqp/client_spec.rb +472 -0
- data/spec/unit/amqp/frame_spec.rb +60 -0
- data/spec/unit/amqp/misc_spec.rb +123 -0
- data/spec/unit/amqp/protocol_spec.rb +53 -0
- data/spec/unit/mq/channel_close_spec.rb +15 -0
- data/spec/unit/mq/collection_spec.rb +129 -0
- data/spec/unit/mq/exchange_declaration_spec.rb +524 -0
- data/spec/unit/mq/misc_spec.rb +228 -0
- data/spec/unit/mq/mq_basic_spec.rb +39 -0
- data/spec/unit/mq/queue_declaration_spec.rb +97 -0
- data/spec/unit/mq/queue_spec.rb +71 -0
- metadata +33 -21
- data/Gemfile.lock +0 -16
- data/old/README +0 -30
- data/old/Rakefile +0 -12
- data/old/amqp-0.8.json +0 -606
- data/old/amqp_spec.rb +0 -796
- data/old/amqpc.rb +0 -695
- data/old/codegen.rb +0 -148
- data/spec/channel_close_spec.rb +0 -13
- data/spec/sync_async_spec.rb +0 -52
@@ -0,0 +1,472 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "amqp/client"
|
5
|
+
|
6
|
+
describe AMQP::Client do
|
7
|
+
include AMQP::SpecHelper
|
8
|
+
include AMQP
|
9
|
+
|
10
|
+
em_after { AMQP.cleanup_state }
|
11
|
+
|
12
|
+
context 'with AMQP.client set to BasicClient (default)' do
|
13
|
+
describe 'creating new connection to AMQP broker using .connect:', :broker => true do
|
14
|
+
it 'when .connect is called outside EM event loop, raises error' do
|
15
|
+
expect { Client.connect }.to raise_error /eventmachine not initialized/
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when .connect is called inside EM event loop:' do
|
19
|
+
include AMQP::SpecHelper
|
20
|
+
|
21
|
+
it 'calls EM.connect with AMQP::Client as a handler class and AMQP options, and' do
|
22
|
+
em do
|
23
|
+
opts = AMQP.settings.merge(AMQP_OPTS)
|
24
|
+
EM.should_receive(:connect).with(opts[:host], opts[:port], Client, opts)
|
25
|
+
Client.connect AMQP_OPTS
|
26
|
+
done
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'either hits connection timeout (with :timeout option), or' do
|
31
|
+
expect { em do
|
32
|
+
Client.connect(:host => 'example.com', :timeout => 0.001)
|
33
|
+
done(2)
|
34
|
+
end
|
35
|
+
}.to raise_error AMQP::Error, /Could not connect to server example.com:5672/
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises connection error (with unresolvable AMQP broker address), or' do
|
39
|
+
pending 'Need to rewrite to eliminate dependency on DNS loockup mechanism'
|
40
|
+
expect { em do
|
41
|
+
Client.connect(:host => 'impossible.')
|
42
|
+
done(2)
|
43
|
+
end
|
44
|
+
}.to raise_error EventMachine::ConnectionError, /unable to resolve server address/
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises connection error (with wrong AMQP host), or' do
|
48
|
+
pending 'Need to rewrite to eliminate dependency on DNS loockup mechanism'
|
49
|
+
expect { em do
|
50
|
+
Client.connect(:host => 'example.com')
|
51
|
+
done(2)
|
52
|
+
end
|
53
|
+
}.to raise_error AMQP::Error, /Could not connect to server example.com:5672/
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'raises connection error (with wrong AMQP port), or' do
|
57
|
+
expect { em do
|
58
|
+
Client.connect(:port => 131313)
|
59
|
+
done(2)
|
60
|
+
end
|
61
|
+
}.to raise_error AMQP::Error, /Could not connect to server 127.0.0.1:131313/
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns client connecting to AMQP broker (with correct AMQP opts) - DELAY!' do
|
65
|
+
em do
|
66
|
+
client = Client.connect AMQP_OPTS
|
67
|
+
client.should_not be_connected
|
68
|
+
done(0.2) { client.should be_connected }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when connection is attempted, initiated client:' do
|
73
|
+
include AMQP::EMSpec
|
74
|
+
em_before { @client = Client.connect AMQP_OPTS }
|
75
|
+
|
76
|
+
specify { @client.should_not be_connected; done }
|
77
|
+
|
78
|
+
context "after a delay, connection is established and the client:" do
|
79
|
+
it 'receives #connection_completed call from EM reactor' do
|
80
|
+
@client.should_receive(:connection_completed).with(no_args)
|
81
|
+
done(0.2)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'fires @connection_status block (if any) with :connected' do
|
85
|
+
# Set up status processing block first
|
86
|
+
@client.connection_status { |status| @status = status }
|
87
|
+
done(0.2) { @status.should == :connected }
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'becomes connected' do
|
91
|
+
done(0.2) { @client.should be_connected }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end # context 'when .connect is called inside EM event loop:
|
97
|
+
end # creating new connection to AMQP broker using .connect
|
98
|
+
|
99
|
+
context 'given a client that is attempting to connect to AMQP broker using AMQP_OPTS' do
|
100
|
+
include AMQP::EMSpec
|
101
|
+
em_before { @client = Client.connect AMQP_OPTS }
|
102
|
+
subject { @client }
|
103
|
+
|
104
|
+
describe 'closing down' do
|
105
|
+
context 'calling #close' do
|
106
|
+
it 'just sets callback (to close connection) if @client is not yet connected' do
|
107
|
+
@client.should_not be_connected
|
108
|
+
@client.should_not_receive(:send)
|
109
|
+
@client.should_receive(:callback)
|
110
|
+
@client.close
|
111
|
+
done
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'if @client is connected'
|
115
|
+
it 'closes all channels first if there are any' do
|
116
|
+
EM.add_timer(0.2) {
|
117
|
+
@client.should be_connected
|
118
|
+
channel1 = MQ.new(@client)
|
119
|
+
channel2 = MQ.new(@client)
|
120
|
+
channel1.should_receive(:close)
|
121
|
+
channel2.should_receive(:close)
|
122
|
+
@client.close
|
123
|
+
done }
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'sends Protocol::Connection::Close method to broker' do
|
127
|
+
EM.add_timer(0.2) {
|
128
|
+
@client.should be_connected
|
129
|
+
@client.should_receive(:send) do |message|
|
130
|
+
message.should be_a Protocol::Connection::Close
|
131
|
+
end
|
132
|
+
@client.close
|
133
|
+
done }
|
134
|
+
end
|
135
|
+
end # 'calling #close'
|
136
|
+
|
137
|
+
context 'after broker responded to connection close request' do
|
138
|
+
it 'client receives Protocol::Connection::CloseOk method from broker' do
|
139
|
+
EM.add_timer(0.2) {
|
140
|
+
@client.should_receive(:process_frame) do |frame|
|
141
|
+
frame.payload.should be_a Protocol::Connection::CloseOk
|
142
|
+
end
|
143
|
+
@client.close
|
144
|
+
done(0.2) }
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'calls block given to #close instead of pre-set callbacks' do
|
148
|
+
# stub it BEFORE #connection_completed fired!
|
149
|
+
@client.should_not_receive(:disconnected)
|
150
|
+
@client.should_not_receive(:reconnect)
|
151
|
+
EM.add_timer(0.2) {
|
152
|
+
@client.close { @on_disconnect_called = true }
|
153
|
+
done(0.2) { @on_disconnect_called.should be_true } }
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'if no block was given to #close' do
|
157
|
+
|
158
|
+
it 'calls registered @on_disconnect hook' do
|
159
|
+
EM.add_timer(0.2) {
|
160
|
+
mock = mock('on_disconnect')
|
161
|
+
mock.should_receive(:call).with(no_args)
|
162
|
+
|
163
|
+
# subject_mock trips something and drops connection :(
|
164
|
+
@client.instance_exec { @on_disconnect = mock }
|
165
|
+
@client.close
|
166
|
+
done(0.2) }
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'normally, @on_disconnect just calls private #disconnected method' do
|
170
|
+
# stub it BEFORE #connection_completed fired!
|
171
|
+
@client.should_receive(:disconnected)
|
172
|
+
EM.add_timer(0.2) { @client.close; done(0.2) }
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'fires @connection_status block (if any) with :disconnected' do
|
176
|
+
EM.add_timer(0.2) {
|
177
|
+
# Set up status processing block first
|
178
|
+
@client.connection_status { |status| @status = status }
|
179
|
+
@client.close
|
180
|
+
done(0.2) { @status.should == :disconnected } }
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'attempts to reconnect' do
|
184
|
+
@client.should_receive(:reconnect)
|
185
|
+
EM.add_timer(0.2) { @client.close; done(0.2) }
|
186
|
+
end
|
187
|
+
end # if no block was given to #close
|
188
|
+
end # after broker responded to connection close request
|
189
|
+
|
190
|
+
context '#unbind' do
|
191
|
+
it 'is a hook method called by EM when network connection is dropped' do
|
192
|
+
@client.should_receive(:unbind).with(no_args)
|
193
|
+
@client.close
|
194
|
+
done
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'unsets @connected status' do
|
198
|
+
EM.add_timer(0.1) {
|
199
|
+
@client.should be_connected
|
200
|
+
@client.unbind
|
201
|
+
@client.should_not be_connected
|
202
|
+
done }
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'seems that it implicitly calls #connection_completed' do
|
206
|
+
@client.should_receive(:connection_completed) do
|
207
|
+
@client.instance_exec do
|
208
|
+
# Avoid raising exception
|
209
|
+
@on_disconnect = method(:disconnected)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
@client.unbind
|
213
|
+
done
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'calls @on_disconnect hook' do
|
217
|
+
block_fired = false
|
218
|
+
EM.add_timer(0.1) {
|
219
|
+
@client.instance_exec do
|
220
|
+
@on_disconnect = proc { block_fired = true }
|
221
|
+
end
|
222
|
+
@client.unbind
|
223
|
+
done(0.1) { block_fired.should be_true } }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end # closing down
|
227
|
+
|
228
|
+
context 'reconnecting' do
|
229
|
+
include AMQP::EMSpec
|
230
|
+
|
231
|
+
it 're-initializes the client' do
|
232
|
+
@client.should_receive(:initialize)
|
233
|
+
@client.reconnect
|
234
|
+
done
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'resets and clears existing channels, if any' do
|
238
|
+
channel1 = MQ.new(@client)
|
239
|
+
channel2 = MQ.new(@client)
|
240
|
+
EM.add_timer(0.2) {
|
241
|
+
channel1.should_receive(:reset)
|
242
|
+
channel2.should_receive(:reset)
|
243
|
+
@client.reconnect
|
244
|
+
@client.channels.should == {}
|
245
|
+
done
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'reconnects to broker through EM.reconnect' do
|
250
|
+
EM.should_receive(:reconnect)
|
251
|
+
@client.reconnect
|
252
|
+
done
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'delays reconnect attempt by 1 sec if reconnect is already in progress' do
|
256
|
+
EM.should_receive(:reconnect).exactly(1).times
|
257
|
+
EM.should_receive(:add_timer).with(1)
|
258
|
+
@client.reconnect
|
259
|
+
@client.reconnect
|
260
|
+
done
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'attempts to automatically reconnect on #close' do
|
264
|
+
@client.should_receive(:reconnect)
|
265
|
+
EM.add_timer(0.2) { @client.close; done(0.2) }
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'receiving data/processing frames' do
|
270
|
+
describe "#receive_data" do
|
271
|
+
it 'is a callback method that EM calls when it gets raw data from broker' do
|
272
|
+
@client.should_receive(:receive_data) do |data|
|
273
|
+
frame = Frame.parse(data)
|
274
|
+
frame.should be_an Frame::Method
|
275
|
+
frame.payload.should be_an Protocol::Connection::Start
|
276
|
+
done
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'delegates actual frame processing to #process_frame' do
|
281
|
+
EM.add_timer(0.2) {
|
282
|
+
@client.should_receive(:process_frame).with(basic_header)
|
283
|
+
@client.receive_data(basic_header.to_s)
|
284
|
+
done }
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'does not call #process_frame on incomplete frames' do
|
288
|
+
EM.add_timer(0.2) {
|
289
|
+
@client.should_not_receive(:process_frame)
|
290
|
+
@client.receive_data(basic_header.to_s[0..5])
|
291
|
+
done }
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'calls #process_frame when frame is complete' do
|
295
|
+
EM.add_timer(0.2) {
|
296
|
+
@client.should_receive(:process_frame).with(basic_header)
|
297
|
+
@client.receive_data(basic_header.to_s[0..5])
|
298
|
+
@client.receive_data(basic_header.to_s[6..-1])
|
299
|
+
done }
|
300
|
+
end
|
301
|
+
end #receive_data
|
302
|
+
|
303
|
+
describe '#process_frame', '(client reaction to messages from broker)' do
|
304
|
+
|
305
|
+
it 'delegates frame processing to channel if the frame indicates channel' do
|
306
|
+
EM.add_timer(0.2) {
|
307
|
+
MQ.new(@client)
|
308
|
+
@client.channels[1].should_receive(:process_frame).
|
309
|
+
with(basic_header(:channel => 1))
|
310
|
+
@client.process_frame(basic_header(:channel => 1))
|
311
|
+
done }
|
312
|
+
end
|
313
|
+
|
314
|
+
describe ' Frame::Method', '(Method with args received)' do
|
315
|
+
describe 'Protocol::Connection::Start',
|
316
|
+
'(broker initiated start of AMQP connection)' do
|
317
|
+
let(:frame) { Frame::Method.new(Protocol::Connection::Start.new) }
|
318
|
+
|
319
|
+
it 'sends back to broker Protocol::Connection::StartOk with details' do
|
320
|
+
EM.add_timer(0.2) {
|
321
|
+
@client.should_receive(:send).
|
322
|
+
with(Protocol::Connection::StartOk.new(
|
323
|
+
{:platform => 'Ruby/EventMachine',
|
324
|
+
:product => 'AMQP',
|
325
|
+
:information => 'http://github.com/ruby-amqp/amqp',
|
326
|
+
:version => AMQP::VERSION}, 'AMQPLAIN',
|
327
|
+
{:LOGIN => AMQP.settings[:user],
|
328
|
+
:PASSWORD => AMQP.settings[:pass]}, 'en_US'))
|
329
|
+
@client.process_frame(frame)
|
330
|
+
done }
|
331
|
+
end
|
332
|
+
end # Protocol::Connection::Start
|
333
|
+
|
334
|
+
describe 'Protocol::Connection::Tune',
|
335
|
+
'(broker suggested connection parameters)' do
|
336
|
+
let(:frame) { Frame::Method.new(Protocol::Connection::Tune.new) }
|
337
|
+
|
338
|
+
it 'sends back to broker TuneOk with parameters and Open' do
|
339
|
+
EM.add_timer(0.2) {
|
340
|
+
@client.should_receive(:send) do |method|
|
341
|
+
if method.is_a? Protocol::Connection::TuneOk
|
342
|
+
method.should == Protocol::Connection::TuneOk.new(
|
343
|
+
:channel_max => 0,
|
344
|
+
:frame_max => 131072,
|
345
|
+
:heartbeat => 0)
|
346
|
+
else
|
347
|
+
method.should == Protocol::Connection::Open.new(
|
348
|
+
:virtual_host => AMQP.settings[:vhost],
|
349
|
+
:capabilities => '',
|
350
|
+
:insist => AMQP.settings[:insist])
|
351
|
+
end
|
352
|
+
end.exactly(2).times
|
353
|
+
@client.process_frame(frame)
|
354
|
+
done }
|
355
|
+
end
|
356
|
+
end # Protocol::Connection::Tune
|
357
|
+
|
358
|
+
describe 'Protocol::Connection::OpenOk',
|
359
|
+
'(broker confirmed connection opening)' do
|
360
|
+
let(:frame) { Frame::Method.new(AMQP::Protocol::Connection::OpenOk.new) }
|
361
|
+
|
362
|
+
it 'succeeds @client (as a deferrable)' do
|
363
|
+
@client.instance_variable_get(:@deferred_status).should == :unknown
|
364
|
+
@client.process_frame(frame)
|
365
|
+
done(0.1) {
|
366
|
+
@client.instance_variable_get(:@deferred_status).should == :succeeded }
|
367
|
+
end
|
368
|
+
end # Protocol::Connection::OpenOk
|
369
|
+
|
370
|
+
describe 'Protocol::Connection::Close',
|
371
|
+
'(unexpectedly received connection close from broker)' do
|
372
|
+
let(:frame) { Frame::Method.new(Protocol::Connection::Close.new(
|
373
|
+
:reply_code => 320,
|
374
|
+
:reply_text => "Nyanya",
|
375
|
+
:class_id => 10,
|
376
|
+
:method_id => 40)) }
|
377
|
+
|
378
|
+
it 'just prints debug info to STDERR' do
|
379
|
+
STDERR.should_receive(:puts).
|
380
|
+
with /Nyanya in AMQP::Protocol::Connection::Open/
|
381
|
+
@client.process_frame(frame)
|
382
|
+
done(0.1)
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'should probably raise exception or something?'
|
386
|
+
end # Protocol::Connection::Close
|
387
|
+
|
388
|
+
describe 'Protocol::Connection::CloseOk',
|
389
|
+
'(broker confirmed our connection close request)' do
|
390
|
+
let(:frame) { Frame::Method.new(Protocol::Connection::CloseOk.new) }
|
391
|
+
|
392
|
+
it 'calls registered @on_disconnect hook' do
|
393
|
+
EM.add_timer(0.1) {
|
394
|
+
subject_mock(:@on_disconnect).should_receive(:call).with(no_args)
|
395
|
+
@client.process_frame(frame)
|
396
|
+
done }
|
397
|
+
end
|
398
|
+
|
399
|
+
end # Protocol::Connection::CloseOk
|
400
|
+
end # Frame::Method
|
401
|
+
end #process_frame
|
402
|
+
end # receiving data/processing frames
|
403
|
+
|
404
|
+
context 'channels' do
|
405
|
+
it 'starts with empty channels set' do
|
406
|
+
@client.channels.should be_empty
|
407
|
+
done
|
408
|
+
end
|
409
|
+
|
410
|
+
context '#add_channel' do
|
411
|
+
it 'adds given channel to channels set' do
|
412
|
+
mq = mock('mq')
|
413
|
+
@client.add_channel mq
|
414
|
+
@client.channels[1].should == mq
|
415
|
+
done
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
context '#send data' do
|
421
|
+
it 'formats data to be sent into Frame, setting channel to 0 by default' do
|
422
|
+
data = mock('data')
|
423
|
+
framed_data = mock('framed data')
|
424
|
+
data.should_receive(:to_frame).and_return(framed_data)
|
425
|
+
framed_data.should_receive(:channel=).with(0)
|
426
|
+
@client.send data
|
427
|
+
done
|
428
|
+
end
|
429
|
+
|
430
|
+
it 'sets channel number given in options' do
|
431
|
+
data = mock('data')
|
432
|
+
framed_data = mock('framed data')
|
433
|
+
data.should_receive(:to_frame).and_return(framed_data)
|
434
|
+
framed_data.should_receive(:channel=).with(1313)
|
435
|
+
@client.send data, :channel =>1313
|
436
|
+
done
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'does not format data if it is already a Frame' do
|
440
|
+
data = basic_header
|
441
|
+
data.should_not_receive(:to_frame)
|
442
|
+
@client.send data
|
443
|
+
done
|
444
|
+
end
|
445
|
+
|
446
|
+
it 'then calls EM:Connection#send_data hook with framed data converted to String' do
|
447
|
+
EM.add_timer(0.1) {
|
448
|
+
data = basic_header
|
449
|
+
@client.should_receive(:send_data) do |data|
|
450
|
+
data.should be_a String
|
451
|
+
frame = Frame.parse(data)
|
452
|
+
frame.class.should == Frame::Header
|
453
|
+
frame.payload.class.should == Protocol::Header
|
454
|
+
frame.channel.should == 0
|
455
|
+
end
|
456
|
+
@client.send data
|
457
|
+
done }
|
458
|
+
end
|
459
|
+
end #send data
|
460
|
+
|
461
|
+
context '#connection_status' do
|
462
|
+
em_before { @called_with_statuses = [] }
|
463
|
+
it 'sets a block to be called on connection status changes' do
|
464
|
+
@client.connection_status { |status| @called_with_statuses << status }
|
465
|
+
@client.close
|
466
|
+
done(0.1) { @called_with_statuses.should == [:connected, :disconnected] }
|
467
|
+
end
|
468
|
+
|
469
|
+
end #connection_status
|
470
|
+
end #given a connected client
|
471
|
+
end # context with AMQP.client set to BasicClient (default)
|
472
|
+
end
|