diff options
Diffstat (limited to 'activesupport/test')
100 files changed, 1980 insertions, 788 deletions
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 3ac11e0fe0..f214898145 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -38,4 +38,8 @@ class ActiveSupport::TestCase private def jruby_skip(message = "") skip message if defined?(JRUBY_VERSION) end + + def frozen_error_class + Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError + end end diff --git a/activesupport/test/array_inquirer_test.rb b/activesupport/test/array_inquirer_test.rb index d5419b862d..9a260edd8a 100644 --- a/activesupport/test/array_inquirer_test.rb +++ b/activesupport/test/array_inquirer_test.rb @@ -9,9 +9,9 @@ class ArrayInquirerTest < ActiveSupport::TestCase end def test_individual - assert @array_inquirer.mobile? - assert @array_inquirer.tablet? - assert_not @array_inquirer.desktop? + assert_predicate @array_inquirer, :mobile? + assert_predicate @array_inquirer, :tablet? + assert_not_predicate @array_inquirer, :desktop? end def test_any diff --git a/activesupport/test/benchmarkable_test.rb b/activesupport/test/benchmarkable_test.rb index 424da0a52c..cb7a69cccf 100644 --- a/activesupport/test/benchmarkable_test.rb +++ b/activesupport/test/benchmarkable_test.rb @@ -26,7 +26,7 @@ class BenchmarkableTest < ActiveSupport::TestCase def test_without_block assert_raise(LocalJumpError) { benchmark } - assert buffer.empty? + assert_empty buffer end def test_defaults diff --git a/activesupport/test/cache/behaviors.rb b/activesupport/test/cache/behaviors.rb index cb08a10bba..2d39976be3 100644 --- a/activesupport/test/cache/behaviors.rb +++ b/activesupport/test/cache/behaviors.rb @@ -3,7 +3,10 @@ require_relative "behaviors/autoloading_cache_behavior" require_relative "behaviors/cache_delete_matched_behavior" require_relative "behaviors/cache_increment_decrement_behavior" +require_relative "behaviors/cache_instrumentation_behavior" require_relative "behaviors/cache_store_behavior" require_relative "behaviors/cache_store_version_behavior" +require_relative "behaviors/connection_pool_behavior" require_relative "behaviors/encoded_key_cache_behavior" +require_relative "behaviors/failure_safety_behavior" require_relative "behaviors/local_cache_behavior" diff --git a/activesupport/test/cache/behaviors/cache_delete_matched_behavior.rb b/activesupport/test/cache/behaviors/cache_delete_matched_behavior.rb index 6f59ce48d2..ed8eba8fc2 100644 --- a/activesupport/test/cache/behaviors/cache_delete_matched_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_delete_matched_behavior.rb @@ -7,9 +7,9 @@ module CacheDeleteMatchedBehavior @cache.write("foo/bar", "baz") @cache.write("fu/baz", "bar") @cache.delete_matched(/oo/) - assert !@cache.exist?("foo") + assert_not @cache.exist?("foo") assert @cache.exist?("fu") - assert !@cache.exist?("foo/bar") + assert_not @cache.exist?("foo/bar") assert @cache.exist?("fu/baz") end end diff --git a/activesupport/test/cache/behaviors/cache_increment_decrement_behavior.rb b/activesupport/test/cache/behaviors/cache_increment_decrement_behavior.rb index 2fa2d7af88..16b7abc679 100644 --- a/activesupport/test/cache/behaviors/cache_increment_decrement_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_increment_decrement_behavior.rb @@ -8,7 +8,9 @@ module CacheIncrementDecrementBehavior assert_equal 2, @cache.read("foo").to_i assert_equal 3, @cache.increment("foo") assert_equal 3, @cache.read("foo").to_i - assert_nil @cache.increment("bar") + + missing = @cache.increment("bar") + assert(missing.nil? || missing == 1) end def test_decrement @@ -18,6 +20,8 @@ module CacheIncrementDecrementBehavior assert_equal 2, @cache.read("foo").to_i assert_equal 1, @cache.decrement("foo") assert_equal 1, @cache.read("foo").to_i - assert_nil @cache.decrement("bar") + + missing = @cache.decrement("bar") + assert(missing.nil? || missing == -1) end end diff --git a/activesupport/test/cache/cache_store_write_multi_test.rb b/activesupport/test/cache/behaviors/cache_instrumentation_behavior.rb index 5b6fd678c5..4e8ff60eb3 100644 --- a/activesupport/test/cache/cache_store_write_multi_test.rb +++ b/activesupport/test/cache/behaviors/cache_instrumentation_behavior.rb @@ -1,28 +1,15 @@ # frozen_string_literal: true -require "abstract_unit" -require "active_support/cache" - -class CacheStoreWriteMultiEntriesStoreProviderInterfaceTest < ActiveSupport::TestCase - setup do - @cache = ActiveSupport::Cache.lookup_store(:null_store) - end - - test "fetch_multi uses write_multi_entries store provider interface" do +module CacheInstrumentationBehavior + def test_fetch_multi_uses_write_multi_entries_store_provider_interface assert_called_with(@cache, :write_multi_entries) do @cache.fetch_multi "a", "b", "c" do |key| key * 2 end end end -end -class CacheStoreWriteMultiInstrumentationTest < ActiveSupport::TestCase - setup do - @cache = ActiveSupport::Cache.lookup_store(:null_store) - end - - test "instrumentation" do + def test_write_multi_instrumentation writes = { "a" => "aa", "b" => "bb" } events = with_instrumentation "write_multi" do @@ -34,16 +21,27 @@ class CacheStoreWriteMultiInstrumentationTest < ActiveSupport::TestCase assert_equal({ "a" => "aa", "b" => "bb" }, events[0].payload[:key]) end - test "instrumentation with fetch_multi as super operation" do - skip "fetch_multi isn't instrumented yet" + def test_instrumentation_with_fetch_multi_as_super_operation + @cache.write("b", "bb") - events = with_instrumentation "write_multi" do + events = with_instrumentation "read_multi" do @cache.fetch_multi("a", "b") { |key| key * 2 } end - assert_equal %w[ cache_write_multi.active_support ], events.map(&:name) - assert_nil events[0].payload[:super_operation] - assert !events[0].payload[:hit] + assert_equal %w[ cache_read_multi.active_support ], events.map(&:name) + assert_equal :fetch_multi, events[0].payload[:super_operation] + assert_equal ["b"], events[0].payload[:hits] + end + + def test_read_multi_instrumentation + @cache.write("b", "bb") + + events = with_instrumentation "read_multi" do + @cache.read_multi("a", "b") { |key| key * 2 } + end + + assert_equal %w[ cache_read_multi.active_support ], events.map(&:name) + assert_equal ["b"], events[0].payload[:hits] end private diff --git a/activesupport/test/cache/behaviors/cache_store_behavior.rb b/activesupport/test/cache/behaviors/cache_store_behavior.rb index 582e902f72..f9153ffe2a 100644 --- a/activesupport/test/cache/behaviors/cache_store_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_store_behavior.rb @@ -33,7 +33,7 @@ module CacheStoreBehavior cache_miss = false assert_equal 3, @cache.fetch("foo") { |key| cache_miss = true; key.length } - assert !cache_miss + assert_not cache_miss end def test_fetch_with_forced_cache_miss @@ -113,6 +113,16 @@ module CacheStoreBehavior assert_equal("fufu", @cache.read("fu")) end + def test_fetch_multi_without_expires_in + @cache.write("foo", "bar") + @cache.write("fud", "biz") + + values = @cache.fetch_multi("foo", "fu", "fud", expires_in: nil) { |value| value * 2 } + + assert_equal({ "foo" => "bar", "fu" => "fufu", "fud" => "biz" }, values) + assert_equal("fufu", @cache.read("fu")) + end + def test_multi_with_objects cache_struct = Struct.new(:cache_key, :title) foo = cache_struct.new("foo", "FOO!") @@ -131,19 +141,111 @@ module CacheStoreBehavior end end - def test_read_and_write_compressed_small_data - @cache.write("foo", "bar", compress: true) - assert_equal "bar", @cache.read("foo") + # Use strings that are guarenteed to compress well, so we can easily tell if + # the compression kicked in or not. + SMALL_STRING = "0" * 100 + LARGE_STRING = "0" * 2.kilobytes + + SMALL_OBJECT = { data: SMALL_STRING } + LARGE_OBJECT = { data: LARGE_STRING } + + def test_nil_with_default_compression_settings + assert_uncompressed(nil) end - def test_read_and_write_compressed_large_data - @cache.write("foo", "bar", compress: true, compress_threshold: 2) - assert_equal "bar", @cache.read("foo") + def test_nil_with_compress_true + assert_uncompressed(nil, compress: true) end - def test_read_and_write_compressed_nil - @cache.write("foo", nil, compress: true) - assert_nil @cache.read("foo") + def test_nil_with_compress_false + assert_uncompressed(nil, compress: false) + end + + def test_nil_with_compress_low_compress_threshold + assert_uncompressed(nil, compress: true, compress_threshold: 1) + end + + def test_small_string_with_default_compression_settings + assert_uncompressed(SMALL_STRING) + end + + def test_small_string_with_compress_true + assert_uncompressed(SMALL_STRING, compress: true) + end + + def test_small_string_with_compress_false + assert_uncompressed(SMALL_STRING, compress: false) + end + + def test_small_string_with_low_compress_threshold + assert_compressed(SMALL_STRING, compress: true, compress_threshold: 1) + end + + def test_small_object_with_default_compression_settings + assert_uncompressed(SMALL_OBJECT) + end + + def test_small_object_with_compress_true + assert_uncompressed(SMALL_OBJECT, compress: true) + end + + def test_small_object_with_compress_false + assert_uncompressed(SMALL_OBJECT, compress: false) + end + + def test_small_object_with_low_compress_threshold + assert_compressed(SMALL_OBJECT, compress: true, compress_threshold: 1) + end + + def test_large_string_with_default_compression_settings + assert_compressed(LARGE_STRING) + end + + def test_large_string_with_compress_true + assert_compressed(LARGE_STRING, compress: true) + end + + def test_large_string_with_compress_false + assert_uncompressed(LARGE_STRING, compress: false) + end + + def test_large_string_with_high_compress_threshold + assert_uncompressed(LARGE_STRING, compress: true, compress_threshold: 1.megabyte) + end + + def test_large_object_with_default_compression_settings + assert_compressed(LARGE_OBJECT) + end + + def test_large_object_with_compress_true + assert_compressed(LARGE_OBJECT, compress: true) + end + + def test_large_object_with_compress_false + assert_uncompressed(LARGE_OBJECT, compress: false) + end + + def test_large_object_with_high_compress_threshold + assert_uncompressed(LARGE_OBJECT, compress: true, compress_threshold: 1.megabyte) + end + + def test_incompressable_data + assert_uncompressed(nil, compress: true, compress_threshold: 1) + assert_uncompressed(true, compress: true, compress_threshold: 1) + assert_uncompressed(false, compress: true, compress_threshold: 1) + assert_uncompressed(0, compress: true, compress_threshold: 1) + assert_uncompressed(1.2345, compress: true, compress_threshold: 1) + assert_uncompressed("", compress: true, compress_threshold: 1) + + incompressible = nil + + # generate an incompressible string + loop do + incompressible = SecureRandom.random_bytes(1.kilobyte) + break if incompressible.bytesize < Zlib::Deflate.deflate(incompressible).bytesize + end + + assert_uncompressed(incompressible, compress: true, compress_threshold: 1) end def test_cache_key @@ -164,6 +266,18 @@ module CacheStoreBehavior assert_equal "bar", @cache.read("foo") end + def test_unversioned_cache_key + obj = Object.new + def obj.cache_key + "foo" + end + def obj.cache_key_with_version + "foo-v1" + end + @cache.write(obj, "bar") + assert_equal "bar", @cache.read("foo") + end + def test_array_as_cache_key @cache.write([:fu, "foo"], "bar") assert_equal "bar", @cache.read("fu/foo") @@ -194,7 +308,7 @@ module CacheStoreBehavior @cache.write("foo", "bar") assert @cache.exist?("foo") assert @cache.delete("foo") - assert !@cache.exist?("foo") + assert_not @cache.exist?("foo") end def test_original_store_objects_should_not_be_immutable @@ -287,8 +401,7 @@ module CacheStoreBehavior end def test_really_long_keys - key = "".dup - 900.times { key << "x" } + key = "x" * 2048 assert @cache.write(key, "bar") assert_equal "bar", @cache.read(key) assert_equal "bar", @cache.fetch(key) @@ -328,4 +441,41 @@ module CacheStoreBehavior ensure ActiveSupport::Notifications.unsubscribe "cache_read.active_support" end + + private + + def assert_compressed(value, **options) + assert_compression(true, value, **options) + end + + def assert_uncompressed(value, **options) + assert_compression(false, value, **options) + end + + def assert_compression(should_compress, value, **options) + freeze_time do + @cache.write("actual", value, options) + @cache.write("uncompressed", value, options.merge(compress: false)) + end + + if value.nil? + assert_nil @cache.read("actual") + assert_nil @cache.read("uncompressed") + else + assert_equal value, @cache.read("actual") + assert_equal value, @cache.read("uncompressed") + end + + actual_entry = @cache.send(:read_entry, @cache.send(:normalize_key, "actual", {}), {}) + uncompressed_entry = @cache.send(:read_entry, @cache.send(:normalize_key, "uncompressed", {}), {}) + + actual_size = Marshal.dump(actual_entry).bytesize + uncompressed_size = Marshal.dump(uncompressed_entry).bytesize + + if should_compress + assert_operator actual_size, :<, uncompressed_size, "value should be compressed" + else + assert_equal uncompressed_size, actual_size, "value should not be compressed" + end + end end diff --git a/activesupport/test/cache/behaviors/cache_store_version_behavior.rb b/activesupport/test/cache/behaviors/cache_store_version_behavior.rb index c2e4d046af..805f061839 100644 --- a/activesupport/test/cache/behaviors/cache_store_version_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_store_version_behavior.rb @@ -30,7 +30,7 @@ module CacheStoreVersionBehavior def test_exist_with_wrong_version_should_be_false @cache.write("foo", "bar", version: 1) - assert !@cache.exist?("foo", version: 2) + assert_not @cache.exist?("foo", version: 2) end def test_reading_and_writing_with_model_supporting_cache_version @@ -65,7 +65,7 @@ module CacheStoreVersionBehavior m1v2 = ModelWithKeyAndVersion.new("model/1", 2) @cache.write(m1v1, "bar") - assert @cache.exist?(m1v1) + assert @cache.exist?(m1v1) assert_not @cache.fetch(m1v2) end diff --git a/activesupport/test/cache/behaviors/connection_pool_behavior.rb b/activesupport/test/cache/behaviors/connection_pool_behavior.rb new file mode 100644 index 0000000000..701cd75595 --- /dev/null +++ b/activesupport/test/cache/behaviors/connection_pool_behavior.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module ConnectionPoolBehavior + def test_connection_pool + Thread.report_on_exception, original_report_on_exception = false, Thread.report_on_exception + + emulating_latency do + begin + cache = ActiveSupport::Cache.lookup_store(store, { pool_size: 2, pool_timeout: 1 }.merge(store_options)) + cache.clear + + threads = [] + + assert_raises Timeout::Error do + # One of the three threads will fail in 1 second because our pool size + # is only two. + 3.times do + threads << Thread.new do + cache.read("latency") + end + end + + threads.each(&:join) + end + ensure + threads.each(&:kill) + end + end + ensure + Thread.report_on_exception = original_report_on_exception + end + + def test_no_connection_pool + emulating_latency do + begin + cache = ActiveSupport::Cache.lookup_store(store, store_options) + cache.clear + + threads = [] + + assert_nothing_raised do + # Default connection pool size is 5, assuming 10 will make sure that + # the connection pool isn't used at all. + 10.times do + threads << Thread.new do + cache.read("latency") + end + end + + threads.each(&:join) + end + ensure + threads.each(&:kill) + end + end + end + + private + def store_options; {}; end +end diff --git a/activesupport/test/cache/behaviors/failure_safety_behavior.rb b/activesupport/test/cache/behaviors/failure_safety_behavior.rb new file mode 100644 index 0000000000..43b67d81db --- /dev/null +++ b/activesupport/test/cache/behaviors/failure_safety_behavior.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +module FailureSafetyBehavior + def test_fetch_read_failure_returns_nil + @cache.write("foo", "bar") + + emulating_unavailability do |cache| + assert_nil cache.fetch("foo") + end + end + + def test_fetch_read_failure_does_not_attempt_to_write + end + + def test_read_failure_returns_nil + @cache.write("foo", "bar") + + emulating_unavailability do |cache| + assert_nil cache.read("foo") + end + end + + def test_read_multi_failure_returns_empty_hash + @cache.write_multi("foo" => "bar", "baz" => "quux") + + emulating_unavailability do |cache| + assert_equal Hash.new, cache.read_multi("foo", "baz") + end + end + + def test_write_failure_returns_false + emulating_unavailability do |cache| + assert_equal false, cache.write("foo", "bar") + end + end + + def test_write_multi_failure_not_raises + emulating_unavailability do |cache| + assert_nothing_raised do + cache.write_multi("foo" => "bar", "baz" => "quux") + end + end + end + + def test_fetch_multi_failure_returns_fallback_results + @cache.write_multi("foo" => "bar", "baz" => "quux") + + emulating_unavailability do |cache| + fetched = cache.fetch_multi("foo", "baz") { |k| "unavailable" } + assert_equal Hash["foo" => "unavailable", "baz" => "unavailable"], fetched + end + end + + def test_delete_failure_returns_false + @cache.write("foo", "bar") + + emulating_unavailability do |cache| + assert_equal false, cache.delete("foo") + end + end + + def test_exist_failure_returns_false + @cache.write("foo", "bar") + + emulating_unavailability do |cache| + assert_not cache.exist?("foo") + end + end + + def test_increment_failure_returns_nil + @cache.write("foo", 1, raw: true) + + emulating_unavailability do |cache| + assert_nil cache.increment("foo") + end + end + + def test_decrement_failure_returns_nil + @cache.write("foo", 1, raw: true) + + emulating_unavailability do |cache| + assert_nil cache.decrement("foo") + end + end + + def test_clear_failure_returns_nil + emulating_unavailability do |cache| + assert_nil cache.clear + end + end +end diff --git a/activesupport/test/cache/behaviors/local_cache_behavior.rb b/activesupport/test/cache/behaviors/local_cache_behavior.rb index 8dec8090b1..baa38ba6ac 100644 --- a/activesupport/test/cache/behaviors/local_cache_behavior.rb +++ b/activesupport/test/cache/behaviors/local_cache_behavior.rb @@ -20,7 +20,11 @@ module LocalCacheBehavior end def test_cleanup_clears_local_cache_but_not_remote_cache - skip unless @cache.class.instance_methods(false).include?(:cleanup) + begin + @cache.cleanup + rescue NotImplementedError + skip + end @cache.with_local_cache do @cache.write("foo", "bar") @@ -115,6 +119,28 @@ module LocalCacheBehavior end end + def test_local_cache_of_fetch_multi + @cache.with_local_cache do + @cache.fetch_multi("foo", "bar") { |_key| true } + @peek.delete("foo") + @peek.delete("bar") + assert_equal true, @cache.read("foo") + assert_equal true, @cache.read("bar") + end + end + + def test_local_cache_of_read_multi + @cache.with_local_cache do + @cache.write("foo", "foo", raw: true) + @cache.write("bar", "bar", raw: true) + values = @cache.read_multi("foo", "bar") + assert_equal "foo", @cache.read("foo") + assert_equal "bar", @cache.read("bar") + assert_equal "foo", values["foo"] + assert_equal "bar", values["bar"] + end + end + def test_middleware app = lambda { |env| result = @cache.write("foo", "bar") diff --git a/activesupport/test/cache/cache_entry_test.rb b/activesupport/test/cache/cache_entry_test.rb index 51b214ad8f..d7baaa5c72 100644 --- a/activesupport/test/cache/cache_entry_test.rb +++ b/activesupport/test/cache/cache_entry_test.rb @@ -13,18 +13,4 @@ class CacheEntryTest < ActiveSupport::TestCase assert entry.expired?, "entry is expired" end end - - def test_compress_values - value = "value" * 100 - entry = ActiveSupport::Cache::Entry.new(value, compress: true, compress_threshold: 1) - assert_equal value, entry.value - assert(value.bytesize > entry.size, "value is compressed") - end - - def test_non_compress_values - value = "value" * 100 - entry = ActiveSupport::Cache::Entry.new(value) - assert_equal value, entry.value - assert_equal value.bytesize, entry.size - end end diff --git a/activesupport/test/cache/cache_store_logger_test.rb b/activesupport/test/cache/cache_store_logger_test.rb index 1af6893cc9..4648b2d361 100644 --- a/activesupport/test/cache/cache_store_logger_test.rb +++ b/activesupport/test/cache/cache_store_logger_test.rb @@ -13,7 +13,7 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase def test_logging @cache.fetch("foo") { "bar" } - assert @buffer.string.present? + assert_predicate @buffer.string, :present? end def test_log_with_string_namespace @@ -31,6 +31,6 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase def test_mute_logging @cache.mute { @cache.fetch("foo") { "bar" } } - assert @buffer.string.blank? + assert_predicate @buffer.string, :blank? end end diff --git a/activesupport/test/cache/cache_store_namespace_test.rb b/activesupport/test/cache/cache_store_namespace_test.rb index b52a61c500..dfdb3262f2 100644 --- a/activesupport/test/cache/cache_store_namespace_test.rb +++ b/activesupport/test/cache/cache_store_namespace_test.rb @@ -25,7 +25,7 @@ class CacheStoreNamespaceTest < ActiveSupport::TestCase cache.write("foo", "bar") cache.write("fu", "baz") cache.delete_matched(/^fo/) - assert !cache.exist?("foo") + assert_not cache.exist?("foo") assert cache.exist?("fu") end @@ -34,7 +34,7 @@ class CacheStoreNamespaceTest < ActiveSupport::TestCase cache.write("foo", "bar") cache.write("fu", "baz") cache.delete_matched(/OO/i) - assert !cache.exist?("foo") + assert_not cache.exist?("foo") assert cache.exist?("fu") end end diff --git a/activesupport/test/cache/stores/file_store_test.rb b/activesupport/test/cache/stores/file_store_test.rb index 391ab60b3a..f6855bb308 100644 --- a/activesupport/test/cache/stores/file_store_test.rb +++ b/activesupport/test/cache/stores/file_store_test.rb @@ -30,6 +30,7 @@ class FileStoreTest < ActiveSupport::TestCase include LocalCacheBehavior include CacheDeleteMatchedBehavior include CacheIncrementDecrementBehavior + include CacheInstrumentationBehavior include AutoloadingCacheBehavior def test_clear @@ -67,7 +68,9 @@ class FileStoreTest < ActiveSupport::TestCase def test_filename_max_size key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}" path = @cache.send(:normalize_key, key, {}) - Dir::Tmpname.create(path) do |tmpname, n, opts| + basename = File.basename(path) + dirname = File.dirname(path) + Dir::Tmpname.create(basename, Dir.tmpdir + dirname) do |tmpname, n, opts| assert File.basename(tmpname + ".lock").length <= 255, "Temp filename too long: #{File.basename(tmpname + '.lock').length}" end end @@ -98,13 +101,13 @@ class FileStoreTest < ActiveSupport::TestCase end assert File.exist?(cache_dir), "Parent of top level cache dir was deleted!" assert File.exist?(sub_cache_dir), "Top level cache dir was deleted!" - assert Dir.entries(sub_cache_dir).reject { |f| ActiveSupport::Cache::FileStore::EXCLUDED_DIRS.include?(f) }.empty? + assert_empty Dir.entries(sub_cache_dir).reject { |f| ActiveSupport::Cache::FileStore::EXCLUDED_DIRS.include?(f) } end def test_log_exception_when_cache_read_fails File.stub(:exist?, -> { raise StandardError.new("failed") }) do @cache.send(:read_entry, "winston", {}) - assert @buffer.string.present? + assert_predicate @buffer.string, :present? end end @@ -118,6 +121,7 @@ class FileStoreTest < ActiveSupport::TestCase assert_not @cache.exist?("foo") assert @cache.exist?("baz") assert @cache.exist?("quux") + assert_equal 2, Dir.glob(File.join(cache_dir, "**")).size end end diff --git a/activesupport/test/cache/stores/mem_cache_store_test.rb b/activesupport/test/cache/stores/mem_cache_store_test.rb index 1b73fb65eb..f426a37c66 100644 --- a/activesupport/test/cache/stores/mem_cache_store_test.rb +++ b/activesupport/test/cache/stores/mem_cache_store_test.rb @@ -5,6 +5,24 @@ require "active_support/cache" require_relative "../behaviors" require "dalli" +# Emulates a latency on Dalli's back-end for the key latency to facilitate +# connection pool testing. +class SlowDalliClient < Dalli::Client + def get(key, options = {}) + if key =~ /latency/ + sleep 3 + else + super + end + end +end + +class UnavailableDalliServer < Dalli::Server + def alive? + false + end +end + class MemCacheStoreTest < ActiveSupport::TestCase begin ss = Dalli::Client.new("localhost:11211").stats @@ -31,8 +49,11 @@ class MemCacheStoreTest < ActiveSupport::TestCase include CacheStoreVersionBehavior include LocalCacheBehavior include CacheIncrementDecrementBehavior + include CacheInstrumentationBehavior include EncodedKeyCacheBehavior include AutoloadingCacheBehavior + include ConnectionPoolBehavior + include FailureSafetyBehavior def test_raw_values cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) @@ -57,6 +78,22 @@ class MemCacheStoreTest < ActiveSupport::TestCase end end + def test_increment_expires_in + cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache.clear + assert_called_with cache.instance_variable_get(:@data), :incr, [ "foo", 1, 60 ] do + cache.increment("foo", 1, expires_in: 60) + end + end + + def test_decrement_expires_in + cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache.clear + assert_called_with cache.instance_variable_get(:@data), :decr, [ "foo", 1, 60 ] do + cache.decrement("foo", 1, expires_in: 60) + end + end + def test_local_cache_raw_values_with_marshal cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) cache.clear @@ -73,4 +110,30 @@ class MemCacheStoreTest < ActiveSupport::TestCase value << "bingo" assert_not_equal value, @cache.read("foo") end + + private + + def store + :mem_cache_store + end + + def emulating_latency + old_client = Dalli.send(:remove_const, :Client) + Dalli.const_set(:Client, SlowDalliClient) + + yield + ensure + Dalli.send(:remove_const, :Client) + Dalli.const_set(:Client, old_client) + end + + def emulating_unavailability + old_server = Dalli.send(:remove_const, :Server) + Dalli.const_set(:Server, UnavailableDalliServer) + + yield ActiveSupport::Cache::MemCacheStore.new + ensure + Dalli.send(:remove_const, :Server) + Dalli.const_set(:Server, old_server) + end end diff --git a/activesupport/test/cache/stores/memory_store_test.rb b/activesupport/test/cache/stores/memory_store_test.rb index 3981f05331..340fb517cb 100644 --- a/activesupport/test/cache/stores/memory_store_test.rb +++ b/activesupport/test/cache/stores/memory_store_test.rb @@ -6,14 +6,21 @@ require_relative "../behaviors" class MemoryStoreTest < ActiveSupport::TestCase def setup - @record_size = ActiveSupport::Cache.lookup_store(:memory_store).send(:cached_size, 1, ActiveSupport::Cache::Entry.new("aaaaaaaaaa")) - @cache = ActiveSupport::Cache.lookup_store(:memory_store, expires_in: 60, size: @record_size * 10 + 1) + @cache = ActiveSupport::Cache.lookup_store(:memory_store, expires_in: 60) end include CacheStoreBehavior include CacheStoreVersionBehavior include CacheDeleteMatchedBehavior include CacheIncrementDecrementBehavior + include CacheInstrumentationBehavior +end + +class MemoryStorePruningTest < ActiveSupport::TestCase + def setup + @record_size = ActiveSupport::Cache.lookup_store(:memory_store).send(:cached_size, 1, ActiveSupport::Cache::Entry.new("aaaaaaaaaa")) + @cache = ActiveSupport::Cache.lookup_store(:memory_store, expires_in: 60, size: @record_size * 10 + 1) + end def test_prune_size @cache.write(1, "aaaaaaaaaa") && sleep(0.001) @@ -97,7 +104,7 @@ class MemoryStoreTest < ActiveSupport::TestCase assert @cache.exist?(4) assert @cache.exist?(3) assert @cache.exist?(2) - assert !@cache.exist?(1) + assert_not @cache.exist?(1) end def test_write_with_unless_exist diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb new file mode 100644 index 0000000000..24c4c5c481 --- /dev/null +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "active_support/cache" +require "active_support/cache/redis_cache_store" +require_relative "../behaviors" + +driver_name = %w[ ruby hiredis ].include?(ENV["REDIS_DRIVER"]) ? ENV["REDIS_DRIVER"] : "hiredis" +driver = Object.const_get("Redis::Connection::#{driver_name.camelize}") + +Redis::Connection.drivers.clear +Redis::Connection.drivers.append(driver) + +# Emulates a latency on Redis's back-end for the key latency to facilitate +# connection pool testing. +class SlowRedis < Redis + def get(key, options = {}) + if key =~ /latency/ + sleep 3 + else + super + end + end +end + +module ActiveSupport::Cache::RedisCacheStoreTests + DRIVER = %w[ ruby hiredis ].include?(ENV["REDIS_DRIVER"]) ? ENV["REDIS_DRIVER"] : "hiredis" + + class LookupTest < ActiveSupport::TestCase + test "may be looked up as :redis_cache_store" do + assert_kind_of ActiveSupport::Cache::RedisCacheStore, + ActiveSupport::Cache.lookup_store(:redis_cache_store) + end + end + + class InitializationTest < ActiveSupport::TestCase + test "omitted URL uses Redis client with default settings" do + assert_called_with Redis, :new, [ + url: nil, + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER + ] do + build + end + end + + test "no URLs uses Redis client with default settings" do + assert_called_with Redis, :new, [ + url: nil, + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER + ] do + build url: [] + end + end + + test "singular URL uses Redis client" do + assert_called_with Redis, :new, [ + url: "redis://localhost:6379/0", + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER + ] do + build url: "redis://localhost:6379/0" + end + end + + test "one URL uses Redis client" do + assert_called_with Redis, :new, [ + url: "redis://localhost:6379/0", + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER + ] do + build url: %w[ redis://localhost:6379/0 ] + end + end + + test "multiple URLs uses Redis::Distributed client" do + assert_called_with Redis, :new, [ + [ url: "redis://localhost:6379/0", + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER ], + [ url: "redis://localhost:6379/1", + connect_timeout: 20, read_timeout: 1, write_timeout: 1, + reconnect_attempts: 0, driver: DRIVER ], + ], returns: Redis.new do + @cache = build url: %w[ redis://localhost:6379/0 redis://localhost:6379/1 ] + assert_kind_of ::Redis::Distributed, @cache.redis + end + end + + test "block argument uses yielded client" do + block = -> { :custom_redis_client } + assert_called block, :call do + build redis: block + end + end + + test "instance of Redis uses given instance" do + redis_instance = Redis.new + @cache = build(redis: redis_instance) + assert_same @cache.redis, redis_instance + end + + private + def build(**kwargs) + ActiveSupport::Cache::RedisCacheStore.new(driver: DRIVER, **kwargs).tap do |cache| + cache.redis + end + end + end + + class StoreTest < ActiveSupport::TestCase + setup do + @namespace = "namespace" + + @cache = ActiveSupport::Cache::RedisCacheStore.new(timeout: 0.1, namespace: @namespace, expires_in: 60, driver: DRIVER) + # @cache.logger = Logger.new($stdout) # For test debugging + + # For LocalCacheBehavior tests + @peek = ActiveSupport::Cache::RedisCacheStore.new(timeout: 0.1, namespace: @namespace, driver: DRIVER) + end + + teardown do + @cache.clear + @cache.redis.disconnect! + end + end + + class RedisCacheStoreCommonBehaviorTest < StoreTest + include CacheStoreBehavior + include CacheStoreVersionBehavior + include LocalCacheBehavior + include CacheIncrementDecrementBehavior + include CacheInstrumentationBehavior + include AutoloadingCacheBehavior + + def test_fetch_multi_uses_redis_mget + assert_called(@cache.redis, :mget, returns: []) do + @cache.fetch_multi("a", "b", "c") do |key| + key * 2 + end + end + end + end + + class ConnectionPoolBehaviourTest < StoreTest + include ConnectionPoolBehavior + + private + + def store + :redis_cache_store + end + + def emulating_latency + old_redis = Object.send(:remove_const, :Redis) + Object.const_set(:Redis, SlowRedis) + + yield + ensure + Object.send(:remove_const, :Redis) + Object.const_set(:Redis, old_redis) + end + end + + class RedisDistributedConnectionPoolBehaviourTest < ConnectionPoolBehaviourTest + private + def store_options + { url: %w[ redis://localhost:6379/0 redis://localhost:6379/0 ] } + end + end + + # Separate test class so we can omit the namespace which causes expected, + # appropriate complaints about incompatible string encodings. + class KeyEncodingSafetyTest < StoreTest + include EncodedKeyCacheBehavior + + setup do + @cache = ActiveSupport::Cache::RedisCacheStore.new(timeout: 0.1, driver: DRIVER) + @cache.logger = nil + end + end + + class StoreAPITest < StoreTest + end + + class UnavailableRedisClient < Redis::Client + def ensure_connected + raise Redis::BaseConnectionError + end + end + + class FailureSafetyTest < StoreTest + include FailureSafetyBehavior + + private + + def emulating_unavailability + old_client = Redis.send(:remove_const, :Client) + Redis.const_set(:Client, UnavailableRedisClient) + + yield ActiveSupport::Cache::RedisCacheStore.new + ensure + Redis.send(:remove_const, :Client) + Redis.const_set(:Client, old_client) + end + end + + class DeleteMatchedTest < StoreTest + test "deletes keys matching glob" do + @cache.write("foo", "bar") + @cache.write("fu", "baz") + @cache.delete_matched("foo*") + assert_not @cache.exist?("foo") + assert @cache.exist?("fu") + end + + test "fails with regexp matchers" do + assert_raise ArgumentError do + @cache.delete_matched(/OO/i) + end + end + end + + class ClearTest < StoreTest + test "clear all cache key" do + @cache.write("foo", "bar") + @cache.write("fu", "baz") + @cache.clear + assert_not @cache.exist?("foo") + assert_not @cache.exist?("fu") + end + + test "only clear namespace cache key" do + @cache.write("foo", "bar") + @cache.redis.set("fu", "baz") + @cache.clear + assert_not @cache.exist?("foo") + assert @cache.redis.exists("fu") + end + end +end diff --git a/activesupport/test/callback_inheritance_test.rb b/activesupport/test/callback_inheritance_test.rb index 67813a749e..5633b6e2b8 100644 --- a/activesupport/test/callback_inheritance_test.rb +++ b/activesupport/test/callback_inheritance_test.rb @@ -164,10 +164,10 @@ end class DynamicInheritedCallbacks < ActiveSupport::TestCase def test_callbacks_looks_to_the_superclass_before_running child = EmptyChild.new.dispatch - assert !child.performed? + assert_not_predicate child, :performed? EmptyParent.set_callback :dispatch, :before, :perform! child = EmptyChild.new.dispatch - assert child.performed? + assert_predicate child, :performed? end def test_callbacks_should_be_performed_once_in_child_class @@ -176,3 +176,13 @@ class DynamicInheritedCallbacks < ActiveSupport::TestCase assert_equal 1, child.count end end + +class DynamicDefinedCallbacks < ActiveSupport::TestCase + def test_callbacks_should_be_performed_once_in_child_class_after_dynamic_define + GrandParent.define_callbacks(:foo) + GrandParent.set_callback(:foo, :before, :before1) + parent = Parent.new("foo") + parent.run_callbacks(:foo) + assert_equal %w(before1), parent.log + end +end diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 3902e41a60..5c9a3b29e7 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -77,7 +77,7 @@ module CallbacksTest 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 + skip_callback :save, :before, CallbackClass, if: :yes def yes; true; end def no; false; end end @@ -193,13 +193,6 @@ module CallbacksTest before_save Proc.new { |r| r.history << "b00m" }, if: :no before_save Proc.new { |r| r.history << [:before_save, :symbol] }, unless: :no before_save Proc.new { |r| r.history << "b00m" }, unless: :yes - # string - ActiveSupport::Deprecation.silence do - before_save Proc.new { |r| r.history << [:before_save, :string] }, if: "yes" - before_save Proc.new { |r| r.history << "b00m" }, if: "no" - before_save Proc.new { |r| r.history << [:before_save, :string] }, unless: "no" - before_save Proc.new { |r| r.history << "b00m" }, unless: "yes" - end # Combined if and unless before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, if: :yes, unless: :no before_save Proc.new { |r| r.history << "b00m" }, if: :yes, unless: :yes @@ -489,10 +482,9 @@ module CallbacksTest "block in run_callbacks", "tweedle_dum", "block in run_callbacks", - ("call" if RUBY_VERSION < "2.3"), "run_callbacks", "save" - ].compact, call_stack.map(&:label) + ], call_stack.map(&:label) end def test_short_call_stack @@ -592,8 +584,6 @@ module CallbacksTest [:before_save, :proc], [:before_save, :symbol], [:before_save, :symbol], - [:before_save, :string], - [:before_save, :string], [:before_save, :combined_symbol], ], person.history end @@ -839,7 +829,7 @@ module CallbacksTest def test_block_never_called_if_terminated obj = CallbackTerminator.new obj.save - assert !obj.saved + assert_not obj.saved end end @@ -867,7 +857,7 @@ module CallbacksTest def test_block_never_called_if_abort_is_thrown obj = CallbackDefaultTerminator.new obj.save - assert !obj.saved + assert_not obj.saved end end @@ -1182,14 +1172,15 @@ module CallbacksTest end end - class DeprecatedWarningTest < ActiveSupport::TestCase - def test_deprecate_string_conditional_options + class NotSupportedStringConditionalTest < ActiveSupport::TestCase + def test_string_conditional_options klass = Class.new(Record) - assert_deprecated { klass.before_save :tweedle, if: "true" } - assert_deprecated { klass.after_save :tweedle, unless: "false" } - assert_deprecated { klass.skip_callback :save, :before, :tweedle, if: "true" } - assert_deprecated { klass.skip_callback :save, :after, :tweedle, unless: "false" } + assert_raises(ArgumentError) { klass.before_save :tweedle, if: ["true"] } + assert_raises(ArgumentError) { klass.before_save :tweedle, if: "true" } + assert_raises(ArgumentError) { klass.after_save :tweedle, unless: "false" } + assert_raises(ArgumentError) { klass.skip_callback :save, :before, :tweedle, if: "true" } + assert_raises(ArgumentError) { klass.skip_callback :save, :after, :tweedle, unless: "false" } end end diff --git a/activesupport/test/class_cache_test.rb b/activesupport/test/class_cache_test.rb index 7b97028e8c..1ef1939b4b 100644 --- a/activesupport/test/class_cache_test.rb +++ b/activesupport/test/class_cache_test.rb @@ -11,17 +11,17 @@ module ActiveSupport end def test_empty? - assert @cache.empty? + assert_empty @cache @cache.store(ClassCacheTest) - assert !@cache.empty? + assert_not_empty @cache end def test_clear! - assert @cache.empty? + assert_empty @cache @cache.store(ClassCacheTest) - assert !@cache.empty? + assert_not_empty @cache @cache.clear! - assert @cache.empty? + assert_empty @cache end def test_set_key @@ -40,35 +40,35 @@ module ActiveSupport end def test_get_constantizes - assert @cache.empty? + assert_empty @cache assert_equal ClassCacheTest, @cache.get(ClassCacheTest.name) end def test_get_constantizes_fails_on_invalid_names - assert @cache.empty? + assert_empty @cache assert_raise NameError do @cache.get("OmgTotallyInvalidConstantName") end end def test_get_alias - assert @cache.empty? + assert_empty @cache assert_equal @cache[ClassCacheTest.name], @cache.get(ClassCacheTest.name) end def test_safe_get_constantizes - assert @cache.empty? + assert_empty @cache assert_equal ClassCacheTest, @cache.safe_get(ClassCacheTest.name) end def test_safe_get_constantizes_doesnt_fail_on_invalid_names - assert @cache.empty? + assert_empty @cache assert_nil @cache.safe_get("OmgTotallyInvalidConstantName") end def test_new_rejects_strings @cache.store ClassCacheTest.name - assert !@cache.key?(ClassCacheTest.name) + assert_not @cache.key?(ClassCacheTest.name) end def test_store_returns_self diff --git a/activesupport/test/concern_test.rb b/activesupport/test/concern_test.rb index ef75a320d1..98d8f3ee0d 100644 --- a/activesupport/test/concern_test.rb +++ b/activesupport/test/concern_test.rb @@ -91,7 +91,7 @@ class ConcernTest < ActiveSupport::TestCase end end @klass.include test_module - assert_equal false, Object.respond_to?(:test) + assert_not_respond_to Object, :test Qux.class_eval do remove_const :ClassMethods end diff --git a/activesupport/test/concurrency/load_interlock_aware_monitor_test.rb b/activesupport/test/concurrency/load_interlock_aware_monitor_test.rb new file mode 100644 index 0000000000..2d0f45ec5f --- /dev/null +++ b/activesupport/test/concurrency/load_interlock_aware_monitor_test.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "concurrent/atomic/count_down_latch" +require "active_support/concurrency/load_interlock_aware_monitor" + +module ActiveSupport + module Concurrency + class LoadInterlockAwareMonitorTest < ActiveSupport::TestCase + def setup + @monitor = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new + end + + def test_entering_with_no_blocking + assert @monitor.mon_enter + end + + def test_entering_with_blocking + load_interlock_latch = Concurrent::CountDownLatch.new + monitor_latch = Concurrent::CountDownLatch.new + + able_to_use_monitor = false + able_to_load = false + + thread_with_load_interlock = Thread.new do + ActiveSupport::Dependencies.interlock.running do + load_interlock_latch.count_down + monitor_latch.wait + + @monitor.synchronize do + able_to_use_monitor = true + end + end + end + + thread_with_monitor_lock = Thread.new do + @monitor.synchronize do + monitor_latch.count_down + load_interlock_latch.wait + + ActiveSupport::Dependencies.interlock.loading do + able_to_load = true + end + end + end + + thread_with_load_interlock.join + thread_with_monitor_lock.join + + assert able_to_use_monitor + assert able_to_load + end + end + end +end diff --git a/activesupport/test/configurable_test.rb b/activesupport/test/configurable_test.rb index 10719596df..1cf40261dc 100644 --- a/activesupport/test/configurable_test.rb +++ b/activesupport/test/configurable_test.rb @@ -43,11 +43,11 @@ class ConfigurableActiveSupport < ActiveSupport::TestCase test "configuration accessors are not available on instance" do instance = Parent.new - assert !instance.respond_to?(:bar) - assert !instance.respond_to?(:bar=) + assert_not_respond_to instance, :bar + assert_not_respond_to instance, :bar= - assert !instance.respond_to?(:baz) - assert !instance.respond_to?(:baz=) + assert_not_respond_to instance, :baz + assert_not_respond_to instance, :baz= end test "configuration accessors can take a default value" do diff --git a/activesupport/test/core_ext/array/conversions_test.rb b/activesupport/test/core_ext/array/conversions_test.rb index 0f919efcb0..0a7c43d421 100644 --- a/activesupport/test/core_ext/array/conversions_test.rb +++ b/activesupport/test/core_ext/array/conversions_test.rb @@ -90,7 +90,7 @@ class ToXmlTest < ActiveSupport::TestCase def test_to_xml_with_hash_elements xml = [ { name: "David", age: 26, age_in_millis: 820497600000 }, - { name: "Jason", age: 31, age_in_millis: BigDecimal.new("1.0") } + { name: "Jason", age: 31, age_in_millis: BigDecimal("1.0") } ].to_xml(skip_instruct: true, indent: 0) assert_equal '<objects type="array"><object>', xml.first(30) @@ -173,7 +173,7 @@ class ToXmlTest < ActiveSupport::TestCase def test_to_xml_with_instruct xml = [ { name: "David", age: 26, age_in_millis: 820497600000 }, - { name: "Jason", age: 31, age_in_millis: BigDecimal.new("1.0") } + { name: "Jason", age: 31, age_in_millis: BigDecimal("1.0") } ].to_xml(skip_instruct: false, indent: 0) assert_match(/^<\?xml [^>]*/, xml) @@ -183,7 +183,7 @@ class ToXmlTest < ActiveSupport::TestCase def test_to_xml_with_block xml = [ { name: "David", age: 26, age_in_millis: 820497600000 }, - { name: "Jason", age: 31, age_in_millis: BigDecimal.new("1.0") } + { name: "Jason", age: 31, age_in_millis: BigDecimal("1.0") } ].to_xml(skip_instruct: true, indent: 0) do |builder| builder.count 2 end diff --git a/activesupport/test/core_ext/array/grouping_test.rb b/activesupport/test/core_ext/array/grouping_test.rb index da9d4963d8..37111a5d7d 100644 --- a/activesupport/test/core_ext/array/grouping_test.rb +++ b/activesupport/test/core_ext/array/grouping_test.rb @@ -4,15 +4,6 @@ require "abstract_unit" require "active_support/core_ext/array" class GroupingTest < ActiveSupport::TestCase - def setup - # In Ruby < 2.4, test we avoid Integer#/ (redefined by mathn) - Fixnum.send :private, :/ unless 0.class == Integer - end - - def teardown - Fixnum.send :public, :/ unless 0.class == Integer - end - def test_in_groups_of_with_perfect_fit groups = [] ("a".."i").to_a.in_groups_of(3) do |group| @@ -116,7 +107,7 @@ class SplitTest < ActiveSupport::TestCase def test_split_with_block a = (1..10).to_a assert_equal [[1, 2], [4, 5], [7, 8], [10]], a.split { |i| i % 3 == 0 } - assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9 , 10], a + assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a end def test_split_with_edge_values diff --git a/activesupport/test/core_ext/bigdecimal_test.rb b/activesupport/test/core_ext/bigdecimal_test.rb index 66e81f1162..62588be33b 100644 --- a/activesupport/test/core_ext/bigdecimal_test.rb +++ b/activesupport/test/core_ext/bigdecimal_test.rb @@ -5,7 +5,7 @@ require "active_support/core_ext/big_decimal" class BigDecimalTest < ActiveSupport::TestCase def test_to_s - bd = BigDecimal.new "0.01" + bd = BigDecimal "0.01" assert_equal "0.01", bd.to_s assert_equal "+0.01", bd.to_s("+F") assert_equal "+0.0 1", bd.to_s("+1F") diff --git a/activesupport/test/core_ext/class_test.rb b/activesupport/test/core_ext/class_test.rb index 9cc006fc63..5ea288738e 100644 --- a/activesupport/test/core_ext/class_test.rb +++ b/activesupport/test/core_ext/class_test.rb @@ -30,11 +30,11 @@ class ClassTest < ActiveSupport::TestCase def test_descendants_excludes_singleton_classes klass = Parent.new.singleton_class - refute Parent.descendants.include?(klass), "descendants should not include singleton classes" + assert_not Parent.descendants.include?(klass), "descendants should not include singleton classes" end def test_subclasses_excludes_singleton_classes klass = Parent.new.singleton_class - refute Parent.subclasses.include?(klass), "subclasses should not include singleton classes" + assert_not Parent.subclasses.include?(klass), "subclasses should not include singleton classes" end end diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index 256353c309..b77ea22701 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -9,6 +9,11 @@ module DateAndTimeBehavior end def test_prev_day + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-2) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(0) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(1) + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(2) assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).prev_day.prev_day end @@ -19,6 +24,11 @@ module DateAndTimeBehavior end def test_next_day + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-2) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(0) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(1) + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(2) assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day assert_equal date_time_init(2005, 3, 2, 10, 10, 10), date_time_init(2005, 2, 28, 10, 10, 10).next_day.next_day end @@ -151,6 +161,16 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 5, 15, 15, 10), date_time_init(2015, 1, 3, 15, 15, 10).next_weekday end + def test_next_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(0) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(1) + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month.next_month + end + def test_next_month_on_31st assert_equal date_time_init(2005, 9, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_month end @@ -160,7 +180,13 @@ module DateAndTimeBehavior end def test_next_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-2) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(0) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(1) + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(2) assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year.next_year end def test_prev_week @@ -203,6 +229,16 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 2, 15, 15, 10), date_time_init(2015, 1, 4, 15, 15, 10).prev_weekday end + def test_prev_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(0) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(1) + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month.prev_month + end + def test_prev_month_on_31st assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 3, 31, 10, 10, 10).prev_month end @@ -212,7 +248,21 @@ module DateAndTimeBehavior end def test_prev_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-2) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(0) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(1) + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(2) assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year.prev_year + end + + def test_last_month_on_31st + assert_equal date_time_init(2004, 2, 29, 0, 0, 0), date_time_init(2004, 3, 31, 0, 0, 0).last_month + end + + def test_last_year + assert_equal date_time_init(2004, 6, 5, 10, 0, 0), date_time_init(2005, 6, 5, 10, 0, 0).last_year end def test_days_to_week_start @@ -247,24 +297,24 @@ module DateAndTimeBehavior def test_beginning_of_week assert_equal date_time_init(2005, 1, 31, 0, 0, 0), date_time_init(2005, 2, 4, 10, 10, 10).beginning_of_week - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 28, 0, 0, 0).beginning_of_week #monday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 29, 0, 0, 0).beginning_of_week #tuesday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 30, 0, 0, 0).beginning_of_week #wednesday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 01, 0, 0, 0).beginning_of_week #thursday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 02, 0, 0, 0).beginning_of_week #friday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 03, 0, 0, 0).beginning_of_week #saturday - assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 04, 0, 0, 0).beginning_of_week #sunday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 28, 0, 0, 0).beginning_of_week # monday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 29, 0, 0, 0).beginning_of_week # tuesday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 30, 0, 0, 0).beginning_of_week # wednesday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 01, 0, 0, 0).beginning_of_week # thursday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 02, 0, 0, 0).beginning_of_week # friday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 03, 0, 0, 0).beginning_of_week # saturday + assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 04, 0, 0, 0).beginning_of_week # sunday end def test_end_of_week assert_equal date_time_init(2008, 1, 6, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 12, 31, 10, 10, 10).end_of_week - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 27, 0, 0, 0).end_of_week #monday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 28, 0, 0, 0).end_of_week #tuesday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 29, 0, 0, 0).end_of_week #wednesday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 30, 0, 0, 0).end_of_week #thursday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 31, 0, 0, 0).end_of_week #friday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 01, 0, 0, 0).end_of_week #saturday - assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 02, 0, 0, 0).end_of_week #sunday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 27, 0, 0, 0).end_of_week # monday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 28, 0, 0, 0).end_of_week # tuesday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 29, 0, 0, 0).end_of_week # wednesday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 30, 0, 0, 0).end_of_week # thursday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 31, 0, 0, 0).end_of_week # friday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 01, 0, 0, 0).end_of_week # saturday + assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 02, 0, 0, 0).end_of_week # sunday end def test_end_of_month @@ -278,6 +328,26 @@ module DateAndTimeBehavior assert_equal date_time_init(2007, 12, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 12, 31, 10, 10, 10).end_of_year end + def test_next_occurring + assert_equal date_time_init(2017, 12, 18, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:monday) + assert_equal date_time_init(2017, 12, 19, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:tuesday) + assert_equal date_time_init(2017, 12, 20, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:wednesday) + assert_equal date_time_init(2017, 12, 21, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:thursday) + assert_equal date_time_init(2017, 12, 15, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:friday) + assert_equal date_time_init(2017, 12, 16, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:saturday) + assert_equal date_time_init(2017, 12, 17, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:sunday) + end + + def test_prev_occurring + assert_equal date_time_init(2017, 12, 11, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:monday) + assert_equal date_time_init(2017, 12, 12, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:tuesday) + assert_equal date_time_init(2017, 12, 13, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:wednesday) + assert_equal date_time_init(2017, 12, 7, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:thursday) + assert_equal date_time_init(2017, 12, 8, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:friday) + assert_equal date_time_init(2017, 12, 9, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:saturday) + assert_equal date_time_init(2017, 12, 10, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:sunday) + end + def test_monday_with_default_beginning_of_week_set with_bw_default(:saturday) do assert_equal date_time_init(2012, 9, 17, 0, 0, 0), date_time_init(2012, 9, 18, 0, 0, 0).monday @@ -291,28 +361,40 @@ module DateAndTimeBehavior end def test_on_weekend_on_saturday - assert date_time_init(2015, 1, 3, 0, 0, 0).on_weekend? - assert date_time_init(2015, 1, 3, 15, 15, 10).on_weekend? + assert_predicate date_time_init(2015, 1, 3, 0, 0, 0), :on_weekend? + assert_predicate date_time_init(2015, 1, 3, 15, 15, 10), :on_weekend? end def test_on_weekend_on_sunday - assert date_time_init(2015, 1, 4, 0, 0, 0).on_weekend? - assert date_time_init(2015, 1, 4, 15, 15, 10).on_weekend? + assert_predicate date_time_init(2015, 1, 4, 0, 0, 0), :on_weekend? + assert_predicate date_time_init(2015, 1, 4, 15, 15, 10), :on_weekend? end def test_on_weekend_on_monday - assert_not date_time_init(2015, 1, 5, 0, 0, 0).on_weekend? - assert_not date_time_init(2015, 1, 5, 15, 15, 10).on_weekend? + assert_not_predicate date_time_init(2015, 1, 5, 0, 0, 0), :on_weekend? + assert_not_predicate date_time_init(2015, 1, 5, 15, 15, 10), :on_weekend? end def test_on_weekday_on_sunday - assert_not date_time_init(2015, 1, 4, 0, 0, 0).on_weekday? - assert_not date_time_init(2015, 1, 4, 15, 15, 10).on_weekday? + assert_not_predicate date_time_init(2015, 1, 4, 0, 0, 0), :on_weekday? + assert_not_predicate date_time_init(2015, 1, 4, 15, 15, 10), :on_weekday? end def test_on_weekday_on_monday - assert date_time_init(2015, 1, 5, 0, 0, 0).on_weekday? - assert date_time_init(2015, 1, 5, 15, 15, 10).on_weekday? + assert_predicate date_time_init(2015, 1, 5, 0, 0, 0), :on_weekday? + assert_predicate date_time_init(2015, 1, 5, 15, 15, 10), :on_weekday? + end + + def test_before + assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 5, 12, 0, 0)) + assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 6, 12, 0, 0)) + assert_equal true, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 7, 12, 0, 0)) + end + + def test_after + assert_equal true, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 5, 12, 0, 0)) + assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 6, 12, 0, 0)) + assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 7, 12, 0, 0)) end def with_bw_default(bw = :monday) diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index b8672eac4b..b8652884ce 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -95,11 +95,11 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end def test_beginning_of_week_in_calendar_reform - assert_equal Date.new(1582, 10, 1), Date.new(1582, 10, 15).beginning_of_week #friday + assert_equal Date.new(1582, 10, 1), Date.new(1582, 10, 15).beginning_of_week # friday end def test_end_of_week_in_calendar_reform - assert_equal Date.new(1582, 10, 17), Date.new(1582, 10, 4).end_of_week #thursday + assert_equal Date.new(1582, 10, 17), Date.new(1582, 10, 4).end_of_week # thursday end def test_end_of_year @@ -120,10 +120,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582, 10, 4), Date.new(1583, 10, 14).prev_year end - def test_last_year - assert_equal Date.new(2004, 6, 5), Date.new(2005, 6, 5).last_year - end - def test_last_year_in_leap_years assert_equal Date.new(1999, 2, 28), Date.new(2000, 2, 29).last_year end @@ -148,7 +144,7 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(2012, 9, 28), Date.new(2005, 2, 28).advance(years: 7, months: 7) assert_equal Date.new(2013, 10, 3), Date.new(2005, 2, 28).advance(years: 7, months: 19, days: 5) assert_equal Date.new(2013, 10, 17), Date.new(2005, 2, 28).advance(years: 7, months: 19, weeks: 2, days: 5) - assert_equal Date.new(2005, 2, 28), Date.new(2004, 2, 29).advance(years: 1) #leap day plus one year + assert_equal Date.new(2005, 2, 28), Date.new(2004, 2, 29).advance(years: 1) # leap day plus one year end def test_advance_does_first_years_and_then_days @@ -185,10 +181,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582, 10, 18), Date.new(1582, 10, 4).next_week end - def test_last_month_on_31st - assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).last_month - end - def test_last_quarter_on_31st assert_equal Date.new(2004, 2, 29), Date.new(2004, 5, 31).last_quarter end @@ -394,11 +386,11 @@ end class DateExtBehaviorTest < ActiveSupport::TestCase def test_date_acts_like_date - assert Date.new.acts_like_date? + assert_predicate Date.new, :acts_like_date? end def test_blank? - assert_not Date.new.blank? + assert_not_predicate Date.new, :blank? end def test_freeze_doesnt_clobber_memoized_instance_methods diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index a3c2018a31..894fb80cba 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -30,28 +30,6 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase end end - def test_next_occur - datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday - assert_equal datetime.next_occurring(:monday), datetime.since(2.days) - assert_equal datetime.next_occurring(:tuesday), datetime.since(3.days) - assert_equal datetime.next_occurring(:wednesday), datetime.since(4.days) - assert_equal datetime.next_occurring(:thursday), datetime.since(5.days) - assert_equal datetime.next_occurring(:friday), datetime.since(6.days) - assert_equal datetime.next_occurring(:saturday), datetime.since(1.week) - assert_equal datetime.next_occurring(:sunday), datetime.since(1.day) - end - - def test_prev_occur - datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday - assert_equal datetime.prev_occurring(:monday), datetime.ago(5.days) - assert_equal datetime.prev_occurring(:tuesday), datetime.ago(4.days) - assert_equal datetime.prev_occurring(:wednesday), datetime.ago(3.days) - assert_equal datetime.prev_occurring(:thursday), datetime.ago(2.days) - assert_equal datetime.prev_occurring(:friday), datetime.ago(1.day) - assert_equal datetime.prev_occurring(:saturday), datetime.ago(1.week) - assert_equal datetime.prev_occurring(:sunday), datetime.ago(6.days) - end - def test_readable_inspect datetime = DateTime.new(2005, 2, 21, 14, 30, 0) assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.readable_inspect @@ -162,10 +140,6 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2005, 4, 30, 23, 59, Rational(59999999999, 1000000000)), DateTime.civil(2005, 4, 20, 10, 10, 10).end_of_month end - def test_last_year - assert_equal DateTime.civil(2004, 6, 5, 10), DateTime.civil(2005, 6, 5, 10, 0, 0).last_year - end - def test_ago assert_equal DateTime.civil(2005, 2, 22, 10, 10, 9), DateTime.civil(2005, 2, 22, 10, 10, 10).ago(1) assert_equal DateTime.civil(2005, 2, 22, 9, 10, 10), DateTime.civil(2005, 2, 22, 10, 10, 10).ago(3600) @@ -213,7 +187,7 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2013, 10, 3, 15, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, days: 5) assert_equal DateTime.civil(2013, 10, 17, 15, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5) assert_equal DateTime.civil(2001, 12, 27, 15, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1) - assert_equal DateTime.civil(2005, 2, 28, 15, 15, 10), DateTime.civil(2004, 2, 29, 15, 15, 10).advance(years: 1) #leap day plus one year + assert_equal DateTime.civil(2005, 2, 28, 15, 15, 10), DateTime.civil(2004, 2, 29, 15, 15, 10).advance(years: 1) # leap day plus one year assert_equal DateTime.civil(2005, 2, 28, 20, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(hours: 5) assert_equal DateTime.civil(2005, 2, 28, 15, 22, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(minutes: 7) assert_equal DateTime.civil(2005, 2, 28, 15, 15, 19), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(seconds: 9) @@ -248,10 +222,6 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2016, 2, 29), DateTime.civil(2016, 3, 7).last_week end - def test_last_month_on_31st - assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 3, 31).last_month - end - def test_last_quarter_on_31st assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 5, 31).last_quarter end @@ -345,15 +315,15 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase end def test_acts_like_date - assert DateTime.new.acts_like_date? + assert_predicate DateTime.new, :acts_like_date? end def test_acts_like_time - assert DateTime.new.acts_like_time? + assert_predicate DateTime.new, :acts_like_time? end def test_blank? - assert_not DateTime.new.blank? + assert_not_predicate DateTime.new, :blank? end def test_utc? @@ -393,45 +363,45 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase end def test_compare_with_time - assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59) - assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0) + assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59) + assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0) assert_equal(-1, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1)) end def test_compare_with_datetime - assert_equal 1, DateTime.civil(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59) - assert_equal 0, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0) + assert_equal 1, DateTime.civil(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59) + assert_equal 0, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0) assert_equal(-1, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1)) end def test_compare_with_time_with_zone - assert_equal 1, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) - assert_equal 0, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) + assert_equal 1, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) + assert_equal 0, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) 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(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_nil DateTime.civil(2000) <=> "Invalid as Time" end def test_compare_with_integer - assert_equal 1, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440587 - assert_equal 0, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440588 + assert_equal 1, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440587 + assert_equal 0, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440588 assert_equal(-1, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440589) end def test_compare_with_float - assert_equal 1, DateTime.civil(1970) <=> 2440586.5 - assert_equal 0, DateTime.civil(1970) <=> 2440587.5 + assert_equal 1, DateTime.civil(1970) <=> 2440586.5 + assert_equal 0, DateTime.civil(1970) <=> 2440587.5 assert_equal(-1, DateTime.civil(1970) <=> 2440588.5) end def test_compare_with_rational - assert_equal 1, DateTime.civil(1970) <=> Rational(4881173, 2) - assert_equal 0, DateTime.civil(1970) <=> Rational(4881175, 2) + assert_equal 1, DateTime.civil(1970) <=> Rational(4881173, 2) + assert_equal 0, DateTime.civil(1970) <=> Rational(4881175, 2) assert_equal(-1, DateTime.civil(1970) <=> Rational(4881177, 2)) end diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index b3e0cd8bd0..240ae3bde0 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -5,6 +5,7 @@ require "active_support/inflector" require "active_support/time" require "active_support/json" require "time_zone_test_helpers" +require "yaml" class DurationTest < ActiveSupport::TestCase include TimeZoneTestHelpers @@ -15,30 +16,30 @@ class DurationTest < ActiveSupport::TestCase assert_kind_of ActiveSupport::Duration, d assert_kind_of Numeric, d assert_kind_of Integer, d - assert !d.is_a?(Hash) + assert_not d.is_a?(Hash) k = Class.new class << k; undef_method :== end - assert !d.is_a?(k) + assert_not d.is_a?(k) end def test_instance_of - assert 1.minute.instance_of?(1.class) + assert 1.minute.instance_of?(Integer) assert 2.days.instance_of?(ActiveSupport::Duration) - assert !3.second.instance_of?(Numeric) + assert_not 3.second.instance_of?(Numeric) end def test_threequals assert ActiveSupport::Duration === 1.day - assert !(ActiveSupport::Duration === 1.day.to_i) - assert !(ActiveSupport::Duration === "foo") + assert_not (ActiveSupport::Duration === 1.day.to_i) + assert_not (ActiveSupport::Duration === "foo") end def test_equals assert 1.day == 1.day assert 1.day == 1.day.to_i assert 1.day.to_i == 1.day - assert !(1.day == "foo") + assert_not (1.day == "foo") end def test_to_s @@ -52,11 +53,11 @@ class DurationTest < ActiveSupport::TestCase assert 1.minute.eql?(1.minute) assert 1.minute.eql?(60.seconds) assert 2.days.eql?(48.hours) - assert !1.second.eql?(1) - assert !1.eql?(1.second) + assert_not 1.second.eql?(1) + assert_not 1.eql?(1.second) assert 1.minute.eql?(180.seconds - 2.minutes) - assert !1.minute.eql?(60) - assert !1.minute.eql?("foo") + assert_not 1.minute.eql?(60) + assert_not 1.minute.eql?("foo") end def test_inspect @@ -71,6 +72,8 @@ class DurationTest < ActiveSupport::TestCase assert_equal "7 days", 7.days.inspect assert_equal "1 week", 1.week.inspect assert_equal "2 weeks", 1.fortnight.inspect + assert_equal "0 seconds", (10 % 5.seconds).inspect + assert_equal "10 minutes", (10.minutes + 0.seconds).inspect end def test_inspect_locale @@ -160,7 +163,7 @@ class DurationTest < ActiveSupport::TestCase end def test_time_plus_duration_returns_same_time_datatype - twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Moscow"] , Time.utc(2016, 4, 28, 00, 45)) + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Moscow"], Time.utc(2016, 4, 28, 00, 45)) now = Time.now.utc %w( second minute hour day week month year ).each do |unit| assert_equal((now + 1.send(unit)).class, Time, "Time + 1.#{unit} must be Time") @@ -640,6 +643,12 @@ class DurationTest < ActiveSupport::TestCase assert_equal time + d1, time + d2 end + def test_durations_survive_yaml_serialization + d1 = YAML.load(YAML.dump(10.minutes)) + assert_equal 600, d1.to_i + assert_equal 660, (d1 + 60).to_i + end + private def eastern_time_zone if Gem.win_platform? diff --git a/activesupport/test/core_ext/file_test.rb b/activesupport/test/core_ext/file_test.rb index 23e3c277cc..9c97700e5d 100644 --- a/activesupport/test/core_ext/file_test.rb +++ b/activesupport/test/core_ext/file_test.rb @@ -8,7 +8,7 @@ class AtomicWriteTest < ActiveSupport::TestCase contents = "Atomic Text" File.atomic_write(file_name, Dir.pwd) do |file| file.write(contents) - assert !File.exist?(file_name) + assert_not File.exist?(file_name) end assert File.exist?(file_name) assert_equal contents, File.read(file_name) @@ -22,7 +22,7 @@ class AtomicWriteTest < ActiveSupport::TestCase raise "something bad" end rescue - assert !File.exist?(file_name) + assert_not File.exist?(file_name) end def test_atomic_write_preserves_file_permissions @@ -50,7 +50,7 @@ class AtomicWriteTest < ActiveSupport::TestCase contents = "Atomic Text" File.atomic_write(file_name, Dir.pwd) do |file| file.write(contents) - assert !File.exist?(file_name) + assert_not File.exist?(file_name) end assert File.exist?(file_name) assert_equal File.probe_stat_in(Dir.pwd).mode, file_mode diff --git a/activesupport/test/core_ext/hash/transform_values_test.rb b/activesupport/test/core_ext/hash/transform_values_test.rb index d34b7fa7b9..e481b5e4a9 100644 --- a/activesupport/test/core_ext/hash/transform_values_test.rb +++ b/activesupport/test/core_ext/hash/transform_values_test.rb @@ -2,25 +2,16 @@ require "abstract_unit" require "active_support/core_ext/hash/indifferent_access" -require "active_support/core_ext/hash/transform_values" -class TransformValuesTest < ActiveSupport::TestCase - test "transform_values returns a new hash with the values computed from the block" do - original = { a: "a", b: "b" } - mapped = original.transform_values { |v| v + "!" } - - assert_equal({ a: "a", b: "b" }, original) - assert_equal({ a: "a!", b: "b!" }, mapped) - end - - test "transform_values! modifies the values of the original" do - original = { a: "a", b: "b" } - mapped = original.transform_values! { |v| v + "!" } - - assert_equal({ a: "a!", b: "b!" }, original) - assert_same original, mapped +class TransformValuesDeprecatedRequireTest < ActiveSupport::TestCase + test "requiring transform_values is deprecated" do + assert_deprecated do + require "active_support/core_ext/hash/transform_values" + end end +end +class IndifferentTransformValuesTest < ActiveSupport::TestCase test "indifferent access is still indifferent after mapping values" do original = { a: "a", b: "b" }.with_indifferent_access mapped = original.transform_values { |v| v + "!" } @@ -28,50 +19,4 @@ class TransformValuesTest < ActiveSupport::TestCase assert_equal "a!", mapped[:a] assert_equal "a!", mapped["a"] end - - # This is to be consistent with the behavior of Ruby's built in methods - # (e.g. #select, #reject) as of 2.2 - test "default values do not persist during mapping" do - original = Hash.new("foo") - original[:a] = "a" - mapped = original.transform_values { |v| v + "!" } - - assert_equal "a!", mapped[:a] - assert_nil mapped[:b] - end - - test "default procs do not persist after mapping" do - original = Hash.new { "foo" } - original[:a] = "a" - mapped = original.transform_values { |v| v + "!" } - - assert_equal "a!", mapped[:a] - assert_nil mapped[:b] - end - - test "transform_values returns a sized Enumerator if no block is given" do - original = { a: "a", b: "b" } - enumerator = original.transform_values - assert_equal original.size, enumerator.size - assert_equal Enumerator, enumerator.class - end - - test "transform_values! returns a sized Enumerator if no block is given" do - original = { a: "a", b: "b" } - enumerator = original.transform_values! - assert_equal original.size, enumerator.size - assert_equal Enumerator, enumerator.class - end - - test "transform_values is chainable with Enumerable methods" do - original = { a: "a", b: "b" } - mapped = original.transform_values.with_index { |v, i| [v, i].join } - assert_equal({ a: "a0", b: "b1" }, mapped) - end - - test "transform_values! is chainable with Enumerable methods" do - original = { a: "a", b: "b" } - original.transform_values!.with_index { |v, i| [v, i].join } - assert_equal({ a: "a0", b: "b1" }, original) - end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 746d7ad416..f4f0dd6b31 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -45,8 +45,6 @@ class HashExtTest < ActiveSupport::TestCase assert_respond_to h, :deep_stringify_keys! assert_respond_to h, :to_options assert_respond_to h, :to_options! - assert_respond_to h, :compact - assert_respond_to h, :compact! assert_respond_to h, :except assert_respond_to h, :except! end @@ -446,7 +444,7 @@ class HashExtTest < ActiveSupport::TestCase original.freeze assert_nothing_raised { original.except(:a) } - assert_raise(RuntimeError) { original.except!(:a) } + assert_raise(frozen_error_class) { original.except!(:a) } end def test_except_does_not_delete_values_in_original @@ -456,38 +454,10 @@ class HashExtTest < ActiveSupport::TestCase end end - def test_compact - hash_contain_nil_value = @symbols.merge(z: nil) - hash_with_only_nil_values = { a: nil, b: nil } - - h = hash_contain_nil_value.dup - assert_equal(@symbols, h.compact) - assert_equal(hash_contain_nil_value, h) - - h = hash_with_only_nil_values.dup - assert_equal({}, h.compact) - assert_equal(hash_with_only_nil_values, h) - - h = @symbols.dup - assert_equal(@symbols, h.compact) - assert_equal(@symbols, h) - end - - def test_compact! - hash_contain_nil_value = @symbols.merge(z: nil) - hash_with_only_nil_values = { a: nil, b: nil } - - h = hash_contain_nil_value.dup - assert_equal(@symbols, h.compact!) - assert_equal(@symbols, h) - - h = hash_with_only_nil_values.dup - assert_equal({}, h.compact!) - assert_equal({}, h) - - h = @symbols.dup - assert_nil(h.compact!) - assert_equal(@symbols, h) + def test_requiring_compact_is_deprecated + assert_deprecated do + require "active_support/core_ext/hash/compact" + end end end @@ -1061,7 +1031,7 @@ class HashToXmlTest < ActiveSupport::TestCase </alert> XML alert_at = Hash.from_xml(alert_xml)["alert"]["alert_at"] - assert alert_at.utc? + assert_predicate alert_at, :utc? assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at end @@ -1072,7 +1042,7 @@ class HashToXmlTest < ActiveSupport::TestCase </alert> XML alert_at = Hash.from_xml(alert_xml)["alert"]["alert_at"] - assert alert_at.utc? + assert_predicate alert_at, :utc? assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at end @@ -1083,7 +1053,7 @@ class HashToXmlTest < ActiveSupport::TestCase </alert> XML alert_at = Hash.from_xml(alert_xml)["alert"]["alert_at"] - assert alert_at.utc? + assert_predicate alert_at, :utc? assert_equal 2050, alert_at.year assert_equal 2, alert_at.month assert_equal 10, alert_at.day diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb index 14169b084d..5691dc5341 100644 --- a/activesupport/test/core_ext/integer_ext_test.rb +++ b/activesupport/test/core_ext/integer_ext_test.rb @@ -8,14 +8,14 @@ class IntegerExtTest < ActiveSupport::TestCase def test_multiple_of [ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) } - [ -7, 7, 14 ].each { |i| assert ! i.multiple_of?(6) } + [ -7, 7, 14 ].each { |i| assert_not i.multiple_of?(6) } # test the 0 edge case assert 0.multiple_of?(0) - assert !5.multiple_of?(0) + assert_not 5.multiple_of?(0) # test with a prime - [2, 3, 5, 7].each { |i| assert !PRIME.multiple_of?(i) } + [2, 3, 5, 7].each { |i| assert_not PRIME.multiple_of?(i) } end def test_ordinalize diff --git a/activesupport/test/core_ext/load_error_test.rb b/activesupport/test/core_ext/load_error_test.rb index 4fdd228ff8..41b11d0c33 100644 --- a/activesupport/test/core_ext/load_error_test.rb +++ b/activesupport/test/core_ext/load_error_test.rb @@ -5,7 +5,7 @@ require "active_support/core_ext/load_error" class TestLoadError < ActiveSupport::TestCase def test_with_require - assert_raise(LoadError) { require 'no_this_file_don\'t_exist' } + assert_raise(LoadError) { require "no_this_file_don't_exist" } end def test_with_load assert_raise(LoadError) { load "nor_does_this_one" } diff --git a/activesupport/test/core_ext/module/anonymous_test.rb b/activesupport/test/core_ext/module/anonymous_test.rb index 606f22c9b5..e03c217015 100644 --- a/activesupport/test/core_ext/module/anonymous_test.rb +++ b/activesupport/test/core_ext/module/anonymous_test.rb @@ -5,12 +5,12 @@ require "active_support/core_ext/module/anonymous" class AnonymousTest < ActiveSupport::TestCase test "an anonymous class or module are anonymous" do - assert Module.new.anonymous? - assert Class.new.anonymous? + assert_predicate Module.new, :anonymous? + assert_predicate Class.new, :anonymous? end test "a named class or module are not anonymous" do - assert !Kernel.anonymous? - assert !Object.anonymous? + assert_not_predicate Kernel, :anonymous? + assert_not_predicate Object, :anonymous? end end diff --git a/activesupport/test/core_ext/module/attr_internal_test.rb b/activesupport/test/core_ext/module/attr_internal_test.rb index c2a28eced4..9a65f75497 100644 --- a/activesupport/test/core_ext/module/attr_internal_test.rb +++ b/activesupport/test/core_ext/module/attr_internal_test.rb @@ -12,7 +12,7 @@ class AttrInternalTest < ActiveSupport::TestCase def test_reader assert_nothing_raised { @target.attr_internal_reader :foo } - assert !@instance.instance_variable_defined?("@_foo") + assert_not @instance.instance_variable_defined?("@_foo") assert_raise(NoMethodError) { @instance.foo = 1 } @instance.instance_variable_set("@_foo", 1) @@ -22,7 +22,7 @@ class AttrInternalTest < ActiveSupport::TestCase def test_writer assert_nothing_raised { @target.attr_internal_writer :foo } - assert !@instance.instance_variable_defined?("@_foo") + assert_not @instance.instance_variable_defined?("@_foo") assert_nothing_raised { assert_equal 1, @instance.foo = 1 } assert_equal 1, @instance.instance_variable_get("@_foo") @@ -32,7 +32,7 @@ class AttrInternalTest < ActiveSupport::TestCase def test_accessor assert_nothing_raised { @target.attr_internal :foo } - assert !@instance.instance_variable_defined?("@_foo") + assert_not @instance.instance_variable_defined?("@_foo") assert_nothing_raised { assert_equal 1, @instance.foo = 1 } assert_equal 1, @instance.instance_variable_get("@_foo") @@ -44,10 +44,10 @@ class AttrInternalTest < ActiveSupport::TestCase assert_nothing_raised { Module.attr_internal_naming_format = "@abc%sdef" } @target.attr_internal :foo - assert !@instance.instance_variable_defined?("@_foo") - assert !@instance.instance_variable_defined?("@abcfoodef") + assert_not @instance.instance_variable_defined?("@_foo") + assert_not @instance.instance_variable_defined?("@abcfoodef") assert_nothing_raised { @instance.foo = 1 } - assert !@instance.instance_variable_defined?("@_foo") + assert_not @instance.instance_variable_defined?("@_foo") assert @instance.instance_variable_defined?("@abcfoodef") ensure Module.attr_internal_naming_format = "@_%s" diff --git a/activesupport/test/core_ext/module/attribute_accessor_per_thread_test.rb b/activesupport/test/core_ext/module/attribute_accessor_per_thread_test.rb index e0fbd1002c..e0e331fc91 100644 --- a/activesupport/test/core_ext/module/attribute_accessor_per_thread_test.rb +++ b/activesupport/test/core_ext/module/attribute_accessor_per_thread_test.rb @@ -43,22 +43,22 @@ class ModuleAttributeAccessorPerThreadTest < ActiveSupport::TestCase assert_respond_to @class, :foo assert_respond_to @class, :foo= assert_respond_to @object, :bar - assert !@object.respond_to?(:bar=) + assert_not_respond_to @object, :bar= end.join end def test_should_not_create_instance_reader Thread.new do assert_respond_to @class, :shaq - assert !@object.respond_to?(:shaq) + assert_not_respond_to @object, :shaq end.join end def test_should_not_create_instance_accessors Thread.new do assert_respond_to @class, :camp - assert !@object.respond_to?(:camp) - assert !@object.respond_to?(:camp=) + assert_not_respond_to @object, :camp + assert_not_respond_to @object, :camp= end.join end diff --git a/activesupport/test/core_ext/module/attribute_accessor_test.rb b/activesupport/test/core_ext/module/attribute_accessor_test.rb index f1d6859a88..33c583947a 100644 --- a/activesupport/test/core_ext/module/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/module/attribute_accessor_test.rb @@ -65,18 +65,18 @@ class ModuleAttributeAccessorTest < ActiveSupport::TestCase assert_respond_to @module, :foo assert_respond_to @module, :foo= assert_respond_to @object, :bar - assert !@object.respond_to?(:bar=) + assert_not_respond_to @object, :bar= end def test_should_not_create_instance_reader assert_respond_to @module, :shaq - assert !@object.respond_to?(:shaq) + assert_not_respond_to @object, :shaq end def test_should_not_create_instance_accessors assert_respond_to @module, :camp - assert !@object.respond_to?(:camp) - assert !@object.respond_to?(:camp=) + assert_not_respond_to @object, :camp + assert_not_respond_to @object, :camp= end def test_should_raise_name_error_if_attribute_name_is_invalid diff --git a/activesupport/test/core_ext/module/attribute_aliasing_test.rb b/activesupport/test/core_ext/module/attribute_aliasing_test.rb index 187a0f4da2..81aac224f9 100644 --- a/activesupport/test/core_ext/module/attribute_aliasing_test.rb +++ b/activesupport/test/core_ext/module/attribute_aliasing_test.rb @@ -30,15 +30,15 @@ class AttributeAliasingTest < ActiveSupport::TestCase def test_attribute_alias e = AttributeAliasing::Email.new - assert !e.subject? + assert_not_predicate e, :subject? e.title = "Upgrade computer" assert_equal "Upgrade computer", e.subject - assert e.subject? + assert_predicate e, :subject? e.subject = "We got a long way to go" assert_equal "We got a long way to go", e.title - assert e.title? + assert_predicate e, :title? end def test_aliasing_to_uppercase_attributes @@ -47,15 +47,15 @@ class AttributeAliasingTest < ActiveSupport::TestCase # to more sensible ones, everything goes *foof*. e = AttributeAliasing::Email.new - assert !e.body? - assert !e.Data? + assert_not_predicate e, :body? + assert_not_predicate e, :Data? e.body = "No, really, this is not a joke." assert_equal "No, really, this is not a joke.", e.Data - assert e.Data? + assert_predicate e, :Data? e.Data = "Uppercased methods are the suck" assert_equal "Uppercased methods are the suck", e.body - assert e.body? + assert_predicate e, :body? end end diff --git a/activesupport/test/core_ext/module/concerning_test.rb b/activesupport/test/core_ext/module/concerning_test.rb index 192c3d5a9c..374114c11b 100644 --- a/activesupport/test/core_ext/module/concerning_test.rb +++ b/activesupport/test/core_ext/module/concerning_test.rb @@ -21,7 +21,7 @@ class ModuleConcernTest < ActiveSupport::TestCase # Declares a concern but doesn't include it assert klass.const_defined?(:Baz, false) - assert !ModuleConcernTest.const_defined?(:Baz) + assert_not ModuleConcernTest.const_defined?(:Baz) assert_kind_of ActiveSupport::Concern, klass::Baz assert_not_includes klass.ancestors, klass::Baz, klass.ancestors.inspect @@ -55,10 +55,10 @@ class ModuleConcernTest < ActiveSupport::TestCase end def test_using_class_methods_blocks_instead_of_ClassMethods_module - assert !Foo.respond_to?(:will_be_orphaned) - assert Foo.respond_to?(:hacked_on) - assert Foo.respond_to?(:nicer_dsl) - assert Foo.respond_to?(:doesnt_clobber) + assert_not_respond_to Foo, :will_be_orphaned + assert_respond_to Foo, :hacked_on + assert_respond_to Foo, :nicer_dsl + assert_respond_to Foo, :doesnt_clobber # Orphan in Foo::ClassMethods, not Bar::ClassMethods. assert Foo.const_defined?(:ClassMethods) diff --git a/activesupport/test/core_ext/module/reachable_test.rb b/activesupport/test/core_ext/module/reachable_test.rb index a69fc6839e..f356d46957 100644 --- a/activesupport/test/core_ext/module/reachable_test.rb +++ b/activesupport/test/core_ext/module/reachable_test.rb @@ -5,13 +5,17 @@ require "active_support/core_ext/module/reachable" class AnonymousTest < ActiveSupport::TestCase test "an anonymous class or module is not reachable" do - assert !Module.new.reachable? - assert !Class.new.reachable? + assert_deprecated do + assert_not_predicate Module.new, :reachable? + assert_not_predicate Class.new, :reachable? + end end test "ordinary named classes or modules are reachable" do - assert Kernel.reachable? - assert Object.reachable? + assert_deprecated do + assert_predicate Kernel, :reachable? + assert_predicate Object, :reachable? + end end test "a named class or module whose constant has gone is not reachable" do @@ -21,8 +25,10 @@ class AnonymousTest < ActiveSupport::TestCase self.class.send(:remove_const, :C) self.class.send(:remove_const, :M) - assert !c.reachable? - assert !m.reachable? + assert_deprecated do + assert_not_predicate c, :reachable? + assert_not_predicate m, :reachable? + end end test "a named class or module whose constants store different objects are not reachable" do @@ -35,9 +41,11 @@ class AnonymousTest < ActiveSupport::TestCase eval "class C; end" eval "module M; end" - assert C.reachable? - assert M.reachable? - assert !c.reachable? - assert !m.reachable? + assert_deprecated do + assert_predicate C, :reachable? + assert_predicate M, :reachable? + assert_not_predicate c, :reachable? + assert_not_predicate m, :reachable? + end end end diff --git a/activesupport/test/core_ext/module/remove_method_test.rb b/activesupport/test/core_ext/module/remove_method_test.rb index dbf71b477d..a18fc0a5e4 100644 --- a/activesupport/test/core_ext/module/remove_method_test.rb +++ b/activesupport/test/core_ext/module/remove_method_test.rb @@ -6,22 +6,22 @@ require "active_support/core_ext/module/remove_method" module RemoveMethodTests class A def do_something - return 1 + 1 end def do_something_protected - return 1 + 1 end protected :do_something_protected def do_something_private - return 1 + 1 end private :do_something_private class << self def do_something_else - return 2 + 2 end end end @@ -32,14 +32,14 @@ class RemoveMethodTest < ActiveSupport::TestCase RemoveMethodTests::A.class_eval { remove_possible_method(:do_something) } - assert !RemoveMethodTests::A.new.respond_to?(:do_something) + assert_not_respond_to RemoveMethodTests::A.new, :do_something end def test_remove_singleton_method_from_an_object RemoveMethodTests::A.class_eval { remove_possible_singleton_method(:do_something_else) } - assert !RemoveMethodTests::A.respond_to?(:do_something_else) + assert_not_respond_to RemoveMethodTests::A, :do_something_else end def test_redefine_method_in_an_object diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index e918823074..04692f1484 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -347,7 +347,7 @@ class ModuleTest < ActiveSupport::TestCase def test_delegation_with_method_arguments has_block = HasBlock.new(Block.new) - assert has_block.hello? + assert_predicate has_block, :hello? end def test_delegate_missing_to_with_method @@ -383,9 +383,9 @@ class ModuleTest < ActiveSupport::TestCase end def test_delegate_missing_to_affects_respond_to - assert DecoratedTester.new(@david).respond_to?(:name) - assert_not DecoratedTester.new(@david).respond_to?(:private_name) - assert_not DecoratedTester.new(@david).respond_to?(:my_fake_method) + assert_respond_to DecoratedTester.new(@david), :name + assert_not_respond_to DecoratedTester.new(@david), :private_name + assert_not_respond_to DecoratedTester.new(@david), :my_fake_method assert DecoratedTester.new(@david).respond_to?(:name, true) assert_not DecoratedTester.new(@david).respond_to?(:private_name, true) @@ -414,8 +414,8 @@ class ModuleTest < ActiveSupport::TestCase place = location.new(Somewhere.new("Such street", "Sad city")) - assert_not place.respond_to?(:street) - assert_not place.respond_to?(:city) + assert_not_respond_to place, :street + assert_not_respond_to place, :city assert place.respond_to?(:street, true) # Asking for private method assert place.respond_to?(:city, true) @@ -432,12 +432,79 @@ class ModuleTest < ActiveSupport::TestCase place = location.new(Somewhere.new("Such street", "Sad city")) - assert_not place.respond_to?(:street) - assert_not place.respond_to?(:city) + assert_not_respond_to place, :street + assert_not_respond_to place, :city - assert_not place.respond_to?(:the_street) + assert_not_respond_to place, :the_street assert place.respond_to?(:the_street, true) - assert_not place.respond_to?(:the_city) + assert_not_respond_to place, :the_city assert place.respond_to?(:the_city, true) end + + def test_private_delegate_with_private_option + location = Class.new do + def initialize(place) + @place = place + end + + delegate(:street, :city, to: :@place, private: true) + end + + place = location.new(Somewhere.new("Such street", "Sad city")) + + assert_not_respond_to place, :street + assert_not_respond_to place, :city + + assert place.respond_to?(:street, true) # Asking for private method + assert place.respond_to?(:city, true) + end + + def test_some_public_some_private_delegate_with_private_option + location = Class.new do + def initialize(place) + @place = place + end + + delegate(:street, to: :@place) + delegate(:city, to: :@place, private: true) + end + + place = location.new(Somewhere.new("Such street", "Sad city")) + + assert_respond_to place, :street + assert_not_respond_to place, :city + + assert place.respond_to?(:city, true) # Asking for private method + end + + def test_private_delegate_prefixed_with_private_option + location = Class.new do + def initialize(place) + @place = place + end + + delegate(:street, :city, to: :@place, prefix: :the, private: true) + end + + place = location.new(Somewhere.new("Such street", "Sad city")) + + assert_not_respond_to place, :the_street + assert place.respond_to?(:the_street, true) + assert_not_respond_to place, :the_city + assert place.respond_to?(:the_city, true) + end + + def test_delegate_with_private_option_returns_names_of_delegate_methods + location = Class.new do + def initialize(place) + @place = place + end + end + + assert_equal [:street, :city], + location.delegate(:street, :city, to: :@place, private: true) + + assert_equal [:the_street, :the_city], + location.delegate(:street, :city, to: :@place, prefix: :the, private: true) + end end diff --git a/activesupport/test/core_ext/name_error_test.rb b/activesupport/test/core_ext/name_error_test.rb index d1dace3713..5c6c12ffc7 100644 --- a/activesupport/test/core_ext/name_error_test.rb +++ b/activesupport/test/core_ext/name_error_test.rb @@ -17,7 +17,7 @@ class NameErrorTest < ActiveSupport::TestCase exc = assert_raise NameError do some_method_that_does_not_exist end - assert !exc.missing_name?(:Foo) + assert_not exc.missing_name?(:Foo) assert_nil exc.missing_name end end diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb index d38124b214..5005b9febd 100644 --- a/activesupport/test/core_ext/numeric_ext_test.rb +++ b/activesupport/test/core_ext/numeric_ext_test.rb @@ -302,7 +302,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase assert_equal "40 KB", 41100.to_s(:human_size, precision: 2) assert_equal "1.0 KB", kilobytes(1.0123).to_s(:human_size, precision: 2, strip_insignificant_zeros: false) assert_equal "1.012 KB", kilobytes(1.0123).to_s(:human_size, precision: 3, significant: false) - assert_equal "1 KB", kilobytes(1.0123).to_s(:human_size, precision: 0, significant: true) #ignores significant it precision is 0 + assert_equal "1 KB", kilobytes(1.0123).to_s(:human_size, precision: 0, significant: true) # ignores significant it precision is 0 end def test_to_s__human_size_with_custom_delimiter_and_separator @@ -330,17 +330,17 @@ class NumericExtFormattingTest < ActiveSupport::TestCase assert_equal "489.0 Thousand", 489000.to_s(:human, precision: 4, strip_insignificant_zeros: false) assert_equal "1.2346 Million", 1234567.to_s(:human, precision: 4, significant: false) assert_equal "1,2 Million", 1234567.to_s(:human, precision: 1, significant: false, separator: ",") - assert_equal "1 Million", 1234567.to_s(:human, precision: 0, significant: true, separator: ",") #significant forced to false + assert_equal "1 Million", 1234567.to_s(:human, precision: 0, significant: true, separator: ",") # significant forced to false end def test_number_to_human_with_custom_units - #Only integers + # Only integers volume = { unit: "ml", thousand: "lt", million: "m3" } assert_equal "123 lt", 123456.to_s(:human, units: volume) assert_equal "12 ml", 12.to_s(:human, units: volume) assert_equal "1.23 m3", 1234567.to_s(:human, units: volume) - #Including fractionals + # Including fractionals distance = { mili: "mm", centi: "cm", deci: "dm", unit: "m", ten: "dam", hundred: "hm", thousand: "km" } assert_equal "1.23 mm", 0.00123.to_s(:human, units: distance) assert_equal "1.23 cm", 0.0123.to_s(:human, units: distance) @@ -353,14 +353,14 @@ class NumericExtFormattingTest < ActiveSupport::TestCase assert_equal "1.23 km", 1230.to_s(:human, units: distance) assert_equal "12.3 km", 12300.to_s(:human, units: distance) - #The quantifiers don't need to be a continuous sequence + # The quantifiers don't need to be a continuous sequence gangster = { hundred: "hundred bucks", million: "thousand quids" } assert_equal "1 hundred bucks", 100.to_s(:human, units: gangster) assert_equal "25 hundred bucks", 2500.to_s(:human, units: gangster) assert_equal "25 thousand quids", 25000000.to_s(:human, units: gangster) assert_equal "12300 thousand quids", 12345000000.to_s(:human, units: gangster) - #Spaces are stripped from the resulting string + # Spaces are stripped from the resulting string assert_equal "4", 4.to_s(:human, units: { unit: "", ten: "tens " }) assert_equal "4.5 tens", 45.to_s(:human, units: { unit: "", ten: " tens " }) end @@ -406,86 +406,9 @@ class NumericExtFormattingTest < ActiveSupport::TestCase 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 - - 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? + def test_requiring_inquiry_is_deprecated + assert_deprecated do + require "active_support/core_ext/numeric/inquiry" 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/acts_like_test.rb b/activesupport/test/core_ext/object/acts_like_test.rb index 9f7b81f7fc..31241caf0a 100644 --- a/activesupport/test/core_ext/object/acts_like_test.rb +++ b/activesupport/test/core_ext/object/acts_like_test.rb @@ -17,19 +17,19 @@ class ObjectTests < ActiveSupport::TestCase dt = DateTime.new duck = DuckTime.new - assert !object.acts_like?(:time) - assert !object.acts_like?(:date) + assert_not object.acts_like?(:time) + assert_not object.acts_like?(:date) assert time.acts_like?(:time) - assert !time.acts_like?(:date) + assert_not time.acts_like?(:date) - assert !date.acts_like?(:time) + assert_not date.acts_like?(:time) assert date.acts_like?(:date) assert dt.acts_like?(:time) assert dt.acts_like?(:date) assert duck.acts_like?(:time) - assert !duck.acts_like?(:date) + assert_not duck.acts_like?(:date) end end diff --git a/activesupport/test/core_ext/object/blank_test.rb b/activesupport/test/core_ext/object/blank_test.rb index 749e59ec00..954f415383 100644 --- a/activesupport/test/core_ext/object/blank_test.rb +++ b/activesupport/test/core_ext/object/blank_test.rb @@ -16,8 +16,8 @@ class BlankTest < ActiveSupport::TestCase end end - BLANK = [ EmptyTrue.new, nil, false, "", " ", " \n\t \r ", " ", "\u00a0", [], {} ] - NOT = [ EmptyFalse.new, Object.new, true, 0, 1, "a", [nil], { nil => 0 }, Time.now ] + BLANK = [ EmptyTrue.new, nil, false, "", " ", " \n\t \r ", " ", "\u00a0", [], {}, " ".encode("UTF-16LE") ] + NOT = [ EmptyFalse.new, Object.new, true, 0, 1, "a", [nil], { nil => 0 }, Time.now, "my value".encode("UTF-16LE") ] def test_blank BLANK.each { |v| assert_equal true, v.blank?, "#{v.inspect} should be blank" } diff --git a/activesupport/test/core_ext/object/deep_dup_test.rb b/activesupport/test/core_ext/object/deep_dup_test.rb index 2486592441..1fb26ebac7 100644 --- a/activesupport/test/core_ext/object/deep_dup_test.rb +++ b/activesupport/test/core_ext/object/deep_dup_test.rb @@ -47,7 +47,7 @@ class DeepDupTest < ActiveSupport::TestCase object = Object.new dup = object.deep_dup dup.instance_variable_set(:@a, 1) - assert !object.instance_variable_defined?(:@a) + assert_not object.instance_variable_defined?(:@a) assert dup.instance_variable_defined?(:@a) end diff --git a/activesupport/test/core_ext/object/duplicable_test.rb b/activesupport/test/core_ext/object/duplicable_test.rb index 93f39b00bb..635dd7f281 100644 --- a/activesupport/test/core_ext/object/duplicable_test.rb +++ b/activesupport/test/core_ext/object/duplicable_test.rb @@ -8,16 +8,10 @@ require "active_support/core_ext/numeric/time" class DuplicableTest < ActiveSupport::TestCase if RUBY_VERSION >= "2.5.0" RAISE_DUP = [method(:puts)] - ALLOW_DUP = ["1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal.new("4.56"), nil, false, true, 1, 2.3, Complex(1), Rational(1)] - elsif RUBY_VERSION >= "2.4.1" - RAISE_DUP = [method(:puts), Complex(1), Rational(1)] - ALLOW_DUP = ["1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal.new("4.56"), nil, false, true, 1, 2.3] - elsif RUBY_VERSION >= "2.4.0" # Due to 2.4.0 bug. This elsif cannot be removed unless we drop 2.4.0 support... - RAISE_DUP = [method(:puts), Complex(1), Rational(1), "symbol_from_string".to_sym] - ALLOW_DUP = ["1", Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal.new("4.56"), nil, false, true, 1, 2.3] + ALLOW_DUP = ["1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal("4.56"), nil, false, true, 1, 2.3, Complex(1), Rational(1)] else - RAISE_DUP = [nil, false, true, :symbol, 1, 2.3, method(:puts), Complex(1), Rational(1)] - ALLOW_DUP = ["1", Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal.new("4.56")] + RAISE_DUP = [method(:puts), Complex(1), Rational(1)] + ALLOW_DUP = ["1", "symbol_from_string".to_sym, Object.new, /foo/, [], {}, Time.now, Class.new, Module.new, BigDecimal("4.56"), nil, false, true, 1, 2.3] end def test_duplicable diff --git a/activesupport/test/core_ext/object/inclusion_test.rb b/activesupport/test/core_ext/object/inclusion_test.rb index 52c21f2e8e..8cbb4f848f 100644 --- a/activesupport/test/core_ext/object/inclusion_test.rb +++ b/activesupport/test/core_ext/object/inclusion_test.rb @@ -6,30 +6,30 @@ require "active_support/core_ext/object/inclusion" class InTest < ActiveSupport::TestCase def test_in_array assert 1.in?([1, 2]) - assert !3.in?([1, 2]) + assert_not 3.in?([1, 2]) end def test_in_hash h = { "a" => 100, "b" => 200 } assert "a".in?(h) - assert !"z".in?(h) + assert_not "z".in?(h) end def test_in_string assert "lo".in?("hello") - assert !"ol".in?("hello") + assert_not "ol".in?("hello") assert ?h.in?("hello") end def test_in_range assert 25.in?(1..50) - assert !75.in?(1..50) + assert_not 75.in?(1..50) end def test_in_set s = Set.new([1, 2]) assert 1.in?(s) - assert !3.in?(s) + assert_not 3.in?(s) end module A @@ -45,8 +45,8 @@ class InTest < ActiveSupport::TestCase def test_in_module assert A.in?(B) assert A.in?(C) - assert !A.in?(A) - assert !A.in?(D) + assert_not A.in?(A) + assert_not A.in?(D) end def test_no_method_catching diff --git a/activesupport/test/core_ext/object/instance_variables_test.rb b/activesupport/test/core_ext/object/instance_variables_test.rb index b9ec827954..a3d8daab5b 100644 --- a/activesupport/test/core_ext/object/instance_variables_test.rb +++ b/activesupport/test/core_ext/object/instance_variables_test.rb @@ -19,7 +19,7 @@ class ObjectInstanceVariableTest < ActiveSupport::TestCase end def test_instance_exec_passes_arguments_to_block - assert_equal %w(hello goodbye), "hello".instance_exec("goodbye") { |v| [self, v] } + assert_equal %w(hello goodbye), "hello".dup.instance_exec("goodbye") { |v| [self, v] } end def test_instance_exec_with_frozen_obj @@ -27,7 +27,7 @@ class ObjectInstanceVariableTest < ActiveSupport::TestCase end def test_instance_exec_nested - assert_equal %w(goodbye olleh bar), "hello".instance_exec("goodbye") { |arg| + assert_equal %w(goodbye olleh bar), "hello".dup.instance_exec("goodbye") { |arg| [arg] + instance_exec("bar") { |v| [reverse, v] } } end end diff --git a/activesupport/test/core_ext/object/try_test.rb b/activesupport/test/core_ext/object/try_test.rb index fe68b24bf5..a838334034 100644 --- a/activesupport/test/core_ext/object/try_test.rb +++ b/activesupport/test/core_ext/object/try_test.rb @@ -10,25 +10,25 @@ class ObjectTryTest < ActiveSupport::TestCase def test_nonexisting_method method = :undefined_method - assert !@string.respond_to?(method) + assert_not_respond_to @string, method assert_nil @string.try(method) end def test_nonexisting_method_with_arguments method = :undefined_method - assert !@string.respond_to?(method) + assert_not_respond_to @string, method assert_nil @string.try(method, "llo", "y") end def test_nonexisting_method_bang method = :undefined_method - assert !@string.respond_to?(method) + assert_not_respond_to @string, method assert_raise(NoMethodError) { @string.try!(method) } end def test_nonexisting_method_with_arguments_bang method = :undefined_method - assert !@string.respond_to?(method) + assert_not_respond_to @string, method assert_raise(NoMethodError) { @string.try!(method, "llo", "y") } end @@ -78,7 +78,6 @@ class ObjectTryTest < ActiveSupport::TestCase def test_try_with_private_method_bang klass = Class.new do private - def private_method "private method" end @@ -90,7 +89,6 @@ class ObjectTryTest < ActiveSupport::TestCase def test_try_with_private_method klass = Class.new do private - def private_method "private method" end @@ -109,7 +107,6 @@ class ObjectTryTest < ActiveSupport::TestCase end private - def private_delegator_method "private delegator method" end @@ -120,11 +117,11 @@ class ObjectTryTest < ActiveSupport::TestCase end def test_try_with_method_on_delegator_target - assert_equal 5, Decorator.new(@string).size + assert_equal 5, Decorator.new(@string).try(:size) end def test_try_with_overridden_method_on_delegator - assert_equal "overridden reverse", Decorator.new(@string).reverse + assert_equal "overridden reverse", Decorator.new(@string).try(:reverse) end def test_try_with_private_method_on_delegator @@ -140,7 +137,6 @@ class ObjectTryTest < ActiveSupport::TestCase def test_try_with_private_method_on_delegator_target klass = Class.new do private - def private_method "private method" end @@ -152,7 +148,6 @@ class ObjectTryTest < ActiveSupport::TestCase def test_try_with_private_method_on_delegator_target_bang klass = Class.new do private - def private_method "private method" end diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index a96e3d62e8..7c7a78f461 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -16,6 +16,11 @@ class RangeTest < ActiveSupport::TestCase assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_s(:db) end + def test_to_s_with_alphabets + alphabet_range = ("a".."z") + assert_equal "BETWEEN 'a' AND 'z'", alphabet_range.to_s(:db) + end + def test_to_s_with_numeric number_range = (1..100) assert_equal "BETWEEN '1' AND '100'", number_range.to_s(:db) @@ -32,7 +37,7 @@ class RangeTest < ActiveSupport::TestCase end def test_overlaps_last_exclusive - assert !(1...5).overlaps?(5..10) + assert_not (1...5).overlaps?(5..10) end def test_overlaps_first_inclusive @@ -40,7 +45,7 @@ class RangeTest < ActiveSupport::TestCase end def test_overlaps_first_exclusive - assert !(5..10).overlaps?(1...5) + assert_not (5..10).overlaps?(1...5) end def test_should_include_identical_inclusive @@ -97,28 +102,31 @@ class RangeTest < ActiveSupport::TestCase def test_no_overlaps_on_time time_range_1 = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30) time_range_2 = Time.utc(2005, 12, 10, 17, 31)..Time.utc(2005, 12, 10, 18, 00) - assert !time_range_1.overlaps?(time_range_2) + assert_not time_range_1.overlaps?(time_range_2) end def test_each_on_time_with_zone - twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"] , Time.utc(2006, 11, 28, 10, 30)) + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"], Time.utc(2006, 11, 28, 10, 30)) assert_raises TypeError do ((twz - 1.hour)..twz).each {} end end def test_step_on_time_with_zone - twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"] , Time.utc(2006, 11, 28, 10, 30)) + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"], Time.utc(2006, 11, 28, 10, 30)) assert_raises TypeError do ((twz - 1.hour)..twz).step(1) {} end end def test_include_on_time_with_zone - twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"] , Time.utc(2006, 11, 28, 10, 30)) - assert_raises TypeError do - ((twz - 1.hour)..twz).include?(twz) - end + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"], Time.utc(2006, 11, 28, 10, 30)) + assert ((twz - 1.hour)..twz).include?(twz) + end + + def test_case_equals_on_time_with_zone + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"], Time.utc(2006, 11, 28, 10, 30)) + assert ((twz - 1.hour)..twz) === twz end def test_date_time_with_each diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 9fd6d8ac0f..b8de16cc5e 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -9,9 +9,9 @@ require "constantize_test_cases" require "active_support/inflector" require "active_support/core_ext/string" require "active_support/time" -require "active_support/core_ext/string/strip" require "active_support/core_ext/string/output_safety" require "active_support/core_ext/string/indent" +require "active_support/core_ext/string/strip" require "time_zone_test_helpers" require "yaml" @@ -24,6 +24,10 @@ class StringInflectionsTest < ActiveSupport::TestCase assert_equal "", "".strip_heredoc end + def test_strip_heredoc_on_a_frozen_string + assert "".freeze.strip_heredoc.frozen? + end + def test_strip_heredoc_on_a_string_with_no_lines assert_equal "x", "x".strip_heredoc assert_equal "x", " x".strip_heredoc @@ -197,7 +201,7 @@ class StringInflectionsTest < ActiveSupport::TestCase end def test_string_parameterized_underscore_preserve_case - StringToParameterizePreserceCaseWithUnderscore.each do |normal, slugged| + StringToParameterizePreserveCaseWithUnderscore.each do |normal, slugged| assert_equal(slugged, normal.parameterize(separator: "_", preserve_case: true)) end end @@ -233,11 +237,11 @@ class StringInflectionsTest < ActiveSupport::TestCase s = "hello" assert s.starts_with?("h") assert s.starts_with?("hel") - assert !s.starts_with?("el") + assert_not s.starts_with?("el") assert s.ends_with?("o") assert s.ends_with?("lo") - assert !s.ends_with?("el") + assert_not s.ends_with?("el") end def test_string_squish @@ -259,8 +263,8 @@ class StringInflectionsTest < ActiveSupport::TestCase end def test_string_inquiry - assert "production".inquiry.production? - assert !"production".inquiry.development? + assert_predicate "production".inquiry, :production? + assert_not_predicate "production".inquiry, :development? end def test_truncate @@ -281,6 +285,68 @@ class StringInflectionsTest < ActiveSupport::TestCase assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, omission: "[...]", separator: /\s/) end + def test_truncate_bytes + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16) + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: nil) + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: " ") + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: "🖖") + + assert_equal "👍👍👍…", "👍👍👍👍".truncate_bytes(15) + assert_equal "👍👍👍", "👍👍👍👍".truncate_bytes(15, omission: nil) + assert_equal "👍👍👍 ", "👍👍👍👍".truncate_bytes(15, omission: " ") + assert_equal "👍👍🖖", "👍👍👍👍".truncate_bytes(15, omission: "🖖") + + assert_equal "…", "👍👍👍👍".truncate_bytes(5) + assert_equal "👍", "👍👍👍👍".truncate_bytes(5, omission: nil) + assert_equal "👍 ", "👍👍👍👍".truncate_bytes(5, omission: " ") + assert_equal "🖖", "👍👍👍👍".truncate_bytes(5, omission: "🖖") + + assert_equal "…", "👍👍👍👍".truncate_bytes(4) + assert_equal "👍", "👍👍👍👍".truncate_bytes(4, omission: nil) + assert_equal " ", "👍👍👍👍".truncate_bytes(4, omission: " ") + assert_equal "🖖", "👍👍👍👍".truncate_bytes(4, omission: "🖖") + + assert_raise ArgumentError do + "👍👍👍👍".truncate_bytes(3, omission: "🖖") + end + end + + def test_truncate_bytes_preserves_codepoints + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16) + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: nil) + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: " ") + assert_equal "👍👍👍👍", "👍👍👍👍".truncate_bytes(16, omission: "🖖") + + assert_equal "👍👍👍…", "👍👍👍👍".truncate_bytes(15) + assert_equal "👍👍👍", "👍👍👍👍".truncate_bytes(15, omission: nil) + assert_equal "👍👍👍 ", "👍👍👍👍".truncate_bytes(15, omission: " ") + assert_equal "👍👍🖖", "👍👍👍👍".truncate_bytes(15, omission: "🖖") + + assert_equal "…", "👍👍👍👍".truncate_bytes(5) + assert_equal "👍", "👍👍👍👍".truncate_bytes(5, omission: nil) + assert_equal "👍 ", "👍👍👍👍".truncate_bytes(5, omission: " ") + assert_equal "🖖", "👍👍👍👍".truncate_bytes(5, omission: "🖖") + + assert_equal "…", "👍👍👍👍".truncate_bytes(4) + assert_equal "👍", "👍👍👍👍".truncate_bytes(4, omission: nil) + assert_equal " ", "👍👍👍👍".truncate_bytes(4, omission: " ") + assert_equal "🖖", "👍👍👍👍".truncate_bytes(4, omission: "🖖") + + assert_raise ArgumentError do + "👍👍👍👍".truncate_bytes(3, omission: "🖖") + end + end + + def test_truncates_bytes_preserves_grapheme_clusters + assert_equal "a ", "a ❤️ b".truncate_bytes(2, omission: nil) + assert_equal "a ", "a ❤️ b".truncate_bytes(3, omission: nil) + assert_equal "a ", "a ❤️ b".truncate_bytes(7, omission: nil) + assert_equal "a ❤️", "a ❤️ b".truncate_bytes(8, omission: nil) + + assert_equal "a ", "a 👩❤️👩".truncate_bytes(13, omission: nil) + assert_equal "", "👩❤️👩".truncate_bytes(13, omission: nil) + end + def test_truncate_words assert_equal "Hello Big World!", "Hello Big World!".truncate_words(3) assert_equal "Hello Big...", "Hello Big World!".truncate_words(2) @@ -317,7 +383,7 @@ class StringInflectionsTest < ActiveSupport::TestCase end def test_truncate_should_not_be_html_safe - assert !"Hello World!".truncate(12).html_safe? + assert_not_predicate "Hello World!".truncate(12), :html_safe? end def test_remove @@ -639,7 +705,7 @@ end class StringBehaviourTest < ActiveSupport::TestCase def test_acts_like_string - assert "Bambi".acts_like_string? + assert_predicate "Bambi", :acts_like_string? end end @@ -654,10 +720,10 @@ class CoreExtStringMultibyteTest < ActiveSupport::TestCase end def test_string_should_recognize_utf8_strings - assert UTF8_STRING.is_utf8? - assert ASCII_STRING.is_utf8? - assert !EUC_JP_STRING.is_utf8? - assert !INVALID_UTF8_STRING.is_utf8? + assert_predicate UTF8_STRING, :is_utf8? + assert_predicate ASCII_STRING, :is_utf8? + assert_not_predicate EUC_JP_STRING, :is_utf8? + assert_not_predicate INVALID_UTF8_STRING, :is_utf8? end def test_mb_chars_returns_instance_of_proxy_class @@ -676,12 +742,12 @@ class OutputSafetyTest < ActiveSupport::TestCase end test "A string is unsafe by default" do - assert !@string.html_safe? + assert_not_predicate @string, :html_safe? end test "A string can be marked safe" do string = @string.html_safe - assert string.html_safe? + assert_predicate string, :html_safe? end test "Marking a string safe returns the string" do @@ -689,15 +755,15 @@ class OutputSafetyTest < ActiveSupport::TestCase end test "An integer is safe by default" do - assert 5.html_safe? + assert_predicate 5, :html_safe? end test "a float is safe by default" do - assert 5.7.html_safe? + assert_predicate 5.7, :html_safe? end test "An object is unsafe by default" do - assert !@object.html_safe? + assert_not_predicate @object, :html_safe? end test "Adding an object to a safe string returns a safe string" do @@ -705,7 +771,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string << @object assert_equal "helloother", string - assert string.html_safe? + assert_predicate string, :html_safe? end test "Adding a safe string to another safe string returns a safe string" do @@ -714,7 +780,7 @@ class OutputSafetyTest < ActiveSupport::TestCase @combination = @other_string + string assert_equal "otherhello", @combination - assert @combination.html_safe? + assert_predicate @combination, :html_safe? end test "Adding an unsafe string to a safe string escapes it and returns a safe string" do @@ -725,20 +791,20 @@ class OutputSafetyTest < ActiveSupport::TestCase assert_equal "other<foo>", @combination assert_equal "hello<foo>", @other_combination - assert @combination.html_safe? - assert !@other_combination.html_safe? + assert_predicate @combination, :html_safe? + assert_not_predicate @other_combination, :html_safe? end test "Prepending safe onto unsafe yields unsafe" do @string.prepend "other".html_safe - assert !@string.html_safe? + assert_not_predicate @string, :html_safe? assert_equal "otherhello", @string end test "Prepending unsafe onto safe yields escaped safe" do other = "other".html_safe other.prepend "<foo>" - assert other.html_safe? + assert_predicate other, :html_safe? assert_equal "<foo>other", other end @@ -747,14 +813,14 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string.concat(string) - assert !@other_string.html_safe? + assert_not_predicate @other_string, :html_safe? end test "Concatting unsafe onto safe yields escaped safe" do @other_string = "other".html_safe string = @other_string.concat("<foo>") assert_equal "other<foo>", string - assert string.html_safe? + assert_predicate string, :html_safe? end test "Concatting safe onto safe yields safe" do @@ -762,7 +828,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string.concat(string) - assert @other_string.html_safe? + assert_predicate @other_string, :html_safe? end test "Concatting safe onto unsafe with << yields unsafe" do @@ -770,14 +836,14 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string << string - assert !@other_string.html_safe? + assert_not_predicate @other_string, :html_safe? end test "Concatting unsafe onto safe with << yields escaped safe" do @other_string = "other".html_safe string = @other_string << "<foo>" assert_equal "other<foo>", string - assert string.html_safe? + assert_predicate string, :html_safe? end test "Concatting safe onto safe with << yields safe" do @@ -785,7 +851,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string << string - assert @other_string.html_safe? + assert_predicate @other_string, :html_safe? end test "Concatting safe onto unsafe with % yields unsafe" do @@ -793,7 +859,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string = @other_string % string - assert !@other_string.html_safe? + assert_not_predicate @other_string, :html_safe? end test "Concatting unsafe onto safe with % yields escaped safe" do @@ -801,7 +867,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @other_string % "<foo>" assert_equal "other<foo>", string - assert string.html_safe? + assert_predicate string, :html_safe? end test "Concatting safe onto safe with % yields safe" do @@ -809,7 +875,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe @other_string = @other_string % string - assert @other_string.html_safe? + assert_predicate @other_string, :html_safe? end test "Concatting with % doesn't modify a string" do @@ -823,7 +889,7 @@ class OutputSafetyTest < ActiveSupport::TestCase string = @string.html_safe string = string.concat(13) assert_equal "hello".dup.concat(13), string - assert string.html_safe? + assert_predicate string, :html_safe? end test "emits normal string yaml" do @@ -832,8 +898,8 @@ class OutputSafetyTest < ActiveSupport::TestCase test "call to_param returns a normal string" do string = @string.html_safe - assert string.html_safe? - assert !string.to_param.html_safe? + assert_predicate string, :html_safe? + assert_not_predicate string.to_param, :html_safe? end test "ERB::Util.html_escape should escape unsafe characters" do diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index dc2f4c5ac7..e1cb22fda8 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -178,10 +178,6 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2005, 2, 4, 19, 30, 59, Rational(999999999, 1000)), Time.local(2005, 2, 4, 19, 30, 10).end_of_minute end - def test_last_year - assert_equal Time.local(2004, 6, 5, 10), Time.local(2005, 6, 5, 10, 0, 0).last_year - end - def test_ago assert_equal Time.local(2005, 2, 22, 10, 10, 9), Time.local(2005, 2, 22, 10, 10, 10).ago(1) assert_equal Time.local(2005, 2, 22, 9, 10, 10), Time.local(2005, 2, 22, 10, 10, 10).ago(3600) @@ -455,7 +451,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2013, 10, 3, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, days: 5) assert_equal Time.local(2013, 10, 17, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5) assert_equal Time.local(2001, 12, 27, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1) - assert_equal Time.local(2005, 2, 28, 15, 15, 10), Time.local(2004, 2, 29, 15, 15, 10).advance(years: 1) #leap day plus one year + assert_equal Time.local(2005, 2, 28, 15, 15, 10), Time.local(2004, 2, 29, 15, 15, 10).advance(years: 1) # leap day plus one year assert_equal Time.local(2005, 2, 28, 20, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(hours: 5) assert_equal Time.local(2005, 2, 28, 15, 22, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(minutes: 7) assert_equal Time.local(2005, 2, 28, 15, 15, 19), Time.local(2005, 2, 28, 15, 15, 10).advance(seconds: 9) @@ -477,7 +473,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.utc(2013, 10, 3, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).advance(years: 7, months: 19, days: 11) assert_equal Time.utc(2013, 10, 17, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5) assert_equal Time.utc(2001, 12, 27, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1) - assert_equal Time.utc(2005, 2, 28, 15, 15, 10), Time.utc(2004, 2, 29, 15, 15, 10).advance(years: 1) #leap day plus one year + assert_equal Time.utc(2005, 2, 28, 15, 15, 10), Time.utc(2004, 2, 29, 15, 15, 10).advance(years: 1) # leap day plus one year assert_equal Time.utc(2005, 2, 28, 20, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(hours: 5) assert_equal Time.utc(2005, 2, 28, 15, 22, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(minutes: 7) assert_equal Time.utc(2005, 2, 28, 15, 15, 19), Time.utc(2005, 2, 28, 15, 15, 10).advance(seconds: 9) @@ -499,7 +495,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.new(2013, 10, 3, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").advance(years: 7, months: 19, days: 11) assert_equal Time.new(2013, 10, 17, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(years: 7, months: 19, weeks: 2, days: 5) assert_equal Time.new(2001, 12, 27, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(years: -3, months: -2, days: -1) - assert_equal Time.new(2005, 2, 28, 15, 15, 10, "-08:00"), Time.new(2004, 2, 29, 15, 15, 10, "-08:00").advance(years: 1) #leap day plus one year + assert_equal Time.new(2005, 2, 28, 15, 15, 10, "-08:00"), Time.new(2004, 2, 29, 15, 15, 10, "-08:00").advance(years: 1) # leap day plus one year assert_equal Time.new(2005, 2, 28, 20, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(hours: 5) assert_equal Time.new(2005, 2, 28, 15, 22, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(minutes: 7) assert_equal Time.new(2005, 2, 28, 15, 15, 19, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(seconds: 9) @@ -664,10 +660,6 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end - def test_last_month_on_31st - assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).last_month - end - def test_xmlschema_is_available assert_nothing_raised { Time.now.xmlschema } end @@ -745,7 +737,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_acts_like_time - assert Time.new.acts_like_time? + assert_predicate Time.new, :acts_like_time? end def test_formatted_offset_with_utc @@ -764,26 +756,26 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_compare_with_time - assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999) - assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0) + assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999) + assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0) assert_equal(-1, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0, 001)) end def test_compare_with_datetime - assert_equal 1, Time.utc(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59) - assert_equal 0, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0) + assert_equal 1, Time.utc(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59) + assert_equal 0, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0) assert_equal(-1, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1)) end def test_compare_with_time_with_zone - assert_equal 1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) - assert_equal 0, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) + assert_equal 1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) + assert_equal 0, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) 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(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_nil Time.utc(2000) <=> "Invalid as Time" end @@ -871,11 +863,11 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_minus_with_time_with_zone - assert_equal 86_400.0, Time.utc(2000, 1, 2) - ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1), ActiveSupport::TimeZone["UTC"]) + assert_equal 86_400.0, Time.utc(2000, 1, 2) - ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1), ActiveSupport::TimeZone["UTC"]) end def test_minus_with_datetime - assert_equal 86_400.0, Time.utc(2000, 1, 2) - DateTime.civil(2000, 1, 1) + assert_equal 86_400.0, Time.utc(2000, 1, 2) - DateTime.civil(2000, 1, 1) end def test_time_created_with_local_constructor_cannot_represent_times_during_hour_skipped_by_dst @@ -883,7 +875,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase # On Apr 2 2006 at 2:00AM in US, clocks were moved forward to 3:00AM. # Therefore, 2AM EST doesn't exist for this date; Time.local fails over to 3:00AM EDT assert_equal Time.local(2006, 4, 2, 3), Time.local(2006, 4, 2, 2) - assert Time.local(2006, 4, 2, 2).dst? + assert_predicate Time.local(2006, 4, 2, 2), :dst? end end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 0f80a24758..e650209268 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -3,7 +3,6 @@ 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 @@ -50,6 +49,12 @@ class TimeWithZoneTest < ActiveSupport::TestCase assert_raise(ArgumentError) { @twz.in_time_zone(Object.new) } end + def test_in_time_zone_with_ambiguous_time + with_env_tz "Europe/Moscow" do + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), Time.local(2014, 10, 26, 1, 0, 0).in_time_zone("Moscow") + end + end + def test_localtime assert_equal @twz.localtime, @twz.utc.getlocal assert_instance_of Time, @twz.localtime @@ -78,7 +83,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase def test_formatted_offset assert_equal "-05:00", @twz.formatted_offset - assert_equal "-04:00", ActiveSupport::TimeWithZone.new(Time.utc(2000, 6), @time_zone).formatted_offset #dst + assert_equal "-04:00", ActiveSupport::TimeWithZone.new(Time.utc(2000, 6), @time_zone).formatted_offset # dst end def test_dst? @@ -88,7 +93,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase def test_zone assert_equal "EST", @twz.zone - assert_equal "EDT", ActiveSupport::TimeWithZone.new(Time.utc(2000, 6), @time_zone).zone #dst + assert_equal "EDT", ActiveSupport::TimeWithZone.new(Time.utc(2000, 6), @time_zone).zone # dst end def test_nsec @@ -157,7 +162,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_to_yaml - yaml = <<-EOF.strip_heredoc + yaml = <<~EOF --- !ruby/object:ActiveSupport::TimeWithZone utc: 2000-01-01 00:00:00.000000000 Z zone: !ruby/object:ActiveSupport::TimeZone @@ -169,7 +174,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_ruby_to_yaml - yaml = <<-EOF.strip_heredoc + yaml = <<~EOF --- twz: !ruby/object:ActiveSupport::TimeWithZone utc: 2000-01-01 00:00:00.000000000 Z @@ -182,7 +187,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_yaml_load - yaml = <<-EOF.strip_heredoc + yaml = <<~EOF --- !ruby/object:ActiveSupport::TimeWithZone utc: 2000-01-01 00:00:00.000000000 Z zone: !ruby/object:ActiveSupport::TimeZone @@ -194,7 +199,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_ruby_yaml_load - yaml = <<-EOF.strip_heredoc + yaml = <<~EOF --- twz: !ruby/object:ActiveSupport::TimeWithZone utc: 2000-01-01 00:00:00.000000000 Z @@ -215,20 +220,20 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_compare_with_time - assert_equal 1, @twz <=> Time.utc(1999, 12, 31, 23, 59, 59) - assert_equal 0, @twz <=> Time.utc(2000, 1, 1, 0, 0, 0) + assert_equal 1, @twz <=> Time.utc(1999, 12, 31, 23, 59, 59) + assert_equal 0, @twz <=> Time.utc(2000, 1, 1, 0, 0, 0) assert_equal(-1, @twz <=> Time.utc(2000, 1, 1, 0, 0, 1)) end def test_compare_with_datetime - assert_equal 1, @twz <=> DateTime.civil(1999, 12, 31, 23, 59, 59) - assert_equal 0, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 0) + assert_equal 1, @twz <=> DateTime.civil(1999, 12, 31, 23, 59, 59) + assert_equal 0, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 0) assert_equal(-1, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 1)) end def test_compare_with_time_with_zone - assert_equal 1, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) - assert_equal 0, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) + assert_equal 1, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]) + assert_equal 0, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]) assert_equal(-1, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 1), ActiveSupport::TimeZone["UTC"])) end @@ -284,6 +289,20 @@ class TimeWithZoneTest < ActiveSupport::TestCase end end + def test_before + twz = ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 0, 0), @time_zone) + assert_equal false, twz.before?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 11, 59, 59), @time_zone)) + assert_equal false, twz.before?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 0, 0), @time_zone)) + assert_equal true, twz.before?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 00, 1), @time_zone)) + end + + def test_after + twz = ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 0, 0), @time_zone) + assert_equal true, twz.after?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 11, 59, 59), @time_zone)) + assert_equal false, twz.after?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 0, 0), @time_zone)) + assert_equal false, twz.after?(ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 00, 1), @time_zone)) + end + def test_eql? assert_equal true, @twz.eql?(@twz.dup) assert_equal true, @twz.eql?(Time.utc(2000)) @@ -301,13 +320,13 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_plus_with_integer - assert_equal Time.utc(1999, 12, 31, 19, 0 , 5), (@twz + 5).time + assert_equal Time.utc(1999, 12, 31, 19, 0, 5), (@twz + 5).time end def test_plus_with_integer_when_self_wraps_datetime datetime = DateTime.civil(2000, 1, 1, 0) twz = ActiveSupport::TimeWithZone.new(datetime, @time_zone) - assert_equal DateTime.civil(1999, 12, 31, 19, 0 , 5), (twz + 5).time + assert_equal DateTime.civil(1999, 12, 31, 19, 0, 5), (twz + 5).time end def test_plus_when_crossing_time_class_limit @@ -316,31 +335,31 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_plus_with_duration - assert_equal Time.utc(2000, 1, 5, 19, 0 , 0), (@twz + 5.days).time + assert_equal Time.utc(2000, 1, 5, 19, 0, 0), (@twz + 5.days).time end def test_minus_with_integer - assert_equal Time.utc(1999, 12, 31, 18, 59 , 55), (@twz - 5).time + assert_equal Time.utc(1999, 12, 31, 18, 59, 55), (@twz - 5).time end def test_minus_with_integer_when_self_wraps_datetime datetime = DateTime.civil(2000, 1, 1, 0) twz = ActiveSupport::TimeWithZone.new(datetime, @time_zone) - assert_equal DateTime.civil(1999, 12, 31, 18, 59 , 55), (twz - 5).time + assert_equal DateTime.civil(1999, 12, 31, 18, 59, 55), (twz - 5).time end def test_minus_with_duration - assert_equal Time.utc(1999, 12, 26, 19, 0 , 0), (@twz - 5.days).time + assert_equal Time.utc(1999, 12, 26, 19, 0, 0), (@twz - 5.days).time end def test_minus_with_time - assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 1) - assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["Hawaii"]) - Time.utc(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["Hawaii"]) - Time.utc(2000, 1, 1) end def test_minus_with_time_precision - assert_equal 86_399.999999998, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 2, 0, 0, 0, Rational(1, 1000)) - assert_equal 86_399.999999998, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["Hawaii"]) - Time.utc(2000, 1, 2, 0, 0, 0, Rational(1, 1000)) + assert_equal 86_399.999999998, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 2, 0, 0, 0, Rational(1, 1000)) + assert_equal 86_399.999999998, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["Hawaii"]) - Time.utc(2000, 1, 2, 0, 0, 0, Rational(1, 1000)) end def test_minus_with_time_with_zone @@ -352,20 +371,20 @@ class TimeWithZoneTest < ActiveSupport::TestCase def test_minus_with_time_with_zone_precision twz1 = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0, Rational(1, 1000)), ActiveSupport::TimeZone["UTC"]) twz2 = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["UTC"]) - assert_equal 86_399.999999998, twz2 - twz1 + assert_equal 86_399.999999998, twz2 - twz1 end def test_minus_with_datetime - assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) end def test_minus_with_datetime_precision - assert_equal 86_399.999999999, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) + assert_equal 86_399.999999999, ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 23, 59, 59, Rational(999999999, 1000)), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) end def test_minus_with_wrapped_datetime - assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 1) - assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - Time.utc(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new(DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone["UTC"]) - DateTime.civil(2000, 1, 1) end def test_plus_and_minus_enforce_spring_dst_rules @@ -475,7 +494,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_acts_like_time - assert @twz.acts_like_time? + assert_predicate @twz, :acts_like_time? assert @twz.acts_like?(:time) assert ActiveSupport::TimeWithZone.new(DateTime.civil(2000), @time_zone).acts_like?(:time) end @@ -486,7 +505,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_blank? - assert_not @twz.blank? + assert_not_predicate @twz, :blank? end def test_is_a @@ -501,17 +520,17 @@ class TimeWithZoneTest < ActiveSupport::TestCase def test_method_missing_with_time_return_value assert_instance_of ActiveSupport::TimeWithZone, @twz.months_since(1) - assert_equal Time.utc(2000, 1, 31, 19, 0 , 0), @twz.months_since(1).time + assert_equal Time.utc(2000, 1, 31, 19, 0, 0), @twz.months_since(1).time end def test_marshal_dump_and_load marshal_str = Marshal.dump(@twz) mtime = Marshal.load(marshal_str) assert_equal Time.utc(2000, 1, 1, 0), mtime.utc - assert mtime.utc.utc? + assert_predicate mtime.utc, :utc? assert_equal ActiveSupport::TimeZone["Eastern Time (US & Canada)"], mtime.time_zone assert_equal Time.utc(1999, 12, 31, 19), mtime.time - assert mtime.time.utc? + assert_predicate mtime.time, :utc? assert_equal @twz.inspect, mtime.inspect end @@ -520,16 +539,16 @@ class TimeWithZoneTest < ActiveSupport::TestCase marshal_str = Marshal.dump(twz) mtime = Marshal.load(marshal_str) assert_equal Time.utc(2000, 1, 1, 0), mtime.utc - assert mtime.utc.utc? + assert_predicate mtime.utc, :utc? assert_equal "America/New_York", mtime.time_zone.name assert_equal Time.utc(1999, 12, 31, 19), mtime.time - assert mtime.time.utc? + assert_predicate mtime.time, :utc? assert_equal @twz.inspect, mtime.inspect end def test_freeze @twz.freeze - assert @twz.frozen? + assert_predicate @twz, :frozen? end def test_freeze_preloads_instance_variables @@ -1029,8 +1048,8 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase def test_nil_time_zone Time.use_zone nil do - assert !@t.in_time_zone.respond_to?(:period), "no period method" - assert !@dt.in_time_zone.respond_to?(:period), "no period method" + assert_not_respond_to @t.in_time_zone, :period, "no period method" + assert_not_respond_to @dt.in_time_zone, :period, "no period method" end end @@ -1218,7 +1237,7 @@ class TimeWithZoneMethodsForDate < ActiveSupport::TestCase def test_nil_time_zone with_tz_default nil do - assert !@d.in_time_zone.respond_to?(:period), "no period method" + assert_not_respond_to @d.in_time_zone, :period, "no period method" end end @@ -1267,9 +1286,9 @@ class TimeWithZoneMethodsForString < ActiveSupport::TestCase def test_nil_time_zone with_tz_default nil do - assert !@s.in_time_zone.respond_to?(:period), "no period method" - assert !@u.in_time_zone.respond_to?(:period), "no period method" - assert !@z.in_time_zone.respond_to?(:period), "no period method" + assert_not_respond_to @s.in_time_zone, :period, "no period method" + assert_not_respond_to @u.in_time_zone, :period, "no period method" + assert_not_respond_to @z.in_time_zone, :period, "no period method" end end @@ -1301,4 +1320,10 @@ class TimeWithZoneMethodsForString < ActiveSupport::TestCase assert_raise(ArgumentError) { @u.in_time_zone(Object.new) } assert_raise(ArgumentError) { @z.in_time_zone(Object.new) } end + + def test_in_time_zone_with_ambiguous_time + with_tz_default "Moscow" do + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), "2014-10-26 01:00:00".in_time_zone + end + end end diff --git a/activesupport/test/core_ext/uri_ext_test.rb b/activesupport/test/core_ext/uri_ext_test.rb index 8816b0d392..c0686bc720 100644 --- a/activesupport/test/core_ext/uri_ext_test.rb +++ b/activesupport/test/core_ext/uri_ext_test.rb @@ -9,6 +9,6 @@ class URIExtTest < ActiveSupport::TestCase str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese. parser = URI.parser - assert_equal str, parser.unescape(parser.escape(str)) + assert_equal str + str, parser.unescape(str + parser.escape(str).encode(Encoding::UTF_8)) end end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index d636da46d2..a4fbab7b55 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -185,6 +185,61 @@ class DependenciesTest < ActiveSupport::TestCase end end + # Regression see https://github.com/rails/rails/issues/31694 + def test_included_constant_that_changes_to_have_exception_then_back_does_not_loop_forever + # This constant references a nested constant whose namespace will be auto-generated + parent_constant = <<-RUBY + class ConstantReloadError + AnotherConstant::ReloadError + end + RUBY + + # This constant's namespace will be auto-generated, + # also, we'll edit it to contain an error at load-time + child_constant = <<-RUBY + class AnotherConstant::ReloadError + # no_such_method_as_this + end + RUBY + + # Create a version which contains an error during loading + child_constant_with_error = child_constant.sub("# no_such_method_as_this", "no_such_method_as_this") + + fixtures_path = File.join(__dir__, "autoloading_fixtures") + Dir.mktmpdir(nil, fixtures_path) do |tmpdir| + # Set up the file structure where constants will be loaded from + child_constant_path = "#{tmpdir}/another_constant/reload_error.rb" + File.write("#{tmpdir}/constant_reload_error.rb", parent_constant) + Dir.mkdir("#{tmpdir}/another_constant") + File.write(child_constant_path, child_constant_with_error) + + tmpdir_name = tmpdir.split("/").last + with_loading("autoloading_fixtures/#{tmpdir_name}") do + # Load the file, with the error: + assert_raises(NameError) { + ConstantReloadError + } + + Timeout.timeout(0.1) do + # Remove the constant, as if Rails development middleware is reloading changed files: + ActiveSupport::Dependencies.remove_unloadable_constants! + assert_not defined?(AnotherConstant::ReloadError) + end + + # Change the file, so that it is **correct** this time: + File.write(child_constant_path, child_constant) + + # Again: Remove the constant, as if Rails development middleware is reloading changed files: + ActiveSupport::Dependencies.remove_unloadable_constants! + assert_not defined?(AnotherConstant::ReloadError) + + # Now, reload the _fixed_ constant: + assert ConstantReloadError + assert AnotherConstant::ReloadError + end + end + end + def test_module_loading with_autoloading_fixtures do assert_kind_of Module, A @@ -480,9 +535,9 @@ class DependenciesTest < ActiveSupport::TestCase def test_qualified_const_defined_should_not_call_const_missing ModuleWithMissing.missing_count = 0 - assert ! ActiveSupport::Dependencies.qualified_const_defined?("ModuleWithMissing::A") + assert_not ActiveSupport::Dependencies.qualified_const_defined?("ModuleWithMissing::A") assert_equal 0, ModuleWithMissing.missing_count - assert ! ActiveSupport::Dependencies.qualified_const_defined?("ModuleWithMissing::A::B") + assert_not ActiveSupport::Dependencies.qualified_const_defined?("ModuleWithMissing::A::B") assert_equal 0, ModuleWithMissing.missing_count end @@ -492,13 +547,13 @@ class DependenciesTest < ActiveSupport::TestCase def test_autoloaded? with_autoloading_fixtures do - assert ! ActiveSupport::Dependencies.autoloaded?("ModuleFolder") - assert ! ActiveSupport::Dependencies.autoloaded?("ModuleFolder::NestedClass") + assert_not ActiveSupport::Dependencies.autoloaded?("ModuleFolder") + assert_not ActiveSupport::Dependencies.autoloaded?("ModuleFolder::NestedClass") assert ActiveSupport::Dependencies.autoloaded?(ModuleFolder) assert ActiveSupport::Dependencies.autoloaded?("ModuleFolder") - assert ! ActiveSupport::Dependencies.autoloaded?("ModuleFolder::NestedClass") + assert_not ActiveSupport::Dependencies.autoloaded?("ModuleFolder::NestedClass") assert ActiveSupport::Dependencies.autoloaded?(ModuleFolder::NestedClass) @@ -509,11 +564,11 @@ class DependenciesTest < ActiveSupport::TestCase assert ActiveSupport::Dependencies.autoloaded?(:ModuleFolder) # Anonymous modules aren't autoloaded. - assert !ActiveSupport::Dependencies.autoloaded?(Module.new) + assert_not ActiveSupport::Dependencies.autoloaded?(Module.new) nil_name = Module.new def nil_name.name() nil end - assert !ActiveSupport::Dependencies.autoloaded?(nil_name) + assert_not ActiveSupport::Dependencies.autoloaded?(nil_name) end ensure remove_constants(:ModuleFolder) @@ -723,7 +778,7 @@ class DependenciesTest < ActiveSupport::TestCase M.unloadable ActiveSupport::Dependencies.clear - assert ! defined?(M) + assert_not defined?(M) Object.const_set :M, Module.new ActiveSupport::Dependencies.clear @@ -752,9 +807,9 @@ class DependenciesTest < ActiveSupport::TestCase Object.const_set :C, Class.new { def self.before_remove_const; end } C.unloadable assert_called(C, :before_remove_const, times: 1) do - assert C.respond_to?(:before_remove_const) + assert_respond_to C, :before_remove_const ActiveSupport::Dependencies.clear - assert !defined?(C) + assert_not defined?(C) end ensure remove_constants(:C) @@ -968,7 +1023,7 @@ class DependenciesTest < ActiveSupport::TestCase assert !defined?(::RaisesNameError), "::RaisesNameError is defined but it should have failed!" end - assert !defined?(::RaisesNameError) + assert_not defined?(::RaisesNameError) 2.times do assert_raise(NameError) { ::RaisesNameError } assert !defined?(::RaisesNameError), "::RaisesNameError is defined but it should have failed!" diff --git a/activesupport/test/deprecation/method_wrappers_test.rb b/activesupport/test/deprecation/method_wrappers_test.rb index 04e2325754..439e117c1d 100644 --- a/activesupport/test/deprecation/method_wrappers_test.rb +++ b/activesupport/test/deprecation/method_wrappers_test.rb @@ -8,6 +8,16 @@ class MethodWrappersTest < ActiveSupport::TestCase @klass = Class.new do def new_method; "abc" end alias_method :old_method, :new_method + + protected + + def new_protected_method; "abc" end + alias_method :old_protected_method, :new_protected_method + + private + + def new_private_method; "abc" end + alias_method :old_private_method, :new_private_method end end @@ -33,4 +43,16 @@ class MethodWrappersTest < ActiveSupport::TestCase assert_deprecated(warning, deprecator) { assert_equal "abc", @klass.new.old_method } end + + def test_deprecate_methods_protected_method + ActiveSupport::Deprecation.deprecate_methods(@klass, old_protected_method: :new_protected_method) + + assert(@klass.protected_method_defined?(:old_protected_method)) + end + + def test_deprecate_methods_private_method + ActiveSupport::Deprecation.deprecate_methods(@klass, old_private_method: :new_private_method) + + assert(@klass.private_method_defined?(:old_private_method)) + end end diff --git a/activesupport/test/deprecation/proxy_wrappers_test.rb b/activesupport/test/deprecation/proxy_wrappers_test.rb index 2f866775f6..9e26052fb4 100644 --- a/activesupport/test/deprecation/proxy_wrappers_test.rb +++ b/activesupport/test/deprecation/proxy_wrappers_test.rb @@ -9,16 +9,16 @@ class ProxyWrappersTest < ActiveSupport::TestCase def test_deprecated_object_proxy_doesnt_wrap_falsy_objects proxy = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(nil, "message") - assert !proxy + assert_not proxy end def test_deprecated_instance_variable_proxy_doesnt_wrap_falsy_objects proxy = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(nil, :waffles) - assert !proxy + assert_not proxy end def test_deprecated_constant_proxy_doesnt_wrap_falsy_objects proxy = ActiveSupport::Deprecation::DeprecatedConstantProxy.new(Waffles, NewWaffles) - assert !proxy + assert_not proxy end end diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index f2267a822f..60673c032b 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -158,7 +158,7 @@ class DeprecationTest < ActiveSupport::TestCase stderr_output = capture(:stderr) { assert_nil behavior.call("Some error!", ["call stack!"], "horizon", "gem") } - assert stderr_output.empty? + assert_empty stderr_output end def test_default_notify_behavior diff --git a/activesupport/test/descendants_tracker_test_cases.rb b/activesupport/test/descendants_tracker_test_cases.rb index 1f8b4a8605..2c94c3c56c 100644 --- a/activesupport/test/descendants_tracker_test_cases.rb +++ b/activesupport/test/descendants_tracker_test_cases.rb @@ -37,7 +37,7 @@ module DescendantsTrackerTestCases mark_as_autoloaded(*ALL) do ActiveSupport::DescendantsTracker.clear ALL.each do |k| - assert ActiveSupport::DescendantsTracker.descendants(k).empty? + assert_empty ActiveSupport::DescendantsTracker.descendants(k) end end end diff --git a/activesupport/test/descendants_tracker_with_autoloading_test.rb b/activesupport/test/descendants_tracker_with_autoloading_test.rb index 7c396b7c8e..d4fedb5a67 100644 --- a/activesupport/test/descendants_tracker_with_autoloading_test.rb +++ b/activesupport/test/descendants_tracker_with_autoloading_test.rb @@ -12,7 +12,7 @@ class DescendantsTrackerWithAutoloadingTest < ActiveSupport::TestCase mark_as_autoloaded(*ALL) do ActiveSupport::DescendantsTracker.clear ALL.each do |k| - assert ActiveSupport::DescendantsTracker.descendants(k).empty? + assert_empty ActiveSupport::DescendantsTracker.descendants(k) end end end diff --git a/activesupport/test/descendants_tracker_without_autoloading_test.rb b/activesupport/test/descendants_tracker_without_autoloading_test.rb index f5c6a3045d..c65f69cba3 100644 --- a/activesupport/test/descendants_tracker_without_autoloading_test.rb +++ b/activesupport/test/descendants_tracker_without_autoloading_test.rb @@ -13,7 +13,7 @@ class DescendantsTrackerWithoutAutoloadingTest < ActiveSupport::TestCase parent_instance = Parent.new parent_instance.singleton_class.descendants ActiveSupport::DescendantsTracker.clear - assert !ActiveSupport::DescendantsTracker.class_variable_get(:@@direct_descendants).key?(parent_instance.singleton_class) + assert_not ActiveSupport::DescendantsTracker.class_variable_get(:@@direct_descendants).key?(parent_instance.singleton_class) end end end diff --git a/activesupport/test/digest_test.rb b/activesupport/test/digest_test.rb new file mode 100644 index 0000000000..83ff2a8d83 --- /dev/null +++ b/activesupport/test/digest_test.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "openssl" + +class DigestTest < ActiveSupport::TestCase + class InvalidDigest; end + def test_with_default_hash_digest_class + assert_equal ::Digest::MD5.hexdigest("hello friend"), ActiveSupport::Digest.hexdigest("hello friend") + end + + def test_with_custom_hash_digest_class + original_hash_digest_class = ActiveSupport::Digest.hash_digest_class + + ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1 + digest = ActiveSupport::Digest.hexdigest("hello friend") + + assert_equal 32, digest.length + assert_equal ::Digest::SHA1.hexdigest("hello friend")[0...32], digest + ensure + ActiveSupport::Digest.hash_digest_class = original_hash_digest_class + end + + def test_should_raise_argument_error_if_custom_digest_is_missing_hexdigest_method + assert_raises(ArgumentError) { ActiveSupport::Digest.hash_digest_class = InvalidDigest } + end +end diff --git a/activesupport/test/encrypted_configuration_test.rb b/activesupport/test/encrypted_configuration_test.rb index 53ea9e393f..93ccf457de 100644 --- a/activesupport/test/encrypted_configuration_test.rb +++ b/activesupport/test/encrypted_configuration_test.rb @@ -10,8 +10,10 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase @credentials_key_path = File.join(Dir.tmpdir, "master.key") File.write(@credentials_key_path, ActiveSupport::EncryptedConfiguration.generate_key) - @credentials = ActiveSupport::EncryptedConfiguration.new \ - config_path: @credentials_config_path, key_path: @credentials_key_path, env_key: "RAILS_MASTER_KEY" + @credentials = ActiveSupport::EncryptedConfiguration.new( + config_path: @credentials_config_path, key_path: @credentials_key_path, + env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true + ) end teardown do @@ -51,15 +53,15 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase assert_equal "things", @credentials[:new] end + test "raise error when writing an invalid format value" do + assert_raise(Psych::SyntaxError) do + @credentials.change do |config_file| + config_file.write "login: *login\n username: dummy" + end + end + end + test "raises key error when accessing config via bang method" do assert_raise(KeyError) { @credentials.something! } end - - private - def new_credentials_configuration - ActiveSupport::EncryptedConfiguration.new \ - config_path: @credentials_config_path, - key_path: @credentials_key_path, - env_key: "RAILS_MASTER_KEY" - end end diff --git a/activesupport/test/encrypted_file_test.rb b/activesupport/test/encrypted_file_test.rb index 7259726d08..ba3bbef903 100644 --- a/activesupport/test/encrypted_file_test.rb +++ b/activesupport/test/encrypted_file_test.rb @@ -12,8 +12,9 @@ class EncryptedFileTest < ActiveSupport::TestCase @key_path = File.join(Dir.tmpdir, "content.txt.key") File.write(@key_path, ActiveSupport::EncryptedFile.generate_key) - @encrypted_file = ActiveSupport::EncryptedFile.new \ - content_path: @content_path, key_path: @key_path, env_key: "CONTENT_KEY" + @encrypted_file = ActiveSupport::EncryptedFile.new( + content_path: @content_path, key_path: @key_path, env_key: "CONTENT_KEY", raise_if_missing_key: true + ) end teardown do @@ -47,4 +48,12 @@ class EncryptedFileTest < ActiveSupport::TestCase assert_equal "#{@content} and went by the lake", @encrypted_file.read end + + test "raise MissingKeyError when key is missing" do + assert_raise(ActiveSupport::EncryptedFile::MissingKeyError) do + ActiveSupport::EncryptedFile.new( + content_path: @content_path, key_path: "", env_key: "", raise_if_missing_key: true + ).read + end + end end diff --git a/activesupport/test/evented_file_update_checker_test.rb b/activesupport/test/evented_file_update_checker_test.rb index 9b560f7f42..d3af0dbef3 100644 --- a/activesupport/test/evented_file_update_checker_test.rb +++ b/activesupport/test/evented_file_update_checker_test.rb @@ -39,18 +39,18 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase FileUtils.touch(tmpfiles) checker = new_checker(tmpfiles) {} - assert !checker.updated? + assert_not_predicate checker, :updated? # Pipes used for flow control across fork. boot_reader, boot_writer = IO.pipe touch_reader, touch_writer = IO.pipe pid = fork do - assert checker.updated? + assert_predicate checker, :updated? # Clear previous check value. checker.execute - assert !checker.updated? + assert_not_predicate checker, :updated? # Fork is booted, ready for file to be touched # notify parent process. @@ -60,7 +60,7 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase # has been touched. IO.select([touch_reader]) - assert checker.updated? + assert_predicate checker, :updated? end assert pid @@ -72,7 +72,7 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase # Notify fork that files have been touched. touch_writer.write("touched") - assert checker.updated? + assert_predicate checker, :updated? Process.wait(pid) end diff --git a/activesupport/test/file_update_checker_shared_tests.rb b/activesupport/test/file_update_checker_shared_tests.rb index f8266dac06..72683816b3 100644 --- a/activesupport/test/file_update_checker_shared_tests.rb +++ b/activesupport/test/file_update_checker_shared_tests.rb @@ -30,7 +30,7 @@ module FileUpdateCheckerSharedTests checker = new_checker { i += 1 } - assert !checker.execute_if_updated + assert_not checker.execute_if_updated assert_equal 0, i end @@ -41,7 +41,7 @@ module FileUpdateCheckerSharedTests checker = new_checker(tmpfiles) { i += 1 } - assert !checker.execute_if_updated + assert_not checker.execute_if_updated assert_equal 0, i end @@ -89,12 +89,12 @@ module FileUpdateCheckerSharedTests i = 0 checker = new_checker(tmpfiles) { i += 1 } - assert !checker.updated? + assert_not_predicate checker, :updated? touch(tmpfiles) wait - assert checker.updated? + assert_predicate checker, :updated? end test "updated should become true when watched files are modified" do @@ -103,12 +103,12 @@ module FileUpdateCheckerSharedTests FileUtils.touch(tmpfiles) checker = new_checker(tmpfiles) { i += 1 } - assert !checker.updated? + assert_not_predicate checker, :updated? touch(tmpfiles) wait - assert checker.updated? + assert_predicate checker, :updated? end test "updated should become true when watched files are deleted" do @@ -117,12 +117,12 @@ module FileUpdateCheckerSharedTests FileUtils.touch(tmpfiles) checker = new_checker(tmpfiles) { i += 1 } - assert !checker.updated? + assert_not_predicate checker, :updated? rm_f(tmpfiles) wait - assert checker.updated? + assert_predicate checker, :updated? end test "should be robust to handle files with wrong modified time" do @@ -164,14 +164,14 @@ module FileUpdateCheckerSharedTests i = 0 checker = new_checker(tmpfiles) { i += 1 } - assert !checker.updated? + assert_not_predicate checker, :updated? touch(tmpfiles) wait - assert checker.updated? + assert_predicate checker, :updated? checker.execute - assert !checker.updated? + assert_not_predicate checker, :updated? end test "should execute the block if files change in a watched directory one extension" do @@ -212,7 +212,7 @@ module FileUpdateCheckerSharedTests touch(tmpfile("foo.rb")) wait - assert !checker.execute_if_updated + assert_not checker.execute_if_updated assert_equal 0, i end @@ -238,7 +238,7 @@ module FileUpdateCheckerSharedTests mkdir(subdir) wait - assert !checker.execute_if_updated + assert_not checker.execute_if_updated assert_equal 0, i touch(File.join(subdir, "nested.rb")) @@ -259,7 +259,7 @@ module FileUpdateCheckerSharedTests touch(tmpfile("new.txt")) wait - assert !checker.execute_if_updated + assert_not checker.execute_if_updated assert_equal 0, i # subdir does not look for Ruby files, but its parent tmpdir does. diff --git a/activesupport/test/hash_with_indifferent_access_test.rb b/activesupport/test/hash_with_indifferent_access_test.rb index b3788ee65c..a20c428bf8 100644 --- a/activesupport/test/hash_with_indifferent_access_test.rb +++ b/activesupport/test/hash_with_indifferent_access_test.rb @@ -169,8 +169,6 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase end def test_indifferent_fetch_values - skip unless Hash.method_defined?(:fetch_values) - @mixed = @mixed.with_indifferent_access assert_equal [1, 2], @mixed.fetch_values("a", "b") @@ -282,7 +280,7 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase replaced = hash.replace(b: 12) assert hash.key?("b") - assert !hash.key?(:a) + assert_not hash.key?(:a) assert_equal 12, hash[:b] assert_same hash, replaced end @@ -294,7 +292,7 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase replaced = hash.replace(HashByConversion.new(b: 12)) assert hash.key?("b") - assert !hash.key?(:a) + assert_not hash.key?(:a) assert_equal 12, hash[:b] assert_same hash, replaced end @@ -399,6 +397,49 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings end + def test_indifferent_transform_keys + hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).transform_keys { |k| k * 2 } + + assert_equal({ "aa" => 1, "bb" => 2 }, hash) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash + + hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).transform_keys { |k| k.to_sym } + + assert_equal(1, hash[:a]) + assert_equal(1, hash["a"]) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash + end + + def test_indifferent_transform_keys_bang + indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@strings) + indifferent_strings.transform_keys! { |k| k * 2 } + + assert_equal({ "aa" => 1, "bb" => 2 }, indifferent_strings) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings + + indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@strings) + indifferent_strings.transform_keys! { |k| k.to_sym } + + assert_equal(1, indifferent_strings[:a]) + assert_equal(1, indifferent_strings["a"]) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings + end + + def test_indifferent_transform_values + hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).transform_values { |v| v * 2 } + + assert_equal({ "a" => 2, "b" => 4 }, hash) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash + end + + def test_indifferent_transform_values_bang + indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@strings) + indifferent_strings.transform_values! { |v| v * 2 } + + assert_equal({ "a" => 2, "b" => 4 }, indifferent_strings) + assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings + end + def test_indifferent_compact hash_contain_nil_value = @strings.merge("z" => nil) hash = ActiveSupport::HashWithIndifferentAccess.new(hash_contain_nil_value) @@ -532,7 +573,6 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase end def test_nested_dig_indifferent_access - skip if RUBY_VERSION < "2.3.0" data = { "this" => { "views" => 1234 } }.with_indifferent_access assert_equal 1234, data.dig(:this, :views) end diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index eeec0ab1a5..5e50acf5db 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -224,6 +224,12 @@ class InflectorTest < ActiveSupport::TestCase assert_equal("json_html_api", ActiveSupport::Inflector.underscore("JSONHTMLAPI")) end + def test_acronym_regexp_is_deprecated + assert_deprecated do + ActiveSupport::Inflector.inflections.acronym_regex + end + end + def test_underscore CamelToUnderscore.each do |camel, underscore| assert_equal(underscore, ActiveSupport::Inflector.underscore(camel)) @@ -356,6 +362,19 @@ class InflectorTest < ActiveSupport::TestCase assert_equal("Col rpted bugs", ActiveSupport::Inflector.humanize("COL_rpted_bugs")) end + def test_humanize_with_acronyms + ActiveSupport::Inflector.inflections do |inflect| + inflect.acronym "LAX" + inflect.acronym "SFO" + end + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("LAX ROUNDTRIP TO SFO")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("LAX ROUNDTRIP TO SFO", capitalize: false)) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("lax roundtrip to sfo")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("lax roundtrip to sfo", capitalize: false)) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("Lax Roundtrip To Sfo")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("Lax Roundtrip To Sfo", capitalize: false)) + end + def test_constantize run_constantize_tests_on do |string| ActiveSupport::Inflector.constantize(string) @@ -441,12 +460,12 @@ class InflectorTest < ActiveSupport::TestCase ActiveSupport::Inflector.inflections(:es) { |inflect| inflect.clear } - assert ActiveSupport::Inflector.inflections(:es).plurals.empty? - assert ActiveSupport::Inflector.inflections(:es).singulars.empty? - assert ActiveSupport::Inflector.inflections(:es).uncountables.empty? - assert !ActiveSupport::Inflector.inflections.plurals.empty? - assert !ActiveSupport::Inflector.inflections.singulars.empty? - assert !ActiveSupport::Inflector.inflections.uncountables.empty? + assert_empty ActiveSupport::Inflector.inflections(:es).plurals + assert_empty ActiveSupport::Inflector.inflections(:es).singulars + assert_empty ActiveSupport::Inflector.inflections(:es).uncountables + assert_not_empty ActiveSupport::Inflector.inflections.plurals + assert_not_empty ActiveSupport::Inflector.inflections.singulars + assert_not_empty ActiveSupport::Inflector.inflections.uncountables end def test_clear_all @@ -459,10 +478,10 @@ class InflectorTest < ActiveSupport::TestCase inflect.clear :all - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? + assert_empty inflect.plurals + assert_empty inflect.singulars + assert_empty inflect.uncountables + assert_empty inflect.humans end end @@ -476,10 +495,10 @@ class InflectorTest < ActiveSupport::TestCase inflect.clear - assert inflect.plurals.empty? - assert inflect.singulars.empty? - assert inflect.uncountables.empty? - assert inflect.humans.empty? + assert_empty inflect.plurals + assert_empty inflect.singulars + assert_empty inflect.uncountables + assert_empty inflect.humans end end diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb index f1214671ce..689370cccf 100644 --- a/activesupport/test/inflector_test_cases.rb +++ b/activesupport/test/inflector_test_cases.rb @@ -221,7 +221,7 @@ module InflectorTestCases "Test with malformed utf8 \251" => "test_with_malformed_utf8" } - StringToParameterizePreserceCaseWithUnderscore = { + StringToParameterizePreserveCaseWithUnderscore = { "Donald E. Knuth" => "Donald_E_Knuth", "Random text with *(bad)* characters" => "Random_text_with_bad_characters", "With-some-dashes" => "With-some-dashes", diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index eafa2e1712..340a2abf75 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -187,7 +187,7 @@ class TestJSONEncoding < ActiveSupport::TestCase def test_array_should_pass_encoding_options_to_children_in_as_json people = [ { name: "John", address: { city: "London", country: "UK" } }, - { name: "Jean", address: { city: "Paris" , country: "France" } } + { name: "Jean", address: { city: "Paris", country: "France" } } ] json = people.as_json only: [:address, :city] expected = [ @@ -201,7 +201,7 @@ class TestJSONEncoding < ActiveSupport::TestCase def test_array_should_pass_encoding_options_to_children_in_to_json people = [ { name: "John", address: { city: "London", country: "UK" } }, - { name: "Jean", address: { city: "Paris" , country: "France" } } + { name: "Jean", address: { city: "Paris", country: "France" } } ] json = people.to_json only: [:address, :city] @@ -210,10 +210,10 @@ class TestJSONEncoding < ActiveSupport::TestCase People = Class.new(BasicObject) do include Enumerable - def initialize() + def initialize @people = [ { name: "John", address: { city: "London", country: "UK" } }, - { name: "Jean", address: { city: "Paris" , country: "France" } } + { name: "Jean", address: { city: "Paris", country: "France" } } ] end def each(*, &blk) @@ -454,6 +454,10 @@ EXPECTED assert_equal '{"number":null}', NaNNumber.new.to_json end + def test_to_json_works_on_io_objects + assert_equal STDOUT.to_s.to_json, STDOUT.to_json + end + private def object_keys(json_object) diff --git a/activesupport/test/key_generator_test.rb b/activesupport/test/key_generator_test.rb index a948cfbd8e..cdde2c573a 100644 --- a/activesupport/test/key_generator_test.rb +++ b/activesupport/test/key_generator_test.rb @@ -36,13 +36,13 @@ else # key would break. expected = "b129376f68f1ecae788d7433310249d65ceec090ecacd4c872a3a9e9ec78e055739be5cc6956345d5ae38e7e1daa66f1de587dc8da2bf9e8b965af4b3918a122" - assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64).generate_key("some_salt").unpack("H*").first + assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64).generate_key("some_salt").unpack1("H*") expected = "b129376f68f1ecae788d7433310249d65ceec090ecacd4c872a3a9e9ec78e055" - assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64).generate_key("some_salt", 32).unpack("H*").first + assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64).generate_key("some_salt", 32).unpack1("H*") expected = "cbea7f7f47df705967dc508f4e446fd99e7797b1d70011c6899cd39bbe62907b8508337d678505a7dc8184e037f1003ba3d19fc5d829454668e91d2518692eae" - assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64, iterations: 2).generate_key("some_salt").unpack("H*").first + assert_equal expected, ActiveSupport::KeyGenerator.new("0" * 64, iterations: 2).generate_key("some_salt").unpack1("H*") end end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index 1fbe655642..9edf07f762 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -115,6 +115,72 @@ class MessageEncryptorTest < ActiveSupport::TestCase assert_equal "Ruby on Rails", encryptor.decrypt_and_verify(encrypted_message) end + def test_rotating_secret + old_message = ActiveSupport::MessageEncryptor.new(secrets[:old], cipher: "aes-256-gcm").encrypt_and_sign("old") + + encryptor = ActiveSupport::MessageEncryptor.new(@secret, cipher: "aes-256-gcm") + encryptor.rotate secrets[:old] + + assert_equal "old", encryptor.decrypt_and_verify(old_message) + end + + def test_rotating_serializer + old_message = ActiveSupport::MessageEncryptor.new(secrets[:old], cipher: "aes-256-gcm", serializer: JSON). + encrypt_and_sign(ahoy: :hoy) + + encryptor = ActiveSupport::MessageEncryptor.new(@secret, cipher: "aes-256-gcm", serializer: JSON) + encryptor.rotate secrets[:old] + + assert_equal({ "ahoy" => "hoy" }, encryptor.decrypt_and_verify(old_message)) + end + + def test_rotating_aes_cbc_secrets + old_encryptor = ActiveSupport::MessageEncryptor.new(secrets[:old], "old sign", cipher: "aes-256-cbc") + old_message = old_encryptor.encrypt_and_sign("old") + + encryptor = ActiveSupport::MessageEncryptor.new(@secret) + encryptor.rotate secrets[:old], "old sign", cipher: "aes-256-cbc" + + assert_equal "old", encryptor.decrypt_and_verify(old_message) + end + + def test_multiple_rotations + older_message = ActiveSupport::MessageEncryptor.new(secrets[:older], "older sign").encrypt_and_sign("older") + old_message = ActiveSupport::MessageEncryptor.new(secrets[:old], "old sign").encrypt_and_sign("old") + + encryptor = ActiveSupport::MessageEncryptor.new(@secret) + encryptor.rotate secrets[:old], "old sign" + encryptor.rotate secrets[:older], "older sign" + + assert_equal "new", encryptor.decrypt_and_verify(encryptor.encrypt_and_sign("new")) + assert_equal "old", encryptor.decrypt_and_verify(old_message) + assert_equal "older", encryptor.decrypt_and_verify(older_message) + end + + def test_on_rotation_is_called_and_returns_modified_messages + older_message = ActiveSupport::MessageEncryptor.new(secrets[:older], "older sign").encrypt_and_sign(encoded: "message") + + encryptor = ActiveSupport::MessageEncryptor.new(@secret) + encryptor.rotate secrets[:old] + encryptor.rotate secrets[:older], "older sign" + + rotated = false + message = encryptor.decrypt_and_verify(older_message, on_rotation: proc { rotated = true }) + + assert_equal({ encoded: "message" }, message) + assert rotated + end + + def test_with_rotated_metadata + old_message = ActiveSupport::MessageEncryptor.new(secrets[:old], cipher: "aes-256-gcm"). + encrypt_and_sign("metadata", purpose: :rotation) + + encryptor = ActiveSupport::MessageEncryptor.new(@secret, cipher: "aes-256-gcm") + encryptor.rotate secrets[:old] + + assert_equal "metadata", encryptor.decrypt_and_verify(old_message, purpose: :rotation) + end + private def assert_aead_not_decrypted(encryptor, value) assert_raise(ActiveSupport::MessageEncryptor::InvalidMessage) do @@ -134,6 +200,10 @@ class MessageEncryptorTest < ActiveSupport::TestCase end end + def secrets + @secrets ||= Hash.new { |h, k| h[k] = SecureRandom.random_bytes(32) } + end + def munge(base64_string) bits = ::Base64.strict_decode64(base64_string) bits.reverse! diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index fbeafca203..0fa53695e0 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -20,16 +20,17 @@ class MessageVerifierTest < ActiveSupport::TestCase def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") @data = { some: "data", now: Time.utc(2010) } + @secret = SecureRandom.random_bytes(32) end def test_valid_message 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") + assert_not @verifier.valid_message?(nil) + assert_not @verifier.valid_message?("") + assert_not @verifier.valid_message?("\xff") # invalid encoding + assert_not @verifier.valid_message?("#{data.reverse}--#{hash}") + assert_not @verifier.valid_message?("#{data}--#{hash.reverse}") + assert_not @verifier.valid_message?("purejunk") end def test_simple_round_tripping @@ -39,7 +40,7 @@ class MessageVerifierTest < ActiveSupport::TestCase end def test_verified_returns_false_on_invalid_message - assert !@verifier.verified("purejunk") + assert_not @verifier.verified("purejunk") end def test_verify_exception_on_invalid_message @@ -90,6 +91,51 @@ class MessageVerifierTest < ActiveSupport::TestCase signed_message = "BAh7BzoJc29tZUkiCWRhdGEGOgZFVDoIbm93SXU6CVRpbWUNIIAbgAAAAAAHOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7BkY=--d03c52c91dfe4ccc5159417c660461bcce005e96" assert_equal @data, @verifier.verify(signed_message) end + + def test_rotating_secret + old_message = ActiveSupport::MessageVerifier.new("old", digest: "SHA1").generate("old") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA1") + verifier.rotate "old" + + assert_equal "old", verifier.verified(old_message) + end + + def test_multiple_rotations + old_message = ActiveSupport::MessageVerifier.new("old", digest: "SHA256").generate("old") + older_message = ActiveSupport::MessageVerifier.new("older", digest: "SHA1").generate("older") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512") + verifier.rotate "old", digest: "SHA256" + verifier.rotate "older", digest: "SHA1" + + assert_equal "new", verifier.verified(verifier.generate("new")) + assert_equal "old", verifier.verified(old_message) + assert_equal "older", verifier.verified(older_message) + end + + def test_on_rotation_is_called_and_verified_returns_message + older_message = ActiveSupport::MessageVerifier.new("older", digest: "SHA1").generate(encoded: "message") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512") + verifier.rotate "old", digest: "SHA256" + verifier.rotate "older", digest: "SHA1" + + rotated = false + message = verifier.verified(older_message, on_rotation: proc { rotated = true }) + + assert_equal({ encoded: "message" }, message) + assert rotated + end + + def test_rotations_with_metadata + old_message = ActiveSupport::MessageVerifier.new("old").generate("old", purpose: :rotation) + + verifier = ActiveSupport::MessageVerifier.new(@secret) + verifier.rotate "old" + + assert_equal "old", verifier.verified(old_message, purpose: :rotation) + end end class MessageVerifierMetadataTest < ActiveSupport::TestCase diff --git a/activesupport/test/messages/rotation_configuration_test.rb b/activesupport/test/messages/rotation_configuration_test.rb new file mode 100644 index 0000000000..2f6824ed21 --- /dev/null +++ b/activesupport/test/messages/rotation_configuration_test.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "active_support/messages/rotation_configuration" + +class MessagesRotationConfiguration < ActiveSupport::TestCase + def setup + @config = ActiveSupport::Messages::RotationConfiguration.new + end + + def test_signed_configurations + @config.rotate :signed, "older secret", salt: "salt", digest: "SHA1" + @config.rotate :signed, "old secret", salt: "salt", digest: "SHA256" + + assert_equal [ + [ "older secret", salt: "salt", digest: "SHA1" ], + [ "old secret", salt: "salt", digest: "SHA256" ] ], @config.signed + end + + def test_encrypted_configurations + @config.rotate :encrypted, "old raw key", cipher: "aes-256-gcm" + + assert_equal [ [ "old raw key", cipher: "aes-256-gcm" ] ], @config.encrypted + end +end diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index f51fbe2671..061446c782 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -75,7 +75,7 @@ class MultibyteCharsTest < ActiveSupport::TestCase def test_consumes_utf8_strings assert @proxy_class.consumes?(UNICODE_STRING) assert @proxy_class.consumes?(ASCII_STRING) - assert !@proxy_class.consumes?(BYTE_STRING) + assert_not @proxy_class.consumes?(BYTE_STRING) end def test_concatenation_should_return_a_proxy_class_instance @@ -148,7 +148,7 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase def test_identity assert_equal @chars, @chars assert @chars.eql?(@chars) - assert !@chars.eql?(UNICODE_STRING) + assert_not @chars.eql?(UNICODE_STRING) end def test_string_methods_are_chainable @@ -469,10 +469,10 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase end def test_respond_to_knows_which_methods_the_proxy_responds_to - assert "".mb_chars.respond_to?(:slice) # Defined on Chars - assert "".mb_chars.respond_to?(:capitalize!) # Defined on Chars - assert "".mb_chars.respond_to?(:gsub) # Defined on String - assert !"".mb_chars.respond_to?(:undefined_method) # Not defined + assert_respond_to "".mb_chars, :slice # Defined on Chars + assert_respond_to "".mb_chars, :capitalize! # Defined on Chars + assert_respond_to "".mb_chars, :gsub # Defined on String + assert_not_respond_to "".mb_chars, :undefined_method # Not defined end def test_method_works_for_proxyed_methods @@ -485,7 +485,7 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase end def test_acts_like_string - assert "Bambi".mb_chars.acts_like_string? + assert_predicate "Bambi".mb_chars, :acts_like_string? end end diff --git a/activesupport/test/multibyte_unicode_database_test.rb b/activesupport/test/multibyte_unicode_database_test.rb deleted file mode 100644 index 540a34493d..0000000000 --- a/activesupport/test/multibyte_unicode_database_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -require "abstract_unit" - -class MultibyteUnicodeDatabaseTest < ActiveSupport::TestCase - include ActiveSupport::Multibyte::Unicode - - def setup - @ucd = UnicodeDatabase.new - end - - UnicodeDatabase::ATTRIBUTES.each do |attribute| - define_method "test_lazy_loading_on_attribute_access_of_#{attribute}" do - assert_called(@ucd, :load) do - @ucd.send(attribute) - end - end - end - - def test_load - @ucd.load - UnicodeDatabase::ATTRIBUTES.each do |attribute| - assert @ucd.send(attribute).length > 1 - end - end -end diff --git a/activesupport/test/notifications/instrumenter_test.rb b/activesupport/test/notifications/instrumenter_test.rb index 1d76c91d30..d5c9e82e9f 100644 --- a/activesupport/test/notifications/instrumenter_test.rb +++ b/activesupport/test/notifications/instrumenter_test.rb @@ -47,13 +47,13 @@ module ActiveSupport def test_start instrumenter.start("foo", payload) assert_equal [["foo", instrumenter.id, payload]], notifier.starts - assert_predicate notifier.finishes, :empty? + assert_empty notifier.finishes end def test_finish instrumenter.finish("foo", payload) assert_equal [["foo", instrumenter.id, payload]], notifier.finishes - assert_predicate notifier.starts, :empty? + assert_empty notifier.starts end end end diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 5cfbd60131..d035f993f7 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -250,8 +250,8 @@ module Notifications time = Time.now event = event(:foo, time, time + 0.01, random_id, {}) - assert_equal :foo, event.name - assert_equal time, event.time + assert_equal :foo, event.name + assert_equal time, event.time assert_in_delta 10.0, event.duration, 0.00001 end @@ -270,9 +270,9 @@ module Notifications parent.children << child assert parent.parent_of?(child) - assert !child.parent_of?(parent) - assert !parent.parent_of?(not_child) - assert !not_child.parent_of?(parent) + assert_not child.parent_of?(parent) + assert_not parent.parent_of?(not_child) + assert_not not_child.parent_of?(parent) end private diff --git a/activesupport/test/number_helper_i18n_test.rb b/activesupport/test/number_helper_i18n_test.rb index 6d6958be49..365fa96f4d 100644 --- a/activesupport/test/number_helper_i18n_test.rb +++ b/activesupport/test/number_helper_i18n_test.rb @@ -35,7 +35,7 @@ module ActiveSupport thousand: "t", million: "m", billion: "b", - trillion: "t" , + trillion: "t", quadrillion: "q" } } @@ -77,10 +77,10 @@ module ActiveSupport end def test_number_with_i18n_precision - #Delimiter was set to "" + # Delimiter was set to "" assert_equal("10000", number_to_rounded(10000, locale: "ts")) - #Precision inherited and significant was set + # Precision inherited and significant was set assert_equal("1.00", number_to_rounded(1.0, locale: "ts")) end @@ -90,7 +90,7 @@ module ActiveSupport end def test_number_with_i18n_delimiter - #Delimiter "," and separator "." + # Delimiter "," and separator "." assert_equal("1,000,000.234", number_to_delimited(1000000.234, locale: "ts")) end @@ -114,7 +114,7 @@ module ActiveSupport end def test_number_to_i18n_human_size - #b for bytes and k for kbytes + # b for bytes and k for kbytes assert_equal("2 k", number_to_human_size(2048, locale: "ts")) assert_equal("42 b", number_to_human_size(42, locale: "ts")) end @@ -125,11 +125,11 @@ module ActiveSupport end def test_number_to_human_with_default_translation_scope - #Using t for thousand + # Using t for thousand assert_equal "2 t", number_to_human(2000, locale: "ts") - #Significant was set to true with precision 2, using b for billion + # Significant was set to true with precision 2, using b for billion assert_equal "1.2 b", number_to_human(1234567890, locale: "ts") - #Using pluralization (Ten/Tens and Tenth/Tenths) + # Using pluralization (Ten/Tens and Tenth/Tenths) assert_equal "1 Tenth", number_to_human(0.1, locale: "ts") assert_equal "1.3 Tenth", number_to_human(0.134, locale: "ts") assert_equal "2 Tenths", number_to_human(0.2, locale: "ts") @@ -144,7 +144,7 @@ module ActiveSupport end def test_number_to_human_with_custom_translation_scope - #Significant was set to true with precision 2, with custom translated units + # Significant was set to true with precision 2, with custom translated units assert_equal "4.3 cm", number_to_human(0.0432, locale: "ts", units: :custom_units_for_number_to_human) end end diff --git a/activesupport/test/number_helper_test.rb b/activesupport/test/number_helper_test.rb index b4795b6ee1..16ccc5572c 100644 --- a/activesupport/test/number_helper_test.rb +++ b/activesupport/test/number_helper_test.rb @@ -260,7 +260,7 @@ module ActiveSupport assert_equal "40 KB", number_helper.number_to_human_size(41100, precision: 2) assert_equal "1.0 KB", number_helper.number_to_human_size(kilobytes(1.0123), precision: 2, strip_insignificant_zeros: false) assert_equal "1.012 KB", number_helper.number_to_human_size(kilobytes(1.0123), precision: 3, significant: false) - assert_equal "1 KB", number_helper.number_to_human_size(kilobytes(1.0123), precision: 0, significant: true) #ignores significant it precision is 0 + assert_equal "1 KB", number_helper.number_to_human_size(kilobytes(1.0123), precision: 0, significant: true) # ignores significant it precision is 0 end end @@ -292,7 +292,7 @@ module ActiveSupport assert_equal "489.0 Thousand", number_helper.number_to_human(489000, precision: 4, strip_insignificant_zeros: false) assert_equal "1.2346 Million", number_helper.number_to_human(1234567, precision: 4, significant: false) assert_equal "1,2 Million", number_helper.number_to_human(1234567, precision: 1, significant: false, separator: ",") - assert_equal "1 Million", number_helper.number_to_human(1234567, precision: 0, significant: true, separator: ",") #significant forced to false + assert_equal "1 Million", number_helper.number_to_human(1234567, precision: 0, significant: true, separator: ",") # significant forced to false assert_equal "1 Million", number_helper.number_to_human(999999) assert_equal "1 Billion", number_helper.number_to_human(999999999) end @@ -300,13 +300,13 @@ module ActiveSupport def test_number_to_human_with_custom_units [@instance_with_helpers, TestClassWithClassNumberHelpers, ActiveSupport::NumberHelper].each do |number_helper| - #Only integers + # Only integers volume = { unit: "ml", thousand: "lt", million: "m3" } assert_equal "123 lt", number_helper.number_to_human(123456, units: volume) assert_equal "12 ml", number_helper.number_to_human(12, units: volume) assert_equal "1.23 m3", number_helper.number_to_human(1234567, units: volume) - #Including fractionals + # Including fractionals distance = { mili: "mm", centi: "cm", deci: "dm", unit: "m", ten: "dam", hundred: "hm", thousand: "km" } assert_equal "1.23 mm", number_helper.number_to_human(0.00123, units: distance) assert_equal "1.23 cm", number_helper.number_to_human(0.0123, units: distance) @@ -319,7 +319,7 @@ module ActiveSupport assert_equal "1.23 km", number_helper.number_to_human(1230, units: distance) assert_equal "12.3 km", number_helper.number_to_human(12300, units: distance) - #The quantifiers don't need to be a continuous sequence + # The quantifiers don't need to be a continuous sequence gangster = { hundred: "hundred bucks", million: "thousand quids" } assert_equal "1 hundred bucks", number_helper.number_to_human(100, units: gangster) assert_equal "25 hundred bucks", number_helper.number_to_human(2500, units: gangster) @@ -329,11 +329,11 @@ module ActiveSupport assert_equal "25 thousand quids", number_helper.number_to_human(25000000, units: gangster) assert_equal "12300 thousand quids", number_helper.number_to_human(12345000000, units: gangster) - #Spaces are stripped from the resulting string + # Spaces are stripped from the resulting string assert_equal "4", number_helper.number_to_human(4, units: { unit: "", ten: "tens " }) assert_equal "4.5 tens", number_helper.number_to_human(45, units: { unit: "", ten: " tens " }) - #Uses only the provided units and does not try to use larger ones + # Uses only the provided units and does not try to use larger ones assert_equal "1000 kilometers", number_helper.number_to_human(1_000_000, units: { unit: "meter", thousand: "kilometers" }) end end diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb index 7f2e774c02..90394fee0a 100644 --- a/activesupport/test/ordered_options_test.rb +++ b/activesupport/test/ordered_options_test.rb @@ -15,7 +15,7 @@ class OrderedOptionsTest < ActiveSupport::TestCase a[:allow_concurrency] = false assert_equal 1, a.size - assert !a[:allow_concurrency] + assert_not a[:allow_concurrency] a["else_where"] = 56 assert_equal 2, a.size @@ -47,7 +47,7 @@ class OrderedOptionsTest < ActiveSupport::TestCase a.allow_concurrency = false assert_equal 1, a.size - assert !a.allow_concurrency + assert_not a.allow_concurrency a.else_where = 56 assert_equal 2, a.size @@ -82,8 +82,8 @@ class OrderedOptionsTest < ActiveSupport::TestCase def test_introspection a = ActiveSupport::OrderedOptions.new - assert a.respond_to?(:blah) - assert a.respond_to?(:blah=) + assert_respond_to a, :blah + assert_respond_to a, :blah= assert_equal 42, a.method(:blah=).call(42) assert_equal 42, a.method(:blah).call end @@ -91,7 +91,20 @@ class OrderedOptionsTest < ActiveSupport::TestCase def test_raises_with_bang a = ActiveSupport::OrderedOptions.new a[:foo] = :bar - assert a.respond_to?(:foo!) + assert_respond_to a, :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 + + def test_inheritable_options_with_bang + a = ActiveSupport::InheritableOptions.new(foo: :bar) assert_nothing_raised { a.foo! } assert_equal a.foo, a.foo! diff --git a/activesupport/test/reloader_test.rb b/activesupport/test/reloader_test.rb index 3e4229eaf7..976917c1a1 100644 --- a/activesupport/test/reloader_test.rb +++ b/activesupport/test/reloader_test.rb @@ -8,18 +8,18 @@ class ReloaderTest < ActiveSupport::TestCase reloader.to_prepare { prepared = true } reloader.to_complete { completed = true } - assert !prepared - assert !completed + assert_not prepared + assert_not completed reloader.prepare! assert prepared - assert !completed + assert_not completed prepared = false reloader.wrap do assert prepared prepared = false end - assert !prepared + assert_not prepared end def test_prepend_prepare_callback @@ -42,7 +42,7 @@ class ReloaderTest < ActiveSupport::TestCase invoked = false r.to_run { invoked = true } r.wrap {} - assert !invoked + assert_not invoked end def test_full_reload_sequence diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 05c2fb59be..1c19c92bb0 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -39,7 +39,7 @@ class SafeBufferTest < ActiveSupport::TestCase end test "Should be considered safe" do - assert @buffer.html_safe? + assert_predicate @buffer, :html_safe? end test "Should return a safe buffer when calling to_s" do @@ -78,13 +78,13 @@ class SafeBufferTest < ActiveSupport::TestCase test "Should not return safe buffer from gsub" do altered_buffer = @buffer.gsub("", "asdf") assert_equal "asdf", altered_buffer - assert !altered_buffer.html_safe? + assert_not_predicate altered_buffer, :html_safe? end test "Should not return safe buffer from gsub!" do @buffer.gsub!("", "asdf") assert_equal "asdf", @buffer - assert !@buffer.html_safe? + assert_not_predicate @buffer, :html_safe? end test "Should escape dirty buffers on add" do @@ -101,13 +101,13 @@ class SafeBufferTest < ActiveSupport::TestCase test "Should preserve html_safe? status on copy" do @buffer.gsub!("", "<>") - assert !@buffer.dup.html_safe? + assert_not_predicate @buffer.dup, :html_safe? end test "Should return safe buffer when added with another safe buffer" do clean = "<script>".html_safe result_buffer = @buffer + clean - assert result_buffer.html_safe? + assert_predicate result_buffer, :html_safe? assert_equal "<script>", result_buffer end @@ -127,8 +127,8 @@ class SafeBufferTest < ActiveSupport::TestCase end test "clone_empty keeps the original dirtyness" do - assert @buffer.clone_empty.html_safe? - assert !@buffer.gsub!("", "").clone_empty.html_safe? + assert_predicate @buffer.clone_empty, :html_safe? + assert_not_predicate @buffer.gsub!("", "").clone_empty, :html_safe? end test "Should be safe when sliced if original value was safe" do diff --git a/activesupport/test/security_utils_test.rb b/activesupport/test/security_utils_test.rb index efd2bcfa0f..fff9cc2a8d 100644 --- a/activesupport/test/security_utils_test.rb +++ b/activesupport/test/security_utils_test.rb @@ -9,8 +9,14 @@ class SecurityUtilsTest < ActiveSupport::TestCase assert_not ActiveSupport::SecurityUtils.secure_compare("a", "b") end - def test_variable_size_secure_compare_should_perform_string_comparison - assert ActiveSupport::SecurityUtils.variable_size_secure_compare("a", "a") - assert_not ActiveSupport::SecurityUtils.variable_size_secure_compare("a", "b") + def test_fixed_length_secure_compare_should_perform_string_comparison + assert ActiveSupport::SecurityUtils.fixed_length_secure_compare("a", "a") + assert_not ActiveSupport::SecurityUtils.fixed_length_secure_compare("a", "b") + end + + def test_fixed_length_secure_compare_raise_on_length_mismatch + assert_raises(ArgumentError, "string length mismatch.") do + ActiveSupport::SecurityUtils.fixed_length_secure_compare("a", "ab") + end end end diff --git a/activesupport/test/string_inquirer_test.rb b/activesupport/test/string_inquirer_test.rb index bf8f878a32..09726b144a 100644 --- a/activesupport/test/string_inquirer_test.rb +++ b/activesupport/test/string_inquirer_test.rb @@ -8,11 +8,11 @@ class StringInquirerTest < ActiveSupport::TestCase end def test_match - assert @string_inquirer.production? + assert_predicate @string_inquirer, :production? end def test_miss - assert_not @string_inquirer.development? + assert_not_predicate @string_inquirer, :development? end def test_missing_question_mark diff --git a/activesupport/test/tagged_logging_test.rb b/activesupport/test/tagged_logging_test.rb index 5fd6a6b316..e2b41cf8ee 100644 --- a/activesupport/test/tagged_logging_test.rb +++ b/activesupport/test/tagged_logging_test.rb @@ -21,7 +21,7 @@ class TaggedLoggingTest < ActiveSupport::TestCase assert_nil logger.formatter ActiveSupport::TaggedLogging.new(logger) assert_not_nil logger.formatter - assert logger.formatter.respond_to?(:tagged) + assert_respond_to logger.formatter, :tagged end test "tagged once" do @@ -74,11 +74,12 @@ class TaggedLoggingTest < ActiveSupport::TestCase test "keeps each tag in their own thread" do @logger.tagged("BCX") do Thread.new do + @logger.info "Dull story" @logger.tagged("OMG") { @logger.info "Cool story" } end.join @logger.info "Funky time" end - assert_equal "[OMG] Cool story\n[BCX] Funky time\n", @output.string + assert_equal "Dull story\n[OMG] Cool story\n[BCX] Funky time\n", @output.string end test "keeps each tag in their own instance" do diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 65b1cb4a14..8a1ecb6b33 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -2,7 +2,7 @@ require "abstract_unit" -class AssertDifferenceTest < ActiveSupport::TestCase +class AssertionsTest < ActiveSupport::TestCase def setup @object = Class.new do attr_accessor :num @@ -87,7 +87,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase def test_expression_is_evaluated_in_the_appropriate_scope silence_warnings do - local_scope = "foo"; + local_scope = "foo" local_scope = local_scope # to suppress unused variable warning assert_difference("local_scope; @object.num") { @object.increment } end @@ -115,6 +115,35 @@ class AssertDifferenceTest < ActiveSupport::TestCase end end + def test_hash_of_expressions + assert_difference "@object.num" => 1, "@object.num + 1" => 1 do + @object.increment + end + end + + def test_hash_of_expressions_with_message + error = assert_raises Minitest::Assertion do + assert_difference({ "@object.num" => 0 }, "Object Changed") do + @object.increment + end + end + assert_equal "Object Changed.\n\"@object.num\" didn't change by 0.\nExpected: 0\n Actual: 1", error.message + end + + def test_hash_of_lambda_expressions + assert_difference -> { @object.num } => 1, -> { @object.num + 1 } => 1 do + @object.increment + end + end + + def test_hash_of_expressions_identify_failure + assert_raises(Minitest::Assertion) do + assert_difference "@object.num" => 1, "1 + 1" => 1 do + @object.increment + end + end + end + def test_assert_changes_pass assert_changes "@object.num" do @object.increment @@ -156,6 +185,16 @@ class AssertDifferenceTest < ActiveSupport::TestCase end end + def test_assert_changes_with_to_option_but_no_change_has_special_message + error = assert_raises Minitest::Assertion do + assert_changes "@object.num", to: 0 do + # no changes + end + end + + assert_equal "\"@object.num\" didn't change. It was already 0", error.message + end + def test_assert_changes_with_wrong_to_option assert_raises Minitest::Assertion do assert_changes "@object.num", to: 2 do @@ -179,6 +218,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase end def test_assert_changes_works_with_any_object + # Silences: instance variable @new_object not initialized. retval = silence_warnings do assert_changes :@new_object, from: nil, to: 42 do @new_object = 42 @@ -201,7 +241,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase def test_assert_changes_with_to_and_case_operator token = nil - assert_changes -> { token }, to: /\w{32}/ do + assert_changes -> { token }, to: /\w{32}/ do token = SecureRandom.hex end end @@ -217,6 +257,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase def test_assert_changes_with_message error = assert_raises Minitest::Assertion do assert_changes "@object.num", "@object.num should 1", to: 1 do + @object.decrement end end @@ -236,7 +277,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase end end - assert_equal "@object.num should not change.\n\"@object.num\" did change to 1.\nExpected: 0\n Actual: 1", error.message + assert_equal "@object.num should not change.\n\"@object.num\" did change to 1", error.message end end diff --git a/activesupport/test/testing/after_teardown_test.rb b/activesupport/test/testing/after_teardown_test.rb new file mode 100644 index 0000000000..961af49479 --- /dev/null +++ b/activesupport/test/testing/after_teardown_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require "abstract_unit" + +module OtherAfterTeardown + def after_teardown + super + + @witness = true + end +end + +class AfterTeardownTest < ActiveSupport::TestCase + include OtherAfterTeardown + + attr_writer :witness + + MyError = Class.new(StandardError) + + teardown do + raise MyError, "Test raises an error, all after_teardown should still get called" + end + + def after_teardown + assert_changes -> { failures.count }, from: 0, to: 1 do + super + end + + assert_equal true, @witness + failures.clear + end + + def test_teardown_raise_but_all_after_teardown_method_are_called + assert true + end +end diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index 4172c18ead..9c2c635f43 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -98,7 +98,7 @@ class TimeTravelTest < ActiveSupport::TestCase travel_to outer_expected_time do e = assert_raises(RuntimeError) do travel_to(inner_expected_time) do - #noop + # noop end end assert_match(/Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing\./, e.message) diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index acb0ecd226..b59f3e9405 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -32,6 +32,12 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_period_for_local_with_ambigiuous_time + zone = ActiveSupport::TimeZone["Moscow"] + period = zone.period_for_local(Time.utc(2015, 1, 1)) + assert_equal period, zone.period_for_local(Time.utc(2014, 10, 26, 1, 0, 0)) + end + def test_from_integer_to_map assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[-28800] # PST end @@ -195,6 +201,11 @@ class TimeZoneTest < ActiveSupport::TestCase assert_equal "EDT", twz.zone end + def test_local_with_ambiguous_time + zone = ActiveSupport::TimeZone["Moscow"] + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.local(2014, 10, 26, 1, 0, 0) + end + def test_at zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"] secs = 946684800.0 @@ -303,6 +314,11 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_iso8601_with_ambiguous_time + zone = ActiveSupport::TimeZone["Moscow"] + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.parse("2014-10-26T01:00:00") + end + def test_parse zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"] twz = zone.parse("1999-12-31 19:00:00") @@ -412,6 +428,11 @@ class TimeZoneTest < ActiveSupport::TestCase assert_equal "argument out of range", exception.message end + def test_parse_with_ambiguous_time + zone = ActiveSupport::TimeZone["Moscow"] + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.parse("2014-10-26 01:00:00") + end + def test_rfc3339 zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"] twz = zone.rfc3339("1999-12-31T14:00:00-10:00") @@ -604,6 +625,11 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_strptime_with_ambiguous_time + zone = ActiveSupport::TimeZone["Moscow"] + assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.strptime("2014-10-26 01:00:00", "%Y-%m-%d %H:%M:%S") + 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) @@ -692,6 +718,28 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_all_uninfluenced_by_time_zone_lookups_delegated_to_tzinfo + ActiveSupport::TimeZone.clear + galapagos = ActiveSupport::TimeZone["Pacific/Galapagos"] + all_zones = ActiveSupport::TimeZone.all + assert_not_includes all_zones, galapagos + end + + def test_all_doesnt_raise_exception_with_missing_tzinfo_data + mappings = { + "Puerto Rico" => "America/Unknown", + "Pittsburgh" => "America/New_York" + } + + with_tz_mappings(mappings) do + assert_nil ActiveSupport::TimeZone["Puerto Rico"] + assert_nil ActiveSupport::TimeZone[-9] + assert_nothing_raised do + ActiveSupport::TimeZone.all + end + end + end + def test_index assert_nil ActiveSupport::TimeZone["bogus"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"] @@ -723,6 +771,16 @@ class TimeZoneTest < ActiveSupport::TestCase assert_not_includes ActiveSupport::TimeZone.country_zones(:ru), ActiveSupport::TimeZone["Kuala Lumpur"] end + def test_country_zones_with_and_without_mappings + assert_includes ActiveSupport::TimeZone.country_zones("au"), ActiveSupport::TimeZone["Adelaide"] + assert_includes ActiveSupport::TimeZone.country_zones("au"), ActiveSupport::TimeZone["Australia/Lord_Howe"] + end + + def test_country_zones_with_multiple_mappings + assert_includes ActiveSupport::TimeZone.country_zones("gb"), ActiveSupport::TimeZone["Edinburgh"] + assert_includes ActiveSupport::TimeZone.country_zones("gb"), ActiveSupport::TimeZone["London"] + end + def test_country_zones_without_mappings assert_includes ActiveSupport::TimeZone.country_zones(:sv), ActiveSupport::TimeZone["America/El_Salvador"] end diff --git a/activesupport/test/time_zone_test_helpers.rb b/activesupport/test/time_zone_test_helpers.rb index 051703a781..85ed727c9b 100644 --- a/activesupport/test/time_zone_test_helpers.rb +++ b/activesupport/test/time_zone_test_helpers.rb @@ -23,4 +23,17 @@ module TimeZoneTestHelpers ensure ActiveSupport.to_time_preserves_timezone = old_preserve_tz end + + def with_tz_mappings(mappings) + old_mappings = ActiveSupport::TimeZone::MAPPING.dup + ActiveSupport::TimeZone.clear + ActiveSupport::TimeZone::MAPPING.clear + ActiveSupport::TimeZone::MAPPING.merge!(mappings) + + yield + ensure + ActiveSupport::TimeZone.clear + ActiveSupport::TimeZone::MAPPING.clear + ActiveSupport::TimeZone::MAPPING.merge!(old_mappings) + end end diff --git a/activesupport/test/xml_mini/libxml_engine_test.rb b/activesupport/test/xml_mini/libxml_engine_test.rb index 5c13f493f1..3eef3946a3 100644 --- a/activesupport/test/xml_mini/libxml_engine_test.rb +++ b/activesupport/test/xml_mini/libxml_engine_test.rb @@ -6,7 +6,7 @@ XMLMiniEngineTest.run_with_gem("libxml") do class LibxmlEngineTest < XMLMiniEngineTest def setup super - LibXML::XML::Error.set_handler(&lambda { |error| }) #silence libxml, exceptions will do + LibXML::XML::Error.set_handler(&lambda { |error| }) # silence libxml, exceptions will do end private diff --git a/activesupport/test/xml_mini_test.rb b/activesupport/test/xml_mini_test.rb index 5e46406a7b..18a3f2ca66 100644 --- a/activesupport/test/xml_mini_test.rb +++ b/activesupport/test/xml_mini_test.rb @@ -114,7 +114,7 @@ module XmlMiniTest end test "#to_tag accepts decimal types" do - @xml.to_tag(:b, ::BigDecimal.new("1.2"), @options) + @xml.to_tag(:b, BigDecimal("1.2"), @options) assert_xml("<b type=\"decimal\">1.2</b>") end |