stomper 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/.gitignore +5 -0
  2. data/{spec/spec.opts → .rspec} +0 -2
  3. data/Gemfile +4 -0
  4. data/LICENSE +201 -201
  5. data/README.md +130 -0
  6. data/Rakefile +5 -0
  7. data/examples/basic.rb +38 -0
  8. data/examples/events.rb +54 -0
  9. data/features/acking_messages.feature +147 -0
  10. data/features/disconnecting.feature +12 -0
  11. data/features/establish_connection.feature +44 -0
  12. data/features/protocol_version_negotiation.feature +61 -0
  13. data/features/receipts.feature +72 -0
  14. data/features/scopes.feature +32 -0
  15. data/features/secure_connections.feature +38 -0
  16. data/features/send_and_message.feature +28 -0
  17. data/features/steps/acking_messages_steps.rb +39 -0
  18. data/features/steps/disconnecting_steps.rb +8 -0
  19. data/features/steps/establish_connection_steps.rb +74 -0
  20. data/features/steps/frame_transmission_steps.rb +35 -0
  21. data/features/steps/protocol_version_negotiation_steps.rb +15 -0
  22. data/features/steps/receipts_steps.rb +79 -0
  23. data/features/steps/scopes_steps.rb +52 -0
  24. data/features/steps/secure_connections_steps.rb +41 -0
  25. data/features/steps/send_and_message_steps.rb +35 -0
  26. data/features/steps/subscribing_steps.rb +36 -0
  27. data/features/steps/threaded_receiver_steps.rb +8 -0
  28. data/features/steps/transactions_steps.rb +0 -0
  29. data/features/subscribing.feature +151 -0
  30. data/features/support/env.rb +11 -0
  31. data/features/support/header_helpers.rb +12 -0
  32. data/features/support/ssl/README +6 -0
  33. data/features/support/ssl/broker_cert.csr +17 -0
  34. data/features/support/ssl/broker_cert.pem +72 -0
  35. data/features/support/ssl/broker_key.pem +27 -0
  36. data/features/support/ssl/client_cert.csr +17 -0
  37. data/features/support/ssl/client_cert.pem +72 -0
  38. data/features/support/ssl/client_key.pem +27 -0
  39. data/features/support/ssl/demoCA/cacert.pem +17 -0
  40. data/features/support/ssl/demoCA/index.txt +2 -0
  41. data/features/support/ssl/demoCA/index.txt.attr +1 -0
  42. data/features/support/ssl/demoCA/index.txt.attr.old +1 -0
  43. data/features/support/ssl/demoCA/index.txt.old +1 -0
  44. data/features/support/ssl/demoCA/newcerts/01.pem +72 -0
  45. data/features/support/ssl/demoCA/newcerts/02.pem +72 -0
  46. data/features/support/ssl/demoCA/private/cakey.pem +17 -0
  47. data/features/support/ssl/demoCA/serial +1 -0
  48. data/features/support/ssl/demoCA/serial.old +1 -0
  49. data/features/support/test_stomp_server.rb +150 -0
  50. data/features/threaded_receiver.feature +11 -0
  51. data/features/transactions.feature +66 -0
  52. data/lib/stomper.rb +30 -20
  53. data/lib/stomper/connection.rb +442 -102
  54. data/lib/stomper/errors.rb +59 -0
  55. data/lib/stomper/extensions.rb +10 -0
  56. data/lib/stomper/extensions/common.rb +258 -0
  57. data/lib/stomper/extensions/events.rb +213 -0
  58. data/lib/stomper/extensions/heartbeat.rb +101 -0
  59. data/lib/stomper/extensions/scoping.rb +56 -0
  60. data/lib/stomper/frame.rb +54 -0
  61. data/lib/stomper/frame_serializer.rb +217 -0
  62. data/lib/stomper/headers.rb +15 -0
  63. data/lib/stomper/receipt_manager.rb +36 -0
  64. data/lib/stomper/receivers.rb +7 -0
  65. data/lib/stomper/receivers/threaded.rb +71 -0
  66. data/lib/stomper/scopes.rb +9 -0
  67. data/lib/stomper/scopes/header_scope.rb +49 -0
  68. data/lib/stomper/scopes/receipt_scope.rb +44 -0
  69. data/lib/stomper/scopes/transaction_scope.rb +109 -0
  70. data/lib/stomper/sockets.rb +66 -28
  71. data/lib/stomper/subscription_manager.rb +79 -0
  72. data/lib/stomper/support.rb +68 -0
  73. data/lib/stomper/support/1.8/frame_serializer.rb +53 -0
  74. data/lib/stomper/support/1.8/headers.rb +183 -0
  75. data/lib/stomper/support/1.9/frame_serializer.rb +64 -0
  76. data/lib/stomper/support/1.9/headers.rb +172 -0
  77. data/lib/stomper/support/ruby.rb +13 -0
  78. data/lib/stomper/uris.rb +49 -0
  79. data/lib/stomper/version.rb +7 -0
  80. data/spec/spec_helper.rb +13 -9
  81. data/spec/stomper/connection_spec.rb +712 -0
  82. data/spec/stomper/extensions/common_spec.rb +187 -0
  83. data/spec/stomper/extensions/events_spec.rb +78 -0
  84. data/spec/stomper/extensions/heartbeat_spec.rb +103 -0
  85. data/spec/stomper/extensions/scoping_spec.rb +21 -0
  86. data/spec/stomper/frame_serializer_1.8_spec.rb +318 -0
  87. data/spec/stomper/frame_serializer_spec.rb +316 -0
  88. data/spec/stomper/frame_spec.rb +36 -0
  89. data/spec/stomper/headers_spec.rb +224 -0
  90. data/spec/stomper/receipt_manager_spec.rb +91 -0
  91. data/spec/stomper/receivers/threaded_spec.rb +116 -0
  92. data/spec/stomper/scopes/header_scope_spec.rb +42 -0
  93. data/spec/stomper/scopes/receipt_scope_spec.rb +51 -0
  94. data/spec/stomper/scopes/transaction_scope_spec.rb +183 -0
  95. data/spec/stomper/sockets_spec.rb +113 -0
  96. data/spec/stomper/subscription_manager_spec.rb +107 -0
  97. data/spec/stomper/support_spec.rb +69 -0
  98. data/spec/stomper/uris_spec.rb +54 -0
  99. data/spec/stomper_spec.rb +9 -0
  100. data/spec/support/custom_argument_matchers.rb +57 -0
  101. data/spec/support/existential_frame_matchers.rb +19 -0
  102. data/spec/support/frame_header_matchers.rb +10 -0
  103. data/stomper.gemspec +30 -0
  104. metadata +272 -97
  105. data/AUTHORS +0 -21
  106. data/CHANGELOG +0 -20
  107. data/README.rdoc +0 -120
  108. data/lib/stomper/client.rb +0 -34
  109. data/lib/stomper/frame_reader.rb +0 -73
  110. data/lib/stomper/frame_writer.rb +0 -21
  111. data/lib/stomper/frames.rb +0 -39
  112. data/lib/stomper/frames/abort.rb +0 -10
  113. data/lib/stomper/frames/ack.rb +0 -25
  114. data/lib/stomper/frames/begin.rb +0 -11
  115. data/lib/stomper/frames/client_frame.rb +0 -89
  116. data/lib/stomper/frames/commit.rb +0 -10
  117. data/lib/stomper/frames/connect.rb +0 -10
  118. data/lib/stomper/frames/connected.rb +0 -30
  119. data/lib/stomper/frames/disconnect.rb +0 -10
  120. data/lib/stomper/frames/error.rb +0 -21
  121. data/lib/stomper/frames/message.rb +0 -48
  122. data/lib/stomper/frames/receipt.rb +0 -19
  123. data/lib/stomper/frames/send.rb +0 -10
  124. data/lib/stomper/frames/server_frame.rb +0 -38
  125. data/lib/stomper/frames/subscribe.rb +0 -42
  126. data/lib/stomper/frames/unsubscribe.rb +0 -19
  127. data/lib/stomper/open_uri_interface.rb +0 -41
  128. data/lib/stomper/receipt_handlers.rb +0 -23
  129. data/lib/stomper/receiptor.rb +0 -38
  130. data/lib/stomper/subscriber.rb +0 -76
  131. data/lib/stomper/subscription.rb +0 -128
  132. data/lib/stomper/subscriptions.rb +0 -95
  133. data/lib/stomper/threaded_receiver.rb +0 -59
  134. data/lib/stomper/transaction.rb +0 -185
  135. data/lib/stomper/transactor.rb +0 -50
  136. data/lib/stomper/uri.rb +0 -55
  137. data/spec/client_spec.rb +0 -29
  138. data/spec/connection_spec.rb +0 -22
  139. data/spec/frame_reader_spec.rb +0 -37
  140. data/spec/frame_writer_spec.rb +0 -27
  141. data/spec/frames/client_frame_spec.rb +0 -66
  142. data/spec/frames/indirect_frame_spec.rb +0 -45
  143. data/spec/frames/server_frame_spec.rb +0 -85
  144. data/spec/open_uri_interface_spec.rb +0 -132
  145. data/spec/receiptor_spec.rb +0 -35
  146. data/spec/shared_connection_examples.rb +0 -79
  147. data/spec/subscriber_spec.rb +0 -77
  148. data/spec/subscription_spec.rb +0 -157
  149. data/spec/subscriptions_spec.rb +0 -145
  150. data/spec/threaded_receiver_spec.rb +0 -33
  151. data/spec/transaction_spec.rb +0 -139
  152. data/spec/transactor_spec.rb +0 -46
