sessionm-thrift 0.8.0.1

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 (81) hide show
  1. data/CHANGELOG +1 -0
  2. data/README +43 -0
  3. data/benchmark/Benchmark.thrift +24 -0
  4. data/benchmark/benchmark.rb +271 -0
  5. data/benchmark/client.rb +74 -0
  6. data/benchmark/server.rb +82 -0
  7. data/benchmark/thin_server.rb +44 -0
  8. data/ext/binary_protocol_accelerated.c +441 -0
  9. data/ext/binary_protocol_accelerated.h +20 -0
  10. data/ext/compact_protocol.c +618 -0
  11. data/ext/compact_protocol.h +20 -0
  12. data/ext/constants.h +96 -0
  13. data/ext/extconf.rb +30 -0
  14. data/ext/macros.h +41 -0
  15. data/ext/memory_buffer.c +131 -0
  16. data/ext/memory_buffer.h +20 -0
  17. data/ext/protocol.c +185 -0
  18. data/ext/protocol.h +20 -0
  19. data/ext/strlcpy.c +41 -0
  20. data/ext/strlcpy.h +30 -0
  21. data/ext/struct.c +691 -0
  22. data/ext/struct.h +25 -0
  23. data/ext/thrift_native.c +196 -0
  24. data/lib/thrift.rb +64 -0
  25. data/lib/thrift/client.rb +62 -0
  26. data/lib/thrift/core_ext.rb +23 -0
  27. data/lib/thrift/core_ext/fixnum.rb +29 -0
  28. data/lib/thrift/exceptions.rb +84 -0
  29. data/lib/thrift/processor.rb +57 -0
  30. data/lib/thrift/protocol/base_protocol.rb +290 -0
  31. data/lib/thrift/protocol/binary_protocol.rb +229 -0
  32. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  33. data/lib/thrift/protocol/compact_protocol.rb +426 -0
  34. data/lib/thrift/serializer/deserializer.rb +33 -0
  35. data/lib/thrift/serializer/serializer.rb +34 -0
  36. data/lib/thrift/server/base_server.rb +31 -0
  37. data/lib/thrift/server/mongrel_http_server.rb +58 -0
  38. data/lib/thrift/server/nonblocking_server.rb +305 -0
  39. data/lib/thrift/server/simple_server.rb +43 -0
  40. data/lib/thrift/server/thread_pool_server.rb +75 -0
  41. data/lib/thrift/server/threaded_server.rb +47 -0
  42. data/lib/thrift/struct.rb +237 -0
  43. data/lib/thrift/struct_union.rb +192 -0
  44. data/lib/thrift/thrift_native.rb +24 -0
  45. data/lib/thrift/transport/base_server_transport.rb +37 -0
  46. data/lib/thrift/transport/base_transport.rb +107 -0
  47. data/lib/thrift/transport/buffered_transport.rb +108 -0
  48. data/lib/thrift/transport/framed_transport.rb +116 -0
  49. data/lib/thrift/transport/http_client_transport.rb +51 -0
  50. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  51. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  52. data/lib/thrift/transport/server_socket.rb +63 -0
  53. data/lib/thrift/transport/socket.rb +137 -0
  54. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  55. data/lib/thrift/transport/unix_socket.rb +40 -0
  56. data/lib/thrift/types.rb +101 -0
  57. data/lib/thrift/union.rb +179 -0
  58. data/spec/ThriftSpec.thrift +132 -0
  59. data/spec/base_protocol_spec.rb +160 -0
  60. data/spec/base_transport_spec.rb +351 -0
  61. data/spec/binary_protocol_accelerated_spec.rb +46 -0
  62. data/spec/binary_protocol_spec.rb +61 -0
  63. data/spec/binary_protocol_spec_shared.rb +375 -0
  64. data/spec/client_spec.rb +100 -0
  65. data/spec/compact_protocol_spec.rb +144 -0
  66. data/spec/exception_spec.rb +142 -0
  67. data/spec/http_client_spec.rb +64 -0
  68. data/spec/mongrel_http_server_spec.rb +117 -0
  69. data/spec/nonblocking_server_spec.rb +265 -0
  70. data/spec/processor_spec.rb +83 -0
  71. data/spec/serializer_spec.rb +69 -0
  72. data/spec/server_socket_spec.rb +80 -0
  73. data/spec/server_spec.rb +159 -0
  74. data/spec/socket_spec.rb +61 -0
  75. data/spec/socket_spec_shared.rb +104 -0
  76. data/spec/spec_helper.rb +58 -0
  77. data/spec/struct_spec.rb +295 -0
  78. data/spec/types_spec.rb +116 -0
  79. data/spec/union_spec.rb +193 -0
  80. data/spec/unix_socket_spec.rb +108 -0
  81. metadata +247 -0
