bunny 0.4.4 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Rakefile +21 -3
  2. data/bunny.gemspec +34 -20
  3. data/examples/{simple.rb → simple_08.rb} +0 -0
  4. data/examples/simple_09.rb +30 -0
  5. data/examples/{simple_ack.rb → simple_ack_08.rb} +0 -0
  6. data/examples/simple_ack_09.rb +33 -0
  7. data/examples/{simple_consumer.rb → simple_consumer_08.rb} +0 -0
  8. data/examples/simple_consumer_09.rb +55 -0
  9. data/examples/{simple_fanout.rb → simple_fanout_08.rb} +0 -0
  10. data/examples/simple_fanout_09.rb +39 -0
  11. data/examples/{simple_headers.rb → simple_headers_08.rb} +0 -0
  12. data/examples/simple_headers_09.rb +40 -0
  13. data/examples/{simple_publisher.rb → simple_publisher_08.rb} +0 -0
  14. data/examples/simple_publisher_09.rb +27 -0
  15. data/examples/{simple_topic.rb → simple_topic_08.rb} +0 -0
  16. data/examples/simple_topic_09.rb +59 -0
  17. data/lib/bunny.rb +19 -14
  18. data/lib/bunny/channel08.rb +38 -0
  19. data/lib/bunny/channel09.rb +38 -0
  20. data/lib/bunny/client08.rb +167 -74
  21. data/lib/bunny/{client091.rb → client09.rb} +195 -92
  22. data/lib/bunny/{exchange091.rb → exchange09.rb} +12 -11
  23. data/lib/bunny/queue08.rb +1 -0
  24. data/lib/bunny/{queue091.rb → queue09.rb} +38 -28
  25. data/lib/qrack/client.rb +7 -0
  26. data/lib/qrack/protocol/{protocol.rb → protocol08.rb} +1 -4
  27. data/lib/qrack/protocol/protocol09.rb +133 -0
  28. data/lib/qrack/protocol/{spec091.rb → spec09.rb} +5 -5
  29. data/lib/qrack/qrack08.rb +2 -10
  30. data/lib/qrack/qrack09.rb +20 -0
  31. data/lib/qrack/transport/{buffer.rb → buffer08.rb} +0 -0
  32. data/lib/qrack/transport/buffer09.rb +276 -0
  33. data/lib/qrack/transport/{frame091.rb → frame09.rb} +8 -8
  34. data/spec/{bunny_spec.rb → spec_08/bunny_spec.rb} +4 -4
  35. data/spec/{exchange_spec.rb → spec_08/exchange_spec.rb} +3 -10
  36. data/spec/{queue_spec.rb → spec_08/queue_spec.rb} +1 -1
  37. data/spec/spec_09/bunny_spec.rb +40 -0
  38. data/spec/spec_09/exchange_spec.rb +131 -0
  39. data/spec/spec_09/queue_spec.rb +106 -0
  40. metadata +38 -22
  41. data/lib/qrack/qrack091.rb +0 -28
data/lib/qrack/qrack08.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  $: << File.expand_path(File.dirname(__FILE__))
2
2
 
3
3
  require 'protocol/spec08'
4
- require 'protocol/protocol'
4
+ require 'protocol/protocol08'
5
5
 
6
- require 'transport/buffer'
6
+ require 'transport/buffer08'
7
7
  require 'transport/frame08'
8
8
 
9
9
  require 'qrack/client'
@@ -17,12 +17,4 @@ module Qrack
17
17
  class BufferOverflowError < StandardError; end
18
18
  class InvalidTypeError < StandardError; end
19
19
 
20
- # Qrack version number
21
- VERSION = '0.0.1'
22
-
23
- # Return the Qrack version
24
- def self.version
25
- VERSION
26
- end
27
-
28
20
  end