@@ -0,0 +1,113 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module Stomper
5
+ describe Sockets do
6
+ describe Sockets::TCP do
7
+ before(:each) do
8
+ @tcp_socket = mock('tcp socket')
9
+ ::TCPSocket.stub(:new => @tcp_socket)
10
+ @tcp = ::Stomper::Sockets::TCP.new('host', 12345)
11
+ end
12
+ it "should create a new instance that delegates to TCPSocket" do
13
+ @tcp_socket.should_receive(:ready?).and_return(true)
14
+ @tcp_socket.should_receive(:read).and_return('this is what we read')
15
+ @tcp_socket.should_receive(:write).with('blather').and_return(42)
16
+
17
+ @tcp.ready?.should be_true
18
+ @tcp.read.should == 'this is what we read'
19
+ @tcp.write('blather').should == 42
20
+ end
21
+ end
22
+
23
+ describe Sockets::SSL do
24
+ before(:each) do
25
+ @tcp_socket = mock('tcp socket')
26
+ ::TCPSocket.stub(:new => @tcp_socket)
27
+ @ssl_socket = mock('ssl socket', :sync_close= => true, :connect => true, :io => @tcp_socket)
28
+ ::OpenSSL::SSL::SSLSocket.stub(:new => @ssl_socket)
29
+ end
30
+
31
+ it "should use the underlying TCP socket for :ready?" do
32
+ @ssl_socket.should_receive(:post_connection_check).with('host').and_return(true)
33
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789)
34
+ @tcp_socket.should_receive(:ready?).and_return(true)
35
+
36
+ @ssl.ready?.should be_true
37
+ end
38
+
39
+ it "should use the underlying TCP socket for :shutdown" do
40
+ @ssl_socket.should_receive(:post_connection_check).with('host').and_return(true)
41
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789)
42
+ @tcp_socket.should_receive(:shutdown).with('args').and_return(true)
43
+
44
+ @ssl.shutdown('args').should be_true
45
+ end
46
+
47
+ it "should delegate unknown methods to SSLSocket" do
48
+ @ssl_socket.should_receive(:post_connection_check).with('host').and_return(true)
49
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789)
50
+ @ssl_socket.should_receive(:read).and_return('this is what we read')
51
+ @ssl_socket.should_receive(:write).with('blather').and_return(42)
52
+
53
+ @ssl.read.should == 'this is what we read'
54
+ @ssl.write('blather').should == 42
55
+ end
56
+
57
+ it "should not perform a post_connection_check if option value is nil or false" do
58
+ @ssl_socket.should_not_receive(:post_connection_check)
59
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789, { :post_connection_check => false })
60
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789, { :post_connection_check => nil })
61
+ end
62
+
63
+ it "should perform a post_connection_check against the host if the option value is true" do
64
+ @ssl_socket.should_receive(:post_connection_check).with('host.name.tld').and_return(true)
65
+ @ssl = ::Stomper::Sockets::SSL.new('host.name.tld', 56789, { :post_connection_check => true })
66
+ end
67
+
68
+ it "should perform a post_connection_check against the option value otherwise" do
69
+ @ssl_socket.should_receive(:post_connection_check).with('user specified name').and_return(true)
70
+ @ssl = ::Stomper::Sockets::SSL.new('host.name.tld', 56789, { :post_connection_check => 'user specified name' })
71
+
72
+ @ssl_socket.should_receive(:post_connection_check).with(66).and_return(true)
73
+ @ssl = ::Stomper::Sockets::SSL.new('host.name.tld', 56789, { :post_connection_check => 66 })
74
+ end
75
+
76
+ describe "SSL Context Options" do
77
+ before(:each) do
78
+ @ssl_context = mock('context')
79
+ ::OpenSSL::SSL::SSLContext.stub(:new => @ssl_context)
80
+ end
81
+
82
+ it "should apply sensible defaults when no options are specified" do
83
+ @ssl_context.should_receive(:verify_mode=).with(::OpenSSL::SSL::VERIFY_PEER |
84
+ ::OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT)
85
+ @ssl_context.should_receive(:ca_file=).with(nil)
86
+ @ssl_context.should_receive(:ca_path=).with(nil)
87
+ @ssl_context.should_receive(:cert=).with(nil)
88
+ @ssl_context.should_receive(:key=).with(nil)
89
+
90
+ @ssl_socket.should_receive(:post_connection_check).with('host').and_return(true)
91
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789)
92
+ end
93
+
94
+ it "should override sensible defaults with supplied options" do
95
+ @ssl_context.should_receive(:verify_mode=).with("kage")
96
+ @ssl_context.should_receive(:ca_file=).with("jables")
97
+ @ssl_context.should_receive(:ca_path=).with("the d")
98
+ @ssl_context.should_receive(:cert=).with("scepter")
99
+ @ssl_context.should_receive(:key=).with("key")
100
+
101
+ @ssl_socket.should_receive(:post_connection_check).with('host').and_return(true)
102
+ @ssl = ::Stomper::Sockets::SSL.new('host', 56789, {
103
+ :verify_mode => "kage",
104
+ :ca_file => "jables",
105
+ :ca_path => "the d",
106
+ :cert => "scepter",
107
+ :key => "key"
108
+ })
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,107 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module Stomper
5
+ describe SubscriptionManager do
6
+ before(:each) do
7
+ @connection = mock("connection")
8
+ end
9
+
10
+ it "should bind to the on_receipt event handler" do
11
+ receipt = mock('receipt')
12
+ @connection.should_receive(:on_message)
13
+ @connection.should_receive(:on_unsubscribe)
14
+ @subscription_manager = SubscriptionManager.new(@connection)
15
+ end
16
+
17
+ describe "usage" do
18
+ before(:each) do
19
+ @connection.extend ::Stomper::Extensions::Events
20
+ @subscription_manager = SubscriptionManager.new(@connection)
21
+ @subscribe_frame = ::Stomper::Frame.new('SUBSCRIBE', {:id => '1234', :destination => '/queue/testing'})
22
+ @unsubscribe_frame = ::Stomper::Frame.new('UNSUBSCRIBE', {:id => '1234'})
23
+ end
24
+
25
+ it "should correctly report subscribed IDs" do
26
+ @subscription_manager.add(@subscribe_frame, lambda { |m| true })
27
+ @subscription_manager.subscribed_id?('1234').should be_true
28
+ @subscription_manager.subscribed_id?('4321').should be_false
29
+ @subscription_manager.__send__(:remove, @unsubscribe_frame)
30
+ @subscription_manager.subscribed_id?('1234').should be_false
31
+ end
32
+
33
+ it "should correctly report subscribed destinations" do
34
+ @subscription_manager.add(@subscribe_frame, lambda { |m| true })
35
+ @subscription_manager.subscribed_destination?('/queue/testing').should be_true
36
+ @subscription_manager.subscribed_destination?('/queue/test').should be_false
37
+ @subscription_manager.__send__(:remove, @unsubscribe_frame)
38
+ @subscription_manager.subscribed_destination?('/queue/testing').should be_false
39
+ end
40
+
41
+ it "should correctly map subscribed destinations to their IDs" do
42
+ alt_subscribe_frame = ::Stomper::Frame.new('SUBSCRIBE', {:id => '4567', :destination => '/queue/testing'})
43
+ alt_unsubscribe_frame = ::Stomper::Frame.new('UNSUBSCRIBE', {:id => '4567'})
44
+ @subscription_manager.add(@subscribe_frame, lambda { |m| true })
45
+ @subscription_manager.add(alt_subscribe_frame, lambda { |m| true })
46
+ @subscription_manager.ids_for_destination('/queue/testing').should == ['1234', '4567']
47
+ @subscription_manager.ids_for_destination('/queue/test').should be_nil
48
+ @subscription_manager.__send__(:remove, @unsubscribe_frame)
49
+ @subscription_manager.ids_for_destination('/queue/testing').should == ['4567']
50
+ @subscription_manager.__send__(:remove, alt_unsubscribe_frame)
51
+ @subscription_manager.ids_for_destination('/queue/testing').should be_nil
52
+ end
53
+
54
+ it "should allow a subscription handler to be registered within a callback" do
55
+ alt_subscribe_frame = ::Stomper::Frame.new('SUBSCRIBE', {:id => '4567', :destination => '/queue/testing'})
56
+ triggered = [false, false]
57
+ callback = lambda do |m|
58
+ triggered[0] = true
59
+ @subscription_manager.add(alt_subscribe_frame, lambda { |m| triggered[1] = true })
60
+ end
61
+ @subscription_manager.add(@subscribe_frame, callback)
62
+ @connection.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '1234' }))
63
+ @connection.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '4567' }))
64
+ triggered.should == [true, true]
65
+ end
66
+
67
+ it "should allow a subscription to be removed within a callback" do
68
+ triggered = 0
69
+ callback = lambda do |m|
70
+ triggered += 1
71
+ @connection.__send__(:trigger_received_frame, ::Stomper::Frame.new('UNSUBSCRIBE', { :id => '1234' }))
72
+ end
73
+ @subscription_manager.add(@subscribe_frame, callback)
74
+ @connection.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '1234' }))
75
+ @connection.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '1234' }))
76
+ triggered.should == 1
77
+ end
78
+
79
+ it "should allow a receipt handler to be registered within a callback in separate threads" do
80
+ alt_subscribe_frame = ::Stomper::Frame.new('SUBSCRIBE', {:id => '4567', :destination => '/queue/testing'})
81
+ triggered = [false, false]
82
+ started_r1 = false
83
+ callback = lambda do |r|
84
+ triggered[0] = true
85
+ Thread.stop
86
+ end
87
+ @subscription_manager.add(@subscribe_frame, callback)
88
+ r_1 = Thread.new(@connection) do |c|
89
+ started_r1 = true
90
+ Thread.stop
91
+ c.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '1234' }))
92
+ end
93
+ r_2 = Thread.new(@connection) do |c|
94
+ Thread.pass until triggered[0]
95
+ @subscription_manager.add(alt_subscribe_frame, lambda { |r| triggered[1] = true })
96
+ r_1.run
97
+ c.__send__(:trigger_received_frame, ::Stomper::Frame.new('MESSAGE', { :subscription => '4567' }))
98
+ end
99
+ Thread.pass until started_r1
100
+ r_1.run
101
+ r_1.join
102
+ r_2.join
103
+ triggered.should == [true, true]
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,69 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module Stomper
5
+ describe Support do
6
+ before(:each) do
7
+ @hash = {
8
+ 'a' => 'value 1',
9
+ :somekey => ['a', :set, 'of values', 33],
10
+ '13' => nil
11
+ }
12
+ end
13
+
14
+ describe "keys_to_sym" do
15
+ it "should symbolize the keys of a hash without changing the original hash" do
16
+ symbolized_hash = Support.keys_to_sym(@hash)
17
+
18
+ @hash['a'].should == 'value 1'
19
+ @hash[:somekey].should == ['a', :set, 'of values', 33]
20
+ @hash['13'].should be_nil
21
+
22
+ symbolized_hash.keys.sort.should == [ :'13', :a, :somekey ]
23
+ symbolized_hash[:a].should == 'value 1'
24
+ symbolized_hash[:somekey].should == ['a', :set, 'of values', 33]
25
+ symbolized_hash[:'13'].should be_nil
26
+ end
27
+ end
28
+
29
+ describe "keys_to_sym!" do
30
+ it "should symbolize the keys of a hash and replace the existing hash" do
31
+ Support.keys_to_sym!(@hash)
32
+ @hash.keys.sort.should == [ :'13', :a, :somekey ]
33
+ @hash[:a].should == 'value 1'
34
+ @hash[:somekey].should == ['a', :set, 'of values', 33]
35
+ @hash[:'13'].should be_nil
36
+ end
37
+ end
38
+
39
+ describe "next_serial" do
40
+ it "should generate sequential numbers" do
41
+ first = Support.next_serial.to_i
42
+ second = Support.next_serial.to_i
43
+ third = Support.next_serial.to_i
44
+ first.should == second - 1
45
+ second.should == third - 1
46
+ end
47
+ end
48
+
49
+ describe "constantize" do
50
+ it "should constantize a Class" do
51
+ Support.constantize(Class).should == ::Class
52
+ Support.constantize(::Stomper::Extensions::Events).should == ::Stomper::Extensions::Events
53
+ end
54
+
55
+ it "should constantize string representations of known classes" do
56
+ Support.constantize("Module").should == ::Module
57
+ Support.constantize("::Module").should == ::Module
58
+ Support.constantize("::Stomper::Extensions").should == ::Stomper::Extensions
59
+ Support.constantize("Stomper::Receivers::Threaded").should == ::Stomper::Receivers::Threaded
60
+ end
61
+
62
+ it "should fail to constantize un-resolvable classes" do
63
+ lambda { Support.constantize("::Not::::Valid") }.should raise_error(NameError)
64
+ lambda { Support.constantize("Module::Does::Not::Exist") }.should raise_error(NameError)
65
+ lambda { Support.constantize("::Stomper::FrameSerializer::Nada") }.should raise_error(NameError)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ module URI
5
+ describe STOMP do
6
+ before(:each) do
7
+ @uri = ::URI.parse('stomp:///')
8
+ @uri_host = ::URI.parse('stomp://host.domain.tld:12345')
9
+ end
10
+
11
+ it "should be the class of URIs with a scheme of 'stomp' parsed by URI.parse" do
12
+ @uri.should be_an_instance_of(::URI::STOMP)
13
+ end
14
+
15
+ it "should use port 61613 as a default if no port is specified" do
16
+ @uri.port.should == 61613
17
+ end
18
+
19
+ it "should respond to :create_socket and return a TCP/IP socket built from its socket_factory" do
20
+ socket = mock('socket')
21
+ host_socket = mock('socket with host')
22
+ ::Stomper::Sockets::TCP.should_receive(:new).with('localhost', 61613).and_return(socket)
23
+ ::Stomper::Sockets::TCP.should_receive(:new).with('host.domain.tld', 12345).and_return(host_socket)
24
+
25
+ @uri.create_socket.should equal(socket)
26
+ @uri_host.create_socket.should equal(host_socket)
27
+ end
28
+ end
29
+
30
+ describe STOMP_SSL do
31
+ before(:each) do
32
+ @uri = ::URI.parse("stomp+ssl:///")
33
+ @uri_host = ::URI.parse('stomp+ssl://other.domain.tld:98765')
34
+ end
35
+
36
+ it "should be the class of URIs with a scheme of 'stomp+ssl' parsed by URI.parse" do
37
+ @uri.should be_an_instance_of(::URI::STOMP_SSL)
38
+ end
39
+
40
+ it "should use port 61612 as a default if no port is specified" do
41
+ @uri.port.should == 61612
42
+ end
43
+
44
+ it "should respond to :create_socket and return a TCP/IP socket built from its socket_factory" do
45
+ socket = mock('socket')
46
+ host_socket = mock('socket with host')
47
+ ::Stomper::Sockets::SSL.should_receive(:new).with('localhost', 61612, {}).and_return(socket)
48
+ ::Stomper::Sockets::SSL.should_receive(:new).with('other.domain.tld', 98765, {}).and_return(host_socket)
49
+
50
+ @uri.create_socket.should equal(socket)
51
+ @uri_host.create_socket.should equal(host_socket)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Stomper do
5
+ it "should define a version" do
6
+ Stomper.const_defined?(:VERSION).should be_true
7
+ Stomper::VERSION.should == '2.0.0'
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module RSpec
3
+ module Mocks
4
+ module ArgumentMatchers
5
+ def stomper_frame_with_headers(*args)
6
+ command = args.last.is_a?(String) ? args.pop : nil
7
+ StomperFrameMatcher.new(command, nil, anythingize_lonely_keys(*args))
8
+ end
9
+
10
+ def stomper_frame_with_body(body, command=nil)
11
+ StomperFrameMatcher.new(command, body, nil)
12
+ end
13
+
14
+ def stomper_frame(body, *args)
15
+ command = args.last.is_a?(String) ? args.pop : nil
16
+ StomperFrameMatcher.new(command, body, anythingize_lonely_keys(*args))
17
+ end
18
+
19
+ def stomper_heartbeat_frame
20
+ StomperFrameMatcher.new(nil, nil, {})
21
+ end
22
+
23
+ class StomperFrameMatcher
24
+ def initialize(e_command, e_body, e_headers)
25
+ @expected_command = e_command && e_command.upcase
26
+ @expected_body = e_body
27
+ @expected_headers = e_headers
28
+ end
29
+
30
+ def ==(actual)
31
+ if @expected_command
32
+ return false unless @expected_command == actual.command
33
+ end
34
+ if @expected_body
35
+ return false unless @expected_body == actual.body
36
+ end
37
+ if @expected_headers
38
+ @expected_headers.each do |key, val|
39
+ return false unless actual[key] == val.to_s
40
+ end
41
+ end
42
+ true
43
+ rescue NoMethodError => ex
44
+ return false
45
+ end
46
+
47
+ def description
48
+ frame_name = @expected_command || 'Any frame'
49
+ with_headers = @expected_headers ? "with headers (#{@expected_headers.inspect.sub(/^\{/,"").sub(/\}$/,"")})" : nil
50
+ with_body = @expected_body ? "with body (#{@expected_body})" : nil
51
+ additional_desc = [with_headers, with_body].compact.join(' and ')
52
+ "#{frame_name} #{additional_desc}"
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Spec::Matchers.define :be_a_registered_server_frame do
3
+ # match do |actual|
4
+ # command_name = actual.name.split('::').last.upcase
5
+ # frame = Stomp::Frames::ServerFrame.build(command_name, { :a_header => 'test' }, 'body')
6
+ # frame.should be_an_instance_of(actual)
7
+ # frame.command.should == command_name
8
+ # frame.headers[:a_header].should == 'test'
9
+ # frame.body.should == 'test body'
10
+ # end
11
+ # end
12
+ #
13
+ # Spec::Matchers.define :be_able_to_access_header_values_like_a_hash do
14
+ # match do |actual|
15
+ # frame = actual.new( { :header_1 => 1, :header_2 => 'test' })
16
+ # frame[:header_1].should == 1
17
+ # frame[:header_2].should == 'test'
18
+ # end
19
+ # end
@@ -0,0 +1,10 @@
1
+ # -*- encoding: utf-8 -*-
2
+ RSpec::Matchers.define :have_header do |header_name, expected|
3
+ match do |actual|
4
+ actual[header_name.to_sym] == expected
5
+ end
6
+ end
7
+
8
+ RSpec::Matchers.define :have_transaction_header do |expected|
9
+ have_frame_header :transaction, expected
10
+ end