tiny_thrift 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -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 +460 -0
  9. data/ext/binary_protocol_accelerated.h +20 -0
  10. data/ext/bytes.c +36 -0
  11. data/ext/bytes.h +31 -0
  12. data/ext/compact_protocol.c +635 -0
  13. data/ext/compact_protocol.h +20 -0
  14. data/ext/constants.h +96 -0
  15. data/ext/extconf.rb +32 -0
  16. data/ext/macros.h +41 -0
  17. data/ext/memory_buffer.c +134 -0
  18. data/ext/memory_buffer.h +20 -0
  19. data/ext/protocol.c +0 -0
  20. data/ext/protocol.h +0 -0
  21. data/ext/strlcpy.c +41 -0
  22. data/ext/strlcpy.h +34 -0
  23. data/ext/struct.c +688 -0
  24. data/ext/struct.h +25 -0
  25. data/ext/thrift_native.c +195 -0
  26. data/lib/thrift.rb +66 -0
  27. data/lib/thrift/bytes.rb +131 -0
  28. data/lib/thrift/client.rb +62 -0
  29. data/lib/thrift/core_ext.rb +23 -0
  30. data/lib/thrift/core_ext/fixnum.rb +29 -0
  31. data/lib/thrift/exceptions.rb +87 -0
  32. data/lib/thrift/processor.rb +57 -0
  33. data/lib/thrift/protocol/base_protocol.rb +377 -0
  34. data/lib/thrift/protocol/binary_protocol.rb +237 -0
  35. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  36. data/lib/thrift/protocol/compact_protocol.rb +434 -0
  37. data/lib/thrift/protocol/json_protocol.rb +769 -0
  38. data/lib/thrift/serializer/deserializer.rb +33 -0
  39. data/lib/thrift/serializer/serializer.rb +34 -0
  40. data/lib/thrift/server/base_server.rb +31 -0
  41. data/lib/thrift/server/mongrel_http_server.rb +60 -0
  42. data/lib/thrift/server/nonblocking_server.rb +305 -0
  43. data/lib/thrift/server/simple_server.rb +43 -0
  44. data/lib/thrift/server/thin_http_server.rb +91 -0
  45. data/lib/thrift/server/thread_pool_server.rb +75 -0
  46. data/lib/thrift/server/threaded_server.rb +47 -0
  47. data/lib/thrift/struct.rb +237 -0
  48. data/lib/thrift/struct_union.rb +192 -0
  49. data/lib/thrift/thrift_native.rb +24 -0
  50. data/lib/thrift/transport/base_server_transport.rb +37 -0
  51. data/lib/thrift/transport/base_transport.rb +109 -0
  52. data/lib/thrift/transport/buffered_transport.rb +114 -0
  53. data/lib/thrift/transport/framed_transport.rb +117 -0
  54. data/lib/thrift/transport/http_client_transport.rb +56 -0
  55. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  56. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  57. data/lib/thrift/transport/server_socket.rb +63 -0
  58. data/lib/thrift/transport/socket.rb +139 -0
  59. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  60. data/lib/thrift/transport/unix_socket.rb +40 -0
  61. data/lib/thrift/types.rb +101 -0
  62. data/lib/thrift/union.rb +179 -0
  63. data/lib/tiny_thrift.rb +1 -0
  64. data/spec/ThriftSpec.thrift +183 -0
  65. data/spec/base_protocol_spec.rb +217 -0
  66. data/spec/base_transport_spec.rb +350 -0
  67. data/spec/binary_protocol_accelerated_spec.rb +42 -0
  68. data/spec/binary_protocol_spec.rb +66 -0
  69. data/spec/binary_protocol_spec_shared.rb +455 -0
  70. data/spec/bytes_spec.rb +160 -0
  71. data/spec/client_spec.rb +99 -0
  72. data/spec/compact_protocol_spec.rb +143 -0
  73. data/spec/exception_spec.rb +141 -0
  74. data/spec/http_client_spec.rb +120 -0
  75. data/spec/json_protocol_spec.rb +513 -0
  76. data/spec/nonblocking_server_spec.rb +263 -0
  77. data/spec/processor_spec.rb +80 -0
  78. data/spec/serializer_spec.rb +67 -0
  79. data/spec/server_socket_spec.rb +79 -0
  80. data/spec/server_spec.rb +147 -0
  81. data/spec/socket_spec.rb +61 -0
  82. data/spec/socket_spec_shared.rb +104 -0
  83. data/spec/spec_helper.rb +61 -0
  84. data/spec/struct_nested_containers_spec.rb +191 -0
  85. data/spec/struct_spec.rb +293 -0
  86. data/spec/thin_http_server_spec.rb +141 -0
  87. data/spec/types_spec.rb +115 -0
  88. data/spec/union_spec.rb +203 -0
  89. data/spec/unix_socket_spec.rb +107 -0
  90. metadata +313 -0
