thrift 0.8.0 → 0.13.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 +7 -0
- data/{README → README.md} +0 -0
- data/ext/binary_protocol_accelerated.c +33 -14
- data/ext/bytes.c +36 -0
- data/ext/bytes.h +31 -0
- data/ext/compact_protocol.c +27 -8
- data/ext/constants.h +8 -5
- data/ext/extconf.rb +5 -1
- data/ext/memory_buffer.c +12 -9
- data/ext/protocol.c +0 -185
- data/ext/protocol.h +0 -20
- data/ext/strlcpy.h +7 -3
- data/ext/struct.c +27 -7
- data/ext/thrift_native.c +16 -11
- data/lib/thrift.rb +10 -4
- data/lib/thrift/bytes.rb +131 -0
- data/lib/thrift/client.rb +13 -4
- data/lib/thrift/exceptions.rb +3 -0
- data/lib/thrift/multiplexed_processor.rb +76 -0
- data/lib/thrift/processor.rb +24 -6
- data/lib/thrift/protocol/base_protocol.rb +109 -12
- data/lib/thrift/protocol/binary_protocol.rb +22 -7
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +8 -0
- data/lib/thrift/protocol/compact_protocol.rb +23 -6
- data/lib/thrift/protocol/json_protocol.rb +786 -0
- data/lib/thrift/protocol/multiplexed_protocol.rb +44 -0
- data/lib/thrift/protocol/protocol_decorator.rb +194 -0
- data/lib/thrift/server/base_server.rb +8 -2
- data/lib/thrift/server/mongrel_http_server.rb +2 -0
- data/lib/thrift/server/simple_server.rb +5 -1
- data/lib/thrift/server/thin_http_server.rb +91 -0
- data/lib/thrift/server/thread_pool_server.rb +5 -1
- data/lib/thrift/server/threaded_server.rb +5 -1
- data/lib/thrift/struct.rb +1 -1
- data/lib/thrift/struct_union.rb +2 -2
- data/lib/thrift/transport/base_server_transport.rb +1 -1
- data/lib/thrift/transport/base_transport.rb +30 -20
- data/lib/thrift/transport/buffered_transport.rb +25 -11
- data/lib/thrift/transport/framed_transport.rb +20 -11
- data/lib/thrift/transport/http_client_transport.rb +16 -6
- data/lib/thrift/transport/io_stream_transport.rb +5 -2
- data/lib/thrift/transport/memory_buffer_transport.rb +10 -6
- data/lib/thrift/transport/server_socket.rb +6 -1
- data/lib/thrift/transport/socket.rb +23 -17
- data/lib/thrift/transport/ssl_server_socket.rb +41 -0
- data/lib/thrift/transport/ssl_socket.rb +51 -0
- data/lib/thrift/transport/unix_server_socket.rb +5 -1
- data/lib/thrift/transport/unix_socket.rb +5 -1
- data/lib/thrift/union.rb +3 -6
- data/spec/BaseService.thrift +27 -0
- data/spec/ExtendedService.thrift +25 -0
- data/spec/Referenced.thrift +44 -0
- data/spec/ThriftNamespacedSpec.thrift +53 -0
- data/spec/ThriftSpec.thrift +52 -1
- data/spec/base_protocol_spec.rb +158 -93
- data/spec/base_transport_spec.rb +194 -157
- data/spec/binary_protocol_accelerated_spec.rb +14 -14
- data/spec/binary_protocol_spec.rb +29 -16
- data/spec/binary_protocol_spec_shared.rb +148 -65
- data/spec/bytes_spec.rb +160 -0
- data/spec/client_spec.rb +45 -47
- data/spec/compact_protocol_spec.rb +36 -22
- data/spec/exception_spec.rb +79 -80
- data/spec/flat_spec.rb +62 -0
- data/spec/http_client_spec.rb +91 -16
- data/spec/json_protocol_spec.rb +552 -0
- data/spec/namespaced_spec.rb +67 -0
- data/spec/nonblocking_server_spec.rb +26 -28
- data/spec/processor_spec.rb +29 -32
- data/spec/serializer_spec.rb +31 -33
- data/spec/server_socket_spec.rb +32 -28
- data/spec/server_spec.rb +112 -84
- data/spec/socket_spec.rb +27 -20
- data/spec/socket_spec_shared.rb +32 -32
- data/spec/spec_helper.rb +17 -11
- data/spec/ssl_server_socket_spec.rb +34 -0
- data/spec/ssl_socket_spec.rb +78 -0
- data/spec/struct_nested_containers_spec.rb +191 -0
- data/spec/struct_spec.rb +159 -161
- data/spec/thin_http_server_spec.rb +141 -0
- data/spec/types_spec.rb +71 -69
- data/spec/union_spec.rb +97 -76
- data/spec/unix_socket_spec.rb +49 -41
- metadata +268 -188
- data/CHANGELOG +0 -1
- data/benchmark/gen-rb/benchmark_constants.rb +0 -10
- data/benchmark/gen-rb/benchmark_service.rb +0 -80
- data/benchmark/gen-rb/benchmark_types.rb +0 -9
- data/spec/gen-rb/nonblocking_service.rb +0 -272
- data/spec/gen-rb/thrift_spec_constants.rb +0 -10
- data/spec/gen-rb/thrift_spec_types.rb +0 -345
- data/spec/mongrel_http_server_spec.rb +0 -117
- data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +0 -273
- data/test/debug_proto/gen-rb/debug_proto_test_types.rb +0 -760
- data/test/debug_proto/gen-rb/empty_service.rb +0 -24
- data/test/debug_proto/gen-rb/inherited.rb +0 -79
- data/test/debug_proto/gen-rb/reverse_order_service.rb +0 -82
- data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +0 -81
- data/test/debug_proto/gen-rb/srv.rb +0 -330
@@ -0,0 +1,34 @@
|
|
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 File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared")
|
22
|
+
|
23
|
+
describe 'SSLServerSocket' do
|
24
|
+
|
25
|
+
describe Thrift::SSLServerSocket do
|
26
|
+
before(:each) do
|
27
|
+
@socket = Thrift::SSLServerSocket.new(1234)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should provide a reasonable to_s" do
|
31
|
+
expect(@socket.to_s).to eq("ssl(socket(:1234))")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,78 @@
|
|
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 File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared")
|
22
|
+
|
23
|
+
describe 'SSLSocket' do
|
24
|
+
|
25
|
+
describe Thrift::SSLSocket do
|
26
|
+
before(:each) do
|
27
|
+
@context = OpenSSL::SSL::SSLContext.new
|
28
|
+
@socket = Thrift::SSLSocket.new
|
29
|
+
@simple_socket_handle = double("Handle", :closed? => false)
|
30
|
+
allow(@simple_socket_handle).to receive(:close)
|
31
|
+
allow(@simple_socket_handle).to receive(:connect_nonblock)
|
32
|
+
allow(@simple_socket_handle).to receive(:setsockopt)
|
33
|
+
|
34
|
+
@handle = double(double("SSLHandle", :connect_nonblock => true, :post_connection_check => true), :closed? => false)
|
35
|
+
allow(@handle).to receive(:connect_nonblock)
|
36
|
+
allow(@handle).to receive(:close)
|
37
|
+
allow(@handle).to receive(:post_connection_check)
|
38
|
+
|
39
|
+
allow(::Socket).to receive(:new).and_return(@simple_socket_handle)
|
40
|
+
allow(OpenSSL::SSL::SSLSocket).to receive(:new).and_return(@handle)
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_behave_like "a socket"
|
44
|
+
|
45
|
+
it "should raise a TransportException when it cannot open a ssl socket" do
|
46
|
+
expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
|
47
|
+
expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) }
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should open a ::Socket with default args" do
|
51
|
+
expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(@simple_socket_handle, nil).and_return(@handle)
|
52
|
+
expect(@handle).to receive(:post_connection_check).with('localhost')
|
53
|
+
@socket.open
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should accept host/port options" do
|
57
|
+
handle = double("Handle", :connect_nonblock => true, :setsockopt => nil)
|
58
|
+
allow(::Socket).to receive(:new).and_return(handle)
|
59
|
+
expect(::Socket).to receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
|
60
|
+
expect(::Socket).to receive(:sockaddr_in)
|
61
|
+
expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(handle, nil).and_return(@handle)
|
62
|
+
expect(@handle).to receive(:post_connection_check).with('my.domain')
|
63
|
+
Thrift::SSLSocket.new('my.domain', 1234, 6000, nil).open
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should accept an optional timeout" do
|
67
|
+
expect(Thrift::SSLSocket.new('localhost', 8080, 5).timeout).to eq(5)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should accept an optional context" do
|
71
|
+
expect(Thrift::SSLSocket.new('localhost', 8080, 5, @context).ssl_context).to eq(@context)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should provide a reasonable to_s" do
|
75
|
+
expect(Thrift::SSLSocket.new('myhost', 8090).to_s).to eq("ssl(socket(myhost:8090))")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'spec_helper'
|
21
|
+
|
22
|
+
describe 'StructNestedContainers' do
|
23
|
+
|
24
|
+
def with_type_checking
|
25
|
+
saved_type_checking, Thrift.type_checking = Thrift.type_checking, true
|
26
|
+
begin
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
Thrift.type_checking = saved_type_checking
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe Thrift::Struct do
|
34
|
+
# Nested container tests, see THRIFT-369.
|
35
|
+
it "should support nested lists inside lists" do
|
36
|
+
with_type_checking do
|
37
|
+
a, b = SpecNamespace::NestedListInList.new, SpecNamespace::NestedListInList.new
|
38
|
+
[a, b].each do |thrift_struct|
|
39
|
+
thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ]
|
40
|
+
thrift_struct.validate
|
41
|
+
end
|
42
|
+
expect(a).to eq(b)
|
43
|
+
b.value.push [3, 4, 5]
|
44
|
+
expect(a).not_to eq(b)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should support nested lists inside sets" do
|
49
|
+
with_type_checking do
|
50
|
+
a, b = SpecNamespace::NestedListInSet.new, SpecNamespace::NestedListInSet.new
|
51
|
+
[a, b].each do |thrift_struct|
|
52
|
+
thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ].to_set
|
53
|
+
thrift_struct.validate
|
54
|
+
end
|
55
|
+
expect(a).to eq(b)
|
56
|
+
b.value.add [3, 4, 5]
|
57
|
+
expect(a).not_to eq(b)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should support nested lists in map keys" do
|
62
|
+
with_type_checking do
|
63
|
+
a, b = SpecNamespace::NestedListInMapKey.new, SpecNamespace::NestedListInMapKey.new
|
64
|
+
[a, b].each do |thrift_struct|
|
65
|
+
thrift_struct.value = { [1, 2, 3] => 1, [2, 3, 4] => 2 }
|
66
|
+
thrift_struct.validate
|
67
|
+
end
|
68
|
+
expect(a).to eq(b)
|
69
|
+
b.value[[3, 4, 5]] = 3
|
70
|
+
expect(a).not_to eq(b)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should support nested lists in map values" do
|
75
|
+
with_type_checking do
|
76
|
+
a, b = SpecNamespace::NestedListInMapValue.new, SpecNamespace::NestedListInMapValue.new
|
77
|
+
[a, b].each do |thrift_struct|
|
78
|
+
thrift_struct.value = { 1 => [1, 2, 3], 2 => [2, 3, 4] }
|
79
|
+
thrift_struct.validate
|
80
|
+
end
|
81
|
+
expect(a).to eq(b)
|
82
|
+
b.value[3] = [3, 4, 5]
|
83
|
+
expect(a).not_to eq(b)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should support nested sets inside lists" do
|
88
|
+
with_type_checking do
|
89
|
+
a, b = SpecNamespace::NestedSetInList.new, SpecNamespace::NestedSetInList.new
|
90
|
+
[a, b].each do |thrift_struct|
|
91
|
+
thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ]
|
92
|
+
thrift_struct.validate
|
93
|
+
end
|
94
|
+
expect(a).to eq(b)
|
95
|
+
b.value.push([3, 4, 5].to_set)
|
96
|
+
expect(a).not_to eq(b)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should support nested sets inside sets" do
|
101
|
+
with_type_checking do
|
102
|
+
a, b = SpecNamespace::NestedSetInSet.new, SpecNamespace::NestedSetInSet.new
|
103
|
+
[a, b].each do |thrift_struct|
|
104
|
+
thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ].to_set
|
105
|
+
thrift_struct.validate
|
106
|
+
end
|
107
|
+
expect(a).to eq(b)
|
108
|
+
b.value.add([3, 4, 5].to_set)
|
109
|
+
expect(a).not_to eq(b)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should support nested sets in map keys" do
|
114
|
+
with_type_checking do
|
115
|
+
a, b = SpecNamespace::NestedSetInMapKey.new, SpecNamespace::NestedSetInMapKey.new
|
116
|
+
[a, b].each do |thrift_struct|
|
117
|
+
thrift_struct.value = { [1, 2, 3].to_set => 1, [2, 3, 4].to_set => 2 }
|
118
|
+
thrift_struct.validate
|
119
|
+
end
|
120
|
+
expect(a).to eq(b)
|
121
|
+
b.value[[3, 4, 5].to_set] = 3
|
122
|
+
expect(a).not_to eq(b)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should support nested sets in map values" do
|
127
|
+
with_type_checking do
|
128
|
+
a, b = SpecNamespace::NestedSetInMapValue.new, SpecNamespace::NestedSetInMapValue.new
|
129
|
+
[a, b].each do |thrift_struct|
|
130
|
+
thrift_struct.value = { 1 => [1, 2, 3].to_set, 2 => [2, 3, 4].to_set }
|
131
|
+
thrift_struct.validate
|
132
|
+
end
|
133
|
+
expect(a).to eq(b)
|
134
|
+
b.value[3] = [3, 4, 5].to_set
|
135
|
+
expect(a).not_to eq(b)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should support nested maps inside lists" do
|
140
|
+
with_type_checking do
|
141
|
+
a, b = SpecNamespace::NestedMapInList.new, SpecNamespace::NestedMapInList.new
|
142
|
+
[a, b].each do |thrift_struct|
|
143
|
+
thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ]
|
144
|
+
thrift_struct.validate
|
145
|
+
end
|
146
|
+
expect(a).to eq(b)
|
147
|
+
b.value.push({ 3 => 4, 5 => 6 })
|
148
|
+
expect(a).not_to eq(b)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should support nested maps inside sets" do
|
153
|
+
with_type_checking do
|
154
|
+
a, b = SpecNamespace::NestedMapInSet.new, SpecNamespace::NestedMapInSet.new
|
155
|
+
[a, b].each do |thrift_struct|
|
156
|
+
thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ].to_set
|
157
|
+
thrift_struct.validate
|
158
|
+
end
|
159
|
+
expect(a).to eq(b)
|
160
|
+
b.value.add({ 3 => 4, 5 => 6 })
|
161
|
+
expect(a).not_to eq(b)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should support nested maps in map keys" do
|
166
|
+
with_type_checking do
|
167
|
+
a, b = SpecNamespace::NestedMapInMapKey.new, SpecNamespace::NestedMapInMapKey.new
|
168
|
+
[a, b].each do |thrift_struct|
|
169
|
+
thrift_struct.value = { { 1 => 2, 3 => 4} => 1, {2 => 3, 4 => 5} => 2 }
|
170
|
+
thrift_struct.validate
|
171
|
+
end
|
172
|
+
expect(a).to eq(b)
|
173
|
+
b.value[{3 => 4, 5 => 6}] = 3
|
174
|
+
expect(a).not_to eq(b)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should support nested maps in map values" do
|
179
|
+
with_type_checking do
|
180
|
+
a, b = SpecNamespace::NestedMapInMapValue.new, SpecNamespace::NestedMapInMapValue.new
|
181
|
+
[a, b].each do |thrift_struct|
|
182
|
+
thrift_struct.value = { 1 => { 1 => 2, 3 => 4}, 2 => {2 => 3, 4 => 5} }
|
183
|
+
thrift_struct.validate
|
184
|
+
end
|
185
|
+
expect(a).to eq(b)
|
186
|
+
b.value[3] = { 3 => 4, 5 => 6 }
|
187
|
+
expect(a).not_to eq(b)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
data/spec/struct_spec.rb
CHANGED
@@ -17,204 +17,202 @@
|
|
17
17
|
# under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
20
|
+
require 'spec_helper'
|
21
21
|
|
22
|
-
|
23
|
-
include Thrift
|
24
|
-
include SpecNamespace
|
22
|
+
describe 'Struct' do
|
25
23
|
|
26
|
-
describe Struct do
|
24
|
+
describe Thrift::Struct do
|
27
25
|
it "should iterate over all fields properly" do
|
28
26
|
fields = {}
|
29
|
-
Foo.new.each_field { |fid,field_info| fields[fid] = field_info }
|
30
|
-
fields.
|
27
|
+
SpecNamespace::Foo.new.each_field { |fid,field_info| fields[fid] = field_info }
|
28
|
+
expect(fields).to eq(SpecNamespace::Foo::FIELDS)
|
31
29
|
end
|
32
30
|
|
33
31
|
it "should initialize all fields to defaults" do
|
34
|
-
validate_default_arguments(Foo.new)
|
32
|
+
validate_default_arguments(SpecNamespace::Foo.new)
|
35
33
|
end
|
36
34
|
|
37
35
|
it "should initialize all fields to defaults and accept a block argument" do
|
38
|
-
Foo.new do |f|
|
36
|
+
SpecNamespace::Foo.new do |f|
|
39
37
|
validate_default_arguments(f)
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
43
41
|
def validate_default_arguments(object)
|
44
|
-
object.simple.
|
45
|
-
object.words.
|
46
|
-
object.hello.
|
47
|
-
object.ints.
|
48
|
-
object.complex.
|
49
|
-
object.shorts.
|
42
|
+
expect(object.simple).to eq(53)
|
43
|
+
expect(object.words).to eq("words")
|
44
|
+
expect(object.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!'))
|
45
|
+
expect(object.ints).to eq([1, 2, 2, 3])
|
46
|
+
expect(object.complex).to be_nil
|
47
|
+
expect(object.shorts).to eq(Set.new([5, 17, 239]))
|
50
48
|
end
|
51
49
|
|
52
50
|
it "should not share default values between instances" do
|
53
51
|
begin
|
54
|
-
struct = Foo.new
|
52
|
+
struct = SpecNamespace::Foo.new
|
55
53
|
struct.ints << 17
|
56
|
-
Foo.new.ints.
|
54
|
+
expect(SpecNamespace::Foo.new.ints).to eq([1,2,2,3])
|
57
55
|
ensure
|
58
56
|
# ensure no leakage to other tests
|
59
|
-
Foo::FIELDS[4][:default] = [1,2,2,3]
|
57
|
+
SpecNamespace::Foo::FIELDS[4][:default] = [1,2,2,3]
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
63
61
|
it "should properly initialize boolean values" do
|
64
|
-
struct = BoolStruct.new(:yesno => false)
|
65
|
-
struct.yesno.
|
62
|
+
struct = SpecNamespace::BoolStruct.new(:yesno => false)
|
63
|
+
expect(struct.yesno).to be_falsey
|
66
64
|
end
|
67
65
|
|
68
66
|
it "should have proper == semantics" do
|
69
|
-
Foo.new.
|
70
|
-
Foo.new.
|
71
|
-
Foo.new(:simple => 52).
|
67
|
+
expect(SpecNamespace::Foo.new).not_to eq(SpecNamespace::Hello.new)
|
68
|
+
expect(SpecNamespace::Foo.new).to eq(SpecNamespace::Foo.new)
|
69
|
+
expect(SpecNamespace::Foo.new(:simple => 52)).not_to eq(SpecNamespace::Foo.new)
|
72
70
|
end
|
73
71
|
|
74
72
|
it "should print enum value names in inspect" do
|
75
|
-
StructWithSomeEnum.new(:some_enum => SomeEnum::ONE).inspect.
|
73
|
+
expect(SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("<SpecNamespace::StructWithSomeEnum some_enum:ONE (0)>")
|
76
74
|
|
77
|
-
StructWithEnumMap.new(:my_map => {SomeEnum::ONE => [SomeEnum::TWO]}).inspect.
|
75
|
+
expect(SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("<SpecNamespace::StructWithEnumMap my_map:{ONE (0): [TWO (1)]}>")
|
78
76
|
end
|
79
77
|
|
80
78
|
it "should pretty print binary fields" do
|
81
|
-
Foo2.new(:my_binary => "\001\002\003").inspect.
|
79
|
+
expect(SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect).to eq("<SpecNamespace::Foo2 my_binary:010203>")
|
82
80
|
end
|
83
81
|
|
84
82
|
it "should offer field? methods" do
|
85
|
-
Foo.new.opt_string
|
86
|
-
Foo.new(:simple => 52).simple
|
87
|
-
Foo.new(:my_bool => false).my_bool
|
88
|
-
Foo.new(:my_bool => true).my_bool
|
83
|
+
expect(SpecNamespace::Foo.new.opt_string?).to be_falsey
|
84
|
+
expect(SpecNamespace::Foo.new(:simple => 52).simple?).to be_truthy
|
85
|
+
expect(SpecNamespace::Foo.new(:my_bool => false).my_bool?).to be_truthy
|
86
|
+
expect(SpecNamespace::Foo.new(:my_bool => true).my_bool?).to be_truthy
|
89
87
|
end
|
90
88
|
|
91
89
|
it "should be comparable" do
|
92
|
-
s1 = StructWithSomeEnum.new(:some_enum => SomeEnum::ONE)
|
93
|
-
s2 = StructWithSomeEnum.new(:some_enum => SomeEnum::TWO)
|
90
|
+
s1 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE)
|
91
|
+
s2 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::TWO)
|
94
92
|
|
95
|
-
(s1 <=> s2).
|
96
|
-
(s2 <=> s1).
|
97
|
-
(s1 <=> s1).
|
98
|
-
(s1 <=> StructWithSomeEnum.new()).
|
93
|
+
expect(s1 <=> s2).to eq(-1)
|
94
|
+
expect(s2 <=> s1).to eq(1)
|
95
|
+
expect(s1 <=> s1).to eq(0)
|
96
|
+
expect(s1 <=> SpecNamespace::StructWithSomeEnum.new()).to eq(-1)
|
99
97
|
end
|
100
98
|
|
101
99
|
it "should read itself off the wire" do
|
102
|
-
struct = Foo.new
|
103
|
-
prot = BaseProtocol.new(
|
104
|
-
prot.
|
105
|
-
prot.
|
106
|
-
prot.
|
107
|
-
['complex', Types::MAP, 5], # Foo
|
108
|
-
['words', Types::STRING, 2], # Foo
|
109
|
-
['hello', Types::STRUCT, 3], # Foo
|
110
|
-
['greeting', Types::STRING, 1], # Hello
|
111
|
-
[nil, Types::STOP, 0], # Hello
|
112
|
-
['simple', Types::I32, 1], # Foo
|
113
|
-
['ints', Types::LIST, 4], # Foo
|
114
|
-
['shorts', Types::SET, 6], # Foo
|
115
|
-
[nil, Types::STOP, 0] # Hello
|
100
|
+
struct = SpecNamespace::Foo.new
|
101
|
+
prot = Thrift::BaseProtocol.new(double("transport"))
|
102
|
+
expect(prot).to receive(:read_struct_begin).twice
|
103
|
+
expect(prot).to receive(:read_struct_end).twice
|
104
|
+
expect(prot).to receive(:read_field_begin).and_return(
|
105
|
+
['complex', Thrift::Types::MAP, 5], # Foo
|
106
|
+
['words', Thrift::Types::STRING, 2], # Foo
|
107
|
+
['hello', Thrift::Types::STRUCT, 3], # Foo
|
108
|
+
['greeting', Thrift::Types::STRING, 1], # Hello
|
109
|
+
[nil, Thrift::Types::STOP, 0], # Hello
|
110
|
+
['simple', Thrift::Types::I32, 1], # Foo
|
111
|
+
['ints', Thrift::Types::LIST, 4], # Foo
|
112
|
+
['shorts', Thrift::Types::SET, 6], # Foo
|
113
|
+
[nil, Thrift::Types::STOP, 0] # Hello
|
116
114
|
)
|
117
|
-
prot.
|
118
|
-
prot.
|
119
|
-
[Types::I32, Types::MAP, 2], # complex
|
120
|
-
[Types::STRING, Types::DOUBLE, 2], # complex/1/value
|
121
|
-
[Types::STRING, Types::DOUBLE, 1] # complex/2/value
|
115
|
+
expect(prot).to receive(:read_field_end).exactly(7).times
|
116
|
+
expect(prot).to receive(:read_map_begin).and_return(
|
117
|
+
[Thrift::Types::I32, Thrift::Types::MAP, 2], # complex
|
118
|
+
[Thrift::Types::STRING, Thrift::Types::DOUBLE, 2], # complex/1/value
|
119
|
+
[Thrift::Types::STRING, Thrift::Types::DOUBLE, 1] # complex/2/value
|
122
120
|
)
|
123
|
-
prot.
|
124
|
-
prot.
|
125
|
-
prot.
|
126
|
-
prot.
|
127
|
-
prot.
|
128
|
-
prot.
|
121
|
+
expect(prot).to receive(:read_map_end).exactly(3).times
|
122
|
+
expect(prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, 4])
|
123
|
+
expect(prot).to receive(:read_list_end)
|
124
|
+
expect(prot).to receive(:read_set_begin).and_return([Thrift::Types::I16, 2])
|
125
|
+
expect(prot).to receive(:read_set_end)
|
126
|
+
expect(prot).to receive(:read_i32).and_return(
|
129
127
|
1, 14, # complex keys
|
130
128
|
42, # simple
|
131
129
|
4, 23, 4, 29 # ints
|
132
130
|
)
|
133
|
-
prot.
|
134
|
-
prot.
|
135
|
-
prot.
|
136
|
-
prot.
|
131
|
+
expect(prot).to receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
|
132
|
+
expect(prot).to receive(:read_double).and_return(Math::PI, Math::E, 4.669201609)
|
133
|
+
expect(prot).to receive(:read_i16).and_return(2, 3)
|
134
|
+
expect(prot).not_to receive(:skip)
|
137
135
|
struct.read(prot)
|
138
136
|
|
139
|
-
struct.simple.
|
140
|
-
struct.complex.
|
141
|
-
struct.hello.
|
142
|
-
struct.words.
|
143
|
-
struct.ints.
|
144
|
-
struct.shorts.
|
137
|
+
expect(struct.simple).to eq(42)
|
138
|
+
expect(struct.complex).to eq({1 => {"pi" => Math::PI, "e" => Math::E}, 14 => {"feigenbaum" => 4.669201609}})
|
139
|
+
expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => "what's up?"))
|
140
|
+
expect(struct.words).to eq("apple banana")
|
141
|
+
expect(struct.ints).to eq([4, 23, 4, 29])
|
142
|
+
expect(struct.shorts).to eq(Set.new([3, 2]))
|
145
143
|
end
|
146
144
|
|
147
145
|
it "should serialize false boolean fields correctly" do
|
148
|
-
b = BoolStruct.new(:yesno => false)
|
149
|
-
prot = BinaryProtocol.new(MemoryBufferTransport.new)
|
150
|
-
prot.
|
146
|
+
b = SpecNamespace::BoolStruct.new(:yesno => false)
|
147
|
+
prot = Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new)
|
148
|
+
expect(prot).to receive(:write_bool).with(false)
|
151
149
|
b.write(prot)
|
152
150
|
end
|
153
151
|
|
154
152
|
it "should skip unexpected fields in structs and use default values" do
|
155
|
-
struct = Foo.new
|
156
|
-
prot = BaseProtocol.new(
|
157
|
-
prot.
|
158
|
-
prot.
|
159
|
-
prot.
|
160
|
-
['simple', Types::I32, 1],
|
161
|
-
['complex', Types::STRUCT, 5],
|
162
|
-
['thinz', Types::MAP, 7],
|
163
|
-
['foobar', Types::I32, 3],
|
164
|
-
['words', Types::STRING, 2],
|
165
|
-
[nil, Types::STOP, 0]
|
153
|
+
struct = SpecNamespace::Foo.new
|
154
|
+
prot = Thrift::BaseProtocol.new(double("transport"))
|
155
|
+
expect(prot).to receive(:read_struct_begin)
|
156
|
+
expect(prot).to receive(:read_struct_end)
|
157
|
+
expect(prot).to receive(:read_field_begin).and_return(
|
158
|
+
['simple', Thrift::Types::I32, 1],
|
159
|
+
['complex', Thrift::Types::STRUCT, 5],
|
160
|
+
['thinz', Thrift::Types::MAP, 7],
|
161
|
+
['foobar', Thrift::Types::I32, 3],
|
162
|
+
['words', Thrift::Types::STRING, 2],
|
163
|
+
[nil, Thrift::Types::STOP, 0]
|
166
164
|
)
|
167
|
-
prot.
|
168
|
-
prot.
|
169
|
-
prot.
|
170
|
-
prot.
|
171
|
-
prot.
|
172
|
-
# prot.should_receive(:read_map_begin).and_return([Types::I32, Types::I32, 0])
|
165
|
+
expect(prot).to receive(:read_field_end).exactly(5).times
|
166
|
+
expect(prot).to receive(:read_i32).and_return(42)
|
167
|
+
expect(prot).to receive(:read_string).and_return("foobar")
|
168
|
+
expect(prot).to receive(:skip).with(Thrift::Types::STRUCT)
|
169
|
+
expect(prot).to receive(:skip).with(Thrift::Types::MAP)
|
170
|
+
# prot.should_receive(:read_map_begin).and_return([Thrift::Types::I32, Thrift::Types::I32, 0])
|
173
171
|
# prot.should_receive(:read_map_end)
|
174
|
-
prot.
|
172
|
+
expect(prot).to receive(:skip).with(Thrift::Types::I32)
|
175
173
|
struct.read(prot)
|
176
174
|
|
177
|
-
struct.simple.
|
178
|
-
struct.complex.
|
179
|
-
struct.words.
|
180
|
-
struct.hello.
|
181
|
-
struct.ints.
|
182
|
-
struct.shorts.
|
175
|
+
expect(struct.simple).to eq(42)
|
176
|
+
expect(struct.complex).to be_nil
|
177
|
+
expect(struct.words).to eq("foobar")
|
178
|
+
expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!'))
|
179
|
+
expect(struct.ints).to eq([1, 2, 2, 3])
|
180
|
+
expect(struct.shorts).to eq(Set.new([5, 17, 239]))
|
183
181
|
end
|
184
182
|
|
185
183
|
it "should write itself to the wire" do
|
186
|
-
prot = BaseProtocol.new(
|
187
|
-
prot.
|
188
|
-
prot.
|
189
|
-
prot.
|
190
|
-
prot.
|
191
|
-
prot.
|
192
|
-
prot.
|
193
|
-
prot.
|
194
|
-
prot.
|
195
|
-
prot.
|
196
|
-
prot.
|
197
|
-
prot.
|
198
|
-
prot.
|
199
|
-
prot.
|
200
|
-
prot.
|
201
|
-
prot.
|
202
|
-
prot.
|
203
|
-
prot.
|
204
|
-
prot.
|
205
|
-
prot.
|
206
|
-
prot.
|
207
|
-
prot.
|
208
|
-
prot.
|
209
|
-
prot.
|
210
|
-
prot.
|
211
|
-
prot.
|
212
|
-
prot.
|
213
|
-
prot.
|
214
|
-
prot.
|
215
|
-
prot.
|
184
|
+
prot = Thrift::BaseProtocol.new(double("transport")) #mock("Protocol")
|
185
|
+
expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Foo")
|
186
|
+
expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Hello")
|
187
|
+
expect(prot).to receive(:write_struct_end).twice
|
188
|
+
expect(prot).to receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4)
|
189
|
+
expect(prot).to receive(:write_i32).with(1)
|
190
|
+
expect(prot).to receive(:write_i32).with(2).twice
|
191
|
+
expect(prot).to receive(:write_i32).with(3)
|
192
|
+
expect(prot).to receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5)
|
193
|
+
expect(prot).to receive(:write_i32).with(5)
|
194
|
+
expect(prot).to receive(:write_string).with('foo')
|
195
|
+
expect(prot).to receive(:write_double).with(1.23)
|
196
|
+
expect(prot).to receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6)
|
197
|
+
expect(prot).to receive(:write_i16).with(5)
|
198
|
+
expect(prot).to receive(:write_i16).with(17)
|
199
|
+
expect(prot).to receive(:write_i16).with(239)
|
200
|
+
expect(prot).to receive(:write_field_stop).twice
|
201
|
+
expect(prot).to receive(:write_field_end).exactly(6).times
|
202
|
+
expect(prot).to receive(:write_field_begin).with('simple', Thrift::Types::I32, 1)
|
203
|
+
expect(prot).to receive(:write_i32).with(53)
|
204
|
+
expect(prot).to receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3)
|
205
|
+
expect(prot).to receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1)
|
206
|
+
expect(prot).to receive(:write_string).with('hello, world!')
|
207
|
+
expect(prot).to receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1)
|
208
|
+
expect(prot).to receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1)
|
209
|
+
expect(prot).to receive(:write_map_end).twice
|
210
|
+
expect(prot).to receive(:write_list_begin).with(Thrift::Types::I32, 4)
|
211
|
+
expect(prot).to receive(:write_list_end)
|
212
|
+
expect(prot).to receive(:write_set_begin).with(Thrift::Types::I16, 3)
|
213
|
+
expect(prot).to receive(:write_set_end)
|
216
214
|
|
217
|
-
struct = Foo.new
|
215
|
+
struct = SpecNamespace::Foo.new
|
218
216
|
struct.words = nil
|
219
217
|
struct.complex = {5 => {"foo" => 1.23}}
|
220
218
|
struct.write(prot)
|
@@ -222,51 +220,51 @@ class ThriftStructSpec < Spec::ExampleGroup
|
|
222
220
|
|
223
221
|
it "should raise an exception if presented with an unknown container" do
|
224
222
|
# yeah this is silly, but I'm going for code coverage here
|
225
|
-
struct = Foo.new
|
226
|
-
|
223
|
+
struct = SpecNamespace::Foo.new
|
224
|
+
expect { struct.send :write_container, nil, nil, {:type => "foo"} }.to raise_error(StandardError, "Not a container type: foo")
|
227
225
|
end
|
228
226
|
|
229
227
|
it "should support optional type-checking in Thrift::Struct.new" do
|
230
228
|
Thrift.type_checking = true
|
231
229
|
begin
|
232
|
-
|
230
|
+
expect { SpecNamespace::Hello.new(:greeting => 3) }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/)
|
233
231
|
ensure
|
234
232
|
Thrift.type_checking = false
|
235
233
|
end
|
236
|
-
|
234
|
+
expect { SpecNamespace::Hello.new(:greeting => 3) }.not_to raise_error
|
237
235
|
end
|
238
236
|
|
239
237
|
it "should support optional type-checking in field accessors" do
|
240
238
|
Thrift.type_checking = true
|
241
239
|
begin
|
242
|
-
hello = Hello.new
|
243
|
-
|
240
|
+
hello = SpecNamespace::Hello.new
|
241
|
+
expect { hello.greeting = 3 }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/)
|
244
242
|
ensure
|
245
243
|
Thrift.type_checking = false
|
246
244
|
end
|
247
|
-
|
245
|
+
expect { hello.greeting = 3 }.not_to raise_error
|
248
246
|
end
|
249
247
|
|
250
248
|
it "should raise an exception when unknown types are given to Thrift::Struct.new" do
|
251
|
-
|
249
|
+
expect { SpecNamespace::Hello.new(:fish => 'salmon') }.to raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
|
252
250
|
end
|
253
251
|
|
254
252
|
it "should support `raise Xception, 'message'` for Exception structs" do
|
255
253
|
begin
|
256
|
-
raise Xception, "something happened"
|
254
|
+
raise SpecNamespace::Xception, "something happened"
|
257
255
|
rescue Thrift::Exception => e
|
258
|
-
e.message.
|
259
|
-
e.code.
|
256
|
+
expect(e.message).to eq("something happened")
|
257
|
+
expect(e.code).to eq(1)
|
260
258
|
# ensure it gets serialized properly, this is the really important part
|
261
|
-
prot = BaseProtocol.new(
|
262
|
-
prot.
|
263
|
-
prot.
|
264
|
-
prot.
|
265
|
-
prot.
|
266
|
-
prot.
|
267
|
-
prot.
|
268
|
-
prot.
|
269
|
-
prot.
|
259
|
+
prot = Thrift::BaseProtocol.new(double("trans"))
|
260
|
+
expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
|
261
|
+
expect(prot).to receive(:write_struct_end)
|
262
|
+
expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)#, "something happened")
|
263
|
+
expect(prot).to receive(:write_string).with("something happened")
|
264
|
+
expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)#, 1)
|
265
|
+
expect(prot).to receive(:write_i32).with(1)
|
266
|
+
expect(prot).to receive(:write_field_stop)
|
267
|
+
expect(prot).to receive(:write_field_end).twice
|
270
268
|
|
271
269
|
e.write(prot)
|
272
270
|
end
|
@@ -274,19 +272,19 @@ class ThriftStructSpec < Spec::ExampleGroup
|
|
274
272
|
|
275
273
|
it "should support the regular initializer for exception structs" do
|
276
274
|
begin
|
277
|
-
raise Xception, :message => "something happened", :code => 5
|
275
|
+
raise SpecNamespace::Xception, :message => "something happened", :code => 5
|
278
276
|
rescue Thrift::Exception => e
|
279
|
-
e.message.
|
280
|
-
e.code.
|
281
|
-
prot = BaseProtocol.new(
|
282
|
-
prot.
|
283
|
-
prot.
|
284
|
-
prot.
|
285
|
-
prot.
|
286
|
-
prot.
|
287
|
-
prot.
|
288
|
-
prot.
|
289
|
-
prot.
|
277
|
+
expect(e.message).to eq("something happened")
|
278
|
+
expect(e.code).to eq(5)
|
279
|
+
prot = Thrift::BaseProtocol.new(double("trans"))
|
280
|
+
expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
|
281
|
+
expect(prot).to receive(:write_struct_end)
|
282
|
+
expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
|
283
|
+
expect(prot).to receive(:write_string).with("something happened")
|
284
|
+
expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
|
285
|
+
expect(prot).to receive(:write_i32).with(5)
|
286
|
+
expect(prot).to receive(:write_field_stop)
|
287
|
+
expect(prot).to receive(:write_field_end).twice
|
290
288
|
|
291
289
|
e.write(prot)
|
292
290
|
end
|