bunny 1.3.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 (143) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +18 -0
  3. data/.gitignore +7 -1
  4. data/.rspec +1 -3
  5. data/.travis.yml +21 -14
  6. data/CONTRIBUTING.md +132 -0
  7. data/ChangeLog.md +887 -1
  8. data/Gemfile +13 -13
  9. data/LICENSE +1 -1
  10. data/README.md +46 -60
  11. data/Rakefile +54 -0
  12. data/bunny.gemspec +5 -11
  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/extensions/basic_nack.rb +1 -1
  30. data/examples/guides/extensions/dead_letter_exchange.rb +1 -1
  31. data/examples/guides/getting_started/hello_world.rb +2 -0
  32. data/examples/guides/getting_started/weathr.rb +2 -0
  33. data/examples/guides/queues/one_off_consumer.rb +2 -0
  34. data/examples/guides/queues/redeliveries.rb +4 -2
  35. data/lib/bunny.rb +8 -4
  36. data/lib/bunny/channel.rb +268 -153
  37. data/lib/bunny/channel_id_allocator.rb +6 -4
  38. data/lib/bunny/concurrent/continuation_queue.rb +34 -13
  39. data/lib/bunny/consumer_work_pool.rb +34 -6
  40. data/lib/bunny/cruby/socket.rb +48 -21
  41. data/lib/bunny/cruby/ssl_socket.rb +65 -4
  42. data/lib/bunny/exceptions.rb +25 -4
  43. data/lib/bunny/exchange.rb +24 -28
  44. data/lib/bunny/get_response.rb +1 -1
  45. data/lib/bunny/heartbeat_sender.rb +3 -2
  46. data/lib/bunny/jruby/socket.rb +23 -6
  47. data/lib/bunny/jruby/ssl_socket.rb +5 -0
  48. data/lib/bunny/queue.rb +31 -22
  49. data/lib/bunny/reader_loop.rb +31 -18
  50. data/lib/bunny/session.rb +448 -159
  51. data/lib/bunny/test_kit.rb +14 -0
  52. data/lib/bunny/timeout.rb +1 -12
  53. data/lib/bunny/transport.rb +205 -98
  54. data/lib/bunny/version.rb +1 -1
  55. data/repl +1 -1
  56. data/spec/config/enabled_plugins +1 -0
  57. data/spec/config/rabbitmq.conf +13 -0
  58. data/spec/higher_level_api/integration/basic_ack_spec.rb +175 -16
  59. data/spec/higher_level_api/integration/basic_cancel_spec.rb +77 -11
  60. data/spec/higher_level_api/integration/basic_consume_spec.rb +60 -55
  61. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +6 -6
  62. data/spec/higher_level_api/integration/basic_get_spec.rb +31 -7
  63. data/spec/higher_level_api/integration/basic_nack_spec.rb +22 -19
  64. data/spec/higher_level_api/integration/basic_publish_spec.rb +11 -100
  65. data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -4
  66. data/spec/higher_level_api/integration/basic_reject_spec.rb +94 -16
  67. data/spec/higher_level_api/integration/basic_return_spec.rb +4 -4
  68. data/spec/higher_level_api/integration/channel_close_spec.rb +51 -10
  69. data/spec/higher_level_api/integration/channel_open_spec.rb +12 -12
  70. data/spec/higher_level_api/integration/connection_recovery_spec.rb +424 -221
  71. data/spec/higher_level_api/integration/connection_spec.rb +300 -126
  72. data/spec/higher_level_api/integration/connection_stop_spec.rb +31 -19
  73. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +17 -17
  74. data/spec/higher_level_api/integration/dead_lettering_spec.rb +34 -11
  75. data/spec/higher_level_api/integration/exchange_bind_spec.rb +5 -5
  76. data/spec/higher_level_api/integration/exchange_declare_spec.rb +32 -31
  77. data/spec/higher_level_api/integration/exchange_delete_spec.rb +12 -12
  78. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +5 -5
  79. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
  80. data/spec/higher_level_api/integration/heartbeat_spec.rb +26 -8
  81. data/spec/higher_level_api/integration/message_properties_access_spec.rb +49 -49
  82. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +2 -2
  83. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +156 -42
  84. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +19 -19
  85. data/spec/higher_level_api/integration/queue_bind_spec.rb +23 -23
  86. data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -34
  87. data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
  88. data/spec/higher_level_api/integration/queue_purge_spec.rb +5 -5
  89. data/spec/higher_level_api/integration/queue_unbind_spec.rb +6 -6
  90. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +9 -9
  91. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +10 -10
  92. data/spec/higher_level_api/integration/tls_connection_spec.rb +224 -89
  93. data/spec/higher_level_api/integration/toxiproxy_spec.rb +76 -0
  94. data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
  95. data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
  96. data/spec/higher_level_api/integration/with_channel_spec.rb +2 -2
  97. data/spec/issues/issue100_spec.rb +11 -11
  98. data/spec/issues/issue141_spec.rb +13 -14
  99. data/spec/issues/issue202_spec.rb +1 -1
  100. data/spec/issues/issue224_spec.rb +40 -0
  101. data/spec/issues/issue465_spec.rb +32 -0
  102. data/spec/issues/issue549_spec.rb +30 -0
  103. data/spec/issues/issue78_spec.rb +21 -24
  104. data/spec/issues/issue83_spec.rb +5 -6
  105. data/spec/issues/issue97_spec.rb +44 -45
  106. data/spec/lower_level_api/integration/basic_cancel_spec.rb +15 -16
  107. data/spec/lower_level_api/integration/basic_consume_spec.rb +20 -21
  108. data/spec/spec_helper.rb +8 -26
  109. data/spec/stress/channel_close_stress_spec.rb +64 -0
  110. data/spec/stress/channel_open_stress_spec.rb +15 -9
  111. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +7 -7
  112. data/spec/stress/concurrent_consumers_stress_spec.rb +18 -16
  113. data/spec/stress/concurrent_publishers_stress_spec.rb +16 -19
  114. data/spec/stress/connection_open_close_spec.rb +9 -9
  115. data/spec/stress/merry_go_round_spec.rb +105 -0
  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_key.pem +49 -25
  121. data/spec/toxiproxy_helper.rb +28 -0
  122. data/spec/unit/bunny_spec.rb +5 -5
  123. data/spec/unit/concurrent/atomic_fixnum_spec.rb +6 -6
  124. data/spec/unit/concurrent/condition_spec.rb +8 -8
  125. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +2 -2
  126. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +16 -16
  127. data/spec/unit/exchange_recovery_spec.rb +39 -0
  128. data/spec/unit/version_delivery_tag_spec.rb +3 -3
  129. metadata +65 -47
  130. data/.ruby-version +0 -1
  131. data/lib/bunny/compatibility.rb +0 -24
  132. data/lib/bunny/system_timer.rb +0 -20
  133. data/spec/compatibility/queue_declare_spec.rb +0 -44
  134. data/spec/compatibility/queue_declare_with_default_channel_spec.rb +0 -33
  135. data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
  136. data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
  137. data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
  138. data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
  139. data/spec/stress/long_running_consumer_spec.rb +0 -83
  140. data/spec/tls/cacert.pem +0 -18
  141. data/spec/tls/client_cert.pem +0 -18
  142. data/spec/tls/server_cert.pem +0 -18
  143. 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,127 +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
