thrift 0.22.0 → 0.23.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +175 -17
  3. data/benchmark/benchmark.rb +22 -8
  4. data/benchmark/client.rb +49 -6
  5. data/benchmark/server.rb +45 -7
  6. data/benchmark/thin_server.rb +1 -0
  7. data/ext/binary_protocol_accelerated.c +76 -19
  8. data/ext/compact_protocol.c +80 -15
  9. data/ext/constants.h +12 -0
  10. data/ext/extconf.rb +10 -9
  11. data/ext/memory_buffer.c +7 -7
  12. data/ext/protocol.c +29 -0
  13. data/ext/protocol.h +35 -0
  14. data/ext/struct.c +36 -5
  15. data/ext/thrift_native.c +27 -3
  16. data/lib/thrift/bytes.rb +68 -101
  17. data/lib/thrift/client.rb +61 -9
  18. data/lib/thrift/exceptions.rb +5 -5
  19. data/lib/thrift/multiplexed_processor.rb +6 -6
  20. data/lib/thrift/processor.rb +6 -6
  21. data/lib/thrift/protocol/base_protocol.rb +37 -15
  22. data/lib/thrift/protocol/binary_protocol.rb +25 -9
  23. data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -5
  24. data/lib/thrift/protocol/compact_protocol.rb +61 -37
  25. data/lib/thrift/protocol/header_protocol.rb +320 -0
  26. data/lib/thrift/protocol/json_protocol.rb +26 -16
  27. data/lib/thrift/protocol/multiplexed_protocol.rb +5 -5
  28. data/lib/thrift/protocol/protocol_decorator.rb +12 -4
  29. data/lib/thrift/serializer/deserializer.rb +5 -5
  30. data/lib/thrift/serializer/serializer.rb +4 -5
  31. data/lib/thrift/server/base_server.rb +4 -4
  32. data/lib/thrift/server/mongrel_http_server.rb +6 -6
  33. data/lib/thrift/server/nonblocking_server.rb +8 -8
  34. data/lib/thrift/server/simple_server.rb +4 -4
  35. data/lib/thrift/server/thin_http_server.rb +3 -3
  36. data/lib/thrift/server/thread_pool_server.rb +6 -6
  37. data/lib/thrift/server/threaded_server.rb +4 -4
  38. data/lib/thrift/struct.rb +11 -11
  39. data/lib/thrift/struct_union.rb +19 -9
  40. data/lib/thrift/thrift_native.rb +1 -1
  41. data/lib/thrift/transport/base_server_transport.rb +5 -5
  42. data/lib/thrift/transport/base_transport.rb +12 -12
  43. data/lib/thrift/transport/buffered_transport.rb +6 -6
  44. data/lib/thrift/transport/framed_transport.rb +7 -7
  45. data/lib/thrift/transport/header_transport.rb +516 -0
  46. data/lib/thrift/transport/http_client_transport.rb +1 -1
  47. data/lib/thrift/transport/io_stream_transport.rb +3 -3
  48. data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
  49. data/lib/thrift/transport/server_socket.rb +8 -5
  50. data/lib/thrift/transport/socket.rb +58 -31
  51. data/lib/thrift/transport/ssl_server_socket.rb +1 -1
  52. data/lib/thrift/transport/ssl_socket.rb +2 -2
  53. data/lib/thrift/transport/unix_server_socket.rb +4 -4
  54. data/lib/thrift/transport/unix_socket.rb +6 -6
  55. data/lib/thrift/types.rb +9 -6
  56. data/lib/thrift/union.rb +14 -8
  57. data/lib/thrift/uuid.rb +49 -0
  58. data/lib/thrift.rb +3 -1
  59. data/spec/ThriftSpec.thrift +5 -1
  60. data/spec/base_protocol_spec.rb +1 -2
  61. data/spec/base_transport_spec.rb +6 -7
  62. data/spec/binary_protocol_spec.rb +0 -2
  63. data/spec/binary_protocol_spec_shared.rb +129 -142
  64. data/spec/bytes_spec.rb +57 -118
  65. data/spec/client_spec.rb +85 -19
  66. data/spec/compact_protocol_spec.rb +54 -16
  67. data/spec/constants_demo_spec.rb +101 -0
  68. data/spec/exception_spec.rb +0 -1
  69. data/spec/header_protocol_spec.rb +475 -0
  70. data/spec/header_transport_spec.rb +386 -0
  71. data/spec/http_client_spec.rb +4 -6
  72. data/spec/json_protocol_spec.rb +47 -47
  73. data/spec/namespaced_spec.rb +0 -1
  74. data/spec/nonblocking_server_spec.rb +102 -4
  75. data/spec/processor_spec.rb +0 -1
  76. data/spec/serializer_spec.rb +0 -1
  77. data/spec/server_socket_spec.rb +1 -1
  78. data/spec/server_spec.rb +8 -9
  79. data/spec/socket_spec.rb +0 -1
  80. data/spec/socket_spec_shared.rb +72 -9
  81. data/spec/spec_helper.rb +1 -1
  82. data/spec/ssl_server_socket_spec.rb +12 -1
  83. data/spec/ssl_socket_spec.rb +10 -1
  84. data/spec/struct_nested_containers_spec.rb +1 -2
  85. data/spec/struct_spec.rb +113 -9
  86. data/spec/support/header_protocol_helper.rb +54 -0
  87. data/spec/thin_http_server_spec.rb +3 -18
  88. data/spec/types_spec.rb +25 -26
  89. data/spec/union_spec.rb +69 -11
  90. data/spec/unix_socket_spec.rb +1 -2
  91. data/spec/uuid_validation_spec.rb +238 -0
  92. data/test/fuzz/Makefile.am +173 -0
  93. data/test/fuzz/README.md +149 -0
  94. data/test/fuzz/fuzz_common.rb +95 -0
  95. data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +3 -4
  96. data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +6 -13
  97. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +22 -0
  98. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +22 -0
  99. data/test/fuzz/fuzz_parse_compact_protocol.rb +22 -0
  100. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +22 -0
  101. data/test/fuzz/fuzz_parse_json_protocol.rb +22 -0
  102. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +22 -0
  103. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +22 -0
  104. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +22 -0
  105. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +22 -0
  106. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +22 -0
  107. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +22 -0
  108. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +22 -0
  109. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +22 -0
  110. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +22 -0
  111. data/test/fuzz/fuzz_tracer.rb +28 -0
  112. metadata +106 -37