@@ -0,0 +1,20 @@
1
+ $: << File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'protocol/spec09'
4
+ require 'protocol/protocol09'
5
+
6
+ require 'transport/buffer09'
7
+ require 'transport/frame09'
8
+
9
+ require 'qrack/client'
10
+
11
+ module Qrack
12
+
13
+ include Protocol09
14
+ include Transport09
15
+
16
+ # Errors
17
+ class BufferOverflowError < StandardError; end
18
+ class InvalidTypeError < StandardError; end
19
+
20
+ end
File without changes
@@ -0,0 +1,276 @@
1
+ if [].map.respond_to? :with_index
2
+ class Array #:nodoc:
3
+ def enum_with_index
4
+ each.with_index
5
+ end
6
+ end
7
+ else
8
+ require 'enumerator'
9
+ end
10
+
11
+ module Qrack
12
+ module Transport09 #:nodoc: all
13
+ class Buffer
14
+
15
+ def initialize data = ''
16
+ @data = data
17
+ @pos = 0
18
+ end
19
+
20
+ attr_reader :pos
21
+
22
+ def data
23
+ @data.clone
24
+ end
25
+ alias :contents :data
26
+ alias :to_s :data
27
+
28
+ def << data
29
+ @data << data.to_s
30
+ self
31
+ end
32
+
33
+ def length
34
+ @data.length
35
+ end
36
+
37
+ def empty?
38
+ pos == length
39
+ end
40
+
41
+ def rewind
42
+ @pos = 0
43
+ end
44
+
45
+ def read_properties *types
46
+ types.shift if types.first == :properties
47
+
48
+ i = 0
49
+ values = []
50
+
51
+ while props = read(:short)
52
+ (0..14).each do |n|
53
+ # no more property types
54
+ break unless types[i]
55
+
56
+ # if flag is set
57
+ if props & (1<<(15-n)) != 0
58
+ if types[i] == :bit
59
+ # bit values exist in flags only
60
+ values << true
61
+ else
62
+ # save type name for later reading
63
+ values << types[i]
64
+ end
65
+ else
66
+ # property not set or is false bit
67
+ values << (types[i] == :bit ? false : nil)
68
+ end
69
+
70
+ i+=1
71
+ end
72
+
73
+ # bit(0) == 0 means no more property flags
74
+ break unless props & 1 == 1
75
+ end
76
+
77
+ values.map do |value|
78
+ value.is_a?(Symbol) ? read(value) : value
79
+ end
80
+ end
81
+
82
+ def read *types
83
+ if types.first == :properties
84
+ return read_properties(*types)
85
+ end
86
+
87
+ values = types.map do |type|
88
+ case type
89
+ when :octet
90
+ _read(1, 'C')
91
+ when :short
92
+ _read(2, 'n')
93
+ when :long
94
+ _read(4, 'N')
95
+ when :longlong
96
+ upper, lower = _read(8, 'NN')
97
+ upper << 32 | lower
98
+ when :shortstr
99
+ _read read(:octet)
100
+ when :longstr
101
+ _read read(:long)
102
+ when :timestamp
103
+ Time.at read(:longlong)
104
+ when :table
105
+ t = Hash.new
106
+
107
+ table = Buffer.new(read(:longstr))
108
+ until table.empty?
109
+ key, type = table.read(:shortstr, :octet)
110
+ key = key.intern
111
+ t[key] ||= case type
112
+ when 83 # 'S'
113
+ table.read(:longstr)
114
+ when 73 # 'I'
115
+ table.read(:long)
116
+ when 68 # 'D'
117
+ exp = table.read(:octet)
118
+ num = table.read(:long)
119
+ num / 10.0**exp
120
+ when 84 # 'T'
121
+ table.read(:timestamp)
122
+ when 70 # 'F'
123
+ table.read(:table)
124
+ end
125
+ end
126
+
127
+ t
128
+ when :bit
129
+ if (@bits ||= []).empty?
130
+ val = read(:octet)
131
+ @bits = (0..7).map{|i| (val & 1<<i) != 0 }
132
+ end
133
+
134
+ @bits.shift
135
+ else
136
+ raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
137
+ end
138
+ end
139
+
140
+ types.size == 1 ? values.first : values
141
+ end
142
+
143
+ def write type, data
144
+ case type
145
+ when :octet
146
+ _write(data, 'C')
147
+ when :short
148
+ _write(data, 'n')
149
+ when :long
150
+ _write(data, 'N')
151
+ when :longlong
152
+ lower = data & 0xffffffff
153
+ upper = (data & ~0xffffffff) >> 32
154
+ _write([upper, lower], 'NN')
155
+ when :shortstr
156
+ data = (data || '').to_s
157
+ _write([data.length, data], 'Ca*')
158
+ when :longstr
159
+ if data.is_a? Hash
160
+ write(:table, data)
161
+ else
162
+ data = (data || '').to_s
163
+ _write([data.length, data], 'Na*')
164
+ end
165
+ when :timestamp
166
+ write(:longlong, data.to_i)
167
+ when :table
168
+ data ||= {}
169
+ write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
170
+ table.write(:shortstr, key.to_s)
171
+
172
+ case value
173
+ when String
174
+ table.write(:octet, 83) # 'S'
175
+ table.write(:longstr, value.to_s)
176
+ when Fixnum
177
+ table.write(:octet, 73) # 'I'
178
+ table.write(:long, value)
179
+ when Float
180
+ table.write(:octet, 68) # 'D'
181
+ # XXX there's gotta be a better way to do this..
182
+ exp = value.to_s.split('.').last.length
183
+ num = value * 10**exp
184
+ table.write(:octet, exp)
185
+ table.write(:long, num)
186
+ when Time
187
+ table.write(:octet, 84) # 'T'
188
+ table.write(:timestamp, value)
189
+ when Hash
190
+ table.write(:octet, 70) # 'F'
191
+ table.write(:table, value)
192
+ end
193
+
194
+ table
195
+ end)
196
+ when :bit
197
+ [*data].to_enum(:each_slice, 8).each{|bits|
198
+ write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
199
+ byte |= 1<<i if bit
200
+ byte
201
+ })
202
+ }
203
+ when :properties
204
+ values = []
205
+ data.enum_with_index.inject(0) do |short, ((type, value), i)|
206
+ n = i % 15
207
+ last = i+1 == data.size
208
+
209
+ if (n == 0 and i != 0) or last
210
+ if data.size > i+1
211
+ short |= 1<<0
212
+ elsif last and value
213
+ values << [type,value]
214
+ short |= 1<<(15-n)
215
+ end
216
+
217
+ write(:short, short)
218
+ short = 0
219
+ end
220
+
221
+ if value and !last
222
+ values << [type,value]
223
+ short |= 1<<(15-n)
224
+ end
225
+
226
+ short
227
+ end
228
+
229
+ values.each do |type, value|
230
+ write(type, value) unless type == :bit
231
+ end
232
+ else
233
+ raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
234
+ end
235
+
236
+ self
237
+ end
238
+
239
+ def extract
240
+ begin
241
+ cur_data, cur_pos = @data.clone, @pos
242
+ yield self
243
+ rescue Qrack::BufferOverflowError
244
+ @data, @pos = cur_data, cur_pos
245
+ nil
246
+ end
247
+ end
248
+
249
+ def _read(size, pack = nil)
250
+ if @data.is_a?(Qrack::Client)
251
+ raw = @data.read(size)
252
+ return raw if raw.nil? or pack.nil?
253
+ return raw.unpack(pack).first
254
+ end
255
+
256
+ if @pos + size > length
257
+ raise Qrack::BufferOverflowError
258
+ else
259
+ data = @data[@pos,size]
260
+ @data[@pos,size] = ''
261
+ if pack
262
+ data = data.unpack(pack)
263
+ data = data.pop if data.size == 1
264
+ end
265
+ data
266
+ end
267
+ end
268
+
269
+ def _write data, pack = nil
270
+ data = [*data].pack(pack) if pack
271
+ @data[@pos,0] = data
272
+ @pos += data.length
273
+ end
274
+ end
275
+ end
276
+ end
@@ -5,7 +5,7 @@
5
5
  # DO NOT EDIT! (edit ext/qparser.rb and config.yml instead, and run 'ruby qparser.rb')
