Skip to content

Commit 0ee157d

Browse files
committed
Improve spec coverage for table decoding and frame handling
1 parent 300607c commit 0ee157d

3 files changed

Lines changed: 126 additions & 5 deletions

File tree

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

spec/amq/protocol/table_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,35 @@ module Protocol
188188
expect(output).to eq(1677)
189189
end
190190

191+
it "decodes TYPE_INTEGER (32-bit unsigned) from raw binary" do
192+
# "\x03key" = 1-byte key length + "key", then 'I' type + 4-byte uint32
193+
binary = [9].pack("N") + "\x03keyI" + [42].pack("N")
194+
expect(Table.decode(binary.force_encoding("BINARY"))).to eq("key" => 42)
195+
end
196+
197+
it "decodes TYPE_BYTE from raw binary" do
198+
# "\x01k" = 1-byte key length + "k", then 'b' type + 1-byte value
199+
binary = [4].pack("N") + "\x01kb\xFF"
200+
expect(Table.decode(binary.force_encoding("BINARY"))).to eq("k" => 255)
201+
end
202+
203+
it "decodes TYPE_SIGNED_16BIT from raw binary" do
204+
binary = [5].pack("N") + "\x01ks" + [1000].pack("s>")
205+
expect(Table.decode(binary.force_encoding("BINARY"))).to eq("k" => 1000)
206+
end
207+
208+
it "decodes TYPE_32BIT_FLOAT from raw binary" do
209+
binary = [7].pack("N") + "\x01kf" + [1.5].pack("f")
210+
result = Table.decode(binary.force_encoding("BINARY"))
211+
expect(result["k"]).to be_within(0.001).of(1.5)
212+
end
213+
214+
it "raises ArgumentError for unknown type bytes" do
215+
# "\x03key" key + unknown type '?'
216+
binary = [5].pack("N") + "\x03key?"
217+
expect { Table.decode(binary.force_encoding("BINARY")) }.to raise_error(ArgumentError, /Not a valid type/)
218+
end
219+
191220
it "is capable of decoding tables" do
192221
input = {
193222
"boolval" => true,

spec/amq/protocol/value_decoder_spec.rb

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,77 @@ module Protocol
178178
expect(value).to eq({"nested" => "value"})
179179
end
180180
end
181+
182+
describe ".decode_array type dispatch" do
183+
# Builds binary for decode_array(data, 1):
184+
# byte 0 = dummy (TYPE_ARRAY tag), bytes 1-4 = content length, bytes 5+ = elements.
185+
def array_binary(element_bytes)
186+
"\x00" + [element_bytes.bytesize].pack("N") + element_bytes
187+
end
188+
189+
it "decodes TYPE_INTEGER (32-bit unsigned)" do
190+
data = array_binary("I" + [99].pack("N"))
191+
result, _ = described_class.decode_array(data, 1)
192+
expect(result).to eq([99])
193+
end
194+
195+
it "decodes TYPE_DECIMAL" do
196+
data = array_binary("D" + "\x02" + [314].pack("N"))
197+
result, _ = described_class.decode_array(data, 1)
198+
expect(result.first).to be_a(BigDecimal)
199+
expect(result.first).to eq(BigDecimal("3.14"))
200+
end
201+
202+
it "decodes TYPE_TIME" do
203+
ts = 1_700_000_000
204+
data = array_binary("T" + [ts].pack("Q>"))
205+
result, _ = described_class.decode_array(data, 1)
206+
expect(result.first.to_i).to eq(ts)
207+
end
208+
209+
it "decodes TYPE_BYTE_ARRAY" do
210+
data = array_binary("x" + [3].pack("N") + "foo")
211+
result, _ = described_class.decode_array(data, 1)
212+
expect(result).to eq(["foo"])
213+
end
214+
215+
it "decodes TYPE_32BIT_FLOAT" do
216+
data = array_binary("f" + [1.5].pack("f"))
217+
result, _ = described_class.decode_array(data, 1)
218+
expect(result.first).to be_within(0.001).of(1.5)
219+
end
220+
221+
it "decodes TYPE_BOOLEAN" do
222+
# Two booleans make content length 4, enough for the loop to enter once
223+
data = array_binary("t\x01t\x00")
224+
result, _ = described_class.decode_array(data, 1)
225+
expect(result).to include(true)
226+
end
227+
228+
it "decodes TYPE_BYTE" do
229+
data = array_binary("b\xFFb\x01")
230+
result, _ = described_class.decode_array(data, 1)
231+
expect(result).to include(255)
232+
end
233+
234+
it "decodes TYPE_SIGNED_16BIT" do
235+
data = array_binary("s" + [1000].pack("s>") + "s" + [2000].pack("s>"))
236+
result, _ = described_class.decode_array(data, 1)
237+
expect(result).to include(1000)
238+
end
239+
240+
it "decodes TYPE_VOID as nil" do
241+
data = array_binary("VVVV")
242+
result, _ = described_class.decode_array(data, 1)
243+
expect(result).to include(nil)
244+
end
245+
246+
it "raises ArgumentError for unsupported types" do
247+
data = array_binary("?\x00\x00\x00")
248+
expect { described_class.decode_array(data, 1) }
249+
.to raise_error(ArgumentError, /unsupported type/)
250+
end
251+
end
181252
end
182253
end
183254
end

0 commit comments

Comments
 (0)