1 require File.dirname(__FILE__) + '/../test_helper'
3 class ResponseCacheTest < Test::Unit::TestCase
5 def method_missing(*args); end
8 class TestResponse < ActionController::TestResponse
9 def initialize(body = '', headers = {})
11 self.headers = headers
16 @dir = File.expand_path("#{RAILS_ROOT}/test/cache")
17 @baddir = File.expand_path("#{RAILS_ROOT}/test/badcache")
18 FileUtils.rm_rf @baddir
19 @old_perform_caching = ResponseCache.defaults[:perform_caching]
20 ResponseCache.defaults[:perform_caching] = true
21 @cache = ResponseCache.new(
23 :perform_caching => true
29 ResponseCache.defaults[:perform_caching] = @old_preform_caching
30 FileUtils.rm_rf @dir if File.exists? @dir
33 def test_initialize_defaults
34 @cache = ResponseCache.new
35 assert_equal "#{RAILS_ROOT}/cache", @cache.directory
36 assert_equal 5.minutes, @cache.expire_time
37 assert_equal '.yml', @cache.default_extension
38 assert_equal true, @cache.perform_caching
39 assert_kind_of ActiveSupport::BufferedLogger, @cache.logger
42 def test_initialize_with_options
43 @cache = ResponseCache.new(
46 :default_extension => ".xhtml",
47 :perform_caching => false,
48 :logger => SilentLogger.new
50 assert_equal "test", @cache.directory
51 assert_equal 5, @cache.expire_time
52 assert_equal ".xhtml", @cache.default_extension
53 assert_equal false, @cache.perform_caching
54 assert_kind_of SilentLogger, @cache.logger
57 def test_cache_response
58 ['test/me', '/test/me', 'test/me/', '/test/me/', 'test//me'].each do |url|
60 response = response('content', 'Last-Modified' => 'Tue, 27 Feb 2007 06:13:43 GMT')
61 response.cache_timeout = Time.gm(2007, 2, 8, 17, 37, 9)
62 @cache.cache_response(url, response)
63 name = "#{@dir}/test/me.yml"
64 assert File.exists?(name), "url: #{url}"
65 assert_equal "--- \nexpires: 2007-02-08 17:37:09 Z\nheaders: \n Last-Modified: Tue, 27 Feb 2007 06:13:43 GMT\n", file(name), "url: #{url}"
66 data_name = "#{@dir}/test/me.data"
67 assert_equal "content", file(data_name), "url: #{url}"
71 def test_cache_response_with_extension
72 @cache.cache_response("styles.css", response('content'))
73 assert File.exists?("#{@dir}/styles.css.yml")
76 def test_cache_response_without_caching
77 @cache.perform_caching = false
78 @cache.cache_response('test', response('content'))
79 assert !File.exists?("#{@dir}/test.yml")
82 def test_update_response
83 @cache.cache_response('/test/me', response('content'))
84 ['test/me', '/test/me', 'test/me/', '/test/me/', 'test//me'].each do |url|
85 assert_equal 'content', @cache.update_response(url, response, ActionController::TestRequest).body, "url: #{url}"
89 def test_update_response_nonexistant
90 assert_equal '', @cache.update_response('nothing/here', response, ActionController::TestRequest).body
93 def test_update_response_without_caching
94 @cache.cache_response('/test/me', response('content'))
95 @cache.perform_caching = false
96 assert_equal '', @cache.update_response('/test/me', response, ActionController::TestRequest).body
100 result = @cache.cache_response('test', response('content', 'Content-Type' => 'text/plain'))
101 cached = @cache.update_response('test', response, ActionController::TestRequest)
102 assert_equal 'content', cached.body
103 assert_equal 'text/plain', cached.headers['Content-Type']
104 assert_kind_of TestResponse, result
107 def test_expire_response
108 @cache.cache_response('test', response('content'))
109 @cache.expire_response('test')
110 assert_equal '', @cache.update_response('test', response, ActionController::TestRequest).body
114 @cache.cache_response('test1', response('content'))
115 @cache.cache_response('test2', response('content'))
116 assert_equal 4, Dir["#{@dir}/*"].size
119 assert_equal 0, Dir["#{@dir}/*"].size
122 def test_response_cached
123 assert_equal false, @cache.response_cached?('test')
124 result = @cache.cache_response('test', response('content'))
125 assert_equal true, @cache.response_cached?('test')
128 def test_response_cached_timed_out
129 @cache.expire_time = 1
130 result = @cache.cache_response('test', response('content'))
132 assert_equal false, @cache.response_cached?('test')
135 def test_response_cached_timed_out_with_response_setting
136 @cache.expire_time = 1
137 response = response('content')
138 response.cache_timeout = 3.seconds
139 result = @cache.cache_response('test', response)
141 assert_equal true, @cache.response_cached?('test')
143 assert_equal false, @cache.response_cached?('test')
146 def test_send_using_x_sendfile
147 @cache.use_x_sendfile = true
148 result = @cache.cache_response('test', response('content', 'Content-Type' => 'text/plain'))
149 cached = @cache.update_response('test', response, ActionController::TestRequest)
150 assert_equal '', cached.body
151 assert_equal "#{@dir}/test.data", cached.headers['X-Sendfile']
152 assert_equal 'text/plain', cached.headers['Content-Type']
153 assert_kind_of TestResponse, result
156 def test_send_cached_page_with_last_modified
157 last_modified = Time.now.httpdate
158 result = @cache.cache_response('test', response('content', 'Last-Modified' => last_modified))
159 request = ActionController::TestRequest.new
160 request.env = { 'HTTP_IF_MODIFIED_SINCE' => last_modified }
161 second_call = @cache.update_response('test', response, request)
162 assert_match /^304/, second_call.headers['Status']
163 assert_equal '', second_call.body
164 assert_kind_of TestResponse, result
167 def test_send_cached_page_with_old_last_modified
168 last_modified = Time.now.httpdate
169 result = @cache.cache_response('test', response('content', 'Last-Modified' => last_modified))
170 request = ActionController::TestRequest.new
171 request.env = { 'HTTP_IF_MODIFIED_SINCE' => 5.minutes.ago.httpdate }
172 second_call = @cache.update_response('test', response, request)
173 assert_equal 'content', second_call.body
174 assert_kind_of TestResponse, result
177 def test_not_cached_if_metadata_empty
178 FileUtils.makedirs(@dir)
179 File.open("#{@dir}/test_me.yml", 'w') { }
180 assert !@cache.response_cached?('/test_me')
183 def test_not_cached_if_metadata_broken
184 FileUtils.makedirs(@dir)
185 File.open("#{@dir}/test_me.yml", 'w') {|f| f.puts '::: bad yaml file:::' }
186 assert !@cache.response_cached?('/test_me')
189 def test_not_cached_if_metadata_not_hash
190 FileUtils.makedirs(@dir)
191 File.open("#{@dir}/test_me.yml", 'w') {|f| f.puts ':symbol' }
192 assert !@cache.response_cached?('/test_me')
195 def test_not_cached_if_metadata_has_no_expire
196 FileUtils.makedirs(@dir)
197 File.open("#{@dir}/test_me.yml", 'w') {|f| f.puts "--- \nheaders: \n Last-Modified: Tue, 27 Feb 2007 06:13:43 GMT\n"}
198 assert !@cache.response_cached?('/test_me')
201 def test_cache_cant_write_outside_dir
202 @cache.cache_response('../badcache/cache_cant_write_outside_dir', response('content'))
203 assert !File.exist?("#{RAILS_ROOT}/test/badcache/cache_cant_write_outside_dir.yml")
206 def test_cache_cant_read_outside_dir
207 FileUtils.makedirs(@baddir)
208 @cache.cache_response('/test_me', response('content'))
209 File.rename "#{@dir}/test_me.yml", "#{@baddir}/test_me.yml"
210 File.rename "#{@dir}/test_me.data", "#{@baddir}/test_me.data"
211 assert !@cache.response_cached?('/../badcache/test_me')
214 def test_cache_cant_expire_outside_dir
215 FileUtils.makedirs(@baddir)
216 @cache.cache_response('/test_me', response('content'))
217 File.rename "#{@dir}/test_me.yml", "#{@baddir}/test_me.yml"
218 File.rename "#{@dir}/test_me.data", "#{@baddir}/test_me.data"
219 @cache.expire_response('/../badcache/test_me')
220 assert File.exist?("#{@baddir}/test_me.yml")
221 assert File.exist?("#{@baddir}/test_me.data")
224 def test_cache_file_gets_renamed_to_index
225 @cache.cache_response('/', response('content'))
226 assert @cache.response_cached?('_site-root')
227 assert @cache.response_cached?('/')
228 assert !File.exist?("#{@dir}/../cache.yml")
229 assert !File.exist?("#{@dir}/../cache.data")
235 assert_same ResponseCache.instance, ResponseCache.instance
241 open(filename) { |f| f.read } rescue ''
245 TestResponse.new(*args)