memcached 0.11 → 0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,13 +9,19 @@ class Memcached
9
9
  DEFAULTS = {}
10
10
 
11
11
  # See Memcached#new for details.
12
- def initialize(servers, opts = {})
12
+ def initialize(*args)
13
+ opts = args.last.is_a?(Hash) ? args.pop : {}
14
+ servers = Array(
15
+ args.any? ? args.unshift : opts.delete(:servers)
16
+ ).flatten.compact
17
+
18
+ opts[:prefix_key] ||= opts[:namespace]
13
19
  super(servers, DEFAULTS.merge(opts))
14
20
  end
15
21
 
16
22
  # Wraps Memcached#get so that it doesn't raise. This has the side-effect of preventing you from
17
23
  # storing <tt>nil</tt> values.
18
- def get(key, raw = false)
24
+ def get(key, raw=false)
19
25
  super(key, !raw)
20
26
  rescue NotFound
21
27
  end
@@ -26,13 +32,33 @@ class Memcached
26
32
  end
27
33
 
28
34
  # Wraps Memcached#set.
29
- def set(key, value, ttl = 0, raw = false)
35
+ def set(key, value, ttl=nil, raw=false)
36
+ super(key, value, ttl, !raw)
37
+ end
38
+
39
+ # Wraps Memcached#add so that it doesn't raise.
40
+ def add(key, value, ttl=nil, raw=false)
30
41
  super(key, value, ttl, !raw)
42
+ true
43
+ rescue NotStored
44
+ false
31
45
  end
32
46
 
33
47
  # Wraps Memcached#delete so that it doesn't raise.
34
48
  def delete(key)
35
- super(key)
49
+ super
50
+ rescue NotFound
51
+ end
52
+
53
+ # Wraps Memcached#incr so that it doesn't raise.
54
+ def incr(*args)
55
+ super
56
+ rescue NotFound
57
+ end
58
+
59
+ # Wraps Memcached#decr so that it doesn't raise.
60
+ def decr(*args)
61
+ super
36
62
  rescue NotFound
37
63
  end
38
64
 
@@ -40,16 +66,11 @@ class Memcached
40
66
  def namespace
41
67
  options[:prefix_key]
42
68
  end
69
+
70
+ alias :flush_all :flush
43
71
 
44
- # Alias for get.
45
- def [](key)
46
- get key
47
- end
48
-
49
- # Alias for Memcached#set.
50
- def []=(key, value)
51
- set key, value
52
- end
72
+ alias :"[]" :get
73
+ alias :"[]=" :set
53
74
 
54
75
  end
55
76
  end
@@ -1,108 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
1
2
 
2
- # Gem::Specification for Memcached-0.11
3
- # Originally generated by Echoe
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{memcached}
5
+ s.version = "0.12"
4
6
 
5
- --- !ruby/object:Gem::Specification
6
- name: memcached
7
- version: !ruby/object:Gem::Version
8
- version: "0.11"
9
- platform: ruby
10
- authors:
11
- - Evan Weaver
12
- autorequire:
13
- bindir: bin
14
- date: 2008-07-14 00:00:00 -04:00
15
- default_executable:
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
18
- name: echoe
19
- type: :development
20
- version_requirement:
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: "0"
26
- version:
27
- description: An interface to the libmemcached C client.
28
- email: ""
29
- executables: []
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Evan Weaver"]
9
+ s.cert_chain = ["/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-public_cert.pem"]
10
+ s.date = %q{2008-12-02}
11
+ s.description = %q{An interface to the libmemcached C client.}
12
+ s.email = %q{}
13
+ s.extensions = ["ext/extconf.rb"]
14
+ s.extra_rdoc_files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "README", "TODO"]
15
+ s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "Rakefile", "README", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO", "memcached.gemspec"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Memcached", "--main", "README"]
19
+ s.require_paths = ["lib", "ext"]
20
+ s.rubyforge_project = %q{fauna}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.signing_key = %q{/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-private_key.pem}
23
+ s.summary = %q{An interface to the libmemcached C client.}
24
+ s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
30
25
 
