amqp 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -2
- data/CHANGELOG +25 -0
- data/Gemfile +4 -2
- data/README.md +2 -0
- data/{amqp.todo → TODO} +1 -3
- data/amqp.gemspec +3 -3
- data/bin/irb +2 -2
- data/bin/jenkins.sh +25 -0
- data/bin/set_test_suite_realms_up.sh +21 -0
- data/doc/EXAMPLE_01_PINGPONG +1 -1
- data/doc/EXAMPLE_02_CLOCK +1 -1
- data/doc/EXAMPLE_03_STOCKS +1 -1
- data/doc/EXAMPLE_04_MULTICLOCK +1 -1
- data/doc/EXAMPLE_05_ACK +1 -1
- data/doc/EXAMPLE_05_POP +1 -1
- data/doc/EXAMPLE_06_HASHTABLE +1 -1
- data/examples/{mq/ack.rb → ack.rb} +6 -6
- data/examples/{mq/automatic_binding_for_default_direct_exchange.rb → automatic_binding_for_default_direct_exchange.rb} +4 -4
- data/examples/{mq/callbacks.rb → callbacks.rb} +2 -2
- data/examples/{mq/clock.rb → clock.rb} +5 -5
- data/examples/{mq/hashtable.rb → hashtable.rb} +4 -4
- data/examples/{mq/internal.rb → internal.rb} +5 -5
- data/examples/{mq/logger.rb → logger.rb} +5 -5
- data/examples/{mq/multiclock.rb → multiclock.rb} +4 -4
- data/examples/{mq/pingpong.rb → pingpong.rb} +5 -5
- data/examples/{mq/pop.rb → pop.rb} +3 -3
- data/examples/{mq/primes-simple.rb → primes-simple.rb} +0 -0
- data/examples/{mq/primes.rb → primes.rb} +6 -6
- data/examples/{amqp/simple.rb → simple.rb} +1 -1
- data/examples/{mq/stocks.rb → stocks.rb} +5 -5
- data/lib/amqp.rb +8 -112
- data/lib/amqp/basic_client.rb +58 -0
- data/lib/amqp/channel.rb +937 -0
- data/lib/amqp/client.rb +72 -79
- data/lib/{mq → amqp}/collection.rb +12 -2
- data/lib/amqp/connection.rb +115 -0
- data/lib/amqp/exceptions.rb +18 -0
- data/lib/{mq → amqp}/exchange.rb +32 -34
- data/lib/{ext → amqp/ext}/em.rb +1 -1
- data/lib/{ext → amqp/ext}/emfork.rb +0 -0
- data/lib/amqp/frame.rb +3 -3
- data/lib/{mq → amqp}/header.rb +5 -11
- data/lib/{mq → amqp}/logger.rb +2 -2
- data/lib/amqp/protocol.rb +2 -2
- data/lib/{mq → amqp}/queue.rb +20 -17
- data/lib/{mq → amqp}/rpc.rb +20 -8
- data/lib/amqp/server.rb +1 -1
- data/lib/amqp/version.rb +1 -1
- data/lib/mq.rb +20 -964
- data/protocol/codegen.rb +1 -1
- data/research/api.rb +3 -3
- data/research/primes-forked.rb +5 -5
- data/research/primes-processes.rb +5 -5
- data/research/primes-threaded.rb +5 -5
- data/spec/integration/authentication_spec.rb +114 -0
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +13 -12
- data/spec/{unit/mq → integration}/channel_close_spec.rb +2 -2
- data/spec/{unit/mq → integration}/exchange_declaration_spec.rb +26 -14
- data/spec/{unit/mq → integration}/queue_declaration_spec.rb +4 -4
- data/spec/integration/queue_exclusivity_spec.rb +95 -0
- data/spec/integration/reply_queue_communication_spec.rb +63 -0
- data/spec/integration/store_and_forward_spec.rb +121 -0
- data/spec/integration/topic_subscription_spec.rb +193 -0
- data/spec/integration/workload_distribution_spec.rb +245 -0
- data/spec/spec_helper.rb +16 -32
- data/spec/unit/{mq/mq_basic_spec.rb → amqp/basic_spec.rb} +4 -4
- data/spec/unit/{mq → amqp}/collection_spec.rb +22 -7
- data/spec/unit/amqp/connection_spec.rb +116 -0
- data/spec/unit/amqp/frame_spec.rb +18 -18
- data/spec/unit/amqp/protocol_spec.rb +9 -11
- metadata +54 -49
- data/lib/ext/blankslate.rb +0 -9
- data/spec/mq_helper.rb +0 -70
- data/spec/unit/amqp/client_spec.rb +0 -472
- data/spec/unit/amqp/misc_spec.rb +0 -123
- data/spec/unit/mq/misc_spec.rb +0 -228
- data/spec/unit/mq/queue_spec.rb +0 -71
@@ -8,53 +8,53 @@ describe AMQP::Frame do
|
|
8
8
|
include AMQP
|
9
9
|
|
10
10
|
it 'should handle basic frame types' do
|
11
|
-
Frame::Method.new.id.should == 1
|
12
|
-
Frame::Header.new.id.should == 2
|
13
|
-
Frame::Body.new.id.should == 3
|
11
|
+
AMQP::Frame::Method.new.id.should == 1
|
12
|
+
AMQP::Frame::Header.new.id.should == 2
|
13
|
+
AMQP::Frame::Body.new.id.should == 3
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should convert method frames to binary' do
|
17
|
-
meth = Protocol::Connection::Secure.new :challenge => 'secret'
|
17
|
+
meth = AMQP::Protocol::Connection::Secure.new :challenge => 'secret'
|
18
18
|
|
19
|
-
frame = Frame::Method.new(meth)
|
20
|
-
frame.to_binary.should be_kind_of
|
19
|
+
frame = AMQP::Frame::Method.new(meth)
|
20
|
+
frame.to_binary.should be_kind_of(AMQP::Buffer)
|
21
21
|
frame.to_s.should == [1, 0, meth.to_s.length, meth.to_s, 206].pack('CnNa*C')
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should convert binary to method frames' do
|
25
|
-
orig = Frame::Method.new
|
25
|
+
orig = AMQP::Frame::Method.new(AMQP::Protocol::Connection::Secure.new(:challenge => 'secret'))
|
26
26
|
|
27
|
-
copy = Frame.parse(orig.to_binary)
|
27
|
+
copy = AMQP::Frame.parse(orig.to_binary)
|
28
28
|
copy.should == orig
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'should ignore partial frames until ready' do
|
32
|
-
frame = Frame::Method.new
|
32
|
+
frame = AMQP::Frame::Method.new(AMQP::Protocol::Connection::Secure.new(:challenge => 'secret'))
|
33
33
|
data = frame.to_s
|
34
34
|
|
35
|
-
buf = Buffer.new
|
36
|
-
Frame.parse(buf).should == nil
|
35
|
+
buf = AMQP::Buffer.new
|
36
|
+
AMQP::Frame.parse(buf).should == nil
|
37
37
|
|
38
38
|
buf << data[0..5]
|
39
|
-
Frame.parse(buf).should == nil
|
39
|
+
AMQP::Frame.parse(buf).should == nil
|
40
40
|
|
41
41
|
buf << data[6..-1]
|
42
|
-
Frame.parse(buf).should == frame
|
42
|
+
AMQP::Frame.parse(buf).should == frame
|
43
43
|
|
44
|
-
Frame.parse(buf).should == nil
|
44
|
+
AMQP::Frame.parse(buf).should == nil
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'should convert header frames to binary' do
|
48
|
-
head = Protocol::Header.new(Protocol::Basic, :priority => 1)
|
48
|
+
head = AMQP::Protocol::Header.new(AMQP::Protocol::Basic, :priority => 1)
|
49
49
|
|
50
|
-
frame = Frame::Header.new(head)
|
50
|
+
frame = AMQP::Frame::Header.new(head)
|
51
51
|
frame.to_s.should == [2, 0, head.to_s.length, head.to_s, 206].pack('CnNa*C')
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'should convert binary to header frame' do
|
55
|
-
orig = Frame::Header.new
|
55
|
+
orig = AMQP::Frame::Header.new(AMQP::Protocol::Header.new(AMQP::Protocol::Basic, :priority => 1))
|
56
56
|
|
57
|
-
copy = Frame.parse(orig.to_binary)
|
57
|
+
copy = AMQP::Frame.parse(orig.to_binary)
|
58
58
|
copy.should == orig
|
59
59
|
end
|
60
60
|
end
|
@@ -4,34 +4,32 @@ require "spec_helper"
|
|
4
4
|
require "amqp/protocol"
|
5
5
|
|
6
6
|
describe AMQP::Protocol do
|
7
|
-
include AMQP
|
8
|
-
|
9
7
|
it 'should instantiate methods with arguments' do
|
10
|
-
meth = Protocol::Connection::StartOk.new nil, 'PLAIN', nil, 'en_US'
|
8
|
+
meth = AMQP::Protocol::Connection::StartOk.new nil, 'PLAIN', nil, 'en_US'
|
11
9
|
meth.locale.should == 'en_US'
|
12
10
|
end
|
13
11
|
|
14
12
|
it 'should instantiate methods with named parameters' do
|
15
|
-
meth = Protocol::Connection::StartOk.new :locale => 'en_US',
|
13
|
+
meth = AMQP::Protocol::Connection::StartOk.new :locale => 'en_US',
|
16
14
|
:mechanism => 'PLAIN'
|
17
15
|
meth.locale.should == 'en_US'
|
18
16
|
end
|
19
17
|
|
20
18
|
it 'should convert methods to binary' do
|
21
|
-
meth = Protocol::Connection::Secure.new :challenge => 'secret'
|
22
|
-
meth.to_binary.should be_kind_of Buffer
|
19
|
+
meth = AMQP::Protocol::Connection::Secure.new :challenge => 'secret'
|
20
|
+
meth.to_binary.should be_kind_of AMQP::Buffer
|
23
21
|
|
24
22
|
meth.to_s.should == [10, 20, 6, 'secret'].pack('nnNa*')
|
25
23
|
end
|
26
24
|
|
27
25
|
it 'should convert binary to method' do
|
28
|
-
orig = Protocol::Connection::Secure.new :challenge => 'secret'
|
29
|
-
copy = Protocol.parse orig.to_binary
|
26
|
+
orig = AMQP::Protocol::Connection::Secure.new :challenge => 'secret'
|
27
|
+
copy = AMQP::Protocol.parse orig.to_binary
|
30
28
|
orig.should == copy
|
31
29
|
end
|
32
30
|
|
33
31
|
it 'should convert headers to binary' do
|
34
|
-
head = Protocol::Header.new Protocol::Basic,
|
32
|
+
head = AMQP::Protocol::Header.new AMQP::Protocol::Basic,
|
35
33
|
size = 5,
|
36
34
|
weight = 0,
|
37
35
|
:content_type => 'text/json',
|
@@ -42,12 +40,12 @@ describe AMQP::Protocol do
|
|
42
40
|
end
|
43
41
|
|
44
42
|
it 'should convert binary to header' do
|
45
|
-
orig = Protocol::Header.new Protocol::Basic,
|
43
|
+
orig = AMQP::Protocol::Header.new AMQP::Protocol::Basic,
|
46
44
|
size = 5,
|
47
45
|
weight = 0,
|
48
46
|
:content_type => 'text/json',
|
49
47
|
:delivery_mode => 1,
|
50
48
|
:priority => 1
|
51
|
-
Protocol::Header.new(orig.to_binary).should == orig
|
49
|
+
AMQP::Protocol::Header.new(orig.to_binary).should == orig
|
52
50
|
end
|
53
51
|
end
|
metadata
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amqp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
9
|
+
- 1
|
10
|
+
version: 0.7.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Aman Gupta
|
13
14
|
- Jakub Stastny aka botanicus
|
15
|
+
- Michael S. Klishin
|
14
16
|
autorequire:
|
15
17
|
bindir: bin
|
16
18
|
cert_chain:
|
17
|
-
date: 2011-
|
19
|
+
date: 2011-03-18 00:00:00 +03:00
|
18
20
|
default_executable:
|
19
21
|
dependencies:
|
20
22
|
- !ruby/object:Gem::Dependency
|
@@ -25,6 +27,7 @@ dependencies:
|
|
25
27
|
requirements:
|
26
28
|
- - ">="
|
27
29
|
- !ruby/object:Gem::Version
|
30
|
+
hash: 39
|
28
31
|
segments:
|
29
32
|
- 0
|
30
33
|
- 12
|
@@ -33,7 +36,9 @@ dependencies:
|
|
33
36
|
type: :runtime
|
34
37
|
version_requirements: *id001
|
35
38
|
description: An implementation of the AMQP protocol in Ruby/EventMachine for writing clients to the RabbitMQ message broker.
|
36
|
-
email:
|
39
|
+
email:
|
40
|
+
- michael@novemberain.com
|
41
|
+
- stastny@101ideas.cz
|
37
42
|
executables: []
|
38
43
|
|
39
44
|
extensions: []
|
@@ -55,11 +60,13 @@ files:
|
|
55
60
|
- Gemfile
|
56
61
|
- README.md
|
57
62
|
- Rakefile
|
63
|
+
- TODO
|
58
64
|
- amqp.gemspec
|
59
65
|
- amqp.pre.gemspec
|
60
|
-
- amqp.todo
|
61
66
|
- bin/cleanify.rb
|
62
67
|
- bin/irb
|
68
|
+
- bin/jenkins.sh
|
69
|
+
- bin/set_test_suite_realms_up.sh
|
63
70
|
- doc/EXAMPLE_01_PINGPONG
|
64
71
|
- doc/EXAMPLE_02_CLOCK
|
65
72
|
- doc/EXAMPLE_03_STOCKS
|
@@ -67,38 +74,41 @@ files:
|
|
67
74
|
- doc/EXAMPLE_05_ACK
|
68
75
|
- doc/EXAMPLE_05_POP
|
69
76
|
- doc/EXAMPLE_06_HASHTABLE
|
70
|
-
- examples/
|
71
|
-
- examples/
|
72
|
-
- examples/
|
73
|
-
- examples/
|
74
|
-
- examples/
|
75
|
-
- examples/
|
76
|
-
- examples/
|
77
|
-
- examples/
|
78
|
-
- examples/
|
79
|
-
- examples/
|
80
|
-
- examples/
|
81
|
-
- examples/
|
82
|
-
- examples/
|
83
|
-
- examples/
|
77
|
+
- examples/ack.rb
|
78
|
+
- examples/automatic_binding_for_default_direct_exchange.rb
|
79
|
+
- examples/callbacks.rb
|
80
|
+
- examples/clock.rb
|
81
|
+
- examples/hashtable.rb
|
82
|
+
- examples/internal.rb
|
83
|
+
- examples/logger.rb
|
84
|
+
- examples/multiclock.rb
|
85
|
+
- examples/pingpong.rb
|
86
|
+
- examples/pop.rb
|
87
|
+
- examples/primes-simple.rb
|
88
|
+
- examples/primes.rb
|
89
|
+
- examples/simple.rb
|
90
|
+
- examples/stocks.rb
|
84
91
|
- lib/amqp.rb
|
92
|
+
- lib/amqp/basic_client.rb
|
85
93
|
- lib/amqp/buffer.rb
|
94
|
+
- lib/amqp/channel.rb
|
86
95
|
- lib/amqp/client.rb
|
96
|
+
- lib/amqp/collection.rb
|
97
|
+
- lib/amqp/connection.rb
|
98
|
+
- lib/amqp/exceptions.rb
|
99
|
+
- lib/amqp/exchange.rb
|
100
|
+
- lib/amqp/ext/em.rb
|
101
|
+
- lib/amqp/ext/emfork.rb
|
87
102
|
- lib/amqp/frame.rb
|
103
|
+
- lib/amqp/header.rb
|
104
|
+
- lib/amqp/logger.rb
|
88
105
|
- lib/amqp/protocol.rb
|
106
|
+
- lib/amqp/queue.rb
|
107
|
+
- lib/amqp/rpc.rb
|
89
108
|
- lib/amqp/server.rb
|
90
109
|
- lib/amqp/spec.rb
|
91
110
|
- lib/amqp/version.rb
|
92
|
-
- lib/ext/blankslate.rb
|
93
|
-
- lib/ext/em.rb
|
94
|
-
- lib/ext/emfork.rb
|
95
111
|
- lib/mq.rb
|
96
|
-
- lib/mq/collection.rb
|
97
|
-
- lib/mq/exchange.rb
|
98
|
-
- lib/mq/header.rb
|
99
|
-
- lib/mq/logger.rb
|
100
|
-
- lib/mq/queue.rb
|
101
|
-
- lib/mq/rpc.rb
|
102
112
|
- protocol/amqp-0.8.json
|
103
113
|
- protocol/amqp-0.8.xml
|
104
114
|
- protocol/codegen.rb
|
@@ -107,37 +117,30 @@ files:
|
|
107
117
|
- research/primes-forked.rb
|
108
118
|
- research/primes-processes.rb
|
109
119
|
- research/primes-threaded.rb
|
120
|
+
- spec/integration/authentication_spec.rb
|
110
121
|
- spec/integration/automatic_binding_for_default_direct_exchange_spec.rb
|
111
|
-
- spec/
|
122
|
+
- spec/integration/channel_close_spec.rb
|
123
|
+
- spec/integration/exchange_declaration_spec.rb
|
124
|
+
- spec/integration/queue_declaration_spec.rb
|
125
|
+
- spec/integration/queue_exclusivity_spec.rb
|
126
|
+
- spec/integration/reply_queue_communication_spec.rb
|
127
|
+
- spec/integration/store_and_forward_spec.rb
|
128
|
+
- spec/integration/topic_subscription_spec.rb
|
129
|
+
- spec/integration/workload_distribution_spec.rb
|
112
130
|
- spec/spec_helper.rb
|
131
|
+
- spec/unit/amqp/basic_spec.rb
|
113
132
|
- spec/unit/amqp/buffer_spec.rb
|
114
|
-
- spec/unit/amqp/
|
133
|
+
- spec/unit/amqp/collection_spec.rb
|
134
|
+
- spec/unit/amqp/connection_spec.rb
|
115
135
|
- spec/unit/amqp/frame_spec.rb
|
116
|
-
- spec/unit/amqp/misc_spec.rb
|
117
136
|
- spec/unit/amqp/protocol_spec.rb
|
118
|
-
- spec/unit/mq/channel_close_spec.rb
|
119
|
-
- spec/unit/mq/collection_spec.rb
|
120
|
-
- spec/unit/mq/exchange_declaration_spec.rb
|
121
|
-
- spec/unit/mq/misc_spec.rb
|
122
|
-
- spec/unit/mq/mq_basic_spec.rb
|
123
|
-
- spec/unit/mq/queue_declaration_spec.rb
|
124
|
-
- spec/unit/mq/queue_spec.rb
|
125
137
|
has_rdoc: true
|
126
138
|
homepage: http://github.com/ruby-amqp/amqp
|
127
139
|
licenses: []
|
128
140
|
|
129
|
-
post_install_message:
|
130
|
-
[\e[32mVersion 0.7\e[0m] [BUG] Sync API for MQ#close (Channel.Close) [issue #34].\n\
|
131
|
-
[\e[32mVersion 0.7\e[0m] [FEATURE] AMQP URL from majek's fork, with some fixes. Example: AMQP.start(\"amqps://\")\n\
|
132
|
-
[\e[32mVersion 0.7\e[0m] [DEVELOP] Added some em-spec-based specs, bin/irb, Gemfile.\n\
|
133
|
-
[\e[32mVersion 0.7\e[0m] [FEATURE] Added MQ::Exchange.default for the default exchange.\n\
|
134
|
-
[\e[32mVersion 0.7\e[0m] [FEATURE] Raise an exception if we're trying to use Basic.Reject with RabbitMQ.\n\
|
135
|
-
[\e[32mVersion 0.7\e[0m] [FEATURE] Fail if an entity is re-declared with different options.\n\
|
136
|
-
[\e[32mVersion 0.7\e[0m] [BUG] Don't reconnect if the credentials are wrong.\n\
|
137
|
-
[\e[32mVersion 0.7\e[0m] [BUG] Fixed an exception which occurred when Queue#bind was called synchronously with a callback.\n\
|
138
|
-
[\e[32mVersion 0.7\e[0m] [DEVELOPMENT] Added a lot of specs (Bacon replaced by rSpec 2).\n"
|
141
|
+
post_install_message:
|
139
142
|
rdoc_options:
|
140
|
-
- --include=examples
|
143
|
+
- --include=examples --main README.md
|
141
144
|
require_paths:
|
142
145
|
- lib
|
143
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -145,6 +148,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
148
|
requirements:
|
146
149
|
- - ">="
|
147
150
|
- !ruby/object:Gem::Version
|
151
|
+
hash: 3
|
148
152
|
segments:
|
149
153
|
- 0
|
150
154
|
version: "0"
|
@@ -153,6 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
157
|
requirements:
|
154
158
|
- - ">="
|
155
159
|
- !ruby/object:Gem::Version
|
160
|
+
hash: 3
|
156
161
|
segments:
|
157
162
|
- 0
|
158
163
|
version: "0"
|
data/lib/ext/blankslate.rb
DELETED
data/spec/mq_helper.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# This helper supports writing specs for MQ (channel)
|
2
|
-
|
3
|
-
require 'mq'
|
4
|
-
|
5
|
-
# Mocking AMQP::Client::EM_CONNECTION_CLASS in order to
|
6
|
-
# specify MQ instance behavior without the need to start EM loop.
|
7
|
-
class MockConnection
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
EM.stub(:reactor_running?).and_return(true)
|
11
|
-
end
|
12
|
-
|
13
|
-
def callback &block
|
14
|
-
callbacks << block
|
15
|
-
block.call(self) if block
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_channel mq
|
19
|
-
channels[key = (channels.keys.max || 0) + 1] = mq
|
20
|
-
key
|
21
|
-
end
|
22
|
-
|
23
|
-
def send data, opts = {}
|
24
|
-
messages << {:data => data, :opts => opts}
|
25
|
-
end
|
26
|
-
|
27
|
-
def connected?
|
28
|
-
true
|
29
|
-
end
|
30
|
-
|
31
|
-
def channels
|
32
|
-
@channels||={}
|
33
|
-
end
|
34
|
-
|
35
|
-
def close
|
36
|
-
end
|
37
|
-
|
38
|
-
# Not part of AMQP::Client::EM_CONNECTION_CLASS interface, for mock introspection only
|
39
|
-
def callbacks
|
40
|
-
@callbacks||=[]
|
41
|
-
end
|
42
|
-
|
43
|
-
def messages
|
44
|
-
@messages||=[]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Sets expectations about @header and @body passed to @consumer.
|
49
|
-
def should_pass_updated_header_and_data_to consumer, opts={}
|
50
|
-
# - Why update @header.properties if @header becomes nil anyways?'
|
51
|
-
# - Because @consumer receives @header and may inspect its properties
|
52
|
-
|
53
|
-
subject_mock(:@method).should_receive(:arguments).
|
54
|
-
with(no_args).and_return(:myprop => 'mine')
|
55
|
-
consumer.should_receive(:receive) do |header, body|
|
56
|
-
header.klass.should == (opts[:klass] || AMQP::Protocol::Test)
|
57
|
-
header.size.should == (opts[:size] || 4)
|
58
|
-
header.weight.should == (opts[:weight] || 2)
|
59
|
-
header.properties.should == (opts[:properties] ||
|
60
|
-
{:delivery_mode => 1, :myprop => 'mine'})
|
61
|
-
body.should == (opts[:body] || 'data')
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Sets expectations that all listed instance variables for subject are nil
|
66
|
-
def should_be_nil *ivars
|
67
|
-
ivars.each do |ivar|
|
68
|
-
subject.instance_variable_get(ivar).should be_nil
|
69
|
-
end
|
70
|
-
end
|
@@ -1,472 +0,0 @@
|
|
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
|