- c.start
44
- c
45
- end
42
+ def no_tls12_supported?
43
+ not tls12_supported?
44
+ end
46
45
 
47
- after :each do
48
- connection.close
49
- 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
50
55
 
51
- 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"])
52
68
  end
53
69
 
70
+ context "peer verification is off" do
71
+ let(:verify_peer) { false }
54
72
 
55
- describe "TLS connection to RabbitMQ without client certificates" do
56
- let(:connection) do
57
- c = Bunny.new(:user => "bunny_gem",
58
- :password => "bunny_password",
59
- :vhost => "bunny_testbed",
60
- :tls => true,
61
- :tls_ca_certificates => ["./spec/tls/cacert.pem"])
62
- c.start
63
- c
73
+ it "uses TLS port" do
74
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
64
75
  end
65
76
 
66
- after :each do
67
- 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
68
81
  end
69
82
 
70
- include_examples "successful TLS connection"
83
+ after :each do
84
+ subject.close
85
+ end
71
86
  end
72
87
 
88
+ context "peer verification is on" do
89
+ let(:verify_peer) { true }
73
90
 
74
- describe "TLS connection to RabbitMQ with a connection string" do
75
- let(:connection) do
76
- c = Bunny.new("amqps://bunny_gem:bunny_password@127.0.0.1/bunny_testbed",
77
- :tls_cert => "spec/tls/client_cert.pem",
78
- :tls_key => "spec/tls/client_key.pem",
79
- :tls_ca_certificates => ["./spec/tls/cacert.pem"])
80
- c.start
81
- c
91
+ it "uses TLS port" do
92
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
82
93
  end
94
+ end
95
+ end
83
96
 
84
- after :each do
85
- connection.close
86
- 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
87
112
 
88
- include_examples "successful TLS connection"
113
+ after :each do
114
+ subject.close
115
+ end
116
+
117
+ include_examples "successful TLS connection"
118
+ end
119
+
120
+
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
134
+
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
89
156
  end
90
157
 
158
+ include_examples "successful TLS connection"
91
159
 
92
- describe "TLS connection to RabbitMQ with a connection string and w/o client certificate and key" do
93
- let(:connection) do
94
- c = Bunny.new("amqps://bunny_gem:bunny_password@127.0.0.1/bunny_testbed",
95
- :tls_ca_certificates => ["./spec/tls/cacert.pem"])
96
- c.start
97
- 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")
98
163
  end
99
164
 
100
- after :each do
101
- 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")
102
173
  end
174
+ end
175
+ end
103
176
 
104
- 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
105
185
  end
106
186
 
187
+ after :each do
188
+ subject.close
189
+ end
107
190
 
108
- describe "TLS connection to RabbitMQ with client certificates provided inline" do
109
- let(:connection) do
110
- c = Bunny.new(:user => "bunny_gem",
111
- :password => "bunny_password",
112
- :vhost => "bunny_testbed",
113
- :tls => true,
114
- :tls_cert => File.read("./spec/tls/client_cert.pem"),
115
- :tls_key => File.read("./spec/tls/client_key.pem"),
116
- :tls_ca_certificates => ["./spec/tls/cacert.pem"])
117
- c.start
118
- c
119
- end
191
+ context "peer verification is off" do
192
+ let(:verify_peer) { false }
120
193
 
121
- after :each do
122
- connection.close
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
123
199
  end
200
+ end
201
+
202
+ context "peer verification is on" do
203
+ let(:verify_peer) { true }
124
204
 
125
205
  include_examples "successful TLS connection"
206
+
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
210
+ end
211
+ end
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"
126
261
  end
127
262
  end