msgpack 1.5.6 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +14 -0
  3. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +4 -9
  4. data/ext/msgpack/buffer.c +51 -38
  5. data/ext/msgpack/buffer.h +5 -9
  6. data/ext/msgpack/buffer_class.c +62 -32
  7. data/ext/msgpack/extconf.rb +3 -5
  8. data/ext/msgpack/factory_class.c +49 -26
  9. data/ext/msgpack/packer.c +3 -4
  10. data/ext/msgpack/packer.h +2 -2
  11. data/ext/msgpack/packer_class.c +58 -63
  12. data/ext/msgpack/packer_class.h +11 -0
  13. data/ext/msgpack/packer_ext_registry.c +2 -2
  14. data/ext/msgpack/packer_ext_registry.h +2 -2
  15. data/ext/msgpack/rbinit.c +1 -1
  16. data/ext/msgpack/sysdep.h +5 -2
  17. data/ext/msgpack/unpacker.c +6 -9
  18. data/ext/msgpack/unpacker.h +4 -3
  19. data/ext/msgpack/unpacker_class.c +55 -37
  20. data/ext/msgpack/unpacker_class.h +11 -0
  21. data/ext/msgpack/unpacker_ext_registry.c +2 -2
  22. data/ext/msgpack/unpacker_ext_registry.h +2 -2
  23. data/lib/msgpack/buffer.rb +9 -0
  24. data/lib/msgpack/packer.rb +4 -0
  25. data/lib/msgpack/unpacker.rb +4 -0
  26. data/lib/msgpack/version.rb +1 -1
  27. data/lib/msgpack.rb +1 -0
  28. data/msgpack.gemspec +5 -2
  29. metadata +18 -46
  30. data/.github/workflows/ci.yaml +0 -57
  31. data/.gitignore +0 -23
  32. data/.rubocop.yml +0 -36
  33. data/Gemfile +0 -9
  34. data/Rakefile +0 -70
  35. data/appveyor.yml +0 -18
  36. data/bench/bench.rb +0 -78
  37. data/doclib/msgpack/buffer.rb +0 -193
  38. data/doclib/msgpack/core_ext.rb +0 -101
  39. data/doclib/msgpack/error.rb +0 -19
  40. data/doclib/msgpack/extension_value.rb +0 -9
  41. data/doclib/msgpack/factory.rb +0 -145
  42. data/doclib/msgpack/packer.rb +0 -209
  43. data/doclib/msgpack/time.rb +0 -22
  44. data/doclib/msgpack/timestamp.rb +0 -44
  45. data/doclib/msgpack/unpacker.rb +0 -183
  46. data/doclib/msgpack.rb +0 -87
  47. data/msgpack.org.md +0 -46
  48. data/spec/bigint_spec.rb +0 -26
  49. data/spec/cases.json +0 -1
  50. data/spec/cases.msg +0 -0
  51. data/spec/cases_compact.msg +0 -0
  52. data/spec/cases_spec.rb +0 -39
  53. data/spec/cruby/buffer_io_spec.rb +0 -255
  54. data/spec/cruby/buffer_packer.rb +0 -29
  55. data/spec/cruby/buffer_spec.rb +0 -575
  56. data/spec/cruby/buffer_unpacker.rb +0 -19
  57. data/spec/cruby/unpacker_spec.rb +0 -70
  58. data/spec/ext_value_spec.rb +0 -99
  59. data/spec/exttypes.rb +0 -51
  60. data/spec/factory_spec.rb +0 -688
  61. data/spec/format_spec.rb +0 -301
  62. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  63. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  64. data/spec/jruby/unpacker_spec.rb +0 -186
  65. data/spec/msgpack_spec.rb +0 -214
  66. data/spec/pack_spec.rb +0 -61
  67. data/spec/packer_spec.rb +0 -575
  68. data/spec/random_compat.rb +0 -24
  69. data/spec/spec_helper.rb +0 -71
  70. data/spec/timestamp_spec.rb +0 -159
  71. data/spec/unpack_spec.rb +0 -57
  72. data/spec/unpacker_spec.rb +0 -859