6
6
 
7
7
  module Qrack
8
- module Transport
8
+ module Transport09
9
9
  class Frame
10
10
 
11
11
  FOOTER = 206
@@ -29,7 +29,7 @@ module Qrack
29
29
  end
30
30
 
31
31
  def to_binary
32
- buf = Transport::Buffer.new
32
+ buf = Transport09::Buffer.new
33
33
  buf.write :octet, id
34
34
  buf.write :short, channel
35
35
  buf.write :longstr, payload
@@ -49,10 +49,10 @@ module Qrack
49
49
  end
50
50
 
51
51
  def self.parse buf
52
- buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
52
+ buf = Transport09::Buffer.new(buf) unless buf.is_a? Transport09::Buffer
53
53
  buf.extract do
54
54
  id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
55
- Qrack::Transport.const_get(@types[id]).new(payload, channel) if footer == FOOTER
55
+ Qrack::Transport09.const_get(@types[id]).new(payload, channel) if footer == FOOTER
56
56
  end
57
57
  end
58
58
 
@@ -64,8 +64,8 @@ module Qrack
64
64
 
65
65
  def initialize payload = nil, channel = 0
66
66
  super
67
- unless @payload.is_a? Protocol::Class::Method or @payload.nil?
68
- @payload = Protocol.parse(@payload)
67
+ unless @payload.is_a? Protocol09::Class::Method or @payload.nil?
68
+ @payload = Protocol09.parse(@payload)
69
69
  end
