scalm-RocketAMF 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.
Files changed (106) hide show
  1. data/README.rdoc +47 -0
  2. data/Rakefile +59 -0
  3. data/RocketAMF.gemspec +20 -0
  4. data/benchmark.rb +74 -0
  5. data/ext/rocketamf_ext/class_mapping.c +484 -0
  6. data/ext/rocketamf_ext/constants.h +52 -0
  7. data/ext/rocketamf_ext/deserializer.c +776 -0
  8. data/ext/rocketamf_ext/deserializer.h +28 -0
  9. data/ext/rocketamf_ext/extconf.rb +18 -0
  10. data/ext/rocketamf_ext/remoting.c +184 -0
  11. data/ext/rocketamf_ext/rocketamf_ext.c +38 -0
  12. data/ext/rocketamf_ext/serializer.c +834 -0
  13. data/ext/rocketamf_ext/serializer.h +29 -0
  14. data/ext/rocketamf_ext/utility.h +4 -0
  15. data/lib/rocketamf.rb +216 -0
  16. data/lib/rocketamf/class_mapping.rb +237 -0
  17. data/lib/rocketamf/constants.rb +50 -0
  18. data/lib/rocketamf/ext.rb +28 -0
  19. data/lib/rocketamf/extensions.rb +22 -0
  20. data/lib/rocketamf/pure.rb +24 -0
  21. data/lib/rocketamf/pure/deserializer.rb +455 -0
  22. data/lib/rocketamf/pure/io_helpers.rb +94 -0
  23. data/lib/rocketamf/pure/remoting.rb +117 -0
  24. data/lib/rocketamf/pure/serializer.rb +474 -0
  25. data/lib/rocketamf/remoting.rb +196 -0
  26. data/lib/rocketamf/values/messages.rb +214 -0
  27. data/lib/rocketamf/values/typed_hash.rb +13 -0
  28. data/spec/class_mapping_spec.rb +110 -0
  29. data/spec/deserializer_spec.rb +455 -0
  30. data/spec/fast_class_mapping_spec.rb +144 -0
  31. data/spec/fixtures/objects/amf0-boolean.bin +1 -0
  32. data/spec/fixtures/objects/amf0-complex-encoded-string.bin +0 -0
  33. data/spec/fixtures/objects/amf0-date.bin +0 -0
  34. data/spec/fixtures/objects/amf0-ecma-ordinal-array.bin +0 -0
  35. data/spec/fixtures/objects/amf0-empty-string-key-hash.bin +0 -0
  36. data/spec/fixtures/objects/amf0-hash.bin +0 -0
  37. data/spec/fixtures/objects/amf0-null.bin +1 -0
  38. data/spec/fixtures/objects/amf0-number.bin +0 -0
  39. data/spec/fixtures/objects/amf0-object.bin +0 -0
  40. data/spec/fixtures/objects/amf0-ref-test.bin +0 -0
  41. data/spec/fixtures/objects/amf0-strict-array.bin +0 -0
  42. data/spec/fixtures/objects/amf0-string.bin +0 -0
  43. data/spec/fixtures/objects/amf0-time.bin +0 -0
  44. data/spec/fixtures/objects/amf0-typed-object.bin +0 -0
  45. data/spec/fixtures/objects/amf0-undefined.bin +1 -0
  46. data/spec/fixtures/objects/amf0-untyped-object.bin +0 -0
  47. data/spec/fixtures/objects/amf0-xml-doc.bin +0 -0
  48. data/spec/fixtures/objects/amf3-0.bin +0 -0
  49. data/spec/fixtures/objects/amf3-array-collection.bin +2 -0
  50. data/spec/fixtures/objects/amf3-array-ref.bin +1 -0
  51. data/spec/fixtures/objects/amf3-associative-array.bin +1 -0
  52. data/spec/fixtures/objects/amf3-bigNum.bin +0 -0
  53. data/spec/fixtures/objects/amf3-byte-array-ref.bin +1 -0
  54. data/spec/fixtures/objects/amf3-byte-array.bin +0 -0
  55. data/spec/fixtures/objects/amf3-complex-array-collection.bin +6 -0
  56. data/spec/fixtures/objects/amf3-complex-encoded-string-array.bin +1 -0
  57. data/spec/fixtures/objects/amf3-date-ref.bin +0 -0
  58. data/spec/fixtures/objects/amf3-date.bin +0 -0
  59. data/spec/fixtures/objects/amf3-dictionary.bin +0 -0
  60. data/spec/fixtures/objects/amf3-dynamic-object.bin +2 -0
  61. data/spec/fixtures/objects/amf3-empty-array-ref.bin +1 -0
  62. data/spec/fixtures/objects/amf3-empty-array.bin +1 -0
  63. data/spec/fixtures/objects/amf3-empty-dictionary.bin +0 -0
  64. data/spec/fixtures/objects/amf3-empty-string-ref.bin +1 -0
  65. data/spec/fixtures/objects/amf3-encoded-string-ref.bin +0 -0
  66. data/spec/fixtures/objects/amf3-externalizable.bin +0 -0
  67. data/spec/fixtures/objects/amf3-false.bin +1 -0
  68. data/spec/fixtures/objects/amf3-float.bin +0 -0
  69. data/spec/fixtures/objects/amf3-graph-member.bin +0 -0
  70. data/spec/fixtures/objects/amf3-hash.bin +2 -0
  71. data/spec/fixtures/objects/amf3-large-max.bin +0 -0
  72. data/spec/fixtures/objects/amf3-large-min.bin +0 -0
  73. data/spec/fixtures/objects/amf3-max.bin +1 -0
  74. data/spec/fixtures/objects/amf3-min.bin +0 -0
  75. data/spec/fixtures/objects/amf3-mixed-array.bin +10 -0
  76. data/spec/fixtures/objects/amf3-null.bin +1 -0
  77. data/spec/fixtures/objects/amf3-object-ref.bin +0 -0
  78. data/spec/fixtures/objects/amf3-primitive-array.bin +1 -0
  79. data/spec/fixtures/objects/amf3-string-ref.bin +0 -0
  80. data/spec/fixtures/objects/amf3-string.bin +1 -0
  81. data/spec/fixtures/objects/amf3-symbol.bin +1 -0
  82. data/spec/fixtures/objects/amf3-trait-ref.bin +3 -0
  83. data/spec/fixtures/objects/amf3-true.bin +1 -0
  84. data/spec/fixtures/objects/amf3-typed-object.bin +2 -0
  85. data/spec/fixtures/objects/amf3-vector-double.bin +0 -0
  86. data/spec/fixtures/objects/amf3-vector-int.bin +0 -0
  87. data/spec/fixtures/objects/amf3-vector-object.bin +0 -0
  88. data/spec/fixtures/objects/amf3-vector-uint.bin +0 -0
  89. data/spec/fixtures/objects/amf3-xml-doc.bin +1 -0
  90. data/spec/fixtures/objects/amf3-xml-ref.bin +1 -0
  91. data/spec/fixtures/objects/amf3-xml.bin +1 -0
  92. data/spec/fixtures/request/acknowledge-response.bin +0 -0
  93. data/spec/fixtures/request/amf0-error-response.bin +0 -0
  94. data/spec/fixtures/request/blaze-response.bin +0 -0
  95. data/spec/fixtures/request/commandMessage.bin +0 -0
  96. data/spec/fixtures/request/flex-request.bin +0 -0
  97. data/spec/fixtures/request/multiple-simple-request.bin +0 -0
  98. data/spec/fixtures/request/remotingMessage.bin +0 -0
  99. data/spec/fixtures/request/simple-request.bin +0 -0
  100. data/spec/fixtures/request/simple-response.bin +0 -0
  101. data/spec/fixtures/request/unsupportedCommandMessage.bin +0 -0
  102. data/spec/messages_spec.rb +39 -0
  103. data/spec/remoting_spec.rb +196 -0
  104. data/spec/serializer_spec.rb +503 -0
  105. data/spec/spec_helper.rb +55 -0
  106. metadata +164 -0
