moqueue 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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