31
- extensions:
32
- - ext/extconf.rb
33
- extra_rdoc_files:
34
- - BENCHMARKS
35
- - CHANGELOG
36
- - COMPATIBILITY
37
- - lib/memcached/behaviors.rb
38
- - lib/memcached/exceptions.rb
39
- - lib/memcached/memcached.rb
40
- - lib/memcached/rails.rb
41
- - lib/memcached.rb
42
- - LICENSE
43
- - README
44
- - TODO
45
- files:
46
- - BENCHMARKS
47
- - CHANGELOG
48
- - COMPATIBILITY
49
- - ext/extconf.rb
50
- - ext/rlibmemcached.i
51
- - ext/rlibmemcached_wrap.c
52
- - lib/memcached/behaviors.rb
53
- - lib/memcached/exceptions.rb
54
- - lib/memcached/integer.rb
55
- - lib/memcached/memcached.rb
56
- - lib/memcached/rails.rb
57
- - lib/memcached.rb
58
- - LICENSE
59
- - Manifest
60
- - Rakefile
61
- - README
62
- - test/profile/benchmark.rb
63
- - test/profile/profile.rb
64
- - test/profile/valgrind.rb
65
- - test/setup.rb
66
- - test/teardown.rb
67
- - test/test_helper.rb
68
- - test/unit/binding_test.rb
69
- - test/unit/memcached_test.rb
70
- - test/unit/rails_test.rb
71
- - TODO
72
- - memcached.gemspec
73
- has_rdoc: true
74
- homepage: http://blog.evanweaver.com/files/doc/fauna/memcached/
75
- post_install_message:
76
- rdoc_options:
77
- - --line-numbers
78
- - --inline-source
79
- - --title
80
- - Memcached
81
- - --main
82
- - README
83
- require_paths:
84
- - lib
85
- - ext
86
- required_ruby_version: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: "0"
91
- version:
92
- required_rubygems_version: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "="
95
- - !ruby/object:Gem::Version
96
- version: "1.2"
97
- version:
98
- requirements: []
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 2
99
29
 