@@ -0,0 +1,475 @@
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
+ require_relative 'support/header_protocol_helper'
22
+
23
+ describe 'HeaderProtocol' do
24
+ include HeaderProtocolHelper
25
+
26
+ describe Thrift::HeaderProtocol do
27
+ before(:each) do
28
+ @buffer = Thrift::MemoryBufferTransport.new
29
+ @protocol = Thrift::HeaderProtocol.new(@buffer)
30
+ end
31
+
32
+ it "should provide a to_s" do
33
+ expect(@protocol.to_s).to match(/header\(compact/)
34
+ end
35
+
36
+ it "should wrap transport in HeaderTransport" do
37
+ expect(@protocol.trans).to be_a(Thrift::HeaderTransport)
38
+ end
39
+
40
+ it "should use existing HeaderTransport if passed" do
41
+ header_trans = Thrift::HeaderTransport.new(@buffer)
42
+ protocol = Thrift::HeaderProtocol.new(header_trans)
43
+ expect(protocol.trans).to equal(header_trans)
44
+ end
45
+
46
+ describe "header management delegation" do
47
+ it "should delegate get_headers" do
48
+ # Write with headers and read back to populate read headers
49
+ @protocol.set_header("key", "value")
50
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
51
+ @protocol.write_struct_begin("args")
52
+ @protocol.write_field_stop
53
+ @protocol.write_struct_end
54
+ @protocol.write_message_end
55
+ @protocol.trans.flush
56
+
57
+ # Read back
58
+ data = @buffer.read(@buffer.available)
59
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
60
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
61
+
62
+ read_protocol.read_message_begin
63
+ headers = read_protocol.get_headers
64
+ expect(headers["key"]).to eq("value")
65
+ end
66
+
67
+ it "should delegate set_header" do
68
+ expect(@protocol.trans).to receive(:set_header).with("key", "value")
69
+ @protocol.set_header("key", "value")
70
+ end
71
+
72
+ it "should delegate clear_headers" do
73
+ expect(@protocol.trans).to receive(:clear_headers)
74
+ @protocol.clear_headers
75
+ end
76
+
77
+ it "should delegate add_transform" do
78
+ expect(@protocol.trans).to receive(:add_transform).with(Thrift::HeaderTransformID::ZLIB)
79
+ @protocol.add_transform(Thrift::HeaderTransformID::ZLIB)
80
+ end
81
+ end
82
+
83
+ describe "protocol delegation with Binary protocol" do
84
+ before(:each) do
85
+ @buffer = Thrift::MemoryBufferTransport.new
86
+ @protocol = Thrift::HeaderProtocol.new(@buffer, nil, Thrift::HeaderSubprotocolID::BINARY)
87
+ end
88
+
89
+ it "should write message begin" do
90
+ @protocol.write_message_begin("test_method", Thrift::MessageTypes::CALL, 123)
91
+ @protocol.write_message_end
92
+ @protocol.trans.flush
93
+
94
+ # Verify we can read it back
95
+ data = @buffer.read(@buffer.available)
96
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
97
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
98
+
99
+ name, type, seqid = read_protocol.read_message_begin
100
+ expect(name).to eq("test_method")
101
+ expect(type).to eq(Thrift::MessageTypes::CALL)
102
+ expect(seqid).to eq(123)
103
+ end
104
+
105
+ it "should propagate seqid to the outer header frame" do
106
+ @protocol.write_message_begin("test_method", Thrift::MessageTypes::CALL, 123)
107
+ @protocol.write_message_end
108
+ @protocol.trans.flush
109
+
110
+ data = @buffer.read(@buffer.available)
111
+ expect(data[8, 4].unpack('N').first).to eq(123)
112
+ end
113
+
114
+ it "should write and read structs" do
115
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
116
+ @protocol.write_struct_begin("TestStruct")
117
+ @protocol.write_field_begin("field1", Thrift::Types::I32, 1)
118
+ @protocol.write_i32(42)
119
+ @protocol.write_field_end
120
+ @protocol.write_field_stop
121
+ @protocol.write_struct_end
122
+ @protocol.write_message_end
123
+ @protocol.trans.flush
124
+
125
+ data = @buffer.read(@buffer.available)
126
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
127
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
128
+
129
+ read_protocol.read_message_begin
130
+ read_protocol.read_struct_begin
131
+ name, type, id = read_protocol.read_field_begin
132
+ expect(type).to eq(Thrift::Types::I32)
133
+ expect(id).to eq(1)
134
+ value = read_protocol.read_i32
135
+ expect(value).to eq(42)
136
+ end
137
+
138
+ it "should write and read all primitive types" do
139
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
140
+ @protocol.write_struct_begin("TestStruct")
141
+
142
+ @protocol.write_field_begin("bool", Thrift::Types::BOOL, 1)
143
+ @protocol.write_bool(true)
144
+ @protocol.write_field_end
145
+
146
+ @protocol.write_field_begin("byte", Thrift::Types::BYTE, 2)
147
+ @protocol.write_byte(127)
148
+ @protocol.write_field_end
149
+
150
+ @protocol.write_field_begin("i16", Thrift::Types::I16, 3)
151
+ @protocol.write_i16(32767)
152
+ @protocol.write_field_end
153
+
154
+ @protocol.write_field_begin("i32", Thrift::Types::I32, 4)
155
+ @protocol.write_i32(2147483647)
156
+ @protocol.write_field_end
157
+
158
+ @protocol.write_field_begin("i64", Thrift::Types::I64, 5)
159
+ @protocol.write_i64(9223372036854775807)
160
+ @protocol.write_field_end
161
+
162
+ @protocol.write_field_begin("double", Thrift::Types::DOUBLE, 6)
163
+ @protocol.write_double(3.14159)
164
+ @protocol.write_field_end
165
+
166
+ @protocol.write_field_begin("string", Thrift::Types::STRING, 7)
167
+ @protocol.write_string("hello")
168
+ @protocol.write_field_end
169
+
170
+ @protocol.write_field_stop
171
+ @protocol.write_struct_end
172
+ @protocol.write_message_end
173
+ @protocol.trans.flush
174
+
175
+ data = @buffer.read(@buffer.available)
176
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
177
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
178
+
179
+ read_protocol.read_message_begin
180
+ read_protocol.read_struct_begin
181
+
182
+ # bool
183
+ _, type, _ = read_protocol.read_field_begin
184
+ expect(type).to eq(Thrift::Types::BOOL)
185
+ expect(read_protocol.read_bool).to eq(true)
186
+ read_protocol.read_field_end
187
+
188
+ # byte
189
+ _, type, _ = read_protocol.read_field_begin
190
+ expect(type).to eq(Thrift::Types::BYTE)
191
+ expect(read_protocol.read_byte).to eq(127)
192
+ read_protocol.read_field_end
193
+
194
+ # i16
195
+ _, type, _ = read_protocol.read_field_begin
196
+ expect(type).to eq(Thrift::Types::I16)
197
+ expect(read_protocol.read_i16).to eq(32767)
198
+ read_protocol.read_field_end
199
+
200
+ # i32
201
+ _, type, _ = read_protocol.read_field_begin
202
+ expect(type).to eq(Thrift::Types::I32)
203
+ expect(read_protocol.read_i32).to eq(2147483647)
204
+ read_protocol.read_field_end
205
+
206
+ # i64
207
+ _, type, _ = read_protocol.read_field_begin
208
+ expect(type).to eq(Thrift::Types::I64)
209
+ expect(read_protocol.read_i64).to eq(9223372036854775807)
210
+ read_protocol.read_field_end
211
+
212
+ # double
213
+ _, type, _ = read_protocol.read_field_begin
214
+ expect(type).to eq(Thrift::Types::DOUBLE)
215
+ expect(read_protocol.read_double).to be_within(0.00001).of(3.14159)
216
+ read_protocol.read_field_end
217
+
218
+ # string
219
+ _, type, _ = read_protocol.read_field_begin
220
+ expect(type).to eq(Thrift::Types::STRING)
221
+ expect(read_protocol.read_string).to eq("hello")
222
+ read_protocol.read_field_end
223
+ end
224
+ end
225
+
226
+ describe "protocol delegation with Compact protocol" do
227
+ before(:each) do
228
+ @buffer = Thrift::MemoryBufferTransport.new
229
+ @protocol = Thrift::HeaderProtocol.new(
230
+ @buffer,
231
+ nil,
232
+ Thrift::HeaderSubprotocolID::COMPACT
233
+ )
234
+ end
235
+
236
+ it "should use Compact protocol" do
237
+ expect(@protocol.to_s).to match(/header\(compact/)
238
+ end
239
+
240
+ it "should write and read with Compact protocol" do
241
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
242
+ @protocol.write_struct_begin("Test")
243
+ @protocol.write_field_begin("field", Thrift::Types::I32, 1)
244
+ @protocol.write_i32(999)
245
+ @protocol.write_field_end
246
+ @protocol.write_field_stop
247
+ @protocol.write_struct_end
248
+ @protocol.write_message_end
249
+ @protocol.trans.flush
250
+
251
+ data = @buffer.read(@buffer.available)
252
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
253
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer, nil, Thrift::HeaderSubprotocolID::COMPACT)
254
+
255
+ read_protocol.read_message_begin
256
+ read_protocol.read_struct_begin
257
+ _, type, _ = read_protocol.read_field_begin
258
+ expect(type).to eq(Thrift::Types::I32)
259
+ expect(read_protocol.read_i32).to eq(999)
260
+ end
261
+ end
262
+
263
+ describe "unknown protocol handling" do
264
+ it "should write an exception response on unknown protocol id" do
265
+ header_data = +""
266
+ header_data << varint32(0x10)
267
+ header_data << varint32(0)
268
+ frame = build_header_frame(header_data)
269
+
270
+ buffer = Thrift::MemoryBufferTransport.new(frame)
271
+ protocol = Thrift::HeaderProtocol.new(buffer)
272
+
273
+ expect { protocol.read_message_begin }.to raise_error(Thrift::ProtocolException)
274
+
275
+ response = buffer.read(buffer.available)
276
+ expect(response.bytesize).to be > 0
277
+ magic = response[4, 2].unpack('n').first
278
+ expect(magic).to eq(Thrift::HeaderTransport::HEADER_MAGIC)
279
+ end
280
+ end
281
+
282
+ describe "protocol auto-detection with legacy frames" do
283
+ it "should detect framed compact messages" do
284
+ write_buffer = Thrift::MemoryBufferTransport.new
285
+ write_protocol = Thrift::CompactProtocol.new(write_buffer)
286
+
287
+ write_protocol.write_message_begin("legacy_framed", Thrift::MessageTypes::CALL, 7)
288
+ write_protocol.write_struct_begin("Args")
289
+ write_protocol.write_field_stop
290
+ write_protocol.write_struct_end
291
+ write_protocol.write_message_end
292
+
293
+ payload = write_buffer.read(write_buffer.available)
294
+ framed = [payload.bytesize].pack('N') + payload
295
+
296
+ read_buffer = Thrift::MemoryBufferTransport.new(framed)
297
+ protocol = Thrift::HeaderProtocol.new(read_buffer)
298
+
299
+ name, type, seqid = protocol.read_message_begin
300
+ expect(name).to eq("legacy_framed")
301
+ expect(type).to eq(Thrift::MessageTypes::CALL)
302
+ expect(seqid).to eq(7)
303
+
304
+ protocol.read_struct_begin
305
+ _, field_type, _ = protocol.read_field_begin
306
+ expect(field_type).to eq(Thrift::Types::STOP)
307
+ protocol.read_struct_end
308
+ protocol.read_message_end
309
+ end
310
+
311
+ it "should detect unframed compact messages" do
312
+ write_buffer = Thrift::MemoryBufferTransport.new
313
+ write_protocol = Thrift::CompactProtocol.new(write_buffer)
314
+
315
+ write_protocol.write_message_begin("legacy_unframed", Thrift::MessageTypes::CALL, 9)
316
+ write_protocol.write_struct_begin("Args")
317
+ write_protocol.write_field_stop
318
+ write_protocol.write_struct_end
319
+ write_protocol.write_message_end
320
+
321
+ payload = write_buffer.read(write_buffer.available)
322
+
323
+ read_buffer = Thrift::MemoryBufferTransport.new(payload)
324
+ protocol = Thrift::HeaderProtocol.new(read_buffer)
325
+
326
+ name, type, seqid = protocol.read_message_begin
327
+ expect(name).to eq("legacy_unframed")
328
+ expect(type).to eq(Thrift::MessageTypes::CALL)
329
+ expect(seqid).to eq(9)
330
+
331
+ protocol.read_struct_begin
332
+ _, field_type, _ = protocol.read_field_begin
333
+ expect(field_type).to eq(Thrift::Types::STOP)
334
+ protocol.read_struct_end
335
+ protocol.read_message_end
336
+ end
337
+ end
338
+
339
+ describe "with compression" do
340
+ it "should work with ZLIB transform" do
341
+ @protocol.add_transform(Thrift::HeaderTransformID::ZLIB)
342
+
343
+ @protocol.write_message_begin("compressed_test", Thrift::MessageTypes::CALL, 42)
344
+ @protocol.write_struct_begin("Args")
345
+ @protocol.write_field_begin("data", Thrift::Types::STRING, 1)
346
+ @protocol.write_string("a" * 100) # Compressible data
347
+ @protocol.write_field_end
348
+ @protocol.write_field_stop
349
+ @protocol.write_struct_end
350
+ @protocol.write_message_end
351
+ @protocol.trans.flush
352
+
353
+ data = @buffer.read(@buffer.available)
354
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
355
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
356
+
357
+ name, type, seqid = read_protocol.read_message_begin
358
+ expect(name).to eq("compressed_test")
359
+ expect(seqid).to eq(42)
360
+
361
+ read_protocol.read_struct_begin
362
+ _, _, _ = read_protocol.read_field_begin
363
+ result = read_protocol.read_string
364
+ expect(result).to eq("a" * 100)
365
+ end
366
+ end
367
+
368
+ describe "containers" do
369
+ it "should write and read lists" do
370
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
371
+ @protocol.write_struct_begin("Test")
372
+ @protocol.write_field_begin("list", Thrift::Types::LIST, 1)
373
+ @protocol.write_list_begin(Thrift::Types::I32, 3)
374
+ @protocol.write_i32(1)
375
+ @protocol.write_i32(2)
376
+ @protocol.write_i32(3)
377
+ @protocol.write_list_end
378
+ @protocol.write_field_end
379
+ @protocol.write_field_stop
380
+ @protocol.write_struct_end
381
+ @protocol.write_message_end
382
+ @protocol.trans.flush
383
+
384
+ data = @buffer.read(@buffer.available)
385
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
386
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
387
+
388
+ read_protocol.read_message_begin
389
+ read_protocol.read_struct_begin
390
+ _, _, _ = read_protocol.read_field_begin
391
+ etype, size = read_protocol.read_list_begin
392
+ expect(etype).to eq(Thrift::Types::I32)
393
+ expect(size).to eq(3)
394
+ expect(read_protocol.read_i32).to eq(1)
395
+ expect(read_protocol.read_i32).to eq(2)
396
+ expect(read_protocol.read_i32).to eq(3)
397
+ end
398
+
399
+ it "should write and read maps" do
400
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
401
+ @protocol.write_struct_begin("Test")
402
+ @protocol.write_field_begin("map", Thrift::Types::MAP, 1)
403
+ @protocol.write_map_begin(Thrift::Types::STRING, Thrift::Types::I32, 2)
404
+ @protocol.write_string("a")
405
+ @protocol.write_i32(1)
406
+ @protocol.write_string("b")
407
+ @protocol.write_i32(2)
408
+ @protocol.write_map_end
409
+ @protocol.write_field_end
410
+ @protocol.write_field_stop
411
+ @protocol.write_struct_end
412
+ @protocol.write_message_end
413
+ @protocol.trans.flush
414
+
415
+ data = @buffer.read(@buffer.available)
416
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
417
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
418
+
419
+ read_protocol.read_message_begin
420
+ read_protocol.read_struct_begin
421
+ _, _, _ = read_protocol.read_field_begin
422
+ ktype, vtype, size = read_protocol.read_map_begin
423
+ expect(ktype).to eq(Thrift::Types::STRING)
424
+ expect(vtype).to eq(Thrift::Types::I32)
425
+ expect(size).to eq(2)
426
+ end
427
+
428
+ it "should write and read sets" do
429
+ @protocol.write_message_begin("test", Thrift::MessageTypes::CALL, 1)
430
+ @protocol.write_struct_begin("Test")
431
+ @protocol.write_field_begin("set", Thrift::Types::SET, 1)
432
+ @protocol.write_set_begin(Thrift::Types::STRING, 2)
433
+ @protocol.write_string("x")
434
+ @protocol.write_string("y")
435
+ @protocol.write_set_end
436
+ @protocol.write_field_end
437
+ @protocol.write_field_stop
438
+ @protocol.write_struct_end
439
+ @protocol.write_message_end
440
+ @protocol.trans.flush
441
+
442
+ data = @buffer.read(@buffer.available)
443
+ read_buffer = Thrift::MemoryBufferTransport.new(data)
444
+ read_protocol = Thrift::HeaderProtocol.new(read_buffer)
445
+
446
+ read_protocol.read_message_begin
447
+ read_protocol.read_struct_begin
448
+ _, _, _ = read_protocol.read_field_begin
449
+ etype, size = read_protocol.read_set_begin
450
+ expect(etype).to eq(Thrift::Types::STRING)
451
+ expect(size).to eq(2)
452
+ end
453
+ end
454
+ end
455
+
456
+ describe Thrift::HeaderProtocolFactory do
457
+ it "should create HeaderProtocol" do
458
+ factory = Thrift::HeaderProtocolFactory.new
459
+ buffer = Thrift::MemoryBufferTransport.new
460
+ protocol = factory.get_protocol(buffer)
461
+ expect(protocol).to be_a(Thrift::HeaderProtocol)
462
+ end
463
+
464
+ it "should provide a reasonable to_s" do
465
+ expect(Thrift::HeaderProtocolFactory.new.to_s).to eq("header")
466
+ end
467
+
468
+ it "should pass configuration to protocol" do
469
+ factory = Thrift::HeaderProtocolFactory.new(nil, Thrift::HeaderSubprotocolID::COMPACT)
470
+ buffer = Thrift::MemoryBufferTransport.new
471
+ protocol = factory.get_protocol(buffer)
472
+ expect(protocol.to_s).to match(/compact/)
473
+ end
474
+ end
475
+ end