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.
@@ -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