amq-protocol 0.0.1.pre → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,44 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
class Confirm
|
9
|
+
describe Select do
|
10
|
+
describe '.decode' do
|
11
|
+
subject do
|
12
|
+
Select.decode("\x01")
|
13
|
+
end
|
14
|
+
|
15
|
+
its(:nowait) { should be_true }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.encode' do
|
19
|
+
it 'encodes the parameters into a MethodFrame' do
|
20
|
+
channel = 1
|
21
|
+
nowait = true
|
22
|
+
method_frame = Select.encode(channel, nowait)
|
23
|
+
method_frame.payload.should == "\x00U\x00\n\x01"
|
24
|
+
method_frame.channel.should == 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe SelectOk do
|
30
|
+
# describe '.decode' do
|
31
|
+
# end
|
32
|
+
|
33
|
+
describe '.encode' do
|
34
|
+
it 'encodes the parameters into a MethodFrame' do
|
35
|
+
channel = 1
|
36
|
+
method_frame = SelectOk.encode(channel)
|
37
|
+
method_frame.payload.should == "\000U\000\v"
|
38
|
+
method_frame.channel.should == 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
class Connection
|
9
|
+
describe Start do
|
10
|
+
describe '.decode' do
|
11
|
+
subject do
|
12
|
+
Start.decode("\x00\t\x00\x00\x00\xFB\tcopyrightS\x00\x00\x00gCopyright (C) 2007-2010 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.\vinformationS\x00\x00\x005Licensed under the MPL. See http://www.rabbitmq.com/\bplatformS\x00\x00\x00\nErlang/OTP\aproductS\x00\x00\x00\bRabbitMQ\aversionS\x00\x00\x00\x052.2.0\x00\x00\x00\x0EPLAIN AMQPLAIN\x00\x00\x00\x05en_US")
|
13
|
+
end
|
14
|
+
|
15
|
+
its(:version_major) { should == 0 }
|
16
|
+
its(:version_minor) { should == 9 }
|
17
|
+
its(:server_properties) { should == {'copyright' => 'Copyright (C) 2007-2010 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.', 'information' => 'Licensed under the MPL. See http://www.rabbitmq.com/', 'platform' => 'Erlang/OTP', 'product' => 'RabbitMQ', 'version' => '2.2.0'} }
|
18
|
+
its(:mechanisms) { should == 'PLAIN AMQPLAIN' }
|
19
|
+
its(:locales) { should == 'en_US' }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe StartOk do
|
24
|
+
describe '.encode' do
|
25
|
+
it 'encodes the parameters into a MethodFrame' do
|
26
|
+
client_properties = {:platform => 'Ruby 1.9.2', :product => 'AMQ Client', :information => 'http://github.com/ruby-amqp/amq-client', :version => '0.2.0'}
|
27
|
+
mechanism = 'PLAIN'
|
28
|
+
response = "\x00guest\x00guest"
|
29
|
+
locale = 'en_GB'
|
30
|
+
method_frame = StartOk.encode(client_properties, mechanism, response, locale)
|
31
|
+
# the order of the table parts isn't deterministic in Ruby 1.8
|
32
|
+
method_frame.payload[0, 8].should == "\x00\n\x00\v\x00\x00\x00x"
|
33
|
+
method_frame.payload.should include("\bplatformS\x00\x00\x00\nRuby 1.9.2")
|
34
|
+
method_frame.payload.should include("\aproductS\x00\x00\x00\nAMQ Client")
|
35
|
+
method_frame.payload.should include("\vinformationS\x00\x00\x00&http://github.com/ruby-amqp/amq-client")
|
36
|
+
method_frame.payload.should include("\aversionS\x00\x00\x00\x050.2.0")
|
37
|
+
method_frame.payload[-28, 28].should == "\x05PLAIN\x00\x00\x00\f\x00guest\x00guest\x05en_GB"
|
38
|
+
method_frame.payload.length.should == 156
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe Secure do
|
44
|
+
describe '.decode' do
|
45
|
+
subject do
|
46
|
+
Secure.decode("\x00\x00\x00\x03foo")
|
47
|
+
end
|
48
|
+
|
49
|
+
its(:challenge) { should == 'foo' }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe SecureOk do
|
54
|
+
describe '.encode' do
|
55
|
+
it 'encodes the parameters as a MethodFrame' do
|
56
|
+
response = 'bar'
|
57
|
+
method_frame = SecureOk.encode(response)
|
58
|
+
method_frame.payload.should == "\x00\x0a\x00\x15\x00\x00\x00\x03bar"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Tune do
|
64
|
+
describe '.decode' do
|
65
|
+
subject do
|
66
|
+
Tune.decode("\x00\x00\x00\x02\x00\x00\x00\x00")
|
67
|
+
end
|
68
|
+
|
69
|
+
its(:channel_max) { should == 0 }
|
70
|
+
its(:frame_max) { should == 131072 }
|
71
|
+
its(:heartbeat) { should == 0}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe TuneOk do
|
76
|
+
describe '.encode' do
|
77
|
+
it 'encodes the parameters into a MethodFrame' do
|
78
|
+
channel_max = 0
|
79
|
+
frame_max = 65536
|
80
|
+
heartbeat = 1
|
81
|
+
method_frame = TuneOk.encode(channel_max, frame_max, heartbeat)
|
82
|
+
method_frame.payload.should == "\x00\n\x00\x1F\x00\x00\x00\x01\x00\x00\x00\x01"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe Open do
|
88
|
+
describe '.encode' do
|
89
|
+
it 'encodes the parameters into a MethodFrame' do
|
90
|
+
vhost = '/test'
|
91
|
+
method_frame = Open.encode(vhost)
|
92
|
+
method_frame.payload.should == "\x00\n\x00(\x05/test\x00\x00"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe OpenOk do
|
98
|
+
describe '.decode' do
|
99
|
+
subject do
|
100
|
+
OpenOk.decode("\x00")
|
101
|
+
end
|
102
|
+
|
103
|
+
its(:known_hosts) { should == '' }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe Close do
|
108
|
+
describe '.decode' do
|
109
|
+
context 'with code 200' do
|
110
|
+
subject do
|
111
|
+
Close.decode("\x00\xc8\x07KTHXBAI\x00\x05\x00\x06")
|
112
|
+
end
|
113
|
+
|
114
|
+
its(:reply_code) { should == 200 }
|
115
|
+
its(:reply_text) { should == 'KTHXBAI' }
|
116
|
+
its(:class_id) { should == 5 }
|
117
|
+
its(:method_id) { should == 6 }
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with an error code' do
|
121
|
+
it 'raises the corresponding error' do
|
122
|
+
expect { Close.decode("\x01\x38\x08NO_ROUTE\x00\x00") }.to raise_error(NoRoute, 'NO_ROUTE')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '.encode' do
|
128
|
+
it 'encodes the parameters into a MethodFrame' do
|
129
|
+
reply_code = 540
|
130
|
+
reply_text = 'NOT_IMPLEMENTED'
|
131
|
+
class_id = 0
|
132
|
+
method_id = 0
|
133
|
+
method_frame = Close.encode(reply_code, reply_text, class_id, method_id)
|
134
|
+
method_frame.payload.should == "\x00\x0a\x002\x02\x1c\x0fNOT_IMPLEMENTED\x00\x00\x00\x00"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe CloseOk do
|
140
|
+
describe '.encode' do
|
141
|
+
it 'encodes a MethodFrame' do
|
142
|
+
method_frame = CloseOk.encode
|
143
|
+
method_frame.payload.should == "\x00\n\x003"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
class Exchange
|
9
|
+
describe Declare do
|
10
|
+
describe '.encode' do
|
11
|
+
it 'encodes the parameters into a MethodFrame' do
|
12
|
+
channel = 1
|
13
|
+
exchange = 'amqclient.adapters.em.exchange1'
|
14
|
+
type = 'fanout'
|
15
|
+
passive = false
|
16
|
+
durable = false
|
17
|
+
auto_delete = false
|
18
|
+
internal = false
|
19
|
+
nowait = false
|
20
|
+
arguments = nil
|
21
|
+
method_frame = Declare.encode(channel, exchange, type, passive, durable, auto_delete, internal, nowait, arguments)
|
22
|
+
method_frame.payload.should == "\x00(\x00\n\x00\x00\x1Famqclient.adapters.em.exchange1\x06fanout\x00\x00\x00\x00\x00"
|
23
|
+
method_frame.channel.should == 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# describe DeclareOk do
|
29
|
+
# describe '.decode' do
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
describe Delete do
|
34
|
+
describe '.encode' do
|
35
|
+
it 'encodes the parameters into a MethodFrame' do
|
36
|
+
channel = 1
|
37
|
+
exchange = 'amqclient.adapters.em.exchange'
|
38
|
+
if_unused = false
|
39
|
+
nowait = false
|
40
|
+
method_frame = Delete.encode(channel, exchange, if_unused, nowait)
|
41
|
+
method_frame.payload.should == "\x00(\x00\x14\x00\x00\x1Eamqclient.adapters.em.exchange\x00"
|
42
|
+
method_frame.channel.should == 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# describe DeleteOk do
|
48
|
+
# describe '.decode' do
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
|
52
|
+
describe Bind do
|
53
|
+
describe '.encode' do
|
54
|
+
it 'encodes the parameters into a MethodFrame' do
|
55
|
+
channel = 1
|
56
|
+
destination = 'foo'
|
57
|
+
source = 'bar'
|
58
|
+
routing_key = 'xyz'
|
59
|
+
nowait = false
|
60
|
+
arguments = nil
|
61
|
+
method_frame = Bind.encode(channel, destination, source, routing_key, nowait, arguments)
|
62
|
+
method_frame.payload.should == "\x00(\x00\x1E\x00\x00\x03foo\x03bar\x03xyz\x00\x00\x00\x00\x00"
|
63
|
+
method_frame.channel.should == 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# describe BindOk do
|
69
|
+
# describe '.decode' do
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
|
73
|
+
describe Unbind do
|
74
|
+
describe '.encode' do
|
75
|
+
it 'encodes the parameters into a MethodFrame' do
|
76
|
+
channel = 1
|
77
|
+
destination = 'foo'
|
78
|
+
source = 'bar'
|
79
|
+
routing_key = 'xyz'
|
80
|
+
nowait = false
|
81
|
+
arguments = nil
|
82
|
+
method_frame = Unbind.encode(channel, destination, source, routing_key, nowait, arguments)
|
83
|
+
method_frame.payload.should == "\x00(\x00(\x00\x00\x03foo\x03bar\x03xyz\x00\x00\x00\x00\x00"
|
84
|
+
method_frame.channel.should == 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# describe UnbindOk do
|
90
|
+
# describe '.decode' do
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,82 +1,97 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Protocol
|
8
|
+
describe Frame do
|
9
|
+
describe ".encode" do
|
10
|
+
it "should raise FrameTypeError if type isn't one of: [:method, :header, :body, :heartbeat]" do
|
11
|
+
lambda { Frame.encode(nil, "", 0) }.should raise_error(FrameTypeError)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should raise FrameTypeError if type isn't valid (when type is a symbol)" do
|
15
|
+
expect { Frame.encode(:xyz, "test", 12) }.to raise_error(FrameTypeError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise FrameTypeError if type isn't valid (when type is a number)" do
|
19
|
+
expect { Frame.encode(16, "test", 12) }.to raise_error(FrameTypeError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should raise RuntimeError if channel isn't 0 or an integer in range 1..65535" do
|
23
|
+
lambda { Frame.encode(:method, "", -1) }.should raise_error(RuntimeError, /^Channel has to be 0 or an integer in range 1\.\.65535/)
|
24
|
+
lambda { Frame.encode(:method, "", 65536) }.should raise_error(RuntimeError, /^Channel has to be 0 or an integer in range 1\.\.65535/)
|
25
|
+
lambda { Frame.encode(:method, "", 65535) }.should_not raise_error(RuntimeError, /^Channel has to be 0 or an integer in range 1\.\.65535/)
|
26
|
+
lambda { Frame.encode(:method, "", 0) }.should_not raise_error(RuntimeError, /^Channel has to be 0 or an integer in range 1\.\.65535/)
|
27
|
+
lambda { Frame.encode(:method, "", 1) }.should_not raise_error(RuntimeError, /^Channel has to be 0 or an integer in range 1\.\.65535/)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should raise RuntimeError if payload is nil" do
|
31
|
+
lambda { Frame.encode(:method, nil, 0) }.should raise_error(RuntimeError, "Payload can't be nil")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should encode type" do
|
35
|
+
Frame.encode(:body, "", 0).unpack("c").first.should eql(3)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should encode channel" do
|
39
|
+
Frame.encode(:body, "", 12).unpack("cn").last.should eql(12)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should encode size" do
|
43
|
+
Frame.encode(:body, "test", 12).unpack("cnN").last.should eql(4)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should include payload" do
|
47
|
+
Frame.encode(:body, "test", 12)[7..-2].should eql("test")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should include final octet" do
|
51
|
+
Frame.encode(:body, "test", 12).should =~ /\xCE$/
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should encode unicode strings" do
|
55
|
+
expect { Frame.encode(:body, "à bientôt!", 12) }.to_not raise_error
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".new" do
|
60
|
+
it "should raise FrameTypeError if the type is not one of the accepted" do
|
61
|
+
expect { Frame.new(10) }.to raise_error(FrameTypeError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#decode_header' do
|
66
|
+
it 'raises FrameTypeError if the decoded type is not one of the accepted' do
|
67
|
+
expect { Frame.decode_header("\n\x00\x01\x00\x00\x00\x05") }.to raise_error(FrameTypeError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises EmptyResponseError if the header is nil' do
|
71
|
+
expect { Frame.decode_header(nil) }.to raise_error(EmptyResponseError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe HeaderFrame do
|
76
|
+
subject { HeaderFrame.new("\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x98\x00\x18application/octet-stream\x02\x00", nil) }
|
77
|
+
|
78
|
+
it "should decode body_size from payload" do
|
79
|
+
subject.body_size.should == 10
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should decode klass_id from payload" do
|
83
|
+
subject.klass_id.should == 60
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should decode weight from payload" do
|
87
|
+
subject.weight.should == 0
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should decode properties from payload" do
|
91
|
+
subject.properties[:delivery_mode].should == 2
|
92
|
+
subject.properties[:priority].should == 0
|
93
|
+
end
|
94
|
+
end
|
80
95
|
end
|
81
96
|
end
|
82
|
-
end
|
97
|
+
end
|