amqp 0.7.0.pre → 0.7.0
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/.gitignore +4 -0
- data/.rspec +2 -0
- data/CHANGELOG +8 -2
- data/CONTRIBUTORS +22 -0
- data/Gemfile +3 -3
- data/README.md +20 -11
- data/Rakefile +30 -6
- data/amqp.gemspec +1 -1
- data/bin/cleanify.rb +50 -0
- data/examples/amqp/simple.rb +6 -4
- data/examples/mq/ack.rb +8 -6
- data/examples/mq/automatic_binding_for_default_direct_exchange.rb +65 -0
- data/examples/mq/callbacks.rb +9 -1
- data/examples/mq/clock.rb +17 -17
- data/examples/mq/hashtable.rb +19 -10
- data/examples/mq/internal.rb +13 -11
- data/examples/mq/logger.rb +38 -36
- data/examples/mq/multiclock.rb +16 -7
- data/examples/mq/pingpong.rb +16 -7
- data/examples/mq/pop.rb +8 -6
- data/examples/mq/primes-simple.rb +2 -0
- data/examples/mq/primes.rb +7 -5
- data/examples/mq/stocks.rb +14 -5
- data/lib/amqp.rb +12 -8
- data/lib/amqp/buffer.rb +35 -158
- data/lib/amqp/client.rb +34 -22
- data/lib/amqp/frame.rb +8 -64
- data/lib/amqp/protocol.rb +21 -70
- data/lib/amqp/server.rb +11 -9
- data/lib/amqp/spec.rb +8 -6
- data/lib/amqp/version.rb +2 -0
- data/lib/ext/blankslate.rb +3 -1
- data/lib/ext/em.rb +2 -0
- data/lib/ext/emfork.rb +13 -11
- data/lib/mq.rb +253 -156
- data/lib/mq/collection.rb +6 -88
- data/lib/mq/exchange.rb +70 -13
- data/lib/mq/header.rb +12 -6
- data/lib/mq/logger.rb +9 -7
- data/lib/mq/queue.rb +42 -30
- data/lib/mq/rpc.rb +6 -4
- data/protocol/codegen.rb +20 -18
- data/research/api.rb +10 -46
- data/research/primes-forked.rb +9 -7
- data/research/primes-processes.rb +74 -72
- data/research/primes-threaded.rb +9 -7
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +61 -0
- data/spec/mq_helper.rb +70 -0
- data/spec/spec_helper.rb +84 -29
- data/spec/unit/amqp/buffer_spec.rb +178 -0
- data/spec/unit/amqp/client_spec.rb +472 -0
- data/spec/unit/amqp/frame_spec.rb +60 -0
- data/spec/unit/amqp/misc_spec.rb +123 -0
- data/spec/unit/amqp/protocol_spec.rb +53 -0
- data/spec/unit/mq/channel_close_spec.rb +15 -0
- data/spec/unit/mq/collection_spec.rb +129 -0
- data/spec/unit/mq/exchange_declaration_spec.rb +524 -0
- data/spec/unit/mq/misc_spec.rb +228 -0
- data/spec/unit/mq/mq_basic_spec.rb +39 -0
- data/spec/unit/mq/queue_declaration_spec.rb +97 -0
- data/spec/unit/mq/queue_spec.rb +71 -0
- metadata +33 -21
- data/Gemfile.lock +0 -16
- data/old/README +0 -30
- data/old/Rakefile +0 -12
- data/old/amqp-0.8.json +0 -606
- data/old/amqp_spec.rb +0 -796
- data/old/amqpc.rb +0 -695
- data/old/codegen.rb +0 -148
- data/spec/channel_close_spec.rb +0 -13
- data/spec/sync_async_spec.rb +0 -52
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
require "spec_helper"
|
5
|
+
require "amqp/frame"
|
6
|
+
|
7
|
+
describe AMQP::Frame do
|
8
|
+
include AMQP
|
9
|
+
|
10
|
+
it 'should handle basic frame types' do
|
11
|
+
Frame::Method.new.id.should == 1
|
12
|
+
Frame::Header.new.id.should == 2
|
13
|
+
Frame::Body.new.id.should == 3
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should convert method frames to binary' do
|
17
|
+
meth = Protocol::Connection::Secure.new :challenge => 'secret'
|
18
|
+
|
19
|
+
frame = Frame::Method.new(meth)
|
20
|
+
frame.to_binary.should be_kind_of Buffer
|
21
|
+
frame.to_s.should == [1, 0, meth.to_s.length, meth.to_s, 206].pack('CnNa*C')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should convert binary to method frames' do
|
25
|
+
orig = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
|
26
|
+
|
27
|
+
copy = Frame.parse(orig.to_binary)
|
28
|
+
copy.should == orig
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should ignore partial frames until ready' do
|
32
|
+
frame = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
|
33
|
+
data = frame.to_s
|
34
|
+
|
35
|
+
buf = Buffer.new
|
36
|
+
Frame.parse(buf).should == nil
|
37
|
+
|
38
|
+
buf << data[0..5]
|
39
|
+
Frame.parse(buf).should == nil
|
40
|
+
|
41
|
+
buf << data[6..-1]
|
42
|
+
Frame.parse(buf).should == frame
|
43
|
+
|
44
|
+
Frame.parse(buf).should == nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should convert header frames to binary' do
|
48
|
+
head = Protocol::Header.new(Protocol::Basic, :priority => 1)
|
49
|
+
|
50
|
+
frame = Frame::Header.new(head)
|
51
|
+
frame.to_s.should == [2, 0, head.to_s.length, head.to_s, 206].pack('CnNa*C')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should convert binary to header frame' do
|
55
|
+
orig = Frame::Header.new Protocol::Header.new(Protocol::Basic, :priority => 1)
|
56
|
+
|
57
|
+
copy = Frame.parse(orig.to_binary)
|
58
|
+
copy.should == orig
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'amqp'
|
4
|
+
|
5
|
+
module MockClientModule
|
6
|
+
def my_mock_method
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class MockClient
|
11
|
+
include AMQP::Client
|
12
|
+
end
|
13
|
+
|
14
|
+
describe AMQP, 'class object' do
|
15
|
+
context 'has class accessors, with default values' do
|
16
|
+
subject { AMQP }
|
17
|
+
|
18
|
+
its(:logging) { should be_false }
|
19
|
+
its(:connection) { should be_nil }
|
20
|
+
its(:conn) { should be_nil } # Alias for #connection
|
21
|
+
its(:closing) { should be_false }
|
22
|
+
its(:settings) { should == {:host => "127.0.0.1",
|
23
|
+
:port => 5672,
|
24
|
+
:user => "guest",
|
25
|
+
:pass => "guest",
|
26
|
+
:vhost => "/",
|
27
|
+
:timeout => nil,
|
28
|
+
:logging => false,
|
29
|
+
:ssl => false} }
|
30
|
+
|
31
|
+
its(:client) { should == AMQP::BasicClient }
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
describe '.client=' do
|
37
|
+
after(:all) { AMQP.client = AMQP::BasicClient }
|
38
|
+
|
39
|
+
it 'is used to change default client module' do
|
40
|
+
AMQP.client = MockClientModule
|
41
|
+
AMQP.client.should == MockClientModule
|
42
|
+
MockClientModule.ancestors.should include AMQP
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'new default client module' do
|
46
|
+
it 'sticks around after being assigned' do
|
47
|
+
AMQP.client.should == MockClientModule
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'extends any object that includes AMQP::Client' do
|
51
|
+
@client = MockClient.new
|
52
|
+
@client.should respond_to :my_mock_method
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end # .client
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
describe 'logging' do
|
61
|
+
after(:all) do
|
62
|
+
AMQP.logging = false
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'is silent by default' do
|
66
|
+
AMQP.logging.should be_false
|
67
|
+
end
|
68
|
+
end # .logging=
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
describe '.start' do
|
74
|
+
context 'inside EM loop' do
|
75
|
+
include AMQP::SpecHelper
|
76
|
+
em_after { AMQP.cleanup_state }
|
77
|
+
|
78
|
+
it 'yields to given block AFTER connection is established' do
|
79
|
+
em do
|
80
|
+
AMQP.start AMQP_OPTS do
|
81
|
+
@block_fired = true
|
82
|
+
AMQP.connection.should be_connected
|
83
|
+
end
|
84
|
+
done(0.1) { @block_fired.should be_true }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end # context 'inside EM loop'
|
88
|
+
end # .start
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
describe '.stop' do
|
94
|
+
it 'is noop if connection is not established' do
|
95
|
+
expect { @res = AMQP.stop }.to_not raise_error
|
96
|
+
@res.should be_nil
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with established AMQP connection' do
|
100
|
+
include AMQP::Spec
|
101
|
+
after { AMQP.cleanup_state; done }
|
102
|
+
default_options AMQP_OPTS
|
103
|
+
|
104
|
+
it 'unsets AMQP.connection property. Mind the delay!' do
|
105
|
+
AMQP.start(AMQP_OPTS)
|
106
|
+
AMQP.connection.should be_connected
|
107
|
+
|
108
|
+
AMQP.stop
|
109
|
+
AMQP.connection.should_not be_nil
|
110
|
+
done(0.1) { AMQP.connection.should be_nil }
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'yields to given block AFTER disconnect (BUT before AMQP.conn is cleared!)' do
|
114
|
+
AMQP.stop do
|
115
|
+
@block_fired = true
|
116
|
+
AMQP.connection.should_not be_nil
|
117
|
+
AMQP.instance_variable_get(:@closing).should be_true
|
118
|
+
end
|
119
|
+
done(0.1) { @block_fired.should be_true }
|
120
|
+
end
|
121
|
+
end # context 'with established AMQP connection'
|
122
|
+
end # .stop
|
123
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "amqp/protocol"
|
5
|
+
|
6
|
+
describe AMQP::Protocol do
|
7
|
+
include AMQP
|
8
|
+
|
9
|
+
it 'should instantiate methods with arguments' do
|
10
|
+
meth = Protocol::Connection::StartOk.new nil, 'PLAIN', nil, 'en_US'
|
11
|
+
meth.locale.should == 'en_US'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should instantiate methods with named parameters' do
|
15
|
+
meth = Protocol::Connection::StartOk.new :locale => 'en_US',
|
16
|
+
:mechanism => 'PLAIN'
|
17
|
+
meth.locale.should == 'en_US'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should convert methods to binary' do
|
21
|
+
meth = Protocol::Connection::Secure.new :challenge => 'secret'
|
22
|
+
meth.to_binary.should be_kind_of Buffer
|
23
|
+
|
24
|
+
meth.to_s.should == [10, 20, 6, 'secret'].pack('nnNa*')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should convert binary to method' do
|
28
|
+
orig = Protocol::Connection::Secure.new :challenge => 'secret'
|
29
|
+
copy = Protocol.parse orig.to_binary
|
30
|
+
orig.should == copy
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should convert headers to binary' do
|
34
|
+
head = Protocol::Header.new Protocol::Basic,
|
35
|
+
size = 5,
|
36
|
+
weight = 0,
|
37
|
+
:content_type => 'text/json',
|
38
|
+
:delivery_mode => 1,
|
39
|
+
:priority => 1
|
40
|
+
head.to_s.should ==
|
41
|
+
[60, weight, 0, size, 0b1001_1000_0000_0000, 9, 'text/json', 1, 1].pack('nnNNnCa*CC')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should convert binary to header' do
|
45
|
+
orig = Protocol::Header.new Protocol::Basic,
|
46
|
+
size = 5,
|
47
|
+
weight = 0,
|
48
|
+
:content_type => 'text/json',
|
49
|
+
:delivery_mode => 1,
|
50
|
+
:priority => 1
|
51
|
+
Protocol::Header.new(orig.to_binary).should == orig
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe MQ, "#close(&callback)" do
|
6
|
+
include AMQP::EMSpec
|
7
|
+
|
8
|
+
default_timeout 5
|
9
|
+
|
10
|
+
it "takes a callback which will run when we get back Channel.Close-Ok" do
|
11
|
+
MQ.new.close do |amq|
|
12
|
+
done
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "mq/collection"
|
5
|
+
|
6
|
+
Item = Struct.new(:name)
|
7
|
+
|
8
|
+
describe MQ::Collection do
|
9
|
+
before do
|
10
|
+
@items = 3.times.map { |int| Item.new("name-#{int}") }
|
11
|
+
@collection = MQ::Collection.new(@items)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "provides access to items by name" do
|
15
|
+
@collection["name-1"].should_not be_nil
|
16
|
+
@collection["name-1"].should eql(@items[1])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "DOES NOT allow modification of existing items" do
|
20
|
+
lambda { @collection["name-1"] = Item.new("test") }.should raise_error(NoMethodError)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
describe "#<<" do
|
25
|
+
it "should raise IncompatibleItemError if the argument doesn't have method :name" do
|
26
|
+
lambda { @collection << nil }.should raise_error(MQ::Collection::IncompatibleItemError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should add an item into the collection" do
|
30
|
+
length = @collection.length
|
31
|
+
@collection << Item.new("test")
|
32
|
+
@collection.length.should eql(length + 1)
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when another item with given name already exists and the name IS NOT nil" do
|
36
|
+
it "should not add an item to the collection" do
|
37
|
+
@collection << Item.new("test")
|
38
|
+
length = @collection.length
|
39
|
+
@collection << Item.new("test")
|
40
|
+
@collection.length.should eql(length)
|
41
|
+
end # it
|
42
|
+
end # context
|
43
|
+
|
44
|
+
|
45
|
+
context "when another item with given name already exists and the name IS nil" do
|
46
|
+
it "should add an item to the collection" do
|
47
|
+
@collection << Item.new(nil)
|
48
|
+
length = @collection.length
|
49
|
+
@collection << Item.new(nil)
|
50
|
+
@collection.length.should eql(length + 1)
|
51
|
+
end # it
|
52
|
+
end # context
|
53
|
+
|
54
|
+
it "should return the item" do
|
55
|
+
item = Item.new("test")
|
56
|
+
(@collection << item).should eql item
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when adding new item with duplicate name" do
|
60
|
+
before do
|
61
|
+
@original_item = Item.new("test")
|
62
|
+
@new_item = Item.new("test")
|
63
|
+
@collection << @original_item
|
64
|
+
end
|
65
|
+
|
66
|
+
it "keeps item already in collection" do
|
67
|
+
@collection << @new_item
|
68
|
+
@collection['test'].should eql @original_item
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns item already in collection" do
|
72
|
+
(@collection << @new_item).should eql @original_item
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when item we add already exists in the collection" do
|
77
|
+
it "should return the item" do
|
78
|
+
item = Item.new("test")
|
79
|
+
@collection << item
|
80
|
+
(@collection << item).should eql item
|
81
|
+
end # it
|
82
|
+
end # context
|
83
|
+
end # describe
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
describe "#add!" do
|
89
|
+
context "when the argument doesn't respond to :name" do
|
90
|
+
it "should raise IncompatibleItemError " do
|
91
|
+
lambda { @collection.add!(nil) }.should raise_error(MQ::Collection::IncompatibleItemError)
|
92
|
+
end # it
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when another item with given name already exists" do
|
96
|
+
it "should add an item to the collection" do
|
97
|
+
@collection.add! Item.new("test")
|
98
|
+
lambda do
|
99
|
+
@collection.add!(Item.new("test"))
|
100
|
+
end.should change(@collection, :length).by(1)
|
101
|
+
end # it
|
102
|
+
end # context
|
103
|
+
|
104
|
+
it "should return the item" do
|
105
|
+
item = Item.new("test")
|
106
|
+
(@collection.add! item).should eql(item)
|
107
|
+
end # it
|
108
|
+
end # describe
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
describe "#<<" do
|
115
|
+
context "when the argument doesn't respond to :name" do
|
116
|
+
it "should raise IncompatibleItemError " do
|
117
|
+
lambda { @collection << nil }.should raise_error(MQ::Collection::IncompatibleItemError)
|
118
|
+
end # it
|
119
|
+
end # context
|
120
|
+
|
121
|
+
context "when the argument DOES respond to :name" do
|
122
|
+
it "should add an item into the collection" do
|
123
|
+
lambda do
|
124
|
+
@collection << Item.new("test")
|
125
|
+
end.should change(@collection, :length).by(1)
|
126
|
+
end
|
127
|
+
end # context
|
128
|
+
end # describe
|
129
|
+
end # describe MQ::Collection
|
@@ -0,0 +1,524 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe MQ do
|
6
|
+
|
7
|
+
#
|
8
|
+
# Environment
|
9
|
+
#
|
10
|
+
|
11
|
+
include AMQP::Spec
|
12
|
+
|
13
|
+
default_timeout 10
|
14
|
+
|
15
|
+
amqp_before do
|
16
|
+
@channel = MQ.new
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# Examples
|
22
|
+
#
|
23
|
+
|
24
|
+
describe "#direct" do
|
25
|
+
context "when exchange name is specified" do
|
26
|
+
it 'declares a new direct exchange with that name' do
|
27
|
+
@channel.direct('name').name.should == 'name'
|
28
|
+
|
29
|
+
done
|
30
|
+
end
|
31
|
+
|
32
|
+
it "declares direct exchange as transient (non-durable)" do
|
33
|
+
exchange = @channel.direct('name')
|
34
|
+
|
35
|
+
exchange.should_not be_durable
|
36
|
+
exchange.should be_transient
|
37
|
+
|
38
|
+
done
|
39
|
+
end
|
40
|
+
|
41
|
+
it "declares direct exchange as non-auto-deleted" do
|
42
|
+
exchange = @channel.direct('name')
|
43
|
+
|
44
|
+
exchange.should_not be_auto_deleted
|
45
|
+
|
46
|
+
done
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
context "when exchange name is omitted" do
|
52
|
+
it 'uses amq.direct' do
|
53
|
+
@channel.direct.name.should == 'amq.direct'
|
54
|
+
done
|
55
|
+
end # it
|
56
|
+
end # context
|
57
|
+
|
58
|
+
|
59
|
+
context "when exchange name was specified as a blank string" do
|
60
|
+
it 'returns direct exchange with server-generated name' do
|
61
|
+
pending <<-EOF
|
62
|
+
This has to be fixed in RabbitMQ first
|
63
|
+
https://bugzilla.rabbitmq.com/show_bug.cgi?id=23509
|
64
|
+
EOF
|
65
|
+
@channel.direct("") do |exchange|
|
66
|
+
exchange.name.should_not be_empty
|
67
|
+
done
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end # context
|
71
|
+
|
72
|
+
|
73
|
+
context "when passive option is used" do
|
74
|
+
context "and exchange with given name already exists" do
|
75
|
+
it "silently returns" do
|
76
|
+
name = "a_new_direct_exchange declared at #{Time.now.to_i}"
|
77
|
+
|
78
|
+
original_exchange = @channel.direct(name)
|
79
|
+
exchange = @channel.direct(name, :passive => true)
|
80
|
+
|
81
|
+
exchange.should == original_exchange
|
82
|
+
|
83
|
+
done
|
84
|
+
end # it
|
85
|
+
end
|
86
|
+
|
87
|
+
context "and exchange with given name DOES NOT exist" do
|
88
|
+
it "raises an exception" do
|
89
|
+
pending "Not yet supported"
|
90
|
+
|
91
|
+
expect {
|
92
|
+
exchange = @channel.direct("direct exchange declared at #{Time.now.to_i}", :passive => true)
|
93
|
+
}.to raise_error
|
94
|
+
|
95
|
+
done
|
96
|
+
end # it
|
97
|
+
end # context
|
98
|
+
end # context
|
99
|
+
|
100
|
+
|
101
|
+
context "when exchange is declared as durable" do
|
102
|
+
it "returns a new durable direct exchange" do
|
103
|
+
exchange = @channel.direct("a_new_durable_direct_exchange", :durable => true)
|
104
|
+
exchange.should be_durable
|
105
|
+
exchange.should_not be_transient
|
106
|
+
|
107
|
+
done
|
108
|
+
end # it
|
109
|
+
end # context
|
110
|
+
|
111
|
+
|
112
|
+
context "when exchange is declared as non-durable" do
|
113
|
+
it "returns a new NON-durable direct exchange" do
|
114
|
+
exchange = @channel.direct("a_new_non_durable_direct_exchange", :durable => false)
|
115
|
+
exchange.should_not be_durable
|
116
|
+
exchange.should be_transient
|
117
|
+
|
118
|
+
done
|
119
|
+
end # it
|
120
|
+
end # context
|
121
|
+
|
122
|
+
|
123
|
+
context "when exchange is declared as auto-deleted" do
|
124
|
+
it "returns a new auto-deleted direct exchange" do
|
125
|
+
exchange = @channel.direct("a new auto-deleted direct exchange", :auto_delete => true)
|
126
|
+
|
127
|
+
exchange.should be_auto_deleted
|
128
|
+
done
|
129
|
+
end # it
|
130
|
+
end # context
|
131
|
+
|
132
|
+
|
133
|
+
context "when exchange is declared as auto-deleted" do
|
134
|
+
it "returns a new auto-deleted direct exchange" do
|
135
|
+
exchange = @channel.direct("a new non-auto-deleted direct exchange", :auto_delete => false)
|
136
|
+
|
137
|
+
exchange.should_not be_auto_deleted
|
138
|
+
done
|
139
|
+
end # it
|
140
|
+
end # context
|
141
|
+
|
142
|
+
|
143
|
+
context "when exchange is declared without explicit :nowait parameter" do
|
144
|
+
it "is declared with :nowait by default" do
|
145
|
+
exchange = @channel.direct("a new non-auto-deleted direct exchange", :auto_delete => false)
|
146
|
+
|
147
|
+
exchange.should_not be_auto_deleted
|
148
|
+
done
|
149
|
+
end # it
|
150
|
+
end # context
|
151
|
+
|
152
|
+
|
153
|
+
context "when exchange is re-declared with parameters different from original declaration" do
|
154
|
+
it "raises an exception" do
|
155
|
+
@channel.direct("previously.declared.durable.direct.exchange", :durable => true)
|
156
|
+
|
157
|
+
expect {
|
158
|
+
@channel.direct("previously.declared.durable.direct.exchange", :durable => false)
|
159
|
+
}.to raise_error(MQ::IncompatibleOptionsError)
|
160
|
+
|
161
|
+
done
|
162
|
+
end # it
|
163
|
+
end # context
|
164
|
+
end # describe
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
describe "#fanout" do
|
170
|
+
context "when exchange name is specified" do
|
171
|
+
let(:name) { "new.fanout.exchange" }
|
172
|
+
|
173
|
+
it "declares a new fanout exchange with that name" do
|
174
|
+
exchange = @channel.fanout(name)
|
175
|
+
|
176
|
+
exchange.name.should == name
|
177
|
+
|
178
|
+
done
|
179
|
+
end
|
180
|
+
end # context
|
181
|
+
|
182
|
+
context "when exchange name is omitted" do
|
183
|
+
it "uses amq.fanout" do
|
184
|
+
exchange = @channel.fanout
|
185
|
+
exchange.name.should == "amq.fanout"
|
186
|
+
exchange.name.should_not == "amq.fanout2"
|
187
|
+
|
188
|
+
done
|
189
|
+
end
|
190
|
+
end # context
|
191
|
+
|
192
|
+
context "when passive option is used" do
|
193
|
+
context "and exchange with given name already exists" do
|
194
|
+
it "silently returns" do
|
195
|
+
name = "a_new_fanout_exchange declared at #{Time.now.to_i}"
|
196
|
+
|
197
|
+
original_exchange = @channel.fanout(name)
|
198
|
+
exchange = @channel.fanout(name, :passive => true)
|
199
|
+
|
200
|
+
exchange.should == original_exchange
|
201
|
+
|
202
|
+
done
|
203
|
+
end # it
|
204
|
+
end
|
205
|
+
|
206
|
+
context "and exchange with given name DOES NOT exist" do
|
207
|
+
it "raises an exception" do
|
208
|
+
pending "Not yet supported"
|
209
|
+
|
210
|
+
expect {
|
211
|
+
exchange = @channel.fanout("fanout exchange declared at #{Time.now.to_i}", :passive => true)
|
212
|
+
}.to raise_error
|
213
|
+
|
214
|
+
done
|
215
|
+
end # it
|
216
|
+
end # context
|
217
|
+
end # context
|
218
|
+
|
219
|
+
|
220
|
+
context "when exchange is declared as durable" do
|
221
|
+
it "returns a new durable fanout exchange" do
|
222
|
+
exchange = @channel.fanout("a_new_durable_fanout_exchange", :durable => true)
|
223
|
+
exchange.should be_durable
|
224
|
+
exchange.should_not be_transient
|
225
|
+
|
226
|
+
done
|
227
|
+
end # it
|
228
|
+
end # context
|
229
|
+
|
230
|
+
|
231
|
+
context "when exchange is declared as non-durable" do
|
232
|
+
it "returns a new NON-durable fanout exchange" do
|
233
|
+
exchange = @channel.fanout("a_new_non_durable_fanout_exchange", :durable => false)
|
234
|
+
exchange.should_not be_durable
|
235
|
+
exchange.should be_transient
|
236
|
+
|
237
|
+
done
|
238
|
+
end # it
|
239
|
+
end # context
|
240
|
+
|
241
|
+
|
242
|
+
context "when exchange is declared as auto-deleted" do
|
243
|
+
it "returns a new auto-deleted fanout exchange" do
|
244
|
+
exchange = @channel.fanout("a new auto-deleted fanout exchange", :auto_delete => true)
|
245
|
+
|
246
|
+
exchange.should be_auto_deleted
|
247
|
+
done
|
248
|
+
end # it
|
249
|
+
end # context
|
250
|
+
|
251
|
+
|
252
|
+
context "when exchange is declared as auto-deleted" do
|
253
|
+
it "returns a new auto-deleted fanout exchange" do
|
254
|
+
exchange = @channel.fanout("a new non-auto-deleted fanout exchange", :auto_delete => false)
|
255
|
+
|
256
|
+
exchange.should_not be_auto_deleted
|
257
|
+
done
|
258
|
+
end # it
|
259
|
+
end # context
|
260
|
+
|
261
|
+
|
262
|
+
context "when exchange is declared without explicit :nowait parameter" do
|
263
|
+
it "is declared with :nowait by default" do
|
264
|
+
exchange = @channel.fanout("a new non-auto-deleted fanout exchange", :auto_delete => false)
|
265
|
+
|
266
|
+
exchange.should_not be_auto_deleted
|
267
|
+
done
|
268
|
+
end # it
|
269
|
+
end # context
|
270
|
+
|
271
|
+
|
272
|
+
context "when exchange is re-declared with parameters different from original declaration" do
|
273
|
+
it "raises an exception" do
|
274
|
+
@channel.fanout("previously.declared.durable.topic.exchange", :durable => true)
|
275
|
+
|
276
|
+
expect {
|
277
|
+
@channel.fanout("previously.declared.durable.topic.exchange", :durable => false)
|
278
|
+
}.to raise_error(MQ::IncompatibleOptionsError)
|
279
|
+
|
280
|
+
done
|
281
|
+
end # it
|
282
|
+
end # context
|
283
|
+
end # describe
|
284
|
+
|
285
|
+
|
286
|
+
|
287
|
+
|
288
|
+
describe "#topic" do
|
289
|
+
context "when exchange name is specified" do
|
290
|
+
let(:name) { "a.topic.exchange" }
|
291
|
+
|
292
|
+
it "declares a new topic exchange with that name" do
|
293
|
+
exchange = @channel.topic(name)
|
294
|
+
exchange.name.should == name
|
295
|
+
|
296
|
+
done
|
297
|
+
end
|
298
|
+
end # context
|
299
|
+
|
300
|
+
context "when exchange name is omitted" do
|
301
|
+
it "uses amq.topic" do
|
302
|
+
exchange = @channel.topic
|
303
|
+
exchange.name.should == "amq.topic"
|
304
|
+
exchange.name.should_not == "amq.topic2"
|
305
|
+
|
306
|
+
done
|
307
|
+
end
|
308
|
+
end # context
|
309
|
+
|
310
|
+
context "when passive option is used" do
|
311
|
+
context "and exchange with given name already exists" do
|
312
|
+
it "silently returns" do
|
313
|
+
name = "a_new_topic_exchange declared at #{Time.now.to_i}"
|
314
|
+
|
315
|
+
original_exchange = @channel.topic(name)
|
316
|
+
exchange = @channel.topic(name, :passive => true)
|
317
|
+
|
318
|
+
exchange.should == original_exchange
|
319
|
+
|
320
|
+
done
|
321
|
+
end # it
|
322
|
+
end
|
323
|
+
|
324
|
+
context "and exchange with given name DOES NOT exist" do
|
325
|
+
it "raises an exception" do
|
326
|
+
pending "Not yet supported"
|
327
|
+
|
328
|
+
expect {
|
329
|
+
exchange = @channel.topic("topic exchange declared at #{Time.now.to_i}", :passive => true)
|
330
|
+
}.to raise_error
|
331
|
+
|
332
|
+
done
|
333
|
+
end # it
|
334
|
+
end # context
|
335
|
+
end # context
|
336
|
+
|
337
|
+
|
338
|
+
context "when exchange is declared as durable" do
|
339
|
+
it "returns a new durable topic exchange" do
|
340
|
+
exchange = @channel.topic("a_new_durable_topic_exchange", :durable => true)
|
341
|
+
exchange.should be_durable
|
342
|
+
exchange.should_not be_transient
|
343
|
+
|
344
|
+
done
|
345
|
+
end # it
|
346
|
+
end # context
|
347
|
+
|
348
|
+
|
349
|
+
context "when exchange is declared as non-durable" do
|
350
|
+
it "returns a new NON-durable topic exchange" do
|
351
|
+
exchange = @channel.topic("a_new_non_durable_topic_exchange", :durable => false)
|
352
|
+
exchange.should_not be_durable
|
353
|
+
exchange.should be_transient
|
354
|
+
|
355
|
+
done
|
356
|
+
end # it
|
357
|
+
end # context
|
358
|
+
|
359
|
+
|
360
|
+
context "when exchange is declared as auto-deleted" do
|
361
|
+
it "returns a new auto-deleted topic exchange" do
|
362
|
+
exchange = @channel.topic("a new auto-deleted topic exchange", :auto_delete => true)
|
363
|
+
|
364
|
+
exchange.should be_auto_deleted
|
365
|
+
done
|
366
|
+
end # it
|
367
|
+
end # context
|
368
|
+
|
369
|
+
|
370
|
+
context "when exchange is declared as auto-deleted" do
|
371
|
+
it "returns a new auto-deleted topic exchange" do
|
372
|
+
exchange = @channel.topic("a new non-auto-deleted topic exchange", :auto_delete => false)
|
373
|
+
|
374
|
+
exchange.should_not be_auto_deleted
|
375
|
+
done
|
376
|
+
end # it
|
377
|
+
end # context
|
378
|
+
|
379
|
+
|
380
|
+
context "when exchange is declared without explicit :nowait parameter" do
|
381
|
+
it "is declared with :nowait by default" do
|
382
|
+
exchange = @channel.topic("a new non-auto-deleted topic exchange", :auto_delete => false)
|
383
|
+
|
384
|
+
exchange.should_not be_auto_deleted
|
385
|
+
done
|
386
|
+
end # it
|
387
|
+
end # context
|
388
|
+
|
389
|
+
|
390
|
+
context "when exchange is re-declared with parameters different from original declaration" do
|
391
|
+
xit "raises an exception" do
|
392
|
+
@channel.topic("previously.declared.durable.topic.exchange", :durable => true)
|
393
|
+
|
394
|
+
expect {
|
395
|
+
@channel.topic("previously.declared.durable.topic.exchange", :durable => false)
|
396
|
+
}.to raise_error(MQ::IncompatibleOptionsError)
|
397
|
+
|
398
|
+
done
|
399
|
+
end # it
|
400
|
+
end # context
|
401
|
+
end # describe
|
402
|
+
|
403
|
+
|
404
|
+
|
405
|
+
|
406
|
+
describe "#headers" do
|
407
|
+
context "when exchange name is specified" do
|
408
|
+
let(:name) { "new.headers.exchange" }
|
409
|
+
|
410
|
+
it "declares a new headers exchange with that name" do
|
411
|
+
exchange = @channel.headers(name)
|
412
|
+
|
413
|
+
exchange.name.should == name
|
414
|
+
|
415
|
+
done
|
416
|
+
end
|
417
|
+
end # context
|
418
|
+
|
419
|
+
context "when exchange name is omitted" do
|
420
|
+
xit "uses amq.match" do
|
421
|
+
pending "Times out. MK."
|
422
|
+
|
423
|
+
exchange = @channel.headers
|
424
|
+
exchange.name.should == "amq.match"
|
425
|
+
exchange.name.should_not == "amq.headers"
|
426
|
+
|
427
|
+
done
|
428
|
+
end
|
429
|
+
end # context
|
430
|
+
|
431
|
+
context "when passive option is used" do
|
432
|
+
context "and exchange with given name already exists" do
|
433
|
+
it "silently returns" do
|
434
|
+
name = "a_new_headers_exchange declared at #{Time.now.to_i}"
|
435
|
+
|
436
|
+
original_exchange = @channel.headers(name)
|
437
|
+
exchange = @channel.headers(name, :passive => true)
|
438
|
+
|
439
|
+
exchange.should == original_exchange
|
440
|
+
|
441
|
+
done
|
442
|
+
end # it
|
443
|
+
end
|
444
|
+
|
445
|
+
context "and exchange with given name DOES NOT exist" do
|
446
|
+
it "raises an exception" do
|
447
|
+
pending "Not yet supported"
|
448
|
+
|
449
|
+
expect {
|
450
|
+
exchange = @channel.headers("headers exchange declared at #{Time.now.to_i}", :passive => true)
|
451
|
+
}.to raise_error
|
452
|
+
|
453
|
+
done
|
454
|
+
end # it
|
455
|
+
end # context
|
456
|
+
end # context
|
457
|
+
|
458
|
+
|
459
|
+
context "when exchange is declared as durable" do
|
460
|
+
it "returns a new durable headers exchange" do
|
461
|
+
exchange = @channel.headers("a_new_durable_headers_exchange", :durable => true)
|
462
|
+
exchange.should be_durable
|
463
|
+
exchange.should_not be_transient
|
464
|
+
|
465
|
+
done
|
466
|
+
end # it
|
467
|
+
end # context
|
468
|
+
|
469
|
+
|
470
|
+
context "when exchange is declared as non-durable" do
|
471
|
+
it "returns a new NON-durable headers exchange" do
|
472
|
+
exchange = @channel.headers("a_new_non_durable_headers_exchange", :durable => false)
|
473
|
+
exchange.should_not be_durable
|
474
|
+
exchange.should be_transient
|
475
|
+
|
476
|
+
done
|
477
|
+
end # it
|
478
|
+
end # context
|
479
|
+
|
480
|
+
|
481
|
+
context "when exchange is declared as auto-deleted" do
|
482
|
+
it "returns a new auto-deleted headers exchange" do
|
483
|
+
exchange = @channel.headers("a new auto-deleted headers exchange", :auto_delete => true)
|
484
|
+
|
485
|
+
exchange.should be_auto_deleted
|
486
|
+
done
|
487
|
+
end # it
|
488
|
+
end # context
|
489
|
+
|
490
|
+
|
491
|
+
context "when exchange is declared as auto-deleted" do
|
492
|
+
it "returns a new auto-deleted headers exchange" do
|
493
|
+
exchange = @channel.headers("a new non-auto-deleted headers exchange", :auto_delete => false)
|
494
|
+
|
495
|
+
exchange.should_not be_auto_deleted
|
496
|
+
done
|
497
|
+
end # it
|
498
|
+
end # context
|
499
|
+
|
500
|
+
|
501
|
+
context "when exchange is declared without explicit :nowait parameter" do
|
502
|
+
it "is declared with :nowait by default" do
|
503
|
+
exchange = @channel.headers("a new non-auto-deleted headers exchange", :auto_delete => false)
|
504
|
+
|
505
|
+
exchange.should_not be_auto_deleted
|
506
|
+
done
|
507
|
+
end # it
|
508
|
+
end # context
|
509
|
+
|
510
|
+
|
511
|
+
context "when exchange is re-declared with parameters different from original declaration" do
|
512
|
+
xit "raises an exception" do
|
513
|
+
pending "Times out. MK."
|
514
|
+
@channel.headers("previously.declared.durable.topic.exchange", :durable => true)
|
515
|
+
|
516
|
+
expect {
|
517
|
+
@channel.headers("previously.declared.durable.topic.exchange", :durable => false)
|
518
|
+
}.to raise_error(MQ::IncompatibleOptionsError)
|
519
|
+
|
520
|
+
done
|
521
|
+
end # it
|
522
|
+
end # context
|
523
|
+
end # describe
|
524
|
+
end # describe MQ
|