msgpack 1.4.4.pre1-java → 1.4.5-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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