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 +2 -2
- data/Rakefile +0 -8
- data/VERSION.yml +5 -5
- data/carrot.gemspec +28 -34
- data/lib/carrot.rb +8 -8
- data/lib/{amqp → carrot/amqp}/buffer.rb +0 -125
- data/lib/{amqp → carrot/amqp}/exchange.rb +0 -0
- data/lib/carrot/amqp/frame.rb +62 -0
- data/lib/{amqp → carrot/amqp}/header.rb +0 -0
- data/lib/{amqp → carrot/amqp}/protocol.rb +0 -51
- data/lib/{amqp → carrot/amqp}/queue.rb +6 -4
- data/lib/{amqp → carrot/amqp}/server.rb +29 -0
- data/lib/{amqp → carrot/amqp}/spec.rb +0 -0
- data/test/buffer_test.rb +122 -0
- data/test/carrot_test.rb +11 -13
- data/test/frame_test.rb +56 -0
- data/test/protocol_test.rb +52 -0
- data/test/test_helper.rb +23 -14
- metadata +52 -76
- data/.gitignore +0 -3
- data/lib/amqp/frame.rb +0 -121
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]
|
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]
|
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:
|
3
|
-
:minor:
|
4
|
-
:
|
5
|
-
:
|
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
|
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
|
+
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{
|
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
|
-
|
17
|
+
"README.markdown"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
-
"
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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(
|
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
|
55
|
+
def status
|
54
56
|
server.send_frame(
|
55
|
-
Protocol::Queue::Declare.new(
|
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
|
data/test/buffer_test.rb
ADDED
@@ -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
|
-
|
3
|
+
context 'test queue' do
|
4
4
|
TEST_QUEUE = '_carrot_test'
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
13
|
-
q.
|
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
|
-
|
19
|
-
q
|
20
|
-
|
21
|
-
q.
|
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
|
data/test/frame_test.rb
ADDED
@@ -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
|
-
|
1
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
2
|
+
$LOAD_PATH.unshift dir + '/../lib'
|
3
|
+
require 'carrot'
|
2
4
|
require 'test/unit'
|
3
|
-
|
4
|
-
require '
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 8
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
segments:
|
9
6
|
- 1
|
10
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
86
|
-
|
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
|
-
|
96
|
-
segments:
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
segments:
|
97
78
|
- 0
|
98
|
-
|
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
|
-
|
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
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
|