thrift 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +107 -4
  3. data/ext/binary_protocol_accelerated.c +52 -17
  4. data/ext/compact_protocol.c +135 -70
  5. data/ext/constants.h +3 -0
  6. data/ext/extconf.rb +4 -4
  7. data/ext/macros.h +11 -0
  8. data/ext/memory_buffer.c +35 -17
  9. data/ext/struct.c +185 -64
  10. data/ext/thrift_native.c +6 -0
  11. data/lib/thrift/bytes.rb +2 -2
  12. data/lib/thrift/client.rb +31 -22
  13. data/lib/thrift/exceptions.rb +10 -8
  14. data/lib/thrift/multiplexed_processor.rb +5 -6
  15. data/lib/thrift/processor.rb +24 -3
  16. data/lib/thrift/protocol/base_protocol.rb +53 -27
  17. data/lib/thrift/protocol/binary_protocol.rb +54 -40
  18. data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -2
  19. data/lib/thrift/protocol/compact_protocol.rb +193 -88
  20. data/lib/thrift/protocol/header_protocol.rb +14 -3
  21. data/lib/thrift/protocol/json_protocol.rb +146 -104
  22. data/lib/thrift/protocol/multiplexed_protocol.rb +2 -3
  23. data/lib/thrift/protocol/protocol_decorator.rb +5 -2
  24. data/lib/thrift/serializer/serializer.rb +6 -0
  25. data/lib/thrift/server/base_server.rb +10 -2
  26. data/lib/thrift/server/nonblocking_server.rb +49 -26
  27. data/lib/thrift/server/rack_application.rb +69 -0
  28. data/lib/thrift/server/simple_server.rb +27 -23
  29. data/lib/thrift/server/thin_http_server.rb +20 -44
  30. data/lib/thrift/server/thread_pool_server.rb +20 -17
  31. data/lib/thrift/server/threaded_server.rb +22 -26
  32. data/lib/thrift/struct.rb +33 -18
  33. data/lib/thrift/struct_union.rb +36 -30
  34. data/lib/thrift/transport/base_transport.rb +23 -5
  35. data/lib/thrift/transport/buffered_transport.rb +4 -4
  36. data/lib/thrift/transport/framed_transport.rb +32 -7
  37. data/lib/thrift/transport/header_transport.rb +130 -50
  38. data/lib/thrift/transport/http_client_transport.rb +27 -14
  39. data/lib/thrift/transport/io_stream_transport.rb +2 -1
  40. data/lib/thrift/transport/memory_buffer_transport.rb +8 -10
  41. data/lib/thrift/transport/server_socket.rb +4 -5
  42. data/lib/thrift/transport/socket.rb +20 -22
  43. data/lib/thrift/transport/ssl_server_socket.rb +64 -4
  44. data/lib/thrift/transport/ssl_socket.rb +32 -5
  45. data/lib/thrift/transport/unix_server_socket.rb +1 -1
  46. data/lib/thrift/transport/unix_socket.rb +4 -6
  47. data/lib/thrift/types.rb +22 -22
  48. data/lib/thrift/union.rb +20 -11
  49. data/lib/thrift/uuid.rb +8 -8
  50. data/lib/thrift.rb +39 -39
  51. metadata +5 -230
  52. data/benchmark/Benchmark.thrift +0 -24
  53. data/benchmark/benchmark.rb +0 -286
  54. data/benchmark/client.rb +0 -118
  55. data/benchmark/server.rb +0 -121
  56. data/benchmark/thin_server.rb +0 -46
  57. data/lib/thrift/server/mongrel_http_server.rb +0 -61
  58. data/spec/BaseService.thrift +0 -27
  59. data/spec/ExtendedService.thrift +0 -25
  60. data/spec/Referenced.thrift +0 -44
  61. data/spec/ThriftNamespacedSpec.thrift +0 -53
  62. data/spec/ThriftSpec.thrift +0 -203
  63. data/spec/base_protocol_spec.rb +0 -244
  64. data/spec/base_transport_spec.rb +0 -428
  65. data/spec/binary_protocol_accelerated_spec.rb +0 -47
  66. data/spec/binary_protocol_spec.rb +0 -73
  67. data/spec/binary_protocol_spec_shared.rb +0 -509
  68. data/spec/bytes_spec.rb +0 -117
  69. data/spec/client_spec.rb +0 -167
  70. data/spec/compact_protocol_spec.rb +0 -295
  71. data/spec/constants_demo_spec.rb +0 -102
  72. data/spec/exception_spec.rb +0 -141
  73. data/spec/flat_spec.rb +0 -63
  74. data/spec/header_protocol_spec.rb +0 -476
  75. data/spec/header_transport_spec.rb +0 -431
  76. data/spec/http_client_spec.rb +0 -160
  77. data/spec/json_protocol_spec.rb +0 -574
  78. data/spec/multiplexed_processor_spec.rb +0 -75
  79. data/spec/namespaced_spec.rb +0 -67
  80. data/spec/nonblocking_server_spec.rb +0 -429
  81. data/spec/processor_spec.rb +0 -80
  82. data/spec/recursion_depth_spec.rb +0 -223
  83. data/spec/serializer_spec.rb +0 -67
  84. data/spec/server_socket_spec.rb +0 -121
  85. data/spec/server_spec.rb +0 -238
  86. data/spec/socket_spec.rb +0 -174
  87. data/spec/socket_spec_shared.rb +0 -168
  88. data/spec/spec_helper.rb +0 -70
  89. data/spec/ssl_server_socket_spec.rb +0 -85
  90. data/spec/ssl_socket_spec.rb +0 -248
  91. data/spec/struct_nested_containers_spec.rb +0 -191
  92. data/spec/struct_spec.rb +0 -398
  93. data/spec/support/header_protocol_helper.rb +0 -55
  94. data/spec/thin_http_server_spec.rb +0 -127
  95. data/spec/types_spec.rb +0 -118
  96. data/spec/union_spec.rb +0 -273
  97. data/spec/unix_socket_spec.rb +0 -131
  98. data/spec/uuid_validation_spec.rb +0 -239
  99. data/test/fuzz/Makefile +0 -779
  100. data/test/fuzz/Makefile.am +0 -173
  101. data/test/fuzz/Makefile.in +0 -775
  102. data/test/fuzz/README.md +0 -149
  103. data/test/fuzz/fuzz_common.rb +0 -96
  104. data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -23
  105. data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -23
  106. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -23
  107. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -23
  108. data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -23
  109. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -23
  110. data/test/fuzz/fuzz_parse_json_protocol.rb +0 -23
  111. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -23
  112. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -23
  113. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -23
  114. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -23
  115. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -23
  116. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -23
  117. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -23
  118. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -23
  119. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -23
  120. data/test/fuzz/fuzz_tracer.rb +0 -29
