thrift 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +235 -17
  3. data/benchmark/benchmark.rb +23 -8
  4. data/benchmark/client.rb +50 -6
  5. data/benchmark/server.rb +46 -7
  6. data/benchmark/thin_server.rb +2 -0
  7. data/ext/binary_protocol_accelerated.c +154 -42
  8. data/ext/bytes.c +14 -0
  9. data/ext/compact_protocol.c +138 -45
  10. data/ext/constants.h +12 -0
  11. data/ext/extconf.rb +17 -8
  12. data/ext/memory_buffer.c +44 -7
  13. data/ext/protocol.c +29 -0
  14. data/ext/protocol.h +35 -0
  15. data/ext/struct.c +48 -17
  16. data/ext/thrift_native.c +28 -3
  17. data/lib/thrift/bytes.rb +70 -100
  18. data/lib/thrift/client.rb +54 -13
  19. data/lib/thrift/exceptions.rb +6 -5
  20. data/lib/thrift/multiplexed_processor.rb +20 -10
  21. data/lib/thrift/processor.rb +7 -6
  22. data/lib/thrift/protocol/base_protocol.rb +52 -21
  23. data/lib/thrift/protocol/binary_protocol.rb +65 -20
  24. data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -5
  25. data/lib/thrift/protocol/compact_protocol.rb +76 -41
  26. data/lib/thrift/protocol/header_protocol.rb +321 -0
  27. data/lib/thrift/protocol/json_protocol.rb +44 -27
  28. data/lib/thrift/protocol/multiplexed_protocol.rb +6 -5
  29. data/lib/thrift/protocol/protocol_decorator.rb +13 -4
  30. data/lib/thrift/serializer/deserializer.rb +6 -5
  31. data/lib/thrift/serializer/serializer.rb +5 -5
  32. data/lib/thrift/server/base_server.rb +5 -4
  33. data/lib/thrift/server/mongrel_http_server.rb +7 -6
  34. data/lib/thrift/server/nonblocking_server.rb +35 -9
  35. data/lib/thrift/server/simple_server.rb +13 -5
  36. data/lib/thrift/server/thin_http_server.rb +4 -3
  37. data/lib/thrift/server/thread_pool_server.rb +7 -6
  38. data/lib/thrift/server/threaded_server.rb +13 -5
  39. data/lib/thrift/struct.rb +12 -11
  40. data/lib/thrift/struct_union.rb +14 -9
  41. data/lib/thrift/thrift_native.rb +3 -2
  42. data/lib/thrift/transport/base_server_transport.rb +8 -5
  43. data/lib/thrift/transport/base_transport.rb +18 -14
  44. data/lib/thrift/transport/buffered_transport.rb +7 -6
  45. data/lib/thrift/transport/framed_transport.rb +8 -7
  46. data/lib/thrift/transport/header_transport.rb +562 -0
  47. data/lib/thrift/transport/http_client_transport.rb +2 -1
  48. data/lib/thrift/transport/io_stream_transport.rb +4 -3
  49. data/lib/thrift/transport/memory_buffer_transport.rb +13 -6
  50. data/lib/thrift/transport/server_socket.rb +14 -8
  51. data/lib/thrift/transport/socket.rb +126 -60
  52. data/lib/thrift/transport/ssl_server_socket.rb +4 -3
  53. data/lib/thrift/transport/ssl_socket.rb +45 -13
  54. data/lib/thrift/transport/unix_server_socket.rb +9 -5
  55. data/lib/thrift/transport/unix_socket.rb +7 -6
  56. data/lib/thrift/types.rb +10 -6
  57. data/lib/thrift/union.rb +15 -8
  58. data/lib/thrift/uuid.rb +50 -0
  59. data/lib/thrift.rb +4 -1
  60. data/spec/ThriftSpec.thrift +21 -1
  61. data/spec/base_protocol_spec.rb +21 -2
  62. data/spec/base_transport_spec.rb +48 -8
  63. data/spec/binary_protocol_accelerated_spec.rb +1 -0
  64. data/spec/binary_protocol_spec.rb +1 -2
  65. data/spec/binary_protocol_spec_shared.rb +206 -155
  66. data/spec/bytes_spec.rb +71 -114
  67. data/spec/client_spec.rb +86 -19
  68. data/spec/compact_protocol_spec.rb +153 -16
  69. data/spec/constants_demo_spec.rb +102 -0
  70. data/spec/exception_spec.rb +1 -1
  71. data/spec/flat_spec.rb +1 -0
  72. data/spec/header_protocol_spec.rb +476 -0
  73. data/spec/header_transport_spec.rb +431 -0
  74. data/spec/http_client_spec.rb +5 -6
  75. data/spec/json_protocol_spec.rb +69 -47
  76. data/spec/multiplexed_processor_spec.rb +75 -0
  77. data/spec/namespaced_spec.rb +1 -1
  78. data/spec/nonblocking_server_spec.rb +174 -8
  79. data/spec/processor_spec.rb +1 -1
  80. data/spec/recursion_depth_spec.rb +223 -0
  81. data/spec/serializer_spec.rb +1 -1
  82. data/spec/server_socket_spec.rb +38 -1
  83. data/spec/server_spec.rb +60 -9
  84. data/spec/socket_spec.rb +119 -13
  85. data/spec/socket_spec_shared.rb +73 -9
  86. data/spec/spec_helper.rb +2 -1
  87. data/spec/ssl_server_socket_spec.rb +52 -1
  88. data/spec/ssl_socket_spec.rb +181 -11
  89. data/spec/struct_nested_containers_spec.rb +2 -2
  90. data/spec/struct_spec.rb +114 -9
  91. data/spec/support/header_protocol_helper.rb +55 -0
  92. data/spec/thin_http_server_spec.rb +4 -18
  93. data/spec/types_spec.rb +26 -26
  94. data/spec/union_spec.rb +70 -11
  95. data/spec/unix_socket_spec.rb +17 -2
  96. data/spec/uuid_validation_spec.rb +239 -0
  97. data/test/fuzz/Makefile +779 -0
  98. data/test/fuzz/Makefile.am +173 -0
  99. data/test/fuzz/Makefile.in +775 -0
  100. data/test/fuzz/README.md +149 -0
  101. data/test/fuzz/fuzz_common.rb +96 -0
  102. data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +4 -4
  103. data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +7 -13
  104. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +23 -0
  105. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +23 -0
  106. data/test/fuzz/fuzz_parse_compact_protocol.rb +23 -0
  107. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +23 -0
  108. data/test/fuzz/fuzz_parse_json_protocol.rb +23 -0
  109. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +23 -0
  110. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +23 -0
  111. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +23 -0
  112. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +23 -0
  113. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +23 -0
  114. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +23 -0
  115. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +23 -0
  116. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +23 -0
  117. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +23 -0
  118. data/test/fuzz/fuzz_tracer.rb +29 -0
  119. metadata +105 -70
