amqp 0.8.0.rc11 → 0.8.0.rc12

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.
Files changed (33) hide show
  1. data/CHANGELOG +1 -0
  2. data/Gemfile +2 -1
  3. data/amqp.gemspec +1 -1
  4. data/docs/ConnectingToTheBroker.textile +136 -6
  5. data/docs/GettingStarted.textile +2 -2
  6. data/docs/Queues.textile +14 -14
  7. data/examples/channels/open_channel_with_one_arity_callback.rb +30 -0
  8. data/examples/deprecated/default_thread_local_channel_instance.rb +34 -0
  9. data/examples/error_handling/channel_level_exception.rb +1 -1
  10. data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +1 -1
  11. data/examples/error_handling/global_channel_level_exception_handler.rb +1 -1
  12. data/examples/guides/getting_started/03_babblr.rb +1 -1
  13. data/examples/guides/queues/05_binding_a_queue_using_exchange_instance.rb +1 -1
  14. data/examples/guides/queues/06_biding_a_queue_using_exchange_name_string.rb +1 -1
  15. data/examples/guides/queues/07_subscribing_to_receive_messages.rb +1 -1
  16. data/examples/guides/queues/08_poll_for_messages.rb +1 -1
  17. data/examples/guides/queues/09_unsubscribing_a_consumer.rb +1 -1
  18. data/examples/guides/queues/10_unbinding_from_exchange.rb +1 -1
  19. data/examples/guides/queues/11_purge_a_queue.rb +1 -1
  20. data/examples/guides/queues/12_deleting_a_queue.rb +1 -1
  21. data/examples/queues/declare_a_queue_without_assignment.rb +1 -1
  22. data/examples/queues/declare_and_bind_a_server_named_queue.rb +1 -1
  23. data/lib/amqp/channel.rb +27 -1
  24. data/lib/amqp/client.rb +36 -8
  25. data/lib/amqp/connection.rb +6 -3
  26. data/lib/amqp/deprecated/mq.rb +0 -22
  27. data/lib/amqp/queue.rb +19 -13
  28. data/lib/amqp/version.rb +1 -1
  29. data/spec/integration/authentication_spec.rb +7 -5
  30. data/spec/spec_helper.rb +1 -0
  31. data/spec/unit/amqp/client_spec.rb +149 -0
  32. data/spec/unit/amqp/connection_spec.rb +20 -0
  33. metadata +108 -86
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://dev.rabbitmq.com:5672/") do |connection|
7
+ AMQP.start("amqp://dev.rabbitmq.com:5672") do |connection|
8
8
  channel = AMQP::Channel.new(connection)
9
9
  exchange = channel.fanout("nba.scores")
10
10
 
@@ -5,7 +5,7 @@ require "rubygems"
5
5
  require "amqp"
6
6
 
7
7
  # Binding a queue to an exchange
8
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
8
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
9
9
  AMQP::Channel.new do |channel, open_ok|
10
10
  exchange = channel.fanout("amq.fanout")
11
11
 
@@ -5,7 +5,7 @@ require "rubygems"
5
5
  require "amqp"
6
6
 
7
7
  # Binding a queue to an exchange
8
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
8
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
9
9
  AMQP::Channel.new do |channel, open_ok|
10
10
  exchange_name = "amq.fanout"
11
11
 
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  AMQP::Channel.new do |channel, open_ok|
9
9
  exchange = channel.fanout("amq.fanout")
10
10
 
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  AMQP::Channel.new do |channel, open_ok|
9
9
  exchange = channel.fanout("amq.fanout")
10
10
 
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  AMQP::Channel.new do |channel, open_ok|
9
9
  exchange = channel.fanout("amq.fanout")
10
10
 
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  puts "Connected"
9
9
  AMQP::Channel.new(connection) do |channel, open_ok|
10
10
  puts "Opened a channel"
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  puts "Connected"
9
9
  AMQP::Channel.new(connection) do |channel, open_ok|
