msgpack 1.4.4.pre1-java → 1.4.5-java

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.
@@ -1,828 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require 'stringio'
4
- require 'tempfile'
5
- require 'zlib'
6
-
7
- require 'spec_helper'
8
-
9
- describe MessagePack::Unpacker do
10
- let :unpacker do
11
- MessagePack::Unpacker.new
12
- end
13
-
14
- let :packer do
15
- MessagePack::Packer.new
16
- end
17
-
18
- it 'gets options to specify how to unpack values' do
19
- u1 = MessagePack::Unpacker.new
20
- u1.symbolize_keys?.should == false
21
- u1.freeze?.should == false
22
- u1.allow_unknown_ext?.should == false
23
-
24
- u2 = MessagePack::Unpacker.new(symbolize_keys: true, freeze: true, allow_unknown_ext: true)
25
- u2.symbolize_keys?.should == true
26
- u2.freeze?.should == true
27
- u2.allow_unknown_ext?.should == true
28
- end
29
-
30
- if automatic_string_keys_deduplication?
31
- it 'ensure string hash keys are deduplicated' do
32
- sample_data = [{"foo" => 1}, {"foo" => 2}]
33
- sample_packed = MessagePack.pack(sample_data).force_encoding('ASCII-8BIT')
34
- unpacker.feed(sample_packed)
35
- hashes = nil
36
- unpacker.each { |obj| hashes = obj }
37
- expect(hashes[0].keys.first).to equal(hashes[1].keys.first)
38
- end
39
-
40
- it 'ensure strings are not deduplicated' do
41
- sample_data = ["foo"]
42
- sample_packed = MessagePack.pack(sample_data).force_encoding('ASCII-8BIT')
43
- unpacker.feed(sample_packed)
44
- ary = nil
45
- unpacker.each { |obj| ary = obj }
46
- expect(ary.first.frozen?).to eq(false)
47
- end
48
- end
49
-
50
- it 'gets IO or object which has #read to read data from it' do
51
- sample_data = {"message" => "morning!", "num" => 1}
52
- sample_packed = MessagePack.pack(sample_data).force_encoding('ASCII-8BIT')
53
-
54
- Tempfile.open("for_io") do |file|
55
- file.sync = true
56
- file.write sample_packed
57
- file.rewind
58
-
59
- u1 = MessagePack::Unpacker.new(file)
60
- u1.each do |obj|
61
- expect(obj).to eql(sample_data)
62
- end
63
- file.unlink
64
- end
65
-
66
- sio = StringIO.new(sample_packed)
67
- u2 = MessagePack::Unpacker.new(sio)
68
- u2.each do |obj|
69
- expect(obj).to eql(sample_data)
70
- end
71
-
72
- dio = StringIO.new
73
- Zlib::GzipWriter.wrap(dio){|gz| gz.write sample_packed }
74
- reader = Zlib::GzipReader.new(StringIO.new(dio.string))
75
- u3 = MessagePack::Unpacker.new(reader)
76
- u3.each do |obj|
77
- expect(obj).to eql(sample_data)
78
- end
79
-
80
- class DummyIO
81
- def initialize
82
- @buf = "".force_encoding('ASCII-8BIT')
83
- @pos = 0
84
- end
85
- def write(val)
86
- @buf << val.to_s
87
- end
88
- def read(length=nil,outbuf="")
89
- if @pos == @buf.size
90
- nil
91
- elsif length.nil?
92
- val = @buf[@pos..(@buf.size)]
93
- @pos = @buf.size
94
- outbuf << val
95
- outbuf
96
- else
97
- val = @buf[@pos..(@pos + length)]
98
- @pos += val.size
99
- @pos = @buf.size if @pos > @buf.size
100
- outbuf << val
101
- outbuf
102
- end
103
- end
104
- def flush
105
- # nop
106
- end
107
- end
108
-
109
- dio = DummyIO.new
110
- dio.write sample_packed
111
- u4 = MessagePack::Unpacker.new(dio)
112
- u4.each do |obj|
113
- expect(obj).to eql(sample_data)
114
- end
115
- end
116
-
117
- it 'read_array_header succeeds' do
118
- unpacker.feed("\x91")
119
- unpacker.read_array_header.should == 1
120
- end
121
-
122
- it 'read_array_header fails' do
123
- unpacker.feed("\x81")
124
- lambda {
125
- unpacker.read_array_header
126
- }.should raise_error(MessagePack::TypeError) # TypeError is included in UnexpectedTypeError
127
- lambda {
128
- unpacker.read_array_header
129
- }.should raise_error(MessagePack::UnexpectedTypeError)
130
- end
131
-
132
- it 'read_map_header converts an map to key-value sequence' do
133
- packer.write_array_header(2)
134
- packer.write("e")
135
- packer.write(1)
136
- unpacker = MessagePack::Unpacker.new
137
- unpacker.feed(packer.to_s)
138
- unpacker.read_array_header.should == 2
139
- unpacker.read.should == "e"
140
- unpacker.read.should == 1
141
- end
142
-
143
- it 'read_map_header succeeds' do
144
- unpacker.feed("\x81")
145
- unpacker.read_map_header.should == 1
146
- end
147
-
148
- it 'read_map_header converts an map to key-value sequence' do
149
- packer.write_map_header(1)
150
- packer.write("k")
151
- packer.write("v")
152
- unpacker = MessagePack::Unpacker.new
153
- unpacker.feed(packer.to_s)
154
- unpacker.read_map_header.should == 1
155
- unpacker.read.should == "k"
156
- unpacker.read.should == "v"
157
- end
158
-
159
- it 'read_map_header fails' do
160
- unpacker.feed("\x91")
161
- lambda {
162
- unpacker.read_map_header
163
- }.should raise_error(MessagePack::TypeError) # TypeError is included in UnexpectedTypeError
164
- lambda {
165
- unpacker.read_map_header
166
- }.should raise_error(MessagePack::UnexpectedTypeError)
167
- end
168
-
169
- it 'read raises EOFError before feeding' do
170
- lambda {
171
- unpacker.read
172
- }.should raise_error(EOFError)
173
- end
174
-
175
- let :sample_object do
176
- [1024, {["a","b"]=>["c","d"]}, ["e","f"], "d", 70000, 4.12, 1.5, 1.5, 1.5]
177
- end
178
-
179
- it 'feed and each continue internal state' do
180
- raw = sample_object.to_msgpack.to_s * 4
181
- objects = []
182
-
183
- raw.split(//).each do |b|
184
- unpacker.feed(b)
185
- unpacker.each {|c|
186
- objects << c
187
- }
188
- end
189
-
190
- objects.should == [sample_object] * 4
191
- end
192
-
193
- it 'feed_each continues internal state' do
194
- raw = sample_object.to_msgpack.to_s * 4
195
- objects = []
196
-
197
- raw.split(//).each do |b|
198
- unpacker.feed_each(b) {|c|
199
- objects << c
200
- }
201
- end
202
-
203
- objects.should == [sample_object] * 4
204
- end
205
-
206
- it 'feed_each enumerator' do
207
- raw = sample_object.to_msgpack.to_s * 4
208
-
209
- enum = unpacker.feed_each(raw)
210
- enum.should be_instance_of(Enumerator)
211
- enum.to_a.should == [sample_object] * 4
212
- end
213
-
214
- it 'reset clears internal buffer' do
215
- # 1-element array
216
- unpacker.feed("\x91")
217
- unpacker.reset
218
- unpacker.feed("\x01")
219
-
220
- unpacker.each.map {|x| x }.should == [1]
221
- end
222
-
223
- it 'reset clears internal state' do
224
- # 1-element array
225
- unpacker.feed("\x91")
226
- unpacker.each.map {|x| x }.should == []
227
-
228
- unpacker.reset
229
-
230
- unpacker.feed("\x01")
231
- unpacker.each.map {|x| x }.should == [1]
232
- end
233
-
234
- it 'frozen short strings' do
235
- raw = sample_object.to_msgpack.to_s.force_encoding('UTF-8')
236
- lambda {
237
- unpacker.feed_each(raw.freeze) { }
238
- }.should_not raise_error
239
- end
240
-
241
- it 'frozen long strings' do
242
- raw = (sample_object.to_msgpack.to_s * 10240).force_encoding('UTF-8')
243
- lambda {
244
- unpacker.feed_each(raw.freeze) { }
245
- }.should_not raise_error
246
- end
247
-
248
- it 'read raises invalid byte error' do
249
- unpacker.feed("\xc1")
250
- lambda {
251
- unpacker.read
252
- }.should raise_error(MessagePack::MalformedFormatError)
253
- end
254
-
255
- it "gc mark" do
256
- raw = sample_object.to_msgpack.to_s * 4
257
-
258
- n = 0
259
- raw.split(//).each do |b|
260
- GC.start
261
- unpacker.feed_each(b) {|o|
262
- GC.start
263
- o.should == sample_object
264
- n += 1
265
- }
266
- GC.start
267
- end
268
-
269
- n.should == 4
270
- end
271
-
272
- it "buffer" do
273
- orig = "a"*32*1024*4
274
- raw = orig.to_msgpack.to_s
275
-
276
- n = 655
277
- times = raw.size / n
278
- times += 1 unless raw.size % n == 0
279
-
280
- off = 0
281
- parsed = false
282
-
283
- times.times do
284
- parsed.should == false
285
-
286
- seg = raw[off, n]
287
- off += seg.length
288
-
289
- unpacker.feed_each(seg) {|obj|
290
- parsed.should == false
291
- obj.should == orig
292
- parsed = true
293
- }
294
- end
295
-
296
- parsed.should == true
297
- end
298
-
299
- it 'MessagePack.unpack symbolize_keys' do
300
- symbolized_hash = {:a => 'b', :c => 'd'}
301
- MessagePack.load(MessagePack.pack(symbolized_hash), :symbolize_keys => true).should == symbolized_hash
302
- MessagePack.unpack(MessagePack.pack(symbolized_hash), :symbolize_keys => true).should == symbolized_hash
303
- end
304
-
305
- it 'Unpacker#unpack symbolize_keys' do
306
- unpacker = MessagePack::Unpacker.new(:symbolize_keys => true)
307
- symbolized_hash = {:a => 'b', :c => 'd'}
308
- unpacker.feed(MessagePack.pack(symbolized_hash)).read.should == symbolized_hash
309
- end
310
-
311
- it "msgpack str 8 type" do
312
- MessagePack.unpack([0xd9, 0x00].pack('C*')).should == ""
313
- MessagePack.unpack([0xd9, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
314
- MessagePack.unpack([0xd9, 0x01].pack('C*') + 'a').should == "a"
315
- MessagePack.unpack([0xd9, 0x02].pack('C*') + 'aa').should == "aa"
316
- end
317
-
318
- it "msgpack str 16 type" do
319
- MessagePack.unpack([0xda, 0x00, 0x00].pack('C*')).should == ""
320
- MessagePack.unpack([0xda, 0x00, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
321
- MessagePack.unpack([0xda, 0x00, 0x01].pack('C*') + 'a').should == "a"
322
- MessagePack.unpack([0xda, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
323
- end
324
-
325
- it "msgpack str 32 type" do
326
- MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x00].pack('C*')).should == ""
327
- MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x00].pack('C*')).encoding.should == Encoding::UTF_8
328
- MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x01].pack('C*') + 'a').should == "a"
329
- MessagePack.unpack([0xdb, 0x00, 0x00, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
330
- end
331
-
332
- it "msgpack bin 8 type" do
333
- MessagePack.unpack([0xc4, 0x00].pack('C*')).should == ""
334
- MessagePack.unpack([0xc4, 0x00].pack('C*')).encoding.should == Encoding::ASCII_8BIT
335
- MessagePack.unpack([0xc4, 0x01].pack('C*') + 'a').should == "a"
336
- MessagePack.unpack([0xc4, 0x02].pack('C*') + 'aa').should == "aa"
337
- end
338
-
339
- it "msgpack bin 16 type" do
340
- MessagePack.unpack([0xc5, 0x00, 0x00].pack('C*')).should == ""
341
- MessagePack.unpack([0xc5, 0x00, 0x00].pack('C*')).encoding.should == Encoding::ASCII_8BIT
342
- MessagePack.unpack([0xc5, 0x00, 0x01].pack('C*') + 'a').should == "a"
343
- MessagePack.unpack([0xc5, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
344
- end
345
-
346
- it "msgpack bin 32 type" do
347
- MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x00].pack('C*')).should == ""
348
- MessagePack.unpack([0xc6, 0x0, 0x00, 0x00, 0x000].pack('C*')).encoding.should == Encoding::ASCII_8BIT
349
- MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x01].pack('C*') + 'a').should == "a"
350
- MessagePack.unpack([0xc6, 0x00, 0x00, 0x00, 0x02].pack('C*') + 'aa').should == "aa"
351
- end
352
-
353
- describe "ext formats" do
354
- let(:unpacker) { MessagePack::Unpacker.new(allow_unknown_ext: true) }
355
-
356
- [1, 2, 4, 8, 16].zip([0xd4, 0xd5, 0xd6, 0xd7, 0xd8]).each do |n,b|
357
- it "msgpack fixext #{n} format" do
358
- unpacker.feed([b, 1].pack('CC') + "a"*n).unpack.should == MessagePack::ExtensionValue.new(1, "a"*n)
359
- unpacker.feed([b, -1].pack('CC') + "a"*n).unpack.should == MessagePack::ExtensionValue.new(-1, "a"*n)
360
- end
361
- end
362
-
363
- it "msgpack ext 8 format" do
364
- unpacker.feed([0xc7, 0, 1].pack('CCC')).unpack.should == MessagePack::ExtensionValue.new(1, "")
365
- unpacker.feed([0xc7, 255, -1].pack('CCC') + "a"*255).unpack.should == MessagePack::ExtensionValue.new(-1, "a"*255)
366
- end
367
-
368
- it "msgpack ext 16 format" do
369
- unpacker.feed([0xc8, 0, 1].pack('CnC')).unpack.should == MessagePack::ExtensionValue.new(1, "")
370
- unpacker.feed([0xc8, 256, -1].pack('CnC') + "a"*256).unpack.should == MessagePack::ExtensionValue.new(-1, "a"*256)
371
- end
372
-
373
- it "msgpack ext 32 format" do
374
- unpacker.feed([0xc9, 0, 1].pack('CNC')).unpack.should == MessagePack::ExtensionValue.new(1, "")
375
- unpacker.feed([0xc9, 256, -1].pack('CNC') + "a"*256).unpack.should == MessagePack::ExtensionValue.new(-1, "a"*256)
376
- unpacker.feed([0xc9, 65536, -1].pack('CNC') + "a"*65536).unpack.should == MessagePack::ExtensionValue.new(-1, "a"*65536)
377
- end
378
- end
379
-
380
- class ValueOne
381
- attr_reader :num
382
- def initialize(num)
383
- @num = num
384
- end
385
- def ==(obj)
386
- self.num == obj.num
387
- end
388
- def num
389
- @num
390
- end
391
- def to_msgpack_ext
392
- @num.to_msgpack
393
- end
394
- def self.from_msgpack_ext(data)
395
- self.new(MessagePack.unpack(data))
396
- end
397
- end
398
-
399
- class ValueTwo
400
- attr_reader :num_s
401
- def initialize(num)
402
- @num_s = num.to_s
403
- end
404
- def ==(obj)
405
- self.num_s == obj.num_s
406
- end
407
- def num
408
- @num_s.to_i
409
- end
410
- def to_msgpack_ext
411
- @num_s.to_msgpack
412
- end
413
- def self.from_msgpack_ext(data)
414
- self.new(MessagePack.unpack(data))
415
- end
416
- end
417
-
418
- describe '#type_registered?' do
419
- it 'receive Class or Integer, and return bool' do
420
- expect(subject.type_registered?(0x00)).to be_falsy
421
- expect(subject.type_registered?(0x01)).to be_falsy
422
- expect(subject.type_registered?(::ValueOne)).to be_falsy
423
- end
424
-
425
- it 'returns true if specified type or class is already registered' do
426
- subject.register_type(0x30, ::ValueOne, :from_msgpack_ext)
427
- subject.register_type(0x31, ::ValueTwo, :from_msgpack_ext)
428
-
429
- expect(subject.type_registered?(0x00)).to be_falsy
430
- expect(subject.type_registered?(0x01)).to be_falsy
431
-
432
- expect(subject.type_registered?(0x30)).to be_truthy
433
- expect(subject.type_registered?(0x31)).to be_truthy
434
- expect(subject.type_registered?(::ValueOne)).to be_truthy
435
- expect(subject.type_registered?(::ValueTwo)).to be_truthy
436
- end
437
-
438
- it 'cannot detect unpack rule with block, not method' do
439
- subject.register_type(0x40){|data| ValueOne.from_msgpack_ext(data) }
440
-
441
- expect(subject.type_registered?(0x40)).to be_truthy
442
- expect(subject.type_registered?(ValueOne)).to be_falsy
443
- end
444
- end
445
-
446
- context 'with ext definitions' do
447
- it 'get type and class mapping for packing' do
448
- unpacker = MessagePack::Unpacker.new
449
- unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
450
- unpacker.register_type(0x02){|data| ValueTwo.from_msgpack_ext(data) }
451
-
452
- unpacker = MessagePack::Unpacker.new
453
- unpacker.register_type(0x01, ValueOne, :from_msgpack_ext)
454
- unpacker.register_type(0x02, ValueTwo, :from_msgpack_ext)
455
- end
456
-
457
- it 'returns a Array of Hash which contains :type, :class and :unpacker' do
458
- unpacker = MessagePack::Unpacker.new
459
- unpacker.register_type(0x02, ValueTwo, :from_msgpack_ext)
460
- unpacker.register_type(0x01, ValueOne, :from_msgpack_ext)
461
-
462
- list = unpacker.registered_types
463
-
464
- expect(list).to be_a(Array)
465
- expect(list.size).to eq(2)
466
-
467
- one = list[0]
468
- expect(one.keys.sort).to eq([:type, :class, :unpacker].sort)
469
- expect(one[:type]).to eq(0x01)
470
- expect(one[:class]).to eq(ValueOne)
471
- expect(one[:unpacker]).to eq(:from_msgpack_ext)
472
-
473
- two = list[1]
474
- expect(two.keys.sort).to eq([:type, :class, :unpacker].sort)
475
- expect(two[:type]).to eq(0x02)
476
- expect(two[:class]).to eq(ValueTwo)
477
- expect(two[:unpacker]).to eq(:from_msgpack_ext)
478
- end
479
-
480
- it 'returns a Array of Hash, which contains nil for class if block unpacker specified' do
481
- unpacker = MessagePack::Unpacker.new
482
- unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
483
- unpacker.register_type(0x02, &ValueTwo.method(:from_msgpack_ext))
484
-
485
- list = unpacker.registered_types
486
-
487
- expect(list).to be_a(Array)
488
- expect(list.size).to eq(2)
489
-
490
- one = list[0]
491
- expect(one.keys.sort).to eq([:type, :class, :unpacker].sort)
492
- expect(one[:type]).to eq(0x01)
493
- expect(one[:class]).to be_nil
494
- expect(one[:unpacker]).to be_instance_of(Proc)
495
-
496
- two = list[1]
497
- expect(two.keys.sort).to eq([:type, :class, :unpacker].sort)
498
- expect(two[:type]).to eq(0x02)
499
- expect(two[:class]).to be_nil
500
- expect(two[:unpacker]).to be_instance_of(Proc)
501
- end
502
-
503
- describe "registering an ext type for a module" do
504
- subject { unpacker.feed("\xc7\x06\x00module").unpack }
505
-
506
- let(:unpacker) { MessagePack::Unpacker.new }
507
-
508
- before do
509
- mod = Module.new do
510
- def self.from_msgpack_ext(data)
511
- "unpacked #{data}"
512
- end
513
- end
514
- stub_const('Mod', mod)
515
- end
516
-
517
- before { unpacker.register_type(0x00, Mod, :from_msgpack_ext) }
518
- it { is_expected.to eq "unpacked module" }
519
- end
520
- end
521
-
522
- def flatten(struct, results = [])
523
- case struct
524
- when Array
525
- struct.each { |v| flatten(v, results) }
526
- when Hash
527
- struct.each { |k, v| flatten(v, flatten(k, results)) }
528
- else
529
- results << struct
530
- end
531
- results
532
- end
533
-
534
- subject do
535
- described_class.new
536
- end
537
-
538
- let :buffer1 do
539
- MessagePack.pack(:foo => 'bar')
540
- end
541
-
542
- let :buffer2 do
543
- MessagePack.pack(:hello => {:world => [1, 2, 3]})
544
- end
545
-
546
- let :buffer3 do
547
- MessagePack.pack(:x => 'y')
548
- end
549
-
550
- describe '#read' do
551
- context 'with a buffer' do
552
- it 'reads objects' do
553
- objects = []
554
- subject.feed(buffer1)
555
- subject.feed(buffer2)
556
- subject.feed(buffer3)
557
- objects << subject.read
558
- objects << subject.read
559
- objects << subject.read
560
- objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
561
- end
562
-
563
- it 'reads map header' do
564
- subject.feed({}.to_msgpack)
565
- subject.read_map_header.should == 0
566
- end
567
-
568
- it 'reads array header' do
569
- subject.feed([].to_msgpack)
570
- subject.read_array_header.should == 0
571
- end
572
- end
573
- end
574
-
575
- describe '#each' do
576
- context 'with a buffer' do
577
- it 'yields each object in the buffer' do
578
- objects = []
579
- subject.feed(buffer1)
580
- subject.feed(buffer2)
581
- subject.feed(buffer3)
582
- subject.each do |obj|
583
- objects << obj
584
- end
585
- objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
586
- end
587
-
588
- it 'returns an enumerator when no block is given' do
589
- subject.feed(buffer1)
590
- subject.feed(buffer2)
591
- subject.feed(buffer3)
592
- enum = subject.each
593
- enum.map { |obj| obj.keys.first }.should == %w[foo hello x]
594
- end
595
- end
596
-
597
- context 'with a stream passed to the constructor' do
598
- it 'yields each object in the stream' do
599
- objects = []
600
- unpacker = described_class.new(StringIO.new(buffer1 + buffer2 + buffer3))
601
- unpacker.each do |obj|
602
- objects << obj
603
- end
604
- objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
605
- end
606
- end
607
-
608
- context 'with a stream and symbolize_keys passed to the constructor' do
609
- it 'yields each object in the stream, with symbolized keys' do
610
- objects = []
611
- unpacker = described_class.new(StringIO.new(buffer1 + buffer2 + buffer3), symbolize_keys: true)
612
- unpacker.each do |obj|
613
- objects << obj
614
- end
615
- objects.should == [{:foo => 'bar'}, {:hello => {:world => [1, 2, 3]}}, {:x => 'y'}]
616
- end
617
- end
618
- end
619
-
620
- describe '#feed_each' do
621
- it 'feeds the buffer then runs #each' do
622
- objects = []
623
- subject.feed_each(buffer1 + buffer2 + buffer3) do |obj|
624
- objects << obj
625
- end
626
- objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
627
- end
628
-
629
- it 'handles chunked data' do
630
- objects = []
631
- buffer = buffer1 + buffer2 + buffer3
632
- buffer.chars.each do |ch|
633
- subject.feed_each(ch) do |obj|
634
- objects << obj
635
- end
636
- end
637
- objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
638
- end
639
- end
640
-
641
- context 'regressions' do
642
- it 'handles massive arrays (issue #2)' do
643
- array = ['foo'] * 10_000
644
- MessagePack.unpack(MessagePack.pack(array)).size.should == 10_000
645
- end
646
-
647
- it 'preserves string encoding (issue #200)' do
648
- string = 'a'.force_encoding(Encoding::UTF_8)
649
- MessagePack.unpack(MessagePack.pack(string)).encoding.should == string.encoding
650
-
651
- string *= 256
652
- MessagePack.unpack(MessagePack.pack(string)).encoding.should == string.encoding
653
- end
654
- end
655
-
656
- context 'extensions' do
657
- context 'symbolized keys' do
658
- let :buffer do
659
- MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
660
- end
661
-
662
- let :unpacker do
663
- described_class.new(:symbolize_keys => true)
664
- end
665
-
666
- it 'can symbolize keys when using #each' do
667
- objs = []
668
- unpacker.feed(buffer)
669
- unpacker.each do |obj|
670
- objs << obj
671
- end
672
- objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
673
- end
674
-
675
- it 'can symbolize keys when using #feed_each' do
676
- objs = []
677
- unpacker.feed_each(buffer) do |obj|
678
- objs << obj
679
- end
680
- objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
681
- end
682
- end
683
-
684
- context 'freeze' do
685
- let :struct do
686
- {'hello' => 'world', 'nested' => ['object', {'structure' => true}]}
687
- end
688
-
689
- let :buffer do
690
- MessagePack.pack(struct)
691
- end
692
-
693
- let :unpacker do
694
- described_class.new(:freeze => true)
695
- end
696
-
697
- it 'can freeze objects when using .unpack' do
698
- parsed_struct = MessagePack.unpack(buffer, freeze: true)
699
- parsed_struct.should == struct
700
-
701
- parsed_struct.should be_frozen
702
- parsed_struct['hello'].should be_frozen
703
- parsed_struct['nested'].should be_frozen
704
- parsed_struct['nested'][0].should be_frozen
705
- parsed_struct['nested'][1].should be_frozen
706
-
707
- if string_deduplication?
708
- parsed_struct.keys[0].should be_equal('hello'.freeze)
709
- parsed_struct.keys[1].should be_equal('nested'.freeze)
710
- parsed_struct.values[0].should be_equal('world'.freeze)
711
- parsed_struct.values[1][0].should be_equal('object'.freeze)
712
- parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
713
- end
714
- end
715
-
716
- it 'can freeze objects when using #each' do
717
- objs = []
718
- unpacker.feed(buffer)
719
- unpacker.each do |obj|
720
- objs << obj
721
- end
722
-
723
- parsed_struct = objs.first
724
- parsed_struct.should == struct
725
-
726
- parsed_struct.should be_frozen
727
- parsed_struct['hello'].should be_frozen
728
- parsed_struct['nested'].should be_frozen
729
- parsed_struct['nested'][0].should be_frozen
730
- parsed_struct['nested'][1].should be_frozen
731
-
732
- if string_deduplication?
733
- parsed_struct.keys[0].should be_equal('hello'.freeze)
734
- parsed_struct.keys[1].should be_equal('nested'.freeze)
735
- parsed_struct.values[0].should be_equal('world'.freeze)
736
- parsed_struct.values[1][0].should be_equal('object'.freeze)
737
- parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
738
- end
739
- end
740
-
741
- it 'can freeze objects when using #feed_each' do
742
- objs = []
743
- unpacker.feed_each(buffer) do |obj|
744
- objs << obj
745
- end
746
-
747
- parsed_struct = objs.first
748
- parsed_struct.should == struct
749
-
750
- parsed_struct.should be_frozen
751
- parsed_struct['hello'].should be_frozen
752
- parsed_struct['nested'].should be_frozen
753
- parsed_struct['nested'][0].should be_frozen
754
- parsed_struct['nested'][1].should be_frozen
755
-
756
- if string_deduplication?
757
- parsed_struct.keys[0].should be_equal('hello'.freeze)
758
- parsed_struct.keys[1].should be_equal('nested'.freeze)
759
- parsed_struct.values[0].should be_equal('world'.freeze)
760
- parsed_struct.values[1][0].should be_equal('object'.freeze)
761
- parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
762
- end
763
- end
764
- end
765
-
766
- context 'binary encoding', :encodings do
767
- let :buffer do
768
- MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
769
- end
770
-
771
- let :unpacker do
772
- described_class.new()
773
- end
774
-
775
- it 'decodes binary as ascii-8bit when using #feed' do
776
- objs = []
777
- unpacker.feed(buffer)
778
- unpacker.each do |obj|
779
- objs << obj
780
- end
781
- strings = flatten(objs).grep(String)
782
- strings.should == %w[hello world nested object structure]
783
- strings.map(&:encoding).uniq.should == [Encoding::ASCII_8BIT]
784
- end
785
-
786
- it 'decodes binary as ascii-8bit when using #feed_each' do
787
- objs = []
788
- unpacker.feed_each(buffer) do |obj|
789
- objs << obj
790
- end
791
- strings = flatten(objs).grep(String)
792
- strings.should == %w[hello world nested object structure]
793
- strings.map(&:encoding).uniq.should == [Encoding::ASCII_8BIT]
794
- end
795
- end
796
-
797
- context 'string encoding', :encodings do
798
- let :buffer do
799
- 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}]})
800
- end
801
-
802
- let :unpacker do
803
- described_class.new()
804
- end
805
-
806
- it 'decodes string as utf-8 when using #feed' do
807
- objs = []
808
- unpacker.feed(buffer)
809
- unpacker.each do |obj|
810
- objs << obj
811
- end
812
- strings = flatten(objs).grep(String)
813
- strings.should == %w[hello world nested object structure]
814
- strings.map(&:encoding).uniq.should == [Encoding::UTF_8]
815
- end
816
-
817
- it 'decodes binary as ascii-8bit when using #feed_each' do
818
- objs = []
819
- unpacker.feed_each(buffer) do |obj|
820
- objs << obj
821
- end
822
- strings = flatten(objs).grep(String)
823
- strings.should == %w[hello world nested object structure]
824
- strings.map(&:encoding).uniq.should == [Encoding::UTF_8]
825
- end
826
- end
827
- end
828
- end