diff options
Diffstat (limited to 'activesupport/test')
48 files changed, 1895 insertions, 889 deletions
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index f65ec962f9..c0e23e89f7 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -15,6 +15,7 @@ silence_warnings do end require 'active_support/testing/autorun' +require 'active_support/testing/method_call_assertions' ENV['NO_RELOAD'] = '1' require 'active_support' @@ -37,9 +38,6 @@ def jruby_skip(message = '') skip message if defined?(JRUBY_VERSION) end -require 'mocha/setup' # FIXME: stop using mocha - -# FIXME: we have tests that depend on run order, we should fix that and -# remove this method call. -require 'active_support/test_case' -ActiveSupport::TestCase.test_order = :sorted +class ActiveSupport::TestCase + include ActiveSupport::Testing::MethodCallAssertions +end diff --git a/activesupport/test/array_inquirer_test.rb b/activesupport/test/array_inquirer_test.rb new file mode 100644 index 0000000000..263ab3802b --- /dev/null +++ b/activesupport/test/array_inquirer_test.rb @@ -0,0 +1,41 @@ +require 'abstract_unit' +require 'active_support/core_ext/array' + +class ArrayInquirerTest < ActiveSupport::TestCase + def setup + @array_inquirer = ActiveSupport::ArrayInquirer.new([:mobile, :tablet, 'api']) + end + + def test_individual + assert @array_inquirer.mobile? + assert @array_inquirer.tablet? + assert_not @array_inquirer.desktop? + end + + def test_any + assert @array_inquirer.any?(:mobile, :desktop) + assert @array_inquirer.any?(:watch, :tablet) + assert_not @array_inquirer.any?(:desktop, :watch) + end + + def test_any_string_symbol_mismatch + assert @array_inquirer.any?('mobile') + assert @array_inquirer.any?(:api) + end + + def test_any_with_block + assert @array_inquirer.any? { |v| v == :mobile } + assert_not @array_inquirer.any? { |v| v == :desktop } + end + + def test_respond_to + assert_respond_to @array_inquirer, :development? + end + + def test_inquiry + result = [:mobile, :tablet, 'api'].inquiry + + assert_instance_of ActiveSupport::ArrayInquirer, result + assert_equal @array_inquirer, result + end +end diff --git a/activesupport/test/autoloading_fixtures/a/c/e/f.rb b/activesupport/test/autoloading_fixtures/a/c/e/f.rb deleted file mode 100644 index 57dba5a307..0000000000 --- a/activesupport/test/autoloading_fixtures/a/c/e/f.rb +++ /dev/null @@ -1,2 +0,0 @@ -class A::C::E::F -end
\ No newline at end of file diff --git a/activesupport/test/autoloading_fixtures/a/c/em/f.rb b/activesupport/test/autoloading_fixtures/a/c/em/f.rb new file mode 100644 index 0000000000..8b28e19148 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/a/c/em/f.rb @@ -0,0 +1,2 @@ +class A::C::EM::F +end
\ No newline at end of file diff --git a/activesupport/test/autoloading_fixtures/d.rb b/activesupport/test/autoloading_fixtures/d.rb new file mode 100644 index 0000000000..45c794d4ca --- /dev/null +++ b/activesupport/test/autoloading_fixtures/d.rb @@ -0,0 +1,2 @@ +class D +end
\ No newline at end of file diff --git a/activesupport/test/autoloading_fixtures/e.rb b/activesupport/test/autoloading_fixtures/e.rb deleted file mode 100644 index 2f59e4fb75..0000000000 --- a/activesupport/test/autoloading_fixtures/e.rb +++ /dev/null @@ -1,2 +0,0 @@ -class E -end
\ No newline at end of file diff --git a/activesupport/test/autoloading_fixtures/em.rb b/activesupport/test/autoloading_fixtures/em.rb new file mode 100644 index 0000000000..16a1838667 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/em.rb @@ -0,0 +1,2 @@ +class EM +end
\ No newline at end of file diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 095e908907..74ceff44f9 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -133,37 +133,42 @@ class CacheStoreSettingTest < ActiveSupport::TestCase end def test_mem_cache_fragment_cache_store - Dalli::Client.expects(:new).with(%w[localhost], {}) - store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost" - assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_called_with(Dalli::Client, :new, [%w[localhost], {}]) do + store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost" + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + end end def test_mem_cache_fragment_cache_store_with_given_mem_cache mem_cache = Dalli::Client.new - Dalli::Client.expects(:new).never - store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache - assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_not_called(Dalli::Client, :new) do + store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + end end def test_mem_cache_fragment_cache_store_with_not_dalli_client - Dalli::Client.expects(:new).never - memcache = Object.new - assert_raises(ArgumentError) do - ActiveSupport::Cache.lookup_store :mem_cache_store, memcache + assert_not_called(Dalli::Client, :new) do + memcache = Object.new + assert_raises(ArgumentError) do + ActiveSupport::Cache.lookup_store :mem_cache_store, memcache + end end end def test_mem_cache_fragment_cache_store_with_multiple_servers - Dalli::Client.expects(:new).with(%w[localhost 192.168.1.1], {}) - store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1' - assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], {}]) do + store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1' + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + end end def test_mem_cache_fragment_cache_store_with_options - Dalli::Client.expects(:new).with(%w[localhost 192.168.1.1], { :timeout => 10 }) - store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo', :timeout => 10 - assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) - assert_equal 'foo', store.options[:namespace] + assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], { :timeout => 10 }]) do + store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo', :timeout => 10 + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_equal 'foo', store.options[:namespace] + end end def test_object_assigned_fragment_cache_store @@ -224,13 +229,15 @@ module CacheStoreBehavior def test_fetch_without_cache_miss @cache.write('foo', 'bar') - @cache.expects(:write).never - assert_equal 'bar', @cache.fetch('foo') { 'baz' } + assert_not_called(@cache, :write) do + assert_equal 'bar', @cache.fetch('foo') { 'baz' } + end end def test_fetch_with_cache_miss - @cache.expects(:write).with('foo', 'baz', @cache.options) - assert_equal 'baz', @cache.fetch('foo') { 'baz' } + assert_called_with(@cache, :write, ['foo', 'baz', @cache.options]) do + assert_equal 'baz', @cache.fetch('foo') { 'baz' } + end end def test_fetch_with_cache_miss_passes_key_to_block @@ -245,15 +252,18 @@ module CacheStoreBehavior def test_fetch_with_forced_cache_miss @cache.write('foo', 'bar') - @cache.expects(:read).never - @cache.expects(:write).with('foo', 'bar', @cache.options.merge(:force => true)) - @cache.fetch('foo', :force => true) { 'bar' } + assert_not_called(@cache, :read) do + assert_called_with(@cache, :write, ['foo', 'bar', @cache.options.merge(:force => true)]) do + @cache.fetch('foo', :force => true) { 'bar' } + end + end end def test_fetch_with_cached_nil @cache.write('foo', nil) - @cache.expects(:write).never - assert_nil @cache.fetch('foo') { 'baz' } + assert_not_called(@cache, :write) do + assert_nil @cache.fetch('foo') { 'baz' } + end end def test_should_read_and_write_hash @@ -288,8 +298,9 @@ module CacheStoreBehavior @cache.write('foo', 'bar', :expires_in => 10) @cache.write('fu', 'baz') @cache.write('fud', 'biz') - Time.stubs(:now).returns(time + 11) - assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu')) + Time.stub(:now, time + 11) do + assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu')) + end end def test_fetch_multi @@ -303,8 +314,9 @@ module CacheStoreBehavior end def test_multi_with_objects - foo = stub(:title => 'FOO!', :cache_key => 'foo') - bar = stub(:cache_key => 'bar') + cache_struct = Struct.new(:cache_key, :title) + foo = cache_struct.new('foo', 'FOO!') + bar = cache_struct.new('bar') @cache.write('bar', 'BAM!') @@ -387,54 +399,74 @@ module CacheStoreBehavior def test_expires_in time = Time.local(2008, 4, 24) - Time.stubs(:now).returns(time) - @cache.write('foo', 'bar') - assert_equal 'bar', @cache.read('foo') + Time.stub(:now, time) do + @cache.write('foo', 'bar') + assert_equal 'bar', @cache.read('foo') + end - Time.stubs(:now).returns(time + 30) - assert_equal 'bar', @cache.read('foo') + Time.stub(:now, time + 30) do + assert_equal 'bar', @cache.read('foo') + end - Time.stubs(:now).returns(time + 61) - assert_nil @cache.read('foo') + Time.stub(:now, time + 61) do + assert_nil @cache.read('foo') + end end - def test_race_condition_protection - time = Time.now - @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 61) - result = @cache.fetch('foo', :race_condition_ttl => 10) do - assert_equal 'bar', @cache.read('foo') - "baz" + def test_race_condition_protection_skipped_if_not_defined + @cache.write('foo', 'bar') + time = @cache.send(:read_entry, 'foo', {}).expires_at + + Time.stub(:now, Time.at(time)) do + result = @cache.fetch('foo') do + assert_equal nil, @cache.read('foo') + 'baz' + end + assert_equal 'baz', result end - assert_equal "baz", result end def test_race_condition_protection_is_limited time = Time.now @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 71) - result = @cache.fetch('foo', :race_condition_ttl => 10) do - assert_equal nil, @cache.read('foo') - "baz" + Time.stub(:now, time + 71) do + result = @cache.fetch('foo', :race_condition_ttl => 10) do + assert_equal nil, @cache.read('foo') + "baz" + end + assert_equal "baz", result end - assert_equal "baz", result end def test_race_condition_protection_is_safe time = Time.now @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 61) - begin - @cache.fetch('foo', :race_condition_ttl => 10) do + Time.stub(:now, time + 61) do + begin + @cache.fetch('foo', :race_condition_ttl => 10) do + assert_equal 'bar', @cache.read('foo') + raise ArgumentError.new + end + rescue ArgumentError + end + assert_equal "bar", @cache.read('foo') + end + Time.stub(:now, time + 91) do + assert_nil @cache.read('foo') + end + end + + def test_race_condition_protection + time = Time.now + @cache.write('foo', 'bar', :expires_in => 60) + Time.stub(:now, time + 61) do + result = @cache.fetch('foo', :race_condition_ttl => 10) do assert_equal 'bar', @cache.read('foo') - raise ArgumentError.new + "baz" end - rescue ArgumentError + assert_equal "baz", result end - assert_equal "bar", @cache.read('foo') - Time.stubs(:now).returns(time + 91) - assert_nil @cache.read('foo') end def test_crazy_key_characters @@ -624,37 +656,37 @@ module AutoloadingCacheBehavior include DependenciesTestHelpers def test_simple_autoloading with_autoloading_fixtures do - @cache.write('foo', E.new) + @cache.write('foo', EM.new) end - remove_constants(:E) + remove_constants(:EM) ActiveSupport::Dependencies.clear with_autoloading_fixtures do - assert_kind_of E, @cache.read('foo') + assert_kind_of EM, @cache.read('foo') end - remove_constants(:E) + remove_constants(:EM) ActiveSupport::Dependencies.clear end def test_two_classes_autoloading with_autoloading_fixtures do - @cache.write('foo', [E.new, ClassFolder.new]) + @cache.write('foo', [EM.new, ClassFolder.new]) end - remove_constants(:E, :ClassFolder) + remove_constants(:EM, :ClassFolder) ActiveSupport::Dependencies.clear with_autoloading_fixtures do loaded = @cache.read('foo') assert_kind_of Array, loaded assert_equal 2, loaded.size - assert_kind_of E, loaded[0] + assert_kind_of EM, loaded[0] assert_kind_of ClassFolder, loaded[1] end - remove_constants(:E, :ClassFolder) + remove_constants(:EM, :ClassFolder) ActiveSupport::Dependencies.clear end end @@ -672,6 +704,7 @@ class FileStoreTest < ActiveSupport::TestCase def teardown FileUtils.rm_r(cache_dir) + rescue Errno::ENOENT end def cache_dir @@ -691,6 +724,11 @@ class FileStoreTest < ActiveSupport::TestCase assert File.exist?(filepath) end + def test_clear_without_cache_dir + FileUtils.rm_r(cache_dir) + @cache.clear + end + def test_long_keys @cache.write("a"*10000, 1) assert_equal 1, @cache.read("a"*10000) @@ -747,9 +785,10 @@ class FileStoreTest < ActiveSupport::TestCase end def test_log_exception_when_cache_read_fails - File.expects(:exist?).raises(StandardError, "failed") - @cache.send(:read_entry, "winston", {}) - assert @buffer.string.present? + File.stub(:exist?, -> { raise StandardError.new("failed") }) do + @cache.send(:read_entry, "winston", {}) + assert @buffer.string.present? + end end def test_cleanup_removes_all_expired_entries @@ -757,11 +796,12 @@ class FileStoreTest < ActiveSupport::TestCase @cache.write('foo', 'bar', expires_in: 10) @cache.write('baz', 'qux') @cache.write('quux', 'corge', expires_in: 20) - Time.stubs(:now).returns(time + 15) - @cache.cleanup - assert_not @cache.exist?('foo') - assert @cache.exist?('baz') - assert @cache.exist?('quux') + Time.stub(:now, time + 15) do + @cache.cleanup + assert_not @cache.exist?('foo') + assert @cache.exist?('baz') + assert @cache.exist?('quux') + end end def test_write_with_unless_exist @@ -998,10 +1038,6 @@ class NullStoreTest < ActiveSupport::TestCase end assert_nil @cache.read("name") end - - def test_setting_nil_cache_store - assert ActiveSupport::Cache.lookup_store.class.name, ActiveSupport::Cache::NullStore.name - end end class CacheStoreLoggerTest < ActiveSupport::TestCase @@ -1028,7 +1064,7 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase @cache.read_multi('hello', 'world') - assert_match "Caches multi read:\n- hello\n- world", @buffer.string.tap { |l| p l } + assert_match "Caches multi read:\n- hello\n- world", @buffer.string end end @@ -1038,9 +1074,9 @@ class CacheEntryTest < ActiveSupport::TestCase assert !entry.expired?, 'entry not expired' entry = ActiveSupport::Cache::Entry.new("value", :expires_in => 60) assert !entry.expired?, 'entry not expired' - time = Time.now + 61 - Time.stubs(:now).returns(time) - assert entry.expired?, 'entry is expired' + Time.stub(:now, Time.now + 61) do + assert entry.expired?, 'entry is expired' + end end def test_compress_values diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index f6abef8cee..cda9732cae 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -73,8 +73,8 @@ module CallbacksTest class PersonSkipper < Person skip_callback :save, :before, :before_save_method, :if => :yes - skip_callback :save, :after, :before_save_method, :unless => :yes - skip_callback :save, :after, :before_save_method, :if => :no + skip_callback :save, :after, :after_save_method, :unless => :yes + skip_callback :save, :after, :after_save_method, :if => :no skip_callback :save, :before, :before_save_method, :unless => :no skip_callback :save, :before, CallbackClass , :if => :yes def yes; true; end @@ -1021,7 +1021,7 @@ module CallbacksTest define_callbacks :foo n.times { set_callback :foo, :before, callback } def run; run_callbacks :foo; end - def self.skip(thing); skip_callback :foo, :before, thing; end + def self.skip(*things); skip_callback :foo, :before, *things; end } end @@ -1070,11 +1070,11 @@ module CallbacksTest } end - def test_skip_lambda # removes nothing + def test_skip_lambda # raises error calls = [] callback = ->(o) { calls << o } klass = build_class(callback) - 10.times { klass.skip callback } + assert_raises(ArgumentError) { klass.skip callback } klass.new.run assert_equal 10, calls.length end @@ -1088,11 +1088,29 @@ module CallbacksTest assert_equal 0, calls.length end - def test_skip_eval # removes nothing + def test_skip_string # raises error calls = [] klass = build_class("bar") klass.class_eval { define_method(:bar) { calls << klass } } - klass.skip "bar" + assert_raises(ArgumentError) { klass.skip "bar" } + klass.new.run + assert_equal 1, calls.length + end + + def test_skip_undefined_callback # raises error + calls = [] + klass = build_class(:bar) + klass.class_eval { define_method(:bar) { calls << klass } } + assert_raises(ArgumentError) { klass.skip :qux } + klass.new.run + assert_equal 1, calls.length + end + + def test_skip_without_raise # removes nothing + calls = [] + klass = build_class(:bar) + klass.class_eval { define_method(:bar) { calls << klass } } + klass.skip :qux, raise: false klass.new.run assert_equal 1, calls.length end diff --git a/activesupport/test/concern_test.rb b/activesupport/test/concern_test.rb index 253c1adc23..8ea701cfb7 100644 --- a/activesupport/test/concern_test.rb +++ b/activesupport/test/concern_test.rb @@ -54,6 +54,11 @@ class ConcernTest < ActiveSupport::TestCase include Bar, Baz end + module Qux + module ClassMethods + end + end + def setup @klass = Class.new end @@ -70,6 +75,26 @@ class ConcernTest < ActiveSupport::TestCase assert_equal ConcernTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0] end + def test_class_methods_are_extended_only_on_expected_objects + ::Object.__send__(:include, Qux) + Object.extend(Qux::ClassMethods) + # module needs to be created after Qux is included in Object or bug won't + # be triggered + test_module = Module.new do + extend ActiveSupport::Concern + + class_methods do + def test + end + end + end + @klass.include test_module + assert_equal false, Object.respond_to?(:test) + Qux.class_eval do + remove_const :ClassMethods + end + end + def test_included_block_is_ran @klass.include(Baz) assert_equal true, @klass.included_ran diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb index 366e4e5ef0..1115bc0fd8 100644 --- a/activesupport/test/constantize_test_cases.rb +++ b/activesupport/test/constantize_test_cases.rb @@ -100,6 +100,10 @@ module ConstantizeTestCases assert_nil yield("Ace::Gas::ConstantizeTestCases") assert_nil yield("#<Class:0x7b8b718b>::Nested_1") assert_nil yield("Ace::gas") + assert_nil yield('Object::ABC') + assert_nil yield('Object::Object::Object::ABC') + assert_nil yield('A::Object::B') + assert_nil yield('A::Object::Object::Object::B') assert_raises(NameError) do with_autoloading_fixtures do diff --git a/activesupport/test/core_ext/array/access_test.rb b/activesupport/test/core_ext/array/access_test.rb index f14f64421d..3f1e0c4cb4 100644 --- a/activesupport/test/core_ext/array/access_test.rb +++ b/activesupport/test/core_ext/array/access_test.rb @@ -27,4 +27,8 @@ class AccessTest < ActiveSupport::TestCase assert_equal array[4], array.fifth assert_equal array[41], array.forty_two end + + def test_without + assert_equal [1, 2, 4], [1, 2, 3, 4, 5].without(3, 5) + end end diff --git a/activesupport/test/core_ext/array/conversions_test.rb b/activesupport/test/core_ext/array/conversions_test.rb index 577b889410..507e13f968 100644 --- a/activesupport/test/core_ext/array/conversions_test.rb +++ b/activesupport/test/core_ext/array/conversions_test.rb @@ -60,6 +60,12 @@ class ToSentenceTest < ActiveSupport::TestCase assert_equal exception.message, "Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale" end + + def test_always_returns_string + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one')].to_sentence + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one'), 'two'].to_sentence + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one'), 'two', 'three'].to_sentence + end end class ToSTest < ActiveSupport::TestCase diff --git a/activesupport/test/core_ext/class/delegating_attributes_test.rb b/activesupport/test/core_ext/class/delegating_attributes_test.rb deleted file mode 100644 index 447b1d10ad..0000000000 --- a/activesupport/test/core_ext/class/delegating_attributes_test.rb +++ /dev/null @@ -1,122 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/class/delegating_attributes' - -module DelegatingFixtures - class Parent - end - - class Child < Parent - ActiveSupport::Deprecation.silence do - superclass_delegating_accessor :some_attribute - end - end - - class Mokopuna < Child - end - - class PercysMom - ActiveSupport::Deprecation.silence do - superclass_delegating_accessor :superpower - end - end - - class Percy < PercysMom - end -end - -class DelegatingAttributesTest < ActiveSupport::TestCase - include DelegatingFixtures - attr_reader :single_class - - def setup - @single_class = Class.new(Object) - end - - def test_simple_accessor_declaration - assert_deprecated do - single_class.superclass_delegating_accessor :both - end - - # Class should have accessor and mutator - # the instance should have an accessor only - assert_respond_to single_class, :both - assert_respond_to single_class, :both= - assert single_class.public_instance_methods.map(&:to_s).include?("both") - assert !single_class.public_instance_methods.map(&:to_s).include?("both=") - end - - def test_simple_accessor_declaration_with_instance_reader_false - _instance_methods = single_class.public_instance_methods - - assert_deprecated do - single_class.superclass_delegating_accessor :no_instance_reader, :instance_reader => false - end - - assert_respond_to single_class, :no_instance_reader - assert_respond_to single_class, :no_instance_reader= - assert !_instance_methods.include?(:no_instance_reader) - assert !_instance_methods.include?(:no_instance_reader?) - assert !_instance_methods.include?(:_no_instance_reader) - end - - def test_working_with_simple_attributes - assert_deprecated do - single_class.superclass_delegating_accessor :both - end - - single_class.both = "HMMM" - - assert_equal "HMMM", single_class.both - assert_equal true, single_class.both? - - assert_equal "HMMM", single_class.new.both - assert_equal true, single_class.new.both? - - single_class.both = false - assert_equal false, single_class.both? - end - - def test_child_class_delegates_to_parent_but_can_be_overridden - parent = Class.new - - assert_deprecated do - parent.superclass_delegating_accessor :both - end - - child = Class.new(parent) - parent.both = "1" - assert_equal "1", child.both - - child.both = "2" - assert_equal "1", parent.both - assert_equal "2", child.both - - parent.both = "3" - assert_equal "3", parent.both - assert_equal "2", child.both - end - - def test_delegation_stops_at_the_right_level - assert_nil Percy.superpower - assert_nil PercysMom.superpower - - PercysMom.superpower = :heatvision - assert_equal :heatvision, Percy.superpower - end - - def test_delegation_stops_for_nil - Mokopuna.some_attribute = nil - Child.some_attribute="1" - - assert_equal "1", Child.some_attribute - assert_nil Mokopuna.some_attribute - ensure - Child.some_attribute=nil - end - - def test_deprecation_warning - assert_deprecated(/superclass_delegating_accessor is deprecated/) do - single_class.superclass_delegating_accessor :test_attribute - end - end -end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index e89be25b53..0fc3f765f5 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -191,8 +191,9 @@ class DateExtCalculationsTest < ActiveSupport::TestCase def test_yesterday_constructor_when_zone_is_set with_env_tz 'UTC' do with_tz_default ActiveSupport::TimeZone['Eastern Time (US & Canada)'] do # UTC -5 - Time.stubs(:now).returns Time.local(2000, 1, 1) - assert_equal Date.new(1999, 12, 30), Date.yesterday + Time.stub(:now, Time.local(2000, 1, 1)) do + assert_equal Date.new(1999, 12, 30), Date.yesterday + end end end end @@ -212,8 +213,9 @@ class DateExtCalculationsTest < ActiveSupport::TestCase def test_tomorrow_constructor_when_zone_is_set with_env_tz 'UTC' do with_tz_default ActiveSupport::TimeZone['Europe/Paris'] do # UTC +1 - Time.stubs(:now).returns Time.local(1999, 12, 31, 23) - assert_equal Date.new(2000, 1, 2), Date.tomorrow + Time.stub(:now, Time.local(1999, 12, 31, 23)) do + assert_equal Date.new(2000, 1, 2), Date.tomorrow + end end end end @@ -317,23 +319,26 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end def test_past - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal true, Date.new(1999, 12, 31).past? - assert_equal false, Date.new(2000,1,1).past? - assert_equal false, Date.new(2000,1,2).past? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal true, Date.new(1999, 12, 31).past? + assert_equal false, Date.new(2000,1,1).past? + assert_equal false, Date.new(2000,1,2).past? + end end def test_future - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Date.new(1999, 12, 31).future? - assert_equal false, Date.new(2000,1,1).future? - assert_equal true, Date.new(2000,1,2).future? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Date.new(1999, 12, 31).future? + assert_equal false, Date.new(2000,1,1).future? + assert_equal true, Date.new(2000,1,2).future? + end end def test_current_returns_date_today_when_zone_not_set with_env_tz 'US/Central' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23) - assert_equal Date.today, Date.current + Time.stub(:now, Time.local(1999, 12, 31, 23)) do + assert_equal Date.today, Date.current + end end end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 74319ecd09..6fe38c45ec 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -204,61 +204,69 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase end def test_today_with_offset - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, DateTime.civil(1999,12,31,23,59,59, Rational(-18000, 86400)).today? - assert_equal true, DateTime.civil(2000,1,1,0,0,0, Rational(-18000, 86400)).today? - assert_equal true, DateTime.civil(2000,1,1,23,59,59, Rational(-18000, 86400)).today? - assert_equal false, DateTime.civil(2000,1,2,0,0,0, Rational(-18000, 86400)).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, DateTime.civil(1999,12,31,23,59,59, Rational(-18000, 86400)).today? + assert_equal true, DateTime.civil(2000,1,1,0,0,0, Rational(-18000, 86400)).today? + assert_equal true, DateTime.civil(2000,1,1,23,59,59, Rational(-18000, 86400)).today? + assert_equal false, DateTime.civil(2000,1,2,0,0,0, Rational(-18000, 86400)).today? + end end def test_today_without_offset - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, DateTime.civil(1999,12,31,23,59,59).today? - assert_equal true, DateTime.civil(2000,1,1,0).today? - assert_equal true, DateTime.civil(2000,1,1,23,59,59).today? - assert_equal false, DateTime.civil(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, DateTime.civil(1999,12,31,23,59,59).today? + assert_equal true, DateTime.civil(2000,1,1,0).today? + assert_equal true, DateTime.civil(2000,1,1,23,59,59).today? + assert_equal false, DateTime.civil(2000,1,2,0).today? + end end def test_past_with_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal true, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).past? - assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).past? - assert_equal false, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).past? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal true, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).past? + assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).past? + assert_equal false, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).past? + end end def test_past_without_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal true, DateTime.civil(2005,2,10,20,30,44).past? - assert_equal false, DateTime.civil(2005,2,10,20,30,45).past? - assert_equal false, DateTime.civil(2005,2,10,20,30,46).past? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal true, DateTime.civil(2005,2,10,20,30,44).past? + assert_equal false, DateTime.civil(2005,2,10,20,30,45).past? + assert_equal false, DateTime.civil(2005,2,10,20,30,46).past? + end end def test_future_with_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal false, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).future? - assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).future? - assert_equal true, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).future? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal false, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).future? + assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).future? + assert_equal true, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).future? + end end def test_future_without_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal false, DateTime.civil(2005,2,10,20,30,44).future? - assert_equal false, DateTime.civil(2005,2,10,20,30,45).future? - assert_equal true, DateTime.civil(2005,2,10,20,30,46).future? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal false, DateTime.civil(2005,2,10,20,30,44).future? + assert_equal false, DateTime.civil(2005,2,10,20,30,45).future? + assert_equal true, DateTime.civil(2005,2,10,20,30,46).future? + end end def test_current_returns_date_today_when_zone_is_not_set with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23, 59, 59) - assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + Time.stub(:now, Time.local(1999, 12, 31, 23, 59, 59)) do + assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + end end end def test_current_returns_time_zone_today_when_zone_is_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23, 59, 59) - assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + Time.stub(:now, Time.local(1999, 12, 31, 23, 59, 59)) do + assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + end end ensure Time.zone = nil @@ -335,6 +343,13 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal(-1, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 1), ActiveSupport::TimeZone['UTC'] )) end + def test_compare_with_string + assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59).to_s + assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0).to_s + assert_equal( -1, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1).to_s) + assert_equal nil, DateTime.civil(2000) <=> "Invalid as Time" + end + def test_to_f assert_equal 946684800.0, DateTime.civil(2000).to_f assert_equal 946684800.0, DateTime.civil(1999,12,31,19,0,0,Rational(-5,24)).to_f diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index c283b546e6..9e97acaffb 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -140,28 +140,30 @@ class DurationTest < ActiveSupport::TestCase def test_since_and_ago_anchored_to_time_now_when_time_zone_is_not_set Time.zone = nil with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - # since - assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.since - assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since - # ago - assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago - assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago + Time.stub(:now, Time.local(2000)) do + # since + assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.since + assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since + # ago + assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago + assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago + end end end def test_since_and_ago_anchored_to_time_zone_now_when_time_zone_is_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - # since - assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.since - assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time - assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name - # ago - assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago - assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time - assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name + Time.stub(:now, Time.local(2000)) do + # since + assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.since + assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time + assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name + # ago + assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago + assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time + assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name + end end ensure Time.zone = nil diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 346dc3d208..f09b7d8850 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -3,6 +3,8 @@ require 'active_support/core_ext/array' require 'active_support/core_ext/enumerable' Payment = Struct.new(:price) +ExpandedPayment = Struct.new(:dollars, :cents) + class SummablePayment < Payment def +(p) self.class.new(price + p.price) end end @@ -103,4 +105,23 @@ class EnumerableTests < ActiveSupport::TestCase assert_equal true, GenericEnumerable.new([ 1 ]).exclude?(2) assert_equal false, GenericEnumerable.new([ 1 ]).exclude?(1) end + + def test_without + assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).without(3, 5) + assert_equal [1, 2, 4], (1..5).to_a.without(3, 5) + assert_equal [1, 2, 4], (1..5).to_set.without(3, 5) + assert_equal({foo: 1, baz: 3}, {foo: 1, bar: 2, baz: 3}.without(:bar)) + end + + def test_pluck + payments = GenericEnumerable.new([ Payment.new(5), Payment.new(15), Payment.new(10) ]) + assert_equal [5, 15, 10], payments.pluck(:price) + + payments = GenericEnumerable.new([ + ExpandedPayment.new(5, 99), + ExpandedPayment.new(15, 0), + ExpandedPayment.new(10, 50) + ]) + assert_equal [[5, 99], [15, 0], [10, 50]], payments.pluck(:dollars, :cents) + end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index e10bee5e00..4624338df1 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -524,6 +524,10 @@ class HashExtTest < ActiveSupport::TestCase end def test_indifferent_reverse_merging + hash = HashWithIndifferentAccess.new key: :old_value + hash.reverse_merge! key: :new_value + assert_equal :old_value, hash[:key] + hash = HashWithIndifferentAccess.new('some' => 'value', 'other' => 'value') hash.reverse_merge!(:some => 'noclobber', :another => 'clobber') assert_equal 'value', hash[:some] @@ -547,6 +551,11 @@ class HashExtTest < ActiveSupport::TestCase assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash end + def test_indifferent_select_returns_enumerator + enum = ActiveSupport::HashWithIndifferentAccess.new(@strings).select + assert_instance_of Enumerator, enum + end + def test_indifferent_select_returns_a_hash_when_unchanged hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).select {|k,v| true} @@ -568,6 +577,11 @@ class HashExtTest < ActiveSupport::TestCase assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash end + def test_indifferent_reject_returns_enumerator + enum = ActiveSupport::HashWithIndifferentAccess.new(@strings).reject + assert_instance_of Enumerator, enum + end + def test_indifferent_reject_bang indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@strings) indifferent_strings.reject! {|k,v| v != 1} @@ -961,10 +975,11 @@ class HashExtTest < ActiveSupport::TestCase assert_raise(RuntimeError) { original.except!(:a) } end - def test_except_with_mocha_expectation_on_original + def test_except_does_not_delete_values_in_original original = { :a => 'x', :b => 'y' } - original.expects(:delete).never - original.except(:a) + assert_not_called(original, :delete) do + original.except(:a) + end end def test_compact @@ -998,6 +1013,37 @@ class HashExtTest < ActiveSupport::TestCase assert hash.key?('a') assert_equal 1, hash[:a] end + + def test_dup_with_default_proc + hash = HashWithIndifferentAccess.new + hash.default_proc = proc { |h, v| raise "walrus" } + assert_nothing_raised { hash.dup } + end + + def test_dup_with_default_proc_sets_proc + hash = HashWithIndifferentAccess.new + hash.default_proc = proc { |h, k| k + 1 } + new_hash = hash.dup + + assert_equal 3, new_hash[2] + + new_hash.default = 2 + assert_equal 2, new_hash[:non_existant] + end + + def test_to_hash_with_raising_default_proc + hash = HashWithIndifferentAccess.new + hash.default_proc = proc { |h, k| raise "walrus" } + + assert_nothing_raised { hash.to_hash } + end + + def test_new_from_hash_copying_default_should_not_raise_when_default_proc_does + hash = Hash.new + hash.default_proc = proc { |h, k| raise "walrus" } + + assert_nothing_raised { HashWithIndifferentAccess.new_from_hash_copying_default(hash) } + end end class IWriteMyOwnXML diff --git a/activesupport/test/core_ext/marshal_test.rb b/activesupport/test/core_ext/marshal_test.rb index 8f3f710dfd..825df439a5 100644 --- a/activesupport/test/core_ext/marshal_test.rb +++ b/activesupport/test/core_ext/marshal_test.rb @@ -8,28 +8,28 @@ class MarshalTest < ActiveSupport::TestCase def teardown ActiveSupport::Dependencies.clear - remove_constants(:E, :ClassFolder) + remove_constants(:EM, :ClassFolder) end test "that Marshal#load still works" do sanity_data = ["test", [1, 2, 3], {a: [1, 2, 3]}, ActiveSupport::TestCase] sanity_data.each do |obj| dumped = Marshal.dump(obj) - assert_equal Marshal.load_without_autoloading(dumped), Marshal.load(dumped) + assert_equal Marshal.method(:load).super_method.call(dumped), Marshal.load(dumped) end end test "that a missing class is autoloaded from string" do dumped = nil with_autoloading_fixtures do - dumped = Marshal.dump(E.new) + dumped = Marshal.dump(EM.new) end - remove_constants(:E) + remove_constants(:EM) ActiveSupport::Dependencies.clear with_autoloading_fixtures do - assert_kind_of E, Marshal.load(dumped) + assert_kind_of EM, Marshal.load(dumped) end end @@ -50,16 +50,16 @@ class MarshalTest < ActiveSupport::TestCase test "that more than one missing class is autoloaded" do dumped = nil with_autoloading_fixtures do - dumped = Marshal.dump([E.new, ClassFolder.new]) + dumped = Marshal.dump([EM.new, ClassFolder.new]) end - remove_constants(:E, :ClassFolder) + remove_constants(:EM, :ClassFolder) ActiveSupport::Dependencies.clear with_autoloading_fixtures do loaded = Marshal.load(dumped) assert_equal 2, loaded.size - assert_kind_of E, loaded[0] + assert_kind_of EM, loaded[0] assert_kind_of ClassFolder, loaded[1] end end @@ -67,10 +67,10 @@ class MarshalTest < ActiveSupport::TestCase test "that a real missing class is causing an exception" do dumped = nil with_autoloading_fixtures do - dumped = Marshal.dump(E.new) + dumped = Marshal.dump(EM.new) end - remove_constants(:E) + remove_constants(:EM) ActiveSupport::Dependencies.clear assert_raise(NameError) do @@ -84,10 +84,10 @@ class MarshalTest < ActiveSupport::TestCase end with_autoloading_fixtures do - dumped = Marshal.dump([E.new, SomeClass.new]) + dumped = Marshal.dump([EM.new, SomeClass.new]) end - remove_constants(:E) + remove_constants(:EM) self.class.send(:remove_const, :SomeClass) ActiveSupport::Dependencies.clear @@ -96,8 +96,8 @@ class MarshalTest < ActiveSupport::TestCase Marshal.load(dumped) end - assert_nothing_raised("E failed to load while we expect only SomeClass to fail loading") do - E.new + assert_nothing_raised("EM failed to load while we expect only SomeClass to fail loading") do + EM.new end assert_raise(NameError, "We expected SomeClass to not be loaded but it is!") do @@ -109,16 +109,16 @@ class MarshalTest < ActiveSupport::TestCase test "loading classes from files trigger autoloading" do Tempfile.open("object_serializer_test") do |f| with_autoloading_fixtures do - Marshal.dump(E.new, f) + Marshal.dump(EM.new, f) end f.rewind - remove_constants(:E) + remove_constants(:EM) ActiveSupport::Dependencies.clear with_autoloading_fixtures do - assert_kind_of E, Marshal.load(f) + assert_kind_of EM, Marshal.load(f) end end end -end
\ No newline at end of file +end diff --git a/activesupport/test/core_ext/module/attribute_accessor_test.rb b/activesupport/test/core_ext/module/attribute_accessor_test.rb index 48f3cc579f..128c5e3d1a 100644 --- a/activesupport/test/core_ext/module/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/module/attribute_accessor_test.rb @@ -76,4 +76,10 @@ class ModuleAttributeAccessorTest < ActiveSupport::TestCase assert_equal 'default_reader_value', @module.defr assert_equal 'default_writer_value', @module.class_variable_get('@@defw') end + + def test_should_not_invoke_default_value_block_multiple_times + count = 0 + @module.cattr_accessor(:defcount){ count += 1 } + assert_equal 1, count + end end diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index c9c9b66a6c..bdfbadcf1d 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -358,148 +358,178 @@ class MethodAliasingTest < ActiveSupport::TestCase Object.instance_eval { remove_const :FooClassWithBarMethod } end - def test_alias_method_chain - assert @instance.respond_to?(:bar) - feature_aliases = [:bar_with_baz, :bar_without_baz] + def test_alias_method_chain_deprecated + assert_deprecated(/alias_method_chain/) do + Module.new do + def base + end + + def base_with_deprecated + end - feature_aliases.each do |method| - assert !@instance.respond_to?(method) + alias_method_chain :base, :deprecated + end end + end - assert_equal 'bar', @instance.bar + def test_alias_method_chain + assert_deprecated(/alias_method_chain/) do + assert @instance.respond_to?(:bar) + feature_aliases = [:bar_with_baz, :bar_without_baz] - FooClassWithBarMethod.class_eval { include BarMethodAliaser } + feature_aliases.each do |method| + assert !@instance.respond_to?(method) + end - feature_aliases.each do |method| - assert_respond_to @instance, method - end + assert_equal 'bar', @instance.bar + + FooClassWithBarMethod.class_eval { include BarMethodAliaser } + + feature_aliases.each do |method| + assert_respond_to @instance, method + end - assert_equal 'bar_with_baz', @instance.bar - assert_equal 'bar', @instance.bar_without_baz + assert_equal 'bar_with_baz', @instance.bar + assert_equal 'bar', @instance.bar_without_baz + end end def test_alias_method_chain_with_punctuation_method - FooClassWithBarMethod.class_eval do - def quux!; 'quux' end - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux!; 'quux' end + end - assert !@instance.respond_to?(:quux_with_baz!) - FooClassWithBarMethod.class_eval do - include BarMethodAliaser - alias_method_chain :quux!, :baz - end - assert_respond_to @instance, :quux_with_baz! + assert !@instance.respond_to?(:quux_with_baz!) + FooClassWithBarMethod.class_eval do + include BarMethodAliaser + alias_method_chain :quux!, :baz + end + assert_respond_to @instance, :quux_with_baz! - assert_equal 'quux_with_baz', @instance.quux! - assert_equal 'quux', @instance.quux_without_baz! + assert_equal 'quux_with_baz', @instance.quux! + assert_equal 'quux', @instance.quux_without_baz! + end end def test_alias_method_chain_with_same_names_between_predicates_and_bang_methods - FooClassWithBarMethod.class_eval do - def quux!; 'quux!' end - def quux?; true end - def quux=(v); 'quux=' end - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux!; 'quux!' end + def quux?; true end + def quux=(v); 'quux=' end + end - assert !@instance.respond_to?(:quux_with_baz!) - assert !@instance.respond_to?(:quux_with_baz?) - assert !@instance.respond_to?(:quux_with_baz=) + assert !@instance.respond_to?(:quux_with_baz!) + assert !@instance.respond_to?(:quux_with_baz?) + assert !@instance.respond_to?(:quux_with_baz=) - FooClassWithBarMethod.class_eval { include BarMethodAliaser } - assert_respond_to @instance, :quux_with_baz! - assert_respond_to @instance, :quux_with_baz? - assert_respond_to @instance, :quux_with_baz= + FooClassWithBarMethod.class_eval { include BarMethodAliaser } + assert_respond_to @instance, :quux_with_baz! + assert_respond_to @instance, :quux_with_baz? + assert_respond_to @instance, :quux_with_baz= - FooClassWithBarMethod.alias_method_chain :quux!, :baz - assert_equal 'quux!_with_baz', @instance.quux! - assert_equal 'quux!', @instance.quux_without_baz! + FooClassWithBarMethod.alias_method_chain :quux!, :baz + assert_equal 'quux!_with_baz', @instance.quux! + assert_equal 'quux!', @instance.quux_without_baz! - FooClassWithBarMethod.alias_method_chain :quux?, :baz - assert_equal false, @instance.quux? - assert_equal true, @instance.quux_without_baz? + FooClassWithBarMethod.alias_method_chain :quux?, :baz + assert_equal false, @instance.quux? + assert_equal true, @instance.quux_without_baz? - FooClassWithBarMethod.alias_method_chain :quux=, :baz - assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234) - assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234) + FooClassWithBarMethod.alias_method_chain :quux=, :baz + assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234) + assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234) + end end def test_alias_method_chain_with_feature_punctuation - FooClassWithBarMethod.class_eval do - def quux; 'quux' end - def quux?; 'quux?' end - include BarMethodAliaser - alias_method_chain :quux, :baz! - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux; 'quux' end + def quux?; 'quux?' end + include BarMethodAliaser + alias_method_chain :quux, :baz! + end - assert_nothing_raised do - assert_equal 'quux_with_baz', @instance.quux_with_baz! - end + assert_nothing_raised do + assert_equal 'quux_with_baz', @instance.quux_with_baz! + end - assert_raise(NameError) do - FooClassWithBarMethod.alias_method_chain :quux?, :baz! + assert_raise(NameError) do + FooClassWithBarMethod.alias_method_chain :quux?, :baz! + end end end def test_alias_method_chain_yields_target_and_punctuation - args = nil + assert_deprecated(/alias_method_chain/) do + args = nil - FooClassWithBarMethod.class_eval do - def quux?; end - include BarMethods + FooClassWithBarMethod.class_eval do + def quux?; end + include BarMethods - FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation| - args = [target, punctuation] + FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation| + args = [target, punctuation] + end end - end - assert_not_nil args - assert_equal 'quux', args[0] - assert_equal '?', args[1] + assert_not_nil args + assert_equal 'quux', args[0] + assert_equal '?', args[1] + end end def test_alias_method_chain_preserves_private_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - private :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + private :duck + alias_method_chain :duck, :orange + end - assert_raise NoMethodError do - @instance.duck - end + assert_raise NoMethodError do + @instance.duck + end - assert_equal 'duck_with_orange', @instance.instance_eval { duck } - assert FooClassWithBarMethod.private_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.instance_eval { duck } + assert FooClassWithBarMethod.private_method_defined?(:duck) + end end def test_alias_method_chain_preserves_protected_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - protected :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + protected :duck + alias_method_chain :duck, :orange + end - assert_raise NoMethodError do - @instance.duck - end + assert_raise NoMethodError do + @instance.duck + end - assert_equal 'duck_with_orange', @instance.instance_eval { duck } - assert FooClassWithBarMethod.protected_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.instance_eval { duck } + assert FooClassWithBarMethod.protected_method_defined?(:duck) + end end def test_alias_method_chain_preserves_public_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - public :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + public :duck + alias_method_chain :duck, :orange + end - assert_equal 'duck_with_orange', @instance.duck - assert FooClassWithBarMethod.public_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.duck + assert FooClassWithBarMethod.public_method_defined?(:duck) + end end def test_delegate_with_case diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb index b82448458d..0ff8f0f89b 100644 --- a/activesupport/test/core_ext/numeric_ext_test.rb +++ b/activesupport/test/core_ext/numeric_ext_test.rb @@ -280,14 +280,16 @@ class NumericExtFormattingTest < ActiveSupport::TestCase end def test_to_s__human_size_with_si_prefix - assert_equal '3 Bytes', 3.14159265.to_s(:human_size, :prefix => :si) - assert_equal '123 Bytes', 123.0.to_s(:human_size, :prefix => :si) - assert_equal '123 Bytes', 123.to_s(:human_size, :prefix => :si) - assert_equal '1.23 KB', 1234.to_s(:human_size, :prefix => :si) - assert_equal '12.3 KB', 12345.to_s(:human_size, :prefix => :si) - assert_equal '1.23 MB', 1234567.to_s(:human_size, :prefix => :si) - assert_equal '1.23 GB', 1234567890.to_s(:human_size, :prefix => :si) - assert_equal '1.23 TB', 1234567890123.to_s(:human_size, :prefix => :si) + assert_deprecated do + assert_equal '3 Bytes', 3.14159265.to_s(:human_size, :prefix => :si) + assert_equal '123 Bytes', 123.0.to_s(:human_size, :prefix => :si) + assert_equal '123 Bytes', 123.to_s(:human_size, :prefix => :si) + assert_equal '1.23 KB', 1234.to_s(:human_size, :prefix => :si) + assert_equal '12.3 KB', 12345.to_s(:human_size, :prefix => :si) + assert_equal '1.23 MB', 1234567.to_s(:human_size, :prefix => :si) + assert_equal '1.23 GB', 1234567890.to_s(:human_size, :prefix => :si) + assert_equal '1.23 TB', 1234567890123.to_s(:human_size, :prefix => :si) + end end def test_to_s__human_size_with_options_hash @@ -389,4 +391,88 @@ class NumericExtFormattingTest < ActiveSupport::TestCase def test_in_milliseconds assert_equal 10_000, 10.seconds.in_milliseconds end + + # TODO: Remove positive and negative tests when we drop support to ruby < 2.3 + b = 2**64 + b *= b until Bignum === b + + T_ZERO = b.coerce(0).first + T_ONE = b.coerce(1).first + T_MONE = b.coerce(-1).first + + def test_positive + assert_predicate(1, :positive?) + assert_not_predicate(0, :positive?) + assert_not_predicate(-1, :positive?) + assert_predicate(+1.0, :positive?) + assert_not_predicate(+0.0, :positive?) + assert_not_predicate(-0.0, :positive?) + assert_not_predicate(-1.0, :positive?) + assert_predicate(+(0.0.next_float), :positive?) + assert_not_predicate(-(0.0.next_float), :positive?) + assert_predicate(Float::INFINITY, :positive?) + assert_not_predicate(-Float::INFINITY, :positive?) + assert_not_predicate(Float::NAN, :positive?) + + a = Class.new(Numeric) do + def >(x); true; end + end.new + assert_predicate(a, :positive?) + + a = Class.new(Numeric) do + def >(x); false; end + end.new + assert_not_predicate(a, :positive?) + + assert_predicate(1/2r, :positive?) + assert_not_predicate(-1/2r, :positive?) + + assert_predicate(T_ONE, :positive?) + assert_not_predicate(T_MONE, :positive?) + assert_not_predicate(T_ZERO, :positive?) + + e = assert_raises(NoMethodError) do + Complex(1).positive? + end + + assert_match(/positive\?/, e.message) + end + + def test_negative + assert_predicate(-1, :negative?) + assert_not_predicate(0, :negative?) + assert_not_predicate(1, :negative?) + assert_predicate(-1.0, :negative?) + assert_not_predicate(-0.0, :negative?) + assert_not_predicate(+0.0, :negative?) + assert_not_predicate(+1.0, :negative?) + assert_predicate(-(0.0.next_float), :negative?) + assert_not_predicate(+(0.0.next_float), :negative?) + assert_predicate(-Float::INFINITY, :negative?) + assert_not_predicate(Float::INFINITY, :negative?) + assert_not_predicate(Float::NAN, :negative?) + + a = Class.new(Numeric) do + def <(x); true; end + end.new + assert_predicate(a, :negative?) + + a = Class.new(Numeric) do + def <(x); false; end + end.new + assert_not_predicate(a, :negative?) + + assert_predicate(-1/2r, :negative?) + assert_not_predicate(1/2r, :negative?) + + assert_not_predicate(T_ONE, :negative?) + assert_predicate(T_MONE, :negative?) + assert_not_predicate(T_ZERO, :negative?) + + e = assert_raises(NoMethodError) do + Complex(1).negative? + end + + assert_match(/negative\?/, e.message) + end end diff --git a/activesupport/test/core_ext/object/deep_dup_test.rb b/activesupport/test/core_ext/object/deep_dup_test.rb index 91d558dbb5..791b5e7172 100644 --- a/activesupport/test/core_ext/object/deep_dup_test.rb +++ b/activesupport/test/core_ext/object/deep_dup_test.rb @@ -50,4 +50,10 @@ class DeepDupTest < ActiveSupport::TestCase assert dup.instance_variable_defined?(:@a) end + def test_deep_dup_with_hash_class_key + hash = { Fixnum => 1 } + dup = hash.deep_dup + assert_equal 1, dup.keys.length + end + end diff --git a/activesupport/test/core_ext/object/duplicable_test.rb b/activesupport/test/core_ext/object/duplicable_test.rb index d37f4bd0d8..042f5cfb34 100644 --- a/activesupport/test/core_ext/object/duplicable_test.rb +++ b/activesupport/test/core_ext/object/duplicable_test.rb @@ -9,6 +9,9 @@ class DuplicableTest < ActiveSupport::TestCase ALLOW_DUP << BigDecimal.new('4.56') def test_duplicable + rubinius_skip "* Method#dup is allowed at the moment on Rubinius\n" \ + "* https://github.com/rubinius/rubinius/issues/3089" + RAISE_DUP.each do |v| assert !v.duplicable? assert_raises(TypeError, v.class.name) { v.dup } diff --git a/activesupport/test/core_ext/object/json_gem_encoding_test.rb b/activesupport/test/core_ext/object/json_gem_encoding_test.rb new file mode 100644 index 0000000000..02ab17fb64 --- /dev/null +++ b/activesupport/test/core_ext/object/json_gem_encoding_test.rb @@ -0,0 +1,66 @@ +require 'abstract_unit' +require 'json' +require 'json/encoding_test_cases' + +# These test cases were added to test that we do not interfere with json gem's +# output when the AS encoder is loaded, primarily for problems reported in +# #20775. They need to be executed in isolation to reproduce the scenario +# correctly, because other test cases might have already loaded additional +# dependencies. + +# The AS::JSON encoder requires the BigDecimal core_ext, which, unfortunately, +# changes the BigDecimal#to_s output, and consequently the JSON gem output. So +# we need to require this unfront to ensure we don't get a false failure, but +# ideally we should just fix the BigDecimal core_ext to not change to_s without +# arguments. +require 'active_support/core_ext/big_decimal' + +class JsonGemEncodingTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + JSONTest::EncodingTestCases.constants.each_with_index do |name| + JSONTest::EncodingTestCases.const_get(name).each_with_index do |(subject, _), i| + test("#{name[0..-6].underscore} #{i}") do + assert_same_with_or_without_active_support(subject) + end + end + end + + class CustomToJson + def to_json(*) + '"custom"' + end + end + + test "custom to_json" do + assert_same_with_or_without_active_support(CustomToJson.new) + end + + private + def require_or_skip(file) + require(file) || skip("'#{file}' was already loaded") + end + + def assert_same_with_or_without_active_support(subject) + begin + expected = JSON.generate(subject, quirks_mode: true) + rescue JSON::GeneratorError => e + exception = e + end + + require_or_skip 'active_support/core_ext/object/json' + + if exception + assert_raises_with_message JSON::GeneratorError, e.message do + JSON.generate(subject, quirks_mode: true) + end + else + assert_equal expected, JSON.generate(subject, quirks_mode: true) + end + end + + def assert_raises_with_message(exception_class, message, &block) + err = assert_raises(exception_class) { block.call } + assert_match message, err.message + end +end diff --git a/activesupport/test/core_ext/object/try_test.rb b/activesupport/test/core_ext/object/try_test.rb index 89438675c1..5ea0f0eca6 100644 --- a/activesupport/test/core_ext/object/try_test.rb +++ b/activesupport/test/core_ext/object/try_test.rb @@ -77,9 +77,9 @@ class ObjectTryTest < ActiveSupport::TestCase klass = Class.new do private - def private_method - 'private method' - end + def private_method + 'private method' + end end assert_raise(NoMethodError) { klass.new.try!(:private_method) } @@ -89,11 +89,75 @@ class ObjectTryTest < ActiveSupport::TestCase klass = Class.new do private - def private_method - 'private method' - end + def private_method + 'private method' + end end assert_nil klass.new.try(:private_method) end + + class Decorator < SimpleDelegator + def delegator_method + 'delegator method' + end + + def reverse + 'overridden reverse' + end + + private + + def private_delegator_method + 'private delegator method' + end + end + + def test_try_with_method_on_delegator + assert_equal 'delegator method', Decorator.new(@string).try(:delegator_method) + end + + def test_try_with_method_on_delegator_target + assert_equal 5, Decorator.new(@string).size + end + + def test_try_with_overriden_method_on_delegator + assert_equal 'overridden reverse', Decorator.new(@string).reverse + end + + def test_try_with_private_method_on_delegator + assert_nil Decorator.new(@string).try(:private_delegator_method) + end + + def test_try_with_private_method_on_delegator_bang + assert_raise(NoMethodError) do + Decorator.new(@string).try!(:private_delegator_method) + end + end + + def test_try_with_private_method_on_delegator_target + klass = Class.new do + private + + def private_method + 'private method' + end + end + + assert_nil Decorator.new(klass.new).try(:private_method) + end + + def test_try_with_private_method_on_delegator_target_bang + klass = Class.new do + private + + def private_method + 'private method' + end + end + + assert_raise(NoMethodError) do + Decorator.new(klass.new).try!(:private_method) + end + end end diff --git a/activesupport/test/core_ext/securerandom.rb b/activesupport/test/core_ext/secure_random_test.rb index dfacb7fe9f..dfacb7fe9f 100644 --- a/activesupport/test/core_ext/securerandom.rb +++ b/activesupport/test/core_ext/secure_random_test.rb diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index cb24147ab3..3a5d6df06d 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -435,117 +435,123 @@ class StringConversionsTest < ActiveSupport::TestCase def test_standard_time_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + end end end def test_standard_time_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + end end end def test_daylight_savings_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + end end end def test_daylight_savings_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + end end end def test_partial_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 6, 0), "10:00 -0100".to_time - assert_equal Time.utc(2012, 1, 1, 11, 0), "10:00 -0100".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 12, 0), "10:00 PDT".to_time - assert_equal Time.utc(2012, 1, 1, 17, 0), "10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 EST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 9, 0), "10:00 EDT".to_time - assert_equal Time.utc(2012, 1, 1, 14, 0), "10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 6, 0), "10:00 -0100".to_time + assert_equal Time.utc(2012, 1, 1, 11, 0), "10:00 -0100".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 12, 0), "10:00 PDT".to_time + assert_equal Time.utc(2012, 1, 1, 17, 0), "10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 EST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 9, 0), "10:00 EDT".to_time + assert_equal Time.utc(2012, 1, 1, 14, 0), "10:00 EDT".to_time(:utc) + end end end def test_partial_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 7, 0), "10:00 -0100".to_time - assert_equal Time.utc(2012, 7, 1, 11, 0), "10:00 -0100".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 -0500".to_time - assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 14, 0), "10:00 PST".to_time - assert_equal Time.utc(2012, 7, 1, 18, 0), "10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 EST".to_time - assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 EST".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 7, 0), "10:00 -0100".to_time + assert_equal Time.utc(2012, 7, 1, 11, 0), "10:00 -0100".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 -0500".to_time + assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 14, 0), "10:00 PST".to_time + assert_equal Time.utc(2012, 7, 1, 18, 0), "10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 EST".to_time + assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 EST".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "10:00 EDT".to_time(:utc) + end end end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index d59775001b..b14c04fba6 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -149,6 +149,9 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2006,3,19,23,59,59,Rational(999999999, 1000)), Time.local(2006,3,19,10,10,10).end_of_day, 'ends DST' assert_equal Time.local(2006,10,1,23,59,59,Rational(999999999, 1000)), Time.local(2006,10,1,10,10,10).end_of_day, 'start DST' end + with_env_tz 'Asia/Yekaterinburg' do + assert_equal Time.local(2015, 2, 8, 23, 59, 59, Rational(999999999, 1000)), Time.new(2015, 2, 8, 8, 0, 0, '+05:00').end_of_day + end end def test_end_of_hour @@ -389,6 +392,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2005,1,2,11,22,33, 8), Time.local(2005,1,2,11,22,33,44).change(:usec => 8) assert_equal Time.local(2005,1,2,11,22,33, 8), Time.local(2005,1,2,11,22,33,2).change(:nsec => 8000) assert_raise(ArgumentError) { Time.local(2005,1,2,11,22,33, 8).change(:usec => 1, :nsec => 1) } + assert_nothing_raised(ArgumentError) { Time.new(2015, 5, 9, 10, 00, 00, '+03:00').change(nsec: 999999999) } end def test_utc_change @@ -601,13 +605,15 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_days_in_month_feb_in_common_year_without_year_arg - Time.stubs(:now).returns(Time.utc(2007)) - assert_equal 28, Time.days_in_month(2) + Time.stub(:now, Time.utc(2007)) do + assert_equal 28, Time.days_in_month(2) + end end def test_days_in_month_feb_in_leap_year_without_year_arg - Time.stubs(:now).returns(Time.utc(2008)) - assert_equal 29, Time.days_in_month(2) + Time.stub(:now, Time.utc(2008)) do + assert_equal 29, Time.days_in_month(2) + end end def test_last_month_on_31st @@ -619,68 +625,74 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_today_with_time_local - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Time.local(1999,12,31,23,59,59).today? - assert_equal true, Time.local(2000,1,1,0).today? - assert_equal true, Time.local(2000,1,1,23,59,59).today? - assert_equal false, Time.local(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Time.local(1999,12,31,23,59,59).today? + assert_equal true, Time.local(2000,1,1,0).today? + assert_equal true, Time.local(2000,1,1,23,59,59).today? + assert_equal false, Time.local(2000,1,2,0).today? + end end def test_today_with_time_utc - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Time.utc(1999,12,31,23,59,59).today? - assert_equal true, Time.utc(2000,1,1,0).today? - assert_equal true, Time.utc(2000,1,1,23,59,59).today? - assert_equal false, Time.utc(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Time.utc(1999,12,31,23,59,59).today? + assert_equal true, Time.utc(2000,1,1,0).today? + assert_equal true, Time.utc(2000,1,1,23,59,59).today? + assert_equal false, Time.utc(2000,1,2,0).today? + end end def test_past_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal true, Time.local(2005,2,10,15,30,44).past? - assert_equal false, Time.local(2005,2,10,15,30,45).past? - assert_equal false, Time.local(2005,2,10,15,30,46).past? - assert_equal true, Time.utc(2005,2,10,20,30,44).past? - assert_equal false, Time.utc(2005,2,10,20,30,45).past? - assert_equal false, Time.utc(2005,2,10,20,30,46).past? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal true, Time.local(2005,2,10,15,30,44).past? + assert_equal false, Time.local(2005,2,10,15,30,45).past? + assert_equal false, Time.local(2005,2,10,15,30,46).past? + assert_equal true, Time.utc(2005,2,10,20,30,44).past? + assert_equal false, Time.utc(2005,2,10,20,30,45).past? + assert_equal false, Time.utc(2005,2,10,20,30,46).past? + end end end def test_past_with_time_current_as_time_with_zone with_env_tz 'US/Eastern' do twz = Time.utc(2005,2,10,15,30,45).in_time_zone('Central Time (US & Canada)') - Time.stubs(:current).returns(twz) - assert_equal true, Time.local(2005,2,10,10,30,44).past? - assert_equal false, Time.local(2005,2,10,10,30,45).past? - assert_equal false, Time.local(2005,2,10,10,30,46).past? - assert_equal true, Time.utc(2005,2,10,15,30,44).past? - assert_equal false, Time.utc(2005,2,10,15,30,45).past? - assert_equal false, Time.utc(2005,2,10,15,30,46).past? + Time.stub(:current, twz) do + assert_equal true, Time.local(2005,2,10,10,30,44).past? + assert_equal false, Time.local(2005,2,10,10,30,45).past? + assert_equal false, Time.local(2005,2,10,10,30,46).past? + assert_equal true, Time.utc(2005,2,10,15,30,44).past? + assert_equal false, Time.utc(2005,2,10,15,30,45).past? + assert_equal false, Time.utc(2005,2,10,15,30,46).past? + end end end def test_future_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal false, Time.local(2005,2,10,15,30,44).future? - assert_equal false, Time.local(2005,2,10,15,30,45).future? - assert_equal true, Time.local(2005,2,10,15,30,46).future? - assert_equal false, Time.utc(2005,2,10,20,30,44).future? - assert_equal false, Time.utc(2005,2,10,20,30,45).future? - assert_equal true, Time.utc(2005,2,10,20,30,46).future? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal false, Time.local(2005,2,10,15,30,44).future? + assert_equal false, Time.local(2005,2,10,15,30,45).future? + assert_equal true, Time.local(2005,2,10,15,30,46).future? + assert_equal false, Time.utc(2005,2,10,20,30,44).future? + assert_equal false, Time.utc(2005,2,10,20,30,45).future? + assert_equal true, Time.utc(2005,2,10,20,30,46).future? + end end end def test_future_with_time_current_as_time_with_zone with_env_tz 'US/Eastern' do twz = Time.utc(2005,2,10,15,30,45).in_time_zone('Central Time (US & Canada)') - Time.stubs(:current).returns(twz) - assert_equal false, Time.local(2005,2,10,10,30,44).future? - assert_equal false, Time.local(2005,2,10,10,30,45).future? - assert_equal true, Time.local(2005,2,10,10,30,46).future? - assert_equal false, Time.utc(2005,2,10,15,30,44).future? - assert_equal false, Time.utc(2005,2,10,15,30,45).future? - assert_equal true, Time.utc(2005,2,10,15,30,46).future? + Time.stub(:current, twz) do + assert_equal false, Time.local(2005,2,10,10,30,44).future? + assert_equal false, Time.local(2005,2,10,10,30,45).future? + assert_equal true, Time.local(2005,2,10,10,30,46).future? + assert_equal false, Time.utc(2005,2,10,15,30,44).future? + assert_equal false, Time.utc(2005,2,10,15,30,45).future? + assert_equal true, Time.utc(2005,2,10,15,30,46).future? + end end end @@ -721,6 +733,13 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal(-1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 1), ActiveSupport::TimeZone['UTC'] )) end + def test_compare_with_string + assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999).to_s + assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0).to_s + assert_equal( -1, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1, 0).to_s) + assert_equal nil, Time.utc(2000) <=> 'Invalid as Time' + end + def test_at_with_datetime assert_equal Time.utc(2000, 1, 1, 0, 0, 0), Time.at(DateTime.civil(2000, 1, 1, 0, 0, 0)) diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 92c233d567..ccb7f02331 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -1,6 +1,8 @@ require 'abstract_unit' require 'active_support/time' require 'time_zone_test_helpers' +require 'active_support/core_ext/string/strip' +require 'yaml' class TimeWithZoneTest < ActiveSupport::TestCase include TimeZoneTestHelpers @@ -123,11 +125,53 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_to_yaml - assert_match(/^--- 2000-01-01 00:00:00(\.0+)?\s*Z\n/, @twz.to_yaml) + yaml = <<-EOF.strip_heredoc + --- !ruby/object:ActiveSupport::TimeWithZone + utc: 2000-01-01 00:00:00.000000000 Z + zone: !ruby/object:ActiveSupport::TimeZone + name: America/New_York + time: 1999-12-31 19:00:00.000000000 Z + EOF + + assert_equal(yaml, @twz.to_yaml) end def test_ruby_to_yaml - assert_match(/---\s*\n:twz: 2000-01-01 00:00:00(\.0+)?\s*Z\n/, {:twz => @twz}.to_yaml) + yaml = <<-EOF.strip_heredoc + --- + twz: !ruby/object:ActiveSupport::TimeWithZone + utc: 2000-01-01 00:00:00.000000000 Z + zone: !ruby/object:ActiveSupport::TimeZone + name: America/New_York + time: 1999-12-31 19:00:00.000000000 Z + EOF + + assert_equal(yaml, { 'twz' => @twz }.to_yaml) + end + + def test_yaml_load + yaml = <<-EOF.strip_heredoc + --- !ruby/object:ActiveSupport::TimeWithZone + utc: 2000-01-01 00:00:00.000000000 Z + zone: !ruby/object:ActiveSupport::TimeZone + name: America/New_York + time: 1999-12-31 19:00:00.000000000 Z + EOF + + assert_equal(@twz, YAML.load(yaml)) + end + + def test_ruby_yaml_load + yaml = <<-EOF.strip_heredoc + --- + twz: !ruby/object:ActiveSupport::TimeWithZone + utc: 2000-01-01 00:00:00.000000000 Z + zone: !ruby/object:ActiveSupport::TimeZone + name: America/New_York + time: 1999-12-31 19:00:00.000000000 Z + EOF + + assert_equal({ 'twz' => @twz }, YAML.load(yaml)) end def test_httpdate @@ -162,52 +206,61 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_today - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(1999,12,31,23,59,59) ).today? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,0) ).today? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,23,59,59) ).today? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,2,0) ).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(1999,12,31,23,59,59) ).today? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,0) ).today? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,23,59,59) ).today? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,2,0) ).today? + end end def test_past_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + end end end def test_past_with_time_current_as_time_with_zone twz = ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45) ) - Time.stubs(:current).returns(twz) - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + Time.stub(:current, twz) do + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + end end def test_future_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + end end end def test_future_with_time_current_as_time_with_zone twz = ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45) ) - Time.stubs(:current).returns(twz) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + Time.stub(:current, twz) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + end end def test_eql? + assert_equal true, @twz.eql?(@twz.dup) assert_equal true, @twz.eql?(Time.utc(2000)) assert_equal true, @twz.eql?( ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone["Hawaii"]) ) assert_equal false, @twz.eql?( Time.utc(2000, 1, 1, 0, 0, 1) ) assert_equal false, @twz.eql?( DateTime.civil(1999, 12, 31, 23, 59, 59) ) + + other_twz = ActiveSupport::TimeWithZone.new(DateTime.now.utc, @time_zone) + assert_equal true, other_twz.eql?(other_twz.dup) end def test_hash @@ -434,22 +487,24 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_method_missing_with_non_time_return_value - @twz.time.expects(:foo).returns('bar') + time = @twz.time + def time.foo; 'bar'; end assert_equal 'bar', @twz.foo end def test_date_part_value_methods twz = ActiveSupport::TimeWithZone.new(Time.utc(1999,12,31,19,18,17,500), @time_zone) - twz.expects(:method_missing).never - assert_equal 1999, twz.year - assert_equal 12, twz.month - assert_equal 31, twz.day - assert_equal 14, twz.hour - assert_equal 18, twz.min - assert_equal 17, twz.sec - assert_equal 500, twz.usec - assert_equal 5, twz.wday - assert_equal 365, twz.yday + assert_not_called(twz, :method_missing) do + assert_equal 1999, twz.year + assert_equal 12, twz.month + assert_equal 31, twz.day + assert_equal 14, twz.hour + assert_equal 18, twz.min + assert_equal 17, twz.sec + assert_equal 500, twz.usec + assert_equal 5, twz.wday + assert_equal 365, twz.yday + end end def test_usec_returns_0_when_datetime_is_wrapped @@ -990,19 +1045,21 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase def test_current_returns_time_now_when_zone_not_set with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - assert_equal false, Time.current.is_a?(ActiveSupport::TimeWithZone) - assert_equal Time.local(2000), Time.current + Time.stub(:now, Time.local(2000)) do + assert_equal false, Time.current.is_a?(ActiveSupport::TimeWithZone) + assert_equal Time.local(2000), Time.current + end end end def test_current_returns_time_zone_now_when_zone_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - assert_equal true, Time.current.is_a?(ActiveSupport::TimeWithZone) - assert_equal 'Eastern Time (US & Canada)', Time.current.time_zone.name - assert_equal Time.utc(2000), Time.current.time + Time.stub(:now, Time.local(2000)) do + assert_equal true, Time.current.is_a?(ActiveSupport::TimeWithZone) + assert_equal 'Eastern Time (US & Canada)', Time.current.time_zone.name + assert_equal Time.utc(2000), Time.current.time + end end end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 702e26859a..757e600646 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -160,7 +160,7 @@ class DependenciesTest < ActiveSupport::TestCase def test_ensures_the_expected_constant_is_defined with_autoloading_fixtures do e = assert_raise(LoadError) { Typo } - assert_match %r{Unable to autoload constant Typo, expected .*activesupport/test/autoloading_fixtures/typo.rb to define it}, e.message + assert_match %r{Unable to autoload constant Typo, expected .*/test/autoloading_fixtures/typo.rb to define it}, e.message end end @@ -178,7 +178,7 @@ class DependenciesTest < ActiveSupport::TestCase assert_equal 1, TypO e = assert_raise(LoadError) { Typo } - assert_match %r{Unable to autoload constant Typo, expected .*activesupport/test/autoloading_fixtures/typo.rb to define it}, e.message + assert_match %r{Unable to autoload constant Typo, expected .*/test/autoloading_fixtures/typo.rb to define it}, e.message end end @@ -187,7 +187,7 @@ class DependenciesTest < ActiveSupport::TestCase assert_kind_of Module, A assert_kind_of Class, A::B assert_kind_of Class, A::C::D - assert_kind_of Class, A::C::E::F + assert_kind_of Class, A::C::EM::F end end @@ -552,24 +552,24 @@ class DependenciesTest < ActiveSupport::TestCase def test_const_missing_in_anonymous_modules_loads_top_level_constants with_autoloading_fixtures do # class_eval STRING pushes the class to the nesting of the eval'ed code. - klass = Class.new.class_eval "E" - assert_equal E, klass + klass = Class.new.class_eval "EM" + assert_equal EM, klass end ensure - remove_constants(:E) + remove_constants(:EM) end def test_const_missing_in_anonymous_modules_raises_if_the_constant_belongs_to_Object with_autoloading_fixtures do - require_dependency 'e' + require_dependency 'em' mod = Module.new - e = assert_raise(NameError) { mod::E } - assert_equal 'E cannot be autoloaded from an anonymous class or module', e.message - assert_equal :E, e.name + e = assert_raise(NameError) { mod::EM } + assert_equal 'EM cannot be autoloaded from an anonymous class or module', e.message + assert_equal :EM, e.name end ensure - remove_constants(:E) + remove_constants(:EM) end def test_removal_from_tree_should_be_detected @@ -664,19 +664,19 @@ class DependenciesTest < ActiveSupport::TestCase def test_preexisting_constants_are_not_marked_as_autoloaded with_autoloading_fixtures do - require_dependency 'e' - assert ActiveSupport::Dependencies.autoloaded?(:E) + require_dependency 'em' + assert ActiveSupport::Dependencies.autoloaded?(:EM) ActiveSupport::Dependencies.clear end - Object.const_set :E, Class.new + Object.const_set :EM, Class.new with_autoloading_fixtures do - require_dependency 'e' - assert ! ActiveSupport::Dependencies.autoloaded?(:E), "E shouldn't be marked autoloaded!" + require_dependency 'em' + assert ! ActiveSupport::Dependencies.autoloaded?(:EM), "EM shouldn't be marked autoloaded!" ActiveSupport::Dependencies.clear end ensure - remove_constants(:E) + remove_constants(:EM) end def test_constants_in_capitalized_nesting_marked_as_autoloaded @@ -721,12 +721,13 @@ class DependenciesTest < ActiveSupport::TestCase end def test_unloadable_constants_should_receive_callback - Object.const_set :C, Class.new + Object.const_set :C, Class.new { def self.before_remove_const; end } C.unloadable - C.expects(:before_remove_const).once - assert C.respond_to?(:before_remove_const) - ActiveSupport::Dependencies.clear - assert !defined?(C) + assert_called(C, :before_remove_const, times: 1) do + assert C.respond_to?(:before_remove_const) + ActiveSupport::Dependencies.clear + assert !defined?(C) + end ensure remove_constants(:C) end diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index 20bd8ee5dd..7e8844b301 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -256,17 +256,17 @@ class DeprecationTest < ActiveSupport::TestCase end def test_deprecate_with_custom_deprecator - custom_deprecator = mock('Deprecator') do - expects(:deprecation_warning) - end + custom_deprecator = Struct.new(:deprecation_warning).new - klass = Class.new do - def method + assert_called_with(custom_deprecator, :deprecation_warning, [:method, nil]) do + klass = Class.new do + def method + end + deprecate :method, deprecator: custom_deprecator end - deprecate :method, deprecator: custom_deprecator - end - klass.new.method + klass.new.method + end end def test_deprecated_constant_with_deprecator_given diff --git a/activesupport/test/hash_with_indifferent_access_test.rb b/activesupport/test/hash_with_indifferent_access_test.rb deleted file mode 100644 index 1facd691fa..0000000000 --- a/activesupport/test/hash_with_indifferent_access_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'abstract_unit' -require 'active_support/hash_with_indifferent_access' - -class HashWithIndifferentAccessTest < ActiveSupport::TestCase - def test_reverse_merge - hash = HashWithIndifferentAccess.new key: :old_value - hash.reverse_merge! key: :new_value - assert_equal :old_value, hash[:key] - end - -end diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index be68bb2e2e..a0764f6d6b 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -8,6 +8,20 @@ class InflectorTest < ActiveSupport::TestCase include InflectorTestCases include ConstantizeTestCases + def setup + # Dups the singleton before each test, restoring the original inflections later. + # + # This helper is implemented by setting @__instance__ because in some tests + # there are module functions that access ActiveSupport::Inflector.inflections, + # so we need to replace the singleton itself. + @original_inflections = ActiveSupport::Inflector::Inflections.instance_variable_get(:@__instance__)[:en] + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: @original_inflections.dup) + end + + def teardown + ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: @original_inflections) + end + def test_pluralize_plurals assert_equal "plurals", ActiveSupport::Inflector.pluralize("plurals") assert_equal "Plurals", ActiveSupport::Inflector.pluralize("Plurals") @@ -26,20 +40,18 @@ class InflectorTest < ActiveSupport::TestCase end def test_uncountable_word_is_not_greedy - with_dup do - uncountable_word = "ors" - countable_word = "sponsor" + uncountable_word = "ors" + countable_word = "sponsor" - ActiveSupport::Inflector.inflections.uncountable << uncountable_word + ActiveSupport::Inflector.inflections.uncountable << uncountable_word - assert_equal uncountable_word, ActiveSupport::Inflector.singularize(uncountable_word) - assert_equal uncountable_word, ActiveSupport::Inflector.pluralize(uncountable_word) - assert_equal ActiveSupport::Inflector.pluralize(uncountable_word), ActiveSupport::Inflector.singularize(uncountable_word) + assert_equal uncountable_word, ActiveSupport::Inflector.singularize(uncountable_word) + assert_equal uncountable_word, ActiveSupport::Inflector.pluralize(uncountable_word) + assert_equal ActiveSupport::Inflector.pluralize(uncountable_word), ActiveSupport::Inflector.singularize(uncountable_word) - assert_equal "sponsor", ActiveSupport::Inflector.singularize(countable_word) - assert_equal "sponsors", ActiveSupport::Inflector.pluralize(countable_word) - assert_equal "sponsor", ActiveSupport::Inflector.singularize(ActiveSupport::Inflector.pluralize(countable_word)) - end + assert_equal "sponsor", ActiveSupport::Inflector.singularize(countable_word) + assert_equal "sponsors", ActiveSupport::Inflector.pluralize(countable_word) + assert_equal "sponsor", ActiveSupport::Inflector.singularize(ActiveSupport::Inflector.pluralize(countable_word)) end SingularToPlural.each do |singular, plural| @@ -70,11 +82,9 @@ class InflectorTest < ActiveSupport::TestCase def test_overwrite_previous_inflectors - with_dup do - assert_equal("series", ActiveSupport::Inflector.singularize("series")) - ActiveSupport::Inflector.inflections.singular "series", "serie" - assert_equal("serie", ActiveSupport::Inflector.singularize("series")) - end + assert_equal("series", ActiveSupport::Inflector.singularize("series")) + ActiveSupport::Inflector.inflections.singular "series", "serie" + assert_equal("serie", ActiveSupport::Inflector.singularize("series")) end MixtureToTitleCase.each_with_index do |(before, titleized), index| @@ -367,10 +377,8 @@ class InflectorTest < ActiveSupport::TestCase %w{plurals singulars uncountables humans}.each do |inflection_type| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def test_clear_#{inflection_type} - with_dup do - ActiveSupport::Inflector.inflections.clear :#{inflection_type} - assert ActiveSupport::Inflector.inflections.#{inflection_type}.empty?, \"#{inflection_type} inflections should be empty after clear :#{inflection_type}\" - end + ActiveSupport::Inflector.inflections.clear :#{inflection_type} + assert ActiveSupport::Inflector.inflections.#{inflection_type}.empty?, \"#{inflection_type} inflections should be empty after clear :#{inflection_type}\" end RUBY end @@ -405,73 +413,63 @@ class InflectorTest < ActiveSupport::TestCase end def test_clear_all - with_dup do - ActiveSupport::Inflector.inflections do |inflect| - # ensure any data is present - inflect.plural(/(quiz)$/i, '\1zes') - inflect.singular(/(database)s$/i, '\1') - inflect.uncountable('series') - inflect.human("col_rpted_bugs", "Reported bugs") - - inflect.clear :all - - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? - end + ActiveSupport::Inflector.inflections do |inflect| + # ensure any data is present + inflect.plural(/(quiz)$/i, '\1zes') + inflect.singular(/(database)s$/i, '\1') + inflect.uncountable('series') + inflect.human("col_rpted_bugs", "Reported bugs") + + inflect.clear :all + + assert inflect.plurals.empty? + assert inflect.singulars.empty? + assert inflect.uncountables.empty? + assert inflect.humans.empty? end end def test_clear_with_default - with_dup do - ActiveSupport::Inflector.inflections do |inflect| - # ensure any data is present - inflect.plural(/(quiz)$/i, '\1zes') - inflect.singular(/(database)s$/i, '\1') - inflect.uncountable('series') - inflect.human("col_rpted_bugs", "Reported bugs") - - inflect.clear - - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? - end + ActiveSupport::Inflector.inflections do |inflect| + # ensure any data is present + inflect.plural(/(quiz)$/i, '\1zes') + inflect.singular(/(database)s$/i, '\1') + inflect.uncountable('series') + inflect.human("col_rpted_bugs", "Reported bugs") + + inflect.clear + + assert inflect.plurals.empty? + assert inflect.singulars.empty? + assert inflect.uncountables.empty? + assert inflect.humans.empty? end end Irregularities.each do |singular, plural| define_method("test_irregularity_between_#{singular}_and_#{plural}") do - with_dup do - ActiveSupport::Inflector.inflections do |inflect| - inflect.irregular(singular, plural) - assert_equal singular, ActiveSupport::Inflector.singularize(plural) - assert_equal plural, ActiveSupport::Inflector.pluralize(singular) - end + ActiveSupport::Inflector.inflections do |inflect| + inflect.irregular(singular, plural) + assert_equal singular, ActiveSupport::Inflector.singularize(plural) + assert_equal plural, ActiveSupport::Inflector.pluralize(singular) end end end Irregularities.each do |singular, plural| define_method("test_pluralize_of_irregularity_#{plural}_should_be_the_same") do - with_dup do - ActiveSupport::Inflector.inflections do |inflect| - inflect.irregular(singular, plural) - assert_equal plural, ActiveSupport::Inflector.pluralize(plural) - end + ActiveSupport::Inflector.inflections do |inflect| + inflect.irregular(singular, plural) + assert_equal plural, ActiveSupport::Inflector.pluralize(plural) end end end Irregularities.each do |singular, plural| define_method("test_singularize_of_irregularity_#{singular}_should_be_the_same") do - with_dup do - ActiveSupport::Inflector.inflections do |inflect| - inflect.irregular(singular, plural) - assert_equal singular, ActiveSupport::Inflector.singularize(singular) - end + ActiveSupport::Inflector.inflections do |inflect| + inflect.irregular(singular, plural) + assert_equal singular, ActiveSupport::Inflector.singularize(singular) end end end @@ -503,12 +501,10 @@ class InflectorTest < ActiveSupport::TestCase %w(plurals singulars uncountables humans acronyms).each do |scope| define_method("test_clear_inflections_with_#{scope}") do - with_dup do - # clear the inflections - ActiveSupport::Inflector.inflections do |inflect| - inflect.clear(scope) - assert_equal [], inflect.send(scope) - end + # clear the inflections + ActiveSupport::Inflector.inflections do |inflect| + inflect.clear(scope) + assert_equal [], inflect.send(scope) end end end @@ -520,18 +516,4 @@ class InflectorTest < ActiveSupport::TestCase assert_equal "HTTP", ActiveSupport::Inflector.pluralize("HTTP") end - - # Dups the singleton and yields, restoring the original inflections later. - # Use this in tests what modify the state of the singleton. - # - # This helper is implemented by setting @__instance__ because in some tests - # there are module functions that access ActiveSupport::Inflector.inflections, - # so we need to replace the singleton itself. - def with_dup - original = ActiveSupport::Inflector::Inflections.instance_variable_get(:@__instance__)[:en] - ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: original.dup) - yield - ensure - ActiveSupport::Inflector::Inflections.instance_variable_set(:@__instance__, en: original) - end end diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 63d921e3b4..9f4b62fd8b 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -4,122 +4,24 @@ require 'active_support/core_ext/string/inflections' require 'active_support/json' require 'active_support/time' require 'time_zone_test_helpers' +require 'json/encoding_test_cases' class TestJSONEncoding < ActiveSupport::TestCase include TimeZoneTestHelpers - class Foo - def initialize(a, b) - @a, @b = a, b - end - end - - class Hashlike - def to_hash - { :foo => "hello", :bar => "world" } - end - end - - class Custom - def initialize(serialized) - @serialized = serialized - end - - def as_json(options = nil) - @serialized - end - end - - class CustomWithOptions - attr_accessor :foo, :bar - - def as_json(options={}) - options[:only] = %w(foo bar) - super(options) - end - end - - class OptionsTest - def as_json(options = :default) - options - end - end - - class HashWithAsJson < Hash - attr_accessor :as_json_called - - def initialize(*) - super - end - - def as_json(options={}) - @as_json_called = true - super - end - end - - TrueTests = [[ true, %(true) ]] - FalseTests = [[ false, %(false) ]] - NilTests = [[ nil, %(null) ]] - NumericTests = [[ 1, %(1) ], - [ 2.5, %(2.5) ], - [ 0.0/0.0, %(null) ], - [ 1.0/0.0, %(null) ], - [ -1.0/0.0, %(null) ], - [ BigDecimal('0.0')/BigDecimal('0.0'), %(null) ], - [ BigDecimal('2.5'), %("#{BigDecimal('2.5')}") ]] - - StringTests = [[ 'this is the <string>', %("this is the \\u003cstring\\u003e")], - [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ], - [ 'http://test.host/posts/1', %("http://test.host/posts/1")], - [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\u2028\u2029", - %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u2028\\u2029") ]] - - ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ], - [ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]] - - RangeTests = [[ 1..2, %("1..2")], - [ 1...2, %("1...2")], - [ 1.5..2.5, %("1.5..2.5")]] - - SymbolTests = [[ :a, %("a") ], - [ :this, %("this") ], - [ :"a b", %("a b") ]] - - ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]] - HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]] - CustomTests = [[ Custom.new("custom"), '"custom"' ], - [ Custom.new(nil), 'null' ], - [ Custom.new(:a), '"a"' ], - [ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ], - [ Custom.new({ :foo => "hello", :bar => "world" }), '{"bar":"world","foo":"hello"}' ], - [ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ], - [ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]] - - RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']] - - DateTests = [[ Date.new(2005,2,1), %("2005/02/01") ]] - TimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]] - DateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]] - - StandardDateTests = [[ Date.new(2005,2,1), %("2005-02-01") ]] - StandardTimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000Z") ]] - StandardDateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000+00:00") ]] - StandardStringTests = [[ 'this is the <string>', %("this is the <string>")]] - def sorted_json(json) return json unless json =~ /^\{.*\}$/ '{' + json[1..-2].split(',').sort.join(',') + '}' end - constants.grep(/Tests$/).each do |class_tests| + JSONTest::EncodingTestCases.constants.each do |class_tests| define_method("test_#{class_tests[0..-6].underscore}") do begin prev = ActiveSupport.use_standard_json_time_format ActiveSupport.escape_html_entities_in_json = class_tests !~ /^Standard/ ActiveSupport.use_standard_json_time_format = class_tests =~ /^Standard/ - self.class.const_get(class_tests).each do |pair| + JSONTest::EncodingTestCases.const_get(class_tests).each do |pair| assert_equal pair.last, sorted_json(ActiveSupport::JSON.encode(pair.first)) end ensure @@ -130,6 +32,8 @@ class TestJSONEncoding < ActiveSupport::TestCase end def test_process_status + rubinius_skip "https://github.com/rubinius/rubinius/issues/3334" + # There doesn't seem to be a good way to get a handle on a Process::Status object without actually # creating a child process, hence this to populate $? system("not_a_real_program_#{SecureRandom.hex}") @@ -145,6 +49,13 @@ class TestJSONEncoding < ActiveSupport::TestCase assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(:a => :b, :c => :d)) end + def test_hash_keys_encoding + ActiveSupport.escape_html_entities_in_json = true + assert_equal "{\"\\u003c\\u003e\":\"\\u003c\\u003e\"}", ActiveSupport::JSON.encode("<>" => "<>") + ensure + ActiveSupport.escape_html_entities_in_json = false + end + def test_utf8_string_encoded_properly result = ActiveSupport::JSON.encode('€2.99') assert_equal '"€2.99"', result @@ -215,7 +126,7 @@ class TestJSONEncoding < ActiveSupport::TestCase end def test_hash_like_with_options - h = Hashlike.new + h = JSONTest::Hashlike.new json = h.to_json :only => [:foo] assert_equal({"foo"=>"hello"}, JSON.parse(json)) @@ -336,6 +247,15 @@ class TestJSONEncoding < ActiveSupport::TestCase assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json) end + class CustomWithOptions + attr_accessor :foo, :bar + + def as_json(options={}) + options[:only] = %w(foo bar) + super(options) + end + end + def test_hash_to_json_should_not_keep_options_around f = CustomWithOptions.new f.foo = "hello" @@ -356,6 +276,12 @@ class TestJSONEncoding < ActiveSupport::TestCase {"foo"=>"other_foo","test"=>"other_test"}], ActiveSupport::JSON.decode(array.to_json)) end + class OptionsTest + def as_json(options = :default) + options + end + end + def test_hash_as_json_without_options json = { foo: OptionsTest.new }.as_json assert_equal({"foo" => :default}, json) @@ -403,6 +329,19 @@ class TestJSONEncoding < ActiveSupport::TestCase assert_equal false, false.as_json end + class HashWithAsJson < Hash + attr_accessor :as_json_called + + def initialize(*) + super + end + + def as_json(options={}) + @as_json_called = true + super + end + end + def test_json_gem_dump_by_passing_active_support_encoder h = HashWithAsJson.new h[:foo] = "hello" diff --git a/activesupport/test/json/encoding_test_cases.rb b/activesupport/test/json/encoding_test_cases.rb new file mode 100644 index 0000000000..0159ba8606 --- /dev/null +++ b/activesupport/test/json/encoding_test_cases.rb @@ -0,0 +1,88 @@ +require 'bigdecimal' + +module JSONTest + class Foo + def initialize(a, b) + @a, @b = a, b + end + end + + class Hashlike + def to_hash + { :foo => "hello", :bar => "world" } + end + end + + class Custom + def initialize(serialized) + @serialized = serialized + end + + def as_json(options = nil) + @serialized + end + end + + class MyStruct < Struct.new(:name, :value) + def initialize(*) + @unused = "unused instance variable" + super + end + end + + module EncodingTestCases + TrueTests = [[ true, %(true) ]] + FalseTests = [[ false, %(false) ]] + NilTests = [[ nil, %(null) ]] + NumericTests = [[ 1, %(1) ], + [ 2.5, %(2.5) ], + [ 0.0/0.0, %(null) ], + [ 1.0/0.0, %(null) ], + [ -1.0/0.0, %(null) ], + [ BigDecimal('0.0')/BigDecimal('0.0'), %(null) ], + [ BigDecimal('2.5'), %("#{BigDecimal('2.5')}") ]] + + StringTests = [[ 'this is the <string>', %("this is the \\u003cstring\\u003e")], + [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ], + [ 'http://test.host/posts/1', %("http://test.host/posts/1")], + [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\u2028\u2029", + %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u2028\\u2029") ]] + + ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ], + [ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]] + + HashTests = [[ {foo: "bar"}, %({\"foo\":\"bar\"}) ], + [ {1 => 1, 2 => 'a', 3 => :b, 4 => nil, 5 => false}, %({\"1\":1,\"2\":\"a\",\"3\":\"b\",\"4\":null,\"5\":false}) ]] + + RangeTests = [[ 1..2, %("1..2")], + [ 1...2, %("1...2")], + [ 1.5..2.5, %("1.5..2.5")]] + + SymbolTests = [[ :a, %("a") ], + [ :this, %("this") ], + [ :"a b", %("a b") ]] + + ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]] + HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]] + StructTests = [[ MyStruct.new(:foo, "bar"), %({\"name\":\"foo\",\"value\":\"bar\"}) ], + [ MyStruct.new(nil, nil), %({\"name\":null,\"value\":null}) ]] + CustomTests = [[ Custom.new("custom"), '"custom"' ], + [ Custom.new(nil), 'null' ], + [ Custom.new(:a), '"a"' ], + [ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ], + [ Custom.new({ :foo => "hello", :bar => "world" }), '{"bar":"world","foo":"hello"}' ], + [ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ], + [ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]] + + RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']] + + DateTests = [[ Date.new(2005,2,1), %("2005/02/01") ]] + TimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]] + DateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]] + + StandardDateTests = [[ Date.new(2005,2,1), %("2005-02-01") ]] + StandardTimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000Z") ]] + StandardDateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005-02-01T15:15:10.000+00:00") ]] + StandardStringTests = [[ 'this is the <string>', %("this is the <string>")]] + end +end diff --git a/activesupport/test/log_subscriber_test.rb b/activesupport/test/log_subscriber_test.rb index 2a0e8d20ed..998a6887c5 100644 --- a/activesupport/test/log_subscriber_test.rb +++ b/activesupport/test/log_subscriber_test.rb @@ -82,10 +82,11 @@ class SyncLogSubscriberTest < ActiveSupport::TestCase def test_does_not_send_the_event_if_logger_is_nil ActiveSupport::LogSubscriber.logger = nil - @log_subscriber.expects(:some_event).never - ActiveSupport::LogSubscriber.attach_to :my_log_subscriber, @log_subscriber - instrument "some_event.my_log_subscriber" - wait + assert_not_called(@log_subscriber, :some_event) do + ActiveSupport::LogSubscriber.attach_to :my_log_subscriber, @log_subscriber + instrument "some_event.my_log_subscriber" + wait + end end def test_does_not_fail_with_non_namespaced_events diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 6c3519df9a..668d78492e 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -24,6 +24,7 @@ class MessageVerifierTest < ActiveSupport::TestCase data, hash = @verifier.generate(@data).split("--") assert !@verifier.valid_message?(nil) assert !@verifier.valid_message?("") + assert !@verifier.valid_message?("\xff") # invalid encoding assert !@verifier.valid_message?("#{data.reverse}--#{hash}") assert !@verifier.valid_message?("#{data}--#{hash.reverse}") assert !@verifier.valid_message?("purejunk") diff --git a/activesupport/test/multibyte_unicode_database_test.rb b/activesupport/test/multibyte_unicode_database_test.rb index 52ae266f01..dd33641ec2 100644 --- a/activesupport/test/multibyte_unicode_database_test.rb +++ b/activesupport/test/multibyte_unicode_database_test.rb @@ -11,8 +11,9 @@ class MultibyteUnicodeDatabaseTest < ActiveSupport::TestCase UnicodeDatabase::ATTRIBUTES.each do |attribute| define_method "test_lazy_loading_on_attribute_access_of_#{attribute}" do - @ucd.expects(:load) - @ucd.send(attribute) + assert_called(@ucd, :load) do + @ucd.send(attribute) + end end end diff --git a/activesupport/test/number_helper_test.rb b/activesupport/test/number_helper_test.rb index 23996ef381..944bce1b41 100644 --- a/activesupport/test/number_helper_test.rb +++ b/activesupport/test/number_helper_test.rb @@ -83,6 +83,10 @@ module ActiveSupport assert_equal("98a%", number_helper.number_to_percentage("98a")) assert_equal("NaN%", number_helper.number_to_percentage(Float::NAN)) assert_equal("Inf%", number_helper.number_to_percentage(Float::INFINITY)) + assert_equal("NaN%", number_helper.number_to_percentage(Float::NAN, precision: 0)) + assert_equal("Inf%", number_helper.number_to_percentage(Float::INFINITY, precision: 0)) + assert_equal("NaN%", number_helper.number_to_percentage(Float::NAN, precision: 1)) + assert_equal("Inf%", number_helper.number_to_percentage(Float::INFINITY, precision: 1)) assert_equal("1000%", number_helper.number_to_percentage(1000, precision: nil)) assert_equal("1000%", number_helper.number_to_percentage(1000, precision: nil)) assert_equal("1000.1%", number_helper.number_to_percentage(1000.1, precision: nil)) @@ -102,6 +106,7 @@ module ActiveSupport assert_equal("123,456,789.78901", number_helper.number_to_delimited(123456789.78901)) assert_equal("0.78901", number_helper.number_to_delimited(0.78901)) assert_equal("123,456.78", number_helper.number_to_delimited("123456.78")) + assert_equal("1,23,456.78", number_helper.number_to_delimited("123456.78", delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)) assert_equal("123,456.78", number_helper.number_to_delimited("123456.78".html_safe)) end end @@ -230,15 +235,17 @@ module ActiveSupport end def test_number_to_human_size_with_si_prefix - [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper| - assert_equal '3 Bytes', number_helper.number_to_human_size(3.14159265, :prefix => :si) - assert_equal '123 Bytes', number_helper.number_to_human_size(123.0, :prefix => :si) - assert_equal '123 Bytes', number_helper.number_to_human_size(123, :prefix => :si) - assert_equal '1.23 KB', number_helper.number_to_human_size(1234, :prefix => :si) - assert_equal '12.3 KB', number_helper.number_to_human_size(12345, :prefix => :si) - assert_equal '1.23 MB', number_helper.number_to_human_size(1234567, :prefix => :si) - assert_equal '1.23 GB', number_helper.number_to_human_size(1234567890, :prefix => :si) - assert_equal '1.23 TB', number_helper.number_to_human_size(1234567890123, :prefix => :si) + assert_deprecated do + [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper| + assert_equal '3 Bytes', number_helper.number_to_human_size(3.14159265, :prefix => :si) + assert_equal '123 Bytes', number_helper.number_to_human_size(123.0, :prefix => :si) + assert_equal '123 Bytes', number_helper.number_to_human_size(123, :prefix => :si) + assert_equal '1.23 KB', number_helper.number_to_human_size(1234, :prefix => :si) + assert_equal '12.3 KB', number_helper.number_to_human_size(12345, :prefix => :si) + assert_equal '1.23 MB', number_helper.number_to_human_size(1234567, :prefix => :si) + assert_equal '1.23 GB', number_helper.number_to_human_size(1234567890, :prefix => :si) + assert_equal '1.23 TB', number_helper.number_to_human_size(1234567890123, :prefix => :si) + end end end diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb index fdc745b23b..18767a3536 100644 --- a/activesupport/test/ordered_options_test.rb +++ b/activesupport/test/ordered_options_test.rb @@ -85,4 +85,19 @@ class OrderedOptionsTest < ActiveSupport::TestCase assert_equal 42, a.method(:blah=).call(42) assert_equal 42, a.method(:blah).call end + + def test_raises_with_bang + a = ActiveSupport::OrderedOptions.new + a[:foo] = :bar + assert a.respond_to?(:foo!) + + assert_nothing_raised { a.foo! } + assert_equal a.foo, a.foo! + + assert_raises(KeyError) do + a.foo = nil + a.foo! + end + assert_raises(KeyError) { a.non_existing_key! } + end end diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb new file mode 100644 index 0000000000..ad41db608b --- /dev/null +++ b/activesupport/test/share_lock_test.rb @@ -0,0 +1,333 @@ +require 'abstract_unit' +require 'concurrent/atomics' +require 'active_support/concurrency/share_lock' + +class ShareLockTest < ActiveSupport::TestCase + def setup + @lock = ActiveSupport::Concurrency::ShareLock.new + end + + def test_reentrancy + thread = Thread.new do + @lock.sharing { @lock.sharing {} } + @lock.exclusive { @lock.exclusive {} } + end + assert_threads_not_stuck thread + end + + def test_sharing_doesnt_block + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_latch| + assert_threads_not_stuck(Thread.new {@lock.sharing {} }) + end + end + + def test_sharing_blocks_exclusive + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + @lock.exclusive(no_wait: true) { flunk } # polling should fail + exclusive_thread = Thread.new { @lock.exclusive {} } + assert_threads_stuck_but_releasable_by_latch exclusive_thread, sharing_thread_release_latch + end + end + + def test_exclusive_blocks_sharing + with_thread_waiting_in_lock_section(:exclusive) do |exclusive_thread_release_latch| + sharing_thread = Thread.new { @lock.sharing {} } + assert_threads_stuck_but_releasable_by_latch sharing_thread, exclusive_thread_release_latch + end + end + + def test_multiple_exlusives_are_able_to_progress + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + exclusive_threads = (1..2).map do + Thread.new do + @lock.exclusive {} + end + end + + assert_threads_stuck_but_releasable_by_latch exclusive_threads, sharing_thread_release_latch + end + end + + def test_sharing_is_upgradeable_to_exclusive + upgrading_thread = Thread.new do + @lock.sharing do + @lock.exclusive {} + end + end + assert_threads_not_stuck upgrading_thread + end + + def test_exclusive_upgrade_waits_for_other_sharers_to_leave + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + in_sharing = Concurrent::CountDownLatch.new + + upgrading_thread = Thread.new do + @lock.sharing do + in_sharing.count_down + @lock.exclusive {} + end + end + + in_sharing.wait + assert_threads_stuck_but_releasable_by_latch upgrading_thread, sharing_thread_release_latch + end + end + + def test_exclusive_matching_purpose + [true, false].each do |use_upgrading| + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + exclusive_threads = (1..2).map do + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + @lock.exclusive(purpose: :load, compatible: [:load, :unload]) {} + end + end + end + + assert_threads_stuck_but_releasable_by_latch exclusive_threads, sharing_thread_release_latch + end + end + end + + def test_killed_thread_loses_lock + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + thread = Thread.new do + @lock.sharing do + @lock.exclusive {} + end + end + + assert_threads_stuck thread + thread.kill + + sharing_thread_release_latch.count_down + + thread = Thread.new do + @lock.exclusive {} + end + + assert_threads_not_stuck thread + end + end + + def test_exclusive_conflicting_purpose + [true, false].each do |use_upgrading| + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + begin + conflicting_exclusive_threads = [ + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + @lock.exclusive(purpose: :red, compatible: [:green, :purple]) {} + end + end, + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + @lock.exclusive(purpose: :blue, compatible: [:green]) {} + end + end + ] + + assert_threads_stuck conflicting_exclusive_threads # wait for threads to get into their respective `exclusive {}` blocks + + # This thread will be stuck as long as any other thread is in + # a sharing block. While it's blocked, it holds no lock, so it + # doesn't interfere with any other attempts. + no_purpose_thread = Thread.new do + @lock.exclusive {} + end + assert_threads_stuck no_purpose_thread + + # This thread is compatible with both of the "primary" + # attempts above. It's initially stuck on the outer share + # lock, but as soon as that's released, it can run -- + # regardless of whether those threads hold share locks. + compatible_thread = Thread.new do + @lock.exclusive(purpose: :green, compatible: []) {} + end + assert_threads_stuck compatible_thread + + assert_threads_stuck conflicting_exclusive_threads + + sharing_thread_release_latch.count_down + + assert_threads_not_stuck compatible_thread # compatible thread is now able to squeak through + + if use_upgrading + # The "primary" threads both each hold a share lock, and are + # mutually incompatible; they're still stuck. + assert_threads_stuck conflicting_exclusive_threads + + # The thread without a specified purpose is also stuck; it's + # not compatible with anything. + assert_threads_stuck no_purpose_thread + else + # As the primaries didn't hold a share lock, as soon as the + # outer one was released, all the exclusive locks are free + # to be acquired in turn. + + assert_threads_not_stuck conflicting_exclusive_threads + assert_threads_not_stuck no_purpose_thread + end + ensure + conflicting_exclusive_threads.each(&:kill) + no_purpose_thread.kill + end + end + end + end + + def test_exclusive_ordering + scratch_pad = [] + scratch_pad_mutex = Mutex.new + + load_params = [:load, [:load]] + unload_params = [:unload, [:unload, :load]] + + [load_params, load_params, unload_params, unload_params].permutation do |thread_params| + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + threads = thread_params.map do |purpose, compatible| + Thread.new do + @lock.sharing do + @lock.exclusive(purpose: purpose, compatible: compatible) do + scratch_pad_mutex.synchronize { scratch_pad << purpose } + end + end + end + end + + sleep(0.01) + scratch_pad_mutex.synchronize { assert_empty scratch_pad } + + sharing_thread_release_latch.count_down + + assert_threads_not_stuck threads + scratch_pad_mutex.synchronize do + assert_equal [:load, :load, :unload, :unload], scratch_pad + scratch_pad.clear + end + end + end + end + + def test_in_shared_section_incompatible_non_upgrading_threads_cannot_preempt_upgrading_threads + scratch_pad = [] + scratch_pad_mutex = Mutex.new + + upgrading_load_params = [:load, [:load], true] + non_upgrading_unload_params = [:unload, [:load, :unload], false] + + [upgrading_load_params, non_upgrading_unload_params].permutation do |thread_params| + with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| + threads = thread_params.map do |purpose, compatible, use_upgrading| + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + @lock.exclusive(purpose: purpose, compatible: compatible) do + scratch_pad_mutex.synchronize { scratch_pad << purpose } + end + end + end + end + + assert_threads_stuck threads + scratch_pad_mutex.synchronize { assert_empty scratch_pad } + + sharing_thread_release_latch.count_down + + assert_threads_not_stuck threads + scratch_pad_mutex.synchronize do + assert_equal [:load, :unload], scratch_pad + scratch_pad.clear + end + end + end + end + + private + + module CustomAssertions + SUFFICIENT_TIMEOUT = 0.2 + + private + + def assert_threads_stuck_but_releasable_by_latch(threads, latch) + assert_threads_stuck threads + latch.count_down + assert_threads_not_stuck threads + end + + def assert_threads_stuck(threads) + sleep(SUFFICIENT_TIMEOUT) # give threads time to do their business + assert(Array(threads).all? { |t| t.join(0.001).nil? }) + end + + def assert_threads_not_stuck(threads) + assert(Array(threads).all? { |t| t.join(SUFFICIENT_TIMEOUT) }) + end + end + + class CustomAssertionsTest < ActiveSupport::TestCase + include CustomAssertions + + def setup + @latch = Concurrent::CountDownLatch.new + @thread = Thread.new { @latch.wait } + end + + def teardown + @latch.count_down + @thread.join + end + + def test_happy_path + assert_threads_stuck_but_releasable_by_latch @thread, @latch + end + + def test_detects_stuck_thread + assert_raises(Minitest::Assertion) do + assert_threads_not_stuck @thread + end + end + + def test_detects_free_thread + @latch.count_down + assert_raises(Minitest::Assertion) do + assert_threads_stuck @thread + end + end + + def test_detects_already_released + @latch.count_down + assert_raises(Minitest::Assertion) do + assert_threads_stuck_but_releasable_by_latch @thread, @latch + end + end + + def test_detects_remains_latched + another_latch = Concurrent::CountDownLatch.new + assert_raises(Minitest::Assertion) do + assert_threads_stuck_but_releasable_by_latch @thread, another_latch + end + end + end + + include CustomAssertions + + def with_thread_waiting_in_lock_section(lock_section) + in_section = Concurrent::CountDownLatch.new + section_release = Concurrent::CountDownLatch.new + + stuck_thread = Thread.new do + @lock.send(lock_section) do + in_section.count_down + section_release.wait + end + end + + in_section.wait + + yield section_release + ensure + section_release.count_down + stuck_thread.join # clean up + end +end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 151b623171..9e6d1a91d0 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -205,15 +205,4 @@ class TestOrderTest < ActiveSupport::TestCase assert_equal :random, self.class.test_order assert_equal :random, Class.new(ActiveSupport::TestCase).test_order end - - def test_i_suck_and_my_tests_are_order_dependent! - ActiveSupport::TestCase.test_order = :random - - klass = Class.new(ActiveSupport::TestCase) do - i_suck_and_my_tests_are_order_dependent! - end - - assert_equal :alpha, klass.test_order - assert_equal :random, ActiveSupport::TestCase.test_order - end end diff --git a/activesupport/test/testing/method_call_assertions_test.rb b/activesupport/test/testing/method_call_assertions_test.rb new file mode 100644 index 0000000000..3e5ba7c079 --- /dev/null +++ b/activesupport/test/testing/method_call_assertions_test.rb @@ -0,0 +1,123 @@ +require 'abstract_unit' +require 'active_support/testing/method_call_assertions' + +class MethodCallAssertionsTest < ActiveSupport::TestCase + include ActiveSupport::Testing::MethodCallAssertions + + class Level + def increment; 1; end + def decrement; end + def <<(arg); end + end + + setup do + @object = Level.new + end + + def test_assert_called_with_defaults_to_expect_once + assert_called @object, :increment do + @object.increment + end + end + + def test_assert_called_more_than_once + assert_called(@object, :increment, times: 2) do + @object.increment + @object.increment + end + end + + def test_assert_called_method_with_arguments + assert_called(@object, :<<) do + @object << 2 + end + end + + def test_assert_called_returns + assert_called(@object, :increment, returns: 10) do + assert_equal 10, @object.increment + end + end + + def test_assert_called_failure + error = assert_raises(Minitest::Assertion) do + assert_called(@object, :increment) do + # Call nothing... + end + end + + assert_equal "Expected increment to be called 1 times, but was called 0 times.\nExpected: 1\n Actual: 0", error.message + end + + def test_assert_called_with_message + error = assert_raises(Minitest::Assertion) do + assert_called(@object, :increment, 'dang it') do + # Call nothing... + end + end + + assert_match(/dang it.\nExpected increment/, error.message) + end + + def test_assert_called_with + assert_called_with(@object, :increment) do + @object.increment + end + end + + def test_assert_called_with_arguments + assert_called_with(@object, :<<, [ 2 ]) do + @object << 2 + end + end + + def test_assert_called_with_failure + assert_raises(MockExpectationError) do + assert_called_with(@object, :<<, [ 4567 ]) do + @object << 2 + end + end + end + + def test_assert_called_with_returns + assert_called_with(@object, :increment, returns: 1) do + @object.increment + end + end + + def test_assert_called_with_multiple_expected_arguments + assert_called_with(@object, :<<, [ [ 1 ], [ 2 ] ]) do + @object << 1 + @object << 2 + end + end + + def test_assert_not_called + assert_not_called(@object, :decrement) do + @object.increment + end + end + + def test_assert_not_called_failure + error = assert_raises(Minitest::Assertion) do + assert_not_called(@object, :increment) do + @object.increment + end + end + + assert_equal "Expected increment to be called 0 times, but was called 1 times.\nExpected: 0\n Actual: 1", error.message + end + + def test_stub_any_instance + stub_any_instance(Level) do |instance| + assert_equal instance, Level.new + end + end + + def test_stub_any_instance_with_instance + stub_any_instance(Level, instance: @object) do |instance| + assert_equal @object, instance + assert_equal instance, Level.new + end + end +end diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index 676a143692..59c3e52c2f 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -1,83 +1,90 @@ require 'abstract_unit' -require 'active_support/core_ext/date' require 'active_support/core_ext/date_time' require 'active_support/core_ext/numeric/time' class TimeTravelTest < ActiveSupport::TestCase - setup do - Time.stubs now: Time.now - end - teardown do travel_back end def test_time_helper_travel - expected_time = Time.now + 1.day - travel 1.day - - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) - assert_equal expected_time.to_date, Date.today - assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) - end - - def test_time_helper_travel_with_block - expected_time = Time.now + 1.day + Time.stub(:now, Time.now) do + expected_time = Time.now + 1.day + travel 1.day - travel 1.day do assert_equal expected_time.to_s(:db), Time.now.to_s(:db) assert_equal expected_time.to_date, Date.today assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) end - - assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db) - assert_not_equal expected_time.to_date, Date.today - assert_not_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) end - def test_time_helper_travel_to - expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time - - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now + 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_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_date, Date.today + assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + end + + assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_not_equal expected_time.to_date, Date.today + assert_not_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + end end - def test_time_helper_travel_to_with_block - expected_time = Time.new(2004, 11, 24, 01, 04, 44) + def test_time_helper_travel_to + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) + travel_to expected_time - travel_to expected_time do assert_equal expected_time, Time.now assert_equal Date.new(2004, 11, 24), Date.today assert_equal expected_time.to_datetime, DateTime.now end + end - assert_not_equal expected_time, Time.now - assert_not_equal Date.new(2004, 11, 24), Date.today - assert_not_equal expected_time.to_datetime, DateTime.now + def test_time_helper_travel_to_with_block + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) + + travel_to expected_time do + assert_equal expected_time, Time.now + 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 Date.new(2004, 11, 24), Date.today + assert_not_equal expected_time.to_datetime, DateTime.now + end end def test_time_helper_travel_back - expected_time = Time.new(2004, 11, 24, 01, 04, 44) + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now - travel_back + travel_to expected_time + assert_equal expected_time, Time.now + 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 Date.new(2004, 11, 24), Date.today - assert_not_equal expected_time.to_datetime, DateTime.now + assert_not_equal expected_time, Time.now + assert_not_equal Date.new(2004, 11, 24), Date.today + assert_not_equal expected_time.to_datetime, DateTime.now + end end def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding - 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 + 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 end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 7888b9919b..00d40c4497 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'active_support/time' require 'time_zone_test_helpers' +require 'yaml' class TimeZoneTest < ActiveSupport::TestCase include TimeZoneTestHelpers @@ -252,9 +253,10 @@ class TimeZoneTest < ActiveSupport::TestCase def test_parse_with_incomplete_date zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] - zone.stubs(:now).returns zone.local(1999,12,31) - twz = zone.parse('19:00:00') - assert_equal Time.utc(1999,12,31,19), twz.time + zone.stub(:now, zone.local(1999,12,31)) do + twz = zone.parse('19:00:00') + assert_equal Time.utc(1999,12,31,19), twz.time + end end def test_parse_with_day_omitted @@ -284,9 +286,10 @@ class TimeZoneTest < ActiveSupport::TestCase def test_parse_with_missing_time_components zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] - zone.stubs(:now).returns zone.local(1999, 12, 31, 12, 59, 59) - twz = zone.parse('2012-12-01') - assert_equal Time.utc(2012, 12, 1), twz.time + zone.stub(:now, zone.local(1999, 12, 31, 12, 59, 59)) do + twz = zone.parse('2012-12-01') + assert_equal Time.utc(2012, 12, 1), twz.time + end end def test_parse_with_javascript_date @@ -311,6 +314,80 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_strptime + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00', '%Y-%m-%d %H:%M:%S') + assert_equal Time.utc(1999,12,31,17), twz + assert_equal Time.utc(1999,12,31,12), twz.time + assert_equal Time.utc(1999,12,31,17), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_nondefault_time_zone + with_tz_default ActiveSupport::TimeZone['Pacific Time (US & Canada)'] do + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00', '%Y-%m-%d %H:%M:%S') + assert_equal Time.utc(1999,12,31,17), twz + assert_equal Time.utc(1999,12,31,12), twz.time + assert_equal Time.utc(1999,12,31,17), twz.utc + assert_equal zone, twz.time_zone + end + end + + def test_strptime_with_explicit_time_zone_as_abbrev + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00 PST', '%Y-%m-%d %H:%M:%S %Z') + assert_equal Time.utc(1999,12,31,20), twz + assert_equal Time.utc(1999,12,31,15), twz.time + assert_equal Time.utc(1999,12,31,20), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_explicit_time_zone_as_h_offset + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00 -08', '%Y-%m-%d %H:%M:%S %:::z') + assert_equal Time.utc(1999,12,31,20), twz + assert_equal Time.utc(1999,12,31,15), twz.time + assert_equal Time.utc(1999,12,31,20), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_explicit_time_zone_as_hm_offset + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00 -08:00', '%Y-%m-%d %H:%M:%S %:z') + assert_equal Time.utc(1999,12,31,20), twz + assert_equal Time.utc(1999,12,31,15), twz.time + assert_equal Time.utc(1999,12,31,20), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_explicit_time_zone_as_hms_offset + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00 -08:00:00', '%Y-%m-%d %H:%M:%S %::z') + assert_equal Time.utc(1999,12,31,20), twz + assert_equal Time.utc(1999,12,31,15), twz.time + assert_equal Time.utc(1999,12,31,20), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_almost_explicit_time_zone + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + twz = zone.strptime('1999-12-31 12:00:00 %Z', '%Y-%m-%d %H:%M:%S %%Z') + assert_equal Time.utc(1999,12,31,17), twz + assert_equal Time.utc(1999,12,31,12), twz.time + assert_equal Time.utc(1999,12,31,17), twz.utc + assert_equal zone, twz.time_zone + end + + def test_strptime_with_day_omitted + with_env_tz 'US/Eastern' do + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + assert_equal Time.local(2000, 2, 1), zone.strptime('Feb', '%b', Time.local(2000, 1, 1)) + assert_equal Time.local(2005, 2, 1), zone.strptime('Feb 2005', '%b %Y', Time.local(2000, 1, 1)) + assert_equal Time.local(2005, 2, 2), zone.strptime('2 Feb 2005', '%e %b %Y', Time.local(2000, 1, 1)) + end + end + def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize tzinfo = TZInfo::Timezone.get('America/New_York') zone = ActiveSupport::TimeZone.create(tzinfo.name, nil, tzinfo) @@ -413,4 +490,13 @@ class TimeZoneTest < ActiveSupport::TestCase assert ActiveSupport::TimeZone.us_zones.include?(ActiveSupport::TimeZone["Hawaii"]) assert !ActiveSupport::TimeZone.us_zones.include?(ActiveSupport::TimeZone["Kuala Lumpur"]) end + + def test_to_yaml + assert_equal("--- !ruby/object:ActiveSupport::TimeZone\nname: Pacific/Honolulu\n", ActiveSupport::TimeZone["Hawaii"].to_yaml) + assert_equal("--- !ruby/object:ActiveSupport::TimeZone\nname: Europe/London\n", ActiveSupport::TimeZone["Europe/London"].to_yaml) + end + + def test_yaml_load + assert_equal(ActiveSupport::TimeZone["Pacific/Honolulu"], YAML.load("--- !ruby/object:ActiveSupport::TimeZone\nname: Pacific/Honolulu\n")) + end end diff --git a/activesupport/test/xml_mini_test.rb b/activesupport/test/xml_mini_test.rb index bcd6997b06..55e8181b54 100644 --- a/activesupport/test/xml_mini_test.rb +++ b/activesupport/test/xml_mini_test.rb @@ -1,9 +1,9 @@ require 'abstract_unit' require 'active_support/xml_mini' require 'active_support/builder' -require 'active_support/core_ext/array' require 'active_support/core_ext/hash' require 'active_support/core_ext/big_decimal' +require 'yaml' module XmlMiniTest class RenameKeyTest < ActiveSupport::TestCase |