@@ -1,4 +1,5 @@
1
1
  # encoding: ascii-8bit
2
+ # frozen_string_literal: true
2
3
  #
3
4
  # Licensed to the Apache Software Foundation (ASF) under one
4
5
  # or more contributor license agreements. See the NOTICE file
@@ -38,25 +39,24 @@ shared_examples_for 'a binary protocol' do
38
39
 
39
40
  it "should make strict_write readable" do
40
41
  expect(@prot.strict_write).to eql(true)
41
- end
42
+ end
42
43
 
43
44
  it "should write the message header" do
44
45
  @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
45
46
  expect(@trans.read(@trans.available)).to eq([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N"))
46
47
  end
47
-
48
+
48
49
  it "should write the message header without version when writes are not strict" do
49
50
  @prot = protocol_class.new(@trans, true, false) # no strict write
50
51
  @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
51
52
  expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021")
52
53
  end
53
-
54
+
54
55
  it "should write the message header with a version when writes are strict" do
55
56
  @prot = protocol_class.new(@trans) # strict write
56
57
  @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
57
58
  expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021")
58
59
  end
59
-
60
60
 
61
61
  # message footer is a noop
62
62
 
@@ -64,44 +64,44 @@ shared_examples_for 'a binary protocol' do
64
64
  @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3)
65
65
  expect(@trans.read(@trans.available)).to eq([Thrift::Types::DOUBLE, 3].pack("cn"))
66
66
  end
67
-
67
+
68
68
  # field footer is a noop
69
-
69
+
70
70
  it "should write the STOP field" do
71
71
  @prot.write_field_stop
72
72
  expect(@trans.read(1)).to eq("\000")
73
73
  end
74
-
74
+
75
75
  it "should write the map header" do
76
76
  @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17)