10
10
  puts "Opened a channel"
@@ -4,7 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
8
8
  puts "Connected"
9
9
  AMQP::Channel.new(connection) do |channel, open_ok|
10
10
  puts "Opened a channel"
@@ -11,7 +11,7 @@ require 'amqp'
11
11
 
12
12
  puts "=> Queue#initialize example that uses a block"
13
13
  puts
14
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
14
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
15
15
  AMQP::Channel.new do |channel, open_ok|
16
16
  puts "Channel ##{channel.id} is now open!"
17
17
 
@@ -11,7 +11,7 @@ require 'amqp'
11
11
 
12
12
  puts "=> Queue#initialize example that uses a block"
13
13
  puts
14
- AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
14
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
15
15
  AMQP::Channel.new do |channel, open_ok|
16
16
  puts "Channel ##{channel.id} is now open!" if channel.open?
17
17
 
@@ -80,7 +80,7 @@ module AMQP
80
80
  # It is possible (and, indeed, recommended) to handle channel-level exceptions by defining an errback using #on_error:
81
81
  #
82
82
  # @example Queue declaration with incompatible attributes results in a channel-level exception
83
- # AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
83
+ # AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672") do |connection, open_ok|
84
84
  # AMQP::Channel.new do |channel, open_ok|
85
85
  # puts "Channel ##{channel.id} is now open!"
86
86
  #
@@ -926,6 +926,32 @@ module AMQP
926
926
  end
927
927
 
928
928
 
929
+ #
930
+ # Backwards compatibility with 0.6.x
931
+ #
932
+
933
+ # unique identifier
934
+ # @deprecated
935
+ def self.id
936
+ Thread.current[:mq_id] ||= "#{`hostname`.strip}-#{Process.pid}-#{Thread.current.object_id}"
937
+ end
938
+
939
+ # @private
940
+ # @deprecated
941
+ def self.default
942
+ # TODO: clear this when connection is closed
943
+ Thread.current[:mq] ||= AMQP::Channel.new
944
+ end
945
+
946
+ # Allows for calls to all MQ instance methods. This implicitly calls
947
+ # AMQP::Channel.new so that a new channel is allocated for subsequent operations.
948
+ # @deprecated
949
+ def self.method_missing(meth, *args, &blk)
950
+ self.default.__send__(meth, *args, &blk)
951
+ end
952
+
953
+
954
+
929
955
  protected
930
956
 
931
957
  # @private
@@ -21,6 +21,8 @@ module AMQP
21
21
  # @see AMQP.start
22
22
  # @see AMQP.connect
23
23
  # @api plugin
24
+ #
25
+ # @see http://bit.ly/ks8MXK Connecting to The Broker documentation guide
24
26
  def self.connect(connection_string_or_options = {}, options = {}, &block)
25
27
  opts = case connection_string_or_options
26
28
  when String then
@@ -40,21 +42,47 @@ module AMQP
40
42
 
41
43
  # Parses AMQP connection string and returns it's components as a hash.
42
44
  #
43
- # @param [String] connection_string AMQP connection URI, à la JDBC connection string. For example: amqp://bus.megacorp.internal:5877/qa
45
+ # h2. vhost naming schemes
46
+ #
47
+ # AMQP 0.9.1 spec does not define what vhost naming scheme should be. RabbitMQ and Apache Qpid use different schemes
48
+ # (Qpid said to have two) but the bottom line is: even though some brokers use / as the default vhost, it can be *any string*.
49
+ # Host (and optional port) part must be separated from vhost (path component) with a slash character (/).
50
+ #
51
+ # This method will also unescape path part of the URI.
52
+ #
53
+ # @example How vhost is parsed
54
+ #
55
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com") # => vhost is nil, so default (/) will be used
56
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/") # => vhost is an empty string
57
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//") # => vhost is /
58
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//vault") # => vhost is /vault
59
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/%2Fvault") # => vhost is /vault
60
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/production") # => vhost is production
61
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/a.b.c") # => vhost is a.b.c
62
+ # AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com///a/b/c/d") # => vhost is //a/b/c/d
63
+ #
64
+ #
65
+ # @param [String] connection_string AMQP connection URI, à la JDBC connection string. For example: amqp://bus.megacorp.internal:5877.
44
66
  # @return [Hash] Connection parameters (:username, :password, :vhost, :host, :port, :ssl)
