Skip to content

Commit 2c07948

Browse files
Merge pull request #86 from eglitobias/modernize-ruby-3
Modernize gem for Ruby 3.0+
2 parents 8bbdf85 + 6e57bf9 commit 2c07948

13 files changed

Lines changed: 155 additions & 47 deletions

Gemfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ source "https://rubygems.org"
44

55

66
group :development do
7-
# excludes Windows, Rubinius and JRuby
8-
gem "ruby-prof", :platforms => [:mri_19, :mri_20, :mri_21]
7+
gem "ruby-prof", platforms: :mri
98

109
gem "rake"
1110
end

amq-protocol.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ Gem::Specification.new do |s|
77
s.name = "amq-protocol"
88
s.version = AMQ::Protocol::VERSION
99
s.authors = ["Jakub Stastny", "Michael S. Klishin", "Theo Hultberg", "Mark Abramov"]
10-
s.homepage = "http://github.com/ruby-amqp/amq-protocol"
10+
s.homepage = "https://github.com/ruby-amqp/amq-protocol"
1111
s.summary = "AMQP 0.9.1 encoding & decoding library."
1212
s.description = <<-DESC
1313
amq-protocol is an AMQP 0.9.1 serialization library for Ruby. It is not a
1414
client: the library only handles serialization and deserialization.
1515
DESC
1616
s.email = ["michael.s.klishin@gmail.com"]
1717
s.licenses = ["MIT"]
18-
s.required_ruby_version = Gem::Requirement.new(">= 2.2")
18+
s.required_ruby_version = ">= 3.0"
1919

2020
# files
2121
s.files = Dir.glob("lib/**/*.rb") + %w[LICENSE README.md ChangeLog.md]

lib/amq/bit_set.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def init_words(nbits)
113113

114114
def check_range(i)
115115
if i < 0 || i >= @nbits
116-
raise IndexError.new("Cannot access bit #{i} from a BitSet with #{@nbits} bits")
116+
raise IndexError, "Cannot access bit #{i} from a BitSet with #{@nbits} bits"
117117
end
118118
end # check_range
119119
end # BitSet

lib/amq/int_allocator.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,12 @@ class IntAllocator
2626
# @param [Integer] hi Upper boundary of the integer range available for allocation
2727
# @raise [ArgumentError] if upper boundary is not greater than the lower one
2828
def initialize(lo, hi)
29-
raise ArgumentError.new "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo
29+
raise ArgumentError, "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo
3030

3131
@hi = hi
3232
@lo = lo
3333

3434
@number_of_bits = hi - lo
35-
@range = Range.new(1, @number_of_bits)
3635
@free_set = BitSet.new(@number_of_bits)
3736
end # initialize(hi, lo)
3837

@@ -47,7 +46,7 @@ def allocate
4746

4847
if n = @free_set.next_clear_bit
4948

50-
if n < @hi - 1 then
49+
if n < @hi - 1
5150
@free_set.set(n)
5251
n + 1
5352
else

lib/amq/protocol/client.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,7 @@ def self.encode_body(body, channel, frame_size)
173173
limit = frame_size - 8
174174
return [BodyFrame.new(body, channel)] if body.bytesize < limit
175175

176-
# Otherwise String#slice on 1.9 will operate with code points,
177-
# and we need bytes. MK.
178-
body.force_encoding("ASCII-8BIT") if RUBY_VERSION.to_f >= 1.9 && body.encoding != Encoding::BINARY
176+
body.force_encoding("ASCII-8BIT") if body.encoding != Encoding::BINARY
179177

180178
array = Array.new
181179
while body && !body.empty?

lib/amq/protocol/frame.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def self.encoded_payload(payload)
2323

2424
# The channel number is 0 for all frames which are global to the connection and 1-65535 for frames that refer to specific channels.
2525
def self.encode_to_array(type, payload, channel)
26-
raise RuntimeError.new("Channel has to be 0 or an integer in range 1..65535 but was #{channel.inspect}") unless CHANNEL_RANGE.include?(channel)
27-
raise RuntimeError.new("Payload can't be nil") if payload.nil?
26+
raise RuntimeError, "Channel has to be 0 or an integer in range 1..65535 but was #{channel.inspect}" unless CHANNEL_RANGE.include?(channel)
27+
raise RuntimeError, "Payload can't be nil" if payload.nil?
2828
components = []
2929
components << [find_type(type), channel, payload.bytesize].pack(PACK_CHAR_UINT16_UINT32)
3030
components << encoded_payload(payload)
@@ -47,13 +47,13 @@ def self.new(original_type, *args)
4747
end
4848

4949
def self.find_type(type)
50-
type_id = if Symbol === type then TYPES[type] else type end
51-
raise FrameTypeError.new(TYPES_OPTIONS) if type == nil || !TYPES_REVERSE.has_key?(type_id)
50+
type_id = type.is_a?(Symbol) ? TYPES[type] : type
51+
raise FrameTypeError, TYPES_OPTIONS if type.nil? || !TYPES_REVERSE.key?(type_id)
5252
type_id
5353
end
5454

5555
def self.decode(*)
56-
raise NotImplementedError.new <<-EOF
56+
raise NotImplementedError, <<-EOF
5757
You are supposed to redefine this method, because it's dependent on used IO adapter.
5858
5959
This functionality is part of the https://github.com/ruby-amqp/amq-client library.
@@ -62,12 +62,12 @@ def self.decode(*)
6262

