bunny 1.7.0 → 2.17.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.
Files changed (141) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +18 -0
  3. data/.gitignore +6 -1
  4. data/.rspec +1 -3
  5. data/.travis.yml +21 -14
  6. data/CONTRIBUTING.md +132 -0
  7. data/ChangeLog.md +745 -1
  8. data/Gemfile +13 -13
  9. data/LICENSE +1 -1
  10. data/README.md +41 -75
  11. data/Rakefile +54 -0
  12. data/bunny.gemspec +4 -10
  13. data/docker-compose.yml +28 -0
  14. data/docker/Dockerfile +24 -0
  15. data/docker/apt/preferences.d/erlang +3 -0
  16. data/docker/apt/sources.list.d/bintray.rabbitmq.list +2 -0
  17. data/docker/docker-entrypoint.sh +26 -0
  18. data/docker/rabbitmq.conf +29 -0
  19. data/examples/connection/automatic_recovery_with_basic_get.rb +1 -1
  20. data/examples/connection/automatic_recovery_with_client_named_queues.rb +1 -1
  21. data/examples/connection/automatic_recovery_with_multiple_consumers.rb +1 -1
  22. data/examples/connection/automatic_recovery_with_republishing.rb +1 -1
  23. data/examples/connection/automatic_recovery_with_server_named_queues.rb +1 -1
  24. data/examples/connection/channel_level_exception.rb +1 -9
  25. data/examples/connection/disabled_automatic_recovery.rb +1 -1
  26. data/examples/connection/heartbeat.rb +1 -1
  27. data/examples/consumers/high_and_low_priority.rb +1 -1
  28. data/examples/guides/extensions/alternate_exchange.rb +2 -0
  29. data/examples/guides/getting_started/hello_world.rb +2 -0
  30. data/examples/guides/getting_started/weathr.rb +2 -0
  31. data/examples/guides/queues/one_off_consumer.rb +2 -0
  32. data/examples/guides/queues/redeliveries.rb +2 -0
  33. data/lib/bunny.rb +6 -2
  34. data/lib/bunny/channel.rb +192 -109
  35. data/lib/bunny/channel_id_allocator.rb +6 -4
  36. data/lib/bunny/concurrent/continuation_queue.rb +34 -13
  37. data/lib/bunny/consumer_work_pool.rb +34 -6
  38. data/lib/bunny/cruby/socket.rb +29 -16
  39. data/lib/bunny/cruby/ssl_socket.rb +20 -7
  40. data/lib/bunny/exceptions.rb +7 -1
  41. data/lib/bunny/exchange.rb +11 -7
  42. data/lib/bunny/get_response.rb +1 -1
  43. data/lib/bunny/heartbeat_sender.rb +3 -2
  44. data/lib/bunny/jruby/socket.rb +23 -6
  45. data/lib/bunny/jruby/ssl_socket.rb +5 -0
  46. data/lib/bunny/queue.rb +12 -10
  47. data/lib/bunny/reader_loop.rb +31 -18
  48. data/lib/bunny/session.rb +389 -134
  49. data/lib/bunny/test_kit.rb +14 -0
  50. data/lib/bunny/timeout.rb +1 -12
  51. data/lib/bunny/transport.rb +114 -67
  52. data/lib/bunny/version.rb +1 -1
  53. data/repl +1 -1
  54. data/spec/config/rabbitmq.conf +13 -0
  55. data/spec/higher_level_api/integration/basic_ack_spec.rb +154 -22
  56. data/spec/higher_level_api/integration/basic_cancel_spec.rb +77 -11
  57. data/spec/higher_level_api/integration/basic_consume_spec.rb +60 -55
  58. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +6 -6
  59. data/spec/higher_level_api/integration/basic_get_spec.rb +31 -7
  60. data/spec/higher_level_api/integration/basic_nack_spec.rb +22 -19
  61. data/spec/higher_level_api/integration/basic_publish_spec.rb +11 -100
  62. data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -4
  63. data/spec/higher_level_api/integration/basic_reject_spec.rb +94 -16
  64. data/spec/higher_level_api/integration/basic_return_spec.rb +4 -4
  65. data/spec/higher_level_api/integration/channel_close_spec.rb +51 -10
  66. data/spec/higher_level_api/integration/channel_open_spec.rb +12 -12
  67. data/spec/higher_level_api/integration/connection_recovery_spec.rb +412 -286
  68. data/spec/higher_level_api/integration/connection_spec.rb +284 -134
  69. data/spec/higher_level_api/integration/connection_stop_spec.rb +31 -19
  70. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +17 -17
  71. data/spec/higher_level_api/integration/dead_lettering_spec.rb +14 -14
  72. data/spec/higher_level_api/integration/exchange_bind_spec.rb +5 -5
  73. data/spec/higher_level_api/integration/exchange_declare_spec.rb +32 -31
  74. data/spec/higher_level_api/integration/exchange_delete_spec.rb +12 -12
  75. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +5 -5
  76. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
  77. data/spec/higher_level_api/integration/heartbeat_spec.rb +4 -4
  78. data/spec/higher_level_api/integration/message_properties_access_spec.rb +49 -49
  79. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +2 -2
  80. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +92 -27
  81. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +19 -19
  82. data/spec/higher_level_api/integration/queue_bind_spec.rb +23 -23
  83. data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -34
  84. data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
  85. data/spec/higher_level_api/integration/queue_purge_spec.rb +5 -5
  86. data/spec/higher_level_api/integration/queue_unbind_spec.rb +6 -6
  87. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +9 -9
  88. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +10 -10
  89. data/spec/higher_level_api/integration/tls_connection_spec.rb +218 -112
  90. data/spec/higher_level_api/integration/toxiproxy_spec.rb +76 -0
  91. data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
  92. data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
  93. data/spec/higher_level_api/integration/with_channel_spec.rb +2 -2
  94. data/spec/issues/issue100_spec.rb +11 -12
  95. data/spec/issues/issue141_spec.rb +13 -14
  96. data/spec/issues/issue202_spec.rb +1 -1
  97. data/spec/issues/issue224_spec.rb +5 -5
  98. data/spec/issues/issue465_spec.rb +32 -0
  99. data/spec/issues/issue549_spec.rb +30 -0
  100. data/spec/issues/issue78_spec.rb +21 -24
  101. data/spec/issues/issue83_spec.rb +5 -6
  102. data/spec/issues/issue97_spec.rb +44 -45
  103. data/spec/lower_level_api/integration/basic_cancel_spec.rb +15 -16
  104. data/spec/lower_level_api/integration/basic_consume_spec.rb +20 -21
  105. data/spec/spec_helper.rb +2 -19
  106. data/spec/stress/channel_close_stress_spec.rb +3 -3
  107. data/spec/stress/channel_open_stress_spec.rb +4 -4
  108. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +7 -7
  109. data/spec/stress/concurrent_consumers_stress_spec.rb +18 -16
  110. data/spec/stress/concurrent_publishers_stress_spec.rb +16 -19
  111. data/spec/stress/connection_open_close_spec.rb +9 -9
  112. data/spec/stress/merry_go_round_spec.rb +105 -0
  113. data/spec/tls/ca_certificate.pem +27 -16
  114. data/spec/tls/ca_key.pem +52 -27
  115. data/spec/tls/client_certificate.pem +27 -16
  116. data/spec/tls/client_key.pem +49 -25
  117. data/spec/tls/generate-server-cert.sh +8 -0
  118. data/spec/tls/server-openssl.cnf +10 -0
  119. data/spec/tls/server.csr +16 -0
  120. data/spec/tls/server_certificate.pem +27 -16
  121. data/spec/tls/server_key.pem +49 -25
  122. data/spec/toxiproxy_helper.rb +28 -0
  123. data/spec/unit/bunny_spec.rb +5 -5
  124. data/spec/unit/concurrent/atomic_fixnum_spec.rb +6 -6
  125. data/spec/unit/concurrent/condition_spec.rb +8 -8
  126. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +2 -2
  127. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +16 -16
  128. data/spec/unit/exchange_recovery_spec.rb +39 -0
  129. data/spec/unit/version_delivery_tag_spec.rb +3 -3
  130. metadata +42 -35
  131. data/lib/bunny/system_timer.rb +0 -20
  132. data/spec/config/rabbitmq.config +0 -18
  133. data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
  134. data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
  135. data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
  136. data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
  137. data/spec/stress/long_running_consumer_spec.rb +0 -83
  138. data/spec/tls/cacert.pem +0 -18
  139. data/spec/tls/client_cert.pem +0 -18
  140. data/spec/tls/server_cert.pem +0 -18
  141. data/spec/unit/system_timer_spec.rb +0 -10
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Queue, "#delete" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -22,7 +22,7 @@ describe Bunny::Queue, "#delete" do
22
22
  # no exception as of RabbitMQ 3.2. MK.