67
+ #
68
+ # @raise [ArgumentError] When connection URI schema is not amqp or amqps.
69
+ #
70
+ # @see http://bit.ly/ks8MXK Connecting to The Broker documentation guide
45
71
  # @api public
46
72
  def self.parse_connection_uri(connection_string)
47
73
  uri = URI.parse(connection_string)
48
- raise("Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766/testbed)") unless %w{amqp amqps}.include?(uri.scheme)
74
+ raise ArgumentError.new("Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK") unless %w{amqp amqps}.include?(uri.scheme)
49
75
 
50
76
  opts = {}
51
77
 
52
- opts[:user] = URI.unescape(uri.user) if uri.user
53
- opts[:pass] = URI.unescape(uri.password) if uri.password
54
- opts[:vhost] = URI.unescape(uri.path) if uri.path
55
- opts[:host] = uri.host if uri.host
56
- opts[:port] = uri.port || AMQP_PORTS[uri.scheme]
57
- opts[:ssl] = uri.scheme == AMQPS
78
+
79
+ opts[:scheme] = uri.scheme
80
+ opts[:user] = URI.unescape(uri.user) if uri.user
81
+ opts[:pass] = URI.unescape(uri.password) if uri.password
82
+ opts[:vhost] = URI.unescape($1) if uri.path =~ %r{^/(.*)}
83
+ opts[:host] = uri.host if uri.host
84
+ opts[:port] = uri.port || AMQP_PORTS[uri.scheme]
85
+ opts[:ssl] = uri.scheme == AMQPS
58
86
 
59
87
  opts
60
88
  end
@@ -15,7 +15,7 @@ module AMQP
15
15
  # to AMQP broker using {AMQP.connect}. It is generally a good idea to
16
16
  # start EventMachine event loop in a separate thread and use {AMQP.connect}.
17
17
  # That said, for applications that do not publish or handle large volumes of
18
- # data {AMQP.start} works very well and it's use is not discouraged.
18
+ # data {AMQP.start} works very well and its use is not discouraged.
19
19
  #
20
20
  # See {AMQP.connect} for information about arguments this method takes and
21
21
  # information about relevant topics such as authentication failure handling.
@@ -37,7 +37,9 @@ module AMQP
37
37
  # @api public
38
38
  def self.start(connection_options_or_string = {}, other_options = {}, &block)
39
39
  EM.run do
40
- @connection ||= connect(connection_options_or_string, other_options, &block)
40
+ if !@connection || @connection.closed? || @connection.closing?
41
+ @connection = connect(connection_options_or_string, other_options, &block)
42
+ end
41
43
  @channel = Channel.new(@connection)
42
44
  @connection
43
45
  end
@@ -169,7 +171,7 @@ module AMQP
169
171
  #
170
172
  # @example Using AMQP.connect to connect to a public RabbitMQ instance with connection settings given as a URI
171
173
  #
172
- # AMQP.connect "amqp://guest:guest@dev.rabbitmq.com:5672/", :on_possible_authentication_failure => Proc.new { puts("Looks like authentication has failed") } do |connection|
174
+ # AMQP.connect "amqp://guest:guest@dev.rabbitmq.com:5672", :on_possible_authentication_failure => Proc.new { puts("Looks like authentication has failed") } do |connection|
173
175
  # AMQP::Channel.new(connection) do |channel|
174
176
  # # ...
175
177
  # end
@@ -191,6 +193,7 @@ module AMQP
191
193
  # @option connection_options_or_string [String] :username ("guest") Username to use. Also can be specified as :user.
