scotttam-RocketAMF 0.2.2

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