libmemcached_store 0.7.0 → 0.7.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.
- data/lib/active_support/cache/libmemcached_store.rb +1 -1
- data/lib/{version.rb → memcached/version.rb} +1 -1
- metadata +9 -34
- data/.gitignore +0 -4
- data/.travis.yml +0 -10
- data/BENCHMARKS +0 -37
- data/CHANGELOG.md +0 -31
- data/Gemfile +0 -7
- data/MIT-LICENSE +0 -20
- data/README.md +0 -78
- data/Rakefile +0 -24
- data/gemfiles/rails30.gemfile +0 -7
- data/gemfiles/rails31.gemfile +0 -7
- data/gemfiles/rails32.gemfile +0 -7
- data/gemfiles/rails40.gemfile +0 -7
- data/libmemcached_store.gemspec +0 -31
- data/test/action_dispatch/abstract_unit.rb +0 -51
- data/test/action_dispatch/libmemcached_store_test.rb +0 -200
- data/test/active_support/libmemcached_store_test.rb +0 -388
- data/test/fixtures/session_autoload_test.rb +0 -10
- data/test/profile/benchmark.rb +0 -94
- data/test/test_helper.rb +0 -6
|
@@ -88,7 +88,7 @@ module ActiveSupport
|
|
|
88
88
|
|
|
89
89
|
def fetch(key, options = nil, &block)
|
|
90
90
|
if block_given?
|
|
91
|
-
if options && options[:race_condition_ttl]
|
|
91
|
+
if options && options[:race_condition_ttl] && options[:expires_in]
|
|
92
92
|
fetch_with_race_condition_ttl(key, options, &block)
|
|
93
93
|
else
|
|
94
94
|
key = expanded_key(key)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libmemcached_store
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2014-06-14 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: memcached
|
|
@@ -82,17 +82,17 @@ dependencies:
|
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
83
83
|
none: false
|
|
84
84
|
requirements:
|
|
85
|
-
- -
|
|
85
|
+
- - ! '>='
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '
|
|
87
|
+
version: '0'
|
|
88
88
|
type: :development
|
|
89
89
|
prerelease: false
|
|
90
90
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
91
|
none: false
|
|
92
92
|
requirements:
|
|
93
|
-
- -
|
|
93
|
+
- - ! '>='
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
95
|
+
version: '0'
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: activesupport
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -134,30 +134,11 @@ executables: []
|
|
|
134
134
|
extensions: []
|
|
135
135
|
extra_rdoc_files: []
|
|
136
136
|
files:
|
|
137
|
-
- .gitignore
|
|
138
|
-
- .travis.yml
|
|
139
|
-
- BENCHMARKS
|
|
140
|
-
- CHANGELOG.md
|
|
141
|
-
- Gemfile
|
|
142
|
-
- MIT-LICENSE
|
|
143
|
-
- README.md
|
|
144
|
-
- Rakefile
|
|
145
|
-
- gemfiles/rails30.gemfile
|
|
146
|
-
- gemfiles/rails31.gemfile
|
|
147
|
-
- gemfiles/rails32.gemfile
|
|
148
|
-
- gemfiles/rails40.gemfile
|
|
149
137
|
- lib/action_dispatch/session/libmemcached_store.rb
|
|
150
138
|
- lib/active_support/cache/libmemcached_store.rb
|
|
151
139
|
- lib/libmemcached_store.rb
|
|
152
140
|
- lib/memcached/get_with_flags.rb
|
|
153
|
-
- lib/version.rb
|
|
154
|
-
- libmemcached_store.gemspec
|
|
155
|
-
- test/action_dispatch/abstract_unit.rb
|
|
156
|
-
- test/action_dispatch/libmemcached_store_test.rb
|
|
157
|
-
- test/active_support/libmemcached_store_test.rb
|
|
158
|
-
- test/fixtures/session_autoload_test.rb
|
|
159
|
-
- test/profile/benchmark.rb
|
|
160
|
-
- test/test_helper.rb
|
|
141
|
+
- lib/memcached/version.rb
|
|
161
142
|
homepage: http://github.com/ccocchi/libmemcached_store
|
|
162
143
|
licenses: []
|
|
163
144
|
post_install_message:
|
|
@@ -178,14 +159,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
178
159
|
version: '0'
|
|
179
160
|
requirements: []
|
|
180
161
|
rubyforge_project:
|
|
181
|
-
rubygems_version: 1.8.
|
|
162
|
+
rubygems_version: 1.8.23
|
|
182
163
|
signing_key:
|
|
183
164
|
specification_version: 3
|
|
184
165
|
summary: ActiveSupport 3+ cache store for the C-based libmemcached client
|
|
185
|
-
test_files:
|
|
186
|
-
- test/action_dispatch/abstract_unit.rb
|
|
187
|
-
- test/action_dispatch/libmemcached_store_test.rb
|
|
188
|
-
- test/active_support/libmemcached_store_test.rb
|
|
189
|
-
- test/fixtures/session_autoload_test.rb
|
|
190
|
-
- test/profile/benchmark.rb
|
|
191
|
-
- test/test_helper.rb
|
|
166
|
+
test_files: []
|
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/BENCHMARKS
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
Testing with
|
|
2
|
-
ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
|
|
3
|
-
Dalli 2.6.3
|
|
4
|
-
Libmemcached_store 0.6.0
|
|
5
|
-
user system total real
|
|
6
|
-
write:short:dalli 0.380000 0.040000 0.420000 ( 0.422342)
|
|
7
|
-
write:short:libm 0.040000 0.020000 0.060000 ( 0.125838)
|
|
8
|
-
write:long:dalli 0.370000 0.040000 0.410000 ( 0.407400)
|
|
9
|
-
write:long:libm 0.050000 0.030000 0.080000 ( 0.130482)
|
|
10
|
-
write:raw:dalli 0.330000 0.030000 0.360000 ( 0.371981)
|
|
11
|
-
write:raw:libm 0.050000 0.030000 0.080000 ( 0.122899)
|
|
12
|
-
|
|
13
|
-
read:miss:dalli 0.310000 0.040000 0.350000 ( 0.352729)
|
|
14
|
-
read:miss:libm 0.080000 0.040000 0.120000 ( 0.182143)
|
|
15
|
-
read:miss2:dalli 0.350000 0.040000 0.390000 ( 0.394071)
|
|
16
|
-
read:miss2:libm 0.090000 0.050000 0.140000 ( 0.190611)
|
|
17
|
-
read:exist:dalli 0.350000 0.040000 0.390000 ( 0.391384)
|
|
18
|
-
read:exist:libm 0.060000 0.040000 0.100000 ( 0.161597)
|
|
19
|
-
read:expired:dalli 0.350000 0.040000 0.390000 ( 0.399342)
|
|
20
|
-
read:expired:libm 0.080000 0.050000 0.130000 ( 0.175674)
|
|
21
|
-
read:raw:dalli 0.360000 0.040000 0.400000 ( 0.400142)
|
|
22
|
-
read:raw:libm 0.050000 0.040000 0.090000 ( 0.160905)
|
|
23
|
-
|
|
24
|
-
exist:miss:dalli 0.310000 0.040000 0.350000 ( 0.342454)
|
|
25
|
-
exist:miss:libm 0.040000 0.030000 0.070000 ( 0.141901)
|
|
26
|
-
exist:hit:dalli 0.320000 0.040000 0.360000 ( 0.354205)
|
|
27
|
-
exist:hit:libm 0.030000 0.020000 0.050000 ( 0.107114)
|
|
28
|
-
|
|
29
|
-
delete:miss:dalli 0.310000 0.040000 0.350000 ( 0.342343)
|
|
30
|
-
delete:miss:libm 0.060000 0.030000 0.090000 ( 0.141960)
|
|
31
|
-
delete:hit:dalli 0.350000 0.040000 0.390000 ( 0.389187)
|
|
32
|
-
delete:hit:libm 0.050000 0.020000 0.070000 ( 0.130604)
|
|
33
|
-
|
|
34
|
-
increment:dalli 0.380000 0.050000 0.430000 ( 0.422802)
|
|
35
|
-
increment:libm 0.040000 0.020000 0.060000 ( 0.119200)
|
|
36
|
-
decrement:dalli 0.390000 0.040000 0.430000 ( 0.426890)
|
|
37
|
-
decrement:libm 0.030000 0.030000 0.060000 ( 0.118954)
|
data/CHANGELOG.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.7.0
|
|
4
|
-
* Add support for memcached 1.7 (grosser)
|
|
5
|
-
* Test with Rails 4 (grosser)
|
|
6
|
-
* Add race_condition_ttl option to #fetch (grosser)
|
|
7
|
-
|
|
8
|
-
## 0.6.2
|
|
9
|
-
* Add :hit to the #fetch payload
|
|
10
|
-
|
|
11
|
-
## 0.6.1
|
|
12
|
-
* Subclass Memcached instead of modifying the instance (staugaard)
|
|
13
|
-
|
|
14
|
-
## 0.6.0
|
|
15
|
-
* New gem name _libmemcached_store_
|
|
16
|
-
* Handle Memcached::Error in read_multi (staugaard)
|
|
17
|
-
|
|
18
|
-
## 0.5.1
|
|
19
|
-
* Remove warning from latest version of mocha
|
|
20
|
-
* Make #clear compatible with Rails.cache#clear (grosser)
|
|
21
|
-
|
|
22
|
-
## 0.5.0
|
|
23
|
-
* Use Memcached#exist if available (performance improvement ~25%)
|
|
24
|
-
* Correctly escape bad characters and too long keys
|
|
25
|
-
* Add benchmarks
|
|
26
|
-
* Remove the use of ActiveSupport::Entry which was a performance bottleneck #3
|
|
27
|
-
|
|
28
|
-
## 0.4.0
|
|
29
|
-
* Optimize read_multi to only make one call to memecached server
|
|
30
|
-
* Update test suite to reflect Rails' one
|
|
31
|
-
* Add session store tests
|
data/Gemfile
DELETED
data/MIT-LICENSE
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2008 37signals
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
-
a copy of this software and associated documentation files (the
|
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
-
the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
|
12
|
-
included in all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# LibmemcachedStore
|
|
2
|
-
|
|
3
|
-
An ActiveSupport cache store that uses the C-based libmemcached client through Evan Weaver's Ruby/SWIG wrapper, [memcached](https://github.com/evan/memcached). libmemcached is fast (fastest memcache client for Ruby), lightweight, and supports consistent hashing, non-blocking IO, and graceful server failover.
|
|
4
|
-
|
|
5
|
-
This cache is designed for Rails 3+ applications.
|
|
6
|
-
|
|
7
|
-
## Prerequisites
|
|
8
|
-
|
|
9
|
-
You'll need the memcached gem installed:
|
|
10
|
-
|
|
11
|
-
```ruby
|
|
12
|
-
gem install memcached
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
or in your Gemfile
|
|
16
|
-
|
|
17
|
-
```ruby
|
|
18
|
-
gem 'memcached'
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
There are no other dependencies.
|
|
22
|
-
|
|
23
|
-
## Installation
|
|
24
|
-
|
|
25
|
-
Just add to your Gemfile
|
|
26
|
-
|
|
27
|
-
```ruby
|
|
28
|
-
gem 'libmemcached_store', '~> 0.6.0'
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
and you're set.
|
|
32
|
-
|
|
33
|
-
## Usage
|
|
34
|
-
|
|
35
|
-
This is a drop-in replacement for the memcache store that ships with Rails. To
|
|
36
|
-
enable, set the `config.cache_store` option to `libmemcached_store`
|
|
37
|
-
in the config for your environment
|
|
38
|
-
|
|
39
|
-
```ruby
|
|
40
|
-
config.cache_store = :libmemcached_store
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
If no servers are specified, localhost is assumed. You can specify a list of
|
|
44
|
-
server addresses, either as hostnames or IP addresses, with or without a port
|
|
45
|
-
designation. If no port is given, 11211 is assumed:
|
|
46
|
-
|
|
47
|
-
```ruby
|
|
48
|
-
config.cache_store = :libmemcached_store, %w(cache-01 cache-02 127.0.0.1:11212)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Standard Rails cache store options can be used
|
|
52
|
-
|
|
53
|
-
```ruby
|
|
54
|
-
config.cache_store = :libmemcached_store, '127.0.0.1:11211', {:compress => true, :expires_in => 3600}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
More advanced options can be passed directly to the client
|
|
58
|
-
|
|
59
|
-
```ruby
|
|
60
|
-
config.cache_store = :libmemcached_store, '127.0.0.1:11211', {:client => { :binary_protocol => true, :no_block => true }}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
You can also use `:libmemcached_store` to store your application sessions
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
require 'action_dispatch/session/libmemcached_store'
|
|
67
|
-
config.session_store = :libmemcached_store, :namespace => '_session', :expire_after => 1800
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Performance
|
|
71
|
-
|
|
72
|
-
Used with Rails, __libmemcached_store__ is at least 1.5x faster than __dalli__. See [BENCHMARKS](https://github.com/ccocchi/libmemcached_store/blob/master/BENCHMARKS)
|
|
73
|
-
for details
|
|
74
|
-
|
|
75
|
-
## Props
|
|
76
|
-
|
|
77
|
-
Thanks to Brian Aker ([http://tangent.org](http://tangent.org)) for creating libmemcached, and Evan
|
|
78
|
-
Weaver ([http://blog.evanweaver.com](http://blog.evanweaver.com)) for the Ruby wrapper.
|
data/Rakefile
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
require 'bundler/setup'
|
|
3
|
-
|
|
4
|
-
require 'rake'
|
|
5
|
-
require 'rake/testtask'
|
|
6
|
-
require 'rdoc/task'
|
|
7
|
-
|
|
8
|
-
task :default => :test
|
|
9
|
-
|
|
10
|
-
Rake::TestTask.new do |t|
|
|
11
|
-
t.libs << 'test'
|
|
12
|
-
t.pattern = 'test/**/*_test.rb'
|
|
13
|
-
t.warning = false
|
|
14
|
-
t.verbose = true
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
desc 'Generate documentation for the libmemcached_store plugin.'
|
|
18
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
19
|
-
rdoc.rdoc_dir = 'rdoc'
|
|
20
|
-
rdoc.title = 'LibmemcachedStore'
|
|
21
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
|
22
|
-
rdoc.rdoc_files.include('README')
|
|
23
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
24
|
-
end
|
data/gemfiles/rails30.gemfile
DELETED
data/gemfiles/rails31.gemfile
DELETED
data/gemfiles/rails32.gemfile
DELETED
data/gemfiles/rails40.gemfile
DELETED
data/libmemcached_store.gemspec
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
-
require "version"
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |s|
|
|
6
|
-
s.name = "libmemcached_store"
|
|
7
|
-
s.version = LibmemcachedStore::VERSION.dup
|
|
8
|
-
s.platform = Gem::Platform::RUBY
|
|
9
|
-
s.summary = "ActiveSupport 3+ cache store for the C-based libmemcached client"
|
|
10
|
-
s.email = "cocchi.c@gmail.com"
|
|
11
|
-
s.homepage = "http://github.com/ccocchi/libmemcached_store"
|
|
12
|
-
s.description = %q{An ActiveSupport cache store that uses the C-based libmemcached client through
|
|
13
|
-
Evan Weaver's Ruby/SWIG wrapper, memcached. libmemcached is fast, lightweight,
|
|
14
|
-
and supports consistent hashing, non-blocking IO, and graceful server failover.}
|
|
15
|
-
s.authors = ["Christopher Cocchi-Perrier", "Ben Hutton", "Jeffrey Hardy"]
|
|
16
|
-
|
|
17
|
-
s.files = `git ls-files`.split("\n")
|
|
18
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
-
s.require_paths = ["lib"]
|
|
21
|
-
|
|
22
|
-
s.add_dependency("memcached", ">= 0")
|
|
23
|
-
|
|
24
|
-
s.add_development_dependency('rack')
|
|
25
|
-
s.add_development_dependency('rake')
|
|
26
|
-
s.add_development_dependency('mocha')
|
|
27
|
-
s.add_development_dependency('minitest', '~> 4.7')
|
|
28
|
-
s.add_development_dependency('activesupport', '>= 3')
|
|
29
|
-
s.add_development_dependency('actionpack', '>= 3')
|
|
30
|
-
end
|
|
31
|
-
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
require 'active_support'
|
|
2
|
-
require 'active_support/core_ext/module/delegation'
|
|
3
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
|
4
|
-
require 'action_controller'
|
|
5
|
-
require 'action_dispatch/routing'
|
|
6
|
-
if ActionPack::VERSION::MAJOR >= 4
|
|
7
|
-
require 'rack/head'
|
|
8
|
-
else
|
|
9
|
-
require 'action_dispatch/middleware/head'
|
|
10
|
-
end
|
|
11
|
-
require 'action_dispatch/testing/assertions'
|
|
12
|
-
require 'action_dispatch/testing/test_process'
|
|
13
|
-
require 'action_dispatch/testing/integration'
|
|
14
|
-
|
|
15
|
-
SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
|
|
16
|
-
|
|
17
|
-
class RoutedRackApp
|
|
18
|
-
attr_reader :routes
|
|
19
|
-
|
|
20
|
-
def initialize(routes, &blk)
|
|
21
|
-
@routes = routes
|
|
22
|
-
@stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def call(env)
|
|
26
|
-
@stack.call(env)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
|
|
31
|
-
def self.build_app(routes = nil)
|
|
32
|
-
RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
|
|
33
|
-
if defined?(ActionDispatch::PublicExceptions)
|
|
34
|
-
middleware.use "ActionDispatch::ShowExceptions", ActionDispatch::PublicExceptions.new("/dev/null")
|
|
35
|
-
middleware.use "ActionDispatch::DebugExceptions"
|
|
36
|
-
else
|
|
37
|
-
middleware.use "ActionDispatch::ShowExceptions"
|
|
38
|
-
end
|
|
39
|
-
middleware.use "ActionDispatch::Callbacks"
|
|
40
|
-
middleware.use "ActionDispatch::ParamsParser"
|
|
41
|
-
middleware.use "ActionDispatch::Cookies"
|
|
42
|
-
middleware.use "ActionDispatch::Flash"
|
|
43
|
-
if ActionPack::VERSION::MAJOR >= 4
|
|
44
|
-
middleware.use "Rack::Head"
|
|
45
|
-
else
|
|
46
|
-
middleware.use "ActionDispatch::Head"
|
|
47
|
-
end
|
|
48
|
-
yield(middleware) if block_given?
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
require_relative '../test_helper'
|
|
2
|
-
require File.expand_path('../abstract_unit', __FILE__)
|
|
3
|
-
require 'action_dispatch/session/libmemcached_store'
|
|
4
|
-
|
|
5
|
-
class LibMemcachedStoreTest < ActionDispatch::IntegrationTest
|
|
6
|
-
class TestController < ActionController::Base
|
|
7
|
-
def no_session_access
|
|
8
|
-
head :ok
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def set_session_value
|
|
12
|
-
session[:foo] = "bar"
|
|
13
|
-
head :ok
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def set_serialized_session_value
|
|
17
|
-
session[:foo] = SessionAutoloadTest::Foo.new
|
|
18
|
-
head :ok
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def get_session_value
|
|
22
|
-
render :text => "foo: #{session[:foo].inspect}"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def get_session_id
|
|
26
|
-
render :text => "#{request.session_options[:id]}"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def call_reset_session
|
|
30
|
-
session[:bar]
|
|
31
|
-
reset_session
|
|
32
|
-
session[:bar] = "baz"
|
|
33
|
-
head :ok
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def self._routes
|
|
37
|
-
SharedTestRoutes
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
test "setting and getting session value" do
|
|
42
|
-
with_test_route_set do
|
|
43
|
-
get '/set_session_value'
|
|
44
|
-
assert_response :success
|
|
45
|
-
assert cookies['_session_id']
|
|
46
|
-
|
|
47
|
-
get '/get_session_value'
|
|
48
|
-
assert_response :success
|
|
49
|
-
assert_equal 'foo: "bar"', response.body
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
test "getting nil session value" do
|
|
54
|
-
with_test_route_set do
|
|
55
|
-
get '/get_session_value'
|
|
56
|
-
assert_response :success
|
|
57
|
-
assert_equal 'foo: nil', response.body
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
test "getting session value after session reset" do
|
|
62
|
-
with_test_route_set do
|
|
63
|
-
get '/set_session_value'
|
|
64
|
-
assert_response :success
|
|
65
|
-
assert cookies['_session_id']
|
|
66
|
-
session_cookie = cookies.send(:hash_for)['_session_id']
|
|
67
|
-
|
|
68
|
-
get '/call_reset_session'
|
|
69
|
-
assert_response :success
|
|
70
|
-
assert_not_equal [], headers['Set-Cookie']
|
|
71
|
-
|
|
72
|
-
cookies << session_cookie # replace our new session_id with our old, pre-reset session_id
|
|
73
|
-
|
|
74
|
-
get '/get_session_value'
|
|
75
|
-
assert_response :success
|
|
76
|
-
assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from memcached"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
test "getting from nonexistent session" do
|
|
81
|
-
with_test_route_set do
|
|
82
|
-
get '/get_session_value'
|
|
83
|
-
assert_response :success
|
|
84
|
-
assert_equal 'foo: nil', response.body
|
|
85
|
-
assert_nil cookies['_session_id'], "should only create session on write, not read"
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
test "setting session value after session reset" do
|
|
90
|
-
with_test_route_set do
|
|
91
|
-
get '/set_session_value'
|
|
92
|
-
assert_response :success
|
|
93
|
-
assert cookies['_session_id']
|
|
94
|
-
session_id = cookies['_session_id']
|
|
95
|
-
|
|
96
|
-
get '/call_reset_session'
|
|
97
|
-
assert_response :success
|
|
98
|
-
assert_not_equal [], headers['Set-Cookie']
|
|
99
|
-
|
|
100
|
-
get '/get_session_value'
|
|
101
|
-
assert_response :success
|
|
102
|
-
assert_equal 'foo: nil', response.body
|
|
103
|
-
|
|
104
|
-
get '/get_session_id'
|
|
105
|
-
assert_response :success
|
|
106
|
-
assert_not_equal session_id, response.body
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
test "getting session id" do
|
|
111
|
-
with_test_route_set do
|
|
112
|
-
get '/set_session_value'
|
|
113
|
-
assert_response :success
|
|
114
|
-
assert cookies['_session_id']
|
|
115
|
-
session_id = cookies['_session_id']
|
|
116
|
-
|
|
117
|
-
get '/get_session_id'
|
|
118
|
-
assert_response :success
|
|
119
|
-
assert_equal session_id, response.body, "should be able to read session id without accessing the session hash"
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
test "deserializes unloaded class" do
|
|
124
|
-
with_test_route_set do
|
|
125
|
-
with_autoload_path "session_autoload_test" do
|
|
126
|
-
get '/set_serialized_session_value'
|
|
127
|
-
assert_response :success
|
|
128
|
-
assert cookies['_session_id']
|
|
129
|
-
end
|
|
130
|
-
with_autoload_path "session_autoload_test" do
|
|
131
|
-
get '/get_session_id'
|
|
132
|
-
assert_response :success
|
|
133
|
-
end
|
|
134
|
-
with_autoload_path "session_autoload_test" do
|
|
135
|
-
get '/get_session_value'
|
|
136
|
-
assert_response :success
|
|
137
|
-
assert_equal 'foo: #<SessionAutoloadTest::Foo bar:"baz">', response.body, "should auto-load unloaded class"
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
test "doesnt write session cookie if session id is already exists" do
|
|
143
|
-
with_test_route_set do
|
|
144
|
-
get '/set_session_value'
|
|
145
|
-
assert_response :success
|
|
146
|
-
assert cookies['_session_id']
|
|
147
|
-
|
|
148
|
-
get '/get_session_value'
|
|
149
|
-
assert_response :success
|
|
150
|
-
assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists"
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
test "prevents session fixation" do
|
|
155
|
-
with_test_route_set do
|
|
156
|
-
get '/get_session_value'
|
|
157
|
-
assert_response :success
|
|
158
|
-
assert_equal 'foo: nil', response.body
|
|
159
|
-
session_id = cookies['_session_id']
|
|
160
|
-
|
|
161
|
-
reset!
|
|
162
|
-
|
|
163
|
-
get '/set_session_value', :_session_id => session_id
|
|
164
|
-
assert_response :success
|
|
165
|
-
assert_not_equal session_id, cookies['_session_id']
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
private
|
|
170
|
-
|
|
171
|
-
def with_test_route_set
|
|
172
|
-
with_routing do |set|
|
|
173
|
-
set.draw do
|
|
174
|
-
get ':action', :to => TestController
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
@app = self.class.build_app(set) do |middleware|
|
|
178
|
-
middleware.use ActionDispatch::Session::LibmemcachedStore, :key => '_session_id'
|
|
179
|
-
middleware.delete "ActionDispatch::ShowExceptions"
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
yield
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def with_autoload_path(path)
|
|
187
|
-
path = File.join(File.dirname(__FILE__), "../fixtures", path)
|
|
188
|
-
if ActiveSupport::Dependencies.autoload_paths.include?(path)
|
|
189
|
-
yield
|
|
190
|
-
else
|
|
191
|
-
begin
|
|
192
|
-
ActiveSupport::Dependencies.autoload_paths << path
|
|
193
|
-
yield
|
|
194
|
-
ensure
|
|
195
|
-
ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
|
|
196
|
-
ActiveSupport::Dependencies.clear
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require_relative '../test_helper'
|
|
4
|
-
require 'memcached'
|
|
5
|
-
require 'active_support'
|
|
6
|
-
require 'active_support/core_ext/module/aliasing'
|
|
7
|
-
require 'active_support/core_ext/object/duplicable'
|
|
8
|
-
require 'active_support/cache/libmemcached_store'
|
|
9
|
-
|
|
10
|
-
# Make it easier to get at the underlying cache options during testing.
|
|
11
|
-
ActiveSupport::Cache::LibmemcachedStore.class_eval do
|
|
12
|
-
def client_options
|
|
13
|
-
@cache.options
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe ActiveSupport::Cache::LibmemcachedStore do
|
|
18
|
-
class MockUser
|
|
19
|
-
def cache_key
|
|
20
|
-
'foo'
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
before do
|
|
25
|
-
@cache = ActiveSupport::Cache.lookup_store(:libmemcached_store, expires_in: 60)
|
|
26
|
-
@cache.clear
|
|
27
|
-
@cache.silence!
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
describe "cache store behavior" do
|
|
31
|
-
def really_long_keys_test
|
|
32
|
-
key = "a" * 251
|
|
33
|
-
assert @cache.write(key, "bar")
|
|
34
|
-
assert_equal "bar", @cache.read(key)
|
|
35
|
-
assert_equal "bar", @cache.fetch(key)
|
|
36
|
-
assert_nil @cache.read("#{key}x")
|
|
37
|
-
assert_equal({key => "bar"}, @cache.read_multi(key))
|
|
38
|
-
assert @cache.delete(key)
|
|
39
|
-
refute @cache.exist?(key)
|
|
40
|
-
assert @cache.write(key, '2', :raw => true)
|
|
41
|
-
assert_equal 3, @cache.increment(key)
|
|
42
|
-
assert_equal 2, @cache.decrement(key)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it "fetch_without_cache_miss" do
|
|
46
|
-
@cache.write('foo', 'bar')
|
|
47
|
-
@cache.expects(:write_entry).never
|
|
48
|
-
assert_equal 'bar', @cache.fetch('foo') { 'baz' }
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "fetch_with_cache_miss" do
|
|
52
|
-
@cache.expects(:write_entry).with('foo', 'baz', nil)
|
|
53
|
-
assert_equal 'baz', @cache.fetch('foo') { 'baz' }
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
it "fetch_with_forced_cache_miss" do
|
|
57
|
-
@cache.write('foo', 'bar')
|
|
58
|
-
@cache.expects(:read_entry).never
|
|
59
|
-
@cache.expects(:write_entry).with('foo', 'baz', force: true)
|
|
60
|
-
assert_equal 'baz', @cache.fetch('foo', force: true) { 'baz' }
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it "fetch_with_cached_false" do
|
|
64
|
-
@cache.write('foo', false)
|
|
65
|
-
refute @cache.fetch('foo') { raise }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it "fetch_with_raw_object" do
|
|
69
|
-
o = Object.new
|
|
70
|
-
o.instance_variable_set :@foo, 'bar'
|
|
71
|
-
assert_equal o, @cache.fetch('foo', raw: true) { o }
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "fetch_with_cache_key" do
|
|
75
|
-
u = MockUser.new
|
|
76
|
-
@cache.write(u.cache_key, 'bar')
|
|
77
|
-
assert_equal 'bar', @cache.fetch(u) { raise }
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "should_read_and_write_strings" do
|
|
81
|
-
assert @cache.write('foo', 'bar')
|
|
82
|
-
assert_equal 'bar', @cache.read('foo')
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "should_read_and_write_hash" do
|
|
86
|
-
assert @cache.write('foo', { a: 'b' })
|
|
87
|
-
assert_equal({ a: 'b' }, @cache.read('foo'))
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it "should_read_and_write_integer" do
|
|
91
|
-
assert @cache.write('foo', 1)
|
|
92
|
-
assert_equal 1, @cache.read('foo')
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "should_read_and_write_nil" do
|
|
96
|
-
assert @cache.write('foo', nil)
|
|
97
|
-
assert_equal nil, @cache.read('foo')
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it "should_read_and_write_false" do
|
|
101
|
-
assert @cache.write('foo', false)
|
|
102
|
-
assert_equal false, @cache.read('foo')
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it "read_and_write_compressed_data" do
|
|
106
|
-
@cache.write('foo', 'bar', :compress => true, :compress_threshold => 1)
|
|
107
|
-
assert_equal 'bar', @cache.read('foo')
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
it "write_should_overwrite" do
|
|
111
|
-
@cache.write('foo', 'bar')
|
|
112
|
-
@cache.write('foo', 'baz')
|
|
113
|
-
assert_equal 'baz', @cache.read('foo')
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it "write_compressed_data" do
|
|
117
|
-
@cache.write('foo', 'bar', :compress => true, :compress_threshold => 1, :raw => true)
|
|
118
|
-
assert_equal Zlib::Deflate.deflate('bar'), @cache.instance_variable_get(:@cache).get('foo', false)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
it "read_miss" do
|
|
122
|
-
assert_nil @cache.read('foo')
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
it "read_should_return_a_different_object_id_each_time_it_is_called" do
|
|
126
|
-
@cache.write('foo', 'bar')
|
|
127
|
-
refute_equal @cache.read('foo').object_id, @cache.read('foo').object_id
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
it "read_multi" do
|
|
131
|
-
@cache.write('foo', 'bar')
|
|
132
|
-
@cache.write('fu', 'baz')
|
|
133
|
-
@cache.write('fud', 'biz')
|
|
134
|
-
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it "read_multi_with_array" do
|
|
138
|
-
@cache.write('foo', 'bar')
|
|
139
|
-
@cache.write('fu', 'baz')
|
|
140
|
-
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi(['foo', 'fu']))
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "read_multi_with_raw" do
|
|
144
|
-
@cache.write('foo', 'bar', :raw => true)
|
|
145
|
-
@cache.write('fu', 'baz', :raw => true)
|
|
146
|
-
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "read_multi_with_compress" do
|
|
150
|
-
@cache.write('foo', 'bar', :compress => true, :compress_threshold => 1)
|
|
151
|
-
@cache.write('fu', 'baz', :compress => true, :compress_threshold => 1)
|
|
152
|
-
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "cache_key" do
|
|
156
|
-
o = MockUser.new
|
|
157
|
-
@cache.write(o, 'bar')
|
|
158
|
-
assert_equal 'bar', @cache.read('foo')
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it "param_as_cache_key" do
|
|
162
|
-
obj = Object.new
|
|
163
|
-
def obj.to_param
|
|
164
|
-
'foo'
|
|
165
|
-
end
|
|
166
|
-
@cache.write(obj, 'bar')
|
|
167
|
-
assert_equal 'bar', @cache.read('foo')
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
it "array_as_cache_key" do
|
|
171
|
-
@cache.write([:fu, 'foo'], 'bar')
|
|
172
|
-
assert_equal 'bar', @cache.read('fu/foo')
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
it "hash_as_cache_key" do
|
|
176
|
-
@cache.write({:foo => 1, :fu => 2}, 'bar')
|
|
177
|
-
assert_equal 'bar', @cache.read('foo=1/fu=2')
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
it "keys_are_case_sensitive" do
|
|
181
|
-
@cache.write('foo', 'bar')
|
|
182
|
-
assert_nil @cache.read('FOO')
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
it "keys_with_spaces" do
|
|
186
|
-
assert_equal 'baz', @cache.fetch('foo bar') { 'baz' }
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
it "exist" do
|
|
190
|
-
@cache.write('foo', 'bar')
|
|
191
|
-
assert @cache.exist?('foo')
|
|
192
|
-
refute @cache.exist?('bar')
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
it "delete" do
|
|
196
|
-
@cache.write('foo', 'bar')
|
|
197
|
-
assert @cache.exist?('foo')
|
|
198
|
-
assert @cache.delete('foo')
|
|
199
|
-
refute @cache.exist?('foo')
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
it "delete_with_unexistent_key" do
|
|
203
|
-
@cache.expects(:log_error).never
|
|
204
|
-
refute @cache.exist?('foo')
|
|
205
|
-
refute @cache.delete('foo')
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
it "store_objects_should_be_immutable" do
|
|
209
|
-
@cache.write('foo', 'bar')
|
|
210
|
-
@cache.read('foo').gsub!(/.*/, 'baz')
|
|
211
|
-
assert_equal 'bar', @cache.read('foo')
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
it "original_store_objects_should_not_be_immutable" do
|
|
215
|
-
bar = 'bar'
|
|
216
|
-
@cache.write('foo', bar)
|
|
217
|
-
assert_equal 'baz', bar.gsub!(/r/, 'z')
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
it "crazy_key_characters" do
|
|
221
|
-
crazy_key = "#/:*(<+=> )&$%@?;'\"\'`~-"
|
|
222
|
-
assert @cache.write(crazy_key, "1", :raw => true)
|
|
223
|
-
assert_equal "1", @cache.read(crazy_key)
|
|
224
|
-
assert_equal "1", @cache.fetch(crazy_key)
|
|
225
|
-
assert @cache.delete(crazy_key)
|
|
226
|
-
refute @cache.exist?(crazy_key)
|
|
227
|
-
assert_equal "2", @cache.fetch(crazy_key, :raw => true) { "2" }
|
|
228
|
-
assert_equal 3, @cache.increment(crazy_key)
|
|
229
|
-
assert_equal 2, @cache.decrement(crazy_key)
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
it "really_long_keys" do
|
|
233
|
-
really_long_keys_test
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
it "really_long_keys_with_namespace" do
|
|
237
|
-
@cache = ActiveSupport::Cache.lookup_store(:libmemcached_store, :expires_in => 60, :namespace => 'namespace')
|
|
238
|
-
@cache.silence!
|
|
239
|
-
really_long_keys_test
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
it "clear" do
|
|
243
|
-
@cache.write("foo", "bar")
|
|
244
|
-
@cache.clear
|
|
245
|
-
assert_nil @cache.read("foo")
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it "clear_with_options" do
|
|
249
|
-
@cache.write("foo", "bar")
|
|
250
|
-
@cache.clear(:some_option => true)
|
|
251
|
-
assert_nil @cache.read("foo")
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
describe "compression" do
|
|
256
|
-
it "read_and_write_compressed_small_data" do
|
|
257
|
-
@cache.write('foo', 'bar', :compress => true)
|
|
258
|
-
raw_value = @cache.send(:read_entry, 'foo', {})
|
|
259
|
-
assert_equal 'bar', @cache.read('foo')
|
|
260
|
-
value = Marshal.load(raw_value) rescue raw_value
|
|
261
|
-
assert_equal 'bar', value
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
it "read_and_write_compressed_large_data" do
|
|
265
|
-
@cache.write('foo', 'bar', :compress => true, :compress_threshold => 2)
|
|
266
|
-
raw_value = @cache.send(:read_entry, 'foo', :raw => true)
|
|
267
|
-
assert_equal 'bar', @cache.read('foo')
|
|
268
|
-
assert_equal 'bar', Marshal.load(raw_value)
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
describe "increment / decrement" do
|
|
273
|
-
it "increment" do
|
|
274
|
-
@cache.write('foo', '1', :raw => true)
|
|
275
|
-
assert_equal 1, @cache.read('foo').to_i
|
|
276
|
-
assert_equal 2, @cache.increment('foo')
|
|
277
|
-
assert_equal 2, @cache.read('foo').to_i
|
|
278
|
-
assert_equal 3, @cache.increment('foo')
|
|
279
|
-
assert_equal 3, @cache.read('foo').to_i
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
it "decrement" do
|
|
283
|
-
@cache.write('foo', '3', :raw => true)
|
|
284
|
-
assert_equal 3, @cache.read('foo').to_i
|
|
285
|
-
assert_equal 2, @cache.decrement('foo')
|
|
286
|
-
assert_equal 2, @cache.read('foo').to_i
|
|
287
|
-
assert_equal 1, @cache.decrement('foo')
|
|
288
|
-
assert_equal 1, @cache.read('foo').to_i
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
it "increment_decrement_non_existing_keys" do
|
|
292
|
-
@cache.expects(:log_error).never
|
|
293
|
-
assert_nil @cache.increment('foo')
|
|
294
|
-
assert_nil @cache.decrement('bar')
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
it "should_identify_cache_store" do
|
|
299
|
-
assert_kind_of ActiveSupport::Cache::LibmemcachedStore, @cache
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
it "should_set_server_addresses_to_nil_if_none_are_given" do
|
|
303
|
-
assert_equal [], @cache.addresses
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
it "should_set_custom_server_addresses" do
|
|
307
|
-
store = ActiveSupport::Cache.lookup_store :libmemcached_store, 'localhost', '192.168.1.1'
|
|
308
|
-
assert_equal %w(localhost 192.168.1.1), store.addresses
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
it "should_enable_consistent_ketema_hashing_by_default" do
|
|
312
|
-
assert_equal :consistent_ketama, @cache.client_options[:distribution]
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
it "should_not_enable_non_blocking_io_by_default" do
|
|
316
|
-
assert_equal false, @cache.client_options[:no_block]
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
it "should_not_enable_server_failover_by_default" do
|
|
320
|
-
assert_nil @cache.client_options[:failover]
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
it "should_allow_configuration_of_custom_options" do
|
|
324
|
-
options = { client: { tcp_nodelay: true, distribution: :modula } }
|
|
325
|
-
|
|
326
|
-
store = ActiveSupport::Cache.lookup_store :libmemcached_store, 'localhost', options
|
|
327
|
-
|
|
328
|
-
assert_equal :modula, store.client_options[:distribution]
|
|
329
|
-
assert_equal true, store.client_options[:tcp_nodelay]
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
it "should_allow_mute_and_silence" do
|
|
333
|
-
cache = ActiveSupport::Cache.lookup_store :libmemcached_store, 'localhost'
|
|
334
|
-
cache.mute do
|
|
335
|
-
assert cache.write('foo', 'bar')
|
|
336
|
-
assert_equal 'bar', cache.read('foo')
|
|
337
|
-
end
|
|
338
|
-
refute cache.silence?
|
|
339
|
-
cache.silence!
|
|
340
|
-
assert cache.silence?
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
describe "#fetch with :race_condition_ttl" do
|
|
344
|
-
let(:options) { {:expires_in => 1, :race_condition_ttl => 5} }
|
|
345
|
-
|
|
346
|
-
def fetch(&block)
|
|
347
|
-
@cache.fetch("unknown", options, &block)
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
after do
|
|
351
|
-
Thread.list.each { |t| t.exit unless t == Thread.current }
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
it "works like a normal fetch" do
|
|
355
|
-
fetch { 1 }.must_equal 1
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
it "keeps a cached value even if the cache expires" do
|
|
359
|
-
fetch { 1 } # fill it
|
|
360
|
-
|
|
361
|
-
future = Time.now + 3 * 60
|
|
362
|
-
Time.stubs(:now).returns future
|
|
363
|
-
|
|
364
|
-
Thread.new do
|
|
365
|
-
sleep 0.1
|
|
366
|
-
fetch { raise }.must_equal 1 # 3rd fetch -> read expired value
|
|
367
|
-
end
|
|
368
|
-
fetch { sleep 0.2; 2 }.must_equal 2 # 2nd fetch -> takes time to generate but returns correct value
|
|
369
|
-
fetch { 3 }.must_equal 2 # 4th fetch still correct value
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
it "can be read by a normal read" do
|
|
373
|
-
fetch { 1 }
|
|
374
|
-
@cache.read("unknown").must_equal 1
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
it "can be read by a normal fetch" do
|
|
378
|
-
fetch { 1 }
|
|
379
|
-
@cache.fetch("unknown") { 2 }.must_equal 1
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
it "can write to things that get fetched" do
|
|
383
|
-
fetch { 1 }
|
|
384
|
-
@cache.write "unknown", 2
|
|
385
|
-
fetch { 1 }.must_equal 2
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
end
|
data/test/profile/benchmark.rb
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
require 'benchmark'
|
|
2
|
-
require 'active_support'
|
|
3
|
-
|
|
4
|
-
require 'libmemcached_store'
|
|
5
|
-
require 'active_support/cache/libmemcached_store'
|
|
6
|
-
|
|
7
|
-
require 'dalli'
|
|
8
|
-
require 'active_support/cache/dalli_store'
|
|
9
|
-
|
|
10
|
-
puts "Testing with"
|
|
11
|
-
puts RUBY_DESCRIPTION
|
|
12
|
-
puts "Dalli #{Dalli::VERSION}"
|
|
13
|
-
puts "Libmemcached_store #{LibmemcachedStore::VERSION}"
|
|
14
|
-
|
|
15
|
-
# We'll use a simple @value to try to avoid spending time in Marshal,
|
|
16
|
-
# which is a constant penalty that both clients have to pay
|
|
17
|
-
@value = []
|
|
18
|
-
@marshalled = Marshal.dump(@value)
|
|
19
|
-
|
|
20
|
-
@servers = ['127.0.0.1:11211']
|
|
21
|
-
@key1 = "Short"
|
|
22
|
-
@key2 = "Sym1-2-3::45"*4
|
|
23
|
-
@key3 = "Long"*40
|
|
24
|
-
@key4 = "Medium"*8
|
|
25
|
-
|
|
26
|
-
N = 2_500
|
|
27
|
-
|
|
28
|
-
@dalli = ActiveSupport::Cache::DalliStore.new(@servers).silence!
|
|
29
|
-
@libm = ActiveSupport::Cache::LibmemcachedStore.new(@servers).silence!
|
|
30
|
-
|
|
31
|
-
def clear
|
|
32
|
-
@dalli.clear
|
|
33
|
-
@libm.clear
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def test_method(title, method_name, key, *arguments)
|
|
37
|
-
{ dalli: @dalli, libm: @libm }.each do |name, store|
|
|
38
|
-
@job.report("#{title}:#{name}") { N.times { store.send(method_name, key, *arguments) } }
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def run_method(method_name, key, *arguments)
|
|
43
|
-
[@dalli, @libm].each do |store|
|
|
44
|
-
store.send(method_name, key, *arguments)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
Benchmark.bm(31) do |x|
|
|
49
|
-
@job = x
|
|
50
|
-
|
|
51
|
-
test_method('write:short', :write, @key1, @value)
|
|
52
|
-
test_method('write:long', :write, @key3, @value)
|
|
53
|
-
test_method('write:raw', :write, @key4, @value, raw: true)
|
|
54
|
-
|
|
55
|
-
puts
|
|
56
|
-
clear
|
|
57
|
-
|
|
58
|
-
test_method('read:miss', :read, @key1)
|
|
59
|
-
test_method('read:miss2', :read, @key1)
|
|
60
|
-
|
|
61
|
-
run_method(:write, @key4, @value)
|
|
62
|
-
test_method('read:exist', :read, @key4)
|
|
63
|
-
|
|
64
|
-
run_method(:write, @key4, @value, expires_in: 1)
|
|
65
|
-
sleep(1)
|
|
66
|
-
test_method('read:expired', :read, @key2)
|
|
67
|
-
|
|
68
|
-
run_method(:write, @key3, @value, raw: true)
|
|
69
|
-
test_method('read:raw', :read, @key3, raw: true)
|
|
70
|
-
|
|
71
|
-
puts
|
|
72
|
-
clear
|
|
73
|
-
|
|
74
|
-
test_method('exist:miss', :exist?, @key4)
|
|
75
|
-
|
|
76
|
-
run_method(:write, @key4, @value)
|
|
77
|
-
test_method('exist:hit', :exist?, @key4)
|
|
78
|
-
|
|
79
|
-
puts
|
|
80
|
-
clear
|
|
81
|
-
|
|
82
|
-
test_method('delete:miss', :delete, @key4)
|
|
83
|
-
|
|
84
|
-
run_method(:write, @key1, @value)
|
|
85
|
-
test_method('delete:hit', :delete, @key1)
|
|
86
|
-
|
|
87
|
-
puts
|
|
88
|
-
clear
|
|
89
|
-
|
|
90
|
-
run_method(:write, @key4, 0, raw: true)
|
|
91
|
-
|
|
92
|
-
test_method('increment', :increment, @key4)
|
|
93
|
-
test_method('decrement', :decrement, @key4)
|
|
94
|
-
end
|