firm 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +12 -0
- data/LICENSE +21 -0
- data/README.md +209 -0
- data/lib/firm/serializable.rb +733 -0
- data/lib/firm/serialize/core.rb +43 -0
- data/lib/firm/serialize/id.rb +104 -0
- data/lib/firm/serializer/json.rb +394 -0
- data/lib/firm/serializer/xml.rb +544 -0
- data/lib/firm/serializer/yaml.rb +118 -0
- data/lib/firm/version.rb +9 -0
- data/lib/firm.rb +5 -0
- data/rakelib/yard/templates/default/fulldoc/html/css/firm.css +97 -0
- data/rakelib/yard/templates/default/fulldoc/html/setup.rb +25 -0
- data/rakelib/yard/templates/default/layout/html/setup.rb +5 -0
- data/rakelib/yard/yard/relative_markdown_links/version.rb +8 -0
- data/rakelib/yard/yard/relative_markdown_links.rb +39 -0
- data/rakelib/yard/yard-custom-templates.rb +2 -0
- data/rakelib/yard/yard-relative_markdown_links.rb +4 -0
- data/tests/serializer_tests.rb +945 -0
- data/tests/test_serialize.rb +8 -0
- data/tests/test_serialize_xml.rb +22 -0
- data/tests/test_serialize_yaml.rb +18 -0
- metadata +110 -0
@@ -0,0 +1,945 @@
|
|
1
|
+
begin
|
2
|
+
require 'bigdecimal'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
begin
|
6
|
+
require 'nokogiri'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
require 'firm'
|
10
|
+
|
11
|
+
module SerializerTestMixin
|
12
|
+
|
13
|
+
class PropTest
|
14
|
+
|
15
|
+
include FIRM::Serializable
|
16
|
+
|
17
|
+
property :prop_a
|
18
|
+
property prop_b: ->(obj, *val) { obj.instance_variable_set(:@prop_b, val.first) unless val.empty?; obj.instance_variable_get(:@prop_b) }
|
19
|
+
property prop_c: :serialize_prop_c
|
20
|
+
property(:prop_d, :prop_e) do |id, obj, *val|
|
21
|
+
case id
|
22
|
+
when :prop_d
|
23
|
+
obj.instance_variable_set('@prop_d', val.first) unless val.empty?
|
24
|
+
obj.instance_variable_get('@prop_d')
|
25
|
+
when :prop_e
|
26
|
+
obj.instance_variable_set('@prop_e', val.first) unless val.empty?
|
27
|
+
obj.instance_variable_get('@prop_e')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
property :prop_f, :prop_g, handler: :serialize_props_f_and_g
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@prop_a = 'string'
|
34
|
+
@prop_b = 123
|
35
|
+
@prop_c = :symbol
|
36
|
+
@prop_d = 100.123
|
37
|
+
@prop_e = [1,2,3]
|
38
|
+
@prop_f = {_1: 1, _2: 2, _3: 3}
|
39
|
+
@prop_g = 1..10
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :prop_a
|
43
|
+
|
44
|
+
def serialize_prop_c(*val)
|
45
|
+
@prop_c = val.first unless val.empty?
|
46
|
+
@prop_c
|
47
|
+
end
|
48
|
+
private :serialize_prop_c
|
49
|
+
|
50
|
+
def serialize_props_f_and_g(id, *val)
|
51
|
+
case id
|
52
|
+
when :prop_f
|
53
|
+
@prop_f = val.shift unless val.empty?
|
54
|
+
@prop_f
|
55
|
+
when :prop_g
|
56
|
+
@prop_g = val.shift unless val.empty?
|
57
|
+
@prop_g
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def ==(other)
|
62
|
+
self.class === other &&
|
63
|
+
@prop_a == other.prop_a &&
|
64
|
+
@prop_b == other.instance_variable_get('@prop_b') &&
|
65
|
+
@prop_c == other.instance_variable_get('@prop_c') &&
|
66
|
+
@prop_d == other.instance_variable_get('@prop_d') &&
|
67
|
+
@prop_e == other.instance_variable_get('@prop_e') &&
|
68
|
+
@prop_g == other.instance_variable_get('@prop_g') &&
|
69
|
+
@prop_f == other.instance_variable_get('@prop_f')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_properties
|
74
|
+
obj = PropTest.new
|
75
|
+
obj_serial = obj.serialize
|
76
|
+
obj_new = nil
|
77
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
78
|
+
assert_instance_of(PropTest, obj_new)
|
79
|
+
assert_equal(obj, obj_new)
|
80
|
+
end
|
81
|
+
|
82
|
+
class Point
|
83
|
+
|
84
|
+
include Comparable
|
85
|
+
|
86
|
+
include FIRM::Serializable
|
87
|
+
|
88
|
+
properties :x, :y
|
89
|
+
|
90
|
+
def initialize(*args)
|
91
|
+
if args.empty?
|
92
|
+
@x = @y = 0
|
93
|
+
else
|
94
|
+
@x, @y = *args
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
attr_accessor :x, :y
|
99
|
+
|
100
|
+
def <=>(other)
|
101
|
+
if other.is_a?(self.class)
|
102
|
+
if @x == other.x
|
103
|
+
@y <=> other.y
|
104
|
+
else
|
105
|
+
@x <=> other.x
|
106
|
+
end
|
107
|
+
else
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def eql?(other)
|
113
|
+
other.is_a?(self.class) ? @x.eql?(other.x) && @y.eql?(other.y) : false
|
114
|
+
end
|
115
|
+
|
116
|
+
def hash
|
117
|
+
"#{@x}x#{@y}".hash
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class Rect
|
123
|
+
|
124
|
+
include FIRM::Serializable
|
125
|
+
|
126
|
+
properties :x, :y, :width, :height
|
127
|
+
|
128
|
+
def initialize(x, y, w, h)
|
129
|
+
@x = x
|
130
|
+
@y = y
|
131
|
+
@width = w
|
132
|
+
@height = h
|
133
|
+
end
|
134
|
+
|
135
|
+
attr_reader :x, :y, :width, :height
|
136
|
+
|
137
|
+
def ==(other)
|
138
|
+
if other.is_a?(self.class)
|
139
|
+
@x == other.x && @y == other.y && @width == other.width && @height == other.height
|
140
|
+
else
|
141
|
+
false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Noop
|
146
|
+
# @param [Hash] _hash ignored
|
147
|
+
# @return [self]
|
148
|
+
def from_serialized(_hash)
|
149
|
+
# no deserializing necessary
|
150
|
+
self
|
151
|
+
end
|
152
|
+
protected :from_serialized
|
153
|
+
|
154
|
+
def init_from_serialized(data)
|
155
|
+
initialize(data[:x], data[:y], data[:width], data[:height])
|
156
|
+
self
|
157
|
+
end
|
158
|
+
protected :init_from_serialized
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
class Colour
|
163
|
+
|
164
|
+
include FIRM::Serializable
|
165
|
+
|
166
|
+
property :colour => ->(col, *val) { col.set(*val.first) unless val.empty?; [col.red, col.green, col.blue, col.alpha] }
|
167
|
+
|
168
|
+
def initialize(*args)
|
169
|
+
if args.empty?
|
170
|
+
@red, @green, @blue, @alpha = *args
|
171
|
+
@alpha ||= 255
|
172
|
+
else
|
173
|
+
@red = @green = @blue = 0
|
174
|
+
@alpha = 255
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def set(r, g, b, a)
|
179
|
+
@red = r
|
180
|
+
@green = g
|
181
|
+
@blue = b
|
182
|
+
@alpha = a
|
183
|
+
end
|
184
|
+
|
185
|
+
attr_reader :red, :green, :blue, :alpha
|
186
|
+
|
187
|
+
def ==(other)
|
188
|
+
if other.is_a?(self.class)
|
189
|
+
@red == other.red && @green == other.green && @blue == other.blue
|
190
|
+
else
|
191
|
+
false
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_data
|
198
|
+
obj = Point.new(10, 90)
|
199
|
+
obj_serial = obj.serialize
|
200
|
+
obj_new = nil
|
201
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
202
|
+
assert_instance_of(Point, obj_new)
|
203
|
+
assert_equal(obj, obj_new)
|
204
|
+
|
205
|
+
obj = Rect.new(10, 20, 100, 900)
|
206
|
+
obj_serial = obj.serialize
|
207
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
208
|
+
assert_instance_of(Rect, obj_new)
|
209
|
+
assert_equal(obj, obj_new)
|
210
|
+
|
211
|
+
obj = Colour.new('red')
|
212
|
+
obj_serial = obj.serialize
|
213
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
214
|
+
assert_instance_of(Colour, obj_new)
|
215
|
+
assert_equal(obj, obj_new)
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_core
|
219
|
+
obj = [Point.new(10, 90), Point.new(20, 80)]
|
220
|
+
obj_serial = obj.serialize
|
221
|
+
obj_new = nil
|
222
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
223
|
+
assert_equal(obj, obj_new)
|
224
|
+
|
225
|
+
obj = { '1' => Point.new(10, 90), '2' => Point.new(20, 80) }
|
226
|
+
obj_serial = obj.serialize
|
227
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
228
|
+
assert_equal(obj, obj_new)
|
229
|
+
|
230
|
+
Struct.new('MyStruct', :one, :two) unless defined? Struct::MyStruct
|
231
|
+
obj = Struct::MyStruct.new(one: Point.new(10, 90), two: Point.new(20, 80))
|
232
|
+
obj_serial = obj.serialize
|
233
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
234
|
+
assert_equal(obj, obj_new)
|
235
|
+
|
236
|
+
obj = ::Set.new(%i[one two three])
|
237
|
+
obj_serial = obj.serialize
|
238
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
239
|
+
assert_equal(obj, obj_new)
|
240
|
+
|
241
|
+
obj = OpenStruct.new(one: Point.new(10, 90), two: Point.new(20, 80))
|
242
|
+
obj_serial = obj.serialize
|
243
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
244
|
+
assert_equal(obj, obj_new)
|
245
|
+
|
246
|
+
obj = [1, nil, 2]
|
247
|
+
obj_serial = obj.serialize
|
248
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
249
|
+
assert_equal(obj, obj_new)
|
250
|
+
|
251
|
+
obj = (0..10)
|
252
|
+
obj_serial = obj.serialize
|
253
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
254
|
+
assert_equal(obj, obj_new)
|
255
|
+
|
256
|
+
obj = Rational(5, 3)
|
257
|
+
obj_serial = obj.serialize
|
258
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
259
|
+
assert_equal(obj, obj_new)
|
260
|
+
|
261
|
+
obj = /\Ahello.*/i
|
262
|
+
obj_serial = obj.serialize
|
263
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
264
|
+
assert_equal(obj, obj_new)
|
265
|
+
|
266
|
+
obj = Time.now - 999
|
267
|
+
obj_serial = obj.serialize
|
268
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
269
|
+
assert_equal(obj, obj_new)
|
270
|
+
|
271
|
+
obj = Date.today - 33
|
272
|
+
obj_serial = obj.serialize
|
273
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
274
|
+
assert_equal(obj, obj_new)
|
275
|
+
|
276
|
+
obj = DateTime.now
|
277
|
+
obj_serial = obj.serialize
|
278
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
279
|
+
assert_equal(obj, obj_new)
|
280
|
+
|
281
|
+
if ::Object.const_defined?(:BigDecimal)
|
282
|
+
obj = BigDecimal(2**64 + 0.1234, 4)
|
283
|
+
obj_serial = obj.serialize
|
284
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
285
|
+
assert_equal(obj, obj_new)
|
286
|
+
end
|
287
|
+
|
288
|
+
obj = Complex(0.5, 0.75)
|
289
|
+
obj_serial = obj.serialize
|
290
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
291
|
+
assert_equal(obj, obj_new)
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
class PointsOwner
|
296
|
+
include FIRM::Serializable
|
297
|
+
|
298
|
+
property :points
|
299
|
+
|
300
|
+
def initialize(points = [])
|
301
|
+
@points = points
|
302
|
+
end
|
303
|
+
|
304
|
+
attr_accessor :points
|
305
|
+
|
306
|
+
def ==(other)
|
307
|
+
self.class === other && @points == other.points
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_composition
|
312
|
+
obj = PointsOwner.new([Point.new(10, 90), Point.new(20, 80)])
|
313
|
+
obj_serial = obj.serialize
|
314
|
+
obj_new = nil
|
315
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
316
|
+
assert_equal(obj, obj_new)
|
317
|
+
end
|
318
|
+
|
319
|
+
class SerializedBase
|
320
|
+
include FIRM::Serializable
|
321
|
+
|
322
|
+
property :a
|
323
|
+
property :b
|
324
|
+
property :c
|
325
|
+
|
326
|
+
def initialize(a=nil, b=nil, c=nil)
|
327
|
+
@a = a
|
328
|
+
@b = b
|
329
|
+
@c = c
|
330
|
+
end
|
331
|
+
|
332
|
+
attr_accessor :a, :b, :c
|
333
|
+
|
334
|
+
def ==(other)
|
335
|
+
self.class === other && self.a == other.a && self.b == other.b && self.c == other.c
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
class SerializedDerived < SerializedBase
|
340
|
+
contains :d
|
341
|
+
excludes :c
|
342
|
+
|
343
|
+
def initialize(a=nil, b=nil, d=nil)
|
344
|
+
super(a, b)
|
345
|
+
@d = d
|
346
|
+
self.c = 'FIXED'
|
347
|
+
end
|
348
|
+
|
349
|
+
attr_accessor :d
|
350
|
+
|
351
|
+
def ==(other)
|
352
|
+
super && self.d == other.d
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_exclusion
|
357
|
+
obj = SerializedBase.new(1, :hello, 'World')
|
358
|
+
obj_serial = obj.serialize
|
359
|
+
obj_new = nil
|
360
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
361
|
+
assert_equal(obj, obj_new)
|
362
|
+
|
363
|
+
obj = SerializedDerived.new(2, :derived, 103.50)
|
364
|
+
obj_serial = obj.serialize
|
365
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
366
|
+
assert_equal(obj, obj_new)
|
367
|
+
end
|
368
|
+
|
369
|
+
class SerializedBase2
|
370
|
+
include FIRM::Serializable
|
371
|
+
|
372
|
+
property :list
|
373
|
+
|
374
|
+
def initialize(list = [])
|
375
|
+
@list = list
|
376
|
+
end
|
377
|
+
|
378
|
+
attr_reader :list
|
379
|
+
|
380
|
+
def set_list(list)
|
381
|
+
@list.insert(0, *(list || []))
|
382
|
+
end
|
383
|
+
private :set_list
|
384
|
+
|
385
|
+
def ==(other)
|
386
|
+
self.class === other && self.list == other.list
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
class SerializedDerived2 < SerializedBase2
|
391
|
+
|
392
|
+
def initialize(list = [])
|
393
|
+
super
|
394
|
+
@fixed_item = Point.new(30, 30)
|
395
|
+
@fixed_item.disable_serialize
|
396
|
+
self.list << @fixed_item
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|
400
|
+
|
401
|
+
class SerializedDerived2_1 < SerializedBase2
|
402
|
+
property :extra_item, force: true
|
403
|
+
|
404
|
+
def initialize(list = [], extra = nil)
|
405
|
+
super(list)
|
406
|
+
set_extra_item(extra)
|
407
|
+
end
|
408
|
+
|
409
|
+
attr_reader :extra_item
|
410
|
+
|
411
|
+
def set_extra_item(extra)
|
412
|
+
@extra_item = extra
|
413
|
+
if @extra_item
|
414
|
+
@extra_item.disable_serialize
|
415
|
+
list << @extra_item
|
416
|
+
end
|
417
|
+
end
|
418
|
+
private :set_extra_item
|
419
|
+
|
420
|
+
def ==(other)
|
421
|
+
super(other) && @extra_item == other.extra_item
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class SerializedBase3
|
426
|
+
include FIRM::Serializable
|
427
|
+
|
428
|
+
property :list
|
429
|
+
|
430
|
+
def initialize(list = ::Set.new)
|
431
|
+
@list = ::Set === list ? list : ::Set.new(list)
|
432
|
+
end
|
433
|
+
|
434
|
+
attr_reader :list
|
435
|
+
|
436
|
+
def set_list(list)
|
437
|
+
@list.merge(list || [])
|
438
|
+
end
|
439
|
+
private :set_list
|
440
|
+
|
441
|
+
def ==(other)
|
442
|
+
self.class === other && self.list == other.list
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
class SerializedDerived3 < SerializedBase3
|
447
|
+
|
448
|
+
def initialize(list = [])
|
449
|
+
super
|
450
|
+
@fixed_item = Point.new(30, 30)
|
451
|
+
@fixed_item.disable_serialize
|
452
|
+
self.list << @fixed_item
|
453
|
+
end
|
454
|
+
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_disable
|
458
|
+
obj = SerializedBase2.new([Point.new(1,1), Point.new(2,2), Point.new(3,3)])
|
459
|
+
obj_serial = obj.serialize
|
460
|
+
obj_new = nil
|
461
|
+
assert_nothing_raised { obj_new = SerializedBase2.deserialize(obj_serial) }
|
462
|
+
assert_equal(obj, obj_new)
|
463
|
+
|
464
|
+
obj = SerializedDerived2.new([Point.new(1,1), Point.new(2,2), Point.new(3,3)])
|
465
|
+
obj_serial = obj.serialize
|
466
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
467
|
+
assert_equal(obj, obj_new)
|
468
|
+
|
469
|
+
obj = SerializedDerived2_1.new([Point.new(1,1), Point.new(2,2), Point.new(3,3)], Rect.new(1, 1, 40, 40))
|
470
|
+
obj_serial = obj.serialize
|
471
|
+
assert_nothing_raised { obj_new = SerializedDerived2_1.deserialize(obj_serial) }
|
472
|
+
assert_equal(obj, obj_new)
|
473
|
+
|
474
|
+
obj = SerializedDerived3.new([Point.new(1,1), Point.new(2,2), Point.new(3,3)])
|
475
|
+
obj_serial = obj.serialize
|
476
|
+
assert_nothing_raised { obj_new = SerializedDerived3.deserialize(obj_serial) }
|
477
|
+
assert_equal(obj, obj_new)
|
478
|
+
end
|
479
|
+
|
480
|
+
class Identifiable
|
481
|
+
include FIRM::Serializable
|
482
|
+
|
483
|
+
property :id, :sym
|
484
|
+
|
485
|
+
def initialize(sym = nil)
|
486
|
+
@id = sym ? FIRM::Serializable::ID.new : nil
|
487
|
+
@sym = sym
|
488
|
+
end
|
489
|
+
|
490
|
+
attr_accessor :sym
|
491
|
+
attr_reader :id
|
492
|
+
|
493
|
+
def set_id(id)
|
494
|
+
@id = id
|
495
|
+
end
|
496
|
+
private :set_id
|
497
|
+
end
|
498
|
+
|
499
|
+
class Container
|
500
|
+
include FIRM::Serializable
|
501
|
+
|
502
|
+
property :map
|
503
|
+
|
504
|
+
def initialize(map = {})
|
505
|
+
@map = map
|
506
|
+
end
|
507
|
+
|
508
|
+
attr_reader :map
|
509
|
+
|
510
|
+
def set_map(map)
|
511
|
+
@map.replace(map)
|
512
|
+
end
|
513
|
+
private :set_map
|
514
|
+
end
|
515
|
+
|
516
|
+
class RefUser
|
517
|
+
include FIRM::Serializable
|
518
|
+
|
519
|
+
property :ref1, :ref2, :ref3
|
520
|
+
|
521
|
+
def initialize(*rids)
|
522
|
+
@ref1, @ref2, @ref3 = *rids
|
523
|
+
end
|
524
|
+
|
525
|
+
attr_accessor :ref1, :ref2, :ref3
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_ids
|
529
|
+
container = Container.new
|
530
|
+
id_obj = Identifiable.new(:one)
|
531
|
+
container.map[id_obj.id] = id_obj
|
532
|
+
id_obj = Identifiable.new(:two)
|
533
|
+
container.map[id_obj.id] = id_obj
|
534
|
+
id_obj = Identifiable.new(:three)
|
535
|
+
container.map[id_obj.id] = id_obj
|
536
|
+
ref_obj = RefUser.new(*container.map.keys)
|
537
|
+
obj_serial = [container, ref_obj].serialize
|
538
|
+
obj_new = nil
|
539
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
540
|
+
assert_instance_of(Array, obj_new)
|
541
|
+
assert_instance_of(Container, obj_new.first)
|
542
|
+
assert_instance_of(RefUser, obj_new.last)
|
543
|
+
assert_instance_of(FIRM::Serializable::ID, obj_new.last.ref1)
|
544
|
+
assert_instance_of(FIRM::Serializable::ID, obj_new.last.ref2)
|
545
|
+
assert_instance_of(FIRM::Serializable::ID, obj_new.last.ref3)
|
546
|
+
assert_equal(:one, obj_new.first.map[obj_new.last.ref1].sym)
|
547
|
+
assert_equal(:two, obj_new.first.map[obj_new.last.ref2].sym)
|
548
|
+
assert_equal(:three, obj_new.first.map[obj_new.last.ref3].sym)
|
549
|
+
end
|
550
|
+
|
551
|
+
class Aliasable
|
552
|
+
include FIRM::Serializable
|
553
|
+
|
554
|
+
property :name, :description
|
555
|
+
|
556
|
+
def initialize(*args)
|
557
|
+
@name, @description = *args
|
558
|
+
end
|
559
|
+
|
560
|
+
attr_accessor :name, :description
|
561
|
+
end
|
562
|
+
|
563
|
+
class DerivedAliasable < Aliasable
|
564
|
+
|
565
|
+
property :extra
|
566
|
+
|
567
|
+
def initialize(*args)
|
568
|
+
@extra = args.pop if args.size>2
|
569
|
+
super
|
570
|
+
end
|
571
|
+
|
572
|
+
attr_accessor :extra
|
573
|
+
|
574
|
+
end
|
575
|
+
|
576
|
+
def test_aliases
|
577
|
+
container = Container.new
|
578
|
+
container.map[:one] = Aliasable.new('one', 'First aliasable')
|
579
|
+
container.map[:two] = Aliasable.new('two', 'Second aliasable')
|
580
|
+
container.map[:three] = container.map[:one]
|
581
|
+
container.map[:four] = container.map[:two]
|
582
|
+
container.map[:five] = DerivedAliasable.new('three', 'Third aliasable', 'Derived aliasable')
|
583
|
+
container.map[:six] = container.map[:five]
|
584
|
+
obj_serial = container.serialize
|
585
|
+
obj_new = nil
|
586
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
587
|
+
assert_instance_of(Container, obj_new)
|
588
|
+
assert_instance_of(Aliasable, obj_new.map[:one])
|
589
|
+
assert_instance_of(Aliasable, obj_new.map[:two])
|
590
|
+
assert_instance_of(Aliasable, obj_new.map[:three])
|
591
|
+
assert_equal(obj_new.map[:one].object_id, obj_new.map[:three].object_id)
|
592
|
+
assert_instance_of(Aliasable, obj_new.map[:four])
|
593
|
+
assert_equal(obj_new.map[:two].object_id, obj_new.map[:four].object_id)
|
594
|
+
assert_instance_of(DerivedAliasable, obj_new.map[:five])
|
595
|
+
assert_instance_of(DerivedAliasable, obj_new.map[:six])
|
596
|
+
assert_equal(obj_new.map[:five].object_id, obj_new.map[:six].object_id)
|
597
|
+
end
|
598
|
+
|
599
|
+
class House
|
600
|
+
|
601
|
+
include FIRM::Serializable
|
602
|
+
|
603
|
+
attr_accessor :address, :city
|
604
|
+
attr_reader :owners
|
605
|
+
|
606
|
+
properties :address, :city, :owners
|
607
|
+
|
608
|
+
def initialize(*args)
|
609
|
+
@address, @city = *args
|
610
|
+
@owners = []
|
611
|
+
end
|
612
|
+
|
613
|
+
def add_owner(owner)
|
614
|
+
@owners << owner
|
615
|
+
owner.houses << self
|
616
|
+
end
|
617
|
+
|
618
|
+
def set_owners(owners)
|
619
|
+
@owners = owners
|
620
|
+
end
|
621
|
+
private :set_owners
|
622
|
+
|
623
|
+
end
|
624
|
+
|
625
|
+
class Person
|
626
|
+
|
627
|
+
include FIRM::Serializable
|
628
|
+
|
629
|
+
attr_accessor :name, :tax_id, :houses
|
630
|
+
|
631
|
+
properties :name, :tax_id, :houses
|
632
|
+
|
633
|
+
def initialize(*args)
|
634
|
+
@name, @tax_id = *args
|
635
|
+
@houses = []
|
636
|
+
end
|
637
|
+
|
638
|
+
end
|
639
|
+
|
640
|
+
def test_cyclic_references
|
641
|
+
person_a = Person.new('Max A', 123456)
|
642
|
+
person_b = Person.new('Joe B', 234567)
|
643
|
+
|
644
|
+
house_1 = House.new('The street 1', 'Nowhere')
|
645
|
+
house_1.add_owner(person_a)
|
646
|
+
house_2 = House.new('The lane 2', 'Somewhere')
|
647
|
+
house_2.add_owner(person_b)
|
648
|
+
house_3 = House.new('The promenade 3', 'ThisPlace')
|
649
|
+
house_3.add_owner(person_a)
|
650
|
+
house_3.add_owner(person_b)
|
651
|
+
|
652
|
+
obj_serial = [house_1, house_2, house_3].serialize
|
653
|
+
h1_new, h2_new, h3_new = nil
|
654
|
+
assert_nothing_raised { h1_new, h2_new, h3_new = *FIRM.deserialize(obj_serial) }
|
655
|
+
assert_instance_of(House, h1_new)
|
656
|
+
assert_instance_of(House, h2_new)
|
657
|
+
assert_instance_of(House, h3_new)
|
658
|
+
assert_true(house_1.address == h1_new.address && house_1.city == h1_new.city)
|
659
|
+
assert_true(house_2.address == h2_new.address && house_2.city == h2_new.city)
|
660
|
+
assert_true(house_3.address == h3_new.address && house_3.city == h3_new.city)
|
661
|
+
assert_equal(h1_new.owners[0].object_id, h3_new.owners[0].object_id)
|
662
|
+
assert_equal(h2_new.owners[0].object_id, h3_new.owners[1].object_id)
|
663
|
+
pa_new, pb_new = *h3_new.owners
|
664
|
+
assert_instance_of(Person, pa_new)
|
665
|
+
assert_instance_of(Person, pb_new)
|
666
|
+
assert_equal(h1_new.object_id, pa_new.houses[0].object_id)
|
667
|
+
assert_equal(h2_new.object_id, pb_new.houses[0].object_id)
|
668
|
+
assert_equal(h3_new.object_id, pa_new.houses[1].object_id)
|
669
|
+
assert_equal(h3_new.object_id, pb_new.houses[1].object_id)
|
670
|
+
end
|
671
|
+
|
672
|
+
CyclicTest = ::Struct.new(:list)
|
673
|
+
|
674
|
+
def test_cyclic_struct
|
675
|
+
struct = CyclicTest.new
|
676
|
+
struct.list = [struct]
|
677
|
+
obj_serial = struct.serialize
|
678
|
+
struct_new = nil
|
679
|
+
assert_nothing_raised { struct_new = FIRM.deserialize(obj_serial) }
|
680
|
+
assert_instance_of(CyclicTest, struct_new)
|
681
|
+
assert_equal(struct_new.object_id, struct_new.list[0].object_id)
|
682
|
+
end
|
683
|
+
|
684
|
+
def test_nested_hash_with_complex_keys
|
685
|
+
id_obj = Identifiable.new(:one)
|
686
|
+
id_obj2 = Identifiable.new(:two)
|
687
|
+
h = {
|
688
|
+
[
|
689
|
+
{ id_obj.id => id_obj }
|
690
|
+
] => 'one',
|
691
|
+
[
|
692
|
+
{ id_obj2.id => id_obj2 }
|
693
|
+
] => 'two'
|
694
|
+
}
|
695
|
+
obj_serial = h.serialize
|
696
|
+
obj_new = nil
|
697
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
698
|
+
assert_instance_of(::Hash, obj_new)
|
699
|
+
obj_new.each_pair do |k,v|
|
700
|
+
assert_instance_of(::Array, k)
|
701
|
+
assert_instance_of(::String, v)
|
702
|
+
assert_instance_of(::Hash, k.first)
|
703
|
+
assert_instance_of(FIRM::Serializable::ID, k.first.first.first)
|
704
|
+
assert_equal(v, k.first[k.first.first.first].sym.to_s)
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
class NestedSerializer
|
709
|
+
include FIRM::Serializable
|
710
|
+
|
711
|
+
property :nested, handler: :marshall_nested
|
712
|
+
|
713
|
+
def initialize(serializable=nil)
|
714
|
+
@nested = serializable
|
715
|
+
end
|
716
|
+
|
717
|
+
attr_reader :nested
|
718
|
+
|
719
|
+
protected
|
720
|
+
|
721
|
+
def marshall_nested(_id, *val)
|
722
|
+
if val.empty?
|
723
|
+
@nested.serialize
|
724
|
+
else
|
725
|
+
@nested = FIRM.deserialize(val.first)
|
726
|
+
nil
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
end
|
731
|
+
|
732
|
+
def test_nested_serialize
|
733
|
+
container = Container.new
|
734
|
+
container.map[:one] = Aliasable.new('one', 'First aliasable')
|
735
|
+
container.map[:two] = Aliasable.new('two', 'Second aliasable')
|
736
|
+
container.map[:three] = container.map[:one]
|
737
|
+
container.map[:four] = container.map[:two]
|
738
|
+
container.map[:five] = DerivedAliasable.new('three', 'Third aliasable', 'Derived aliasable')
|
739
|
+
container.map[:six] = container.map[:five]
|
740
|
+
id_obj = Identifiable.new(:seven)
|
741
|
+
container.map[id_obj.sym] = id_obj
|
742
|
+
id_obj = Identifiable.new(:eight)
|
743
|
+
container.map[id_obj.sym] = id_obj
|
744
|
+
id_obj = Identifiable.new(:nine)
|
745
|
+
container.map[id_obj.sym] = id_obj
|
746
|
+
ref_obj = RefUser.new(container.map[:seven].id, container.map[:eight].id, container.map[:nine].id)
|
747
|
+
container.map[:ten] = ref_obj
|
748
|
+
nest_obj = NestedSerializer.new(container)
|
749
|
+
obj_serial = [nest_obj, container.map[:one], container.map[:two], container.map[:five], [container.map[:three], container.map[:four], container.map[:six]], ref_obj].serialize(nil, pretty: true)
|
750
|
+
obj_new = nil
|
751
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
752
|
+
assert_instance_of(::Array, obj_new)
|
753
|
+
assert_instance_of(NestedSerializer, obj_new[0])
|
754
|
+
container = obj_new[0].nested
|
755
|
+
assert_instance_of(Container, container)
|
756
|
+
assert_instance_of(Aliasable, container.map[:one])
|
757
|
+
assert_instance_of(Aliasable, container.map[:two])
|
758
|
+
assert_instance_of(Aliasable, container.map[:three])
|
759
|
+
assert_equal(container.map[:one].object_id, container.map[:three].object_id)
|
760
|
+
assert_instance_of(Aliasable, container.map[:four])
|
761
|
+
assert_equal(container.map[:two].object_id, container.map[:four].object_id)
|
762
|
+
assert_instance_of(DerivedAliasable, container.map[:five])
|
763
|
+
assert_instance_of(DerivedAliasable, container.map[:six])
|
764
|
+
assert_equal(container.map[:five].object_id, container.map[:six].object_id)
|
765
|
+
|
766
|
+
assert_instance_of(RefUser, container.map[:ten])
|
767
|
+
assert_instance_of(FIRM::Serializable::ID, container.map[:ten].ref1)
|
768
|
+
assert_instance_of(FIRM::Serializable::ID, container.map[:ten].ref2)
|
769
|
+
assert_instance_of(FIRM::Serializable::ID, container.map[:ten].ref3)
|
770
|
+
assert_equal(:seven, container.map[:seven].sym)
|
771
|
+
assert_equal(container.map[:ten].ref1, container.map[:seven].id)
|
772
|
+
assert_equal(:eight, container.map[:eight].sym)
|
773
|
+
assert_equal(container.map[:ten].ref2, container.map[:eight].id)
|
774
|
+
assert_equal(:nine, container.map[:nine].sym)
|
775
|
+
assert_equal(container.map[:ten].ref3, container.map[:nine].id)
|
776
|
+
|
777
|
+
assert_instance_of(Aliasable, obj_new[1])
|
778
|
+
assert_instance_of(Aliasable, obj_new[2])
|
779
|
+
assert_instance_of(DerivedAliasable, obj_new[3])
|
780
|
+
assert_instance_of(::Array, obj_new[4])
|
781
|
+
assert_instance_of(Aliasable, obj_new[4][0])
|
782
|
+
assert_instance_of(Aliasable, obj_new[4][1])
|
783
|
+
assert_instance_of(DerivedAliasable, obj_new[4][2])
|
784
|
+
assert_equal(obj_new[1].object_id, obj_new[4][0].object_id)
|
785
|
+
assert_equal(obj_new[2].object_id, obj_new[4][1].object_id)
|
786
|
+
assert_equal(obj_new[3].object_id, obj_new[4][2].object_id)
|
787
|
+
|
788
|
+
assert_equal(container.map[:one].name, obj_new[4][0].name)
|
789
|
+
assert_not_equal(container.map[:one].object_id, obj_new[4][0].object_id)
|
790
|
+
assert_equal(container.map[:two].name, obj_new[4][1].name)
|
791
|
+
assert_not_equal(container.map[:two].object_id, obj_new[4][1].object_id)
|
792
|
+
assert_equal(container.map[:five].name, obj_new[4][2].name)
|
793
|
+
assert_not_equal(container.map[:five].object_id, obj_new[4][2].object_id)
|
794
|
+
|
795
|
+
assert_not_equal(container.map[:ten].ref1, obj_new.last.ref1)
|
796
|
+
assert_not_equal(container.map[:ten].ref2, obj_new.last.ref2)
|
797
|
+
assert_not_equal(container.map[:ten].ref3, obj_new.last.ref3)
|
798
|
+
end
|
799
|
+
|
800
|
+
class CreateFinalizer
|
801
|
+
|
802
|
+
include FIRM::Serializable
|
803
|
+
|
804
|
+
property :value
|
805
|
+
|
806
|
+
def initialize(val = nil)
|
807
|
+
@value = val
|
808
|
+
create if val
|
809
|
+
end
|
810
|
+
|
811
|
+
# default finalizer
|
812
|
+
def create
|
813
|
+
@symbol = case @value
|
814
|
+
when 1
|
815
|
+
:one
|
816
|
+
when 2
|
817
|
+
:two
|
818
|
+
when 3
|
819
|
+
:three
|
820
|
+
else
|
821
|
+
:none
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
825
|
+
attr_reader :value, :symbol
|
826
|
+
|
827
|
+
def set_value(v)
|
828
|
+
@value = v
|
829
|
+
end
|
830
|
+
private :set_value
|
831
|
+
|
832
|
+
end
|
833
|
+
|
834
|
+
class BlockFinalizer
|
835
|
+
|
836
|
+
include FIRM::Serializable
|
837
|
+
|
838
|
+
property :value
|
839
|
+
|
840
|
+
define_deserialize_finalizer do |obj|
|
841
|
+
obj.symbol = case obj.value
|
842
|
+
when 1
|
843
|
+
:one
|
844
|
+
when 2
|
845
|
+
:two
|
846
|
+
when 3
|
847
|
+
:three
|
848
|
+
else
|
849
|
+
:none
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
def initialize(val = 0)
|
854
|
+
@value = val
|
855
|
+
@symbol = case @value
|
856
|
+
when 1
|
857
|
+
:one
|
858
|
+
when 2
|
859
|
+
:two
|
860
|
+
when 3
|
861
|
+
:three
|
862
|
+
else
|
863
|
+
:none
|
864
|
+
end
|
865
|
+
end
|
866
|
+
|
867
|
+
attr_reader :value
|
868
|
+
attr_accessor :symbol
|
869
|
+
|
870
|
+
def set_value(v)
|
871
|
+
@value = v
|
872
|
+
end
|
873
|
+
private :set_value
|
874
|
+
end
|
875
|
+
|
876
|
+
class MethodFinalizer
|
877
|
+
|
878
|
+
include FIRM::Serializable
|
879
|
+
|
880
|
+
property :value
|
881
|
+
|
882
|
+
define_deserialize_finalizer :finalize_deserialize
|
883
|
+
|
884
|
+
def initialize(val = 0)
|
885
|
+
@value = val
|
886
|
+
@symbol = case @value
|
887
|
+
when 1
|
888
|
+
:one
|
889
|
+
when 2
|
890
|
+
:two
|
891
|
+
when 3
|
892
|
+
:three
|
893
|
+
else
|
894
|
+
:none
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
attr_reader :value, :symbol
|
899
|
+
|
900
|
+
# default finalizer
|
901
|
+
def finalize_deserialize
|
902
|
+
@symbol = case @value
|
903
|
+
when 1
|
904
|
+
:one
|
905
|
+
when 2
|
906
|
+
:two
|
907
|
+
when 3
|
908
|
+
:three
|
909
|
+
else
|
910
|
+
:none
|
911
|
+
end
|
912
|
+
end
|
913
|
+
private :finalize_deserialize
|
914
|
+
|
915
|
+
def set_value(v)
|
916
|
+
@value = v
|
917
|
+
end
|
918
|
+
private :set_value
|
919
|
+
|
920
|
+
end
|
921
|
+
|
922
|
+
def test_deserialize_finalizers
|
923
|
+
obj = CreateFinalizer.new(2)
|
924
|
+
obj_serial = obj.serialize
|
925
|
+
obj_new = nil
|
926
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
927
|
+
assert_equal(obj.value, obj_new.value)
|
928
|
+
assert_equal(obj.symbol, obj_new.symbol)
|
929
|
+
|
930
|
+
obj = BlockFinalizer.new(2)
|
931
|
+
obj_serial = obj.serialize
|
932
|
+
obj_new = nil
|
933
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
934
|
+
assert_equal(obj.value, obj_new.value)
|
935
|
+
assert_equal(obj.symbol, obj_new.symbol)
|
936
|
+
|
937
|
+
obj = MethodFinalizer.new(2)
|
938
|
+
obj_serial = obj.serialize
|
939
|
+
obj_new = nil
|
940
|
+
assert_nothing_raised { obj_new = FIRM.deserialize(obj_serial) }
|
941
|
+
assert_equal(obj.value, obj_new.value)
|
942
|
+
assert_equal(obj.symbol, obj_new.symbol)
|
943
|
+
end
|
944
|
+
|
945
|
+
end
|