77
77
  expect(@trans.read(@trans.available)).to eq([Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN"));
78
78
  end
79
-
79
+
80
80
  # map footer is a noop
81
-
81
+
82
82
  it "should write the list header" do
83
83
  @prot.write_list_begin(Thrift::Types::I16, 42)
84
84
  expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN"))
85
85
  end
86
-
86
+
87
87
  # list footer is a noop
88
-
88
+
89
89
  it "should write the set header" do
90
90
  @prot.write_set_begin(Thrift::Types::I16, 42)
91
91
  expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN"))
92
92
  end
93
-
93
+
94
94
  it "should write a bool" do
95
95
  @prot.write_bool(true)
96
96
  @prot.write_bool(false)
97
97
  expect(@trans.read(@trans.available)).to eq("\001\000")
98
98
  end
99
-
99
+
100
100
  it "should treat a nil bool as false" do
101
101
  @prot.write_bool(nil)
102
102
  expect(@trans.read(1)).to eq("\000")
103
103
  end
104
-
104
+
105
105
  it "should write a byte" do
106
106
  # byte is small enough, let's check -128..127
107
107
  (-128..127).each do |i|
@@ -110,64 +110,72 @@ shared_examples_for 'a binary protocol' do
110
110
  end
111
111
  end
112
112
 
113
- it "should clip numbers out of signed range" do
114
- (128..255).each do |i|
115
- @prot.write_byte(i)
116
- expect(@trans.read(1)).to eq([i].pack('c'))
113
+ it "should reject bytes outside the signed byte range" do
114
+ [-129, 128, 255, 2**65].each do |i|
115
+ expect { @prot.write_byte(i) }.to raise_error(RangeError)
117
116
  end
117
+ expect(@trans.available).to eq(0)
118
118
  end
119
119
 
120
- it "errors out with a Bignum" do
121
- expect { @prot.write_byte(2**65) }.to raise_error(RangeError)
120
+ it "should reject non-integer bytes" do
121
+ expect { @prot.write_byte(1.5) }.to raise_error(TypeError)
122
122
  end
123
-
123
+
124
124
  it "should error gracefully when trying to write a nil byte" do
125
- expect { @prot.write_byte(nil) }.to raise_error
125
+ expect { @prot.write_byte(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
126
126
  end
127
-
127
+
128
128
  it "should write an i16" do
129
129
  # try a random scattering of values
130
130
  # include the signed i16 minimum/maximum
131
131
  [-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i|
132
132
  @prot.write_i16(i)
133
133
  end
134
- # and try something out of signed range, it should clip
135
- @prot.write_i16(2**15 + 5)
136
-
137
- expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005")
138
-
139
- # a Bignum should error
140
- # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError)
141
- end
142
-
134
+
135
+ expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377")
136
+ end
137
+
138
+ it "should reject i16 values outside the signed i16 range" do
139
+ [-2**15 - 1, 2**15, 2**65].each do |i|
140
+ expect { @prot.write_i16(i) }.to raise_error(RangeError)
141
+ end
142
+ expect(@trans.available).to eq(0)
143
+ end
144
+
145
+ it "should reject non-integer i16 values" do
146
+ expect { @prot.write_i16(1.5) }.to raise_error(TypeError)
147
+ end
148
+
143
149
  it "should error gracefully when trying to write a nil i16" do
144
- expect { @prot.write_i16(nil) }.to raise_error
150
+ expect { @prot.write_i16(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
145
151
  end
146
-
152
+
147
153
  it "should write an i32" do
148
154
  # try a random scattering of values
149
155
  # include the signed i32 minimum/maximum
150
156
  [-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i|
151
157
  @prot.write_i32(i)
152
158
  end
153
- # try something out of signed range, it should clip
154
159
  expect(@trans.read(@trans.available)).to eq("\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")
155
- [2 ** 31 + 5, 2 ** 65 + 5].each do |i|
156
- expect { @prot.write_i32(i) }.to raise_error(RangeError)
160
+ [-2 ** 31 - 1, 2 ** 31, 2 ** 65 + 5].each do |i|
161
+ expect { @prot.write_i32(i) }.to raise_error(RangeError)
157
162
  end
158
163
  end
159
-
164
+
165
+ it "should reject non-integer i32 values" do
166
+ expect { @prot.write_i32(1.5) }.to raise_error(TypeError)
167
+ end
168
+
160
169
  it "should error gracefully when trying to write a nil i32" do
161
- expect { @prot.write_i32(nil) }.to raise_error
170
+ expect { @prot.write_i32(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
162
171
  end
163
-
172
+
164
173
  it "should write an i64" do
165
174
  # try a random scattering of values
166
175
  # try the signed i64 minimum/maximum
167
176
  [-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i|
168
177
  @prot.write_i64(i)
169
178
  end
170
- # try something out of signed range, it should clip
171
179
  expect(@trans.read(@trans.available)).to eq(["\200\000\000\000\000\000\000\000",
172
180
  "\377\377\364\303\035\244+]",
173
181
  "\377\377\377\377\376\231:\341",
@@ -177,100 +185,131 @@ shared_examples_for 'a binary protocol' do
177
185
  "\000\000\000\000\000#\340\204",
178
186
  "\000\000\000\002\340\311~\365",
179
187
  "\177\377\377\377\377\377\377\377"].join(""))
180
- expect { @prot.write_i64(2 ** 65 + 5) }.to raise_error(RangeError)
188
+ [-2 ** 63 - 1, 2 ** 63, 2 ** 65 + 5].each do |i|
189
+ expect { @prot.write_i64(i) }.to raise_error(RangeError)
190
+ end
191
+ end
192
+
193
+ it "should reject non-integer i64 values" do
194
+ expect { @prot.write_i64(1.5) }.to raise_error(TypeError)
181
195
  end
182
-
196
+
183
197
  it "should error gracefully when trying to write a nil i64" do
184
- expect { @prot.write_i64(nil) }.to raise_error
198
+ expect { @prot.write_i64(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
199
+ end
200
+
201
+ it "should reject out-of-range field ids" do
202
+ expect { @prot.write_field_begin('foo', Thrift::Types::DOUBLE, -2**15 - 1) }.to raise_error(RangeError)
203
+ expect { @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 2**15) }.to raise_error(RangeError)
185
204
  end
186
-
205
+
206
+ it "should reject out-of-range container sizes" do
207
+ expect { @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, -1) }.to raise_error(RangeError)
208
+ expect { @prot.write_list_begin(Thrift::Types::I16, 2**31) }.to raise_error(RangeError)
209
+ expect { @prot.write_set_begin(Thrift::Types::I16, 2**31) }.to raise_error(RangeError)
210
+ end
211
+
187
212
  it "should write a double" do
188
213
  # try a random scattering of values, including min/max
189
- values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
214
+ values = [Float::MIN, -1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
190
215
  values.each do |f|
191
216
  @prot.write_double(f)
192
217
  expect(@trans.read(@trans.available)).to eq([f].pack("G"))
193
218
  end
194
219
  end
195
-
220
+
196
221
  it "should error gracefully when trying to write a nil double" do
197
- expect { @prot.write_double(nil) }.to raise_error
222
+ expect { @prot.write_double(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
198
223
  end
199
224
 
200
- if RUBY_VERSION >= '1.9'
201
- it 'should write a string' do
202
- str = 'abc'
203
- @prot.write_string(str)
204
- a = @trans.read(@trans.available)
205
- expect(a.encoding).to eq(Encoding::BINARY)
206
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63])
207
- end
225
+ it 'should write a string' do
226
+ str = 'abc'
227
+ @prot.write_string(str)
228
+ a = @trans.read(@trans.available)
229
+ expect(a.encoding).to eq(Encoding::BINARY)
230
+ expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63])
231
+ end
208
232
 
209
- it 'should write a string with unicode characters' do
210
- str = "abc \u20AC \u20AD".encode('UTF-8')
211
- @prot.write_string(str)
212
- a = @trans.read(@trans.available)
213
- expect(a.encoding).to eq(Encoding::BINARY)
214
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x0B, 0x61, 0x62, 0x63, 0x20,
215
- 0xE2, 0x82, 0xAC, 0x20, 0xE2, 0x82, 0xAD])
216
- end
233
+ it 'should write a string with unicode characters' do
234
+ str = "abc \u20AC \u20AD".encode('UTF-8')
235
+ @prot.write_string(str)
236
+ a = @trans.read(@trans.available)
237
+ expect(a.encoding).to eq(Encoding::BINARY)
238
+ expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x0B, 0x61, 0x62, 0x63, 0x20,
239
+ 0xE2, 0x82, 0xAC, 0x20, 0xE2, 0x82, 0xAD])
240
+ end
217
241
 
218
- it 'should write should write a string with unicode characters and transcoding' do
219
- str = "abc \u20AC".encode('ISO-8859-15')
220
- @prot.write_string(str)
221
- a = @trans.read(@trans.available)
222
- expect(a.encoding).to eq(Encoding::BINARY)
223
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
224
- end
242
+ it 'should write should write a string with unicode characters and transcoding' do
243
+ str = "abc \u20AC".encode('ISO-8859-15')
244
+ @prot.write_string(str)
245
+ a = @trans.read(@trans.available)
246
+ expect(a.encoding).to eq(Encoding::BINARY)
247
+ expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
248
+ end
225
249
 
226
- it 'should write a binary string' do
227
- buffer = [0, 1, 2, 3].pack('C*')
228
- @prot.write_binary(buffer)
229
- a = @trans.read(@trans.available)
230
- expect(a.encoding).to eq(Encoding::BINARY)
231
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
232
- end
233
- else
234
- it 'should write a string' do
235
- str = 'abc'
236
- @prot.write_string(str)
237
- a = @trans.read(@trans.available)
238
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63])
239
- end
250
+ it 'should write a binary string' do
251
+ buffer = [0, 1, 2, 3].pack('C*')
252
+ @prot.write_binary(buffer)
253
+ a = @trans.read(@trans.available)
254
+ expect(a.encoding).to eq(Encoding::BINARY)
255
+ expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
256
+ end
240
257
 
241
- it 'should write a binary string' do
242
- buffer = [0, 1, 2, 3].pack('C*')
243
- @prot.write_binary(buffer)
244
- a = @trans.read(@trans.available)
245
- expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03])
246
- end
258
+ it 'should write a frozen non-binary string without mutating the input' do
259
+ buffer = "abc \u20AC".encode('UTF-8').freeze
260
+ @prot.write_binary(buffer)
261
+ a = @trans.read(@trans.available)
262
+ expect(buffer.encoding).to eq(Encoding::UTF_8)
263
+ expect(buffer).to be_frozen
264
+ expect(a.encoding).to eq(Encoding::BINARY)
265
+ expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC])
247
266
  end
