thrift 0.0.751142

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/CHANGELOG +2 -0
  2. data/COPYING +14 -0
  3. data/LICENSE +14 -0
  4. data/Makefile.am +15 -0
  5. data/Manifest +78 -0
  6. data/README +30 -0
  7. data/Rakefile +102 -0
  8. data/benchmark/Benchmark.thrift +5 -0
  9. data/benchmark/benchmark.rb +254 -0
  10. data/benchmark/client.rb +56 -0
  11. data/benchmark/gen-rb/BenchmarkService.rb +81 -0
  12. data/benchmark/gen-rb/Benchmark_constants.rb +11 -0
  13. data/benchmark/gen-rb/Benchmark_types.rb +10 -0
  14. data/benchmark/server.rb +64 -0
  15. data/benchmark/thin_server.rb +26 -0
  16. data/ext/binary_protocol_accelerated.c +463 -0
  17. data/ext/binary_protocol_accelerated.h +1 -0
  18. data/ext/constants.h +77 -0
  19. data/ext/extconf.rb +7 -0
  20. data/ext/memory_buffer.c +52 -0
  21. data/ext/memory_buffer.h +1 -0
  22. data/ext/protocol.c +166 -0
  23. data/ext/protocol.h +1 -0
  24. data/ext/struct.c +574 -0
  25. data/ext/struct.h +48 -0
  26. data/ext/thrift_native.c +173 -0
  27. data/lib/thrift/client.rb +44 -0
  28. data/lib/thrift/deprecation.rb +155 -0
  29. data/lib/thrift/exceptions.rb +65 -0
  30. data/lib/thrift/processor.rb +39 -0
  31. data/lib/thrift/protocol/binaryprotocol.rb +213 -0
  32. data/lib/thrift/protocol/binaryprotocolaccelerated.rb +19 -0
  33. data/lib/thrift/protocol/tbinaryprotocol.rb +2 -0
  34. data/lib/thrift/protocol/tprotocol.rb +2 -0
  35. data/lib/thrift/protocol.rb +270 -0
  36. data/lib/thrift/serializer.rb +27 -0
  37. data/lib/thrift/server/httpserver.rb +44 -0
  38. data/lib/thrift/server/nonblockingserver.rb +278 -0
  39. data/lib/thrift/server/thttpserver.rb +2 -0
  40. data/lib/thrift/server/tserver.rb +2 -0
  41. data/lib/thrift/server.rb +135 -0
  42. data/lib/thrift/struct.rb +272 -0
  43. data/lib/thrift/thrift.rb +14 -0
  44. data/lib/thrift/transport/httpclient.rb +29 -0
  45. data/lib/thrift/transport/socket.rb +167 -0
  46. data/lib/thrift/transport/thttpclient.rb +2 -0
  47. data/lib/thrift/transport/tsocket.rb +2 -0
  48. data/lib/thrift/transport/ttransport.rb +2 -0
  49. data/lib/thrift/transport/unixsocket.rb +58 -0
  50. data/lib/thrift/transport.rb +319 -0
  51. data/lib/thrift/types.rb +83 -0
  52. data/lib/thrift.rb +28 -0
  53. data/setup.rb +1585 -0
  54. data/spec/ThriftSpec.thrift +46 -0
  55. data/spec/backwards_compatibility_spec.rb +136 -0
  56. data/spec/binaryprotocol_spec.rb +45 -0
  57. data/spec/binaryprotocol_spec_shared.rb +274 -0
  58. data/spec/binaryprotocolaccelerated_spec.rb +101 -0
  59. data/spec/client_spec.rb +81 -0
  60. data/spec/deprecation_spec.rb +443 -0
  61. data/spec/exception_spec.rb +123 -0
  62. data/spec/gen-rb/NonblockingService.rb +268 -0
  63. data/spec/gen-rb/ThriftSpec_constants.rb +11 -0
  64. data/spec/gen-rb/ThriftSpec_types.rb +134 -0
  65. data/spec/httpclient_spec.rb +31 -0
  66. data/spec/httpserver_spec.rb +98 -0
  67. data/spec/nonblockingserver_spec.rb +245 -0
  68. data/spec/processor_spec.rb +64 -0
  69. data/spec/protocol_spec.rb +142 -0
  70. data/spec/serializer_spec.rb +52 -0
  71. data/spec/server_spec.rb +141 -0
  72. data/spec/socket_spec.rb +97 -0
  73. data/spec/socket_spec_shared.rb +85 -0
  74. data/spec/spec_helper.rb +35 -0
  75. data/spec/struct_spec.rb +244 -0
  76. data/spec/transport_spec.rb +359 -0
  77. data/spec/types_spec.rb +98 -0
  78. data/spec/unixsocket_spec.rb +90 -0
  79. data/thrift.gemspec +33 -0
  80. data.tar.gz.sig +0 -0
  81. metadata +200 -0
  82. metadata.gz.sig +0 -0
