dalli 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dalli might be problematic. Click here for more details.

@@ -1,10 +1,18 @@
1
1
  require 'rubygems'
2
+
3
+ # require 'simplecov-html'
4
+ # SimpleCov.start
5
+
2
6
  require 'test/unit'
3
7
  require 'shoulda'
8
+ require 'memcached_mock'
9
+ require 'mocha'
4
10
 
5
11
  require 'dalli'
6
12
 
7
13
  class Test::Unit::TestCase
14
+ include MemcachedMock::Helper
15
+
8
16
  def assert_error(error, regexp=nil, &block)
9
17
  ex = assert_raise(error, &block)
10
18
  assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
@@ -1,16 +1,15 @@
1
1
  require "socket"
2
2
 
3
3
  module MemcachedMock
4
- def self.start(port=22122, &block)
4
+ def self.start(port=19123, &block)
5
5
  server = TCPServer.new("localhost", port)
6
6
  session = server.accept
7
7
  block.call session
8
8
  end
9
9
 
10
- def self.delayed_start(port=22122, wait=1, &block)
10
+ def self.delayed_start(port=19123, wait=1, &block)
11
11
  server = TCPServer.new("localhost", port)
12
12
  sleep wait
13
- # session = server.accept
14
13
  block.call server
15
14
  end
16
15
 
@@ -41,5 +40,52 @@ module MemcachedMock
41
40
  end
42
41
  end
43
42
  end
43
+
44
+ PATHS = %w(
45
+ /usr/local/bin/
46
+ /opt/local/bin/
47
+ /usr/bin/
48
+ )
49
+
50
+ def find_memcached
51
+ output = `memcached -h | head -1`.strip
52
+ if output && output =~ /^memcached (\d.\d.\d+)/ && $1 > '1.4'
53
+ return (puts "Found #{output} in PATH"; '')
54
+ end
55
+ PATHS.each do |path|
56
+ output = `memcached -h | head -1`.strip
57
+ if output && output =~ /^memcached (\d\.\d\.\d+)/ && $1 > '1.4'
58
+ return (puts "Found #{output} in #{path}"; path)
59
+ end
60
+ end
61
+
62
+ raise Errno::ENOENT, "Unable to find memcached 1.4+ locally"
63
+ nil
64
+ end
65
+
66
+ def memcached(port=19122, args='')
67
+ Memcached.path ||= find_memcached
68
+ cmd = "#{Memcached.path}memcached #{args} -p #{port}"
69
+ # puts "Starting: #{cmd}..."
70
+ pid = IO.popen(cmd).pid
71
+ begin
72
+ sleep 0.3
73
+ yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"])
74
+ ensure
75
+ begin
76
+ Process.kill("TERM", pid)
77
+ Process.wait(pid)
78
+ rescue Errno::ECHILD
79
+ # the memcached_mock forks will try to run this at_exit block also
80
+ # but since they are not the parent process, will get an ECHILD error.
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ module Memcached
88
+ class << self
89
+ attr_accessor :path
44
90
  end
45
91
  end
@@ -4,70 +4,83 @@ require 'active_support/cache/dalli_store'
4
4
 
5
5
  class TestDalli < Test::Unit::TestCase
6
6
  context 'activesupport caching' do
7
- setup do
8
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:11211', :expires_in => 10.seconds)
9
- @mc = ActiveSupport::Cache.lookup_store(:mem_cache_store, 'localhost:11211', :expires_in => 10.seconds, :namespace => 'a')
10
- @dalli.clear
11
- end
12
7
 
13
8
  should 'support fetch' do
14
- dvalue = @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
15
- mvalue = @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
16
- assert_equal mvalue, dvalue
9
+ memcached do
10
+ connect
11
+ dvalue = @mc.fetch('some key with spaces', :expires_in => 1.second) { 123 }
12
+ mvalue = @dalli.fetch('some other key with spaces', :expires_in => 1.second) { 123 }
13
+ assert_equal mvalue, dvalue
17
14
 
18
- o = Object.new
19
- o.instance_variable_set :@foo, 'bar'
20
- dvalue = @mc.fetch(rand_key, :raw => true) { o }
21
- mvalue = @dalli.fetch(rand_key, :raw => true) { o }
22
- assert_equal mvalue, dvalue
23
- assert_equal o, dvalue
15
+ o = Object.new
16
+ o.instance_variable_set :@foo, 'bar'
17
+ dvalue = @mc.fetch(rand_key, :raw => true) { o }
18
+ mvalue = @dalli.fetch(rand_key, :raw => true) { o }
19
+ assert_equal mvalue, dvalue
20
+ assert_equal o, dvalue
24
21
 
