caching_test.rb 25.4 KB
Newer Older
1
require 'logger'
2
require 'abstract_unit'
J
Jeremy Kemper 已提交
3
require 'active_support/cache'
4

5
class CacheKeyTest < ActiveSupport::TestCase
6
  def test_expand_cache_key
7 8
    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)
9
  end
10 11

  def test_expand_cache_key_with_rails_cache_id
12 13 14
    begin
      ENV['RAILS_CACHE_ID'] = 'c99'
      assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key(:foo)
15 16
      assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key([:foo])
      assert_equal 'c99/foo/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar])
17
      assert_equal 'nm/c99/foo', ActiveSupport::Cache.expand_cache_key(:foo, :nm)
18 19
      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)
20 21 22
    ensure
      ENV['RAILS_CACHE_ID'] = nil
    end
23
  end
24 25

  def test_expand_cache_key_with_rails_app_version
26 27 28 29 30 31
    begin
      ENV['RAILS_APP_VERSION'] = 'rails3'
      assert_equal 'rails3/foo', ActiveSupport::Cache.expand_cache_key(:foo)
    ensure
      ENV['RAILS_APP_VERSION'] = nil
    end
32 33 34
  end

  def test_expand_cache_key_rails_cache_id_should_win_over_rails_app_version
35 36 37 38 39 40 41 42 43 44
    begin
      ENV['RAILS_CACHE_ID'] = 'c99'
      ENV['RAILS_APP_VERSION'] = 'rails3'
      assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key(:foo)
    ensure
      ENV['RAILS_CACHE_ID'] = nil
      ENV['RAILS_APP_VERSION'] = nil
    end
  end

45
  def test_expand_cache_key_respond_to_cache_key
46 47 48 49 50
    key = 'foo'
    def key.cache_key
      :foo_key
    end
    assert_equal 'foo_key', ActiveSupport::Cache.expand_cache_key(key)
51 52
  end

53
  def test_expand_cache_key_array_with_something_that_responds_to_cache_key
54 55 56 57
    key = 'foo'
    def key.cache_key
      :foo_key
    end
58
    assert_equal 'foo_key', ActiveSupport::Cache.expand_cache_key([key])
59 60
  end

61 62 63 64 65 66 67 68 69 70 71
  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
72 73 74 75
  
  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
76 77
end

78
class CacheStoreSettingTest < ActiveSupport::TestCase
79 80 81 82 83
  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
84

85
  def test_mem_cache_fragment_cache_store
86
    MemCache.expects(:new).with(%w[localhost], {})
87 88
    store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost"
    assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
89 90 91 92 93 94 95
  end

  def test_mem_cache_fragment_cache_store_with_given_mem_cache
    mem_cache = MemCache.new
    MemCache.expects(:new).never
    store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache
    assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
96
  end
97

98 99
  def test_mem_cache_fragment_cache_store_with_given_mem_cache_like_object
    MemCache.expects(:new).never
100 101 102
    memcache = Object.new
    def memcache.get() true end
    store = ActiveSupport::Cache.lookup_store :mem_cache_store, memcache
103 104 105
    assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
  end

106
  def test_mem_cache_fragment_cache_store_with_multiple_servers
107
    MemCache.expects(:new).with(%w[localhost 192.168.1.1], {})
108 109 110
    store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1'
    assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
  end
111

112
  def test_mem_cache_fragment_cache_store_with_options
B
Brian Durand 已提交
113 114
    MemCache.expects(:new).with(%w[localhost 192.168.1.1], { :timeout => 10 })
    store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo', :timeout => 10
115
    assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
B
Brian Durand 已提交
116
    assert_equal 'foo', store.options[:namespace]
117
  end
118 119 120 121 122 123 124

  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
125

B
Brian Durand 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
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/)
148 149
    assert !cache.exist?("foo")
    assert cache.exist?("fu")
B
Brian Durand 已提交
150 151 152 153 154 155 156
  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)
157 158
    assert !cache.exist?("foo")
    assert cache.exist?("fu")
B
Brian Durand 已提交
159 160 161 162 163 164
  end
end