248
267
 
249
268
  it "should error gracefully when trying to write a nil string" do
250
- expect { @prot.write_string(nil) }.to raise_error
269
+ expect { @prot.write_string(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
270
+ end
271
+
272
+ it "should error gracefully when trying to write a nil binary" do
273
+ expect { @prot.write_binary(nil) }.to raise_error(StandardError, 'nil argument not allowed!')
274
+ end
275
+
276
+ it "should write a uuid" do
277
+ @prot.write_uuid("00112233-4455-6677-8899-aabbccddeeff")
278
+ a = @trans.read(@trans.available)
279
+ expect(a.unpack('C*')).to eq([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])
280
+ end
281
+
282
+ it "should read a uuid" do
283
+ @trans.write([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff].pack('C*'))
284
+ uuid = @prot.read_uuid
285
+ expect(uuid).to eq("00112233-4455-6677-8899-aabbccddeeff")
251
286
  end
252
-
287
+
288
+ it "should error gracefully when trying to write an invalid uuid" do
289
+ expect { @prot.write_uuid("invalid") }.to raise_error(Thrift::ProtocolException)
290
+ end
291
+
253
292
  it "should write the message header without version when writes are not strict" do
254
293
  @prot = protocol_class.new(@trans, true, false) # no strict write
255
294
  @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
256
295
  expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021")
257
296
  end
258
-
297
+
259
298
  it "should write the message header with a version when writes are strict" do
260
299
  @prot = protocol_class.new(@trans) # strict write
261
300
  @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
262
301
  expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021")
263
302
  end
264
-
303
+
265
304
  # message footer is a noop
266
-
305
+
267
306
  it "should read a field header" do
268
307
  @trans.write([Thrift::Types::STRING, 3].pack("cn"))
269
308
  expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STRING, 3])