100
- rubyforge_project: fauna
101
- rubygems_version: 1.2.0
102
- specification_version: 2
103
- summary: An interface to the libmemcached C client.
104
- test_files:
105
- - test/test_helper.rb
106
- - test/unit/binding_test.rb
107
- - test/unit/memcached_test.rb
108
- - test/unit/rails_test.rb
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ s.add_development_dependency(%q<echoe>, [">= 0"])
32
+ else
33
+ s.add_dependency(%q<echoe>, [">= 0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<echoe>, [">= 0"])
37
+ end
38
+ end
@@ -1,25 +1,27 @@
1
1
 
2
2
  require "#{File.dirname(__FILE__)}/../test_helper"
3
+ require 'socket'
4
+ require 'benchmark'
3
5
 
4
6
  class MemcachedTest < Test::Unit::TestCase
5
7
 
6
8
  def setup
7
9
  @servers = ['localhost:43042', 'localhost:43043']
8
10
 
9
- # Maximum allowed prefix key size
10
- @prefix_key = 'prefix_key_'
11
-
12
- @options = {
13
- :prefix_key => @prefix_key,
11
+ # Maximum allowed prefix key size for :hash_with_prefix_key_key => false
12
+ @prefix_key = 'prefix_key_'
13
+
14
+ @options = {
15
+ :prefix_key => @prefix_key,
14
16
  :hash => :default,
15
17
  :distribution => :modula
16
18
  }
17
19
  @cache = Memcached.new(@servers, @options)
18
-
20
+
19
21
  @nb_options = {
20
- :prefix_key => @prefix_key,
21
- :no_block => true,
22
- :buffer_requests => true,
22
+ :prefix_key => @prefix_key,
23
+ :no_block => true,
24
+ :buffer_requests => true,
23
25
  :hash => :default
24
26
  }
25
27
  @nb_cache = Memcached.new(@servers, @nb_options)
@@ -27,7 +29,7 @@ class MemcachedTest < Test::Unit::TestCase
27
29
  @value = OpenStruct.new(:a => 1, :b => 2, :c => GenericClass)
28
30
  @marshalled_value = Marshal.dump(@value)
29
31
  end
30
-
32
+
31
33
  # Initialize
32
34
 
33
35
  def test_initialize
@@ -38,32 +40,48 @@ class MemcachedTest < Test::Unit::TestCase
38
40
  assert_equal 'localhost', cache.send(:server_structs).last.hostname
39
41
  assert_equal 43043, cache.send(:server_structs).last.port
40
42
  end
41
-
43
+
42
44
  def test_initialize_with_ip_addresses
43
- cache = Memcached.new ['127.0.0.1:43042', '127.0.0.1:43043'], :prefix_key => 'test'
45
+ cache = Memcached.new ['127.0.0.1:43042', '127.0.0.1:43043']
44
46
  assert_equal '127.0.0.1', cache.send(:server_structs).first.hostname
45
47
  assert_equal '127.0.0.1', cache.send(:server_structs).last.hostname
46
48
  end
47
-
49
+
48
50
  def test_initialize_without_port
49
- cache = Memcached.new ['localhost'], :prefix_key => 'test'
51
+ cache = Memcached.new ['localhost']
50
52
  assert_equal 'localhost', cache.send(:server_structs).first.hostname
51
53
  assert_equal 11211, cache.send(:server_structs).first.port
52
54
  end
53
55
 
56
+ def test_initialize_with_ports_and_weights
57
+ cache = Memcached.new ['localhost:43042:2', 'localhost:43043:10']
58
+ assert_equal 2, cache.send(:server_structs).first.weight
59
+ assert_equal 43043, cache.send(:server_structs).last.port
60
+ assert_equal 10, cache.send(:server_structs).last.weight
61
+ end
62
+
63
+ def test_initialize_with_hostname_only
64
+ addresses = (1..8).map { |i| "app-cache-%02d" % i }
65
+ cache = Memcached.new(addresses)
66
+ addresses.each_with_index do |address, index|
67
+ assert_equal address, cache.send(:server_structs)[index].hostname
68
+ assert_equal 11211, cache.send(:server_structs)[index].port
69
+ end
70
+ end
71
+
54
72
  def test_options_are_set
55
73
  Memcached::DEFAULTS.merge(@nb_options).each do |key, expected|
56
74
  value = @nb_cache.options[key]
57
75
  assert(expected == value, "#{key} should be #{expected} but was #{value}")
58
76
  end
59
77
  end
60
-
78
+
61
79
  def test_options_are_frozen
62
80
  assert_raise(TypeError) do
63
81
  @cache.options[:no_block] = true
64
82
  end
65
83
  end
66
-
84
+
67
85
  def test_behaviors_are_set
68
86
  Memcached::BEHAVIORS.keys.each do |key, value|
69
87
  assert_not_nil @cache.send(:get_behavior, key)
@@ -75,37 +93,34 @@ class MemcachedTest < Test::Unit::TestCase
75
93
  assert_raise(ArgumentError) { Memcached.new "localhost:memcached" }
76
94
  assert_raise(ArgumentError) { Memcached.new "local host:43043:1" }
77
95
  end
78
-
79
- if ENV['USER'] == "eweaver"
80
- def test_initialize_with_resolvable_hosts
81
- `hostname` =~ /(chloe|mackenzie)/
82
- host = "#{$1}.lan"
83
- cache = Memcached.new ["#{host}:43042"]
84
- assert_equal host, cache.send(:server_structs).first.hostname
85
-
86
- cache.set(key, @value)
87
- assert_equal @value, cache.get(key)
88
- end
96
+
97
+ def test_initialize_with_resolvable_hosts
98
+ host = `hostname`.chomp
99
+ cache = Memcached.new ["#{host}:43042"]
100
+ assert_equal host, cache.send(:server_structs).first.hostname
101
+
102
+ cache.set(key, @value)
103
+ assert_equal @value, cache.get(key)
89
104
  end
90
-
105
+
91
106
  def test_initialize_with_invalid_options
92
- assert_raise(ArgumentError) do
107
+ assert_raise(ArgumentError) do
93
108
  Memcached.new @servers, :sort_hosts => true, :distribution => :consistent
94
109
  end
95
110
  end
96
111
 
97
112
  def test_initialize_with_invalid_prefix_key
98
- assert_raise(ArgumentError) do
99
- Memcached.new @servers, :prefix_key => "prefix_key__"
113
+ assert_raise(ArgumentError) do
114
+ Memcached.new @servers, :prefix_key => "x" * 128
100
115
  end
101
116
  end
102
-
117
+
103
118
  def test_initialize_without_prefix_key
104
119
  cache = Memcached.new @servers
105
120
  assert_equal nil, cache.options[:prefix_key]
106
121
  assert_equal 2, cache.send(:server_structs).size
107
122
  end
108
-
123
+
109
124
  def test_initialize_negative_behavior
110
125
  cache = Memcached.new @servers,
111
126
  :buffer_requests => false
@@ -113,10 +128,10 @@ class MemcachedTest < Test::Unit::TestCase
113
128
  cache.set key, @value
114
129
  end
115
130
  end
116
-
117
- def test_initialize_without_not_found_backtraces
131
+
132
+ def test_initialize_without_backtraces
118
133
  cache = Memcached.new @servers,
119
- :show_not_found_backtraces => false
134
+ :show_backtraces => false
120
135
  cache.delete key rescue
121
136
  begin
122
137
  cache.get key
@@ -125,24 +140,24 @@ class MemcachedTest < Test::Unit::TestCase
125
140
  end
126
141
  end
127
142
 
128
- def test_initialize_with_not_found_backtraces
143
+ def test_initialize_with_backtraces
129
144
  cache = Memcached.new @servers,
130
- :show_not_found_backtraces => true
145
+ :show_backtraces => true
131
146
  cache.delete key rescue
132
147
  begin
133
148
  cache.get key
134
149
  rescue Memcached::NotFound => e
135
150
  assert !e.backtrace.empty?
136
- end
137
- end
138
-
151
+ end
152
+ end
153
+
139
154
  def test_initialize_sort_hosts
140
155
  # Original
141
156
  cache = Memcached.new(@servers.sort,
142
157
  :sort_hosts => false,
143
158
  :distribution => :modula
144
159
  )
145
- assert_equal @servers.sort,
160
+ assert_equal @servers.sort,
146
161
  cache.servers
147
162
 
148
163
  # Original with sort_hosts
@@ -150,26 +165,26 @@ class MemcachedTest < Test::Unit::TestCase
150
165
  :sort_hosts => true,
151
166
  :distribution => :modula
152
167
  )
153
- assert_equal @servers.sort,
168
+ assert_equal @servers.sort,
154
169
  cache.servers
155
-
156
- # Reversed
170
+
171
+ # Reversed
157
172
  cache = Memcached.new(@servers.sort.reverse,
158
173
  :sort_hosts => false,
159
174
  :distribution => :modula
160
175
  )
161
- assert_equal @servers.sort.reverse,
176
+ assert_equal @servers.sort.reverse,
162
177
  cache.servers
163
-
178
+
164
179
  # Reversed with sort_hosts
165
180
  cache = Memcached.new(@servers.sort.reverse,
166
181
  :sort_hosts => true,
167
182
  :distribution => :modula
168
183
  )
169
- assert_equal @servers.sort,
184
+ assert_equal @servers.sort,
170
185
  cache.servers
171
186
  end
172
-
187
+
173
188
  def test_initialize_single_server
174
189
  cache = Memcached.new 'localhost:43042'
175
190
  assert_equal nil, cache.options[:prefix_key]
@@ -179,9 +194,9 @@ class MemcachedTest < Test::Unit::TestCase
179
194
  def test_initialize_strange_argument
180
195
  assert_raise(ArgumentError) { Memcached.new 1 }
181
196
  end
182
-
197
+
183
198
  # Get
184
-
199
+
185
200
  def test_get
186
201
  @cache.set key, @value
187
202
  result = @cache.get key
@@ -193,33 +208,60 @@ class MemcachedTest < Test::Unit::TestCase
193
208
  result = @cache.get key
194
209
  assert_equal nil, result
195
210
  end
196
-
211
+
197
212
  def test_get_missing
198
213
  @cache.delete key rescue nil
199
214
  assert_raise(Memcached::NotFound) do
200
215
  result = @cache.get key
201
216
  end
202
217
  end
203
-
218
+
219
+ def test_get_with_server_timeout
220
+ socket = stub_server 43047
221
+ cache = Memcached.new(
222
+ "localhost:43047:1",
223
+ :timeout => 0.5
224
+ )
225
+ assert 0.49 < (Benchmark.measure do
226
+ assert_raise(Memcached::UnknownReadFailure) do
227
+ result = cache.get key
228
+ end
229
+ end).real
230
+ end
231
+
232
+ def test_get_with_no_block_server_timeout
233
+ socket = stub_server 43048
234
+ cache = Memcached.new(
235
+ "localhost:43048:1",
236
+ :no_block => true,
237
+ :timeout => 0.25
238
+ )
239
+ assert 0.24 < (Benchmark.measure do
240
+ assert_raise(Memcached::UnknownReadFailure) do
241
+ result = cache.get key
242
+ end
243
+ end).real
244
+ end
245
+
204
246
  def test_get_with_prefix_key
205
247
  # Prefix_key
206
248
  cache = Memcached.new(
207
249
  # We can only use one server because the key is hashed separately from the prefix key
208
250
  @servers.first,
209
- :prefix_key => @prefix_key,
251
+ :prefix_key => @prefix_key,
210
252
  :hash => :default,
211
253
  :distribution => :modula
212
254
  )
213
255
  cache.set key, @value
214
256
  assert_equal @value, cache.get(key)
215
-
257
+
216
258
  # No prefix_key specified
217
259
  cache = Memcached.new(
218
260
  @servers.first,
219
261
  :hash => :default,
220
262
  :distribution => :modula
221
263
  )
222
- assert_nothing_raised do
264
+ assert_nothing_raised do
223
265
  assert_equal @value, cache.get("#{@prefix_key}#{key}")
224
266
  end
225
267
  end
@@ -229,11 +271,11 @@ class MemcachedTest < Test::Unit::TestCase
229
271
  @cache.set key, value
230
272
  result = @cache.get key, false
231
273
  non_wrapped_result = Rlibmemcached.memcached_get(
232
- @cache.instance_variable_get("@struct"),
274
+ @cache.instance_variable_get("@struct"),
233
275
  key
234
276
  ).first
235
- assert result.size > non_wrapped_result.size
236
- end
277
+ assert result.size > non_wrapped_result.size
278
+ end
237
279
 
238
280
  def test_get_multi
239
281
  @cache.set "#{key}_1", 1
@@ -241,33 +283,33 @@ class MemcachedTest < Test::Unit::TestCase
241
283
  assert_equal({"#{key}_1" => 1, "#{key}_2" => 2},
242
284
  @cache.get(["#{key}_1", "#{key}_2"]))
243
285
  end
244
-
286
+
245
287
  def test_get_multi_missing
246
288
  @cache.set "#{key}_1", 1
247
289
  @cache.delete "#{key}_2" rescue nil
248
290
  @cache.set "#{key}_3", 3
249
- @cache.delete "#{key}_4" rescue nil
291
+ @cache.delete "#{key}_4" rescue nil
250
292
  assert_equal(
251
- {"test_get_multi_missing_3"=>3, "test_get_multi_missing_1"=>1},
293
+ {"test_get_multi_missing_3"=>3, "test_get_multi_missing_1"=>1},
252
294
  @cache.get(["#{key}_1", "#{key}_2", "#{key}_3", "#{key}_4"])
253
295
  )
254
296
  end
255
-
297
+
256
298
  def test_get_multi_completely_missing
257
299
  @cache.delete "#{key}_1" rescue nil
258
- @cache.delete "#{key}_2" rescue nil
300
+ @cache.delete "#{key}_2" rescue nil
259
301
  assert_equal(
260
302
  {},
261
303
  @cache.get(["#{key}_1", "#{key}_2"])
262
304
  )
263
- end
305
+ end
264
306
 
265
307
  def test_set_and_get_unmarshalled
266
308
  @cache.set key, @value
267
309
  result = @cache.get key, false
268
310
  assert_equal @marshalled_value, result
269
311
  end
270
-
312
+
271
313
  def test_get_multi_unmarshalled
272
314
  @cache.set "#{key}_1", 1, 0, false
273
315
  @cache.set "#{key}_2", 2, 0, false
@@ -276,7 +318,7 @@ class MemcachedTest < Test::Unit::TestCase
276
318
  @cache.get(["#{key}_1", "#{key}_2"], false)
277
319
  )
278
320
  end
279
-
321
+
280
322
  def test_get_multi_mixed_marshalling
281
323
  @cache.set "#{key}_1", 1
282
324
  @cache.set "#{key}_2", 2, 0, false
@@ -286,7 +328,22 @@ class MemcachedTest < Test::Unit::TestCase
286
328
  assert_raise(ArgumentError) do
287
329
  @cache.get(["#{key}_1", "#{key}_2"])
288
330
  end
289
- end
331
+ end
332
+
333
+ def test_get_with_random_distribution
334
+ cache = Memcached.new(@servers, :distribution => :random)
335
+ cache.set key, @value
336
+
337
+ hits = (0..10).to_a.map do
338
+ begin
339
+ cache.get(key)
340
+ rescue Memcached::NotFound
341
+ end
342
+ end.compact.size
343
+
344
+ assert 0 < hits
345
+ assert 10 > hits
346
+ end
290
347
 
291
348
  # Set
292
349
 
@@ -295,7 +352,7 @@ class MemcachedTest < Test::Unit::TestCase
295
352
  @cache.set(key, @value)
296
353
  end
297
354
  end
298
-
355
+
299
356
  def test_set_expiry
300
357
  @cache.set key, @value, 1
301
358
  assert_nothing_raised do
@@ -306,16 +363,31 @@ class MemcachedTest < Test::Unit::TestCase
306
363
  @cache.get key
307
364
  end
308
365
  end
309
-
366
+
367
+ def test_set_with_default_ttl
368
+ cache = Memcached.new(
369
+ @servers,
370
+ :default_ttl => 1
371
+ )
372
+ cache.set key, @value
373
+ assert_nothing_raised do
374
+ cache.get key
375
+ end
376
+ sleep(2)
377
+ assert_raise(Memcached::NotFound) do
378
+ cache.get key
379
+ end
380
+ end
381
+
310
382
  # Delete
311
-
383
+
312
384
  def test_delete
313
385
  @cache.set key, @value
314
386
  @cache.delete key
315
387
  assert_raise(Memcached::NotFound) do
316
388
  @cache.get key
317
389
  end
318
- end
390
+ end
319
391
 
320
392
  def test_missing_delete
321
393
  @cache.delete key rescue nil
@@ -323,19 +395,19 @@ class MemcachedTest < Test::Unit::TestCase
323
395
  @cache.delete key
324
396
  end
325
397
  end
326
-
398
+
327
399
  # Flush
328
-
400
+
329
401
  def test_flush
330
402
  @cache.set key, @value
331
- assert_equal @value,
403
+ assert_equal @value,
332
404
  @cache.get(key)
333
405
  @cache.flush
334
- assert_raise(Memcached::NotFound) do
406
+ assert_raise(Memcached::NotFound) do
335
407
  @cache.get key
336
408
  end
337
409
  end
338
-
410
+
339
411
  # Add
340
412
 
341
413
  def test_add
@@ -360,7 +432,7 @@ class MemcachedTest < Test::Unit::TestCase
360
432
  sleep(1)
361
433
  assert_raise(Memcached::NotFound) do
362
434
  @cache.get key
363
- end
435
+ end
364
436
  end
365
437
 
366
438
  def test_unmarshalled_add
@@ -369,14 +441,14 @@ class MemcachedTest < Test::Unit::TestCase
369
441
  assert_equal @marshalled_value, @cache.get(key, false)
370
442
  assert_equal @value, @cache.get(key)
371
443
  end
372
-
444
+
373
445
  # Increment and decrement
374
446
 
375
447
  def test_increment
376
448
  @cache.set key, 10, 0, false
377
449
  assert_equal 11, @cache.increment(key)
378
450
  end
379
-
451
+
380
452
  def test_increment_offset
381
453
  @cache.set key, 10, 0, false
382
454
  assert_equal 15, @cache.increment(key, 5)
@@ -393,11 +465,11 @@ class MemcachedTest < Test::Unit::TestCase
393
465
  @cache.set key, 10, 0, false
394
466
  assert_equal 9, @cache.decrement(key)
395
467
  end
396
-
468
+
397
469
  def test_decrement_offset
398
470
  @cache.set key, 10, 0, false
399
471
  assert_equal 5, @cache.decrement(key, 5)
400
- end
472
+ end
401
473
 
402
474
  def test_missing_decrement
403
475
  @cache.delete key rescue nil
@@ -405,9 +477,9 @@ class MemcachedTest < Test::Unit::TestCase
405
477
  @cache.decrement key
406
478
  end
407
479
  end
408
-
480
+
409
481
  # Replace
410
-
482
+
411
483
  def test_replace
412
484
  @cache.set key, nil
413
485
  assert_nothing_raised do
@@ -421,11 +493,11 @@ class MemcachedTest < Test::Unit::TestCase
421
493
  assert_raise(Memcached::NotStored) do
422
494
  @cache.replace key, @value
423
495
  end
424
- assert_raise(Memcached::NotFound) do
425
- assert_equal @value, @cache.get(key)
496
+ assert_raise(Memcached::NotFound) do
497
+ assert_equal @value, @cache.get(key)
426
498
  end
427
499
  end
428
-
500
+
429
501
  # Append and prepend
430
502
 
431
503
  def test_append
@@ -441,8 +513,8 @@ class MemcachedTest < Test::Unit::TestCase
441
513
  assert_raise(Memcached::NotStored) do
442
514
  @cache.append key, "end"
443
515
  end
444
- assert_raise(Memcached::NotFound) do
445
- assert_equal @value, @cache.get(key)
516
+ assert_raise(Memcached::NotFound) do
517
+ assert_equal @value, @cache.get(key)
446
518
  end
447
519
  end
448
520
 
@@ -459,17 +531,17 @@ class MemcachedTest < Test::Unit::TestCase
459
531
  assert_raise(Memcached::NotStored) do
460
532
  @cache.prepend key, "end"
461
533
  end
462
- assert_raise(Memcached::NotFound) do
463
- assert_equal @value, @cache.get(key)
534
+ assert_raise(Memcached::NotFound) do
535
+ assert_equal @value, @cache.get(key)
464
536
  end
465
537
  end
466
538
 
467
539
  def test_cas
468
540
  cache = Memcached.new(
469
- @servers,
470
- :prefix_key => @prefix_key,
541
+ @servers,
542
+ :prefix_key => @prefix_key,
471
543
  :support_cas => true
472
- )
544
+ )
473
545
  value2 = OpenStruct.new(:d => 3, :e => 4, :f => GenericClass)
