thrift 0.0.751142

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 (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