bunny 1.7.0 → 2.17.0

Sign up to get free protection for your applications and to get access to all the features.
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