mcmire-cache 0.3.4
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/.gitignore +7 -0
- data/CHANGELOG +21 -0
- data/Gemfile +22 -0
- data/README.md +229 -0
- data/Rakefile +41 -0
- data/benchmarks/afterrefactor.txt +86 -0
- data/benchmarks/midrefactor.txt +89 -0
- data/benchmarks/v0.0.2.txt +95 -0
- data/benchmarks/v0.0.3.txt +96 -0
- data/benchmarks/v0.1.2.txt +94 -0
- data/benchmarks/v0.2.1.txt +94 -0
- data/benchmarks/v0.2.2.txt +94 -0
- data/lib/cache.rb +233 -0
- data/lib/cache/active_support_cache_dalli_store.rb +15 -0
- data/lib/cache/active_support_cache_file_store.rb +11 -0
- data/lib/cache/active_support_cache_memory_store.rb +11 -0
- data/lib/cache/active_support_cache_store.rb +37 -0
- data/lib/cache/config.rb +27 -0
- data/lib/cache/dalli_client.rb +54 -0
- data/lib/cache/mem_cache.rb +46 -0
- data/lib/cache/memcached.rb +54 -0
- data/lib/cache/memcached_rails.rb +34 -0
- data/lib/cache/nothing.rb +20 -0
- data/lib/cache/redis.rb +44 -0
- data/lib/cache/redis_namespace.rb +7 -0
- data/lib/cache/version.rb +3 -0
- data/mcmire-cache.gemspec +22 -0
- data/test/helper.rb +29 -0
- data/test/profile/benchmark.rb +258 -0
- data/test/shared_tests.rb +169 -0
- data/test/test_active_support_cache_dalli_store.rb +77 -0
- data/test/test_active_support_cache_file_store.rb +19 -0
- data/test/test_active_support_cache_memory_store.rb +12 -0
- data/test/test_dalli_client.rb +70 -0
- data/test/test_mem_cache.rb +64 -0
- data/test/test_memcached.rb +64 -0
- data/test/test_memcached_rails.rb +61 -0
- data/test/test_memcached_with_binary.rb +17 -0
- data/test/test_missing_driver.rb +16 -0
- data/test/test_nothing.rb +147 -0
- data/test/test_redis.rb +60 -0
- data/test/test_redis_namespace.rb +64 -0
- metadata +108 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'cache/memcached'
|
2
|
+
|
3
|
+
module Cache::MemcachedRails
|
4
|
+
def self.extended(base)
|
5
|
+
base.extend Cache::Memcached
|
6
|
+
base.extend Override
|
7
|
+
end
|
8
|
+
|
9
|
+
module Override
|
10
|
+
def _exist?(k)
|
11
|
+
thread_metal.exist? k
|
12
|
+
end
|
13
|
+
|
14
|
+
def _get(k)
|
15
|
+
thread_metal.get k
|
16
|
+
end
|
17
|
+
|
18
|
+
def _get_multi(ks)
|
19
|
+
thread_metal.get_multi ks
|
20
|
+
end
|
21
|
+
|
22
|
+
def _cas(k, ttl, &blk)
|
23
|
+
if _valid_ttl?(ttl)
|
24
|
+
thread_metal.cas k, ttl, &blk
|
25
|
+
else
|
26
|
+
thread_metal.cas k, &blk
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def _delete(k)
|
31
|
+
thread_metal.delete k
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Cache::Nothing
|
3
|
+
def _get(k); end
|
4
|
+
|
5
|
+
def _get_multi(ks); {}; end
|
6
|
+
|
7
|
+
def _set(k, v, ttl); end
|
8
|
+
|
9
|
+
def _fetch(k, ttl)
|
10
|
+
yield if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def _delete(k); end
|
14
|
+
|
15
|
+
def _flush; end
|
16
|
+
|
17
|
+
def _exist?(k); end
|
18
|
+
|
19
|
+
def _stats; end
|
20
|
+
end
|
data/lib/cache/redis.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Cache::Redis
|
2
|
+
def after_fork
|
3
|
+
@metal.client.reconnect
|
4
|
+
end
|
5
|
+
|
6
|
+
def _get(k)
|
7
|
+
if cached_v = @metal.get(k) and cached_v.is_a?(String)
|
8
|
+
Marshal.load cached_v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def _get_multi(ks)
|
13
|
+
ks.inject({}) do |memo, k|
|
14
|
+
if v = _get(k)
|
15
|
+
memo[k] = v
|
16
|
+
end
|
17
|
+
memo
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def _set(k, v, ttl)
|
22
|
+
if _valid_ttl?(ttl)
|
23
|
+
@metal.setex k, ttl, Marshal.dump(v)
|
24
|
+
else
|
25
|
+
@metal.set k, Marshal.dump(v)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def _delete(k)
|
30
|
+
@metal.del k
|
31
|
+
end
|
32
|
+
|
33
|
+
def _flush
|
34
|
+
@metal.flushdb
|
35
|
+
end
|
36
|
+
|
37
|
+
def _exist?(k)
|
38
|
+
@metal.exists k
|
39
|
+
end
|
40
|
+
|
41
|
+
def _stats
|
42
|
+
@metal.info
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/cache/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "mcmire-cache"
|
7
|
+
s.version = Cache::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Seamus Abshere","Christoph Grabo", "Elliot Winkler"]
|
10
|
+
s.email = ["seamus@abshere.net","chris@dinarrr.com", "elliot.winkler@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/seamusabshere/cache"
|
12
|
+
s.summary = %q{A unified cache handling interface inspired by libraries like ActiveSupport::Cache::Store, Perl's Cache::Cache, CHI, etc.}
|
13
|
+
s.description = %q{Wraps memcached, redis(-namespace), memcache-client, dalli and handles their weirdnesses, including forking}
|
14
|
+
|
15
|
+
s.rubyforge_project = "cache"
|
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
|
+
end
|
22
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
require 'test/unit'
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'cache'
|
8
|
+
|
9
|
+
if ::Bundler.definition.specs['ruby-debug19'].first or ::Bundler.definition.specs['ruby-debug'].first
|
10
|
+
require 'ruby-debug'
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'shared_tests'
|
14
|
+
|
15
|
+
class TestCase < Test::Unit::TestCase
|
16
|
+
def raw_client_class
|
17
|
+
raise NotImplementedError, "You must add a #raw_client_class method to your test case"
|
18
|
+
end
|
19
|
+
|
20
|
+
def raw_client
|
21
|
+
raw_client_class.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def cache
|
25
|
+
@cache ||= Cache.new(raw_client).tap {|c| c.flush }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
ENV['CACHE_DEBUG'] = 'true'
|
@@ -0,0 +1,258 @@
|
|
1
|
+
# sabshere 2/22/11 thanks to memcached
|
2
|
+
HERE = File.dirname(__FILE__)
|
3
|
+
$LOAD_PATH << "#{HERE}/../../lib/"
|
4
|
+
UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached')
|
5
|
+
|
6
|
+
require 'cache'
|
7
|
+
require 'benchmark'
|
8
|
+
require 'rubygems'
|
9
|
+
require 'ruby-debug' if ENV['DEBUG']
|
10
|
+
begin; require 'memory'; rescue LoadError; end
|
11
|
+
|
12
|
+
puts `uname -a`
|
13
|
+
puts `ruby -v`
|
14
|
+
puts `env | egrep '^RUBY'`
|
15
|
+
puts "Ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}"
|
16
|
+
|
17
|
+
[ ["memcached", "memcached"],
|
18
|
+
# ["remix-stash", "remix/stash"],
|
19
|
+
# ["astro-remcached", "remcached"], # Clobbers the "Memcached" constant
|
20
|
+
["memcache-client", "memcache"],
|
21
|
+
["cache", "cache"],
|
22
|
+
["kgio", "kgio"],
|
23
|
+
["dalli","dalli"]].each do |gem_name, requirement|
|
24
|
+
require requirement
|
25
|
+
gem gem_name
|
26
|
+
puts "Loaded #{gem_name} #{Gem.loaded_specs[gem_name].version.to_s rescue nil}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# class Remix::Stash
|
30
|
+
# # Remix::Stash API doesn't let you set servers
|
31
|
+
# @@clusters = {:default => Remix::Stash::Cluster.new(['127.0.0.1:43042', '127.0.0.1:43043'])}
|
32
|
+
# end
|
33
|
+
|
34
|
+
class Dalli::ClientCompat < Dalli::Client
|
35
|
+
def set(*args)
|
36
|
+
super(*args[0..2])
|
37
|
+
end
|
38
|
+
def get(*args)
|
39
|
+
super(args.first)
|
40
|
+
end
|
41
|
+
def get_multi(*args)
|
42
|
+
super(args.first)
|
43
|
+
end
|
44
|
+
def append(*args)
|
45
|
+
super
|
46
|
+
rescue Dalli::DalliError
|
47
|
+
end
|
48
|
+
def prepend(*args)
|
49
|
+
super
|
50
|
+
rescue Dalli::DalliError
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# class Cache::Compat < Cache
|
55
|
+
# def set(*args)
|
56
|
+
# super(*args[0..2])
|
57
|
+
# end
|
58
|
+
# def get(*args)
|
59
|
+
# super(args.first)
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
|
63
|
+
class Bench
|
64
|
+
|
65
|
+
def initialize(loops = nil, stack_depth = nil)
|
66
|
+
@loops = (loops || 20000).to_i
|
67
|
+
@stack_depth = (stack_depth || 0).to_i
|
68
|
+
|
69
|
+
puts "Loops is #{@loops}"
|
70
|
+
puts "Stack depth is #{@stack_depth}"
|
71
|
+
|
72
|
+
@m_value = Marshal.dump(
|
73
|
+
@small_value = ["testing"])
|
74
|
+
@m_large_value = Marshal.dump(
|
75
|
+
@large_value = [{"test" => "1", "test2" => "2", Object.new => "3", 4 => 4, "test5" => 2**65}] * 2048)
|
76
|
+
|
77
|
+
puts "Small value size is: #{@m_value.size} bytes"
|
78
|
+
puts "Large value size is: #{@m_large_value.size} bytes"
|
79
|
+
|
80
|
+
@keys = [
|
81
|
+
@k1 = "Short",
|
82
|
+
@k2 = "Sym1-2-3::45" * 8,
|
83
|
+
@k3 = "Long" * 40,
|
84
|
+
@k4 = "Medium" * 8,
|
85
|
+
@k5 = "Medium2" * 8,
|
86
|
+
@k6 = "Long3" * 40]
|
87
|
+
|
88
|
+
reset_servers
|
89
|
+
reset_clients
|
90
|
+
|
91
|
+
Benchmark.bm(36) do |x|
|
92
|
+
@benchmark = x
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def run(level = @stack_depth)
|
97
|
+
level > 0 ? run(level - 1) : run_without_recursion
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def reset_servers
|
103
|
+
# Kill memcached
|
104
|
+
system("killall -9 memcached")
|
105
|
+
|
106
|
+
# Start memcached
|
107
|
+
verbosity = (ENV['DEBUG'] ? "-vv" : "")
|
108
|
+
log = "/tmp/memcached.log"
|
109
|
+
memcached = ENV['MEMCACHED_COMMAND'] || 'memcached'
|
110
|
+
system ">#{log}"
|
111
|
+
|
112
|
+
# TCP memcached
|
113
|
+
(43042..43046).each do |port|
|
114
|
+
cmd = "#{memcached} #{verbosity} -U 0 -p #{port} >> #{log} 2>&1 &"
|
115
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
116
|
+
end
|
117
|
+
# UDP memcached
|
118
|
+
(43052..43053).each do |port|
|
119
|
+
cmd = "#{memcached} #{verbosity} -U #{port} -p 0 >> #{log} 2>&1 &"
|
120
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
121
|
+
end
|
122
|
+
# Domain socket memcached
|
123
|
+
(0..1).each do |i|
|
124
|
+
cmd = "#{memcached} -M -s #{UNIX_SOCKET_NAME}#{i} #{verbosity} >> #{log} 2>&1 &"
|
125
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def reset_clients
|
130
|
+
@clients = {
|
131
|
+
"cache:libm:bin" => Cache.wrap(Memcached.new(['127.0.0.1:43042', '127.0.0.1:43043'], :buffer_requests => false, :no_block => false, :namespace => "namespace", :binary_protocol => true)),
|
132
|
+
"cache:dalli:bin" => Cache.wrap(Dalli::Client.new(['127.0.0.1:43042', '127.0.0.1:43043'], :marshal => false, :threadsafe => false)),
|
133
|
+
"libm:ascii" => Memcached::Rails.new(
|
134
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
135
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace"),
|
136
|
+
"libm:ascii:pipeline" => Memcached::Rails.new(
|
137
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
138
|
+
:no_block => true, :buffer_requests => true, :noreply => true, :namespace => "namespace"),
|
139
|
+
"libm:ascii:udp" => Memcached::Rails.new(
|
140
|
+
["#{UNIX_SOCKET_NAME}0", "#{UNIX_SOCKET_NAME}1"],
|
141
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace"),
|
142
|
+
"libm:bin" => Memcached::Rails.new(
|
143
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
144
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace", :binary_protocol => true),
|
145
|
+
"libm:bin:buffer" => Memcached::Rails.new(
|
146
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
147
|
+
:no_block => true, :buffer_requests => true, :namespace => "namespace", :binary_protocol => true),
|
148
|
+
"mclient:ascii" => MemCache.new(['127.0.0.1:43042', '127.0.0.1:43043']),
|
149
|
+
# "stash:bin" => Remix::Stash.new(:root),
|
150
|
+
"dalli:bin" => Dalli::ClientCompat.new(['127.0.0.1:43042', '127.0.0.1:43043'], :marshal => false, :threadsafe => false)}
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def benchmark_clients(test_name, clients = @clients)
|
155
|
+
clients.keys.sort.each do |client_name|
|
156
|
+
next if client_name == "stash" and test_name == "set-large" # Don't let stash break the world
|
157
|
+
client = clients[client_name]
|
158
|
+
begin
|
159
|
+
yield client
|
160
|
+
@benchmark.report("#{test_name}: #{client_name}") { @loops.times { yield client } }
|
161
|
+
rescue Exception => e
|
162
|
+
puts "#{test_name}:#{client_name} => #{e.inspect}"
|
163
|
+
reset_clients
|
164
|
+
end
|
165
|
+
end
|
166
|
+
puts
|
167
|
+
end
|
168
|
+
|
169
|
+
def benchmark_hashes(hashes, test_name)
|
170
|
+
hashes.each do |hash_name, int|
|
171
|
+
@m = Memcached::Rails.new(:hash => hash_name)
|
172
|
+
@benchmark.report("#{test_name}:#{hash_name}") do
|
173
|
+
(@loops * 5).times { yield int }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def run_without_recursion
|
179
|
+
benchmark_clients("set") do |c|
|
180
|
+
c.set @k1, @m_value, 0, true
|
181
|
+
c.set @k2, @m_value, 0, true
|
182
|
+
c.set @k3, @m_value, 0, true
|
183
|
+
end
|
184
|
+
|
185
|
+
benchmark_clients("get") do |c|
|
186
|
+
c.get @k1, true
|
187
|
+
c.get @k2, true
|
188
|
+
c.get @k3, true
|
189
|
+
end
|
190
|
+
|
191
|
+
# benchmark_clients("get-multi") do |c|
|
192
|
+
# c.get_multi @keys, true
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# benchmark_clients("append") do |c|
|
196
|
+
# c.append @k1, @m_value
|
197
|
+
# c.append @k2, @m_value
|
198
|
+
# c.append @k3, @m_value
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# benchmark_clients("prepend") do |c|
|
202
|
+
# c.prepend @k1, @m_value
|
203
|
+
# c.prepend @k2, @m_value
|
204
|
+
# c.prepend @k3, @m_value
|
205
|
+
# end
|
206
|
+
|
207
|
+
benchmark_clients("delete") do |c|
|
208
|
+
c.delete @k1
|
209
|
+
c.delete @k2
|
210
|
+
c.delete @k3
|
211
|
+
end
|
212
|
+
|
213
|
+
benchmark_clients("get-missing") do |c|
|
214
|
+
c.get @k1
|
215
|
+
c.get @k2
|
216
|
+
c.get @k3
|
217
|
+
end
|
218
|
+
|
219
|
+
# benchmark_clients("append-missing") do |c|
|
220
|
+
# c.append @k1, @m_value
|
221
|
+
# c.append @k2, @m_value
|
222
|
+
# c.append @k3, @m_value
|
223
|
+
# end
|
224
|
+
#
|
225
|
+
# benchmark_clients("prepend-missing") do |c|
|
226
|
+
# c.prepend @k1, @m_value
|
227
|
+
# c.prepend @k2, @m_value
|
228
|
+
# c.prepend @k3, @m_value
|
229
|
+
# end
|
230
|
+
|
231
|
+
benchmark_clients("set-large") do |c|
|
232
|
+
c.set @k1, @m_large_value, 0, true
|
233
|
+
c.set @k2, @m_large_value, 0, true
|
234
|
+
c.set @k3, @m_large_value, 0, true
|
235
|
+
end
|
236
|
+
|
237
|
+
benchmark_clients("get-large") do |c|
|
238
|
+
c.get @k1, true
|
239
|
+
c.get @k2, true
|
240
|
+
c.get @k3, true
|
241
|
+
end
|
242
|
+
|
243
|
+
benchmark_hashes(Memcached::HASH_VALUES, "hash") do |i|
|
244
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k1, i)
|
245
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k2, i)
|
246
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k3, i)
|
247
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k4, i)
|
248
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k5, i)
|
249
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k6, i)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
Bench.new(ENV["LOOPS"], ENV["STACK_DEPTH"]).run
|
255
|
+
|
256
|
+
Process.memory.each do |key, value|
|
257
|
+
puts "#{key}: #{value/1024.0}M"
|
258
|
+
end if Process.respond_to? :memory
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module SharedTests
|
2
|
+
def test_metal
|
3
|
+
assert_equal raw_client_class, cache.metal.class
|
4
|
+
end
|
5
|
+
|
6
|
+
def test_wrap_twice
|
7
|
+
c = Cache.new(Cache.new(raw_client))
|
8
|
+
assert_equal raw_client_class, c.metal.class
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_wrap_absurd
|
12
|
+
c = Cache.new(Cache.new(Cache.new(raw_client)))
|
13
|
+
assert_equal raw_client_class, c.metal.class
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_get
|
17
|
+
assert_equal nil, cache.get('hello')
|
18
|
+
cache.set 'hello', 'world'
|
19
|
+
assert_equal 'world', cache.get('hello')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_set
|
23
|
+
assert_nothing_raised do
|
24
|
+
cache.set 'hello', 'world'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_set_with_ttl
|
29
|
+
cache.set 'hello', 'world', 1
|
30
|
+
assert_equal 'world', cache.get('hello')
|
31
|
+
sleep 2
|
32
|
+
assert_equal nil, cache.get('hello')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_set_with_zero_ttl_meaning_eternal
|
36
|
+
cache.set 'hello', 'world', 0
|
37
|
+
assert_equal 'world', cache.get('hello')
|
38
|
+
sleep 1
|
39
|
+
assert_equal 'world', cache.get('hello')
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_delete
|
43
|
+
cache.set 'hello', 'world'
|
44
|
+
assert_equal 'world', cache.get('hello')
|
45
|
+
cache.delete 'hello'
|
46
|
+
assert_equal nil, cache.get('hello')
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_flush
|
50
|
+
cache.set 'hello', 'world'
|
51
|
+
assert cache.exist?('hello')
|
52
|
+
cache.flush
|
53
|
+
assert !cache.exist?('hello')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_exist
|
57
|
+
assert !cache.exist?('hello')
|
58
|
+
cache.set 'hello', 'world'
|
59
|
+
assert cache.exist?('hello')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_exists
|
63
|
+
assert !cache.exists?('hello')
|
64
|
+
cache.set 'hello', 'world'
|
65
|
+
assert cache.exists?('hello')
|
66
|
+
end
|
67
|
+
|
68
|
+
# This is not working with the Dalli client
|
69
|
+
#def test_exist_key_with_nil_value
|
70
|
+
# assert !cache.exist?('hello')
|
71
|
+
# cache.set 'hello', nil
|
72
|
+
# assert cache.exist?('hello')
|
73
|
+
#end
|
74
|
+
|
75
|
+
def test_stats
|
76
|
+
assert_nothing_raised do
|
77
|
+
cache.stats
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_fetch
|
82
|
+
assert_equal nil, cache.fetch('hello')
|
83
|
+
assert_equal 'world', cache.fetch('hello') { 'world' }
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_fetch_with_false_boolean
|
87
|
+
assert_equal nil, cache.fetch('hello')
|
88
|
+
assert_equal false, cache.fetch('hello') { false }
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_fetch_with_expires_in
|
92
|
+
assert_equal 'world', cache.fetch('hello', :expires_in => 5) { 'world' }
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_fetch_with_expires_in_stringified
|
96
|
+
assert_equal 'world', cache.fetch('hello', 'expires_in' => 5) { 'world' }
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_fetch_with_ignored_options
|
100
|
+
assert_equal 'world', cache.fetch('hello', :foo => 'bar') { 'world' }
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_cas
|
104
|
+
toggle = lambda do |current|
|
105
|
+
current == 'on' ? 'off' : 'on'
|
106
|
+
end
|
107
|
+
|
108
|
+
cache.set 'lights', 'on'
|
109
|
+
assert_equal 'on', cache.get('lights')
|
110
|
+
cache.cas 'lights', &toggle
|
111
|
+
assert_equal 'off', cache.get('lights')
|
112
|
+
cache.cas 'lights', &toggle
|
113
|
+
assert_equal 'on', cache.get('lights')
|
114
|
+
cache.cas 'lights', &toggle
|
115
|
+
assert_equal 'off', cache.get('lights')
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_write
|
119
|
+
cache.write 'hello', 'world'
|
120
|
+
assert_equal 'world', cache.get('hello')
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_write_with_expires_in
|
124
|
+
cache.write 'hello', 'world', :expires_in => 1
|
125
|
+
assert_equal 'world', cache.get('hello')
|
126
|
+
sleep 2
|
127
|
+
assert_equal nil, cache.get('hello')
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_write_with_ignored_options
|
131
|
+
cache.write 'hello', 'world', :foobar => 'bazboo'
|
132
|
+
assert_equal 'world', cache.get('hello')
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_read
|
136
|
+
cache.set 'hello', 'world'
|
137
|
+
assert_equal 'world', cache.read('hello')
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_increment
|
141
|
+
assert !cache.exist?('high-fives')
|
142
|
+
assert_equal 1, cache.increment('high-fives')
|
143
|
+
assert_equal 1, cache.get('high-fives')
|
144
|
+
assert_equal 2, cache.increment('high-fives')
|
145
|
+
assert_equal 2, cache.get('high-fives')
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_decrement
|
149
|
+
assert !cache.exist?('high-fives')
|
150
|
+
assert_equal -1, cache.decrement('high-fives')
|
151
|
+
assert_equal -1, cache.get('high-fives')
|
152
|
+
assert_equal -2, cache.decrement('high-fives')
|
153
|
+
assert_equal -2, cache.get('high-fives')
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_get_multi
|
157
|
+
cache.set 'hello', 'world'
|
158
|
+
cache.set 'privyet', 'mir'
|
159
|
+
assert_equal({ 'hello' => 'world', 'privyet' => 'mir'}, cache.get_multi('hello', 'privyet', 'yoyoyo'))
|
160
|
+
end
|
161
|
+
|
162
|
+
# https://github.com/fauna/memcached/pull/50
|
163
|
+
def test_get_set_behavior
|
164
|
+
cache.flush
|
165
|
+
cache.get 'get_set'
|
166
|
+
cache.set 'get_set', 'go'
|
167
|
+
assert_equal 'go', cache.get('get_set')
|
168
|
+
end
|
169
|
+
end
|