rails/activesupport/test/time_travel_test.rb
Jean Boussier aa84a783ee ruby-head: handle unused block warnings
Ref: https://bugs.ruby-lang.org/issues/15554

This new Ruby 3.4 warning is still being fined tuned to reduce false positives,
so we shouldn't fail builds on it just yet.

It however caught one mistake in the test suite which is valuable.
2024-04-17 12:24:12 +02:00

415 lines
13 KiB
Ruby

# frozen_string_literal: true
require_relative "abstract_unit"
require "active_support/core_ext/date_time"
require "active_support/core_ext/numeric/time"
require "active_support/core_ext/string/conversions"
require_relative "time_zone_test_helpers"
class TimeTravelTest < ActiveSupport::TestCase
include TimeZoneTestHelpers
class TimeSubclass < ::Time; end
class DateSubclass < ::Date; end
class DateTimeSubclass < ::DateTime; end
class TravelClass
include ActiveSupport::Testing::TimeHelpers
def travel_to_no_block(date)
travel_to(date)
end
def travel_to_block(date)
travel_to(date) { }
end
end
def test_time_helper_travel
Time.stub(:now, Time.now) do
expected_time = Time.now + 1.day
travel 1.day
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
assert_equal expected_time.to_date, Date.today
assert_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
if RUBY_VERSION >= "3.2"
assert_not_equal expected_time.to_fs(:db), Time.new(precision: 3).to_fs(:db)
end
ensure
travel_back
end
end
def test_time_helper_travel_with_block
Time.stub(:now, Time.now) do
expected_time = Time.now + 1.day
travel 1.day do
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
assert_equal expected_time.to_date, Date.today
assert_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
if RUBY_VERSION >= "3.2"
assert_not_equal expected_time.to_fs(:db), Time.new(precision: 3).to_fs(:db)
assert_equal Time.new("2000-12-31 23:59:59.567"), Time.new("2000-12-31 23:59:59.56789", precision: 3)
end
end
assert_not_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
assert_not_equal expected_time.to_date, Date.today
assert_not_equal expected_time.to_datetime.to_fs(:db), DateTime.now.to_fs(:db)
if RUBY_VERSION >= "3.2"
assert_equal Time.new("2000-12-31 23:59:59.567"), Time.new("2000-12-31 23:59:59.56789", precision: 3)
end
end
end
def test_time_helper_travel_to
Time.stub(:now, Time.now) do
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
travel_to expected_time
assert_equal expected_time, Time.now
assert_equal expected_time, Time.new
assert_not_equal expected_time, Time.new(2004, 11, 25)
if RUBY_VERSION >= "3.2"
assert_not_equal expected_time, Time.new(precision: 3)
end
assert_equal Date.new(2004, 11, 24), Date.today
assert_equal expected_time.to_datetime, DateTime.now
ensure
travel_back
end
end
def test_time_helper_travel_to_with_block
Time.stub(:now, Time.now) do
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
travel_to expected_time do
assert_equal expected_time, Time.now
assert_equal expected_time, Time.new
if RUBY_VERSION >= "3.2"
assert_not_equal expected_time, Time.new(precision: 3)
end
assert_not_equal expected_time, Time.new(2004, 11, 25)
assert_equal Date.new(2004, 11, 24), Date.today
assert_equal expected_time.to_datetime, DateTime.now
end
assert_not_equal expected_time, Time.now
assert_not_equal expected_time, Time.new
assert_not_equal Date.new(2004, 11, 24), Date.today
assert_not_equal expected_time.to_datetime, DateTime.now
end
end
def test_time_helper_travel_to_with_time_zone
with_env_tz "US/Eastern" do
with_tz_default ActiveSupport::TimeZone["UTC"] do
Time.stub(:now, Time.now) do
expected_time = 5.minutes.ago
travel_to 5.minutes.ago do
assert_equal expected_time.to_fs(:db), Time.zone.now.to_fs(:db)
end
end
end
end
end
def test_time_helper_travel_to_with_different_system_and_application_time_zones
with_env_tz "US/Eastern" do # system time zone: -05
expected_time_in_2021 = Time.new(2021)
with_tz_default ActiveSupport::TimeZone["Ekaterinburg"] do # application time zone: +05
destination_time = Time.new(2023, 12, 1, 5, 6, 7, 5 * 3600)
# All stubbed methods are expected to return values in system (-05) time zone
expected_utc_offset = -5 * 3600
expected_time = Time.new(2023, 11, 30, 19, 6, 7, expected_utc_offset)
expected_datetime = DateTime.new(2023, 11, 30, 19, 6, 7, -Rational(5, 24))
expected_date = Date.new(2023, 11, 30)
travel_to destination_time do
assert_equal expected_time, Time.now
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
assert_equal expected_utc_offset, Time.now.utc_offset
assert_equal expected_datetime, DateTime.now
assert_equal expected_datetime.to_fs(:db), DateTime.now.to_fs(:db)
assert_equal expected_utc_offset, DateTime.now.utc_offset
assert_equal expected_date, Date.today
# Time.new with no args equals to Time.now
assert_equal expected_time, Time.new
assert_equal expected_time.to_fs(:db), Time.new.to_fs(:db)
assert_equal expected_utc_offset, Time.new.utc_offset
# Time.new with any args falls back to original Ruby implementation
assert_equal expected_time_in_2021, Time.new(2021)
assert_equal expected_time_in_2021.to_fs(:db), Time.new(2021).to_fs(:db)
assert_equal expected_time_in_2021.utc_offset, Time.new(2021).utc_offset
end
end
end
end
def test_time_helper_travel_to_with_string_for_time_zone
with_env_tz "US/Eastern" do
with_tz_default ActiveSupport::TimeZone["UTC"] do
Time.stub(:now, Time.now) do
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
travel_to "2004-11-24 01:04:44" do
assert_equal expected_time.to_fs(:db), Time.zone.now.to_fs(:db)
end
end
end
end
end
def test_time_helper_travel_to_with_separate_class
travel_object = TravelClass.new
date1 = Date.new(2004, 11, 24)
date2 = Date.new(2005, 11, 24)
Time.stub(:now, now = Time.now) do
travel_to(date1) do
travel_object.travel_to_no_block(date2)
end
assert_equal now, Time.now
travel_to(date1) do
travel_object.travel_to_no_block(date2)
assert_equal date2, Date.today
end
assert_equal now, Time.now
travel_to(date1) do
travel_object.travel_to_block(date2)
assert_equal date1, Date.today
end
assert_equal now, Time.now
end
end
def test_time_helper_travel_back
Time.stub(:now, Time.now) do
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
travel_to expected_time
assert_equal expected_time, Time.now
assert_equal expected_time, Time.new
assert_equal Date.new(2004, 11, 24), Date.today
assert_equal expected_time.to_datetime, DateTime.now
travel_back
assert_not_equal expected_time, Time.now
assert_not_equal expected_time, Time.new
assert_not_equal Date.new(2004, 11, 24), Date.today
assert_not_equal expected_time.to_datetime, DateTime.now
ensure
travel_back
end
end
def test_time_helper_travel_back_with_block
Time.stub(:now, Time.now) do
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
travel_to expected_time
assert_equal expected_time, Time.now
assert_equal expected_time, Time.new
assert_equal Date.new(2004, 11, 24), Date.today
assert_equal expected_time.to_datetime, DateTime.now
travel_back do
assert_not_equal expected_time, Time.now
assert_not_equal expected_time, Time.new
assert_not_equal Date.new(2004, 11, 24), Date.today
assert_not_equal expected_time.to_datetime, DateTime.now
end
assert_equal expected_time, Time.now
assert_equal expected_time, Time.new
assert_equal Date.new(2004, 11, 24), Date.today
assert_equal expected_time.to_datetime, DateTime.now
ensure
travel_back
end
end
def test_time_helper_travel_to_with_nested_calls_with_blocks
Time.stub(:now, Time.now) do
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
travel_to outer_expected_time do
e = assert_raises(RuntimeError) do
travel_to(inner_expected_time) do
# noop
end
end
assert_match(/Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing\./, e.message)
end
end
end
def test_time_helper_travel_to_with_nested_calls
Time.stub(:now, Time.now) do
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
travel_to outer_expected_time do
assert_nothing_raised do
travel_to(inner_expected_time)
assert_equal inner_expected_time, Time.now
end
end
end
end
def test_time_helper_travel_to_with_subsequent_calls
Time.stub(:now, Time.now) do
initial_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
subsequent_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
assert_nothing_raised do
travel_to initial_expected_time
travel_to subsequent_expected_time
assert_equal subsequent_expected_time, Time.now
travel_back
end
ensure
travel_back
end
end
def test_time_helper_travel_to_with_usec
Time.stub(:now, Time.now) do
duration_usec = 0.1.seconds
traveled_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
expected_time = Time.new(2004, 11, 24, 1, 4, 44)
assert_nothing_raised do
travel_to traveled_time
assert_equal expected_time, Time.now
travel_back
end
ensure
travel_back
end
end
def test_time_helper_with_usec_true
Time.stub(:now, Time.now) do
duration_usec = 0.1.seconds
expected_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
assert_nothing_raised do
travel_to expected_time, with_usec: true
assert_equal expected_time.to_f, Time.now.to_f
travel 0.5, with_usec: true
assert_equal((expected_time + 0.5).to_f, Time.now.to_f)
travel_back
end
ensure
travel_back
end
end
def test_time_helper_freeze_time_with_usec_true
# repeatedly test in case Time.now happened to actually be 0 usec
checks = 9.times.map do
freeze_time(with_usec: true) do
Time.now.usec != 0
end
end
assert_predicate checks, :any?
end
def test_time_helper_travel_with_subsequent_block
Time.stub(:now, Time.now) do
outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
travel_to outer_expected_time
assert_equal outer_expected_time, Time.now
assert_nothing_raised do
travel_to(inner_expected_time) do
assert_equal inner_expected_time, Time.now
end
end
assert_equal outer_expected_time, Time.now
ensure
travel_back
end
end
def test_travel_to_will_reset_the_usec_to_avoid_mysql_rounding
Time.stub(:now, Time.now) do
travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
assert_equal 50, Time.now.sec
assert_equal 0, Time.now.usec
assert_equal 50, DateTime.now.sec
assert_equal 0, DateTime.now.usec
end
end
end
def test_time_helper_travel_with_time_subclass
assert_equal TimeSubclass, TimeSubclass.now.class
assert_equal DateSubclass, DateSubclass.today.class
assert_equal DateTimeSubclass, DateTimeSubclass.now.class
travel 1.day do
assert_equal TimeSubclass, TimeSubclass.now.class
assert_equal DateSubclass, DateSubclass.today.class
assert_equal DateTimeSubclass, DateTimeSubclass.now.class
assert_equal Time.now.to_s, TimeSubclass.now.to_s
assert_equal Date.today.to_s, DateSubclass.today.to_s
assert_equal DateTime.now.to_s, DateTimeSubclass.now.to_s
end
end
def test_time_helper_freeze_time
expected_time = Time.now
freeze_time
sleep(1)
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
ensure
travel_back
end
def test_time_helper_freeze_time_with_block
expected_time = Time.now
freeze_time do
sleep(1)
assert_equal expected_time.to_fs(:db), Time.now.to_fs(:db)
end
assert_operator expected_time.to_fs(:db), :<, Time.now.to_fs(:db)
end
def test_time_helper_unfreeze_time
assert_equal method(:travel_back), method(:unfreeze_time)
end
end