474
546
 
475
547
  # Existing set
@@ -479,20 +551,20 @@ class MemcachedTest < Test::Unit::TestCase
479
551
  value2
480
552
  end
481
553
  assert_equal value2, cache.get(key)
482
-
554
+
483
555
  # Existing test without marshalling
484
556
  cache.set(key, "foo", 0, false)
485
557
  cache.cas(key, 0, false) do |current|
486
558
  "#{current}bar"
487
559
  end
488
560
  assert_equal "foobar", cache.get(key, false)
489
-
561
+
490
562
  # Missing set
491
563
  cache.delete key
492
564
  assert_raises(Memcached::NotFound) do
493
565
  cache.cas(key) {}
494
566
  end
495
-
567
+
496
568
  # Conflicting set
497
569
  cache.set key, @value
498
570
  assert_raises(Memcached::ConnectionDataExists) do
@@ -502,9 +574,9 @@ class MemcachedTest < Test::Unit::TestCase
502
574
  end
503
575
  end
504
576
  end
505
-
577
+
506
578
  # Error states
507
-
579
+
508
580
  def test_key_with_spaces
509
581
  key = "i have a space"
510
582
  assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
@@ -514,7 +586,7 @@ class MemcachedTest < Test::Unit::TestCase
514
586
  @cache.get(key)
