amq-protocol 0.7.0.alpha7 → 0.7.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +9 -2
- data/Gemfile +0 -2
- data/lib/amq/protocol/table.rb +10 -5
- data/lib/amq/protocol/version.rb +1 -1
- data/spec/amq/protocol/table_spec.rb +39 -5
- metadata +22 -45
- data/CONTRIBUTORS +0 -4
- data/examples/00_manual_test.rb +0 -139
data/.travis.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
# https://github.com/travis-ci/travis-ci/wiki/.travis.yml-options
|
2
|
+
bundler_args: --without development
|
1
3
|
script: "bundle exec rspec spec"
|
2
4
|
rvm:
|
3
5
|
- 1.8.7
|
4
|
-
- 1.8.7-p174
|
5
6
|
- 1.9.2
|
6
7
|
- jruby
|
7
8
|
- rbx
|
8
|
-
- ree
|
9
|
+
- ree
|
10
|
+
- 1.8.7-p174
|
11
|
+
notifications:
|
12
|
+
recipients:
|
13
|
+
- jakub@rabbitmq.com
|
14
|
+
- michaelklishin@me.com
|
15
|
+
- markizko@gmail.com
|
data/Gemfile
CHANGED
data/lib/amq/protocol/table.rb
CHANGED
@@ -29,6 +29,10 @@ module AMQ
|
|
29
29
|
TYPE_BYTE_ARRAY = 'x'.freeze
|
30
30
|
TEN = '10'.freeze
|
31
31
|
|
32
|
+
BOOLEAN_TRUE = "\x01".freeze
|
33
|
+
BOOLEAN_FALSE = "\x00".freeze
|
34
|
+
|
35
|
+
|
32
36
|
def self.encode(table)
|
33
37
|
buffer = String.new
|
34
38
|
table ||= {}
|
@@ -47,10 +51,9 @@ module AMQ
|
|
47
51
|
when Float then
|
48
52
|
buffer << TYPE_64BIT_FLOAT
|
49
53
|
buffer << [value].pack(PACK_64BIT_FLOAT)
|
50
|
-
when
|
51
|
-
|
52
|
-
buffer <<
|
53
|
-
buffer << [value].pack(PACK_UINT32)
|
54
|
+
when true, false then
|
55
|
+
buffer << TYPE_BOOLEAN
|
56
|
+
buffer << (value ? BOOLEAN_TRUE : BOOLEAN_FALSE)
|
54
57
|
when Hash then
|
55
58
|
buffer << TYPE_HASH # TODO: encoding support
|
56
59
|
buffer << self.encode(value)
|
@@ -95,6 +98,7 @@ module AMQ
|
|
95
98
|
offset += key_length
|
96
99
|
type = data.slice(offset, 1)
|
97
100
|
offset += 1
|
101
|
+
|
98
102
|
case type
|
99
103
|
when TYPE_STRING
|
100
104
|
length = data.slice(offset, 4).unpack(PACK_UINT32).first
|
@@ -119,8 +123,9 @@ module AMQ
|
|
119
123
|
when TYPE_BOOLEAN
|
120
124
|
value = data.slice(offset, 2)
|
121
125
|
integer = value.unpack(PACK_CHAR).first # 0 or 1
|
122
|
-
value = integer == 1
|
126
|
+
value = (integer == 1)
|
123
127
|
offset += 1
|
128
|
+
value
|
124
129
|
when TYPE_SIGNED_8BIT then raise NotImplementedError.new
|
125
130
|
when TYPE_SIGNED_16BIT then raise NotImplementedError.new
|
126
131
|
when TYPE_SIGNED_64BIT then raise NotImplementedError.new
|
data/lib/amq/protocol/version.rb
CHANGED
@@ -48,12 +48,20 @@ module AMQ
|
|
48
48
|
Table.encode(nil).should eql(encoded_value)
|
49
49
|
end
|
50
50
|
|
51
|
-
it "should return \
|
52
|
-
Table.encode(:test => true).should eql("\x00\x00\x00\
|
51
|
+
it "should return \x00\x00\x00\a\x04testt\x01 for { :test => true }" do
|
52
|
+
Table.encode(:test => true).should eql("\x00\x00\x00\a\x04testt\x01")
|
53
53
|
end
|
54
54
|
|
55
|
-
it "should return \
|
56
|
-
Table.encode(:
|
55
|
+
it "should return \x00\x00\x00\a\x04testt\x00 for { :test => false }" do
|
56
|
+
Table.encode(:test => false).should eql("\x00\x00\x00\a\x04testt\x00")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return \"\x00\x00\x00\n\x04testI\x00\x00\x00\x01\" for { :coordinates => { :latitude => 59.35 } }" do
|
60
|
+
Table.encode(:coordinates => { :latitude => 59.35 }).should eql("\000\000\000#\vcoordinatesF\000\000\000\022\blatituded\315\314\314\314\314\254M@")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return \"\x00\x00\x00\n\x04testI\x00\x00\x00\x01\" for { :coordinates => { :longitude => 18.066667 } }" do
|
64
|
+
Table.encode(:coordinates => { :longitude => 18.066667 }).should eql("\000\000\000$\vcoordinatesF\000\000\000\023\tlongituded\361\270\250\026\021\0212@")
|
57
65
|
end
|
58
66
|
|
59
67
|
DATA.each do |data, encoded|
|
@@ -72,8 +80,34 @@ module AMQ
|
|
72
80
|
it "is capable of decoding what it encodes" do
|
73
81
|
Table.decode(Table.encode(data)).should == data
|
74
82
|
end
|
83
|
+
end # DATA.each
|
84
|
+
|
85
|
+
|
86
|
+
it "is capable of decoding booleans" do
|
87
|
+
input1 = { "boolval" => true }
|
88
|
+
Table.decode(Table.encode(input1)).should == input1
|
89
|
+
|
90
|
+
|
91
|
+
input2 = { "boolval" => false }
|
92
|
+
Table.decode(Table.encode(input2)).should == input2
|
75
93
|
end
|
76
|
-
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
it "is capable of decoding tables" do
|
98
|
+
input = {
|
99
|
+
"boolval" => true,
|
100
|
+
"intval" => 1,
|
101
|
+
"strval" => "Test",
|
102
|
+
"timestampval" => Time.parse("2011-07-14 01:17:46 +0400"),
|
103
|
+
"floatval" => 3.14,
|
104
|
+
"longval" => 912598613,
|
105
|
+
"hashval" => { "protocol" => "AMQP091" }
|
106
|
+
}
|
107
|
+
Table.decode(Table.encode(input)).should == input
|
108
|
+
end
|
109
|
+
|
110
|
+
end # describe
|
77
111
|
end
|
78
112
|
end
|
79
113
|
end
|
metadata
CHANGED
@@ -1,17 +1,10 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: amq-protocol
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0.beta1
|
5
5
|
prerelease: 6
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 7
|
9
|
-
- 0
|
10
|
-
- alpha
|
11
|
-
- 7
|
12
|
-
version: 0.7.0.alpha7
|
13
6
|
platform: ruby
|
14
|
-
authors:
|
7
|
+
authors:
|
15
8
|
- Jakub Stastny
|
16
9
|
- Michael S. Klishin
|
17
10
|
- Theo Hultberg
|
@@ -19,26 +12,23 @@ authors:
|
|
19
12
|
autorequire:
|
20
13
|
bindir: bin
|
21
14
|
cert_chain: []
|
22
|
-
|
23
|
-
date: 2011-06-16 00:00:00 Z
|
15
|
+
date: 2011-07-13 00:00:00.000000000Z
|
24
16
|
dependencies: []
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
description: ! " amq-protocol is an AMQP 0.9.1 serialization library for Ruby. It
|
18
|
+
is not an\n AMQP client: amq-protocol only handles serialization and deserialization.\n
|
19
|
+
\ If you want to write your own AMQP client, this gem can help you with that.\n"
|
20
|
+
email:
|
28
21
|
- michael@novemberain.com
|
29
22
|
- stastny@101ideas.cz
|
30
23
|
executables: []
|
31
|
-
|
32
24
|
extensions: []
|
33
|
-
|
34
|
-
extra_rdoc_files:
|
25
|
+
extra_rdoc_files:
|
35
26
|
- README.textile
|
36
|
-
files:
|
27
|
+
files:
|
37
28
|
- .gitignore
|
38
29
|
- .gitmodules
|
39
30
|
- .rspec
|
40
31
|
- .travis.yml
|
41
|
-
- CONTRIBUTORS
|
42
32
|
- Gemfile
|
43
33
|
- LICENSE
|
44
34
|
- PROFILING.md
|
@@ -49,7 +39,6 @@ files:
|
|
49
39
|
- amqp_0.9.1_changes.json
|
50
40
|
- codegen.py
|
51
41
|
- codegen_helpers.py
|
52
|
-
- examples/00_manual_test.rb
|
53
42
|
- irb.rb
|
54
43
|
- lib/amq/hacks.rb
|
55
44
|
- lib/amq/protocol.rb
|
@@ -75,38 +64,26 @@ files:
|
|
75
64
|
- tasks.rb
|
76
65
|
homepage: http://github.com/ruby-amqp/amq-protocol
|
77
66
|
licenses: []
|
78
|
-
|
79
67
|
post_install_message:
|
80
68
|
rdoc_options: []
|
81
|
-
|
82
|
-
require_paths:
|
69
|
+
require_paths:
|
83
70
|
- lib
|
84
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
72
|
none: false
|
86
|
-
requirements:
|
87
|
-
- -
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
|
90
|
-
|
91
|
-
- 0
|
92
|
-
version: "0"
|
93
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
78
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
hash: 25
|
99
|
-
segments:
|
100
|
-
- 1
|
101
|
-
- 3
|
102
|
-
- 1
|
79
|
+
requirements:
|
80
|
+
- - ! '>'
|
81
|
+
- !ruby/object:Gem::Version
|
103
82
|
version: 1.3.1
|
104
83
|
requirements: []
|
105
|
-
|
106
84
|
rubyforge_project: amq-protocol
|
107
|
-
rubygems_version: 1.8.
|
85
|
+
rubygems_version: 1.8.4
|
108
86
|
signing_key:
|
109
87
|
specification_version: 3
|
110
88
|
summary: AMQP 0.9.1 encoder & decoder.
|
111
89
|
test_files: []
|
112
|
-
|
data/CONTRIBUTORS
DELETED
data/examples/00_manual_test.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
# Usage:
|
5
|
-
# ./examples/00_manual_test.rb
|
6
|
-
# ./examples/00_manual_test.rb 5673
|
7
|
-
|
8
|
-
require "socket"
|
9
|
-
require_relative "../lib/amq/protocol/client.rb"
|
10
|
-
|
11
|
-
include AMQ::Protocol
|
12
|
-
|
13
|
-
# Stolen from amq-client:
|
14
|
-
class AMQ::Protocol::Frame
|
15
|
-
def self.decode(io)
|
16
|
-
header = io.read(7)
|
17
|
-
type, channel, size = self.decode_header(header)
|
18
|
-
data = io.read(size + 1)
|
19
|
-
payload, frame_end = data[0..-2], data[-1]
|
20
|
-
|
21
|
-
if frame_end != FINAL_OCTET
|
22
|
-
raise "Frame has to end with #{FINAL_OCTET.inspect}!"
|
23
|
-
end
|
24
|
-
|
25
|
-
self.new(type, payload, channel)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# NOTE: this doesn't work with "localhost", I don't know why:
|
30
|
-
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
31
|
-
sockaddr = Socket.pack_sockaddr_in((ARGV.first || 5672).to_i, "127.0.0.1")
|
32
|
-
|
33
|
-
# helpers
|
34
|
-
def socket.encode(klass, *args)
|
35
|
-
STDERR.puts "#{klass}.encode(#{args.inspect[1..-2]})"
|
36
|
-
result = klass.encode(*args)
|
37
|
-
STDERR.puts "=> #{result}"
|
38
|
-
if result.is_a?(Frame)
|
39
|
-
self.write(result.encode)
|
40
|
-
else
|
41
|
-
data = result.inject("") do |buffer, frame|
|
42
|
-
self.write(frame.encode) ###
|
43
|
-
buffer += frame.encode
|
44
|
-
end
|
45
|
-
# self.write(data)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def socket.decode
|
50
|
-
frame = Frame.decode(self)
|
51
|
-
STDERR.puts "Frame.decode(#{self.inspect})"
|
52
|
-
STDERR.puts "=> #{frame.inspect}"
|
53
|
-
STDERR.puts "frame.decode_payload"
|
54
|
-
STDERR.puts "=> #{res = frame.decode_payload}\n\n"
|
55
|
-
return res
|
56
|
-
end
|
57
|
-
|
58
|
-
begin
|
59
|
-
socket.connect(sockaddr)
|
60
|
-
rescue Errno::ECONNREFUSED
|
61
|
-
abort "Don't forget to start an AMQP broker first!"
|
62
|
-
end
|
63
|
-
|
64
|
-
begin
|
65
|
-
# AMQP preamble
|
66
|
-
puts "Sending AMQP preamble (#{AMQ::Protocol::PREAMBLE.inspect})\n\n"
|
67
|
-
socket.write AMQ::Protocol::PREAMBLE
|
68
|
-
|
69
|
-
# Connection.Start/Connection.Start-Ok
|
70
|
-
connection_start_response = socket.decode
|
71
|
-
socket.encode Connection::StartOk, {client: "AMQ Protocol"}, "PLAIN", "\0guest\0guest", "en_GB"
|
72
|
-
|
73
|
-
# Connection.Tune/Connection.Tune-Ok
|
74
|
-
connection_tune_response = socket.decode
|
75
|
-
channel_max = connection_tune_response.channel_max
|
76
|
-
frame_max = connection_tune_response.frame_max
|
77
|
-
heartbeat = connection_tune_response.heartbeat
|
78
|
-
socket.encode Connection::TuneOk, channel_max, frame_max, heartbeat
|
79
|
-
puts "Max agreed frame size: #{frame_max}"
|
80
|
-
|
81
|
-
# Connection.Open/Connection.Open-Ok
|
82
|
-
socket.encode Connection::Open, "/"
|
83
|
-
connection_open_ok_response = socket.decode
|
84
|
-
|
85
|
-
begin
|
86
|
-
# Channel.Open/Channel.Open-Ok
|
87
|
-
socket.encode Channel::Open, 1, ""
|
88
|
-
channel_open_ok_response = socket.decode
|
89
|
-
|
90
|
-
begin
|
91
|
-
# Exchange.Declare/Exchange.Declare-Ok
|
92
|
-
socket.encode Exchange::Declare, 1, "tasks", "fanout", false, false, false, false, false, {}
|
93
|
-
exchange_declare_ok_response = socket.decode
|
94
|
-
|
95
|
-
# Queue.Declare/Queue.Declare-Ok
|
96
|
-
socket.encode Queue::Declare, 1, "", false, false, false, false, false, {}
|
97
|
-
queue_declare_ok_response = socket.decode
|
98
|
-
|
99
|
-
puts "Queue name: #{queue_declare_ok_response.queue.inspect}"
|
100
|
-
|
101
|
-
# Queue.Bind/Queue.Bind-Ok
|
102
|
-
socket.encode Queue::Bind, 1, queue_declare_ok_response.queue, "tasks", "", false, {}
|
103
|
-
queue_bind_ok_response = socket.decode
|
104
|
-
|
105
|
-
# Basic.Consume
|
106
|
-
socket.encode Basic::Consume, 1, queue_declare_ok_response.queue, "", false, false, false, false, Hash.new
|
107
|
-
|
108
|
-
# Basic.Publish
|
109
|
-
socket.encode Basic::Publish, 1, "this is a payload", {content_type: "text/plain"}, "tasks", "", false, false, frame_max
|
110
|
-
|
111
|
-
# Basic.Consume-Ok
|
112
|
-
basic_consume_ok_response = socket.decode
|
113
|
-
puts "Consumed successfully, consumer tag: #{basic_consume_ok_response.consumer_tag}"
|
114
|
-
|
115
|
-
# Basic.Deliver
|
116
|
-
basic_deliver = socket.decode
|
117
|
-
basic_deliver_header = socket.decode # header frame: {}
|
118
|
-
basic_deliver_body = socket.decode # body frame: "this is a payload"
|
119
|
-
puts "[Received] headers: #{basic_deliver_header.inspect}, payload: #{basic_deliver_body.inspect}"
|
120
|
-
ensure
|
121
|
-
# Channel.Close/Channel.Close-Ok
|
122
|
-
socket.encode Channel::Close, 1, 200, "bye", 0, 0
|
123
|
-
channel_close_ok_response = socket.decode
|
124
|
-
end
|
125
|
-
ensure
|
126
|
-
# Connection.Close/Connection.Close-Ok
|
127
|
-
socket.encode Connection::Close, 200, "", 0, 0
|
128
|
-
close_ok_response = socket.decode
|
129
|
-
end
|
130
|
-
rescue Exception => exception
|
131
|
-
STDERR.puts "\n\e[1;31m[#{exception.class}] #{exception.message}\e[0m"
|
132
|
-
exception.backtrace.each do |line|
|
133
|
-
line = "\e[0;36m#{line}\e[0m" if line.match(Regexp::quote(File.basename(__FILE__)))
|
134
|
-
STDERR.puts " - " + line
|
135
|
-
end
|
136
|
-
exit 1 # Yes, this works with the ensure block, even though the rescue block run first. Magic.
|
137
|
-
ensure
|
138
|
-
socket.close
|
139
|
-
end
|