pivotal-moqueue 0.1.0.200907241602

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.
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/example_helper'
3
+
4
+ describe Moqueue, "when testing the ping pong example" do
5
+ include ExampleHelper
6
+
7
+ def ping_pong
8
+ AMQP.start(:host => 'localhost') do
9
+
10
+ # AMQP.logging = true
11
+
12
+ amq = MQ.new
13
+ EM.add_periodic_timer(0.1){
14
+ @counter_val = counter
15
+ capture_output @counter_val, :sending, 'ping'
16
+ amq.queue('one').publish('ping')
17
+ }
18
+
19
+ amq = MQ.new
20
+ amq.queue('one').subscribe{ |msg|
21
+ capture_output @counter_val, 'one', :received, msg, :sending, 'pong'
22
+ amq.queue('two').publish('pong')
23
+ }
24
+
25
+ amq = MQ.new
26
+ amq.queue('two').subscribe{ |msg|
27
+ capture_output @counter_val, 'two', :received, msg
28
+ }
29
+
30
+ end
31
+
32
+ end
33
+
34
+ before(:all) do
35
+ overload_amqp
36
+ end
37
+
38
+ before(:each) do
39
+ reset!
40
+ end
41
+
42
+ it "should get the correct result without error" do
43
+ Timeout::timeout(5) do
44
+ ping_pong
45
+ end
46
+ expected = [[1, :sending, "ping"], [1, "one", :received, "ping", :sending, "pong"], [1, "two", :received, "pong"],
47
+ [2, :sending, "ping"], [2, "one", :received, "ping", :sending, "pong"], [2, "two", :received, "pong"]]
48
+ @captured_output.should == expected
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/example_helper'
3
+
4
+ describe Moqueue, "when running the stocks example" do
5
+ include ExampleHelper
6
+
7
+ def run_stocks
8
+ AMQP.start(:host => 'localhost') do
9
+
10
+ def log *args
11
+ #p [ Time.now, *args ]
12
+ end
13
+
14
+ def publish_stock_prices
15
+ mq = MQ.new
16
+ counter = 0
17
+ EM.add_periodic_timer(0.1){
18
+ counter += 1
19
+ EM.stop if counter > 5
20
+
21
+ {:appl => 170+rand(1000)/100.0, :msft => 22+rand(500)/100.0}.each do |stock, price|
22
+ stock = "usd.#{stock}"
23
+
24
+ log :publishing, stock, price
25
+ mq.topic('stocks').publish(price, :key => stock)
26
+ end
27
+ }
28
+ end
29
+
30
+ def watch_appl_stock
31
+ mq = MQ.new
32
+ @apple_queue = mq.queue('apple stock')
33
+ @apple_queue.bind(mq.topic('stocks'), :key => 'usd.appl').subscribe{ |price|
34
+ log 'apple stock', price
35
+ }
36
+ end
37
+
38
+ def watch_us_stocks
39
+ mq = MQ.new
40
+ @us_stocks = mq.queue('us stocks')
41
+ @us_stocks.bind(mq.topic('stocks'), :key => 'usd.*').subscribe{ |info, price|
42
+ log 'us stock', info.routing_key, price
43
+ }
44
+ end
45
+
46
+ publish_stock_prices
47
+ watch_appl_stock
48
+ watch_us_stocks
49
+
50
+ end
51
+ end
52
+
53
+ before(:each) do
54
+ overload_amqp
55
+ reset_broker
56
+ end
57
+
58
+ it "should get the correct results" do
59
+ run_stocks
60
+ @us_stocks.should have(12).received_messages
61
+ @apple_queue.should have(6).received_messages
62
+ end
63
+
64
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ -c -f specdoc
@@ -0,0 +1,21 @@
1
+ require "rubygems"
2
+ require "spec"
3
+
4
+ Spec::Runner.configure do |config|
5
+ config.mock_with :mocha
6
+ end
7
+
8
+ require File.dirname(__FILE__) + "/../lib/moqueue"
9
+
10
+ # Make sure tests fail if deferred blocks (for susbscribe and pop) don't get called
11
+ def ensure_deferred_block_called(opts={:times=>1})
12
+ @poke_me = mock("poke_me")
13
+ @poke_me.expects(:deferred_block_called).times(opts[:times])
14
+ end
15
+
16
+ def deferred_block_called
17
+ @poke_me.deferred_block_called
18
+ true
19
+ end
20
+
21
+ include Moqueue
@@ -0,0 +1,92 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Matchers do
4
+ class MatcherHarness
5
+ include Moqueue::Matchers
6
+ end
7
+
8
+ before(:each) do
9
+ @matchable = MatcherHarness.new
10
+ @mock_moqueue = mock("mock Moqueue::MockQueue")
11
+ @failure_exception = Spec::Expectations::ExpectationNotMetError
12
+ end
13
+
14
+ it "should include matchers in describe blocks automatically when using rspec" do
15
+ self.class.include?(Moqueue::Matchers).should be_true
16
+ end
17
+
18
+ it "should implement Object#should have_received_message" do
19
+ @mock_moqueue.expects(:received_message?).with("matchtacular").returns(true)
20
+ @mock_moqueue.should have_received_message("matchtacular")
21
+ end
22
+
23
+ it "should implement Object#should_not have_received_message" do
24
+ @mock_moqueue.expects(:received_message?).with("no match").returns(false)
25
+ @mock_moqueue.should_not have_received_message("no match")
26
+ end
27
+
28
+ it "should have a useful failure message" do
29
+ @mock_moqueue.expects(:received_message?).with("this fails").returns(false)
30
+ failing_example = lambda {@mock_moqueue.should have_received_message("this fails")}
31
+ error_message = "expected #{@mock_moqueue.inspect} to have received message ``this fails''"
32
+ failing_example.should raise_error(@failure_exception, error_message)
33
+ end
34
+
35
+ it "should have a useful negative failure message" do
36
+ @mock_moqueue.expects(:received_message?).with("FAIL").returns(true)
37
+ failing_example = lambda{@mock_moqueue.should_not have_received_message("FAIL")}
38
+ error_message = "expected #{@mock_moqueue.inspect} to not have received message ``FAIL''"
39
+ failing_example.should raise_error(@failure_exception, error_message)
40
+ end
41
+
42
+ it "should fail gracefully if object being tested for #have_received doesn't respond to #received_message?" do
43
+ begin
44
+ Object.new.should have_received_message("foo")
45
+ rescue => e
46
+ end
47
+ e.should be_a NoMethodError
48
+ e.message.should match /you can't use \`\`should have_received_message\'\' on #\<Object/
49
+ end
50
+
51
+ it "should alias #have_received_message as #have_received for less verbosity" do
52
+ @matchable.should respond_to(:have_received)
53
+ end
54
+
55
+ it "should alias #have_received_ack_for as #have_ack_for for less verbosity" do
56
+ @matchable.should respond_to(:have_ack_for)
57
+ end
58
+
59
+ it "should implement Object#should have_received_ack_for(msg_text)" do
60
+ @mock_moqueue.expects(:received_ack_for_message?).with("foo bar").returns(true)
61
+ @mock_moqueue.should have_received_ack_for("foo bar")
62
+ end
63
+
64
+ it "should implement Object#should_not have_received_ack_for(msg_text)" do
65
+ @mock_moqueue.expects(:received_ack_for_message?).with("bar baz").returns(false)
66
+ @mock_moqueue.should_not have_received_ack_for("bar baz")
67
+ end
68
+
69
+ it "should have a helpful failure message" do
70
+ @mock_moqueue.expects(:received_ack_for_message?).with("foo baz").returns(false)
71
+ failure = lambda {@mock_moqueue.should have_received_ack_for("foo baz")}
72
+ fail_msg = "expected #{@mock_moqueue.inspect} to have received an ack for the message ``foo baz''"
73
+ failure.should raise_error(@failure_exception, fail_msg)
74
+ end
75
+
76
+ it "should have a helpful negative failure message" do
77
+ @mock_moqueue.expects(:received_ack_for_message?).with("bar foo").returns(true)
78
+ failure = lambda {@mock_moqueue.should_not have_received_ack_for("bar foo")}
79
+ fail_msg = "expected #{@mock_moqueue.inspect} to not have received an ack for the message ``bar foo''"
80
+ failure.should raise_error(@failure_exception, fail_msg)
81
+ end
82
+
83
+ it "should fail gracefully if object being tested for #have_received_ack_for doesn't respond to #received_ack_for_message?" do
84
+ begin
85
+ Object.new.should have_received_message("foo")
86
+ rescue => e
87
+ end
88
+ e.should be_a NoMethodError
89
+ e.message.should match /you can't use \`\`should have_received_message\'\' on #\<Object/
90
+ end
91
+
92
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe MockBroker do
4
+
5
+ before(:each) do
6
+ @broker = MockBroker.instance
7
+ @broker.reset!
8
+ end
9
+
10
+ it "should keep a list of named queues" do
11
+ queue = MockQueue.new("one-mocked-queue")
12
+ @broker.register_queue(queue)
13
+ @broker.find_queue("one-mocked-queue").should == queue
14
+ end
15
+
16
+ it "should reset itself" do
17
+ @broker.register_queue(MockQueue.new("throwaway"))
18
+ @broker.reset!
19
+ @broker.registered_queues.count.should == 0
20
+ end
21
+
22
+ it "should keep a list of topic exchanges" do
23
+ exchange = MockExchange.new(:topic => "lolcats")
24
+ @broker.register_topic_exchange(exchange)
25
+ @broker.find_topic_exchange("lolcats").should equal(exchange)
26
+ end
27
+
28
+ it "should keep a list of fanout queues" do
29
+ exchange = MockExchange.new(:fanout => "joinTheNaniteBorg")
30
+ @broker.register_fanout_exchange(exchange)
31
+ @broker.find_fanout_exchange("joinTheNaniteBorg").should equal(exchange)
32
+ end
33
+
34
+ end
@@ -0,0 +1,102 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe MockExchange do
4
+
5
+ before(:each) do
6
+ reset_broker
7
+ @queue, @exchange = mock_queue_and_exchange
8
+ end
9
+
10
+ it "should manually attach queues" do
11
+ ensure_deferred_block_called(:times => 2)
12
+ exchange = mock_exchange
13
+ one_queue, another_queue = mock_queue("one"), mock_queue("two")
14
+ exchange.attach_queue(one_queue)
15
+ exchange.attach_queue(another_queue)
16
+ one_queue.subscribe do |msg|
17
+ deferred_block_called && msg.should == "mmm, smoothies"
18
+ end
19
+ another_queue.subscribe do |msg|
20
+ deferred_block_called && msg.should == "mmm, smoothies"
21
+ end
22
+ exchange.publish("mmm, smoothies")
23
+ end
24
+
25
+ it "should accept options for the publish method" do
26
+ lambda {@exchange.publish("whateva eva", :key=>"foo.bar")}.should_not raise_error(ArgumentError)
27
+ end
28
+
29
+ it "should emulate topic exchanges" do
30
+ #pending "support for storing and retrieving topic exchanges in MockBroker"
31
+ topic_exchange = MockExchange.new(:topic => "lolcats")
32
+ topic_exchange.topic.should == "lolcats"
33
+ end
34
+
35
+ it "should register new topic exchanges with the mock broker" do
36
+ MockBroker.instance.expects(:register_topic_exchange)
37
+ MockExchange.new(:topic => "lolz")
38
+ end
39
+
40
+ it "should return a previously created topic exchange when asked to create a new one with the same topic" do
41
+ exchange = MockExchange.new(:topic => "fails")
42
+ MockExchange.new(:topic => "fails").should equal exchange
43
+ end
44
+
45
+ it "should determine if routing keys match" do
46
+ exchange = MockExchange.new(:topic => "lolz")
47
+ key = MockExchange::BindingKey
48
+ key.new("cats").matches?("cats").should be_true
49
+ key.new("cats").matches?("cats").should be_true
50
+ key.new("cats").matches?("dogs").should be_false
51
+ key.new("cats.*").matches?("cats.fridge").should be_true
52
+ key.new("cats.evil").matches?("cats.fridge").should be_false
53
+ key.new("cats.*").matches?("cats.fridge.in_urs").should be_false
54
+ key.new("cats.#").matches?("cats.fridge.in_urs").should be_true
55
+ end
56
+
57
+ it "should forward messages to a queue only if the keys match when emulating a topic exchange" do
58
+ ensure_deferred_block_called
59
+ exchange = MockExchange.new(:topic => "lolz")
60
+ queue = MockQueue.new("lolz-lover")
61
+ queue.bind(exchange, :key=>"cats.*").subscribe do |msg|
62
+ msg.should == "ohai"
63
+ deferred_block_called
64
+ end
65
+ exchange.publish("ohai", :key => "cats.attack")
66
+ end
67
+
68
+ it "should add the routing key to the headers' properties when publishing as a topic exchange" do
69
+ ensure_deferred_block_called
70
+ exchange = MockExchange.new(:topic => "mehDogs")
71
+ queue = MockQueue.new("dogzLover").bind(exchange, :key=>"boxers.*")
72
+ queue.subscribe do |headers, msg|
73
+ deferred_block_called
74
+ headers.routing_key.should == "boxers.awesome"
75
+ msg.should == "Roxie"
76
+ end
77
+ exchange.publish("Roxie", :key=>"boxers.awesome")
78
+ end
79
+
80
+ it "should raise an error when publishing to a topic exchange without specifying a key" do
81
+ exchange = MockExchange.new(:topic=>"failz")
82
+ fail_msg = "you must provide a key when publishing to a topic exchange"
83
+ lambda {exchange.publish("failtacular")}.should raise_error(ArgumentError, fail_msg)
84
+ end
85
+
86
+ it "should allow the fanout exchange name to be queried" do
87
+ exchange = MockExchange.new(:fanout => "hiMyNameIs")
88
+ exchange.fanout.should == "hiMyNameIs"
89
+ end
90
+
91
+ it "should register new fanout exchanges with the MockBroker" do
92
+ MockBroker.instance.expects(:register_fanout_exchange)
93
+ MockExchange.new(:fanout => "nanite friendly")
94
+ end
95
+
96
+ it "should return the exact same fanout exchange if creating one with an identical name" do
97
+ the_first_fanout = MockExchange.new(:fanout => "pseudo singleton")
98
+ the_second_one = MockExchange.new(:fanout => "pseudo singleton")
99
+ the_first_fanout.should equal the_second_one
100
+ end
101
+
102
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe MockHeaders do
4
+
5
+ it "should respond to the same methods as real AMQP::Protocol::Header" do
6
+ headers = Moqueue::MockHeaders.new
7
+ headers.should respond_to(:size)
8
+ headers.should respond_to(:weight)
9
+ headers.should respond_to(:properties)
10
+ headers.should respond_to(:to_frame)
11
+ end
12
+
13
+ it "should add properties given to constructor" do
14
+ headers = MockHeaders.new({:routing_key=>"lolz.cats.inKitchen"})
15
+ end
16
+
17
+ it "should lookup unknown methods as keys in the hash" do
18
+ headers = MockHeaders.new(:wtf_ftw_lolz_yo => "did I really write that?")
19
+ headers.wtf_ftw_lolz_yo.should == "did I really write that?"
20
+ end
21
+
22
+ end
@@ -0,0 +1,141 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe MockQueue do
4
+
5
+ before(:each) do
6
+ reset_broker
7
+ @queue, @exchange = mock_queue_and_exchange
8
+ end
9
+
10
+ it "should accept options for :ack=>(true|false) :nowait=>(true|false)" do
11
+ lambda {@queue.subscribe(:ack=>true) { |message| p message}}.should_not raise_error(ArgumentError)
12
+ end
13
+
14
+ it "should pass mock headers to block when subscribe is given a block w/ 2 arity" do
15
+ ensure_deferred_block_called
16
+ @queue.subscribe do |headers, msg|
17
+ headers.should be_kind_of(Moqueue::MockHeaders)
18
+ msg.should == "the message"
19
+ deferred_block_called
20
+ end
21
+ @exchange.publish("the message")
22
+ end
23
+
24
+ it "should create mock headers if pop is given a block w/ 2 arity" do
25
+ pending
26
+ end
27
+
28
+ it "should process pending messages after a handler block is defined" do
29
+ ensure_deferred_block_called
30
+ @exchange.publish("found!")
31
+ @queue.subscribe { |msg| deferred_block_called && msg.should == "found!" }
32
+ end
33
+
34
+ it "should not process pending messages twice" do
35
+ ensure_deferred_block_called(:times=>2)
36
+ @exchange.publish("take out the garbage")
37
+ @queue.subscribe do |msg|
38
+ deferred_block_called
39
+ msg.should match(/take out (.*) garbage/)
40
+ end
41
+ @exchange.publish("take out more garbage")
42
+ end
43
+
44
+ it "should not ack messages when given or defaulting to :ack=>false" do
45
+ ensure_deferred_block_called
46
+ @queue.subscribe { |msg| deferred_block_called && msg.should == "hew-row" }
47
+ @exchange.publish("hew-row")
48
+ @exchange.received_ack_for_message?("hew-row").should_not be_true
49
+ end
50
+
51
+ it "should not ack messages when given :ack => true, but headers don't receive #ack" do
52
+ ensure_deferred_block_called
53
+ @queue.subscribe(:ack=>true) do |headers, msg|
54
+ deferred_block_called
55
+ msg.should == "10-4"
56
+ end
57
+ @exchange.publish("10-4")
58
+ @exchange.received_ack_for_message?("10-4").should be_false
59
+ end
60
+
61
+ it "should ack messages when subscribe is given :ack=>true and headers are acked" do
62
+ @queue.subscribe(:ack=>true) do |headers, msg|
63
+ msg.should == "10-4"
64
+ headers.ack
65
+ end
66
+ @exchange.publish("10-4")
67
+ @exchange.received_ack_for_message?("10-4").should be_true
68
+ end
69
+
70
+ it "should provide ability to check for acks when direct exchange is used" do
71
+ queue = MockQueue.new("direct-ack-check")
72
+ queue.subscribe(:ack => true) do |headers, msg|
73
+ msg.should == "ack me"
74
+ headers.ack
75
+ end
76
+ queue.publish("ack me")
77
+ queue.received_ack_for_message?("ack me").should be_true
78
+ end
79
+
80
+ it "should store received messages in the queues" do
81
+ @queue.subscribe { |msg| msg.should == "save me!" }
82
+ @exchange.publish("save me!")
83
+ @queue.received_message?("save me!").should be_true
84
+ end
85
+
86
+ it "should #unsubscribe" do
87
+ pending ("should really remove the association with exchange")
88
+ @queue.should respond_to(:unsubscribe)
89
+ end
90
+
91
+ it "should raise an error on double subscribe" do
92
+ @queue.subscribe { |msg| "once" }
93
+ second_subscribe = lambda { @queue.subscribe {|msg| "twice"} }
94
+ second_subscribe.should raise_error DoubleSubscribeError
95
+ end
96
+
97
+ it "should emulate direct exchange publishing" do
98
+ ensure_deferred_block_called
99
+ @queue.subscribe { |msg|deferred_block_called && msg.should == "Dyrekt" }
100
+ @queue.publish("Dyrekt")
101
+ end
102
+
103
+ it "should take an optional name argument" do
104
+ lambda { MockQueue.new("say-my-name") }.should_not raise_error
105
+ end
106
+
107
+ it "should register itself with the mock broker if given a name" do
108
+ MockBroker.instance.expects(:register_queue)
109
+ queue = MockQueue.new("with-a-name")
110
+ end
111
+
112
+ it "should return the previously created queue when trying to create a queue with the same name" do
113
+ queue = MockQueue.new("firsties")
114
+ MockQueue.new("firsties").should equal(queue)
115
+ end
116
+
117
+ it "should support binding to a topic exchange" do
118
+ queue = MockQueue.new("lolz lover")
119
+ topic_exchange = MockExchange.new(:topic => "lolcats")
120
+ topic_exchange.expects(:attach_queue).with(queue, :key=>"lolcats.fridges")
121
+ queue.bind(topic_exchange, :key => "lolcats.fridges") #http://lolcatz.net/784/im-in-ur-fridge-eatin-ur-foodz/
122
+ end
123
+
124
+ it "should make the callback (#subscribe block) available for direct use" do
125
+ queue = MockQueue.new("inspect my guts, plz")
126
+ queue.subscribe { |msg| msg + "yo" }
127
+ queue.run_callback("hey-").should == "hey-yo"
128
+ end
129
+
130
+ it "should bind to a fanout exchange" do
131
+ queue = MockQueue.new("fanouts are cool, too")
132
+ lambda {queue.bind(MockExchange.new)}.should_not raise_error
133
+ end
134
+
135
+ it "should provide a null subscribe that does nothing but allows messages to be received" do
136
+ queue = MockQueue.new("nilly").null_subscribe
137
+ queue.publish("I'm feelin this")
138
+ queue.received_message?("I'm feelin this").should be_true
139
+ end
140
+
141
+ end