192
194
  # @option connection_options_or_string [String] :password ("guest") Password to use. Also can be specified as :pass.
193
195
  # @option connection_options_or_string [Hash] :ssl TLS (SSL) parameters to use.
196
+ # @option connection_options_or_string [#call] :on_tcp_connection_failure A callable object that will be run if connection to server fails
194
197
  # @option connection_options_or_string [#call] :on_possible_authentication_failure A callable object that will be run if authentication fails (see Authentication failure section)
195
198
  #
196
199
  #
@@ -17,26 +17,4 @@ class MQ
17
17
  # @note This class will be removed before 1.0 release.
18
18
  # @deprecated
19
19
  class Queue < ::AMQP::Queue; end
20
-
21
-
22
- #
23
- # Backwards compatibility with 0.6.x
24
- #
25
-
26
- # unique identifier
27
- def MQ.id
28
- Thread.current[:mq_id] ||= "#{`hostname`.strip}-#{Process.pid}-#{Thread.current.object_id}"
29
- end
30
-
31
- # @private
32
- def MQ.default
33
- # TODO: clear this when connection is closed
34
- Thread.current[:mq] ||= MQ.new
35
- end
36
-
37
- # Allows for calls to all MQ instance methods. This implicitly calls
38
- # MQ.new so that a new channel is allocated for subsequent operations.
39
- def MQ.method_missing(meth, *args, &blk)
40
- MQ.default.__send__(meth, *args, &blk)
41
- end
42
20
  end
@@ -219,27 +219,33 @@ module AMQP
219
219
  end # server_named?
220
220
 
221
221
 
222
- # This method binds a queue to an exchange. Until a queue is
223
- # bound it will not receive any messages. In a classic messaging
222
+ # This method binds a queue to an exchange. Until a queue is
223
+ # bound it will not receive any messages. In a classic messaging
224
224
  # model, store-and-forward queues are bound to a dest exchange
225
225
  # and subscription queues are bound to a dest_wild exchange.
226
226
  #
227
227
  # A valid exchange name (or reference) must be passed as the first
228
228
  # parameter.
229
- # @example Both of these are valid
230
- # exch = AMQP::Channel.direct('foo exchange')
231
- # queue = AMQP::Channel.queue('bar queue')
232
- # queue.bind('foo.exchange') # OR
233
- # queue.bind(exch)
229
+ # @example Binding a queue to exchange using AMQP::Exchange instance
234
230
  #
235
- # It is not valid to call #bind without the +exchange+ parameter.
231
+ # ch = AMQP::Channel.new(connection)
232
+ # exchange = ch.direct('backlog.events')
233
+ # queue = ch.queue('', :exclusive => true)
234
+ # queue.bind(exchange)
236
235
  #
237
- # It is unnecessary to call #bind when the exchange name and queue
238
- # name match exactly (for :direct and :fanout exchanges only).
239
- # There is an implicit bind which will deliver the messages from
240
- # the exchange to the queue.
241
236
  #
242
- # @param [Exchange] Exchange to bind to.
237
+ # @example Binding a queue to exchange using exchange name
238
+ #
239
+ # ch = AMQP::Channel.new(connection)
240
+ # queue = ch.queue('', :exclusive => true)
241
+ # queue.bind('backlog.events')
242
+ #
243
+ #
244
+ # Note that if your producer application knows consumer queue name and wants to deliver
245
+ # a message there, direct exchange may be sufficient (in other words, if your code declares an exchange with
246
+ # the same name as a queue and binds it to that queue, consider using the default exchange and routing key on publishing).
247
+ #
248
+ # @param [Exchange] Exchange to bind to. May also be a string or any object that responds to #name.
243
249
  #
244
250
  # @option opts [String] :routing_key Specifies the routing key for the binding. The routing key is
245
251
  # used for routing messages depending on the exchange configuration.
@@ -6,5 +6,5 @@ module AMQP
6
6
  #
7
7
  # @see AMQ::Protocol::VERSION
8
8
  # @return [String] AMQP gem version
