pivotal-moqueue 0.1.0.200907241602
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +57 -0
- data/Rakefile +25 -0
- data/VERSION.yml +4 -0
- data/lib/moqueue.rb +15 -0
- data/lib/moqueue/fibers18.rb +57 -0
- data/lib/moqueue/matchers.rb +74 -0
- data/lib/moqueue/mock_broker.rb +44 -0
- data/lib/moqueue/mock_exchange.rb +114 -0
- data/lib/moqueue/mock_headers.rb +31 -0
- data/lib/moqueue/mock_queue.rb +126 -0
- data/lib/moqueue/object_methods.rb +31 -0
- data/lib/moqueue/overloads.rb +46 -0
- data/moqueue.gemspec +29 -0
- data/spec/examples/ack_spec.rb +60 -0
- data/spec/examples/basic_usage_spec.rb +101 -0
- data/spec/examples/example_helper.rb +16 -0
- data/spec/examples/logger_spec.rb +159 -0
- data/spec/examples/ping_pong_spec.rb +50 -0
- data/spec/examples/stocks_spec.rb +64 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/unit/matchers_spec.rb +92 -0
- data/spec/unit/mock_broker_spec.rb +34 -0
- data/spec/unit/mock_exchange_spec.rb +102 -0
- data/spec/unit/mock_headers_spec.rb +22 -0
- data/spec/unit/mock_queue_spec.rb +141 -0
- data/spec/unit/moqueue_spec.rb +9 -0
- data/spec/unit/object_methods_spec.rb +49 -0
- data/spec/unit/overloads_spec.rb +48 -0
- metadata +87 -0
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|