23
23
  q.delete
24
24
 
25
- ch.queues.size.should == 0
25
+ expect(ch.queues.size).to eq 0
26
26
  end
27
27
  end
28
28
 
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Queue do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -15,15 +15,15 @@ describe Bunny::Queue do
15
15
  it "can be purged" do
16
16
  ch = connection.create_channel
17
17
 
18
- q = ch.queue("", :exclusive => true)
18
+ q = ch.queue("", exclusive: true)
19
19
  x = ch.default_exchange
20
20
 
21
- x.publish("xyzzy", :routing_key => q.name)
21
+ x.publish("xyzzy", routing_key: q.name)
22
22
  sleep(0.5)
23
23
 
24
- q.message_count.should == 1
24
+ expect(q.message_count).to eq 1
25
25
  q.purge
26
- q.message_count.should == 0
26
+ expect(q.message_count).to eq 0
27
27
 
28
28
  ch.close
29
29
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Queue, "bound to an exchange" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -15,16 +15,16 @@ describe Bunny::Queue, "bound to an exchange" do
15
15
  it "can be unbound from an exchange it was bound to" do
16
16
  ch = connection.create_channel
17
17
  x = ch.fanout("amq.fanout")
18
- q = ch.queue("", :exclusive => true).bind(x)
18
+ q = ch.queue("", exclusive: true).bind(x)
19
19
 