# Tests the base functionality that should be identical across all cache stores.
module CacheStoreBehavior
  def test_should_read_and_write_strings
165
    assert @cache.write('foo', 'bar')
B
Brian Durand 已提交
166 167 168 169 170 171 172
    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')
173
  end
174

175
  def test_fetch_without_cache_miss
B
Brian Durand 已提交
176
    @cache.write('foo', 'bar')
177 178 179
    @cache.expects(:write).never
    assert_equal 'bar', @cache.fetch('foo') { 'baz' }
  end
180

181
  def test_fetch_with_cache_miss
B
Brian Durand 已提交
182
    @cache.expects(:write).with('foo', 'baz', @cache.options)
183 184
    assert_equal 'baz', @cache.fetch('foo') { 'baz' }
  end
185

186
  def test_fetch_with_forced_cache_miss
B
Brian Durand 已提交
187
    @cache.write('foo', 'bar')
188
    @cache.expects(:read).never
B
Brian Durand 已提交
189
    @cache.expects(:write).with('foo', 'bar', @cache.options.merge(:force => true))
190
    @cache.fetch('foo', :force => true) { 'bar' }
191
  end
J
Joshua Peek 已提交
192

B
Brian Durand 已提交
193 194 195 196
  def test_fetch_with_cached_nil
    @cache.write('foo', nil)
    @cache.expects(:write).never
    assert_nil @cache.fetch('foo') { 'baz' }
J
Joshua Peek 已提交
197 198 199
  end

  def test_should_read_and_write_hash
200
    assert @cache.write('foo', {:a => "b"})
J
Joshua Peek 已提交
201 202 203
    assert_equal({:a => "b"}, @cache.read('foo'))
  end

204
  def test_should_read_and_write_integer
205
    assert @cache.write('foo', 1)
206 207 208
    assert_equal 1, @cache.read('foo')
  end

J
Joshua Peek 已提交
209
  def test_should_read_and_write_nil
210
    assert @cache.write('foo', nil)
J
Joshua Peek 已提交
211
    assert_equal nil, @cache.read('foo')
212 213
  end

214
  def test_should_read_and_write_false
215
    assert @cache.write('foo', false)
216
    assert_equal false, @cache.read('foo')
217 218
  end

B
Brian Durand 已提交
219
  def test_read_multi
220
    @cache.write('foo', 'bar')
B
Brian Durand 已提交
221 222 223
    @cache.write('fu', 'baz')
    @cache.write('fud', 'biz')
    assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
224
  end
225

226 227 228 229 230 231 232
  def test_read_multi_with_expires
    @cache.write('foo', 'bar', :expires_in => 0.001)
    @cache.write('fu', 'baz')
    @cache.write('fud', 'biz')
    sleep(0.002)
    assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu'))
  end
233

B
Brian Durand 已提交
234 235 236 237
  def test_read_and_write_compressed_small_data
    @cache.write('foo', 'bar', :compress => true)
    raw_value = @cache.send(:read_entry, 'foo', {}).raw_value
    assert_equal 'bar', @cache.read('foo')
238
    assert_equal 'bar', Marshal.load(raw_value)
239 240
  end

B
Brian Durand 已提交
241 242 243 244 245
  def test_read_and_write_compressed_large_data
    @cache.write('foo', 'bar', :compress => true, :compress_threshold => 2)
    raw_value = @cache.send(:read_entry, 'foo', {}).raw_value
    assert_equal 'bar', @cache.read('foo')
    assert_equal 'bar', Marshal.load(Zlib::Inflate.inflate(raw_value))
246
  end
247

B
Brian Durand 已提交
248 249 250
  def test_read_and_write_compressed_nil
    @cache.write('foo', nil, :compress => true)
    assert_nil @cache.read('foo')
251 252
  end

B
Brian Durand 已提交
253 254 255 256 257 258 259
  def test_cache_key
    obj = Object.new
    def obj.cache_key
      :foo
    end
    @cache.write(obj, "bar")
    assert_equal "bar", @cache.read("foo")
260
  end
261

B
Brian Durand 已提交
262 263 264 265 266 267 268
  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")
269
  end
270

B
Brian Durand 已提交
271 272 273
  def test_array_as_cache_key
    @cache.write([:fu, "foo"], "bar")
    assert_equal "bar", @cache.read("fu/foo")
274 275
  end

B
Brian Durand 已提交
276 277 278
  def test_hash_as_cache_key
    @cache.write({:foo => 1, :fu => 2}, "bar")
    assert_equal "bar", @cache.read("foo=1/fu=2")
279 280
  end

B
Brian Durand 已提交
281 282 283 284
  def test_keys_are_case_sensitive
    @cache.write("foo", "bar")
    assert_nil @cache.read("FOO")
  end
285

B
Brian Durand 已提交
286
  def test_exist
287
    @cache.write('foo', 'bar')
288 289
    assert @cache.exist?('foo')
    assert !@cache.exist?('bar')
290
  end
291

B
Brian Durand 已提交
292 293
  def test_nil_exist
    @cache.write('foo', nil)
294
    assert @cache.exist?('foo')
295 296
  end

B
Brian Durand 已提交
297 298 299
  def test_delete
    @cache.write('foo', 'bar')
    assert @cache.exist?('foo')
300
    assert @cache.delete('foo')
B
Brian Durand 已提交
301 302
    assert !@cache.exist?('foo')
  end
303

304
  def test_read_should_return_a_different_object_id_each_time_it_is_called
305
    @cache.write('foo', 'bar')
306 307 308 309
    assert_not_equal @cache.read('foo').object_id, @cache.read('foo').object_id
    value = @cache.read('foo')
    value << 'bingo'
    assert_not_equal value, @cache.read('foo')
310
  end
311 312 313 314 315 316

  def test_original_store_objects_should_not_be_immutable
    bar = 'bar'
    @cache.write('foo', bar)
    assert_nothing_raised { bar.gsub!(/.*/, 'baz') }
  end
317

B
Brian Durand 已提交
318 319 320 321 322 323 324 325 326 327 328 329
  def test_expires_in
    time = Time.local(2008, 4, 24)
    Time.stubs(:now).returns(time)

    @cache.write('foo', 'bar')
    assert_equal 'bar', @cache.read('foo')

    Time.stubs(:now).returns(time + 30)
    assert_equal 'bar', @cache.read('foo')

    Time.stubs(:now).returns(time + 61)
    assert_nil @cache.read('foo')
330
  end
331

B
Brian Durand 已提交
332 333 334 335 336 337 338
  def test_race_condition_protection
    time = Time.now
    @cache.write('foo', 'bar', :expires_in => 60)
    Time.stubs(:now).returns(time + 61)
    result = @cache.fetch('foo', :race_condition_ttl => 10) do
      assert_equal 'bar', @cache.read('foo')
      "baz"
339
    end
B
Brian Durand 已提交
340 341
    assert_equal "baz", result
  end
342

B
Brian Durand 已提交
343 344 345 346 347 348 349 350 351 352
  def test_race_condition_protection_is_limited
    time = Time.now
    @cache.write('foo', 'bar', :expires_in => 60)
    Time.stubs(:now).returns(time + 71)
    result = @cache.fetch('foo', :race_condition_ttl => 10) do
      assert_equal nil, @cache.read('foo')
      "baz"
    end
    assert_equal "baz", result
  end
353

B
Brian Durand 已提交
354 355 356 357 358 359
  def test_race_condition_protection_is_safe
    time = Time.now
    @cache.write('foo', 'bar', :expires_in => 60)
    Time.stubs(:now).returns(time + 61)
    begin
      @cache.fetch('foo', :race_condition_ttl => 10) do
360
        assert_equal 'bar', @cache.read('foo')
B
Brian Durand 已提交
361
        raise ArgumentError.new
362
      end
S
Santiago Pastorino 已提交
363
    rescue ArgumentError
364
    end
B
Brian Durand 已提交
365 366 367 368 369 370 371
    assert_equal "bar", @cache.read('foo')
    Time.stubs(:now).returns(time + 71)
    assert_nil @cache.read('foo')
  end

  def test_crazy_key_characters
    crazy_key = "#/:*(<+=> )&$%@?;'\"\'`~-"
372
    assert @cache.write(crazy_key, "1", :raw => true)
B
Brian Durand 已提交
373 374
    assert_equal "1", @cache.read(crazy_key)
    assert_equal "1", @cache.fetch(crazy_key)
375
    assert @cache.delete(crazy_key)
B
Brian Durand 已提交
376 377 378 379 380 381 382
    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 = ""
383
    900.times{key << "x"}
384
    assert @cache.write(key, "bar")
B
Brian Durand 已提交
385 386 387 388
    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))
389
    assert @cache.delete(key)
B
Brian Durand 已提交
390 391
  end
end
392

393 394 395 396
# https://rails.lighthouseapp.com/projects/8994/tickets/6225-memcachestore-cant-deal-with-umlauts-and-special-characters
# The error is caused by charcter encodings that can't be compared with ASCII-8BIT regular expressions and by special
# characters like the umlaut in UTF-8.
module EncodedKeyCacheBehavior
397 398 399
  Encoding.list.each do |encoding|
    define_method "test_#{encoding.name.underscore}_encoded_values" do
      key = "foo".force_encoding(encoding)
400
      assert @cache.write(key, "1", :raw => true)
401 402
      assert_equal "1", @cache.read(key)
      assert_equal "1", @cache.fetch(key)
403
      assert @cache.delete(key)
404 405 406 407
      assert_equal "2", @cache.fetch(key, :raw => true) { "2" }
      assert_equal 3, @cache.increment(key)
      assert_equal 2, @cache.decrement(key)
    end
408
  end
409

410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
  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
425 426 427
  end
end

B
Brian Durand 已提交
428 429 430 431
module CacheDeleteMatchedBehavior
  def test_delete_matched
    @cache.write("foo", "bar")
    @cache.write("fu", "baz")
432 433
    @cache.write("foo/bar", "baz")
    @cache.write("fu/baz", "bar")
B
Brian Durand 已提交
434
    @cache.delete_matched(/oo/)
435 436 437 438
    assert !@cache.exist?("foo")
    assert @cache.exist?("fu")
    assert !@cache.exist?("foo/bar")
    assert @cache.exist?("fu/baz")
B
Brian Durand 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  end
end

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
  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
  end
end

module LocalCacheBehavior
  def test_local_writes_are_persistent_on_the_remote_cache
    retval = @cache.with_local_cache do
      @cache.write('foo', 'bar')
466
    end
467
    assert retval
B
Brian Durand 已提交
468 469
    assert_equal 'bar', @cache.read('foo')
  end
470

B
Brian Durand 已提交
471 472 473 474 475
  def test_clear_also_clears_local_cache
    @cache.with_local_cache do
      @cache.write('foo', 'bar')
      @cache.clear
      assert_nil @cache.read('foo')
476 477
    end

B
Brian Durand 已提交
478 479
    assert_nil @cache.read('foo')
  end
480

B
Brian Durand 已提交
481 482 483 484
  def test_local_cache_of_write
    @cache.with_local_cache do
      @cache.write('foo', 'bar')
      @peek.delete('foo')
485 486
      assert_equal 'bar', @cache.read('foo')
    end
B
Brian Durand 已提交
487
  end
488

B
Brian Durand 已提交
489 490 491 492
  def test_local_cache_of_read
    @cache.write('foo', 'bar')
    @cache.with_local_cache do
      assert_equal 'bar', @cache.read('foo')
493
    end
B
Brian Durand 已提交
494
  end
495

B
Brian Durand 已提交
496 497
  def test_local_cache_of_write_nil
    @cache.with_local_cache do
498
      assert @cache.write('foo', nil)
B
Brian Durand 已提交
499 500 501
      assert_nil @cache.read('foo')
      @peek.write('foo', 'bar')
      assert_nil @cache.read('foo')
502
    end
B
Brian Durand 已提交
503
  end
504

B
Brian Durand 已提交
505 506 507 508 509
  def test_local_cache_of_delete
    @cache.with_local_cache do
      @cache.write('foo', 'bar')
      @cache.delete('foo')
      assert_nil @cache.read('foo')
510
    end
B
Brian Durand 已提交
511
  end
512

B
Brian Durand 已提交
513 514 515 516
  def test_local_cache_of_exist
    @cache.with_local_cache do
      @cache.write('foo', 'bar')
      @peek.delete('foo')
517
      assert @cache.exist?('foo')
518
    end
B
Brian Durand 已提交
519
  end
520

B
Brian Durand 已提交
521 522 523 524 525 526
  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')
527
    end
B
Brian Durand 已提交
528
  end
529

B
Brian Durand 已提交
530 531 532 533 534 535
  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')
536
    end
B
Brian Durand 已提交
537
  end
538

B
Brian Durand 已提交
539 540 541 542 543 544 545 546 547 548
  def test_middleware
    app = lambda { |env|
      result = @cache.write('foo', 'bar')
      assert_equal 'bar', @cache.read('foo') # make sure 'foo' was written
      assert result
    }
    app = @cache.middleware.new(app)
    app.call({})
  end
end
549

B
Brian Durand 已提交
550 551 552 553 554
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)
555
    @cache_with_pathname = ActiveSupport::Cache.lookup_store(:file_store, Pathname.new(cache_dir), :expires_in => 60)
B
Brian Durand 已提交
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
  end

  def teardown
    FileUtils.rm_r(cache_dir)
  end

  def cache_dir
    File.join(Dir.pwd, 'tmp_cache')
  end

  include CacheStoreBehavior
  include LocalCacheBehavior
  include CacheDeleteMatchedBehavior
  include CacheIncrementDecrementBehavior

571 572 573 574 575 576 577
  def test_clear
    filepath = File.join(cache_dir, ".gitkeep")
    FileUtils.touch(filepath)
    @cache.clear
    assert File.exist?(filepath)
  end

578 579 580 581
  def test_key_transformation
    key = @cache.send(:key_file_path, "views/index?id=1")
    assert_equal "views/index?id=1", @cache.send(:file_path_key, key)
  end
582 583 584 585 586 587

  def test_key_transformation_with_pathname
    FileUtils.touch(File.join(cache_dir, "foo"))
    key = @cache_with_pathname.send(:key_file_path, "views/index?id=1")
    assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key)
  end
588

589 590 591 592 593 594
  # 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(:key_file_path, key)
    Dir::Tmpname.create(path) do |tmpname, n, opts|
595
      assert File.basename(tmpname+'.lock').length <= 255, "Temp filename too long: #{File.basename(tmpname+'.lock').length}"
596 597 598
    end
  end

599 600 601 602
  # 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"
603
    path = @cache.send(:key_file_path, key)
604 605 606
    assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}
    assert_equal 'B', File.basename(path)
  end
607

608 609 610 611 612
  # 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(Exception) do
      ActiveSupport::Cache::FileStore.new('/test/cache/directory').delete_matched(/does_not_exist/)
613 614
    end
  end
B
Brian Durand 已提交
615
end
616

B
Brian Durand 已提交
617 618
class MemoryStoreTest < ActiveSupport::TestCase
  def setup
619 620
    @record_size = Marshal.dump("aaaaaaaaaa").bytesize
    @cache = ActiveSupport::Cache.lookup_store(:memory_store, :expires_in => 60, :size => @record_size * 10)
B
Brian Durand 已提交
621 622 623 624 625 626 627 628 629 630 631 632 633 634
  end

  include CacheStoreBehavior
  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)
635
    @cache.prune(@record_size * 3)
636 637 638 639 640
    assert @cache.exist?(5)
    assert @cache.exist?(4)
    assert !@cache.exist?(3)
    assert @cache.exist?(2)
    assert !@cache.exist?(1)
B
Brian Durand 已提交
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
  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")
657 658 659 660 661 662 663 664 665 666 667
    assert @cache.exist?(11)
    assert @cache.exist?(10)
    assert @cache.exist?(9)
    assert @cache.exist?(8)
    assert @cache.exist?(7)
    assert !@cache.exist?(6)
    assert !@cache.exist?(5)
    assert @cache.exist?(4)
    assert !@cache.exist?(3)
    assert @cache.exist?(2)
    assert !@cache.exist?(1)
