amq-protocol 2.4.0 → 2.5.1
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.
- checksums.yaml +4 -4
- data/ChangeLog.md +12 -5
- data/lib/amq/protocol/client.rb +30 -37
- data/lib/amq/protocol/frame.rb +2 -0
- data/lib/amq/protocol/version.rb +1 -1
- metadata +3 -52
- data/.github/ISSUE_TEMPLATE.md +0 -18
- data/.github/workflows/ci.yml +0 -31
- data/.gitignore +0 -18
- data/.gitmodules +0 -3
- data/.rspec +0 -1
- data/.travis.yml +0 -17
- data/Gemfile +0 -27
- data/Rakefile +0 -55
- data/amq-protocol.gemspec +0 -27
- data/benchmarks/frame_encoding.rb +0 -75
- data/benchmarks/int_allocator.rb +0 -34
- data/benchmarks/method_encoding.rb +0 -198
- data/benchmarks/pack_unpack.rb +0 -158
- data/benchmarks/pure/body_framing_with_256k_payload.rb +0 -28
- data/benchmarks/pure/body_framing_with_2k_payload.rb +0 -28
- data/benchmarks/run_all.rb +0 -64
- data/benchmarks/table_encoding.rb +0 -110
- data/codegen/__init__.py +0 -0
- data/codegen/amqp_0.9.1_changes.json +0 -1
- data/codegen/codegen.py +0 -151
- data/codegen/codegen_helpers.py +0 -162
- data/codegen/protocol.rb.pytemplate +0 -320
- data/generate.rb +0 -24
- data/profiling/README.md +0 -9
- data/profiling/stackprof/body_framing_with_2k_payload.rb +0 -33
- data/spec/amq/bit_set_spec.rb +0 -249
- data/spec/amq/endianness_spec.rb +0 -23
- data/spec/amq/int_allocator_spec.rb +0 -136
- data/spec/amq/pack_spec.rb +0 -58
- data/spec/amq/protocol/basic_spec.rb +0 -325
- data/spec/amq/protocol/blank_body_encoding_spec.rb +0 -9
- data/spec/amq/protocol/channel_spec.rb +0 -127
- data/spec/amq/protocol/confirm_spec.rb +0 -41
- data/spec/amq/protocol/connection_spec.rb +0 -146
- data/spec/amq/protocol/constants_spec.rb +0 -10
- data/spec/amq/protocol/exceptions_spec.rb +0 -70
- data/spec/amq/protocol/exchange_spec.rb +0 -106
- data/spec/amq/protocol/float_32bit_spec.rb +0 -27
- data/spec/amq/protocol/frame_spec.rb +0 -156
- data/spec/amq/protocol/method_spec.rb +0 -43
- data/spec/amq/protocol/queue_spec.rb +0 -126
- data/spec/amq/protocol/table_spec.rb +0 -291
- data/spec/amq/protocol/tx_spec.rb +0 -55
- data/spec/amq/protocol/value_decoder_spec.rb +0 -183
- data/spec/amq/protocol/value_encoder_spec.rb +0 -161
- data/spec/amq/protocol_spec.rb +0 -812
- data/spec/amq/settings_spec.rb +0 -58
- data/spec/amq/uri_parsing_spec.rb +0 -287
- data/spec/spec_helper.rb +0 -29
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
require 'time'
|
|
2
|
-
|
|
3
|
-
module AMQ
|
|
4
|
-
module Protocol
|
|
5
|
-
RSpec.describe Table do
|
|
6
|
-
timestamp = Time.utc(2010, 12, 31, 23, 58, 59)
|
|
7
|
-
bigdecimal_1 = BigDecimal("1.0")
|
|
8
|
-
bigdecimal_2 = BigDecimal("5E-3")
|
|
9
|
-
|
|
10
|
-
DATA = {
|
|
11
|
-
{} => "\x00\x00\x00\x00",
|
|
12
|
-
{"test" => 1} => "\x00\x00\x00\x0E\x04testl\x00\x00\x00\x00\x00\x00\x00\x01",
|
|
13
|
-
{"float" => 1.92} => "\x00\x00\x00\x0F\x05floatd?\xFE\xB8Q\xEB\x85\x1E\xB8",
|
|
14
|
-
{"test" => "string"} => "\x00\x00\x00\x10\x04testS\x00\x00\x00\x06string",
|
|
15
|
-
{"test" => {}} => "\x00\x00\x00\n\x04testF\x00\x00\x00\x00",
|
|
16
|
-
{"test" => bigdecimal_1} => "\x00\x00\x00\v\x04testD\x00\x00\x00\x00\x01",
|
|
17
|
-
{"test" => bigdecimal_2} => "\x00\x00\x00\v\x04testD\x03\x00\x00\x00\x05",
|
|
18
|
-
{"test" => timestamp} => "\x00\x00\x00\x0e\x04testT\x00\x00\x00\x00M\x1enC"
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
describe ".encode" do
|
|
22
|
-
it "should return \"\x00\x00\x00\x00\" for nil" do
|
|
23
|
-
encoded_value = "\x00\x00\x00\x00"
|
|
24
|
-
|
|
25
|
-
expect(Table.encode(nil)).to eql(encoded_value)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "should serialize { :test => true }" do
|
|
29
|
-
expect(Table.encode(:test => true)).
|
|
30
|
-
to eql("\x00\x00\x00\a\x04testt\x01".force_encoding(Encoding::ASCII_8BIT))
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "should serialize { :test => false }" do
|
|
34
|
-
expect(Table.encode(:test => false)).
|
|
35
|
-
to eql("\x00\x00\x00\a\x04testt\x00".force_encoding(Encoding::ASCII_8BIT))
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "should serialize { :coordinates => { :latitude => 59.35 } }" do
|
|
39
|
-
expect(Table.encode(:coordinates => { :latitude => 59.35 })).
|
|
40
|
-
to eql("\x00\x00\x00#\vcoordinatesF\x00\x00\x00\x12\blatituded@M\xAC\xCC\xCC\xCC\xCC\xCD".force_encoding(Encoding::ASCII_8BIT))
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "should serialize { :coordinates => { :longitude => 18.066667 } }" do
|
|
44
|
-
expect(Table.encode(:coordinates => { :longitude => 18.066667 })).
|
|
45
|
-
to eql("\x00\x00\x00$\vcoordinatesF\x00\x00\x00\x13\tlongituded@2\x11\x11\x16\xA8\xB8\xF1".force_encoding(Encoding::ASCII_8BIT))
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
it "should serialize long UTF-8 strings and symbols" do
|
|
49
|
-
long_utf8 = "à" * 192
|
|
50
|
-
long_ascii8 = long_utf8.dup.force_encoding(::Encoding::ASCII_8BIT)
|
|
51
|
-
|
|
52
|
-
input = { "utf8_string" => long_utf8, "utf8_symbol" => long_utf8.to_sym }
|
|
53
|
-
output = { "utf8_string" => long_ascii8, "utf8_symbol" => long_ascii8 }
|
|
54
|
-
|
|
55
|
-
expect(Table.decode(Table.encode(input))).to eq(output)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
DATA.each do |data, encoded|
|
|
59
|
-
it "should return #{encoded.inspect} for #{data.inspect}" do
|
|
60
|
-
expect(Table.encode(data)).to eql(encoded.force_encoding(Encoding::ASCII_8BIT))
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
describe ".decode" do
|
|
66
|
-
DATA.each do |data, encoded|
|
|
67
|
-
it "should return #{data.inspect} for #{encoded.inspect}" do
|
|
68
|
-
expect(Table.decode(encoded)).to eql(data)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "is capable of decoding what it encodes" do
|
|
72
|
-
expect(Table.decode(Table.encode(data))).to eq(data)
|
|
73
|
-
end
|
|
74
|
-
end # DATA.each
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
it "is capable of decoding boolean table values" do
|
|
78
|
-
input1 = { "boolval" => true }
|
|
79
|
-
expect(Table.decode(Table.encode(input1))).to eq(input1)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
input2 = { "boolval" => false }
|
|
83
|
-
expect(Table.decode(Table.encode(input2))).to eq(input2)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
it "is capable of decoding nil table values" do
|
|
88
|
-
input = { "nilval" => nil }
|
|
89
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it "is capable of decoding nil table in nested hash/map values" do
|
|
93
|
-
input = { "hash" => {"nil" => nil} }
|
|
94
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it "is capable of decoding string table values" do
|
|
98
|
-
input = { "stringvalue" => "string" }
|
|
99
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
100
|
-
|
|
101
|
-
expect(Table.decode("\x00\x00\x00\x17\vstringvalueS\x00\x00\x00\x06string")).to eq(input)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
it "is capable of decoding byte array table values (as Ruby strings)" do
|
|
105
|
-
expect(Table.decode("\x00\x00\x00\x17\vstringvaluex\x00\x00\x00\x06string")).to eq({"stringvalue" => "string"})
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "is capable of decoding string table values with UTF-8 characters" do
|
|
109
|
-
input = {
|
|
110
|
-
"строка".force_encoding(::Encoding::ASCII_8BIT) => "значение".force_encoding(::Encoding::ASCII_8BIT)
|
|
111
|
-
}
|
|
112
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
it "is capable of decoding integer table values" do
|
|
117
|
-
input = { "intvalue" => 10 }
|
|
118
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
it "is capable of decoding signed integer table values" do
|
|
123
|
-
input = { "intvalue" => -10 }
|
|
124
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
it "is capable of decoding long table values" do
|
|
129
|
-
input = { "longvalue" => 912598613 }
|
|
130
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
it "is capable of decoding float table values" do
|
|
136
|
-
input = { "floatvalue" => 100.0 }
|
|
137
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
it "is capable of decoding time table values" do
|
|
143
|
-
input = { "intvalue" => Time.parse("2011-07-14 01:17:46 +0400") }
|
|
144
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
it "is capable of decoding empty hash table values" do
|
|
150
|
-
input = { "hashvalue" => Hash.new }
|
|
151
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
it "is capable of decoding empty array table values" do
|
|
157
|
-
input = { "arrayvalue" => Array.new }
|
|
158
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
it "is capable of decoding single string value array table values" do
|
|
163
|
-
input = { "arrayvalue" => ["amq-protocol"] }
|
|
164
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
it "is capable of decoding simple nested hash table values" do
|
|
170
|
-
input = { "hashvalue" => { "a" => "b" } }
|
|
171
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
it "is capable of decoding nil table values" do
|
|
177
|
-
input = { "nil" => nil }
|
|
178
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it 'is capable of decoding 8bit signed integers' do
|
|
182
|
-
output = TableValueDecoder.decode_byte("\xC0",0).first
|
|
183
|
-
expect(output).to eq(192)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
it 'is capable of decoding 16bit signed integers' do
|
|
187
|
-
output = TableValueDecoder.decode_short("\x06\x8D", 0).first
|
|
188
|
-
expect(output).to eq(1677)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
it "is capable of decoding tables" do
|
|
192
|
-
input = {
|
|
193
|
-
"boolval" => true,
|
|
194
|
-
"intval" => 1,
|
|
195
|
-
"strval" => "Test",
|
|
196
|
-
"timestampval" => Time.parse("2011-07-14 01:17:46 +0400"),
|
|
197
|
-
"floatval" => 3.14,
|
|
198
|
-
"longval" => 912598613,
|
|
199
|
-
"hashval" => { "protocol" => "AMQP091", "true" => true, "false" => false, "nil" => nil }
|
|
200
|
-
}
|
|
201
|
-
expect(Table.decode(Table.encode(input))).to eq(input)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
it "is capable of decoding deeply nested tables" do
|
|
207
|
-
input = {
|
|
208
|
-
"hashval" => {
|
|
209
|
-
"protocol" => {
|
|
210
|
-
"name" => "AMQP",
|
|
211
|
-
"major" => 0,
|
|
212
|
-
"minor" => "9",
|
|
213
|
-
"rev" => 1.0,
|
|
214
|
-
"spec" => {
|
|
215
|
-
"url" => "http://bit.ly/hw2ELX",
|
|
216
|
-
"utf8" => "à bientôt"
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
"true" => true,
|
|
220
|
-
"false" => false,
|
|
221
|
-
"nil" => nil
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
expect(Table.decode(Table.encode(input))).to eq(input.tap { |r| r["hashval"]["protocol"]["spec"]["utf8"].force_encoding(::Encoding::ASCII_8BIT) })
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
it "is capable of decoding array values in tables" do
|
|
230
|
-
input1 = {
|
|
231
|
-
"arrayval1" => [198, 3, 77, 8.0, ["inner", "array", { "oh" => "well", "it" => "should work", "3" => 6 }], "two", { "a" => "value", "is" => nil }],
|
|
232
|
-
"arrayval2" => [198, 3, 77, "two", { "a" => "value", "is" => nil }, 8.0, ["inner", "array", { "oh" => "well", "it" => "should work", "3" => 6 }]]
|
|
233
|
-
}
|
|
234
|
-
expect(Table.decode(Table.encode(input1))).to eq(input1)
|
|
235
|
-
|
|
236
|
-
now = Time.now
|
|
237
|
-
input2 = {
|
|
238
|
-
"coordinates" => {
|
|
239
|
-
"latitude" => 59.35,
|
|
240
|
-
"longitude" => 18.066667
|
|
241
|
-
},
|
|
242
|
-
"participants" => 11,
|
|
243
|
-
"venue" => "Stockholm",
|
|
244
|
-
"true_field" => true,
|
|
245
|
-
"false_field" => false,
|
|
246
|
-
"nil_field" => nil,
|
|
247
|
-
"ary_field" => ["one", 2.0, 3]
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
expect(Table.decode(Table.encode(input2))).to eq(input2)
|
|
251
|
-
|
|
252
|
-
input3 = { "timely" => { "now" => now } }
|
|
253
|
-
expect(Table.decode(Table.encode(input3))["timely"]["now"].to_i).to eq(now.to_i)
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
end # describe
|
|
257
|
-
|
|
258
|
-
describe ".length" do
|
|
259
|
-
it "returns the table length from binary data" do
|
|
260
|
-
encoded = Table.encode({"test" => 1})
|
|
261
|
-
expect(Table.length(encoded)).to eq(14)
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
it "returns 0 for empty table" do
|
|
265
|
-
encoded = Table.encode({})
|
|
266
|
-
expect(Table.length(encoded)).to eq(0)
|
|
267
|
-
end
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
describe ".hash_size" do
|
|
271
|
-
it "calculates size for simple hash" do
|
|
272
|
-
size = Table.hash_size({"key" => "value"})
|
|
273
|
-
expect(size).to be > 0
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
it "returns 0 for empty hash" do
|
|
277
|
-
size = Table.hash_size({})
|
|
278
|
-
expect(size).to eq(0)
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
describe "Table::InvalidTableError" do
|
|
283
|
-
it "formats error message with key and value" do
|
|
284
|
-
error = Table::InvalidTableError.new("mykey", Object.new)
|
|
285
|
-
expect(error.message).to include("mykey")
|
|
286
|
-
expect(error.message).to include("Object")
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# encoding: binary
|
|
2
|
-
|
|
3
|
-
module AMQ
|
|
4
|
-
module Protocol
|
|
5
|
-
class Tx
|
|
6
|
-
RSpec.describe Select do
|
|
7
|
-
describe '.encode' do
|
|
8
|
-
it 'encodes the parameters into a MethodFrame' do
|
|
9
|
-
channel = 1
|
|
10
|
-
method_frame = Select.encode(channel)
|
|
11
|
-
expect(method_frame.payload).to eq("\000Z\000\n")
|
|
12
|
-
expect(method_frame.channel).to eq(1)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# RSpec.describe SelectOk do
|
|
18
|
-
# describe '.decode' do
|
|
19
|
-
# end
|
|
20
|
-
# end
|
|
21
|
-
|
|
22
|
-
RSpec.describe Commit do
|
|
23
|
-
describe '.encode' do
|
|
24
|
-
it 'encodes the parameters into a MethodFrame' do
|
|
25
|
-
channel = 1
|
|
26
|
-
method_frame = Commit.encode(channel)
|
|
27
|
-
expect(method_frame.payload).to eq("\000Z\000\024")
|
|
28
|
-
expect(method_frame.channel).to eq(1)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# RSpec.describe CommitOk do
|
|
34
|
-
# describe '.decode' do
|
|
35
|
-
# end
|
|
36
|
-
# end
|
|
37
|
-
|
|
38
|
-
RSpec.describe Rollback do
|
|
39
|
-
describe '.encode' do
|
|
40
|
-
it 'encodes the parameters into a MethodFrame' do
|
|
41
|
-
channel = 1
|
|
42
|
-
method_frame = Rollback.encode(channel)
|
|
43
|
-
expect(method_frame.payload).to eq("\000Z\000\036")
|
|
44
|
-
expect(method_frame.channel).to eq(1)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# RSpec.describe RollbackOk do
|
|
50
|
-
# describe '.decode' do
|
|
51
|
-
# end
|
|
52
|
-
# end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
require 'time'
|
|
2
|
-
require "amq/protocol/table_value_decoder"
|
|
3
|
-
|
|
4
|
-
module AMQ
|
|
5
|
-
module Protocol
|
|
6
|
-
RSpec.describe TableValueDecoder do
|
|
7
|
-
|
|
8
|
-
it "is capable of decoding basic arrays TableValueEncoder encodes" do
|
|
9
|
-
input1 = [1, 2, 3]
|
|
10
|
-
|
|
11
|
-
value, _offset = described_class.decode_array(TableValueEncoder.encode(input1), 1)
|
|
12
|
-
expect(value.size).to eq(3)
|
|
13
|
-
expect(value.first).to eq(1)
|
|
14
|
-
expect(value).to eq(input1)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
input2 = ["one", 2, "three"]
|
|
19
|
-
|
|
20
|
-
value, _offset = described_class.decode_array(TableValueEncoder.encode(input2), 1)
|
|
21
|
-
expect(value.size).to eq(3)
|
|
22
|
-
expect(value.first).to eq("one")
|
|
23
|
-
expect(value).to eq(input2)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
input3 = ["one", 2, "three", 4.0, 5000000.0]
|
|
28
|
-
|
|
29
|
-
value, _offset = described_class.decode_array(TableValueEncoder.encode(input3), 1)
|
|
30
|
-
expect(value.size).to eq(5)
|
|
31
|
-
expect(value.last).to eq(5000000.0)
|
|
32
|
-
expect(value).to eq(input3)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
it "is capable of decoding arrays TableValueEncoder encodes" do
|
|
38
|
-
input1 = [{ "one" => 2 }, 3]
|
|
39
|
-
data1 = TableValueEncoder.encode(input1)
|
|
40
|
-
|
|
41
|
-
# puts(TableValueEncoder.encode({ "one" => 2 }).inspect)
|
|
42
|
-
# puts(TableValueEncoder.encode(input1).inspect)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
value, _offset = described_class.decode_array(data1, 1)
|
|
46
|
-
expect(value.size).to eq(2)
|
|
47
|
-
expect(value.first).to eq(Hash["one" => 2])
|
|
48
|
-
expect(value).to eq(input1)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
input2 = ["one", 2, { "three" => { "four" => 5.0 } }]
|
|
53
|
-
|
|
54
|
-
value, _offset = described_class.decode_array(TableValueEncoder.encode(input2), 1)
|
|
55
|
-
expect(value.size).to eq(3)
|
|
56
|
-
expect(value.last["three"]["four"]).to eq(5.0)
|
|
57
|
-
expect(value).to eq(input2)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it "is capable of decoding 32 bit float values" do
|
|
61
|
-
input = Float32Bit.new(10.0)
|
|
62
|
-
data = TableValueEncoder.encode(input)
|
|
63
|
-
|
|
64
|
-
value = described_class.decode_32bit_float(data, 1)[0]
|
|
65
|
-
expect(value).to eq(10.0)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
context "8bit/byte decoding" do
|
|
69
|
-
let(:examples) {
|
|
70
|
-
{
|
|
71
|
-
0x00 => "\x00",
|
|
72
|
-
0x01 => "\x01",
|
|
73
|
-
0x10 => "\x10",
|
|
74
|
-
255 => "\xFF" # not -1
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
it "is capable of decoding byte values" do
|
|
79
|
-
examples.each do |key, value|
|
|
80
|
-
expect(described_class.decode_byte(value, 0).first).to eq(key)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
describe ".decode_string" do
|
|
86
|
-
it "decodes string values" do
|
|
87
|
-
# 4 bytes length + string content
|
|
88
|
-
data = "\x00\x00\x00\x05hello"
|
|
89
|
-
value, offset = described_class.decode_string(data, 0)
|
|
90
|
-
expect(value).to eq("hello")
|
|
91
|
-
expect(offset).to eq(9)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
describe ".decode_integer" do
|
|
96
|
-
it "decodes 32-bit unsigned integers" do
|
|
97
|
-
data = "\x00\x00\x00\x0A"
|
|
98
|
-
value, offset = described_class.decode_integer(data, 0)
|
|
99
|
-
expect(value).to eq(10)
|
|
100
|
-
expect(offset).to eq(4)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
describe ".decode_long" do
|
|
105
|
-
it "decodes 64-bit signed integers" do
|
|
106
|
-
data = "\x00\x00\x00\x00\x00\x00\x00\x0A"
|
|
107
|
-
value, offset = described_class.decode_long(data, 0)
|
|
108
|
-
expect(value).to eq(10)
|
|
109
|
-
expect(offset).to eq(8)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
describe ".decode_time" do
|
|
114
|
-
it "decodes timestamp values" do
|
|
115
|
-
timestamp = Time.now.to_i
|
|
116
|
-
data = [timestamp].pack('Q>')
|
|
117
|
-
value, offset = described_class.decode_time(data, 0)
|
|
118
|
-
expect(value.to_i).to eq(timestamp)
|
|
119
|
-
expect(offset).to eq(8)
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
describe ".decode_boolean" do
|
|
124
|
-
it "decodes true" do
|
|
125
|
-
value, offset = described_class.decode_boolean("\x01", 0)
|
|
126
|
-
expect(value).to eq(true)
|
|
127
|
-
expect(offset).to eq(1)
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
it "decodes false" do
|
|
131
|
-
value, offset = described_class.decode_boolean("\x00", 0)
|
|
132
|
-
expect(value).to eq(false)
|
|
133
|
-
expect(offset).to eq(1)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
describe ".decode_64bit_float" do
|
|
138
|
-
it "decodes 64-bit floats" do
|
|
139
|
-
data = [3.14159].pack('G')
|
|
140
|
-
value, offset = described_class.decode_64bit_float(data, 0)
|
|
141
|
-
expect(value).to be_within(0.00001).of(3.14159)
|
|
142
|
-
expect(offset).to eq(8)
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
describe ".decode_value_type" do
|
|
147
|
-
it "returns the type byte and incremented offset" do
|
|
148
|
-
data = "Shello"
|
|
149
|
-
type, offset = described_class.decode_value_type(data, 0)
|
|
150
|
-
expect(type).to eq("S")
|
|
151
|
-
expect(offset).to eq(1)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
describe ".decode_short" do
|
|
156
|
-
it "decodes 16-bit signed integers" do
|
|
157
|
-
data = "\x06\x8D"
|
|
158
|
-
value, offset = described_class.decode_short(data, 0)
|
|
159
|
-
expect(value).to eq(1677)
|
|
160
|
-
expect(offset).to eq(2)
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
describe ".decode_big_decimal" do
|
|
165
|
-
it "decodes BigDecimal values" do
|
|
166
|
-
# Scale 2, raw value 100 = 1.00
|
|
167
|
-
data = "\x02\x00\x00\x00\x64"
|
|
168
|
-
value, offset = described_class.decode_big_decimal(data, 0)
|
|
169
|
-
expect(value).to be_a(BigDecimal)
|
|
170
|
-
expect(offset).to eq(5)
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
describe ".decode_hash" do
|
|
175
|
-
it "decodes nested hash values" do
|
|
176
|
-
encoded = AMQ::Protocol::Table.encode({"nested" => "value"})
|
|
177
|
-
value, _offset = described_class.decode_hash(encoded, 0)
|
|
178
|
-
expect(value).to eq({"nested" => "value"})
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
end
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
require 'time'
|
|
2
|
-
require "amq/protocol/table_value_encoder"
|
|
3
|
-
require "amq/protocol/float_32bit"
|
|
4
|
-
|
|
5
|
-
module AMQ
|
|
6
|
-
module Protocol
|
|
7
|
-
RSpec.describe TableValueEncoder do
|
|
8
|
-
|
|
9
|
-
it "calculates size of string field values" do
|
|
10
|
-
expect(described_class.field_value_size("amqp")).to eq(9)
|
|
11
|
-
expect(described_class.encode("amqp").bytesize).to eq(9)
|
|
12
|
-
|
|
13
|
-
expect(described_class.field_value_size("amq-protocol")).to eq(17)
|
|
14
|
-
expect(described_class.encode("amq-protocol").bytesize).to eq(17)
|
|
15
|
-
|
|
16
|
-
expect(described_class.field_value_size("à bientôt")).to eq(16)
|
|
17
|
-
expect(described_class.encode("à bientôt").bytesize).to eq(16)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "calculates size of integer field values" do
|
|
21
|
-
expect(described_class.field_value_size(10)).to eq(9)
|
|
22
|
-
expect(described_class.encode(10).bytesize).to eq(9)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it "calculates size of float field values (considering them to be 64-bit)" do
|
|
26
|
-
expect(described_class.field_value_size(10.0)).to eq(9)
|
|
27
|
-
expect(described_class.encode(10.0).bytesize).to eq(9)
|
|
28
|
-
|
|
29
|
-
expect(described_class.field_value_size(120000.0)).to eq(9)
|
|
30
|
-
expect(described_class.encode(120000.0).bytesize).to eq(9)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "calculates size of float field values (boxed as 32-bit)" do
|
|
34
|
-
expect(described_class.encode(AMQ::Protocol::Float32Bit.new(10.0)).bytesize).to eq(5)
|
|
35
|
-
expect(described_class.encode(AMQ::Protocol::Float32Bit.new(120000.0)).bytesize).to eq(5)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "calculates size of boolean field values" do
|
|
39
|
-
expect(described_class.field_value_size(true)).to eq(2)
|
|
40
|
-
expect(described_class.encode(true).bytesize).to eq(2)
|
|
41
|
-
|
|
42
|
-
expect(described_class.field_value_size(false)).to eq(2)
|
|
43
|
-
expect(described_class.encode(false).bytesize).to eq(2)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it "calculates size of void field values" do
|
|
47
|
-
expect(described_class.field_value_size(nil)).to eq(1)
|
|
48
|
-
expect(described_class.encode(nil).bytesize).to eq(1)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "calculates size of time field values" do
|
|
52
|
-
t = Time.parse("2011-07-14 01:17:46 +0400")
|
|
53
|
-
|
|
54
|
-
expect(described_class.field_value_size(t)).to eq(9)
|
|
55
|
-
expect(described_class.encode(t).bytesize).to eq(9)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
it "calculates size of basic table field values" do
|
|
60
|
-
input1 = { "key" => "value" }
|
|
61
|
-
expect(described_class.field_value_size(input1)).to eq(19)
|
|
62
|
-
expect(described_class.encode(input1).bytesize).to eq(19)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
input2 = { "intval" => 1 }
|
|
66
|
-
expect(described_class.field_value_size(input2)).to eq(21)
|
|
67
|
-
expect(described_class.encode(input2).bytesize).to eq(21)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
input3 = { "intval" => 1, "key" => "value" }
|
|
71
|
-
expect(described_class.field_value_size(input3)).to eq(35)
|
|
72
|
-
expect(described_class.encode(input3).bytesize).to eq(35)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
it "calculates size of table field values" do
|
|
77
|
-
input1 = {
|
|
78
|
-
"hashval" => {
|
|
79
|
-
"protocol" => {
|
|
80
|
-
"name" => "AMQP",
|
|
81
|
-
"major" => 0,
|
|
82
|
-
"minor" => "9",
|
|
83
|
-
"rev" => 1.0,
|
|
84
|
-
"spec" => {
|
|
85
|
-
"url" => "http://bit.ly/hw2ELX",
|
|
86
|
-
"utf8" => "à bientôt".force_encoding(::Encoding::ASCII_8BIT)
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
"true" => true,
|
|
90
|
-
"false" => false,
|
|
91
|
-
"nil" => nil
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
expect(described_class.field_value_size(input1)).to eq(166)
|
|
96
|
-
# puts(described_class.encode(input1).inspect)
|
|
97
|
-
expect(described_class.encode(input1).bytesize).to eq(166)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
input2 = {
|
|
102
|
-
"boolval" => true,
|
|
103
|
-
"intval" => 1,
|
|
104
|
-
"strval" => "Test",
|
|
105
|
-
"timestampval" => Time.parse("2011-07-14 01:17:46 +0400"),
|
|
106
|
-
"floatval" => 3.14,
|
|
107
|
-
"longval" => 912598613,
|
|
108
|
-
"hashval" => { "protocol" => "AMQP091", "true" => true, "false" => false, "nil" => nil }
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
expect(described_class.field_value_size(input2)).to eq(158)
|
|
112
|
-
expect(described_class.encode(input2).bytesize).to eq(158)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
it "calculates size of basic array field values" do
|
|
116
|
-
input1 = [1, 2, 3]
|
|
117
|
-
|
|
118
|
-
expect(described_class.field_value_size(input1)).to eq(32)
|
|
119
|
-
expect(described_class.encode(input1).bytesize).to eq(32)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
input2 = ["one", "two", "three"]
|
|
123
|
-
expect(described_class.field_value_size(input2)).to eq(31)
|
|
124
|
-
expect(described_class.encode(input2).bytesize).to eq(31)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
input3 = ["one", 2, "three"]
|
|
128
|
-
expect(described_class.field_value_size(input3)).to eq(32)
|
|
129
|
-
expect(described_class.encode(input3).bytesize).to eq(32)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
input4 = ["one", 2, "three", ["four", 5, [6.0]]]
|
|
133
|
-
expect(described_class.field_value_size(input4)).to eq(69)
|
|
134
|
-
expect(described_class.encode(input4).bytesize).to eq(69)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it "encodes symbols as strings" do
|
|
138
|
-
encoded = described_class.encode(:test_symbol)
|
|
139
|
-
expect(encoded).to start_with("S")
|
|
140
|
-
expect(encoded).to include("test_symbol")
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "encodes BigDecimal values" do
|
|
144
|
-
bd = BigDecimal("123.45")
|
|
145
|
-
encoded = described_class.encode(bd)
|
|
146
|
-
expect(encoded).to start_with("D")
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "encodes BigDecimal with zero exponent" do
|
|
150
|
-
bd = BigDecimal("100")
|
|
151
|
-
encoded = described_class.encode(bd)
|
|
152
|
-
expect(encoded).to start_with("D")
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "raises ArgumentError for unsupported types" do
|
|
156
|
-
expect { described_class.encode(Object.new) }.to raise_error(ArgumentError)
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
end # TableValueEncoder
|
|
160
|
-
end # Protocol
|
|
161
|
-
end # AMQ
|