515
587
  end
516
588
  end
517
-
589
+
518
590
  def test_key_with_null
519
591
  key = "with\000null"
520
592
  assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
@@ -527,8 +599,8 @@ class MemcachedTest < Test::Unit::TestCase
527
599
  assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
528
600
  response = @cache.get([key])
529
601
  end
530
- end
531
-
602
+ end
603
+
532
604
  def test_key_with_invalid_control_characters
533
605
  key = "ch\303\242teau"
534
606
  assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
@@ -542,7 +614,7 @@ class MemcachedTest < Test::Unit::TestCase
542
614
  response = @cache.get([key])
543
615
  end
544
616
  end
545
-
617
+
546
618
  def test_key_too_long
547
619
  key = "x"*251
548
620
  assert_raises(Memcached::ClientError) do
@@ -551,18 +623,18 @@ class MemcachedTest < Test::Unit::TestCase
551
623
  assert_raises(Memcached::ClientError) do
552
624
  @cache.get(key)
553
625
  end
554
-
626
+
555
627
  assert_raises(Memcached::ClientError) do
556
628
  @cache.get([key])
557
629
  end
558
- end
630
+ end
559
631
 
560
632
  def test_set_object_too_large
561
633
  assert_raise(Memcached::ServerError) do
562
634
  @cache.set key, "I'm big" * 1000000