data/spec/struct_spec.rb DELETED
@@ -1,398 +0,0 @@
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 'Struct' do
24
- describe Thrift::Struct do
25
- it "should iterate over all fields properly" do
26
- fields = {}
27
- SpecNamespace::Foo.new.each_field { |fid, field_info| fields[fid] = field_info }
28
- expect(fields).to eq(SpecNamespace::Foo::FIELDS)
29
- end
30
-
31
- it "should initialize all fields to defaults" do
32
- validate_default_arguments(SpecNamespace::Foo.new)
33
- end
34
-
35
- it "should initialize all fields to defaults and accept a block argument" do
36
- SpecNamespace::Foo.new do |f|
37
- validate_default_arguments(f)
38
- end
39
- end
40
-
41
- def validate_default_arguments(object)
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]))
48
- end
49
-
50
- it "should not share default values between instances" do
51
- begin
52
- struct = SpecNamespace::Foo.new
53
- struct.ints << 17
54
- expect(SpecNamespace::Foo.new.ints).to eq([1, 2, 2, 3])
55
- ensure
56
- # ensure no leakage to other tests
57
- SpecNamespace::Foo::FIELDS[4][:default] = [1, 2, 2, 3]
58
- end
59
- end
60
-
61
- it "should properly initialize boolean values" do
62
- struct = SpecNamespace::BoolStruct.new(:yesno => false)
63
- expect(struct.yesno).to be_falsey
64
- end
65
-
66
- it "should have proper == semantics" do
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)
70
- end
71
-
72
- it "should print enum value names in inspect" do
73
- expect(SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("<SpecNamespace::StructWithSomeEnum some_enum:ONE (0)>")
74
-
75
- expect(SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("<SpecNamespace::StructWithEnumMap my_map:{ONE (0): [TWO (1)]}>")
76
- end
77
-
78
- it "should pretty print binary fields" do
79
- expect(SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect).to eq("<SpecNamespace::Foo2 my_binary:010203>")
80
- end
81
-
82
- it "should offer field? methods" do
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
87
- end
88
-
89
- it "should be comparable" do
90
- s1 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE)
91
- s2 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::TWO)
92
-
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)
97
- end
98
-
99
- it "should read itself off the wire" do
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
114
- )
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
120
- )
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(
127
- 1, 14, # complex keys
128
- 42, # simple
129
- 4, 23, 4, 29 # ints
130
- )
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)
135
- struct.read(prot)
136
-
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]))
143
- end
144
-
145
- it "rejects negative container sizes while reading" do
146
- struct = SpecNamespace::Foo.new
147
- prot = Thrift::BaseProtocol.new(double("transport"))
148
-
149
- expect(prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, -1])
150
-
151
- expect {
152
- struct.send(:read_field, prot, SpecNamespace::Foo::FIELDS[4])
153
- }.to raise_error(Thrift::ProtocolException, "Negative size") { |error|
154
- expect(error.type).to eq(Thrift::ProtocolException::NEGATIVE_SIZE)
155
- }
156
- end
157
-
158
- it "does not preallocate arrays from declared list sizes" do
159
- struct = SpecNamespace::Foo.new
160
- prot = Thrift::BaseProtocol.new(double("transport"))
161
- declared_size = 1 << 30
162
- sentinel = RuntimeError.new("stop after first element")
163
-
164
- expect(prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, declared_size])
165
- expect(prot).to receive(:read_i32).and_raise(sentinel)
166
- expect(Array).not_to receive(:new).with(declared_size)
167
-
168
- expect {
169
- struct.send(:read_field, prot, SpecNamespace::Foo::FIELDS[4])
170
- }.to raise_error(sentinel)
171
- end
172
-
173
- it "should serialize false boolean fields correctly" do
174
- b = SpecNamespace::BoolStruct.new(:yesno => false)
175
- prot = Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new)
176
- expect(prot).to receive(:write_bool).with(false)
177
- b.write(prot)
178
- end
179
-
180
- it "should skip unexpected fields in structs and use default values" do
181
- struct = SpecNamespace::Foo.new
182
- prot = Thrift::BaseProtocol.new(double("transport"))
183
- expect(prot).to receive(:read_struct_begin)
184
- expect(prot).to receive(:read_struct_end)
185
- expect(prot).to receive(:read_field_begin).and_return(
186
- ['simple', Thrift::Types::I32, 1],
187
- ['complex', Thrift::Types::STRUCT, 5],
188
- ['thinz', Thrift::Types::MAP, 7],
189
- ['foobar', Thrift::Types::I32, 3],
190
- ['words', Thrift::Types::STRING, 2],
191
- [nil, Thrift::Types::STOP, 0]
192
- )
193
- expect(prot).to receive(:read_field_end).exactly(5).times
194
- expect(prot).to receive(:read_i32).and_return(42)
195
- expect(prot).to receive(:read_string).and_return("foobar")
196
- expect(prot).to receive(:skip).with(Thrift::Types::STRUCT)
197
- expect(prot).to receive(:skip).with(Thrift::Types::MAP)
198
- # prot.should_receive(:read_map_begin).and_return([Thrift::Types::I32, Thrift::Types::I32, 0])
199
- # prot.should_receive(:read_map_end)
200
- expect(prot).to receive(:skip).with(Thrift::Types::I32)
201
- struct.read(prot)
202
-
203
- expect(struct.simple).to eq(42)
204
- expect(struct.complex).to be_nil
205
- expect(struct.words).to eq("foobar")
206
- expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!'))
207
- expect(struct.ints).to eq([1, 2, 2, 3])
208
- expect(struct.shorts).to eq(Set.new([5, 17, 239]))
209
- end
210
-
211
- it "should write itself to the wire" do
212
- prot = Thrift::BaseProtocol.new(double("transport")) # mock("Protocol")
213
- expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Foo")
214
- expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Hello")
215
- expect(prot).to receive(:write_struct_end).twice
216
- expect(prot).to receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4)
217
- expect(prot).to receive(:write_i32).with(1)
218
- expect(prot).to receive(:write_i32).with(2).twice
219
- expect(prot).to receive(:write_i32).with(3)
220
- expect(prot).to receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5)
221
- expect(prot).to receive(:write_i32).with(5)
222
- expect(prot).to receive(:write_string).with('foo')
223
- expect(prot).to receive(:write_double).with(1.23)
224
- expect(prot).to receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6)
225
- expect(prot).to receive(:write_i16).with(5)
226
- expect(prot).to receive(:write_i16).with(17)
227
- expect(prot).to receive(:write_i16).with(239)
228
- expect(prot).to receive(:write_field_stop).twice
229
- expect(prot).to receive(:write_field_end).exactly(6).times
230
- expect(prot).to receive(:write_field_begin).with('simple', Thrift::Types::I32, 1)
231
- expect(prot).to receive(:write_i32).with(53)
232
- expect(prot).to receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3)
233
- expect(prot).to receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1)
234
- expect(prot).to receive(:write_string).with('hello, world!')
235
- expect(prot).to receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1)
236
- expect(prot).to receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1)
237
- expect(prot).to receive(:write_map_end).twice
238
- expect(prot).to receive(:write_list_begin).with(Thrift::Types::I32, 4)
239
- expect(prot).to receive(:write_list_end)
240
- expect(prot).to receive(:write_set_begin).with(Thrift::Types::I16, 3)
241
- expect(prot).to receive(:write_set_end)
242
-
243
- struct = SpecNamespace::Foo.new
244
- struct.words = nil
245
- struct.complex = {5 => {"foo" => 1.23}}
246
- struct.write(prot)
247
- end
248
-
249
- it "should raise an exception if presented with an unknown container" do
250
- # yeah this is silly, but I'm going for code coverage here
251
- struct = SpecNamespace::Foo.new
252
- expect { struct.send :write_container, nil, nil, {:type => "foo"} }.to raise_error(StandardError, "Not a container type: foo")
253
- end
254
-
255
- it "should support optional type-checking in Thrift::Struct.new" do
256
- Thrift.type_checking = true
257
- begin
258
- expect { SpecNamespace::Hello.new(:greeting => 3) }.to raise_error(Thrift::TypeError, "Expected Types::STRING, received Integer for field greeting")
259
- ensure
260
- Thrift.type_checking = false
261
- end
262
- expect { SpecNamespace::Hello.new(:greeting => 3) }.not_to raise_error
263
- end
264
-
265
- it "should support optional type-checking in field accessors" do
266
- Thrift.type_checking = true
267
- begin
268
- hello = SpecNamespace::Hello.new
269
- expect { hello.greeting = 3 }.to raise_error(Thrift::TypeError, "Expected Types::STRING, received Integer for field greeting")
270
- ensure
271
- Thrift.type_checking = false
272
- end
273
- expect { hello.greeting = 3 }.not_to raise_error
274
- end
275
-
276
- it "should raise an exception when unknown types are given to Thrift::Struct.new" do
277
- expect { SpecNamespace::Hello.new(:fish => 'salmon') }.to raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
278
- end
279
-
280
- it "should support `raise Xception, 'message'` for Exception structs" do
281
- begin
282
- raise SpecNamespace::Xception, "something happened"
283
- rescue Thrift::Exception => e
284
- expect(e.message).to eq("something happened")
285
- expect(e.code).to eq(1)
286
- # ensure it gets serialized properly, this is the really important part
287
- prot = Thrift::BaseProtocol.new(double("trans"))
288
- expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
289
- expect(prot).to receive(:write_struct_end)
290
- expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
291
- expect(prot).to receive(:write_string).with("something happened")
292
- expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
293
- expect(prot).to receive(:write_i32).with(1)
294
- expect(prot).to receive(:write_field_stop)
295
- expect(prot).to receive(:write_field_end).twice
296
-
297
- e.write(prot)
298
- end
299
- end
300
-
301
- it "should support the regular initializer for exception structs" do
302
- begin
303
- raise SpecNamespace::Xception, :message => "something happened", :code => 5
304
- rescue Thrift::Exception => e
305
- expect(e.message).to eq("something happened")
306
- expect(e.code).to eq(5)
307
- prot = Thrift::BaseProtocol.new(double("trans"))
308
- expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception")
309
- expect(prot).to receive(:write_struct_end)
310
- expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
311
- expect(prot).to receive(:write_string).with("something happened")
312
- expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
313
- expect(prot).to receive(:write_i32).with(5)
314
- expect(prot).to receive(:write_field_stop)
315
- expect(prot).to receive(:write_field_end).twice
316
-
317
- e.write(prot)
318
- end
319
- end
320
-
321
- it "should handle UUID fields in structs" do
322
- struct = SpecNamespace::Foo.new(
323
- simple: 42,
324
- words: 'test',
325
- opt_uuid: '550e8400-e29b-41d4-a716-446655440000'
326
- )
327
-
328
- trans = Thrift::MemoryBufferTransport.new
329
- prot = Thrift::BinaryProtocol.new(trans)
330
-
331
- struct.write(prot)
332
-
333
- result = SpecNamespace::Foo.new
334
- result.read(prot)
335
-
336
- expect(result.simple).to eq(42)
337
- expect(result.words).to eq('test')
338
- expect(result.opt_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
339
- end
340
-
341
- it "should handle optional UUID fields when unset" do
342
- struct = SpecNamespace::Foo.new(simple: 42, words: 'test')
343
- expect(struct.opt_uuid).to be_nil
344
- expect(struct.opt_uuid?).to be_falsey
345
- end
346
-
347
- it "should handle list of UUIDs in SimpleList" do
348
- uuids = ['550e8400-e29b-41d4-a716-446655440000', '6ba7b810-9dad-11d1-80b4-00c04fd430c8']
349
- struct = SpecNamespace::SimpleList.new(uuids: uuids)
350
-
351
- trans = Thrift::MemoryBufferTransport.new
352
- prot = Thrift::CompactProtocol.new(trans)
353
-
354
- struct.write(prot)
355
-
356
- result = SpecNamespace::SimpleList.new
357
- result.read(prot)
358
-
359
- expect(result.uuids).to eq(uuids)
360
- end
361
-
362
- it "should normalize UUID case to lowercase" do
363
- struct = SpecNamespace::Foo.new(opt_uuid: '550E8400-E29B-41D4-A716-446655440000')
364
-
365
- trans = Thrift::MemoryBufferTransport.new
366
- prot = Thrift::BinaryProtocol.new(trans)
367
-
368
- struct.write(prot)
369
-
370
- result = SpecNamespace::Foo.new
371
- result.read(prot)
372
-
373
- expect(result.opt_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
374
- end
375
-
376
- it "should handle UUID alongside other types in SimpleList" do
377
- struct = SpecNamespace::SimpleList.new(
378
- bools: [true, false],
379
- i32s: [1, 2, 3],
380
- strings: ['hello', 'world'],
381
- uuids: ['550e8400-e29b-41d4-a716-446655440000', '00000000-0000-0000-0000-000000000000']
382
- )
383
-
384
- trans = Thrift::MemoryBufferTransport.new
385
- prot = Thrift::BinaryProtocol.new(trans)
386
-
387
- struct.write(prot)
388
-
389
- result = SpecNamespace::SimpleList.new
390
- result.read(prot)
391
-
392
- expect(result.bools).to eq([true, false])
393
- expect(result.i32s).to eq([1, 2, 3])
394
- expect(result.strings).to eq(['hello', 'world'])
395
- expect(result.uuids).to eq(['550e8400-e29b-41d4-a716-446655440000', '00000000-0000-0000-0000-000000000000'])
396
- end
397
- end
398
- end
@@ -1,55 +0,0 @@
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,127 +0,0 @@
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
- require 'rack/test'
23
- require 'thrift/server/thin_http_server'
24
-
25
- describe Thrift::ThinHTTPServer do
26
- let(:processor) { double('processor') }
27
-
28
- describe "#initialize" do
29
- context "when using the defaults" do
30
- it "binds to port 80, with host 0.0.0.0, a path of '/'" do
31
- expect(Thin::Server).to receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder))
32
- Thrift::ThinHTTPServer.new(processor)
33
- end
34
-
35
- it 'creates a ThinHTTPServer::RackApplicationContext' do
36
- expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::BinaryProtocolFactory)).and_return(anything)
37
- Thrift::ThinHTTPServer.new(processor)
38
- end
39
-
40
- it "uses the BinaryProtocolFactory" do
41
- expect(Thrift::BinaryProtocolFactory).to receive(:new)
42
- Thrift::ThinHTTPServer.new(processor)
43
- end
44
- end
45
-
46
- context "when using the options" do
47
- it 'accepts :ip, :port, :path' do
48
- ip = "192.168.0.1"
49
- port = 3000
50
- path = "/thin"
51
- expect(Thin::Server).to receive(:new).with(ip, port, an_instance_of(Rack::Builder))
52
- Thrift::ThinHTTPServer.new(processor,
53
- :ip => ip,
54
- :port => port,
55
- :path => path)
56
- end
57
-
58
- it 'creates a ThinHTTPServer::RackApplicationContext with a different protocol factory' do
59
- expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::JsonProtocolFactory)).and_return(anything)
60
- Thrift::ThinHTTPServer.new(processor,
61
- :protocol_factory => Thrift::JsonProtocolFactory.new)
62
- end
63
- end
64
- end
65
-
66
- describe "#serve" do
67
- it 'starts the Thin server' do
68
- underlying_thin_server = double('thin server', :start => true)
69
- allow(Thin::Server).to receive(:new).and_return(underlying_thin_server)
70
-
71
- thin_thrift_server = Thrift::ThinHTTPServer.new(processor)
72
-
73
- expect(underlying_thin_server).to receive(:start)
74
- thin_thrift_server.serve
75
- end
76
- end
77
- end
78
-
79
- describe Thrift::ThinHTTPServer::RackApplication do
80
- include Rack::Test::Methods
81
-
82
- let(:processor) { double('processor') }
83
- let(:protocol_factory) { double('protocol factory') }
84
-
85
- def app
86
- Thrift::ThinHTTPServer::RackApplication.for("/", processor, protocol_factory)
87
- end
88
-
89
- context "404 response" do
90
- it 'receives a non-POST' do
91
- header('Content-Type', "application/x-thrift")
92
- get "/"
93
- expect(last_response.status).to eq 404
94
- end
95
-
96
- it 'receives a header other than application/x-thrift' do
97
- header('Content-Type', "application/json")
98
- post "/"
99
- expect(last_response.status).to eq 404
100
- end
101
- end
102
-
103
- context "200 response" do
104
- before do
105
- allow(protocol_factory).to receive(:get_protocol)
106
- allow(processor).to receive(:process)
107
- end
108
-
109
- it 'creates an IOStreamTransport' do
110
- header('Content-Type', "application/x-thrift")
111
- expect(Thrift::IOStreamTransport).to receive(:new).with(an_instance_of(Rack::Lint::InputWrapper), an_instance_of(Rack::Response))
112
- post "/"
113
- end
114
-
115
- it 'fetches the right protocol based on the Transport' do
116
- header('Content-Type', "application/x-thrift")
117
- expect(protocol_factory).to receive(:get_protocol).with(an_instance_of(Thrift::IOStreamTransport))
118
- post "/"
119
- end
120
-
121
- it 'status code 200' do
122
- header('Content-Type', "application/x-thrift")
123
- post "/"
124
- expect(last_response.ok?).to be true
125
- end
126
- end
127
- end