25
- dvalue = @mc.fetch(rand_key) { o }
26
- mvalue = @dalli.fetch(rand_key) { o }
27
- assert_equal mvalue, dvalue
28
- assert_equal o, dvalue
22
+ dvalue = @mc.fetch(rand_key) { o }
23
+ mvalue = @dalli.fetch(rand_key) { o }
24
+ assert_equal mvalue, dvalue
25
+ assert_equal o, dvalue
26
+ end
29
27
  end
30
28
 
31
29
  should 'support read_multi' do
32
- x = rand_key
33
- y = rand_key
34
- assert_equal({}, @mc.read_multi(x, y))
35
- assert_equal({}, @dalli.read_multi(x, y))
36
- @dalli.write(x, '123')
37
- @dalli.write(y, 123)
38
- @mc.write(x, '123')
39
- @mc.write(y, 123)
40
- assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
41
- assert_equal({ x => '123', y => 123 }, @mc.read_multi(x, y))
30
+ memcached do
31
+ connect
32
+ x = rand_key
33
+ y = rand_key
34
+ assert_equal({}, @mc.read_multi(x, y))
35
+ assert_equal({}, @dalli.read_multi(x, y))
36
+ @dalli.write(x, '123')
37
+ @dalli.write(y, 123)
38
+ @mc.write(x, '123')
39
+ @mc.write(y, 123)
40
+ assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
41
+ assert_equal({ x => '123', y => 123 }, @mc.read_multi(x, y))
42
+ end
42
43
  end
43
44
 
44
45
  should 'support read, write and delete' do
45
- x = rand_key
46
- y = rand_key
47
- assert_nil @mc.read(x)
48
- assert_nil @dalli.read(y)
49
- mres = @mc.write(x, 123)
50
- dres = @dalli.write(y, 123)
51
- assert_equal mres, dres
46
+ memcached do
47
+ connect
48
+ x = rand_key
49
+ y = rand_key
50
+ assert_nil @mc.read(x)
51
+ assert_nil @dalli.read(y)
52
+ mres = @mc.write(x, 123)
53
+ dres = @dalli.write(y, 123)
54
+ assert_equal mres, dres
52
55
 
53
- mres = @mc.read(x)
54
- dres = @dalli.read(y)
55
- assert_equal mres, dres
56
- assert_equal 123, dres
56
+ mres = @mc.read(x)
57
+ dres = @dalli.read(y)
58
+ assert_equal mres, dres
59
+ assert_equal 123, dres
57
60
 
58
- mres = @mc.delete(x)
59
- dres = @dalli.delete(y)
60
- assert_equal mres, dres
61
- assert_equal true, dres
61
+ mres = @mc.delete(x)
62
+ dres = @dalli.delete(y)
63
+ assert_equal mres, dres
64
+ assert_equal true, dres
65
+ end
62
66
  end
63
67
 
64
68
  should 'support other esoteric commands' do
65
- ms = @mc.stats
66
- ds = @dalli.stats
67
- assert_equal ms.keys.sort, ds.keys.sort
68
- assert_equal ms[ms.keys.first].keys.sort, ds[ds.keys.first].keys.sort
69
+ memcached do
70
+ connect
71
+ ms = @mc.stats
72
+ ds = @dalli.stats
73
+ assert_equal ms.keys.sort, ds.keys.sort
74
+ assert_equal ms[ms.keys.first].keys.sort, ds[ds.keys.first].keys.sort
75
+ end
69
76
  end
70
77
  end
78
+
79
+ def connect
80
+ @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122', :expires_in => 10.seconds)
81
+ @mc = ActiveSupport::Cache.lookup_store(:mem_cache_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => 'a')
82
+ @dalli.clear
83
+ end
71
84
 
72
85
  def rand_key
73
86
  rand(1_000_000_000)
@@ -10,7 +10,7 @@ class TestBenchmark < Test::Unit::TestCase
10
10
  @value = []
11
11
  @marshalled = Marshal.dump(@value)
12
12
 
13
- @servers = ['127.0.0.1:11211', 'localhost:11211']
13
+ @servers = ['127.0.0.1:19122', 'localhost:19122']
14
14
  @key1 = "Short"
