ruby_sol 0.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +90 -0
  3. data/Rakefile +43 -0
  4. data/lib/ruby_sol.rb +113 -0
  5. data/lib/ruby_sol/class_mapping.rb +250 -0
  6. data/lib/ruby_sol/constants.rb +50 -0
  7. data/lib/ruby_sol/extensions.rb +22 -0
  8. data/lib/ruby_sol/pure/deserializer.rb +461 -0
  9. data/lib/ruby_sol/pure/io_helpers.rb +94 -0
  10. data/lib/ruby_sol/pure/serializer.rb +490 -0
  11. data/spec/class_mapping_spec.rb +110 -0
  12. data/spec/deserializer_spec.rb +449 -0
  13. data/spec/fixtures/objects/amf0-boolean.bin +1 -0
  14. data/spec/fixtures/objects/amf0-complex-encoded-string.bin +0 -0
  15. data/spec/fixtures/objects/amf0-date.bin +0 -0
  16. data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
  17. data/spec/fixtures/objects/amf0-hash.bin +0 -0
  18. data/spec/fixtures/objects/amf0-null.bin +1 -0
  19. data/spec/fixtures/objects/amf0-number.bin +0 -0
  20. data/spec/fixtures/objects/amf0-object.bin +0 -0
  21. data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
  22. data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
  23. data/spec/fixtures/objects/amf0-string.bin +0 -0
  24. data/spec/fixtures/objects/amf0-time.bin +0 -0
  25. data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
  26. data/spec/fixtures/objects/amf0-undefined.bin +1 -0
  27. data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
  28. data/spec/fixtures/objects/amf0-xml-doc.bin +0 -0
  29. data/spec/fixtures/objects/amf3-0.bin +0 -0
  30. data/spec/fixtures/objects/amf3-array-collection.bin +2 -0
  31. data/spec/fixtures/objects/amf3-array-ref.bin +1 -0
  32. data/spec/fixtures/objects/amf3-associative-array.bin +1 -0
  33. data/spec/fixtures/objects/amf3-bigNum.bin +0 -0
  34. data/spec/fixtures/objects/amf3-byte-array-ref.bin +1 -0
  35. data/spec/fixtures/objects/amf3-byte-array.bin +0 -0
  36. data/spec/fixtures/objects/amf3-complex-array-collection.bin +6 -0
  37. data/spec/fixtures/objects/amf3-complex-encoded-string-array.bin +1 -0
  38. data/spec/fixtures/objects/amf3-date-ref.bin +0 -0
  39. data/spec/fixtures/objects/amf3-date.bin +0 -0
  40. data/spec/fixtures/objects/amf3-dictionary.bin +0 -0
  41. data/spec/fixtures/objects/amf3-dynamic-object.bin +2 -0
  42. data/spec/fixtures/objects/amf3-empty-array-ref.bin +1 -0
  43. data/spec/fixtures/objects/amf3-empty-array.bin +1 -0
  44. data/spec/fixtures/objects/amf3-empty-dictionary.bin +0 -0
  45. data/spec/fixtures/objects/amf3-empty-string-ref.bin +1 -0
  46. data/spec/fixtures/objects/amf3-encoded-string-ref.bin +0 -0
  47. data/spec/fixtures/objects/amf3-externalizable.bin +0 -0
  48. data/spec/fixtures/objects/amf3-false.bin +1 -0
  49. data/spec/fixtures/objects/amf3-float.bin +0 -0
  50. data/spec/fixtures/objects/amf3-graph-member.bin +0 -0
  51. data/spec/fixtures/objects/amf3-hash.bin +2 -0
  52. data/spec/fixtures/objects/amf3-large-max.bin +0 -0
  53. data/spec/fixtures/objects/amf3-large-min.bin +0 -0
  54. data/spec/fixtures/objects/amf3-max.bin +1 -0
  55. data/spec/fixtures/objects/amf3-min.bin +0 -0
  56. data/spec/fixtures/objects/amf3-mixed-array.bin +10 -0
  57. data/spec/fixtures/objects/amf3-null.bin +1 -0
  58. data/spec/fixtures/objects/amf3-object-ref.bin +0 -0
  59. data/spec/fixtures/objects/amf3-primitive-array.bin +1 -0
  60. data/spec/fixtures/objects/amf3-string-ref.bin +0 -0
  61. data/spec/fixtures/objects/amf3-string.bin +1 -0
  62. data/spec/fixtures/objects/amf3-symbol.bin +1 -0
  63. data/spec/fixtures/objects/amf3-trait-ref.bin +3 -0
  64. data/spec/fixtures/objects/amf3-true.bin +1 -0
  65. data/spec/fixtures/objects/amf3-typed-object.bin +2 -0
  66. data/spec/fixtures/objects/amf3-vector-double.bin +0 -0
  67. data/spec/fixtures/objects/amf3-vector-int.bin +0 -0
  68. data/spec/fixtures/objects/amf3-vector-object.bin +0 -0
  69. data/spec/fixtures/objects/amf3-vector-uint.bin +0 -0
  70. data/spec/fixtures/objects/amf3-xml-doc.bin +1 -0
  71. data/spec/fixtures/objects/amf3-xml-ref.bin +1 -0
  72. data/spec/fixtures/objects/amf3-xml.bin +1 -0
  73. data/spec/serializer_spec.rb +503 -0
  74. data/spec/spec_helper.rb +59 -0
  75. metadata +128 -0