@@ -0,0 +1,375 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
21
+
22
+ shared_examples_for 'a binary protocol' do
23
+ before(:each) do
24
+ @trans = Thrift::MemoryBufferTransport.new
25
+ @prot = protocol_class.new(@trans)
26
+ end
27
+
28
+ it "should define the proper VERSION_1, VERSION_MASK AND TYPE_MASK" do
29
+ protocol_class.const_get(:VERSION_MASK).should == 0xffff0000
30
+ protocol_class.const_get(:VERSION_1).should == 0x80010000
31
+ protocol_class.const_get(:TYPE_MASK).should == 0x000000ff
32
+ end
33
+
34
+ it "should make strict_read readable" do
35
+ @prot.strict_read.should eql(true)
36
+ end
37
+
38
+ it "should make strict_write readable" do
39
+ @prot.strict_write.should eql(true)
40
+ end
41
+
42
+ it "should write the message header" do
43
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
44
+ @trans.read(@trans.available).should == [protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N")
45
+ end
46
+
47
+ it "should write the message header without version when writes are not strict" do
48
+ @prot = protocol_class.new(@trans, true, false) # no strict write
49
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
50
+ @trans.read(@trans.available).should == "\000\000\000\vtestMessage\001\000\000\000\021"
51
+ end
52
+
53
+ it "should write the message header with a version when writes are strict" do
54
+ @prot = protocol_class.new(@trans) # strict write
55
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
56
+ @trans.read(@trans.available).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
57
+ end
58
+
59
+
60
+ # message footer is a noop
61
+
62
+ it "should write the field header" do
63
+ @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3)
64
+ @trans.read(@trans.available).should == [Thrift::Types::DOUBLE, 3].pack("cn")
65
+ end
66
+
67
+ # field footer is a noop
68
+
69
+ it "should write the STOP field" do
70
+ @prot.write_field_stop
71
+ @trans.read(1).should == "\000"
72
+ end
73
+
74
+ it "should write the map header" do
75
+ @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17)
76
+ @trans.read(@trans.available).should == [Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN");
77
+ end
78
+
79
+ # map footer is a noop
80
+
81
+ it "should write the list header" do
82
+ @prot.write_list_begin(Thrift::Types::I16, 42)
83
+ @trans.read(@trans.available).should == [Thrift::Types::I16, 42].pack("cN")
84
+ end
85
+
86
+ # list footer is a noop
87
+
88
+ it "should write the set header" do
89
+ @prot.write_set_begin(Thrift::Types::I16, 42)
90
+ @trans.read(@trans.available).should == [Thrift::Types::I16, 42].pack("cN")
91
+ end
92
+
93
+ it "should write a bool" do
94
+ @prot.write_bool(true)
95
+ @prot.write_bool(false)
96
+ @trans.read(@trans.available).should == "\001\000"
97
+ end
98
+
99
+ it "should treat a nil bool as false" do
100
+ @prot.write_bool(nil)
101
+ @trans.read(1).should == "\000"
102
+ end
103
+
104
+ it "should write a byte" do
105
+ # byte is small enough, let's check -128..127
106
+ (-128..127).each do |i|
107
+ @prot.write_byte(i)
108
+ @trans.read(1).should == [i].pack('c')
109
+ end
110
+ # handing it numbers out of signed range should clip
111
+ @trans.rspec_verify
112
+ (128..255).each do |i|
113
+ @prot.write_byte(i)
114
+ @trans.read(1).should == [i].pack('c')
115
+ end
116
+ # and lastly, a Bignum is going to error out
117
+ lambda { @prot.write_byte(2**65) }.should raise_error(RangeError)
118
+ end
119
+
120
+ it "should error gracefully when trying to write a nil byte" do
121
+ lambda { @prot.write_byte(nil) }.should raise_error
122
+ end
123
+
124
+ it "should write an i16" do
125
+ # try a random scattering of values
126
+ # include the signed i16 minimum/maximum
127
+ [-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i|
128
+ @prot.write_i16(i)
129
+ end
130
+ # and try something out of signed range, it should clip
131
+ @prot.write_i16(2**15 + 5)
132
+
133
+ @trans.read(@trans.available).should == "\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005"
134
+
135
+ # a Bignum should error
136
+ # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError)
137
+ end
138
+
139
+ it "should error gracefully when trying to write a nil i16" do
140
+ lambda { @prot.write_i16(nil) }.should raise_error
141
+ end
142
+
143
+ it "should write an i32" do
144
+ # try a random scattering of values
145
+ # include the signed i32 minimum/maximum
146
+ [-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i|
147
+ @prot.write_i32(i)
148
+ end
149
+ # try something out of signed range, it should clip
150
+ @trans.read(@trans.available).should == "\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377"
151
+ [2 ** 31 + 5, 2 ** 65 + 5].each do |i|
152
+ lambda { @prot.write_i32(i) }.should raise_error(RangeError)
153
+ end
154
+ end
155
+
156
+ it "should error gracefully when trying to write a nil i32" do
157
+ lambda { @prot.write_i32(nil) }.should raise_error
158
+ end
159
+
160
+ it "should write an i64" do
161
+ # try a random scattering of values
162
+ # try the signed i64 minimum/maximum
163
+ [-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i|
164
+ @prot.write_i64(i)
165
+ end
166
+ # try something out of signed range, it should clip
167
+ @trans.read(@trans.available).should == ["\200\000\000\000\000\000\000\000",
168
+ "\377\377\364\303\035\244+]",
169
+ "\377\377\377\377\376\231:\341",
170
+ "\377\377\377\377\377\377\377\026",
171
+ "\000\000\000\000\000\000\000\000",
172
+ "\000\000\000\000\000\000\004\317",
173
+ "\000\000\000\000\000#\340\204",
174
+ "\000\000\000\002\340\311~\365",
175
+ "\177\377\377\377\377\377\377\377"].join("")
176
+ lambda { @prot.write_i64(2 ** 65 + 5) }.should raise_error(RangeError)
177
+ end
178
+
179
+ it "should error gracefully when trying to write a nil i64" do
180
+ lambda { @prot.write_i64(nil) }.should raise_error
181
+ end
182
+
183
+ it "should write a double" do
184
+ # try a random scattering of values, including min/max
185
+ values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
186
+ values.each do |f|
187
+ @prot.write_double(f)
188
+ @trans.read(@trans.available).should == [f].pack("G")
189
+ end
190
+ end
191
+
192
+ it "should error gracefully when trying to write a nil double" do
193
+ lambda { @prot.write_double(nil) }.should raise_error
194
+ end
195
+
196
+ it "should write a string" do
197
+ str = "hello world"
198
+ @prot.write_string(str)
199
+ @trans.read(@trans.available).should == [str.size].pack("N") + str
200
+ end
201
+
202
+ it "should error gracefully when trying to write a nil string" do
203
+ lambda { @prot.write_string(nil) }.should raise_error
204
+ end
205
+
206
+ it "should write the message header without version when writes are not strict" do
207
+ @prot = protocol_class.new(@trans, true, false) # no strict write
208
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
209
+ @trans.read(@trans.available).should == "\000\000\000\vtestMessage\001\000\000\000\021"
210
+ end
211
+
212
+ it "should write the message header with a version when writes are strict" do
213
+ @prot = protocol_class.new(@trans) # strict write
214
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
215
+ @trans.read(@trans.available).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
216
+ end
217
+
218
+ # message footer is a noop
219
+
220
+ it "should read a field header" do
221
+ @trans.write([Thrift::Types::STRING, 3].pack("cn"))
222
+ @prot.read_field_begin.should == [nil, Thrift::Types::STRING, 3]
223
+ end
224
+
225
+ # field footer is a noop
226
+
227
+ it "should read a stop field" do
228
+ @trans.write([Thrift::Types::STOP].pack("c"));
229
+ @prot.read_field_begin.should == [nil, Thrift::Types::STOP, 0]
230
+ end
231
+
232
+ it "should read a map header" do
233
+ @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN"))
234
+ @prot.read_map_begin.should == [Thrift::Types::DOUBLE, Thrift::Types::I64, 42]
235
+ end
236
+
237
+ # map footer is a noop
238
+
239
+ it "should read a list header" do
240
+ @trans.write([Thrift::Types::STRING, 17].pack("cN"))
241
+ @prot.read_list_begin.should == [Thrift::Types::STRING, 17]
242
+ end
243
+
244
+ # list footer is a noop
245
+
246
+ it "should read a set header" do
247
+ @trans.write([Thrift::Types::STRING, 17].pack("cN"))
248
+ @prot.read_set_begin.should == [Thrift::Types::STRING, 17]
249
+ end
250
+
251
+ # set footer is a noop
252
+
253
+ it "should read a bool" do
254
+ @trans.write("\001\000");
255
+ @prot.read_bool.should == true
256
+ @prot.read_bool.should == false
257
+ end
258
+
259
+ it "should read a byte" do
260
+ [-128, -57, -3, 0, 17, 24, 127].each do |i|
261
+ @trans.write([i].pack("c"))
262
+ @prot.read_byte.should == i
263
+ end
264
+ end
265
+
266
+ it "should read an i16" do
267
+ # try a scattering of values, including min/max
268
+ [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i|
269
+ @trans.write([i].pack("n"));
270
+ @prot.read_i16.should == i
271
+ end
272
+ end
273
+
274
+ it "should read an i32" do
275
+ # try a scattering of values, including min/max
276
+ [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i|
277
+ @trans.write([i].pack("N"))
278
+ @prot.read_i32.should == i
279
+ end
280
+ end
281
+
282
+ it "should read an i64" do
283
+ # try a scattering of values, including min/max
284
+ [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i|
285
+ @trans.write([i >> 32, i & 0xFFFFFFFF].pack("NN"))
286
+ @prot.read_i64.should == i
287
+ end
288
+ end
289
+
290
+ it "should read a double" do
291
+ # try a random scattering of values, including min/max
292
+ [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f|
293
+ @trans.write([f].pack("G"));
294
+ @prot.read_double.should == f
295
+ end
296
+ end
297
+
298
+ it "should read a string" do
299
+ str = "hello world"
300
+ @trans.write([str.size].pack("N") + str)
301
+ @prot.read_string.should == str
302
+ end
303
+
304
+ it "should perform a complete rpc with no args or return" do
305
+ srv_test(
306
+ proc {|client| client.send_voidMethod()},
307
+ proc {|client| client.recv_voidMethod.should == nil}
308
+ )
309
+ end
310
+
311
+ it "should perform a complete rpc with a primitive return type" do
312
+ srv_test(
313
+ proc {|client| client.send_primitiveMethod()},
314
+ proc {|client| client.recv_primitiveMethod.should == 1}
315
+ )
316
+ end
317
+
318
+ it "should perform a complete rpc with a struct return type" do
319
+ srv_test(
320
+ proc {|client| client.send_structMethod()},
321
+ proc {|client|
322
+ result = client.recv_structMethod
323
+ result.set_byte_map = nil
324
+ result.map_byte_map = nil
325
+ result.should == Fixtures::COMPACT_PROTOCOL_TEST_STRUCT
326
+ }
327
+ )
328
+ end
329
+
330
+ def get_socket_connection
331
+ server = Thrift::ServerSocket.new("localhost", 9090)
332
+ server.listen
333
+
334
+ clientside = Thrift::Socket.new("localhost", 9090)
335
+ clientside.open
336
+ serverside = server.accept
337
+ [clientside, serverside, server]
338
+ end
339
+
340
+ def srv_test(firstblock, secondblock)
341
+ clientside, serverside, server = get_socket_connection
342
+
343
+ clientproto = protocol_class.new(clientside)
344
+ serverproto = protocol_class.new(serverside)
345
+
346
+ processor = Srv::Processor.new(SrvHandler.new)
347
+
348
+ client = Srv::Client.new(clientproto, clientproto)
349
+
350
+ # first block
351
+ firstblock.call(client)
352
+
353
+ processor.process(serverproto, serverproto)
354
+
355
+ # second block
356
+ secondblock.call(client)
357
+ ensure
358
+ clientside.close
359
+ serverside.close
360
+ server.close
361
+ end
362
+
363
+ class SrvHandler
364
+ def voidMethod()
365
+ end
366
+
367
+ def primitiveMethod
368
+ 1
369
+ end
370
+
371
+ def structMethod
372
+ Fixtures::COMPACT_PROTOCOL_TEST_STRUCT
373
+ end
374
+ end
375
+ end
@@ -0,0 +1,100 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
21
+
22
+ class ThriftClientSpec < Spec::ExampleGroup
23
+ include Thrift
24
+
25
+ class ClientSpec
26
+ include Thrift::Client
27
+ end
28
+
29
+ before(:each) do
30
+ @prot = mock("MockProtocol")
31
+ @client = ClientSpec.new(@prot)
32
+ end
33
+
34
+ describe Client do
35
+ it "should re-use iprot for oprot if not otherwise specified" do
36
+ @client.instance_variable_get(:'@iprot').should eql(@prot)
37
+ @client.instance_variable_get(:'@oprot').should eql(@prot)
38
+ end
39
+
40
+ it "should send a test message" do
41
+ @prot.should_receive(:write_message_begin).with('testMessage', MessageTypes::CALL, 0)
42
+ mock_args = mock('#<TestMessage_args:mock>')
43
+ mock_args.should_receive(:foo=).with('foo')
44
+ mock_args.should_receive(:bar=).with(42)
45
+ mock_args.should_receive(:write).with(@prot)
46
+ @prot.should_receive(:write_message_end)
47
+ @prot.should_receive(:trans) do
48
+ mock('trans').tee do |trans|
49
+ trans.should_receive(:flush)
50
+ end
51
+ end
52
+ klass = stub("TestMessage_args", :new => mock_args)
53
+ @client.send_message('testMessage', klass, :foo => 'foo', :bar => 42)
54
+ end
55
+
56
+ it "should increment the sequence id when sending messages" do
57
+ pending "it seems sequence ids are completely ignored right now" do
58
+ @prot.should_receive(:write_message_begin).with('testMessage', MessageTypes::CALL, 0).ordered
59
+ @prot.should_receive(:write_message_begin).with('testMessage2', MessageTypes::CALL, 1).ordered
60
+ @prot.should_receive(:write_message_begin).with('testMessage3', MessageTypes::CALL, 2).ordered
61
+ @prot.stub!(:write_message_end)
62
+ @prot.stub!(:trans).and_return mock("trans").as_null_object
63
+ @client.send_message('testMessage', mock("args class").as_null_object)
64
+ @client.send_message('testMessage2', mock("args class").as_null_object)
65
+ @client.send_message('testMessage3', mock("args class").as_null_object)
66
+ end
67
+ end
68
+
69
+ it "should receive a test message" do
70
+ @prot.should_receive(:read_message_begin).and_return [nil, MessageTypes::CALL, 0]
71
+ @prot.should_receive(:read_message_end)
72
+ mock_klass = mock("#<MockClass:mock>")
73
+ mock_klass.should_receive(:read).with(@prot)
74
+ @client.receive_message(stub("MockClass", :new => mock_klass))
75
+ end
76
+
77
+ it "should handle received exceptions" do
78
+ @prot.should_receive(:read_message_begin).and_return [nil, MessageTypes::EXCEPTION, 0]
79
+ @prot.should_receive(:read_message_end)
80
+ ApplicationException.should_receive(:new).and_return do
81
+ StandardError.new.tee do |mock_exc|
82
+ mock_exc.should_receive(:read).with(@prot)
83
+ end
84
+ end
85
+ lambda { @client.receive_message(nil) }.should raise_error(StandardError)
86
+ end
87
+
88
+ it "should close the transport if an error occurs while sending a message" do
89
+ @prot.stub!(:write_message_begin)
90
+ @prot.should_not_receive(:write_message_end)
91
+ mock_args = mock("#<TestMessage_args:mock>")
92
+ mock_args.should_receive(:write).with(@prot).and_raise(StandardError)
93
+ trans = mock("MockTransport")
94
+ @prot.stub!(:trans).and_return(trans)
95
+ trans.should_receive(:close)
96
+ klass = mock("TestMessage_args", :new => mock_args)
97
+ lambda { @client.send_message("testMessage", klass) }.should raise_error(StandardError)
98
+ end
99
+ end
100
+ end