15
15
  @key2 = "Sym1-2-3::45"*8
16
16
  @key3 = "Long"*40
@@ -21,97 +21,100 @@ class TestBenchmark < Test::Unit::TestCase
21
21
  end
22
22
 
23
23
  def test_benchmark
24
- Benchmark.bm(31) do |x|
24
+ memcached do
25
+
26
+ Benchmark.bm(31) do |x|
25
27
 
26
- n = 2500
28
+ n = 2500
27
29
 
28
- @m = Dalli::Client.new(@servers, :marshal => false)
29
- x.report("set:plain:dalli") do
30
- n.times do
31
- @m.set @key1, @marshalled
32
- @m.set @key2, @marshalled
33
- @m.set @key3, @marshalled
34
- @m.set @key1, @marshalled
35
- @m.set @key2, @marshalled
36
- @m.set @key3, @marshalled
30
+ @m = Dalli::Client.new(@servers, :marshal => false)
31
+ x.report("set:plain:dalli") do
32
+ n.times do
33
+ @m.set @key1, @marshalled
34
+ @m.set @key2, @marshalled
35
+ @m.set @key3, @marshalled
36
+ @m.set @key1, @marshalled
37
+ @m.set @key2, @marshalled
38
+ @m.set @key3, @marshalled
39
+ end
37
40
  end
38
- end
39
41
 
40
- @m = Dalli::Client.new(@servers)
41
- x.report("set:ruby:dalli") do
42
- n.times do
43
- @m.set @key1, @value
44
- @m.set @key2, @value
45
- @m.set @key3, @value
46
- @m.set @key1, @value
47
- @m.set @key2, @value
48
- @m.set @key3, @value
42
+ @m = Dalli::Client.new(@servers)
43
+ x.report("set:ruby:dalli") do
44
+ n.times do
45
+ @m.set @key1, @value
46
+ @m.set @key2, @value
47
+ @m.set @key3, @value
48
+ @m.set @key1, @value
49
+ @m.set @key2, @value
50
+ @m.set @key3, @value
51
+ end
49
52
  end
50
- end
51
53
 
52
- @m = Dalli::Client.new(@servers, :marshal => false)
53
- x.report("get:plain:dalli") do
54
- n.times do
55
- @m.get @key1
56
- @m.get @key2
57
- @m.get @key3
58
- @m.get @key1
59
- @m.get @key2
60
- @m.get @key3
54
+ @m = Dalli::Client.new(@servers, :marshal => false)
55
+ x.report("get:plain:dalli") do
56
+ n.times do
57
+ @m.get @key1
58
+ @m.get @key2
59
+ @m.get @key3
60
+ @m.get @key1
61
+ @m.get @key2
62
+ @m.get @key3
63
+ end
61
64
  end
62
- end
63
65
 
64
- @m = Dalli::Client.new(@servers)
65
- x.report("get:ruby:dalli") do
66
- n.times do
67
- @m.get @key1
68
- @m.get @key2
69
- @m.get @key3
70
- @m.get @key1
71
- @m.get @key2
72
- @m.get @key3
66
+ @m = Dalli::Client.new(@servers)
67
+ x.report("get:ruby:dalli") do
68
+ n.times do
69
+ @m.get @key1
70
+ @m.get @key2
71
+ @m.get @key3
72
+ @m.get @key1
73
+ @m.get @key2
74
+ @m.get @key3
75
+ end
73
76
  end
74
- end
75
77
 
76
- @m = Dalli::Client.new(@servers)
77
- x.report("multiget:ruby:dalli") do
78
- n.times do
79
- # We don't use the keys array because splat is slow
80
- @m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
78
+ @m = Dalli::Client.new(@servers)
79
+ x.report("multiget:ruby:dalli") do
80
+ n.times do
81
+ # We don't use the keys array because splat is slow
82
+ @m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
83
+ end
81
84
  end
82
- end
83
85
 
84
- @m = Dalli::Client.new(@servers)
85
- x.report("missing:ruby:dalli") do
86
- n.times do
87
- begin @m.delete @key1; rescue; end
88
- begin @m.get @key1; rescue; end
89
- begin @m.delete @key2; rescue; end
90
- begin @m.get @key2; rescue; end
91
- begin @m.delete @key3; rescue; end
92
- begin @m.get @key3; rescue; end
86
+ @m = Dalli::Client.new(@servers)
87
+ x.report("missing:ruby:dalli") do
88
+ n.times do
89
+ begin @m.delete @key1; rescue; end
90
+ begin @m.get @key1; rescue; end
91
+ begin @m.delete @key2; rescue; end
92
+ begin @m.get @key2; rescue; end
93
+ begin @m.delete @key3; rescue; end
94
+ begin @m.get @key3; rescue; end
95
+ end
93
96
  end