9
- VERSION = '0.8.0.rc11'
9
+ VERSION = '0.8.0.rc12'
10
10
  end
@@ -10,6 +10,8 @@ describe "Authentication attempt" do
10
10
  include EventedSpec::EMSpec
11
11
  include EventedSpec::SpecHelper
12
12
 
13
+ default_timeout 1.0
14
+
13
15
 
14
16
  describe "with default connection parameters" do
15
17
 
@@ -45,12 +47,12 @@ describe "Authentication attempt" do
45
47
 
46
48
  # assuming there is an account amqp_gem with password of "amqp_gem_password" that has
47
49
  # access to /amqp_gem_testbed
48
- context "when amqp_gem/amqp_gem_testbed has access to /amqp_gem_testbed" do
50
+ context "when amqp_gem/amqp_gem_testbed has access to amqp_gem_testbed" do
49
51
  context "and provided credentials are correct" do
50
52
  it "succeeds" do
51
- connection = AMQP.connect :username => "amqp_gem", :password => "amqp_gem_password", :vhost => "/amqp_gem_testbed"
53
+ connection = AMQP.connect(AMQP_OPTS.merge(:username => "amqp_gem", :password => "amqp_gem_password", :vhost => "/amqp_gem_testbed"))
52
54
 
53
- done(0.5) {
55
+ done(0.4) {
54
56
  connection.should be_connected
55
57
  connection.close
56
58
  }
@@ -99,10 +101,10 @@ describe "Authentication attempt" do
99
101
 
100
102
  # assuming there is an account amqp_gem with password of "amqp_gem_password" that has
101
103
  # access to /amqp_gem_testbed
102
- context "when amqp_gem/amqp_gem_testbed has access to /amqp_gem_testbed" do
104
+ context "when amqp_gem/amqp_gem_testbed has access to amqp_gem_testbed" do
103
105
  context "and provided credentials are correct" do
104
106
  it "succeeds" do
105
- connection = AMQP.connect "amqp://amqp_gem:amqp_gem_password@localhost/amqp_gem_testbed"
107
+ connection = AMQP.connect "amqp://amqp_gem:amqp_gem_password@localhost/%2Famqp_gem_testbed"
106
108
 
107
109
  done(0.3) {
108
110
  connection.should be_connected
@@ -93,6 +93,7 @@ else
93
93
  AMQP_OPTS = {:host => 'localhost', :port => 5672}
94
94
  end
95
95
 
96
+ puts "AMQP_OPTS = #{AMQP_OPTS.inspect}"
96
97
 
97
98
  #
98
99
  # Ruby version-specific
@@ -0,0 +1,149 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe AMQP::Client do
6
+
7
+ #
8
+ # Examples
9
+ #
10
+
11
+
12
+ describe ".parse_connection_uri(connection_string)" do
13
+ context "when schema is not one of [amqp, amqps]" do
14
+ it "raises ArgumentError" do
15
+ expect {
16
+ described_class.parse_connection_uri("http://dev.rabbitmq.com")
17
+ }.to raise_error(ArgumentError, /amqp or amqps schema/)
18
+ end
19
+ end
20
+
21
+
22
+ it "handles amqp:// URIs w/o path part" do
23
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com")
24
+
25
+ val[:vhost].should be_nil # in this case, default / will be used
26
+ val[:host].should == "dev.rabbitmq.com"
27
+ val[:port].should == 5672
28
+ val[:scheme].should == "amqp"
29
+ val[:ssl].should be_false
30
+ end
31
+
32
+ it "handles amqps:// URIs w/o path part" do
33
+ val = described_class.parse_connection_uri("amqps://dev.rabbitmq.com")
34
+
35
+ val[:vhost].should be_nil
36
+ val[:host].should == "dev.rabbitmq.com"
37
+ val[:port].should == 5671
38
+ val[:scheme].should == "amqps"
39
+ val[:ssl].should be_true
40
+ end
41
+
42
+
43
+ context "when URI ends in a slash" do
44
+ it "parses vhost as an empty string" do
45
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com/")
46
+
47
+ val[:host].should == "dev.rabbitmq.com"
48
+ val[:port].should == 5672
49
+ val[:scheme].should == "amqp"
50
+ val[:ssl].should be_false
51
+ val[:vhost].should == ""
52
+ end
53
+ end
54
+
55
+
56
+ context "when URI ends in two consecutive slashes (//)" do
57
+ it "parses vhost as /" do
58
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com//")
59
+
60
+ val[:host].should == "dev.rabbitmq.com"
61
+ val[:port].should == 5672
62
+ val[:scheme].should == "amqp"
63
+ val[:ssl].should be_false
64
+ val[:vhost].should == "/"
65
+ end
66
+ end
67
+
68
+
69
+ context "when URI ends in //vault" do
70
+ it "parses vhost as /vault" do
71
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com//vault")
72
+
73
+ val[:host].should == "dev.rabbitmq.com"
74
+ val[:port].should == 5672
75
+ val[:scheme].should == "amqp"
76
+ val[:ssl].should be_false
77
+ val[:vhost].should == "/vault"
78
+ end
79
+ end
80
+
81
+
82
+
83
+ context "when URI ends in /%2Fvault" do
84
+ it "parses vhost as /vault" do
85
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com/%2Fvault")
86
+
87
+ val[:host].should == "dev.rabbitmq.com"
88
+ val[:port].should == 5672
89
+ val[:scheme].should == "amqp"
90
+ val[:ssl].should be_false
91
+ val[:vhost].should == "/vault"
92
+ end
93
+ end
94
+
95
+
96
+ context "when URI is amqp://dev.rabbitmq.com/i.am.a.vhost.without.slashes" do
97
+ it "parses vhost as i.am.a.vhost.without.slashes" do
98
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com/i.am.a.vhost.without.slashes")
99
+
100
+ val[:host].should == "dev.rabbitmq.com"
101
+ val[:port].should == 5672
102
+ val[:scheme].should == "amqp"
103
+ val[:ssl].should be_false
104
+ val[:vhost].should == "i.am.a.vhost.without.slashes"
105
+ end
106
+ end
107
+
108
+
109
+ context "when URI is amqp://dev.rabbitmq.com/production" do
110
+ it "parses vhost as production" do
111
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com/production")
112
+
113
+ val[:host].should == "dev.rabbitmq.com"
114
+ val[:port].should == 5672
115
+ val[:scheme].should == "amqp"
116
+ val[:ssl].should be_false
117
+ val[:vhost].should == "production"
118
+ end
119
+ end
120
+
121
+
122
+ context "when URI is amqp://dev.rabbitmq.com///a/b/c/d" do
123
+ it "parses vhost as ///a/b/c/d" do
124
+ val = described_class.parse_connection_uri("amqp://dev.rabbitmq.com///a/b/c/d")
125
+
126
+ val[:host].should == "dev.rabbitmq.com"
127
+ val[:port].should == 5672
128
+ val[:scheme].should == "amqp"
129
+ val[:ssl].should be_false
130
+ val[:vhost].should == "//a/b/c/d"
131
+ end
132
+ end
133
+
134
+
135
+ context "when URI has username:password, for instance, amqp://hedgehog:t0ps3kr3t@hub.megacorp.internal" do
136
+ it "parses them out" do
137
+ val = described_class.parse_connection_uri("amqp://hedgehog:t0ps3kr3t@hub.megacorp.internal")
138
+
139
+ val[:host].should == "hub.megacorp.internal"
140
+ val[:port].should == 5672
141
+ val[:scheme].should == "amqp"
142
+ val[:ssl].should be_false
143
+ val[:user].should == "hedgehog"
144
+ val[:pass].should == "t0ps3kr3t"
145
+ val[:vhost].should be_nil # in this case, default / will be used
146
+ end
147
+ end
148
+ end
149
+ end