diff options
Diffstat (limited to 'activesupport/test')
-rw-r--r-- | activesupport/test/caching_test.rb | 649 | ||||
-rw-r--r-- | activesupport/test/configurable_test.rb | 42 | ||||
-rw-r--r-- | activesupport/test/core_ext/hash_ext_test.rb | 41 | ||||
-rw-r--r-- | activesupport/test/core_ext/string_ext_test.rb | 9 | ||||
-rw-r--r-- | activesupport/test/core_ext/time_with_zone_test.rb | 7 | ||||
-rw-r--r-- | activesupport/test/core_ext/uri_ext_test.rb | 2 | ||||
-rw-r--r-- | activesupport/test/json/encoding_test.rb | 25 | ||||
-rw-r--r-- | activesupport/test/multibyte_chars_test.rb | 2 | ||||
-rw-r--r-- | activesupport/test/notifications_test.rb | 22 | ||||
-rw-r--r-- | activesupport/test/time_zone_test.rb | 8 |
10 files changed, 602 insertions, 205 deletions
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index e62e7ef9aa..d9ff1207e7 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -4,6 +4,7 @@ require 'active_support/cache' class CacheKeyTest < ActiveSupport::TestCase 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 end @@ -43,9 +44,10 @@ class CacheStoreSettingTest < ActiveSupport::TestCase end def test_mem_cache_fragment_cache_store_with_options - MemCache.expects(:new).with(%w[localhost 192.168.1.1], { :namespace => "foo" }) - store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo' + 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 assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_equal 'foo', store.options[:namespace] end def test_object_assigned_fragment_cache_store @@ -55,124 +57,170 @@ class CacheStoreSettingTest < ActiveSupport::TestCase end end -class CacheStoreTest < ActiveSupport::TestCase - def setup - @cache = ActiveSupport::Cache.lookup_store(:memory_store) +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_equal false, cache.exist?("foo") + assert_equal true, 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_equal false, cache.exist?("foo") + assert_equal true, cache.exist?("fu") + end +end + +# Tests the base functionality that should be identical across all cache stores. +module CacheStoreBehavior + def test_should_read_and_write_strings + assert_equal true, @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.stubs(:read).with('foo', {}).returns('bar') + @cache.write('foo', 'bar') @cache.expects(:write).never assert_equal 'bar', @cache.fetch('foo') { 'baz' } end def test_fetch_with_cache_miss - @cache.stubs(:read).with('foo', {}).returns(nil) - @cache.expects(:write).with('foo', 'baz', {}) + @cache.expects(:write).with('foo', 'baz', @cache.options) assert_equal 'baz', @cache.fetch('foo') { 'baz' } end def test_fetch_with_forced_cache_miss + @cache.write('foo', 'bar') @cache.expects(:read).never - @cache.expects(:write).with('foo', 'bar', :force => true) + @cache.expects(:write).with('foo', 'bar', @cache.options.merge(:force => true)) @cache.fetch('foo', :force => true) { 'bar' } end -end -# Tests the base functionality that should be identical across all cache stores. -module CacheStoreBehavior - def test_should_read_and_write_strings - @cache.write('foo', 'bar') - assert_equal 'bar', @cache.read('foo') + def test_fetch_with_cached_nil + @cache.write('foo', nil) + @cache.expects(:write).never + assert_nil @cache.fetch('foo') { 'baz' } end def test_should_read_and_write_hash - @cache.write('foo', {:a => "b"}) + assert_equal true, @cache.write('foo', {:a => "b"}) assert_equal({:a => "b"}, @cache.read('foo')) end def test_should_read_and_write_integer - @cache.write('foo', 1) + assert_equal true, @cache.write('foo', 1) assert_equal 1, @cache.read('foo') end def test_should_read_and_write_nil - @cache.write('foo', nil) + assert_equal true, @cache.write('foo', nil) assert_equal nil, @cache.read('foo') end - def test_fetch_without_cache_miss + def test_read_multi @cache.write('foo', 'bar') - assert_equal 'bar', @cache.fetch('foo') { 'baz' } + @cache.write('fu', 'baz') + @cache.write('fud', 'biz') + assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu')) end - def test_fetch_with_cache_miss - assert_equal 'baz', @cache.fetch('foo') { 'baz' } + 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') + assert_equal 'bar', raw_value end - def test_fetch_with_forced_cache_miss - @cache.fetch('foo', :force => true) { 'bar' } + 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)) end - def test_increment - @cache.write('foo', 1, :raw => true) - assert_equal 1, @cache.read('foo', :raw => true).to_i - assert_equal 2, @cache.increment('foo') - assert_equal 2, @cache.read('foo', :raw => true).to_i - assert_equal 3, @cache.increment('foo') - assert_equal 3, @cache.read('foo', :raw => true).to_i + def test_read_and_write_compressed_nil + @cache.write('foo', nil, :compress => true) + assert_nil @cache.read('foo') end - def test_decrement - @cache.write('foo', 3, :raw => true) - assert_equal 3, @cache.read('foo', :raw => true).to_i - assert_equal 2, @cache.decrement('foo') - assert_equal 2, @cache.read('foo', :raw => true).to_i - assert_equal 1, @cache.decrement('foo') - assert_equal 1, @cache.read('foo', :raw => true).to_i + 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_exist - @cache.write('foo', 'bar') - assert @cache.exist?('foo') - assert !@cache.exist?('bar') + 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 -end -class FileStoreTest < ActiveSupport::TestCase - def setup - @cache = ActiveSupport::Cache.lookup_store(:file_store, Dir.pwd) + def test_array_as_cache_key + @cache.write([:fu, "foo"], "bar") + assert_equal "bar", @cache.read("fu/foo") end - def teardown - File.delete("foo.cache") + def test_hash_as_cache_key + @cache.write({:foo => 1, :fu => 2}, "bar") + assert_equal "bar", @cache.read("foo=1/fu=2") end - include CacheStoreBehavior - - def test_expires_in - time = Time.local(2008, 4, 24) - Time.stubs(:now).returns(time) - File.stubs(:mtime).returns(time) + def test_keys_are_case_sensitive + @cache.write("foo", "bar") + assert_nil @cache.read("FOO") + end + def test_exist @cache.write('foo', 'bar') - cache_read = lambda { @cache.read('foo', :expires_in => 60) } - assert_equal 'bar', cache_read.call - - Time.stubs(:now).returns(time + 30) - assert_equal 'bar', cache_read.call - - Time.stubs(:now).returns(time + 120) - assert_nil cache_read.call + assert_equal true, @cache.exist?('foo') + assert_equal false, @cache.exist?('bar') end -end -class MemoryStoreTest < ActiveSupport::TestCase - def setup - @cache = ActiveSupport::Cache.lookup_store(:memory_store) + def test_nil_exist + @cache.write('foo', nil) + assert_equal true, @cache.exist?('foo') end - include CacheStoreBehavior + def test_delete + @cache.write('foo', 'bar') + assert @cache.exist?('foo') + assert_equal true, @cache.delete('foo') + assert !@cache.exist?('foo') + end def test_store_objects_should_be_immutable @cache.write('foo', 'bar') @@ -186,175 +234,365 @@ class MemoryStoreTest < ActiveSupport::TestCase assert_nothing_raised { bar.gsub!(/.*/, 'baz') } end - def test_multi_get - @cache.write('foo', 1) - @cache.write('goo', 2) - result = @cache.read_multi('foo', 'goo') - assert_equal({'foo' => 1, 'goo' => 2}, result) + 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') end -end -uses_memcached 'memcached backed store' do - class MemCacheStoreTest < ActiveSupport::TestCase - def setup - @cache = ActiveSupport::Cache.lookup_store(:mem_cache_store) - @data = @cache.instance_variable_get(:@data) - @cache.clear - @cache.silence! - @cache.logger = Logger.new("/dev/null") + 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" end + assert_equal "baz", result + end - include CacheStoreBehavior + 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 - def test_store_objects_should_be_immutable - @cache.with_local_cache do - @cache.write('foo', 'bar') - @cache.read('foo').gsub!(/.*/, 'baz') + 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 assert_equal 'bar', @cache.read('foo') + raise ArgumentError.new end + rescue ArgumentError => e end + 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 = "#/:*(<+=> )&$%@?;'\"\'`~-" + assert_equal true, @cache.write(crazy_key, "1", :raw => true) + assert_equal "1", @cache.read(crazy_key) + assert_equal "1", @cache.fetch(crazy_key) + assert_equal true, @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 = "" + 1000.times{key << "x"} + assert_equal true, @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_equal true, @cache.delete(key) + end +end - def test_stored_objects_should_not_be_frozen - @cache.with_local_cache do - @cache.write('foo', 'bar') - end - @cache.with_local_cache do - assert !@cache.read('foo').frozen? - end +module CacheDeleteMatchedBehavior + def test_delete_matched + @cache.write("foo", "bar") + @cache.write("fu", "baz") + @cache.delete_matched(/oo/) + assert_equal false, @cache.exist?("foo") + assert_equal true, @cache.exist?("fu") + 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') end + assert_equal true, retval + assert_equal 'bar', @cache.read('foo') + end - def test_write_should_return_true_on_success - @cache.with_local_cache do - result = @cache.write('foo', 'bar') - assert_equal 'bar', @cache.read('foo') # make sure 'foo' was written - assert result - 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 - def test_local_writes_are_persistent_on_the_remote_cache - @cache.with_local_cache do - @cache.write('foo', 'bar') - 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_clear_also_clears_local_cache - @cache.with_local_cache do - @cache.write('foo', 'bar') - @cache.clear - assert_nil @cache.read('foo') - 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_and_write - @cache.with_local_cache do - @cache.write('foo', 'bar') - @data.flush_all # Clear remote cache - assert_equal 'bar', @cache.read('foo') - end + def test_local_cache_of_write_nil + @cache.with_local_cache do + assert true, @cache.write('foo', nil) + assert_nil @cache.read('foo') + @peek.write('foo', 'bar') + assert_nil @cache.read('foo') end + end - def test_local_cache_should_read_and_write_integer - @cache.with_local_cache do - @cache.write('foo', 1) - assert_equal 1, @cache.read('foo') - 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_delete - @cache.with_local_cache do - @cache.write('foo', 'bar') - @cache.delete('foo') - @data.flush_all # Clear remote cache - assert_nil @cache.read('foo') - end + def test_local_cache_of_exist + @cache.with_local_cache do + @cache.write('foo', 'bar') + @peek.delete('foo') + assert true, @cache.exist?('foo') end + end - def test_local_cache_of_exist - @cache.with_local_cache do - @cache.write('foo', 'bar') - @cache.instance_variable_set(:@data, nil) - @data.flush_all # Clear remote cache - assert @cache.exist?('foo') - 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_increment - @cache.with_local_cache do - @cache.write('foo', 1, :raw => true) - @cache.increment('foo') - @data.flush_all # Clear remote cache - assert_equal 2, @cache.read('foo', :raw => true).to_i - 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_local_cache_of_decrement - @cache.with_local_cache do - @cache.write('foo', 1, :raw => true) - @cache.decrement('foo') - @data.flush_all # Clear remote cache - assert_equal 0, @cache.read('foo', :raw => true).to_i - 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 + } + app = @cache.middleware.new(app) + app.call({}) + end +end - def test_exist_with_nulls_cached_locally - @cache.with_local_cache do - @cache.write('foo', 'bar') - @cache.delete('foo') - assert !@cache.exist?('foo') - end +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) + 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 + + def test_deprecated_expires_in_on_read + ActiveSupport::Deprecation.silence do + old_cache = ActiveSupport::Cache.lookup_store(:file_store, cache_dir) + + time = Time.local(2008, 4, 24) + Time.stubs(:now).returns(time) + + old_cache.write("foo", "bar") + assert_equal 'bar', old_cache.read('foo', :expires_in => 60) + + Time.stubs(:now).returns(time + 30) + assert_equal 'bar', old_cache.read('foo', :expires_in => 60) + + Time.stubs(:now).returns(time + 61) + assert_equal 'bar', old_cache.read('foo') + assert_nil old_cache.read('foo', :expires_in => 60) + assert_nil old_cache.read('foo') end + end +end - def test_multi_get - @cache.with_local_cache do - @cache.write('foo', 1) - @cache.write('goo', 2) - result = @cache.read_multi('foo', 'goo') - assert_equal({'foo' => 1, 'goo' => 2}, result) - end +class MemoryStoreTest < ActiveSupport::TestCase + def setup + @cache = ActiveSupport::Cache.lookup_store(:memory_store, :expires_in => 60, :size => 100) + 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) + @cache.prune(30) + assert_equal true, @cache.exist?(5) + assert_equal true, @cache.exist?(4) + assert_equal false, @cache.exist?(3) + assert_equal true, @cache.exist?(2) + assert_equal false, @cache.exist?(1) + 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_equal true, @cache.exist?(11) + assert_equal true, @cache.exist?(10) + assert_equal true, @cache.exist?(9) + assert_equal true, @cache.exist?(8) + assert_equal true, @cache.exist?(7) + assert_equal false, @cache.exist?(6) + assert_equal false, @cache.exist?(5) + assert_equal true, @cache.exist?(4) + assert_equal false, @cache.exist?(3) + assert_equal true, @cache.exist?(2) + assert_equal false, @cache.exist?(1) + 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_equal true, @cache.exist?(5) + assert_equal true, @cache.exist?(4) + assert_equal true, @cache.exist?(3) + assert_equal true, @cache.exist?(2) + assert_equal false, @cache.exist?(1) + 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 - } - app = @cache.middleware.new(app) - app.call({}) +class SynchronizedStoreTest < ActiveSupport::TestCase + def setup + ActiveSupport::Deprecation.silence do + @cache = ActiveSupport::Cache.lookup_store(:memory_store, :expires_in => 60) end + end - def test_expires_in - result = @cache.write('foo', 'bar', :expires_in => 1) - assert_equal 'bar', @cache.read('foo') - sleep 2 - assert_equal nil, @cache.read('foo') + include CacheStoreBehavior + include CacheDeleteMatchedBehavior + include CacheIncrementDecrementBehavior +end + +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! + @cache.logger = Logger.new("/dev/null") end - def test_expires_in_with_invalid_value - @cache.write('baz', 'bat') - assert_raise(RuntimeError) do - @cache.write('foo', 'bar', :expires_in => 'Mon Jun 29 13:10:40 -0700 2150') - end - assert_equal 'bat', @cache.read('baz') - assert_equal nil, @cache.read('foo') + include CacheStoreBehavior + include LocalCacheBehavior + include CacheIncrementDecrementBehavior + + 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_delete_should_only_pass_key_to_data - key = 'foo' - @data.expects(:delete).with(key) - @cache.delete(key) + 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 end class CompressedMemCacheStore < ActiveSupport::TestCase def setup - @cache = ActiveSupport::Cache.lookup_store(:compressed_mem_cache_store) - @cache.clear + ActiveSupport::Deprecation.silence do + @cache = ActiveSupport::Cache.lookup_store(:compressed_mem_cache_store, :expires_in => 60) + @cache.clear + end end include CacheStoreBehavior + include CacheIncrementDecrementBehavior end end @@ -376,3 +614,38 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase assert @buffer.string.blank? end end + +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 + assert_equal false, entry.compressed? + assert_equal 300, entry.expires_in + end + + def test_expired + entry = ActiveSupport::Cache::Entry.new("value") + assert_equal false, entry.expired? + entry = ActiveSupport::Cache::Entry.new("value", :expires_in => 60) + assert_equal false, entry.expired? + time = Time.now + 61 + Time.stubs(:now).returns(time) + assert_equal true, entry.expired? + end + + def test_compress_values + entry = ActiveSupport::Cache::Entry.new("value", :compress => true, :compress_threshold => 1) + assert_equal "value", entry.value + assert_equal true, entry.compressed? + 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 + assert_equal "value", entry.raw_value + assert_equal false, entry.compressed? + end +end diff --git a/activesupport/test/configurable_test.rb b/activesupport/test/configurable_test.rb new file mode 100644 index 0000000000..cef67e3cf9 --- /dev/null +++ b/activesupport/test/configurable_test.rb @@ -0,0 +1,42 @@ +require 'abstract_unit' +require 'active_support/configurable' + +class ConfigurableActiveSupport < ActiveSupport::TestCase + class Parent + include ActiveSupport::Configurable + config_accessor :foo + end + + class Child < Parent + end + + setup do + Parent.config.clear + Parent.config.foo = :bar + + Child.config.clear + end + + test "adds a configuration hash" do + assert_equal({ :foo => :bar }, Parent.config) + end + + test "configuration hash is inheritable" do + assert_equal :bar, Child.config.foo + assert_equal :bar, Parent.config.foo + + Child.config.foo = :baz + assert_equal :baz, Child.config.foo + assert_equal :bar, Parent.config.foo + end + + test "configuration hash is available on instance" do + instance = Parent.new + assert_equal :bar, instance.config.foo + assert_equal :bar, Parent.config.foo + + instance.config.foo = :baz + assert_equal :baz, instance.config.foo + assert_equal :bar, Parent.config.foo + end +end
\ No newline at end of file diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 86272a28c1..b2a9731578 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -60,6 +60,43 @@ class HashExtTest < Test::Unit::TestCase assert_equal @strings, @mixed.dup.stringify_keys! end + def test_symbolize_keys_for_hash_with_indifferent_access + assert_instance_of Hash, @symbols.with_indifferent_access.symbolize_keys + assert_equal @symbols, @symbols.with_indifferent_access.symbolize_keys + assert_equal @symbols, @strings.with_indifferent_access.symbolize_keys + assert_equal @symbols, @mixed.with_indifferent_access.symbolize_keys + end + + def test_symbolize_keys_bang_for_hash_with_indifferent_access + assert_raise(NoMethodError) { @symbols.with_indifferent_access.dup.symbolize_keys! } + assert_raise(NoMethodError) { @strings.with_indifferent_access.dup.symbolize_keys! } + assert_raise(NoMethodError) { @mixed.with_indifferent_access.dup.symbolize_keys! } + end + + def test_symbolize_keys_preserves_keys_that_cant_be_symbolized_for_hash_with_indifferent_access + assert_equal @illegal_symbols, @illegal_symbols.with_indifferent_access.symbolize_keys + assert_raise(NoMethodError) { @illegal_symbols.with_indifferent_access.dup.symbolize_keys! } + end + + def test_symbolize_keys_preserves_fixnum_keys_for_hash_with_indifferent_access + assert_equal @fixnums, @fixnums.with_indifferent_access.symbolize_keys + assert_raise(NoMethodError) { @fixnums.with_indifferent_access.dup.symbolize_keys! } + end + + def test_stringify_keys_for_hash_with_indifferent_access + assert_instance_of ActiveSupport::HashWithIndifferentAccess, @symbols.with_indifferent_access.stringify_keys + assert_equal @strings, @symbols.with_indifferent_access.stringify_keys + assert_equal @strings, @strings.with_indifferent_access.stringify_keys + assert_equal @strings, @mixed.with_indifferent_access.stringify_keys + end + + def test_stringify_keys_bang_for_hash_with_indifferent_access + assert_instance_of ActiveSupport::HashWithIndifferentAccess, @symbols.with_indifferent_access.dup.stringify_keys! + assert_equal @strings, @symbols.with_indifferent_access.dup.stringify_keys! + assert_equal @strings, @strings.with_indifferent_access.dup.stringify_keys! + assert_equal @strings, @mixed.with_indifferent_access.dup.stringify_keys! + end + def test_indifferent_assorted @strings = @strings.with_indifferent_access @symbols = @symbols.with_indifferent_access @@ -213,11 +250,11 @@ class HashExtTest < Test::Unit::TestCase def test_stringify_and_symbolize_keys_on_indifferent_preserves_hash h = HashWithIndifferentAccess.new h[:first] = 1 - h.stringify_keys! + h = h.stringify_keys assert_equal 1, h['first'] h = HashWithIndifferentAccess.new h['first'] = 1 - h.symbolize_keys! + h = h.symbolize_keys assert_equal 1, h[:first] end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 58ca215970..97b08da0e4 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -117,17 +117,20 @@ class StringInflectionsTest < Test::Unit::TestCase assert_equal Time.local(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time(:local) assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time assert_equal Time.local_time(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time(:local) + assert_equal nil, "".to_time end - + def test_string_to_datetime assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_datetime assert_equal 0, "2039-02-27 23:50".to_datetime.offset # use UTC offset assert_equal ::Date::ITALY, "2039-02-27 23:50".to_datetime.start # use Ruby's default start value assert_equal DateTime.civil(2039, 2, 27, 23, 50, 19 + Rational(275038, 1000000), "-04:00"), "2039-02-27T23:50:19.275038-04:00".to_datetime + assert_equal nil, "".to_datetime end - + def test_string_to_date assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date + assert_equal nil, "".to_date end def test_access @@ -255,7 +258,7 @@ end string.rb - Interpolation for String. Copyright (C) 2005-2009 Masao Mutoh - + You may redistribute it and/or modify it under the same license terms as Ruby. =end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index d88f79ae4f..a808a25821 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -823,9 +823,12 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase assert_equal(-18_000, Time.zone.utc_offset) end - def test_time_zone_setter_with_non_identifying_argument_returns_nil + def test_time_zone_setter_with_invalid_zone Time.zone = 'foo' - assert_equal nil, Time.zone + assert_not_nil Time.zone + assert_equal 'foo', Time.zone.name + assert_raise(TZInfo::InvalidTimezoneIdentifier) { Time.zone.utc_offset } + Time.zone = -15.hours assert_equal nil, Time.zone end diff --git a/activesupport/test/core_ext/uri_ext_test.rb b/activesupport/test/core_ext/uri_ext_test.rb index e4a242abc4..d988837603 100644 --- a/activesupport/test/core_ext/uri_ext_test.rb +++ b/activesupport/test/core_ext/uri_ext_test.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require 'abstract_unit' require 'uri' require 'active_support/core_ext/uri' @@ -5,7 +6,6 @@ require 'active_support/core_ext/uri' class URIExtTest < Test::Unit::TestCase def test_uri_decode_handle_multibyte str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese. - str.force_encoding(Encoding::UTF_8) if str.respond_to?(:force_encoding) if URI.const_defined?(:Parser) parser = URI::Parser.new diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 188b799f3f..ac7ca96c4d 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -9,6 +9,12 @@ class TestJSONEncoding < Test::Unit::TestCase end end + class Hashlike + def to_hash + { :a => 1 } + end + end + class Custom def as_json(options) 'custom' @@ -19,7 +25,8 @@ class TestJSONEncoding < Test::Unit::TestCase FalseTests = [[ false, %(false) ]] NilTests = [[ nil, %(null) ]] NumericTests = [[ 1, %(1) ], - [ 2.5, %(2.5) ]] + [ 2.5, %(2.5) ], + [ BigDecimal('2.5'), %("#{BigDecimal('2.5').to_s('F')}") ]] StringTests = [[ 'this is the <string>', %("this is the \\u003Cstring\\u003E")], [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ], @@ -35,11 +42,12 @@ class TestJSONEncoding < Test::Unit::TestCase [ :"a b", %("a b") ]] ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]] + HashlikeTests = [[ Hashlike.new, %({\"a\":1}) ]] CustomTests = [[ Custom.new, '"custom"' ]] VariableTests = [[ ActiveSupport::JSON::Variable.new('foo'), 'foo'], [ ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")']] - RegexpTests = [[ /^a/, '/^a/' ], [/^\w{1,2}[a-z]+/ix, '/^\\w{1,2}[a-z]+/ix']] + RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']] DateTests = [[ Date.new(2005,2,1), %("2005/02/01") ]] TimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]] @@ -91,6 +99,15 @@ class TestJSONEncoding < Test::Unit::TestCase end end + if '1.9'.respond_to?(:force_encoding) + def test_non_utf8_string_transcodes + s = '二'.encode('Shift_JIS') + result = ActiveSupport::JSON.encode(s) + assert_equal '"\\u4e8c"', result + assert_equal Encoding::UTF_8, result.encoding + end + end + def test_exception_raised_when_encoding_circular_reference a = [1] a << a @@ -109,7 +126,7 @@ class TestJSONEncoding < Test::Unit::TestCase def test_hash_should_allow_key_filtering_with_except assert_equal %({"b":2}), ActiveSupport::JSON.encode({'foo' => 'bar', :b => 2, :c => 3}, :except => ['foo', :c]) end - + def test_time_to_json_includes_local_offset ActiveSupport.use_standard_json_time_format = true with_env_tz 'US/Eastern' do @@ -136,7 +153,7 @@ class TestJSONEncoding < Test::Unit::TestCase def object_keys(json_object) json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort end - + def with_env_tz(new_tz = 'US/Eastern') old_tz, ENV['TZ'] = ENV['TZ'], new_tz yield diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 1b8d13c024..caf50aa1c9 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -105,7 +105,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase @whitespace = "\n\t#{[32, 8195].pack('U*')}" else # Ruby 1.9 only supports basic whitespace - @whitespace = "\n\t ".force_encoding(Encoding::UTF_8) + @whitespace = "\n\t " end @byte_order_mark = [65279].pack('U') diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 92fbe5b92f..c2e1c588f0 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -6,7 +6,9 @@ module Notifications ActiveSupport::Notifications.notifier = nil @notifier = ActiveSupport::Notifications.notifier @events = [] + @named_events = [] @subscription = @notifier.subscribe { |*args| @events << event(*args) } + @named_subscription = @notifier.subscribe("named.subscription") { |*args| @named_events << event(*args) } end private @@ -30,6 +32,26 @@ module Notifications assert_equal [[:foo]], @events end + def test_unsubscribing_by_name_removes_a_subscription + @notifier.publish "named.subscription", :foo + @notifier.wait + assert_equal [["named.subscription", :foo]], @named_events + @notifier.unsubscribe("named.subscription") + @notifier.publish "named.subscription", :foo + @notifier.wait + assert_equal [["named.subscription", :foo]], @named_events + end + + def test_unsubscribing_by_name_leaves_the_other_subscriptions + @notifier.publish "named.subscription", :foo + @notifier.wait + assert_equal [["named.subscription", :foo]], @events + @notifier.unsubscribe("named.subscription") + @notifier.publish "named.subscription", :foo + @notifier.wait + assert_equal [["named.subscription", :foo], ["named.subscription", :foo]], @events + end + private def event(*args) args diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 3b7fbb7808..516da7a14c 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -268,16 +268,16 @@ class TimeZoneTest < Test::Unit::TestCase end def test_index - assert_nil ActiveSupport::TimeZone["bogus"] + assert_not_nil ActiveSupport::TimeZone["bogus"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[8] assert_raise(ArgumentError) { ActiveSupport::TimeZone[false] } end - def test_unknown_zone_shouldnt_have_tzinfo_nor_utc_offset + def test_unknown_zone_should_have_tzinfo_but_exception_on_utc_offset zone = ActiveSupport::TimeZone.create("bogus") - assert_nil zone.tzinfo - assert_nil zone.utc_offset + assert_instance_of TZInfo::TimezoneProxy, zone.tzinfo + assert_raise(TZInfo::InvalidTimezoneIdentifier) { zone.utc_offset } end def test_unknown_zone_with_utc_offset |