Skip to content

Commit

Permalink
prevent global timezone state from leaking out of test cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
senny committed Oct 25, 2013
1 parent 3e5bb86 commit abe91cb
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 214 deletions.
40 changes: 15 additions & 25 deletions activerecord/test/cases/adapters/postgresql/datatype_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -589,38 +589,28 @@ def test_update_oid
end end


def test_timestamp_with_zone_values_with_rails_time_zone_support def test_timestamp_with_zone_values_with_rails_time_zone_support
old_tz = ActiveRecord::Base.time_zone_aware_attributes with_timezone_config default: :utc, aware_attributes: true do
old_default_tz = ActiveRecord::Base.default_timezone @connection.reconnect!


ActiveRecord::Base.time_zone_aware_attributes = true @first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
ActiveRecord::Base.default_timezone = :utc assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time

assert_instance_of Time, @first_timestamp_with_zone.time
@connection.reconnect! end

@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
assert_instance_of Time, @first_timestamp_with_zone.time
ensure ensure
ActiveRecord::Base.default_timezone = old_default_tz
ActiveRecord::Base.time_zone_aware_attributes = old_tz
@connection.reconnect! @connection.reconnect!
end end


def test_timestamp_with_zone_values_without_rails_time_zone_support def test_timestamp_with_zone_values_without_rails_time_zone_support
old_tz = ActiveRecord::Base.time_zone_aware_attributes with_timezone_config default: :local, aware_attributes: false do
old_default_tz = ActiveRecord::Base.default_timezone @connection.reconnect!

# make sure to use a non-UTC time zone
ActiveRecord::Base.time_zone_aware_attributes = false @connection.execute("SET time zone 'America/Jamaica'", 'SCHEMA')
ActiveRecord::Base.default_timezone = :local

@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
@connection.reconnect! assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time

