protobuffy 3.1.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 (192) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +5 -0
  5. data/CHANGES.md +261 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +14 -0
  9. data/README.md +58 -0
  10. data/Rakefile +61 -0
  11. data/bin/protoc-gen-ruby +17 -0
  12. data/bin/rpc_server +4 -0
  13. data/examples/bin/reverse-client-http +4 -0
  14. data/examples/bin/reverse-client-socket +4 -0
  15. data/examples/bin/reverse-client-zmq +4 -0
  16. data/examples/config.ru +6 -0
  17. data/examples/definitions/example/reverse.proto +12 -0
  18. data/examples/lib/example/reverse-client.rb +23 -0
  19. data/examples/lib/example/reverse-service.rb +9 -0
  20. data/examples/lib/example/reverse.pb.rb +36 -0
  21. data/lib/protobuf.rb +106 -0
  22. data/lib/protobuf/cli.rb +249 -0
  23. data/lib/protobuf/code_generator.rb +41 -0
  24. data/lib/protobuf/decoder.rb +74 -0
  25. data/lib/protobuf/deprecator.rb +42 -0
  26. data/lib/protobuf/descriptors.rb +3 -0
  27. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
  28. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
  29. data/lib/protobuf/encoder.rb +62 -0
  30. data/lib/protobuf/enum.rb +319 -0
  31. data/lib/protobuf/exceptions.rb +9 -0
  32. data/lib/protobuf/field.rb +74 -0
  33. data/lib/protobuf/field/base_field.rb +280 -0
  34. data/lib/protobuf/field/bool_field.rb +53 -0
  35. data/lib/protobuf/field/bytes_field.rb +81 -0
  36. data/lib/protobuf/field/double_field.rb +26 -0
  37. data/lib/protobuf/field/enum_field.rb +57 -0
  38. data/lib/protobuf/field/field_array.rb +86 -0
  39. data/lib/protobuf/field/fixed32_field.rb +25 -0
  40. data/lib/protobuf/field/fixed64_field.rb +29 -0
  41. data/lib/protobuf/field/float_field.rb +38 -0
  42. data/lib/protobuf/field/int32_field.rb +22 -0
  43. data/lib/protobuf/field/int64_field.rb +22 -0
  44. data/lib/protobuf/field/integer_field.rb +24 -0
  45. data/lib/protobuf/field/message_field.rb +66 -0
  46. data/lib/protobuf/field/sfixed32_field.rb +28 -0
  47. data/lib/protobuf/field/sfixed64_field.rb +29 -0
  48. data/lib/protobuf/field/signed_integer_field.rb +30 -0
  49. data/lib/protobuf/field/sint32_field.rb +22 -0
  50. data/lib/protobuf/field/sint64_field.rb +22 -0
  51. data/lib/protobuf/field/string_field.rb +35 -0
  52. data/lib/protobuf/field/uint32_field.rb +22 -0
  53. data/lib/protobuf/field/uint64_field.rb +22 -0
  54. data/lib/protobuf/field/varint_field.rb +68 -0
  55. data/lib/protobuf/generators/base.rb +71 -0
  56. data/lib/protobuf/generators/enum_generator.rb +42 -0
  57. data/lib/protobuf/generators/extension_generator.rb +28 -0
  58. data/lib/protobuf/generators/field_generator.rb +132 -0
  59. data/lib/protobuf/generators/file_generator.rb +140 -0
  60. data/lib/protobuf/generators/group_generator.rb +113 -0
  61. data/lib/protobuf/generators/message_generator.rb +99 -0
  62. data/lib/protobuf/generators/printable.rb +161 -0
  63. data/lib/protobuf/generators/service_generator.rb +27 -0
  64. data/lib/protobuf/http.rb +20 -0
  65. data/lib/protobuf/lifecycle.rb +46 -0
  66. data/lib/protobuf/logger.rb +86 -0
  67. data/lib/protobuf/message.rb +182 -0
  68. data/lib/protobuf/message/fields.rb +122 -0
  69. data/lib/protobuf/message/serialization.rb +84 -0
  70. data/lib/protobuf/optionable.rb +23 -0
  71. data/lib/protobuf/rpc/buffer.rb +79 -0
  72. data/lib/protobuf/rpc/client.rb +168 -0
  73. data/lib/protobuf/rpc/connector.rb +21 -0
  74. data/lib/protobuf/rpc/connectors/base.rb +54 -0
  75. data/lib/protobuf/rpc/connectors/common.rb +172 -0
  76. data/lib/protobuf/rpc/connectors/http.rb +90 -0
  77. data/lib/protobuf/rpc/connectors/socket.rb +73 -0
  78. data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
  79. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
  80. data/lib/protobuf/rpc/env.rb +58 -0
  81. data/lib/protobuf/rpc/error.rb +28 -0
  82. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  83. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  84. data/lib/protobuf/rpc/middleware.rb +25 -0
  85. data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
  86. data/lib/protobuf/rpc/middleware/logger.rb +91 -0
  87. data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
  88. data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
  89. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  90. data/lib/protobuf/rpc/rpc.pb.rb +53 -0
  91. data/lib/protobuf/rpc/server.rb +39 -0
  92. data/lib/protobuf/rpc/servers/http/server.rb +101 -0
  93. data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
  94. data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
  95. data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
  96. data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
  97. data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
  98. data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
  99. data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
  100. data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
  101. data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
  102. data/lib/protobuf/rpc/service.rb +179 -0
  103. data/lib/protobuf/rpc/service_directory.rb +245 -0
  104. data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
  105. data/lib/protobuf/rpc/service_filters.rb +273 -0
  106. data/lib/protobuf/rpc/stat.rb +148 -0
  107. data/lib/protobuf/socket.rb +22 -0
  108. data/lib/protobuf/tasks.rb +1 -0
  109. data/lib/protobuf/tasks/compile.rake +61 -0
  110. data/lib/protobuf/version.rb +3 -0
  111. data/lib/protobuf/wire_type.rb +10 -0
  112. data/lib/protobuf/zmq.rb +21 -0
  113. data/proto/dynamic_discovery.proto +44 -0
  114. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  115. data/proto/google/protobuf/descriptor.proto +620 -0
  116. data/proto/rpc.proto +62 -0
  117. data/protobuffy.gemspec +37 -0
  118. data/spec/benchmark/tasks.rb +113 -0
  119. data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
  120. data/spec/data/data.bin +3 -0
  121. data/spec/data/types.bin +0 -0
  122. data/spec/encoding/all_types_spec.rb +91 -0
  123. data/spec/encoding/extreme_values_spec.rb +0 -0
  124. data/spec/functional/socket_server_spec.rb +59 -0
  125. data/spec/functional/zmq_server_spec.rb +103 -0
  126. data/spec/lib/protobuf/cli_spec.rb +267 -0
  127. data/spec/lib/protobuf/code_generator_spec.rb +60 -0
  128. data/spec/lib/protobuf/enum_spec.rb +239 -0
  129. data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
  130. data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
  131. data/spec/lib/protobuf/field_spec.rb +194 -0
  132. data/spec/lib/protobuf/generators/base_spec.rb +87 -0
  133. data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
  134. data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
  135. data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
  136. data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
  137. data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
  138. data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
  139. data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
  140. data/spec/lib/protobuf/logger_spec.rb +136 -0
  141. data/spec/lib/protobuf/message_spec.rb +368 -0
  142. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  143. data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
  144. data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
  145. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
  146. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
  147. data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
  148. data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
  149. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
  150. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
  151. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  152. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  153. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  154. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
  155. data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
  156. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
  157. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
  158. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
  159. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
  160. data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
  161. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
  162. data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
  163. data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
  164. data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
  165. data/spec/lib/protobuf_spec.rb +78 -0
  166. data/spec/spec_helper.rb +57 -0
  167. data/spec/support/all.rb +7 -0
  168. data/spec/support/packed_field.rb +22 -0
  169. data/spec/support/server.rb +94 -0
  170. data/spec/support/test/all_types.data.bin +0 -0
  171. data/spec/support/test/all_types.data.txt +119 -0
  172. data/spec/support/test/defaults.pb.rb +25 -0
  173. data/spec/support/test/defaults.proto +9 -0
  174. data/spec/support/test/enum.pb.rb +59 -0
  175. data/spec/support/test/enum.proto +34 -0
  176. data/spec/support/test/extended.pb.rb +22 -0
  177. data/spec/support/test/extended.proto +10 -0
  178. data/spec/support/test/extreme_values.data.bin +0 -0
  179. data/spec/support/test/google_unittest.pb.rb +543 -0
  180. data/spec/support/test/google_unittest.proto +713 -0
  181. data/spec/support/test/google_unittest_import.pb.rb +37 -0
  182. data/spec/support/test/google_unittest_import.proto +64 -0
  183. data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
  184. data/spec/support/test/google_unittest_import_public.proto +38 -0
  185. data/spec/support/test/multi_field_extensions.pb.rb +56 -0
  186. data/spec/support/test/multi_field_extensions.proto +33 -0
  187. data/spec/support/test/resource.pb.rb +117 -0
  188. data/spec/support/test/resource.proto +94 -0
  189. data/spec/support/test/resource_service.rb +26 -0
  190. data/spec/support/test_app_file.rb +2 -0
  191. data/spec/support/tolerance_matcher.rb +40 -0
  192. metadata +367 -0
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'protobuf/rpc/service_dispatcher'
3
+
4
+ describe Protobuf::Rpc::ServiceDispatcher do
5
+ let(:app) { proc { |env| env } }
6
+ let(:env) {
7
+ Protobuf::Rpc::Env.new(
8
+ 'method_name' => method_name,
9
+ 'request' => request,
10
+ 'rpc_service' => service_class,
11
+ 'service_name' => service_name,
12
+ )
13
+ }
14
+ let(:method_name) { :find }
15
+ let(:request) { request_type.new(:name => 'required') }
16
+ let(:request_type) { service_class.rpcs[method_name].request_type }
17
+ let(:response) { response_type.new(:name => 'required') }
18
+ let(:response_type) { service_class.rpcs[method_name].response_type }
19
+
20
+ let(:rpc_service) { service_class.new(env) }
21
+ let(:service_class) { Test::ResourceService }
22
+ let(:service_name) { service_class.to_s }
23
+
24
+ subject { described_class.new(app) }
25
+
26
+ before { subject.stub(:rpc_service).and_return(rpc_service) }
27
+
28
+ describe '#call' do
29
+ before { rpc_service.stub(:response).and_return(response) }
30
+
31
+ it "dispatches the request" do
32
+ stack_env = subject.call(env)
33
+ stack_env.response.should eq response
34
+ end
35
+
36
+ context "when the given RPC method is not implemented" do
37
+ let(:method_name) { :find_not_implemented }
38
+
39
+ it "raises a method not found exception" do
40
+ expect { subject.call(env) }.to raise_exception(Protobuf::Rpc::MethodNotFound)
41
+ end
42
+ end
43
+
44
+ context "when the given RPC method is implemented and a NoMethodError is raised" do
45
+ before { rpc_service.stub(:callable_rpc_method).and_return(lambda { rpc_service.__send__(:foo) }) }
46
+
47
+ it "raises the exeception" do
48
+ expect { subject.call(env) }.to raise_exception(NoMethodError)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,484 @@
1
+ require 'spec_helper'
2
+
3
+ class FilterTest
4
+ include Protobuf::Rpc::ServiceFilters
5
+
6
+ attr_accessor :called
7
+
8
+ # Initialize the hash keys as instance vars
9
+ def initialize(ivar_hash)
10
+ @called = []
11
+ ivar_hash.each_pair do |key, value|
12
+ self.class.class_eval do
13
+ attr_accessor key
14
+ end
15
+ __send__("#{key}=", value)
16
+ end
17
+ end
18
+
19
+ def endpoint
20
+ @called << :endpoint
21
+ end
22
+
23
+ def self.clear_filters!
24
+ @defined_filters = nil
25
+ @filters = nil
26
+ @rescue_filters = nil
27
+ end
28
+ end
29
+
30
+ describe Protobuf::Rpc::ServiceFilters do
31
+ let(:params) { {} }
32
+ subject { FilterTest.new(params) }
33
+ after(:each) { FilterTest.clear_filters! }
34
+
35
+ describe '#before_filter' do
36
+ let(:params) { { :before_filter_calls => 0 } }
37
+
38
+ before(:all) do
39
+ class FilterTest
40
+ private
41
+ def verify_before
42
+ @called << :verify_before
43
+ @before_filter_calls += 1
44
+ end
45
+
46
+ def foo
47
+ @called << :foo
48
+ end
49
+ end
50
+ end
51
+
52
+ before do
53
+ FilterTest.before_filter(:verify_before)
54
+ FilterTest.before_filter(:verify_before)
55
+ FilterTest.before_filter(:foo)
56
+ end
57
+
58
+ specify { subject.class.should respond_to(:before_filter) }
59
+ specify { subject.class.should respond_to(:before_action) }
60
+
61
+ it 'calls filters in the order they were defined' do
62
+ subject.__send__(:run_filters, :endpoint)
63
+ subject.called.should eq [ :verify_before, :foo, :endpoint ]
64
+ subject.before_filter_calls.should eq 1
65
+ end
66
+
67
+ context 'when filter is configured with "only"' do
68
+ before(:all) do
69
+ class FilterTest
70
+ private
71
+ def endpoint_with_verify
72
+ @called << :endpoint_with_verify
73
+ end
74
+ end
75
+ end
76
+
77
+ before do
78
+ FilterTest.clear_filters!
79
+ FilterTest.before_filter(:verify_before, :only => :endpoint_with_verify)
80
+ end
81
+
82
+ context 'when invoking a method defined in "only" option' do
83
+ it 'invokes the filter' do
84
+ subject.__send__(:run_filters, :endpoint_with_verify)
85
+ subject.called.should eq [ :verify_before, :endpoint_with_verify ]
86
+ end
87
+ end
88
+
89
+ context 'when invoking a method not defined by "only" option' do
90
+ it 'does not invoke the filter' do
91
+ subject.__send__(:run_filters, :endpoint)
92
+ subject.called.should eq [ :endpoint ]
93
+ end
94
+ end
95
+ end
96
+
97
+ context 'when filter is configured with "except"' do
98
+ before(:all) do
99
+ class FilterTest
100
+ private
101
+ def endpoint_without_verify
102
+ @called << :endpoint_without_verify
103
+ end
104
+ end
105
+ end
106
+
107
+ before do
108
+ FilterTest.clear_filters!
109
+ FilterTest.before_filter(:verify_before, :except => :endpoint_without_verify)
110
+ end
111
+
112
+ context 'when invoking a method not defined in "except" option' do
113
+ it 'invokes the filter' do
114
+ subject.__send__(:run_filters, :endpoint)
115
+ subject.called.should eq [ :verify_before, :endpoint ]
116
+ end
117
+ end
118
+
119
+ context 'when invoking a method defined by "except" option' do
120
+ it 'does not invoke the filter' do
121
+ subject.__send__(:run_filters, :endpoint_without_verify)
122
+ subject.called.should eq [ :endpoint_without_verify ]
123
+ end
124
+ end
125
+ end
126
+
127
+ context 'when filter is configured with "if"' do
128
+ before(:all) do
129
+ class FilterTest
130
+ private
131
+ def check_true; return true; end
132
+ def check_false; return false; end
133
+ def verify_before; @called << :verify_before; end
134
+ end
135
+ end
136
+
137
+ context 'when "if" option is a method that returns true' do
138
+ before do
139
+ FilterTest.clear_filters!
140
+ FilterTest.before_filter(:verify_before, :if => :check_true)
141
+ end
142
+
143
+ it 'invokes the filter' do
144
+ subject.__send__(:run_filters, :endpoint)
145
+ subject.called.should eq [ :verify_before, :endpoint ]
146
+ end
147
+ end
148
+
149
+ context 'when "if" option is a callable that returns true' do
150
+ before do
151
+ FilterTest.clear_filters!
152
+ FilterTest.before_filter(:verify_before, :if => lambda { |service| true })
153
+ end
154
+
155
+ it 'invokes the filter' do
156
+ subject.__send__(:run_filters, :endpoint)
157
+ subject.called.should eq [ :verify_before, :endpoint ]
158
+ end
159
+ end
160
+
161
+ context 'when "if" option is a method that returns false' do
162
+ before do
163
+ FilterTest.clear_filters!
164
+ FilterTest.before_filter(:verify_before, :if => :check_false)
165
+ end
166
+
167
+ it 'skips the filter' do
168
+ subject.__send__(:run_filters, :endpoint)
169
+ subject.called.should eq [ :endpoint ]
170
+ end
171
+ end
172
+
173
+ context 'when "if" option is a callable that returns false' do
174
+ before do
175
+ FilterTest.clear_filters!
176
+ FilterTest.before_filter(:verify_before, :if => lambda { |service| false })
177
+ end
178
+
179
+ it 'skips the filter' do
180
+ subject.__send__(:run_filters, :endpoint)
181
+ subject.called.should eq [ :endpoint ]
182
+ end
183
+ end
184
+ end
185
+
186
+ context 'when filter is configured with "unless"' do
187
+ before(:all) do
188
+ class FilterTest
189
+ private
190
+ def check_true; return true; end
191
+ def check_false; return false; end
192
+ def verify_before; @called << :verify_before; end
193
+ end
194
+ end
195
+
196
+ context 'when "unless" option is a method that returns false' do
197
+ before do
198
+ FilterTest.clear_filters!
199
+ FilterTest.before_filter(:verify_before, :unless => :check_false)
200
+ end
201
+
202
+ it 'invokes the filter' do
203
+ subject.__send__(:run_filters, :endpoint)
204
+ subject.called.should eq [ :verify_before, :endpoint ]
205
+ end
206
+ end
207
+
208
+ context 'when "unless" option is a callable that returns true' do
209
+ before do
210
+ FilterTest.clear_filters!
211
+ FilterTest.before_filter(:verify_before, :unless => lambda { |service| false })
212
+ end
213
+
214
+ it 'invokes the filter' do
215
+ subject.__send__(:run_filters, :endpoint)
216
+ subject.called.should eq [ :verify_before, :endpoint ]
217
+ end
218
+ end
219
+
220
+ context 'when "unless" option is a method that returns false' do
221
+ before do
222
+ FilterTest.clear_filters!
223
+ FilterTest.before_filter(:verify_before, :unless => :check_true)
224
+ end
225
+
226
+ it 'skips the filter' do
227
+ subject.__send__(:run_filters, :endpoint)
228
+ subject.called.should eq [ :endpoint ]
229
+ end
230
+ end
231
+
232
+ context 'when "unless" option is a callable that returns false' do
233
+ before do
234
+ FilterTest.clear_filters!
235
+ FilterTest.before_filter(:verify_before, :unless => lambda { |service| true })
236
+ end
237
+
238
+ it 'skips the filter' do
239
+ subject.__send__(:run_filters, :endpoint)
240
+ subject.called.should eq [ :endpoint ]
241
+ end
242
+ end
243
+ end
244
+
245
+ context 'when filter returns false' do
246
+ before(:all) do
247
+ class FilterTest
248
+ private
249
+ def short_circuit_filter
250
+ @called << :short_circuit_filter
251
+ return false
252
+ end
253
+ end
254
+ end
255
+
256
+ before do
257
+ FilterTest.clear_filters!
258
+ FilterTest.before_filter(:short_circuit_filter)
259
+ end
260
+
261
+ it 'does not invoke the rpc method' do
262
+ subject.should_not_receive(:endpoint)
263
+ subject.__send__(:run_filters, :endpoint)
264
+ subject.called.should eq [ :short_circuit_filter ]
265
+ end
266
+ end
267
+ end
268
+
269
+ describe '#after_filter' do
270
+ let(:params) { { :after_filter_calls => 0 } }
271
+
272
+ before(:all) do
273
+ class FilterTest
274
+ private
275
+ def verify_after
276
+ @called << :verify_after
277
+ @after_filter_calls += 1
278
+ end
279
+
280
+ def foo
281
+ @called << :foo
282
+ end
283
+ end
284
+ end
285
+
286
+ before do
287
+ FilterTest.after_filter(:verify_after)
288
+ FilterTest.after_filter(:verify_after)
289
+ FilterTest.after_filter(:foo)
290
+ end
291
+
292
+ specify { subject.class.should respond_to(:after_filter) }
293
+ specify { subject.class.should respond_to(:after_action) }
294
+
295
+ it 'calls filters in the order they were defined' do
296
+ subject.__send__(:run_filters, :endpoint)
297
+ subject.called.should eq [ :endpoint, :verify_after, :foo ]
298
+ subject.after_filter_calls.should eq 1
299
+ end
300
+ end
301
+
302
+ describe '#around_filter' do
303
+ let(:params) { {} }
304
+
305
+ before(:all) do
306
+ class FilterTest
307
+ private
308
+ def outer_around
309
+ @called << :outer_around_top
310
+ yield
311
+ @called << :outer_around_bottom
312
+ end
313
+
314
+ def inner_around
315
+ @called << :inner_around_top
316
+ yield
317
+ @called << :inner_around_bottom
318
+ end
319
+ end
320
+ end
321
+
322
+ before do
323
+ FilterTest.around_filter(:outer_around)
324
+ FilterTest.around_filter(:inner_around)
325
+ FilterTest.around_filter(:outer_around)
326
+ FilterTest.around_filter(:inner_around)
327
+ end
328
+
329
+ specify { subject.class.should respond_to(:around_filter) }
330
+ specify { subject.class.should respond_to(:around_action) }
331
+
332
+ it 'calls filters in the order they were defined' do
333
+ subject.__send__(:run_filters, :endpoint)
334
+ subject.called.should eq([ :outer_around_top,
335
+ :inner_around_top,
336
+ :endpoint,
337
+ :inner_around_bottom,
338
+ :outer_around_bottom ])
339
+ end
340
+
341
+ context 'when around_filter does not yield' do
342
+ before do
343
+ class FilterTest
344
+ private
345
+ def inner_around
346
+ @called << :inner_around
347
+ end
348
+ end
349
+ end
350
+
351
+ before do
352
+ FilterTest.around_filter(:outer_around)
353
+ FilterTest.around_filter(:inner_around)
354
+ end
355
+
356
+ it 'cancels calling the rest of the filters and the endpoint' do
357
+ subject.should_not_receive(:endpoint)
358
+ subject.__send__(:run_filters, :endpoint)
359
+ subject.called.should eq([ :outer_around_top,
360
+ :inner_around,
361
+ :outer_around_bottom ])
362
+ end
363
+
364
+ end
365
+ end
366
+
367
+ describe '#rescue_from' do
368
+ before do
369
+ class CustomError1 < StandardError; end
370
+ class CustomError2 < StandardError; end
371
+ class CustomError3 < StandardError; end
372
+ end
373
+
374
+ before do
375
+ class FilterTest
376
+ private
377
+
378
+ def filter_with_error1
379
+ @called << :filter_with_error1
380
+ raise CustomError1, 'Filter 1 failed'
381
+ end
382
+
383
+ def filter_with_error2
384
+ @called << :filter_with_error2
385
+ raise CustomError1, 'Filter 2 failed'
386
+ end
387
+
388
+ def filter_with_error3
389
+ @called << :filter_with_error3
390
+ raise CustomError3, 'Filter 3 failed'
391
+ end
392
+
393
+ def filter_with_runtime_error
394
+ @called << :filter_with_runtime_error
395
+ raise RuntimeError, 'Filter with runtime error failed'
396
+ end
397
+
398
+ def custom_error_occurred(ex)
399
+ @ex_class = ex.class
400
+ @called << :custom_error_occurred
401
+ end
402
+ end
403
+ end
404
+
405
+ let(:params) { { :ex_class => nil } }
406
+
407
+ context 'when defining multiple errors with a given callback' do
408
+ before do
409
+ FilterTest.rescue_from(CustomError1, CustomError2, CustomError3, :with => :custom_error_occurred)
410
+ end
411
+ before { FilterTest.before_filter(:filter_with_error3) }
412
+
413
+ it 'short-circuits the call stack' do
414
+ expect {
415
+ subject.should_not_receive(:endpoint)
416
+ subject.__send__(:run_filters, :endpoint)
417
+ subject.called.should eq([ :filter_with_error3, :custom_error_occurred ])
418
+ subject.ex_class.should eq CustomError3
419
+ }.not_to raise_error
420
+ end
421
+ end
422
+
423
+ context 'when defined with options' do
424
+ context 'when :with option is not given' do
425
+ specify do
426
+ expect { FilterTest.rescue_from(CustomError1) }.to raise_error(ArgumentError, /with/)
427
+ end
428
+ end
429
+
430
+ context 'when error occurs inside filter' do
431
+ before { FilterTest.rescue_from(CustomError1, :with => :custom_error_occurred) }
432
+ before { FilterTest.before_filter(:filter_with_error1) }
433
+
434
+ it 'short-circuits the call stack' do
435
+ expect {
436
+ subject.should_not_receive(:endpoint)
437
+ subject.__send__(:run_filters, :endpoint)
438
+ subject.called.should eq([ :filter_with_error1, :custom_error_occurred ])
439
+ subject.ex_class.should eq CustomError1
440
+ }.not_to raise_error
441
+ end
442
+ end
443
+ end
444
+
445
+ context 'when defined with block' do
446
+ before do
447
+ FilterTest.rescue_from(CustomError1) do |service, ex|
448
+ service.ex_class = ex.class
449
+ service.called << :block_rescue_handler
450
+ end
451
+ end
452
+ before { FilterTest.before_filter(:filter_with_error1) }
453
+
454
+ it 'short-circuits the call stack' do
455
+ expect {
456
+ subject.should_not_receive(:endpoint)
457
+ subject.__send__(:run_filters, :endpoint)
458
+ subject.called.should eq([ :filter_with_error1, :block_rescue_handler ])
459
+ subject.ex_class.should eq CustomError1
460
+ }.not_to raise_error
461
+ end
462
+ end
463
+
464
+ context 'when thrown exception inherits from a mapped exception' do
465
+ before do
466
+ FilterTest.rescue_from(StandardError) do |service, ex|
467
+ service.ex_class = ex.class
468
+ service.called << :standard_error_rescue_handler
469
+ end
470
+ end
471
+ before { FilterTest.before_filter(:filter_with_runtime_error) }
472
+
473
+ it 'rescues with the given callable' do
474
+ expect {
475
+ subject.should_not_receive(:endpoint)
476
+ subject.__send__(:run_filters, :endpoint)
477
+ subject.called.should eq([ :filter_with_runtime_error, :standard_error_rescue_handler ])
478
+ subject.ex_class.should eq RuntimeError
479
+ }.not_to raise_error
480
+ end
481
+ end
482
+ end
483
+
484
+ end