Update test suite for compatibility with Ruby 3.4-dev

https://bugs.ruby-lang.org/issues/19117 and https://bugs.ruby-lang.org/issues/16495
slightly change how backtrace are rendered which makes a few tests fail.
This commit is contained in:
Jean Boussier 2024-02-16 09:53:45 +01:00
parent 9e01d93547
commit 50daadaa71
15 changed files with 149 additions and 70 deletions

@ -701,7 +701,7 @@ def self.build_app(app, *args)
# assert application trace refers to line that calls method_that_raises is first
assert_select "#Application-Trace-0" do
assert_select "code a:first", %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call}
assert_select "code a:first", %r{test/dispatch/debug_exceptions_test\.rb:\d+:in .*call}
end
# assert framework trace that threw the error is first
@ -747,19 +747,32 @@ def self.build_app(app, *args)
assert_select "pre .line.active", /raise "Third error"/
end
# assert application trace refers to line that raises the last exception
assert_select "#Application-Trace-0" do
assert_select "code a:first", %r{in `rescue in rescue in raise_nested_exceptions'}
end
if RUBY_VERSION >= "3.4"
# Possible Ruby 3.4-dev bug: https://bugs.ruby-lang.org/issues/19117#note-45
# assert application trace refers to line that raises the last exception
assert_select "#Application-Trace-0" do
assert_select "code a:first", %r{in '.*raise_nested_exceptions'}
end
# assert the second application trace refers to the line that raises the second exception
assert_select "#Application-Trace-1" do
assert_select "code a:first", %r{in `rescue in raise_nested_exceptions'}
# assert the second application trace refers to the line that raises the second exception
assert_select "#Application-Trace-1" do
assert_select "code a:first", %r{in '.*raise_nested_exceptions'}
end
else
# assert application trace refers to line that raises the last exception
assert_select "#Application-Trace-0" do
assert_select "code a:first", %r{in [`']rescue in rescue in .*raise_nested_exceptions'}
end
# assert the second application trace refers to the line that raises the second exception
assert_select "#Application-Trace-1" do
assert_select "code a:first", %r{in [`']rescue in .*raise_nested_exceptions'}
end
end
# assert the third application trace refers to the line that raises the first exception
assert_select "#Application-Trace-2" do
assert_select "code a:first", %r{in `raise_nested_exceptions'}
assert_select "code a:first", %r{in [`'].*raise_nested_exceptions'}
end
end
end
@ -810,6 +823,6 @@ def self.build_app(app, *args)
assert_response 500
assert_select "#container p", /Showing #{__FILE__} where line #\d+ raised/
assert_select "#container code", /undefined local variable or method `string”'/
assert_select "#container code", /undefined local variable or method ['`]string”'/
end
end

@ -114,7 +114,11 @@ def backtrace
exception = begin index; rescue TestError => ex; ex; end
wrapper = ExceptionWrapper.new(@cleaner, TopErrorProxy.new(exception, 1))
assert_equal [ "lib/file.rb:42:in `index'" ], wrapper.application_trace.map(&:to_s)
if RUBY_VERSION >= "3.4"
assert_equal [ "lib/file.rb:42:in 'ActionDispatch::ExceptionWrapperTest#index'" ], wrapper.application_trace.map(&:to_s)
else
assert_equal [ "lib/file.rb:42:in `index'" ], wrapper.application_trace.map(&:to_s)
end
end
test "#status_code returns 400 for Rack::Utils::ParameterTypeError" do
@ -182,30 +186,57 @@ def backtrace
exception = begin in_rack; rescue TestError => ex; TopErrorProxy.new(ex, 2); end
wrapper = ExceptionWrapper.new(@cleaner, exception)
assert_equal({
"Application Trace" => [
exception_object_id: exception.object_id,
id: 0,
trace: "lib/file.rb:42:in `index'"
],
"Framework Trace" => [
exception_object_id: exception.object_id,
id: 1,
trace: "/gems/rack.rb:43:in `in_rack'"
],
"Full Trace" => [
{
if RUBY_VERSION >= "3.4"
assert_equal({
"Application Trace" => [
exception_object_id: exception.object_id,
id: 0,
trace: "lib/file.rb:42:in 'ActionDispatch::ExceptionWrapperTest#index'"
],
"Framework Trace" => [
exception_object_id: exception.object_id,
id: 1,
trace: "/gems/rack.rb:43:in 'ActionDispatch::ExceptionWrapperTest#in_rack'"
],
"Full Trace" => [
{
exception_object_id: exception.object_id,
id: 0,
trace: "lib/file.rb:42:in 'ActionDispatch::ExceptionWrapperTest#index'"
},
{
exception_object_id: exception.object_id,
id: 1,
trace: "/gems/rack.rb:43:in 'ActionDispatch::ExceptionWrapperTest#in_rack'"
}
]
}.inspect, wrapper.traces.inspect)
else
assert_equal({
"Application Trace" => [
exception_object_id: exception.object_id,
id: 0,
trace: "lib/file.rb:42:in `index'"
},
{
],
"Framework Trace" => [
exception_object_id: exception.object_id,
id: 1,
trace: "/gems/rack.rb:43:in `in_rack'"
}
]
}.inspect, wrapper.traces.inspect)
],
"Full Trace" => [
{
exception_object_id: exception.object_id,
id: 0,
trace: "lib/file.rb:42:in `index'"
},
{
exception_object_id: exception.object_id,
id: 1,
trace: "/gems/rack.rb:43:in `in_rack'"
}
]
}.inspect, wrapper.traces.inspect)
end
end
test "#show? returns false when using :rescuable and the exceptions is not rescuable" do

@ -213,7 +213,7 @@ def test_with_nil_in_list_does_not_generate_invalid_link
@series.save
polymorphic_url([nil, @series])
end
assert_match(/undefined method `series_url'/, exception.message)
assert_match(/undefined method [`']series_url'/, exception.message)
end
end

@ -316,7 +316,7 @@ def test_render_renderable_does_not_mask_nomethoderror_from_within_render_in
renderable = Object.new
renderable.define_singleton_method(:render_in) { |*| nil.render_in }
assert_raises NoMethodError, match: "undefined method `render_in' for nil" do
assert_raises NoMethodError, match: /undefined method [`']render_in' for nil/ do
@view.render renderable: renderable
end
end
@ -390,7 +390,7 @@ def test_render_sub_template_with_errors
def test_undefined_method_error_references_named_class
e = assert_raises(ActionView::Template::Error) { @view.render(inline: "<%= undefined %>") }
assert_match(/undefined local variable or method `undefined'/, e.message)
assert_match(/undefined local variable or method [`']undefined'/, e.message)
end
def test_render_renderable_object

@ -278,14 +278,14 @@ def test_job_error_logging
RescueJob.perform_later "other"
rescue RescueJob::OtherError
assert_match(/Performing RescueJob \(Job ID: .*?\) from .*? with arguments:.*other/, @logger.messages)
assert_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: RescueJob::OtherError \(Bad hair\):\n.*\brescue_job\.rb:\d+:in `perform'/, @logger.messages)
assert_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: RescueJob::OtherError \(Bad hair\):\n.*\brescue_job\.rb:\d+:in .*perform'/, @logger.messages)
end
end
def test_job_no_error_logging_on_rescuable_job
perform_enqueued_jobs { RescueJob.perform_later "david" }
assert_match(/Performing RescueJob \(Job ID: .*?\) from .*? with arguments:.*david/, @logger.messages)
assert_no_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: ArgumentError \(Hair too good\):\n.*\brescue_job\.rb:\d+:in `perform'/, @logger.messages)
assert_no_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: ArgumentError \(Hair too good\):\n.*\brescue_job\.rb:\d+:in .*perform'/, @logger.messages)
end
def test_enqueue_retry_logging

@ -262,7 +262,7 @@ def attribute(name)
assert_equal("Active Model Topic", topic_class.new.subject_to_be_undefined)
topic_class.undefine_attribute_methods
assert_raises(NoMethodError, match: /undefined method `subject_to_be_undefined'/) do
assert_raises(NoMethodError, match: /undefined method [`']subject_to_be_undefined'/) do
topic_class.new.subject_to_be_undefined
end
end

@ -291,14 +291,14 @@ def test_overriding_default_journal_size_limit_pragma
conn.execute("PRAGMA journal_size_limit")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
error = assert_raises(ActiveRecord::StatementInvalid) do
send(method_name, pragmas: { journal_size_limit: :false }) do |conn|
conn.execute("PRAGMA journal_size_limit")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
end
def test_overriding_default_mmap_size_pragma
@ -317,14 +317,14 @@ def test_overriding_default_mmap_size_pragma
conn.execute("PRAGMA mmap_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
error = assert_raises(ActiveRecord::StatementInvalid) do
with_memory_connection(pragmas: { mmap_size: :false }) do |conn|
conn.execute("PRAGMA mmap_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
else
with_file_connection(pragmas: { mmap_size: 100 }) do |conn|
assert_equal [{ "mmap_size" => 100 }], conn.execute("PRAGMA mmap_size")
@ -339,14 +339,14 @@ def test_overriding_default_mmap_size_pragma
conn.execute("PRAGMA mmap_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
error = assert_raises(ActiveRecord::StatementInvalid) do
with_file_connection(pragmas: { mmap_size: :false }) do |conn|
conn.execute("PRAGMA mmap_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
end
end
@ -366,14 +366,14 @@ def test_overriding_default_cache_size_pragma
conn.execute("PRAGMA cache_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
error = assert_raises(ActiveRecord::StatementInvalid) do
send(method_name, pragmas: { cache_size: :false }) do |conn|
conn.execute("PRAGMA cache_size")
end
end
assert_match(/undefined method `to_i'/, error.message)
assert_match(/undefined method [`']to_i'/, error.message)
end
def test_setting_new_pragma

@ -473,18 +473,33 @@ def test_tidy_call_stack
# callbacks that have been invoked, if there are any (plus
# whatever the callbacks do themselves, of course).
assert_equal [
"block in save",
"block in run_callbacks",
"tweedle_deedle",
"block in run_callbacks",
"w0tyes",
"block in run_callbacks",
"tweedle_dum",
"block in run_callbacks",
"run_callbacks",
"save"
], call_stack.map(&:label)
if RUBY_VERSION >= "3.4"
assert_equal [
"block in CallbacksTest::MySlate#save",
"block in ActiveSupport::Callbacks#run_callbacks",
"CallbacksTest::AroundPerson#tweedle_deedle",
"block in ActiveSupport::Callbacks#run_callbacks",
"CallbacksTest::AroundPerson#w0tyes",
"block in ActiveSupport::Callbacks#run_callbacks",
"CallbacksTest::AroundPerson#tweedle_dum",
"block in ActiveSupport::Callbacks#run_callbacks",
"ActiveSupport::Callbacks#run_callbacks",
"CallbacksTest::MySlate#save",
].join("\n"), call_stack.map(&:label).join("\n")
else
assert_equal [
"block in save",
"block in run_callbacks",
"tweedle_deedle",
"block in run_callbacks",
"w0tyes",
"block in run_callbacks",
"tweedle_dum",
"block in run_callbacks",
"run_callbacks",
"save",
].join("\n"), call_stack.map(&:label).join("\n")
end
end
def test_short_call_stack
@ -503,11 +518,19 @@ def test_short_call_stack
# there should be just one line. run_callbacks yields directly
# back to its caller.
assert_equal [
"block in save",
"run_callbacks",
"save"
], call_stack.map(&:label)
if RUBY_VERSION >= "3.4"
assert_equal [
"block in CallbacksTest::Person#save",
"ActiveSupport::Callbacks#run_callbacks",
"CallbacksTest::Person#save",
].join("\n"), call_stack.map(&:label).join("\n")
else
assert_equal [
"block in save",
"run_callbacks",
"save",
].join("\n"), call_stack.map(&:label).join("\n")
end
end
end

@ -426,7 +426,7 @@ def test_delegate_missing_to_does_not_delegate_to_private_methods
DecoratedReserved.new(@david).private_name
end
assert_match(/undefined method `private_name' for/, e.message)
assert_match(/undefined method [`']private_name' for/, e.message)
end
def test_delegate_missing_to_does_not_delegate_to_fake_methods
@ -434,7 +434,7 @@ def test_delegate_missing_to_does_not_delegate_to_fake_methods
DecoratedReserved.new(@david).my_fake_method
end
assert_match(/undefined method `my_fake_method' for/, e.message)
assert_match(/undefined method [`']my_fake_method' for/, e.message)
end
def test_delegate_missing_to_raises_delegation_error_if_target_nil

@ -1080,7 +1080,7 @@ def test_no_method_error_has_proper_context
e = assert_raises(NoMethodError) {
@twz.this_method_does_not_exist
}
assert_match(/undefined method `this_method_does_not_exist' for.*ActiveSupport::TimeWithZone/, e.message)
assert_match(/undefined method [`']this_method_does_not_exist' for.*ActiveSupport::TimeWithZone/, e.message)
assert_no_match "rescue", e.backtrace.first
end
end

@ -968,7 +968,11 @@ def generated_method_that_call_deprecation(deprecator)
test "warn deprecation can blame code generated with eval" do
@deprecator.behavior = ->(message, *) { @message = message }
generated_method_that_call_deprecation(@deprecator)
assert_equal "DEPRECATION WARNING: Here (called from generated_method_that_call_deprecation at /path/to/template.html.erb:2)", @message
if RUBY_VERSION >= "3.4"
assert_equal "DEPRECATION WARNING: Here (called from DeprecationTest#generated_method_that_call_deprecation at /path/to/template.html.erb:2)", @message
else
assert_equal "DEPRECATION WARNING: Here (called from generated_method_that_call_deprecation at /path/to/template.html.erb:2)", @message
end
end
private

@ -416,8 +416,8 @@ def test_fails_and_warning_is_logged_if_wrong_error_caught
Other block based assertions (e.g. `assert_no_changes`) can be used, as long as `assert_raises` is inside their block.
MSG
assert_includes @out.string, expected
assert error.message.include?("ArgumentError: ArgumentError")
assert error.message.include?("in `block (2 levels) in run_test_that_should_fail_confusingly'")
assert_includes error.message, "ArgumentError: ArgumentError"
assert_includes error.message, "run_test_that_should_fail_confusingly"
end
private

@ -19,7 +19,11 @@ def teardown
app("development")
get "/"
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in `index'"
if RUBY_VERSION >= "3.4"
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in 'FooController#index'"
else
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in `index'"
end
assert_not_includes last_response.body, "rails/railties/test/env_helpers.rb"
end
@ -29,7 +33,11 @@ def teardown
app("development")
get "/"
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in `index'"
if RUBY_VERSION >= "3.4"
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in 'FooController#index'"
else
assert_includes last_response.body, "app/app/controllers/foo_controller.rb:4:in `index'"
end
assert_includes last_response.body, "rails/railties/test/env_helpers.rb"
end
end

@ -122,7 +122,7 @@ def test_runner_detects_syntax_errors
def test_runner_detects_bad_script_name
output = rails("runner", "iuiqwiourowe", allow_failure: true)
assert_not_predicate $?, :success?
assert_match "undefined local variable or method `iuiqwiourowe' for", output
assert_match(/undefined local variable or method [`']iuiqwiourowe' for/, output)
end
def test_environment_with_rails_env

@ -243,7 +243,7 @@ class Foo < Rails::Railtie
Foo.instance.abc
end
assert_match(/undefined method `abc' for.*RailtiesTest::RailtieTest::Foo/, error.original_message)
assert_match(/undefined method [`']abc' for.*RailtiesTest::RailtieTest::Foo/, error.original_message)
end
test "rake environment can be called in the ralitie" do