94
- end
95
97
 
96
- @m = Dalli::Client.new(@servers)
97
- x.report("mixed:ruby:dalli") do
98
- n.times do
99
- @m.set @key1, @value
100
- @m.set @key2, @value
101
- @m.set @key3, @value
102
- @m.get @key1
103
- @m.get @key2
104
- @m.get @key3
105
- @m.set @key1, @value
106
- @m.get @key1
107
- @m.set @key2, @value
108
- @m.get @key2
109
- @m.set @key3, @value
110
- @m.get @key3
98
+ @m = Dalli::Client.new(@servers)
99
+ x.report("mixed:ruby:dalli") do
100
+ n.times do
101
+ @m.set @key1, @value
102
+ @m.set @key2, @value
103
+ @m.set @key3, @value
104
+ @m.get @key1
105
+ @m.get @key2
106
+ @m.get @key3
107
+ @m.set @key1, @value
108
+ @m.get @key1
109
+ @m.set @key2, @value
110
+ @m.get @key2
111
+ @m.set @key3, @value
112
+ @m.get @key3
113
+ end
111
114
  end
112
- end
113
115
 
114
- assert true
116
+ assert true
117
+ end
115
118
  end
116
119
 
117
120
  end
@@ -1,97 +1,258 @@
1
1
  require 'helper'
2
+ require 'memcached_mock'
2
3
 
3
4
  class TestDalli < Test::Unit::TestCase
4
5
  context 'using a live server' do
5
- setup do
6
- begin
7
- TCPSocket.new('localhost', 11211)
8
- rescue => ex
9
- $skip = true
10
- puts "Skipping live test as memcached is not running at localhost:11211. Start it with 'memcached -d'"
11
- end
12
- end
13
6
 
14
7
  should "support huge get/set" do
15
- return if $skip
16
- dc = Dalli::Client.new('localhost:11211')
17
- dc.flush
8
+ memcached do |dc|
9
+ dc.flush
18
10
 
19
- val1 = "1234567890"*105000
20
- assert_error Dalli::DalliError, /too large/ do
11
+ val1 = "1234567890"*105000
12
+ assert_error Dalli::DalliError, /too large/ do
13
+ dc.set('a', val1)
14
+ val2 = dc.get('a')
15
+ assert_equal val1, val2
16
+ end
17
+
18
+ val1 = "1234567890"*100000
21
19
  dc.set('a', val1)
22
20
  val2 = dc.get('a')
23
21
  assert_equal val1, val2
24
22
  end
23
+ end
24
+
25
+ should "support the fetch operation" do
26
+ memcached do |dc|
27
+ dc.flush
28
+
29
+ expected = { 'blah' => 'blerg!' }
30
+ executed = false
31
+ value = dc.fetch('fetch_key') do
32
+ executed = true
33
+ expected
34
+ end
35
+ assert_equal expected, value
36
+ assert_equal true, executed
37
+
38
+ executed = false
39
+ value = dc.fetch('fetch_key') do
40
+ executed = true
41
+ expected
42
+ end
43
+ assert_equal expected, value
44
+ assert_equal false, executed
45
+ end
46
+ end
47
+
48
+ should "support the cas operation" do
49
+ memcached do |dc|
50
+ dc.flush
51
+
52
+ expected = { 'blah' => 'blerg!' }
25
53
 
26
- val1 = "1234567890"*100000
27
- dc.set('a', val1)
28
- val2 = dc.get('a')
29
- assert_equal val1, val2
54
+ resp = dc.cas('cas_key') do |value|
55
+ fail('Value should not exist')
56
+ end
57
+ assert_nil resp
58
+
59
+ mutated = { 'blah' => 'foo!' }
60
+ dc.set('cas_key', expected)
61
+ resp = dc.cas('cas_key') do |value|
62
+ assert_equal expected, value
63
+ mutated
64
+ end
65
+ assert_equal true, resp
66
+
67
+ resp = dc.get('cas_key')
68
+ assert_equal mutated, resp
69
+
70
+ # TODO Need to verify failure when value is mutated between get and add.
71
+ end
30
72
  end