@@ -0,0 +1,110 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubySol::ClassMapping do
4
+ before :each do
5
+ RubySol::ClassMapping.reset
6
+ RubySol::ClassMapping.define do |m|
7
+ m.map :as => 'ASClass', :ruby => 'ClassMappingTest'
8
+ end
9
+ @mapper = RubySol::ClassMapping.new
10
+ end
11
+
12
+ describe "class name mapping" do
13
+ # it "should allow resetting of mappings back to defaults" do
14
+ # @mapper.get_as_class_name('ClassMappingTest').should_not be_nil
15
+ # RubySol::ClassMapping.reset
16
+ # @mapper = RubySol::ClassMapping.new
17
+ # @mapper.get_as_class_name('ClassMappingTest').should be_nil
18
+ # @mapper.get_as_class_name('RubySol::Values::AcknowledgeMessage').should_not be_nil
19
+ # end
20
+
21
+ it "should return AS class name for ruby objects" do
22
+ @mapper.get_as_class_name(ClassMappingTest.new).should == 'ASClass'
23
+ @mapper.get_as_class_name('ClassMappingTest').should == 'ASClass'
24
+ @mapper.get_as_class_name(RubySol::Values::TypedHash.new('ClassMappingTest')).should == 'ASClass'
25
+ @mapper.get_as_class_name('BadClass').should be_nil
26
+ end
27
+
28
+ it "should instantiate a ruby class" do
29
+ @mapper.get_ruby_obj('ASClass').should be_a(ClassMappingTest)
30
+ end
31
+
32
+ it "should properly instantiate namespaced classes" do
33
+ RubySol::ClassMapping.mappings.map :as => 'ASClass', :ruby => 'ANamespace::TestRubyClass'
34
+ @mapper = RubySol::ClassMapping.new
35
+ @mapper.get_ruby_obj('ASClass').should be_a(ANamespace::TestRubyClass)
36
+ end
37
+
38
+ it "should return a hash with original type if not mapped" do
39
+ obj = @mapper.get_ruby_obj('UnmappedClass')
40
+ obj.should be_a(RubySol::Values::TypedHash)
41
+ obj.type.should == 'UnmappedClass'
42
+ end
43
+
44
+ # it "should map special classes from AS by default" do
45
+ # as_classes = [
46
+ # 'flex.messaging.messages.AcknowledgeMessage',
47
+ # 'flex.messaging.messages.CommandMessage',
48
+ # 'flex.messaging.messages.RemotingMessage'
49
+ # ]
50
+ #
51
+ # as_classes.each do |as_class|
52
+ # @mapper.get_ruby_obj(as_class).should_not be_a(RubySol::Values::TypedHash)
53
+ # end
54
+ # end
55
+ #
56
+ # it "should map special classes from ruby by default" do
57
+ # ruby_classes = [
58
+ # 'RubySol::Values::AcknowledgeMessage',
59
+ # 'RubySol::Values::ErrorMessage'
60
+ # ]
61
+ #
62
+ # ruby_classes.each do |obj|
63
+ # @mapper.get_as_class_name(obj).should_not be_nil
64
+ # end
65
+ # end
66
+
67
+ it "should allow config modification" do
68
+ RubySol::ClassMapping.mappings.map :as => 'SecondClass', :ruby => 'ClassMappingTest'
69
+ @mapper = RubySol::ClassMapping.new
70
+ @mapper.get_as_class_name(ClassMappingTest.new).should == 'SecondClass'
71
+ end
72
+ end
73
+
74
+ describe "ruby object populator" do
75
+ it "should populate a ruby class" do
76
+ obj = @mapper.populate_ruby_obj ClassMappingTest.new, {:prop_a => 'Data'}
77
+ obj.prop_a.should == 'Data'
78
+ end
79
+
80
+ it "should populate a typed hash" do
81
+ obj = @mapper.populate_ruby_obj RubySol::Values::TypedHash.new('UnmappedClass'), {:prop_a => 'Data'}
82
+ obj[:prop_a].should == 'Data'
83
+ end
84
+ end
85
+
86
+ describe "property extractor" do
87
+ it "should extract hash properties" do
88
+ hash = {:a => 'test1', 'b' => 'test2'}
89
+ props = @mapper.props_for_serialization(hash)
90
+ props.should == {'a' => 'test1', 'b' => 'test2'}
91
+ end
92
+
93
+ it "should extract object properties" do
94
+ obj = ClassMappingTest.new
95
+ obj.prop_a = 'Test A'
96
+
97
+ hash = @mapper.props_for_serialization obj
98
+ hash.should == {'prop_a' => 'Test A', 'prop_b' => nil}
99
+ end
100
+
101
+ it "should extract inherited object properties" do
102
+ obj = ClassMappingTest2.new
103
+ obj.prop_a = 'Test A'
104
+ obj.prop_c = 'Test C'
105
+
106
+ hash = @mapper.props_for_serialization obj
107
+ hash.should == {'prop_a' => 'Test A', 'prop_b' => nil, 'prop_c' => 'Test C'}
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,449 @@
1
+ # encoding: UTF-8
2
+
3
+ require "spec_helper.rb"
4
+
5
+ describe "when deserializing" do
6
+ before :each do
7
+ RubySol::ClassMapper.reset
8
+ end
9
+
10
+ it "should raise exception with invalid version number" do
11
+ lambda {
12
+ RubySol.deserialize("", 5)
13
+ }.should raise_error("unsupported version 5")
14
+ end
15
+
16
+ describe "AMF0" do
17
+ it "should update source pos if source is a StringIO object" do
18
+ input = StringIO.new(object_fixture('amf0-number.bin'))
19
+ input.pos.should == 0
20
+ output = RubySol.deserialize(input, 0)
21
+ input.pos.should == 9
22
+ end
23
+
24
+ it "should deserialize numbers" do
25
+ input = object_fixture('amf0-number.bin')
26
+ output = RubySol.deserialize(input, 0)
27
+ output.should == 3.5
28
+ end
29
+
30
+ it "should deserialize booleans" do
31
+ input = object_fixture('amf0-boolean.bin')
32
+ output = RubySol.deserialize(input, 0)
33
+ output.should === true
34
+ end
35
+
36
+ it "should deserialize UTF8 strings" do
37
+ input = object_fixture('amf0-string.bin')
38
+ output = RubySol.deserialize(input, 0)
39
+ output.should == "this is a テスト"
40
+ end
41
+
42
+ it "should deserialize nulls" do
43
+ input = object_fixture('amf0-null.bin')
44
+ output = RubySol.deserialize(input, 0)
45
+ output.should == nil
46
+ end
47
+
48
+ it "should deserialize undefineds" do
49
+ input = object_fixture('amf0-undefined.bin')
50
+ output = RubySol.deserialize(input, 0)
51
+ output.should == nil
52
+ end
53
+
54
+ it "should deserialize hashes" do
55
+ input = object_fixture('amf0-hash.bin')
56
+ output = RubySol.deserialize(input, 0)
57
+ output.should == {'a' => 'b', 'c' => 'd'}
58
+ end
59
+
60
+ it "should deserialize arrays from flash player" do
61
+ # Even Array is serialized as a "hash"
62
+ input = object_fixture('amf0-ecma-ordinal-array.bin')
63
+ output = RubySol.deserialize(input, 0)
64
+ output.should == {'0' => 'a', '1' => 'b', '2' => 'c', '3' => 'd'}
65
+ end
66
+
67
+ it "should deserialize strict arrays" do
68
+ input = object_fixture('amf0-strict-array.bin')
69
+ output = RubySol.deserialize(input, 0)
70
+ output.should == ['a', 'b', 'c', 'd']
71
+ end
72
+
73
+ it "should deserialize dates" do
74
+ input = object_fixture('amf0-time.bin')
75
+ output = RubySol.deserialize(input, 0)
76
+ output.should == Time.utc(2003, 2, 13, 5)
77
+ end
78
+
79
+ it "should deserialize an XML document" do
80
+ input = object_fixture('amf0-xml-doc.bin')
81
+ output = RubySol.deserialize(input, 0)
82
+ output.should == '<parent><child prop="test" /></parent>'
83
+ end
84
+
85
+ it "should deserialize anonymous objects" do
86
+ input = object_fixture('amf0-object.bin')
87
+ output = RubySol.deserialize(input, 0)
88
+ output.should == {'foo' => 'baz', 'bar' => 3.14}
89
+ output.type.should == ""
90
+ end
91
+
92
+ it "should deserialize an unmapped object as a dynamic anonymous object" do
93
+ input = object_fixture("amf0-typed-object.bin")
94
+ output = RubySol.deserialize(input, 0)
95
+
96
+ output.type.should == 'org.amf.ASClass'
97
+ output.should == {'foo' => 'bar', 'baz' => nil}
98
+ end
99
+
100
+ it "should deserialize a mapped object as a mapped ruby class instance" do
101
+ RubySol::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
102
+
103
+ input = object_fixture("amf0-typed-object.bin")
104
+ output = RubySol.deserialize(input, 0)
105
+
106
+ output.should be_a(RubyClass)
107
+ output.foo.should == 'bar'
108
+ output.baz.should == nil
109
+ end
110
+
111
+ it "should deserialize references properly" do
112
+ input = object_fixture('amf0-ref-test.bin')
113
+ output = RubySol.deserialize(input, 0)
114
+ output.length.should == 2
115
+ output["0"].should === output["1"]
116
+ end
117
+ end
118
+
119
+ describe "AMF3" do
120
+ it "should update source pos if source is a StringIO object" do
121
+ input = StringIO.new(object_fixture('amf3-null.bin'))
122
+ input.pos.should == 0
123
+ output = RubySol.deserialize(input, 3)
124
+ input.pos.should == 1
125
+ end
126
+
127
+ describe "simple messages" do
128
+ it "should deserialize a null" do
129
+ input = object_fixture("amf3-null.bin")
130
+ output = RubySol.deserialize(input, 3)
131
+ output.should == nil
132
+ end
133
+
134
+ it "should deserialize a false" do
135
+ input = object_fixture("amf3-false.bin")
136
+ output = RubySol.deserialize(input, 3)
137
+ output.should == false
138
+ end
139
+
140
+ it "should deserialize a true" do
141
+ input = object_fixture("amf3-true.bin")
142
+ output = RubySol.deserialize(input, 3)
143
+ output.should == true
144
+ end
145
+
146
+ it "should deserialize integers" do
147
+ input = object_fixture("amf3-max.bin")
148
+ output = RubySol.deserialize(input, 3)
149
+ output.should == RubySol::MAX_INTEGER
150
+
151
+ input = object_fixture("amf3-0.bin")
152
+ output = RubySol.deserialize(input, 3)
153
+ output.should == 0
154
+
155
+ input = object_fixture("amf3-min.bin")
156
+ output = RubySol.deserialize(input, 3)
157
+ output.should == RubySol::MIN_INTEGER
158
+ end
159
+
160
+ it "should deserialize large integers" do
161
+ input = object_fixture("amf3-large-max.bin")
162
+ output = RubySol.deserialize(input, 3)
163
+ output.should == RubySol::MAX_INTEGER + 1
164
+
165
+ input = object_fixture("amf3-large-min.bin")
166
+ output = RubySol.deserialize(input, 3)
167
+ output.should == RubySol::MIN_INTEGER - 1
168
+ end
169
+
170
+ it "should deserialize BigNums" do
171
+ input = object_fixture("amf3-bigNum.bin")
172
+ output = RubySol.deserialize(input, 3)
173
+ output.should == 2**1000
174
+ end
175
+
176
+ it "should deserialize a simple string" do
177
+ input = object_fixture("amf3-string.bin")
178
+ output = RubySol.deserialize(input, 3)
179
+ output.should == "String . String"
180
+ end
181
+
182
+ it "should deserialize a symbol as a string" do
183
+ input = object_fixture("amf3-symbol.bin")
184
+ output = RubySol.deserialize(input, 3)
185
+ output.should == "foo"
186
+ end
187
+
188
+ it "should deserialize dates" do
189
+ input = object_fixture("amf3-date.bin")
190
+ output = RubySol.deserialize(input, 3)
191
+ output.should == Time.at(0)
192
+ end
193
+
194
+ it "should deserialize XML" do
195
+ # XMLDocument tag
196
+ input = object_fixture("amf3-xml-doc.bin")
197
+ output = RubySol.deserialize(input, 3)
198
+ output.should == '<parent><child prop="test" /></parent>'
199
+
200
+ # XML tag
201
+ input = object_fixture("amf3-xml.bin")
202
+ output = RubySol.deserialize(input, 3)
203
+ output.should == '<parent><child prop="test"/></parent>'
204
+ end
205
+ end
206
+
207
+ describe "objects" do
208
+ it "should deserialize an unmapped object as a dynamic anonymous object" do
209
+ input = object_fixture("amf3-dynamic-object.bin")
210
+ output = RubySol.deserialize(input, 3)
211
+
212
+ expected = {
213
+ 'property_one' => 'foo',
214
+ 'nil_property' => nil,
215
+ 'another_public_property' => 'a_public_value'
216
+ }
217
+ output.should == expected
218
+ output.type.should == ""
219
+ end
220
+
221
+ it "should deserialize a mapped object as a mapped ruby class instance" do
222
+ RubySol::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
223
+
224
+ input = object_fixture("amf3-typed-object.bin")
225
+ output = RubySol.deserialize(input, 3)
226
+
227
+ output.should be_a(RubyClass)
228
+ output.foo.should == 'bar'
229
+ output.baz.should == nil
230
+ end
231
+
232
+ it "should deserialize externalizable objects" do
233
+ RubySol::ClassMapper.define {|m| m.map :as => 'ExternalizableTest', :ruby => 'ExternalizableTest'}
234
+
235
+ input = object_fixture("amf3-externalizable.bin")
236
+ output = RubySol.deserialize(input, 3)
237
+
238
+ output.length.should == 2
239
+ output[0].one.should == 5
240
+ output[1].two.should == 5
241
+ end
242
+
243
+ it "should deserialize a hash as a dynamic anonymous object" do
244
+ input = object_fixture("amf3-hash.bin")
245
+ output = RubySol.deserialize(input, 3)
246
+ output.should == {'foo' => "bar", 'answer' => 42}
247
+ end
248
+
249
+ it "should deserialize an empty array" do
250
+ input = object_fixture("amf3-empty-array.bin")
251
+ output = RubySol.deserialize(input, 3)
252
+ output.should == []
253
+ end
254
+
255
+ it "should deserialize an array of primitives" do
256
+ input = object_fixture("amf3-primitive-array.bin")
257
+ output = RubySol.deserialize(input, 3)
258
+ output.should == [1,2,3,4,5]
259
+ end
260
+
261
+ it "should deserialize an associative array" do
262
+ input = object_fixture("amf3-associative-array.bin")
263
+ output = RubySol.deserialize(input, 3)
264
+ output.should == {0=>"bar1", 1=>"bar2", 2=>"bar3", "asdf"=>"fdsa", "foo"=>"bar", "42"=>"bar"}
265
+ end
266
+
267
+ it "should deserialize an array of mixed objects" do
268
+ input = object_fixture("amf3-mixed-array.bin")
269
+ output = RubySol.deserialize(input, 3)
270
+
271
+ h1 = {'foo_one' => "bar_one"}
272
+ h2 = {'foo_two' => ""}
273
+ so1 = {'foo_three' => 42}
274
+ output.should == [h1, h2, so1, {}, [h1, h2, so1], [], 42, "", [], "", {}, "bar_one", so1]
275
+ end
276
+
277
+ it "should deserialize an array collection as an array" do
278
+ input = object_fixture("amf3-array-collection.bin")
279
+ output = RubySol.deserialize(input, 3)
280
+
281
+ output.class.should == Array
282
+ output.should == ["foo", "bar"]
283
+ end
284
+
285
+ it "should deserialize a complex set of array collections" do
286
+ RubySol::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
287
+ input = object_fixture('amf3-complex-array-collection.bin')
288
+
289
+ output = RubySol.deserialize(input, 3)
290
+
291
+ output[0].should == ["foo", "bar"]
292
+ output[1][0].should be_a(RubyClass)
293
+ output[1][1].should be_a(RubyClass)
294
+ output[2].should === output[1]
295
+ end
296
+
297
+ it "should deserialize a byte array" do
298
+ input = object_fixture("amf3-byte-array.bin")
299
+ output = RubySol.deserialize(input, 3)
300
+
301
+ output.should be_a(StringIO)
302
+ expected = "\000\003これtest\100"
303
+ expected.force_encoding("ASCII-8BIT") if expected.respond_to?(:force_encoding)
304
+ output.string.should == expected
305
+ end
306
+
307
+ it "should deserialize an empty dictionary" do
308
+ input = object_fixture("amf3-empty-dictionary.bin")
309
+ output = RubySol.deserialize(input, 3)
310
+ output.should == {}
311
+ end
312
+
313
+ it "should deserialize a dictionary" do
314
+ input = object_fixture("amf3-dictionary.bin")
315
+ output = RubySol.deserialize(input, 3)
316
+
317
+ keys = output.keys
318
+ keys.length.should == 2
319
+ obj_key, str_key = keys[0].is_a?(RubySol::Values::TypedHash) ? [keys[0], keys[1]] : [keys[1], keys[0]]
320
+ obj_key.type.should == 'org.amf.ASClass'
321
+ output[obj_key].should == "asdf2"
322
+ str_key.should == "bar"
323
+ output[str_key].should == "asdf1"
324
+ end
325
+
326
+ it "should deserialize Vector.<int>" do
327
+ input = object_fixture('amf3-vector-int.bin')
328
+ output = RubySol.deserialize(input, 3)
329
+ output.should == [4, -20, 12]
330
+ end
331
+
332
+ it "should deserialize Vector.<uint>" do
333
+ input = object_fixture('amf3-vector-uint.bin')
334
+ output = RubySol.deserialize(input, 3)
335
+ output.should == [4, 20, 12]
336
+ end
337
+
338
+ it "should deserialize Vector.<Number>" do
339
+ input = object_fixture('amf3-vector-double.bin')
340
+ output = RubySol.deserialize(input, 3)
341
+ output.should == [4.3, -20.6]
342
+ end
343
+
344
+ it "should deserialize Vector.<Object>" do
345
+ input = object_fixture('amf3-vector-object.bin')
346
+ output = RubySol.deserialize(input, 3)
347
+ output[0]['foo'].should == 'foo'
348
+ output[1].type.should == 'org.amf.ASClass'
349
+ output[2]['foo'].should == 'baz'
350
+ end
351
+ end
352
+
353
+ describe "and implementing the AMF Spec" do
354
+ it "should keep references of duplicate strings" do
355
+ input = object_fixture("amf3-string-ref.bin")
356
+ output = RubySol.deserialize(input, 3)
357
+
358
+ foo = "foo"
359
+ bar = "str"
360
+ output.should == [foo, bar, foo, bar, foo, {'str' => "foo"}]
361
+ end
362
+
363
+ it "should not reference the empty string" do
364
+ input = object_fixture("amf3-empty-string-ref.bin")
365
+ output = RubySol.deserialize(input, 3)
366
+ output.should == ["",""]
367
+ end
368
+
369
+ it "should keep references of duplicate dates" do
370
+ input = object_fixture("amf3-date-ref.bin")
371
+ output = RubySol.deserialize(input, 3)
372
+
373
+ output[0].should == Time.at(0)
374
+ output[0].should equal(output[1])
375
+ # Expected object:
376
+ # [DateTime.parse "1/1/1970", DateTime.parse "1/1/1970"]
377
+ end
378
+
379
+ it "should keep reference of duplicate objects" do
380
+ input = object_fixture("amf3-object-ref.bin")
381
+ output = RubySol.deserialize(input, 3)
382
+
383
+ obj1 = {'foo' => "bar"}
384
+ obj2 = {'foo' => obj1['foo']}
385
+ output.should == [[obj1, obj2], "bar", [obj1, obj2]]
386
+ end
387
+
388
+ it "should keep reference of duplicate object traits" do
389
+ RubySol::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
390
+
391
+ input = object_fixture("amf3-trait-ref.bin")
392
+ output = RubySol.deserialize(input, 3)
393
+
394
+ output[0].foo.should == "foo"
395
+ output[1].foo.should == "bar"
396
+ end
397
+
398
+ it "should keep references of duplicate arrays" do
399
+ input = object_fixture("amf3-array-ref.bin")
400
+ output = RubySol.deserialize(input, 3)
401
+
402
+ a = [1,2,3]
403
+ b = %w{ a b c }
404
+ output.should == [a, b, a, b]
405
+ end
406
+
407
+ it "should not keep references of duplicate empty arrays unless the object_id matches" do
408
+ input = object_fixture("amf3-empty-array-ref.bin")
409
+ output = RubySol.deserialize(input, 3)
410
+
411
+ a = []
412
+ b = []
413
+ output.should == [a,b,a,b]
414
+ end
415
+
416
+ it "should keep references of duplicate XML and XMLDocuments" do
417
+ input = object_fixture("amf3-xml-ref.bin")
418
+ output = RubySol.deserialize(input, 3)
419
+ output.should == ['<parent><child prop="test"/></parent>', '<parent><child prop="test"/></parent>']
420
+ end
421
+
422
+ it "should keep references of duplicate byte arrays" do
423
+ input = object_fixture("amf3-byte-array-ref.bin")
424
+ output = RubySol.deserialize(input, 3)
425
+ output[0].object_id.should == output[1].object_id
426
+ output[0].string.should == "ASDF"
427
+ end
428
+
429
+ it "should deserialize a deep object graph with circular references" do
430
+ input = object_fixture("amf3-graph-member.bin")
431
+ output = RubySol.deserialize(input, 3)
432
+
433
+ output['children'][0]['parent'].should === output
434
+ output['parent'].should === nil
435
+ output['children'].length.should == 2
436
+ # Expected object:
437
+ # parent = Hash.new
438
+ # child1 = Hash.new
439
+ # child1[:parent] = parent
440
+ # child1[:children] = []
441
+ # child2 = Hash.new
442
+ # child2[:parent] = parent
443
+ # child2[:children] = []
444
+ # parent[:parent] = nil
445
+ # parent[:children] = [child1, child2]
446
+ end
447
+ end
448
+ end
449
+ end