20
20
  x.publish("")
21
21
  sleep 0.3
22
- q.message_count.should == 1
22
+ expect(q.message_count).to eq 1
23
23
 
24
24
  q.unbind(x)
25
25
 
26
26
  x.publish("")
27
- q.message_count.should == 1
27
+ expect(q.message_count).to eq 1
28
28
  end
29
29
  end
30
30
 
@@ -32,7 +32,7 @@ end
32
32
 
33
33
  describe Bunny::Queue, "NOT bound to an exchange" do
34
34
  let(:connection) do
35
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
35
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
36
36
  c.start
37
37
  c
38
38
  end
@@ -45,7 +45,7 @@ describe Bunny::Queue, "NOT bound to an exchange" do
45
45
  it "is idempotent (succeeds)" do
46
46
  ch = connection.create_channel
47
47
  x = ch.fanout("amq.fanout")
48
- q = ch.queue("", :exclusive => true)
48
+ q = ch.queue("", exclusive: true)
49
49
 
50
50
  # No exception as of RabbitMQ 3.2. MK.
51
51
  q.unbind(x)
@@ -2,13 +2,13 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Queue, "#subscribe" do
4
4
  let(:publisher_connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
9
9
 
10
10
  let(:consumer_connection) do
11
- c = Bunny.new(:user => "bunny_reader", :password => "reader_password", :vhost => "bunny_testbed")
11
+ c = Bunny.new(username: "bunny_reader", password: "reader_password", vhost: "bunny_testbed")
12
12
  c.start
13
13
  c
14
14
  end
@@ -28,7 +28,7 @@ describe Bunny::Queue, "#subscribe" do
28
28
  ch = publisher_connection.create_channel
29
29
  # declare the queue because the read-only user won't be able to issue
30
30
  # queue.declare
31
- q = ch.queue(queue_name, :auto_delete => true, :durable => false)
31
+ q = ch.queue(queue_name, auto_delete: true, durable: false)
32
32
 
33
33
  t = Thread.new do
34
34
  # give the main thread a bit of time to declare the queue
@@ -36,8 +36,8 @@ describe Bunny::Queue, "#subscribe" do
36
36
  ch = consumer_connection.create_channel
37
37
  # this connection is read only, use passive declare to only get
38
38
  # a reference to the queue
39
- q = ch.queue(queue_name, :auto_delete => true, :durable => false, :passive => true)
40
- q.subscribe(:exclusive => false) do |delivery_info, properties, payload|
39
+ q = ch.queue(queue_name, auto_delete: true, durable: false, passive: true)
40
+ q.subscribe(exclusive: false) do |delivery_info, properties, payload|
41
41
  delivered_keys << delivery_info.routing_key
42
42
  delivered_data << payload
43
43
  end
@@ -46,13 +46,13 @@ describe Bunny::Queue, "#subscribe" do
46
46
  sleep 0.5
47
47
 
48
48
  x = ch.default_exchange
49
- x.publish("hello", :routing_key => queue_name)
49
+ x.publish("hello", routing_key: queue_name)
50
50
 
51
51
  sleep 0.7
52
- delivered_keys.should include(queue_name)
53
- delivered_data.should include("hello")
52
+ expect(delivered_keys).to include(queue_name)
53
+ expect(delivered_data).to include("hello")
54
54
 
55
- ch.queue(queue_name, :auto_delete => true, :durable => false).message_count.should == 0
55
+ expect(ch.queue(queue_name, auto_delete: true, durable: false).message_count).to eq 0
56
56
 
57
57
  ch.close
58
58
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe "Sender-selected distribution" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -14,22 +14,22 @@ describe "Sender-selected distribution" do
14
14
  it "lets publishers specify additional routing keys using CC and BCC headers" do
15
15
  ch = connection.create_channel
16
16
  x = ch.direct("bunny.tests.ssd.exchange")
17
- q1 = ch.queue("", :exclusive => true).bind(x, :routing_key => "one")
18
- q2 = ch.queue("", :exclusive => true).bind(x, :routing_key => "two")
19
- q3 = ch.queue("", :exclusive => true).bind(x, :routing_key => "three")
20
- q4 = ch.queue("", :exclusive => true).bind(x, :routing_key => "four")
17
+ q1 = ch.queue("", exclusive: true).bind(x, routing_key: "one")
18
+ q2 = ch.queue("", exclusive: true).bind(x, routing_key: "two")
19
+ q3 = ch.queue("", exclusive: true).bind(x, routing_key: "three")
20
+ q4 = ch.queue("", exclusive: true).bind(x, routing_key: "four")
21
21
 
22
22
  n = 10
23
23
  n.times do |i|
24
- x.publish("Message #{i}", :routing_key => "one", :headers => {"CC" => ["two", "three"]})
24
+ x.publish("Message #{i}", routing_key: "one", headers: {"CC" => ["two", "three"]})
25
25
  end
26
26
 
27
27
  sleep 0.5
28
28
 
29
- q1.message_count.should == n
30
- q2.message_count.should == n
31
- q3.message_count.should == n
32
- q4.message_count.should be_zero
29
+ expect(q1.message_count).to eq n
30
+ expect(q2.message_count).to eq n
31
+ expect(q3.message_count).to eq n
32
+ expect(q4.message_count).to be_zero
33
33
 
34
34
  x.delete
35
35
  end
@@ -1,156 +1,262 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require "spec_helper"
3
3
 
4
- unless ENV["CI"]
5
- shared_examples_for "successful TLS connection" do
6
- it "succeeds" do
7
- connection.should be_tls
8
- ch = connection.create_channel
9
-
10
- q = ch.queue("", :exclusive => true)
11
- x = ch.default_exchange
12
-
13
- x.publish("xyzzy", :routing_key => q.name).
14
- publish("xyzzy", :routing_key => q.name).
15
- publish("xyzzy", :routing_key => q.name).
16
- publish("xyzzy", :routing_key => q.name)
17
-
18
- sleep 0.5
19
- q.message_count.should == 4
20
-
21
- i = 0
22
- q.subscribe do |delivery_info, _, payload|
23
- i += 1
24
- end
25
- sleep 1.0
26
- i.should == 4
27
- q.message_count.should == 0
28
-
29
- ch.close
4
+ require "socket"
5
+
6
+ CERTIFICATE_DIR = ENV.fetch("BUNNY_CERTIFICATE_DIR", "./spec/tls")
7
+ puts "Will use certificates from #{CERTIFICATE_DIR}"
8
+
9
+ shared_examples_for "successful TLS connection" do
10
+ it "succeeds", skip: ENV["CI"] do
11
+ expect(subject).to be_tls
12
+ ch = subject.create_channel
13
+ ch.confirm_select
14
+
15
+ q = ch.queue("", exclusive: true)
16
+ x = ch.default_exchange
17
+
18
+ x.publish("xyzzy", routing_key: q.name).
19
+ publish("xyzzy", routing_key: q.name).
20
+ publish("xyzzy", routing_key: q.name).
21
+ publish("xyzzy", routing_key: q.name)
22
+
23
+ x.wait_for_confirms
24
+ expect(q.message_count).to eq 4
25
+
26
+ i = 0
27
+ q.subscribe do |delivery_info, _, payload|
28
+ i += 1
30
29
  end
30
+ sleep 1.0
31
+ expect(i).to eq 4
32
+ expect(q.message_count).to eq 0
33
+
34
+ ch.close
31
35
  end
36
+ end
32
37
 
38
+ def local_hostname
39
+ ENV.fetch("BUNNY_RABBITMQ_HOSTNAME", "localhost")
40
+ end
33
41
 
34
- describe "TLS connection to RabbitMQ with client certificates" do
35
- let(:connection) do
36
- c = Bunny.new(:user => "bunny_gem",
37
- :password => "bunny_password",
38
- :vhost => "bunny_testbed",
39
- :tls => true,
40
- :tls_cert => "spec/tls/client_cert.pem",
41
- :tls_key => "spec/tls/client_key.pem",
42
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
43
- :verify_peer => false)
44
- c.start
45
- c
46
- end
42
+ def no_tls12_supported?
43
+ not tls12_supported?
44
+ end
47
45
 
48
- after :each do
49
- connection.close
50
- end
46
+ def tls12_supported?
47
+ begin
48
+ ctx = OpenSSL::SSL::SSLContext.new
49
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
50
+ true
51
+ rescue
52
+ false
53
+ end
54
+ end
51
55
 
52
- include_examples "successful TLS connection"
56
+ context "initialized with tls: true", skip: ENV["CI"] do
57
+ let(:subject) do
58
+ Bunny.new(
59
+ hostname: local_hostname(),
60
+ user: "bunny_gem",
61
+ password: "bunny_password",
62
+ vhost: "bunny_testbed",
63
+ tls: true,
64
+ verify_peer: verify_peer,
65
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
66
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
67
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"])
53
68
  end
54
69
 
70
+ context "peer verification is off" do
71
+ let(:verify_peer) { false }
55
72
 
56
- describe "TLS connection to RabbitMQ without client certificates" do
57
- let(:connection) do
58
- c = Bunny.new(:user => "bunny_gem",
59
- :password => "bunny_password",
60
- :vhost => "bunny_testbed",
61
- :tls => true,
62
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
63
- :verify_peer => false)
64
- c.start
65
- c
73
+ it "uses TLS port" do
74
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
66
75
  end
67
76
 
68
- after :each do
69
- connection.close
77
+ it "sends the SNI details" do
78
+ # https://github.com/ruby-amqp/bunny/issues/440
79
+ subject.start
80
+ expect(subject.transport.socket.hostname).to_not be_empty
70
81
  end
71
82
 
72
- include_examples "successful TLS connection"
83
+ after :each do
84
+ subject.close
85
+ end
73
86
  end
74
87
 
88
+ context "peer verification is on" do
89
+ let(:verify_peer) { true }
75
90
 
76
- describe "TLS connection to RabbitMQ with a connection string" do
77
- let(:connection) do
78
- c = Bunny.new("amqps://bunny_gem:bunny_password@127.0.0.1/bunny_testbed",
79
- :tls_cert => "spec/tls/client_cert.pem",
80
- :tls_key => "spec/tls/client_key.pem",
81
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
82
- :verify_peer => false)
83
- c.start
84
- c
91
+ it "uses TLS port" do
92
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
85
93
  end
94
+ end
95
+ end
86
96
 
87
- after :each do
88
- connection.close
89
- end
97
+ describe "TLS connection to RabbitMQ with client certificates", skip: ENV["CI"] do
98
+ let(:subject) do
99
+ c = Bunny.new(
100
+ hostname: local_hostname(),
101
+ username: "bunny_gem",
102
+ password: "bunny_password",
103
+ vhost: "bunny_testbed",
104
+ tls: true,
105
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
106
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
107
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
108
+ verify_peer: false)
109
+ c.start
110
+ c
111
+ end
90
112
 
91
- include_examples "successful TLS connection"
113
+ after :each do
114
+ subject.close
92
115
  end
93
116
 
117
+ include_examples "successful TLS connection"
118
+ end
94
119
 
95
- describe "TLS connection to RabbitMQ with a connection string and w/o client certificate and key" do
96
- let(:connection) do
97
- c = Bunny.new("amqps://bunny_gem:bunny_password@127.0.0.1/bunny_testbed",
98
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
99
- :verify_peer => false)
100
- c.start
101
- c
102
- end
103
120
 
104
- after :each do
105
- connection.close
106
- end
121
+ describe "TLS connection to RabbitMQ without client certificates", skip: ENV["CI"] do
122
+ let(:subject) do
123
+ c = Bunny.new(
124
+ hostname: local_hostname(),
125
+ username: "bunny_gem",
126
+ password: "bunny_password",
127
+ vhost: "bunny_testbed",
128
+ tls: true,
129
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
130
+ verify_peer: false)
131
+ c.start
132
+ c
133
+ end
107
134
 
108
- include_examples "successful TLS connection"
135
+ after :each do
136
+ subject.close
137
+ end
138
+
139
+ include_examples "successful TLS connection"
140
+ end
141
+
142
+
143
+ describe "TLS connection to RabbitMQ with a connection string", skip: ENV["CI"] do
144
+ let(:subject) do
145
+ c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
146
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
147
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
148
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
149
+ verify_peer: false)
150
+ c.start
151
+ c
152
+ end
153
+
154
+ after :each do
155
+ subject.close
109
156
  end
110
157
 
158
+ include_examples "successful TLS connection"
111
159
 
112
- describe "TLS connection to RabbitMQ with client certificates provided inline" do
113
- let(:connection) do
114
- c = Bunny.new(:user => "bunny_gem",
115
- :password => "bunny_password",
116
- :vhost => "bunny_testbed",
117
- :tls => true,
118
- :tls_cert => File.read("./spec/tls/client_cert.pem"),
119
- :tls_key => File.read("./spec/tls/client_key.pem"),
120
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
121
- :verify_peer => false)
122
- c.start
123
- c
160
+ context "when URI contains query parameters" do
161
+ subject(:session) do
162
+ Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed?heartbeat=10&connection_timeout=100&channel_max=1000&verify=false&cacertfile=#{CERTIFICATE_DIR}/ca_certificate.pem&certfile=#{CERTIFICATE_DIR}/client_certificate.pem&keyfile=#{CERTIFICATE_DIR}/client_key.pem")
124
163
  end
125
164
 
126
- after :each do
127
- connection.close
165
+ it "parses extra connection parameters" do
166
+ session.start
167
+
168
+ expect(session.uses_tls?).to eq(true)
169
+ expect(session.transport.verify_peer).to eq(false)
170
+ expect(session.transport.tls_ca_certificates).to eq(["#{CERTIFICATE_DIR}/ca_certificate.pem"])
171
+ expect(session.transport.tls_certificate_path).to eq("#{CERTIFICATE_DIR}/client_certificate.pem")
172
+ expect(session.transport.tls_key_path).to eq("#{CERTIFICATE_DIR}/client_key.pem")
128
173
  end
174
+ end
175
+ end
129
176
 
130
- include_examples "successful TLS connection"
177
+
178
+ describe "TLS connection to RabbitMQ with a connection string and w/o client certificate and key", skip: ENV["CI"] do
179
+ let(:subject) do
180
+ c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
181
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
182
+ verify_peer: verify_peer)
183
+ c.start
184
+ c
131
185
  end