31
73
 
32
74
  should "support multi-get" do
33
- return if $skip
34
- dc = Dalli::Client.new(['localhost:11211', '127.0.0.1'])
35
- dc.flush
36
- resp = dc.get_multi(%w(a b c d e f))
37
- assert_equal({}, resp)
38
-
39
- dc.set('a', 'foo')
40
- dc.set('b', 123)
41
- dc.set('c', %w(a b c))
42
- resp = dc.get_multi(%w(a b c d e f))
43
- assert_equal({ 'a' => 'foo', 'b' => 123, 'c' => %w(a b c) }, resp)
75
+ memcached do |dc|
76
+ dc.flush
77
+ resp = dc.get_multi(%w(a b c d e f))
78
+ assert_equal({}, resp)
79
+
80
+ dc.set('a', 'foo')
81
+ dc.set('b', 123)
82
+ dc.set('c', %w(a b c))
83
+ resp = dc.get_multi(%w(a b c d e f))
84
+ assert_equal({ 'a' => 'foo', 'b' => 123, 'c' => %w(a b c) }, resp)
85
+ end
44
86
  end
45
87
 
46
- should "pass a simple smoke test" do
47
- return if $skip
48
-
49
- dc = Dalli::Client.new('localhost:11211')
50
- resp = dc.flush
51
- assert_not_nil resp
52
- assert_equal [true], resp
53
-
54
- resp = dc.get('123')
55
- assert_equal nil, resp
56
-
57
- resp = dc.set('123', 'xyz')
58
- assert_equal true, resp
59
-
60
- resp = dc.get('123')
61
- assert_equal 'xyz', resp
62
-
63
- resp = dc.set('123', 'abc')
64
- assert_equal true, resp
65
-
66
- assert_raises Dalli::DalliError do
67
- dc.prepend('123', '0')
88
+ should "support incr/decr operations" do
89
+ memcached do |dc|
90
+ dc.flush
91
+
92
+ resp = dc.decr('counter', 100, 5, 0)
93
+ assert_equal 0, resp
94
+
95
+ resp = dc.decr('counter', 10)
96
+ assert_equal 0, resp
97
+
98
+ resp = dc.incr('counter', 10)
99
+ assert_equal 10, resp
100
+
101
+ current = 10
102
+ 100.times do |x|
103
+ resp = dc.incr('counter', 10)
104
+ assert_equal current + ((x+1)*10), resp
105
+ end
106
+
107
+ resp = dc.decr('10billion', 0, 5, 10)
108
+ # go over the 32-bit mark to verify proper (un)packing
109
+ resp = dc.incr('10billion', 10_000_000_000)
110
+ assert_equal 10_000_000_010, resp
111
+
112
+ resp = dc.decr('10billion', 1)
113
+ assert_equal 10_000_000_009, resp
114
+
115
+ resp = dc.decr('10billion', 0)
116
+ assert_equal 10_000_000_009, resp
117
+
118
+ resp = dc.incr('10billion', 0)
119
+ assert_equal 10_000_000_009, resp
120
+
121
+ assert_nil dc.incr('DNE', 10)
122
+ assert_nil dc.decr('DNE', 10)
123
+
124
+ resp = dc.incr('big', 100, 5, 0xFFFFFFFFFFFFFFFE)
125
+ assert_equal 0xFFFFFFFFFFFFFFFE, resp
126
+ resp = dc.incr('big', 1)
127
+ assert_equal 0xFFFFFFFFFFFFFFFF, resp
128
+
129
+ # rollover the 64-bit value, we'll get something undefined.
130
+ resp = dc.incr('big', 1)
131
+ assert_not_equal 0x10000000000000000, resp
68
132
  end
