diff options
Diffstat (limited to 'activesupport/test')
41 files changed, 605 insertions, 376 deletions
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 168d3655d3..01e60abd99 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -39,8 +39,6 @@ class ActiveSupport::TestCase def jruby_skip(message = "") skip message if defined?(JRUBY_VERSION) end - - def frozen_error_class - Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError - end end + +require_relative "../../tools/test_common" diff --git a/activesupport/test/actionable_error_test.rb b/activesupport/test/actionable_error_test.rb new file mode 100644 index 0000000000..63046b937c --- /dev/null +++ b/activesupport/test/actionable_error_test.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "active_support/actionable_error" + +class ActionableErrorTest < ActiveSupport::TestCase + NonActionableError = Class.new(StandardError) + + class DispatchableError < StandardError + include ActiveSupport::ActionableError + + class_attribute :flip1, default: false + class_attribute :flip2, default: false + + action "Flip 1" do + self.flip1 = true + end + + action "Flip 2" do + self.flip2 = true + end + end + + test "returns all action of an actionable error" do + assert_equal ["Flip 1", "Flip 2"], ActiveSupport::ActionableError.actions(DispatchableError).keys + assert_equal ["Flip 1", "Flip 2"], ActiveSupport::ActionableError.actions(DispatchableError.new).keys + end + + test "returns no actions for non-actionable errors" do + assert ActiveSupport::ActionableError.actions(Exception).empty? + assert ActiveSupport::ActionableError.actions(Exception.new).empty? + end + + test "dispatches actions from error and name" do + assert_changes "DispatchableError.flip1", from: false, to: true do + ActiveSupport::ActionableError.dispatch DispatchableError, "Flip 1" + end + end + + test "cannot dispatch missing actions" do + err = assert_raises ActiveSupport::ActionableError::NonActionable do + ActiveSupport::ActionableError.dispatch NonActionableError, "action" + end + + assert_equal 'Cannot find action "action"', err.to_s + end +end diff --git a/activesupport/test/autoloading_fixtures/raises_load_error.rb b/activesupport/test/autoloading_fixtures/raises_load_error.rb new file mode 100644 index 0000000000..f97be29b71 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/raises_load_error.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +# raises a load error typical of the dynamic code that manually raises load errors +raise LoadError, "required gem not present kind of error" diff --git a/activesupport/test/cache/behaviors/cache_store_behavior.rb b/activesupport/test/cache/behaviors/cache_store_behavior.rb index 9f54b1e7de..a696760bb2 100644 --- a/activesupport/test/cache/behaviors/cache_store_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_store_behavior.rb @@ -130,7 +130,7 @@ module CacheStoreBehavior assert_equal("fufu", @cache.read("fu")) end - def test_multi_with_objects + def test_fetch_multi_with_objects cache_struct = Struct.new(:cache_key, :title) foo = cache_struct.new("foo", "FOO!") bar = cache_struct.new("bar") @@ -142,6 +142,14 @@ module CacheStoreBehavior assert_equal({ foo => "FOO!", bar => "BAM!" }, values) end + def test_fetch_multi_returns_ordered_names + @cache.write("bam", "BAM") + + values = @cache.fetch_multi("foo", "bar", "bam") { |key| key.upcase } + + assert_equal(%w(foo bar bam), values.keys) + end + def test_fetch_multi_without_block assert_raises(ArgumentError) do @cache.fetch_multi("foo") diff --git a/activesupport/test/cache/behaviors/connection_pool_behavior.rb b/activesupport/test/cache/behaviors/connection_pool_behavior.rb index 4d1901a173..aed04d07d4 100644 --- a/activesupport/test/cache/behaviors/connection_pool_behavior.rb +++ b/activesupport/test/cache/behaviors/connection_pool_behavior.rb @@ -7,24 +7,22 @@ module ConnectionPoolBehavior threads = [] emulating_latency do - begin - cache = ActiveSupport::Cache.lookup_store(store, { pool_size: 2, pool_timeout: 1 }.merge(store_options)) - cache.clear - - 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 + cache = ActiveSupport::Cache.lookup_store(*store, { pool_size: 2, pool_timeout: 1 }.merge(store_options)) + cache.clear + + 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 - - threads.each(&:join) end - ensure - threads.each(&:kill) + + threads.each(&:join) end + ensure + threads.each(&:kill) end ensure Thread.report_on_exception = original_report_on_exception @@ -34,24 +32,22 @@ module ConnectionPoolBehavior threads = [] emulating_latency do - begin - cache = ActiveSupport::Cache.lookup_store(store, store_options) - cache.clear - - 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 + cache = ActiveSupport::Cache.lookup_store(*store, store_options) + cache.clear + + 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 - - threads.each(&:join) end - ensure - threads.each(&:kill) + + threads.each(&:join) end + ensure + threads.each(&:kill) end end diff --git a/activesupport/test/cache/stores/file_store_test.rb b/activesupport/test/cache/stores/file_store_test.rb index f6855bb308..0364d9ab64 100644 --- a/activesupport/test/cache/stores/file_store_test.rb +++ b/activesupport/test/cache/stores/file_store_test.rb @@ -101,7 +101,7 @@ 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_empty Dir.entries(sub_cache_dir).reject { |f| ActiveSupport::Cache::FileStore::EXCLUDED_DIRS.include?(f) } + assert_empty Dir.children(sub_cache_dir) end def test_log_exception_when_cache_read_fails diff --git a/activesupport/test/cache/stores/mem_cache_store_test.rb b/activesupport/test/cache/stores/mem_cache_store_test.rb index f426a37c66..0e472f5a1a 100644 --- a/activesupport/test/cache/stores/mem_cache_store_test.rb +++ b/activesupport/test/cache/stores/mem_cache_store_test.rb @@ -25,8 +25,9 @@ end class MemCacheStoreTest < ActiveSupport::TestCase begin - ss = Dalli::Client.new("localhost:11211").stats - raise Dalli::DalliError unless ss["localhost:11211"] + servers = ENV["MEMCACHE_SERVERS"] || "localhost:11211" + ss = Dalli::Client.new(servers).stats + raise Dalli::DalliError unless ss[servers] MEMCACHE_UP = true rescue Dalli::DalliError @@ -37,8 +38,8 @@ class MemCacheStoreTest < ActiveSupport::TestCase def setup skip "memcache server is not up" unless MEMCACHE_UP - @cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, expires_in: 60) - @peek = ActiveSupport::Cache.lookup_store(:mem_cache_store) + @cache = ActiveSupport::Cache.lookup_store(*store, expires_in: 60) + @peek = ActiveSupport::Cache.lookup_store(*store) @data = @cache.instance_variable_get(:@data) @cache.clear @cache.silence! @@ -56,21 +57,21 @@ class MemCacheStoreTest < ActiveSupport::TestCase include FailureSafetyBehavior def test_raw_values - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*store, raw: true) cache.clear cache.write("foo", 2) assert_equal "2", cache.read("foo") end def test_raw_values_with_marshal - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*store, raw: true) cache.clear cache.write("foo", Marshal.dump([])) assert_equal [], cache.read("foo") end def test_local_cache_raw_values - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*store, raw: true) cache.clear cache.with_local_cache do cache.write("foo", 2) @@ -79,7 +80,7 @@ class MemCacheStoreTest < ActiveSupport::TestCase end def test_increment_expires_in - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*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) @@ -87,7 +88,7 @@ class MemCacheStoreTest < ActiveSupport::TestCase end def test_decrement_expires_in - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*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) @@ -95,7 +96,7 @@ class MemCacheStoreTest < ActiveSupport::TestCase end def test_local_cache_raw_values_with_marshal - cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true) + cache = ActiveSupport::Cache.lookup_store(*store, raw: true) cache.clear cache.with_local_cache do cache.write("foo", Marshal.dump([])) @@ -114,7 +115,7 @@ class MemCacheStoreTest < ActiveSupport::TestCase private def store - :mem_cache_store + [:mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"] end def emulating_latency diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index 305a2c184d..790534cd3c 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -140,6 +140,12 @@ module ActiveSupport::Cache::RedisCacheStoreTests end end + def test_fetch_multi_without_names + assert_not_called(@cache.redis, :mget) do + @cache.fetch_multi() { } + end + end + def test_increment_expires_in assert_called_with @cache.redis, :incrby, [ "#{@namespace}:foo", 1 ] do assert_called_with @cache.redis, :expire, [ "#{@namespace}:foo", 60 ] do @@ -187,7 +193,7 @@ module ActiveSupport::Cache::RedisCacheStoreTests private def store - :redis_cache_store + [:redis_cache_store] end def emulating_latency @@ -204,7 +210,7 @@ module ActiveSupport::Cache::RedisCacheStoreTests class RedisDistributedConnectionPoolBehaviourTest < ConnectionPoolBehaviourTest private def store_options - { url: %w[ redis://localhost:6379/0 redis://localhost:6379/0 ] } + { url: [ENV["REDIS_URL"] || "redis://localhost:6379/0"] * 2 } end end diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 466b364e9d..79098b2a7d 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -31,7 +31,7 @@ module CallbacksTest def callback_object(callback_method) klass = Class.new - klass.send(:define_method, callback_method) do |model| + klass.define_method(callback_method) do |model| model.history << [:"#{callback_method}_save", :object] end klass.new diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb index 2c6145940b..cdb8441b81 100644 --- a/activesupport/test/constantize_test_cases.rb +++ b/activesupport/test/constantize_test_cases.rb @@ -112,6 +112,16 @@ module ConstantizeTestCases assert_nil yield("A::Object::B") assert_nil yield("A::Object::Object::Object::B") + with_autoloading_fixtures do + assert_nil yield("Em") + end + + assert_raises(LoadError) do + with_autoloading_fixtures do + yield("RaisesLoadError") + end + end + assert_raises(NameError) do with_autoloading_fixtures do yield("RaisesNameError") diff --git a/activesupport/test/core_ext/array/access_test.rb b/activesupport/test/core_ext/array/access_test.rb index 8c217023cf..427b058925 100644 --- a/activesupport/test/core_ext/array/access_test.rb +++ b/activesupport/test/core_ext/array/access_test.rb @@ -32,6 +32,18 @@ class AccessTest < ActiveSupport::TestCase assert_equal array[-2], array.second_to_last end + def test_including + assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including(3, 5).sort + assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including([3, 5]).sort + assert_equal [[0, 1], [1, 0]], [[0, 1]].including([[1, 0]]) + end + + def test_excluding + assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding(3, 5) + assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding([3, 5]) + assert_equal [[0, 1]], [[0, 1], [1, 0]].excluding([[1, 0]]) + end + def test_without assert_equal [1, 2, 4], [1, 2, 3, 4, 5].without(3, 5) end diff --git a/activesupport/test/core_ext/array/prepend_append_test.rb b/activesupport/test/core_ext/array/prepend_append_test.rb index c34acd66ad..8573dbd5a6 100644 --- a/activesupport/test/core_ext/array/prepend_append_test.rb +++ b/activesupport/test/core_ext/array/prepend_append_test.rb @@ -1,14 +1,11 @@ # frozen_string_literal: true require "abstract_unit" -require "active_support/core_ext/array" class PrependAppendTest < ActiveSupport::TestCase - def test_append - assert_equal [1, 2], [1].append(2) - end - - def test_prepend - assert_equal [2, 1], [1].prepend(2) + def test_requiring_prepend_and_append_is_deprecated + assert_deprecated do + require "active_support/core_ext/array/prepend_and_append" + end end end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index b63464a36a..381b5a1f32 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -217,11 +217,18 @@ class EnumerableTests < ActiveSupport::TestCase assert_equal false, GenericEnumerable.new([ 1 ]).exclude?(1) end + def test_excluding + assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).excluding(3, 5) + assert_equal [3, 4, 5], GenericEnumerable.new((1..5).to_a).excluding([1, 2]) + assert_equal [[0, 1]], GenericEnumerable.new([[0, 1], [1, 0]]).excluding([[1, 0]]) + assert_equal [1, 2, 4], (1..5).to_a.excluding(3, 5) + assert_equal [1, 2, 4], (1..5).to_set.excluding(3, 5) + assert_equal({ foo: 1, baz: 3 }, { foo: 1, bar: 2, baz: 3 }.excluding(:bar)) + end + def test_without assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).without(3, 5) - assert_equal [1, 2, 4], (1..5).to_a.without(3, 5) - assert_equal [1, 2, 4], (1..5).to_set.without(3, 5) - assert_equal({ foo: 1, baz: 3 }, { foo: 1, bar: 2, baz: 3 }.without(:bar)) + assert_equal [3, 4, 5], GenericEnumerable.new((1..5).to_a).without([1, 2]) end def test_pluck diff --git a/activesupport/test/core_ext/hash/transform_keys_test.rb b/activesupport/test/core_ext/hash/transform_keys_test.rb deleted file mode 100644 index b9e41f7b25..0000000000 --- a/activesupport/test/core_ext/hash/transform_keys_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -require "abstract_unit" -require "active_support/core_ext/hash/keys" - -class TransformKeysTest < ActiveSupport::TestCase - test "transform_keys returns a new hash with the keys computed from the block" do - original = { a: "a", b: "b" } - mapped = original.transform_keys { |k| "#{k}!".to_sym } - - assert_equal({ a: "a", b: "b" }, original) - assert_equal({ a!: "a", b!: "b" }, mapped) - end - - test "transform_keys! modifies the keys of the original" do - original = { a: "a", b: "b" } - mapped = original.transform_keys! { |k| "#{k}!".to_sym } - - assert_equal({ a!: "a", b!: "b" }, original) - assert_same original, mapped - end - - test "transform_keys returns a sized Enumerator if no block is given" do - original = { a: "a", b: "b" } - enumerator = original.transform_keys - assert_equal original.size, enumerator.size - assert_equal Enumerator, enumerator.class - end - - test "transform_keys! returns a sized Enumerator if no block is given" do - original = { a: "a", b: "b" } - enumerator = original.transform_keys! - assert_equal original.size, enumerator.size - assert_equal Enumerator, enumerator.class - end - - test "transform_keys is chainable with Enumerable methods" do - original = { a: "a", b: "b" } - mapped = original.transform_keys.with_index { |k, i| [k, i].join.to_sym } - assert_equal({ a0: "a", b1: "b" }, mapped) - end - - test "transform_keys! is chainable with Enumerable methods" do - original = { a: "a", b: "b" } - original.transform_keys!.with_index { |k, i| [k, i].join.to_sym } - assert_equal({ a0: "a", b1: "b" }, original) - end - - test "transform_keys returns a Hash instance when self is inherited from Hash" do - class HashDescendant < ::Hash - def initialize(elements = nil) - super(elements) - (elements || {}).each_pair { |key, value| self[key] = value } - end - end - - original = HashDescendant.new(a: "a", b: "b") - mapped = original.transform_keys { |k| "#{k}!".to_sym } - - assert_equal({ a: "a", b: "b" }, original) - assert_equal({ a!: "a", b!: "b" }, mapped) - assert_equal(::Hash, mapped.class) - end -end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index f4f0dd6b31..8572d56722 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -31,10 +31,10 @@ class HashExtTest < ActiveSupport::TestCase def test_methods h = {} - assert_respond_to h, :transform_keys - assert_respond_to h, :transform_keys! assert_respond_to h, :deep_transform_keys assert_respond_to h, :deep_transform_keys! + assert_respond_to h, :deep_transform_values + assert_respond_to h, :deep_transform_values! assert_respond_to h, :symbolize_keys assert_respond_to h, :symbolize_keys! assert_respond_to h, :deep_symbolize_keys @@ -49,18 +49,6 @@ class HashExtTest < ActiveSupport::TestCase assert_respond_to h, :except! end - def test_transform_keys - assert_equal @upcase_strings, @strings.transform_keys { |key| key.to_s.upcase } - assert_equal @upcase_strings, @symbols.transform_keys { |key| key.to_s.upcase } - assert_equal @upcase_strings, @mixed.transform_keys { |key| key.to_s.upcase } - end - - def test_transform_keys_not_mutates - transformed_hash = @mixed.dup - transformed_hash.transform_keys { |key| key.to_s.upcase } - assert_equal @mixed, transformed_hash - end - def test_deep_transform_keys assert_equal @nested_upcase_strings, @nested_symbols.deep_transform_keys { |key| key.to_s.upcase } assert_equal @nested_upcase_strings, @nested_strings.deep_transform_keys { |key| key.to_s.upcase } @@ -76,19 +64,6 @@ class HashExtTest < ActiveSupport::TestCase assert_equal @nested_mixed, transformed_hash end - def test_transform_keys! - assert_equal @upcase_strings, @symbols.dup.transform_keys! { |key| key.to_s.upcase } - assert_equal @upcase_strings, @strings.dup.transform_keys! { |key| key.to_s.upcase } - assert_equal @upcase_strings, @mixed.dup.transform_keys! { |key| key.to_s.upcase } - end - - def test_transform_keys_with_bang_mutates - transformed_hash = @mixed.dup - transformed_hash.transform_keys! { |key| key.to_s.upcase } - assert_equal @upcase_strings, transformed_hash - assert_equal({ :a => 1, "b" => 2 }, @mixed) - end - def test_deep_transform_keys! assert_equal @nested_upcase_strings, @nested_symbols.deep_dup.deep_transform_keys! { |key| key.to_s.upcase } assert_equal @nested_upcase_strings, @nested_strings.deep_dup.deep_transform_keys! { |key| key.to_s.upcase } @@ -105,6 +80,31 @@ class HashExtTest < ActiveSupport::TestCase assert_equal({ "a" => { b: { "c" => 3 } } }, @nested_mixed) end + def test_deep_transform_values + assert_equal({ "a" => "1", "b" => "2" }, @strings.deep_transform_values { |value| value.to_s }) + assert_equal({ "a" => { "b" => { "c" => "3" } } }, @nested_strings.deep_transform_values { |value| value.to_s }) + assert_equal({ "a" => [ { "b" => "2" }, { "c" => "3" }, "4" ] }, @string_array_of_hashes.deep_transform_values { |value| value.to_s }) + end + + def test_deep_transform_values_not_mutates + transformed_hash = @nested_mixed.deep_dup + transformed_hash.deep_transform_values { |value| value.to_s } + assert_equal @nested_mixed, transformed_hash + end + + def test_deep_transform_values! + assert_equal({ "a" => "1", "b" => "2" }, @strings.deep_transform_values! { |value| value.to_s }) + assert_equal({ "a" => { "b" => { "c" => "3" } } }, @nested_strings.deep_transform_values! { |value| value.to_s }) + assert_equal({ "a" => [ { "b" => "2" }, { "c" => "3" }, "4" ] }, @string_array_of_hashes.deep_transform_values! { |value| value.to_s }) + end + + def test_deep_transform_values_with_bang_mutates + transformed_hash = @nested_mixed.deep_dup + transformed_hash.deep_transform_values! { |value| value.to_s } + assert_equal({ "a" => { b: { "c" => "3" } } }, transformed_hash) + assert_equal({ "a" => { b: { "c" => 3 } } }, @nested_mixed) + end + def test_symbolize_keys assert_equal @symbols, @symbols.symbolize_keys assert_equal @symbols, @strings.symbolize_keys @@ -337,30 +337,16 @@ class HashExtTest < ActiveSupport::TestCase assert_equal expected, merged end - def test_slice - original = { a: "x", b: "y", c: 10 } - expected = { a: "x", b: "y" } - - # Should return a new hash with only the given keys. - assert_equal expected, original.slice(:a, :b) - assert_not_equal expected, original - end - def test_slice_inplace original = { a: "x", b: "y", c: 10 } - expected = { c: 10 } - - # Should replace the hash with only the given keys. - assert_equal expected, original.slice!(:a, :b) - end + expected_return = { c: 10 } + expected_original = { a: "x", b: "y" } - def test_slice_with_an_array_key - original = { :a => "x", :b => "y", :c => 10, [:a, :b] => "an array key" } - expected = { [:a, :b] => "an array key", :c => 10 } + # Should return a hash containing the removed key/value pairs. + assert_equal expected_return, original.slice!(:a, :b) - # Should return a new hash with only the given keys when given an array key. - assert_equal expected, original.slice([:a, :b], :c) - assert_not_equal expected, original + # Should replace the hash with only the given keys. + assert_equal expected_original, original end def test_slice_inplace_with_an_array_key @@ -371,14 +357,6 @@ class HashExtTest < ActiveSupport::TestCase assert_equal expected, original.slice!([:a, :b], :c) end - def test_slice_with_splatted_keys - original = { :a => "x", :b => "y", :c => 10, [:a, :b] => "an array key" } - expected = { a: "x", b: "y" } - - # Should grab each of the splatted keys. - assert_equal expected, original.slice(*[:a, :b]) - end - def test_slice_bang_does_not_override_default hash = Hash.new(0) hash.update(a: 1, b: 2) @@ -444,7 +422,7 @@ class HashExtTest < ActiveSupport::TestCase original.freeze assert_nothing_raised { original.except(:a) } - assert_raise(frozen_error_class) { original.except!(:a) } + assert_raise(FrozenError) { original.except!(:a) } end def test_except_does_not_delete_values_in_original diff --git a/activesupport/test/core_ext/load_error_test.rb b/activesupport/test/core_ext/load_error_test.rb index 126aa51cb4..6d3726e407 100644 --- a/activesupport/test/core_ext/load_error_test.rb +++ b/activesupport/test/core_ext/load_error_test.rb @@ -13,10 +13,9 @@ class TestLoadError < ActiveSupport::TestCase end def test_path - begin load "nor/this/one.rb" - rescue LoadError => e - assert_equal "nor/this/one.rb", e.path - end + load "nor/this/one.rb" + rescue LoadError => e + assert_equal "nor/this/one.rb", e.path end def test_is_missing_with_nil_path diff --git a/activesupport/test/core_ext/module/reachable_test.rb b/activesupport/test/core_ext/module/reachable_test.rb deleted file mode 100644 index f356d46957..0000000000 --- a/activesupport/test/core_ext/module/reachable_test.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -require "abstract_unit" -require "active_support/core_ext/module/reachable" - -class AnonymousTest < ActiveSupport::TestCase - test "an anonymous class or module is not reachable" do - 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_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 - c = eval "class C; end; C" - m = eval "module M; end; M" - - self.class.send(:remove_const, :C) - self.class.send(:remove_const, :M) - - 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 - c = eval "class C; end; C" - m = eval "module M; end; M" - - self.class.send(:remove_const, :C) - self.class.send(:remove_const, :M) - - eval "class C; end" - eval "module M; end" - - 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/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 4b8efb8a93..16d6a4c2f2 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -57,7 +57,7 @@ class RangeTest < ActiveSupport::TestCase end def test_should_include_other_with_exclusive_end - assert((1..10).include?(1...10)) + assert((1..10).include?(1...11)) end def test_should_compare_identical_inclusive @@ -69,7 +69,7 @@ class RangeTest < ActiveSupport::TestCase end def test_should_compare_other_with_exclusive_end - assert((1..10) === (1...10)) + assert((1..10) === (1...11)) end def test_exclusive_end_should_not_include_identical_with_inclusive_end @@ -93,6 +93,10 @@ class RangeTest < ActiveSupport::TestCase assert range.method(:include?) != range.method(:cover?) end + def test_should_cover_other_with_exclusive_end + assert((1..10).cover?(1...11)) + end + def test_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, 00)..Time.utc(2005, 12, 10, 18, 00) diff --git a/activesupport/test/core_ext/secure_random_test.rb b/activesupport/test/core_ext/secure_random_test.rb index 7067fb524c..4b73233971 100644 --- a/activesupport/test/core_ext/secure_random_test.rb +++ b/activesupport/test/core_ext/secure_random_test.rb @@ -19,4 +19,24 @@ class SecureRandomTest < ActiveSupport::TestCase assert_not_equal s1, s2 assert_equal 24, s1.length end + + def test_base36 + s1 = SecureRandom.base36 + s2 = SecureRandom.base36 + + assert_not_equal s1, s2 + assert_equal 16, s1.length + assert_match(/^[a-z0-9]+$/, s1) + assert_match(/^[a-z0-9]+$/, s2) + end + + def test_base36_with_length + s1 = SecureRandom.base36(24) + s2 = SecureRandom.base36(24) + + assert_not_equal s1, s2 + assert_equal 24, s1.length + assert_match(/^[a-z0-9]+$/, s1) + assert_match(/^[a-z0-9]+$/, s2) + end end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 2468fe3603..c5a000b67a 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -206,6 +206,12 @@ class StringInflectionsTest < ActiveSupport::TestCase end end + def test_parameterize_with_locale + word = "FΓΌnf autos" + I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ΓΌ" => "ue" } } }) + assert_equal("fuenf-autos", word.parameterize(locale: :de)) + end + def test_humanize UnderscoreToHuman.each do |underscore, human| assert_equal(human, underscore.humanize) @@ -285,6 +291,11 @@ class StringInflectionsTest < ActiveSupport::TestCase assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, omission: "[...]", separator: /\s/) end + def test_truncate_returns_frozen_string + assert_not "Hello World!".truncate(12).frozen? + assert_not "Hello World!!".truncate(12).frozen? + end + def test_truncate_bytes assert_equal "ππππ", "ππππ".truncate_bytes(16) assert_equal "ππππ", "ππππ".truncate_bytes(16, omission: nil) diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 7078f3506d..590b81b770 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -514,6 +514,8 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(1582, 10, 15, 15, 15, 10), Time.local(1582, 10, 14, 15, 15, 10).advance(days: 1) assert_equal Time.local(1582, 10, 5, 15, 15, 10), Time.local(1582, 10, 4, 15, 15, 10).advance(days: 1) assert_equal Time.local(1582, 10, 4, 15, 15, 10), Time.local(1582, 10, 5, 15, 15, 10).advance(days: -1) + assert_equal Time.local(999, 10, 4, 15, 15, 10), Time.local(1000, 10, 4, 15, 15, 10).advance(years: -1) + assert_equal Time.local(1000, 10, 4, 15, 15, 10), Time.local(999, 10, 4, 15, 15, 10).advance(years: 1) end def test_last_week diff --git a/activesupport/test/current_attributes_test.rb b/activesupport/test/current_attributes_test.rb index 1669f08f68..adbdc646bc 100644 --- a/activesupport/test/current_attributes_test.rb +++ b/activesupport/test/current_attributes_test.rb @@ -3,13 +3,18 @@ require "abstract_unit" class CurrentAttributesTest < ActiveSupport::TestCase - Person = Struct.new(:name, :time_zone) + Person = Struct.new(:id, :name, :time_zone) class Current < ActiveSupport::CurrentAttributes attribute :world, :account, :person, :request delegate :time_zone, to: :person - resets { Time.zone = "UTC" } + before_reset { Session.previous = person.try(:id) } + + resets do + Time.zone = "UTC" + Session.current = nil + end def account=(account) super @@ -19,6 +24,7 @@ class CurrentAttributesTest < ActiveSupport::TestCase def person=(person) super Time.zone = person.try(:time_zone) + Session.current = person.try(:id) end def request @@ -30,9 +36,14 @@ class CurrentAttributesTest < ActiveSupport::TestCase end end + class Session < ActiveSupport::CurrentAttributes + attribute :current, :previous + end + setup do @original_time_zone = Time.zone Current.reset + Session.reset end teardown do @@ -56,16 +67,28 @@ class CurrentAttributesTest < ActiveSupport::TestCase end test "set auxiliary class via overwritten method" do - Current.person = Person.new("David", "Central Time (US & Canada)") + Current.person = Person.new(42, "David", "Central Time (US & Canada)") assert_equal "Central Time (US & Canada)", Time.zone.name + assert_equal 42, Session.current end - test "resets auxiliary class via callback" do - Current.person = Person.new("David", "Central Time (US & Canada)") + test "resets auxiliary classes via callback" do + Current.person = Person.new(42, "David", "Central Time (US & Canada)") assert_equal "Central Time (US & Canada)", Time.zone.name Current.reset assert_equal "UTC", Time.zone.name + assert_nil Session.current + end + + test "set auxiliary class based on current attributes via before callback" do + Current.person = Person.new(42, "David", "Central Time (US & Canada)") + assert_nil Session.previous + assert_equal 42, Session.current + + Current.reset + assert_equal 42, Session.previous + assert_nil Session.current end test "set attribute only via scope" do @@ -92,13 +115,13 @@ class CurrentAttributesTest < ActiveSupport::TestCase end test "delegation" do - Current.person = Person.new("David", "Central Time (US & Canada)") + Current.person = Person.new(42, "David", "Central Time (US & Canada)") assert_equal "Central Time (US & Canada)", Current.time_zone assert_equal "Central Time (US & Canada)", Current.instance.time_zone end test "all methods forward to the instance" do - Current.person = Person.new("David", "Central Time (US & Canada)") + Current.person = Person.new(42, "David", "Central Time (US & Canada)") assert_equal "David, in Central Time (US & Canada)", Current.intro assert_equal "David, in Central Time (US & Canada)", Current.instance.intro end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index b1b3070891..d4e709137e 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -841,7 +841,7 @@ class DependenciesTest < ActiveSupport::TestCase remove_constants(:C) end - def test_new_contants_in_without_constants + def test_new_constants_in_without_constants assert_equal [], (ActiveSupport::Dependencies.new_constants_in(Object) { }) assert ActiveSupport::Dependencies.constant_watch_stack.all? { |k, v| v.empty? } end diff --git a/activesupport/test/deprecation/method_wrappers_test.rb b/activesupport/test/deprecation/method_wrappers_test.rb index b04bce7a11..0aa3233aab 100644 --- a/activesupport/test/deprecation/method_wrappers_test.rb +++ b/activesupport/test/deprecation/method_wrappers_test.rb @@ -21,6 +21,13 @@ class MethodWrappersTest < ActiveSupport::TestCase end end + def test_deprecate_methods_without_alternate_method + warning = /old_method is deprecated and will be removed from Rails \d.\d./ + ActiveSupport::Deprecation.deprecate_methods(@klass, :old_method) + + assert_deprecated(warning) { assert_equal "abc", @klass.new.old_method } + end + def test_deprecate_methods_warning_default warning = /old_method is deprecated and will be removed from Rails \d.\d \(use new_method instead\)/ ActiveSupport::Deprecation.deprecate_methods(@klass, old_method: :new_method) @@ -82,12 +89,4 @@ class MethodWrappersTest < ActiveSupport::TestCase warning = /old_method is deprecated and will be removed from Rails \d.\d \(use new_method instead\)/ assert_deprecated(warning) { assert_equal "abc", @klass.old_method } end - - def test_method_with_without_deprecation_is_exposed - ActiveSupport::Deprecation.deprecate_methods(@klass, old_method: :new_method) - - warning = /old_method is deprecated and will be removed from Rails \d.\d \(use new_method instead\)/ - assert_deprecated(warning) { assert_equal "abc", @klass.new.old_method_with_deprecation } - assert_equal "abc", @klass.new.old_method_without_deprecation - end end diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index 105153584d..f25c704586 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -31,6 +31,9 @@ class Deprecatee def f=(v); end deprecate :f= + deprecate :g + def g; end + module B C = 1 end @@ -425,6 +428,10 @@ class DeprecationTest < ActiveSupport::TestCase end end + def test_deprecate_work_before_define_method + assert_deprecated { @dtc.g } + end + private def deprecator_with_messages klass = Class.new(ActiveSupport::Deprecation) diff --git a/activesupport/test/descendants_tracker_test_cases.rb b/activesupport/test/descendants_tracker_test_cases.rb index 2c94c3c56c..f8752688d2 100644 --- a/activesupport/test/descendants_tracker_test_cases.rb +++ b/activesupport/test/descendants_tracker_test_cases.rb @@ -27,6 +27,15 @@ module DescendantsTrackerTestCases assert_equal_sets [], Child2.descendants end + def test_descendants_with_garbage_collected_classes + 1.times do + child_klass = Class.new(Parent) + assert_equal_sets [Child1, Grandchild1, Grandchild2, Child2, child_klass], Parent.descendants + end + GC.start + assert_equal_sets [Child1, Grandchild1, Grandchild2, Child2], Parent.descendants + end + def test_direct_descendants assert_equal_sets [Child1, Child2], Parent.direct_descendants assert_equal_sets [Grandchild1, Grandchild2], Child1.direct_descendants diff --git a/activesupport/test/evented_file_update_checker_test.rb b/activesupport/test/evented_file_update_checker_test.rb index a557608986..b2d5eb94c2 100644 --- a/activesupport/test/evented_file_update_checker_test.rb +++ b/activesupport/test/evented_file_update_checker_test.rb @@ -76,6 +76,34 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase Process.wait(pid) end + + test "updated should become true when nonexistent directory is added later" do + Dir.mktmpdir do |dir| + watched_dir = File.join(dir, "app") + unwatched_dir = File.join(dir, "node_modules") + not_exist_watched_dir = File.join(dir, "test") + + Dir.mkdir(watched_dir) + Dir.mkdir(unwatched_dir) + + checker = new_checker([], watched_dir => ".rb", not_exist_watched_dir => ".rb") { } + + FileUtils.touch(File.join(watched_dir, "a.rb")) + wait + assert_predicate checker, :updated? + assert checker.execute_if_updated + + Dir.mkdir(not_exist_watched_dir) + wait + assert_predicate checker, :updated? + assert checker.execute_if_updated + + FileUtils.touch(File.join(unwatched_dir, "a.rb")) + wait + assert_not_predicate checker, :updated? + assert_not checker.execute_if_updated + end + end end class EventedFileUpdateCheckerPathHelperTest < ActiveSupport::TestCase diff --git a/activesupport/test/file_update_checker_shared_tests.rb b/activesupport/test/file_update_checker_shared_tests.rb index 72683816b3..84d89fa0a7 100644 --- a/activesupport/test/file_update_checker_shared_tests.rb +++ b/activesupport/test/file_update_checker_shared_tests.rb @@ -186,6 +186,18 @@ module FileUpdateCheckerSharedTests assert_equal 1, i end + test "should execute the block if files change in a watched directory any extensions" do + i = 0 + + checker = new_checker([], tmpdir => []) { i += 1 } + + touch(tmpfile("foo.rb")) + wait + + assert checker.execute_if_updated + assert_equal 1, i + end + test "should execute the block if files change in a watched directory several extensions" do i = 0 diff --git a/activesupport/test/hash_with_indifferent_access_test.rb b/activesupport/test/hash_with_indifferent_access_test.rb index 90f7107b5c..af96231801 100644 --- a/activesupport/test/hash_with_indifferent_access_test.rb +++ b/activesupport/test/hash_with_indifferent_access_test.rb @@ -447,6 +447,14 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings end + def test_indifferent_assoc + indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@strings) + key, value = indifferent_strings.assoc(:a) + + assert_equal("a", key) + assert_equal(1, value) + end + def test_indifferent_compact hash_contain_nil_value = @strings.merge("z" => nil) hash = ActiveSupport::HashWithIndifferentAccess.new(hash_contain_nil_value) @@ -478,7 +486,7 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase assert_equal @strings, roundtrip assert_equal "1234", roundtrip.default - # Ensure nested hashes are not HashWithIndiffereneAccess + # Ensure nested hashes are not HashWithIndifferentAccess new_to_hash = @nested_mixed.with_indifferent_access.to_hash assert_not new_to_hash.instance_of?(HashWithIndifferentAccess) assert_not new_to_hash["a"].instance_of?(HashWithIndifferentAccess) diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index 5e50acf5db..ddf765a220 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -224,12 +224,6 @@ 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)) @@ -310,6 +304,12 @@ class InflectorTest < ActiveSupport::TestCase end end + def test_parameterize_with_locale + word = "FΓΌnf autos" + I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ΓΌ" => "ue" } } }) + assert_equal("fuenf-autos", ActiveSupport::Inflector.parameterize(word, locale: :de)) + end + def test_classify ClassNameToTableName.each do |class_name, table_name| assert_equal(class_name, ActiveSupport::Inflector.classify(table_name)) diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 8062873386..7589ffd0ea 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -21,20 +21,18 @@ class TestJSONEncoding < ActiveSupport::TestCase JSONTest::EncodingTestCases.constants.each do |class_tests| define_method("test_#{class_tests[0..-6].underscore}") do - begin - prev = ActiveSupport.use_standard_json_time_format - - standard_class_tests = /Standard/.match?(class_tests) - - ActiveSupport.escape_html_entities_in_json = !standard_class_tests - ActiveSupport.use_standard_json_time_format = standard_class_tests - JSONTest::EncodingTestCases.const_get(class_tests).each do |pair| - assert_equal pair.last, sorted_json(ActiveSupport::JSON.encode(pair.first)) - end - ensure - ActiveSupport.escape_html_entities_in_json = false - ActiveSupport.use_standard_json_time_format = prev + prev = ActiveSupport.use_standard_json_time_format + + standard_class_tests = /Standard/.match?(class_tests) + + ActiveSupport.escape_html_entities_in_json = !standard_class_tests + ActiveSupport.use_standard_json_time_format = standard_class_tests + JSONTest::EncodingTestCases.const_get(class_tests).each do |pair| + assert_equal pair.last, sorted_json(ActiveSupport::JSON.encode(pair.first)) end + ensure + ActiveSupport.escape_html_entities_in_json = false + ActiveSupport.use_standard_json_time_format = prev end end diff --git a/activesupport/test/notifications/evented_notification_test.rb b/activesupport/test/notifications/evented_notification_test.rb index 4beb8194b9..ab2a9b8659 100644 --- a/activesupport/test/notifications/evented_notification_test.rb +++ b/activesupport/test/notifications/evented_notification_test.rb @@ -84,6 +84,39 @@ module ActiveSupport [:finish, "hi", 1, {}] ], listener.events end + + def test_listen_to_regexp + notifier = Fanout.new + listener = Listener.new + notifier.subscribe(/[a-z]*.world/, listener) + notifier.start("hi.world", 1, {}) + notifier.finish("hi.world", 2, {}) + notifier.start("hello.world", 1, {}) + notifier.finish("hello.world", 2, {}) + + assert_equal [ + [:start, "hi.world", 1, {}], + [:finish, "hi.world", 2, {}], + [:start, "hello.world", 1, {}], + [:finish, "hello.world", 2, {}] + ], listener.events + end + + def test_listen_to_regexp_with_exclusions + notifier = Fanout.new + listener = Listener.new + notifier.subscribe(/[a-z]*.world/, listener) + notifier.unsubscribe("hi.world") + notifier.start("hi.world", 1, {}) + notifier.finish("hi.world", 2, {}) + notifier.start("hello.world", 1, {}) + notifier.finish("hello.world", 2, {}) + + assert_equal [ + [:start, "hello.world", 1, {}], + [:finish, "hello.world", 2, {}] + ], listener.events + end end end end diff --git a/activesupport/test/notifications/instrumenter_test.rb b/activesupport/test/notifications/instrumenter_test.rb index d5c9e82e9f..9729ad5c89 100644 --- a/activesupport/test/notifications/instrumenter_test.rb +++ b/activesupport/test/notifications/instrumenter_test.rb @@ -44,6 +44,12 @@ module ActiveSupport assert_equal Hash[result: 2], payload end + def test_instrument_works_without_a_block + instrumenter.instrument("no.block", payload) + assert_equal 1, notifier.finishes.size + assert_equal "no.block", notifier.finishes.first.first + end + def test_start instrumenter.start("foo", payload) assert_equal [["foo", instrumenter.id, payload]], notifier.starts diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 54fd4345fb..d3c660a014 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -26,7 +26,7 @@ module Notifications end end - class SubscribeEventObjects < TestCase + class SubscribeEventObjectsTest < TestCase def test_subscribe_events events = [] @notifier.subscribe do |event| @@ -81,7 +81,7 @@ module Notifications assert_equal expected, events end - def test_subsribing_to_instrumentation_while_inside_it + def test_subscribing_to_instrumentation_while_inside_it # the repro requires that there are no evented subscribers for the "foo" event, # so we have to duplicate some of the setup code old_notifier = ActiveSupport::Notifications.notifier @@ -128,6 +128,25 @@ module Notifications assert_equal [["named.subscription", :foo], ["named.subscription", :foo]], @events end + def test_unsubscribing_by_name_leaves_regexp_matched_subscriptions + @matched_events = [] + @notifier.subscribe(/subscription/) { |*args| @matched_events << event(*args) } + @notifier.publish("named.subscription", :before) + @notifier.wait + [@events, @named_events, @matched_events].each do |collector| + assert_includes(collector, ["named.subscription", :before]) + end + @notifier.unsubscribe("named.subscription") + @notifier.publish("named.subscription", :after) + @notifier.publish("other.subscription", :after) + @notifier.wait + assert_includes(@events, ["named.subscription", :after]) + assert_includes(@events, ["other.subscription", :after]) + assert_includes(@matched_events, ["other.subscription", :after]) + assert_not_includes(@matched_events, ["named.subscription", :after]) + assert_not_includes(@named_events, ["named.subscription", :after]) + end + private def event(*args) args @@ -291,15 +310,23 @@ module Notifications assert_in_delta 10.0, event.duration, 0.00001 end + def test_event_cpu_time_does_not_raise_error_when_start_or_finished_not_called + time = Time.now + event = event(:foo, time, time + 0.01, random_id, {}) + + assert_equal 0, event.cpu_time + end + + def test_events_consumes_information_given_as_payload - event = event(:foo, Time.now, Time.now + 1, random_id, payload: :bar) + event = event(:foo, Concurrent.monotonic_time, Concurrent.monotonic_time + 1, random_id, payload: :bar) assert_equal Hash[payload: :bar], event.payload end def test_event_is_parent_based_on_children - time = Time.utc(2009, 01, 01, 0, 0, 1) + time = Concurrent.monotonic_time - parent = event(:foo, Time.utc(2009), Time.utc(2009) + 100, random_id, {}) + parent = event(:foo, Concurrent.monotonic_time, Concurrent.monotonic_time + 100, random_id, {}) child = event(:foo, time, time + 10, random_id, {}) not_child = event(:foo, time, time + 100, random_id, {}) diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 49a3951623..f475e05c9a 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -112,12 +112,52 @@ class SafeBufferTest < ActiveSupport::TestCase end end + test "can assign value into zero-index" do + buffer = ActiveSupport::SafeBuffer.new("012345") + + buffer[0] = "<" + + assert_equal "<12345", buffer + end + + test "can assign value into non zero-index" do + buffer = ActiveSupport::SafeBuffer.new("012345") + + buffer[2] = "<" + + assert_equal "01<345", buffer + end + + test "can assign value into slice" do + buffer = ActiveSupport::SafeBuffer.new("012345") + + buffer[0, 3] = "<" + + assert_equal "<345", buffer + end + + test "can assign value into offset slice" do + buffer = ActiveSupport::SafeBuffer.new("012345") + + buffer[1, 3] = "<" + + assert_equal "0<45", buffer + end + test "Should escape dirty buffers on add" do clean = "hello".html_safe @buffer.gsub!("", "<>") assert_equal "hello<>", clean + @buffer end + test "Should preserve html_safe? status on multiplication" do + multiplied_safe_buffer = "<br />".html_safe * 2 + assert_predicate multiplied_safe_buffer, :html_safe? + + multiplied_unsafe_buffer = @buffer.gsub("", "<>") * 2 + assert_not_predicate multiplied_unsafe_buffer, :html_safe? + end + test "Should concat as a normal string when safe" do clean = "hello".html_safe @buffer.gsub!("", "<>") @@ -151,7 +191,7 @@ class SafeBufferTest < ActiveSupport::TestCase assert_equal "", ActiveSupport::SafeBuffer.new("foo").clone_empty end - test "clone_empty keeps the original dirtyness" do + test "clone_empty keeps the original dirtiness" do assert_predicate @buffer.clone_empty, :html_safe? assert_not_predicate @buffer.gsub!("", "").clone_empty, :html_safe? end @@ -216,4 +256,22 @@ class SafeBufferTest < ActiveSupport::TestCase x = "Hello".html_safe assert_nil x[/a/, 1] end + + test "Should set back references" do + a = "foo123".html_safe + a2 = a.sub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a2 + assert_not_predicate a2, :html_safe? + a.sub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a + assert_not_predicate a, :html_safe? + + b = "foo123 bar456".html_safe + b2 = b.gsub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b2 + assert_not_predicate b2, :html_safe? + b.gsub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b + assert_not_predicate b, :html_safe? + end end diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb index 34479020e1..a40c813fe3 100644 --- a/activesupport/test/share_lock_test.rb +++ b/activesupport/test/share_lock_test.rb @@ -38,7 +38,7 @@ class ShareLockTest < ActiveSupport::TestCase end end - def test_multiple_exlusives_are_able_to_progress + def test_multiple_exclusives_are_able_to_progress with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| exclusive_threads = (1..2).map do Thread.new do @@ -115,68 +115,66 @@ class ShareLockTest < ActiveSupport::TestCase def test_exclusive_conflicting_purpose [true, false].each do |use_upgrading| with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch| - begin - together = Concurrent::CyclicBarrier.new(2) - conflicting_exclusive_threads = [ - Thread.new do - @lock.send(use_upgrading ? :sharing : :tap) do - together.wait - @lock.exclusive(purpose: :red, compatible: [:green, :purple]) { } - end - end, - Thread.new do - @lock.send(use_upgrading ? :sharing : :tap) do - together.wait - @lock.exclusive(purpose: :blue, compatible: [:green]) { } - end + together = Concurrent::CyclicBarrier.new(2) + conflicting_exclusive_threads = [ + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + together.wait + @lock.exclusive(purpose: :red, compatible: [:green, :purple]) { } + end + end, + Thread.new do + @lock.send(use_upgrading ? :sharing : :tap) do + together.wait + @lock.exclusive(purpose: :blue, compatible: [:green]) { } end - ] - - assert_threads_stuck conflicting_exclusive_threads # wait for threads to get into their respective `exclusive {}` blocks - - # This thread will be stuck as long as any other thread is in - # a sharing block. While it's blocked, it holds no lock, so it - # doesn't interfere with any other attempts. - no_purpose_thread = Thread.new do - @lock.exclusive { } end - assert_threads_stuck no_purpose_thread + ] - # This thread is compatible with both of the "primary" - # attempts above. It's initially stuck on the outer share - # lock, but as soon as that's released, it can run -- - # regardless of whether those threads hold share locks. - compatible_thread = Thread.new do - @lock.exclusive(purpose: :green, compatible: []) { } - end - assert_threads_stuck compatible_thread + assert_threads_stuck conflicting_exclusive_threads # wait for threads to get into their respective `exclusive {}` blocks - assert_threads_stuck conflicting_exclusive_threads + # This thread will be stuck as long as any other thread is in + # a sharing block. While it's blocked, it holds no lock, so it + # doesn't interfere with any other attempts. + no_purpose_thread = Thread.new do + @lock.exclusive { } + end + assert_threads_stuck no_purpose_thread + + # This thread is compatible with both of the "primary" + # attempts above. It's initially stuck on the outer share + # lock, but as soon as that's released, it can run -- + # regardless of whether those threads hold share locks. + compatible_thread = Thread.new do + @lock.exclusive(purpose: :green, compatible: []) { } + end + assert_threads_stuck compatible_thread - sharing_thread_release_latch.count_down + assert_threads_stuck conflicting_exclusive_threads - assert_threads_not_stuck compatible_thread # compatible thread is now able to squeak through + sharing_thread_release_latch.count_down - if use_upgrading - # The "primary" threads both each hold a share lock, and are - # mutually incompatible; they're still stuck. - assert_threads_stuck conflicting_exclusive_threads + assert_threads_not_stuck compatible_thread # compatible thread is now able to squeak through - # The thread without a specified purpose is also stuck; it's - # not compatible with anything. - assert_threads_stuck no_purpose_thread - else - # As the primaries didn't hold a share lock, as soon as the - # outer one was released, all the exclusive locks are free - # to be acquired in turn. + if use_upgrading + # The "primary" threads both each hold a share lock, and are + # mutually incompatible; they're still stuck. + assert_threads_stuck conflicting_exclusive_threads - assert_threads_not_stuck conflicting_exclusive_threads - assert_threads_not_stuck no_purpose_thread - end - ensure - conflicting_exclusive_threads.each(&:kill) - no_purpose_thread.kill + # The thread without a specified purpose is also stuck; it's + # not compatible with anything. + assert_threads_stuck no_purpose_thread + else + # As the primaries didn't hold a share lock, as soon as the + # outer one was released, all the exclusive locks are free + # to be acquired in turn. + + assert_threads_not_stuck conflicting_exclusive_threads + assert_threads_not_stuck no_purpose_thread end + ensure + conflicting_exclusive_threads.each(&:kill) + no_purpose_thread.kill end end end diff --git a/activesupport/test/subscriber_test.rb b/activesupport/test/subscriber_test.rb index 6b012e43af..bc8d8f1c13 100644 --- a/activesupport/test/subscriber_test.rb +++ b/activesupport/test/subscriber_test.rb @@ -23,6 +23,21 @@ class TestSubscriber < ActiveSupport::Subscriber end end +class TestSubscriber2 < ActiveSupport::Subscriber + attach_to :doodle + detach_from :doodle + + cattr_reader :events + + def self.clear + @@events = [] + end + + def open_party(event) + events << event + end +end + # Monkey patch subscriber to test that only one subscriber per method is added. class TestSubscriber remove_method :open_party @@ -34,6 +49,7 @@ end class SubscriberTest < ActiveSupport::TestCase def setup TestSubscriber.clear + TestSubscriber2.clear end def test_attaches_subscribers @@ -53,4 +69,11 @@ class SubscriberTest < ActiveSupport::TestCase assert_equal [], TestSubscriber.events end + + def test_detaches_subscribers + ActiveSupport::Notifications.instrument("open_party.doodle") + + assert_equal [], TestSubscriber2.events + assert_equal 1, TestSubscriber.events.size + end end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 8698c66e6d..56cd2665e0 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -104,7 +104,7 @@ class AssertionsTest < ActiveSupport::TestCase def test_expression_is_evaluated_in_the_appropriate_scope silence_warnings do local_scope = "foo" - local_scope = local_scope # to suppress unused variable warning + _ = local_scope # to suppress unused variable warning assert_difference("local_scope; @object.num") { @object.increment } end end diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index 8c47f2cdc7..a1f84bf69e 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -3,24 +3,25 @@ require "abstract_unit" require "active_support/core_ext/date_time" require "active_support/core_ext/numeric/time" +require "time_zone_test_helpers" class TimeTravelTest < ActiveSupport::TestCase + include TimeZoneTestHelpers + class TimeSubclass < ::Time; end class DateSubclass < ::Date; end class DateTimeSubclass < ::DateTime; end def test_time_helper_travel Time.stub(:now, Time.now) do - begin - expected_time = Time.now + 1.day - travel 1.day + expected_time = Time.now + 1.day + travel 1.day - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) - assert_equal expected_time.to_date, Date.today - assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) - ensure - travel_back - end + assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_date, Date.today + assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + ensure + travel_back end end @@ -42,16 +43,14 @@ class TimeTravelTest < ActiveSupport::TestCase def test_time_helper_travel_to Time.stub(:now, Time.now) do - begin - expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time + expected_time = Time.new(2004, 11, 24, 01, 04, 44) + travel_to expected_time - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now - ensure - travel_back - end + assert_equal expected_time, Time.now + assert_equal Date.new(2004, 11, 24), Date.today + assert_equal expected_time.to_datetime, DateTime.now + ensure + travel_back end end @@ -71,23 +70,35 @@ class TimeTravelTest < ActiveSupport::TestCase end end + def test_time_helper_travel_to_with_time_zone + with_env_tz "US/Eastern" do + with_tz_default ActiveSupport::TimeZone["UTC"] do + Time.stub(:now, Time.now) do + expected_time = 5.minutes.ago + + travel_to 5.minutes.ago do + assert_equal expected_time.to_s(:db), Time.zone.now.to_s(:db) + end + end + end + end + end + def test_time_helper_travel_back Time.stub(:now, Time.now) do - begin - expected_time = Time.new(2004, 11, 24, 01, 04, 44) + expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now - travel_back + travel_to expected_time + assert_equal expected_time, Time.now + assert_equal Date.new(2004, 11, 24), Date.today + assert_equal expected_time.to_datetime, DateTime.now + travel_back - assert_not_equal expected_time, Time.now - assert_not_equal Date.new(2004, 11, 24), Date.today - assert_not_equal expected_time.to_datetime, DateTime.now - ensure - travel_back - end + assert_not_equal expected_time, Time.now + assert_not_equal Date.new(2004, 11, 24), Date.today + assert_not_equal expected_time.to_datetime, DateTime.now + ensure + travel_back end end @@ -122,24 +133,22 @@ class TimeTravelTest < ActiveSupport::TestCase def test_time_helper_travel_to_with_subsequent_calls Time.stub(:now, Time.now) do - begin - initial_expected_time = Time.new(2004, 11, 24, 01, 04, 44) - subsequent_expected_time = Time.new(2004, 10, 24, 01, 04, 44) - assert_nothing_raised do - travel_to initial_expected_time - travel_to subsequent_expected_time + initial_expected_time = Time.new(2004, 11, 24, 01, 04, 44) + subsequent_expected_time = Time.new(2004, 10, 24, 01, 04, 44) + assert_nothing_raised do + travel_to initial_expected_time + travel_to subsequent_expected_time - assert_equal subsequent_expected_time, Time.now + assert_equal subsequent_expected_time, Time.now - travel_back - end - ensure travel_back end + ensure + travel_back end end - def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding + def test_travel_to_will_reset_the_usec_to_avoid_mysql_rounding Time.stub(:now, Time.now) do travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do assert_equal 50, Time.now.sec diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 6d45a6726d..f948c363df 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -32,7 +32,7 @@ class TimeZoneTest < ActiveSupport::TestCase end end - def test_period_for_local_with_ambigiuous_time + def test_period_for_local_with_ambiguous_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)) diff --git a/activesupport/test/transliterate_test.rb b/activesupport/test/transliterate_test.rb index 7d19447598..9e29a93ea0 100644 --- a/activesupport/test/transliterate_test.rb +++ b/activesupport/test/transliterate_test.rb @@ -30,6 +30,12 @@ class TransliterateTest < ActiveSupport::TestCase I18n.locale = default_locale end + def test_transliterate_respects_the_locale_argument + char = [117, 776].pack("U*") # "ΓΌ" as ASCII "u" plus COMBINING DIAERESIS + I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ΓΌ" => "ue" } } }) + assert_equal "ue", ActiveSupport::Inflector.transliterate(char, locale: :de) + end + def test_transliterate_should_allow_a_custom_replacement_char assert_equal "a*b", ActiveSupport::Inflector.transliterate("aη΄’b", "*") end |