Split up the cache test suite so it's easier to understand and extend (#29404)
Split up the caching tests as prep for adding a new cache store. Slices the mega test/caching_test.rb into behavior modules, concrete store tests, and cross-cutting store tests. Considering moving cache store behavior modules into lib/ so they may be used for acceptance testing by third parties.
This commit is contained in:
parent
57cfd45b16
commit
ddea316425
|
@ -0,0 +1,7 @@
|
|||
require_relative "behaviors/autoloading_cache_behavior"
|
||||
require_relative "behaviors/cache_delete_matched_behavior"
|
||||
require_relative "behaviors/cache_increment_decrement_behavior"
|
||||
require_relative "behaviors/cache_store_behavior"
|
||||
require_relative "behaviors/cache_store_version_behavior"
|
||||
require_relative "behaviors/encoded_key_cache_behavior"
|
||||
require_relative "behaviors/local_cache_behavior"
|
|
@ -0,0 +1,41 @@
|
|||
require "dependencies_test_helpers"
|
||||
|
||||
module AutoloadingCacheBehavior
|
||||
include DependenciesTestHelpers
|
||||
|
||||
def test_simple_autoloading
|
||||
with_autoloading_fixtures do
|
||||
@cache.write("foo", EM.new)
|
||||
end
|
||||
|
||||
remove_constants(:EM)
|
||||
ActiveSupport::Dependencies.clear
|
||||
|
||||
with_autoloading_fixtures do
|
||||
assert_kind_of EM, @cache.read("foo")
|
||||
end
|
||||
|
||||
remove_constants(:EM)
|
||||
ActiveSupport::Dependencies.clear
|
||||
end
|
||||
|
||||
def test_two_classes_autoloading
|
||||
with_autoloading_fixtures do
|
||||
@cache.write("foo", [EM.new, ClassFolder.new])
|
||||
end
|
||||
|
||||
remove_constants(:EM, :ClassFolder)
|
||||
ActiveSupport::Dependencies.clear
|
||||
|
||||
with_autoloading_fixtures do
|
||||
loaded = @cache.read("foo")
|
||||
assert_kind_of Array, loaded
|
||||
assert_equal 2, loaded.size
|
||||
assert_kind_of EM, loaded[0]
|
||||
assert_kind_of ClassFolder, loaded[1]
|
||||
end
|
||||
|
||||
remove_constants(:EM, :ClassFolder)
|
||||
ActiveSupport::Dependencies.clear
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module CacheDeleteMatchedBehavior
|
||||
def test_delete_matched
|
||||
@cache.write("foo", "bar")
|
||||
@cache.write("fu", "baz")
|
||||
@cache.write("foo/bar", "baz")
|
||||
@cache.write("fu/baz", "bar")
|
||||
@cache.delete_matched(/oo/)
|
||||
assert !@cache.exist?("foo")
|
||||
assert @cache.exist?("fu")
|
||||
assert !@cache.exist?("foo/bar")
|
||||
assert @cache.exist?("fu/baz")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module CacheIncrementDecrementBehavior
|
||||
def test_increment
|
||||
@cache.write("foo", 1, raw: true)
|
||||
assert_equal 1, @cache.read("foo").to_i
|
||||
assert_equal 2, @cache.increment("foo")
|
||||
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")
|
||||
end
|
||||
|
||||
def test_decrement
|
||||
@cache.write("foo", 3, raw: true)
|
||||
assert_equal 3, @cache.read("foo").to_i
|
||||
assert_equal 2, @cache.decrement("foo")
|
||||
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")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,329 @@
|
|||
# Tests the base functionality that should be identical across all cache stores.
|
||||
module CacheStoreBehavior
|
||||
def test_should_read_and_write_strings
|
||||
assert @cache.write("foo", "bar")
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_should_overwrite
|
||||
@cache.write("foo", "bar")
|
||||
@cache.write("foo", "baz")
|
||||
assert_equal "baz", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_fetch_without_cache_miss
|
||||
@cache.write("foo", "bar")
|
||||
assert_not_called(@cache, :write) do
|
||||
assert_equal "bar", @cache.fetch("foo") { "baz" }
|
||||
end
|
||||
end
|
||||
|
||||
def test_fetch_with_cache_miss
|
||||
assert_called_with(@cache, :write, ["foo", "baz", @cache.options]) do
|
||||
assert_equal "baz", @cache.fetch("foo") { "baz" }
|
||||
end
|
||||
end
|
||||
|
||||
def test_fetch_with_cache_miss_passes_key_to_block
|
||||
cache_miss = false
|
||||
assert_equal 3, @cache.fetch("foo") { |key| cache_miss = true; key.length }
|
||||
assert cache_miss
|
||||
|
||||
cache_miss = false
|
||||
assert_equal 3, @cache.fetch("foo") { |key| cache_miss = true; key.length }
|
||||
assert !cache_miss
|
||||
end
|
||||
|
||||
def test_fetch_with_forced_cache_miss
|
||||
@cache.write("foo", "bar")
|
||||
assert_not_called(@cache, :read) do
|
||||
assert_called_with(@cache, :write, ["foo", "bar", @cache.options.merge(force: true)]) do
|
||||
@cache.fetch("foo", force: true) { "bar" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_fetch_with_cached_nil
|
||||
@cache.write("foo", nil)
|
||||
assert_not_called(@cache, :write) do
|
||||
assert_nil @cache.fetch("foo") { "baz" }
|
||||
end
|
||||
end
|
||||
|
||||
def test_fetch_with_forced_cache_miss_with_block
|
||||
@cache.write("foo", "bar")
|
||||
assert_equal "foo_bar", @cache.fetch("foo", force: true) { "foo_bar" }
|
||||
end
|
||||
|
||||
def test_fetch_with_forced_cache_miss_without_block
|
||||
@cache.write("foo", "bar")
|
||||
assert_raises(ArgumentError) do
|
||||
@cache.fetch("foo", force: true)
|
||||
end
|
||||
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_should_read_and_write_hash
|
||||
assert @cache.write("foo", a: "b")
|
||||
assert_equal({ a: "b" }, @cache.read("foo"))
|
||||
end
|
||||
|
||||
def test_should_read_and_write_integer
|
||||
assert @cache.write("foo", 1)
|
||||
assert_equal 1, @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_should_read_and_write_nil
|
||||
assert @cache.write("foo", nil)
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_should_read_and_write_false
|
||||
assert @cache.write("foo", false)
|
||||
assert_equal false, @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_read_multi
|
||||
@cache.write("foo", "bar")
|
||||
@cache.write("fu", "baz")
|
||||
@cache.write("fud", "biz")
|
||||
assert_equal({ "foo" => "bar", "fu" => "baz" }, @cache.read_multi("foo", "fu"))
|
||||
end
|
||||
|
||||
def test_read_multi_with_expires
|
||||
time = Time.now
|
||||
@cache.write("foo", "bar", expires_in: 10)
|
||||
@cache.write("fu", "baz")
|
||||
@cache.write("fud", "biz")
|
||||
Time.stub(:now, time + 11) do
|
||||
assert_equal({ "fu" => "baz" }, @cache.read_multi("foo", "fu"))
|
||||
end
|
||||
end
|
||||
|
||||
def test_fetch_multi
|
||||
@cache.write("foo", "bar")
|
||||
@cache.write("fud", "biz")
|
||||
|
||||
values = @cache.fetch_multi("foo", "fu", "fud") { |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!")
|
||||
bar = cache_struct.new("bar")
|
||||
|
||||
@cache.write("bar", "BAM!")
|
||||
|
||||
values = @cache.fetch_multi(foo, bar) { |object| object.title }
|
||||
|
||||
assert_equal({ foo => "FOO!", bar => "BAM!" }, values)
|
||||
end
|
||||
|
||||
def test_fetch_multi_without_block
|
||||
assert_raises(ArgumentError) do
|
||||
@cache.fetch_multi("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_read_and_write_compressed_small_data
|
||||
@cache.write("foo", "bar", compress: true)
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_read_and_write_compressed_large_data
|
||||
@cache.write("foo", "bar", compress: true, compress_threshold: 2)
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_read_and_write_compressed_nil
|
||||
@cache.write("foo", nil, compress: true)
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_cache_key
|
||||
obj = Object.new
|
||||
def obj.cache_key
|
||||
:foo
|
||||
end
|
||||
@cache.write(obj, "bar")
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_param_as_cache_key
|
||||
obj = Object.new
|
||||
def obj.to_param
|
||||
"foo"
|
||||
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")
|
||||
end
|
||||
|
||||
def test_hash_as_cache_key
|
||||
@cache.write({ foo: 1, fu: 2 }, "bar")
|
||||
assert_equal "bar", @cache.read("foo=1/fu=2")
|
||||
end
|
||||
|
||||
def test_keys_are_case_sensitive
|
||||
@cache.write("foo", "bar")
|
||||
assert_nil @cache.read("FOO")
|
||||
end
|
||||
|
||||
def test_exist
|
||||
@cache.write("foo", "bar")
|
||||
assert_equal true, @cache.exist?("foo")
|
||||
assert_equal false, @cache.exist?("bar")
|
||||
end
|
||||
|
||||
def test_nil_exist
|
||||
@cache.write("foo", nil)
|
||||
assert @cache.exist?("foo")
|
||||
end
|
||||
|
||||
def test_delete
|
||||
@cache.write("foo", "bar")
|
||||
assert @cache.exist?("foo")
|
||||
assert @cache.delete("foo")
|
||||
assert !@cache.exist?("foo")
|
||||
end
|
||||
|
||||
def test_original_store_objects_should_not_be_immutable
|
||||
bar = "bar"
|
||||
@cache.write("foo", bar)
|
||||
assert_nothing_raised { bar.gsub!(/.*/, "baz") }
|
||||
end
|
||||
|
||||
def test_expires_in
|
||||
time = Time.local(2008, 4, 24)
|
||||
|
||||
Time.stub(:now, time) do
|
||||
@cache.write("foo", "bar")
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
Time.stub(:now, time + 30) do
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
Time.stub(:now, time + 61) do
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_race_condition_protection_skipped_if_not_defined
|
||||
@cache.write("foo", "bar")
|
||||
time = @cache.send(:read_entry, @cache.send(:normalize_key, "foo", {}), {}).expires_at
|
||||
|
||||
Time.stub(:now, Time.at(time)) do
|
||||
result = @cache.fetch("foo") do
|
||||
assert_nil @cache.read("foo")
|
||||
"baz"
|
||||
end
|
||||
assert_equal "baz", result
|
||||
end
|
||||
end
|
||||
|
||||
def test_race_condition_protection_is_limited
|
||||
time = Time.now
|
||||
@cache.write("foo", "bar", expires_in: 60)
|
||||
Time.stub(:now, time + 71) do
|
||||
result = @cache.fetch("foo", race_condition_ttl: 10) do
|
||||
assert_nil @cache.read("foo")
|
||||
"baz"
|
||||
end
|
||||
assert_equal "baz", result
|
||||
end
|
||||
end
|
||||
|
||||
def test_race_condition_protection_is_safe
|
||||
time = Time.now
|
||||
@cache.write("foo", "bar", expires_in: 60)
|
||||
Time.stub(:now, time + 61) do
|
||||
begin
|
||||
@cache.fetch("foo", race_condition_ttl: 10) do
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
raise ArgumentError.new
|
||||
end
|
||||
rescue ArgumentError
|
||||
end
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
Time.stub(:now, time + 91) do
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_race_condition_protection
|
||||
time = Time.now
|
||||
@cache.write("foo", "bar", expires_in: 60)
|
||||
Time.stub(:now, time + 61) do
|
||||
result = @cache.fetch("foo", race_condition_ttl: 10) do
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
"baz"
|
||||
end
|
||||
assert_equal "baz", result
|
||||
end
|
||||
end
|
||||
|
||||
def test_crazy_key_characters
|
||||
crazy_key = "#/:*(<+=> )&$%@?;'\"\'`~-"
|
||||
assert @cache.write(crazy_key, "1", raw: true)
|
||||
assert_equal "1", @cache.read(crazy_key)
|
||||
assert_equal "1", @cache.fetch(crazy_key)
|
||||
assert @cache.delete(crazy_key)
|
||||
assert_equal "2", @cache.fetch(crazy_key, raw: true) { "2" }
|
||||
assert_equal 3, @cache.increment(crazy_key)
|
||||
assert_equal 2, @cache.decrement(crazy_key)
|
||||
end
|
||||
|
||||
def test_really_long_keys
|
||||
key = ""
|
||||
900.times { key << "x" }
|
||||
assert @cache.write(key, "bar")
|
||||
assert_equal "bar", @cache.read(key)
|
||||
assert_equal "bar", @cache.fetch(key)
|
||||
assert_nil @cache.read("#{key}x")
|
||||
assert_equal({ key => "bar" }, @cache.read_multi(key))
|
||||
assert @cache.delete(key)
|
||||
end
|
||||
|
||||
def test_cache_hit_instrumentation
|
||||
key = "test_key"
|
||||
@events = []
|
||||
ActiveSupport::Notifications.subscribe "cache_read.active_support" do |*args|
|
||||
@events << ActiveSupport::Notifications::Event.new(*args)
|
||||
end
|
||||
assert @cache.write(key, "1", raw: true)
|
||||
assert @cache.fetch(key) {}
|
||||
assert_equal 1, @events.length
|
||||
assert_equal "cache_read.active_support", @events[0].name
|
||||
assert_equal :fetch, @events[0].payload[:super_operation]
|
||||
assert @events[0].payload[:hit]
|
||||
ensure
|
||||
ActiveSupport::Notifications.unsubscribe "cache_read.active_support"
|
||||
end
|
||||
|
||||
def test_cache_miss_instrumentation
|
||||
@events = []
|
||||
ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args|
|
||||
@events << ActiveSupport::Notifications::Event.new(*args)
|
||||
end
|
||||
assert_not @cache.fetch("bad_key") {}
|
||||
assert_equal 3, @events.length
|
||||
assert_equal "cache_read.active_support", @events[0].name
|
||||
assert_equal "cache_generate.active_support", @events[1].name
|
||||
assert_equal "cache_write.active_support", @events[2].name
|
||||
assert_equal :fetch, @events[0].payload[:super_operation]
|
||||
assert_not @events[0].payload[:hit]
|
||||
ensure
|
||||
ActiveSupport::Notifications.unsubscribe "cache_read.active_support"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,86 @@
|
|||
module CacheStoreVersionBehavior
|
||||
ModelWithKeyAndVersion = Struct.new(:cache_key, :cache_version)
|
||||
|
||||
def test_fetch_with_right_version_should_hit
|
||||
@cache.fetch("foo", version: 1) { "bar" }
|
||||
assert_equal "bar", @cache.read("foo", version: 1)
|
||||
end
|
||||
|
||||
def test_fetch_with_wrong_version_should_miss
|
||||
@cache.fetch("foo", version: 1) { "bar" }
|
||||
assert_nil @cache.read("foo", version: 2)
|
||||
end
|
||||
|
||||
def test_read_with_right_version_should_hit
|
||||
@cache.write("foo", "bar", version: 1)
|
||||
assert_equal "bar", @cache.read("foo", version: 1)
|
||||
end
|
||||
|
||||
def test_read_with_wrong_version_should_miss
|
||||
@cache.write("foo", "bar", version: 1)
|
||||
assert_nil @cache.read("foo", version: 2)
|
||||
end
|
||||
|
||||
def test_exist_with_right_version_should_be_true
|
||||
@cache.write("foo", "bar", version: 1)
|
||||
assert @cache.exist?("foo", version: 1)
|
||||
end
|
||||
|
||||
def test_exist_with_wrong_version_should_be_false
|
||||
@cache.write("foo", "bar", version: 1)
|
||||
assert !@cache.exist?("foo", version: 2)
|
||||
end
|
||||
|
||||
def test_reading_and_writing_with_model_supporting_cache_version
|
||||
m1v1 = ModelWithKeyAndVersion.new("model/1", 1)
|
||||
m1v2 = ModelWithKeyAndVersion.new("model/1", 2)
|
||||
|
||||
@cache.write(m1v1, "bar")
|
||||
assert_equal "bar", @cache.read(m1v1)
|
||||
assert_nil @cache.read(m1v2)
|
||||
end
|
||||
|
||||
def test_reading_and_writing_with_model_supporting_cache_version_using_nested_key
|
||||
m1v1 = ModelWithKeyAndVersion.new("model/1", 1)
|
||||
m1v2 = ModelWithKeyAndVersion.new("model/1", 2)
|
||||
|
||||
@cache.write([ "something", m1v1 ], "bar")
|
||||
assert_equal "bar", @cache.read([ "something", m1v1 ])
|
||||
assert_nil @cache.read([ "something", m1v2 ])
|
||||
end
|
||||
|
||||
def test_fetching_with_model_supporting_cache_version
|
||||
m1v1 = ModelWithKeyAndVersion.new("model/1", 1)
|
||||
m1v2 = ModelWithKeyAndVersion.new("model/1", 2)
|
||||
|
||||
@cache.fetch(m1v1) { "bar" }
|
||||
assert_equal "bar", @cache.fetch(m1v1) { "bu" }
|
||||
assert_equal "bu", @cache.fetch(m1v2) { "bu" }
|
||||
end
|
||||
|
||||
def test_exist_with_model_supporting_cache_version
|
||||
m1v1 = ModelWithKeyAndVersion.new("model/1", 1)
|
||||
m1v2 = ModelWithKeyAndVersion.new("model/1", 2)
|
||||
|
||||
@cache.write(m1v1, "bar")
|
||||
assert @cache.exist?(m1v1)
|
||||
assert_not @cache.fetch(m1v2)
|
||||
end
|
||||
|
||||
def test_fetch_multi_with_model_supporting_cache_version
|
||||
m1v1 = ModelWithKeyAndVersion.new("model/1", 1)
|
||||
m2v1 = ModelWithKeyAndVersion.new("model/2", 1)
|
||||
m2v2 = ModelWithKeyAndVersion.new("model/2", 2)
|
||||
|
||||
first_fetch_values = @cache.fetch_multi(m1v1, m2v1) { |m| m.cache_key }
|
||||
second_fetch_values = @cache.fetch_multi(m1v1, m2v2) { |m| m.cache_key + " 2nd" }
|
||||
|
||||
assert_equal({ m1v1 => "model/1", m2v1 => "model/2" }, first_fetch_values)
|
||||
assert_equal({ m1v1 => "model/1", m2v2 => "model/2 2nd" }, second_fetch_values)
|
||||
end
|
||||
|
||||
def test_version_is_normalized
|
||||
@cache.write("foo", "bar", version: 1)
|
||||
assert_equal "bar", @cache.read("foo", version: "1")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
# https://rails.lighthouseapp.com/projects/8994/tickets/6225-memcachestore-cant-deal-with-umlauts-and-special-characters
|
||||
# The error is caused by character encodings that can't be compared with ASCII-8BIT regular expressions and by special
|
||||
# characters like the umlaut in UTF-8.
|
||||
module EncodedKeyCacheBehavior
|
||||
Encoding.list.each do |encoding|
|
||||
define_method "test_#{encoding.name.underscore}_encoded_values" do
|
||||
key = "foo".force_encoding(encoding)
|
||||
assert @cache.write(key, "1", raw: true)
|
||||
assert_equal "1", @cache.read(key)
|
||||
assert_equal "1", @cache.fetch(key)
|
||||
assert @cache.delete(key)
|
||||
assert_equal "2", @cache.fetch(key, raw: true) { "2" }
|
||||
assert_equal 3, @cache.increment(key)
|
||||
assert_equal 2, @cache.decrement(key)
|
||||
end
|
||||
end
|
||||
|
||||
def test_common_utf8_values
|
||||
key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
|
||||
assert @cache.write(key, "1", raw: true)
|
||||
assert_equal "1", @cache.read(key)
|
||||
assert_equal "1", @cache.fetch(key)
|
||||
assert @cache.delete(key)
|
||||
assert_equal "2", @cache.fetch(key, raw: true) { "2" }
|
||||
assert_equal 3, @cache.increment(key)
|
||||
assert_equal 2, @cache.decrement(key)
|
||||
end
|
||||
|
||||
def test_retains_encoding
|
||||
key = "\xC3\xBCmlaut".force_encoding(Encoding::UTF_8)
|
||||
assert @cache.write(key, "1", raw: true)
|
||||
assert_equal Encoding::UTF_8, key.encoding
|
||||
end
|
||||
end
|
|
@ -0,0 +1,111 @@
|
|||
module LocalCacheBehavior
|
||||
def test_local_writes_are_persistent_on_the_remote_cache
|
||||
retval = @cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
end
|
||||
assert retval
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_clear_also_clears_local_cache
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
@cache.clear
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
|
||||
def test_local_cache_of_write
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
@peek.delete("foo")
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_read
|
||||
@cache.write("foo", "bar")
|
||||
@cache.with_local_cache do
|
||||
assert_equal "bar", @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_read_nil
|
||||
@cache.with_local_cache do
|
||||
assert_nil @cache.read("foo")
|
||||
@cache.send(:bypass_local_cache) { @cache.write "foo", "bar" }
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_fetch
|
||||
@cache.with_local_cache do
|
||||
@cache.send(:local_cache).write "foo", "bar"
|
||||
assert_equal "bar", @cache.send(:local_cache).fetch("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_write_nil
|
||||
@cache.with_local_cache do
|
||||
assert @cache.write("foo", nil)
|
||||
assert_nil @cache.read("foo")
|
||||
@peek.write("foo", "bar")
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_write_with_unless_exist
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
@cache.write("foo", "baz", unless_exist: true)
|
||||
assert_equal @peek.read("foo"), @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_delete
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
@cache.delete("foo")
|
||||
assert_nil @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_exist
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", "bar")
|
||||
@peek.delete("foo")
|
||||
assert @cache.exist?("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_increment
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", 1, raw: true)
|
||||
@peek.write("foo", 2, raw: true)
|
||||
@cache.increment("foo")
|
||||
assert_equal 3, @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_of_decrement
|
||||
@cache.with_local_cache do
|
||||
@cache.write("foo", 1, raw: true)
|
||||
@peek.write("foo", 3, raw: true)
|
||||
@cache.decrement("foo")
|
||||
assert_equal 2, @cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_middleware
|
||||
app = lambda { |env|
|
||||
result = @cache.write("foo", "bar")
|
||||
assert_equal "bar", @cache.read("foo") # make sure 'foo' was written
|
||||
assert result
|
||||
[200, {}, []]
|
||||
}
|
||||
app = @cache.middleware.new(app)
|
||||
app.call({})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
|
||||
class CacheEntryTest < ActiveSupport::TestCase
|
||||
def test_expired
|
||||
entry = ActiveSupport::Cache::Entry.new("value")
|
||||
assert !entry.expired?, "entry not expired"
|
||||
entry = ActiveSupport::Cache::Entry.new("value", expires_in: 60)
|
||||
assert !entry.expired?, "entry not expired"
|
||||
Time.stub(:now, Time.now + 61) do
|
||||
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
|
|
@ -0,0 +1,88 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
|
||||
class CacheKeyTest < ActiveSupport::TestCase
|
||||
def test_entry_legacy_optional_ivars
|
||||
legacy = Class.new(ActiveSupport::Cache::Entry) do
|
||||
def initialize(value, options = {})
|
||||
@value = value
|
||||
@expires_in = nil
|
||||
@created_at = nil
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
entry = legacy.new "foo"
|
||||
assert_equal "foo", entry.value
|
||||
end
|
||||
|
||||
def test_expand_cache_key
|
||||
assert_equal "1/2/true", ActiveSupport::Cache.expand_cache_key([1, "2", true])
|
||||
assert_equal "name/1/2/true", ActiveSupport::Cache.expand_cache_key([1, "2", true], :name)
|
||||
end
|
||||
|
||||
def test_expand_cache_key_with_rails_cache_id
|
||||
with_env("RAILS_CACHE_ID" => "c99") do
|
||||
assert_equal "c99/foo", ActiveSupport::Cache.expand_cache_key(:foo)
|
||||
assert_equal "c99/foo", ActiveSupport::Cache.expand_cache_key([:foo])
|
||||
assert_equal "c99/foo/bar", ActiveSupport::Cache.expand_cache_key([:foo, :bar])
|
||||
assert_equal "nm/c99/foo", ActiveSupport::Cache.expand_cache_key(:foo, :nm)
|
||||
assert_equal "nm/c99/foo", ActiveSupport::Cache.expand_cache_key([:foo], :nm)
|
||||
assert_equal "nm/c99/foo/bar", ActiveSupport::Cache.expand_cache_key([:foo, :bar], :nm)
|
||||
end
|
||||
end
|
||||
|
||||
def test_expand_cache_key_with_rails_app_version
|
||||
with_env("RAILS_APP_VERSION" => "rails3") do
|
||||
assert_equal "rails3/foo", ActiveSupport::Cache.expand_cache_key(:foo)
|
||||
end
|
||||
end
|
||||
|
||||
def test_expand_cache_key_rails_cache_id_should_win_over_rails_app_version
|
||||
with_env("RAILS_CACHE_ID" => "c99", "RAILS_APP_VERSION" => "rails3") do
|
||||
assert_equal "c99/foo", ActiveSupport::Cache.expand_cache_key(:foo)
|
||||
end
|
||||
end
|
||||
|
||||
def test_expand_cache_key_respond_to_cache_key
|
||||
key = "foo"
|
||||
def key.cache_key
|
||||
:foo_key
|
||||
end
|
||||
assert_equal "foo_key", ActiveSupport::Cache.expand_cache_key(key)
|
||||
end
|
||||
|
||||
def test_expand_cache_key_array_with_something_that_responds_to_cache_key
|
||||
key = "foo"
|
||||
def key.cache_key
|
||||
:foo_key
|
||||
end
|
||||
assert_equal "foo_key", ActiveSupport::Cache.expand_cache_key([key])
|
||||
end
|
||||
|
||||
def test_expand_cache_key_of_nil
|
||||
assert_equal "", ActiveSupport::Cache.expand_cache_key(nil)
|
||||
end
|
||||
|
||||
def test_expand_cache_key_of_false
|
||||
assert_equal "false", ActiveSupport::Cache.expand_cache_key(false)
|
||||
end
|
||||
|
||||
def test_expand_cache_key_of_true
|
||||
assert_equal "true", ActiveSupport::Cache.expand_cache_key(true)
|
||||
end
|
||||
|
||||
def test_expand_cache_key_of_array_like_object
|
||||
assert_equal "foo/bar/baz", ActiveSupport::Cache.expand_cache_key(%w{foo bar baz}.to_enum)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_env(kv)
|
||||
old_values = {}
|
||||
kv.each { |key, value| old_values[key], ENV[key] = ENV[key], value }
|
||||
yield
|
||||
ensure
|
||||
old_values.each { |key, value| ENV[key] = value }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
|
||||
class CacheStoreLoggerTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
@cache = ActiveSupport::Cache.lookup_store(:memory_store)
|
||||
|
||||
@buffer = StringIO.new
|
||||
@cache.logger = ActiveSupport::Logger.new(@buffer)
|
||||
end
|
||||
|
||||
def test_logging
|
||||
@cache.fetch("foo") { "bar" }
|
||||
assert @buffer.string.present?
|
||||
end
|
||||
|
||||
def test_log_with_string_namespace
|
||||
@cache.fetch("foo", namespace: "string_namespace") { "bar" }
|
||||
assert_match %r{string_namespace:foo}, @buffer.string
|
||||
end
|
||||
|
||||
def test_log_with_proc_namespace
|
||||
proc = Proc.new do
|
||||
"proc_namespace"
|
||||
end
|
||||
@cache.fetch("foo", namespace: proc) { "bar" }
|
||||
assert_match %r{proc_namespace:foo}, @buffer.string
|
||||
end
|
||||
|
||||
def test_mute_logging
|
||||
@cache.mute { @cache.fetch("foo") { "bar" } }
|
||||
assert @buffer.string.blank?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
|
||||
class CacheStoreNamespaceTest < ActiveSupport::TestCase
|
||||
def test_static_namespace
|
||||
cache = ActiveSupport::Cache.lookup_store(:memory_store, namespace: "tester")
|
||||
cache.write("foo", "bar")
|
||||
assert_equal "bar", cache.read("foo")
|
||||
assert_equal "bar", cache.instance_variable_get(:@data)["tester:foo"].value
|
||||
end
|
||||
|
||||
def test_proc_namespace
|
||||
test_val = "tester"
|
||||
proc = lambda { test_val }
|
||||
cache = ActiveSupport::Cache.lookup_store(:memory_store, namespace: proc)
|
||||
cache.write("foo", "bar")
|
||||
assert_equal "bar", cache.read("foo")
|
||||
assert_equal "bar", cache.instance_variable_get(:@data)["tester:foo"].value
|
||||
end
|
||||
|
||||
def test_delete_matched_key_start
|
||||
cache = ActiveSupport::Cache.lookup_store(:memory_store, namespace: "tester")
|
||||
cache.write("foo", "bar")
|
||||
cache.write("fu", "baz")
|
||||
cache.delete_matched(/^fo/)
|
||||
assert !cache.exist?("foo")
|
||||
assert cache.exist?("fu")
|
||||
end
|
||||
|
||||
def test_delete_matched_key
|
||||
cache = ActiveSupport::Cache.lookup_store(:memory_store, namespace: "foo")
|
||||
cache.write("foo", "bar")
|
||||
cache.write("fu", "baz")
|
||||
cache.delete_matched(/OO/i)
|
||||
assert !cache.exist?("foo")
|
||||
assert cache.exist?("fu")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
require "dalli"
|
||||
|
||||
class CacheStoreSettingTest < ActiveSupport::TestCase
|
||||
def test_memory_store_gets_created_if_no_arguments_passed_to_lookup_store_method
|
||||
store = ActiveSupport::Cache.lookup_store
|
||||
assert_kind_of(ActiveSupport::Cache::MemoryStore, store)
|
||||
end
|
||||
|
||||
def test_memory_store
|
||||
store = ActiveSupport::Cache.lookup_store :memory_store
|
||||
assert_kind_of(ActiveSupport::Cache::MemoryStore, store)
|
||||
end
|
||||
|
||||
def test_file_fragment_cache_store
|
||||
store = ActiveSupport::Cache.lookup_store :file_store, "/path/to/cache/directory"
|
||||
assert_kind_of(ActiveSupport::Cache::FileStore, store)
|
||||
assert_equal "/path/to/cache/directory", store.cache_path
|
||||
end
|
||||
|
||||
def test_mem_cache_fragment_cache_store
|
||||
assert_called_with(Dalli::Client, :new, [%w[localhost], {}]) do
|
||||
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost"
|
||||
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
|
||||
end
|
||||
end
|
||||
|
||||
def test_mem_cache_fragment_cache_store_with_given_mem_cache
|
||||
mem_cache = Dalli::Client.new
|
||||
assert_not_called(Dalli::Client, :new) do
|
||||
store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache
|
||||
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
|
||||
end
|
||||
end
|
||||
|
||||
def test_mem_cache_fragment_cache_store_with_not_dalli_client
|
||||
assert_not_called(Dalli::Client, :new) do
|
||||
memcache = Object.new
|
||||
assert_raises(ArgumentError) do
|
||||
ActiveSupport::Cache.lookup_store :mem_cache_store, memcache
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_mem_cache_fragment_cache_store_with_multiple_servers
|
||||
assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], {}]) do
|
||||
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", "192.168.1.1"
|
||||
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
|
||||
end
|
||||
end
|
||||
|
||||
def test_mem_cache_fragment_cache_store_with_options
|
||||
assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], { timeout: 10 }]) do
|
||||
store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", "192.168.1.1", namespace: "foo", timeout: 10
|
||||
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
|
||||
assert_equal "foo", store.options[:namespace]
|
||||
end
|
||||
end
|
||||
|
||||
def test_object_assigned_fragment_cache_store
|
||||
store = ActiveSupport::Cache.lookup_store ActiveSupport::Cache::FileStore.new("/path/to/cache/directory")
|
||||
assert_kind_of(ActiveSupport::Cache::FileStore, store)
|
||||
assert_equal "/path/to/cache/directory", store.cache_path
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
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
|
||||
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
|
||||
writes = { "a" => "aa", "b" => "bb" }
|
||||
|
||||
events = with_instrumentation "write_multi" do
|
||||
@cache.write_multi(writes)
|
||||
end
|
||||
|
||||
assert_equal %w[ cache_write_multi.active_support ], events.map(&:name)
|
||||
assert_nil events[0].payload[:super_operation]
|
||||
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"
|
||||
|
||||
events = with_instrumentation "write_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]
|
||||
end
|
||||
|
||||
private
|
||||
def with_instrumentation(method)
|
||||
event_name = "cache_#{method}.active_support"
|
||||
|
||||
[].tap do |events|
|
||||
ActiveSupport::Notifications.subscribe event_name do |*args|
|
||||
events << ActiveSupport::Notifications::Event.new(*args)
|
||||
end
|
||||
yield
|
||||
end
|
||||
ensure
|
||||
ActiveSupport::Notifications.unsubscribe event_name
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
|
||||
module ActiveSupport
|
||||
module Cache
|
||||
module Strategy
|
||||
module LocalCache
|
||||
class MiddlewareTest < ActiveSupport::TestCase
|
||||
def test_local_cache_cleared_on_close
|
||||
key = "super awesome key"
|
||||
assert_nil LocalCacheRegistry.cache_for key
|
||||
middleware = Middleware.new("<3", key).new(->(env) {
|
||||
assert LocalCacheRegistry.cache_for(key), "should have a cache"
|
||||
[200, {}, []]
|
||||
})
|
||||
_, _, body = middleware.call({})
|
||||
assert LocalCacheRegistry.cache_for(key), "should still have a cache"
|
||||
body.each {}
|
||||
assert LocalCacheRegistry.cache_for(key), "should still have a cache"
|
||||
body.close
|
||||
assert_nil LocalCacheRegistry.cache_for(key)
|
||||
end
|
||||
|
||||
def test_local_cache_cleared_and_response_should_be_present_on_invalid_parameters_error
|
||||
key = "super awesome key"
|
||||
assert_nil LocalCacheRegistry.cache_for key
|
||||
middleware = Middleware.new("<3", key).new(->(env) {
|
||||
assert LocalCacheRegistry.cache_for(key), "should have a cache"
|
||||
raise Rack::Utils::InvalidParameterError
|
||||
})
|
||||
response = middleware.call({})
|
||||
assert response, "response should exist"
|
||||
assert_nil LocalCacheRegistry.cache_for(key)
|
||||
end
|
||||
|
||||
def test_local_cache_cleared_on_exception
|
||||
key = "super awesome key"
|
||||
assert_nil LocalCacheRegistry.cache_for key
|
||||
middleware = Middleware.new("<3", key).new(->(env) {
|
||||
assert LocalCacheRegistry.cache_for(key), "should have a cache"
|
||||
raise
|
||||
})
|
||||
assert_raises(RuntimeError) { middleware.call({}) }
|
||||
assert_nil LocalCacheRegistry.cache_for(key)
|
||||
end
|
||||
|
||||
def test_local_cache_cleared_on_throw
|
||||
key = "super awesome key"
|
||||
assert_nil LocalCacheRegistry.cache_for key
|
||||
middleware = Middleware.new("<3", key).new(->(env) {
|
||||
assert LocalCacheRegistry.cache_for(key), "should have a cache"
|
||||
throw :warden
|
||||
})
|
||||
assert_throws(:warden) { middleware.call({}) }
|
||||
assert_nil LocalCacheRegistry.cache_for(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
require_relative "../behaviors"
|
||||
require "pathname"
|
||||
|
||||
class FileStoreTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
Dir.mkdir(cache_dir) unless File.exist?(cache_dir)
|
||||
@cache = ActiveSupport::Cache.lookup_store(:file_store, cache_dir, expires_in: 60)
|
||||
@peek = ActiveSupport::Cache.lookup_store(:file_store, cache_dir, expires_in: 60)
|
||||
@cache_with_pathname = ActiveSupport::Cache.lookup_store(:file_store, Pathname.new(cache_dir), expires_in: 60)
|
||||
|
||||
@buffer = StringIO.new
|
||||
@cache.logger = ActiveSupport::Logger.new(@buffer)
|
||||
end
|
||||
|
||||
def teardown
|
||||
FileUtils.rm_r(cache_dir)
|
||||
rescue Errno::ENOENT
|
||||
end
|
||||
|
||||
def cache_dir
|
||||
File.join(Dir.pwd, "tmp_cache")
|
||||
end
|
||||
|
||||
include CacheStoreBehavior
|
||||
include CacheStoreVersionBehavior
|
||||
include LocalCacheBehavior
|
||||
include CacheDeleteMatchedBehavior
|
||||
include CacheIncrementDecrementBehavior
|
||||
include AutoloadingCacheBehavior
|
||||
|
||||
def test_clear
|
||||
gitkeep = File.join(cache_dir, ".gitkeep")
|
||||
keep = File.join(cache_dir, ".keep")
|
||||
FileUtils.touch([gitkeep, keep])
|
||||
@cache.clear
|
||||
assert File.exist?(gitkeep)
|
||||
assert File.exist?(keep)
|
||||
end
|
||||
|
||||
def test_clear_without_cache_dir
|
||||
FileUtils.rm_r(cache_dir)
|
||||
@cache.clear
|
||||
end
|
||||
|
||||
def test_long_uri_encoded_keys
|
||||
@cache.write("%" * 870, 1)
|
||||
assert_equal 1, @cache.read("%" * 870)
|
||||
end
|
||||
|
||||
def test_key_transformation
|
||||
key = @cache.send(:normalize_key, "views/index?id=1", {})
|
||||
assert_equal "views/index?id=1", @cache.send(:file_path_key, key)
|
||||
end
|
||||
|
||||
def test_key_transformation_with_pathname
|
||||
FileUtils.touch(File.join(cache_dir, "foo"))
|
||||
key = @cache_with_pathname.send(:normalize_key, "views/index?id=1", {})
|
||||
assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key)
|
||||
end
|
||||
|
||||
# Test that generated cache keys are short enough to have Tempfile stuff added to them and
|
||||
# remain valid
|
||||
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|
|
||||
assert File.basename(tmpname + ".lock").length <= 255, "Temp filename too long: #{File.basename(tmpname + '.lock').length}"
|
||||
end
|
||||
end
|
||||
|
||||
# Because file systems have a maximum filename size, filenames > max size should be split in to directories
|
||||
# If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B
|
||||
def test_key_transformation_max_filename_size
|
||||
key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B"
|
||||
path = @cache.send(:normalize_key, key, {})
|
||||
assert path.split("/").all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE }
|
||||
assert_equal "B", File.basename(path)
|
||||
end
|
||||
|
||||
# If nothing has been stored in the cache, there is a chance the cache directory does not yet exist
|
||||
# Ensure delete_matched gracefully handles this case
|
||||
def test_delete_matched_when_cache_directory_does_not_exist
|
||||
assert_nothing_raised do
|
||||
ActiveSupport::Cache::FileStore.new("/test/cache/directory").delete_matched(/does_not_exist/)
|
||||
end
|
||||
end
|
||||
|
||||
def test_delete_does_not_delete_empty_parent_dir
|
||||
sub_cache_dir = File.join(cache_dir, "subdir/")
|
||||
sub_cache_store = ActiveSupport::Cache::FileStore.new(sub_cache_dir)
|
||||
assert_nothing_raised do
|
||||
assert sub_cache_store.write("foo", "bar")
|
||||
assert sub_cache_store.delete("foo")
|
||||
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?
|
||||
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?
|
||||
end
|
||||
end
|
||||
|
||||
def test_cleanup_removes_all_expired_entries
|
||||
time = Time.now
|
||||
@cache.write("foo", "bar", expires_in: 10)
|
||||
@cache.write("baz", "qux")
|
||||
@cache.write("quux", "corge", expires_in: 20)
|
||||
Time.stub(:now, time + 15) do
|
||||
@cache.cleanup
|
||||
assert_not @cache.exist?("foo")
|
||||
assert @cache.exist?("baz")
|
||||
assert @cache.exist?("quux")
|
||||
end
|
||||
end
|
||||
|
||||
def test_write_with_unless_exist
|
||||
assert_equal true, @cache.write(1, "aaaaaaaaaa")
|
||||
assert_equal false, @cache.write(1, "aaaaaaaaaa", unless_exist: true)
|
||||
@cache.write(1, nil)
|
||||
assert_equal false, @cache.write(1, "aaaaaaaaaa", unless_exist: true)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
require_relative "../behaviors"
|
||||
require "dalli"
|
||||
|
||||
class MemCacheStoreTest < ActiveSupport::TestCase
|
||||
begin
|
||||
ss = Dalli::Client.new("localhost:11211").stats
|
||||
raise Dalli::DalliError unless ss["localhost:11211"]
|
||||
|
||||
MEMCACHE_UP = true
|
||||
rescue Dalli::DalliError
|
||||
$stderr.puts "Skipping memcached tests. Start memcached and try again."
|
||||
MEMCACHE_UP = false
|
||||
end
|
||||
|
||||
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)
|
||||
@data = @cache.instance_variable_get(:@data)
|
||||
@cache.clear
|
||||
@cache.silence!
|
||||
@cache.logger = ActiveSupport::Logger.new("/dev/null")
|
||||
end
|
||||
|
||||
include CacheStoreBehavior
|
||||
include CacheStoreVersionBehavior
|
||||
include LocalCacheBehavior
|
||||
include CacheIncrementDecrementBehavior
|
||||
include EncodedKeyCacheBehavior
|
||||
include AutoloadingCacheBehavior
|
||||
|
||||
def test_raw_values
|
||||
cache = ActiveSupport::Cache.lookup_store(:mem_cache_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.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.clear
|
||||
cache.with_local_cache do
|
||||
cache.write("foo", 2)
|
||||
assert_equal "2", cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_cache_raw_values_with_marshal
|
||||
cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, raw: true)
|
||||
cache.clear
|
||||
cache.with_local_cache do
|
||||
cache.write("foo", Marshal.dump([]))
|
||||
assert_equal [], cache.read("foo")
|
||||
end
|
||||
end
|
||||
|
||||
def test_read_should_return_a_different_object_id_each_time_it_is_called
|
||||
@cache.write("foo", "bar")
|
||||
value = @cache.read("foo")
|
||||
assert_not_equal value.object_id, @cache.read("foo").object_id
|
||||
value << "bingo"
|
||||
assert_not_equal value, @cache.read("foo")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,107 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
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)
|
||||
end
|
||||
|
||||
include CacheStoreBehavior
|
||||
include CacheStoreVersionBehavior
|
||||
include CacheDeleteMatchedBehavior
|
||||
include CacheIncrementDecrementBehavior
|
||||
|
||||
def test_prune_size
|
||||
@cache.write(1, "aaaaaaaaaa") && sleep(0.001)
|
||||
@cache.write(2, "bbbbbbbbbb") && sleep(0.001)
|
||||
@cache.write(3, "cccccccccc") && sleep(0.001)
|
||||
@cache.write(4, "dddddddddd") && sleep(0.001)
|
||||
@cache.write(5, "eeeeeeeeee") && sleep(0.001)
|
||||
@cache.read(2) && sleep(0.001)
|
||||
@cache.read(4)
|
||||
@cache.prune(@record_size * 3)
|
||||
assert @cache.exist?(5)
|
||||
assert @cache.exist?(4)
|
||||
assert !@cache.exist?(3), "no entry"
|
||||
assert @cache.exist?(2)
|
||||
assert !@cache.exist?(1), "no entry"
|
||||
end
|
||||
|
||||
def test_prune_size_on_write
|
||||
@cache.write(1, "aaaaaaaaaa") && sleep(0.001)
|
||||
@cache.write(2, "bbbbbbbbbb") && sleep(0.001)
|
||||
@cache.write(3, "cccccccccc") && sleep(0.001)
|
||||
@cache.write(4, "dddddddddd") && sleep(0.001)
|
||||
@cache.write(5, "eeeeeeeeee") && sleep(0.001)
|
||||
@cache.write(6, "ffffffffff") && sleep(0.001)
|
||||
@cache.write(7, "gggggggggg") && sleep(0.001)
|
||||
@cache.write(8, "hhhhhhhhhh") && sleep(0.001)
|
||||
@cache.write(9, "iiiiiiiiii") && sleep(0.001)
|
||||
@cache.write(10, "kkkkkkkkkk") && sleep(0.001)
|
||||
@cache.read(2) && sleep(0.001)
|
||||
@cache.read(4) && sleep(0.001)
|
||||
@cache.write(11, "llllllllll")
|
||||
assert @cache.exist?(11)
|
||||
assert @cache.exist?(10)
|
||||
assert @cache.exist?(9)
|
||||
assert @cache.exist?(8)
|
||||
assert @cache.exist?(7)
|
||||
assert !@cache.exist?(6), "no entry"
|
||||
assert !@cache.exist?(5), "no entry"
|
||||
assert @cache.exist?(4)
|
||||
assert !@cache.exist?(3), "no entry"
|
||||
assert @cache.exist?(2)
|
||||
assert !@cache.exist?(1), "no entry"
|
||||
end
|
||||
|
||||
def test_prune_size_on_write_based_on_key_length
|
||||
@cache.write(1, "aaaaaaaaaa") && sleep(0.001)
|
||||
@cache.write(2, "bbbbbbbbbb") && sleep(0.001)
|
||||
@cache.write(3, "cccccccccc") && sleep(0.001)
|
||||
@cache.write(4, "dddddddddd") && sleep(0.001)
|
||||
@cache.write(5, "eeeeeeeeee") && sleep(0.001)
|
||||
@cache.write(6, "ffffffffff") && sleep(0.001)
|
||||
@cache.write(7, "gggggggggg") && sleep(0.001)
|
||||
@cache.write(8, "hhhhhhhhhh") && sleep(0.001)
|
||||
@cache.write(9, "iiiiiiiiii") && sleep(0.001)
|
||||
long_key = "*" * 2 * @record_size
|
||||
@cache.write(long_key, "llllllllll")
|
||||
assert @cache.exist?(long_key)
|
||||
assert @cache.exist?(9)
|
||||
assert @cache.exist?(8)
|
||||
assert @cache.exist?(7)
|
||||
assert @cache.exist?(6)
|
||||
assert !@cache.exist?(5), "no entry"
|
||||
assert !@cache.exist?(4), "no entry"
|
||||
assert !@cache.exist?(3), "no entry"
|
||||
assert !@cache.exist?(2), "no entry"
|
||||
assert !@cache.exist?(1), "no entry"
|
||||
end
|
||||
|
||||
def test_pruning_is_capped_at_a_max_time
|
||||
def @cache.delete_entry(*args)
|
||||
sleep(0.01)
|
||||
super
|
||||
end
|
||||
@cache.write(1, "aaaaaaaaaa") && sleep(0.001)
|
||||
@cache.write(2, "bbbbbbbbbb") && sleep(0.001)
|
||||
@cache.write(3, "cccccccccc") && sleep(0.001)
|
||||
@cache.write(4, "dddddddddd") && sleep(0.001)
|
||||
@cache.write(5, "eeeeeeeeee") && sleep(0.001)
|
||||
@cache.prune(30, 0.001)
|
||||
assert @cache.exist?(5)
|
||||
assert @cache.exist?(4)
|
||||
assert @cache.exist?(3)
|
||||
assert @cache.exist?(2)
|
||||
assert !@cache.exist?(1)
|
||||
end
|
||||
|
||||
def test_write_with_unless_exist
|
||||
assert_equal true, @cache.write(1, "aaaaaaaaaa")
|
||||
assert_equal false, @cache.write(1, "aaaaaaaaaa", unless_exist: true)
|
||||
@cache.write(1, nil)
|
||||
assert_equal false, @cache.write(1, "aaaaaaaaaa", unless_exist: true)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
require "abstract_unit"
|
||||
require "active_support/cache"
|
||||
require_relative "../behaviors"
|
||||
|
||||
class NullStoreTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
@cache = ActiveSupport::Cache.lookup_store(:null_store)
|
||||
end
|
||||
|
||||
def test_clear
|
||||
@cache.clear
|
||||
end
|
||||
|
||||
def test_cleanup
|
||||
@cache.cleanup
|
||||
end
|
||||
|
||||
def test_write
|
||||
assert_equal true, @cache.write("name", "value")
|
||||
end
|
||||
|
||||
def test_read
|
||||
@cache.write("name", "value")
|
||||
assert_nil @cache.read("name")
|
||||
end
|
||||
|
||||
def test_delete
|
||||
@cache.write("name", "value")
|
||||
assert_equal false, @cache.delete("name")
|
||||
end
|
||||
|
||||
def test_increment
|
||||
@cache.write("name", 1, raw: true)
|
||||
assert_nil @cache.increment("name")
|
||||
end
|
||||
|
||||
def test_decrement
|
||||
@cache.write("name", 1, raw: true)
|
||||
assert_nil @cache.increment("name")
|
||||
end
|
||||
|
||||
def test_delete_matched
|
||||
@cache.write("name", "value")
|
||||
@cache.delete_matched(/name/)
|
||||
end
|
||||
|
||||
def test_local_store_strategy
|
||||
@cache.with_local_cache do
|
||||
@cache.write("name", "value")
|
||||
assert_equal "value", @cache.read("name")
|
||||
@cache.delete("name")
|
||||
assert_nil @cache.read("name")
|
||||
@cache.write("name", "value")
|
||||
end
|
||||
assert_nil @cache.read("name")
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue