thrift-mavericks 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGELOG +1 -0
  3. data/README +43 -0
  4. data/benchmark/Benchmark.thrift +24 -0
  5. data/benchmark/benchmark.rb +271 -0
  6. data/benchmark/client.rb +74 -0
  7. data/benchmark/gen-rb/benchmark_constants.rb +11 -0
  8. data/benchmark/gen-rb/benchmark_service.rb +80 -0
  9. data/benchmark/gen-rb/benchmark_types.rb +10 -0
  10. data/benchmark/server.rb +82 -0
  11. data/benchmark/thin_server.rb +44 -0
  12. data/ext/binary_protocol_accelerated.c +441 -0
  13. data/ext/binary_protocol_accelerated.h +20 -0
  14. data/ext/compact_protocol.c +618 -0
  15. data/ext/compact_protocol.h +20 -0
  16. data/ext/constants.h +96 -0
  17. data/ext/extconf.rb +30 -0
  18. data/ext/macros.h +41 -0
  19. data/ext/memory_buffer.c +131 -0
  20. data/ext/memory_buffer.h +20 -0
  21. data/ext/protocol.c +185 -0
  22. data/ext/protocol.h +20 -0
  23. data/ext/strlcpy.c +41 -0
  24. data/ext/strlcpy.h +32 -0
  25. data/ext/struct.c +691 -0
  26. data/ext/struct.h +25 -0
  27. data/ext/thrift_native.c +196 -0
  28. data/lib/thrift.rb +64 -0
  29. data/lib/thrift/client.rb +62 -0
  30. data/lib/thrift/core_ext.rb +23 -0
  31. data/lib/thrift/core_ext/fixnum.rb +29 -0
  32. data/lib/thrift/exceptions.rb +84 -0
  33. data/lib/thrift/processor.rb +57 -0
  34. data/lib/thrift/protocol/base_protocol.rb +290 -0
  35. data/lib/thrift/protocol/binary_protocol.rb +229 -0
  36. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  37. data/lib/thrift/protocol/compact_protocol.rb +426 -0
  38. data/lib/thrift/serializer/deserializer.rb +33 -0
  39. data/lib/thrift/serializer/serializer.rb +34 -0
  40. data/lib/thrift/server/base_server.rb +31 -0
  41. data/lib/thrift/server/mongrel_http_server.rb +58 -0
  42. data/lib/thrift/server/nonblocking_server.rb +305 -0
  43. data/lib/thrift/server/simple_server.rb +43 -0
  44. data/lib/thrift/server/thread_pool_server.rb +75 -0
  45. data/lib/thrift/server/threaded_server.rb +47 -0
  46. data/lib/thrift/struct.rb +237 -0
  47. data/lib/thrift/struct_union.rb +192 -0
  48. data/lib/thrift/thrift_native.rb +24 -0
  49. data/lib/thrift/transport/base_server_transport.rb +37 -0
  50. data/lib/thrift/transport/base_transport.rb +107 -0
  51. data/lib/thrift/transport/buffered_transport.rb +108 -0
  52. data/lib/thrift/transport/framed_transport.rb +116 -0
  53. data/lib/thrift/transport/http_client_transport.rb +51 -0
  54. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  55. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  56. data/lib/thrift/transport/server_socket.rb +63 -0
  57. data/lib/thrift/transport/socket.rb +137 -0
  58. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  59. data/lib/thrift/transport/unix_socket.rb +40 -0
  60. data/lib/thrift/types.rb +101 -0
  61. data/lib/thrift/union.rb +179 -0
  62. data/spec/ThriftSpec.thrift +132 -0
  63. data/spec/base_protocol_spec.rb +160 -0
  64. data/spec/base_transport_spec.rb +351 -0
  65. data/spec/binary_protocol_accelerated_spec.rb +46 -0
  66. data/spec/binary_protocol_spec.rb +61 -0
  67. data/spec/binary_protocol_spec_shared.rb +375 -0
  68. data/spec/client_spec.rb +100 -0
  69. data/spec/compact_protocol_spec.rb +144 -0
  70. data/spec/exception_spec.rb +142 -0
  71. data/spec/gen-rb/nonblocking_service.rb +272 -0
  72. data/spec/gen-rb/thrift_spec_constants.rb +11 -0
  73. data/spec/gen-rb/thrift_spec_types.rb +346 -0
  74. data/spec/http_client_spec.rb +64 -0
  75. data/spec/mongrel_http_server_spec.rb +117 -0
  76. data/spec/nonblocking_server_spec.rb +265 -0
  77. data/spec/processor_spec.rb +83 -0
  78. data/spec/serializer_spec.rb +69 -0
  79. data/spec/server_socket_spec.rb +80 -0
  80. data/spec/server_spec.rb +159 -0
  81. data/spec/socket_spec.rb +61 -0
  82. data/spec/socket_spec_shared.rb +104 -0
  83. data/spec/spec_helper.rb +58 -0
  84. data/spec/struct_spec.rb +295 -0
  85. data/spec/types_spec.rb +116 -0
  86. data/spec/union_spec.rb +193 -0
  87. data/spec/unix_socket_spec.rb +108 -0
  88. data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +274 -0
  89. data/test/debug_proto/gen-rb/debug_proto_test_types.rb +761 -0
  90. data/test/debug_proto/gen-rb/empty_service.rb +24 -0
  91. data/test/debug_proto/gen-rb/inherited.rb +79 -0
  92. data/test/debug_proto/gen-rb/reverse_order_service.rb +82 -0
  93. data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +81 -0
  94. data/test/debug_proto/gen-rb/srv.rb +330 -0
  95. metadata +281 -0