B
Brian Durand 已提交
668 669 670 671 672 673
  end

  def test_pruning_is_capped_at_a_max_time
    def @cache.delete_entry (*args)
      sleep(0.01)
      super
674
    end
B
Brian Durand 已提交
675 676 677 678 679 680
    @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)
681 682 683 684 685
    assert @cache.exist?(5)
    assert @cache.exist?(4)
    assert @cache.exist?(3)
    assert @cache.exist?(2)
    assert !@cache.exist?(1)
B
Brian Durand 已提交
686 687
  end
end
688

B
Brian Durand 已提交
689 690 691 692 693 694 695 696
uses_memcached 'memcached backed store' do
  class MemCacheStoreTest < ActiveSupport::TestCase
    def setup
      @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!
697
      @cache.logger = ActiveSupport::Logger.new("/dev/null")
698 699
    end

B
Brian Durand 已提交
700 701 702
    include CacheStoreBehavior
    include LocalCacheBehavior
    include CacheIncrementDecrementBehavior
703
    include EncodedKeyCacheBehavior
B
Brian Durand 已提交
704 705 706 707 708 709

    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")
710
    end
711

712 713 714 715
    def test_raw_values_with_marshal
      cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true)
      cache.clear
      cache.write("foo", Marshal.dump([]))
716
      assert_equal [], cache.read("foo")
717
    end
718

B
Brian Durand 已提交
719 720 721 722 723 724 725
    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
726
    end
727 728 729 730 731 732 733 734 735

    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
736 737
  end
end
738

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
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

  def test_setting_nil_cache_store
    assert ActiveSupport::Cache.lookup_store.class.name, ActiveSupport::Cache::NullStore.name
  end
end

797 798 799 800 801
class CacheStoreLoggerTest < ActiveSupport::TestCase
  def setup
    @cache = ActiveSupport::Cache.lookup_store(:memory_store)

    @buffer = StringIO.new
802
    @cache.logger = ActiveSupport::Logger.new(@buffer)
803 804 805 806
  end

  def test_logging
    @cache.fetch('foo') { 'bar' }
807
    assert_present @buffer.string
808 809 810 811
  end

  def test_mute_logging
    @cache.mute { @cache.fetch('foo') { 'bar' } }
812
    assert_blank @buffer.string
813 814
  end
end
B
Brian Durand 已提交
815 816 817 818 819 820 821

class CacheEntryTest < ActiveSupport::TestCase
  def test_create_raw_entry
    time = Time.now
    entry = ActiveSupport::Cache::Entry.create("raw", time, :compress => false, :expires_in => 300)
    assert_equal "raw", entry.raw_value
    assert_equal time.to_f, entry.created_at
822
    assert !entry.compressed?
B
Brian Durand 已提交
823 824 825 826 827
    assert_equal 300, entry.expires_in
  end

  def test_expired
    entry = ActiveSupport::Cache::Entry.new("value")
828
    assert !entry.expired?, 'entry not expired'
B
Brian Durand 已提交
829
    entry = ActiveSupport::Cache::Entry.new("value", :expires_in => 60)
830
    assert !entry.expired?, 'entry not expired'
B
Brian Durand 已提交
831 832
    time = Time.now + 61
    Time.stubs(:now).returns(time)
833
    assert entry.expired?, 'entry is expired'
B
Brian Durand 已提交
834 835 836 837 838
  end

  def test_compress_values
    entry = ActiveSupport::Cache::Entry.new("value", :compress => true, :compress_threshold => 1)
    assert_equal "value", entry.value
839
    assert entry.compressed?
B
Brian Durand 已提交
840 841 842 843 844 845
    assert_equal "value", Marshal.load(Zlib::Inflate.inflate(entry.raw_value))
  end

  def test_non_compress_values
    entry = ActiveSupport::Cache::Entry.new("value")
    assert_equal "value", entry.value
846
    assert_equal "value", Marshal.load(entry.raw_value)
847
    assert !entry.compressed?
B
Brian Durand 已提交
848 849
  end
end