msgpack 0.7.0dev1-x86-mingw32 → 0.7.0-x86-mingw32
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/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/ChangeLog +8 -0
- data/README.rdoc +36 -2
- data/ext/java/org/msgpack/jruby/Decoder.java +55 -16
- data/ext/java/org/msgpack/jruby/Encoder.java +31 -8
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +159 -0
- data/ext/java/org/msgpack/jruby/Factory.java +117 -0
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +23 -6
- data/ext/java/org/msgpack/jruby/Packer.java +65 -6
- data/ext/java/org/msgpack/jruby/Unpacker.java +104 -22
- data/ext/msgpack/packer_class.c +7 -0
- data/ext/msgpack/packer_ext_registry.c +0 -8
- data/ext/msgpack/packer_ext_registry.h +0 -3
- data/ext/msgpack/unpacker_class.c +14 -0
- data/ext/msgpack/unpacker_ext_registry.c +0 -6
- data/ext/msgpack/unpacker_ext_registry.h +0 -3
- data/lib/msgpack/version.rb +1 -1
- data/msgpack.gemspec +5 -3
- data/spec/cruby/unpacker_spec.rb +0 -247
- data/spec/factory_spec.rb +0 -3
- data/spec/jruby/{msgpack/unpacker_spec.rb → unpacker_spec.rb} +30 -159
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +135 -4
- data/spec/unpacker_spec.rb +465 -6
- metadata +9 -6
- data/spec/cruby/packer_spec.rb +0 -138
data/spec/msgpack_spec.rb
CHANGED
data/spec/packer_spec.rb
CHANGED
@@ -1,6 +1,141 @@
|
|
1
|
+
# encoding: ascii-8bit
|
1
2
|
require 'spec_helper'
|
2
3
|
|
4
|
+
require 'stringio'
|
5
|
+
if defined?(Encoding)
|
6
|
+
Encoding.default_external = 'ASCII-8BIT'
|
7
|
+
end
|
8
|
+
|
3
9
|
describe MessagePack::Packer do
|
10
|
+
let :packer do
|
11
|
+
MessagePack::Packer.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'initialize' do
|
15
|
+
MessagePack::Packer.new
|
16
|
+
MessagePack::Packer.new(nil)
|
17
|
+
MessagePack::Packer.new(StringIO.new)
|
18
|
+
MessagePack::Packer.new({})
|
19
|
+
MessagePack::Packer.new(StringIO.new, {})
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets options to specify how to pack values' do
|
23
|
+
u1 = MessagePack::Packer.new
|
24
|
+
u1.compatibility_mode?.should == false
|
25
|
+
|
26
|
+
u2 = MessagePack::Packer.new(compatibility_mode: true)
|
27
|
+
u2.compatibility_mode?.should == true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'write' do
|
31
|
+
packer.write([])
|
32
|
+
packer.to_s.should == "\x90"
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'write_nil' do
|
36
|
+
packer.write_nil
|
37
|
+
packer.to_s.should == "\xc0"
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'write_array_header 0' do
|
41
|
+
packer.write_array_header(0)
|
42
|
+
packer.to_s.should == "\x90"
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'write_array_header 1' do
|
46
|
+
packer.write_array_header(1)
|
47
|
+
packer.to_s.should == "\x91"
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'write_map_header 0' do
|
51
|
+
packer.write_map_header(0)
|
52
|
+
packer.to_s.should == "\x80"
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'write_map_header 1' do
|
56
|
+
packer.write_map_header(1)
|
57
|
+
packer.to_s.should == "\x81"
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'flush' do
|
61
|
+
io = StringIO.new
|
62
|
+
pk = MessagePack::Packer.new(io)
|
63
|
+
pk.write_nil
|
64
|
+
pk.flush
|
65
|
+
pk.to_s.should == ''
|
66
|
+
io.string.should == "\xc0"
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'to_msgpack returns String' do
|
70
|
+
nil.to_msgpack.class.should == String
|
71
|
+
true.to_msgpack.class.should == String
|
72
|
+
false.to_msgpack.class.should == String
|
73
|
+
1.to_msgpack.class.should == String
|
74
|
+
1.0.to_msgpack.class.should == String
|
75
|
+
"".to_msgpack.class.should == String
|
76
|
+
Hash.new.to_msgpack.class.should == String
|
77
|
+
Array.new.to_msgpack.class.should == String
|
78
|
+
end
|
79
|
+
|
80
|
+
class CustomPack01
|
81
|
+
def to_msgpack(pk=nil)
|
82
|
+
return MessagePack.pack(self, pk) unless pk.class == MessagePack::Packer
|
83
|
+
pk.write_array_header(2)
|
84
|
+
pk.write(1)
|
85
|
+
pk.write(2)
|
86
|
+
return pk
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class CustomPack02
|
91
|
+
def to_msgpack(pk=nil)
|
92
|
+
[1,2].to_msgpack(pk)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'calls custom to_msgpack method' do
|
97
|
+
MessagePack.pack(CustomPack01.new).should == [1,2].to_msgpack
|
98
|
+
MessagePack.pack(CustomPack02.new).should == [1,2].to_msgpack
|
99
|
+
CustomPack01.new.to_msgpack.should == [1,2].to_msgpack
|
100
|
+
CustomPack02.new.to_msgpack.should == [1,2].to_msgpack
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'calls custom to_msgpack method with io' do
|
104
|
+
s01 = StringIO.new
|
105
|
+
MessagePack.pack(CustomPack01.new, s01)
|
106
|
+
s01.string.should == [1,2].to_msgpack
|
107
|
+
|
108
|
+
s02 = StringIO.new
|
109
|
+
MessagePack.pack(CustomPack02.new, s02)
|
110
|
+
s02.string.should == [1,2].to_msgpack
|
111
|
+
|
112
|
+
s03 = StringIO.new
|
113
|
+
CustomPack01.new.to_msgpack(s03)
|
114
|
+
s03.string.should == [1,2].to_msgpack
|
115
|
+
|
116
|
+
s04 = StringIO.new
|
117
|
+
CustomPack02.new.to_msgpack(s04)
|
118
|
+
s04.string.should == [1,2].to_msgpack
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'in compatibility mode' do
|
122
|
+
it 'does not use the bin types' do
|
123
|
+
packed = MessagePack.pack('hello'.force_encoding(Encoding::BINARY), compatibility_mode: true)
|
124
|
+
packed.should eq("\xA5hello")
|
125
|
+
packed = MessagePack.pack(('hello' * 100).force_encoding(Encoding::BINARY), compatibility_mode: true)
|
126
|
+
packed.should start_with("\xDA\x01\xF4")
|
127
|
+
|
128
|
+
packer = MessagePack::Packer.new(compatibility_mode: 1)
|
129
|
+
packed = packer.pack(('hello' * 100).force_encoding(Encoding::BINARY))
|
130
|
+
packed.to_str.should start_with("\xDA\x01\xF4")
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'does not use the str8 type' do
|
134
|
+
packed = MessagePack.pack('x' * 32, compatibility_mode: true)
|
135
|
+
packed.should start_with("\xDA\x00\x20")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
4
139
|
class ValueOne
|
5
140
|
def initialize(num)
|
6
141
|
@num = num
|
@@ -33,14 +168,12 @@ describe MessagePack::Packer do
|
|
33
168
|
|
34
169
|
describe '#type_registered?' do
|
35
170
|
it 'receive Class or Integer, and return bool' do
|
36
|
-
skip("not supported yet in JRuby implementation") if java?
|
37
171
|
expect(subject.type_registered?(0x00)).to be_falsy
|
38
172
|
expect(subject.type_registered?(0x01)).to be_falsy
|
39
173
|
expect(subject.type_registered?(::ValueOne)).to be_falsy
|
40
174
|
end
|
41
175
|
|
42
176
|
it 'returns true if specified type or class is already registered' do
|
43
|
-
skip("not supported yet in JRuby implementation") if java?
|
44
177
|
subject.register_type(0x30, ::ValueOne, :to_msgpack_ext)
|
45
178
|
subject.register_type(0x31, ::ValueTwo, :to_msgpack_ext)
|
46
179
|
|
@@ -56,7 +189,6 @@ describe MessagePack::Packer do
|
|
56
189
|
|
57
190
|
describe '#register_type' do
|
58
191
|
it 'get type and class mapping for packing' do
|
59
|
-
skip("not supported yet in JRuby implementation") if java?
|
60
192
|
packer = MessagePack::Packer.new
|
61
193
|
packer.register_type(0x01, ValueOne){|obj| obj.to_msgpack_ext }
|
62
194
|
packer.register_type(0x02, ValueTwo){|obj| obj.to_msgpack_ext }
|
@@ -71,7 +203,6 @@ describe MessagePack::Packer do
|
|
71
203
|
end
|
72
204
|
|
73
205
|
it 'returns a Hash which contains map of Class and type' do
|
74
|
-
skip("not supported yet in JRuby implementation") if java?
|
75
206
|
packer = MessagePack::Packer.new
|
76
207
|
packer.register_type(0x01, ValueOne, :to_msgpack_ext)
|
77
208
|
packer.register_type(0x02, ValueTwo, :to_msgpack_ext)
|
data/spec/unpacker_spec.rb
CHANGED
@@ -1,6 +1,265 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'tempfile'
|
5
|
+
|
1
6
|
require 'spec_helper'
|
2
7
|
|
3
8
|
describe MessagePack::Unpacker do
|
9
|
+
let :unpacker do
|
10
|
+
MessagePack::Unpacker.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let :packer do
|
14
|
+
MessagePack::Packer.new
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'gets options to specify how to unpack values' do
|
18
|
+
u1 = MessagePack::Unpacker.new
|
19
|
+
u1.symbolize_keys?.should == false
|
20
|
+
u1.allow_unknown_ext?.should == false
|
21
|
+
|
22
|
+
u2 = MessagePack::Unpacker.new(symbolize_keys: true, allow_unknown_ext: true)
|
23
|
+
u2.symbolize_keys?.should == true
|
24
|
+
u2.allow_unknown_ext?.should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'read_array_header succeeds' do
|
28
|
+
unpacker.feed("\x91")
|
29
|
+
unpacker.read_array_header.should == 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'read_array_header fails' do
|
33
|
+
unpacker.feed("\x81")
|
34
|
+
lambda {
|
35
|
+
unpacker.read_array_header
|
36
|
+
}.should raise_error(MessagePack::TypeError) # TypeError is included in UnexpectedTypeError
|
37
|
+
lambda {
|
38
|
+
unpacker.read_array_header
|
39
|
+
}.should raise_error(MessagePack::UnexpectedTypeError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'read_map_header converts an map to key-value sequence' do
|
43
|
+
packer.write_array_header(2)
|
44
|
+
packer.write("e")
|
45
|
+
packer.write(1)
|
46
|
+
unpacker = MessagePack::Unpacker.new
|
47
|
+
unpacker.feed(packer.to_s)
|
48
|
+
unpacker.read_array_header.should == 2
|
49
|
+
unpacker.read.should == "e"
|
50
|
+
unpacker.read.should == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'read_map_header succeeds' do
|
54
|
+
unpacker.feed("\x81")
|
55
|
+
unpacker.read_map_header.should == 1
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'read_map_header converts an map to key-value sequence' do
|
59
|
+
packer.write_map_header(1)
|
60
|
+
packer.write("k")
|
61
|
+
packer.write("v")
|
62
|
+
unpacker = MessagePack::Unpacker.new
|
63
|
+
unpacker.feed(packer.to_s)
|
64
|
+
unpacker.read_map_header.should == 1
|
65
|
+
unpacker.read.should == "k"
|
66
|
+
unpacker.read.should == "v"
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'read_map_header fails' do
|
70
|
+
unpacker.feed("\x91")
|
71
|
+
lambda {
|
72
|
+
unpacker.read_map_header
|
73
|
+
}.should raise_error(MessagePack::TypeError) # TypeError is included in UnexpectedTypeError
|
74
|
+
lambda {
|
75
|
+
unpacker.read_map_header
|
76
|
+
}.should raise_error(MessagePack::UnexpectedTypeError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'read raises EOFError before feeding' do
|
80
|
+
lambda {
|
81
|
+
unpacker.read
|
82
|
+
}.should raise_error(EOFError)
|
83
|
+
end
|
84
|
+
|
85
|
+
let :sample_object do
|
86
|
+
[1024, {["a","b"]=>["c","d"]}, ["e","f"], "d", 70000, 4.12, 1.5, 1.5, 1.5]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'feed and each continue internal state' do
|
90
|
+
raw = sample_object.to_msgpack.to_s * 4
|
91
|
+
objects = []
|
92
|
+
|
93
|
+
raw.split(//).each do |b|
|
94
|
+
unpacker.feed(b)
|
95
|
+
unpacker.each {|c|
|
96
|
+
objects << c
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
objects.should == [sample_object] * 4
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'feed_each continues internal state' do
|
104
|
+
raw = sample_object.to_msgpack.to_s * 4
|
105
|
+
objects = []
|
106
|
+
|
107
|
+
raw.split(//).each do |b|
|
108
|
+
unpacker.feed_each(b) {|c|
|
109
|
+
objects << c
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
objects.should == [sample_object] * 4
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'feed_each enumerator' do
|
117
|
+
raw = sample_object.to_msgpack.to_s * 4
|
118
|
+
|
119
|
+
enum = unpacker.feed_each(raw)
|
120
|
+
enum.should be_instance_of(Enumerator)
|
121
|
+
enum.to_a.should == [sample_object] * 4
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'reset clears internal buffer' do
|
125
|
+
# 1-element array
|
126
|
+
unpacker.feed("\x91")
|
127
|
+
unpacker.reset
|
128
|
+
unpacker.feed("\x01")
|
129
|
+
|
130
|
+
unpacker.each.map {|x| x }.should == [1]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'reset clears internal state' do
|
134
|
+
# 1-element array
|
135
|
+
unpacker.feed("\x91")
|
136
|
+
unpacker.each.map {|x| x }.should == []
|
137
|
+
|
138
|
+
unpacker.reset
|
139
|
+
|
140
|
+
unpacker.feed("\x01")
|
141
|
+
unpacker.each.map {|x| x }.should == [1]
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'frozen short strings' do
|
145
|
+
raw = sample_object.to_msgpack.to_s.force_encoding('UTF-8')
|
146
|
+
lambda {
|
147
|
+
unpacker.feed_each(raw.freeze) { }
|
148
|
+
}.should_not raise_error
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'frozen long strings' do
|
152
|
+
raw = (sample_object.to_msgpack.to_s * 10240).force_encoding('UTF-8')
|
153
|
+
lambda {
|
154
|
+
unpacker.feed_each(raw.freeze) { }
|
155
|
+
}.should_not raise_error
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'read raises invalid byte error' do
|
159
|
+
unpacker.feed("\xc1")
|
160
|
+
lambda {
|
161
|
+
unpacker.read
|
162
|
+
}.should raise_error(MessagePack::MalformedFormatError)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "gc mark" do
|
166
|
+
raw = sample_object.to_msgpack.to_s * 4
|
167
|
+
|
168
|
+
n = 0
|
169
|
+
raw.split(//).each do |b|
|
170
|
+
GC.start
|
171
|
+
unpacker.feed_each(b) {|o|
|
172
|
+
GC.start
|
173
|
+
o.should == sample_object
|
174
|
+
n += 1
|
175
|
+
}
|
176
|
+
GC.start
|
177
|
+
end
|
178
|
+
|
179
|
+
n.should == 4
|
180
|
+
end
|
181
|
+
|
182
|
+
it "buffer" do
|
183
|
+
orig = "a"*32*1024*4
|
184
|
+
raw = orig.to_msgpack.to_s
|
185
|
+
|
186
|
+
n = 655
|
187
|
+
times = raw.size / n
|
188
|
+
times += 1 unless raw.size % n == 0
|
189
|
+
|
190
|
+
off = 0
|
191
|
+
parsed = false
|
192
|
+
|
193
|
+
times.times do
|
194
|
+
parsed.should == false
|
195
|
+
|
196
|
+
seg = raw[off, n]
|
197
|
+
off += seg.length
|
198
|
+
|
199
|
+
unpacker.feed_each(seg) {|obj|
|
200
|
+
parsed.should == false
|
201
|
+
obj.should == orig
|
202
|
+
parsed = true
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
206
|
+
parsed.should == true
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'MessagePack.unpack symbolize_keys' do
|
210
|
+
symbolized_hash = {:a => 'b', :c => 'd'}
|
211
|
+
MessagePack.load(MessagePack.pack(symbolized_hash), :symbolize_keys => true).should == symbolized_hash
|
212
|
+
MessagePack.unpack(MessagePack.pack(symbolized_hash), :symbolize_keys => true).should == symbolized_hash
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'Unpacker#unpack symbolize_keys' do
|
216
|
+
unpacker = MessagePack::Unpacker.new(:symbolize_keys => true)
|
217
|
+
symbolized_hash = {:a => 'b', :c => 'd'}
|
218
|
+
unpacker.feed(MessagePack.pack(symbolized_hash)).read.should == symbolized_hash
|
219
|
+
end
|
220
|
+
|
221
|
+
it "msgpack str 8 type" do
|
222
|
+
MessagePack.unpack([0xd9, 0x00].pack('C*')).should == ""
|
223
|
+
MessagePack.unpack([0xd9, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
|
224
|
+
MessagePack.unpack([0xd9, 0x01].pack('C*') + 'a').should == "a"
|
225
|
+
MessagePack.unpack([0xd9, 0x02].pack('C*') + 'aa').should == "aa"
|
226
|
+
end
|
227
|
+
|
228
|
+
it "msgpack str 16 type" do
|
229
|
+
MessagePack.unpack([0xda, 0x00, 0x00].pack('C*')).should == ""
|
230
|
+
MessagePack.unpack([0xda, 0x00, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
|
231
|
+
MessagePack.unpack([0xda, 0x00, 0x01].pack('C*') + 'a').should == "a"
|
232
|
+
MessagePack.unpack([0xda, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
|
233
|
+
end
|
234
|
+
|
235
|
+
it "msgpack str 32 type" do
|
236
|
+
MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x00].pack('C*')).should == ""
|
237
|
+
MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
|
238
|
+
MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x01].pack('C*') + 'a').should == "a"
|
239
|
+
MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
|
240
|
+
end
|
241
|
+
|
242
|
+
it "msgpack bin 8 type" do
|
243
|
+
MessagePack.unpack([0xc4, 0x00].pack('C*')).should == ""
|
244
|
+
MessagePack.unpack([0xc4, 0x00].pack('C*')).encoding.should == Encoding::ASCII_8BIT
|
245
|
+
MessagePack.unpack([0xc4, 0x01].pack('C*') + 'a').should == "a"
|
246
|
+
MessagePack.unpack([0xc4, 0x02].pack('C*') + 'aa').should == "aa"
|
247
|
+
end
|
248
|
+
|
249
|
+
it "msgpack bin 16 type" do
|
250
|
+
MessagePack.unpack([0xc5, 0x00, 0x00].pack('C*')).should == ""
|
251
|
+
MessagePack.unpack([0xc5, 0x00, 0x00].pack('C*')).encoding.should == Encoding::ASCII_8BIT
|
252
|
+
MessagePack.unpack([0xc5, 0x00, 0x01].pack('C*') + 'a').should == "a"
|
253
|
+
MessagePack.unpack([0xc5, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
|
254
|
+
end
|
255
|
+
|
256
|
+
it "msgpack bin 32 type" do
|
257
|
+
MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x00].pack('C*')).should == ""
|
258
|
+
MessagePack.unpack([0xc6, 0x0, 0x00, 0x00, 0x000].pack('C*')).encoding.should == Encoding::ASCII_8BIT
|
259
|
+
MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x01].pack('C*') + 'a').should == "a"
|
260
|
+
MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
|
261
|
+
end
|
262
|
+
|
4
263
|
class ValueOne
|
5
264
|
attr_reader :num
|
6
265
|
def initialize(num)
|
@@ -41,14 +300,12 @@ describe MessagePack::Unpacker do
|
|
41
300
|
|
42
301
|
describe '#type_registered?' do
|
43
302
|
it 'receive Class or Integer, and return bool' do
|
44
|
-
skip("not supported yet in JRuby implementation") if java?
|
45
303
|
expect(subject.type_registered?(0x00)).to be_falsy
|
46
304
|
expect(subject.type_registered?(0x01)).to be_falsy
|
47
305
|
expect(subject.type_registered?(::ValueOne)).to be_falsy
|
48
306
|
end
|
49
307
|
|
50
308
|
it 'returns true if specified type or class is already registered' do
|
51
|
-
skip("not supported yet in JRuby implementation") if java?
|
52
309
|
subject.register_type(0x30, ::ValueOne, :from_msgpack_ext)
|
53
310
|
subject.register_type(0x31, ::ValueTwo, :from_msgpack_ext)
|
54
311
|
|
@@ -62,7 +319,6 @@ describe MessagePack::Unpacker do
|
|
62
319
|
end
|
63
320
|
|
64
321
|
it 'cannot detect unpack rule with block, not method' do
|
65
|
-
skip("not supported yet in JRuby implementation") if java?
|
66
322
|
subject.register_type(0x40){|data| ValueOne.from_msgpack_ext(data) }
|
67
323
|
|
68
324
|
expect(subject.type_registered?(0x40)).to be_truthy
|
@@ -72,7 +328,6 @@ describe MessagePack::Unpacker do
|
|
72
328
|
|
73
329
|
context 'with ext definitions' do
|
74
330
|
it 'get type and class mapping for packing' do
|
75
|
-
skip("not supported yet in JRuby implementation") if java?
|
76
331
|
unpacker = MessagePack::Unpacker.new
|
77
332
|
unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
|
78
333
|
unpacker.register_type(0x02){|data| ValueTwo.from_msgpack_ext(data) }
|
@@ -83,7 +338,6 @@ describe MessagePack::Unpacker do
|
|
83
338
|
end
|
84
339
|
|
85
340
|
it 'returns a Array of Hash which contains :type, :class and :unpacker' do
|
86
|
-
skip("not supported yet in JRuby implementation") if java?
|
87
341
|
unpacker = MessagePack::Unpacker.new
|
88
342
|
unpacker.register_type(0x02, ValueTwo, :from_msgpack_ext)
|
89
343
|
unpacker.register_type(0x01, ValueOne, :from_msgpack_ext)
|
@@ -107,7 +361,6 @@ describe MessagePack::Unpacker do
|
|
107
361
|
end
|
108
362
|
|
109
363
|
it 'returns a Array of Hash, which contains nil for class if block unpacker specified' do
|
110
|
-
skip("not supported yet in JRuby implementation") if java?
|
111
364
|
unpacker = MessagePack::Unpacker.new
|
112
365
|
unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
|
113
366
|
unpacker.register_type(0x02, &ValueTwo.method(:from_msgpack_ext))
|
@@ -130,4 +383,210 @@ describe MessagePack::Unpacker do
|
|
130
383
|
expect(two[:unpacker]).to be_instance_of(Proc)
|
131
384
|
end
|
132
385
|
end
|
386
|
+
|
387
|
+
def flatten(struct, results = [])
|
388
|
+
case struct
|
389
|
+
when Array
|
390
|
+
struct.each { |v| flatten(v, results) }
|
391
|
+
when Hash
|
392
|
+
struct.each { |k, v| flatten(v, flatten(k, results)) }
|
393
|
+
else
|
394
|
+
results << struct
|
395
|
+
end
|
396
|
+
results
|
397
|
+
end
|
398
|
+
|
399
|
+
subject do
|
400
|
+
described_class.new
|
401
|
+
end
|
402
|
+
|
403
|
+
let :buffer1 do
|
404
|
+
MessagePack.pack(:foo => 'bar')
|
405
|
+
end
|
406
|
+
|
407
|
+
let :buffer2 do
|
408
|
+
MessagePack.pack(:hello => {:world => [1, 2, 3]})
|
409
|
+
end
|
410
|
+
|
411
|
+
let :buffer3 do
|
412
|
+
MessagePack.pack(:x => 'y')
|
413
|
+
end
|
414
|
+
|
415
|
+
describe '#read' do
|
416
|
+
context 'with a buffer' do
|
417
|
+
it 'reads objects' do
|
418
|
+
objects = []
|
419
|
+
subject.feed(buffer1)
|
420
|
+
subject.feed(buffer2)
|
421
|
+
subject.feed(buffer3)
|
422
|
+
objects << subject.read
|
423
|
+
objects << subject.read
|
424
|
+
objects << subject.read
|
425
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
426
|
+
end
|
427
|
+
|
428
|
+
it 'reads map header' do
|
429
|
+
subject.feed({}.to_msgpack)
|
430
|
+
subject.read_map_header.should == 0
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'reads array header' do
|
434
|
+
subject.feed([].to_msgpack)
|
435
|
+
subject.read_array_header.should == 0
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe '#each' do
|
441
|
+
context 'with a buffer' do
|
442
|
+
it 'yields each object in the buffer' do
|
443
|
+
objects = []
|
444
|
+
subject.feed(buffer1)
|
445
|
+
subject.feed(buffer2)
|
446
|
+
subject.feed(buffer3)
|
447
|
+
subject.each do |obj|
|
448
|
+
objects << obj
|
449
|
+
end
|
450
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
451
|
+
end
|
452
|
+
|
453
|
+
it 'returns an enumerator when no block is given' do
|
454
|
+
subject.feed(buffer1)
|
455
|
+
subject.feed(buffer2)
|
456
|
+
subject.feed(buffer3)
|
457
|
+
enum = subject.each
|
458
|
+
enum.map { |obj| obj.keys.first }.should == %w[foo hello x]
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
context 'with a stream passed to the constructor' do
|
463
|
+
it 'yields each object in the stream' do
|
464
|
+
objects = []
|
465
|
+
unpacker = described_class.new(StringIO.new(buffer1 + buffer2 + buffer3))
|
466
|
+
unpacker.each do |obj|
|
467
|
+
objects << obj
|
468
|
+
end
|
469
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
describe '#feed_each' do
|
475
|
+
it 'feeds the buffer then runs #each' do
|
476
|
+
objects = []
|
477
|
+
subject.feed_each(buffer1 + buffer2 + buffer3) do |obj|
|
478
|
+
objects << obj
|
479
|
+
end
|
480
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
481
|
+
end
|
482
|
+
|
483
|
+
it 'handles chunked data' do
|
484
|
+
objects = []
|
485
|
+
buffer = buffer1 + buffer2 + buffer3
|
486
|
+
buffer.chars.each do |ch|
|
487
|
+
subject.feed_each(ch) do |obj|
|
488
|
+
objects << obj
|
489
|
+
end
|
490
|
+
end
|
491
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
context 'regressions' do
|
496
|
+
it 'handles massive arrays (issue #2)' do
|
497
|
+
array = ['foo'] * 10_000
|
498
|
+
MessagePack.unpack(MessagePack.pack(array)).size.should == 10_000
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
context 'extensions' do
|
503
|
+
context 'symbolized keys' do
|
504
|
+
let :buffer do
|
505
|
+
MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
|
506
|
+
end
|
507
|
+
|
508
|
+
let :unpacker do
|
509
|
+
described_class.new(:symbolize_keys => true)
|
510
|
+
end
|
511
|
+
|
512
|
+
it 'can symbolize keys when using #each' do
|
513
|
+
objs = []
|
514
|
+
unpacker.feed(buffer)
|
515
|
+
unpacker.each do |obj|
|
516
|
+
objs << obj
|
517
|
+
end
|
518
|
+
objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
|
519
|
+
end
|
520
|
+
|
521
|
+
it 'can symbolize keys when using #feed_each' do
|
522
|
+
objs = []
|
523
|
+
unpacker.feed_each(buffer) do |obj|
|
524
|
+
objs << obj
|
525
|
+
end
|
526
|
+
objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
context 'binary encoding', :encodings do
|
531
|
+
let :buffer do
|
532
|
+
MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
|
533
|
+
end
|
534
|
+
|
535
|
+
let :unpacker do
|
536
|
+
described_class.new()
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'decodes binary as ascii-8bit when using #feed' do
|
540
|
+
objs = []
|
541
|
+
unpacker.feed(buffer)
|
542
|
+
unpacker.each do |obj|
|
543
|
+
objs << obj
|
544
|
+
end
|
545
|
+
strings = flatten(objs).grep(String)
|
546
|
+
strings.should == %w[hello world nested object structure]
|
547
|
+
strings.map(&:encoding).uniq.should == [Encoding::ASCII_8BIT]
|
548
|
+
end
|
549
|
+
|
550
|
+
it 'decodes binary as ascii-8bit when using #feed_each' do
|
551
|
+
objs = []
|
552
|
+
unpacker.feed_each(buffer) do |obj|
|
553
|
+
objs << obj
|
554
|
+
end
|
555
|
+
strings = flatten(objs).grep(String)
|
556
|
+
strings.should == %w[hello world nested object structure]
|
557
|
+
strings.map(&:encoding).uniq.should == [Encoding::ASCII_8BIT]
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
context 'string encoding', :encodings do
|
562
|
+
let :buffer do
|
563
|
+
MessagePack.pack({'hello'.force_encoding(Encoding::UTF_8) => 'world'.force_encoding(Encoding::UTF_8), 'nested'.force_encoding(Encoding::UTF_8) => ['object'.force_encoding(Encoding::UTF_8), {'structure'.force_encoding(Encoding::UTF_8) => true}]})
|
564
|
+
end
|
565
|
+
|
566
|
+
let :unpacker do
|
567
|
+
described_class.new()
|
568
|
+
end
|
569
|
+
|
570
|
+
it 'decodes string as utf-8 when using #feed' do
|
571
|
+
objs = []
|
572
|
+
unpacker.feed(buffer)
|
573
|
+
unpacker.each do |obj|
|
574
|
+
objs << obj
|
575
|
+
end
|
576
|
+
strings = flatten(objs).grep(String)
|
577
|
+
strings.should == %w[hello world nested object structure]
|
578
|
+
strings.map(&:encoding).uniq.should == [Encoding::UTF_8]
|
579
|
+
end
|
580
|
+
|
581
|
+
it 'decodes binary as ascii-8bit when using #feed_each' do
|
582
|
+
objs = []
|
583
|
+
unpacker.feed_each(buffer) do |obj|
|
584
|
+
objs << obj
|
585
|
+
end
|
586
|
+
strings = flatten(objs).grep(String)
|
587
|
+
strings.should == %w[hello world nested object structure]
|
588
|
+
strings.map(&:encoding).uniq.should == [Encoding::UTF_8]
|
589
|
+
end
|
590
|
+
end
|
591
|
+
end
|
133
592
|
end
|