scotttam-RocketAMF 0.2.2

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 (81) hide show
  1. data/README.rdoc +45 -0
  2. data/Rakefile +54 -0
  3. data/lib/rocketamf.rb +128 -0
  4. data/lib/rocketamf/class_mapping.rb +231 -0
  5. data/lib/rocketamf/constants.rb +46 -0
  6. data/lib/rocketamf/pure.rb +28 -0
  7. data/lib/rocketamf/pure/deserializer.rb +419 -0
  8. data/lib/rocketamf/pure/io_helpers.rb +94 -0
  9. data/lib/rocketamf/pure/remoting.rb +134 -0
  10. data/lib/rocketamf/pure/serializer.rb +433 -0
  11. data/lib/rocketamf/remoting.rb +144 -0
  12. data/lib/rocketamf/values/array_collection.rb +13 -0
  13. data/lib/rocketamf/values/messages.rb +133 -0
  14. data/lib/rocketamf/values/typed_hash.rb +13 -0
  15. data/spec/amf/class_mapping_spec.rb +150 -0
  16. data/spec/amf/deserializer_spec.rb +367 -0
  17. data/spec/amf/remoting_spec.rb +132 -0
  18. data/spec/amf/serializer_spec.rb +384 -0
  19. data/spec/amf/values/array_collection_spec.rb +19 -0
  20. data/spec/amf/values/messages_spec.rb +31 -0
  21. data/spec/fixtures/objects/amf0-boolean.bin +1 -0
  22. data/spec/fixtures/objects/amf0-complexEncodedStringArray.bin +0 -0
  23. data/spec/fixtures/objects/amf0-date.bin +0 -0
  24. data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
  25. data/spec/fixtures/objects/amf0-hash.bin +0 -0
  26. data/spec/fixtures/objects/amf0-null.bin +1 -0
  27. data/spec/fixtures/objects/amf0-number.bin +0 -0
  28. data/spec/fixtures/objects/amf0-object.bin +0 -0
  29. data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
  30. data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
  31. data/spec/fixtures/objects/amf0-string.bin +0 -0
  32. data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
  33. data/spec/fixtures/objects/amf0-undefined.bin +1 -0
  34. data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
  35. data/spec/fixtures/objects/amf0-xmlDoc.bin +0 -0
  36. data/spec/fixtures/objects/amf3-0.bin +0 -0
  37. data/spec/fixtures/objects/amf3-arrayCollection.bin +2 -0
  38. data/spec/fixtures/objects/amf3-arrayRef.bin +1 -0
  39. data/spec/fixtures/objects/amf3-bigNum.bin +0 -0
  40. data/spec/fixtures/objects/amf3-byteArray.bin +0 -0
  41. data/spec/fixtures/objects/amf3-byteArrayRef.bin +1 -0
  42. data/spec/fixtures/objects/amf3-complexEncodedStringArray.bin +1 -0
  43. data/spec/fixtures/objects/amf3-date.bin +0 -0
  44. data/spec/fixtures/objects/amf3-datesRef.bin +0 -0
  45. data/spec/fixtures/objects/amf3-dictionary.bin +0 -0
  46. data/spec/fixtures/objects/amf3-dynObject.bin +2 -0
  47. data/spec/fixtures/objects/amf3-emptyArray.bin +1 -0
  48. data/spec/fixtures/objects/amf3-emptyArrayRef.bin +1 -0
  49. data/spec/fixtures/objects/amf3-emptyDictionary.bin +0 -0
  50. data/spec/fixtures/objects/amf3-emptyStringRef.bin +1 -0
  51. data/spec/fixtures/objects/amf3-encodedStringRef.bin +0 -0
  52. data/spec/fixtures/objects/amf3-false.bin +1 -0
  53. data/spec/fixtures/objects/amf3-float.bin +0 -0
  54. data/spec/fixtures/objects/amf3-graphMember.bin +0 -0
  55. data/spec/fixtures/objects/amf3-hash.bin +2 -0
  56. data/spec/fixtures/objects/amf3-largeMax.bin +0 -0
  57. data/spec/fixtures/objects/amf3-largeMin.bin +0 -0
  58. data/spec/fixtures/objects/amf3-max.bin +1 -0
  59. data/spec/fixtures/objects/amf3-min.bin +0 -0
  60. data/spec/fixtures/objects/amf3-mixedArray.bin +11 -0
  61. data/spec/fixtures/objects/amf3-null.bin +1 -0
  62. data/spec/fixtures/objects/amf3-objRef.bin +0 -0
  63. data/spec/fixtures/objects/amf3-primArray.bin +1 -0
  64. data/spec/fixtures/objects/amf3-string.bin +1 -0
  65. data/spec/fixtures/objects/amf3-stringRef.bin +0 -0
  66. data/spec/fixtures/objects/amf3-symbol.bin +1 -0
  67. data/spec/fixtures/objects/amf3-traitRef.bin +3 -0
  68. data/spec/fixtures/objects/amf3-true.bin +1 -0
  69. data/spec/fixtures/objects/amf3-typedObject.bin +2 -0
  70. data/spec/fixtures/objects/amf3-xml.bin +1 -0
  71. data/spec/fixtures/objects/amf3-xmlDoc.bin +1 -0
  72. data/spec/fixtures/objects/amf3-xmlRef.bin +1 -0
  73. data/spec/fixtures/request/acknowledge-response.bin +0 -0
  74. data/spec/fixtures/request/amf0-error-response.bin +0 -0
  75. data/spec/fixtures/request/commandMessage.bin +0 -0
  76. data/spec/fixtures/request/remotingMessage.bin +0 -0
  77. data/spec/fixtures/request/simple-response.bin +0 -0
  78. data/spec/fixtures/request/unsupportedCommandMessage.bin +0 -0
  79. data/spec/spec.opts +1 -0
  80. data/spec/spec_helper.rb +31 -0
  81. metadata +153 -0
