amq-protocol 0.0.1.pre → 0.5.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 +3 -1
- data/.travis.yml +7 -0
- data/CONTRIBUTORS +2 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +1 -1
- data/PROFILING.md +81 -0
- data/README.textile +34 -17
- data/TODO.todo +24 -0
- data/__init__.py +0 -0
- data/amq-protocol.gemspec +16 -11
- data/amqp_0.9.1_changes.json +1 -1
- data/bin/jenkins.sh +23 -0
- data/codegen.py +50 -16
- data/codegen_helpers.py +81 -26
- data/examples/00_manual_test.rb +117 -38
- data/irb.rb +76 -4
- data/lib/amq/hacks.rb +33 -0
- data/lib/amq/protocol.rb +3 -1472
- data/lib/amq/protocol/client.rb +2230 -0
- data/lib/amq/protocol/frame.rb +111 -38
- data/lib/amq/protocol/table.rb +89 -42
- data/lib/amq/protocol/version.rb +5 -0
- data/post-processing.rb +1 -0
- data/protocol.rb.pytemplate +217 -63
- data/spec/amq/hacks_spec.rb +39 -0
- data/spec/amq/protocol/basic_spec.rb +320 -0
- data/spec/amq/protocol/channel_spec.rb +117 -0
- data/spec/amq/protocol/confirm_spec.rb +44 -0
- data/spec/amq/protocol/connection_spec.rb +149 -0
- data/spec/amq/protocol/exchange_spec.rb +95 -0
- data/spec/amq/protocol/frame_spec.rb +93 -78
- data/spec/amq/protocol/method_spec.rb +40 -0
- data/spec/amq/protocol/queue_spec.rb +129 -0
- data/spec/amq/protocol/table_spec.rb +59 -36
- data/spec/amq/protocol/tx_spec.rb +58 -0
- data/spec/amq/protocol_spec.rb +572 -643
- data/spec/spec_helper.rb +25 -2
- data/tasks.rb +13 -8
- metadata +44 -25
- data/amq-protocol.pre.gemspec +0 -6
- data/examples/01_basics.rb +0 -14
- data/examples/02_eventmachine.rb +0 -4
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
describe Hacks do
|
8
|
+
context "64-bit big-endian packing / unpacking" do
|
9
|
+
let(:examples) {
|
10
|
+
{
|
11
|
+
0x0000000000000000 => "\x00\x00\x00\x00\x00\x00\x00\x00",
|
12
|
+
0x000000000000000A => "\x00\x00\x00\x00\x00\x00\x00\x0A",
|
13
|
+
0x00000000000000A0 => "\x00\x00\x00\x00\x00\x00\x00\xA0",
|
14
|
+
0x000000000000B0A0 => "\x00\x00\x00\x00\x00\x00\xB0\xA0",
|
15
|
+
0x00000000000CB0AD => "\x00\x00\x00\x00\x00\x0C\xB0\xAD",
|
16
|
+
0x8BADF00DDEFEC8ED => "\x8B\xAD\xF0\x0D\xDE\xFE\xC8\xED",
|
17
|
+
0x0D15EA5EFEE1DEAD => "\x0D\x15\xEA\x5E\xFE\xE1\xDE\xAD",
|
18
|
+
0xDEADBEEFDEADBABE => "\xDE\xAD\xBE\xEF\xDE\xAD\xBA\xBE"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
describe ".pack_64_big_endian" do
|
23
|
+
it "packs integers into big-endian string" do
|
24
|
+
examples.each do |key, value|
|
25
|
+
described_class.pack_64_big_endian(key).should == value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".unpack_64_big_endian" do
|
31
|
+
it "should unpack string representation into integer" do
|
32
|
+
examples.each do |key, value|
|
33
|
+
described_class.unpack_64_big_endian(value)[0].should == key
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,320 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
describe Basic do
|
9
|
+
describe '.encode_timestamp' do
|
10
|
+
it 'encodes the timestamp as a 64 byte big endian integer' do
|
11
|
+
Basic.encode_timestamp(12345).last.should == "\x00\x00\x00\x00\x00\x0009"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# describe '.decode_timestamp' do
|
16
|
+
# it 'decodes the timestamp from a 64 byte big endian integer and returns a Time object' do
|
17
|
+
# Basic.decode_timestamp("\x00\x00\x00\x00\x00\x0009").should == Time.at(12345)
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
describe '.encode_headers' do
|
22
|
+
it 'encodes the headers as a table' do
|
23
|
+
Basic.encode_headers(:hello => 'world').last.should == "\x00\x00\x00\x10\x05helloS\x00\x00\x00\x05world"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# describe '.decode_headers' do
|
28
|
+
# it 'decodes the headers from a table' do
|
29
|
+
# Basic.decode_headers("\x00\x00\x00\x10\x05helloS\x00\x00\x00\x05world").should == {'hello' => 'world'}
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
describe '.encode_properties' do
|
34
|
+
it 'packs the parameters into a byte array using the other encode_* methods' do
|
35
|
+
result = Basic.encode_properties(10, {:priority => 0, :delivery_mode => 2, :content_type => 'application/octet-stream'})
|
36
|
+
result.should == "\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x98\x00\x18application/octet-stream\x02\x00"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.decode_properties' do
|
41
|
+
it 'unpacks the properties from a byte array using the decode_* methods' do
|
42
|
+
result = Basic.decode_properties("\x98@\x18application/octet-stream\x02\x00\x00\x00\x00\x00\x00\x00\x00{")
|
43
|
+
result.should == {:priority => 0, :delivery_mode => 2, :content_type => 'application/octet-stream', :timestamp => Time.at(123)}
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'unpacks the properties from a byte array using the decode_* methods, including a table' do
|
47
|
+
result = Basic.decode_properties("\xB8@\x18application/octet-stream\x00\x00\x00\x10\x05helloS\x00\x00\x00\x05world\x02\x00\x00\x00\x00\x00\x00\x00\x00{")
|
48
|
+
result.should == {:priority => 0, :delivery_mode => 2, :content_type => 'application/octet-stream', :timestamp => Time.at(123), :headers => {'hello' => 'world'}}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
%w(content_type content_encoding correlation_id reply_to expiration message_id type user_id app_id cluster_id).each do |method|
|
53
|
+
describe ".encode_#{method}" do
|
54
|
+
it 'encodes the parameter as a Pascal string' do
|
55
|
+
Basic.send("encode_#{method}", 'hello world').last.should == "\x0bhello world"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# describe ".decode_#{method}" do
|
60
|
+
# it 'returns the string' do
|
61
|
+
# # the length has been stripped in .decode_properties
|
62
|
+
# Basic.send("decode_#{method}", 'hello world').should == 'hello world'
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
end
|
66
|
+
|
67
|
+
%w(delivery_mode priority).each do |method|
|
68
|
+
describe ".encode_#{method}" do
|
69
|
+
it 'encodes the parameter as a char' do
|
70
|
+
Basic.send("encode_#{method}", 10).last.should == "\x0a"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# describe ".decode_#{method}" do
|
75
|
+
# it 'decodes the value from a char' do
|
76
|
+
# Basic.send("decode_#{method}", "\x10").should == 16
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Basic
|
83
|
+
describe Qos do
|
84
|
+
describe '.encode' do
|
85
|
+
it 'encodes the parameters into a MethodFrame' do
|
86
|
+
channel = 1
|
87
|
+
prefetch_size = 3
|
88
|
+
prefetch_count = 5
|
89
|
+
global = false
|
90
|
+
method_frame = Qos.encode(channel, prefetch_size, prefetch_count, global)
|
91
|
+
method_frame.payload.should == "\x00<\x00\n\x00\x00\x00\x03\x00\x05\x00"
|
92
|
+
method_frame.channel.should == 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# describe QosOk do
|
98
|
+
# describe '.decode' do
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
|
102
|
+
describe Consume do
|
103
|
+
describe '.encode' do
|
104
|
+
it 'encodes the parameters into a MethodFrame' do
|
105
|
+
channel = 1
|
106
|
+
queue = 'foo'
|
107
|
+
consumer_tag = 'me'
|
108
|
+
no_local = false
|
109
|
+
no_ack = false
|
110
|
+
exclusive = true
|
111
|
+
nowait = false
|
112
|
+
arguments = nil
|
113
|
+
method_frame = Consume.encode(channel, queue, consumer_tag, no_local, no_ack, exclusive, nowait, arguments)
|
114
|
+
method_frame.payload.should == "\x00<\x00\x14\x00\x00\x03foo\x02me\x04\x00\x00\x00\x00"
|
115
|
+
method_frame.channel.should == 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe ConsumeOk do
|
121
|
+
describe '.decode' do
|
122
|
+
subject do
|
123
|
+
ConsumeOk.decode("\x03foo")
|
124
|
+
end
|
125
|
+
|
126
|
+
its(:consumer_tag) { should == 'foo' }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe Cancel do
|
131
|
+
describe '.encode' do
|
132
|
+
it 'encodes the parameters into a MethodFrame' do
|
133
|
+
channel = 1
|
134
|
+
consumer_tag = 'foo'
|
135
|
+
nowait = true
|
136
|
+
method_frame = Cancel.encode(channel, consumer_tag, nowait)
|
137
|
+
method_frame.payload.should == "\x00<\x00\x1E\x03foo\x01"
|
138
|
+
method_frame.channel.should == 1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe CancelOk do
|
144
|
+
describe '.decode' do
|
145
|
+
subject do
|
146
|
+
CancelOk.decode("\x03foo")
|
147
|
+
end
|
148
|
+
|
149
|
+
its(:consumer_tag) { should == 'foo' }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe Publish do
|
154
|
+
describe '.encode' do
|
155
|
+
it 'encodes the parameters into a list of MethodFrames' do
|
156
|
+
channel = 1
|
157
|
+
payload = 'Hello World!'
|
158
|
+
user_headers = {:priority => 0, :content_type => 'application/octet-stream'}
|
159
|
+
exchange = 'foo'
|
160
|
+
routing_key = 'xyz'
|
161
|
+
mandatory = false
|
162
|
+
immediate = true
|
163
|
+
frame_size = 512
|
164
|
+
method_frames = Publish.encode(channel, payload, user_headers, exchange, routing_key, mandatory, immediate, frame_size)
|
165
|
+
method_frames[0].payload.should == "\x00<\x00(\x00\x00\x03foo\x03xyz\x02"
|
166
|
+
method_frames[1].payload.should == "\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\f\x88\x00\x18application/octet-stream\x00"
|
167
|
+
method_frames[2].payload.should == "Hello World!"
|
168
|
+
method_frames[0].channel.should == 1
|
169
|
+
method_frames[1].channel.should == 1
|
170
|
+
method_frames[2].channel.should == 1
|
171
|
+
method_frames.should have(3).items
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe Return do
|
177
|
+
describe '.decode' do
|
178
|
+
subject do
|
179
|
+
Return.decode("\x019\fNO_CONSUMERS\namq.fanout\x00")
|
180
|
+
end
|
181
|
+
|
182
|
+
its(:reply_code) { should == 313 }
|
183
|
+
its(:reply_text) { should == 'NO_CONSUMERS' }
|
184
|
+
its(:exchange) { should == 'amq.fanout' }
|
185
|
+
its(:routing_key) { should == '' }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe Deliver do
|
190
|
+
describe '.decode' do
|
191
|
+
subject do
|
192
|
+
Deliver.decode("\e-1300560114000-445586772970\x00\x00\x00\x00\x00\x00\x00c\x00\namq.fanout\x00")
|
193
|
+
end
|
194
|
+
|
195
|
+
its(:consumer_tag) { should == '-1300560114000-445586772970' }
|
196
|
+
its(:delivery_tag) { should == 99 }
|
197
|
+
its(:redelivered) { should == false }
|
198
|
+
its(:exchange) { should == 'amq.fanout' }
|
199
|
+
its(:routing_key) { should == '' }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe Get do
|
204
|
+
describe '.encode' do
|
205
|
+
it 'encodes the parameters into a MethodFrame' do
|
206
|
+
channel = 1
|
207
|
+
queue = 'foo'
|
208
|
+
no_ack = true
|
209
|
+
method_frame = Get.encode(channel, queue, no_ack)
|
210
|
+
method_frame.payload.should == "\x00\x3c\x00\x46\x00\x00\x03foo\x01"
|
211
|
+
method_frame.channel.should == 1
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe GetOk do
|
217
|
+
describe '.decode' do
|
218
|
+
subject do
|
219
|
+
GetOk.decode("\x00\x00\x00\x00\x00\x00\x00\x06\x00\namq.fanout\x00\x00\x00\x00^")
|
220
|
+
end
|
221
|
+
|
222
|
+
its(:delivery_tag) { should == 6 }
|
223
|
+
its(:redelivered) { should == false }
|
224
|
+
its(:exchange) { should == 'amq.fanout' }
|
225
|
+
its(:routing_key) { should == '' }
|
226
|
+
its(:message_count) { should == 94 }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe GetEmpty do
|
231
|
+
describe '.decode' do
|
232
|
+
subject do
|
233
|
+
GetEmpty.decode("\x03foo")
|
234
|
+
end
|
235
|
+
|
236
|
+
its(:cluster_id) { should == 'foo' }
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe Ack do
|
241
|
+
describe '.encode' do
|
242
|
+
it 'encodes the parameters into a MethodFrame' do
|
243
|
+
channel = 1
|
244
|
+
delivery_tag = 6
|
245
|
+
multiple = false
|
246
|
+
method_frame = Ack.encode(channel, delivery_tag, multiple)
|
247
|
+
method_frame.payload.should == "\x00<\x00P\x00\x00\x00\x00\x00\x00\x00\x06\x00"
|
248
|
+
method_frame.channel.should == 1
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe Reject do
|
254
|
+
describe '.encode' do
|
255
|
+
it 'encodes the parameters into a MethodFrame' do
|
256
|
+
channel = 1
|
257
|
+
delivery_tag = 8
|
258
|
+
requeue = true
|
259
|
+
method_frame = Reject.encode(channel, delivery_tag, requeue)
|
260
|
+
method_frame.payload.should == "\x00<\x00Z\x00\x00\x00\x00\x00\x00\x00\x08\x01"
|
261
|
+
method_frame.channel.should == 1
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
describe RecoverAsync do
|
267
|
+
describe '.encode' do
|
268
|
+
it 'encodes the parameters into a MethodFrame' do
|
269
|
+
channel = 1
|
270
|
+
requeue = true
|
271
|
+
method_frame = RecoverAsync.encode(channel, requeue)
|
272
|
+
method_frame.payload.should == "\x00<\x00d\x01"
|
273
|
+
method_frame.channel.should == 1
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe Recover do
|
279
|
+
describe '.encode' do
|
280
|
+
it 'encodes the parameters into a MethodFrame' do
|
281
|
+
channel = 1
|
282
|
+
requeue = true
|
283
|
+
method_frame = Recover.encode(channel, requeue)
|
284
|
+
method_frame.payload.should == "\x00<\x00n\x01"
|
285
|
+
method_frame.channel.should == 1
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# describe RecoverOk do
|
291
|
+
# describe '.decode' do
|
292
|
+
# end
|
293
|
+
# end
|
294
|
+
|
295
|
+
describe Nack do
|
296
|
+
describe '.decode' do
|
297
|
+
subject do
|
298
|
+
Nack.decode("\x00\x00\x00\x00\x00\x00\x00\x09\x03")
|
299
|
+
end
|
300
|
+
|
301
|
+
its(:delivery_tag) { should == 9 }
|
302
|
+
its(:multiple) { should == true }
|
303
|
+
its(:requeue) { should == true }
|
304
|
+
end
|
305
|
+
|
306
|
+
describe '.encode' do
|
307
|
+
it 'encodes the parameters into a MethodFrame' do
|
308
|
+
channel = 1
|
309
|
+
delivery_tag = 10
|
310
|
+
multiple = false
|
311
|
+
requeue = true
|
312
|
+
method_frame = Nack.encode(channel, delivery_tag, multiple, requeue)
|
313
|
+
method_frame.payload.should == "\x00<\x00x\x00\x00\x00\x00\x00\x00\x00\x0a\x02"
|
314
|
+
method_frame.channel.should == 1
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
class Channel
|
9
|
+
describe Open do
|
10
|
+
describe '.encode' do
|
11
|
+
it 'encodes the parameters into a MethodFrame' do
|
12
|
+
channel = 1
|
13
|
+
out_of_band = ''
|
14
|
+
method_frame = Open.encode(channel, out_of_band)
|
15
|
+
method_frame.payload.should == "\x00\x14\x00\n\x00"
|
16
|
+
method_frame.channel.should == 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe OpenOk do
|
22
|
+
describe '.decode' do
|
23
|
+
subject do
|
24
|
+
OpenOk.decode("\x00\x00\x00\x03foo")
|
25
|
+
end
|
26
|
+
|
27
|
+
its(:channel_id) { should == 'foo' }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Flow do
|
32
|
+
describe '.decode' do
|
33
|
+
subject do
|
34
|
+
Flow.decode("\x01")
|
35
|
+
end
|
36
|
+
|
37
|
+
its(:active) { should be_true }
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.encode' do
|
41
|
+
it 'encodes the parameters as a MethodFrame' do
|
42
|
+
channel = 1
|
43
|
+
active = true
|
44
|
+
method_frame = Flow.encode(channel, active)
|
45
|
+
method_frame.payload.should == "\x00\x14\x00\x14\x01"
|
46
|
+
method_frame.channel.should == 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe FlowOk do
|
52
|
+
describe '.decode' do
|
53
|
+
subject do
|
54
|
+
FlowOk.decode("\x00")
|
55
|
+
end
|
56
|
+
|
57
|
+
its(:active) { should be_false }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '.encode' do
|
61
|
+
it 'encodes the parameters as a MethodFrame' do
|
62
|
+
channel = 1
|
63
|
+
active = true
|
64
|
+
method_frame = FlowOk.encode(channel, active)
|
65
|
+
method_frame.payload.should == "\x00\x14\x00\x15\x01"
|
66
|
+
method_frame.channel.should == 1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe Close do
|
72
|
+
describe '.decode' do
|
73
|
+
context 'with code 200' do
|
74
|
+
subject do
|
75
|
+
Close.decode("\x00\xc8\x07KTHXBAI\x00\x05\x00\x06")
|
76
|
+
end
|
77
|
+
|
78
|
+
its(:reply_code) { should == 200 }
|
79
|
+
its(:reply_text) { should == 'KTHXBAI' }
|
80
|
+
its(:class_id) { should == 5 }
|
81
|
+
its(:method_id) { should == 6 }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with an error code' do
|
85
|
+
it 'raises the corresponding error' do
|
86
|
+
expect { Close.decode("\x01\x38\x08NO_ROUTE\x00\x00") }.to raise_error(NoRoute, 'NO_ROUTE')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '.encode' do
|
92
|
+
it 'encodes the parameters into a MethodFrame' do
|
93
|
+
channel = 1
|
94
|
+
reply_code = 540
|
95
|
+
reply_text = 'NOT_IMPLEMENTED'
|
96
|
+
class_id = 0
|
97
|
+
method_id = 0
|
98
|
+
method_frame = Close.encode(channel, reply_code, reply_text, class_id, method_id)
|
99
|
+
method_frame.payload.should == "\x00\x14\x00(\x02\x1c\x0fNOT_IMPLEMENTED\x00\x00\x00\x00"
|
100
|
+
method_frame.channel.should == 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe CloseOk do
|
106
|
+
describe '.encode' do
|
107
|
+
it 'encodes the parameters into a MethodFrame' do
|
108
|
+
channel = 1
|
109
|
+
method_frame = CloseOk.encode(1)
|
110
|
+
method_frame.payload.should == "\x00\x14\x00\x29"
|
111
|
+
method_frame.channel.should == 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|