msgpack 0.7.0dev1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -116,7 +116,7 @@ describe MessagePack do
116
116
  end
117
117
 
118
118
  it 'rasies an error on #unpack with garbage' do
119
- skip "???"
119
+ skip "but nothing was raised. why?"
120
120
  expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
121
121
  end
122
122
  end
@@ -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)
@@ -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