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.
- 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
|