Froze rails gems
[depot.git] / vendor / rails / actionpack / test / controller / rescue_test.rb
1 require 'abstract_unit'
2
3 uses_mocha 'rescue' do
4
5 class RescueController < ActionController::Base
6 class NotAuthorized < StandardError
7 end
8 class NotAuthorizedToRescueAsString < StandardError
9 end
10
11 class RecordInvalid < StandardError
12 end
13 class RecordInvalidToRescueAsString < StandardError
14 end
15
16 class NotAllowed < StandardError
17 end
18 class NotAllowedToRescueAsString < StandardError
19 end
20
21 class InvalidRequest < StandardError
22 end
23 class InvalidRequestToRescueAsString < StandardError
24 end
25
26 class BadGateway < StandardError
27 end
28 class BadGatewayToRescueAsString < StandardError
29 end
30
31 class ResourceUnavailable < StandardError
32 end
33 class ResourceUnavailableToRescueAsString < StandardError
34 end
35
36 # We use a fully-qualified name in some strings, and a relative constant
37 # name in some other to test correct handling of both cases.
38
39 rescue_from NotAuthorized, :with => :deny_access
40 rescue_from 'RescueController::NotAuthorizedToRescueAsString', :with => :deny_access
41
42 rescue_from RecordInvalid, :with => :show_errors
43 rescue_from 'RescueController::RecordInvalidToRescueAsString', :with => :show_errors
44
45 rescue_from NotAllowed, :with => proc { head :forbidden }
46 rescue_from 'RescueController::NotAllowedToRescueAsString', :with => proc { head :forbidden }
47
48 rescue_from InvalidRequest, :with => proc { |exception| render :text => exception.message }
49 rescue_from 'InvalidRequestToRescueAsString', :with => proc { |exception| render :text => exception.message }
50
51 rescue_from BadGateway do
52 head :status => 502
53 end
54 rescue_from 'BadGatewayToRescueAsString' do
55 head :status => 502
56 end
57
58 rescue_from ResourceUnavailable do |exception|
59 render :text => exception.message
60 end
61 rescue_from 'ResourceUnavailableToRescueAsString' do |exception|
62 render :text => exception.message
63 end
64
65 # This is a Dispatcher exception and should be in ApplicationController.
66 rescue_from ActionController::RoutingError do
67 render :text => 'no way'
68 end
69
70 def raises
71 render :text => 'already rendered'
72 raise "don't panic!"
73 end
74
75 def method_not_allowed
76 raise ActionController::MethodNotAllowed.new(:get, :head, :put)
77 end
78
79 def not_implemented
80 raise ActionController::NotImplemented.new(:get, :put)
81 end
82
83 def not_authorized
84 raise NotAuthorized
85 end
86 def not_authorized_raise_as_string
87 raise NotAuthorizedToRescueAsString
88 end
89
90 def not_allowed
91 raise NotAllowed
92 end
93 def not_allowed_raise_as_string
94 raise NotAllowedToRescueAsString
95 end
96
97 def invalid_request
98 raise InvalidRequest
99 end
100 def invalid_request_raise_as_string
101 raise InvalidRequestToRescueAsString
102 end
103
104 def record_invalid
105 raise RecordInvalid
106 end
107 def record_invalid_raise_as_string
108 raise RecordInvalidToRescueAsString
109 end
110
111 def bad_gateway
112 raise BadGateway
113 end
114 def bad_gateway_raise_as_string
115 raise BadGatewayToRescueAsString
116 end
117
118 def resource_unavailable
119 raise ResourceUnavailable
120 end
121 def resource_unavailable_raise_as_string
122 raise ResourceUnavailableToRescueAsString
123 end
124
125 def missing_template
126 end
127
128 protected
129 def deny_access
130 head :forbidden
131 end
132
133 def show_errors(exception)
134 head :unprocessable_entity
135 end
136 end
137
138 class RescueControllerTest < ActionController::TestCase
139 FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze
140
141 setup :set_all_requests_local
142 setup :populate_exception_object
143
144 def set_all_requests_local
145 RescueController.consider_all_requests_local = true
146 @request.remote_addr = '1.2.3.4'
147 @request.host = 'example.com'
148 end
149
150 def populate_exception_object
151 begin
152 raise 'foo'
153 rescue => @exception
154 end
155 end
156
157 def test_rescue_action_locally_if_all_requests_local
158 @controller.expects(:local_request?).never
159 @controller.expects(:rescue_action_locally).with(@exception)
160 @controller.expects(:rescue_action_in_public).never
161
162 with_all_requests_local do
163 @controller.send :rescue_action, @exception
164 end
165 end
166
167 def test_rescue_action_locally_if_remote_addr_is_localhost
168 @controller.expects(:local_request?).returns(true)
169 @controller.expects(:rescue_action_locally).with(@exception)
170 @controller.expects(:rescue_action_in_public).never
171
172 with_all_requests_local false do
173 @controller.send :rescue_action, @exception
174 end
175 end
176
177 def test_rescue_action_in_public_otherwise
178 @controller.expects(:local_request?).returns(false)
179 @controller.expects(:rescue_action_locally).never
180 @controller.expects(:rescue_action_in_public).with(@exception)
181
182 with_all_requests_local false do
183 @controller.send :rescue_action, @exception
184 end
185 end
186
187 def test_rescue_action_in_public_with_error_file
188 with_rails_root FIXTURE_PUBLIC do
189 with_all_requests_local false do
190 get :raises
191 end
192 end
193
194 assert_response :internal_server_error
195 body = File.read("#{FIXTURE_PUBLIC}/public/500.html")
196 assert_equal body, @response.body
197 end
198
199 def test_rescue_action_in_public_without_error_file
200 with_rails_root '/tmp' do
201 with_all_requests_local false do
202 get :raises
203 end
204 end
205
206 assert_response :internal_server_error
207 assert_equal ' ', @response.body
208 end
209
210 def test_rescue_unknown_action_in_public_with_error_file
211 with_rails_root FIXTURE_PUBLIC do
212 with_all_requests_local false do
213 get :foobar_doesnt_exist
214 end
215 end
216
217 assert_response :not_found
218 body = File.read("#{FIXTURE_PUBLIC}/public/404.html")
219 assert_equal body, @response.body
220 end
221
222 def test_rescue_unknown_action_in_public_without_error_file
223 with_rails_root '/tmp' do
224 with_all_requests_local false do
225 get :foobar_doesnt_exist
226 end
227 end
228
229 assert_response :not_found
230 assert_equal ' ', @response.body
231 end
232
233 def test_rescue_missing_template_in_public
234 with_rails_root FIXTURE_PUBLIC do
235 with_all_requests_local true do
236 get :missing_template
237 end
238 end
239
240 assert_response :internal_server_error
241 assert @response.body.include?('missing_template'), "Response should include the template name."
242 end
243
244 def test_rescue_action_locally
245 get :raises
246 assert_response :internal_server_error
247 assert_template 'diagnostics.erb'
248 assert @response.body.include?('RescueController#raises'), "Response should include controller and action."
249 assert @response.body.include?("don't panic"), "Response should include exception message."
250 end
251
252 def test_local_request_when_remote_addr_is_localhost
253 @controller.expects(:request).returns(@request).at_least_once
254 with_remote_addr '127.0.0.1' do
255 assert @controller.send(:local_request?)
256 end
257 end
258
259 def test_local_request_when_remote_addr_isnt_locahost
260 @controller.expects(:request).returns(@request)
261 with_remote_addr '1.2.3.4' do
262 assert !@controller.send(:local_request?)
263 end
264 end
265
266 def test_rescue_responses
267 responses = ActionController::Base.rescue_responses
268
269 assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses.default
270 assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses[Exception.new]
271
272 assert_equal :not_found, responses[ActionController::RoutingError.name]
273 assert_equal :not_found, responses[ActionController::UnknownAction.name]
274 assert_equal :not_found, responses['ActiveRecord::RecordNotFound']
275 assert_equal :conflict, responses['ActiveRecord::StaleObjectError']
276 assert_equal :unprocessable_entity, responses['ActiveRecord::RecordInvalid']
277 assert_equal :unprocessable_entity, responses['ActiveRecord::RecordNotSaved']
278 assert_equal :method_not_allowed, responses['ActionController::MethodNotAllowed']
279 assert_equal :not_implemented, responses['ActionController::NotImplemented']
280 end
281
282 def test_rescue_templates
283 templates = ActionController::Base.rescue_templates
284
285 assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates.default
286 assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates[Exception.new]
287
288 assert_equal 'missing_template', templates[ActionView::MissingTemplate.name]
289 assert_equal 'routing_error', templates[ActionController::RoutingError.name]
290 assert_equal 'unknown_action', templates[ActionController::UnknownAction.name]
291 assert_equal 'template_error', templates[ActionView::TemplateError.name]
292 end
293
294 def test_clean_backtrace
295 with_rails_root nil do
296 # No action if RAILS_ROOT isn't set.
297 cleaned = @controller.send(:clean_backtrace, @exception)
298 assert_equal @exception.backtrace, cleaned
299 end
300
301 with_rails_root Dir.pwd do
302 # RAILS_ROOT is removed from backtrace.
303 cleaned = @controller.send(:clean_backtrace, @exception)
304 expected = @exception.backtrace.map { |line| line.sub(RAILS_ROOT, '') }
305 assert_equal expected, cleaned
306
307 # No action if backtrace is nil.
308 assert_nil @controller.send(:clean_backtrace, Exception.new)
309 end
310 end
311
312 def test_not_implemented
313 with_all_requests_local false do
314 with_rails_public_path(".") do
315 head :not_implemented
316 end
317 end
318 assert_response :not_implemented
319 assert_equal "GET, PUT", @response.headers['Allow']
320 end
321
322 def test_method_not_allowed
323 with_all_requests_local false do
324 with_rails_public_path(".") do
325 get :method_not_allowed
326 end
327 end
328 assert_response :method_not_allowed
329 assert_equal "GET, HEAD, PUT", @response.headers['Allow']
330 end
331
332 def test_rescue_handler
333 get :not_authorized
334 assert_response :forbidden
335 end
336 def test_rescue_handler_string
337 get :not_authorized_raise_as_string
338 assert_response :forbidden
339 end
340
341 def test_rescue_handler_with_argument
342 @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) }
343 get :record_invalid
344 end
345 def test_rescue_handler_with_argument_as_string
346 @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) }
347 get :record_invalid_raise_as_string
348 end
349
350 def test_proc_rescue_handler
351 get :not_allowed
352 assert_response :forbidden
353 end
354 def test_proc_rescue_handler_as_string
355 get :not_allowed_raise_as_string
356 assert_response :forbidden
357 end
358
359 def test_proc_rescue_handle_with_argument
360 get :invalid_request
361 assert_equal "RescueController::InvalidRequest", @response.body
362 end
363 def test_proc_rescue_handle_with_argument_as_string
364 get :invalid_request_raise_as_string
365 assert_equal "RescueController::InvalidRequestToRescueAsString", @response.body
366 end
367
368 def test_block_rescue_handler
369 get :bad_gateway
370 assert_response 502
371 end
372 def test_block_rescue_handler_as_string
373 get :bad_gateway_raise_as_string
374 assert_response 502
375 end
376
377 def test_block_rescue_handler_with_argument
378 get :resource_unavailable
379 assert_equal "RescueController::ResourceUnavailable", @response.body
380 end
381
382 def test_block_rescue_handler_with_argument_as_string
383 get :resource_unavailable_raise_as_string
384 assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body
385 end
386
387 def test_rescue_dispatcher_exceptions
388 RescueController.process_with_exception(@request, @response, ActionController::RoutingError.new("Route not found"))
389 assert_equal "no way", @response.body
390 end
391
392 protected
393 def with_all_requests_local(local = true)
394 old_local, ActionController::Base.consider_all_requests_local =
395 ActionController::Base.consider_all_requests_local, local
396 yield
397 ensure
398 ActionController::Base.consider_all_requests_local = old_local
399 end
400
401 def with_remote_addr(addr)
402 old_remote_addr, @request.remote_addr = @request.remote_addr, addr
403 yield
404 ensure
405 @request.remote_addr = old_remote_addr
406 end
407
408 def with_rails_public_path(rails_root)
409 old_rails = Object.const_get(:Rails) rescue nil
410 mod = Object.const_set(:Rails, Module.new)
411 (class << mod; self; end).instance_eval do
412 define_method(:public_path) { "#{rails_root}/public" }
413 end
414 yield
415 ensure
416 Object.module_eval { remove_const(:Rails) } if defined?(Rails)
417 Object.const_set(:Rails, old_rails) if old_rails
418 end
419
420 def with_rails_root(path = nil,&block)
421 old_rails_root = RAILS_ROOT if defined?(RAILS_ROOT)
422 if path
423 silence_warnings { Object.const_set(:RAILS_ROOT, path) }
424 else
425 Object.remove_const(:RAILS_ROOT) rescue nil
426 end
427
428 with_rails_public_path(path, &block)
429
430 ensure
431 if old_rails_root
432 silence_warnings { Object.const_set(:RAILS_ROOT, old_rails_root) }
433 else
434 Object.remove_const(:RAILS_ROOT) rescue nil
435 end
436 end
437 end
438
439 class ExceptionInheritanceRescueController < ActionController::Base
440
441 class ParentException < StandardError
442 end
443
444 class ChildException < ParentException
445 end
446
447 class GrandchildException < ChildException
448 end
449
450 rescue_from ChildException, :with => lambda { head :ok }
451 rescue_from ParentException, :with => lambda { head :created }
452 rescue_from GrandchildException, :with => lambda { head :no_content }
453
454 def raise_parent_exception
455 raise ParentException
456 end
457
458 def raise_child_exception
459 raise ChildException
460 end
461
462 def raise_grandchild_exception
463 raise GrandchildException
464 end
465 end
466
467 class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
468 def test_bottom_first
469 get :raise_grandchild_exception
470 assert_response :no_content
471 end
472
473 def test_inheritance_works
474 get :raise_child_exception
475 assert_response :created
476 end
477 end
478
479 class ControllerInheritanceRescueController < ExceptionInheritanceRescueController
480 class FirstExceptionInChildController < StandardError
481 end
482
483 class SecondExceptionInChildController < StandardError
484 end
485
486 rescue_from FirstExceptionInChildController, 'SecondExceptionInChildController', :with => lambda { head :gone }
487
488 def raise_first_exception_in_child_controller
489 raise FirstExceptionInChildController
490 end
491
492 def raise_second_exception_in_child_controller
493 raise SecondExceptionInChildController
494 end
495 end
496
497 class ControllerInheritanceRescueControllerTest < ActionController::TestCase
498 def test_first_exception_in_child_controller
499 get :raise_first_exception_in_child_controller
500 assert_response :gone
501 end
502
503 def test_second_exception_in_child_controller
504 get :raise_second_exception_in_child_controller
505 assert_response :gone
506 end
507
508 def test_exception_in_parent_controller
509 get :raise_parent_exception
510 assert_response :created
511 end
512 end
513 end # uses_mocha