rack-cache 1.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rack-cache might be problematic. Click here for more details.

data/CHANGES CHANGED
@@ -1,3 +1,22 @@
1
+ ## 1.0.1 / April 2011
2
+
3
+ * Added lib/rack-cache.rb to match package name for auto-requiring machinery.
4
+
5
+ * Fixed a number of issues caused by Rack::Cache not closing the body received
6
+ from the application. Rack::Lock and other middleware use body.close to
7
+ signal the true end of request processing so failure to call this method
8
+ can result in strange issues (e.g.,
9
+ "ThreadError: deadlock; recursive locking")
10
+
11
+ * Fixed a bug where Rack::Cache would blow up writing the rack env to the meta
12
+ store when the env contained an all uppercase key whose value wasn't
13
+ marshalable. Passenger and some other stuff write such keys apparently.
14
+
15
+ * The test suite has moved from test-spec to bacon. This is a short term
16
+ solution to the problem of not being able to run tests under Ruby 1.9.x.
17
+ The test suite will be moved to basic Test::Unit style sometime in the
18
+ future.
19
+
1
20
  ## 1.0 / December 2010
2
21
 
3
22
  * Rack::Cache is 1.0 and will now maintain semantic versioning <http://semver.org/>
data/Rakefile CHANGED
@@ -7,20 +7,21 @@ CLOBBER.include %w[dist]
7
7
 
8
8
  # SPECS =====================================================================
9
9
 
10
- desc 'Run specs with story style output'
11
- task :spec do
12
- sh 'specrb --specdox -Ilib:test test/*_test.rb'
13
- end
14
-
15
10
  desc 'Run specs with unit test style output'
16
11
  task :test => FileList['test/*_test.rb'] do |t|
17
12
  suite = t.prerequisites
18
- sh "specrb -Ilib:test #{suite.join(' ')}", :verbose => false
13
+ sh "bacon -q -I.:lib:test #{suite.join(' ')}", :verbose => false
14
+ end
15
+
16
+ desc 'Run specs with story style output'
17
+ task :spec => FileList['test/*_test.rb'] do |t|
18
+ suite = t.prerequisites
19
+ sh "bacon -I.:lib:test #{suite.join(' ')}", :verbose => false
19
20
  end
20
21
 
21
22
  desc 'Generate test coverage report'
22
23
  task :rcov do
23
- sh "rcov -Ilib:test test/*_test.rb"
24
+ sh "rcov -I.:lib:test test/*_test.rb"
24
25
  end
25
26
 
26
27
  # DOC =======================================================================