563
635
  end
564
636
  end
565
-
637
+
566
638
  # Stats
567
639
 
568
640
  def test_stats
@@ -571,25 +643,25 @@ class MemcachedTest < Test::Unit::TestCase
571
643
  assert_instance_of Fixnum, stats[:pid].first
572
644
  assert_instance_of String, stats[:version].first
573
645
  end
574
-
646
+
575
647
  # Clone
576
-
648
+
577
649
  def test_clone
578
650
  cache = @cache.clone
579
651
  assert_equal cache.servers, @cache.servers
580
652
  assert_not_equal cache, @cache
581
-
653
+
582
654
  # Definitely check that the structs are unlinked
583
655
  assert_not_equal @cache.instance_variable_get('@struct').object_id,
584
656
  cache.instance_variable_get('@struct').object_id
585
-
657
+
586
658
  assert_nothing_raised do
587
659
  @cache.set key, @value
588
660
  end
589
661
  end
590
-
662
+
591
663
  # Non-blocking IO
592
-
664
+
593
665
  def test_buffered_requests_return_value
594
666
  cache = Memcached.new @servers,
595
667
  :buffer_requests => true
@@ -597,13 +669,13 @@ class MemcachedTest < Test::Unit::TestCase
597
669
  cache.set key, @value
598
670
  end
