rocketamf_pure 1.0.0
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.
- data/README.rdoc +47 -0
- data/Rakefile +9 -0
- data/benchmark.rb +73 -0
- data/lib/rocketamf.rb +212 -0
- data/lib/rocketamf/class_mapping.rb +237 -0
- data/lib/rocketamf/constants.rb +46 -0
- data/lib/rocketamf/ext.rb +28 -0
- data/lib/rocketamf/extensions.rb +22 -0
- data/lib/rocketamf/pure.rb +24 -0
- data/lib/rocketamf/pure/deserializer.rb +417 -0
- data/lib/rocketamf/pure/io_helpers.rb +94 -0
- data/lib/rocketamf/pure/remoting.rb +117 -0
- data/lib/rocketamf/pure/serializer.rb +474 -0
- data/lib/rocketamf/remoting.rb +196 -0
- data/lib/rocketamf/values/messages.rb +212 -0
- data/lib/rocketamf/values/typed_hash.rb +13 -0
- data/lib/rocketamf_pure.rb +1 -0
- data/spec/class_mapping_spec.rb +110 -0
- data/spec/deserializer_spec.rb +423 -0
- data/spec/fast_class_mapping_spec.rb +144 -0
- data/spec/fixtures/objects/amf0-boolean.bin +1 -0
- data/spec/fixtures/objects/amf0-complex-encoded-string.bin +0 -0
- data/spec/fixtures/objects/amf0-date.bin +0 -0
- data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
- data/spec/fixtures/objects/amf0-hash.bin +0 -0
- data/spec/fixtures/objects/amf0-null.bin +1 -0
- data/spec/fixtures/objects/amf0-number.bin +0 -0
- data/spec/fixtures/objects/amf0-object.bin +0 -0
- data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
- data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
- data/spec/fixtures/objects/amf0-string.bin +0 -0
- data/spec/fixtures/objects/amf0-time.bin +0 -0
- data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
- data/spec/fixtures/objects/amf0-undefined.bin +1 -0
- data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
- data/spec/fixtures/objects/amf0-xml-doc.bin +0 -0
- data/spec/fixtures/objects/amf3-0.bin +0 -0
- data/spec/fixtures/objects/amf3-array-collection.bin +2 -0
- data/spec/fixtures/objects/amf3-array-ref.bin +1 -0
- data/spec/fixtures/objects/amf3-associative-array.bin +1 -0
- data/spec/fixtures/objects/amf3-bigNum.bin +0 -0
- data/spec/fixtures/objects/amf3-byte-array-ref.bin +1 -0
- data/spec/fixtures/objects/amf3-byte-array.bin +0 -0
- data/spec/fixtures/objects/amf3-complex-array-collection.bin +6 -0
- data/spec/fixtures/objects/amf3-complex-encoded-string-array.bin +1 -0
- data/spec/fixtures/objects/amf3-date-ref.bin +0 -0
- data/spec/fixtures/objects/amf3-date.bin +0 -0
- data/spec/fixtures/objects/amf3-dictionary.bin +0 -0
- data/spec/fixtures/objects/amf3-dynamic-object.bin +2 -0
- data/spec/fixtures/objects/amf3-empty-array-ref.bin +1 -0
- data/spec/fixtures/objects/amf3-empty-array.bin +1 -0
- data/spec/fixtures/objects/amf3-empty-dictionary.bin +0 -0
- data/spec/fixtures/objects/amf3-empty-string-ref.bin +1 -0
- data/spec/fixtures/objects/amf3-encoded-string-ref.bin +0 -0
- data/spec/fixtures/objects/amf3-externalizable.bin +0 -0
- data/spec/fixtures/objects/amf3-false.bin +1 -0
- data/spec/fixtures/objects/amf3-float.bin +0 -0
- data/spec/fixtures/objects/amf3-graph-member.bin +0 -0
- data/spec/fixtures/objects/amf3-hash.bin +2 -0
- data/spec/fixtures/objects/amf3-large-max.bin +0 -0
- data/spec/fixtures/objects/amf3-large-min.bin +0 -0
- data/spec/fixtures/objects/amf3-max.bin +1 -0
- data/spec/fixtures/objects/amf3-min.bin +0 -0
- data/spec/fixtures/objects/amf3-mixed-array.bin +10 -0
- data/spec/fixtures/objects/amf3-null.bin +1 -0
- data/spec/fixtures/objects/amf3-object-ref.bin +0 -0
- data/spec/fixtures/objects/amf3-primitive-array.bin +1 -0
- data/spec/fixtures/objects/amf3-string-ref.bin +0 -0
- data/spec/fixtures/objects/amf3-string.bin +1 -0
- data/spec/fixtures/objects/amf3-symbol.bin +1 -0
- data/spec/fixtures/objects/amf3-trait-ref.bin +3 -0
- data/spec/fixtures/objects/amf3-true.bin +1 -0
- data/spec/fixtures/objects/amf3-typed-object.bin +2 -0
- data/spec/fixtures/objects/amf3-xml-doc.bin +1 -0
- data/spec/fixtures/objects/amf3-xml-ref.bin +1 -0
- data/spec/fixtures/objects/amf3-xml.bin +1 -0
- data/spec/fixtures/request/acknowledge-response.bin +0 -0
- data/spec/fixtures/request/amf0-error-response.bin +0 -0
- data/spec/fixtures/request/blaze-response.bin +0 -0
- data/spec/fixtures/request/commandMessage.bin +0 -0
- data/spec/fixtures/request/flex-request.bin +0 -0
- data/spec/fixtures/request/multiple-simple-request.bin +0 -0
- data/spec/fixtures/request/remotingMessage.bin +0 -0
- data/spec/fixtures/request/simple-request.bin +0 -0
- data/spec/fixtures/request/simple-response.bin +0 -0
- data/spec/fixtures/request/unsupportedCommandMessage.bin +0 -0
- data/spec/messages_spec.rb +39 -0
- data/spec/remoting_spec.rb +196 -0
- data/spec/serializer_spec.rb +503 -0
- data/spec/spec_helper.rb +55 -0
- metadata +148 -0
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
abc
|
@@ -0,0 +1 @@
|
|
1
|
+
asdf fdsafoobar42 bar1 bar2 bar3
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
ASDF
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
Shift テストUTF テスト
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
����
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
String . String
|
@@ -0,0 +1 @@
|
|
1
|
+
foo
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
M<parent><child prop="test" /></parent>
|
@@ -0,0 +1 @@
|
|
1
|
+
K<parent><child prop="test"/></parent>
|
@@ -0,0 +1 @@
|
|
1
|
+
K<parent><child prop="test"/></parent>
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "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
|
+
|
12
|
+
it "should read externalized shortened BlazeDS messages" do
|
13
|
+
env = create_envelope('blaze-response.bin')
|
14
|
+
msg = env.messages[0].data
|
15
|
+
msg.class.name.should == "RocketAMF::Values::AcknowledgeMessageExt"
|
16
|
+
msg.clientId.should == "8814a067-fe0d-3a9c-a274-4aaed9bd7b0b"
|
17
|
+
msg.body.should =~ /xmlsoap\.org/
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe RocketAMF::Values::ErrorMessage do
|
22
|
+
before :each do
|
23
|
+
@e = Exception.new('Error message')
|
24
|
+
@e.set_backtrace(['Backtrace 1', 'Backtrace 2'])
|
25
|
+
@message = RocketAMF::Values::ErrorMessage.new(nil, @e)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should serialize as a hash in AMF0" do
|
29
|
+
response = RocketAMF::Envelope.new
|
30
|
+
response.messages << RocketAMF::Message.new('1/onStatus', '', @message)
|
31
|
+
response.serialize.should == request_fixture('amf0-error-response.bin')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should extract exception properties correctly" do
|
35
|
+
@message.faultCode.should == 'Exception'
|
36
|
+
@message.faultString.should == 'Error message'
|
37
|
+
@message.faultDetail.should == "Backtrace 1\nBacktrace 2"
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require "spec_helper.rb"
|
2
|
+
|
3
|
+
describe RocketAMF::Envelope do
|
4
|
+
describe 'deserializer' do
|
5
|
+
it "should handle remoting message from remote object" do
|
6
|
+
req = create_envelope("remotingMessage.bin")
|
7
|
+
|
8
|
+
req.headers.length.should == 0
|
9
|
+
req.messages.length.should == 1
|
10
|
+
message = req.messages[0].data
|
11
|
+
message.should be_a(RocketAMF::Values::RemotingMessage)
|
12
|
+
message.messageId.should == "FE4AF2BC-DD3C-5470-05D8-9971D51FF89D"
|
13
|
+
message.body.should == [true]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should handle command message from remote object" do
|
17
|
+
req = create_envelope("commandMessage.bin")
|
18
|
+
|
19
|
+
req.headers.length.should == 0
|
20
|
+
req.messages.length.should == 1
|
21
|
+
message = req.messages[0].data
|
22
|
+
message.should be_a(RocketAMF::Values::CommandMessage)
|
23
|
+
message.messageId.should == "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
|
24
|
+
message.body.should == {}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'request builder' do
|
29
|
+
it "should create simple call" do
|
30
|
+
req = RocketAMF::Envelope.new
|
31
|
+
req.call('TestController.test', 'first_arg', 'second_arg')
|
32
|
+
|
33
|
+
expected = request_fixture('simple-request.bin')
|
34
|
+
req.serialize.should == expected
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should allow multiple simple calls" do
|
38
|
+
req = RocketAMF::Envelope.new
|
39
|
+
req.call('TestController.test', 'first_arg', 'second_arg')
|
40
|
+
req.call('TestController.test2', 'first_arg', 'second_arg')
|
41
|
+
|
42
|
+
expected = request_fixture('multiple-simple-request.bin')
|
43
|
+
req.serialize.should == expected
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should create flex remoting call" do
|
47
|
+
req = RocketAMF::Envelope.new :amf_version => 3
|
48
|
+
req.call_flex('TestController.test', 'first_arg', 'second_arg')
|
49
|
+
req.messages[0].data.timestamp = 0
|
50
|
+
req.messages[0].data.messageId = "9D108E33-B591-BE79-210D-F1A72D06B578"
|
51
|
+
|
52
|
+
expected = request_fixture('flex-request.bin')
|
53
|
+
req.serialize.should == expected
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should require AMF version 3 for remoting calls" do
|
57
|
+
req = RocketAMF::Envelope.new :amf_version => 0
|
58
|
+
lambda {
|
59
|
+
req.call_flex('TestController.test')
|
60
|
+
}.should raise_error("Cannot use flex remoting calls with AMF0")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should require all calls be the same type" do
|
64
|
+
req = RocketAMF::Envelope.new :amf_version => 0
|
65
|
+
lambda {
|
66
|
+
req.call('TestController.test')
|
67
|
+
req.call_flex('TestController.test')
|
68
|
+
}.should raise_error("Cannot use different call types")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'serializer' do
|
73
|
+
it "should serialize response when converted to string" do
|
74
|
+
res = RocketAMF::Envelope.new
|
75
|
+
res.should_receive(:serialize).and_return('serialized')
|
76
|
+
res.to_s.should == 'serialized'
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should serialize a simple call" do
|
80
|
+
res = RocketAMF::Envelope.new :amf_version => 3
|
81
|
+
res.messages << RocketAMF::Message.new('/1/onResult', '', 'hello')
|
82
|
+
|
83
|
+
expected = request_fixture('simple-response.bin')
|
84
|
+
res.serialize.should == expected
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should serialize a AcknowledgeMessage response" do
|
88
|
+
ak = RocketAMF::Values::AcknowledgeMessage.new
|
89
|
+
ak.clientId = "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
|
90
|
+
ak.messageId = "7B0ACE15-8D57-6AE5-B9D4-99C2D32C8246"
|
91
|
+
ak.timestamp = 0
|
92
|
+
res = RocketAMF::Envelope.new :amf_version => 3
|
93
|
+
res.messages << RocketAMF::Message.new('/1/onResult', '', ak)
|
94
|
+
|
95
|
+
expected = request_fixture('acknowledge-response.bin')
|
96
|
+
res.serialize.should == expected
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'message handler' do
|
101
|
+
it "should respond to ping command" do
|
102
|
+
res = RocketAMF::Envelope.new
|
103
|
+
req = create_envelope('commandMessage.bin')
|
104
|
+
res.each_method_call req do |method, args|
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
res.messages.length.should == 1
|
109
|
+
res.messages[0].data.should be_a(RocketAMF::Values::AcknowledgeMessage)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should fail on unsupported command" do
|
113
|
+
res = RocketAMF::Envelope.new
|
114
|
+
req = create_envelope('unsupportedCommandMessage.bin')
|
115
|
+
res.each_method_call req do |method, args|
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
|
119
|
+
res.messages.length.should == 1
|
120
|
+
res.messages[0].data.should be_a(RocketAMF::Values::ErrorMessage)
|
121
|
+
res.messages[0].data.faultString.should == "CommandMessage 10000 not implemented"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should handle RemotingMessages properly" do
|
125
|
+
res = RocketAMF::Envelope.new
|
126
|
+
req = create_envelope('remotingMessage.bin')
|
127
|
+
res.each_method_call req do |method, args|
|
128
|
+
method.should == 'WritesController.save'
|
129
|
+
args.should == [true]
|
130
|
+
true
|
131
|
+
end
|
132
|
+
|
133
|
+
res.messages.length.should == 1
|
134
|
+
res.messages[0].data.should be_a(RocketAMF::Values::AcknowledgeMessage)
|
135
|
+
res.messages[0].data.body.should == true
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should catch exceptions properly" do
|
139
|
+
res = RocketAMF::Envelope.new
|
140
|
+
req = create_envelope('remotingMessage.bin')
|
141
|
+
res.each_method_call req do |method, args|
|
142
|
+
raise 'Error in call'
|
143
|
+
end
|
144
|
+
|
145
|
+
res.messages.length.should == 1
|
146
|
+
res.messages[0].data.should be_a(RocketAMF::Values::ErrorMessage)
|
147
|
+
res.messages[0].target_uri.should =~ /onStatus$/
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not crash if source missing on RemotingMessage" do
|
151
|
+
res = RocketAMF::Envelope.new
|
152
|
+
req = create_envelope('remotingMessage.bin')
|
153
|
+
req.messages[0].data.instance_variable_set("@source", nil)
|
154
|
+
lambda {
|
155
|
+
res.each_method_call req do |method,args|
|
156
|
+
true
|
157
|
+
end
|
158
|
+
}.should_not raise_error
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'response parser' do
|
163
|
+
it "should return the result of a simple response" do
|
164
|
+
req = RocketAMF::Envelope.new
|
165
|
+
req.call('TestController.test', 'first_arg', 'second_arg')
|
166
|
+
res = RocketAMF::Envelope.new
|
167
|
+
res.each_method_call req do |method, args|
|
168
|
+
['a', 'b']
|
169
|
+
end
|
170
|
+
|
171
|
+
res.result.should == ['a', 'b']
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should return the results of multiple simple response in a single request" do
|
175
|
+
req = RocketAMF::Envelope.new
|
176
|
+
req.call('TestController.test', 'first_arg', 'second_arg')
|
177
|
+
req.call('TestController.test2', 'first_arg', 'second_arg')
|
178
|
+
res = RocketAMF::Envelope.new
|
179
|
+
res.each_method_call req do |method, args|
|
180
|
+
['a', 'b']
|
181
|
+
end
|
182
|
+
|
183
|
+
res.result.should == [['a', 'b'], ['a', 'b']]
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should return the results of a flex response" do
|
187
|
+
req = RocketAMF::Envelope.new :amf_version => 3
|
188
|
+
req.call_flex('TestController.test', 'first_arg', 'second_arg')
|
189
|
+
res = RocketAMF::Envelope.new
|
190
|
+
res.each_method_call req do |method, args|
|
191
|
+
['a', 'b']
|
192
|
+
end
|
193
|
+
res.result.should == ['a', 'b']
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,503 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper.rb"
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'bigdecimal'
|
6
|
+
require 'rational'
|
7
|
+
|
8
|
+
describe "when serializing" do
|
9
|
+
before :each do
|
10
|
+
RocketAMF::ClassMapper.reset
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should raise exception with invalid version number" do
|
14
|
+
lambda {
|
15
|
+
RocketAMF.serialize("", 5)
|
16
|
+
}.should raise_error("unsupported version 5")
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "AMF0" do
|
20
|
+
it "should serialize nils" do
|
21
|
+
output = RocketAMF.serialize(nil, 0)
|
22
|
+
output.should == object_fixture('amf0-null.bin')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should serialize booleans" do
|
26
|
+
output = RocketAMF.serialize(true, 0)
|
27
|
+
output.should === object_fixture('amf0-boolean.bin')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should serialize numbers" do
|
31
|
+
output = RocketAMF.serialize(3.5, 0)
|
32
|
+
output.should == object_fixture('amf0-number.bin')
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should serialize Numeric conformers" do
|
36
|
+
output = RocketAMF.serialize(BigDecimal.new("3.5"), 0)
|
37
|
+
output.should == object_fixture('amf0-number.bin')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should serialize strings" do
|
41
|
+
output = RocketAMF.serialize("this is a テスト", 0)
|
42
|
+
output.should == object_fixture('amf0-string.bin')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should serialize frozen strings" do
|
46
|
+
output = RocketAMF.serialize("this is a テスト".freeze, 0)
|
47
|
+
output.should == object_fixture('amf0-string.bin')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should serialize arrays" do
|
51
|
+
output = RocketAMF.serialize(['a', 'b', 'c', 'd'], 0)
|
52
|
+
output.should == object_fixture('amf0-strict-array.bin')
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should serialize references" do
|
56
|
+
obj = OtherClass.new
|
57
|
+
obj.foo = "baz"
|
58
|
+
obj.bar = 3.14
|
59
|
+
|
60
|
+
output = RocketAMF.serialize({'0' => obj, '1' => obj}, 0)
|
61
|
+
output.should == object_fixture('amf0-ref-test.bin')
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should serialize Time objects" do
|
65
|
+
output = RocketAMF.serialize(Time.utc(2003, 2, 13, 5), 0)
|
66
|
+
output.bytesize.should == 11
|
67
|
+
output[0,9].should == object_fixture('amf0-time.bin')[0,9] # Ignore TZ
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should serialize Date objects" do
|
71
|
+
output = RocketAMF.serialize(Date.civil(2020, 5, 30), 0)
|
72
|
+
output.bytesize.should == 11
|
73
|
+
output[0,9].should == object_fixture('amf0-date.bin')[0,9] # Ignore TZ
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should serialize DateTime objects" do
|
77
|
+
output = RocketAMF.serialize(DateTime.civil(2003, 2, 13, 5), 0)
|
78
|
+
output.bytesize.should == 11
|
79
|
+
output[0,9].should == object_fixture('amf0-time.bin')[0,9] # Ignore TZ
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should serialize hashes as objects" do
|
83
|
+
output = RocketAMF.serialize({:baz => nil, "foo" => "bar"}, 0)
|
84
|
+
output.should == object_fixture('amf0-untyped-object.bin')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should serialize unmapped objects" do
|
88
|
+
obj = RubyClass.new
|
89
|
+
obj.foo = "bar"
|
90
|
+
|
91
|
+
output = RocketAMF.serialize(obj, 0)
|
92
|
+
output.should == object_fixture('amf0-untyped-object.bin')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should serialize mapped objects" do
|
96
|
+
obj = RubyClass.new
|
97
|
+
obj.foo = "bar"
|
98
|
+
RocketAMF::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
|
99
|
+
|
100
|
+
output = RocketAMF.serialize(obj, 0)
|
101
|
+
output.should == object_fixture('amf0-typed-object.bin')
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "and handling encodings", :if => "".respond_to?(:force_encoding) do
|
105
|
+
it "should support multiple encodings" do
|
106
|
+
shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
|
107
|
+
utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
|
108
|
+
output = RocketAMF.serialize({:shift => shift_str, :utf => utf_str, :zed => 5}, 0)
|
109
|
+
output.should == object_fixture("amf0-complex-encoded-string.bin")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "AMF3" do
|
115
|
+
describe "simple messages" do
|
116
|
+
it "should serialize a null" do
|
117
|
+
expected = object_fixture("amf3-null.bin")
|
118
|
+
output = RocketAMF.serialize(nil, 3)
|
119
|
+
output.should == expected
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should serialize a false" do
|
123
|
+
expected = object_fixture("amf3-false.bin")
|
124
|
+
output = RocketAMF.serialize(false, 3)
|
125
|
+
output.should == expected
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should serialize a true" do
|
129
|
+
expected = object_fixture("amf3-true.bin")
|
130
|
+
output = RocketAMF.serialize(true, 3)
|
131
|
+
output.should == expected
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should serialize integers" do
|
135
|
+
expected = object_fixture("amf3-max.bin")
|
136
|
+
input = RocketAMF::MAX_INTEGER
|
137
|
+
output = RocketAMF.serialize(input, 3)
|
138
|
+
output.should == expected
|
139
|
+
|
140
|
+
expected = object_fixture("amf3-0.bin")
|
141
|
+
output = RocketAMF.serialize(0, 3)
|
142
|
+
output.should == expected
|
143
|
+
|
144
|
+
expected = object_fixture("amf3-min.bin")
|
145
|
+
input = RocketAMF::MIN_INTEGER
|
146
|
+
output = RocketAMF.serialize(input, 3)
|
147
|
+
output.should == expected
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should serialize large integers" do
|
151
|
+
expected = object_fixture("amf3-large-max.bin")
|
152
|
+
input = RocketAMF::MAX_INTEGER + 1
|
153
|
+
output = RocketAMF.serialize(input, 3)
|
154
|
+
output.should == expected
|
155
|
+
|
156
|
+
expected = object_fixture("amf3-large-min.bin")
|
157
|
+
input = RocketAMF::MIN_INTEGER - 1
|
158
|
+
output = RocketAMF.serialize(input, 3)
|
159
|
+
output.should == expected
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should serialize floats" do
|
163
|
+
expected = object_fixture("amf3-float.bin")
|
164
|
+
input = 3.5
|
165
|
+
output = RocketAMF.serialize(input, 3)
|
166
|
+
output.should == expected
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should serialize BigNums" do
|
170
|
+
expected = object_fixture("amf3-bigNum.bin")
|
171
|
+
input = 2**1000
|
172
|
+
output = RocketAMF.serialize(input, 3)
|
173
|
+
output.should == expected
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should serialize float Numeric conformers" do
|
177
|
+
expected = object_fixture("amf3-float.bin")
|
178
|
+
input = Rational(7, 2) # 3.5
|
179
|
+
output = RocketAMF.serialize(input, 3)
|
180
|
+
output.should == expected
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should serialize a simple string" do
|
184
|
+
expected = object_fixture("amf3-string.bin")
|
185
|
+
input = "String . String"
|
186
|
+
output = RocketAMF.serialize(input, 3)
|
187
|
+
output.should == expected
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should serialize a frozen string" do
|
191
|
+
expected = object_fixture("amf3-string.bin")
|
192
|
+
input = "String . String".freeze
|
193
|
+
output = RocketAMF.serialize(input, 3)
|
194
|
+
output.should == expected
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should serialize a symbol as a string" do
|
198
|
+
expected = object_fixture("amf3-symbol.bin")
|
199
|
+
output = RocketAMF.serialize(:foo, 3)
|
200
|
+
output.should == expected
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should serialize Time objects" do
|
204
|
+
expected = object_fixture("amf3-date.bin")
|
205
|
+
input = Time.utc 1970, 1, 1, 0
|
206
|
+
output = RocketAMF.serialize(input, 3)
|
207
|
+
output.should == expected
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should serialize Date objects" do
|
211
|
+
expected = object_fixture("amf3-date.bin")
|
212
|
+
input = Date.civil 1970, 1, 1, 0
|
213
|
+
output = RocketAMF.serialize(input, 3)
|
214
|
+
output.should == expected
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should serialize DateTime objects" do
|
218
|
+
expected = object_fixture("amf3-date.bin")
|
219
|
+
input = DateTime.civil 1970, 1, 1, 0
|
220
|
+
output = RocketAMF.serialize(input, 3)
|
221
|
+
output.should == expected
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "objects" do
|
226
|
+
it "should serialize an unmapped object as a dynamic anonymous object" do
|
227
|
+
class NonMappedObject
|
228
|
+
def another_public_property
|
229
|
+
'a_public_value'
|
230
|
+
end
|
231
|
+
|
232
|
+
attr_accessor :nil_property
|
233
|
+
attr_accessor :property_one
|
234
|
+
attr_writer :read_only_prop
|
235
|
+
|
236
|
+
def method_with_arg arg='foo'
|
237
|
+
arg
|
238
|
+
end
|
239
|
+
end
|
240
|
+
obj = NonMappedObject.new
|
241
|
+
obj.property_one = 'foo'
|
242
|
+
obj.nil_property = nil
|
243
|
+
|
244
|
+
expected = object_fixture("amf3-dynamic-object.bin")
|
245
|
+
input = obj
|
246
|
+
output = RocketAMF.serialize(input, 3)
|
247
|
+
output.should == expected
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should serialize externalizable objects" do
|
251
|
+
a = ExternalizableTest.new
|
252
|
+
a.one = 5
|
253
|
+
a.two = 7
|
254
|
+
b = ExternalizableTest.new
|
255
|
+
b.one = 13
|
256
|
+
b.two = 5
|
257
|
+
obj = [a, b]
|
258
|
+
|
259
|
+
expected = object_fixture("amf3-externalizable.bin")
|
260
|
+
input = obj
|
261
|
+
output = RocketAMF.serialize(input, 3)
|
262
|
+
output.should == expected
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should serialize a hash as a dynamic anonymous object" do
|
266
|
+
hash = {}
|
267
|
+
hash[:answer] = 42
|
268
|
+
hash['foo'] = "bar"
|
269
|
+
|
270
|
+
expected = object_fixture("amf3-hash.bin")
|
271
|
+
input = hash
|
272
|
+
output = RocketAMF.serialize(input, 3)
|
273
|
+
output.should == expected
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should serialize an empty array" do
|
277
|
+
expected = object_fixture("amf3-empty-array.bin")
|
278
|
+
input = []
|
279
|
+
output = RocketAMF.serialize(input, 3)
|
280
|
+
output.should == expected
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should serialize an array of primatives" do
|
284
|
+
expected = object_fixture("amf3-primitive-array.bin")
|
285
|
+
input = [1, 2, 3, 4, 5]
|
286
|
+
output = RocketAMF.serialize(input, 3)
|
287
|
+
output.should == expected
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should serialize an array of mixed objects" do
|
291
|
+
h1 = {:foo_one => "bar_one"}
|
292
|
+
h2 = {:foo_two => ""}
|
293
|
+
class SimpleObj
|
294
|
+
attr_accessor :foo_three
|
295
|
+
end
|
296
|
+
so1 = SimpleObj.new
|
297
|
+
so1.foo_three = 42
|
298
|
+
|
299
|
+
expected = object_fixture("amf3-mixed-array.bin")
|
300
|
+
input = [h1, h2, so1, {}, [h1, h2, so1], [], 42, "", [], "", {}, "bar_one", so1]
|
301
|
+
output = RocketAMF.serialize(input, 3)
|
302
|
+
output.should == expected
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should serialize an array as an array collection" do
|
306
|
+
expected = object_fixture('amf3-array-collection.bin')
|
307
|
+
|
308
|
+
# Test global
|
309
|
+
RocketAMF::ClassMapper.use_array_collection = true
|
310
|
+
input = ["foo", "bar"]
|
311
|
+
output = RocketAMF.serialize(input, 3)
|
312
|
+
output.should == expected
|
313
|
+
RocketAMF::ClassMapper.use_array_collection = false
|
314
|
+
|
315
|
+
# Test override
|
316
|
+
input = ["foo", "bar"]
|
317
|
+
input.is_array_collection = true
|
318
|
+
output = RocketAMF.serialize(input, 3)
|
319
|
+
output.should == expected
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should serialize a complex set of array collections" do
|
323
|
+
RocketAMF::ClassMapper.define {|m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass'}
|
324
|
+
expected = object_fixture('amf3-complex-array-collection.bin')
|
325
|
+
|
326
|
+
a = ["foo", "bar"]
|
327
|
+
a.is_array_collection = true
|
328
|
+
obj1 = RubyClass.new
|
329
|
+
obj1.foo = "bar"
|
330
|
+
def obj1.encode_amf serializer
|
331
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
|
332
|
+
end
|
333
|
+
obj2 = RubyClass.new
|
334
|
+
obj2.foo = "asdf"
|
335
|
+
def obj2.encode_amf serializer
|
336
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
|
337
|
+
end
|
338
|
+
b = [obj1, obj2]
|
339
|
+
b.is_array_collection = true
|
340
|
+
input = [a, b, b]
|
341
|
+
|
342
|
+
output = RocketAMF.serialize(input, 3)
|
343
|
+
output.should == expected
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should serialize a byte array" do
|
347
|
+
expected = object_fixture("amf3-byte-array.bin")
|
348
|
+
str = "\000\003これtest\100"
|
349
|
+
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
|
350
|
+
input = StringIO.new(str)
|
351
|
+
output = RocketAMF.serialize(input, 3)
|
352
|
+
output.should == expected
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
describe "and implementing the AMF Spec" do
|
357
|
+
it "should keep references of duplicate strings" do
|
358
|
+
class StringCarrier
|
359
|
+
attr_accessor :str
|
360
|
+
end
|
361
|
+
foo = "foo"
|
362
|
+
bar = "str"
|
363
|
+
sc = StringCarrier.new
|
364
|
+
sc.str = foo
|
365
|
+
|
366
|
+
expected = object_fixture("amf3-string-ref.bin")
|
367
|
+
input = [foo, bar, foo, bar, foo, sc]
|
368
|
+
output = RocketAMF.serialize(input, 3)
|
369
|
+
output.should == expected
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should not reference the empty string" do
|
373
|
+
expected = object_fixture("amf3-empty-string-ref.bin")
|
374
|
+
input = ""
|
375
|
+
output = RocketAMF.serialize([input,input], 3)
|
376
|
+
output.should == expected
|
377
|
+
end
|
378
|
+
|
379
|
+
it "should keep references of duplicate dates" do
|
380
|
+
expected = object_fixture("amf3-date-ref.bin")
|
381
|
+
input = Time.utc 1970, 1, 1, 0
|
382
|
+
output = RocketAMF.serialize([input,input], 3)
|
383
|
+
output.should == expected
|
384
|
+
end
|
385
|
+
|
386
|
+
it "should keep reference of duplicate objects" do
|
387
|
+
class SimpleReferenceableObj
|
388
|
+
attr_accessor :foo
|
389
|
+
end
|
390
|
+
obj1 = SimpleReferenceableObj.new
|
391
|
+
obj1.foo = :bar
|
392
|
+
obj2 = SimpleReferenceableObj.new
|
393
|
+
obj2.foo = obj1.foo
|
394
|
+
|
395
|
+
expected = object_fixture("amf3-object-ref.bin")
|
396
|
+
input = [[obj1, obj2], "bar", [obj1, obj2]]
|
397
|
+
output = RocketAMF.serialize(input, 3)
|
398
|
+
output.should == expected
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should keep reference of duplicate object traits" do
|
402
|
+
obj1 = RubyClass.new
|
403
|
+
obj1.foo = "foo"
|
404
|
+
def obj1.encode_amf serializer
|
405
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
|
406
|
+
end
|
407
|
+
obj2 = RubyClass.new
|
408
|
+
obj2.foo = "bar"
|
409
|
+
def obj2.encode_amf serializer
|
410
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => ["baz", "foo"]})
|
411
|
+
end
|
412
|
+
input = [obj1, obj2]
|
413
|
+
|
414
|
+
expected = object_fixture("amf3-trait-ref.bin")
|
415
|
+
output = RocketAMF.serialize(input, 3)
|
416
|
+
output.should == expected
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should keep references of duplicate arrays" do
|
420
|
+
a = [1,2,3]
|
421
|
+
b = %w{ a b c }
|
422
|
+
|
423
|
+
expected = object_fixture("amf3-array-ref.bin")
|
424
|
+
input = [a, b, a, b]
|
425
|
+
output = RocketAMF.serialize(input, 3)
|
426
|
+
output.should == expected
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should not keep references of duplicate empty arrays unless the object_id matches" do
|
430
|
+
a = []
|
431
|
+
b = []
|
432
|
+
a.should == b
|
433
|
+
a.object_id.should_not == b.object_id
|
434
|
+
|
435
|
+
expected = object_fixture("amf3-empty-array-ref.bin")
|
436
|
+
input = [a,b,a,b]
|
437
|
+
output = RocketAMF.serialize(input, 3)
|
438
|
+
output.should == expected
|
439
|
+
end
|
440
|
+
|
441
|
+
it "should keep references of duplicate byte arrays" do
|
442
|
+
b = StringIO.new "ASDF"
|
443
|
+
|
444
|
+
expected = object_fixture("amf3-byte-array-ref.bin")
|
445
|
+
input = [b, b]
|
446
|
+
output = RocketAMF.serialize(input, 3)
|
447
|
+
output.should == expected
|
448
|
+
end
|
449
|
+
|
450
|
+
it "should serialize a deep object graph with circular references" do
|
451
|
+
class GraphMember
|
452
|
+
attr_accessor :children
|
453
|
+
attr_accessor :parent
|
454
|
+
|
455
|
+
def initialize
|
456
|
+
self.children = []
|
457
|
+
end
|
458
|
+
|
459
|
+
def add_child child
|
460
|
+
children << child
|
461
|
+
child.parent = self
|
462
|
+
child
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
parent = GraphMember.new
|
467
|
+
level_1_child_1 = parent.add_child GraphMember.new
|
468
|
+
level_1_child_2 = parent.add_child GraphMember.new
|
469
|
+
|
470
|
+
expected = object_fixture("amf3-graph-member.bin")
|
471
|
+
input = parent
|
472
|
+
output = RocketAMF.serialize(input, 3)
|
473
|
+
output.should == expected
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
describe "and handling encodings", :if => "".respond_to?(:force_encoding) do
|
478
|
+
it "should support multiple encodings" do
|
479
|
+
shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS") # "Shift テスト"
|
480
|
+
utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding("UTF-8") # "UTF テスト"
|
481
|
+
output = RocketAMF.serialize([5, shift_str, utf_str, 5], 3)
|
482
|
+
output.should == object_fixture("amf3-complex-encoded-string-array.bin")
|
483
|
+
end
|
484
|
+
|
485
|
+
it "should keep references of duplicate strings with different encodings" do
|
486
|
+
# String is "this is a テスト"
|
487
|
+
shift_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\x83\x65\x83\x58\x83\x67".force_encoding("Shift_JIS")
|
488
|
+
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")
|
489
|
+
|
490
|
+
expected = object_fixture("amf3-encoded-string-ref.bin")
|
491
|
+
output = RocketAMF.serialize([shift_str, utf_str], 3)
|
492
|
+
output.should == expected
|
493
|
+
end
|
494
|
+
|
495
|
+
it "should handle inappropriate UTF-8 characters in byte arrays" do
|
496
|
+
str = "\xff\xff\xff".force_encoding("ASCII-8BIT")
|
497
|
+
str.freeze # For added amusement
|
498
|
+
output = RocketAMF.serialize(StringIO.new(str), 3)
|
499
|
+
output.should == "\x0c\x07\xff\xff\xff".force_encoding("ASCII-8BIT")
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|