RocketAMF 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/README.rdoc +36 -0
  2. data/Rakefile +54 -0
  3. data/lib/rocketamf.rb +12 -0
  4. data/lib/rocketamf/class_mapping.rb +211 -0
  5. data/lib/rocketamf/common.rb +35 -0
  6. data/lib/rocketamf/constants.rb +47 -0
  7. data/lib/rocketamf/pure.rb +30 -0
  8. data/lib/rocketamf/pure/deserializer.rb +361 -0
  9. data/lib/rocketamf/pure/io_helpers.rb +94 -0
  10. data/lib/rocketamf/pure/remoting.rb +89 -0
  11. data/lib/rocketamf/pure/serializer.rb +327 -0
  12. data/lib/rocketamf/remoting.rb +133 -0
  13. data/lib/rocketamf/values/array_collection.rb +9 -0
  14. data/lib/rocketamf/values/messages.rb +133 -0
  15. data/lib/rocketamf/values/typed_hash.rb +13 -0
  16. data/lib/rocketamf/version.rb +9 -0
  17. data/spec/amf/class_mapping_set_spec.rb +34 -0
  18. data/spec/amf/class_mapping_spec.rb +120 -0
  19. data/spec/amf/deserializer_spec.rb +311 -0
  20. data/spec/amf/request_spec.rb +25 -0
  21. data/spec/amf/response_spec.rb +68 -0
  22. data/spec/amf/serializer_spec.rb +328 -0
  23. data/spec/amf/values/array_collection_spec.rb +6 -0
  24. data/spec/amf/values/messages_spec.rb +31 -0
  25. data/spec/fixtures/objects/amf0-boolean.bin +1 -0
  26. data/spec/fixtures/objects/amf0-date.bin +0 -0
  27. data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
  28. data/spec/fixtures/objects/amf0-hash.bin +0 -0
  29. data/spec/fixtures/objects/amf0-null.bin +1 -0
  30. data/spec/fixtures/objects/amf0-number.bin +0 -0
  31. data/spec/fixtures/objects/amf0-object.bin +0 -0
  32. data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
  33. data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
  34. data/spec/fixtures/objects/amf0-string.bin +0 -0
  35. data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
  36. data/spec/fixtures/objects/amf0-undefined.bin +1 -0
  37. data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
  38. data/spec/fixtures/objects/amf3-0.bin +0 -0
  39. data/spec/fixtures/objects/amf3-arrayRef.bin +1 -0
  40. data/spec/fixtures/objects/amf3-bigNum.bin +0 -0
  41. data/spec/fixtures/objects/amf3-date.bin +0 -0
  42. data/spec/fixtures/objects/amf3-datesRef.bin +0 -0
  43. data/spec/fixtures/objects/amf3-dynObject.bin +2 -0
  44. data/spec/fixtures/objects/amf3-emptyArray.bin +1 -0
  45. data/spec/fixtures/objects/amf3-emptyArrayRef.bin +1 -0
  46. data/spec/fixtures/objects/amf3-emptyStringRef.bin +1 -0
  47. data/spec/fixtures/objects/amf3-false.bin +1 -0
  48. data/spec/fixtures/objects/amf3-graphMember.bin +0 -0
  49. data/spec/fixtures/objects/amf3-hash.bin +2 -0
  50. data/spec/fixtures/objects/amf3-largeMax.bin +0 -0
  51. data/spec/fixtures/objects/amf3-largeMin.bin +0 -0
  52. data/spec/fixtures/objects/amf3-max.bin +1 -0
  53. data/spec/fixtures/objects/amf3-min.bin +0 -0
  54. data/spec/fixtures/objects/amf3-mixedArray.bin +11 -0
  55. data/spec/fixtures/objects/amf3-null.bin +1 -0
  56. data/spec/fixtures/objects/amf3-objRef.bin +0 -0
  57. data/spec/fixtures/objects/amf3-primArray.bin +1 -0
  58. data/spec/fixtures/objects/amf3-string.bin +1 -0
  59. data/spec/fixtures/objects/amf3-stringRef.bin +0 -0
  60. data/spec/fixtures/objects/amf3-symbol.bin +1 -0
  61. data/spec/fixtures/objects/amf3-true.bin +1 -0
  62. data/spec/fixtures/objects/amf3-typedObject.bin +2 -0
  63. data/spec/fixtures/request/acknowledge-response.bin +0 -0
  64. data/spec/fixtures/request/amf0-error-response.bin +0 -0
  65. data/spec/fixtures/request/commandMessage.bin +0 -0
  66. data/spec/fixtures/request/remotingMessage.bin +0 -0
  67. data/spec/fixtures/request/simple-response.bin +0 -0
  68. data/spec/spec.opts +1 -0
  69. data/spec/spec_helper.rb +32 -0
  70. metadata +133 -0