assert_instance_of Time, @first_timestamp_with_zone.time
@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1) end
assert_equal Time.local(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
assert_instance_of Time, @first_timestamp_with_zone.time
ensure ensure
ActiveRecord::Base.default_timezone = old_default_tz
ActiveRecord::Base.time_zone_aware_attributes = old_tz
@connection.reconnect! @connection.reconnect!
end end
end end
97 changes: 47 additions & 50 deletions activerecord/test/cases/base_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ def setup
class BasicsTest < ActiveRecord::TestCase class BasicsTest < ActiveRecord::TestCase
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts


def setup
ActiveRecord::Base.time_zone_aware_attributes = false
ActiveRecord::Base.default_timezone = :local
Time.zone = nil
end

def test_generated_methods_modules def test_generated_methods_modules
modules = Computer.ancestors modules = Computer.ancestors
assert modules.include?(Computer::GeneratedFeatureMethods) assert modules.include?(Computer::GeneratedFeatureMethods)
Expand Down Expand Up @@ -234,7 +228,7 @@ def test_preserving_time_objects


def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :utc do with_timezone_config default: :utc do
time = Time.local(2000) time = Time.local(2000)
topic = Topic.create('written_on' => time) topic = Topic.create('written_on' => time)
saved_time = Topic.find(topic.id).reload.written_on saved_time = Topic.find(topic.id).reload.written_on
Expand All @@ -247,7 +241,7 @@ def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_


def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :utc do with_timezone_config default: :utc do
Time.use_zone 'Central Time (US & Canada)' do Time.use_zone 'Central Time (US & Canada)' do
time = Time.zone.local(2000) time = Time.zone.local(2000)
topic = Topic.create('written_on' => time) topic = Topic.create('written_on' => time)
Expand All @@ -262,18 +256,20 @@ def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timez


def test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local def test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
time = Time.utc(2000) with_timezone_config default: :local do
topic = Topic.create('written_on' => time) time = Time.utc(2000)
saved_time = Topic.find(topic.id).reload.written_on topic = Topic.create('written_on' => time)
assert_equal time, saved_time saved_time = Topic.find(topic.id).reload.written_on
assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a assert_equal time, saved_time
assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
end
end end
end end


def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :local do with_timezone_config default: :local do
Time.use_zone 'Central Time (US & Canada)' do Time.use_zone 'Central Time (US & Canada)' do
time = Time.zone.local(2000) time = Time.zone.local(2000)
topic = Topic.create('written_on' => time) topic = Topic.create('written_on' => time)
Expand Down Expand Up @@ -493,25 +489,25 @@ def test_default_values
# Oracle, and Sybase do not have a TIME datatype. # Oracle, and Sybase do not have a TIME datatype.
unless current_adapter?(:OracleAdapter, :SybaseAdapter) unless current_adapter?(:OracleAdapter, :SybaseAdapter)
def test_utc_as_time_zone def test_utc_as_time_zone
Topic.default_timezone = :utc with_timezone_config default: :utc do
attributes = { "bonus_time" => "5:42:00AM" } attributes = { "bonus_time" => "5:42:00AM" }
topic = Topic.find(1) topic = Topic.find(1)
topic.attributes = attributes topic.attributes = attributes
assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
Topic.default_timezone = :local end
end end


def test_utc_as_time_zone_and_new def test_utc_as_time_zone_and_new
Topic.default_timezone = :utc with_timezone_config default: :utc do
attributes = { "bonus_time(1i)"=>"2000", attributes = { "bonus_time(1i)"=>"2000",
"bonus_time(2i)"=>"1", "bonus_time(2i)"=>"1",
"bonus_time(3i)"=>"1", "bonus_time(3i)"=>"1",
"bonus_time(4i)"=>"10", "bonus_time(4i)"=>"10",
"bonus_time(5i)"=>"35", "bonus_time(5i)"=>"35",
"bonus_time(6i)"=>"50" } "bonus_time(6i)"=>"50" }
topic = Topic.new(attributes) topic = Topic.new(attributes)
assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
Topic.default_timezone = :local end
end end
end end


Expand Down Expand Up @@ -634,12 +630,14 @@ def test_attributes_on_dummy_time
# Oracle, and Sybase do not have a TIME datatype. # Oracle, and Sybase do not have a TIME datatype.
return true if current_adapter?(:OracleAdapter, :SybaseAdapter) return true if current_adapter?(:OracleAdapter, :SybaseAdapter)


attributes = { with_timezone_config default: :local do
"bonus_time" => "5:42:00AM" attributes = {
} "bonus_time" => "5:42:00AM"
topic = Topic.find(1) }
topic.attributes = attributes topic = Topic.find(1)
assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time topic.attributes = attributes
assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
end
end end


def test_attributes_on_dummy_time_with_invalid_time def test_attributes_on_dummy_time_with_invalid_time
Expand Down Expand Up @@ -827,19 +825,18 @@ def test_bignum
# TODO: extend defaults tests to other databases! # TODO: extend defaults tests to other databases!
if current_adapter?(:PostgreSQLAdapter) if current_adapter?(:PostgreSQLAdapter)
def test_default def test_default
tz = Default.default_timezone with_timezone_config default: :local do
Default.default_timezone = :local default = Default.new
default = Default.new
Default.default_timezone = tz # fixed dates / times

assert_equal Date.new(2004, 1, 1), default.fixed_date
# fixed dates / times assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
assert_equal Date.new(2004, 1, 1), default.fixed_date
assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time # char types

assert_equal 'Y', default.char1
# char types assert_equal 'a varchar field', default.char2
assert_equal 'Y', default.char1 assert_equal 'a text field', default.char3
assert_equal 'a varchar field', default.char2 end
assert_equal 'a text field', default.char3
end end


class Geometric < ActiveRecord::Base; end class Geometric < ActiveRecord::Base; end
Expand Down
8 changes: 3 additions & 5 deletions activerecord/test/cases/column_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -112,13 +112,11 @@ def test_type_cast_duration_to_integer
end end


def test_string_to_time_with_timezone def test_string_to_time_with_timezone
old = ActiveRecord::Base.default_timezone
[:utc, :local].each do |zone| [:utc, :local].each do |zone|
ActiveRecord::Base.default_timezone = zone with_timezone_config default: zone do
assert_equal Time.utc(2013, 9, 4, 0, 0, 0), Column.string_to_time("Wed, 04 Sep 2013 03:00:00 EAT") assert_equal Time.utc(2013, 9, 4, 0, 0, 0), Column.string_to_time("Wed, 04 Sep 2013 03:00:00 EAT")
end
end end
rescue
ActiveRecord::Base.default_timezone = old
end end
end end
end end
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/cases/date_time_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class DateTimeTest < ActiveRecord::TestCase class DateTimeTest < ActiveRecord::TestCase
def test_saves_both_date_and_time def test_saves_both_date_and_time
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :utc do with_timezone_config default: :utc do
time_values = [1807, 2, 10, 15, 30, 45] time_values = [1807, 2, 10, 15, 30, 45]
# create DateTime value with local time zone offset # create DateTime value with local time zone offset
local_offset = Rational(Time.local(*time_values).utc_offset, 86400) local_offset = Rational(Time.local(*time_values).utc_offset, 86400)
Expand Down
8 changes: 4 additions & 4 deletions activerecord/test/cases/finder_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ def test_hash_condition_find_with_one_condition_being_aggregate_and_another_not


def test_condition_utc_time_interpolation_with_default_timezone_local def test_condition_utc_time_interpolation_with_default_timezone_local
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :local do with_timezone_config default: :local do
topic = Topic.first topic = Topic.first
assert_equal topic, Topic.all.merge!(:where => ['written_on = ?', topic.written_on.getutc]).first assert_equal topic, Topic.all.merge!(:where => ['written_on = ?', topic.written_on.getutc]).first
end end
Expand All @@ -488,7 +488,7 @@ def test_condition_utc_time_interpolation_with_default_timezone_local


def test_hash_condition_utc_time_interpolation_with_default_timezone_local def test_hash_condition_utc_time_interpolation_with_default_timezone_local
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :local do with_timezone_config default: :local do
topic = Topic.first topic = Topic.first
assert_equal topic, Topic.all.merge!(:where => {:written_on => topic.written_on.getutc}).first assert_equal topic, Topic.all.merge!(:where => {:written_on => topic.written_on.getutc}).first
end end
Expand All @@ -497,7 +497,7 @@ def test_hash_condition_utc_time_interpolation_with_default_timezone_local


def test_condition_local_time_interpolation_with_default_timezone_utc def test_condition_local_time_interpolation_with_default_timezone_utc
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :utc do with_timezone_config default: :utc do
topic = Topic.first topic = Topic.first
assert_equal topic, Topic.all.merge!(:where => ['written_on = ?', topic.written_on.getlocal]).first assert_equal topic, Topic.all.merge!(:where => ['written_on = ?', topic.written_on.getlocal]).first
end end
Expand All @@ -506,7 +506,7 @@ def test_condition_local_time_interpolation_with_default_timezone_utc


def test_hash_condition_local_time_interpolation_with_default_timezone_utc def test_hash_condition_local_time_interpolation_with_default_timezone_utc
with_env_tz 'America/New_York' do with_env_tz 'America/New_York' do
with_active_record_default_timezone :utc do with_timezone_config default: :utc do
topic = Topic.first topic = Topic.first
assert_equal topic, Topic.all.merge!(:where => {:written_on => topic.written_on.getlocal}).first assert_equal topic, Topic.all.merge!(:where => {:written_on => topic.written_on.getlocal}).first
end end
Expand Down
50 changes: 47 additions & 3 deletions activerecord/test/cases/helper.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,11 +49,55 @@ def with_env_tz(new_tz = 'US/Eastern')
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
end end


def with_active_record_default_timezone(zone) def with_timezone_config(cfg)
old_zone, ActiveRecord::Base.default_timezone = ActiveRecord::Base.default_timezone, zone verify_default_timezone_config

old_default_zone = ActiveRecord::Base.default_timezone
old_awareness = ActiveRecord::Base.time_zone_aware_attributes
old_zone = Time.zone

if cfg.has_key?(:default)
ActiveRecord::Base.default_timezone = cfg[:default]
end
if cfg.has_key?(:aware_attributes)
ActiveRecord::Base.time_zone_aware_attributes = cfg[:aware_attributes]
end
if cfg.has_key?(:zone)
Time.zone = cfg[:zone]
end
yield yield
ensure ensure
ActiveRecord::Base.default_timezone = old_zone ActiveRecord::Base.default_timezone = old_default_zone
ActiveRecord::Base.time_zone_aware_attributes = old_awareness
Time.zone = old_zone
end

# This method makes sure that tests don't leak global state related to time zones.
EXPECTED_ZONE = nil
EXPECTED_DEFAULT_TIMEZONE = :utc
EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES = false
def verify_default_timezone_config
if Time.zone != EXPECTED_ZONE
raise <<-MSG
Global state `Time.zone` was leaked.
Expected: #{EXPECTED_ZONE}
Got: #{Time.zone}
MSG
end
if ActiveRecord::Base.default_timezone != EXPECTED_DEFAULT_TIMEZONE
raise <<-MSG
Global state `ActiveRecord::Base.default_timezone` was leaked.
Expected: #{EXPECTED_DEFAULT_TIMEZONE}
Got: #{ActiveRecord::Base.default_timezone}
MSG
end
if ActiveRecord::Base.time_zone_aware_attributes != EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES
raise <<-MSG
Global state `ActiveRecord::Base.time_zone_aware_attributes` was leaked.
Expected: #{EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES}
Got: #{ActiveRecord::Base.time_zone_aware_attributes}
MSG
end
end end


unless ENV['FIXTURE_DEBUG'] unless ENV['FIXTURE_DEBUG']
Expand Down
13 changes: 4 additions & 9 deletions activerecord/test/cases/integration_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@ def test_to_param_returns_id_if_not_persisted_but_id_is_set
end end


def test_cache_key_for_existing_record_is_not_timezone_dependent def test_cache_key_for_existing_record_is_not_timezone_dependent
ActiveRecord::Base.time_zone_aware_attributes = true

Time.zone = 'UTC'
utc_key = Developer.first.cache_key utc_key = Developer.first.cache_key


Time.zone = 'EST' with_timezone_config zone: "EST" do
est_key = Developer.first.cache_key est_key = Developer.first.cache_key

assert_equal utc_key, est_key
assert_equal utc_key, est_key end
ensure
Time.zone = 'UTC'
end end


def test_cache_key_format_for_existing_record_with_updated_at def test_cache_key_format_for_existing_record_with_updated_at
Expand Down
Loading

0 comments on commit abe91cb

Please sign in to comment.