dalli 0.9.0

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.

@@ -0,0 +1,3 @@
1
+ module Dalli
2
+ VERSION = '0.9.0'
3
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ require 'dalli'
6
+
7
+ class Test::Unit::TestCase
8
+ def assert_error(error, regexp=nil, &block)
9
+ ex = assert_raise(error, &block)
10
+ assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ require "socket"
2
+
3
+ module MemcachedMock
4
+ def self.start(port=22122, &block)
5
+ server = TCPServer.new("localhost", port)
6
+ session = server.accept
7
+ block.call session
8
+ end
9
+
10
+ def self.delayed_start(port=22122, wait=1, &block)
11
+ server = TCPServer.new("localhost", port)
12
+ sleep wait
13
+ # session = server.accept
14
+ block.call server
15
+ end
16
+
17
+ module Helper
18
+ # Forks the current process and starts a new mock Memcached server on
19
+ # port 22122.
20
+ #
21
+ # memcached_mock(lambda {|sock| socket.write('123') }) do
22
+ # assert_equal "PONG", Dalli::Client.new('localhost:22122').get('abc')
23
+ # end
24
+ #
25
+ def memcached_mock(proc, meth = :start)
26
+ begin
27
+ pid = fork do
28
+ trap("TERM") { exit }
29
+
30
+ MemcachedMock.send(meth) do |*args|
31
+ proc.call(*args)
32
+ end
33
+ end
34
+
35
+ sleep 0.5 # Give time for the socket to start listening.
36
+ yield
37
+ ensure
38
+ if pid
39
+ Process.kill("TERM", pid)
40
+ Process.wait(pid)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,75 @@
1
+ require 'helper'
2
+ require 'active_support/all'
3
+ require 'active_support/cache/dalli_store'
4
+
5
+ class TestDalli < Test::Unit::TestCase
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
+
13
+ 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
17
+
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
24
+
25
+ dvalue = @mc.fetch(rand_key) { o }
26
+ mvalue = @dalli.fetch(rand_key) { o }
27
+ assert_equal mvalue, dvalue
28
+ assert_equal o, dvalue
29
+ end
30
+
31
+ 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))
42
+ end
43
+
44
+ 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
52
+
53
+ mres = @mc.read(x)
54
+ dres = @dalli.read(y)
55
+ assert_equal mres, dres
56
+ assert_equal 123, dres
57
+
58
+ mres = @mc.delete(x)
59
+ dres = @dalli.delete(y)
60
+ assert_equal mres, dres
61
+ assert_equal true, dres
62
+ end
63
+
64
+ 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
+ end
70
+ end
71
+
72
+ def rand_key
73
+ rand(1_000_000_000)
74
+ end
75
+ end
@@ -0,0 +1,118 @@
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:11211', 'localhost:11211']
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
+ end
22
+
23
+ def test_benchmark
24
+ Benchmark.bm(31) do |x|
25
+
26
+ n = 2500
27
+
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
37
+ end
38
+ end
39
+
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
49
+ end
50
+ end
51
+
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
61
+ end
62
+ end
63
+
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
73
+ end
74
+ end
75
+
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
81
+ end
82
+ end
83
+
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
93
+ end
94
+ end
95
+
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
111
+ end
112
+ end
113
+
114
+ assert true
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,97 @@
1
+ require 'helper'
2
+
3
+ class TestDalli < Test::Unit::TestCase
4
+ 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
+
14
+ should "support huge get/set" do
15
+ return if $skip
16
+ dc = Dalli::Client.new('localhost:11211')
17
+ dc.flush
18
+
19
+ val1 = "1234567890"*105000
20
+ assert_error Dalli::DalliError, /too large/ do
21
+ dc.set('a', val1)
22
+ val2 = dc.get('a')
23
+ assert_equal val1, val2
24
+ end
25
+
26
+ val1 = "1234567890"*100000
27
+ dc.set('a', val1)
28
+ val2 = dc.get('a')
29
+ assert_equal val1, val2
30
+ end
31
+
32
+ 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)
44
+ end
45
+
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')
68
+ end
69
+
70
+ assert_raises Dalli::DalliError do
71
+ dc.append('123', '0')
72
+ end
73
+
74
+ resp = dc.get('123')
75
+ assert_equal 'abc', resp
76
+ dc.close
77
+ dc = nil
78
+
79
+ dc = Dalli::Client.new('localhost:11211', :marshal => false)
80
+
81
+ resp = dc.set('456', 'xyz')
82
+ assert_equal true, resp
83
+
84
+ resp = dc.prepend '456', '0'
85
+ assert_equal true, resp
86
+
87
+ resp = dc.append '456', '9'
88
+ assert_equal true, resp
89
+
90
+ resp = dc.get('456')
91
+ assert_equal '0xyz9', resp
92
+
93
+ resp = dc.stats
94
+ assert_equal Hash, resp.class
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,59 @@
1
+ require 'helper'
2
+ require 'memcached_mock'
3
+
4
+ class TestNetwork < Test::Unit::TestCase
5
+
6
+ include MemcachedMock::Helper
7
+
8
+ context 'assuming a bad network' do
9
+
10
+ should 'handle connection refused' do
11
+ assert_raise Dalli::NetworkError do
12
+ dc = Dalli::Client.new 'localhost:19122'
13
+ dc.get 'foo'
14
+ end
15
+ end
16
+
17
+ context 'with a fake server' do
18
+
19
+ should 'handle connection reset' do
20
+ memcached_mock(lambda {|sock| sock.close }) do
21
+ assert_error Dalli::NetworkError, /ECONNRESET/ do
22
+ dc = Dalli::Client.new('localhost:22122')
23
+ dc.get('abc')
24
+ end
25
+ end
26
+ end
27
+
28
+ should 'handle malformed response' do
29
+ memcached_mock(lambda {|sock| sock.write('123') }) do
30
+ assert_error Dalli::NetworkError, /EOFError/ do
31
+ dc = Dalli::Client.new('localhost:22122')
32
+ dc.get('abc')
33
+ end
34
+ end
35
+ end
36
+
37
+ should 'handle connect timeouts' do
38
+ memcached_mock(lambda {|sock| sleep(0.6); sock.close }, :delayed_start) do
39
+ assert_error Dalli::NetworkError, /Timeout::Error/ do
40
+ dc = Dalli::Client.new('localhost:22122')
41
+ dc.get('abc')
42
+ end
43
+ end
44
+ end
45
+
46
+
47
+ should 'handle read timeouts' do
48
+ memcached_mock(lambda {|sock| sleep(0.6); sock.write('giraffe') }) do
49
+ assert_error Dalli::NetworkError, /Timeout::Error/ do
50
+ dc = Dalli::Client.new('localhost:22122')
51
+ dc.get('abc')
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dalli
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 9
8
+ - 0
9
+ version: 0.9.0
10
+ platform: ruby
11
+ authors:
12
+ - Mike Perham
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-08-19 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rails
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 3
43
+ - 0
44
+ - 0
45
+ - rc
46
+ version: 3.0.0.rc
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: memcache-client
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 1
59
+ - 8
60
+ - 5
61
+ version: 1.8.5
62
+ type: :development
63
+ version_requirements: *id003
64
+ description: High performance memcached client for Ruby
65
+ email: mperham@gmail.com
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - lib/active_support/cache/dalli_store.rb
74
+ - lib/dalli/client.rb
75
+ - lib/dalli/options.rb
76
+ - lib/dalli/ring.rb
77
+ - lib/dalli/server.rb
78
+ - lib/dalli/version.rb
79
+ - lib/dalli.rb
80
+ - LICENSE
81
+ - README.md
82
+ - Rakefile
83
+ - Gemfile
84
+ - dalli.gemspec
85
+ - Performance.md
86
+ - test/helper.rb
87
+ - test/memcached_mock.rb
88
+ - test/test_active_support.rb
89
+ - test/test_benchmark.rb
90
+ - test/test_dalli.rb
91
+ - test/test_network.rb
92
+ has_rdoc: true
93
+ homepage: http://github.com/mperham/dalli
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options:
98
+ - --charset=UTF-8
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project:
120
+ rubygems_version: 1.3.7
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: High performance memcached client for Ruby
124
+ test_files:
125
+ - test/helper.rb
126
+ - test/memcached_mock.rb
127
+ - test/test_active_support.rb
128
+ - test/test_benchmark.rb
129
+ - test/test_dalli.rb
130
+ - test/test_network.rb