data/doc/index.markdown CHANGED
@@ -12,8 +12,8 @@ for [Rack][]-based applications that produce freshness (`Expires`,
12
12
  News
13
13
  ----
14
14
 
15
- * Rack::Cache 0.5 was released on May 25, 2009. See the
16
- [`CHANGES`](http://github.com/rtomayko/rack-cache/blob/0.5.0/CHANGES) file
15
+ * Rack::Cache 1.0 was released on December 24, 2010. See the
16
+ [`CHANGES`](http://github.com/rtomayko/rack-cache/blob/1.0/CHANGES) file
17
17
  for details.
18
18
  * [How to use Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1) - it's really easy.
19
19
  * [RailsLab's Advanced HTTP Caching Screencast](http://railslab.newrelic.com/2009/02/26/episode-11-advanced-http-caching)
data/doc/storage.markdown CHANGED
@@ -141,11 +141,11 @@ The URI must specify the host and port of a remote memcached daemon. The path
141
141
  portion is an optional (but recommended) namespace that is prepended to each
142
142
  cache key.
143
143
 
144
- The memcached storage backend requires either the `memcache-client` or
145
- `memcached` libraries. By default, the `memcache-client` library is used;
146
- require the `memcached` library explicitly to use it instead.
144
+ The memcached storage backend requires either the `dalli` or `memcached`
145
+ libraries. By default, the `dalli` library is used; require the `memcached`
146
+ library explicitly to use it instead.
147
147
 
148
- gem install memcache-client
148
+ gem install dalli
149
149
 
150
150
  Memcached storage is reasonably fast and allows multiple backends to share a
151
151
  single cache. It is also the only storage implementation that allows the cache
data/lib/rack-cache.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rack/cache'
@@ -83,7 +83,10 @@ module Rack::Cache
83
83
 
84
84
  # tidy up response a bit
85
85
  response.not_modified! if not_modified?(response)
86
- response.body = [] if @request.head?
86
+ if @request.head?
87
+ response.body.close if response.body.respond_to?(:close)
88
+ response.body = []
89
+ end
87
90
  response.to_a
88
91
  end
89
92
 
@@ -212,6 +215,11 @@ module Rack::Cache
212
215
  next unless value = response.headers[name]
213
216
  entry.headers[name] = value
214
217
  end
218
+
219
+ # even though it's empty, be sure to close the response body from upstream
220
+ # because middleware use close to signal end of response
221
+ response.body.close if response.body.respond_to?(:close)
222
+
215
223
  response = entry
216
224
  else
217
225
  record :invalid
@@ -222,7 +222,9 @@ module Rack::Cache
222
222
  end
223
223
 
224
224
  def read(key)
225
- cache.get(key)
225
+ data = cache.get(key)
226
+ data.force_encoding('BINARY') if data.respond_to?(:force_encoding)
227
+ data
226
228
  end
227
229
 
228
230
  def write(body)
@@ -1,6 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'digest/sha1'
3
3
  require 'rack/utils'
4
+ require 'rack/cache/key'
4
5
 
5
6
  module Rack::Cache
6
7
 
@@ -110,7 +111,7 @@ module Rack::Cache
110
111
  # returned must be marshalable.
111
112
  def persist_request(request)
112
113
  env = request.env.dup
113
- env.reject! { |key,val| key =~ /[^0-9A-Z_]/ }
114
+ env.reject! { |key,val| key =~ /[^0-9A-Z_]/ || !val.respond_to?(:to_str) }
114
115
  env
115
116
  end
116
117
 
@@ -227,6 +227,7 @@ module Rack::Cache
227
227
  #
228
228
  # http://tools.ietf.org/html/rfc2616#section-10.3.5
229
229
  def not_modified!
230
+ body.close if body.respond_to?(:close)
230
231
  self.status = 304
231
232
  self.body = []
232
233
  NOT_MODIFIED_OMIT_HEADERS.each { |name| headers.delete(name) }
data/rack-cache.gemspec CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'rack-cache'
6
- s.version = '1.0'
7
- s.date = '2010-12-24'
6
+ s.version = '1.0.1'
7
+ s.date = '2011-04-13'
8
8
 
9
9
  s.description = "HTTP Caching for Rack"
10
10
  s.summary = "HTTP Caching for Rack"
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
29
29
  doc/storage.markdown
30
30
  example/sinatra/app.rb
31
31
  example/sinatra/views/index.erb
32
+ lib/rack-cache.rb
32
33
  lib/rack/cache.rb
33
34
  lib/rack/cache/appengine.rb
34
35
  lib/rack/cache/cachecontrol.rb
@@ -61,7 +62,7 @@ Gem::Specification.new do |s|
61
62
  s.extra_rdoc_files = %w[README COPYING TODO CHANGES]
62
63
  s.add_dependency 'rack', '>= 0.4'
63
64
 
64
- s.add_development_dependency 'test-spec'
65
+ s.add_development_dependency 'bacon'
65
66
  s.add_development_dependency 'memcached'
66
67
  s.add_development_dependency 'dalli'
67
68
 
data/test/cache_test.rb CHANGED
@@ -25,7 +25,7 @@ describe 'Rack::Cache::new' do
25
25
  end
26
26
 
27
27
  it 'takes a block; executes it during initialization' do
28
- state, object = 'not invoked', nil
28
+ state, object = 'not invoked', nil
29
29
  instance =
30
30
  Rack::Cache.new @app do |cache|
31
31
  object = cache
@@ -33,6 +33,6 @@ describe 'Rack::Cache::new' do
33
33
  cache.should.respond_to :set
34
34
  end
35
35
  state.should.equal 'invoked'
36
- object.should.be instance
36
+ object.should.be.same_as instance
37
37
  end
38
38
  end
@@ -11,7 +11,7 @@ describe 'Rack::Cache::CacheControl' do
11
11
  it 'takes a String and parses it into a Hash when created' do
12
12
  cache_control = Rack::Cache::CacheControl.new('max-age=600, foo')
13
13
  cache_control['max-age'].should.equal '600'
14
- cache_control['foo'].should.be true
14
+ cache_control['foo'].should.be.true
15
15
  end
16
16
 
17
17
  it 'takes a String with a single name=value pair' do
@@ -29,17 +29,17 @@ describe 'Rack::Cache::CacheControl' do
29
29
  it 'takes a String with a single flag value' do
30
30
  cache_control = Rack::Cache::CacheControl.new('no-cache')
31
31
  cache_control.should.include 'no-cache'
32
- cache_control['no-cache'].should.be true
32
+ cache_control['no-cache'].should.be.true
33
33
  end
34
34
 
35
35
  it 'takes a String with a bunch of all kinds of stuff' do
36
36
  cache_control =
37
37
  Rack::Cache::CacheControl.new('max-age=600,must-revalidate,min-fresh=3000,foo=bar,baz')
38
38
  cache_control['max-age'].should.equal '600'
39
- cache_control['must-revalidate'].should.be true
39
+ cache_control['must-revalidate'].should.be.true
40
40
  cache_control['min-fresh'].should.equal '3000'
41
41
  cache_control['foo'].should.equal 'bar'
42
- cache_control['baz'].should.be true
42
+ cache_control['baz'].should.be.true
43
43
  end
44
44
 
45
45
  it 'strips leading and trailing spaces from header value' do
@@ -80,7 +80,7 @@ describe 'Rack::Cache::CacheControl' do
80
80
 
81
81
  it 'responds to #max_age with nil when no max-age directive present' do
82
82
  cache_control = Rack::Cache::CacheControl.new('public')
83
- cache_control.max_age.should.be nil
83
+ cache_control.max_age.should.be.nil
84
84
  end
85
85
 
86
86
  it 'responds to #shared_max_age with an integer when s-maxage directive present' do
@@ -90,7 +90,7 @@ describe 'Rack::Cache::CacheControl' do
90
90
 
91
91
  it 'responds to #shared_max_age with nil when no s-maxage directive present' do
92
92
  cache_control = Rack::Cache::CacheControl.new('public')
93
- cache_control.shared_max_age.should.be nil
93
+ cache_control.shared_max_age.should.be.nil
94
94
  end
95
95
 
96
96
  it 'responds to #public? truthfully when public directive present' do
data/test/context_test.rb CHANGED
@@ -2,8 +2,8 @@ require "#{File.dirname(__FILE__)}/spec_setup"
2
2
  require 'rack/cache/context'
3
3
 
4
4
  describe 'Rack::Cache::Context' do
5
- before(:each) { setup_cache_context }
6
- after(:each) { teardown_cache_context }
5
+ before { setup_cache_context }
6
+ after { teardown_cache_context }
7
7
 
8
8
  it 'passes on non-GET/HEAD requests' do
9
9
  respond_with 200
@@ -771,7 +771,7 @@ describe 'Rack::Cache::Context' do
771
771
  end
772
772
 
773
773
  describe 'with responses that include a Vary header' do
774
- before(:each) do
774
+ before do
775
775
  count = 0
776
776
  respond_with 200 do |req,res|
777
777
  res['Vary'] = 'Accept User-Agent Foo'
@@ -8,8 +8,7 @@ class Object
8
8
  end
9
9
  end
10
10
 
11
- describe_shared 'A Rack::Cache::EntityStore Implementation' do
12
-
11
+ shared 'A Rack::Cache::EntityStore Implementation' do
13
12
  it 'responds to all required messages' do
14
13
  %w[read open write exist?].each do |message|
15
14
  @store.should.respond_to message
@@ -86,8 +85,8 @@ end
86
85
  describe 'Rack::Cache::EntityStore' do
87
86
 
88
87
  describe 'Heap' do
89
- it_should_behave_like 'A Rack::Cache::EntityStore Implementation'
90
88
  before { @store = Rack::Cache::EntityStore::Heap.new }
89
+ behaves_like 'A Rack::Cache::EntityStore Implementation'
91
90
  it 'takes a Hash to ::new' do
92
91
  @store = Rack::Cache::EntityStore::Heap.new('foo' => ['bar'])
93
92
  @store.read('foo').should.equal 'bar'
@@ -98,7 +97,6 @@ describe 'Rack::Cache::EntityStore' do
98
97
  end
99
98
 
100
99
  describe 'Disk' do
101
- it_should_behave_like 'A Rack::Cache::EntityStore Implementation'
102
100
  before do
103
101
  @temp_dir = create_temp_directory
104
102
  @store = Rack::Cache::EntityStore::Disk.new(@temp_dir)
@@ -107,6 +105,8 @@ describe 'Rack::Cache::EntityStore' do
107
105
  @store = nil
108
106
  remove_entry_secure @temp_dir
109
107
  end
108
+ behaves_like 'A Rack::Cache::EntityStore Implementation'
109
+
110
110
  it 'takes a path to ::new and creates the directory' do
111
111
  path = @temp_dir + '/foo'
112
112
  @store = Rack::Cache::EntityStore::Disk.new(path)
@@ -177,20 +177,19 @@ describe 'Rack::Cache::EntityStore' do
177
177
 
178
178
  need_memcached 'entity store tests' do
179
179
  describe 'MemCached' do
180
- it_should_behave_like 'A Rack::Cache::EntityStore Implementation'
181
180
  before do
182
181
  @store = Rack::Cache::EntityStore::MemCached.new($memcached)
183
182
  end
184
183
  after do
185
184
  @store = nil
186
185
  end
186
+ behaves_like 'A Rack::Cache::EntityStore Implementation'
187
187
  end
188
188
  end
189
189
 
190
190
 
191
191
  need_dalli 'entity store tests' do
192
192
  describe 'Dalli' do
193
- it_should_behave_like 'A Rack::Cache::EntityStore Implementation'
194
193
  before do
195
194
  $dalli.flush_all
196
195
  @store = Rack::Cache::EntityStore::Dalli.new($dalli)
@@ -198,26 +197,25 @@ describe 'Rack::Cache::EntityStore' do
198
197
  after do
199
198
  @store = nil
200
199
  end
200
+ behaves_like 'A Rack::Cache::EntityStore Implementation'
201
201
  end
202
202
  end
203
-
203
+
204
204
  need_java 'entity store testing' do
205
205
  module Rack::Cache::AppEngine
206
206
  module MC
207
207
  class << (Service = {})
208
-
209
208
  def contains(key); include?(key); end
210
209
  def get(key); self[key]; end;
211
210
  def put(key, value, ttl = nil)
212
211
  self[key] = value
213
- end
212
+ end
214
213
  end
215
-
214
+
216
215
  end
217
216
  end
218
-
217
+
219
218
  describe 'GAEStore' do
220
- it_should_behave_like 'A Rack::Cache::EntityStore Implementation'
221
219
  before do
222
220
  puts Rack::Cache::AppEngine::MC::Service.inspect
223
221
  @store = Rack::Cache::EntityStore::GAEStore.new
@@ -225,6 +223,7 @@ describe 'Rack::Cache::EntityStore' do
225
223
  after do
226
224
  @store = nil
227
225
  end
226
+ behaves_like 'A Rack::Cache::EntityStore Implementation'
228
227
  end
229
228
  end
230
229
  end
data/test/key_test.rb CHANGED
@@ -2,6 +2,18 @@ require "#{File.dirname(__FILE__)}/spec_setup"
2
2
  require 'rack/cache/key'
3
3
 
4
4
  describe 'A Rack::Cache::Key' do
5
+ # Helper Methods =============================================================
6
+
7
+ def mock_request(*args)
8
+ uri, opts = args
9
+ env = Rack::MockRequest.env_for(uri, opts || {})
10
+ Rack::Cache::Request.new(env)
11
+ end
12
+
13
+ def new_key(request)
14
+ Rack::Cache::Key.call(request)
15
+ end
16
+
5
17
  it "sorts params" do
6
18
  request = mock_request('/test?z=last&a=first')
7
19
  new_key(request).should.include('a=first&z=last')
@@ -35,16 +47,4 @@ describe 'A Rack::Cache::Key' do
35
47
  request = mock_request('/test?x=y', "HTTP_HOST" => 'www2.example.org')
36
48
  new_key(request).should.equal "http://www2.example.org/test?x=y"
37
49
  end
38
-
39
- # Helper Methods =============================================================
40
-
41
- define_method :mock_request do |*args|
42
- uri, opts = args
43
- env = Rack::MockRequest.env_for(uri, opts || {})
44
- Rack::Cache::Request.new(env)
45
- end
46
-
47
- define_method :new_key do |request|
48
- Rack::Cache::Key.call(request)
49
- end
50
50
  end
@@ -1,11 +1,44 @@
1
1
  require "#{File.dirname(__FILE__)}/spec_setup"
2
2
  require 'rack/cache/metastore'
3
+ require 'rack/cache/entitystore'
4
+
5
+ shared 'A Rack::Cache::MetaStore Implementation' do
6
+
7
+ ###
8
+ # Helpers
9
+
10
+ def mock_request(uri, opts)
11
+ env = Rack::MockRequest.env_for(uri, opts || {})
12
+ Rack::Cache::Request.new(env)
13
+ end
14
+
15
+ def mock_response(status, headers, body)
16
+ headers ||= {}
17
+ body = Array(body).compact
18
+ Rack::Cache::Response.new(status, headers, body)
19
+ end
20
+
21
+ def slurp(body)
22
+ buf = ''
23
+ body.each { |part| buf << part }
24
+ buf
25
+ end
26
+
27
+ # Stores an entry for the given request args, returns a url encoded cache key
28
+ # for the request.
29
+ def store_simple_entry(*request_args)
30
+ path, headers = request_args
31
+ @request = mock_request(path || '/test', headers || {})
32
+ @response = mock_response(200, {'Cache-Control' => 'max-age=420'}, ['test'])
33
+ body = @response.body
34
+ cache_key = @store.store(@request, @response, @entity_store)
35
+ @response.body.should.not.be.same_as body
36
+ cache_key
37
+ end
3
38
 
4
- describe_shared 'A Rack::Cache::MetaStore Implementation' do
5
39
  before do
6
40
  @request = mock_request('/', {})
7
41
  @response = mock_response(200, {}, ['hello world'])
8
- @entity_store = nil
9
42
  end
10
43
  after do
11
44
  @store = nil
@@ -43,7 +76,7 @@ describe_shared 'A Rack::Cache::MetaStore Implementation' do
43
76
 
44
77
  it 'returns nil from #purge' do
45
78
  @store.write('/test', [[{},{}]])
46
- @store.purge('/test').should.be nil
79
+ @store.purge('/test').should.be.nil
47
80
  @store.read('/test').should.equal []
48
81
  end
49
82
 
@@ -75,20 +108,12 @@ describe_shared 'A Rack::Cache::MetaStore Implementation' do
75
108
  @store.cache_key(request).should == 'tset/'
76
109
  end
77
110
 
78
- # Abstract methods ===========================================================
79
-
80
- # Stores an entry for the given request args, returns a url encoded cache key
81
- # for the request.
82
- define_method :store_simple_entry do |*request_args|
83
- path, headers = request_args
84
- @request = mock_request(path || '/test', headers || {})
85
- @response = mock_response(200, {'Cache-Control' => 'max-age=420'}, ['test'])
86
- body = @response.body
87
- cache_key = @store.store(@request, @response, @entity_store)
88
- @response.body.should.not.be body
89
- cache_key
111
+ it 'does not blow up when given a non-marhsalable object with an ALL_CAPS key' do
112
+ store_simple_entry('/bad', { 'SOME_THING' => Proc.new {} })
90
113
  end
91
114
 
115
+ # Abstract methods ===========================================================
116
+
92
117
  it 'stores a cache entry' do
93
118
  cache_key = store_simple_entry
94
119
  @store.read(cache_key).should.not.be.empty
@@ -206,39 +231,19 @@ describe_shared 'A Rack::Cache::MetaStore Implementation' do
206
231
 
207
232
  @store.read(key).length.should.equal 2
208
233
  end
209
-
210
- # Helper Methods =============================================================
211
-
212
- define_method :mock_request do |uri,opts|
213
- env = Rack::MockRequest.env_for(uri, opts || {})
214
- Rack::Cache::Request.new(env)
215
- end
216
-
217
- define_method :mock_response do |status,headers,body|
218
- headers ||= {}
219
- body = Array(body).compact
220
- Rack::Cache::Response.new(status, headers, body)
221
- end
222
-
223
- define_method :slurp do |body|
224
- buf = ''
225
- body.each {|part| buf << part }
226
- buf
227
- end
228
234
  end
229
235
 
230
236
 
231
237
  describe 'Rack::Cache::MetaStore' do
232
238
  describe 'Heap' do
233
- it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
234
239
  before do
235
240
  @store = Rack::Cache::MetaStore::Heap.new
236
241
  @entity_store = Rack::Cache::EntityStore::Heap.new
237
242
  end
243
+ behaves_like 'A Rack::Cache::MetaStore Implementation'
238
244
  end
239
245
 
240
246
  describe 'Disk' do
241
- it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
242
247
  before do
243
248
  @temp_dir = create_temp_directory
244
249
  @store = Rack::Cache::MetaStore::Disk.new("#{@temp_dir}/meta")
@@ -247,29 +252,30 @@ describe 'Rack::Cache::MetaStore' do
247
252
  after do
248
253
  remove_entry_secure @temp_dir
249
254
  end
255
+ behaves_like 'A Rack::Cache::MetaStore Implementation'
250
256
  end
251
257
 
252
258
  need_memcached 'metastore tests' do
253
259
  describe 'MemCached' do
254
- it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
255
- before :each do
260
+ before do
256
261
  @temp_dir = create_temp_directory
257
262
  $memcached.flush
258
263
  @store = Rack::Cache::MetaStore::MemCached.new($memcached)
259
264
  @entity_store = Rack::Cache::EntityStore::Heap.new
260
265
  end
266
+ behaves_like 'A Rack::Cache::MetaStore Implementation'
261
267
  end
262
268
  end
263
269
 
264
270
  need_dalli 'metastore tests' do
265
271
  describe 'Dalli' do
266
- it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
267
- before :each do
272
+ before do
268
273
  @temp_dir = create_temp_directory
269
274
  $dalli.flush_all
270
275
  @store = Rack::Cache::MetaStore::Dalli.new($dalli)
271
276
  @entity_store = Rack::Cache::EntityStore::Heap.new
272
277
  end
278
+ behaves_like 'A Rack::Cache::MetaStore Implementation'
273
279
  end
274
280
  end
275
281
 
@@ -289,12 +295,12 @@ describe 'Rack::Cache::MetaStore' do
289
295
  end
290
296
 
291
297
  describe 'GAEStore' do
292
- it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
293
298
  before :each do
294
299
  Rack::Cache::AppEngine::MC::Service.clear
295
300
  @store = Rack::Cache::MetaStore::GAEStore.new
296
301
  @entity_store = Rack::Cache::EntityStore::Heap.new
297
302
  end
303
+ behaves_like 'A Rack::Cache::MetaStore Implementation'
298
304
  end
299
305
 
300
306
  end
data/test/options_test.rb CHANGED
@@ -59,13 +59,13 @@ describe 'Rack::Cache::Options' do
59
59
  it 'allows the meta store to be configured' do
60
60
  @options.should.respond_to :metastore
61
61
  @options.should.respond_to :metastore=
62
- @options.metastore.should.not.be nil
62
+ @options.metastore.should.not.be.nil
63
63
  end
64
64
 
65
65
  it 'allows the entity store to be configured' do
66
66
  @options.should.respond_to :entitystore
67
67
  @options.should.respond_to :entitystore=
68
- @options.entitystore.should.not.be nil
68
+ @options.entitystore.should.not.be.nil
69
69
  end
70
70
 
71
71
  it 'allows log verbosity to be configured' do
data/test/request_test.rb CHANGED
@@ -4,16 +4,16 @@ require 'rack/cache/request'
4
4
  describe 'Rack::Cache::Request' do
5
5
  it 'is marked as no_cache when the Cache-Control header includes the no-cache directive' do
6
6
  request = Rack::Cache::Request.new('HTTP_CACHE_CONTROL' => 'public, no-cache')
7
- assert request.no_cache?
7
+ request.should.be.no_cache
8
8
  end
9
9
 
10
10
  it 'is marked as no_cache when request should not be loaded from cache' do
11
11
  request = Rack::Cache::Request.new('HTTP_PRAGMA' => 'no-cache')
12
- assert request.no_cache?
12
+ request.should.be.no_cache
13
13
  end
14
14
 
15
15
  it 'is not marked as no_cache when neither no-cache directive is specified' do
16
16
  request = Rack::Cache::Request.new('HTTP_CACHE_CONTROL' => 'public')
17
- assert !request.no_cache?
17
+ request.should.not.be.no_cache
18
18
  end
19
19
  end
@@ -1,21 +1,21 @@
1
1
  require "#{File.dirname(__FILE__)}/spec_setup"
2
2
 
3
3
  describe 'Rack::Cache::Response' do
4
- before :each do
4
+ before do
5
5
  @now = Time.httpdate(Time.now.httpdate)
6
6
  @one_hour_ago = Time.httpdate((Time.now - (60**2)).httpdate)
7
7
  @one_hour_later = Time.httpdate((Time.now + (60**2)).httpdate)
8
8
  @res = Rack::Cache::Response.new(200, {'Date' => @now.httpdate}, [])
9
9
  end
10
10
 
11
- after :each do
11
+ after do
12
12
  @now, @res, @one_hour_ago = nil
13
13
  end
14
14
 
15
15
  it 'marks Rack tuples with string typed statuses as cacheable' do
16
16
  @res = Rack::Cache::Response.new('200',{'Date' => @now.httpdate},[])
17
17
  @res.headers['Expires'] = @one_hour_later.httpdate
18
- @res.cacheable?.should.equal true
18
+ @res.should.be.cacheable
19
19
  end
20
20
 
21
21
  it 'responds to #to_a with a Rack response tuple' do
@@ -60,7 +60,7 @@ describe 'Rack::Cache::Response' do
60
60
  end
61
61
  it 'uses the current time when no Date header present' do
62
62
  @res = Rack::Cache::Response.new(200, {}, [])
63
- @res.date.should.be.close Time.now, 1
63
+ @res.date.to_i.should.be.close Time.now.to_i, 1
64
64
  end
65
65
  it 'returns the correct date when the header is modified directly' do
66
66
  @res = Rack::Cache::Response.new(200, { 'Date' => @one_hour_ago.httpdate }, [])
data/test/spec_setup.rb CHANGED
@@ -2,13 +2,13 @@ require 'pp'
2
2
  require 'tmpdir'
3
3
  require 'stringio'
4
4
 
5
- [ STDOUT, STDERR ].each { |io| io.sync = true }
5
+ [STDOUT, STDERR].each { |io| io.sync = true }
6
6
 
7
7
  begin
8
- require 'test/spec'
8
+ require 'bacon'
9
9
  rescue LoadError => boom
10
10
  require 'rubygems' rescue nil
11
- require 'test/spec'
11
+ require 'bacon'
12
12
  end
13
13
 
14
14
  # Set the MEMCACHED environment variable as follows to enable testing
@@ -19,17 +19,24 @@ $dalli = nil
19
19
 
20
20
  def have_memcached?(server=ENV['MEMCACHED'])
21
21
  return $memcached unless $memcached.nil?
22
- v, $VERBOSE = $VERBOSE, nil # silence warnings from memcached
23
- require 'memcached'
24
- $VERBOSE = v
22
+
23
+ # silence warnings from memcached
24
+ begin
25
+ v, $VERBOSE = $VERBOSE, nil
26
+ require 'memcached'
27
+ ensure
28
+ $VERBOSE = v
29
+ end
30
+
25
31
  $memcached = Memcached.new(server)
26
32
  $memcached.set('ping', '')
27
33
  true
28
34
  rescue LoadError => boom
35
+ warn "memcached library not available. related tests will be skipped."
29
36
  $memcached = false
30
37
  false
31
38
  rescue => boom
32
- STDERR.puts "memcached not working. related tests will be skipped."
39
+ warn "memcached not working. related tests will be skipped."
33
40
  $memcached = false
34
41
  false
35
42
  end
@@ -43,10 +50,11 @@ def have_dalli?(server=ENV['MEMCACHED'])
43
50
  $dalli.set('ping', '')
44
51
  true
45
52
  rescue LoadError => boom
53
+ warn "dalli library not available. related tests will be skipped."
46
54
  $dalli = false
47
55
  false
48
56
  rescue => boom
49
- STDERR.puts "dalli not working. related tests will be skipped."
57
+ warn "dalli not working. related tests will be skipped."
50
58
  $dalli = false
51
59
  false
52
60
  end
@@ -54,27 +62,15 @@ end
54
62
  have_dalli?
55
63
 
56
64
  def need_dalli(forwhat)
57
- if have_dalli?
58
- yield
59
- else
60
- STDERR.puts "skipping Dalli #{forwhat}"
61
- end
65
+ yield if have_dalli?
62
66
  end
63
67
 
64
68
  def need_memcached(forwhat)
65
- if have_memcached?
66
- yield
67
- else
68
- STDERR.puts "skipping memcached #{forwhat}"
69
- end
69
+ yield if have_memcached?
70
70
  end
71
71
 
72
72
  def need_java(forwhat)
73
- if RUBY_PLATFORM =~ /java/
74
- yield
75
- else
76
- STDERR.puts "skipping app engine #{forwhat}"
77
- end
73
+ yield if RUBY_PLATFORM =~ /java/
78
74
  end
79
75
 
80
76
 
@@ -84,7 +80,6 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
84
80
 
85
81
  require 'rack/cache'
86
82
 
87
-
88
83
  # Methods for constructing downstream applications / response
89
84
  # generators.
90
85
  module CacheContextHelpers
@@ -128,18 +123,18 @@ module CacheContextHelpers
128
123
 
129
124
  def teardown_cache_context
130
125
  @app, @cache_template, @cache, @caches, @called,
131
- @request, @response, @responses, @cache_config = nil
126
+ @request, @response, @responses, @cache_config, @cache_prototype = nil
132
127
  end
133
128
 
134
129
  # A basic response with 200 status code and a tiny body.
135
- def respond_with(status=200, headers={}, body=['Hello World'])
130
+ def respond_with(status=200, headers={}, body=['Hello World'], &bk)
136
131
  called = false
137
132
  @app =
138
133
  lambda do |env|
139
134
  called = true
140
135
  response = Rack::Response.new(body, status, headers)
141
136
  request = Rack::Request.new(env)
142
- yield request, response if block_given?
137
+ bk.call(request, response) if bk
143
138
  response.finish
144
139
  end
145
140
  @app.meta_def(:called?) { called }
@@ -210,7 +205,7 @@ module TestHelpers
210
205
 
211
206
  end
212
207
 
213
- class Test::Unit::TestCase
208
+ class Bacon::Context
214
209
  include TestHelpers
215
210
  include CacheContextHelpers
216
211
  end
data/test/storage_test.rb CHANGED
@@ -15,7 +15,7 @@ describe 'Rack::Cache::Storage' do
15
15
  end
16
16
  it "returns an existing MetaStore instance for URI that exists" do
17
17
  store = @storage.resolve_metastore_uri('heap:/')
18
- @storage.resolve_metastore_uri('heap:/').should.be store
18
+ @storage.resolve_metastore_uri('heap:/').should.be.same_as store
19
19
  end
20
20
  it "creates a new EntityStore for URI if none exists" do
21
21
  @storage.resolve_entitystore_uri('heap:/').
@@ -23,14 +23,14 @@ describe 'Rack::Cache::Storage' do
23
23
  end
24
24
  it "returns an existing EntityStore instance for URI that exists" do
25
25
  store = @storage.resolve_entitystore_uri('heap:/')
26
- @storage.resolve_entitystore_uri('heap:/').should.be store
26
+ @storage.resolve_entitystore_uri('heap:/').should.be.same_as store
27
27
  end
28
28
  it "clears all URI -> store mappings with #clear" do
29
29
  meta = @storage.resolve_metastore_uri('heap:/')
30
30
  entity = @storage.resolve_entitystore_uri('heap:/')
31
31
  @storage.clear
32
- @storage.resolve_metastore_uri('heap:/').should.not.be meta
33
- @storage.resolve_entitystore_uri('heap:/').should.not.be entity
32
+ @storage.resolve_metastore_uri('heap:/').should.not.be.same_as meta
33
+ @storage.resolve_entitystore_uri('heap:/').should.not.be.same_as entity
34
34
  end
35
35
 
36
36
  describe 'Heap Store URIs' do
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-cache
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 0
9
- version: "1.0"
4
+ prerelease:
5
+ version: 1.0.1
10
6
  platform: ruby
11
7
  authors:
12
8
  - Ryan Tomayko
@@ -14,7 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2010-12-24 00:00:00 -08:00
13
+ date: 2011-04-13 00:00:00 +01:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
@@ -25,24 +21,17 @@ dependencies:
25
21
  requirements:
26
22
  - - ">="
27
23
  - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- - 4
32
24
  version: "0.4"
33
25
  type: :runtime
34
26
  version_requirements: *id001
35
27
  - !ruby/object:Gem::Dependency
36
- name: test-spec
28
+ name: bacon
37
29
  prerelease: false
38
30
  requirement: &id002 !ruby/object:Gem::Requirement
39
31
  none: false
40
32
  requirements:
41
33
  - - ">="
42
34
  - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 0
46
35
  version: "0"
47
36
  type: :development
48
37
  version_requirements: *id002
@@ -54,9 +43,6 @@ dependencies:
54
43
  requirements:
55
44
  - - ">="
56
45
  - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
46
  version: "0"
61
47
  type: :development
62
48
  version_requirements: *id003
@@ -68,9 +54,6 @@ dependencies:
68
54
  requirements:
69
55
  - - ">="
70
56
  - !ruby/object:Gem::Version
71
- hash: 3
72
- segments:
73
- - 0
74
57
  version: "0"
75
58
  type: :development
76
59
  version_requirements: *id004
@@ -101,6 +84,7 @@ files:
101
84
  - doc/storage.markdown
102
85
  - example/sinatra/app.rb
103
86
  - example/sinatra/views/index.erb
87
+ - lib/rack-cache.rb
104
88
  - lib/rack/cache.rb
105
89
  - lib/rack/cache/appengine.rb
106
90
  - lib/rack/cache/cachecontrol.rb
@@ -144,23 +128,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
128
  requirements:
145
129
  - - ">="
146
130
  - !ruby/object:Gem::Version
147
- hash: 3
148
- segments:
149
- - 0
150
131
  version: "0"
151
132
  required_rubygems_version: !ruby/object:Gem::Requirement
152
133
  none: false
153
134
  requirements:
154
135
  - - ">="
155
136
  - !ruby/object:Gem::Version
156
- hash: 3
157
- segments:
158
- - 0
159
137
  version: "0"
160
138
  requirements: []
161
139
 
162
140
  rubyforge_project:
163
- rubygems_version: 1.3.7
141
+ rubygems_version: 1.6.0
164
142
  signing_key:
165
143
  specification_version: 2
166
144
  summary: HTTP Caching for Rack