mob-dalli 1.1.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.
@@ -0,0 +1,170 @@
1
+ require 'helper'
2
+ require 'benchmark'
3
+
4
+ class TestBenchmark < Test::Unit::TestCase
5
+
6
+ def setup
7
+ puts "Testing #{Dalli::VERSION} with #{RUBY_DESCRIPTION}"
8
+ # We'll use a simple @value to try to avoid spending time in Marshal,
9
+ # which is a constant penalty that both clients have to pay
10
+ @value = []
11
+ @marshalled = Marshal.dump(@value)
12
+
13
+ @servers = ['127.0.0.1:19122', 'localhost:19122']
14
+ @key1 = "Short"
15
+ @key2 = "Sym1-2-3::45"*8
16
+ @key3 = "Long"*40
17
+ @key4 = "Medium"*8
18
+ # 5 and 6 are only used for multiget miss test
19
+ @key5 = "Medium2"*8
20
+ @key6 = "Long3"*40
21
+ @counter = 'counter'
22
+ end
23
+
24
+ def test_benchmark
25
+ memcached do
26
+
27
+ Benchmark.bm(31) do |x|
28
+
29
+ n = 2500
30
+
31
+ @m = Dalli::Client.new(@servers)
32
+ x.report("set:plain:dalli") do
33
+ n.times do
34
+ @m.set @key1, @marshalled, 0, :raw => true
35
+ @m.set @key2, @marshalled, 0, :raw => true
36
+ @m.set @key3, @marshalled, 0, :raw => true
37
+ @m.set @key1, @marshalled, 0, :raw => true
38
+ @m.set @key2, @marshalled, 0, :raw => true
39
+ @m.set @key3, @marshalled, 0, :raw => true
40
+ end
41
+ end
42
+
43
+ @m = Dalli::Client.new(@servers)
44
+ x.report("setq:plain:dalli") do
45
+ @m.multi do
46
+ n.times do
47
+ @m.set @key1, @marshalled, 0, :raw => true
48
+ @m.set @key2, @marshalled, 0, :raw => true
49
+ @m.set @key3, @marshalled, 0, :raw => true
50
+ @m.set @key1, @marshalled, 0, :raw => true
51
+ @m.set @key2, @marshalled, 0, :raw => true
52
+ @m.set @key3, @marshalled, 0, :raw => true
53
+ end
54
+ end
55
+ end
56
+
57
+ @m = Dalli::Client.new(@servers)
58
+ x.report("set:ruby:dalli") do
59
+ n.times do
60
+ @m.set @key1, @value
61
+ @m.set @key2, @value
62
+ @m.set @key3, @value
63
+ @m.set @key1, @value
64
+ @m.set @key2, @value
65
+ @m.set @key3, @value
66
+ end
67
+ end
68
+
69
+ @m = Dalli::Client.new(@servers)
70
+ x.report("get:plain:dalli") do
71
+ n.times do
72
+ @m.get @key1, :raw => true
73
+ @m.get @key2, :raw => true
74
+ @m.get @key3, :raw => true
75
+ @m.get @key1, :raw => true
76
+ @m.get @key2, :raw => true
77
+ @m.get @key3, :raw => true
78
+ end
79
+ end
80
+
81
+ @m = Dalli::Client.new(@servers)
82
+ x.report("get:ruby:dalli") do
83
+ n.times do
84
+ @m.get @key1
85
+ @m.get @key2
86
+ @m.get @key3
87
+ @m.get @key1
88
+ @m.get @key2
89
+ @m.get @key3
90
+ end
91
+ end
92
+
93
+ @m = Dalli::Client.new(@servers)
94
+ x.report("multiget:ruby:dalli") do
95
+ n.times do
96
+ # We don't use the keys array because splat is slow
97
+ @m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
98
+ end
99
+ end
100
+
101
+ @m = Dalli::Client.new(@servers)
102
+ x.report("missing:ruby:dalli") do
103
+ n.times do
104
+ begin @m.delete @key1; rescue; end
105
+ begin @m.get @key1; rescue; end
106
+ begin @m.delete @key2; rescue; end
107
+ begin @m.get @key2; rescue; end
108
+ begin @m.delete @key3; rescue; end
109
+ begin @m.get @key3; rescue; end
110
+ end
111
+ end
112
+
113
+ @m = Dalli::Client.new(@servers)
114
+ x.report("mixed:ruby:dalli") do
115
+ n.times do
116
+ @m.set @key1, @value
117
+ @m.set @key2, @value
118
+ @m.set @key3, @value
119
+ @m.get @key1
120
+ @m.get @key2
121
+ @m.get @key3
122
+ @m.set @key1, @value
123
+ @m.get @key1
124
+ @m.set @key2, @value
125
+ @m.get @key2
126
+ @m.set @key3, @value
127
+ @m.get @key3
128
+ end
129
+ end
130
+
131
+ @m = Dalli::Client.new(@servers)
132
+ x.report("mixedq:ruby:dalli") do
133
+ @m.multi do
134
+ n.times do
135
+ @m.set @key1, @value
136
+ @m.set @key2, @value
137
+ @m.set @key3, @value
138
+ @m.get @key1
139
+ @m.get @key2
140
+ @m.get @key3
141
+ @m.set @key1, @value
142
+ @m.get @key1
143
+ @m.set @key2, @value
144
+ @m.replace @key2, @value
145
+ @m.delete @key3
146
+ @m.add @key3, @value
147
+ @m.get @key2
148
+ @m.set @key3, @value
149
+ @m.get @key3
150
+ end
151
+ end
152
+ end
153
+
154
+ @m = Dalli::Client.new(@servers)
155
+ x.report("incr:ruby:dalli") do
156
+ n.times do
157
+ @m.incr @counter, 1, 0, 1
158
+ end
159
+ n.times do
160
+ @m.decr @counter, 1
161
+ end
162
+
163
+ assert_equal 0, @m.incr(@counter, 0)
164
+ end
165
+
166
+ end
167
+ end
168
+
169
+ end
170
+ end
@@ -0,0 +1,39 @@
1
+ $TESTING = true
2
+ require 'rubygems'
3
+ # require 'simplecov'
4
+ # SimpleCov.start
5
+ WANT_RAILS_VERSION = ENV['RAILS_VERSION'] || '>= 3.0.0'
6
+ gem 'rails', WANT_RAILS_VERSION
7
+ require 'rails'
8
+ puts "Testing with Rails #{Rails.version}"
9
+
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+ require 'memcached_mock'
13
+ require 'mocha'
14
+
15
+ require 'dalli'
16
+ require 'logger'
17
+
18
+ Dalli.logger = Logger.new(STDOUT)
19
+ Dalli.logger.level = Logger::ERROR
20
+
21
+ class Test::Unit::TestCase
22
+ include MemcachedMock::Helper
23
+
24
+ def assert_error(error, regexp=nil, &block)
25
+ ex = assert_raise(error, &block)
26
+ assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
27
+ end
28
+
29
+ def with_activesupport
30
+ require 'active_support/all'
31
+ yield
32
+ end
33
+
34
+ def with_actionpack
35
+ require 'action_dispatch'
36
+ require 'action_controller'
37
+ yield
38
+ end
39
+ end
@@ -0,0 +1,126 @@
1
+ require "socket"
2
+
3
+ $started = {}
4
+
5
+ module MemcachedMock
6
+ def self.start(port=19123, &block)
7
+ server = TCPServer.new("localhost", port)
8
+ session = server.accept
9
+ block.call session
10
+ end
11
+
12
+ def self.delayed_start(port=19123, wait=1, &block)
13
+ server = TCPServer.new("localhost", port)
14
+ sleep wait
15
+ block.call server
16
+ end
17
+
18
+ def self.tmp_socket_path
19
+ "#{Dir.pwd}/tmp.sock"
20
+ end
21
+
22
+ module Helper
23
+ # Forks the current process and starts a new mock Memcached server on
24
+ # port 22122.
25
+ #
26
+ # memcached_mock(lambda {|sock| socket.write('123') }) do
27
+ # assert_equal "PONG", Dalli::Client.new('localhost:22122').get('abc')
28
+ # end
29
+ #
30
+ def memcached_mock(proc, meth = :start)
31
+ return unless supports_fork?
32
+ begin
33
+ pid = fork do
34
+ trap("TERM") { exit }
35
+
36
+ MemcachedMock.send(meth) do |*args|
37
+ proc.call(*args)
38
+ end
39
+ end
40
+
41
+ sleep 0.3 # Give time for the socket to start listening.
42
+ yield
43
+ ensure
44
+ if pid
45
+ Process.kill("TERM", pid)
46
+ Process.wait(pid)
47
+ end
48
+ end
49
+ end
50
+
51
+ PATHS = %w(
52
+ /usr/local/bin/
53
+ /opt/local/bin/
54
+ /usr/bin/
55
+ )
56
+
57
+ def find_memcached
58
+ output = `memcached -h | head -1`.strip
59
+ if output && output =~ /^memcached (\d.\d.\d+)/ && $1 > '1.4'
60
+ return (puts "Found #{output} in PATH"; '')
61
+ end
62
+ PATHS.each do |path|
63
+ output = `memcached -h | head -1`.strip
64
+ if output && output =~ /^memcached (\d\.\d\.\d+)/ && $1 > '1.4'
65
+ return (puts "Found #{output} in #{path}"; path)
66
+ end
67
+ end
68
+
69
+ raise Errno::ENOENT, "Unable to find memcached 1.4+ locally"
70
+ nil
71
+ end
72
+
73
+ def memcached(port=19122, args='', options={})
74
+ return unless supports_fork?
75
+ Memcached.path ||= find_memcached
76
+
77
+ cmd = if options[:unix]
78
+ "#{Memcached.path}memcached #{args} -s #{MemcachedMock.tmp_socket_path}"
79
+ else
80
+ "#{Memcached.path}memcached #{args} -p #{port}"
81
+ end
82
+
83
+ $started[port] ||= begin
84
+ #puts "Starting: #{cmd}..."
85
+ pid = IO.popen(cmd).pid
86
+ at_exit do
87
+ begin
88
+ Process.kill("TERM", pid)
89
+ Process.wait(pid)
90
+ File.delete(MemcachedMock.tmp_socket_path) if options[:unix]
91
+ rescue Errno::ECHILD, Errno::ESRCH
92
+ end
93
+ end
94
+ sleep 0.1
95
+ pid
96
+ end
97
+ if options[:unix]
98
+ yield Dalli::Client.new(MemcachedMock.tmp_socket_path)
99
+ else
100
+ yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"], options)
101
+ end
102
+ end
103
+
104
+ def supports_fork?
105
+ !defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby'
106
+ end
107
+
108
+ def memcached_kill(port)
109
+ pid = $started.delete(port)
110
+ if pid
111
+ begin
112
+ Process.kill("TERM", pid)
113
+ Process.wait(pid)
114
+ rescue Errno::ECHILD, Errno::ESRCH
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ module Memcached
123
+ class << self
124
+ attr_accessor :path
125
+ end
126
+ end
@@ -0,0 +1,201 @@
1
+ # encoding: utf-8
2
+ require 'helper'
3
+
4
+ class TestActiveSupport < Test::Unit::TestCase
5
+ context 'active_support caching' do
6
+
7
+ should 'support fetch' do
8
+ with_activesupport do
9
+ memcached do
10
+ connect
11
+ mvalue = @mc.fetch('somekeywithoutspaces', :expires_in => 1.second) { 123 }
12
+ dvalue = @dalli.fetch('someotherkeywithoutspaces', :expires_in => 1.second) { 123 }
13
+ assert_equal 123, dvalue
14
+ assert_equal mvalue, dvalue
15
+
16
+ o = Object.new
17
+ o.instance_variable_set :@foo, 'bar'
18
+ mvalue = @mc.fetch(rand_key, :raw => true) { o }
19
+ dvalue = @dalli.fetch(rand_key, :raw => true) { o }
20
+ assert_equal mvalue, dvalue
21
+ assert_equal o, mvalue
22
+
23
+ mvalue = @mc.fetch(rand_key) { o }
24
+ dvalue = @dalli.fetch(rand_key) { o }
25
+ assert_equal mvalue, dvalue
26
+ assert_equal o, dvalue
27
+ end
28
+ end
29
+ end
30
+
31
+ should 'support keys with spaces on Rails3' do
32
+ with_activesupport do
33
+ memcached do
34
+ connect
35
+ dvalue = @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
36
+ mvalue = @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
37
+ assert_equal mvalue, dvalue
38
+ end
39
+ end
40
+ end
41
+
42
+ should 'support read_multi' do
43
+ with_activesupport do
44
+ memcached do
45
+ connect
46
+ x = rand_key
47
+ y = rand_key
48
+ assert_equal({}, @mc.read_multi(x, y))
49
+ assert_equal({}, @dalli.read_multi(x, y))
50
+ @dalli.write(x, '123')
51
+ @dalli.write(y, 123)
52
+ @mc.write(x, '123')
53
+ @mc.write(y, 123)
54
+ assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
55
+ assert_equal({ x => '123', y => 123 }, @mc.read_multi(x, y))
56
+ end
57
+ end
58
+ end
59
+
60
+ should 'support read_multi with an array' do
61
+ with_activesupport do
62
+ memcached do
63
+ connect
64
+ x = rand_key
65
+ y = rand_key
66
+ assert_equal({}, @mc.read_multi([x, y]))
67
+ assert_equal({}, @dalli.read_multi([x, y]))
68
+ @dalli.write(x, '123')
69
+ @dalli.write(y, 123)
70
+ @mc.write(x, '123')
71
+ @mc.write(y, 123)
72
+ assert_equal({ x => '123', y => 123 }, @dalli.read_multi([x, y]))
73
+ assert_equal({}, @mc.read_multi([x,y]))
74
+ end
75
+ end
76
+ end
77
+
78
+ should 'support raw read_multi' do
79
+ with_activesupport do
80
+ memcached do
81
+ connect
82
+ @mc.write("abc", 5, :raw => true)
83
+ @mc.write("cba", 5, :raw => true)
84
+ assert_equal({'abc' => '5', 'cba' => '5' }, @mc.read_multi("abc", "cba"))
85
+
86
+ @dalli.write("abc", 5, :raw => true)
87
+ @dalli.write("cba", 5, :raw => true)
88
+ assert_equal({'abc' => '5', 'cba' => '5' }, @dalli.read_multi("abc", "cba"))
89
+ end
90
+ end
91
+ end
92
+
93
+ should 'support read, write and delete' do
94
+ with_activesupport do
95
+ memcached do
96
+ connect
97
+ x = rand_key
98
+ y = rand_key
99
+ assert_nil @mc.read(x)
100
+ assert_nil @dalli.read(y)
101
+ mres = @mc.write(x, 123)
102
+ dres = @dalli.write(y, 123)
103
+ assert_equal mres, dres
104
+
105
+ mres = @mc.read(x)
106
+ dres = @dalli.read(y)
107
+ assert_equal mres, dres
108
+ assert_equal 123, dres
109
+
110
+ mres = @mc.delete(x)
111
+ dres = @dalli.delete(y)
112
+ assert_equal mres, dres
113
+ assert_equal true, dres
114
+ end
115
+ end
116
+ end
117
+
118
+ should 'support increment/decrement commands' do
119
+ with_activesupport do
120
+ memcached do
121
+ connect
122
+ assert_equal true, @mc.write('counter', 0, :raw => true)
123
+ assert_equal 1, @mc.increment('counter')
124
+ assert_equal 2, @mc.increment('counter')
125
+ assert_equal 1, @mc.decrement('counter')
126
+ assert_equal "1", @mc.read('counter', :raw => true)
127
+
128
+ assert_equal true, @dalli.write('counter', 0, :raw => true)
129
+ assert_equal 1, @dalli.increment('counter')
130
+ assert_equal 2, @dalli.increment('counter')
131
+ assert_equal 1, @dalli.decrement('counter')
132
+ assert_equal "1", @dalli.read('counter', :raw => true)
133
+
134
+ assert_equal 0, @mc.increment('counterX')
135
+ assert_equal 0, @mc.increment('counterX')
136
+ assert_equal nil, @mc.read('counterX')
137
+
138
+ assert_equal 1, @dalli.increment('counterX')
139
+ assert_equal 2, @dalli.increment('counterX')
140
+ assert_equal 2, @dalli.read('counterX', :raw => true).to_i
141
+ end
142
+ end
143
+ end
144
+
145
+ should 'support other esoteric commands' do
146
+ with_activesupport do
147
+ memcached do
148
+ connect
149
+ ms = @mc.stats
150
+ ds = @dalli.stats
151
+ assert_equal ms.keys.sort, ds.keys.sort
152
+ assert_equal ms[ms.keys.first].keys.sort, ds[ds.keys.first].keys.sort
153
+
154
+ assert_equal true, @dalli.write(:foo, 'a')
155
+ assert_equal true, @mc.write(:foo, 'a')
156
+
157
+ assert_equal true, @mc.exist?(:foo)
158
+ assert_equal true, @dalli.exist?(:foo)
159
+
160
+ assert_equal false, @mc.exist?(:bar)
161
+ assert_equal false, @dalli.exist?(:bar)
162
+
163
+ @dalli.reset
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ should 'handle crazy characters from far-away lands' do
170
+ with_activesupport do
171
+ memcached do
172
+ connect
173
+ key = "fooƒ"
174
+ value = 'bafƒ'
175
+ # assert_equal true, @mc.write(key, value)
176
+ assert_equal true, @dalli.write(key, value)
177
+ # assert_equal true, @mc.read(key, value)
178
+ assert_equal value, @dalli.read(key)
179
+ end
180
+ end
181
+ end
182
+
183
+ should 'normalize options as expected' do
184
+ with_activesupport do
185
+ memcached do
186
+ @dalli = ActiveSupport::Cache::DalliStore.new('localhost:19122', :expires_in => 1, :race_condition_ttl => 1)
187
+ assert_equal 2, @dalli.instance_variable_get(:@data).instance_variable_get(:@options)[:expires_in]
188
+ end
189
+ end
190
+ end
191
+
192
+ def connect
193
+ @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => 'x')
194
+ @mc = ActiveSupport::Cache.lookup_store(:mem_cache_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => 'a')
195
+ @dalli.clear
196
+ end
197
+
198
+ def rand_key
199
+ rand(1_000_000_000)
200
+ end
201
+ end