rack-cache 1.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/{COPYING → MIT-LICENSE} +0 -0
- data/README.md +95 -0
- data/lib/rack/cache/cachecontrol.rb +14 -0
- data/lib/rack/cache/context.rb +16 -3
- data/lib/rack/cache/metastore.rb +1 -1
- data/lib/rack/cache/options.rb +4 -6
- data/lib/rack/cache/response.rb +13 -6
- metadata +76 -74
- data/Gemfile +0 -2
- data/README +0 -126
- data/Rakefile +0 -139
- data/TODO +0 -27
- data/doc/configuration.markdown +0 -127
- data/doc/faq.markdown +0 -148
- data/doc/index.markdown +0 -121
- data/doc/layout.html.erb +0 -34
- data/doc/license.markdown +0 -24
- data/doc/rack-cache.css +0 -362
- data/doc/server.ru +0 -34
- data/doc/storage.markdown +0 -164
- data/example/sinatra/app.rb +0 -21
- data/example/sinatra/views/index.erb +0 -44
- data/rack-cache.gemspec +0 -75
- data/test/cache_test.rb +0 -38
- data/test/cachecontrol_test.rb +0 -145
- data/test/context_test.rb +0 -916
- data/test/entitystore_test.rb +0 -268
- data/test/key_test.rb +0 -50
- data/test/metastore_test.rb +0 -338
- data/test/options_test.rb +0 -77
- data/test/pony.jpg +0 -0
- data/test/request_test.rb +0 -19
- data/test/response_test.rb +0 -184
- data/test/spec_setup.rb +0 -232
- data/test/storage_test.rb +0 -94
data/test/options_test.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
require 'rack/cache/options'
|
3
|
-
|
4
|
-
module Rack::Cache::Options
|
5
|
-
option_accessor :foo
|
6
|
-
end
|
7
|
-
|
8
|
-
class MockOptions
|
9
|
-
include Rack::Cache::Options
|
10
|
-
def initialize
|
11
|
-
@env = nil
|
12
|
-
initialize_options
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe 'Rack::Cache::Options' do
|
17
|
-
before { @options = MockOptions.new }
|
18
|
-
|
19
|
-
describe '#set' do
|
20
|
-
it 'sets a Symbol option as rack-cache.symbol' do
|
21
|
-
@options.set :bar, 'baz'
|
22
|
-
@options.options['rack-cache.bar'].should.equal 'baz'
|
23
|
-
end
|
24
|
-
it 'sets a String option as string' do
|
25
|
-
@options.set 'foo.bar', 'bling'
|
26
|
-
@options.options['foo.bar'].should.equal 'bling'
|
27
|
-
end
|
28
|
-
it 'sets all key/value pairs when given a Hash' do
|
29
|
-
@options.set :foo => 'bar', :bar => 'baz', 'foo.bar' => 'bling'
|
30
|
-
@options.foo.should.equal 'bar'
|
31
|
-
@options.options['rack-cache.bar'].should.equal 'baz'
|
32
|
-
@options.options['foo.bar'].should.equal 'bling'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'makes options declared with option_accessor available as attributes' do
|
37
|
-
@options.set :foo, 'bar'
|
38
|
-
@options.foo.should.equal 'bar'
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'allows setting multiple options via assignment' do
|
42
|
-
@options.options = { :foo => 'bar', :bar => 'baz', 'foo.bar' => 'bling' }
|
43
|
-
@options.foo.should.equal 'bar'
|
44
|
-
@options.options['foo.bar'].should.equal 'bling'
|
45
|
-
@options.options['rack-cache.bar'].should.equal 'baz'
|
46
|
-
end
|
47
|
-
|
48
|
-
it "allows storing the value as a block" do
|
49
|
-
block = Proc.new { "bar block" }
|
50
|
-
@options.set(:foo, &block)
|
51
|
-
@options.options['rack-cache.foo'].should.equal block
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'allows the cache key generator to be configured' do
|
55
|
-
@options.should.respond_to :cache_key
|
56
|
-
@options.should.respond_to :cache_key=
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'allows the meta store to be configured' do
|
60
|
-
@options.should.respond_to :metastore
|
61
|
-
@options.should.respond_to :metastore=
|
62
|
-
@options.metastore.should.not.be.nil
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'allows the entity store to be configured' do
|
66
|
-
@options.should.respond_to :entitystore
|
67
|
-
@options.should.respond_to :entitystore=
|
68
|
-
@options.entitystore.should.not.be.nil
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'allows log verbosity to be configured' do
|
72
|
-
@options.should.respond_to :verbose
|
73
|
-
@options.should.respond_to :verbose=
|
74
|
-
@options.should.respond_to :verbose?
|
75
|
-
@options.verbose.should.not.be.nil
|
76
|
-
end
|
77
|
-
end
|
data/test/pony.jpg
DELETED
Binary file
|
data/test/request_test.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
require 'rack/cache/request'
|
3
|
-
|
4
|
-
describe 'Rack::Cache::Request' do
|
5
|
-
it 'is marked as no_cache when the Cache-Control header includes the no-cache directive' do
|
6
|
-
request = Rack::Cache::Request.new('HTTP_CACHE_CONTROL' => 'public, no-cache')
|
7
|
-
request.should.be.no_cache
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'is marked as no_cache when request should not be loaded from cache' do
|
11
|
-
request = Rack::Cache::Request.new('HTTP_PRAGMA' => 'no-cache')
|
12
|
-
request.should.be.no_cache
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'is not marked as no_cache when neither no-cache directive is specified' do
|
16
|
-
request = Rack::Cache::Request.new('HTTP_CACHE_CONTROL' => 'public')
|
17
|
-
request.should.not.be.no_cache
|
18
|
-
end
|
19
|
-
end
|
data/test/response_test.rb
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
|
3
|
-
describe 'Rack::Cache::Response' do
|
4
|
-
before do
|
5
|
-
@now = Time.httpdate(Time.now.httpdate)
|
6
|
-
@one_hour_ago = Time.httpdate((Time.now - (60**2)).httpdate)
|
7
|
-
@one_hour_later = Time.httpdate((Time.now + (60**2)).httpdate)
|
8
|
-
@res = Rack::Cache::Response.new(200, {'Date' => @now.httpdate}, [])
|
9
|
-
end
|
10
|
-
|
11
|
-
after do
|
12
|
-
@now, @res, @one_hour_ago = nil
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'marks Rack tuples with string typed statuses as cacheable' do
|
16
|
-
@res = Rack::Cache::Response.new('200',{'Date' => @now.httpdate},[])
|
17
|
-
@res.headers['Expires'] = @one_hour_later.httpdate
|
18
|
-
@res.should.be.cacheable
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'responds to #to_a with a Rack response tuple' do
|
22
|
-
@res.should.respond_to :to_a
|
23
|
-
@res.to_a.should.equal [200, {'Date' => @now.httpdate}, []]
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '#cache_control' do
|
27
|
-
it 'handles multiple name=value pairs' do
|
28
|
-
@res.headers['Cache-Control'] = 'max-age=600, max-stale=300, min-fresh=570'
|
29
|
-
@res.cache_control['max-age'].should.equal '600'
|
30
|
-
@res.cache_control['max-stale'].should.equal '300'
|
31
|
-
@res.cache_control['min-fresh'].should.equal '570'
|
32
|
-
end
|
33
|
-
it 'removes the header when given an empty hash' do
|
34
|
-
@res.headers['Cache-Control'] = 'max-age=600, must-revalidate'
|
35
|
-
@res.cache_control['max-age'].should.equal '600'
|
36
|
-
@res.cache_control = {}
|
37
|
-
@res.headers.should.not.include 'Cache-Control'
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '#validateable?' do
|
42
|
-
it 'is true when Last-Modified header present' do
|
43
|
-
@res = Rack::Cache::Response.new(200, {'Last-Modified' => @one_hour_ago.httpdate}, [])
|
44
|
-
@res.should.be.validateable
|
45
|
-
end
|
46
|
-
it 'is true when ETag header present' do
|
47
|
-
@res = Rack::Cache::Response.new(200, {'ETag' => '"12345"'}, [])
|
48
|
-
@res.should.be.validateable
|
49
|
-
end
|
50
|
-
it 'is false when no validator is present' do
|
51
|
-
@res = Rack::Cache::Response.new(200, {}, [])
|
52
|
-
@res.should.not.be.validateable
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#date' do
|
57
|
-
it 'uses the Date header if present' do
|
58
|
-
@res = Rack::Cache::Response.new(200, {'Date' => @one_hour_ago.httpdate}, [])
|
59
|
-
@res.date.should.equal @one_hour_ago
|
60
|
-
end
|
61
|
-
it 'uses the current time when no Date header present' do
|
62
|
-
@res = Rack::Cache::Response.new(200, {}, [])
|
63
|
-
@res.date.to_i.should.be.close Time.now.to_i, 1
|
64
|
-
end
|
65
|
-
it 'returns the correct date when the header is modified directly' do
|
66
|
-
@res = Rack::Cache::Response.new(200, { 'Date' => @one_hour_ago.httpdate }, [])
|
67
|
-
@res.date.should.equal @one_hour_ago
|
68
|
-
@res.headers['Date'] = @now.httpdate
|
69
|
-
@res.date.should.equal @now
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe '#max_age' do
|
74
|
-
it 'uses s-maxage cache control directive when present' do
|
75
|
-
@res.headers['Cache-Control'] = 's-maxage=600, max-age=0'
|
76
|
-
@res.max_age.should.equal 600
|
77
|
-
end
|
78
|
-
it 'falls back to max-age when no s-maxage directive present' do
|
79
|
-
@res.headers['Cache-Control'] = 'max-age=600'
|
80
|
-
@res.max_age.should.equal 600
|
81
|
-
end
|
82
|
-
it 'falls back to Expires when no max-age or s-maxage directive present' do
|
83
|
-
@res.headers['Cache-Control'] = 'must-revalidate'
|
84
|
-
@res.headers['Expires'] = @one_hour_later.httpdate
|
85
|
-
@res.max_age.should.equal 60 ** 2
|
86
|
-
end
|
87
|
-
it 'gives a #max_age of nil when no freshness information available' do
|
88
|
-
@res.max_age.should.be.nil
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe '#private=' do
|
93
|
-
it 'adds the private Cache-Control directive when set true' do
|
94
|
-
@res.headers['Cache-Control'] = 'max-age=100'
|
95
|
-
@res.private = true
|
96
|
-
@res.headers['Cache-Control'].split(', ').sort.
|
97
|
-
should.equal ['max-age=100', 'private']
|
98
|
-
end
|
99
|
-
it 'removes the public Cache-Control directive' do
|
100
|
-
@res.headers['Cache-Control'] = 'public, max-age=100'
|
101
|
-
@res.private = true
|
102
|
-
@res.headers['Cache-Control'].split(', ').sort.
|
103
|
-
should.equal ['max-age=100', 'private']
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe '#expire!' do
|
108
|
-
it 'sets the Age to be equal to the max-age' do
|
109
|
-
@res.headers['Cache-Control'] = 'max-age=100'
|
110
|
-
@res.expire!
|
111
|
-
@res.headers['Age'].should.equal '100'
|
112
|
-
end
|
113
|
-
it 'sets the Age to be equal to the s-maxage when both max-age and s-maxage present' do
|
114
|
-
@res.headers['Cache-Control'] = 'max-age=100, s-maxage=500'
|
115
|
-
@res.expire!
|
116
|
-
@res.headers['Age'].should.equal '500'
|
117
|
-
end
|
118
|
-
it 'does nothing when the response is already stale/expired' do
|
119
|
-
@res.headers['Cache-Control'] = 'max-age=5, s-maxage=500'
|
120
|
-
@res.headers['Age'] = '1000'
|
121
|
-
@res.expire!
|
122
|
-
@res.headers['Age'].should.equal '1000'
|
123
|
-
end
|
124
|
-
it 'does nothing when the response does not include freshness information' do
|
125
|
-
@res.expire!
|
126
|
-
@res.headers.should.not.include 'Age'
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe '#ttl' do
|
131
|
-
it 'is nil when no Expires or Cache-Control headers present' do
|
132
|
-
@res.ttl.should.be.nil
|
133
|
-
end
|
134
|
-
it 'uses the Expires header when no max-age is present' do
|
135
|
-
@res.headers['Expires'] = (@res.now + (60**2)).httpdate
|
136
|
-
@res.ttl.should.be.close(60**2, 1)
|
137
|
-
end
|
138
|
-
it 'returns negative values when Expires is in part' do
|
139
|
-
@res.ttl.should.be.nil
|
140
|
-
@res.headers['Expires'] = @one_hour_ago.httpdate
|
141
|
-
@res.ttl.should.be < 0
|
142
|
-
end
|
143
|
-
it 'uses the Cache-Control max-age value when present' do
|
144
|
-
@res.headers['Cache-Control'] = 'max-age=60'
|
145
|
-
@res.ttl.should.be.close(60, 1)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
describe '#vary' do
|
150
|
-
it 'is nil when no Vary header is present' do
|
151
|
-
@res.vary.should.be.nil
|
152
|
-
end
|
153
|
-
it 'returns the literal value of the Vary header' do
|
154
|
-
@res.headers['Vary'] = 'Foo Bar Baz'
|
155
|
-
@res.vary.should.equal 'Foo Bar Baz'
|
156
|
-
end
|
157
|
-
it 'can be checked for existence using the #vary? method' do
|
158
|
-
@res.should.respond_to :vary?
|
159
|
-
@res.should.not.vary
|
160
|
-
@res.headers['Vary'] = '*'
|
161
|
-
@res.should.vary
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe '#vary_header_names' do
|
166
|
-
it 'returns an empty Array when no Vary header is present' do
|
167
|
-
@res.vary_header_names.should.be.empty
|
168
|
-
end
|
169
|
-
it 'parses a single header name value' do
|
170
|
-
@res.headers['Vary'] = 'Accept-Language'
|
171
|
-
@res.vary_header_names.should.equal ['Accept-Language']
|
172
|
-
end
|
173
|
-
it 'parses multiple header name values separated by spaces' do
|
174
|
-
@res.headers['Vary'] = 'Accept-Language User-Agent X-Foo'
|
175
|
-
@res.vary_header_names.should.equal \
|
176
|
-
['Accept-Language', 'User-Agent', 'X-Foo']
|
177
|
-
end
|
178
|
-
it 'parses multiple header name values separated by commas' do
|
179
|
-
@res.headers['Vary'] = 'Accept-Language,User-Agent, X-Foo'
|
180
|
-
@res.vary_header_names.should.equal \
|
181
|
-
['Accept-Language', 'User-Agent', 'X-Foo']
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
data/test/spec_setup.rb
DELETED
@@ -1,232 +0,0 @@
|
|
1
|
-
require 'pp'
|
2
|
-
require 'tmpdir'
|
3
|
-
require 'stringio'
|
4
|
-
|
5
|
-
[STDOUT, STDERR].each { |io| io.sync = true }
|
6
|
-
|
7
|
-
begin
|
8
|
-
require 'bacon'
|
9
|
-
rescue LoadError => boom
|
10
|
-
require 'rubygems' rescue nil
|
11
|
-
require 'bacon'
|
12
|
-
end
|
13
|
-
|
14
|
-
# Set the MEMCACHED environment variable as follows to enable testing
|
15
|
-
# of the MemCached meta and entity stores.
|
16
|
-
ENV['MEMCACHED'] ||= 'localhost:11211'
|
17
|
-
$memcached = nil
|
18
|
-
$dalli = nil
|
19
|
-
|
20
|
-
def have_memcached?(server=ENV['MEMCACHED'])
|
21
|
-
return $memcached unless $memcached.nil?
|
22
|
-
|
23
|
-
# silence warnings from memcached
|
24
|
-
begin
|
25
|
-
v, $VERBOSE = $VERBOSE, nil
|
26
|
-
require 'memcached'
|
27
|
-
ensure
|
28
|
-
$VERBOSE = v
|
29
|
-
end
|
30
|
-
|
31
|
-
$memcached = Memcached.new(server)
|
32
|
-
$memcached.set('ping', '')
|
33
|
-
true
|
34
|
-
rescue LoadError => boom
|
35
|
-
warn "memcached library not available. related tests will be skipped."
|
36
|
-
$memcached = false
|
37
|
-
false
|
38
|
-
rescue => boom
|
39
|
-
warn "memcached not working. related tests will be skipped."
|
40
|
-
$memcached = false
|
41
|
-
false
|
42
|
-
end
|
43
|
-
|
44
|
-
have_memcached?
|
45
|
-
|
46
|
-
def have_dalli?(server=ENV['MEMCACHED'])
|
47
|
-
return $dalli unless $dalli.nil?
|
48
|
-
require 'dalli'
|
49
|
-
$dalli = Dalli::Client.new(server)
|
50
|
-
$dalli.set('ping', '')
|
51
|
-
true
|
52
|
-
rescue LoadError => boom
|
53
|
-
warn "dalli library not available. related tests will be skipped."
|
54
|
-
$dalli = false
|
55
|
-
false
|
56
|
-
rescue => boom
|
57
|
-
warn "dalli not working. related tests will be skipped."
|
58
|
-
$dalli = false
|
59
|
-
false
|
60
|
-
end
|
61
|
-
|
62
|
-
have_dalli?
|
63
|
-
|
64
|
-
def need_dalli(forwhat)
|
65
|
-
yield if have_dalli?
|
66
|
-
end
|
67
|
-
|
68
|
-
def need_memcached(forwhat)
|
69
|
-
yield if have_memcached?
|
70
|
-
end
|
71
|
-
|
72
|
-
def need_java(forwhat)
|
73
|
-
yield if RUBY_PLATFORM =~ /java/
|
74
|
-
end
|
75
|
-
|
76
|
-
|
77
|
-
# Setup the load path ..
|
78
|
-
$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + '/lib'
|
79
|
-
$LOAD_PATH.unshift File.dirname(__FILE__)
|
80
|
-
|
81
|
-
require 'rack/cache'
|
82
|
-
|
83
|
-
# Methods for constructing downstream applications / response
|
84
|
-
# generators.
|
85
|
-
module CacheContextHelpers
|
86
|
-
|
87
|
-
# The Rack::Cache::Context instance used for the most recent
|
88
|
-
# request.
|
89
|
-
attr_reader :cache
|
90
|
-
|
91
|
-
# An Array of Rack::Cache::Context instances used for each request, in
|
92
|
-
# request order.
|
93
|
-
attr_reader :caches
|
94
|
-
|
95
|
-
# The Rack::Response instance result of the most recent request.
|
96
|
-
attr_reader :response
|
97
|
-
|
98
|
-
# An Array of Rack::Response instances for each request, in request order.
|
99
|
-
attr_reader :responses
|
100
|
-
|
101
|
-
# The backend application object.
|
102
|
-
attr_reader :app
|
103
|
-
|
104
|
-
def setup_cache_context
|
105
|
-
# holds each Rack::Cache::Context
|
106
|
-
@app = nil
|
107
|
-
|
108
|
-
# each time a request is made, a clone of @cache_template is used
|
109
|
-
# and appended to @caches.
|
110
|
-
@cache_template = nil
|
111
|
-
@cache = nil
|
112
|
-
@caches = []
|
113
|
-
@errors = StringIO.new
|
114
|
-
@cache_config = nil
|
115
|
-
|
116
|
-
@called = false
|
117
|
-
@request = nil
|
118
|
-
@response = nil
|
119
|
-
@responses = []
|
120
|
-
|
121
|
-
@storage = Rack::Cache::Storage.new
|
122
|
-
end
|
123
|
-
|
124
|
-
def teardown_cache_context
|
125
|
-
@app, @cache_template, @cache, @caches, @called,
|
126
|
-
@request, @response, @responses, @cache_config, @cache_prototype = nil
|
127
|
-
end
|
128
|
-
|
129
|
-
# A basic response with 200 status code and a tiny body.
|
130
|
-
def respond_with(status=200, headers={}, body=['Hello World'], &bk)
|
131
|
-
called = false
|
132
|
-
@app =
|
133
|
-
lambda do |env|
|
134
|
-
called = true
|
135
|
-
response = Rack::Response.new(body, status, headers)
|
136
|
-
request = Rack::Request.new(env)
|
137
|
-
bk.call(request, response) if bk
|
138
|
-
response.finish
|
139
|
-
end
|
140
|
-
@app.meta_def(:called?) { called }
|
141
|
-
@app.meta_def(:reset!) { called = false }
|
142
|
-
@app
|
143
|
-
end
|
144
|
-
|
145
|
-
def cache_config(&block)
|
146
|
-
@cache_config = block
|
147
|
-
end
|
148
|
-
|
149
|
-
def request(method, uri='/', opts={})
|
150
|
-
opts = {
|
151
|
-
'rack.run_once' => true,
|
152
|
-
'rack.errors' => @errors,
|
153
|
-
'rack-cache.storage' => @storage
|
154
|
-
}.merge(opts)
|
155
|
-
|
156
|
-
fail 'response not specified (use respond_with)' if @app.nil?
|
157
|
-
@app.reset! if @app.respond_to?(:reset!)
|
158
|
-
|
159
|
-
@cache_prototype ||= Rack::Cache::Context.new(@app, &@cache_config)
|
160
|
-
@cache = @cache_prototype.clone
|
161
|
-
@caches << @cache
|
162
|
-
@request = Rack::MockRequest.new(@cache)
|
163
|
-
yield @cache if block_given?
|
164
|
-
@response = @request.request(method.to_s.upcase, uri, opts)
|
165
|
-
@responses << @response
|
166
|
-
@response
|
167
|
-
end
|
168
|
-
|
169
|
-
def get(stem, env={}, &b)
|
170
|
-
request(:get, stem, env, &b)
|
171
|
-
end
|
172
|
-
|
173
|
-
def head(stem, env={}, &b)
|
174
|
-
request(:head, stem, env, &b)
|
175
|
-
end
|
176
|
-
|
177
|
-
def post(*args, &b)
|
178
|
-
request(:post, *args, &b)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
|
183
|
-
module TestHelpers
|
184
|
-
include FileUtils
|
185
|
-
F = File
|
186
|
-
|
187
|
-
@@temp_dir_count = 0
|
188
|
-
|
189
|
-
def create_temp_directory
|
190
|
-
@@temp_dir_count += 1
|
191
|
-
path = F.join(Dir.tmpdir, "rack-cache-#{$$}-#{@@temp_dir_count}")
|
192
|
-
mkdir_p path
|
193
|
-
if block_given?
|
194
|
-
yield path
|
195
|
-
remove_entry_secure path
|
196
|
-
end
|
197
|
-
path
|
198
|
-
end
|
199
|
-
|
200
|
-
def create_temp_file(root, file, data='')
|
201
|
-
path = F.join(root, file)
|
202
|
-
mkdir_p F.dirname(path)
|
203
|
-
F.open(path, 'w') { |io| io.write(data) }
|
204
|
-
end
|
205
|
-
|
206
|
-
end
|
207
|
-
|
208
|
-
class Bacon::Context
|
209
|
-
include TestHelpers
|
210
|
-
include CacheContextHelpers
|
211
|
-
end
|
212
|
-
|
213
|
-
# Metaid == a few simple metaclass helper
|
214
|
-
# (See http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html.)
|
215
|
-
class Object
|
216
|
-
# The hidden singleton lurks behind everyone
|
217
|
-
def metaclass; class << self; self; end; end
|
218
|
-
def meta_eval(&blk); metaclass.instance_eval(&blk); end
|
219
|
-
# Adds methods to a metaclass
|
220
|
-
def meta_def name, &blk
|
221
|
-
meta_eval { define_method name, &blk }
|
222
|
-
end
|
223
|
-
# Defines an instance method within a class
|
224
|
-
def class_def name, &blk
|
225
|
-
class_eval { define_method name, &blk }
|
226
|
-
end
|
227
|
-
|
228
|
-
# True when the Object is neither false or nil.
|
229
|
-
def truthy?
|
230
|
-
!!self
|
231
|
-
end
|
232
|
-
end
|
data/test/storage_test.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
require 'rack/cache/storage'
|
3
|
-
|
4
|
-
describe 'Rack::Cache::Storage' do
|
5
|
-
before do
|
6
|
-
@storage = Rack::Cache::Storage.new
|
7
|
-
end
|
8
|
-
|
9
|
-
it "fails when an unknown URI scheme is provided" do
|
10
|
-
lambda { @storage.resolve_metastore_uri('foo:/') }.should.raise
|
11
|
-
end
|
12
|
-
it "creates a new MetaStore for URI if none exists" do
|
13
|
-
@storage.resolve_metastore_uri('heap:/').
|
14
|
-
should.be.kind_of Rack::Cache::MetaStore
|
15
|
-
end
|
16
|
-
it "returns an existing MetaStore instance for URI that exists" do
|
17
|
-
store = @storage.resolve_metastore_uri('heap:/')
|
18
|
-
@storage.resolve_metastore_uri('heap:/').should.be.same_as store
|
19
|
-
end
|
20
|
-
it "creates a new EntityStore for URI if none exists" do
|
21
|
-
@storage.resolve_entitystore_uri('heap:/').
|
22
|
-
should.be.kind_of Rack::Cache::EntityStore
|
23
|
-
end
|
24
|
-
it "returns an existing EntityStore instance for URI that exists" do
|
25
|
-
store = @storage.resolve_entitystore_uri('heap:/')
|
26
|
-
@storage.resolve_entitystore_uri('heap:/').should.be.same_as store
|
27
|
-
end
|
28
|
-
it "clears all URI -> store mappings with #clear" do
|
29
|
-
meta = @storage.resolve_metastore_uri('heap:/')
|
30
|
-
entity = @storage.resolve_entitystore_uri('heap:/')
|
31
|
-
@storage.clear
|
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
|
-
end
|
35
|
-
|
36
|
-
describe 'Heap Store URIs' do
|
37
|
-
%w[heap:/ mem:/].each do |uri|
|
38
|
-
it "resolves #{uri} meta store URIs" do
|
39
|
-
@storage.resolve_metastore_uri(uri).
|
40
|
-
should.be.kind_of Rack::Cache::MetaStore
|
41
|
-
end
|
42
|
-
it "resolves #{uri} entity store URIs" do
|
43
|
-
@storage.resolve_entitystore_uri(uri).
|
44
|
-
should.be.kind_of Rack::Cache::EntityStore
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe 'Disk Store URIs' do
|
50
|
-
before do
|
51
|
-
@temp_dir = create_temp_directory
|
52
|
-
end
|
53
|
-
after do
|
54
|
-
remove_entry_secure @temp_dir
|
55
|
-
@temp_dir = nil
|
56
|
-
end
|
57
|
-
|
58
|
-
%w[file: disk:].each do |uri|
|
59
|
-
it "resolves #{uri} meta store URIs" do
|
60
|
-
@storage.resolve_metastore_uri(uri + @temp_dir).
|
61
|
-
should.be.kind_of Rack::Cache::MetaStore
|
62
|
-
end
|
63
|
-
it "resolves #{uri} entity store URIs" do
|
64
|
-
@storage.resolve_entitystore_uri(uri + @temp_dir).
|
65
|
-
should.be.kind_of Rack::Cache::EntityStore
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
if have_memcached?
|
71
|
-
|
72
|
-
describe 'MemCache Store URIs' do
|
73
|
-
%w[memcache: memcached:].each do |scheme|
|
74
|
-
it "resolves #{scheme} meta store URIs" do
|
75
|
-
uri = scheme + '//' + ENV['MEMCACHED']
|
76
|
-
@storage.resolve_metastore_uri(uri).
|
77
|
-
should.be.kind_of Rack::Cache::MetaStore
|
78
|
-
end
|
79
|
-
it "resolves #{scheme} entity store URIs" do
|
80
|
-
uri = scheme + '//' + ENV['MEMCACHED']
|
81
|
-
@storage.resolve_entitystore_uri(uri).
|
82
|
-
should.be.kind_of Rack::Cache::EntityStore
|
83
|
-
end
|
84
|
-
end
|
85
|
-
it 'supports namespaces in memcached: URIs' do
|
86
|
-
uri = "memcached://" + ENV['MEMCACHED'] + "/namespace"
|
87
|
-
@storage.resolve_metastore_uri(uri).
|
88
|
-
should.be.kind_of Rack::Cache::MetaStore
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|