@@ -0,0 +1,144 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RocketAMF::Ext::FastClassMapping do
4
+ before :each do
5
+ RocketAMF::Ext::FastClassMapping.reset
6
+ RocketAMF::Ext::FastClassMapping.define do |m|
7
+ m.map :as => 'ASClass', :ruby => 'ClassMappingTest'
8
+ end
9
+ @mapper = RocketAMF::Ext::FastClassMapping.new
10
+ end
11
+
12
+ describe "class name mapping" do
13
+ it "should allow resetting of mappings back to defaults" do
14
+ @mapper.get_as_class_name('ClassMappingTest').should_not be_nil
15
+ RocketAMF::Ext::FastClassMapping.reset
16
+ @mapper = RocketAMF::Ext::FastClassMapping.new
17
+ @mapper.get_as_class_name('ClassMappingTest').should be_nil
18
+ @mapper.get_as_class_name('RocketAMF::Values::AcknowledgeMessage').should_not be_nil
19
+ end
20
+
21
+ it "should return AS class name for ruby objects" do
22
+ @mapper.get_as_class_name(ClassMappingTest.new).should == 'ASClass'
23
+ @mapper.get_as_class_name('ClassMappingTest').should == 'ASClass'
24
+ @mapper.get_as_class_name(RocketAMF::Values::TypedHash.new('ClassMappingTest')).should == 'ASClass'
25
+ @mapper.get_as_class_name('BadClass').should be_nil
26
+ end
27
+
28
+ it "should instantiate a ruby class" do
29
+ @mapper.get_ruby_obj('ASClass').should be_a(ClassMappingTest)
30
+ end
31
+
32
+ it "should properly instantiate namespaced classes" do
33
+ RocketAMF::Ext::FastClassMapping.mappings.map :as => 'ASClass', :ruby => 'ANamespace::TestRubyClass'
34
+ @mapper = RocketAMF::Ext::FastClassMapping.new
35
+ @mapper.get_ruby_obj('ASClass').should be_a(ANamespace::TestRubyClass)
36
+ end
37
+
38
+ it "should return a hash with original type if not mapped" do
39
+ obj = @mapper.get_ruby_obj('UnmappedClass')
40
+ obj.should be_a(RocketAMF::Values::TypedHash)
41
+ obj.type.should == 'UnmappedClass'
42
+ end
43
+
44
+ it "should map special classes from AS by default" do
45
+ as_classes = [
46
+ 'flex.messaging.messages.AcknowledgeMessage',
47
+ 'flex.messaging.messages.CommandMessage',
48
+ 'flex.messaging.messages.RemotingMessage'
49
+ ]
50
+
51
+ as_classes.each do |as_class|
52
+ @mapper.get_ruby_obj(as_class).should_not be_a(RocketAMF::Values::TypedHash)
53
+ end
54
+ end
55
+
56
+ it "should map special classes from ruby by default" do
57
+ ruby_classes = [
58
+ 'RocketAMF::Values::AcknowledgeMessage',
59
+ 'RocketAMF::Values::ErrorMessage'
60
+ ]
61
+
62
+ ruby_classes.each do |obj|
63
+ @mapper.get_as_class_name(obj).should_not be_nil
64
+ end
65
+ end
66
+
67
+ it "should allow config modification" do
68
+ RocketAMF::Ext::FastClassMapping.mappings.map :as => 'SecondClass', :ruby => 'ClassMappingTest'
69
+ @mapper = RocketAMF::Ext::FastClassMapping.new
70
+ @mapper.get_as_class_name(ClassMappingTest.new).should == 'SecondClass'
71
+ end
72
+ end
73
+
74
+ describe "ruby object populator" do
75
+ it "should populate a ruby class" do
76
+ obj = @mapper.populate_ruby_obj ClassMappingTest.new, {:prop_a => 'Data'}
77
+ obj.prop_a.should == 'Data'
78
+ end
79
+
80
+ it "should populate a typed hash" do
81
+ obj = @mapper.populate_ruby_obj RocketAMF::Values::TypedHash.new('UnmappedClass'), {'prop_a' => 'Data'}
82
+ obj['prop_a'].should == 'Data'
83
+ end
84
+ end
85
+
86
+ describe "property extractor" do
87
+ # Use symbol keys for properties in Ruby >1.9
88
+ def prop_hash hash
89
+ out = {}
90
+ if RUBY_VERSION =~ /^1\.8/
91
+ hash.each {|k,v| out[k.to_s] = v}
92
+ else
93
+ hash.each {|k,v| out[k.to_sym] = v}
94
+ end
95
+ out
96
+ end
97
+
98
+ it "should return hash without modification" do
99
+ hash = {:a => 'test1', 'b' => 'test2'}
100
+ props = @mapper.props_for_serialization(hash)
101
+ props.should === hash
102
+ end
103
+
104
+ it "should extract object properties" do
105
+ obj = ClassMappingTest.new
106
+ obj.prop_a = 'Test A'
107
+
108
+ hash = @mapper.props_for_serialization obj
109
+ hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => nil})
110
+ end
111
+
112
+ it "should extract inherited object properties" do
113
+ obj = ClassMappingTest2.new
114
+ obj.prop_a = 'Test A'
115
+ obj.prop_c = 'Test C'
116
+
117
+ hash = @mapper.props_for_serialization obj
118
+ hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => nil, 'prop_c' => 'Test C'})
119
+ end
120
+
121
+ it "should cache property lookups by instance" do
122
+ class ClassMappingTest3; attr_accessor :prop_a; end;
123
+
124
+ # Cache properties
125
+ obj = ClassMappingTest3.new
126
+ hash = @mapper.props_for_serialization obj
127
+
128
+ # Add a method to ClassMappingTest3
129
+ class ClassMappingTest3; attr_accessor :prop_b; end;
130
+
131
+ # Test property list does not have new property
132
+ obj = ClassMappingTest3.new
133
+ obj.prop_a = 'Test A'
134
+ obj.prop_b = 'Test B'
135
+ hash = @mapper.props_for_serialization obj
136
+ hash.should == prop_hash({'prop_a' => 'Test A'})
137
+
138
+ # Test that new class mapper *does* have new property (cache per instance)
139
+ @mapper = RocketAMF::Ext::FastClassMapping.new
140
+ hash = @mapper.props_for_serialization obj
141
+ hash.should == prop_hash({'prop_a' => 'Test A', 'prop_b' => 'Test B'})
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,2 @@
1
+
2
+ Cflex.messaging.io.ArrayCollection foobar
@@ -0,0 +1 @@
1
+   abc  
@@ -0,0 +1 @@
1
+  asdf fdsafoobar42 bar1 bar2 bar3
@@ -0,0 +1,6 @@
1
+ 
2
+ Cflex.messaging.io.ArrayCollection foobar
3
+  
4
+ #org.amf.ASClassbaz
5
+  asdf
6
+ 
@@ -0,0 +1 @@
1
+ Shift テストUTF テスト
@@ -0,0 +1,2 @@
1
+
2
+ /another_public_propertya_public_valuenil_propertyproperty_onefoo
@@ -0,0 +1 @@
1
+ ����
@@ -0,0 +1,10 @@
1
+ 
2
+ foo_onebar_one
3
+ foo_two
4
+ foo_three*
5
+  
6
+ 
7
+ 
8
+  * 
9
+ 
10
+ 
@@ -0,0 +1 @@
1
+ String . String
@@ -0,0 +1,3 @@
1
+ 
2
+ #org.amf.ASClassbazfoo
3
+ bar
@@ -0,0 +1,2 @@
1
+
2
+ #org.amf.ASClassbazfoobar
@@ -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>
@@ -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