carrot 0.8.1 → 1.0.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/README.markdown CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  A synchronous amqp client. Based on Aman's amqp client:
4
4
 
5
- [http://github.com/tmm1/amqp/tree/master] (http://github.com/tmm1/amqp/tree/master)
5
+ [http://github.com/tmm1/amqp/tree/master](http://github.com/tmm1/amqp/tree/master)
6
6
 
7
7
  ## Motivation
8
8
 
9
- This client does not use eventmachine so no background thread necessary. As a result, it is much easier to use from script/console and Passenger. It also solves the problem of buffering messages and ack responses. For more details see [this thread] (http://groups.google.com/group/ruby-amqp/browse_thread/thread/fdae324a0ebb1961/fa185fdce1841b68).
9
+ This client does not use eventmachine so no background thread necessary. As a result, it is much easier to use from script/console and Passenger. It also solves the problem of buffering messages and ack responses. For more details see [this thread](http://groups.google.com/group/ruby-amqp/browse_thread/thread/fdae324a0ebb1961/fa185fdce1841b68).
10
10
 
11
11
  There is currently no way to prevent buffering using eventmachine. Support for prefetch is still unreliable.
12
12
 
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rake/rdoctask'
4
- require 'rcov/rcovtask'
5
4
 
6
5
  begin
7
6
  require 'jeweler'
@@ -12,7 +11,6 @@ begin
12
11
  s.description = "A synchronous version of the ruby amqp client"
13
12
  s.summary = "A synchronous version of the ruby amqp client"
14
13
  s.authors = ["Amos Elliston"]
15
- s.add_development_dependency "rcov"
16
14
  s.add_development_dependency "mocha"
17
15
  end
18
16
  Jeweler::GemcutterTasks.new
@@ -34,10 +32,4 @@ Rake::RDocTask.new do |rdoc|
34
32
  rdoc.rdoc_files.include('lib/**/*.rb')
35
33
  end
36
34
 
37
- Rcov::RcovTask.new do |t|
38
- t.libs << ['lib', 'test']
39
- t.test_files = FileList['test/**/*_test.rb']
40
- t.verbose = true
41
- end
42
-
43
35
  task :default => :test
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
- ---
2
- :major: 0
3
- :minor: 8
4
- :build:
5
- :patch: 1
1
+ ---
2
+ :major: 1
3
+ :minor: 0
4
+ :patch: 0
5
+ :build: !!null
data/carrot.gemspec CHANGED
@@ -1,68 +1,62 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{carrot}
8
- s.version = "0.8.1"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Amos Elliston"]
12
- s.date = %q{2010-11-01}
12
+ s.date = %q{2011-08-03}
13
13
  s.description = %q{A synchronous version of the ruby amqp client}
14
14
  s.email = %q{amos@geni.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.markdown"
17
+ "README.markdown"
18
18
  ]
19
19
  s.files = [
20
- ".gitignore",
21
- "LICENSE",
22
- "README.markdown",
23
- "Rakefile",
24
- "VERSION.yml",
25
- "carrot.gemspec",
26
- "lib/amqp/buffer.rb",
27
- "lib/amqp/exchange.rb",
28
- "lib/amqp/frame.rb",
29
- "lib/amqp/header.rb",
30
- "lib/amqp/protocol.rb",
31
- "lib/amqp/queue.rb",
32
- "lib/amqp/server.rb",
33
- "lib/amqp/spec.rb",
34
- "lib/carrot.rb",
35
- "lib/examples/simple_pop.rb",
36
- "protocol/amqp-0.8.json",
37
- "protocol/amqp-0.8.xml",
38
- "protocol/codegen.rb",
39
- "protocol/doc.txt",
40
- "test/carrot_test.rb",
41
- "test/test_helper.rb"
20
+ "LICENSE",
21
+ "README.markdown",
22
+ "Rakefile",
23
+ "VERSION.yml",
24
+ "carrot.gemspec",
25
+ "lib/carrot.rb",
26
+ "lib/carrot/amqp/buffer.rb",
27
+ "lib/carrot/amqp/exchange.rb",
28
+ "lib/carrot/amqp/frame.rb",
29
+ "lib/carrot/amqp/header.rb",
30
+ "lib/carrot/amqp/protocol.rb",
31
+ "lib/carrot/amqp/queue.rb",
32
+ "lib/carrot/amqp/server.rb",
33
+ "lib/carrot/amqp/spec.rb",
34
+ "lib/examples/simple_pop.rb",
35
+ "protocol/amqp-0.8.json",
36
+ "protocol/amqp-0.8.xml",
37
+ "protocol/codegen.rb",
38
+ "protocol/doc.txt",
39
+ "test/buffer_test.rb",
40
+ "test/carrot_test.rb",
41
+ "test/frame_test.rb",
42
+ "test/protocol_test.rb",
43
+ "test/test_helper.rb"
42
44
  ]
43
45
  s.homepage = %q{http://github.com/famoseagle/carrot}
44
- s.rdoc_options = ["--charset=UTF-8"]
45
46
  s.require_paths = ["lib"]
46
47
  s.rubygems_version = %q{1.3.7}
47
48
  s.summary = %q{A synchronous version of the ruby amqp client}
48
- s.test_files = [
49
- "test/carrot_test.rb",
50
- "test/test_helper.rb"
51
- ]
52
49
 
53
50
  if s.respond_to? :specification_version then
54
51
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
52
  s.specification_version = 3
56
53
 
57
54
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_development_dependency(%q<rcov>, [">= 0"])
59
55
  s.add_development_dependency(%q<mocha>, [">= 0"])
60
56
  else
61
- s.add_dependency(%q<rcov>, [">= 0"])
62
57
  s.add_dependency(%q<mocha>, [">= 0"])
63
58
  end
64
59
  else
65
- s.add_dependency(%q<rcov>, [">= 0"])
66
60
  s.add_dependency(%q<mocha>, [">= 0"])
67
61
  end
68
62
  end
data/lib/carrot.rb CHANGED
@@ -8,14 +8,14 @@ class Carrot
8
8
  end
9
9
 
10
10
  $:.unshift File.expand_path(File.dirname(File.expand_path(__FILE__)))
11
- require 'amqp/spec'
12
- require 'amqp/buffer'
13
- require 'amqp/exchange'
14
- require 'amqp/frame'
15
- require 'amqp/header'
16
- require 'amqp/queue'
17
- require 'amqp/server'
18
- require 'amqp/protocol'
11
+ require 'carrot/amqp/spec'
12
+ require 'carrot/amqp/buffer'
13
+ require 'carrot/amqp/exchange'
14
+ require 'carrot/amqp/frame'
15
+ require 'carrot/amqp/header'
16
+ require 'carrot/amqp/queue'
17
+ require 'carrot/amqp/server'
18
+ require 'carrot/amqp/protocol'
19
19
 
20
20
  class Carrot
21
21
  @logging = false
@@ -274,128 +274,3 @@ module Carrot::AMQP
274
274
  end
275
275
  end
276
276
  end
277
-
278
- if $0 =~ /bacon/ or $0 == __FILE__
279
- require 'bacon'
280
- include AMQP
281
-
282
- describe Buffer do
283
- before do
284
- @buf = Buffer.new
285
- end
286
-
287
- should 'have contents' do
288
- @buf.contents.should == ''
289
- end
290
-
291
- should 'initialize with data' do
292
- @buf = Buffer.new('abc')
293
- @buf.contents.should == 'abc'
294
- end
295
-
296
- should 'append raw data' do
297
- @buf << 'abc'
298
- @buf << 'def'
299
- @buf.contents.should == 'abcdef'
300
- end
301
-
302
- should 'append other buffers' do
303
- @buf << Buffer.new('abc')
304
- @buf.data.should == 'abc'
305
- end
306
-
307
- should 'have a position' do
308
- @buf.pos.should == 0
309
- end
310
-
311
- should 'have a length' do
312
- @buf.length.should == 0
313
- @buf << 'abc'
314
- @buf.length.should == 3
315
- end
316
-
317
- should 'know the end' do
318
- @buf.empty?.should == true
319
- end
320
-
321
- should 'read and write data' do
322
- @buf._write('abc')
323
- @buf.rewind
324
- @buf._read(2).should == 'ab'
325
- @buf._read(1).should == 'c'
326
- end
327
-
328
- should 'raise on overflow' do
329
- lambda{ @buf._read(1) }.should.raise Buffer::Overflow
330
- end
331
-
332
- should 'raise on invalid types' do
333
- lambda{ @buf.read(:junk) }.should.raise Buffer::InvalidType
334
- lambda{ @buf.write(:junk, 1) }.should.raise Buffer::InvalidType
335
- end
336
-
337
- { :octet => 0b10101010,
338
- :short => 100,
339
- :long => 100_000_000,
340
- :longlong => 666_555_444_333_222_111,
341
- :shortstr => 'hello',
342
- :longstr => 'bye'*500,
343
- :timestamp => time = Time.at(Time.now.to_i),
344
- :table => { :this => 'is', :a => 'hash', :with => {:nested => 123, :and => time, :also => 123.456} },
345
- :bit => true
346
- }.each do |type, value|
347
-
348
- should "read and write a #{type}" do
349
- @buf.write(type, value)
350
- @buf.rewind
351
- @buf.read(type).should == value
352
- @buf.should.be.empty
353
- end
354
-
355
- end
356
-
357
- should 'read and write multiple bits' do
358
- bits = [true, false, false, true, true, false, false, true, true, false]
359
- @buf.write(:bit, bits)
360
- @buf.write(:octet, 100)
361
-
362
- @buf.rewind
363
-
364
- bits.map do
365
- @buf.read(:bit)
366
- end.should == bits
367
- @buf.read(:octet).should == 100
368
- end
369
-
370
- should 'read and write properties' do
371
- properties = ([
372
- [:octet, 1],
373
- [:shortstr, 'abc'],
374
- [:bit, true],
375
- [:bit, false],
376
- [:shortstr, nil],
377
- [:timestamp, nil],
378
- [:table, { :a => 'hash' }],
379
- ]*5).sort_by{rand}
380
-
381
- @buf.write(:properties, properties)
382
- @buf.rewind
383
- @buf.read(:properties, *properties.map{|type,_| type }).should == properties.map{|_,value| value }
384
- @buf.should.be.empty
385
- end
386
-
387
- should 'do transactional reads with #extract' do
388
- @buf.write :octet, 8
389
- orig = @buf.to_s
390
-
391
- @buf.rewind
392
- @buf.extract do |b|
393
- b.read :octet
394
- b.read :short
395
- end
396
-
397
- @buf.pos.should == 0
398
- @buf.data.should == orig
399
- end
400
- end
401
- end
File without changes
@@ -0,0 +1,62 @@
1
+ module Carrot::AMQP
2
+ class Frame #:nodoc: all
3
+ def initialize payload = nil, channel = 0
4
+ @channel, @payload = channel, payload
5
+ end
6
+ attr_accessor :channel, :payload
7
+
8
+ def id
9
+ self.class::ID
10
+ end
11
+
12
+ def to_binary
13
+ buf = Buffer.new
14
+ buf.write :octet, id
15
+ buf.write :short, channel
16
+ buf.write :longstr, payload
17
+ buf.write :octet, FOOTER
18
+ buf.rewind
19
+ buf
20
+ end
21
+
22
+ def to_s
23
+ to_binary.to_s
24
+ end
25
+
26
+ def == frame
27
+ [ :id, :channel, :payload ].inject(true) do |eql, field|
28
+ eql and __send__(field) == frame.__send__(field)
29
+ end
30
+ end
31
+
32
+ class Invalid < StandardError; end
33
+
34
+ class Method
35
+ def initialize payload = nil, channel = 0
36
+ super
37
+ unless @payload.is_a? Protocol::Class::Method or @payload.nil?
38
+ @payload = Protocol.parse(@payload)
39
+ end
40
+ end
41
+ end
42
+
43
+ class Header
44
+ def initialize payload = nil, channel = 0
45
+ super
46
+ unless @payload.is_a? Protocol::Header or @payload.nil?
47
+ @payload = Protocol::Header.new(@payload)
48
+ end
49
+ end
50
+ end
51
+
52
+ class Body; end
53
+
54
+ def self.parse(buf)
55
+ buf = Buffer.new(buf) unless buf.is_a? Buffer
56
+ buf.extract do
57
+ id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
58
+ Frame.types[id].new(payload, channel) if footer == FOOTER
59
+ end
60
+ end
61
+ end
62
+ end
File without changes
@@ -156,54 +156,3 @@ module Carrot::AMQP
156
156
  #:stopdoc:
157
157
  end
158
158
  end
159
-
160
- if $0 =~ /bacon/ or $0 == __FILE__
161
- require 'bacon'
162
- include AMQP
163
-
164
- describe Protocol do
165
- should 'instantiate methods with arguments' do
166
- meth = Protocol::Connection::StartOk.new nil, 'PLAIN', nil, 'en_US'
167
- meth.locale.should == 'en_US'
168
- end
169
-
170
- should 'instantiate methods with named parameters' do
171
- meth = Protocol::Connection::StartOk.new :locale => 'en_US',
172
- :mechanism => 'PLAIN'
173
- meth.locale.should == 'en_US'
174
- end
175
-
176
- should 'convert methods to binary' do
177
- meth = Protocol::Connection::Secure.new :challenge => 'secret'
178
- meth.to_binary.should.be.kind_of? Buffer
179
-
180
- meth.to_s.should == [ 10, 20, 6, 'secret' ].pack('nnNa*')
181
- end
182
-
183
- should 'convert binary to method' do
184
- orig = Protocol::Connection::Secure.new :challenge => 'secret'
185
- copy = Protocol.parse orig.to_binary
186
- orig.should == copy
187
- end
188
-
189
- should 'convert headers to binary' do
190
- head = Protocol::Header.new Protocol::Basic,
191
- size = 5,
192
- weight = 0,
193
- :content_type => 'text/json',
194
- :delivery_mode => 1,
195
- :priority => 1
196
- head.to_s.should == [ 60, weight, 0, size, 0b1001_1000_0000_0000, 9, 'text/json', 1, 1 ].pack('nnNNnCa*CC')
197
- end
198
-
199
- should 'convert binary to header' do
200
- orig = Protocol::Header.new Protocol::Basic,
201
- size = 5,
202
- weight = 0,
203
- :content_type => 'text/json',
204
- :delivery_mode => 1,
205
- :priority => 1
206
- Protocol::Header.new(orig.to_binary).should == orig
207
- end
208
- end
209
- end
@@ -1,14 +1,16 @@
1
1
  module Carrot::AMQP
2
2
  class Queue
3
3
  attr_reader :name, :carrot
4
- attr_accessor :delivery_tag
4
+ attr_accessor :delivery_tag, :opts
5
5
 
6
6
  def initialize(carrot, name, opts = {})
7
7
  @opts = opts
8
8
  @name = name
9
9
  @carrot = carrot
10
+
11
+ @opts[:queue] = name
10
12
  server.send_frame(
11
- Protocol::Queue::Declare.new({ :queue => name, :nowait => true }.merge(opts))
13
+ Protocol::Queue::Declare.new(@opts.merge(:nowait => true))
12
14
  )
13
15
  end
14
16
 
@@ -50,9 +52,9 @@ module Carrot::AMQP
50
52
  status.last
51
53
  end
52
54
 
53
- def status(opts = {}, &blk)
55
+ def status
54
56
  server.send_frame(
55
- Protocol::Queue::Declare.new({ :queue => name, :passive => true }.merge(opts))
57
+ Protocol::Queue::Declare.new(opts)
56
58
  )
57
59
  method = server.next_method
58
60
  return [nil, nil] if method.kind_of?(Protocol::Connection::Close)
@@ -2,6 +2,12 @@ require 'socket'
2
2
  require 'thread'
3
3
  require 'timeout'
4
4
 
5
+ begin
6
+ require 'openssl'
7
+ rescue LoadError
8
+ warn "Unable to load SSL extension - you will be unable to make ssl connections."
9
+ end
10
+
5
11
  module Carrot::AMQP
6
12
  class Server
7
13
  CONNECT_TIMEOUT = 1.0
@@ -23,6 +29,9 @@ module Carrot::AMQP
23
29
  @insist = opts[:insist]
24
30
  @status = 'NOT CONNECTED'
25
31
 
32
+ @use_ssl = !!opts[:ssl]
33
+ @ssl_verify = opts[:ssl_verify] || OpenSSL::SSL::VERIFY_PEER
34
+
26
35
  @multithread = opts[:multithread]
27
36
  start_session
28
37
  end
@@ -93,6 +102,23 @@ module Carrot::AMQP
93
102
  end
94
103
  end
95
104
 
105
+ def start_ssl
106
+ unless defined?(OpenSSL)
107
+ raise "SSL Extension not installed"
108
+ end
109
+
110
+ ctx = OpenSSL::SSL::SSLContext.new
111
+ ctx.verify_mode = @ssl_verify
112
+
113
+ @socket = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
114
+ @socket.sync_close = true
115
+ @socket.connect
116
+
117
+ if ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE
118
+ @socket.post_connection_check(@host)
119
+ end
120
+ end
121
+
96
122
  def socket
97
123
  return @socket if @socket and not @socket.closed?
98
124
 
@@ -106,6 +132,9 @@ module Carrot::AMQP
106
132
  if Socket.constants.include? 'TCP_NODELAY'
107
133
  @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
108
134
  end
135
+
136
+ start_ssl if @use_ssl
137
+
109
138
  @status = 'CONNECTED'
110
139
  rescue SocketError, SystemCallError, IOError, Timeout::Error => e
111
140
  msg = e.message << " - #{@host}:#{@port}"
File without changes
@@ -0,0 +1,122 @@
1
+ require 'test_helper'
2
+ require 'carrot/amqp/buffer'
3
+
4
+ module Carrot::AMQP
5
+ context 'Buffer' do
6
+ setup do
7
+ @buf = Buffer.new
8
+ end
9
+
10
+ test 'have contents' do
11
+ assert_equal '', @buf.contents
12
+ end
13
+
14
+ test 'initialize with data' do
15
+ @buf = Buffer.new('abc')
16
+ assert_equal 'abc', @buf.contents
17
+ end
18
+
19
+ test 'append raw data' do
20
+ @buf << 'abc'
21
+ @buf << 'def'
22
+ assert_equal 'abcdef', @buf.contents
23
+ end
24
+
25
+ test 'append other buffers' do
26
+ @buf << Buffer.new('abc')
27
+ assert_equal 'abc', @buf.contents
28
+ end
29
+
30
+ test 'have a position' do
31
+ assert_equal 0, @buf.pos
32
+ end
33
+
34
+ test 'have a length' do
35
+ assert_equal 0, @buf.length
36
+ @buf << 'abc'
37
+ assert_equal 3, @buf.length
38
+ end
39
+
40
+ test 'know the end' do
41
+ assert_equal true, @buf.empty?
42
+ end
43
+
44
+ test 'read and write data' do
45
+ @buf._write('abc')
46
+ @buf.rewind
47
+ assert_equal 'ab', @buf._read(2)
48
+ assert_equal 'c', @buf._read(1)
49
+ end
50
+
51
+ test 'raise on overflow' do
52
+ assert_raise(Buffer::Overflow) { @buf._read(1) }
53
+ end
54
+
55
+ test 'raise on invalid types' do
56
+ assert_raise(Buffer::InvalidType) { @buf.read(:junk) }
57
+ assert_raise(Buffer::InvalidType) { @buf.write(:junk, 1) }
58
+ end
59
+
60
+ { :octet => 0b10101010,
61
+ :short => 100,
62
+ :long => 100_000_000,
63
+ :longlong => 666_555_444_333_222_111,
64
+ :shortstr => 'hello',
65
+ :longstr => 'bye'*500,
66
+ :timestamp => time = Time.at(Time.now.to_i),
67
+ :table => { :this => 'is', :a => 'hash', :with => {:nested => 123, :and => time, :also => 123.456} },
68
+ :bit => true
69
+ }.each do |type, value|
70
+
71
+ test "read and write a #{type}" do
72
+ @buf.write(type, value)
73
+ @buf.rewind
74
+ assert_equal value, @buf.read(type)
75
+ assert_equal true, @buf.empty?
76
+ end
77
+
78
+ end
79
+
80
+ test 'read and write multiple bits' do
81
+ bits = [true, false, false, true, true, false, false, true, true, false]
82
+ @buf.write(:bit, bits)
83
+ @buf.write(:octet, 100)
84
+
85
+ @buf.rewind
86
+
87
+ assert_equal bits, bits.collect{ @buf.read(:bit) }
88
+ assert_equal 100, @buf.read(:octet)
89
+ end
90
+
91
+ test 'read and write properties' do
92
+ properties = ([
93
+ [:octet, 1],
94
+ [:shortstr, 'abc'],
95
+ [:bit, true],
96
+ [:bit, false],
97
+ [:shortstr, nil],
98
+ [:timestamp, nil],
99
+ [:table, { :a => 'hash' }],
100
+ ]*5).sort_by{rand}
101
+
102
+ @buf.write(:properties, properties)
103
+ @buf.rewind
104
+ assert_equal properties.map{|_,value| value }, @buf.read(:properties, *properties.map{|type,_| type })
105
+ assert_equal true, @buf.empty?
106
+ end
107
+
108
+ test 'do transactional reads with #extract' do
109
+ @buf.write :octet, 8
110
+ orig = @buf.to_s
111
+
112
+ @buf.rewind
113
+ @buf.extract do |b|
114
+ b.read :octet
115
+ b.read :short
116
+ end
117
+
118
+ assert_equal 0, @buf.pos
119
+ assert_equal orig, @buf.data
120
+ end
121
+ end
122
+ end
data/test/carrot_test.rb CHANGED
@@ -1,25 +1,23 @@
1
1
  require 'test_helper'
2
2
 
3
- class CarrotTest < Test::Unit::TestCase
3
+ context 'test queue' do
4
4
  TEST_QUEUE = '_carrot_test'
5
-
6
- test "simple server connection" do
7
- c = Carrot.new
5
+ setup do
6
+ @carrot = Carrot.new
7
+ @q = @carrot.queue(TEST_QUEUE)
8
+ @q.purge
8
9
  end
9
10
 
10
11
  test "large messages" do
11
12
  msg = 'a' * 1024 * 1024
12
- q = Carrot.queue(TEST_QUEUE)
13
- q.publish(msg)
14
- assert_equal msg, q.pop
13
+ @q.publish(msg)
14
+ assert_equal msg, @q.pop
15
15
  end
16
16
 
17
17
  test "reset" do
18
- c = Carrot.new
19
- q = c.queue(TEST_QUEUE)
20
- count = q.message_count
21
- q.publish('test')
22
- c.reset
23
- assert_equal count + 1, q.message_count
18
+ count = @q.message_count
19
+ @q.publish('test')
20
+ @carrot.reset
21
+ assert_equal count + 1, @q.message_count
24
22
  end
25
23
  end
@@ -0,0 +1,56 @@
1
+ require 'test_helper'
2
+
3
+ module Carrot::AMQP
4
+ context 'Frame' do
5
+ test 'handle basic frame types' do
6
+ assert_equal 1, Frame::Method.new.id
7
+ assert_equal 2, Frame::Header.new.id
8
+ assert_equal 3, Frame::Body.new.id
9
+ end
10
+
11
+ test 'convert method frames to binary' do
12
+ meth = Protocol::Connection::Secure.new :challenge => 'secret'
13
+
14
+ frame = Frame::Method.new(meth)
15
+ assert frame.to_binary.kind_of?(Buffer)
16
+ assert_equal [ 1, 0, meth.to_s.length, meth.to_s, 206 ].pack('CnNa*C'), frame.to_s
17
+ end
18
+
19
+ test 'convert binary to method frames' do
20
+ orig = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
21
+
22
+ copy = Frame.parse(orig.to_binary)
23
+ assert_equal orig, copy
24
+ end
25
+
26
+ test 'ignore partial frames until ready' do
27
+ frame = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
28
+ data = frame.to_s
29
+
30
+ buf = Buffer.new
31
+ assert_equal nil, Frame.parse(buf)
32
+
33
+ buf << data[0..5]
34
+ assert_equal nil, Frame.parse(buf)
35
+
36
+ buf << data[6..-1]
37
+ assert_equal frame, Frame.parse(buf)
38
+
39
+ assert_equal nil, Frame.parse(buf)
40
+ end
41
+
42
+ test 'convert header frames to binary' do
43
+ head = Protocol::Header.new(Protocol::Basic, :priority => 1)
44
+
45
+ frame = Frame::Header.new(head)
46
+ assert_equal [ 2, 0, head.to_s.length, head.to_s, 206 ].pack('CnNa*C'), frame.to_s
47
+ end
48
+
49
+ test 'convert binary to header frame' do
50
+ orig = Frame::Header.new Protocol::Header.new(Protocol::Basic, :priority => 1)
51
+
52
+ copy = Frame.parse(orig.to_binary)
53
+ assert_equal orig, copy
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ require 'test_helper'
2
+
3
+ module Carrot::AMQP
4
+ context 'Protocol' do
5
+ test 'instantiate methods with arguments' do
6
+ meth = Protocol::Connection::StartOk.new(nil, 'PLAIN', nil, 'en_US')
7
+ assert_equal 'en_US', meth.locale
8
+ end
9
+
10
+ test 'instantiate methods with named parameters' do
11
+ meth = Protocol::Connection::StartOk.new(:locale => 'en_US', :mechanism => 'PLAIN')
12
+ assert_equal 'en_US', meth.locale
13
+ end
14
+
15
+ test 'convert methods to binary' do
16
+ meth = Protocol::Connection::Secure.new(:challenge => 'secret')
17
+ assert meth.to_binary.kind_of?(Buffer)
18
+
19
+ assert_equal [ 10, 20, 6, 'secret' ].pack('nnNa*'), meth.to_s
20
+ end
21
+
22
+ test 'convert binary to method' do
23
+ orig = Protocol::Connection::Secure.new(:challenge => 'secret')
24
+ copy = Protocol.parse orig.to_binary
25
+ assert_equal copy, orig
26
+ end
27
+
28
+ test 'convert headers to binary' do
29
+ head = Protocol::Header.new(
30
+ Protocol::Basic,
31
+ size = 5,
32
+ weight = 0,
33
+ :content_type => 'text/json',
34
+ :delivery_mode => 1,
35
+ :priority => 1
36
+ )
37
+ assert_equal [ 60, weight, 0, size, 0b1001_1000_0000_0000, 9, 'text/json', 1, 1 ].pack('nnNNnCa*CC'), head.to_s
38
+ end
39
+
40
+ test 'convert binary to header' do
41
+ orig = Protocol::Header.new(
42
+ Protocol::Basic,
43
+ size = 5,
44
+ weight = 0,
45
+ :content_type => 'text/json',
46
+ :delivery_mode => 1,
47
+ :priority => 1
48
+ )
49
+ assert_equal orig, Protocol::Header.new(orig.to_binary)
50
+ end
51
+ end
52
+ end
data/test/test_helper.rb CHANGED
@@ -1,18 +1,27 @@
1
- require 'rubygems'
1
+ dir = File.dirname(File.expand_path(__FILE__))
2
+ $LOAD_PATH.unshift dir + '/../lib'
3
+ require 'carrot'
2
4
  require 'test/unit'
3
- #require 'shoulda'
4
- require 'mocha'
5
- require File.dirname(__FILE__) + '/../lib/carrot'
6
-
7
- class << Test::Unit::TestCase
8
- def test(name, &block)
9
- test_name = "test_#{name.gsub(/[\s\W]/,'_')}"
10
- raise ArgumentError, "#{test_name} is already defined" if self.instance_methods.include? test_name
11
- define_method test_name, &block
12
- end
5
+ require 'rubygems'
6
+ require 'pp'
13
7
 
14
- def xtest(name, &block)
15
- # no-op, an empty test method is defined to prevent "no tests in testcase" errors when all tests are disabled
16
- define_method(:test_disabled) { assert true }
8
+ ##
9
+ # test/spec/mini 3
10
+ # http://gist.github.com/25455
11
+ # chris@ozmm.org
12
+ # file:lib/test/spec/mini.rb
13
+ #
14
+ def context(*args, &block)
15
+ return super unless (name = args.first) && block
16
+ require 'test/unit'
17
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
18
+ def self.test(name, &block)
19
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
20
+ end
21
+ def self.xtest(*args) end
22
+ def self.setup(&block) define_method(:setup, &block) end
23
+ def self.teardown(&block) define_method(:teardown, &block) end
17
24
  end
25
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
26
+ klass.class_eval &block
18
27
  end
metadata CHANGED
@@ -1,117 +1,93 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: carrot
3
- version: !ruby/object:Gem::Version
4
- hash: 61
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 8
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ segments:
9
6
  - 1
10
- version: 0.8.1
7
+ - 0
8
+ - 0
9
+ prerelease: false
11
10
  platform: ruby
12
- authors:
11
+ authors:
13
12
  - Amos Elliston
14
- autorequire:
13
+ autorequire: !!null
15
14
  bindir: bin
16
15
  cert_chain: []
17
-
18
- date: 2010-11-01 00:00:00 -07:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: rcov
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
33
- type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
16
+ date: 2011-08-03 00:00:00.000000000 -07:00
17
+ default_executable: !!null
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
36
20
  name: mocha
37
- prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
21
+ requirement: &2152420380 !ruby/object:Gem::Requirement
39
22
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ segments:
45
28
  - 0
46
- version: "0"
47
29
  type: :development
48
- version_requirements: *id002
30
+ prerelease: false
31
+ version_requirements: *2152420380
49
32
  description: A synchronous version of the ruby amqp client
50
33
  email: amos@geni.com
51
34
  executables: []
52
-
53
35
  extensions: []
54
-
55
- extra_rdoc_files:
36
+ extra_rdoc_files:
56
37
  - LICENSE
57
38
  - README.markdown
58
- files:
59
- - .gitignore
39
+ files:
60
40
  - LICENSE
61
41
  - README.markdown
62
42
  - Rakefile
63
43
  - VERSION.yml
64
44
  - carrot.gemspec
65
- - lib/amqp/buffer.rb
66
- - lib/amqp/exchange.rb
67
- - lib/amqp/frame.rb
68
- - lib/amqp/header.rb
69
- - lib/amqp/protocol.rb
70
- - lib/amqp/queue.rb
71
- - lib/amqp/server.rb
72
- - lib/amqp/spec.rb
73
45
  - lib/carrot.rb
46
+ - lib/carrot/amqp/buffer.rb
47
+ - lib/carrot/amqp/exchange.rb
48
+ - lib/carrot/amqp/frame.rb
49
+ - lib/carrot/amqp/header.rb
50
+ - lib/carrot/amqp/protocol.rb
51
+ - lib/carrot/amqp/queue.rb
52
+ - lib/carrot/amqp/server.rb
53
+ - lib/carrot/amqp/spec.rb
74
54
  - lib/examples/simple_pop.rb
75
55
  - protocol/amqp-0.8.json
76
56
  - protocol/amqp-0.8.xml
77
57
  - protocol/codegen.rb
78
58
  - protocol/doc.txt
59
+ - test/buffer_test.rb
79
60
  - test/carrot_test.rb
61
+ - test/frame_test.rb
62
+ - test/protocol_test.rb
80
63
  - test/test_helper.rb
81
64
  has_rdoc: true
82
65
  homepage: http://github.com/famoseagle/carrot
83
66
  licenses: []
84
-
85
- post_install_message:
86
- rdoc_options:
87
- - --charset=UTF-8
88
- require_paths:
67
+ post_install_message: !!null
68
+ rdoc_options: []
69
+ require_paths:
89
70
  - lib
90
- required_ruby_version: !ruby/object:Gem::Requirement
71
+ required_ruby_version: !ruby/object:Gem::Requirement
91
72
  none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- hash: 3
96
- segments:
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ segments:
97
78
  - 0
98
- version: "0"
99
- required_rubygems_version: !ruby/object:Gem::Requirement
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
80
  none: false
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- hash: 3
105
- segments:
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ segments:
106
86
  - 0
107
- version: "0"
108
87
  requirements: []
109
-
110
- rubyforge_project:
88
+ rubyforge_project: !!null
111
89
  rubygems_version: 1.3.7
112
- signing_key:
90
+ signing_key: !!null
113
91
  specification_version: 3
114
92
  summary: A synchronous version of the ruby amqp client
115
- test_files:
116
- - test/carrot_test.rb
117
- - test/test_helper.rb
93
+ test_files: []
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
data/lib/amqp/frame.rb DELETED
@@ -1,121 +0,0 @@
1
- module Carrot::AMQP
2
- class Frame #:nodoc: all
3
- def initialize payload = nil, channel = 0
4
- @channel, @payload = channel, payload
5
- end
6
- attr_accessor :channel, :payload
7
-
8
- def id
9
- self.class::ID
10
- end
11
-
12
- def to_binary
13
- buf = Buffer.new
14
- buf.write :octet, id
15
- buf.write :short, channel
16
- buf.write :longstr, payload
17
- buf.write :octet, FOOTER
18
- buf.rewind
19
- buf
20
- end
21
-
22
- def to_s
23
- to_binary.to_s
24
- end
25
-
26
- def == frame
27
- [ :id, :channel, :payload ].inject(true) do |eql, field|
28
- eql and __send__(field) == frame.__send__(field)
29
- end
30
- end
31
-
32
- class Invalid < StandardError; end
33
-
34
- class Method
35
- def initialize payload = nil, channel = 0
36
- super
37
- unless @payload.is_a? Protocol::Class::Method or @payload.nil?
38
- @payload = Protocol.parse(@payload)
39
- end
40
- end
41
- end
42
-
43
- class Header
44
- def initialize payload = nil, channel = 0
45
- super
46
- unless @payload.is_a? Protocol::Header or @payload.nil?
47
- @payload = Protocol::Header.new(@payload)
48
- end
49
- end
50
- end
51
-
52
- class Body; end
53
-
54
- def self.parse(buf)
55
- buf = Buffer.new(buf) unless buf.is_a? Buffer
56
- buf.extract do
57
- id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
58
- Frame.types[id].new(payload, channel) if footer == FOOTER
59
- end
60
- end
61
- end
62
- end
63
-
64
- if $0 =~ /bacon/ or $0 == __FILE__
65
- require 'rubygems'
66
- require 'bacon'
67
- include AMQP
68
-
69
- describe Frame do
70
- should 'handle basic frame types' do
71
- Frame::Method.new.id.should == 1
72
- Frame::Header.new.id.should == 2
73
- Frame::Body.new.id.should == 3
74
- end
75
-
76
- should 'convert method frames to binary' do
77
- meth = Protocol::Connection::Secure.new :challenge => 'secret'
78
-
79
- frame = Frame::Method.new(meth)
80
- frame.to_binary.should.be.kind_of? Buffer
81
- frame.to_s.should == [ 1, 0, meth.to_s.length, meth.to_s, 206 ].pack('CnNa*C')
82
- end
83
-
84
- should 'convert binary to method frames' do
85
- orig = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
86
-
87
- copy = Frame.parse(orig.to_binary)
88
- copy.should == orig
89
- end
90
-
91
- should 'ignore partial frames until ready' do
92
- frame = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
93
- data = frame.to_s
94
-
95
- buf = Buffer.new
96
- Frame.parse(buf).should == nil
97
-
98
- buf << data[0..5]
99
- Frame.parse(buf).should == nil
100
-
101
- buf << data[6..-1]
102
- Frame.parse(buf).should == frame
103
-
104
- Frame.parse(buf).should == nil
105
- end
106
-
107
- should 'convert header frames to binary' do
108
- head = Protocol::Header.new(Protocol::Basic, :priority => 1)
109
-
110
- frame = Frame::Header.new(head)
111
- frame.to_s.should == [ 2, 0, head.to_s.length, head.to_s, 206 ].pack('CnNa*C')
112
- end
113
-
114
- should 'convert binary to header frame' do
115
- orig = Frame::Header.new Protocol::Header.new(Protocol::Basic, :priority => 1)
116
-
117
- copy = Frame.parse(orig.to_binary)
118
- copy.should == orig
119
- end
120
- end
121
- end