599
671
  ret = Rlibmemcached.memcached_set(
600
- cache.instance_variable_get("@struct"),
601
- key,
602
- @marshalled_value,
603
- 0,
672
+ cache.instance_variable_get("@struct"),
673
+ key,
674
+ @marshalled_value,
675
+ 0,
604
676
  Memcached::FLAGS
605
677
  )
606
- assert_equal 31, ret
678
+ assert_equal Rlibmemcached::MEMCACHED_BUFFERED, ret
607
679
  end
608
680
 
609
681
  def test_no_block_return_value
@@ -611,71 +683,79 @@ class MemcachedTest < Test::Unit::TestCase
611
683
  @nb_cache.set key, @value
612
684
  end
613
685
  ret = Rlibmemcached.memcached_set(
614
- @nb_cache.instance_variable_get("@struct"),
615
- key,
616
- @marshalled_value,
617
- 0,
686
+ @nb_cache.instance_variable_get("@struct"),
687
+ key,
688
+ @marshalled_value,
689
+ 0,
618
690
  Memcached::FLAGS
619
691
  )
620
- assert_equal 31, ret
692
+ assert_equal Rlibmemcached::MEMCACHED_BUFFERED, ret
621
693
  end
622
694
 
695
+ def test_no_block_get
696
+ @nb_cache.set key, @value
697
+ assert_equal @value,
698
+ @nb_cache.get(key)
699
+ end
700
+
623
701
  def test_no_block_missing_delete
624
702
  @nb_cache.delete key rescue nil
625
703
  assert_nothing_raised do
626
704
  @nb_cache.delete key
627
705
  end
628
- end
706
+ end
629
707
 
630
708
  def test_no_block_set_invalid_key
631
709
  assert_raises(Memcached::ABadKeyWasProvidedOrCharactersOutOfRange) do
632
710
  @nb_cache.set "I'm so bad", @value
633
711
  end
634
- end
712
+ end
635
713
 
636
714
  def test_no_block_set_object_too_large
637
715
  assert_nothing_raised do
638
716
  @nb_cache.set key, "I'm big" * 1000000
639
717
  end
640
718
  end
641
-
719
+
642
720
  def test_no_block_existing_add
643
721
  # Should still raise
644
722
  @nb_cache.set key, @value
645
723
  assert_raise(Memcached::NotStored) do
646
724
  @nb_cache.add key, @value
647
725
  end
648
- end
649
-
726
+ end
727
+
650
728
  # Server removal and consistent hashing
651
-
652
- def test_missing_server
729
+
730
+ def test_dying_server
731
+ socket = stub_server 43041
653
732
  cache = Memcached.new(
654
- [@servers.last, 'localhost:43041'], # Use a server that isn't running
733
+ [@servers.last, 'localhost:43041'],
655
734
  :prefix_key => @prefix_key,
656
735
  :failover => true,
736
+ :hash_with_prefix_key => false,
657
737
  :hash => :md5
658
738
  )