133
+ end
134
+
135
+ should "pass a simple smoke test" do
136
+ memcached do |dc|
137
+ resp = dc.flush
138
+ assert_not_nil resp
139
+ assert_equal [true, true], resp
140
+
141
+ resp = dc.get('123')
142
+ assert_equal nil, resp
143
+
144
+ resp = dc.set('123', 'xyz')
145
+ assert_equal true, resp
146
+
147
+ resp = dc.get('123')
148
+ assert_equal 'xyz', resp
149
+
150
+ resp = dc.set('123', 'abc')
151
+ assert_equal true, resp
152
+
153
+ assert_raises Dalli::DalliError do
154
+ dc.prepend('123', '0')
155
+ end
156
+
157
+ assert_raises Dalli::DalliError do
158
+ dc.append('123', '0')
159
+ end
160
+
161
+ resp = dc.get('123')
162
+ assert_equal 'abc', resp
163
+ dc.close
164
+ dc = nil
165
+
166
+ dc = Dalli::Client.new('localhost:19122', :marshal => false)
167
+
168
+ resp = dc.set('456', 'xyz')
169
+ assert_equal true, resp
170
+
171
+ resp = dc.prepend '456', '0'
172
+ assert_equal true, resp
69
173
 
70
- assert_raises Dalli::DalliError do
71
- dc.append('123', '0')
174
+ resp = dc.append '456', '9'
175
+ assert_equal true, resp
176
+
177
+ resp = dc.get('456')
178
+ assert_equal '0xyz9', resp
179
+
180
+ resp = dc.stats
181
+ assert_equal Hash, resp.class
72
182
  end
183
+ end
184
+
185
+ should "support multithreaded access" do
186
+ memcached(11211) do |cache|
187
+ cache.flush
188
+ workers = []
73
189
 
74
- resp = dc.get('123')
75
- assert_equal 'abc', resp
76
- dc.close
77
- dc = nil
190
+ cache.set('f', 'zzz')
191
+ assert_equal true, (cache.cas('f') do |value|
192
+ value << 'z'
193
+ end)
194
+ assert_equal 'zzzz', cache.get('f')
78
195
 
79
- dc = Dalli::Client.new('localhost:11211', :marshal => false)
196
+ # Have a bunch of threads perform a bunch of operations at the same time.
197
+ # Verify the result of each operation to ensure the request and response
198
+ # are not intermingled between threads.
199
+ 10.times do
200
+ workers << Thread.new do
201
+ 100.times do
202
+ cache.set('a', 9)
203
+ cache.set('b', 11)
204
+ inc = cache.incr('cat', 10, 0, 10)
205
+ cache.set('f', 'zzz')
206
+ assert_not_nil(cache.cas('f') do |value|
207
+ value << 'z'
208
+ end)
209
+ assert_equal false, cache.add('a', 11)
210
+ assert_equal({ 'a' => 9, 'b' => 11 }, cache.get_multi(['a', 'b']))
211
+ inc = cache.incr('cat', 10)
212
+ assert_equal 0, inc % 5
213
+ dec = cache.decr('cat', 5)
214
+ assert_equal 11, cache.get('b')
215
+ end
216
+ end
217
+ end
80
218
 
81
- resp = dc.set('456', 'xyz')
82
- assert_equal true, resp
83
-
84
- resp = dc.prepend '456', '0'
85
- assert_equal true, resp
219
+ workers.each { |w| w.join }
220
+ cache.flush
221
+ end
222
+ end
86
223
 
87
- resp = dc.append '456', '9'
88
- assert_equal true, resp
224
+ should 'gracefully handle authentication failures' do
225
+ memcached(19122, '-S') do |dc|
226
+ assert_raise Dalli::DalliError, /32/ do
227
+ dc.set('abc', 123)
228
+ end
229
+ end
230
+ end
89
231
 
90
- resp = dc.get('456')
91
- assert_equal '0xyz9', resp
92
-
93
- resp = dc.stats
94
- assert_equal Hash, resp.class
232
+ # OSX: Create a SASL user for the memcached application like so:
233
+ #
234
+ # saslpasswd2 -a memcached -c testuser
235
+ #
236
+ # with password 'testtest'
237
+ context 'in an authenticated environment' do
238
+ setup do
239
+ ENV['MEMCACHE_USERNAME'] = 'testuser'
240
+ ENV['MEMCACHE_PASSWORD'] = 'testtest'
241
+ end
242
+
243
+ teardown do
244
+ ENV['MEMCACHE_USERNAME'] = nil
245
+ ENV['MEMCACHE_PASSWORD'] = nil
246
+ end
247
+
248
+ should 'support SASL authentication' do
249
+ memcached(19121, '-S') do |dc|
250
+ assert_equal true, dc.set('abc', 123)
251
+ assert_equal 123, dc.get('abc')
252
+ assert_equal({"localhost:19121"=>{}}, dc.stats)
253
+ end
254
+ end
95
255
  end
256
+
96
257
  end
97
258
  end