moqueue 0.1.4

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,40 @@
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.size.should == 0
20
+ end
21
+
22
+ it "should keep a list of direct exchanges" do
23
+ exchange = MockExchange.new(:direct => "thundercats")
24
+ @broker.register_direct_exchange(exchange)
25
+ @broker.find_direct_exchange("thundercats").should equal(exchange)
26
+ end
27
+
28
+ it "should keep a list of topic exchanges" do
29
+ exchange = MockExchange.new(:topic => "lolcats")
30
+ @broker.register_topic_exchange(exchange)
31
+ @broker.find_topic_exchange("lolcats").should equal(exchange)
32
+ end
33
+
34
+ it "should keep a list of fanout queues" do
35
+ exchange = MockExchange.new(:fanout => "joinTheNaniteBorg")
36
+ @broker.register_fanout_exchange(exchange)
37
+ @broker.find_fanout_exchange("joinTheNaniteBorg").should equal(exchange)
38
+ end
39
+
40
+ end
@@ -0,0 +1,168 @@
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 direct exchanges" do
30
+ direct_exchange = MockExchange.new(:direct => "thundercats")
31
+ direct_exchange.direct.should == "thundercats"
32
+ end
33
+
34
+ it "should register new direct exchanges with the mock broker" do
35
+ MockBroker.instance.expects(:register_direct_exchange)
36
+ MockExchange.new(:direct => "lolz")
37
+ end
38
+
39
+ it "should return a previously created direct exchange when asked to create a new one with the same name" do
40
+ exchange = MockExchange.new(:direct => "smoochie")
41
+ MockExchange.new(:direct => "smoochie").should equal(exchange)
42
+ end
43
+
44
+ it "should determine if routing keys match exactly on the direct exchange" do
45
+ exchange = MockExchange.new(:direct => "lolz")
46
+ key = MockExchange::DirectBindingKey
47
+ key.new("cats").matches?("cats").should be_true
48
+ key.new("cats").matches?("dogs").should be_false
49
+ key.new("cats.*").matches?("cats.fridge").should be_false
50
+ key.new("cats.evil").matches?("cats.fridge").should be_false
51
+ key.new("cats.*").matches?("cats.fridge.in_urs").should be_false
52
+ key.new("cats.#").matches?("cats.fridge.in_urs").should be_false
53
+ end
54
+
55
+ it "should forward messages to a queue only if the keys match exactly when emulating a direct exchange" do
56
+ ensure_deferred_block_called
57
+ exchange = MockExchange.new(:direct => "thundercats")
58
+ queue = MockQueue.new("ho")
59
+ queue.bind(exchange, :key=>"cats").subscribe do |msg|
60
+ msg.should == "ohai"
61
+ deferred_block_called
62
+ end
63
+ exchange.publish("ohai", :key => "cats")
64
+ end
65
+
66
+ it "should NOT forward messages to a queue if the keys mismatch when emulating a direct exchange" do
67
+ ensure_deferred_block_skipped
68
+ exchange = MockExchange.new(:direct => "thundercats")
69
+ queue = MockQueue.new("ho")
70
+ queue.bind(exchange, :key=>"cats").subscribe do |msg|
71
+ msg.should == "ohai"
72
+ deferred_block_called # should never execute!
73
+ end
74
+ exchange.publish("ohai", :key => "cats.attack")
75
+ end
76
+
77
+ it "should add the routing key to the headers' properties when publishing as a direct exchange" do
78
+ ensure_deferred_block_called
79
+ exchange = MockExchange.new(:direct => "thunderdogs")
80
+ queue = MockQueue.new("dogzh8er").bind(exchange, :key=>"boxers")
81
+ queue.subscribe do |headers, msg|
82
+ deferred_block_called
83
+ headers.routing_key.should == "boxers"
84
+ msg.should == "Roxie"
85
+ end
86
+ exchange.publish("Roxie", :key=>"boxers")
87
+ end
88
+
89
+ it "should NOT raise an error when publishing to a direct exchange without specifying a key" do
90
+ exchange = MockExchange.new(:direct => "spike")
91
+ fail_msg = "you must provide a key when publishing to a topic exchange"
92
+ lambda {exchange.publish("failtacular")}.should_not raise_error(ArgumentError, fail_msg)
93
+ end
94
+
95
+ it "should emulate topic exchanges" do
96
+ #pending "support for storing and retrieving topic exchanges in MockBroker"
97
+ topic_exchange = MockExchange.new(:topic => "lolcats")
98
+ topic_exchange.topic.should == "lolcats"
99
+ end
100
+
101
+ it "should register new topic exchanges with the mock broker" do
102
+ MockBroker.instance.expects(:register_topic_exchange)
103
+ MockExchange.new(:topic => "lolz")
104
+ end
105
+
106
+ it "should return a previously created topic exchange when asked to create a new one with the same topic" do
107
+ exchange = MockExchange.new(:topic => "fails")
108
+ MockExchange.new(:topic => "fails").should equal(exchange)
109
+ end
110
+
111
+ it "should determine if routing keys match" do
112
+ exchange = MockExchange.new(:topic => "lolz")
113
+ key = MockExchange::TopicBindingKey
114
+ key.new("cats").matches?("cats").should be_true
115
+ key.new("cats").matches?("cats").should be_true
116
+ key.new("cats").matches?("dogs").should be_false
117
+ key.new("cats.*").matches?("cats.fridge").should be_true
118
+ key.new("cats.evil").matches?("cats.fridge").should be_false
119
+ key.new("cats.*").matches?("cats.fridge.in_urs").should be_false
120
+ key.new("cats.#").matches?("cats.fridge.in_urs").should be_true
121
+ end
122
+
123
+ it "should forward messages to a queue only if the keys match when emulating a topic exchange" do
124
+ ensure_deferred_block_called
125
+ exchange = MockExchange.new(:topic => "lolz")
126
+ queue = MockQueue.new("lolz-lover")
127
+ queue.bind(exchange, :key=>"cats.*").subscribe do |msg|
128
+ msg.should == "ohai"
129
+ deferred_block_called
130
+ end
131
+ exchange.publish("ohai", :key => "cats.attack")
132
+ end
133
+
134
+ it "should add the routing key to the headers' properties when publishing as a topic exchange" do
135
+ ensure_deferred_block_called
136
+ exchange = MockExchange.new(:topic => "mehDogs")
137
+ queue = MockQueue.new("dogzLover").bind(exchange, :key=>"boxers.*")
138
+ queue.subscribe do |headers, msg|
139
+ deferred_block_called
140
+ headers.routing_key.should == "boxers.awesome"
141
+ msg.should == "Roxie"
142
+ end
143
+ exchange.publish("Roxie", :key=>"boxers.awesome")
144
+ end
145
+
146
+ it "should raise an error when publishing to a topic exchange without specifying a key" do
147
+ exchange = MockExchange.new(:topic=>"failz")
148
+ fail_msg = "you must provide a key when publishing to a topic exchange"
149
+ lambda {exchange.publish("failtacular")}.should raise_error(ArgumentError, fail_msg)
150
+ end
151
+
152
+ it "should allow the fanout exchange name to be queried" do
153
+ exchange = MockExchange.new(:fanout => "hiMyNameIs")
154
+ exchange.fanout.should == "hiMyNameIs"
155
+ end
156
+
157
+ it "should register new fanout exchanges with the MockBroker" do
158
+ MockBroker.instance.expects(:register_fanout_exchange)
159
+ MockExchange.new(:fanout => "nanite friendly")
160
+ end
161
+
162
+ it "should return the exact same fanout exchange if creating one with an identical name" do
163
+ the_first_fanout = MockExchange.new(:fanout => "pseudo singleton")
164
+ the_second_one = MockExchange.new(:fanout => "pseudo singleton")
165
+ the_first_fanout.should equal(the_second_one)
166
+ end
167
+
168
+ 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,151 @@
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 allow retrieval of the headers for any published messages" do
25
+ @queue.subscribe { |msg| msg }
26
+ @exchange.publish("the message")
27
+ @queue.received_headers.first.should be_kind_of(Moqueue::MockHeaders)
28
+ end
29
+
30
+ it "should create mock headers if pop is given a block w/ 2 arity" do
31
+ pending
32
+ end
33
+
34
+ it "should process pending messages after a handler block is defined" do
35
+ ensure_deferred_block_called
36
+ @exchange.publish("found!")
37
+ @queue.subscribe { |msg| deferred_block_called && msg.should == "found!" }
38
+ end
39
+
40
+ it "should not process pending messages twice" do
41
+ ensure_deferred_block_called(:times=>2)
42
+ @exchange.publish("take out the garbage")
43
+ @queue.subscribe do |msg|
44
+ deferred_block_called
45
+ msg.should match(/take out (.*) garbage/)
46
+ end
47
+ @exchange.publish("take out more garbage")
48
+ end
49
+
50
+ it "should not ack messages when given or defaulting to :ack=>false" do
51
+ ensure_deferred_block_called
52
+ @queue.subscribe { |msg| deferred_block_called && msg.should == "hew-row" }
53
+ @exchange.publish("hew-row")
54
+ @exchange.received_ack_for_message?("hew-row").should_not be_true
55
+ end
56
+
57
+ it "should not ack messages when given :ack => true, but headers don't receive #ack" do
58
+ ensure_deferred_block_called
59
+ @queue.subscribe(:ack=>true) do |headers, msg|
60
+ deferred_block_called
61
+ msg.should == "10-4"
62
+ end
63
+ @exchange.publish("10-4")
64
+ @exchange.received_ack_for_message?("10-4").should be_false
65
+ end
66
+
67
+ it "should ack messages when subscribe is given :ack=>true and headers are acked" do
68
+ @queue.subscribe(:ack=>true) do |headers, msg|
69
+ msg.should == "10-4"
70
+ headers.ack
71
+ end
72
+ @exchange.publish("10-4")
73
+ @exchange.received_ack_for_message?("10-4").should be_true
74
+ end
75
+
76
+ it "should provide ability to check for acks when direct exchange is used" do
77
+ queue = MockQueue.new("direct-ack-check")
78
+ queue.subscribe(:ack => true) do |headers, msg|
79
+ msg.should == "ack me"
80
+ headers.ack
81
+ end
82
+ queue.publish("ack me")
83
+ queue.received_ack_for_message?("ack me").should be_true
84
+ end
85
+
86
+ it "should store received messages in the queues" do
87
+ @queue.subscribe { |msg| msg.should == "save me!" }
88
+ @exchange.publish("save me!")
89
+ @queue.received_message?("save me!").should be_true
90
+ end
91
+
92
+ it "should #unsubscribe" do
93
+ pending("should really remove the association with exchange")
94
+ @queue.should respond_to(:unsubscribe)
95
+ end
96
+
97
+ it "should ignore #prefetch but at least raise an error" do
98
+ lambda { @queue.prefetch(1337) }.should_not raise_error
99
+ end
100
+
101
+ it "should raise an error on double subscribe" do
102
+ @queue.subscribe { |msg| "once" }
103
+ second_subscribe = lambda { @queue.subscribe {|msg| "twice"} }
104
+ second_subscribe.should raise_error(DoubleSubscribeError)
105
+ end
106
+
107
+ it "should emulate direct exchange publishing" do
108
+ ensure_deferred_block_called
109
+ @queue.subscribe { |msg|deferred_block_called && msg.should == "Dyrekt" }
110
+ @queue.publish("Dyrekt")
111
+ end
112
+
113
+ it "should take an optional name argument" do
114
+ lambda { MockQueue.new("say-my-name") }.should_not raise_error
115
+ end
116
+
117
+ it "should register itself with the mock broker if given a name" do
118
+ MockBroker.instance.expects(:register_queue)
119
+ queue = MockQueue.new("with-a-name")
120
+ end
121
+
122
+ it "should return the previously created queue when trying to create a queue with the same name" do
123
+ queue = MockQueue.new("firsties")
124
+ MockQueue.new("firsties").should equal(queue)
125
+ end
126
+
127
+ it "should support binding to a topic exchange" do
128
+ queue = MockQueue.new("lolz lover")
129
+ topic_exchange = MockExchange.new(:topic => "lolcats")
130
+ topic_exchange.expects(:attach_queue).with(queue, :key=>"lolcats.fridges")
131
+ queue.bind(topic_exchange, :key => "lolcats.fridges") #http://lolcatz.net/784/im-in-ur-fridge-eatin-ur-foodz/
132
+ end
133
+
134
+ it "should make the callback (#subscribe block) available for direct use" do
135
+ queue = MockQueue.new("inspect my guts, plz")
136
+ queue.subscribe { |msg| msg + "yo" }
137
+ queue.run_callback("hey-").should == "hey-yo"
138
+ end
139
+
140
+ it "should bind to a fanout exchange" do
141
+ queue = MockQueue.new("fanouts are cool, too")
142
+ lambda {queue.bind(MockExchange.new)}.should_not raise_error
143
+ end
144
+
145
+ it "should provide a null subscribe that does nothing but allows messages to be received" do
146
+ queue = MockQueue.new("nilly").null_subscribe
147
+ queue.publish("I'm feelin this")
148
+ queue.received_message?("I'm feelin this").should be_true
149
+ end
150
+
151
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Moqueue do
4
+
5
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ObjectMethods do
4
+
5
+ before(:each) do
6
+ reset_broker
7
+ @queue, @exchange = mock_queue_and_exchange
8
+ end
9
+
10
+ it "should reset the MockBroker" do
11
+ MockBroker.instance.expects(:reset!)
12
+ reset_broker
13
+ end
14
+
15
+ it "should name the queue ``anonymous-RANDOM_GARBAGE'' if not given a name" do
16
+ @queue.name.should match(/anonymous\-[0-9a-f]{0,8}/)
17
+ end
18
+
19
+ it "should name the queue with the name given" do
20
+ q, exchange = mock_queue_and_exchange("wassup")
21
+ q.name.should == "wassup"
22
+ q2 = mock_queue("watup")
23
+ q2.name.should == "watup"
24
+ end
25
+
26
+ it "should create a matched mock queue and mock exchange" do
27
+ ensure_deferred_block_called
28
+ @queue.subscribe do |message|
29
+ deferred_block_called
30
+ message.should == "FTW"
31
+ end
32
+ @exchange.publish("FTW")
33
+ end
34
+
35
+ it "should allow for overloading AMQP and MQ" do
36
+ overload_amqp
37
+ defined?(AMQP).should be_true
38
+ defined?(MQ).should be_true
39
+ end
40
+
41
+ it "should provide a convenience method for creating mock queues" do
42
+ mock_queue("Sugary").should be_kind_of(Moqueue::MockQueue)
43
+ end
44
+
45
+ it "should provide a convenience method for creating mock exchanges" do
46
+ mock_exchange(:topic => "sweetSugar").should be_kind_of(Moqueue::MockExchange)
47
+ end
48
+
49
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "AMQP and MQ", "when overloaded by moqueue/overloads" do
4
+
5
+ before(:all) do
6
+ overload_amqp
7
+ end
8
+
9
+ it "should make AMQP.start take options and a block without connecting to AMQP broker" do
10
+ ensure_deferred_block_called
11
+ AMQP.start(:host => "localhost") do
12
+ deferred_block_called
13
+ EM.stop
14
+ end
15
+ end
16
+
17
+ it "should run EM in AMQP.start" do
18
+ EM.expects(:run)
19
+ AMQP.start { EM.stop }
20
+ end
21
+
22
+ it "should provide a MQ.queue class method" do
23
+ MQ.queue('FTW').should be_a(Moqueue::MockQueue)
24
+ end
25
+
26
+ it "should emulate the behavior of MQ.closing?" do
27
+ ensure_deferred_block_called
28
+ AMQP.stop do
29
+ deferred_block_called
30
+ AMQP.should be_closing
31
+ end
32
+ end
33
+
34
+ it "should create direct exchanges" do
35
+ MQ.new.direct("directamundo").should == MockExchange.new(:direct => "directamundo")
36
+ end
37
+
38
+ it "should create topic exchanges" do
39
+ MQ.new.topic("lolzFTW").should == MockExchange.new(:topic => "lolzFTW")
40
+ end
41
+
42
+ it "should provide a MQ.direct class method" do
43
+ MQ.direct("direct", :durable=>true).should be_a(Moqueue::MockExchange)
44
+ end
45
+
46
+ it "should provide a MQ.fanout class method" do
47
+ MQ.fanout("fanout", :durable=>true).should be_a(Moqueue::MockExchange)
48
+ end
49
+
50
+ it "should create a named fanout queue via MQ.fanout" do
51
+ fanout = MQ.fanout("SayMyNameSayMyName", :durable=>true)
52
+ fanout.should be_a(Moqueue::MockExchange)
53
+ fanout.fanout.should == "SayMyNameSayMyName"
54
+ end
55
+
56
+ end