@@ -0,0 +1,11 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.9.0)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'thrift'
8
+ require 'thrift_spec_types'
9
+
10
+ module SpecNamespace
11
+ end
@@ -0,0 +1,346 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.9.0)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'thrift'
8
+
9
+ module SpecNamespace
10
+ module SomeEnum
11
+ ONE = 0
12
+ TWO = 1
13
+ VALUE_MAP = {0 => "ONE", 1 => "TWO"}
14
+ VALID_VALUES = Set.new([ONE, TWO]).freeze
15
+ end
16
+
17
+ class Hello
18
+ include ::Thrift::Struct, ::Thrift::Struct_Union
19
+ GREETING = 1
20
+
21
+ FIELDS = {
22
+ GREETING => {:type => ::Thrift::Types::STRING, :name => 'greeting', :default => %q"hello world"}
23
+ }
24
+
25
+ def struct_fields; FIELDS; end
26
+
27
+ def validate
28
+ end
29
+
30
+ ::Thrift::Struct.generate_accessors self
31
+ end
32
+
33
+ class StructWithSomeEnum
34
+ include ::Thrift::Struct, ::Thrift::Struct_Union
35
+ SOME_ENUM = 1
36
+
37
+ FIELDS = {
38
+ SOME_ENUM => {:type => ::Thrift::Types::I32, :name => 'some_enum', :enum_class => ::SpecNamespace::SomeEnum}
39
+ }
40
+
41
+ def struct_fields; FIELDS; end
42
+
43
+ def validate
44
+ unless @some_enum.nil? || ::SpecNamespace::SomeEnum::VALID_VALUES.include?(@some_enum)
45
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field some_enum!')
46
+ end
47
+ end
48
+
49
+ ::Thrift::Struct.generate_accessors self
50
+ end
51
+
52
+ class TestUnion < ::Thrift::Union
53
+ include ::Thrift::Struct_Union
54
+ class << self
55
+ def string_field(val)
56
+ TestUnion.new(:string_field, val)
57
+ end
58
+
59
+ def i32_field(val)
60
+ TestUnion.new(:i32_field, val)
61
+ end
62
+
63
+ def other_i32_field(val)
64
+ TestUnion.new(:other_i32_field, val)
65
+ end
66
+
67
+ def enum_field(val)
68
+ TestUnion.new(:enum_field, val)
69
+ end
70
+
71
+ def binary_field(val)
72
+ TestUnion.new(:binary_field, val)
73
+ end
74
+ end
75
+
76
+ STRING_FIELD = 1
77
+ I32_FIELD = 2
78
+ OTHER_I32_FIELD = 3
79
+ ENUM_FIELD = 4
80
+ BINARY_FIELD = 5
81
+
82
+ FIELDS = {
83
+ # A doc string
84
+ STRING_FIELD => {:type => ::Thrift::Types::STRING, :name => 'string_field'},
85
+ I32_FIELD => {:type => ::Thrift::Types::I32, :name => 'i32_field'},
86
+ OTHER_I32_FIELD => {:type => ::Thrift::Types::I32, :name => 'other_i32_field'},
87
+ ENUM_FIELD => {:type => ::Thrift::Types::I32, :name => 'enum_field', :enum_class => ::SpecNamespace::SomeEnum},
88
+ BINARY_FIELD => {:type => ::Thrift::Types::STRING, :name => 'binary_field', :binary => true}
89
+ }
90
+
91
+ def struct_fields; FIELDS; end
92
+
93
+ def validate
94
+ raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?
95
+ if get_set_field == :enum_field
96
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field enum_field!') unless ::SpecNamespace::SomeEnum::VALID_VALUES.include?(get_value)
97
+ end
98
+ end
99
+
100
+ ::Thrift::Union.generate_accessors self
101
+ end
102
+
103
+ class Foo
104
+ include ::Thrift::Struct, ::Thrift::Struct_Union
105
+ SIMPLE = 1
106
+ WORDS = 2
107
+ HELLO = 3
108
+ INTS = 4
109
+ COMPLEX = 5
110
+ SHORTS = 6
111
+ OPT_STRING = 7
112
+ MY_BOOL = 8
113
+
114
+ FIELDS = {
115
+ SIMPLE => {:type => ::Thrift::Types::I32, :name => 'simple', :default => 53},
116
+ WORDS => {:type => ::Thrift::Types::STRING, :name => 'words', :default => %q"words"},
117
+ HELLO => {:type => ::Thrift::Types::STRUCT, :name => 'hello', :default => ::SpecNamespace::Hello.new({
118
+ %q"greeting" => %q"hello, world!",
119
+ }), :class => ::SpecNamespace::Hello},
120
+ INTS => {:type => ::Thrift::Types::LIST, :name => 'ints', :default => [
121
+ 1,
122
+ 2,
123
+ 2,
124
+ 3,
125
+ ], :element => {:type => ::Thrift::Types::I32}},
126
+ COMPLEX => {:type => ::Thrift::Types::MAP, :name => 'complex', :key => {:type => ::Thrift::Types::I32}, :value => {:type => ::Thrift::Types::MAP, :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::DOUBLE}}},
127
+ SHORTS => {:type => ::Thrift::Types::SET, :name => 'shorts', :default => Set.new([
128
+ 5,
129
+ 17,
130
+ 239,
131
+ ]), :element => {:type => ::Thrift::Types::I16}},
132
+ OPT_STRING => {:type => ::Thrift::Types::STRING, :name => 'opt_string', :optional => true},
133
+ MY_BOOL => {:type => ::Thrift::Types::BOOL, :name => 'my_bool'}
134
+ }
135
+
136
+ def struct_fields; FIELDS; end
137
+
138
+ def validate
139
+ end
140
+
141
+ ::Thrift::Struct.generate_accessors self
142
+ end
143
+
144
+ class Foo2
145
+ include ::Thrift::Struct, ::Thrift::Struct_Union
146
+ MY_BINARY = 1
147
+
148
+ FIELDS = {
149
+ MY_BINARY => {:type => ::Thrift::Types::STRING, :name => 'my_binary', :binary => true}
150
+ }
151
+
152
+ def struct_fields; FIELDS; end
153
+
154
+ def validate
155
+ end
156
+
157
+ ::Thrift::Struct.generate_accessors self
158
+ end
159
+
160
+ class BoolStruct
161
+ include ::Thrift::Struct, ::Thrift::Struct_Union
162
+ YESNO = 1
163
+
164
+ FIELDS = {
165
+ YESNO => {:type => ::Thrift::Types::BOOL, :name => 'yesno', :default => true}
166
+ }
167
+
168
+ def struct_fields; FIELDS; end
169
+
170
+ def validate
171
+ end
172
+
173
+ ::Thrift::Struct.generate_accessors self
174
+ end
175
+
176
+ class SimpleList
177
+ include ::Thrift::Struct, ::Thrift::Struct_Union
178
+ BOOLS = 1
179
+ BYTES = 2
180
+ I16S = 3
181
+ I32S = 4
182
+ I64S = 5
183
+ DOUBLES = 6
184
+ STRINGS = 7
185
+ MAPS = 8
186
+ LISTS = 9
187
+ SETS = 10
188
+ HELLOS = 11
189
+
190
+ FIELDS = {
191
+ BOOLS => {:type => ::Thrift::Types::LIST, :name => 'bools', :element => {:type => ::Thrift::Types::BOOL}},
192
+ BYTES => {:type => ::Thrift::Types::LIST, :name => 'bytes', :element => {:type => ::Thrift::Types::BYTE}},
193
+ I16S => {:type => ::Thrift::Types::LIST, :name => 'i16s', :element => {:type => ::Thrift::Types::I16}},
194
+ I32S => {:type => ::Thrift::Types::LIST, :name => 'i32s', :element => {:type => ::Thrift::Types::I32}},
195
+ I64S => {:type => ::Thrift::Types::LIST, :name => 'i64s', :element => {:type => ::Thrift::Types::I64}},
196
+ DOUBLES => {:type => ::Thrift::Types::LIST, :name => 'doubles', :element => {:type => ::Thrift::Types::DOUBLE}},
197
+ STRINGS => {:type => ::Thrift::Types::LIST, :name => 'strings', :element => {:type => ::Thrift::Types::STRING}},
198
+ MAPS => {:type => ::Thrift::Types::LIST, :name => 'maps', :element => {:type => ::Thrift::Types::MAP, :key => {:type => ::Thrift::Types::I16}, :value => {:type => ::Thrift::Types::I16}}},
199
+ LISTS => {:type => ::Thrift::Types::LIST, :name => 'lists', :element => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::I16}}},
200
+ SETS => {:type => ::Thrift::Types::LIST, :name => 'sets', :element => {:type => ::Thrift::Types::SET, :element => {:type => ::Thrift::Types::I16}}},
201
+ HELLOS => {:type => ::Thrift::Types::LIST, :name => 'hellos', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SpecNamespace::Hello}}
202
+ }
203
+
204
+ def struct_fields; FIELDS; end
205
+
206
+ def validate
207
+ end
208
+
209
+ ::Thrift::Struct.generate_accessors self
210
+ end
211
+
212
+ class Xception < ::Thrift::Exception
213
+ include ::Thrift::Struct, ::Thrift::Struct_Union
214
+ MESSAGE = 1
215
+ CODE = 2
216
+
217
+ FIELDS = {
218
+ MESSAGE => {:type => ::Thrift::Types::STRING, :name => 'message'},
219
+ CODE => {:type => ::Thrift::Types::I32, :name => 'code', :default => 1}
220
+ }
221
+
222
+ def struct_fields; FIELDS; end
223
+
224
+ def validate
225
+ end
226
+
227
+ ::Thrift::Struct.generate_accessors self
228
+ end
229
+
230
+ class My_union < ::Thrift::Union
231
+ include ::Thrift::Struct_Union
232
+ class << self
233
+ def im_true(val)
234
+ My_union.new(:im_true, val)
235
+ end
236
+
237
+ def a_bite(val)
238
+ My_union.new(:a_bite, val)
239
+ end
240
+
241
+ def integer16(val)
242
+ My_union.new(:integer16, val)
243
+ end
244
+
245
+ def integer32(val)
246
+ My_union.new(:integer32, val)
247
+ end
248
+
249
+ def integer64(val)
250
+ My_union.new(:integer64, val)
251
+ end
252
+
253
+ def double_precision(val)
254
+ My_union.new(:double_precision, val)
255
+ end
256
+
257
+ def some_characters(val)
258
+ My_union.new(:some_characters, val)
259
+ end
260
+
261
+ def other_i32(val)
262
+ My_union.new(:other_i32, val)
263
+ end
264
+
265
+ def some_enum(val)
266
+ My_union.new(:some_enum, val)
267
+ end
268
+
269
+ def my_map(val)
270
+ My_union.new(:my_map, val)
271
+ end
272
+ end
273
+
274
+ IM_TRUE = 1
275
+ A_BITE = 2
276
+ INTEGER16 = 3
277
+ INTEGER32 = 4
278
+ INTEGER64 = 5
279
+ DOUBLE_PRECISION = 6
280
+ SOME_CHARACTERS = 7
281
+ OTHER_I32 = 8
282
+ SOME_ENUM = 9
283
+ MY_MAP = 10
284
+
285
+ FIELDS = {
286
+ IM_TRUE => {:type => ::Thrift::Types::BOOL, :name => 'im_true'},
287
+ A_BITE => {:type => ::Thrift::Types::BYTE, :name => 'a_bite'},
288
+ INTEGER16 => {:type => ::Thrift::Types::I16, :name => 'integer16'},
289
+ INTEGER32 => {:type => ::Thrift::Types::I32, :name => 'integer32'},
290
+ INTEGER64 => {:type => ::Thrift::Types::I64, :name => 'integer64'},
291
+ DOUBLE_PRECISION => {:type => ::Thrift::Types::DOUBLE, :name => 'double_precision'},
292
+ SOME_CHARACTERS => {:type => ::Thrift::Types::STRING, :name => 'some_characters'},
293
+ OTHER_I32 => {:type => ::Thrift::Types::I32, :name => 'other_i32'},
294
+ SOME_ENUM => {:type => ::Thrift::Types::I32, :name => 'some_enum', :enum_class => ::SpecNamespace::SomeEnum},
295
+ MY_MAP => {:type => ::Thrift::Types::MAP, :name => 'my_map', :key => {:type => ::Thrift::Types::I32, :enum_class => ::SpecNamespace::SomeEnum}, :value => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::I32, :enum_class => ::SpecNamespace::SomeEnum}}}
296
+ }
297
+
298
+ def struct_fields; FIELDS; end
299
+
300
+ def validate
301
+ raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?
302
+ if get_set_field == :some_enum
303
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field some_enum!') unless ::SpecNamespace::SomeEnum::VALID_VALUES.include?(get_value)
304
+ end
305
+ end
306
+
307
+ ::Thrift::Union.generate_accessors self
308
+ end
309
+
310
+ class Struct_with_union
311
+ include ::Thrift::Struct, ::Thrift::Struct_Union
312
+ FUN_UNION = 1
313
+ INTEGER32 = 2
314
+ SOME_CHARACTERS = 3
315
+
316
+ FIELDS = {
317
+ FUN_UNION => {:type => ::Thrift::Types::STRUCT, :name => 'fun_union', :class => ::SpecNamespace::My_union},
318
+ INTEGER32 => {:type => ::Thrift::Types::I32, :name => 'integer32'},
319
+ SOME_CHARACTERS => {:type => ::Thrift::Types::STRING, :name => 'some_characters'}
320
+ }
321
+
322
+ def struct_fields; FIELDS; end
323
+
324
+ def validate
325
+ end
326
+
327
+ ::Thrift::Struct.generate_accessors self
328
+ end
329
+
330
+ class StructWithEnumMap
331
+ include ::Thrift::Struct, ::Thrift::Struct_Union
332
+ MY_MAP = 1
333
+
334
+ FIELDS = {
335
+ MY_MAP => {:type => ::Thrift::Types::MAP, :name => 'my_map', :key => {:type => ::Thrift::Types::I32, :enum_class => ::SpecNamespace::SomeEnum}, :value => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::I32, :enum_class => ::SpecNamespace::SomeEnum}}}
336
+ }
337
+
338
+ def struct_fields; FIELDS; end
339
+
340
+ def validate
341
+ end
342
+
343
+ ::Thrift::Struct.generate_accessors self
344
+ end
345
+
346
+ end
@@ -0,0 +1,64 @@
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 File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
21
+
22
+ class ThriftHTTPClientTransportSpec < Spec::ExampleGroup
23
+ include Thrift
24
+
25
+ describe HTTPClientTransport do
26
+ before(:each) do
27
+ @client = HTTPClientTransport.new("http://my.domain.com/path/to/service?param=value")
28
+ end
29
+
30
+ it "should always be open" do
31
+ @client.should be_open
32
+ @client.close
33
+ @client.should be_open
34
+ end
35
+
36
+ it "should post via HTTP and return the results" do
37
+ @client.write "a test"
38
+ @client.write " frame"
39
+ Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
40
+ mock("Net::HTTP").tee do |http|
41
+ http.should_receive(:use_ssl=).with(false)
42
+ http.should_receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}).and_return([nil, "data"])
43
+ end
44
+ end
45
+ @client.flush
46
+ @client.read(10).should == "data"
47
+ end
48
+
49
+ it "should send custom headers if defined" do
50
+ @client.write "test"
51
+ custom_headers = {"Cookie" => "Foo"}
52
+ headers = {"Content-Type"=>"application/x-thrift"}.merge(custom_headers)
53
+
54
+ @client.add_headers(custom_headers)
55
+ Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
56
+ mock("Net::HTTP").tee do |http|
57
+ http.should_receive(:use_ssl=).with(false)
58
+ http.should_receive(:post).with("/path/to/service?param=value", "test", headers).and_return([nil, "data"])
59
+ end
60
+ end
61
+ @client.flush
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,117 @@
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 File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
21
+ require 'thrift/server/mongrel_http_server'
22
+
23
+ class ThriftHTTPServerSpec < Spec::ExampleGroup
24
+ include Thrift
25
+
26
+ Handler = MongrelHTTPServer::Handler
27
+
28
+ describe MongrelHTTPServer do
29
+ it "should have appropriate defaults" do
30
+ mock_factory = mock("BinaryProtocolFactory")
31
+ mock_proc = mock("Processor")
32
+ BinaryProtocolFactory.should_receive(:new).and_return(mock_factory)
33
+ Mongrel::HttpServer.should_receive(:new).with("0.0.0.0", 80).and_return do
34
+ mock("Mongrel::HttpServer").tee do |mock|
35
+ handler = mock("Handler")
36
+ Handler.should_receive(:new).with(mock_proc, mock_factory).and_return(handler)
37
+ mock.should_receive(:register).with("/", handler)
38
+ end
39
+ end
40
+ MongrelHTTPServer.new(mock_proc)
41
+ end
42
+
43
+ it "should understand :ip, :port, :path, and :protocol_factory" do
44
+ mock_proc = mock("Processor")
45
+ mock_factory = mock("ProtocolFactory")
46
+ Mongrel::HttpServer.should_receive(:new).with("1.2.3.4", 1234).and_return do
47
+ mock("Mongrel::HttpServer").tee do |mock|
48
+ handler = mock("Handler")
49
+ Handler.should_receive(:new).with(mock_proc, mock_factory).and_return(handler)
50
+ mock.should_receive(:register).with("/foo", handler)
51
+ end
52
+ end
53
+ MongrelHTTPServer.new(mock_proc, :ip => "1.2.3.4", :port => 1234, :path => "foo",
54
+ :protocol_factory => mock_factory)
55
+ end
56
+
57
+ it "should serve using Mongrel::HttpServer" do
58
+ BinaryProtocolFactory.stub!(:new)
59
+ Mongrel::HttpServer.should_receive(:new).and_return do
60
+ mock("Mongrel::HttpServer").tee do |mock|
61
+ Handler.stub!(:new)
62
+ mock.stub!(:register)
63
+ mock.should_receive(:run).and_return do
64
+ mock("Mongrel::HttpServer.run").tee do |runner|
65
+ runner.should_receive(:join)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ MongrelHTTPServer.new(nil).serve
71
+ end
72
+ end
73
+
74
+ describe MongrelHTTPServer::Handler do
75
+ before(:each) do
76
+ @processor = mock("Processor")
77
+ @factory = mock("ProtocolFactory")
78
+ @handler = Handler.new(@processor, @factory)
79
+ end
80
+
81
+ it "should return 404 for non-POST requests" do
82
+ request = mock("request", :params => {"REQUEST_METHOD" => "GET"})
83
+ response = mock("response")
84
+ response.should_receive(:start).with(404)
85
+ response.should_not_receive(:start).with(200)
86
+ @handler.process(request, response)
87
+ end
88
+
89
+ it "should serve using application/x-thrift" do
90
+ request = mock("request", :params => {"REQUEST_METHOD" => "POST"}, :body => nil)
91
+ response = mock("response")
92
+ head = mock("head")
93
+ head.should_receive(:[]=).with("Content-Type", "application/x-thrift")
94
+ IOStreamTransport.stub!(:new)
95
+ @factory.stub!(:get_protocol)
96
+ @processor.stub!(:process)
97
+ response.should_receive(:start).with(200).and_yield(head, nil)
98
+ @handler.process(request, response)
99
+ end
100
+
101
+ it "should use the IOStreamTransport" do
102
+ body = mock("body")
103
+ request = mock("request", :params => {"REQUEST_METHOD" => "POST"}, :body => body)
104
+ response = mock("response")
105
+ head = mock("head")
106
+ head.stub!(:[]=)
107
+ out = mock("out")
108
+ protocol = mock("protocol")
109
+ transport = mock("transport")
110
+ IOStreamTransport.should_receive(:new).with(body, out).and_return(transport)
111
+ @factory.should_receive(:get_protocol).with(transport).and_return(protocol)
112
+ @processor.should_receive(:process).with(protocol, protocol)
113
+ response.should_receive(:start).with(200).and_yield(head, out)
114
+ @handler.process(request, response)
115
+ end
116
+ end
117
+ end