132
186
 
133
- describe "TLS connection to RabbitMQ with tls_version TLSv1 specified" do
134
- let(:connection) do
135
- c = Bunny.new(:user => "bunny_gem",
136
- :password => "bunny_password",
137
- :vhost => "bunny_testbed",
138
- :tls => true,
139
- :tls_protocol => :TLSv1,
140
- :tls_ca_certificates => ["./spec/tls/cacert.pem"],
141
- :verify_peer => false)
142
- c.start
143
- c
144
- end
187
+ after :each do
188
+ subject.close
189
+ end
145
190
 
146
- after :each do
147
- connection.close
191
+ context "peer verification is off" do
192
+ let(:verify_peer) { false }
193
+
194
+ include_examples "successful TLS connection"
195
+
196
+ it "sends the SNI details" do
197
+ # https://github.com/ruby-amqp/bunny/issues/440
198
+ expect(subject.transport.socket.hostname).to_not be_empty
148
199
  end
200
+ end
201
+
202
+ context "peer verification is on" do
203
+ let(:verify_peer) { true }
149
204
 
150
205
  include_examples "successful TLS connection"
151
206
 
152
- it "connects using TLSv1" do
153
- connection.transport.socket.ssl_version.should == "TLSv1"
207
+ it "sends the SNI details" do
208
+ # https://github.com/ruby-amqp/bunny/issues/440
209
+ expect(subject.transport.socket.hostname).to_not be_empty
154
210
  end