@@ -0,0 +1,160 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ require 'spec_helper'
22
+
23
+ describe Thrift::Bytes do
24
+ if RUBY_VERSION >= '1.9'
25
+ describe '.empty_byte_buffer' do
26
+ it 'should create an empty buffer' do
27
+ b = Thrift::Bytes.empty_byte_buffer
28
+ b.length.should == 0
29
+ b.encoding.should == Encoding::BINARY
30
+ end
31
+
32
+ it 'should create an empty buffer of given size' do
33
+ b = Thrift::Bytes.empty_byte_buffer 2
34
+ b.length.should == 2
35
+ b.getbyte(0).should == 0
36
+ b.getbyte(1).should == 0
37
+ b.encoding.should == Encoding::BINARY
38
+ end
39
+ end
40
+
41
+ describe '.force_binary_encoding' do
42
+ it 'should change encoding' do
43
+ e = 'STRING'.encode('UTF-8')
44
+ e.encoding.should_not == Encoding::BINARY
45
+ a = Thrift::Bytes.force_binary_encoding e
46
+ a.encoding.should == Encoding::BINARY
47
+ end
48
+ end
49
+
50
+ describe '.get_string_byte' do
51
+ it 'should get the byte at index' do
52
+ s = "\x41\x42"
53
+ Thrift::Bytes.get_string_byte(s, 0).should == 0x41
54
+ Thrift::Bytes.get_string_byte(s, 1).should == 0x42
55
+ end
56
+ end
57
+
58
+ describe '.set_string_byte' do
59
+ it 'should set byte value at index' do
60
+ s = "\x41\x42"
61
+ Thrift::Bytes.set_string_byte(s, 0, 0x43)
62
+ s.getbyte(0).should == 0x43
63
+ s.should == 'CB'
64
+ end
65
+ end
66
+
67
+ describe '.convert_to_utf8_byte_buffer' do
68
+ it 'should convert UTF-8 String to byte buffer' do
69
+ e = "\u20AC".encode('UTF-8') # a string with euro sign character U+20AC
70
+ e.length.should == 1
71
+
72
+ a = Thrift::Bytes.convert_to_utf8_byte_buffer e
73
+ a.encoding.should == Encoding::BINARY
74
+ a.length.should == 3
75
+ a.unpack('C*').should == [0xE2, 0x82, 0xAC]
76
+ end
77
+
78
+ it 'should convert ISO-8859-15 String to UTF-8 byte buffer' do
79
+ # Assumptions
80
+ e = "\u20AC".encode('ISO-8859-15') # a string with euro sign character U+20AC, then converted to ISO-8859-15
81
+ e.length.should == 1
82
+ e.unpack('C*').should == [0xA4] # euro sign is a different code point in ISO-8859-15
83
+
84
+ a = Thrift::Bytes.convert_to_utf8_byte_buffer e
85
+ a.encoding.should == Encoding::BINARY
86
+ a.length.should == 3
87
+ a.unpack('C*').should == [0xE2, 0x82, 0xAC]
88
+ end
89
+ end
90
+
91
+ describe '.convert_to_string' do
92
+ it 'should convert UTF-8 byte buffer to a UTF-8 String' do
93
+ e = [0xE2, 0x82, 0xAC].pack("C*")
94
+ e.encoding.should == Encoding::BINARY
95
+ a = Thrift::Bytes.convert_to_string e
96
+ a.encoding.should == Encoding::UTF_8
97
+ a.should == "\u20AC"
98
+ end
99
+ end
100
+
101
+ else # RUBY_VERSION
102
+ describe '.empty_byte_buffer' do
103
+ it 'should create an empty buffer' do
104
+ b = Thrift::Bytes.empty_byte_buffer
105
+ b.length.should == 0
106
+ end
107
+
108
+ it 'should create an empty buffer of given size' do
109
+ b = Thrift::Bytes.empty_byte_buffer 2
110
+ b.length.should == 2
111
+ b[0].should == 0
112
+ b[1].should == 0
113
+ end
114
+ end
115
+
116
+ describe '.force_binary_encoding' do
117
+ it 'should be a no-op' do
118
+ e = 'STRING'
119
+ a = Thrift::Bytes.force_binary_encoding e
120
+ a.should == e
121
+ a.should be(e)
122
+ end
123
+ end
124
+
125
+ describe '.get_string_byte' do
126
+ it 'should get the byte at index' do
127
+ s = "\x41\x42"
128
+ Thrift::Bytes.get_string_byte(s, 0).should == 0x41
129
+ Thrift::Bytes.get_string_byte(s, 1).should == 0x42
130
+ end
131
+ end
132
+
133
+ describe '.set_string_byte' do
134
+ it 'should set byte value at index' do
135
+ s = "\x41\x42"
136
+ Thrift::Bytes.set_string_byte(s, 0, 0x43)
137
+ s[0].should == 0x43
138
+ s.should == 'CB'
139
+ end
140
+ end
141
+
142
+ describe '.convert_to_utf8_byte_buffer' do
143
+ it 'should be a no-op' do
144
+ e = 'STRING'
145
+ a = Thrift::Bytes.convert_to_utf8_byte_buffer e
146
+ a.should == e
147
+ a.should be(e)
148
+ end
149
+ end
150
+
151
+ describe '.convert_to_string' do
152
+ it 'should be a no-op' do
153
+ e = 'STRING'
154
+ a = Thrift::Bytes.convert_to_string e
155
+ a.should == e
156
+ a.should be(e)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,99 @@
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 'spec_helper'
21
+
22
+ describe 'Client' do
23
+
24
+ class ClientSpec
25
+ include Thrift::Client
26
+ end
27
+
28
+ before(:each) do
29
+ @prot = mock("MockProtocol")
30
+ @client = ClientSpec.new(@prot)
31
+ end
32
+
33
+ describe Thrift::Client do
34
+ it "should re-use iprot for oprot if not otherwise specified" do
35
+ @client.instance_variable_get(:'@iprot').should eql(@prot)
36
+ @client.instance_variable_get(:'@oprot').should eql(@prot)
37
+ end
38
+
39
+ it "should send a test message" do
40
+ @prot.should_receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0)
41
+ mock_args = mock('#<TestMessage_args:mock>')
42
+ mock_args.should_receive(:foo=).with('foo')
43
+ mock_args.should_receive(:bar=).with(42)
44
+ mock_args.should_receive(:write).with(@prot)
45
+ @prot.should_receive(:write_message_end)
46
+ @prot.should_receive(:trans) do
47
+ mock('trans').tap do |trans|
48
+ trans.should_receive(:flush)
49
+ end
50
+ end
51
+ klass = stub("TestMessage_args", :new => mock_args)
52
+ @client.send_message('testMessage', klass, :foo => 'foo', :bar => 42)
53
+ end
54
+
55
+ it "should increment the sequence id when sending messages" do
56
+ pending "it seems sequence ids are completely ignored right now" do
57
+ @prot.should_receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0).ordered
58
+ @prot.should_receive(:write_message_begin).with('testMessage2', Thrift::MessageTypes::CALL, 1).ordered
59
+ @prot.should_receive(:write_message_begin).with('testMessage3', Thrift::MessageTypes::CALL, 2).ordered
60
+ @prot.stub!(:write_message_end)
61
+ @prot.stub!(:trans).and_return mock("trans").as_null_object
62
+ @client.send_message('testMessage', mock("args class").as_null_object)
63
+ @client.send_message('testMessage2', mock("args class").as_null_object)
64
+ @client.send_message('testMessage3', mock("args class").as_null_object)
65
+ end
66
+ end
67
+
68
+ it "should receive a test message" do
69
+ @prot.should_receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::CALL, 0]
70
+ @prot.should_receive(:read_message_end)
71
+ mock_klass = mock("#<MockClass:mock>")
72
+ mock_klass.should_receive(:read).with(@prot)
73
+ @client.receive_message(stub("MockClass", :new => mock_klass))
74
+ end
75
+
76
+ it "should handle received exceptions" do
77
+ @prot.should_receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::EXCEPTION, 0]
78
+ @prot.should_receive(:read_message_end)
79
+ Thrift::ApplicationException.should_receive(:new).and_return do
80
+ StandardError.new.tap do |mock_exc|
81
+ mock_exc.should_receive(:read).with(@prot)
82
+ end
83
+ end
84
+ lambda { @client.receive_message(nil) }.should raise_error(StandardError)
85
+ end
86
+
87
+ it "should close the transport if an error occurs while sending a message" do
88
+ @prot.stub!(:write_message_begin)
89
+ @prot.should_not_receive(:write_message_end)
90
+ mock_args = mock("#<TestMessage_args:mock>")
91
+ mock_args.should_receive(:write).with(@prot).and_raise(StandardError)
92
+ trans = mock("MockTransport")
93
+ @prot.stub!(:trans).and_return(trans)
94
+ trans.should_receive(:close)
95
+ klass = mock("TestMessage_args", :new => mock_args)
96
+ lambda { @client.send_message("testMessage", klass) }.should raise_error(StandardError)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,143 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ require 'spec_helper'
22
+
23
+ describe Thrift::CompactProtocol do
24
+ TESTS = {
25
+ :byte => (-127..127).to_a,
26
+ :i16 => (0..14).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort,
27
+ :i32 => (0..30).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort,
28
+ :i64 => (0..62).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort,
29
+ :string => ["", "1", "short", "fourteen123456", "fifteen12345678", "unicode characters: \u20AC \u20AD", "1" * 127, "1" * 3000],
30
+ :binary => ["", "\001", "\001" * 5, "\001" * 14, "\001" * 15, "\001" * 127, "\001" * 3000],
31
+ :double => [0.0, 1.0, -1.0, 1.1, -1.1, 10000000.1, 1.0/0.0, -1.0/0.0],
32
+ :bool => [true, false]
33
+ }
34
+
35
+ it "should encode and decode naked primitives correctly" do
36
+ TESTS.each_pair do |primitive_type, test_values|
37
+ test_values.each do |value|
38
+ # puts "testing #{value}" if primitive_type == :i64
39
+ trans = Thrift::MemoryBufferTransport.new
40
+ proto = Thrift::CompactProtocol.new(trans)
41
+
42
+ proto.send(writer(primitive_type), value)
43
+ # puts "buf: #{trans.inspect_buffer}" if primitive_type == :i64
44
+ read_back = proto.send(reader(primitive_type))
45
+ read_back.should == value
46
+ end
47
+ end
48
+ end
49
+
50
+ it "should encode and decode primitives in fields correctly" do
51
+ TESTS.each_pair do |primitive_type, test_values|
52
+ final_primitive_type = primitive_type == :binary ? :string : primitive_type
53
+ thrift_type = Thrift::Types.const_get(final_primitive_type.to_s.upcase)
54
+ # puts primitive_type
55
+ test_values.each do |value|
56
+ trans = Thrift::MemoryBufferTransport.new
57
+ proto = Thrift::CompactProtocol.new(trans)
58
+
59
+ proto.write_field_begin(nil, thrift_type, 15)
60
+ proto.send(writer(primitive_type), value)
61
+ proto.write_field_end
62
+
63
+ proto = Thrift::CompactProtocol.new(trans)
64
+ name, type, id = proto.read_field_begin
65
+ type.should == thrift_type
66
+ id.should == 15
67
+ read_back = proto.send(reader(primitive_type))
68
+ read_back.should == value
69
+ proto.read_field_end
70
+ end
71
+ end
72
+ end
73
+
74
+ it "should encode and decode a monster struct correctly" do
75
+ trans = Thrift::MemoryBufferTransport.new
76
+ proto = Thrift::CompactProtocol.new(trans)
77
+
78
+ struct = CompactProtoTestStruct.new
79
+ # sets and maps don't hash well... not sure what to do here.
80
+ struct.write(proto)
81
+
82
+ struct2 = CompactProtoTestStruct.new
83
+ struct2.read(proto)
84
+ struct2.should == struct
85
+ end
86
+
87
+ it "should make method calls correctly" do
88
+ client_out_trans = Thrift::MemoryBufferTransport.new
89
+ client_out_proto = Thrift::CompactProtocol.new(client_out_trans)
90
+
91
+ client_in_trans = Thrift::MemoryBufferTransport.new
92
+ client_in_proto = Thrift::CompactProtocol.new(client_in_trans)
93
+
94
+ processor = Srv::Processor.new(JankyHandler.new)
95
+
96
+ client = Srv::Client.new(client_in_proto, client_out_proto)
97
+ client.send_Janky(1)
98
+ # puts client_out_trans.inspect_buffer
99
+ processor.process(client_out_proto, client_in_proto)
100
+ client.recv_Janky.should == 2
101
+ end
102
+
103
+ it "should deal with fields following fields that have non-delta ids" do
104
+ brcp = BreaksRubyCompactProtocol.new(
105
+ :field1 => "blah",
106
+ :field2 => BigFieldIdStruct.new(
107
+ :field1 => "string1",
108
+ :field2 => "string2"),
109
+ :field3 => 3)
110
+ ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new)
111
+ bytes = ser.serialize(brcp)
112
+
113
+ deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
114
+ brcp2 = BreaksRubyCompactProtocol.new
115
+ deser.deserialize(brcp2, bytes)
116
+ brcp2.should == brcp
117
+ end
118
+
119
+ it "should deserialize an empty map to an empty hash" do
120
+ struct = SingleMapTestStruct.new(:i32_map => {})
121
+ ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new)
122
+ bytes = ser.serialize(struct)
123
+
124
+ deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
125
+ struct2 = SingleMapTestStruct.new
126
+ deser.deserialize(struct2, bytes)
127
+ struct.should == struct2
128
+ end
129
+
130
+ class JankyHandler
131
+ def Janky(i32arg)
132
+ i32arg * 2
133
+ end
134
+ end
135
+
136
+ def writer(sym)
137
+ "write_#{sym.to_s}"
138
+ end
139
+
140
+ def reader(sym)
141
+ "read_#{sym.to_s}"
142
+ end
143
+ end
@@ -0,0 +1,141 @@
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 'spec_helper'
21
+
22
+ describe 'Exception' do
23
+
24
+ describe Thrift::Exception do
25
+ it "should have an accessible message" do
26
+ e = Thrift::Exception.new("test message")
27
+ e.message.should == "test message"
28
+ end
29
+ end
30
+
31
+ describe Thrift::ApplicationException do
32
+ it "should inherit from Thrift::Exception" do
33
+ Thrift::ApplicationException.superclass.should == Thrift::Exception
34
+ end
35
+
36
+ it "should have an accessible type and message" do
37
+ e = Thrift::ApplicationException.new
38
+ e.type.should == Thrift::ApplicationException::UNKNOWN
39
+ e.message.should be_nil
40
+ e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message")
41
+ e.type.should == Thrift::ApplicationException::UNKNOWN_METHOD
42
+ e.message.should == "test message"
43
+ end
44
+
45
+ it "should read a struct off of a protocol" do
46
+ prot = mock("MockProtocol")
47
+ prot.should_receive(:read_struct_begin).ordered
48
+ prot.should_receive(:read_field_begin).exactly(3).times.and_return(
49
+ ["message", Thrift::Types::STRING, 1],
50
+ ["type", Thrift::Types::I32, 2],
51
+ [nil, Thrift::Types::STOP, 0]
52
+ )
53
+ prot.should_receive(:read_string).ordered.and_return "test message"
54
+ prot.should_receive(:read_i32).ordered.and_return Thrift::ApplicationException::BAD_SEQUENCE_ID
55
+ prot.should_receive(:read_field_end).exactly(2).times
56
+ prot.should_receive(:read_struct_end).ordered
57
+
58
+ e = Thrift::ApplicationException.new
59
+ e.read(prot)
60
+ e.message.should == "test message"
61
+ e.type.should == Thrift::ApplicationException::BAD_SEQUENCE_ID
62
+ end
63
+
64
+ it "should skip bad fields when reading a struct" do
65
+ prot = mock("MockProtocol")
66
+ prot.should_receive(:read_struct_begin).ordered
67
+ prot.should_receive(:read_field_begin).exactly(5).times.and_return(
68
+ ["type", Thrift::Types::I32, 2],
69
+ ["type", Thrift::Types::STRING, 2],
70
+ ["message", Thrift::Types::MAP, 1],
71
+ ["message", Thrift::Types::STRING, 3],
72
+ [nil, Thrift::Types::STOP, 0]
73
+ )
74
+ prot.should_receive(:read_i32).and_return Thrift::ApplicationException::INVALID_MESSAGE_TYPE
75
+ prot.should_receive(:skip).with(Thrift::Types::STRING).twice
76
+ prot.should_receive(:skip).with(Thrift::Types::MAP)
77
+ prot.should_receive(:read_field_end).exactly(4).times
78
+ prot.should_receive(:read_struct_end).ordered
79
+
80
+ e = Thrift::ApplicationException.new
81
+ e.read(prot)
82
+ e.message.should be_nil
83
+ e.type.should == Thrift::ApplicationException::INVALID_MESSAGE_TYPE
84
+ end
85
+
86
+ it "should write a Thrift::ApplicationException struct to the oprot" do
87
+ prot = mock("MockProtocol")
88
+ prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
89
+ prot.should_receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
90
+ prot.should_receive(:write_string).with("test message").ordered
91
+ prot.should_receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
92
+ prot.should_receive(:write_i32).with(Thrift::ApplicationException::UNKNOWN_METHOD).ordered
93
+ prot.should_receive(:write_field_end).twice
94
+ prot.should_receive(:write_field_stop).ordered
95
+ prot.should_receive(:write_struct_end).ordered
96
+
97
+ e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message")
98
+ e.write(prot)
99
+ end
100
+
101
+ it "should skip nil fields when writing to the oprot" do
102
+ prot = mock("MockProtocol")
103
+ prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
104
+ prot.should_receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered
105
+ prot.should_receive(:write_string).with("test message").ordered
106
+ prot.should_receive(:write_field_end).ordered
107
+ prot.should_receive(:write_field_stop).ordered
108
+ prot.should_receive(:write_struct_end).ordered
109
+
110
+ e = Thrift::ApplicationException.new(nil, "test message")
111
+ e.write(prot)
112
+
113
+ prot = mock("MockProtocol")
114
+ prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
115
+ prot.should_receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered
116
+ prot.should_receive(:write_i32).with(Thrift::ApplicationException::BAD_SEQUENCE_ID).ordered
117
+ prot.should_receive(:write_field_end).ordered
118
+ prot.should_receive(:write_field_stop).ordered
119
+ prot.should_receive(:write_struct_end).ordered
120
+
121
+ e = Thrift::ApplicationException.new(Thrift::ApplicationException::BAD_SEQUENCE_ID)
122
+ e.write(prot)
123
+
124
+ prot = mock("MockProtocol")
125
+ prot.should_receive(:write_struct_begin).with("Thrift::ApplicationException").ordered
126
+ prot.should_receive(:write_field_stop).ordered
127
+ prot.should_receive(:write_struct_end).ordered
128
+
129
+ e = Thrift::ApplicationException.new(nil)
130
+ e.write(prot)
131
+ end
132
+ end
133
+
134
+ describe Thrift::ProtocolException do
135
+ it "should have an accessible type" do
136
+ prot = Thrift::ProtocolException.new(Thrift::ProtocolException::SIZE_LIMIT, "message")
137
+ prot.type.should == Thrift::ProtocolException::SIZE_LIMIT
138
+ prot.message.should == "message"
139
+ end
140
+ end
141
+ end