stomper 1.0.0 → 2.0.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 (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