155
211
  end
156
212
  end
213
+
214
+
215
+ describe "TLS connection to RabbitMQ with client certificates provided inline", skip: ENV["CI"] do
216
+ let(:subject) do
217
+ c = Bunny.new(
218
+ hostname: local_hostname(),
219
+ username: "bunny_gem",
220
+ password: "bunny_password",
221
+ vhost: "bunny_testbed",
222
+ tls: true,
223
+ tls_cert: File.read("#{CERTIFICATE_DIR}/client_certificate.pem"),
224
+ tls_key: File.read("#{CERTIFICATE_DIR}/client_key.pem"),
225
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
226
+ verify_peer: false)
227
+ c.start
228
+ c
229
+ end
230
+
231
+ after :each do
232
+ subject.close
233
+ end
234
+
235
+ include_examples "successful TLS connection"
236
+ end
237
+
238
+ describe "TLS connection to RabbitMQ with tls_version TLSv1.2 specified", skip: ENV["CI"] do
239
+ let(:subject) do
240
+ c = Bunny.new(
241
+ hostname: local_hostname(),
242
+ username: "bunny_gem",
243
+ password: "bunny_password",
244
+ vhost: "bunny_testbed",
245
+ tls: true,
246
+ tls_protocol: :TLSv1_2,
247
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
248
+ verify_peer: false)
249
+ c.start
250
+ c
251
+ end
252
+
253
+ after :each do
254
+ subject.close
255
+ end
256
+
257
+ include_examples "successful TLS connection"
258
+
259
+ it "connects using TLSv1.2", skip: no_tls12_supported? do
260
+ expect(subject.transport.socket.ssl_version).to eq "TLSv1.2"
261
+ end
262
+ end