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.
- checksums.yaml +4 -4
- data/README.md +235 -17
- data/benchmark/benchmark.rb +23 -8
- data/benchmark/client.rb +50 -6
- data/benchmark/server.rb +46 -7
- data/benchmark/thin_server.rb +2 -0
- data/ext/binary_protocol_accelerated.c +154 -42
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +138 -45
- data/ext/constants.h +12 -0
- data/ext/extconf.rb +17 -8
- data/ext/memory_buffer.c +44 -7
- data/ext/protocol.c +29 -0
- data/ext/protocol.h +35 -0
- data/ext/struct.c +48 -17
- data/ext/thrift_native.c +28 -3
- data/lib/thrift/bytes.rb +70 -100
- data/lib/thrift/client.rb +54 -13
- data/lib/thrift/exceptions.rb +6 -5
- data/lib/thrift/multiplexed_processor.rb +20 -10
- data/lib/thrift/processor.rb +7 -6
- data/lib/thrift/protocol/base_protocol.rb +52 -21
- data/lib/thrift/protocol/binary_protocol.rb +65 -20
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -5
- data/lib/thrift/protocol/compact_protocol.rb +76 -41
- data/lib/thrift/protocol/header_protocol.rb +321 -0
- data/lib/thrift/protocol/json_protocol.rb +44 -27
- data/lib/thrift/protocol/multiplexed_protocol.rb +6 -5
- data/lib/thrift/protocol/protocol_decorator.rb +13 -4
- data/lib/thrift/serializer/deserializer.rb +6 -5
- data/lib/thrift/serializer/serializer.rb +5 -5
- data/lib/thrift/server/base_server.rb +5 -4
- data/lib/thrift/server/mongrel_http_server.rb +7 -6
- data/lib/thrift/server/nonblocking_server.rb +35 -9
- data/lib/thrift/server/simple_server.rb +13 -5
- data/lib/thrift/server/thin_http_server.rb +4 -3
- data/lib/thrift/server/thread_pool_server.rb +7 -6
- data/lib/thrift/server/threaded_server.rb +13 -5
- data/lib/thrift/struct.rb +12 -11
- data/lib/thrift/struct_union.rb +14 -9
- data/lib/thrift/thrift_native.rb +3 -2
- data/lib/thrift/transport/base_server_transport.rb +8 -5
- data/lib/thrift/transport/base_transport.rb +18 -14
- data/lib/thrift/transport/buffered_transport.rb +7 -6
- data/lib/thrift/transport/framed_transport.rb +8 -7
- data/lib/thrift/transport/header_transport.rb +562 -0
- data/lib/thrift/transport/http_client_transport.rb +2 -1
- data/lib/thrift/transport/io_stream_transport.rb +4 -3
- data/lib/thrift/transport/memory_buffer_transport.rb +13 -6
- data/lib/thrift/transport/server_socket.rb +14 -8
- data/lib/thrift/transport/socket.rb +126 -60
- data/lib/thrift/transport/ssl_server_socket.rb +4 -3
- data/lib/thrift/transport/ssl_socket.rb +45 -13
- data/lib/thrift/transport/unix_server_socket.rb +9 -5
- data/lib/thrift/transport/unix_socket.rb +7 -6
- data/lib/thrift/types.rb +10 -6
- data/lib/thrift/union.rb +15 -8
- data/lib/thrift/uuid.rb +50 -0
- data/lib/thrift.rb +4 -1
- data/spec/ThriftSpec.thrift +21 -1
- data/spec/base_protocol_spec.rb +21 -2
- data/spec/base_transport_spec.rb +48 -8
- data/spec/binary_protocol_accelerated_spec.rb +1 -0
- data/spec/binary_protocol_spec.rb +1 -2
- data/spec/binary_protocol_spec_shared.rb +206 -155
- data/spec/bytes_spec.rb +71 -114
- data/spec/client_spec.rb +86 -19
- data/spec/compact_protocol_spec.rb +153 -16
- data/spec/constants_demo_spec.rb +102 -0
- data/spec/exception_spec.rb +1 -1
- data/spec/flat_spec.rb +1 -0
- data/spec/header_protocol_spec.rb +476 -0
- data/spec/header_transport_spec.rb +431 -0
- data/spec/http_client_spec.rb +5 -6
- data/spec/json_protocol_spec.rb +69 -47
- data/spec/multiplexed_processor_spec.rb +75 -0
- data/spec/namespaced_spec.rb +1 -1
- data/spec/nonblocking_server_spec.rb +174 -8
- data/spec/processor_spec.rb +1 -1
- data/spec/recursion_depth_spec.rb +223 -0
- data/spec/serializer_spec.rb +1 -1
- data/spec/server_socket_spec.rb +38 -1
- data/spec/server_spec.rb +60 -9
- data/spec/socket_spec.rb +119 -13
- data/spec/socket_spec_shared.rb +73 -9
- data/spec/spec_helper.rb +2 -1
- data/spec/ssl_server_socket_spec.rb +52 -1
- data/spec/ssl_socket_spec.rb +181 -11
- data/spec/struct_nested_containers_spec.rb +2 -2
- data/spec/struct_spec.rb +114 -9
- data/spec/support/header_protocol_helper.rb +55 -0
- data/spec/thin_http_server_spec.rb +4 -18
- data/spec/types_spec.rb +26 -26
- data/spec/union_spec.rb +70 -11
- data/spec/unix_socket_spec.rb +17 -2
- data/spec/uuid_validation_spec.rb +239 -0
- data/test/fuzz/Makefile +779 -0
- data/test/fuzz/Makefile.am +173 -0
- data/test/fuzz/Makefile.in +775 -0
- data/test/fuzz/README.md +149 -0
- data/test/fuzz/fuzz_common.rb +96 -0
- data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +4 -4
- data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +7 -13
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +23 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +23 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_tracer.rb +29 -0
- metadata +105 -70
data/spec/json_protocol_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
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
|
|
@@ -21,7 +22,6 @@
|
|
|
21
22
|
require 'spec_helper'
|
|
22
23
|
|
|
23
24
|
describe 'JsonProtocol' do
|
|
24
|
-
|
|
25
25
|
describe Thrift::JsonProtocol do
|
|
26
26
|
before(:each) do
|
|
27
27
|
@trans = Thrift::MemoryBufferTransport.new
|
|
@@ -221,25 +221,18 @@ describe 'JsonProtocol' do
|
|
|
221
221
|
expect(@trans.read(@trans.available)).to eq("\"-Infinity\"")
|
|
222
222
|
end
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
end
|
|
224
|
+
it 'should write string' do
|
|
225
|
+
@prot.write_string('this is a test string')
|
|
226
|
+
a = @trans.read(@trans.available)
|
|
227
|
+
expect(a).to eq('"this is a test string"'.b)
|
|
228
|
+
expect(a.encoding).to eq(Encoding::BINARY)
|
|
229
|
+
end
|
|
231
230
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
end
|
|
238
|
-
else
|
|
239
|
-
it 'should write string' do
|
|
240
|
-
@prot.write_string('this is a test string')
|
|
241
|
-
expect(@trans.read(@trans.available)).to eq('"this is a test string"')
|
|
242
|
-
end
|
|
231
|
+
it 'should write string with unicode characters' do
|
|
232
|
+
@prot.write_string("this is a test string with unicode characters: \u20AC \u20AD")
|
|
233
|
+
a = @trans.read(@trans.available)
|
|
234
|
+
expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".b)
|
|
235
|
+
expect(a.encoding).to eq(Encoding::BINARY)
|
|
243
236
|
end
|
|
244
237
|
|
|
245
238
|
it "should write binary" do
|
|
@@ -252,9 +245,14 @@ describe 'JsonProtocol' do
|
|
|
252
245
|
expect(@trans.read(@trans.available)).to eq("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"")
|
|
253
246
|
end
|
|
254
247
|
|
|
248
|
+
it "should write a uuid" do
|
|
249
|
+
@prot.write_uuid("00112233-4455-6677-8899-aabbccddeeff")
|
|
250
|
+
expect(@trans.read(@trans.available)).to eq("\"00112233-4455-6677-8899-aabbccddeeff\"")
|
|
251
|
+
end
|
|
252
|
+
|
|
255
253
|
it "should get type name for type id" do
|
|
256
|
-
expect {@prot.get_type_name_for_type_id(Thrift::Types::STOP)}.to raise_error(NotImplementedError)
|
|
257
|
-
expect {@prot.get_type_name_for_type_id(Thrift::Types::VOID)}.to raise_error(NotImplementedError)
|
|
254
|
+
expect { @prot.get_type_name_for_type_id(Thrift::Types::STOP) }.to raise_error(NotImplementedError)
|
|
255
|
+
expect { @prot.get_type_name_for_type_id(Thrift::Types::VOID) }.to raise_error(NotImplementedError)
|
|
258
256
|
expect(@prot.get_type_name_for_type_id(Thrift::Types::BOOL)).to eq("tf")
|
|
259
257
|
expect(@prot.get_type_name_for_type_id(Thrift::Types::BYTE)).to eq("i8")
|
|
260
258
|
expect(@prot.get_type_name_for_type_id(Thrift::Types::DOUBLE)).to eq("dbl")
|
|
@@ -269,7 +267,7 @@ describe 'JsonProtocol' do
|
|
|
269
267
|
end
|
|
270
268
|
|
|
271
269
|
it "should get type id for type name" do
|
|
272
|
-
expect {@prot.get_type_id_for_type_name("pp")}.to raise_error(NotImplementedError)
|
|
270
|
+
expect { @prot.get_type_id_for_type_name("pp") }.to raise_error(NotImplementedError)
|
|
273
271
|
expect(@prot.get_type_id_for_type_name("tf")).to eq(Thrift::Types::BOOL)
|
|
274
272
|
expect(@prot.get_type_id_for_type_name("i8")).to eq(Thrift::Types::BYTE)
|
|
275
273
|
expect(@prot.get_type_id_for_type_name("dbl")).to eq(Thrift::Types::DOUBLE)
|
|
@@ -285,7 +283,7 @@ describe 'JsonProtocol' do
|
|
|
285
283
|
|
|
286
284
|
it "should read json syntax char" do
|
|
287
285
|
@trans.write('F')
|
|
288
|
-
expect {@prot.read_json_syntax_char('G')}.to raise_error(Thrift::ProtocolException)
|
|
286
|
+
expect { @prot.read_json_syntax_char('G') }.to raise_error(Thrift::ProtocolException)
|
|
289
287
|
@trans.write('H')
|
|
290
288
|
@prot.read_json_syntax_char('H')
|
|
291
289
|
end
|
|
@@ -321,7 +319,7 @@ describe 'JsonProtocol' do
|
|
|
321
319
|
|
|
322
320
|
it "should read json string" do
|
|
323
321
|
@trans.write("\"\\P")
|
|
324
|
-
expect {@prot.read_json_string(false)}.to raise_error(Thrift::ProtocolException)
|
|
322
|
+
expect { @prot.read_json_string(false) }.to raise_error(Thrift::ProtocolException)
|
|
325
323
|
|
|
326
324
|
@trans.write("\"this is a test string\"")
|
|
327
325
|
expect(@prot.read_json_string).to eq("this is a test string")
|
|
@@ -358,7 +356,7 @@ describe 'JsonProtocol' do
|
|
|
358
356
|
|
|
359
357
|
it "should read json integer" do
|
|
360
358
|
@trans.write("1.45\"\"")
|
|
361
|
-
expect {@prot.read_json_integer}.to raise_error(Thrift::ProtocolException)
|
|
359
|
+
expect { @prot.read_json_integer }.to raise_error(Thrift::ProtocolException)
|
|
362
360
|
@prot.read_string
|
|
363
361
|
|
|
364
362
|
@trans.write("1453T")
|
|
@@ -367,11 +365,11 @@ describe 'JsonProtocol' do
|
|
|
367
365
|
|
|
368
366
|
it "should read json double" do
|
|
369
367
|
@trans.write("1.45e3e01\"\"")
|
|
370
|
-
expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException)
|
|
368
|
+
expect { @prot.read_json_double }.to raise_error(Thrift::ProtocolException)
|
|
371
369
|
@prot.read_string
|
|
372
370
|
|
|
373
371
|
@trans.write("\"1.453e01\"")
|
|
374
|
-
expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException)
|
|
372
|
+
expect { @prot.read_json_double }.to raise_error(Thrift::ProtocolException)
|
|
375
373
|
|
|
376
374
|
@trans.write("1.453e01\"\"")
|
|
377
375
|
expect(@prot.read_json_double).to eq(14.53)
|
|
@@ -409,7 +407,7 @@ describe 'JsonProtocol' do
|
|
|
409
407
|
|
|
410
408
|
it "should read_message_begin" do
|
|
411
409
|
@trans.write("[2,")
|
|
412
|
-
expect {@prot.read_message_begin}.to raise_error(Thrift::ProtocolException)
|
|
410
|
+
expect { @prot.read_message_begin }.to raise_error(Thrift::ProtocolException)
|
|
413
411
|
|
|
414
412
|
@trans.write("[1,\"name\",12,32\"\"")
|
|
415
413
|
expect(@prot.read_message_begin).to eq(["name", 12, 32])
|
|
@@ -445,6 +443,13 @@ describe 'JsonProtocol' do
|
|
|
445
443
|
expect(@prot.read_map_begin).to eq([12, 15, 2])
|
|
446
444
|
end
|
|
447
445
|
|
|
446
|
+
it "should reject a negative map size" do
|
|
447
|
+
@trans.write("[\"rec\",\"lst\",-1,{")
|
|
448
|
+
expect { @prot.read_map_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
449
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
448
453
|
it "should read map end" do
|
|
449
454
|
@trans.write("}]")
|
|
450
455
|
expect(@prot.read_map_end).to eq(nil)
|
|
@@ -455,6 +460,13 @@ describe 'JsonProtocol' do
|
|
|
455
460
|
expect(@prot.read_list_begin).to eq([12, 2])
|
|
456
461
|
end
|
|
457
462
|
|
|
463
|
+
it "should reject a negative list size" do
|
|
464
|
+
@trans.write("[\"rec\",-1\"\"")
|
|
465
|
+
expect { @prot.read_list_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
466
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
458
470
|
it "should read list end" do
|
|
459
471
|
@trans.write("]")
|
|
460
472
|
expect(@prot.read_list_end).to eq(nil)
|
|
@@ -465,6 +477,13 @@ describe 'JsonProtocol' do
|
|
|
465
477
|
expect(@prot.read_set_begin).to eq([12, 2])
|
|
466
478
|
end
|
|
467
479
|
|
|
480
|
+
it "should reject a negative set size" do
|
|
481
|
+
@trans.write("[\"rec\",-1\"\"")
|
|
482
|
+
expect { @prot.read_set_begin }.to raise_error(Thrift::ProtocolException, "Negative size") do |e|
|
|
483
|
+
expect(e.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
468
487
|
it "should read set end" do
|
|
469
488
|
@trans.write("]")
|
|
470
489
|
expect(@prot.read_set_end).to eq(nil)
|
|
@@ -504,25 +523,18 @@ describe 'JsonProtocol' do
|
|
|
504
523
|
expect(@prot.read_double).to eq(12.23)
|
|
505
524
|
end
|
|
506
525
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
end
|
|
526
|
+
it 'should read string' do
|
|
527
|
+
@trans.write('"this is a test string"'.b)
|
|
528
|
+
a = @prot.read_string
|
|
529
|
+
expect(a).to eq('this is a test string')
|
|
530
|
+
expect(a.encoding).to eq(Encoding::UTF_8)
|
|
531
|
+
end
|
|
514
532
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
end
|
|
521
|
-
else
|
|
522
|
-
it 'should read string' do
|
|
523
|
-
@trans.write('"this is a test string"')
|
|
524
|
-
expect(@prot.read_string).to eq('this is a test string')
|
|
525
|
-
end
|
|
533
|
+
it 'should read string with unicode characters' do
|
|
534
|
+
@trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.b)
|
|
535
|
+
a = @prot.read_string
|
|
536
|
+
expect(a).to eq("this is a test string with unicode characters: \u20AC \u20AD")
|
|
537
|
+
expect(a.encoding).to eq(Encoding::UTF_8)
|
|
526
538
|
end
|
|
527
539
|
|
|
528
540
|
it "should read binary" do
|
|
@@ -534,7 +546,17 @@ describe 'JsonProtocol' do
|
|
|
534
546
|
@trans.write("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"")
|
|
535
547
|
expect(@prot.read_binary.bytes.to_a).to eq((0...256).to_a)
|
|
536
548
|
end
|
|
537
|
-
|
|
549
|
+
|
|
550
|
+
it "should read a uuid" do
|
|
551
|
+
@trans.write("\"00112233-4455-6677-8899-aabbccddeeff\"")
|
|
552
|
+
expect(@prot.read_uuid).to eq("00112233-4455-6677-8899-aabbccddeeff")
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "should normalize uppercase uuid on read" do
|
|
556
|
+
@trans.write("\"00112233-4455-6677-8899-AABBCCDDEEFF\"")
|
|
557
|
+
expect(@prot.read_uuid).to eq("00112233-4455-6677-8899-aabbccddeeff")
|
|
558
|
+
end
|
|
559
|
+
|
|
538
560
|
it "should provide a reasonable to_s" do
|
|
539
561
|
expect(@prot.to_s).to eq("json(memory)")
|
|
540
562
|
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
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::MultiplexedProcessor do
|
|
24
|
+
before(:each) do
|
|
25
|
+
@processor = Thrift::MultiplexedProcessor.new
|
|
26
|
+
@iprot = double('MockInputProtocol')
|
|
27
|
+
@oprot = double('MockOutputProtocol')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'dispatches multiplexed calls to the registered service processor' do
|
|
31
|
+
actual_processor = double('ActualProcessor')
|
|
32
|
+
@processor.register_processor('ThriftTest', actual_processor)
|
|
33
|
+
|
|
34
|
+
expect(@iprot).to receive(:read_message_begin).and_return(['ThriftTest:testVoid', Thrift::MessageTypes::CALL, 1])
|
|
35
|
+
expect(actual_processor).to receive(:process) do |stored_protocol, oprot|
|
|
36
|
+
expect(stored_protocol.read_message_begin).to eq(['testVoid', Thrift::MessageTypes::CALL, 1])
|
|
37
|
+
expect(oprot).to eq(@oprot)
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
expect(@processor.process(@iprot, @oprot)).to eq(true)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'dispatches non-multiplexed calls to the default processor' do
|
|
45
|
+
default_processor = double('DefaultProcessor')
|
|
46
|
+
@processor.register_default(default_processor)
|
|
47
|
+
|
|
48
|
+
expect(@iprot).to receive(:read_message_begin).and_return(['testVoid', Thrift::MessageTypes::CALL, 2])
|
|
49
|
+
expect(default_processor).to receive(:process) do |stored_protocol, oprot|
|
|
50
|
+
expect(stored_protocol.read_message_begin).to eq(['testVoid', Thrift::MessageTypes::CALL, 2])
|
|
51
|
+
expect(oprot).to eq(@oprot)
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
expect(@processor.process(@iprot, @oprot)).to eq(true)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'raises for non-multiplexed calls when no default processor is registered' do
|
|
59
|
+
expect(@iprot).to receive(:read_message_begin).and_return(['testVoid', Thrift::MessageTypes::CALL, 3])
|
|
60
|
+
|
|
61
|
+
expect { @processor.process(@iprot, @oprot) }.to raise_error(
|
|
62
|
+
Thrift::Exception,
|
|
63
|
+
'Service name not found in message name: testVoid. Did you forget to use a Thrift::Protocol::MultiplexedProtocol in your client?'
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'raises for unknown multiplexed service names' do
|
|
68
|
+
expect(@iprot).to receive(:read_message_begin).and_return(['Missing:testVoid', Thrift::MessageTypes::CALL, 4])
|
|
69
|
+
|
|
70
|
+
expect { @processor.process(@iprot, @oprot) }.to raise_error(
|
|
71
|
+
Thrift::Exception,
|
|
72
|
+
'Service name not found: Missing. Did you forget to call Thrift::MultiplexedProcessor#register_processor?'
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
end
|
data/spec/namespaced_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -63,5 +64,4 @@ describe 'namespaced generation' do
|
|
|
63
64
|
it "extended a service" do
|
|
64
65
|
require "extended/extended_service"
|
|
65
66
|
end
|
|
66
|
-
|
|
67
67
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -18,9 +19,9 @@
|
|
|
18
19
|
#
|
|
19
20
|
|
|
20
21
|
require 'spec_helper'
|
|
22
|
+
require 'timeout'
|
|
21
23
|
|
|
22
24
|
describe 'NonblockingServer' do
|
|
23
|
-
|
|
24
25
|
class Handler
|
|
25
26
|
def initialize
|
|
26
27
|
@queue = Queue.new
|
|
@@ -76,7 +77,7 @@ describe 'NonblockingServer' do
|
|
|
76
77
|
@transport.read(sz)
|
|
77
78
|
end
|
|
78
79
|
|
|
79
|
-
def write(buf,sz=nil)
|
|
80
|
+
def write(buf, sz = nil)
|
|
80
81
|
@transport.write(buf, sz)
|
|
81
82
|
end
|
|
82
83
|
|
|
@@ -101,7 +102,7 @@ describe 'NonblockingServer' do
|
|
|
101
102
|
|
|
102
103
|
describe Thrift::NonblockingServer do
|
|
103
104
|
before(:each) do
|
|
104
|
-
@port =
|
|
105
|
+
@port = available_port
|
|
105
106
|
handler = Handler.new
|
|
106
107
|
processor = SpecNamespace::NonblockingService::Processor.new(handler)
|
|
107
108
|
queue = Queue.new
|
|
@@ -121,6 +122,7 @@ describe 'NonblockingServer' do
|
|
|
121
122
|
end
|
|
122
123
|
end
|
|
123
124
|
queue.pop
|
|
125
|
+
wait_until_listening(@transport, @server_thread)
|
|
124
126
|
|
|
125
127
|
@clients = []
|
|
126
128
|
@catch_exceptions = false
|
|
@@ -128,9 +130,11 @@ describe 'NonblockingServer' do
|
|
|
128
130
|
|
|
129
131
|
after(:each) do
|
|
130
132
|
@clients.each { |client, trans| trans.close }
|
|
131
|
-
|
|
132
|
-
@server_thread.
|
|
133
|
-
@
|
|
133
|
+
@server.shutdown(1, false) if @server
|
|
134
|
+
@server_thread.join(2) if @server_thread
|
|
135
|
+
@server_thread.kill if @server_thread && @server_thread.alive?
|
|
136
|
+
@server_thread.join(2) if @server_thread
|
|
137
|
+
@transport.close if @transport
|
|
134
138
|
end
|
|
135
139
|
|
|
136
140
|
def setup_client(queue = nil)
|
|
@@ -166,7 +170,7 @@ describe 'NonblockingServer' do
|
|
|
166
170
|
break
|
|
167
171
|
end
|
|
168
172
|
end
|
|
169
|
-
@clients.each { |c,t| t.close and break if c == client } #close the transport
|
|
173
|
+
@clients.each { |c, t| t.close and break if c == client } # close the transport
|
|
170
174
|
rescue => e
|
|
171
175
|
raise e unless @catch_exceptions
|
|
172
176
|
end
|
|
@@ -245,7 +249,7 @@ describe 'NonblockingServer' do
|
|
|
245
249
|
it "should kill active messages when they don't expire while shutting down" do
|
|
246
250
|
result = Queue.new
|
|
247
251
|
client = setup_client_thread(result)
|
|
248
|
-
client << [:sleep, 10]
|
|
252
|
+
client << [:sleep, 10.0]
|
|
249
253
|
sleep 0.1 # start processing the client's message
|
|
250
254
|
@server.shutdown(1)
|
|
251
255
|
@catch_exceptions = true
|
|
@@ -260,4 +264,166 @@ describe 'NonblockingServer' do
|
|
|
260
264
|
expect(@server_thread.join(2)).not_to be_nil
|
|
261
265
|
end
|
|
262
266
|
end
|
|
267
|
+
|
|
268
|
+
describe Thrift::NonblockingServer::IOManager do
|
|
269
|
+
def build_io_manager
|
|
270
|
+
logger = Logger.new(IO::NULL)
|
|
271
|
+
logger.level = Logger::FATAL
|
|
272
|
+
Thrift::NonblockingServer::IOManager.new(
|
|
273
|
+
double('processor'),
|
|
274
|
+
double('server_transport'),
|
|
275
|
+
Thrift::BaseTransportFactory.new,
|
|
276
|
+
Thrift::BinaryProtocolFactory.new,
|
|
277
|
+
1,
|
|
278
|
+
logger
|
|
279
|
+
)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it "closes tracked connections and signal pipes during forced cleanup" do
|
|
283
|
+
io_manager = build_io_manager
|
|
284
|
+
connection = double('connection', :close => nil)
|
|
285
|
+
pipe_a = double('pipe_a', :closed? => false, :close => nil)
|
|
286
|
+
pipe_b = double('pipe_b', :closed? => false, :close => nil)
|
|
287
|
+
|
|
288
|
+
io_manager.instance_variable_set(:@connections, [connection])
|
|
289
|
+
io_manager.instance_variable_set(:@buffers, { connection => 'frame' })
|
|
290
|
+
io_manager.instance_variable_set(:@signal_pipes, [pipe_a, pipe_b])
|
|
291
|
+
io_manager.instance_variable_set(:@worker_threads, [])
|
|
292
|
+
|
|
293
|
+
io_manager.ensure_closed
|
|
294
|
+
|
|
295
|
+
expect(connection).to have_received(:close)
|
|
296
|
+
expect(pipe_a).to have_received(:close)
|
|
297
|
+
expect(pipe_b).to have_received(:close)
|
|
298
|
+
expect(io_manager.instance_variable_get(:@connections)).to be_empty
|
|
299
|
+
expect(io_manager.instance_variable_get(:@buffers)).to be_empty
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
it "continues closing remaining signal pipes when one close raises" do
|
|
303
|
+
io_manager = build_io_manager
|
|
304
|
+
pipe_a = double('pipe_a', :closed? => false)
|
|
305
|
+
pipe_b = double('pipe_b', :closed? => false, :close => nil)
|
|
306
|
+
|
|
307
|
+
allow(pipe_a).to receive(:close).and_raise(IOError)
|
|
308
|
+
|
|
309
|
+
io_manager.instance_variable_set(:@signal_pipes, [pipe_a, pipe_b])
|
|
310
|
+
io_manager.instance_variable_set(:@worker_threads, [])
|
|
311
|
+
|
|
312
|
+
io_manager.send(:close_signal_pipes)
|
|
313
|
+
|
|
314
|
+
expect(pipe_a).to have_received(:close)
|
|
315
|
+
expect(pipe_b).to have_received(:close)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "drops removed connections from bookkeeping" do
|
|
319
|
+
io_manager = build_io_manager
|
|
320
|
+
connection = double('connection', :close => nil)
|
|
321
|
+
|
|
322
|
+
io_manager.instance_variable_set(:@connections, [connection])
|
|
323
|
+
io_manager.instance_variable_set(:@buffers, { connection => 'frame' })
|
|
324
|
+
|
|
325
|
+
io_manager.send(:remove_connection, connection)
|
|
326
|
+
|
|
327
|
+
expect(io_manager.instance_variable_get(:@connections)).to be_empty
|
|
328
|
+
expect(io_manager.instance_variable_get(:@buffers)).to be_empty
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
describe "#{Thrift::NonblockingServer} with TLS transport" do
|
|
333
|
+
before(:each) do
|
|
334
|
+
@port = available_port
|
|
335
|
+
handler = Handler.new
|
|
336
|
+
processor = SpecNamespace::NonblockingService::Processor.new(handler)
|
|
337
|
+
@transport = Thrift::SSLServerSocket.new('localhost', @port, create_server_ssl_context)
|
|
338
|
+
transport_factory = Thrift::FramedTransportFactory.new
|
|
339
|
+
logger = Logger.new(STDERR)
|
|
340
|
+
logger.level = Logger::WARN
|
|
341
|
+
@server = Thrift::NonblockingServer.new(processor, @transport, transport_factory, nil, 5, logger)
|
|
342
|
+
handler.server = @server
|
|
343
|
+
|
|
344
|
+
@server_thread = Thread.new(Thread.current) do |master_thread|
|
|
345
|
+
begin
|
|
346
|
+
@server.serve
|
|
347
|
+
rescue => e
|
|
348
|
+
master_thread.raise e
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
@clients = []
|
|
353
|
+
wait_until_listening(@transport, @server_thread)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
after(:each) do
|
|
357
|
+
@clients.each(&:close)
|
|
358
|
+
@server.shutdown if @server
|
|
359
|
+
@server_thread.join(2) if @server_thread
|
|
360
|
+
@transport.close if @transport
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
it "should handle requests over TLS" do
|
|
364
|
+
expect(@server_thread).to be_alive
|
|
365
|
+
|
|
366
|
+
client = setup_tls_client
|
|
367
|
+
expect(client.greeting(true)).to eq(SpecNamespace::Hello.new)
|
|
368
|
+
|
|
369
|
+
@server.shutdown
|
|
370
|
+
expect(@server_thread.join(2)).to be_an_instance_of(Thread)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def setup_tls_client
|
|
374
|
+
transport = Thrift::FramedTransport.new(
|
|
375
|
+
Thrift::SSLSocket.new('localhost', @port, nil, create_client_ssl_context)
|
|
376
|
+
)
|
|
377
|
+
protocol = Thrift::BinaryProtocol.new(transport)
|
|
378
|
+
client = SpecNamespace::NonblockingService::Client.new(protocol)
|
|
379
|
+
transport.open
|
|
380
|
+
@clients << transport
|
|
381
|
+
client
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def ssl_keys_dir
|
|
385
|
+
File.expand_path('../../../test/keys', __dir__)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def create_server_ssl_context
|
|
389
|
+
OpenSSL::SSL::SSLContext.new.tap do |ctx|
|
|
390
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
391
|
+
if ctx.respond_to?(:min_version=) && OpenSSL::SSL.const_defined?(:TLS1_2_VERSION)
|
|
392
|
+
ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
|
|
393
|
+
end
|
|
394
|
+
ctx.ca_file = File.join(ssl_keys_dir, 'CA.pem')
|
|
395
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(File.join(ssl_keys_dir, 'server.crt')))
|
|
396
|
+
ctx.cert_store = OpenSSL::X509::Store.new
|
|
397
|
+
ctx.cert_store.add_file(File.join(ssl_keys_dir, 'client.pem'))
|
|
398
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.read(File.join(ssl_keys_dir, 'server.key')))
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def create_client_ssl_context
|
|
403
|
+
OpenSSL::SSL::SSLContext.new.tap do |ctx|
|
|
404
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
405
|
+
if ctx.respond_to?(:min_version=) && OpenSSL::SSL.const_defined?(:TLS1_2_VERSION)
|
|
406
|
+
ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
|
|
407
|
+
end
|
|
408
|
+
ctx.ca_file = File.join(ssl_keys_dir, 'CA.pem')
|
|
409
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(File.join(ssl_keys_dir, 'client.crt')))
|
|
410
|
+
ctx.cert_store = OpenSSL::X509::Store.new
|
|
411
|
+
ctx.cert_store.add_file(File.join(ssl_keys_dir, 'server.pem'))
|
|
412
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.read(File.join(ssl_keys_dir, 'client.key')))
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def wait_until_listening(server_transport, server_thread)
|
|
418
|
+
Timeout.timeout(2) do
|
|
419
|
+
until server_transport.handle
|
|
420
|
+
raise "Server thread exited unexpectedly" unless server_thread.alive?
|
|
421
|
+
sleep 0.01
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def available_port
|
|
427
|
+
TCPServer.open('localhost', 0) { |server| server.addr[1] }
|
|
428
|
+
end
|
|
263
429
|
end
|
data/spec/processor_spec.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -20,7 +21,6 @@
|
|
|
20
21
|
require 'spec_helper'
|
|
21
22
|
|
|
22
23
|
describe 'Processor' do
|
|
23
|
-
|
|
24
24
|
class ProcessorSpec
|
|
25
25
|
include Thrift::Processor
|
|
26
26
|
end
|