659
-
739
+
660
740
  # Hit first server
661
- key = 'test_missing_server3'
662
- cache.set(key, @value)
663
- cache.get(key) == @value
664
-
741
+ key1 = 'test_missing_server6'
742
+ cache.set(key1, @value)
743
+ cache.get(key1) == @value
744
+
665
745
  # Hit second server
666
- key = 'test_missing_server'
667
- assert_raise(Memcached::SystemError) do
668
- cache.set(key, @value)
669
- cache.get(key)
670
- end
746
+ key2 = 'test_missing_server'
747
+ assert_raise(Memcached::UnknownReadFailure) do
748
+ cache.set(key2, @value)
749
+ cache.get(key2)
750
+ end
671
751
 
672
752
  # Hit first server on retry
673
753
  assert_nothing_raised do
674
- cache.set(key, @value)
675
- cache.get(key)
676
- end
754
+ cache.set(key2, @value)
755
+ cache.get(key2)
756
+ end
677
757
  end
678
-
758
+
679
759
  def test_sweep_servers_with_missing_server_first
680
760
  cache = Memcached.new(['127.0.0.1:00000'] + @servers)
681
761
  assert_nothing_raised do
@@ -686,24 +766,24 @@ class MemcachedTest < Test::Unit::TestCase
686
766
  def test_consistent_hashing
687
767
 
688
768
  keys = %w(EN6qtgMW n6Oz2W4I ss4A8Brr QShqFLZt Y3hgP9bs CokDD4OD Nd3iTSE1 24vBV4AU H9XBUQs5 E5j8vUq1 AzSh8fva PYBlK2Pi Ke3TgZ4I AyAIYanO oxj8Xhyd eBFnE6Bt yZyTikWQ pwGoU7Pw 2UNDkKRN qMJzkgo2 keFXbQXq pBl2QnIg ApRl3mWY wmalTJW1 TLueug8M wPQL4Qfg uACwus23 nmOk9R6w lwgZJrzJ v1UJtKdG RK629Cra U2UXFRqr d9OQLNl8 KAm1K3m5 Z13gKZ1v tNVai1nT LhpVXuVx pRib1Itj I1oLUob7 Z1nUsd5Q ZOwHehUa aXpFX29U ZsnqxlGz ivQRjOdb mB3iBEAj)
689
-
769
+
690
770
  # Five servers
691
771
  cache = Memcached.new(
692
- @servers + ['localhost:43044', 'localhost:43045', 'localhost:43046'],
772
+ @servers + ['localhost:43044', 'localhost:43045', 'localhost:43046'],
693
773
  :prefix_key => @prefix_key
694
- )
695
-
696
- cache.flush
774
+ )
775
+
776
+ cache.flush
697
777
  keys.each do |key|
698
778
  cache.set(key, @value)
699
- end
779
+ end
700
780
 
701
781
  # Pull a server
702
782
  cache = Memcached.new(
703
783
  @servers + ['localhost:43044', 'localhost:43046'],
704
784
  :prefix_key => @prefix_key
705
785
  )
706
-
786
+
707
787
  failed = 0
708
788
  keys.each_with_index do |key, i|
709
789
  begin
@@ -713,15 +793,15 @@ class MemcachedTest < Test::Unit::TestCase
713
793
  end
714
794
  end
715
795
 
716
- assert(failed < keys.size / 3, "#{failed} failed out of #{keys.size}")
796
+ assert(failed < keys.size / 3, "#{failed} failed out of #{keys.size}")
717
797
  end
718
798
 
719
799
  # Concurrency
720
-
800
+
721
801
  def test_thread_contention
722
802
  threads = []
723
803
  4.times do |index|
724
- threads << Thread.new do
804
+ threads << Thread.new do
725
805
  cache = @cache.clone
726
806
  assert_nothing_raised do
727
807
  cache.set("test_thread_contention_#{index}", index)
@@ -731,23 +811,29 @@ class MemcachedTest < Test::Unit::TestCase
731
811
  end
732
812
  threads.each {|thread| thread.join}
733
813
  end
734
-
814
+
735
815
  # Memory cleanup
736
-
816
+
737
817
  def test_reset
738
818
  original_struct = @cache.instance_variable_get("@struct")
739
819
  assert_nothing_raised do
740
820
  @cache.reset
741
- end
742
- assert_not_equal original_struct,
743
- @cache.instance_variable_get("@struct")
821
+ end
822
+ assert_not_equal original_struct,
823
+ @cache.instance_variable_get("@struct")
744
824
  end
745
-
825
+
746
826
  private
747
-
827
+
748
828
  def key
749
- caller.first[/`(.*)'/, 1]
829
+ caller.first[/`(.*)'/, 1] # '
750
830
  end
751
-
831
+
832
+ def stub_server(port)
833
+ socket = TCPServer.new('127.0.0.1', port)
834
+ Thread.new { socket.accept }
835
+ socket
836
+ end
837
+
752
838
  end
753
839