dalli 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dalli might be problematic. Click here for more details.
- data/History.md +9 -0
- data/README.md +42 -3
- data/Rakefile +5 -0
- data/TODO.md +1 -0
- data/Upgrade.md +44 -0
- data/dalli.gemspec +2 -1
- data/lib/action_dispatch/middleware/session/dalli_store.rb +76 -0
- data/lib/active_support/cache/dalli_store.rb +4 -0
- data/lib/active_support/cache/dalli_store23.rb +172 -0
- data/lib/dalli/client.rb +23 -14
- data/lib/dalli/server.rb +0 -2
- data/lib/dalli/version.rb +1 -1
- data/test/abstract_unit.rb +285 -0
- data/test/{test_benchmark.rb → benchmark_test.rb} +0 -0
- data/test/helper.rb +23 -1
- data/test/memcached_mock.rb +2 -7
- data/test/test_active_support.rb +72 -54
- data/test/test_dalli.rb +5 -1
- data/test/test_session_store.rb +200 -0
- metadata +12 -8
- data/lib/dalli/sasl/base64.rb +0 -14
- data/lib/dalli/sasl/digest_md5.rb +0 -175
data/lib/dalli/server.rb
CHANGED
data/lib/dalli/version.rb
CHANGED
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'rails'
|
2
|
+
# Used to test the full Rails stack.
|
3
|
+
# Stolen from the Rails 3.0 source.
|
4
|
+
# Needed for the session store tests.
|
5
|
+
require 'active_support/core_ext/kernel/reporting'
|
6
|
+
require 'active_support/core_ext/string/encoding'
|
7
|
+
if "ruby".encoding_aware?
|
8
|
+
# These are the normal settings that will be set up by Railties
|
9
|
+
# TODO: Have these tests support other combinations of these values
|
10
|
+
silence_warnings do
|
11
|
+
Encoding.default_internal = "UTF-8"
|
12
|
+
Encoding.default_external = "UTF-8"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'test/unit'
|
17
|
+
require 'abstract_controller'
|
18
|
+
require 'action_controller'
|
19
|
+
require 'action_view'
|
20
|
+
require 'action_dispatch'
|
21
|
+
require 'active_support/dependencies'
|
22
|
+
require 'action_controller/caching'
|
23
|
+
require 'action_controller/caching/sweeping'
|
24
|
+
|
25
|
+
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
|
26
|
+
|
27
|
+
module Rails
|
28
|
+
def self.logger
|
29
|
+
@logger ||= begin
|
30
|
+
l = Logger.new(STDOUT)
|
31
|
+
l.level = Logger::INFO; l
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Monkey patch the old routes initialization to be silenced.
|
37
|
+
class ActionDispatch::Routing::DeprecatedMapper
|
38
|
+
def initialize_with_silencer(*args)
|
39
|
+
ActiveSupport::Deprecation.silence { initialize_without_silencer(*args) }
|
40
|
+
end
|
41
|
+
alias_method_chain :initialize, :silencer
|
42
|
+
end
|
43
|
+
|
44
|
+
ActiveSupport::Dependencies.hook!
|
45
|
+
|
46
|
+
# Show backtraces for deprecated behavior for quicker cleanup.
|
47
|
+
ActiveSupport::Deprecation.debug = true
|
48
|
+
|
49
|
+
ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort
|
50
|
+
|
51
|
+
module RackTestUtils
|
52
|
+
def body_to_string(body)
|
53
|
+
if body.respond_to?(:each)
|
54
|
+
str = ""
|
55
|
+
body.each {|s| str << s }
|
56
|
+
str
|
57
|
+
else
|
58
|
+
body
|
59
|
+
end
|
60
|
+
end
|
61
|
+
extend self
|
62
|
+
end
|
63
|
+
|
64
|
+
module SetupOnce
|
65
|
+
extend ActiveSupport::Concern
|
66
|
+
|
67
|
+
included do
|
68
|
+
cattr_accessor :setup_once_block
|
69
|
+
self.setup_once_block = nil
|
70
|
+
|
71
|
+
setup :run_setup_once
|
72
|
+
end
|
73
|
+
|
74
|
+
module ClassMethods
|
75
|
+
def setup_once(&block)
|
76
|
+
self.setup_once_block = block
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def run_setup_once
|
82
|
+
if self.setup_once_block
|
83
|
+
self.setup_once_block.call
|
84
|
+
self.setup_once_block = nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
|
90
|
+
|
91
|
+
module ActiveSupport
|
92
|
+
class TestCase
|
93
|
+
include SetupOnce
|
94
|
+
# Hold off drawing routes until all the possible controller classes
|
95
|
+
# have been loaded.
|
96
|
+
setup_once do
|
97
|
+
SharedTestRoutes.draw do |map|
|
98
|
+
# FIXME: match ':controller(/:action(/:id))'
|
99
|
+
map.connect ':controller/:action/:id'
|
100
|
+
end
|
101
|
+
|
102
|
+
ActionController::IntegrationTest.app.routes.draw do |map|
|
103
|
+
# FIXME: match ':controller(/:action(/:id))'
|
104
|
+
map.connect ':controller/:action/:id'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class RoutedRackApp
|
111
|
+
attr_reader :routes
|
112
|
+
|
113
|
+
def initialize(routes, &blk)
|
114
|
+
@routes = routes
|
115
|
+
@stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
|
116
|
+
end
|
117
|
+
|
118
|
+
def call(env)
|
119
|
+
@stack.call(env)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class BasicController
|
124
|
+
attr_accessor :request
|
125
|
+
|
126
|
+
def config
|
127
|
+
@config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config|
|
128
|
+
# VIEW TODO: View tests should not require a controller
|
129
|
+
public_dir = File.expand_path("../fixtures/public", __FILE__)
|
130
|
+
config.assets_dir = public_dir
|
131
|
+
config.javascripts_dir = "#{public_dir}/javascripts"
|
132
|
+
config.stylesheets_dir = "#{public_dir}/stylesheets"
|
133
|
+
config
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
|
139
|
+
setup do
|
140
|
+
@routes = SharedTestRoutes
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class ActionController::IntegrationTest < ActiveSupport::TestCase
|
145
|
+
def self.build_app(routes = nil)
|
146
|
+
RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
|
147
|
+
middleware.use "ActionDispatch::ShowExceptions"
|
148
|
+
middleware.use "ActionDispatch::Callbacks"
|
149
|
+
middleware.use "ActionDispatch::ParamsParser"
|
150
|
+
middleware.use "ActionDispatch::Cookies"
|
151
|
+
middleware.use "ActionDispatch::Flash"
|
152
|
+
middleware.use "ActionDispatch::Head"
|
153
|
+
yield(middleware) if block_given?
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
self.app = build_app
|
158
|
+
|
159
|
+
# Stub Rails dispatcher so it does not get controller references and
|
160
|
+
# simply return the controller#action as Rack::Body.
|
161
|
+
class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
|
162
|
+
protected
|
163
|
+
def controller_reference(controller_param)
|
164
|
+
controller_param
|
165
|
+
end
|
166
|
+
|
167
|
+
def dispatch(controller, action, env)
|
168
|
+
[200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.stub_controllers
|
173
|
+
old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
|
174
|
+
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
|
175
|
+
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
|
176
|
+
yield ActionDispatch::Routing::RouteSet.new
|
177
|
+
ensure
|
178
|
+
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
|
179
|
+
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
|
180
|
+
end
|
181
|
+
|
182
|
+
def with_routing(&block)
|
183
|
+
temporary_routes = ActionDispatch::Routing::RouteSet.new
|
184
|
+
old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
|
185
|
+
old_routes = SharedTestRoutes
|
186
|
+
silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
|
187
|
+
|
188
|
+
yield temporary_routes
|
189
|
+
ensure
|
190
|
+
self.class.app = old_app
|
191
|
+
silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
|
192
|
+
end
|
193
|
+
|
194
|
+
def with_autoload_path(path)
|
195
|
+
path = File.join(File.dirname(__FILE__), "fixtures", path)
|
196
|
+
if ActiveSupport::Dependencies.autoload_paths.include?(path)
|
197
|
+
yield
|
198
|
+
else
|
199
|
+
begin
|
200
|
+
ActiveSupport::Dependencies.autoload_paths << path
|
201
|
+
yield
|
202
|
+
ensure
|
203
|
+
ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
|
204
|
+
ActiveSupport::Dependencies.clear
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# Temporary base class
|
211
|
+
class Rack::TestCase < ActionController::IntegrationTest
|
212
|
+
def self.testing(klass = nil)
|
213
|
+
if klass
|
214
|
+
@testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
|
215
|
+
else
|
216
|
+
@testing
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def get(thing, *args)
|
221
|
+
if thing.is_a?(Symbol)
|
222
|
+
super("#{self.class.testing}/#{thing}", *args)
|
223
|
+
else
|
224
|
+
super
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def assert_body(body)
|
229
|
+
assert_equal body, Array.wrap(response.body).join
|
230
|
+
end
|
231
|
+
|
232
|
+
def assert_status(code)
|
233
|
+
assert_equal code, response.status
|
234
|
+
end
|
235
|
+
|
236
|
+
def assert_response(body, status = 200, headers = {})
|
237
|
+
assert_body body
|
238
|
+
assert_status status
|
239
|
+
headers.each do |header, value|
|
240
|
+
assert_header header, value
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def assert_content_type(type)
|
245
|
+
assert_equal type, response.headers["Content-Type"]
|
246
|
+
end
|
247
|
+
|
248
|
+
def assert_header(name, value)
|
249
|
+
assert_equal value, response.headers[name]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class ActionController::Base
|
254
|
+
def self.test_routes(&block)
|
255
|
+
routes = ActionDispatch::Routing::RouteSet.new
|
256
|
+
routes.draw(&block)
|
257
|
+
include routes.url_helpers
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class ::ApplicationController < ActionController::Base
|
262
|
+
end
|
263
|
+
|
264
|
+
module ActionController
|
265
|
+
class Base
|
266
|
+
include ActionController::Testing
|
267
|
+
end
|
268
|
+
|
269
|
+
Base.view_paths = []
|
270
|
+
|
271
|
+
class TestCase
|
272
|
+
include ActionDispatch::TestProcess
|
273
|
+
|
274
|
+
setup do
|
275
|
+
@routes = SharedTestRoutes
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# This stub emulates the Railtie including the URL helpers from a Rails application
|
281
|
+
module ActionController
|
282
|
+
class Base
|
283
|
+
include SharedTestRoutes.url_helpers
|
284
|
+
end
|
285
|
+
end
|
File without changes
|
data/test/helper.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
|
3
2
|
# require 'simplecov-html'
|
4
3
|
# SimpleCov.start
|
5
4
|
|
@@ -17,4 +16,27 @@ class Test::Unit::TestCase
|
|
17
16
|
ex = assert_raise(error, &block)
|
18
17
|
assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
|
19
18
|
end
|
19
|
+
|
20
|
+
def with_activesupport
|
21
|
+
case Rails.version
|
22
|
+
when '3.0.0'
|
23
|
+
require 'active_support/all'
|
24
|
+
# when '2.3.0'
|
25
|
+
# require 'active_support'
|
26
|
+
# require 'active_support/cache/dalli_store23'
|
27
|
+
end
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_actionpack
|
32
|
+
case Rails.version
|
33
|
+
when '3.0.0'
|
34
|
+
require 'action_dispatch'
|
35
|
+
require 'action_controller'
|
36
|
+
# when '2.3.0'
|
37
|
+
# raise NotImplementedError
|
38
|
+
end
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
|
20
42
|
end
|
data/test/memcached_mock.rb
CHANGED
@@ -72,13 +72,8 @@ module MemcachedMock
|
|
72
72
|
sleep 0.3
|
73
73
|
yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"])
|
74
74
|
ensure
|
75
|
-
|
76
|
-
|
77
|
-
Process.wait(pid)
|
78
|
-
rescue Errno::ECHILD
|
79
|
-
# the memcached_mock forks will try to run this at_exit block also
|
80
|
-
# but since they are not the parent process, will get an ECHILD error.
|
81
|
-
end
|
75
|
+
Process.kill("TERM", pid)
|
76
|
+
Process.wait(pid)
|
82
77
|
end
|
83
78
|
end
|
84
79
|
end
|
data/test/test_active_support.rb
CHANGED
@@ -1,77 +1,95 @@
|
|
1
1
|
require 'helper'
|
2
|
-
require '
|
3
|
-
require 'active_support/cache/dalli_store'
|
2
|
+
require 'rails'
|
4
3
|
|
5
|
-
class
|
6
|
-
context '
|
4
|
+
class TestActiveSupport < Test::Unit::TestCase
|
5
|
+
context 'active_support caching' do
|
7
6
|
|
8
7
|
should 'support fetch' do
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
with_activesupport do
|
9
|
+
memcached do
|
10
|
+
connect
|
11
|
+
dvalue = @mc.fetch('somekeywithoutspaces', :expires_in => 1.second) { 123 }
|
12
|
+
mvalue = @dalli.fetch('someotherkeywithoutspaces', :expires_in => 1.second) { 123 }
|
13
|
+
assert_equal mvalue, dvalue
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
o = Object.new
|
16
|
+
o.instance_variable_set :@foo, 'bar'
|
17
|
+
dvalue = @mc.fetch(rand_key, :raw => true) { o }
|
18
|
+
mvalue = @dalli.fetch(rand_key, :raw => true) { o }
|
19
|
+
assert_equal mvalue, dvalue
|
20
|
+
assert_equal o, dvalue
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
dvalue = @mc.fetch(rand_key) { o }
|
23
|
+
mvalue = @dalli.fetch(rand_key) { o }
|
24
|
+
assert_equal mvalue, dvalue
|
25
|
+
assert_equal o, dvalue
|
26
|
+
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
30
|
+
should 'support keys with spaces' do
|
31
|
+
with_activesupport do
|
32
|
+
memcached do
|
33
|
+
connect
|
34
|
+
dvalue = @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
|
35
|
+
mvalue = @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
|
36
|
+
assert_equal mvalue, dvalue
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
29
41
|
should 'support read_multi' do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
with_activesupport do
|
43
|
+
memcached do
|
44
|
+
connect
|
45
|
+
x = rand_key
|
46
|
+
y = rand_key
|
47
|
+
assert_equal({}, @mc.read_multi(x, y))
|
48
|
+
assert_equal({}, @dalli.read_multi(x, y))
|
49
|
+
@dalli.write(x, '123')
|
50
|
+
@dalli.write(y, 123)
|
51
|
+
@mc.write(x, '123')
|
52
|
+
@mc.write(y, 123)
|
53
|
+
assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
|
54
|
+
assert_equal({ x => '123', y => 123 }, @mc.read_multi(x, y))
|
55
|
+
end
|
42
56
|
end
|
43
57
|
end
|
44
58
|
|
45
59
|
should 'support read, write and delete' do
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
with_activesupport do
|
61
|
+
memcached do
|
62
|
+
connect
|
63
|
+
x = rand_key
|
64
|
+
y = rand_key
|
65
|
+
assert_nil @mc.read(x)
|
66
|
+
assert_nil @dalli.read(y)
|
67
|
+
mres = @mc.write(x, 123)
|
68
|
+
dres = @dalli.write(y, 123)
|
69
|
+
assert_equal mres, dres
|
55
70
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
71
|
+
mres = @mc.read(x)
|
72
|
+
dres = @dalli.read(y)
|
73
|
+
assert_equal mres, dres
|
74
|
+
assert_equal 123, dres
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
76
|
+
mres = @mc.delete(x)
|
77
|
+
dres = @dalli.delete(y)
|
78
|
+
assert_equal mres, dres
|
79
|
+
assert_equal true, dres
|
80
|
+
end
|
65
81
|
end
|
66
82
|
end
|
67
83
|
|
68
84
|
should 'support other esoteric commands' do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
85
|
+
with_activesupport do
|
86
|
+
memcached do
|
87
|
+
connect
|
88
|
+
ms = @mc.stats
|
89
|
+
ds = @dalli.stats
|
90
|
+
assert_equal ms.keys.sort, ds.keys.sort
|
91
|
+
assert_equal ms[ms.keys.first].keys.sort, ds[ds.keys.first].keys.sort
|
92
|
+
end
|
75
93
|
end
|
76
94
|
end
|
77
95
|
end
|