@@ -0,0 +1,384 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
4
+
5
+ require 'rexml/document'
6
+
7
+ describe "when serializing" do
8
+ before :each do
9
+ RocketAMF::ClassMapper.reset
10
+ end
11
+
12
+ describe "AMF0" do
13
+ it "should serialize nils" do
14
+ output = RocketAMF.serialize(nil, 0)
15
+ output.should == object_fixture('amf0-null.bin')
16
+ end
17
+
18
+ it "should serialize booleans" do
19
+ output = RocketAMF.serialize(true, 0)
20
+ output.should === object_fixture('amf0-boolean.bin')
21
+ end
22
+
23
+ it "should serialize numbers" do
24
+ output = RocketAMF.serialize(3.5, 0)
25
+ output.should == object_fixture('amf0-number.bin')
26
+ end
27
+
28
+ it "should serialize strings" do
29
+ output = RocketAMF.serialize("this is a テスト", 0)
30
+ output.should == object_fixture('amf0-string.bin')
31
+ end
32
+
33
+ it "should serialize arrays" do
34
+ output = RocketAMF.serialize(['a', 'b', 'c', 'd'], 0)
35
+ output.should == object_fixture('amf0-strict-array.bin')
36
+ end
37
+
38
+ it "should serialize references" do
39
+ obj = OtherClass.new
40
+ obj.foo = "baz"
41
+ obj.bar = 3.14
42
+
43
+ output = RocketAMF.serialize({'0' => obj, '1' => obj}, 0)
44
+ output.should == object_fixture('amf0-ref-test.bin')
45
+ end
46
+
47
+ it "should serialize dates" do
48
+ output = RocketAMF.serialize(Time.utc(2003, 2, 13, 5), 0)
49
+ output.should == object_fixture('amf0-date.bin')
50
+ end
51
+
52
+ it "should serialize hashes" do
53
+ output = RocketAMF.serialize({:a => 'b', 'c' => 'd'}, 0)
54
+ output.should == object_fixture('amf0-hash.bin')
55
+ end
56
+
57
+ it "should serialize unmapped objects" do
58
+ obj = RubyClass.new
59
+ obj.foo = "bar"
60
+
61
+ output = RocketAMF.serialize(obj, 0)
62
+ output.should == object_fixture('amf0-untyped-object.bin')
63
+ end
64
+
65
+ it "should serialize mapped objects" do
66
+ obj = RubyClass.new
67
+ obj.foo = "bar"
68
+ RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
69
+
70
+ output = RocketAMF.serialize(obj, 0)
71
+ output.should == object_fixture('amf0-typed-object.bin')
72
+ end
73
+
74
+ if "".respond_to?(:force_encoding)
75
+ it "should support multiple encodings" do
76
+ shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
77
+ utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
78
+ output = RocketAMF.serialize({"0" => 5, "1" => shift_str, "2" => utf_str, "3" => 5}, 0)
79
+ output.should == object_fixture("amf0-complexEncodedStringArray.bin")
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "AMF3" do
85
+ describe "simple messages" do
86
+ it "should serialize a null" do
87
+ expected = object_fixture("amf3-null.bin")
88
+ output = RocketAMF.serialize(nil, 3)
89
+ output.should == expected
90
+ end
91
+
92
+ it "should serialize a false" do
93
+ expected = object_fixture("amf3-false.bin")
94
+ output = RocketAMF.serialize(false, 3)
95
+ output.should == expected
96
+ end
97
+
98
+ it "should serialize a true" do
99
+ expected = object_fixture("amf3-true.bin")
100
+ output = RocketAMF.serialize(true, 3)
101
+ output.should == expected
102
+ end
103
+
104
+ it "should serialize integers" do
105
+ expected = object_fixture("amf3-max.bin")
106
+ input = RocketAMF::MAX_INTEGER
107
+ output = RocketAMF.serialize(input, 3)
108
+ output.should == expected
109
+
110
+ expected = object_fixture("amf3-0.bin")
111
+ output = RocketAMF.serialize(0, 3)
112
+ output.should == expected
113
+
114
+ expected = object_fixture("amf3-min.bin")
115
+ input = RocketAMF::MIN_INTEGER
116
+ output = RocketAMF.serialize(input, 3)
117
+ output.should == expected
118
+ end
119
+
120
+ it "should serialize large integers" do
121
+ expected = object_fixture("amf3-largeMax.bin")
122
+ input = RocketAMF::MAX_INTEGER + 1
123
+ output = RocketAMF.serialize(input, 3)
124
+ output.should == expected
125
+
126
+ expected = object_fixture("amf3-largeMin.bin")
127
+ input = RocketAMF::MIN_INTEGER - 1
128
+ output = RocketAMF.serialize(input, 3)
129
+ output.should == expected
130
+ end
131
+
132
+ it "should serialize floats" do
133
+ expected = object_fixture("amf3-float.bin")
134
+ input = 3.5
135
+ output = RocketAMF.serialize(input, 3)
136
+ output.should == expected
137
+ end
138
+
139
+ it "should serialize BigNums" do
140
+ expected = object_fixture("amf3-bigNum.bin")
141
+ input = 2**1000
142
+ output = RocketAMF.serialize(input, 3)
143
+ output.should == expected
144
+ end
145
+
146
+ it "should serialize a simple string" do
147
+ expected = object_fixture("amf3-string.bin")
148
+ input = "String . String"
149
+ output = RocketAMF.serialize(input, 3)
150
+ output.should == expected
151
+ end
152
+
153
+ it "should serialize a symbol as a string" do
154
+ expected = object_fixture("amf3-symbol.bin")
155
+ output = RocketAMF.serialize(:foo, 3)
156
+ output.should == expected
157
+ end
158
+
159
+ it "should serialize Times" do
160
+ expected = object_fixture("amf3-date.bin")
161
+ input = Time.utc 1970, 1, 1, 0
162
+ output = RocketAMF.serialize(input, 3)
163
+ output.should == expected
164
+ end
165
+ end
166
+
167
+ describe "objects" do
168
+ it "should serialize an unmapped object as a dynamic anonymous object" do
169
+ class NonMappedObject
170
+ attr_accessor :property_one
171
+ attr_accessor :property_two
172
+ attr_accessor :nil_property
173
+ attr_writer :read_only_prop
174
+
175
+ def another_public_property
176
+ 'a_public_value'
177
+ end
178
+
179
+ def method_with_arg arg='foo'
180
+ arg
181
+ end
182
+ end
183
+ obj = NonMappedObject.new
184
+ obj.property_one = 'foo'
185
+ obj.property_two = 1
186
+ obj.nil_property = nil
187
+
188
+ expected = object_fixture("amf3-dynObject.bin")
189
+ input = obj
190
+ output = RocketAMF.serialize(input, 3)
191
+ output.should == expected
192
+ end
193
+
194
+ it "should serialize a hash as a dynamic anonymous object" do
195
+ hash = {}
196
+ hash[:answer] = 42
197
+ hash['foo'] = "bar"
198
+
199
+ expected = object_fixture("amf3-hash.bin")
200
+ input = hash
201
+ output = RocketAMF.serialize(input, 3)
202
+ output.should == expected
203
+ end
204
+
205
+ it "should serialize an empty array" do
206
+ expected = object_fixture("amf3-emptyArray.bin")
207
+ input = []
208
+ output = RocketAMF.serialize(input, 3)
209
+ output.should == expected
210
+ end
211
+
212
+ it "should serialize an array of primatives" do
213
+ expected = object_fixture("amf3-primArray.bin")
214
+ input = [1, 2, 3, 4, 5]
215
+ output = RocketAMF.serialize(input, 3)
216
+ output.should == expected
217
+ end
218
+
219
+ it "should serialize an array of mixed objects" do
220
+ h1 = {:foo_one => "bar_one"}
221
+ h2 = {:foo_two => ""}
222
+ class SimpleObj
223
+ attr_accessor :foo_three
224
+ end
225
+ so1 = SimpleObj.new
226
+ so1.foo_three = 42
227
+
228
+ expected = object_fixture("amf3-mixedArray.bin")
229
+ input = [h1, h2, so1, SimpleObj.new, {}, [h1, h2, so1], [], 42, "", [], "", {}, "bar_one", so1]
230
+ output = RocketAMF.serialize(input, 3)
231
+ output.should == expected
232
+ end
233
+
234
+ it "should serialize a byte array" do
235
+ expected = object_fixture("amf3-byteArray.bin")
236
+ input = StringIO.new "\000\003これtest\100"
237
+ output = RocketAMF.serialize(input, 3)
238
+ output.should == expected
239
+ end
240
+ end
241
+
242
+ describe "and implementing the AMF Spec" do
243
+ it "should keep references of duplicate strings" do
244
+ class StringCarrier
245
+ attr_accessor :str
246
+ end
247
+ foo = "foo"
248
+ bar = "str"
249
+ sc = StringCarrier.new
250
+ sc.str = foo
251
+
252
+ expected = object_fixture("amf3-stringRef.bin")
253
+ input = [foo, bar, foo, bar, foo, sc]
254
+ output = RocketAMF.serialize(input, 3)
255
+ output.should == expected
256
+ end
257
+
258
+ it "should not reference the empty string" do
259
+ expected = object_fixture("amf3-emptyStringRef.bin")
260
+ input = ""
261
+ output = RocketAMF.serialize([input,input], 3)
262
+ output.should == expected
263
+ end
264
+
265
+ it "should keep references of duplicate dates" do
266
+ expected = object_fixture("amf3-datesRef.bin")
267
+ input = Time.utc 1970, 1, 1, 0
268
+ output = RocketAMF.serialize([input,input], 3)
269
+ output.should == expected
270
+ end
271
+
272
+ it "should keep reference of duplicate objects" do
273
+ class SimpleReferenceableObj
274
+ attr_accessor :foo
275
+ end
276
+ obj1 = SimpleReferenceableObj.new
277
+ obj1.foo = :bar
278
+ obj2 = SimpleReferenceableObj.new
279
+ obj2.foo = obj1.foo
280
+
281
+ expected = object_fixture("amf3-objRef.bin")
282
+ input = [[obj1, obj2], "bar", [obj1, obj2]]
283
+ output = RocketAMF.serialize(input, 3)
284
+ output.should == expected
285
+ end
286
+
287
+ it "should keep reference of duplicate object traits" do
288
+ obj1 = RubyClass.new
289
+ obj1.foo = "foo"
290
+ def obj1.encode_amf serializer
291
+ serializer.write_object(self, {:class_name => 'org.rocketAMF.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
292
+ end
293
+ obj2 = RubyClass.new
294
+ obj2.foo = "bar"
295
+ def obj2.encode_amf serializer
296
+ serializer.write_object(self, {:class_name => 'org.rocketAMF.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
297
+ end
298
+ input = [obj1, obj2]
299
+
300
+ expected = object_fixture("amf3-traitRef.bin")
301
+ output = RocketAMF.serialize(input, 3)
302
+ output.should == expected
303
+ end
304
+
305
+ it "should keep references of duplicate arrays" do
306
+ a = [1,2,3]
307
+ b = %w{ a b c }
308
+
309
+ expected = object_fixture("amf3-arrayRef.bin")
310
+ input = [a, b, a, b]
311
+ output = RocketAMF.serialize(input, 3)
312
+ output.should == expected
313
+ end
314
+
315
+ it "should not keep references of duplicate empty arrays unless the object_id matches" do
316
+ a = []
317
+ b = []
318
+ a.should == b
319
+ a.object_id.should_not == b.object_id
320
+
321
+ expected = object_fixture("amf3-emptyArrayRef.bin")
322
+ input = [a,b,a,b]
323
+ output = RocketAMF.serialize(input, 3)
324
+ output.should == expected
325
+ end
326
+
327
+ it "should keep references of duplicate byte arrays" do
328
+ b = StringIO.new "ASDF"
329
+
330
+ expected = object_fixture("amf3-byteArrayRef.bin")
331
+ input = [b, b]
332
+ output = RocketAMF.serialize(input, 3)
333
+ output.should == expected
334
+ end
335
+
336
+ it "should serialize a deep object graph with circular references" do
337
+ class GraphMember
338
+ attr_accessor :children
339
+ attr_accessor :parent
340
+
341
+ def initialize
342
+ self.children = []
343
+ end
344
+
345
+ def add_child child
346
+ children << child
347
+ child.parent = self
348
+ child
349
+ end
350
+ end
351
+
352
+ parent = GraphMember.new
353
+ level_1_child_1 = parent.add_child GraphMember.new
354
+ level_1_child_2 = parent.add_child GraphMember.new
355
+
356
+ expected = object_fixture("amf3-graphMember.bin")
357
+ input = parent
358
+ output = RocketAMF.serialize(input, 3)
359
+ output.should == expected
360
+ end
361
+ end
362
+
363
+ if "".respond_to?(:force_encoding)
364
+ describe "and handling encodings" do
365
+ it "should support multiple encodings" do
366
+ shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
367
+ utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
368
+ output = RocketAMF.serialize([5, shift_str, utf_str, 5], 3)
369
+ output.should == object_fixture("amf3-complexEncodedStringArray.bin")
370
+ end
371
+
372
+ it "should keep references of duplicate strings with different encodings" do
373
+ # String is "this is a テスト"
374
+ shift_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS")
375
+ utf_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8")
376
+
377
+ expected = object_fixture("amf3-encodedStringRef.bin")
378
+ output = RocketAMF.serialize([shift_str, utf_str], 3)
379
+ output.should == expected
380
+ end
381
+ end
382
+ end
383
+ end
384
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe RocketAMF::Values::ArrayCollection do
4
+ it "should deserialize properly" do
5
+ input = object_fixture("amf3-arrayCollection.bin")
6
+ output = RocketAMF.deserialize(input, 3)
7
+
8
+ output.should be_a(RocketAMF::Values::ArrayCollection)
9
+ output.should == ["foo", "bar"]
10
+ end
11
+
12
+ it "should serialize properly" do
13
+ expected = object_fixture('amf3-arrayCollection.bin')
14
+ input = RocketAMF::Values::ArrayCollection.new
15
+ input.push("foo", "bar")
16
+ output = RocketAMF.serialize(input, 3)
17
+ output.should == expected
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe RocketAMF::Values::AbstractMessage do
4
+ before :each do
5
+ @message = RocketAMF::Values::AbstractMessage.new
6
+ end
7
+
8
+ it "should generate conforming uuids" do
9
+ @message.send(:rand_uuid).should =~ /[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}/i
10
+ end
11
+ end
12
+
13
+ describe RocketAMF::Values::ErrorMessage do
14
+ before :each do
15
+ @e = Exception.new('Error message')
16
+ @e.set_backtrace(['Backtrace 1', 'Backtrace 2'])
17
+ @message = RocketAMF::Values::ErrorMessage.new(nil, @e)
18
+ end
19
+
20
+ it "should serialize as a hash in AMF0" do
21
+ response = RocketAMF::Envelope.new
22
+ response.messages << RocketAMF::Message.new('1/onStatus', '', @message)
23
+ response.serialize.should == request_fixture('amf0-error-response.bin')
24
+ end
25
+
26
+ it "should extract exception properties correctly" do
27
+ @message.faultCode.should == 'Exception'
28
+ @message.faultString.should == 'Error message'
29
+ @message.faultDetail.should == "Backtrace 1\nBacktrace 2"
30
+ end
31
+ end