@@ -0,0 +1,311 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "when deserializing" do
4
+ before :each do
5
+ RocketAMF::ClassMapper.reset
6
+ end
7
+
8
+ describe "AMF0" do
9
+ it "should deserialize numbers" do
10
+ input = object_fixture('amf0-number.bin')
11
+ output = RocketAMF.deserialize(input, 0)
12
+ output.should == 3.5
13
+ end
14
+
15
+ it "should deserialize booleans" do
16
+ input = object_fixture('amf0-boolean.bin')
17
+ output = RocketAMF.deserialize(input, 0)
18
+ output.should === true
19
+ end
20
+
21
+ it "should deserialize strings" do
22
+ input = object_fixture('amf0-string.bin')
23
+ output = RocketAMF.deserialize(input, 0)
24
+ output.should == "this is a テスト"
25
+ end
26
+
27
+ it "should deserialize anonymous objects" do
28
+ input = object_fixture('amf0-object.bin')
29
+ output = RocketAMF.deserialize(input, 0)
30
+ output.should == {:foo => 'baz', :bar => 3.14}
31
+ end
32
+
33
+ it "should deserialize nulls" do
34
+ input = object_fixture('amf0-null.bin')
35
+ output = RocketAMF.deserialize(input, 0)
36
+ output.should == nil
37
+ end
38
+
39
+ it "should deserialize undefineds" do
40
+ input = object_fixture('amf0-undefined.bin')
41
+ output = RocketAMF.deserialize(input, 0)
42
+ output.should == nil
43
+ end
44
+
45
+ it "should deserialize references properly" do
46
+ input = object_fixture('amf0-ref-test.bin')
47
+ output = RocketAMF.deserialize(input, 0)
48
+ output.length.should == 2
49
+ output[0].should === output[1]
50
+ end
51
+
52
+ it "should deserialize hashes" do
53
+ input = object_fixture('amf0-hash.bin')
54
+ output = RocketAMF.deserialize(input, 0)
55
+ output.should == {:a => 'b', :c => 'd'}
56
+ end
57
+
58
+ it "should deserialize arrays from flash player" do
59
+ # Even Array is serialized as a "hash", so check that deserializer converts to array
60
+ input = object_fixture('amf0-ecma-ordinal-array.bin')
61
+ output = RocketAMF.deserialize(input, 0)
62
+ output.should == ['a', 'b', 'c', 'd']
63
+ end
64
+
65
+ it "should serialize strict arrays" do
66
+ input = object_fixture('amf0-strict-array.bin')
67
+ output = RocketAMF.deserialize(input, 0)
68
+ output.should == ['a', 'b', 'c', 'd']
69
+ end
70
+
71
+ it "should deserialize dates" do
72
+ input = object_fixture('amf0-date.bin')
73
+ output = RocketAMF.deserialize(input, 0)
74
+ output.should == Time.utc(2003, 2, 13, 5)
75
+ end
76
+
77
+ it "should deserialize XML"
78
+
79
+ it "should deserialize an unmapped object as a dynamic anonymous object" do
80
+ input = object_fixture("amf0-typed-object.bin")
81
+ output = RocketAMF.deserialize(input, 0)
82
+
83
+ output.type.should == 'org.rocketAMF.ASClass'
84
+ output.should == {:foo => 'bar', :baz => nil}
85
+ end
86
+
87
+ it "should deserialize a mapped object as a mapped ruby class instance" do
88
+ class RubyClass
89
+ attr_accessor :foo, :baz
90
+ end
91
+ RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
92
+
93
+ input = object_fixture("amf0-typed-object.bin")
94
+ output = RocketAMF.deserialize(input, 0)
95
+
96
+ output.should be_a(RubyClass)
97
+ output.foo.should == 'bar'
98
+ output.baz.should == nil
99
+ end
100
+ end
101
+
102
+ describe "AMF3" do
103
+ describe "simple messages" do
104
+ it "should deserialize a null" do
105
+ input = object_fixture("amf3-null.bin")
106
+ output = RocketAMF.deserialize(input, 3)
107
+ output.should == nil
108
+ end
109
+
110
+ it "should deserialize a false" do
111
+ input = object_fixture("amf3-false.bin")
112
+ output = RocketAMF.deserialize(input, 3)
113
+ output.should == false
114
+ end
115
+
116
+ it "should deserialize a true" do
117
+ input = object_fixture("amf3-true.bin")
118
+ output = RocketAMF.deserialize(input, 3)
119
+ output.should == true
120
+ end
121
+
122
+ it "should deserialize integers" do
123
+ input = object_fixture("amf3-max.bin")
124
+ output = RocketAMF.deserialize(input, 3)
125
+ output.should == RocketAMF::MAX_INTEGER
126
+
127
+ input = object_fixture("amf3-0.bin")
128
+ output = RocketAMF.deserialize(input, 3)
129
+ output.should == 0
130
+
131
+ input = object_fixture("amf3-min.bin")
132
+ output = RocketAMF.deserialize(input, 3)
133
+ output.should == RocketAMF::MIN_INTEGER
134
+ end
135
+
136
+ it "should deserialize large integers" do
137
+ input = object_fixture("amf3-largeMax.bin")
138
+ output = RocketAMF.deserialize(input, 3)
139
+ output.should == RocketAMF::MAX_INTEGER + 1
140
+
141
+ input = object_fixture("amf3-largeMin.bin")
142
+ output = RocketAMF.deserialize(input, 3)
143
+ output.should == RocketAMF::MIN_INTEGER - 1
144
+ end
145
+
146
+ it "should deserialize BigNums" do
147
+ input = object_fixture("amf3-bigNum.bin")
148
+ output = RocketAMF.deserialize(input, 3)
149
+ output.should == 2**1000
150
+ end
151
+
152
+ it "should deserialize a simple string" do
153
+ input = object_fixture("amf3-string.bin")
154
+ output = RocketAMF.deserialize(input, 3)
155
+ output.should == "String . String"
156
+ end
157
+
158
+ it "should deserialize a symbol as a string" do
159
+ input = object_fixture("amf3-symbol.bin")
160
+ output = RocketAMF.deserialize(input, 3)
161
+ output.should == "foo"
162
+ end
163
+
164
+ it "should deserialize dates" do
165
+ input = object_fixture("amf3-date.bin")
166
+ output = RocketAMF.deserialize(input, 3)
167
+ output.should == Time.at(0)
168
+ end
169
+
170
+ #BAH! Who sends XML over AMF?
171
+ it "should deserialize a REXML document"
172
+ end
173
+
174
+ describe "objects" do
175
+ it "should deserialize an unmapped object as a dynamic anonymous object" do
176
+ input = object_fixture("amf3-dynObject.bin")
177
+ output = RocketAMF.deserialize(input, 3)
178
+
179
+ expected = {
180
+ :property_one => 'foo',
181
+ :property_two => 1,
182
+ :nil_property => nil,
183
+ :another_public_property => 'a_public_value'
184
+ }
185
+ output.should == expected
186
+ end
187
+
188
+ it "should deserialize a mapped object as a mapped ruby class instance" do
189
+ class RubyClass
190
+ attr_accessor :foo, :baz
191
+ end
192
+ RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
193
+
194
+ input = object_fixture("amf3-typedObject.bin")
195
+ output = RocketAMF.deserialize(input, 3)
196
+
197
+ output.should be_a(RubyClass)
198
+ output.foo.should == 'bar'
199
+ output.baz.should == nil
200
+ end
201
+
202
+ it "should deserialize a hash as a dynamic anonymous object" do
203
+ input = object_fixture("amf3-hash.bin")
204
+ output = RocketAMF.deserialize(input, 3)
205
+ output.should == {:foo => "bar", :answer => 42}
206
+ end
207
+
208
+ it "should deserialize an empty array" do
209
+ input = object_fixture("amf3-emptyArray.bin")
210
+ output = RocketAMF.deserialize(input, 3)
211
+ output.should == []
212
+ end
213
+
214
+ it "should deserialize an array of primatives" do
215
+ input = object_fixture("amf3-primArray.bin")
216
+ output = RocketAMF.deserialize(input, 3)
217
+ output.should == [1,2,3,4,5]
218
+ end
219
+
220
+ it "should deserialize an array of mixed objects" do
221
+ input = object_fixture("amf3-mixedArray.bin")
222
+ output = RocketAMF.deserialize(input, 3)
223
+
224
+ h1 = {:foo_one => "bar_one"}
225
+ h2 = {:foo_two => ""}
226
+ so1 = {:foo_three => 42}
227
+ output.should == [h1, h2, so1, {:foo_three => nil}, {}, [h1, h2, so1], [], 42, "", [], "", {}, "bar_one", so1]
228
+ end
229
+
230
+ it "should deserialize a byte array"
231
+ end
232
+
233
+ describe "and implementing the AMF Spec" do
234
+ it "should keep references of duplicate strings" do
235
+ input = object_fixture("amf3-stringRef.bin")
236
+ output = RocketAMF.deserialize(input, 3)
237
+
238
+ class StringCarrier; attr_accessor :str; end
239
+ foo = "foo"
240
+ bar = "str"
241
+ sc = StringCarrier.new
242
+ sc = {:str => foo}
243
+ output.should == [foo, bar, foo, bar, foo, sc]
244
+ end
245
+
246
+ it "should not reference the empty string" do
247
+ input = object_fixture("amf3-emptyStringRef.bin")
248
+ output = RocketAMF.deserialize(input, 3)
249
+ output.should == ["",""]
250
+ end
251
+
252
+ it "should keep references of duplicate dates" do
253
+ input = object_fixture("amf3-datesRef.bin")
254
+ output = RocketAMF.deserialize(input, 3)
255
+
256
+ output[0].should equal(output[1])
257
+ # Expected object:
258
+ # [DateTime.parse "1/1/1970", DateTime.parse "1/1/1970"]
259
+ end
260
+
261
+ it "should keep reference of duplicate objects" do
262
+ input = object_fixture("amf3-objRef.bin")
263
+ output = RocketAMF.deserialize(input, 3)
264
+
265
+ obj1 = {:foo => "bar"}
266
+ obj2 = {:foo => obj1[:foo]}
267
+ output.should == [[obj1, obj2], "bar", [obj1, obj2]]
268
+ end
269
+
270
+ it "should keep references of duplicate arrays" do
271
+ input = object_fixture("amf3-arrayRef.bin")
272
+ output = RocketAMF.deserialize(input, 3)
273
+
274
+ a = [1,2,3]
275
+ b = %w{ a b c }
276
+ output.should == [a, b, a, b]
277
+ end
278
+
279
+ it "should not keep references of duplicate empty arrays unless the object_id matches" do
280
+ input = object_fixture("amf3-emptyArrayRef.bin")
281
+ output = RocketAMF.deserialize(input, 3)
282
+
283
+ a = []
284
+ b = []
285
+ output.should == [a,b,a,b]
286
+ end
287
+
288
+ it "should keep references of duplicate XML and XMLDocuments"
289
+ it "should keep references of duplicate byte arrays"
290
+
291
+ it "should deserialize a deep object graph with circular references" do
292
+ input = object_fixture("amf3-graphMember.bin")
293
+ output = RocketAMF.deserialize(input, 3)
294
+
295
+ output[:children][0][:parent].should === output
296
+ output[:parent].should === nil
297
+ output[:children].length.should == 2
298
+ # Expected object:
299
+ # parent = Hash.new
300
+ # child1 = Hash.new
301
+ # child1[:parent] = parent
302
+ # child1[:children] = []
303
+ # child2 = Hash.new
304
+ # child2[:parent] = parent
305
+ # child2[:children] = []
306
+ # parent[:parent] = nil
307
+ # parent[:children] = [child1, child2]
308
+ end
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe RocketAMF::Request do
4
+ it "should handle remoting message from remote object" do
5
+ req = create_request("remotingMessage.bin")
6
+
7
+ req.headers.length.should == 0
8
+ req.messages.length.should == 1
9
+ message = req.messages[0].data
10
+ message.should be_a(RocketAMF::Values::RemotingMessage)
11
+ message.messageId.should == "FE4AF2BC-DD3C-5470-05D8-9971D51FF89D"
12
+ message.body.should == [true]
13
+ end
14
+
15
+ it "should handle command message from remote object" do
16
+ req = create_request("commandMessage.bin")
17
+
18
+ req.headers.length.should == 0
19
+ req.messages.length.should == 1
20
+ message = req.messages[0].data
21
+ message.should be_a(RocketAMF::Values::CommandMessage)
22
+ message.messageId.should == "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
23
+ message.body.should == {}
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe RocketAMF::Response do
4
+ it "should serialize response when converted to string" do
5
+ res = RocketAMF::Response.new
6
+ res.should_receive(:serialize).and_return('serialized')
7
+ res.to_s.should == 'serialized'
8
+ end
9
+
10
+ it "should serialize a simple call" do
11
+ res = RocketAMF::Response.new
12
+ res.amf_version = 3
13
+ res.messages << RocketAMF::Message.new('/1/onResult', '', 'hello')
14
+
15
+ expected = request_fixture('simple-response.bin')
16
+ res.serialize.should == expected
17
+ end
18
+
19
+ it "should serialize a AcknowledgeMessage response" do
20
+ ak = RocketAMF::Values::AcknowledgeMessage.new
21
+ ak.clientId = "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
22
+ ak.messageId = "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
23
+ ak.timestamp = 0
24
+ res = RocketAMF::Response.new
25
+ res.amf_version = 3
26
+ res.messages << RocketAMF::Message.new('/1/onResult', '', ak)
27
+
28
+ expected = request_fixture('acknowledge-response.bin')
29
+ res.serialize.should == expected
30
+ end
31
+
32
+ it "should respond to ping command" do
33
+ res = RocketAMF::Response.new
34
+ req = create_request('commandMessage.bin')
35
+ res.each_method_call req do |method, args|
36
+ nil
37
+ end
38
+
39
+ res.messages.length.should == 1
40
+ res.messages[0].data.should be_a(RocketAMF::Values::AcknowledgeMessage)
41
+ end
42
+
43
+ it "should handle RemotingMessages properly" do
44
+ res = RocketAMF::Response.new
45
+ req = create_request('remotingMessage.bin')
46
+ res.each_method_call req do |method, args|
47
+ method.should == 'WritesController.save'
48
+ args.should == [true]
49
+ true
50
+ end
51
+
52
+ res.messages.length.should == 1
53
+ res.messages[0].data.should be_a(RocketAMF::Values::AcknowledgeMessage)
54
+ res.messages[0].data.body.should == true
55
+ end
56
+
57
+ it "should catch exceptions properly" do
58
+ res = RocketAMF::Response.new
59
+ req = create_request('remotingMessage.bin')
60
+ res.each_method_call req do |method, args|
61
+ raise 'Error in call'
62
+ end
63
+
64
+ res.messages.length.should == 1
65
+ res.messages[0].data.should be_a(RocketAMF::Values::ErrorMessage)
66
+ res.messages[0].target_uri.should =~ /onStatus$/
67
+ end
68
+ end
@@ -0,0 +1,328 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'rexml/document'
4
+
5
+ describe "when serializing" do
6
+ before :each do
7
+ RocketAMF::ClassMapper.reset
8
+ end
9
+
10
+ describe "AMF0" do
11
+ it "should serialize nils" do
12
+ output = RocketAMF.serialize(nil, 0)
13
+ output.should == object_fixture('amf0-null.bin')
14
+ end
15
+
16
+ it "should serialize booleans" do
17
+ output = RocketAMF.serialize(true, 0)
18
+ output.should === object_fixture('amf0-boolean.bin')
19
+ end
20
+
21
+ it "should serialize numbers" do
22
+ output = RocketAMF.serialize(3.5, 0)
23
+ output.should == object_fixture('amf0-number.bin')
24
+ end
25
+
26
+ it "should serialize strings" do
27
+ output = RocketAMF.serialize("this is a テスト", 0)
28
+ output.should == object_fixture('amf0-string.bin')
29
+ end
30
+
31
+ it "should serialize arrays" do
32
+ output = RocketAMF.serialize(['a', 'b', 'c', 'd'], 0)
33
+ output.should == object_fixture('amf0-strict-array.bin')
34
+ end
35
+
36
+ it "should serialize references" do
37
+ class OtherClass
38
+ attr_accessor :foo, :bar
39
+ end
40
+ obj = OtherClass.new
41
+ obj.foo = "baz"
42
+ obj.bar = 3.14
43
+
44
+ output = RocketAMF.serialize({'0' => obj, '1' => obj}, 0)
45
+ output.should == object_fixture('amf0-ref-test.bin')
46
+ end
47
+
48
+ it "should serialize dates" do
49
+ output = RocketAMF.serialize(Time.utc(2003, 2, 13, 5), 0)
50
+ output.should == object_fixture('amf0-date.bin')
51
+ end
52
+
53
+ it "should serialize hashes" do
54
+ output = RocketAMF.serialize({:a => 'b', :c => 'd'}, 0)
55
+ output.should == object_fixture('amf0-hash.bin')
56
+ end
57
+
58
+ it "should serialize unmapped objects" do
59
+ class RubyClass
60
+ attr_accessor :foo, :baz
61
+ end
62
+ obj = RubyClass.new
63
+ obj.foo = "bar"
64
+
65
+ output = RocketAMF.serialize(obj, 0)
66
+ output.should == object_fixture('amf0-untyped-object.bin')
67
+ end
68
+
69
+ it "should serialize mapped objects" do
70
+ class RubyClass
71
+ attr_accessor :foo, :baz
72
+ end
73
+ obj = RubyClass.new
74
+ obj.foo = "bar"
75
+ RocketAMF::ClassMapper.define {|m| m.map :as => 'org.rocketAMF.ASClass', :ruby => 'RubyClass'}
76
+
77
+ output = RocketAMF.serialize(obj, 0)
78
+ output.should == object_fixture('amf0-typed-object.bin')
79
+ end
80
+ end
81
+
82
+ describe "AMF3" do
83
+ describe "simple messages" do
84
+ it "should serialize a null" do
85
+ expected = object_fixture("amf3-null.bin")
86
+ output = RocketAMF.serialize(nil, 3)
87
+ output.should == expected
88
+ end
89
+
90
+ it "should serialize a false" do
91
+ expected = object_fixture("amf3-false.bin")
92
+ output = RocketAMF.serialize(false, 3)
93
+ output.should == expected
94
+ end
95
+
96
+ it "should serialize a true" do
97
+ expected = object_fixture("amf3-true.bin")
98
+ output = RocketAMF.serialize(true, 3)
99
+ output.should == expected
100
+ end
101
+
102
+ it "should serialize integers" do
103
+ expected = object_fixture("amf3-max.bin")
104
+ input = RocketAMF::MAX_INTEGER
105
+ output = RocketAMF.serialize(input, 3)
106
+ output.should == expected
107
+
108
+ expected = object_fixture("amf3-0.bin")
109
+ output = RocketAMF.serialize(0, 3)
110
+ output.should == expected
111
+
112
+ expected = object_fixture("amf3-min.bin")
113
+ input = RocketAMF::MIN_INTEGER
114
+ output = RocketAMF.serialize(input, 3)
115
+ output.should == expected
116
+ end
117
+
118
+ it "should serialize large integers" do
119
+ expected = object_fixture("amf3-largeMax.bin")
120
+ input = RocketAMF::MAX_INTEGER + 1
121
+ output = RocketAMF.serialize(input, 3)
122
+ output.should == expected
123
+
124
+ expected = object_fixture("amf3-largeMin.bin")
125
+ input = RocketAMF::MIN_INTEGER - 1
126
+ output = RocketAMF.serialize(input, 3)
127
+ output.should == expected
128
+ end
129
+
130
+ it "should serialize BigNums" do
131
+ expected = object_fixture("amf3-bigNum.bin")
132
+ input = 2**1000
133
+ output = RocketAMF.serialize(input, 3)
134
+ output.should == expected
135
+ end
136
+
137
+ it "should serialize a simple string" do
138
+ expected = object_fixture("amf3-string.bin")
139
+ input = "String . String"
140
+ output = RocketAMF.serialize(input, 3)
141
+ output.should == expected
142
+ end
143
+
144
+ it "should serialize a symbol as a string" do
145
+ expected = object_fixture("amf3-symbol.bin")
146
+ output = RocketAMF.serialize(:foo, 3)
147
+ output.should == expected
148
+ end
149
+
150
+ it "should serialize Times" do
151
+ expected = object_fixture("amf3-date.bin")
152
+ input = Time.utc 1970, 1, 1, 0
153
+ output = RocketAMF.serialize(input, 3)
154
+ output.should == expected
155
+ end
156
+
157
+ #BAH! Who sends XML over AMF?
158
+ it "should serialize a REXML document"
159
+ end
160
+
161
+ describe "objects" do
162
+ it "should serialize an unmapped object as a dynamic anonymous object" do
163
+ class NonMappedObject
164
+ attr_accessor :property_one
165
+ attr_accessor :property_two
166
+ attr_accessor :nil_property
167
+ attr_writer :read_only_prop
168
+
169
+ def another_public_property
170
+ 'a_public_value'
171
+ end
172
+
173
+ def method_with_arg arg='foo'
174
+ arg
175
+ end
176
+ end
177
+ obj = NonMappedObject.new
178
+ obj.property_one = 'foo'
179
+ obj.property_two = 1
180
+ obj.nil_property = nil
181
+
182
+ expected = object_fixture("amf3-dynObject.bin")
183
+ input = obj
184
+ output = RocketAMF.serialize(input, 3)
185
+ output.should == expected
186
+ end
187
+
188
+ it "should serialize a hash as a dynamic anonymous object" do
189
+ hash = {}
190
+ hash[:answer] = 42
191
+ hash[:foo] = "bar"
192
+
193
+ expected = object_fixture("amf3-hash.bin")
194
+ input = hash
195
+ output = RocketAMF.serialize(input, 3)
196
+ output.should == expected
197
+ end
198
+
199
+ it "should serialize an empty array" do
200
+ expected = object_fixture("amf3-emptyArray.bin")
201
+ input = []
202
+ output = RocketAMF.serialize(input, 3)
203
+ output.should == expected
204
+ end
205
+
206
+ it "should serialize an array of primatives" do
207
+ expected = object_fixture("amf3-primArray.bin")
208
+ input = [1, 2, 3, 4, 5]
209
+ output = RocketAMF.serialize(input, 3)
210
+ output.should == expected
211
+ end
212
+
213
+ it "should serialize an array of mixed objects" do
214
+ h1 = {:foo_one => "bar_one"}
215
+ h2 = {:foo_two => ""}
216
+ class SimpleObj
217
+ attr_accessor :foo_three
218
+ end
219
+ so1 = SimpleObj.new
220
+ so1.foo_three = 42
221
+
222
+ expected = object_fixture("amf3-mixedArray.bin")
223
+ input = [h1, h2, so1, SimpleObj.new, {}, [h1, h2, so1], [], 42, "", [], "", {}, "bar_one", so1]
224
+ output = RocketAMF.serialize(input, 3)
225
+ output.should == expected
226
+ end
227
+
228
+ it "should serialize a byte array"
229
+ end
230
+
231
+ describe "and implementing the AMF Spec" do
232
+ it "should keep references of duplicate strings" do
233
+ class StringCarrier
234
+ attr_accessor :str
235
+ end
236
+ foo = "foo"
237
+ bar = "str"
238
+ sc = StringCarrier.new
239
+ sc.str = foo
240
+
241
+ expected = object_fixture("amf3-stringRef.bin")
242
+ input = [foo, bar, foo, bar, foo, sc]
243
+ output = RocketAMF.serialize(input, 3)
244
+ output.should == expected
245
+ end
246
+
247
+ it "should not reference the empty string" do
248
+ expected = object_fixture("amf3-emptyStringRef.bin")
249
+ input = ""
250
+ output = RocketAMF.serialize([input,input], 3)
251
+ output.should == expected
252
+ end
253
+
254
+ it "should keep references of duplicate dates" do
255
+ expected = object_fixture("amf3-datesRef.bin")
256
+ input = Time.utc 1970, 1, 1, 0
257
+ output = RocketAMF.serialize([input,input], 3)
258
+ output.should == expected
259
+ end
260
+
261
+ it "should keep reference of duplicate objects" do
262
+ class SimpleReferenceableObj
263
+ attr_accessor :foo
264
+ end
265
+ obj1 = SimpleReferenceableObj.new
266
+ obj1.foo = :bar
267
+ obj2 = SimpleReferenceableObj.new
268
+ obj2.foo = obj1.foo
269
+
270
+ expected = object_fixture("amf3-objRef.bin")
271
+ input = [[obj1, obj2], "bar", [obj1, obj2]]
272
+ output = RocketAMF.serialize(input, 3)
273
+ output.should == expected
274
+ end
275
+
276
+ it "should keep references of duplicate arrays" do
277
+ a = [1,2,3]
278
+ b = %w{ a b c }
279
+
280
+ expected = object_fixture("amf3-arrayRef.bin")
281
+ input = [a, b, a, b]
282
+ output = RocketAMF.serialize(input, 3)
283
+ output.should == expected
284
+ end
285
+
286
+ it "should not keep references of duplicate empty arrays unless the object_id matches" do
287
+ a = []
288
+ b = []
289
+ a.should == b
290
+ a.object_id.should_not == b.object_id
291
+
292
+ expected = object_fixture("amf3-emptyArrayRef.bin")
293
+ input = [a,b,a,b]
294
+ output = RocketAMF.serialize(input, 3)
295
+ output.should == expected
296
+ end
297
+
298
+ it "should keep references of duplicate XML and XMLDocuments"
299
+ it "should keep references of duplicate byte arrays"
300
+
301
+ it "should serialize a deep object graph with circular references" do
302
+ class GraphMember
303
+ attr_accessor :parent
304
+ attr_accessor :children
305
+
306
+ def initialize
307
+ self.children = []
308
+ end
309
+
310
+ def add_child child
311
+ children << child
312
+ child.parent = self
313
+ child
314
+ end
315
+ end
316
+
317
+ parent = GraphMember.new
318
+ level_1_child_1 = parent.add_child GraphMember.new
319
+ level_1_child_2 = parent.add_child GraphMember.new
320
+
321
+ expected = object_fixture("amf3-graphMember.bin")
322
+ input = parent
323
+ output = RocketAMF.serialize(input, 3)
324
+ output.should == expected
325
+ end
326
+ end
327
+ end
328
+ end