6363
# Optimized header decode using unpack1 for single values where appropriate
6464
def self.decode_header(header)
65-
raise EmptyResponseError if header == nil || header.empty?
65+
raise EmptyResponseError if header.nil? || header.empty?
6666

6767
# Use unpack for multiple values - this is the optimal approach
6868
type_id, channel, size = header.unpack(PACK_CHAR_UINT16_UINT32)
6969
type = TYPES_REVERSE[type_id]
70-
raise FrameTypeError.new(TYPES_OPTIONS) unless type
70+
raise FrameTypeError, TYPES_OPTIONS unless type
7171
[type, channel, size]
7272
end
7373

lib/amq/protocol/table_value_decoder.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def self.decode_array(data, initial_offset)
8383
v, offset = decode_array(data, offset)
8484
v
8585
else
86-
raise ArgumentError.new("unsupported type in a table value: #{type.inspect}, do not know how to decode!")
86+
raise ArgumentError, "unsupported type in a table value: #{type.inspect}, do not know how to decode!"
8787
end
8888

8989
ary << i

lib/amq/protocol/table_value_encoder.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def self.encode(value)
7272
accumulator << [0, value.to_i].pack(PACK_UCHAR_UINT32)
7373
end
7474
else
75-
raise ArgumentError.new("Unsupported value #{value.inspect} of type #{value.class.name}")
75+
raise ArgumentError, "Unsupported value #{value.inspect} of type #{value.class.name}"
7676
end # if
7777
end # case
7878

lib/amq/uri.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ class URI
3131

3232
def self.parse(connection_string)
3333
uri = ::URI.parse(connection_string)
34-
raise ArgumentError.new("Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK") unless %w{amqp amqps}.include?(uri.scheme)
34+
unless %w{amqp amqps}.include?(uri.scheme)
35+
raise ArgumentError, "Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK"
36+
end
3537

3638
opts = DEFAULTS.dup
3739

@@ -42,7 +44,9 @@ def self.parse(connection_string)
4244
opts[:port] = uri.port || AMQP_DEFAULT_PORTS[uri.scheme]
4345
opts[:ssl] = uri.scheme.to_s.downcase =~ /amqps/i # TODO: rename to tls
4446
if uri.path =~ %r{^/(.*)}
45-
raise ArgumentError.new("#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris") if $1.index('/')
47+
if $1.index('/')
48+
raise ArgumentError, "#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris"
49+
end
4650
opts[:vhost] = ::CGI::unescape($1)
4751
end
4852

@@ -63,15 +67,15 @@ def self.parse(connection_string)
6367

6468
%w(cacertfile certfile keyfile).each do |tls_option|
6569
if query_params[tls_option] && uri.scheme == "amqp"
66-
raise ArgumentError.new("The option '#{tls_option}' can only be used in URIs that use amqps schema")
70+
raise ArgumentError, "The option '#{tls_option}' can only be used in URIs that use amqps schema"
6771
else
6872
opts[tls_option.to_sym] = query_params[tls_option]
6973
end
7074
end
7175

7276
%w(verify fail_if_no_peer_cert).each do |tls_option|
7377
if query_params[tls_option] && uri.scheme == "amqp"
74-
raise ArgumentError.new("The option '#{tls_option}' can only be used in URIs that use amqps schema")
78+
raise ArgumentError, "The option '#{tls_option}' can only be used in URIs that use amqps schema"
7579
else
7680
opts[tls_option.to_sym] = as_boolean(query_params[tls_option])
7781
end

spec/amq/protocol/frame_spec.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ module Protocol
5555
it "should raise FrameTypeError if the type is not one of the accepted" do
5656
expect { Frame.new(10) }.to raise_error(FrameTypeError)
5757
end
58+
59+
it "returns the correct subclass for a valid type" do
60+
frame = Frame.new(:body, "test", 1)
61+
expect(frame).to be_a(BodyFrame)
62+
end
63+
end
64+
65+
describe ".decode" do
66+
it "raises NotImplementedError" do
67+
expect { Frame.decode("anything") }.to raise_error(NotImplementedError)
68+
end
5869
end
5970

6071
describe '#decode_header' do
@@ -65,6 +76,14 @@ module Protocol
6576
it 'raises EmptyResponseError if the header is nil' do
6677
expect { Frame.decode_header(nil) }.to raise_error(EmptyResponseError)
6778
end
79+
80+
it "returns type, channel and size for a valid header" do
81+
header = "\x03\x00\x01\x00\x00\x00\x04"
82+
type, channel, size = Frame.decode_header(header)
83+
expect(type).to eq(:body)
84+
expect(channel).to eq(1)
85+
expect(size).to eq(4)
86+
end
6887
end
6988

7089
describe HeaderFrame do
@@ -121,12 +140,14 @@ module Protocol
121140
end
122141

123142
describe MethodFrame do
143+
subject { MethodFrame.new("\x00\x3C\x00\x28\x00\x00\x00\x00\x00", 1) }
144+
145+
it "resolves method_class from payload" do
146+
expect(subject.method_class).to eq(AMQ::Protocol::Basic::Publish)
147+
end
148+
124149
it "is not final when method has content" do
125-
# Basic.Publish has content
126-
payload = "\x00\x3C\x00\x28\x00\x00\x00\x00\x00"
127-
frame = MethodFrame.new(payload, 1)
128-
# This will depend on the method class
129-
expect(frame).to respond_to(:final?)
150+
expect(subject.final?).to eq(false)
130151
end
131152
end
132153

0 commit comments

Comments
 (0)