270
309
  end
271
-
310
+
272
311
  # field footer is a noop
273
-
312
+
274
313
  it "should read a stop field" do
275
314
  @trans.write([Thrift::Types::STOP].pack("c"));
276
315
  expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STOP, 0])
@@ -280,36 +319,57 @@ shared_examples_for 'a binary protocol' do
280
319
  @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN"))
281
320
  expect(@prot.read_map_begin).to eq([Thrift::Types::DOUBLE, Thrift::Types::I64, 42])
282
321
  end
283
-
322
+
323
+ it "should reject a negative map size" do
324
+ @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 0xffffffff].pack("ccN"))
325
+ expect { @prot.read_map_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
326
+ expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
327
+ end
328
+ end
329
+
284
330
  # map footer is a noop
285
-
331
+
286
332
  it "should read a list header" do
287
333
  @trans.write([Thrift::Types::STRING, 17].pack("cN"))
288
334
  expect(@prot.read_list_begin).to eq([Thrift::Types::STRING, 17])
289
335
  end
290
-
336
+
337
+ it "should reject a negative list size" do
338
+ @trans.write([Thrift::Types::STRING, 0xffffffff].pack("cN"))
339
+ expect { @prot.read_list_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
340
+ expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
341
+ end
342
+ end
343
+
291
344
  # list footer is a noop
292
-
345
+
293
346
  it "should read a set header" do
294
347
  @trans.write([Thrift::Types::STRING, 17].pack("cN"))
295
348
  expect(@prot.read_set_begin).to eq([Thrift::Types::STRING, 17])
296
349
  end
297
-
350
+
351
+ it "should reject a negative set size" do
352
+ @trans.write([Thrift::Types::STRING, 0xffffffff].pack("cN"))
353
+ expect { @prot.read_set_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
354
+ expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
355
+ end
356
+ end
357
+
298
358
  # set footer is a noop
299
-
359
+
300
360
  it "should read a bool" do
301
361
  @trans.write("\001\000");
302
362
  expect(@prot.read_bool).to eq(true)
303
363
  expect(@prot.read_bool).to eq(false)
304
364
  end
305
-
365
+
306
366
  it "should read a byte" do
307
367
  [-128, -57, -3, 0, 17, 24, 127].each do |i|
308
368
  @trans.write([i].pack("c"))
309
369
  expect(@prot.read_byte).to eq(i)
310
370
  end
311
371
  end
312
-
372
+
313
373
  it "should read an i16" do
314
374
  # try a scattering of values, including min/max
315
375
  [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i|
@@ -317,7 +377,7 @@ shared_examples_for 'a binary protocol' do
317
377
  expect(@prot.read_i16).to eq(i)
318
378
  end
319
379
  end
320
-
380
+
321
381
  it "should read an i32" do
322
382
  # try a scattering of values, including min/max
323
383
  [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i|
@@ -325,7 +385,7 @@ shared_examples_for 'a binary protocol' do
325
385
  expect(@prot.read_i32).to eq(i)
326
386
  end
327
387
  end
328
-
388
+
329
389
  it "should read an i64" do
330
390
  # try a scattering of values, including min/max
331
391
  [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i|
@@ -333,7 +393,7 @@ shared_examples_for 'a binary protocol' do
333
393
  expect(@prot.read_i64).to eq(i)
334
394
  end
335
395
  end
336
-
396
+
337
397
  it "should read a double" do
338
398
  # try a random scattering of values, including min/max
339
399
  [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f|
@@ -342,66 +402,57 @@ shared_examples_for 'a binary protocol' do
342
402
  end
343
403
  end
344
404
 
345
- if RUBY_VERSION >= '1.9'
346
- it 'should read a string' do
347
- # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c'
348
- buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*')
349
- @trans.write(buffer)
350
- a = @prot.read_string
351
- expect(a).to eq('abc'.encode('UTF-8'))
352
- expect(a.encoding).to eq(Encoding::UTF_8)
353
- end
405
+ it 'should read a string' do
406
+ # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c'
407
+ buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*')
408
+ @trans.write(buffer)
409
+ a = @prot.read_string
410
+ expect(a).to eq('abc'.encode('UTF-8'))
411
+ expect(a.encoding).to eq(Encoding::UTF_8)
412
+ end
354
413
 
355
- it 'should read a string containing unicode characters from UTF-8 encoded buffer' do
356
- # i32 of value 3, followed by one character U+20AC made up of three bytes
357
- buffer = [0x00, 0x00, 0x00, 0x03, 0xE2, 0x82, 0xAC].pack('C*')
358
- @trans.write(buffer)
359
- a = @prot.read_string
360
- expect(a).to eq("\u20AC".encode('UTF-8'))
361
- expect(a.encoding).to eq(Encoding::UTF_8)
362
- end
414
+ it 'should read a string containing unicode characters from UTF-8 encoded buffer' do
415
+ # i32 of value 3, followed by one character U+20AC made up of three bytes
416
+ buffer = [0x00, 0x00, 0x00, 0x03, 0xE2, 0x82, 0xAC].pack('C*')
417
+ @trans.write(buffer)
418
+ a = @prot.read_string
419
+ expect(a).to eq("\u20AC".encode('UTF-8'))
420
+ expect(a.encoding).to eq(Encoding::UTF_8)
421
+ end
363
422
 
364
- it 'should read a binary string' do
365
- buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*')
366
- @trans.write(buffer)
367
- a = @prot.read_binary
368
- expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*'))
369
- expect(a.encoding).to eq(Encoding::BINARY)
370
- end
371
- else
372
- it 'should read a string' do
373
- # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c'
374
- buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*')
375
- @trans.write(buffer)
376
- expect(@prot.read_string).to eq('abc')
377
- end
423
+ it 'should read a binary string' do
424
+ buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*')
425
+ @trans.write(buffer)
426
+ a = @prot.read_binary
427
+ expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*'))
428
+ expect(a.encoding).to eq(Encoding::BINARY)
429
+ end
378
430
 
379
- it 'should read a binary string' do
380
- buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*')
381
- @trans.write(buffer)
382
- a = @prot.read_binary
383
- expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*'))
431
+ it "should reject a negative binary size" do
432
+ @trans.write([0xff, 0xff, 0xff, 0xff].pack('C*'))
433
+ expect { @prot.read_binary }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
434
+ expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
384
435
  end
385
436
  end
386
437
 
387
438
  it "should perform a complete rpc with no args or return" do
388
439
  srv_test(
389
- proc {|client| client.send_voidMethod()},
390
- proc {|client| expect(client.recv_voidMethod).to eq(nil)}
440
+ proc { |client| client.send_voidMethod() },
441
+ proc { |client| expect(client.recv_voidMethod).to eq(nil) }
391
442
  )
392
443
  end
393
444
 
394
445
  it "should perform a complete rpc with a primitive return type" do
395
446
  srv_test(
396
- proc {|client| client.send_primitiveMethod()},
397
- proc {|client| expect(client.recv_primitiveMethod).to eq(1)}
447
+ proc { |client| client.send_primitiveMethod() },
448
+ proc { |client| expect(client.recv_primitiveMethod).to eq(1) }
398
449
  )
399
450
  end
400
451
 
401
452
  it "should perform a complete rpc with a struct return type" do
402
453
  srv_test(
403
- proc {|client| client.send_structMethod()},
404
- proc {|client|
454
+ proc { |client| client.send_structMethod() },
455
+ proc { |client|
405
456
  result = client.recv_structMethod
406
457
  result.set_byte_map = nil
407
458
  result.map_byte_map = nil
@@ -413,7 +464,7 @@ shared_examples_for 'a binary protocol' do
413
464
  def get_socket_connection
414
465
  server = Thrift::ServerSocket.new("localhost", 9090)
415
466
  server.listen
416
-
467
+
417
468
  clientside = Thrift::Socket.new("localhost", 9090)
418
469
  clientside.open
419
470
  serverside = server.accept
@@ -443,14 +494,14 @@ shared_examples_for 'a binary protocol' do
443
494
  server.close
444
495
  end
445
496
 
446
- class SrvHandler
497
+ class SrvHandler
447
498
  def voidMethod()
448
499
  end
449
-
500
+
450
501
  def primitiveMethod
451
502
  1
452
503
  end
453
-
504
+
454
505
  def structMethod
455
506
  Fixtures::COMPACT_PROTOCOL_TEST_STRUCT
456
507
  end