mrpin-rocketamf 1.0.4 → 2.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.
- checksums.yaml +4 -4
- data/README.rdoc +1 -1
- data/Rakefile +7 -7
- data/benchmark.rb +44 -37
- data/ext/rocketamf_ext/class_mapping.c +11 -11
- data/ext/rocketamf_ext/remoting.c +1 -1
- data/lib/rocketamf.rb +41 -98
- data/lib/rocketamf/constants.rb +20 -20
- data/lib/rocketamf/errors.rb +2 -0
- data/lib/rocketamf/errors/amf_error.rb +5 -0
- data/lib/rocketamf/errors/amf_error_incomplete.rb +5 -0
- data/lib/rocketamf/ext.rb +0 -6
- data/lib/rocketamf/extensions.rb +4 -4
- data/lib/rocketamf/{class_mapping.rb → mapping/class_mapping.rb} +70 -103
- data/lib/rocketamf/mapping/mapping_set.rb +63 -0
- data/lib/rocketamf/pure.rb +1 -9
- data/lib/rocketamf/pure/deserializer.rb +234 -262
- data/lib/rocketamf/pure/helpers/io_helper_base.rb +19 -0
- data/lib/rocketamf/pure/helpers/io_helper_read.rb +67 -0
- data/lib/rocketamf/pure/helpers/io_helper_write.rb +48 -0
- data/lib/rocketamf/pure/helpers/object_cache.rb +20 -0
- data/lib/rocketamf/pure/helpers/string_cache.rb +14 -0
- data/lib/rocketamf/pure/serializer.rb +138 -271
- data/lib/rocketamf/types.rb +1 -0
- data/lib/rocketamf/{values → types}/typed_hash.rb +12 -2
- data/mrpin-rocketamf.gemspec +27 -16
- data/spec/class_mapping_spec.rb +59 -52
- data/spec/deserializer_spec.rb +164 -328
- data/spec/fast_class_mapping_spec.rb +52 -46
- data/spec/helpers/class_mapping_test.rb +4 -0
- data/spec/helpers/class_mapping_test2.rb +3 -0
- data/spec/helpers/externalizable_test.rb +24 -0
- data/spec/helpers/fixtures.rb +28 -0
- data/spec/helpers/other_class.rb +4 -0
- data/spec/helpers/ruby_class.rb +4 -0
- data/spec/helpers/test_ruby_class.rb +4 -0
- data/spec/serializer_spec.rb +248 -339
- data/spec/spec_helper.rb +4 -49
- metadata +47 -53
- data/lib/rocketamf/pure/io_helpers.rb +0 -94
- data/lib/rocketamf/pure/remoting.rb +0 -117
- data/lib/rocketamf/remoting.rb +0 -196
- data/lib/rocketamf/values/messages.rb +0 -214
- data/spec/fixtures/objects/amf0-boolean.bin +0 -1
- 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-empty-string-key-hash.bin +0 -0
- data/spec/fixtures/objects/amf0-hash.bin +0 -0
- data/spec/fixtures/objects/amf0-null.bin +0 -1
- 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 +0 -1
- data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
- data/spec/fixtures/objects/amf0-xml-doc.bin +0 -0
- data/spec/messages_spec.rb +0 -39
- data/spec/remoting_spec.rb +0 -196
@@ -1,116 +1,118 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper.rb'
|
2
2
|
|
3
3
|
describe RocketAMF::Ext::FastClassMapping do
|
4
4
|
before :each do
|
5
5
|
RocketAMF::Ext::FastClassMapping.reset
|
6
6
|
RocketAMF::Ext::FastClassMapping.define do |m|
|
7
|
-
m.map :as => 'ASClass', :
|
7
|
+
m.map :as => 'ASClass', ruby: 'ClassMappingTest'
|
8
8
|
end
|
9
9
|
@mapper = RocketAMF::Ext::FastClassMapping.new
|
10
10
|
end
|
11
11
|
|
12
|
-
describe
|
13
|
-
it
|
12
|
+
describe 'class name mapping' do
|
13
|
+
it 'should allow resetting of mappings back to defaults' do
|
14
14
|
@mapper.get_as_class_name('ClassMappingTest').should_not be_nil
|
15
15
|
RocketAMF::Ext::FastClassMapping.reset
|
16
16
|
@mapper = RocketAMF::Ext::FastClassMapping.new
|
17
17
|
@mapper.get_as_class_name('ClassMappingTest').should be_nil
|
18
|
-
@mapper.get_as_class_name('RocketAMF::
|
18
|
+
@mapper.get_as_class_name('RocketAMF::Types::AcknowledgeMessage').should_not be_nil
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
21
|
+
it 'should return AS class name for ruby objects' do
|
22
22
|
@mapper.get_as_class_name(ClassMappingTest.new).should == 'ASClass'
|
23
23
|
@mapper.get_as_class_name('ClassMappingTest').should == 'ASClass'
|
24
|
-
@mapper.get_as_class_name(RocketAMF::
|
24
|
+
@mapper.get_as_class_name(RocketAMF::Types::TypedHash.new('ClassMappingTest')).should == 'ASClass'
|
25
25
|
@mapper.get_as_class_name('BadClass').should be_nil
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
28
|
+
it 'should instantiate a ruby class' do
|
29
29
|
@mapper.get_ruby_obj('ASClass').should be_a(ClassMappingTest)
|
30
30
|
end
|
31
31
|
|
32
|
-
it
|
33
|
-
RocketAMF::Ext::FastClassMapping.mappings.map :as => 'ASClass', :
|
32
|
+
it 'should properly instantiate namespaced classes' do
|
33
|
+
RocketAMF::Ext::FastClassMapping.mappings.map :as => 'ASClass', ruby: 'ANamespace::TestRubyClass'
|
34
34
|
@mapper = RocketAMF::Ext::FastClassMapping.new
|
35
35
|
@mapper.get_ruby_obj('ASClass').should be_a(ANamespace::TestRubyClass)
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
38
|
+
it 'should return a hash with original type if not mapped' do
|
39
39
|
obj = @mapper.get_ruby_obj('UnmappedClass')
|
40
|
-
obj.should be_a(RocketAMF::
|
40
|
+
obj.should be_a(RocketAMF::Types::TypedHash)
|
41
41
|
obj.type.should == 'UnmappedClass'
|
42
42
|
end
|
43
43
|
|
44
|
-
it
|
45
|
-
as_classes =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
it 'should map special classes from AS by default' do
|
45
|
+
as_classes =
|
46
|
+
%w(
|
47
|
+
flex.messaging.messages.AcknowledgeMessage
|
48
|
+
flex.messaging.messages.CommandMessage
|
49
|
+
flex.messaging.messages.RemotingMessage
|
50
|
+
)
|
50
51
|
|
51
52
|
as_classes.each do |as_class|
|
52
|
-
@mapper.get_ruby_obj(as_class).should_not be_a(RocketAMF::
|
53
|
+
@mapper.get_ruby_obj(as_class).should_not be_a(RocketAMF::Types::TypedHash)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
it
|
57
|
-
ruby_classes =
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
it 'should map special classes from ruby by default' do
|
58
|
+
ruby_classes =
|
59
|
+
%w(
|
60
|
+
RocketAMF::Types::AcknowledgeMessage
|
61
|
+
RocketAMF::Types::ErrorMessage
|
62
|
+
)
|
61
63
|
|
62
64
|
ruby_classes.each do |obj|
|
63
65
|
@mapper.get_as_class_name(obj).should_not be_nil
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
67
|
-
it
|
68
|
-
RocketAMF::Ext::FastClassMapping.mappings.map :as => 'SecondClass', :
|
69
|
+
it 'should allow config modification' do
|
70
|
+
RocketAMF::Ext::FastClassMapping.mappings.map :as => 'SecondClass', ruby: 'ClassMappingTest'
|
69
71
|
@mapper = RocketAMF::Ext::FastClassMapping.new
|
70
72
|
@mapper.get_as_class_name(ClassMappingTest.new).should == 'SecondClass'
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
74
|
-
describe
|
75
|
-
it
|
76
|
+
describe 'ruby object populator' do
|
77
|
+
it 'should populate a ruby class' do
|
76
78
|
obj = @mapper.populate_ruby_obj ClassMappingTest.new, {:prop_a => 'Data'}
|
77
79
|
obj.prop_a.should == 'Data'
|
78
80
|
end
|
79
81
|
|
80
|
-
it
|
81
|
-
obj = @mapper.populate_ruby_obj RocketAMF::
|
82
|
+
it 'should populate a typed hash' do
|
83
|
+
obj = @mapper.populate_ruby_obj RocketAMF::Types::TypedHash.new('UnmappedClass'), {'prop_a' => 'Data'}
|
82
84
|
obj['prop_a'].should == 'Data'
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
86
|
-
describe
|
88
|
+
describe 'property extractor' do
|
87
89
|
# Use symbol keys for properties in Ruby >1.9
|
88
90
|
def prop_hash hash
|
89
91
|
out = {}
|
90
92
|
if RUBY_VERSION =~ /^1\.8/
|
91
|
-
hash.each {|k,v| out[k.to_s] = v}
|
93
|
+
hash.each { |k, v| out[k.to_s] = v }
|
92
94
|
else
|
93
|
-
hash.each {|k,v| out[k.to_sym] = v}
|
95
|
+
hash.each { |k, v| out[k.to_sym] = v }
|
94
96
|
end
|
95
97
|
out
|
96
98
|
end
|
97
99
|
|
98
|
-
it
|
99
|
-
hash
|
100
|
+
it 'should return hash without modification' do
|
101
|
+
hash = {:a => 'test1', 'b' => 'test2'}
|
100
102
|
props = @mapper.props_for_serialization(hash)
|
101
103
|
props.should === hash
|
102
104
|
end
|
103
105
|
|
104
|
-
it
|
105
|
-
obj
|
106
|
+
it 'should extract object properties' do
|
107
|
+
obj = ClassMappingTest.new
|
106
108
|
obj.prop_a = 'Test A'
|
107
109
|
|
108
110
|
hash = @mapper.props_for_serialization obj
|
109
111
|
hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => nil})
|
110
112
|
end
|
111
113
|
|
112
|
-
it
|
113
|
-
obj
|
114
|
+
it 'should extract inherited object properties' do
|
115
|
+
obj = ClassMappingTest2.new
|
114
116
|
obj.prop_a = 'Test A'
|
115
117
|
obj.prop_c = 'Test C'
|
116
118
|
|
@@ -118,26 +120,30 @@ describe RocketAMF::Ext::FastClassMapping do
|
|
118
120
|
hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => nil, 'prop_c' => 'Test C'})
|
119
121
|
end
|
120
122
|
|
121
|
-
it
|
122
|
-
class ClassMappingTest3;
|
123
|
+
it 'should cache property lookups by instance' do
|
124
|
+
class ClassMappingTest3;
|
125
|
+
attr_accessor :prop_a;
|
126
|
+
end;
|
123
127
|
|
124
128
|
# Cache properties
|
125
|
-
obj
|
129
|
+
obj = ClassMappingTest3.new
|
126
130
|
hash = @mapper.props_for_serialization obj
|
127
131
|
|
128
132
|
# Add a method to ClassMappingTest3
|
129
|
-
class ClassMappingTest3;
|
133
|
+
class ClassMappingTest3;
|
134
|
+
attr_accessor :prop_b;
|
135
|
+
end;
|
130
136
|
|
131
137
|
# Test property list does not have new property
|
132
|
-
obj
|
138
|
+
obj = ClassMappingTest3.new
|
133
139
|
obj.prop_a = 'Test A'
|
134
140
|
obj.prop_b = 'Test B'
|
135
|
-
hash
|
141
|
+
hash = @mapper.props_for_serialization obj
|
136
142
|
hash.should == prop_hash({'prop_a' => 'Test A'})
|
137
143
|
|
138
144
|
# Test that new class mapper *does* have new property (cache per instance)
|
139
145
|
@mapper = RocketAMF::Ext::FastClassMapping.new
|
140
|
-
hash
|
146
|
+
hash = @mapper.props_for_serialization obj
|
141
147
|
hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => 'Test B'})
|
142
148
|
end
|
143
149
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ExternalizableTest
|
2
|
+
include RocketAMF::Pure::IOHelperRead
|
3
|
+
include RocketAMF::Pure::IOHelperWrite
|
4
|
+
|
5
|
+
attr_accessor :one, :two
|
6
|
+
|
7
|
+
#
|
8
|
+
# Methods
|
9
|
+
#
|
10
|
+
|
11
|
+
def encode_amf(serializer)
|
12
|
+
serializer.write_object(self, nil, {class_name: 'ExternalizableTest', dynamic: false, externalizable: true, members: []})
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_external(deserializer)
|
16
|
+
@one = read_double(deserializer.source)
|
17
|
+
@two = read_double(deserializer.source)
|
18
|
+
end
|
19
|
+
|
20
|
+
def write_external(serializer)
|
21
|
+
serializer.stream << pack_double(@one)
|
22
|
+
serializer.stream << pack_double(@two)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
def request_fixture(binary_path)
|
2
|
+
data = File.open(File.dirname(__FILE__) + '/../fixtures/request/' + binary_path, 'rb').read
|
3
|
+
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
|
4
|
+
data
|
5
|
+
end
|
6
|
+
|
7
|
+
def object_fixture(binary_path)
|
8
|
+
data = File.open(File.dirname(__FILE__) + '/../fixtures/objects/' + binary_path, 'rb').read
|
9
|
+
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
|
10
|
+
data
|
11
|
+
end
|
12
|
+
|
13
|
+
def first_request_eq(object_fixture, value)
|
14
|
+
input = object_fixture(object_fixture)
|
15
|
+
output = RocketAMF.deserialize(input)
|
16
|
+
|
17
|
+
request = output[:requests][0]
|
18
|
+
|
19
|
+
expect(request).to eq(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_first_request(object_fixture)
|
23
|
+
input = object_fixture(object_fixture)
|
24
|
+
output = RocketAMF.deserialize(input)
|
25
|
+
|
26
|
+
requests = output[:requests]
|
27
|
+
requests[0]
|
28
|
+
end
|
data/spec/serializer_spec.rb
CHANGED
@@ -1,229 +1,128 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'spec_helper.rb'
|
4
4
|
require 'rexml/document'
|
5
5
|
require 'bigdecimal'
|
6
6
|
require 'rational'
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe 'when serializing' do
|
9
9
|
before :each do
|
10
|
-
RocketAMF::
|
10
|
+
RocketAMF::CLASS_MAPPER.reset
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
13
|
+
describe 'AMF3' do
|
14
|
+
describe 'simple messages' do
|
15
|
+
it 'should serialize a null' do
|
16
|
+
expected = object_fixture('amf3-null.bin')
|
17
|
+
output = RocketAMF.serialize(nil)
|
18
|
+
expect(output).to eq(expected)
|
120
19
|
end
|
121
20
|
|
122
|
-
it
|
123
|
-
expected = object_fixture(
|
124
|
-
output
|
125
|
-
output.
|
21
|
+
it 'should serialize a false' do
|
22
|
+
expected = object_fixture('amf3-false.bin')
|
23
|
+
output = RocketAMF.serialize(false)
|
24
|
+
expect(output).to eq(expected)
|
126
25
|
end
|
127
26
|
|
128
|
-
it
|
129
|
-
expected = object_fixture(
|
130
|
-
output
|
131
|
-
output.
|
27
|
+
it 'should serialize a true' do
|
28
|
+
expected = object_fixture('amf3-true.bin')
|
29
|
+
output = RocketAMF.serialize(true)
|
30
|
+
expect(output).to eq(expected)
|
132
31
|
end
|
133
32
|
|
134
|
-
it
|
135
|
-
expected = object_fixture(
|
136
|
-
input
|
137
|
-
output
|
138
|
-
output.
|
33
|
+
it 'should serialize integers' do
|
34
|
+
expected = object_fixture('amf3-max.bin')
|
35
|
+
input = RocketAMF::MAX_INTEGER
|
36
|
+
output = RocketAMF.serialize(input)
|
37
|
+
expect(output).to eq(expected)
|
139
38
|
|
140
|
-
expected = object_fixture(
|
141
|
-
output
|
142
|
-
output.
|
39
|
+
expected = object_fixture('amf3-0.bin')
|
40
|
+
output = RocketAMF.serialize(0)
|
41
|
+
expect(output).to eq(expected)
|
143
42
|
|
144
|
-
expected = object_fixture(
|
145
|
-
input
|
146
|
-
output
|
147
|
-
output.
|
43
|
+
expected = object_fixture('amf3-min.bin')
|
44
|
+
input = RocketAMF::MIN_INTEGER
|
45
|
+
output = RocketAMF.serialize(input)
|
46
|
+
expect(output).to eq(expected)
|
148
47
|
end
|
149
48
|
|
150
|
-
it
|
151
|
-
expected = object_fixture(
|
152
|
-
input
|
153
|
-
output
|
154
|
-
output.
|
49
|
+
it 'should serialize large integers' do
|
50
|
+
expected = object_fixture('amf3-large-max.bin')
|
51
|
+
input = RocketAMF::MAX_INTEGER + 1
|
52
|
+
output = RocketAMF.serialize(input)
|
53
|
+
expect(output).to eq(expected)
|
155
54
|
|
156
|
-
expected = object_fixture(
|
157
|
-
input
|
158
|
-
output
|
159
|
-
output.
|
55
|
+
expected = object_fixture('amf3-large-min.bin')
|
56
|
+
input = RocketAMF::MIN_INTEGER - 1
|
57
|
+
output = RocketAMF.serialize(input)
|
58
|
+
expect(output).to eq(expected)
|
160
59
|
end
|
161
60
|
|
162
|
-
it
|
163
|
-
expected = object_fixture(
|
164
|
-
input
|
165
|
-
output
|
166
|
-
output.
|
61
|
+
it 'should serialize floats' do
|
62
|
+
expected = object_fixture('amf3-float.bin')
|
63
|
+
input = 3.5
|
64
|
+
output = RocketAMF.serialize(input)
|
65
|
+
expect(output).to eq(expected)
|
167
66
|
end
|
168
67
|
|
169
|
-
it
|
170
|
-
expected = object_fixture(
|
171
|
-
input
|
172
|
-
output
|
173
|
-
output.
|
68
|
+
it 'should serialize BigNums' do
|
69
|
+
expected = object_fixture('amf3-bigNum.bin')
|
70
|
+
input = 2**1000
|
71
|
+
output = RocketAMF.serialize(input)
|
72
|
+
expect(output).to eq(expected)
|
174
73
|
end
|
175
74
|
|
176
|
-
it
|
177
|
-
expected = object_fixture(
|
178
|
-
input
|
179
|
-
output
|
180
|
-
output.
|
75
|
+
it 'should serialize float Numeric conformers' do
|
76
|
+
expected = object_fixture('amf3-float.bin')
|
77
|
+
input = Rational(7, 2) # 3.5
|
78
|
+
output = RocketAMF.serialize(input)
|
79
|
+
expect(output).to eq(expected)
|
181
80
|
end
|
182
81
|
|
183
|
-
it
|
184
|
-
expected = object_fixture(
|
185
|
-
input
|
186
|
-
output
|
187
|
-
output.
|
82
|
+
it 'should serialize a simple string' do
|
83
|
+
expected = object_fixture('amf3-string.bin')
|
84
|
+
input = 'String . String'
|
85
|
+
output = RocketAMF.serialize(input)
|
86
|
+
expect(output).to eq(expected)
|
188
87
|
end
|
189
88
|
|
190
|
-
it
|
191
|
-
expected = object_fixture(
|
192
|
-
input
|
193
|
-
output
|
194
|
-
output.
|
89
|
+
it 'should serialize a frozen string' do
|
90
|
+
expected = object_fixture('amf3-string.bin')
|
91
|
+
input = 'String . String'.freeze
|
92
|
+
output = RocketAMF.serialize(input)
|
93
|
+
expect(output).to eq(expected)
|
195
94
|
end
|
196
95
|
|
197
|
-
it
|
198
|
-
expected = object_fixture(
|
199
|
-
output
|
200
|
-
output.
|
96
|
+
it 'should serialize a symbol as a string' do
|
97
|
+
expected = object_fixture('amf3-symbol.bin')
|
98
|
+
output = RocketAMF.serialize(:foo)
|
99
|
+
expect(output).to eq(expected)
|
201
100
|
end
|
202
101
|
|
203
|
-
it
|
204
|
-
expected = object_fixture(
|
205
|
-
input
|
206
|
-
output
|
207
|
-
output.
|
102
|
+
it 'should serialize Time objects' do
|
103
|
+
expected = object_fixture('amf3-date.bin')
|
104
|
+
input = Time.utc 1970, 1, 1, 0
|
105
|
+
output = RocketAMF.serialize(input)
|
106
|
+
expect(output).to eq(expected)
|
208
107
|
end
|
209
108
|
|
210
|
-
it
|
211
|
-
expected = object_fixture(
|
212
|
-
input
|
213
|
-
output
|
214
|
-
output.
|
109
|
+
it 'should serialize Date objects' do
|
110
|
+
expected = object_fixture('amf3-date.bin')
|
111
|
+
input = Date.civil 1970, 1, 1, 0
|
112
|
+
output = RocketAMF.serialize(input)
|
113
|
+
expect(output).to eq(expected)
|
215
114
|
end
|
216
115
|
|
217
|
-
it
|
218
|
-
expected = object_fixture(
|
219
|
-
input
|
220
|
-
output
|
221
|
-
output.
|
116
|
+
it 'should serialize DateTime objects' do
|
117
|
+
expected = object_fixture('amf3-date.bin')
|
118
|
+
input = DateTime.civil 1970, 1, 1, 0
|
119
|
+
output = RocketAMF.serialize(input)
|
120
|
+
expect(output).to eq(expected)
|
222
121
|
end
|
223
122
|
end
|
224
123
|
|
225
|
-
describe
|
226
|
-
it
|
124
|
+
describe 'objects' do
|
125
|
+
it 'should serialize an unmapped object as a dynamic anonymous object' do
|
227
126
|
class NonMappedObject
|
228
127
|
def another_public_property
|
229
128
|
'a_public_value'
|
@@ -233,221 +132,229 @@ describe "when serializing" do
|
|
233
132
|
attr_accessor :property_one
|
234
133
|
attr_writer :read_only_prop
|
235
134
|
|
236
|
-
def method_with_arg
|
135
|
+
def method_with_arg(arg = 'foo')
|
237
136
|
arg
|
238
137
|
end
|
239
138
|
end
|
240
|
-
obj
|
139
|
+
obj = NonMappedObject.new
|
241
140
|
obj.property_one = 'foo'
|
242
141
|
obj.nil_property = nil
|
243
142
|
|
244
|
-
expected = object_fixture(
|
245
|
-
input
|
246
|
-
output
|
247
|
-
output.
|
143
|
+
expected = object_fixture('amf3-dynamic-object.bin')
|
144
|
+
input = obj
|
145
|
+
output = RocketAMF.serialize(input)
|
146
|
+
expect(output).to eq(expected)
|
248
147
|
end
|
249
148
|
|
250
|
-
it
|
251
|
-
a
|
149
|
+
it 'should serialize externalizable objects' do
|
150
|
+
a = ExternalizableTest.new
|
252
151
|
a.one = 5
|
253
152
|
a.two = 7
|
254
|
-
b
|
153
|
+
b = ExternalizableTest.new
|
255
154
|
b.one = 13
|
256
155
|
b.two = 5
|
257
|
-
obj
|
156
|
+
obj = [a, b]
|
258
157
|
|
259
|
-
expected = object_fixture(
|
260
|
-
input
|
261
|
-
output
|
262
|
-
output.
|
158
|
+
expected = object_fixture('amf3-externalizable.bin')
|
159
|
+
input = obj
|
160
|
+
output = RocketAMF.serialize(input)
|
161
|
+
expect(output).to eq(expected)
|
263
162
|
end
|
264
163
|
|
265
|
-
it
|
266
|
-
hash
|
164
|
+
it 'should serialize a hash as a dynamic anonymous object' do
|
165
|
+
hash = {}
|
267
166
|
hash[:answer] = 42
|
268
|
-
hash['foo']
|
167
|
+
hash['foo'] = 'bar'
|
269
168
|
|
270
|
-
expected = object_fixture(
|
271
|
-
input
|
272
|
-
output
|
273
|
-
output.
|
169
|
+
expected = object_fixture('amf3-hash.bin')
|
170
|
+
input = hash
|
171
|
+
output = RocketAMF.serialize(input)
|
172
|
+
expect(output).to eq(expected)
|
274
173
|
end
|
275
174
|
|
276
|
-
it
|
277
|
-
expected = object_fixture(
|
278
|
-
input
|
279
|
-
output
|
280
|
-
output.
|
175
|
+
it 'should serialize an empty array' do
|
176
|
+
expected = object_fixture('amf3-empty-array.bin')
|
177
|
+
input = []
|
178
|
+
output = RocketAMF.serialize(input)
|
179
|
+
expect(output).to eq(expected)
|
281
180
|
end
|
282
181
|
|
283
|
-
it
|
284
|
-
expected = object_fixture(
|
285
|
-
input
|
286
|
-
output
|
287
|
-
output.
|
182
|
+
it 'should serialize an array of primatives' do
|
183
|
+
expected = object_fixture('amf3-primitive-array.bin')
|
184
|
+
input = [1, 2, 3, 4, 5]
|
185
|
+
output = RocketAMF.serialize(input)
|
186
|
+
expect(output).to eq(expected)
|
288
187
|
end
|
289
188
|
|
290
|
-
it
|
291
|
-
h1 = {:foo_one =>
|
292
|
-
h2 = {:foo_two =>
|
189
|
+
it 'should serialize an array of mixed objects' do
|
190
|
+
h1 = {:foo_one => 'bar_one'}
|
191
|
+
h2 = {:foo_two => ''}
|
293
192
|
class SimpleObj
|
294
193
|
attr_accessor :foo_three
|
295
194
|
end
|
296
|
-
so1
|
195
|
+
so1 = SimpleObj.new
|
297
196
|
so1.foo_three = 42
|
298
197
|
|
299
|
-
expected = object_fixture(
|
300
|
-
input
|
301
|
-
output
|
302
|
-
output.
|
198
|
+
expected = object_fixture('amf3-mixed-array.bin')
|
199
|
+
input = [h1, h2, so1, {}, [h1, h2, so1], [], 42, '', [], '', {}, 'bar_one', so1]
|
200
|
+
output = RocketAMF.serialize(input)
|
201
|
+
expect(output).to eq(expected)
|
303
202
|
end
|
304
203
|
|
305
|
-
it
|
306
|
-
expected
|
204
|
+
it 'should serialize an array as an array collection' do
|
205
|
+
expected = object_fixture('amf3-array-collection.bin')
|
307
206
|
|
308
207
|
# Test global
|
309
|
-
RocketAMF::
|
310
|
-
input
|
311
|
-
output
|
312
|
-
output.
|
313
|
-
RocketAMF::
|
208
|
+
RocketAMF::CLASS_MAPPER.use_array_collection = true
|
209
|
+
input = %w( foo bar )
|
210
|
+
output = RocketAMF.serialize(input)
|
211
|
+
expect(output).to eq(expected)
|
212
|
+
RocketAMF::CLASS_MAPPER.use_array_collection = false
|
314
213
|
|
315
214
|
# Test override
|
316
|
-
input
|
317
|
-
input.is_array_collection
|
318
|
-
output
|
319
|
-
output.
|
215
|
+
input = %w( foo bar )
|
216
|
+
input.is_array_collection = true
|
217
|
+
output = RocketAMF.serialize(input)
|
218
|
+
expect(output).to eq(expected)
|
320
219
|
end
|
321
220
|
|
322
|
-
it
|
323
|
-
RocketAMF::
|
221
|
+
it 'should serialize a complex set of array collections' do
|
222
|
+
RocketAMF::CLASS_MAPPER.define { |m| m.map :as => 'org.amf.ASClass', :ruby => 'RubyClass' }
|
324
223
|
expected = object_fixture('amf3-complex-array-collection.bin')
|
325
224
|
|
326
|
-
a
|
225
|
+
a = %w(foo bar)
|
327
226
|
a.is_array_collection = true
|
328
|
-
obj1
|
329
|
-
obj1.foo
|
330
|
-
|
331
|
-
|
227
|
+
obj1 = RubyClass.new
|
228
|
+
obj1.foo = 'bar'
|
229
|
+
|
230
|
+
def obj1.encode_amf(serializer)
|
231
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, members: %w( baz foo )})
|
332
232
|
end
|
333
|
-
|
334
|
-
obj2
|
335
|
-
|
336
|
-
|
233
|
+
|
234
|
+
obj2 = RubyClass.new
|
235
|
+
obj2.foo = 'asdf'
|
236
|
+
|
237
|
+
def obj2.encode_amf(serializer)
|
238
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, members: %w( baz foo )})
|
337
239
|
end
|
338
|
-
|
240
|
+
|
241
|
+
b = [obj1, obj2]
|
339
242
|
b.is_array_collection = true
|
340
|
-
input
|
243
|
+
input = [a, b, b]
|
341
244
|
|
342
|
-
output = RocketAMF.serialize(input
|
343
|
-
output.
|
245
|
+
output = RocketAMF.serialize(input)
|
246
|
+
expect(output).to eq(expected)
|
344
247
|
end
|
345
248
|
|
346
|
-
it
|
347
|
-
expected = object_fixture(
|
348
|
-
str
|
349
|
-
str.force_encoding(
|
350
|
-
input
|
351
|
-
output = RocketAMF.serialize(input
|
352
|
-
output.
|
249
|
+
it 'should serialize a byte array' do
|
250
|
+
expected = object_fixture('amf3-byte-array.bin')
|
251
|
+
str = "\000\003これtest\100"
|
252
|
+
str.force_encoding('ASCII-8BIT') if str.respond_to?(:force_encoding)
|
253
|
+
input = StringIO.new(str)
|
254
|
+
output = RocketAMF.serialize(input)
|
255
|
+
expect(output).to eq(expected)
|
353
256
|
end
|
354
257
|
end
|
355
258
|
|
356
|
-
describe
|
357
|
-
it
|
259
|
+
describe 'and implementing the AMF Spec' do
|
260
|
+
it 'should keep references of duplicate strings' do
|
358
261
|
class StringCarrier
|
359
262
|
attr_accessor :str
|
360
263
|
end
|
361
|
-
foo
|
362
|
-
bar
|
363
|
-
sc
|
264
|
+
foo = 'foo'
|
265
|
+
bar = 'str'
|
266
|
+
sc = StringCarrier.new
|
364
267
|
sc.str = foo
|
365
268
|
|
366
|
-
expected = object_fixture(
|
367
|
-
input
|
368
|
-
output
|
369
|
-
output.
|
269
|
+
expected = object_fixture('amf3-string-ref.bin')
|
270
|
+
input = [foo, bar, foo, bar, foo, sc]
|
271
|
+
output = RocketAMF.serialize(input)
|
272
|
+
expect(output).to eq(expected)
|
370
273
|
end
|
371
274
|
|
372
|
-
it
|
373
|
-
expected = object_fixture(
|
374
|
-
input
|
375
|
-
output
|
376
|
-
output.
|
275
|
+
it 'should not reference the empty string' do
|
276
|
+
expected = object_fixture('amf3-empty-string-ref.bin')
|
277
|
+
input = ''
|
278
|
+
output = RocketAMF.serialize([input, input])
|
279
|
+
expect(output).to eq(expected)
|
377
280
|
end
|
378
281
|
|
379
|
-
it
|
380
|
-
expected = object_fixture(
|
381
|
-
input
|
382
|
-
output
|
383
|
-
output.
|
282
|
+
it 'should keep references of duplicate dates' do
|
283
|
+
expected = object_fixture('amf3-date-ref.bin')
|
284
|
+
input = Time.utc 1970, 1, 1, 0
|
285
|
+
output = RocketAMF.serialize([input, input])
|
286
|
+
expect(output).to eq(expected)
|
384
287
|
end
|
385
288
|
|
386
|
-
it
|
289
|
+
it 'should keep reference of duplicate objects' do
|
387
290
|
class SimpleReferenceableObj
|
388
291
|
attr_accessor :foo
|
389
292
|
end
|
390
|
-
obj1
|
293
|
+
obj1 = SimpleReferenceableObj.new
|
391
294
|
obj1.foo = :bar
|
392
|
-
obj2
|
295
|
+
obj2 = SimpleReferenceableObj.new
|
393
296
|
obj2.foo = obj1.foo
|
394
297
|
|
395
|
-
expected = object_fixture(
|
396
|
-
input
|
397
|
-
output
|
398
|
-
output.
|
298
|
+
expected = object_fixture('amf3-object-ref.bin')
|
299
|
+
input = [[obj1, obj2], 'bar', [obj1, obj2]]
|
300
|
+
output = RocketAMF.serialize(input)
|
301
|
+
expect(output).to eq(expected)
|
399
302
|
end
|
400
303
|
|
401
|
-
it
|
402
|
-
obj1
|
403
|
-
obj1.foo =
|
404
|
-
|
405
|
-
|
304
|
+
it 'should keep reference of duplicate object traits' do
|
305
|
+
obj1 = RubyClass.new
|
306
|
+
obj1.foo = 'foo'
|
307
|
+
|
308
|
+
def obj1.encode_amf(serializer)
|
309
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => %w( baz foo )})
|
406
310
|
end
|
407
|
-
|
408
|
-
obj2
|
409
|
-
|
410
|
-
|
311
|
+
|
312
|
+
obj2 = RubyClass.new
|
313
|
+
obj2.foo = 'bar'
|
314
|
+
|
315
|
+
def obj2.encode_amf(serializer)
|
316
|
+
serializer.write_object(self, nil, {:class_name => 'org.amf.ASClass', :dynamic => false, :externalizable => false, :members => %w( baz foo )})
|
411
317
|
end
|
318
|
+
|
412
319
|
input = [obj1, obj2]
|
413
320
|
|
414
|
-
expected = object_fixture(
|
415
|
-
output
|
416
|
-
output.
|
321
|
+
expected = object_fixture('amf3-trait-ref.bin')
|
322
|
+
output = RocketAMF.serialize(input)
|
323
|
+
expect(output).to eq(expected)
|
417
324
|
end
|
418
325
|
|
419
|
-
it
|
420
|
-
a = [1,2,3]
|
326
|
+
it 'should keep references of duplicate arrays' do
|
327
|
+
a = [1, 2, 3]
|
421
328
|
b = %w{ a b c }
|
422
329
|
|
423
|
-
expected = object_fixture(
|
424
|
-
input
|
425
|
-
output
|
426
|
-
output.
|
330
|
+
expected = object_fixture('amf3-array-ref.bin')
|
331
|
+
input = [a, b, a, b]
|
332
|
+
output = RocketAMF.serialize(input)
|
333
|
+
expect(output).to eq(expected)
|
427
334
|
end
|
428
335
|
|
429
|
-
it
|
336
|
+
it 'should not keep references of duplicate empty arrays unless the object_id matches' do
|
430
337
|
a = []
|
431
338
|
b = []
|
432
|
-
a.
|
433
|
-
a.object_id.
|
339
|
+
expect(a).to eq(b)
|
340
|
+
expect(a.object_id).not_to eq(b.object_id)
|
434
341
|
|
435
|
-
expected = object_fixture(
|
436
|
-
input
|
437
|
-
output
|
438
|
-
output.
|
342
|
+
expected = object_fixture('amf3-empty-array-ref.bin')
|
343
|
+
input = [a, b, a, b]
|
344
|
+
output = RocketAMF.serialize(input)
|
345
|
+
expect(output).to eq(expected)
|
439
346
|
end
|
440
347
|
|
441
|
-
it
|
442
|
-
b = StringIO.new
|
348
|
+
it 'should keep references of duplicate byte arrays' do
|
349
|
+
b = StringIO.new 'ASDF'
|
443
350
|
|
444
|
-
expected = object_fixture(
|
445
|
-
input
|
446
|
-
output
|
447
|
-
output.
|
351
|
+
expected = object_fixture('amf3-byte-array-ref.bin')
|
352
|
+
input = [b, b]
|
353
|
+
output = RocketAMF.serialize(input)
|
354
|
+
expect(output).to eq(expected)
|
448
355
|
end
|
449
356
|
|
450
|
-
it
|
357
|
+
it 'should serialize a deep object graph with circular references' do
|
451
358
|
class GraphMember
|
452
359
|
attr_accessor :children
|
453
360
|
attr_accessor :parent
|
@@ -456,7 +363,7 @@ describe "when serializing" do
|
|
456
363
|
self.children = []
|
457
364
|
end
|
458
365
|
|
459
|
-
def add_child
|
366
|
+
def add_child(child)
|
460
367
|
children << child
|
461
368
|
child.parent = self
|
462
369
|
child
|
@@ -464,39 +371,41 @@ describe "when serializing" do
|
|
464
371
|
end
|
465
372
|
|
466
373
|
parent = GraphMember.new
|
467
|
-
level_1_child_1
|
468
|
-
|
374
|
+
#level_1_child_1
|
375
|
+
parent.add_child(GraphMember.new)
|
376
|
+
#level_1_child_2
|
377
|
+
parent.add_child(GraphMember.new)
|
469
378
|
|
470
|
-
expected = object_fixture(
|
471
|
-
input
|
472
|
-
output
|
473
|
-
output.
|
379
|
+
expected = object_fixture('amf3-graph-member.bin')
|
380
|
+
input = parent
|
381
|
+
output = RocketAMF.serialize(input)
|
382
|
+
expect(output).to eq(expected)
|
474
383
|
end
|
475
384
|
end
|
476
385
|
|
477
|
-
describe
|
478
|
-
it
|
479
|
-
shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding(
|
480
|
-
utf_str
|
481
|
-
output
|
482
|
-
output.
|
386
|
+
describe 'and handling encodings', if: ''.respond_to?(:force_encoding) do
|
387
|
+
it 'should support multiple encodings' do
|
388
|
+
shift_str = "\x53\x68\x69\x66\x74\x20\x83\x65\x83\x58\x83\x67".force_encoding('Shift_JIS') # 'Shift テスト'
|
389
|
+
utf_str = "\x55\x54\x46\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8') # 'UTF テスト'
|
390
|
+
output = RocketAMF.serialize([5, shift_str, utf_str, 5])
|
391
|
+
expect(output).to eq(object_fixture('amf3-complex-encoded-string-array.bin'))
|
483
392
|
end
|
484
393
|
|
485
|
-
it
|
486
|
-
# String is
|
487
|
-
shift_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\x83\x65\x83\x58\x83\x67".force_encoding(
|
488
|
-
utf_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding(
|
394
|
+
it 'should keep references of duplicate strings with different encodings' do
|
395
|
+
# String is 'this is a テスト'
|
396
|
+
shift_str = "\x74\x68\x69\x73\x20\x69\x73\x20\x61\x20\x83\x65\x83\x58\x83\x67".force_encoding('Shift_JIS')
|
397
|
+
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
398
|
|
490
|
-
expected = object_fixture(
|
491
|
-
output
|
492
|
-
output.
|
399
|
+
expected = object_fixture('amf3-encoded-string-ref.bin')
|
400
|
+
output = RocketAMF.serialize([shift_str, utf_str])
|
401
|
+
expect(output).to eq(expected)
|
493
402
|
end
|
494
403
|
|
495
|
-
it
|
496
|
-
str = "\xff\xff\xff".force_encoding(
|
404
|
+
it 'should handle inappropriate UTF-8 characters in byte arrays' do
|
405
|
+
str = "\xff\xff\xff".force_encoding('ASCII-8BIT')
|
497
406
|
str.freeze # For added amusement
|
498
|
-
output = RocketAMF.serialize(StringIO.new(str)
|
499
|
-
output.
|
407
|
+
output = RocketAMF.serialize(StringIO.new(str))
|
408
|
+
expect(output).to eq("\x0c\x07\xff\xff\xff".force_encoding('ASCII-8BIT'))
|
500
409
|
end
|
501
410
|
end
|
502
411
|
end
|