@@ -0,0 +1,46 @@
1
+ namespace rb SpecNamespace
2
+
3
+ struct Hello {
4
+ 1: string greeting = "hello world"
5
+ }
6
+
7
+ struct Foo {
8
+ 1: i32 simple = 53,
9
+ 2: string words = "words",
10
+ 3: Hello hello = {'greeting' : "hello, world!"},
11
+ 4: list<i32> ints = [1, 2, 2, 3],
12
+ 5: map<i32, map<string, double>> complex,
13
+ 6: set<i16> shorts = [5, 17, 239],
14
+ 7: optional string opt_string
15
+ }
16
+
17
+ struct BoolStruct {
18
+ 1: bool yesno = 1
19
+ }
20
+
21
+ struct SimpleList {
22
+ 1: list<bool> bools,
23
+ 2: list<byte> bytes,
24
+ 3: list<i16> i16s,
25
+ 4: list<i32> i32s,
26
+ 5: list<i64> i64s,
27
+ 6: list<double> doubles,
28
+ 7: list<string> strings,
29
+ 8: list<map<i16, i16>> maps,
30
+ 9: list<list<i16>> lists,
31
+ 10: list<set<i16>> sets,
32
+ 11: list<Hello> hellos
33
+ }
34
+
35
+ exception Xception {
36
+ 1: string message,
37
+ 2: i32 code = 1
38
+ }
39
+
40
+ service NonblockingService {
41
+ Hello greeting(1:bool english)
42
+ bool block()
43
+ async void unblock(1:i32 n)
44
+ async void shutdown()
45
+ void sleep(1:double seconds)
46
+ }
@@ -0,0 +1,136 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'thrift/protocol/binaryprotocol'
3
+ require 'thrift/server/httpserver'
4
+ require 'thrift/transport/httpclient'
5
+
6
+ context "Backwards compatibility" do
7
+ specify "old class names should map to new classes" do
8
+ Thrift::DeprecationProxy.reset_deprecation_warnings
9
+ # use an Array because a Hash will call #hash and trigger deprecation warnings
10
+ klasses = [
11
+ [:module, :ThriftClient, Thrift::Client],
12
+ [:class, :TException, Thrift::Exception],
13
+ [:class, :TApplicationException, Thrift::ApplicationException],
14
+ [:module, :TProcessor, Thrift::Processor],
15
+ [:class, :TProtocolException, Thrift::ProtocolException],
16
+ [:class, :TProtocol, Thrift::Protocol],
17
+ [:class, :TProtocolFactory, Thrift::ProtocolFactory],
18
+ [:class, :TBinaryProtocol, Thrift::BinaryProtocol],
19
+ [:class, :TBinaryProtocolFactory, Thrift::BinaryProtocolFactory],
20
+ [:class, :TSimpleMongrelHTTPServer, Thrift::SimpleMongrelHTTPServer],
21
+ [:class, :TServer, Thrift::Server],
22
+ [:class, :TSimpleServer, Thrift::SimpleServer],
23
+ [:class, :TThreadedServer, Thrift::ThreadedServer],
24
+ [:class, :TThreadPoolServer, Thrift::ThreadPoolServer],
25
+ [:module, :ThriftStruct, Thrift::Struct],
26
+ [:class, :THttpClient, Thrift::HTTPClient],
27
+ [:class, :TSocket, Thrift::Socket],
28
+ [:class, :TServerSocket, Thrift::ServerSocket],
29
+ [:class, :TTransportException, Thrift::TransportException],
30
+ [:class, :TTransport, Thrift::Transport],
31
+ [:class, :TServerTransport, Thrift::ServerTransport],
32
+ [:class, :TTransportFactory, Thrift::TransportFactory],
33
+ [:class, :TBufferedTransport, Thrift::BufferedTransport],
34
+ [:class, :TBufferedTransportFactory, Thrift::BufferedTransportFactory],
35
+ [:class, :TFramedTransport, Thrift::FramedTransport],
36
+ [:class, :TFramedTransportFactory, Thrift::FramedTransportFactory],
37
+ [:class, :TMemoryBuffer, Thrift::MemoryBuffer],
38
+ [:class, :TIOStreamTransport, Thrift::IOStreamTransport],
39
+ [:module, :TType, Thrift::Types],
40
+ [:module, :TMessageType, Thrift::MessageTypes]
41
+ ]
42
+ klasses.each do |(type, oldname, newklass)|
43
+ oldklass = Object.const_get(oldname)
44
+ STDERR.should_receive(:puts).with("Warning: #{type} #{oldname} is deprecated").ordered
45
+ STDERR.should_receive(:puts).with(" from #{__FILE__}:#{__LINE__+1}").ordered
46
+ oldklass.should eql(newklass)
47
+ STDERR.rspec_verify
48
+ STDERR.rspec_reset
49
+ end
50
+ end
51
+
52
+ specify "old method names should map to new method names" do
53
+ mapping = {
54
+ Thrift::Protocol => {
55
+ :writeMessageBegin => :write_message_begin,
56
+ :writeMessageEnd => :write_message_end,
57
+ :writeStructBegin => :write_struct_begin,
58
+ :writeStructEnd => :write_struct_end,
59
+ :writeFieldBegin => :write_field_begin,
60
+ :writeFieldEnd => :write_field_end,
61
+ :writeFieldStop => :write_field_stop,
62
+ :writeMapBegin => :write_map_begin,
63
+ :writeMapEnd => :write_map_end,
64
+ :writeListBegin => :write_list_begin,
65
+ :writeListEnd => :write_list_end,
66
+ :writeSetBegin => :write_set_begin,
67
+ :writeSetEnd => :write_set_end,
68
+ :writeBool => :write_bool,
69
+ :writeByte => :write_byte,
70
+ :writeI16 => :write_i16,
71
+ :writeI32 => :write_i32,
72
+ :writeI64 => :write_i64,
73
+ :writeDouble => :write_double,
74
+ :writeString => :write_string,
75
+ :readMessageBegin => :read_message_begin,
76
+ :readMessageEnd => :read_message_end,
77
+ :readStructBegin => :read_struct_begin,
78
+ :readStructEnd => :read_struct_end,
79
+ :readFieldBegin => :read_field_begin,
80
+ :readFieldEnd => :read_field_end,
81
+ :readMapBegin => :read_map_begin,
82
+ :readMapEnd => :read_map_end,
83
+ :readListBegin => :read_list_begin,
84
+ :readListEnd => :read_list_end,
85
+ :readSetBegin => :read_set_begin,
86
+ :readSetEnd => :read_set_end,
87
+ :readBool => :read_bool,
88
+ :readByte => :read_byte,
89
+ :readI16 => :read_i16,
90
+ :readI32 => :read_i32,
91
+ :readI64 => :read_i64,
92
+ :readDouble => :read_double,
93
+ :readString => :read_string
94
+ },
95
+ Thrift::ProtocolFactory => {
96
+ :getProtocol => :get_protocol
97
+ },
98
+ Thrift::Transport => {
99
+ :isOpen => :open?,
100
+ :is_open? => :open?,
101
+ :readAll => :read_all
102
+ },
103
+ Thrift::TransportFactory => {
104
+ :getTransport => :get_transport
105
+ }
106
+ }
107
+ STDERR.stub!(:puts) # stub the deprecation warnings
108
+ mapping.each_pair do |klass, methods|
109
+ # save these so they can be used after being mocked up
110
+ defn_method = klass.method(:define_method)
111
+ inst_method = klass.method(:instance_method)
112
+ methods.each_pair do |oldmeth, newmeth|
113
+ # ensure that calling the old method will call the new method
114
+ # and then redefine the old method to be the new one
115
+ klass.should be_method_defined(oldmeth)
116
+ klass.should be_method_defined(newmeth)
117
+ orig_method = inst_method.call(:initialize)
118
+ defn_method.call(:initialize, proc {} ) # stub out initialize
119
+ begin
120
+ mockmeth = mock("UnboundMethod: #{newmeth}")
121
+ mockmeth.should_receive(:bind).and_return do
122
+ mock("Method: #{newmeth}").tee do |meth|
123
+ meth.should_receive(:call)
124
+ end
125
+ end
126
+ klass.should_receive(:instance_method).with(newmeth).twice.and_return(mockmeth)
127
+ klass.should_receive(:define_method).with(oldmeth, mockmeth)
128
+ klass.new.send oldmeth
129
+ klass.rspec_verify
130
+ ensure
131
+ defn_method.call(:initialize, orig_method)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'thrift/protocol/binaryprotocol'
3
+ require File.dirname(__FILE__) + '/binaryprotocol_spec_shared'
4
+
5
+ class ThriftBinaryProtocolSpec < Spec::ExampleGroup
6
+ include Thrift
7
+
8
+ describe BinaryProtocol do
9
+ it_should_behave_like 'a binary protocol'
10
+
11
+ def protocol_class
12
+ BinaryProtocol
13
+ end
14
+
15
+ it "should read a message header" do
16
+ @trans.should_receive(:read_all).exactly(2).times.and_return(
17
+ [protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::REPLY].pack('N'),
18
+ [42].pack('N')
19
+ )
20
+ @prot.should_receive(:read_string).and_return('testMessage')
21
+ @prot.read_message_begin.should == ['testMessage', Thrift::MessageTypes::REPLY, 42]
22
+ end
23
+
24
+ it "should raise an exception if the message header has the wrong version" do
25
+ @prot.should_receive(:read_i32).and_return(-1)
26
+ lambda { @prot.read_message_begin }.should raise_error(Thrift::ProtocolException, 'Missing version identifier') do |e|
27
+ e.type == Thrift::ProtocolException::BAD_VERSION
28
+ end
29
+ end
30
+
31
+ it "should raise an exception if the message header does not exist and strict_read is enabled" do
32
+ @prot.should_receive(:read_i32).and_return(42)
33
+ @prot.should_receive(:strict_read).and_return(true)
34
+ lambda { @prot.read_message_begin }.should raise_error(Thrift::ProtocolException, 'No version identifier, old protocol client?') do |e|
35
+ e.type == Thrift::ProtocolException::BAD_VERSION
36
+ end
37
+ end
38
+ end
39
+
40
+ describe BinaryProtocolFactory do
41
+ it "should create a BinaryProtocol" do
42
+ BinaryProtocolFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(BinaryProtocol)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,274 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ shared_examples_for 'a binary protocol' do
4
+ before(:each) do
5
+ @trans = Thrift::MemoryBuffer.new
6
+ @prot = protocol_class.new(@trans)
7
+ end
8
+
9
+ it "should define the proper VERSION_1, VERSION_MASK AND TYPE_MASK" do
10
+ protocol_class.const_get(:VERSION_MASK).should == 0xffff0000
11
+ protocol_class.const_get(:VERSION_1).should == 0x80010000
12
+ protocol_class.const_get(:TYPE_MASK).should == 0x000000ff
13
+ end
14
+
15
+ it "should make strict_read readable" do
16
+ @prot.strict_read.should eql(true)
17
+ end
18
+
19
+ it "should make strict_write readable" do
20
+ @prot.strict_write.should eql(true)
21
+ end
22
+
23
+ it "should write the message header" do
24
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
25
+ @trans.read(1000).should == [protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N")
26
+ end
27
+
28
+ it "should write the message header without version when writes are not strict" do
29
+ @prot = protocol_class.new(@trans, true, false) # no strict write
30
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
31
+ @trans.read(1000).should == "\000\000\000\vtestMessage\001\000\000\000\021"
32
+ end
33
+
34
+ it "should write the message header with a version when writes are strict" do
35
+ @prot = protocol_class.new(@trans) # strict write
36
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
37
+ @trans.read(1000).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
38
+ end
39
+
40
+
41
+ # message footer is a noop
42
+
43
+ it "should write the field header" do
44
+ @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3)
45
+ @trans.read(1000).should == [Thrift::Types::DOUBLE, 3].pack("cn")
46
+ end
47
+
48
+ # field footer is a noop
49
+
50
+ it "should write the STOP field" do
51
+ @prot.write_field_stop
52
+ @trans.read(1).should == "\000"
53
+ end
54
+
55
+ it "should write the map header" do
56
+ @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17)
57
+ @trans.read(1000).should == [Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN");
58
+ end
59
+
60
+ # map footer is a noop
61
+
62
+ it "should write the list header" do
63
+ @prot.write_list_begin(Thrift::Types::I16, 42)
64
+ @trans.read(1000).should == [Thrift::Types::I16, 42].pack("cN")
65
+ end
66
+
67
+ # list footer is a noop
68
+
69
+ it "should write the set header" do
70
+ @prot.write_set_begin(Thrift::Types::I16, 42)
71
+ @trans.read(1000).should == [Thrift::Types::I16, 42].pack("cN")
72
+ end
73
+
74
+ it "should write a bool" do
75
+ @prot.write_bool(true)
76
+ @prot.write_bool(false)
77
+ @trans.read(1000).should == "\001\000"
78
+ end
79
+
80
+ it "should treat a nil bool as false" do
81
+ @prot.write_bool(nil)
82
+ @trans.read(1).should == "\000"
83
+ end
84
+
85
+ it "should write a byte" do
86
+ # byte is small enough, let's check -128..127
87
+ (-128..127).each do |i|
88
+ @prot.write_byte(i)
89
+ @trans.read(1).should == [i].pack('c')
90
+ end
91
+ (-128..127).each do |i|
92
+ end
93
+ # handing it numbers out of signed range should clip
94
+ @trans.rspec_verify
95
+ (128..255).each do |i|
96
+ @prot.write_byte(i)
97
+ @trans.read(1).should == [i].pack('c')
98
+ end
99
+ # and lastly, a Bignum is going to error out
100
+ lambda { @prot.write_byte(2**65) }.should raise_error(RangeError)
101
+ end
102
+
103
+ it "should error gracefully when trying to write a nil byte" do
104
+ lambda { @prot.write_byte(nil) }.should raise_error
105
+ end
106
+
107
+ it "should write an i16" do
108
+ # try a random scattering of values
109
+ # include the signed i16 minimum/maximum
110
+ [-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i|
111
+ @prot.write_i16(i)
112
+ end
113
+ # and try something out of signed range, it should clip
114
+ @prot.write_i16(2**15 + 5)
115
+
116
+ @trans.read(1000).should == "\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005"
117
+
118
+ # a Bignum should error
119
+ # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError)
120
+ end
121
+
122
+ it "should error gracefully when trying to write a nil i16" do
123
+ lambda { @prot.write_i16(nil) }.should raise_error
124
+ end
125
+
126
+ it "should write an i32" do
127
+ # try a random scattering of values
128
+ # include the signed i32 minimum/maximum
129
+ [-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i|
130
+ @prot.write_i32(i)
131
+ end
132
+ # try something out of signed range, it should clip
133
+ @trans.read(1000).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"
134
+ [2 ** 31 + 5, 2 ** 65 + 5].each do |i|
135
+ lambda { @prot.write_i32(i) }.should raise_error(RangeError)
136
+ end
137
+ end
138
+
139
+ it "should error gracefully when trying to write a nil i32" do
140
+ lambda { @prot.write_i32(nil) }.should raise_error
141
+ end
142
+
143
+ it "should write an i64" do
144
+ # try a random scattering of values
145
+ # try the signed i64 minimum/maximum
146
+ [-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i|
147
+ @prot.write_i64(i)
148
+ end
149
+ # try something out of signed range, it should clip
150
+ @trans.read(1000).should == ["\200\000\000\000\000\000\000\000",
151
+ "\377\377\364\303\035\244+]",
152
+ "\377\377\377\377\376\231:\341",
153
+ "\377\377\377\377\377\377\377\026",
154
+ "\000\000\000\000\000\000\000\000",
155
+ "\000\000\000\000\000\000\004\317",
156
+ "\000\000\000\000\000#\340\204",
157
+ "\000\000\000\002\340\311~\365",
158
+ "\177\377\377\377\377\377\377\377"].join("")
159
+ lambda { @prot.write_i64(2 ** 65 + 5) }.should raise_error(RangeError)
160
+ end
161
+
162
+ it "should error gracefully when trying to write a nil i64" do
163
+ lambda { @prot.write_i64(nil) }.should raise_error
164
+ end
165
+
166
+ it "should write a double" do
167
+ # try a random scattering of values, including min/max
168
+ values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
169
+ values.each do |f|
170
+ @prot.write_double(f)
171
+ @trans.read(1000).should == [f].pack("G")
172
+ end
173
+ end
174
+
175
+ it "should error gracefully when trying to write a nil double" do
176
+ lambda { @prot.write_double(nil) }.should raise_error
177
+ end
178
+
179
+ it "should write a string" do
180
+ str = "hello world"
181
+ @prot.write_string(str)
182
+ @trans.read(1000).should == [str.size].pack("N") + str
183
+ end
184
+
185
+ it "should error gracefully when trying to write a nil string" do
186
+ lambda { @prot.write_string(nil) }.should raise_error
187
+ end
188
+
189
+ # message footer is a noop
190
+
191
+ it "should read a field header" do
192
+ @trans.write([Thrift::Types::STRING, 3].pack("cn"))
193
+ @prot.read_field_begin.should == [nil, Thrift::Types::STRING, 3]
194
+ end
195
+
196
+ # field footer is a noop
197
+
198
+ it "should read a stop field" do
199
+ @trans.write([Thrift::Types::STOP].pack("c"));
200
+ @prot.read_field_begin.should == [nil, Thrift::Types::STOP, 0]
201
+ end
202
+
203
+ it "should read a map header" do
204
+ @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN"))
205
+ @prot.read_map_begin.should == [Thrift::Types::DOUBLE, Thrift::Types::I64, 42]
206
+ end
207
+
208
+ # map footer is a noop
209
+
210
+ it "should read a list header" do
211
+ @trans.write([Thrift::Types::STRING, 17].pack("cN"))
212
+ @prot.read_list_begin.should == [Thrift::Types::STRING, 17]
213
+ end
214
+
215
+ # list footer is a noop
216
+
217
+ it "should read a set header" do
218
+ @trans.write([Thrift::Types::STRING, 17].pack("cN"))
219
+ @prot.read_set_begin.should == [Thrift::Types::STRING, 17]
220
+ end
221
+
222
+ # set footer is a noop
223
+
224
+ it "should read a bool" do
225
+ @trans.write("\001\000");
226
+ @prot.read_bool.should == true
227
+ @prot.read_bool.should == false
228
+ end
229
+
230
+ it "should read a byte" do
231
+ [-128, -57, -3, 0, 17, 24, 127].each do |i|
232
+ @trans.write([i].pack("c"))
233
+ @prot.read_byte.should == i
234
+ end
235
+ end
236
+
237
+ it "should read an i16" do
238
+ # try a scattering of values, including min/max
239
+ [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i|
240
+ @trans.write([i].pack("n"));
241
+ @prot.read_i16.should == i
242
+ end
243
+ end
244
+
245
+ it "should read an i32" do
246
+ # try a scattering of values, including min/max
247
+ [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i|
248
+ @trans.write([i].pack("N"))
249
+ @prot.read_i32.should == i
250
+ end
251
+ end
252
+
253
+ it "should read an i64" do
254
+ # try a scattering of values, including min/max
255
+ [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i|
256
+ @trans.write([i >> 32, i & 0xFFFFFFFF].pack("NN"))
257
+ @prot.read_i64.should == i
258
+ end
259
+ end
260
+
261
+ it "should read a double" do
262
+ # try a random scattering of values, including min/max
263
+ [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f|
264
+ @trans.write([f].pack("G"));
265
+ @prot.read_double.should == f
266
+ end
267
+ end
268
+
269
+ it "should read a string" do
270
+ str = "hello world"
271
+ @trans.write([str.size].pack("N") + str)
272
+ @prot.read_string.should == str
273
+ end
274
+ end
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'thrift/protocol/binaryprotocolaccelerated'
3
+ require File.dirname(__FILE__) + '/binaryprotocol_spec_shared'
4
+ require File.dirname(__FILE__) + '/gen-rb/ThriftSpec_types'
5
+
6
+ class ThriftBinaryProtocolAcceleratedSpec < Spec::ExampleGroup
7
+ include Thrift
8
+
9
+ describe Thrift::BinaryProtocolAccelerated do
10
+ # since BinaryProtocolAccelerated should be directly equivalent to
11
+ # BinaryProtocol, we don't need any custom specs!
12
+ it_should_behave_like 'a binary protocol'
13
+
14
+ def protocol_class
15
+ BinaryProtocolAccelerated
16
+ end
17
+
18
+ # before(:each) do
19
+ # @buffer = ""
20
+ # @trans.stub!(:borrow).and_return { @buffer }
21
+ # @trans.stub!(:consume!).and_return do |*args|
22
+ # n = args.first || 0
23
+ # @buffer.slice!(0,n)
24
+ # end
25
+ # end
26
+ #
27
+ #
28
+ # it "should raise an exception if the message header has the wrong version" do
29
+ # @buffer = "\000\000\000\v"
30
+ # # @prot.should_receive(:read_i32).and_return(42)
31
+ # lambda { @prot.read_message_begin }.should raise_error(Thrift::ProtocolException, 'Missing version identifier') do |e|
32
+ # e.type == Thrift::ProtocolException::BAD_VERSION
33
+ # end
34
+ # end
35
+ #
36
+ # it "should encode a string with null bytes in it" do
37
+ # foo = SpecNamespace::Hello.new(:greeting => "Hello\000World!")
38
+ # @prot.encode_binary(foo).should == "\v\000\001\000\000\000\fHello\000World!\000"
39
+ # end
40
+ #
41
+ # it "should decode a string with null bytes in it" do
42
+ # trans = Thrift::MemoryBuffer.new("\v\000\001\000\000\000\fHello\000World!\000")
43
+ # @prot.decode_binary(SpecNamespace::Hello.new, trans).should == SpecNamespace::Hello.new(:greeting => "Hello\000World!")
44
+ # end
45
+ #
46
+ # it "should error when encoding a struct with a nil value in a list" do
47
+ # Thrift.type_checking = false
48
+ # sl = SpecNamespace::SimpleList
49
+ # hello = SpecNamespace::Hello
50
+ # # nil counts as false for bools
51
+ # # lambda { @prot.encode_binary(sl.new(:bools => [true, false, nil, false])) }.should raise_error
52
+ # lambda { @prot.encode_binary(sl.new(:bytes => [1, 2, nil, 3])) }.should raise_error
53
+ # lambda { @prot.encode_binary(sl.new(:i16s => [1, 2, nil, 3])) }.should raise_error
54
+ # lambda { @prot.encode_binary(sl.new(:i32s => [1, 2, nil, 3])) }.should raise_error
55
+ # lambda { @prot.encode_binary(sl.new(:i64s => [1, 2, nil, 3])) }.should raise_error
56
+ # lambda { @prot.encode_binary(sl.new(:doubles => [1.0, 2.0, nil, 3.0])) }.should raise_error
57
+ # lambda { @prot.encode_binary(sl.new(:strings => ["one", "two", nil, "three"])) }.should raise_error
58
+ # lambda { @prot.encode_binary(sl.new(:lists => [[1, 2], nil, [3, 4]])) }.should raise_error
59
+ # lambda { @prot.encode_binary(sl.new(:maps => [{1 => 2}, nil, {3 => 4}])) }.should raise_error
60
+ # lambda { @prot.encode_binary(sl.new(:sets => [Set.new([1, 2]), nil, Set.new([3, 4])])) }.should raise_error
61
+ # lambda { @prot.encode_binary(sl.new(:structs => [hello.new, nil, hello.new(:greeting => "hi")])) }.should raise_error
62
+ # end
63
+ #
64
+ # it "should error when encoding a non-nil, non-correctly-typed value in a list" do
65
+ # Thrift.type_checking = false
66
+ # sl = SpecNamespace::SimpleList
67
+ # hello = SpecNamespace::Hello
68
+ # # bool should accept any value
69
+ # # lambda { @prot.encode_binary(sl.new(:bools => [true, false, 3])) }.should raise_error
70
+ # lambda { @prot.encode_binary(sl.new(:bytes => [1, 2, "3", 5])) }.should raise_error
71
+ # lambda { @prot.encode_binary(sl.new(:i16s => ["one", 2, 3])) }.should raise_error
72
+ # lambda { @prot.encode_binary(sl.new(:i32s => [[1,2], 3, 4])) }.should raise_error
73
+ # lambda { @prot.encode_binary(sl.new(:i64s => [{1 => 2}, 3, 4])) }.should raise_error
74
+ # lambda { @prot.encode_binary(sl.new(:doubles => ["one", 2.3, 3.4])) }.should raise_error
75
+ # lambda { @prot.encode_binary(sl.new(:strings => ["one", "two", 3, 4])) }.should raise_error
76
+ # lambda { @prot.encode_binary(sl.new(:lists => [{1 => 2}, [3, 4]])) }.should raise_error
77
+ # lambda { @prot.encode_binary(sl.new(:maps => [{1 => 2}, [3, 4]])) }.should raise_error
78
+ # lambda { @prot.encode_binary(sl.new(:sets => [Set.new([1, 2]), 3, 4])) }.should raise_error
79
+ # lambda { @prot.encode_binary(sl.new(:structs => [3, "four"])) }.should raise_error
80
+ # end
81
+ #
82
+ # it "should error when encoding an improper object where a container is expected" do
83
+ # Thrift.type_checking = false
84
+ # sl = SpecNamespace::SimpleList
85
+ # lambda { @prot.encode_binary(sl.new(:strings => {"one" => "two", nil => "three"})) }.should raise_error
86
+ # lambda { @prot.encode_binary(sl.new(:maps => [[1, 2]])) }.should raise_error
87
+ # end
88
+ #
89
+ # it "should accept arrays and hashes as sets" do
90
+ # Thrift.type_checking = false
91
+ # sl = SpecNamespace::SimpleList
92
+ # lambda { @prot.encode_binary(sl.new(:sets => [[1, 2], {3 => true, 4 => true}])) }.should_not raise_error
93
+ # end
94
+ end
95
+
96
+ describe BinaryProtocolAcceleratedFactory do
97
+ it "should create a BinaryProtocolAccelerated" do
98
+ BinaryProtocolAcceleratedFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(BinaryProtocolAccelerated)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,81 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class ThriftClientSpec < Spec::ExampleGroup
4
+ include Thrift
5
+
6
+ class ClientSpec
7
+ include Thrift::Client
8
+ end
9
+
10
+ before(:each) do
11
+ @prot = mock("MockProtocol")
12
+ @client = ClientSpec.new(@prot)
13
+ end
14
+
15
+ describe Client do
16
+ it "should re-use iprot for oprot if not otherwise specified" do
17
+ @client.instance_variable_get(:'@iprot').should eql(@prot)
18
+ @client.instance_variable_get(:'@oprot').should eql(@prot)
19
+ end
20
+
21
+ it "should send a test message" do
22
+ @prot.should_receive(:write_message_begin).with('testMessage', MessageTypes::CALL, 0)
23
+ mock_args = mock('#<TestMessage_args:mock>')
24
+ mock_args.should_receive(:foo=).with('foo')
25
+ mock_args.should_receive(:bar=).with(42)
26
+ mock_args.should_receive(:write).with(@prot)
27
+ @prot.should_receive(:write_message_end)
28
+ @prot.should_receive(:trans) do
29
+ mock('trans').tee do |trans|
30
+ trans.should_receive(:flush)
31
+ end
32
+ end
33
+ klass = stub("TestMessage_args", :new => mock_args)
34
+ @client.send_message('testMessage', klass, :foo => 'foo', :bar => 42)
35
+ end
36
+
37
+ it "should increment the sequence id when sending messages" do
38
+ pending "it seems sequence ids are completely ignored right now" do
39
+ @prot.should_receive(:write_message_begin).with('testMessage', MessageTypes::CALL, 0).ordered
40
+ @prot.should_receive(:write_message_begin).with('testMessage2', MessageTypes::CALL, 1).ordered
41
+ @prot.should_receive(:write_message_begin).with('testMessage3', MessageTypes::CALL, 2).ordered
42
+ @prot.stub!(:write_message_end)
43
+ @prot.stub!(:trans).and_return stub_everything("trans")
44
+ @client.send_message('testMessage', stub_everything("args class"))
45
+ @client.send_message('testMessage2', stub_everything("args class"))
46
+ @client.send_message('testMessage3', stub_everything("args class"))
47
+ end
48
+ end
49
+
50
+ it "should receive a test message" do
51
+ @prot.should_receive(:read_message_begin).and_return [nil, MessageTypes::CALL, 0]
52
+ @prot.should_receive(:read_message_end)
53
+ mock_klass = mock("#<MockClass:mock>")
54
+ mock_klass.should_receive(:read).with(@prot)
55
+ @client.receive_message(stub("MockClass", :new => mock_klass))
56
+ end
57
+
58
+ it "should handle received exceptions" do
59
+ @prot.should_receive(:read_message_begin).and_return [nil, MessageTypes::EXCEPTION, 0]
60
+ @prot.should_receive(:read_message_end)
61
+ ApplicationException.should_receive(:new).and_return do
62
+ StandardError.new.tee do |mock_exc|
63
+ mock_exc.should_receive(:read).with(@prot)
64
+ end
65
+ end
66
+ lambda { @client.receive_message(nil) }.should raise_error(StandardError)
67
+ end
68
+
69
+ it "should close the transport if an error occurs while sending a message" do
70
+ @prot.stub!(:write_message_begin)
71
+ @prot.should_not_receive(:write_message_end)
72
+ mock_args = mock("#<TestMessage_args:mock>")
73
+ mock_args.should_receive(:write).with(@prot).and_raise(StandardError)
74
+ trans = mock("MockTransport")
75
+ @prot.stub!(:trans).and_return(trans)
76
+ trans.should_receive(:close)
77
+ klass = mock("TestMessage_args", :new => mock_args)
78
+ lambda { @client.send_message("testMessage", klass) }.should raise_error(StandardError)
79
+ end
80
+ end
81
+ end