data/spec/factory_spec.rb DELETED
@@ -1,688 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MessagePack::Factory do
4
- subject do
5
- described_class.new
6
- end
7
-
8
- describe '#packer' do
9
- it 'creates a Packer instance' do
10
- subject.packer.should be_kind_of(MessagePack::Packer)
11
- end
12
-
13
- it 'creates new instance' do
14
- subject.packer.object_id.should_not == subject.packer.object_id
15
- end
16
- end
17
-
18
- describe '#unpacker' do
19
- it 'creates a Unpacker instance' do
20
- subject.unpacker.should be_kind_of(MessagePack::Unpacker)
21
- end
22
-
23
- it 'creates new instance' do
24
- subject.unpacker.object_id.should_not == subject.unpacker.object_id
25
- end
26
-
27
- it 'creates unpacker with symbolize_keys option' do
28
- unpacker = subject.unpacker(symbolize_keys: true)
29
- unpacker.feed(MessagePack.pack({'k'=>'v'}))
30
- unpacker.read.should == {:k => 'v'}
31
- end
32
-
33
- it 'creates unpacker with allow_unknown_ext option' do
34
- unpacker = subject.unpacker(allow_unknown_ext: true)
35
- unpacker.feed(MessagePack::ExtensionValue.new(1, 'a').to_msgpack)
36
- unpacker.read.should == MessagePack::ExtensionValue.new(1, 'a')
37
- end
38
-
39
- it 'creates unpacker without allow_unknown_ext option' do
40
- unpacker = subject.unpacker
41
- unpacker.feed(MessagePack::ExtensionValue.new(1, 'a').to_msgpack)
42
- expect{ unpacker.read }.to raise_error(MessagePack::UnknownExtTypeError)
43
- end
44
-
45
- it 'does not share the extension registry with unpackers' do
46
- subject.register_type(0x00, Symbol)
47
- expect do
48
- unpacker = subject.unpacker
49
- expect do
50
- unpacker.register_type(0x01) {}
51
- end.to change { unpacker.registered_types }
52
-
53
- second_unpacker = subject.unpacker
54
- expect do
55
- second_unpacker.register_type(0x01) {}
56
- end.to_not change { unpacker.registered_types }
57
- end.to_not change { subject.registered_types }
58
- end
59
- end
60
-
61
- describe '#dump and #load' do
62
- it 'can be used like a standard coder' do
63
- subject.register_type(0x00, Symbol)
64
- expect(subject.load(subject.dump(:symbol))).to be == :symbol
65
- end
66
-
67
- it 'is alias as pack and unpack' do
68
- subject.register_type(0x00, Symbol)
69
- expect(subject.unpack(subject.pack(:symbol))).to be == :symbol
70
- end
71
-
72
- it 'accept options' do
73
- hash = subject.unpack(MessagePack.pack('k' => 'v'), symbolize_keys: true)
74
- expect(hash).to be == { k: 'v' }
75
- end
76
- end
77
-
78
- describe '#freeze' do
79
- it 'can freeze factory instance to deny new registrations anymore' do
80
- subject.register_type(0x00, Symbol)
81
- subject.freeze
82
- expect(subject.frozen?).to be_truthy
83
- expect{ subject.register_type(0x01, Array) }.to raise_error(RuntimeError, "can't modify frozen Factory")
84
- end
85
- end
86
-
87
- class MyType
88
- def initialize(a, b)
89
- @a = a
90
- @b = b
91
- end
92
-
93
- attr_reader :a, :b
94
-
95
- def to_msgpack_ext
96
- [a, b].pack('CC')
97
- end
98
-
99
- def self.from_msgpack_ext(data)
100
- new(*data.unpack('CC'))
101
- end
102
-
103
- def to_msgpack_ext_only_a
104
- [a, 0].pack('CC')
105
- end
106
-
107
- def self.from_msgpack_ext_only_b(data)
108
- a, b = *data.unpack('CC')
109
- new(0, b)
110
- end
111
- end
112
-
113
- class MyType2 < MyType
114
- end
115
-
116
- describe '#registered_types' do
117
- it 'returns Array' do
118
- expect(subject.registered_types).to be_instance_of(Array)
119
- end
120
-
121
- it 'returns Array of Hash contains :type, :class, :packer, :unpacker' do
122
- subject.register_type(0x20, ::MyType)
123
- subject.register_type(0x21, ::MyType2)
124
-
125
- list = subject.registered_types
126
-
127
- expect(list.size).to eq(2)
128
- expect(list[0]).to be_instance_of(Hash)
129
- expect(list[1]).to be_instance_of(Hash)
130
- expect(list[0].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
131
- expect(list[1].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
132
-
133
- expect(list[0][:type]).to eq(0x20)
134
- expect(list[0][:class]).to eq(::MyType)
135
- expect(list[0][:packer]).to eq(:to_msgpack_ext)
136
- expect(list[0][:unpacker]).to eq(:from_msgpack_ext)
137
-
138
- expect(list[1][:type]).to eq(0x21)
139
- expect(list[1][:class]).to eq(::MyType2)
140
- expect(list[1][:packer]).to eq(:to_msgpack_ext)
141
- expect(list[1][:unpacker]).to eq(:from_msgpack_ext)
142
- end
143
-
144
- it 'returns Array of Hash which has nil for unregistered feature' do
145
- subject.register_type(0x21, ::MyType2, unpacker: :from_msgpack_ext)
146
- subject.register_type(0x20, ::MyType, packer: :to_msgpack_ext)
147
-
148
- list = subject.registered_types
149
-
150
- expect(list.size).to eq(2)
151
- expect(list[0]).to be_instance_of(Hash)
152
- expect(list[1]).to be_instance_of(Hash)
153
- expect(list[0].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
154
- expect(list[1].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
155
-
156
- expect(list[0][:type]).to eq(0x20)
157
- expect(list[0][:class]).to eq(::MyType)
158
- expect(list[0][:packer]).to eq(:to_msgpack_ext)
159
- expect(list[0][:unpacker]).to be_nil
160
-
161
- expect(list[1][:type]).to eq(0x21)
162
- expect(list[1][:class]).to eq(::MyType2)
163
- expect(list[1][:packer]).to be_nil
164
- expect(list[1][:unpacker]).to eq(:from_msgpack_ext)
165
- end
166
- end
167
-
168
- describe '#type_registered?' do
169
- it 'receive Class or Integer, and return bool' do
170
- expect(subject.type_registered?(0x00)).to be_falsy
171
- expect(subject.type_registered?(0x01)).to be_falsy
172
- expect(subject.type_registered?(::MyType)).to be_falsy
173
- end
174
-
175
- it 'has option to specify what types are registered for' do
176
- expect(subject.type_registered?(0x00, :both)).to be_falsy
177
- expect(subject.type_registered?(0x00, :packer)).to be_falsy
178
- expect(subject.type_registered?(0x00, :unpacker)).to be_falsy
179
- expect{ subject.type_registered?(0x00, :something) }.to raise_error(ArgumentError)
180
- end
181
-
182
- it 'returns true if specified type or class is already registered' do
183
- subject.register_type(0x20, ::MyType)
184
- subject.register_type(0x21, ::MyType2)
185
-
186
- expect(subject.type_registered?(0x00)).to be_falsy
187
- expect(subject.type_registered?(0x01)).to be_falsy
188
-
189
- expect(subject.type_registered?(0x20)).to be_truthy
190
- expect(subject.type_registered?(0x21)).to be_truthy
191
- expect(subject.type_registered?(::MyType)).to be_truthy
192
- expect(subject.type_registered?(::MyType2)).to be_truthy
193
- end
194
- end
195
-
196
- describe '#register_type' do
197
- let :src do
198
- ::MyType.new(1, 2)
199
- end
200
-
201
- it 'registers #to_msgpack_ext and .from_msgpack_ext by default' do
202
- subject.register_type(0x7f, ::MyType)
203
-
204
- data = subject.packer.write(src).to_s
205
- my = subject.unpacker.feed(data).read
206
- my.a.should == 1
207
- my.b.should == 2
208
- end
209
-
210
- it 'registers custom packer method name' do
211
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext_only_a, unpacker: :from_msgpack_ext)
212
-
213
- data = subject.packer.write(src).to_s
214
- my = subject.unpacker.feed(data).read
215
- my.a.should == 1
216
- my.b.should == 0
217
- end
218
-
219
- it 'registers custom unpacker method name' do
220
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext, unpacker: 'from_msgpack_ext_only_b')
221
-
222
- data = subject.packer.write(src).to_s
223
- my = subject.unpacker.feed(data).read
224
- my.a.should == 0
225
- my.b.should == 2
226
- end
227
-
228
- it 'registers custom proc objects' do
229
- pk = lambda {|obj| [obj.a + obj.b].pack('C') }
230
- uk = lambda {|data| ::MyType.new(data.unpack('C').first, -1) }
231
- subject.register_type(0x7f, ::MyType, packer: pk, unpacker: uk)
232
-
233
- data = subject.packer.write(src).to_s
234
- my = subject.unpacker.feed(data).read
235
- my.a.should == 3
236
- my.b.should == -1
237
- end
238
-
239
- it 'does not affect existent packer and unpackers' do
240
- subject.register_type(0x7f, ::MyType)
241
- packer = subject.packer
242
- unpacker = subject.unpacker
243
-
244
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext_only_a, unpacker: :from_msgpack_ext_only_b)
245
-
246
- data = packer.write(src).to_s
247
- my = unpacker.feed(data).read
248
- my.a.should == 1
249
- my.b.should == 2
250
- end
251
-
252
- describe "registering an ext type for a module" do
253
- before do
254
- mod = Module.new do
255
- def self.from_msgpack_ext(data)
256
- "unpacked #{data}"
257
- end
258
-
259
- def to_msgpack_ext
260
- 'value_msgpacked'
261
- end
262
- end
263
- stub_const('Mod', mod)
264
- end
265
- let(:factory) { described_class.new }
266
- before { factory.register_type(0x01, Mod) }
267
-
268
- describe "packing an object whose class included the module" do
269
- subject { factory.packer.pack(value).to_s }
270
- before { stub_const('Value', Class.new{ include Mod }) }
271
- let(:value) { Value.new }
272
- it { is_expected.to eq "\xC7\x0F\x01value_msgpacked".force_encoding(Encoding::BINARY) }
273
- end
274
-
275
- describe "packing an object which has been extended by the module" do
276
- subject { factory.packer.pack(object).to_s }
277
- let(:object) { Object.new.extend Mod }
278
- it { is_expected.to eq "\xC7\x0F\x01value_msgpacked".force_encoding(Encoding::BINARY) }
279
- end
280
-
281
- describe "unpacking with the module" do
282
- subject { factory.unpacker.feed("\xC7\x06\x01module".force_encoding(Encoding::BINARY)).unpack }
283
- it { is_expected.to eq "unpacked module" }
284
- end
285
- end
286
-
287
- describe "registering an ext type for Integer" do
288
- let(:factory) { described_class.new }
289
- let(:bigint) { 10**150 }
290
-
291
- it 'does not work by default without passing `oversized_integer_extension: true`' do
292
- factory.register_type(0x01, Integer, packer: :to_s, unpacker: method(:Integer))
293
-
294
- expect do
295
- factory.dump(bigint)
296
- end.to raise_error RangeError
297
- end
298
-
299
- it 'raises ArgumentError if the type is not Integer' do
300
- expect do
301
- factory.register_type(0x01, MyType, packer: :to_s, unpacker: method(:Integer), oversized_integer_extension: true)
302
- end.to raise_error(ArgumentError)
303
- end
304
-
305
- it 'invokes the packer if registered with `oversized_integer_extension: true`' do
306
- factory.register_type(0x01, Integer, packer: :to_s, unpacker: method(:Integer), oversized_integer_extension: true)
307
-
308
- expect(factory.load(factory.dump(bigint))).to be == bigint
309
- end
310
-
311
- it 'does not use the oversized_integer_extension packer for integers fitting in native types' do
312
- factory.register_type(
313
- 0x01,
314
- Integer,
315
- packer: ->(int) { raise NotImplementedError },
316
- unpacker: ->(payload) { raise NotImplementedError },
317
- oversized_integer_extension: true
318
- )
319
-
320
- expect(factory.dump(42)).to eq(MessagePack.dump(42))
321
- end
322
- end
323
-
324
- describe "registering ext type with recursive serialization" do
325
- before do
326
- stub_const("Point", Struct.new(:x, :y, :z))
327
- end
328
-
329
- it 'can receive the packer as argument (proc)' do
330
- factory = MessagePack::Factory.new
331
- factory.register_type(0x00, Symbol)
332
- factory.register_type(
333
- 0x01,
334
- Point,
335
- packer: ->(point, packer) do
336
- packer.write(point.to_h)
337
- nil
338
- end,
339
- unpacker: ->(unpacker) do
340
- attrs = unpacker.read
341
- Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
342
- end,
343
- recursive: true,
344
- )
345
-
346
- point = Point.new(1, 2, 3)
347
- payload = factory.dump(point)
348
- expect(factory.load(payload)).to be == point
349
- end
350
-
351
- it 'can receive the packer as argument (Method)' do
352
- mod = Module.new
353
- mod.define_singleton_method(:packer) do |point, packer|
354
- packer.write(point.to_h)
355
- nil
356
- end
357
-
358
- mod.define_singleton_method(:unpacker) do |unpacker|
359
- attrs = unpacker.read
360
- Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
361
- end
362
-
363
- factory = MessagePack::Factory.new
364
- factory.register_type(0x00, Symbol)
365
- factory.register_type(
366
- 0x01,
367
- Point,
368
- packer: mod.method(:packer),
369
- unpacker: mod.method(:unpacker),
370
- recursive: true,
371
- )
372
-
373
- point = Point.new(1, 2, 3)
374
- payload = factory.dump(point)
375
- expect(factory.load(payload)).to be == point
376
- end
377
-
378
- it 'respect message pack format' do
379
- factory = MessagePack::Factory.new
380
- factory.register_type(0x00, Symbol)
381
- factory.register_type(
382
- 0x01,
383
- Point,
384
- packer: ->(point, packer) do
385
- packer.write(point.to_a)
386
- nil
387
- end,
388
- unpacker: ->(unpacker) do
389
- attrs = unpacker.read
390
- Point.new(*attrs)
391
- end,
392
- recursive: true,
393
- )
394
-
395
- point = Point.new(1, 2, 3)
396
- expect(factory.dump(point)).to be == "\xD6\x01".b + MessagePack.dump([1, 2, 3])
397
- end
398
-
399
- it 'sets the correct length' do
400
- factory = MessagePack::Factory.new
401
- factory.register_type(0x00, Symbol)
402
- factory.register_type(
403
- 0x01,
404
- Point,
405
- packer: ->(point, packer) do
406
- packer.write(point.to_h)
407
- nil
408
- end,
409
- unpacker: ->(unpacker) do
410
- attrs = unpacker.read
411
- Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
412
- end,
413
- recursive: true,
414
- )
415
-
416
- point = Point.new(1, 2, 3)
417
- payload = factory.dump([1, point, 3])
418
-
419
- obj = MessagePack::Factory.new.load(payload, allow_unknown_ext: true)
420
- expect(obj).to be == [
421
- 1,
422
- MessagePack::ExtensionValue.new(1, factory.dump(x: 1, y: 2, z: 3)),
423
- 3,
424
- ]
425
-
426
- expect(factory.load(payload)).to be == [
427
- 1,
428
- Point.new(1, 2, 3),
429
- 3,
430
- ]
431
- end
432
-
433
- it 'can be nested' do
434
- factory = MessagePack::Factory.new
435
- factory.register_type(
436
- 0x02,
437
- Set,
438
- packer: ->(set, packer) do
439
- packer.write(set.to_a)
440
- nil
441
- end,
442
- unpacker: ->(unpacker) do
443
- unpacker.read.to_set
444
- end,
445
- recursive: true,
446
- )
447
-
448
- expected = Set[1, Set[2, Set[3]]]
449
- payload = factory.dump(expected)
450
- expect(payload).to be == "\xC7\v\x02\x92\x01\xC7\x06\x02\x92\x02\xD5\x02\x91\x03".b
451
- expect(factory.load(factory.dump(expected))).to be == expected
452
- end
453
- end
454
- end
455
-
456
- describe 'the special treatment of symbols with ext type' do
457
- def roundtrip(object, options = nil)
458
- subject.load(subject.dump(object), options)
459
- end
460
-
461
- context 'using the optimized symbol unpacker' do
462
- before do
463
- skip if IS_JRUBY # JRuby implementation doesn't support the optimized symbols unpacker for now
464
- subject.register_type(
465
- 0x00,
466
- ::Symbol,
467
- packer: :to_msgpack_ext,
468
- unpacker: :from_msgpack_ext,
469
- optimized_symbols_parsing: true,
470
- )
471
- end
472
-
473
- it 'lets symbols survive a roundtrip' do
474
- expect(roundtrip(:symbol)).to be :symbol
475
- end
476
-
477
- it 'works with empty symbol' do
478
- expect(roundtrip(:"")).to be :""
479
- end
480
-
481
- it 'preserves encoding for ASCII symbols' do
482
- expect(:symbol.encoding).to be Encoding::US_ASCII
483
- expect(roundtrip(:symbol)).to be :symbol
484
- expect(roundtrip(:symbol).encoding).to be Encoding::US_ASCII
485
- end
486
-
487
- it 'preserves encoding for UTF-8 symbols' do
488
- expect(:"fée".encoding).to be Encoding::UTF_8
489
- expect(roundtrip(:"fée").encoding).to be Encoding::UTF_8
490
- expect(roundtrip(:"fée")).to be :"fée"
491
- end
492
- end
493
-
494
- context 'if no ext type is registered for symbols' do
495
- it 'converts symbols to string' do
496
- expect(roundtrip(:symbol)).to eq 'symbol'
497
- end
498
- end
499
-
500
- context 'if an ext type is registered for symbols' do
501
- context 'if using the default serializer' do
502
- before { subject.register_type(0x00, ::Symbol) }
503
-
504
- it 'lets symbols survive a roundtrip' do
505
- expect(roundtrip(:symbol)).to be :symbol
506
- end
507
-
508
- it 'works with hash keys' do
509
- expect(roundtrip(symbol: 1)).to be == { symbol: 1 }
510
- end
511
-
512
- it 'works with frozen: true option' do
513
- expect(roundtrip(:symbol, freeze: true)).to be :symbol
514
- end
515
-
516
- it 'preserves encoding for ASCII symbols' do
517
- expect(:symbol.encoding).to be Encoding::US_ASCII
518
- expect(roundtrip(:symbol)).to be :symbol
519
- expect(roundtrip(:symbol).encoding).to be Encoding::US_ASCII
520
- end
521
-
522
- it 'preserves encoding for UTF-8 symbols' do
523
- expect(:"fée".encoding).to be Encoding::UTF_8
524
- expect(roundtrip(:"fée")).to be :"fée"
525
- expect(roundtrip(:"fée").encoding).to be Encoding::UTF_8
526
- end
527
-
528
- it 'does not handle symbols in other encodings' do
529
- symbol = "fàe".encode(Encoding::ISO_8859_1).to_sym
530
- expect(symbol.encoding).to be Encoding::ISO_8859_1
531
-
532
- if IS_JRUBY
533
- # JRuby doesn't quite behave like MRI here.
534
- # "fàe".force_encoding(Encoding::BINARY).to_sym is able to lookup the existing ISO-8859-1 symbol
535
- # It likely is a JRuby bug.
536
- expect(roundtrip(symbol).encoding).to be Encoding::ISO_8859_1
537
- else
538
- expect(roundtrip(symbol).encoding).to be Encoding::BINARY
539
- end
540
- end
541
- end
542
-
543
- context 'if using a custom serializer' do
544
- before do
545
- class Symbol
546
- alias_method :to_msgpack_ext_orig, :to_msgpack_ext
547
- def to_msgpack_ext
548
- self.to_s.codepoints.to_a.pack('n*')
549
- end
550
- end
551
-
552
- class << Symbol
553
- alias_method :from_msgpack_ext_orig, :from_msgpack_ext
554
- def from_msgpack_ext(data)
555
- data.unpack('n*').map(&:chr).join.to_sym
556
- end
557
- end
558
- end
559
-
560
- before { subject.register_type(0x00, ::Symbol) }
561
-
562
- it 'lets symbols survive a roundtrip' do
563
- expect(roundtrip(:symbol)).to be :symbol
564
- end
565
-
566
- after do
567
- class Symbol
568
- alias_method :to_msgpack_ext, :to_msgpack_ext_orig
569
- end
570
-
571
- class << Symbol
572
- alias_method :from_msgpack_ext, :from_msgpack_ext_orig
573
- end
574
- end
575
- end
576
- end
577
- end
578
-
579
- describe 'under stressful GC' do
580
- it 'works well' do
581
- begin
582
- GC.stress = true
583
-
584
- f = MessagePack::Factory.new
585
- f.register_type(0x0a, Symbol)
586
- ensure
587
- GC.stress = false
588
- end
589
- end
590
-
591
- it 'does not crash in recursive extensions' do
592
- my_hash_type = Class.new(Hash)
593
- factory = MessagePack::Factory.new
594
- factory.register_type(7,
595
- my_hash_type,
596
- packer: ->(value, packer) do
597
- packer.write(value.to_h)
598
- end,
599
- unpacker: ->(unpacker) { my_hash_type.new(unpacker.read) },
600
- recursive: true,
601
- )
602
-
603
- payload = factory.dump(
604
- [my_hash_type.new]
605
- )
606
-
607
- begin
608
- GC.stress = true
609
- factory.load(payload)
610
- ensure
611
- GC.stress = false
612
- end
613
- end
614
- end
615
-
616
- describe 'DefaultFactory' do
617
- it 'is a factory' do
618
- MessagePack::DefaultFactory.should be_kind_of(MessagePack::Factory)
619
- end
620
-
621
- require_relative 'exttypes'
622
-
623
- it 'should be referred by MessagePack.pack and MessagePack.unpack' do
624
- MessagePack::DefaultFactory.register_type(DummyTimeStamp1::TYPE, DummyTimeStamp1)
625
- MessagePack::DefaultFactory.register_type(DummyTimeStamp2::TYPE, DummyTimeStamp2, packer: :serialize, unpacker: :deserialize)
626
-
627
- t = Time.now
628
-
629
- dm1 = DummyTimeStamp1.new(t.to_i, t.usec)
630
- expect(MessagePack.unpack(MessagePack.pack(dm1))).to eq(dm1)
631
-
632
- dm2 = DummyTimeStamp1.new(t.to_i, t.usec)
633
- expect(MessagePack.unpack(MessagePack.pack(dm2))).to eq(dm2)
634
- end
635
- end
636
-
637
- describe '#pool' do
638
- let(:factory) { described_class.new }
639
-
640
- it 'responds to serializers interface' do
641
- pool = factory.pool(1)
642
- expect(pool.load(pool.dump(42))).to be == 42
643
- end
644
-
645
- it 'types can be registered before the pool is created' do
646
- factory.register_type(0x00, Symbol)
647
- pool = factory.pool(1)
648
- expect(pool.load(pool.dump(:foo))).to be == :foo
649
- end
650
-
651
- it 'types cannot be registered after the pool is created' do
652
- pool = factory.pool(1)
653
- factory.register_type(0x20, ::MyType)
654
-
655
- expect do
656
- pool.dump(MyType.new(1, 2))
657
- end.to raise_error NoMethodError
658
-
659
- payload = factory.dump(MyType.new(1, 2))
660
- expect do
661
- pool.load(payload)
662
- end.to raise_error MessagePack::UnknownExtTypeError
663
- end
664
-
665
- it 'support symbolize_keys: true' do
666
- pool = factory.pool(1, symbolize_keys: true)
667
- expect(pool.load(pool.dump('foo' => 1))).to be == { foo: 1 }
668
- end
669
-
670
- it 'support freeze: true' do
671
- pool = factory.pool(1, freeze: true)
672
- expect(pool.load(pool.dump('foo'))).to be_frozen
673
- end
674
-
675
- it 'is thread safe' do
676
- pool = factory.pool(1)
677
-
678
- threads = 10.times.map do
679
- Thread.new do
680
- 1_000.times do |i|
681
- expect(pool.load(pool.dump(i))).to be == i
682
- end
683
- end
684
- end
685
- threads.each(&:join)
686
- end
687
- end
688
- end