70
70
  end
71
71
  end
@@ -76,8 +76,8 @@ module Qrack
76
76
 
77
77
  def initialize payload = nil, channel = 0
78
78
  super
79
- unless @payload.is_a? Protocol::Header or @payload.nil?
80
- @payload = Protocol::Header.new(@payload)
79
+ unless @payload.is_a? Protocol09::Header or @payload.nil?
80
+ @payload = Protocol09::Header.new(@payload)
81
81
  end
82
82
  end
83
83
  end
@@ -6,15 +6,15 @@
6
6
  # If this is not the case, please change the 'Bunny.new' call below to include
7
7
  # the relevant arguments e.g. @b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
8
 
9
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bunny]))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib bunny]))
10
10
 
11
11
  describe Bunny do
12
-
12
+
13
13
  before(:each) do
14
14
  @b = Bunny.new
15
15
  @b.start
16
16
  end
17
-
17
+
18
18
  it "should connect to an AMQP server" do
19
19
  @b.status.should == :connected
20
20
  end
@@ -36,5 +36,5 @@ describe Bunny do
36
36
  it "should be able to set QoS" do
37
37
  @b.qos.should == :qos_ok
38
38
  end
39
-
39
+
40
40
  end
@@ -6,15 +6,15 @@
6
6
  # If this is not the case, please change the 'Bunny.new' call below to include
7
7
  # the relevant arguments e.g. @b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
8
 
9
- require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bunny]))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib bunny]))
10
10
 
11
11
  describe Bunny do
12
-
12
+
13
13
  before(:each) do
14
14
  @b = Bunny.new
15
15
  @b.start
16
16
  end
17
-
17
+
18
18
  it "should raise an error if instantiated as non-existent type" do
19
19
  lambda { @b.exchange('bogus_ex', :type => :bogus) }.should raise_error(Bunny::ProtocolError)
20
20
  end
@@ -51,9 +51,6 @@ describe Bunny do
51
51
  @b.exchanges.has_key?('amq.topic').should be true
52
52
  end
53
53
 
54
-
55
- =begin
56
- #*** Uncomment these tests if your broker/server supports headers exchanges ***
57
54
  it "should allow a default headers (amq.match) exchange to be instantiated without specifying :type" do
58
55
  exch = @b.exchange('amq.match')
59
56
  exch.should be_an_instance_of Bunny::Exchange
@@ -69,7 +66,6 @@ describe Bunny do
69
66
  exch.type.should == :headers
70
67
  @b.exchanges.has_key?('amq.headers').should be true
71
68
  end
72
- =end
73
69
 
74
70
  it "should create an exchange as direct by default" do
75
71
  exch = @b.exchange('direct_defaultex')
@@ -103,8 +99,6 @@ describe Bunny do
103
99
  @b.exchanges.has_key?('fanout_exchange').should be true
104
100
  end
105
101
 
106
- =begin
107
- #*** Uncomment this test if your broker/server supports headers exchanges ***
108
102
  it "should be able to be instantiated as a headers exchange" do
109
103
  exch = @b.exchange('headers_exchange', :type => :headers)
110
104
  exch.should be_an_instance_of Bunny::Exchange
@@ -112,7 +106,6 @@ describe Bunny do
112
106
  exch.type.should == :headers
113
107
  @b.exchanges.has_key?('headers_exchange').should be true
114
108
  end
115
- =end
116
109
 
117
110
  it "should ignore the :nowait option when instantiated" do
118
111
  exch = @b.exchange('direct2_exchange', :nowait => true)