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
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
module HeaderProtocolHelper
|
|
22
|
+
def varint32(n)
|
|
23
|
+
bytes = []
|
|
24
|
+
loop do
|
|
25
|
+
if (n & ~0x7f) == 0
|
|
26
|
+
bytes << n
|
|
27
|
+
break
|
|
28
|
+
else
|
|
29
|
+
bytes << ((n & 0x7f) | 0x80)
|
|
30
|
+
n >>= 7
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
bytes.pack('C*')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def build_header_frame(header_data, payload = Thrift::Bytes.empty_byte_buffer, header_words: nil)
|
|
37
|
+
header_data = header_data.b
|
|
38
|
+
if header_words.nil?
|
|
39
|
+
padding = (4 - (header_data.bytesize % 4)) % 4
|
|
40
|
+
header_data += "\x00" * padding
|
|
41
|
+
header_words = header_data.bytesize / 4
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
frame_size = 2 + 2 + 4 + 2 + header_data.bytesize + payload.bytesize
|
|
45
|
+
frame = Thrift::Bytes.empty_byte_buffer
|
|
46
|
+
frame << [frame_size].pack('N')
|
|
47
|
+
frame << [Thrift::HeaderTransport::HEADER_MAGIC].pack('n')
|
|
48
|
+
frame << [0].pack('n')
|
|
49
|
+
frame << [0].pack('N')
|
|
50
|
+
frame << [header_words].pack('n')
|
|
51
|
+
frame << header_data
|
|
52
|
+
frame << payload
|
|
53
|
+
frame
|
|
54
|
+
end
|
|
55
|
+
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
|
|
@@ -22,13 +23,10 @@ require 'rack/test'
|
|
|
22
23
|
require 'thrift/server/thin_http_server'
|
|
23
24
|
|
|
24
25
|
describe Thrift::ThinHTTPServer do
|
|
25
|
-
|
|
26
26
|
let(:processor) { double('processor') }
|
|
27
27
|
|
|
28
28
|
describe "#initialize" do
|
|
29
|
-
|
|
30
29
|
context "when using the defaults" do
|
|
31
|
-
|
|
32
30
|
it "binds to port 80, with host 0.0.0.0, a path of '/'" do
|
|
33
31
|
expect(Thin::Server).to receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder))
|
|
34
32
|
Thrift::ThinHTTPServer.new(processor)
|
|
@@ -43,11 +41,9 @@ describe Thrift::ThinHTTPServer do
|
|
|
43
41
|
expect(Thrift::BinaryProtocolFactory).to receive(:new)
|
|
44
42
|
Thrift::ThinHTTPServer.new(processor)
|
|
45
43
|
end
|
|
46
|
-
|
|
47
44
|
end
|
|
48
45
|
|
|
49
46
|
context "when using the options" do
|
|
50
|
-
|
|
51
47
|
it 'accepts :ip, :port, :path' do
|
|
52
48
|
ip = "192.168.0.1"
|
|
53
49
|
port = 3000
|
|
@@ -64,13 +60,10 @@ describe Thrift::ThinHTTPServer do
|
|
|
64
60
|
Thrift::ThinHTTPServer.new(processor,
|
|
65
61
|
:protocol_factory => Thrift::JsonProtocolFactory.new)
|
|
66
62
|
end
|
|
67
|
-
|
|
68
63
|
end
|
|
69
|
-
|
|
70
64
|
end
|
|
71
65
|
|
|
72
66
|
describe "#serve" do
|
|
73
|
-
|
|
74
67
|
it 'starts the Thin server' do
|
|
75
68
|
underlying_thin_server = double('thin server', :start => true)
|
|
76
69
|
allow(Thin::Server).to receive(:new).and_return(underlying_thin_server)
|
|
@@ -81,7 +74,6 @@ describe Thrift::ThinHTTPServer do
|
|
|
81
74
|
thin_thrift_server.serve
|
|
82
75
|
end
|
|
83
76
|
end
|
|
84
|
-
|
|
85
77
|
end
|
|
86
78
|
|
|
87
79
|
describe Thrift::ThinHTTPServer::RackApplication do
|
|
@@ -95,23 +87,20 @@ describe Thrift::ThinHTTPServer::RackApplication do
|
|
|
95
87
|
end
|
|
96
88
|
|
|
97
89
|
context "404 response" do
|
|
98
|
-
|
|
99
90
|
it 'receives a non-POST' do
|
|
100
91
|
header('Content-Type', "application/x-thrift")
|
|
101
92
|
get "/"
|
|
102
|
-
expect(last_response.status).to
|
|
93
|
+
expect(last_response.status).to eq 404
|
|
103
94
|
end
|
|
104
95
|
|
|
105
96
|
it 'receives a header other than application/x-thrift' do
|
|
106
97
|
header('Content-Type', "application/json")
|
|
107
98
|
post "/"
|
|
108
|
-
expect(last_response.status).to
|
|
99
|
+
expect(last_response.status).to eq 404
|
|
109
100
|
end
|
|
110
|
-
|
|
111
101
|
end
|
|
112
102
|
|
|
113
103
|
context "200 response" do
|
|
114
|
-
|
|
115
104
|
before do
|
|
116
105
|
allow(protocol_factory).to receive(:get_protocol)
|
|
117
106
|
allow(processor).to receive(:process)
|
|
@@ -132,10 +121,7 @@ describe Thrift::ThinHTTPServer::RackApplication do
|
|
|
132
121
|
it 'status code 200' do
|
|
133
122
|
header('Content-Type', "application/x-thrift")
|
|
134
123
|
post "/"
|
|
135
|
-
expect(last_response.ok?).to
|
|
124
|
+
expect(last_response.ok?).to be true
|
|
136
125
|
end
|
|
137
|
-
|
|
138
126
|
end
|
|
139
|
-
|
|
140
127
|
end
|
|
141
|
-
|
data/spec/types_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 Thrift::Types do
|
|
23
|
-
|
|
24
24
|
before(:each) do
|
|
25
25
|
Thrift.type_checking = true
|
|
26
26
|
end
|
|
@@ -39,33 +39,33 @@ describe Thrift::Types do
|
|
|
39
39
|
|
|
40
40
|
it "should check types properly" do
|
|
41
41
|
# lambda { Thrift.check_type(nil, Thrift::Types::STOP) }.should raise_error(Thrift::TypeError)
|
|
42
|
-
expect { Thrift.check_type(3,
|
|
43
|
-
expect { Thrift.check_type(nil,
|
|
44
|
-
expect { Thrift.check_type(3,
|
|
45
|
-
expect { Thrift.check_type(true,
|
|
46
|
-
expect { Thrift.check_type(3,
|
|
47
|
-
expect { Thrift.check_type(42,
|
|
48
|
-
expect { Thrift.check_type(42,
|
|
49
|
-
expect { Thrift.check_type(42,
|
|
50
|
-
expect { Thrift.check_type(42,
|
|
51
|
-
expect { Thrift.check_type(3.14,
|
|
52
|
-
expect { Thrift.check_type(3.14,
|
|
53
|
-
expect { Thrift.check_type(3,
|
|
54
|
-
expect { Thrift.check_type("3",
|
|
55
|
-
expect { Thrift.check_type(3,
|
|
42
|
+
expect { Thrift.check_type(3, {:type => Thrift::Types::STOP}, :foo) }.to raise_error(Thrift::TypeError)
|
|
43
|
+
expect { Thrift.check_type(nil, {:type => Thrift::Types::VOID}, :foo) }.not_to raise_error
|
|
44
|
+
expect { Thrift.check_type(3, {:type => Thrift::Types::VOID}, :foo) }.to raise_error(Thrift::TypeError)
|
|
45
|
+
expect { Thrift.check_type(true, {:type => Thrift::Types::BOOL}, :foo) }.not_to raise_error
|
|
46
|
+
expect { Thrift.check_type(3, {:type => Thrift::Types::BOOL}, :foo) }.to raise_error(Thrift::TypeError)
|
|
47
|
+
expect { Thrift.check_type(42, {:type => Thrift::Types::BYTE}, :foo) }.not_to raise_error
|
|
48
|
+
expect { Thrift.check_type(42, {:type => Thrift::Types::I16}, :foo) }.not_to raise_error
|
|
49
|
+
expect { Thrift.check_type(42, {:type => Thrift::Types::I32}, :foo) }.not_to raise_error
|
|
50
|
+
expect { Thrift.check_type(42, {:type => Thrift::Types::I64}, :foo) }.not_to raise_error
|
|
51
|
+
expect { Thrift.check_type(3.14, {:type => Thrift::Types::I32}, :foo) }.to raise_error(Thrift::TypeError)
|
|
52
|
+
expect { Thrift.check_type(3.14, {:type => Thrift::Types::DOUBLE}, :foo) }.not_to raise_error
|
|
53
|
+
expect { Thrift.check_type(3, {:type => Thrift::Types::DOUBLE}, :foo) }.to raise_error(Thrift::TypeError)
|
|
54
|
+
expect { Thrift.check_type("3", {:type => Thrift::Types::STRING}, :foo) }.not_to raise_error
|
|
55
|
+
expect { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError)
|
|
56
56
|
hello = SpecNamespace::Hello.new
|
|
57
|
-
expect { Thrift.check_type(hello,
|
|
58
|
-
expect { Thrift.check_type("foo",
|
|
57
|
+
expect { Thrift.check_type(hello, {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello}, :foo) }.not_to raise_error
|
|
58
|
+
expect { Thrift.check_type("foo", {:type => Thrift::Types::STRUCT}, :foo) }.to raise_error(Thrift::TypeError)
|
|
59
59
|
field = {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRING}}
|
|
60
|
-
expect { Thrift.check_type({1 => "one"},
|
|
61
|
-
expect { Thrift.check_type([1],
|
|
60
|
+
expect { Thrift.check_type({1 => "one"}, field, :foo) }.not_to raise_error
|
|
61
|
+
expect { Thrift.check_type([1], field, :foo) }.to raise_error(Thrift::TypeError)
|
|
62
62
|
field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::I32}}
|
|
63
|
-
expect { Thrift.check_type([1],
|
|
64
|
-
expect { Thrift.check_type({:foo => 1},
|
|
63
|
+
expect { Thrift.check_type([1], field, :foo) }.not_to raise_error
|
|
64
|
+
expect { Thrift.check_type({:foo => 1}, field, :foo) }.to raise_error(Thrift::TypeError)
|
|
65
65
|
field = {:type => Thrift::Types::SET, :element => {:type => Thrift::Types::I32}}
|
|
66
|
-
expect { Thrift.check_type(Set.new([1,2]), field, :foo) }.not_to raise_error
|
|
67
|
-
expect { Thrift.check_type([1,2], field, :foo) }.to raise_error(Thrift::TypeError)
|
|
68
|
-
expect { Thrift.check_type({:foo => true},
|
|
66
|
+
expect { Thrift.check_type(Set.new([1, 2]), field, :foo) }.not_to raise_error
|
|
67
|
+
expect { Thrift.check_type([1, 2], field, :foo) }.to raise_error(Thrift::TypeError)
|
|
68
|
+
expect { Thrift.check_type({:foo => true}, field, :foo) }.to raise_error(Thrift::TypeError)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
it "should error out if nil is passed and skip_types is false" do
|
|
@@ -100,9 +100,9 @@ describe Thrift::Types do
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
it "should give the Thrift::TypeError a readable message" do
|
|
103
|
-
msg =
|
|
103
|
+
msg = "Expected Types::STRING, received Integer for field foo"
|
|
104
104
|
expect { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError, msg)
|
|
105
|
-
msg =
|
|
105
|
+
msg = "Expected Types::STRING, received Integer for field foo.element"
|
|
106
106
|
field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::STRING}}
|
|
107
107
|
expect { Thrift.check_type([3], field, :foo) }.to raise_error(Thrift::TypeError, msg)
|
|
108
108
|
msg = "Expected Types::I32, received NilClass for field foo.element.key"
|
data/spec/union_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 'Union' do
|
|
23
|
-
|
|
24
24
|
describe Thrift::Union do
|
|
25
25
|
it "should return nil value in unset union" do
|
|
26
26
|
union = SpecNamespace::My_union.new
|
|
@@ -51,7 +51,9 @@ describe 'Union' do
|
|
|
51
51
|
it "should raise for wrong set field when hash initialized and type checking is off" do
|
|
52
52
|
Thrift.type_checking = false
|
|
53
53
|
union = SpecNamespace::My_union.new({incorrect_field: :incorrect})
|
|
54
|
-
expect { Thrift::Serializer.new.serialize(union) }.to raise_error(
|
|
54
|
+
expect { Thrift::Serializer.new.serialize(union) }.to raise_error(Thrift::ProtocolException, "set_field is not valid for this union!") { |error|
|
|
55
|
+
expect(error.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
56
|
+
}
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
it "should not be equal to nil" do
|
|
@@ -91,6 +93,24 @@ describe 'Union' do
|
|
|
91
93
|
expect(union).not_to eq(other_union)
|
|
92
94
|
end
|
|
93
95
|
|
|
96
|
+
it "should equate two unions with the same UUID value" do
|
|
97
|
+
union = SpecNamespace::My_union.new(:unique_id, '550e8400-e29b-41d4-a716-446655440000')
|
|
98
|
+
other_union = SpecNamespace::My_union.new(:unique_id, '550e8400-e29b-41d4-a716-446655440000')
|
|
99
|
+
expect(union).to eq(other_union)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should not equate two unions with different UUID values" do
|
|
103
|
+
union = SpecNamespace::My_union.new(:unique_id, '550e8400-e29b-41d4-a716-446655440000')
|
|
104
|
+
other_union = SpecNamespace::My_union.new(:unique_id, '6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
|
105
|
+
expect(union).not_to eq(other_union)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should not equate UUID union with different field type" do
|
|
109
|
+
union = SpecNamespace::My_union.new(:unique_id, '550e8400-e29b-41d4-a716-446655440000')
|
|
110
|
+
other_union = SpecNamespace::My_union.new(:some_characters, '550e8400-e29b-41d4-a716-446655440000')
|
|
111
|
+
expect(union).not_to eq(other_union)
|
|
112
|
+
end
|
|
113
|
+
|
|
94
114
|
it "should inspect properly" do
|
|
95
115
|
union = SpecNamespace::My_union.new(:integer32, 25)
|
|
96
116
|
expect(union.inspect).to eq("<SpecNamespace::My_union integer32: 25>")
|
|
@@ -130,7 +150,9 @@ describe 'Union' do
|
|
|
130
150
|
|
|
131
151
|
it "should raise when validating unset union" do
|
|
132
152
|
union = SpecNamespace::My_union.new
|
|
133
|
-
expect { union.validate }.to raise_error(
|
|
153
|
+
expect { union.validate }.to raise_error(Thrift::ProtocolException, "Union fields are not set.") { |error|
|
|
154
|
+
expect(error.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
155
|
+
}
|
|
134
156
|
|
|
135
157
|
other_union = SpecNamespace::My_union.new(:integer32, 1)
|
|
136
158
|
expect { other_union.validate }.not_to raise_error
|
|
@@ -139,7 +161,9 @@ describe 'Union' do
|
|
|
139
161
|
it "should validate an enum field properly" do
|
|
140
162
|
union = SpecNamespace::TestUnion.new(:enum_field, 3)
|
|
141
163
|
expect(union.get_set_field).to eq(:enum_field)
|
|
142
|
-
expect { union.validate }.to raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!")
|
|
164
|
+
expect { union.validate }.to raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!") { |error|
|
|
165
|
+
expect(error.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
166
|
+
}
|
|
143
167
|
|
|
144
168
|
other_union = SpecNamespace::TestUnion.new(:enum_field, 1)
|
|
145
169
|
expect { other_union.validate }.not_to raise_error
|
|
@@ -170,7 +194,7 @@ describe 'Union' do
|
|
|
170
194
|
end
|
|
171
195
|
|
|
172
196
|
it "should not throw an error when inspected and unset" do
|
|
173
|
-
expect{SpecNamespace::TestUnion.new().inspect}.not_to raise_error
|
|
197
|
+
expect{ SpecNamespace::TestUnion.new().inspect }.not_to raise_error
|
|
174
198
|
end
|
|
175
199
|
|
|
176
200
|
it "should print enum value name when inspected" do
|
|
@@ -192,23 +216,58 @@ describe 'Union' do
|
|
|
192
216
|
|
|
193
217
|
it "should be comparable" do
|
|
194
218
|
relationships = [
|
|
195
|
-
[0, -1, -1, -1],
|
|
196
|
-
[1, 0, -1, -1],
|
|
197
|
-
[1, 1, 0, -1],
|
|
198
|
-
[1, 1, 1, 0]
|
|
219
|
+
[0, -1, -1, -1, -1, -1],
|
|
220
|
+
[1, 0, -1, -1, -1, -1],
|
|
221
|
+
[1, 1, 0, -1, -1, -1],
|
|
222
|
+
[1, 1, 1, 0, -1, -1],
|
|
223
|
+
[1, 1, 1, 1, 0, -1],
|
|
224
|
+
[1, 1, 1, 1, 1, 0]]
|
|
199
225
|
|
|
200
226
|
objs = [
|
|
201
227
|
SpecNamespace::TestUnion.new(:string_field, "blah"),
|
|
202
228
|
SpecNamespace::TestUnion.new(:string_field, "blahblah"),
|
|
203
229
|
SpecNamespace::TestUnion.new(:i32_field, 1),
|
|
230
|
+
SpecNamespace::TestUnion.new(:uuid_field, '550e8400-e29b-41d4-a716-446655440000'),
|
|
231
|
+
SpecNamespace::TestUnion.new(:uuid_field, '6ba7b810-9dad-11d1-80b4-00c04fd430c8'),
|
|
204
232
|
SpecNamespace::TestUnion.new()]
|
|
205
233
|
|
|
206
|
-
|
|
207
|
-
|
|
234
|
+
objs.size.times do |y|
|
|
235
|
+
objs.size.times do |x|
|
|
208
236
|
# puts "#{objs[y].inspect} <=> #{objs[x].inspect} should == #{relationships[y][x]}"
|
|
209
237
|
expect(objs[y] <=> objs[x]).to eq(relationships[y][x])
|
|
210
238
|
end
|
|
211
239
|
end
|
|
212
240
|
end
|
|
241
|
+
|
|
242
|
+
it "should handle UUID as union value" do
|
|
243
|
+
union = SpecNamespace::My_union.new
|
|
244
|
+
union.unique_id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
|
|
245
|
+
|
|
246
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
247
|
+
prot = Thrift::CompactProtocol.new(trans)
|
|
248
|
+
|
|
249
|
+
union.write(prot)
|
|
250
|
+
|
|
251
|
+
result = SpecNamespace::My_union.new
|
|
252
|
+
result.read(prot)
|
|
253
|
+
|
|
254
|
+
expect(result.unique_id).to eq('ffffffff-ffff-ffff-ffff-ffffffffffff')
|
|
255
|
+
expect(result.get_set_field).to eq(:unique_id)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should normalize UUID case in union" do
|
|
259
|
+
union = SpecNamespace::My_union.new
|
|
260
|
+
union.unique_id = '550E8400-E29B-41D4-A716-446655440000'
|
|
261
|
+
|
|
262
|
+
trans = Thrift::MemoryBufferTransport.new
|
|
263
|
+
prot = Thrift::BinaryProtocol.new(trans)
|
|
264
|
+
|
|
265
|
+
union.write(prot)
|
|
266
|
+
|
|
267
|
+
result = SpecNamespace::My_union.new
|
|
268
|
+
result.read(prot)
|
|
269
|
+
|
|
270
|
+
expect(result.unique_id).to eq('550e8400-e29b-41d4-a716-446655440000')
|
|
271
|
+
end
|
|
213
272
|
end
|
|
214
273
|
end
|
data/spec/unix_socket_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
|
|
@@ -21,7 +22,6 @@ require 'spec_helper'
|
|
|
21
22
|
require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared")
|
|
22
23
|
|
|
23
24
|
describe 'UNIXSocket' do
|
|
24
|
-
|
|
25
25
|
describe Thrift::UNIXSocket do
|
|
26
26
|
before(:each) do
|
|
27
27
|
@path = '/tmp/thrift_spec_socket'
|
|
@@ -42,7 +42,7 @@ describe 'UNIXSocket' do
|
|
|
42
42
|
allow(::UNIXSocket).to receive(:new)
|
|
43
43
|
expect(Thrift::UNIXSocket.new(@path, 5).timeout).to eq(5)
|
|
44
44
|
end
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
it "should provide a reasonable to_s" do
|
|
47
47
|
allow(::UNIXSocket).to receive(:new)
|
|
48
48
|
expect(Thrift::UNIXSocket.new(@path).to_s).to eq("domain(#{@path})")
|
|
@@ -68,10 +68,25 @@ describe 'UNIXSocket' do
|
|
|
68
68
|
expect(handle).to receive(:accept).and_return(sock)
|
|
69
69
|
trans = double("UNIXSocket")
|
|
70
70
|
expect(Thrift::UNIXSocket).to receive(:new).and_return(trans)
|
|
71
|
+
expect(trans).to receive(:timeout=).with(Thrift::BaseServerTransport::DEFAULT_CLIENT_TIMEOUT)
|
|
71
72
|
expect(trans).to receive(:handle=).with(sock)
|
|
72
73
|
expect(@socket.accept).to eq(trans)
|
|
73
74
|
end
|
|
74
75
|
|
|
76
|
+
it "should default accepted sockets to a finite client timeout" do
|
|
77
|
+
expect(@socket.client_timeout).to eq(5)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should accept a custom client timeout" do
|
|
81
|
+
@socket = Thrift::UNIXServerSocket.new(@path, client_timeout: 2.5)
|
|
82
|
+
expect(@socket.client_timeout).to eq(2.5)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should allow blocking accepted sockets with nil or zero client timeout" do
|
|
86
|
+
expect(Thrift::UNIXServerSocket.new(@path, client_timeout: nil).client_timeout).to be_nil
|
|
87
|
+
expect(Thrift::UNIXServerSocket.new(@path, client_timeout: 0).client_timeout).to eq(0)
|
|
88
|
+
end
|
|
89
|
+
|
|
75
90
|
it "should close the handle when closed" do
|
|
76
91
|
handle = double("UNIXServer", :closed? => false)
|
|
77
92
|
expect(UNIXServer).to receive(:new).with(@path).and_return(handle)
|
|
@@ -0,0 +1,239 @@
|
|
|
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 'UUID Validation' do
|
|
24
|
+
protocols = [
|
|
25
|
+
['BinaryProtocol', Thrift::BinaryProtocol],
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
if defined?(Thrift::BinaryProtocolAccelerated)
|
|
29
|
+
protocols << ['BinaryProtocolAccelerated', Thrift::BinaryProtocolAccelerated]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
protocols << ['CompactProtocol', Thrift::CompactProtocol]
|
|
33
|
+
protocols << ['JsonProtocol', Thrift::JsonProtocol]
|
|
34
|
+
|
|
35
|
+
protocols.each do |protocol_name, protocol_class|
|
|
36
|
+
describe protocol_name do
|
|
37
|
+
before(:each) do
|
|
38
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
39
|
+
@prot = protocol_class.new(@trans)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'valid UUIDs' do
|
|
43
|
+
it 'should accept lowercase UUIDs' do
|
|
44
|
+
uuid = '550e8400-e29b-41d4-a716-446655440000'
|
|
45
|
+
expect { @prot.write_uuid(uuid) }.not_to raise_error
|
|
46
|
+
result = @prot.read_uuid
|
|
47
|
+
expect(result).to eq(uuid)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'should accept uppercase UUIDs' do
|
|
51
|
+
uuid = '550E8400-E29B-41D4-A716-446655440000'
|
|
52
|
+
expect { @prot.write_uuid(uuid) }.not_to raise_error
|
|
53
|
+
result = @prot.read_uuid
|
|
54
|
+
# Result should be lowercase
|
|
55
|
+
expect(result).to eq('550e8400-e29b-41d4-a716-446655440000')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should accept mixed case UUIDs' do
|
|
59
|
+
uuid = '550e8400-E29B-41d4-A716-446655440000'
|
|
60
|
+
expect { @prot.write_uuid(uuid) }.not_to raise_error
|
|
61
|
+
result = @prot.read_uuid
|
|
62
|
+
expect(result).to eq('550e8400-e29b-41d4-a716-446655440000')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'should accept all zeros' do
|
|
66
|
+
uuid = '00000000-0000-0000-0000-000000000000'
|
|
67
|
+
expect { @prot.write_uuid(uuid) }.not_to raise_error
|
|
68
|
+
result = @prot.read_uuid
|
|
69
|
+
expect(result).to eq(uuid)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should accept all fs' do
|
|
73
|
+
uuid = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
|
|
74
|
+
expect { @prot.write_uuid(uuid) }.not_to raise_error
|
|
75
|
+
result = @prot.read_uuid
|
|
76
|
+
expect(result).to eq(uuid)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'invalid UUIDs' do
|
|
81
|
+
def expect_invalid_uuid(value, message)
|
|
82
|
+
expect { @prot.write_uuid(value) }.to raise_error(Thrift::ProtocolException) do |error|
|
|
83
|
+
expect(error.type).to eq(Thrift::ProtocolException::INVALID_DATA)
|
|
84
|
+
expect(error.message).to eq(message)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'should reject nil' do
|
|
89
|
+
expect_invalid_uuid(nil, 'UUID must be a string')
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should reject non-string' do
|
|
93
|
+
expect_invalid_uuid(12345, 'UUID must be a string')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should reject wrong length' do
|
|
97
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716', 'Invalid UUID format')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should reject missing hyphens' do
|
|
101
|
+
expect_invalid_uuid('550e8400e29b41d4a716446655440000', 'Invalid UUID format')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should reject hyphens in wrong positions' do
|
|
105
|
+
expect_invalid_uuid('550e840-0e29b-41d4-a716-446655440000', 'Invalid UUID format')
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'should reject invalid hex characters (g)' do
|
|
109
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000g', 'Invalid UUID format')
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'should reject invalid hex characters (z)' do
|
|
113
|
+
expect_invalid_uuid('z50e8400-e29b-41d4-a716-446655440000', 'Invalid UUID format')
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should reject invalid hex characters (space)' do
|
|
117
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000 ', 'Invalid UUID format')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should reject empty string' do
|
|
121
|
+
expect_invalid_uuid('', 'Invalid UUID format')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'should reject UUID with extra characters' do
|
|
125
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716-446655440000x', 'Invalid UUID format')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'should reject trailing hyphen' do
|
|
129
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000-', 'Invalid UUID format')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'should reject hyphen inside hex pair' do
|
|
133
|
+
expect_invalid_uuid('550e8400-e29b-41d4-a716-4466-5544000', 'Invalid UUID format')
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context 'malformed binary data on read' do
|
|
138
|
+
it 'should raise error on truncated data' do
|
|
139
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
140
|
+
@prot = protocol_class.new(@trans)
|
|
141
|
+
|
|
142
|
+
# Write only 10 bytes instead of 16
|
|
143
|
+
if protocol_class == Thrift::JsonProtocol
|
|
144
|
+
@trans.write('"00000000-0000-0000-0000"')
|
|
145
|
+
else
|
|
146
|
+
@trans.write("\x00" * 10)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
expect { @prot.read_uuid }.to raise_error(EOFError)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'should raise error on 15 bytes (one byte short)' do
|
|
153
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
154
|
+
@prot = protocol_class.new(@trans)
|
|
155
|
+
|
|
156
|
+
if protocol_class == Thrift::JsonProtocol
|
|
157
|
+
@trans.write('"00000000-0000-0000-0000-000000000"')
|
|
158
|
+
else
|
|
159
|
+
@trans.write("\x00" * 15)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
expect { @prot.read_uuid }.to raise_error(EOFError)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'should raise error on empty buffer' do
|
|
166
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
167
|
+
@prot = protocol_class.new(@trans)
|
|
168
|
+
|
|
169
|
+
expect { @prot.read_uuid }.to raise_error(EOFError)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'multiple UUIDs in sequence' do
|
|
174
|
+
it 'should handle 10 UUIDs in sequence' do
|
|
175
|
+
uuids = 10.times.map { |i| sprintf('%08x-0000-0000-0000-000000000000', i) }
|
|
176
|
+
|
|
177
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
178
|
+
@prot = protocol_class.new(@trans)
|
|
179
|
+
|
|
180
|
+
uuids.each { |uuid| @prot.write_uuid(uuid) }
|
|
181
|
+
|
|
182
|
+
results = 10.times.map { @prot.read_uuid }
|
|
183
|
+
expect(results).to eq(uuids)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'should handle UUIDs interleaved with other types' do
|
|
187
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
188
|
+
@prot = protocol_class.new(@trans)
|
|
189
|
+
|
|
190
|
+
@prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 0)
|
|
191
|
+
@prot.write_i32(42)
|
|
192
|
+
@prot.write_uuid('550e8400-e29b-41d4-a716-446655440000')
|
|
193
|
+
@prot.write_string('test')
|
|
194
|
+
@prot.write_uuid('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
|
195
|
+
@prot.write_i64(123456789)
|
|
196
|
+
@prot.write_message_end
|
|
197
|
+
|
|
198
|
+
@prot.read_message_begin
|
|
199
|
+
expect(@prot.read_i32).to eq(42)
|
|
200
|
+
expect(@prot.read_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
|
|
201
|
+
expect(@prot.read_string).to eq('test')
|
|
202
|
+
expect(@prot.read_uuid).to eq('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
|
203
|
+
expect(@prot.read_i64).to eq(123456789)
|
|
204
|
+
@prot.read_message_end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'should handle UUIDs in struct fields context' do
|
|
208
|
+
@trans = Thrift::MemoryBufferTransport.new
|
|
209
|
+
@prot = protocol_class.new(@trans)
|
|
210
|
+
|
|
211
|
+
# Simulate struct field headers
|
|
212
|
+
@prot.write_struct_begin('test')
|
|
213
|
+
@prot.write_field_begin('uuid1', Thrift::Types::UUID, 1)
|
|
214
|
+
@prot.write_uuid('550e8400-e29b-41d4-a716-446655440000')
|
|
215
|
+
@prot.write_field_end
|
|
216
|
+
@prot.write_field_begin('uuid2', Thrift::Types::UUID, 2)
|
|
217
|
+
@prot.write_uuid('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
|
218
|
+
@prot.write_field_end
|
|
219
|
+
@prot.write_field_stop
|
|
220
|
+
@prot.write_struct_end
|
|
221
|
+
|
|
222
|
+
@prot.read_struct_begin
|
|
223
|
+
name, type, id = @prot.read_field_begin
|
|
224
|
+
expect(type).to eq(Thrift::Types::UUID)
|
|
225
|
+
expect(@prot.read_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
|
|
226
|
+
@prot.read_field_end
|
|
227
|
+
|
|
228
|
+
name, type, id = @prot.read_field_begin
|
|
229
|
+
expect(type).to eq(Thrift::Types::UUID)
|
|
230
|
+
expect(@prot.read_uuid).to eq('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
|
|
231
|
+
@prot.read_field_end
|
|
232
|
+
|
|
233
|
+
name, type, id = @prot.read_field_begin
|
|
234
|
+
expect(type).to eq(Thrift::Types::STOP)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|