dalli 0.9.2 → 0.9.3

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.

@@ -73,6 +73,7 @@ class TestDalli < Test::Unit::TestCase
73
73
 
74
74
  should "support multi-get" do
75
75
  memcached do |dc|
76
+ dc.close
76
77
  dc.flush
77
78
  resp = dc.get_multi(%w(a b c d e f))
78
79
  assert_equal({}, resp)
@@ -129,6 +130,7 @@ class TestDalli < Test::Unit::TestCase
129
130
  # rollover the 64-bit value, we'll get something undefined.
130
131
  resp = dc.incr('big', 1)
131
132
  assert_not_equal 0x10000000000000000, resp
133
+ dc.reset
132
134
  end
133
135
  end
134
136
 
@@ -179,11 +181,13 @@ class TestDalli < Test::Unit::TestCase
179
181
 
180
182
  resp = dc.stats
181
183
  assert_equal Hash, resp.class
184
+
185
+ dc.close
182
186
  end
183
187
  end
184
188
 
185
189
  should "support multithreaded access" do
186
- memcached(11211) do |cache|
190
+ memcached(19123) do |cache|
187
191
  cache.flush
188
192
  workers = []
189
193
 
@@ -0,0 +1,200 @@
1
+ require 'helper'
2
+
3
+ require 'abstract_unit'
4
+ require 'action_dispatch/middleware/session/dalli_store'
5
+
6
+ class Foo
7
+ def initialize(bar='baz')
8
+ @bar = bar
9
+ end
10
+ def inspect
11
+ "#<#{self.class} bar:#{@bar.inspect}>"
12
+ end
13
+ end
14
+
15
+ class TestSessionStore < ActionController::IntegrationTest
16
+ class TestController < ActionController::Base
17
+ def no_session_access
18
+ head :ok
19
+ end
20
+
21
+ def set_session_value
22
+ session[:foo] = "bar"
23
+ head :ok
24
+ end
25
+
26
+ def set_serialized_session_value
27
+ session[:foo] = Foo.new
28
+ head :ok
29
+ end
30
+
31
+ def get_session_value
32
+ render :text => "foo: #{session[:foo].inspect}"
33
+ end
34
+
35
+ def get_session_id
36
+ render :text => "#{request.session_options[:id]}"
37
+ end
38
+
39
+ def call_reset_session
40
+ session[:bar]
41
+ reset_session
42
+ session[:bar] = "baz"
43
+ head :ok
44
+ end
45
+
46
+ def rescue_action(e) raise end
47
+ end
48
+
49
+ begin
50
+ require 'dalli'
51
+ memcache = Dalli::Client.new('localhost:11211')
52
+ memcache.set('ping', '')
53
+
54
+ def test_setting_and_getting_session_value
55
+ with_test_route_set do
56
+ get '/set_session_value'
57
+ assert_response :success
58
+ assert cookies['_session_id']
59
+
60
+ get '/get_session_value'
61
+ assert_response :success
62
+ assert_equal 'foo: "bar"', response.body
63
+ end
64
+ end
65
+
66
+ def test_getting_nil_session_value
67
+ with_test_route_set do
68
+ get '/get_session_value'
69
+ assert_response :success
70
+ assert_equal 'foo: nil', response.body
71
+ end
72
+ end
73
+
74
+ def test_getting_session_value_after_session_reset
75
+ with_test_route_set do
76
+ get '/set_session_value'
77
+ assert_response :success
78
+ assert cookies['_session_id']
79
+ session_cookie = cookies.send(:hash_for)['_session_id']
80
+
81
+ get '/call_reset_session'
82
+ assert_response :success
83
+ assert_not_equal [], headers['Set-Cookie']
84
+
85
+ cookies << session_cookie # replace our new session_id with our old, pre-reset session_id
86
+
87
+ get '/get_session_value'
88
+ assert_response :success
89
+ assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from memcached"
90
+ end
91
+ end
92
+
93
+ def test_getting_from_nonexistent_session
94
+ with_test_route_set do
95
+ get '/get_session_value'
96
+ assert_response :success
97
+ assert_equal 'foo: nil', response.body
98
+ assert_nil cookies['_session_id'], "should only create session on write, not read"
99
+ end
100
+ end
101
+
102
+ def test_setting_session_value_after_session_reset
103
+ with_test_route_set do
104
+ get '/set_session_value'
105
+ assert_response :success
106
+ assert cookies['_session_id']
107
+ session_id = cookies['_session_id']
108
+
109
+ get '/call_reset_session'
110
+ assert_response :success
111
+ assert_not_equal [], headers['Set-Cookie']
112
+
113
+ get '/get_session_value'
114
+ assert_response :success
115
+ assert_equal 'foo: nil', response.body
116
+
117
+ get '/get_session_id'
118
+ assert_response :success
119
+ assert_not_equal session_id, response.body
120
+ end
121
+ end
122
+
123
+ def test_getting_session_id
124
+ with_test_route_set do
125
+ get '/set_session_value'
126
+ assert_response :success
127
+ assert cookies['_session_id']
128
+ session_id = cookies['_session_id']
129
+
130
+ get '/get_session_id'
131
+ assert_response :success
132
+ assert_equal session_id, response.body, "should be able to read session id without accessing the session hash"
133
+ end
134
+ end
135
+
136
+ def test_deserializes_unloaded_class
137
+ with_test_route_set do
138
+ with_autoload_path "session_autoload_test" do
139
+ get '/set_serialized_session_value'
140
+ assert_response :success
141
+ assert cookies['_session_id']
142
+ end
143
+ with_autoload_path "session_autoload_test" do
144
+ get '/get_session_id'
145
+ assert_response :success
146
+ end
147
+ with_autoload_path "session_autoload_test" do
148
+ get '/get_session_value'
149
+ assert_response :success
150
+ assert_equal 'foo: #<Foo bar:"baz">', response.body, "should auto-load unloaded class"
151
+ end
152
+ end
153
+ end
154
+
155
+ def test_doesnt_write_session_cookie_if_session_id_is_already_exists
156
+ with_test_route_set do
157
+ get '/set_session_value'
158
+ assert_response :success
159
+ assert cookies['_session_id']
160
+
161
+ get '/get_session_value'
162
+ assert_response :success
163
+ assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists"
164
+ end
165
+ end
166
+
167
+ def test_prevents_session_fixation
168
+ with_test_route_set do
169
+ get '/get_session_value'
170
+ assert_response :success
171
+ assert_equal 'foo: nil', response.body
172
+ session_id = cookies['_session_id']
173
+
174
+ reset!
175
+
176
+ get '/set_session_value', :_session_id => session_id
177
+ assert_response :success
178
+ assert_not_equal session_id, cookies['_session_id']
179
+ end
180
+ end
181
+ rescue LoadError, RuntimeError
182
+ $stderr.puts "Skipping TestSessionStore tests. Start memcached and try again."
183
+ end
184
+
185
+ private
186
+ def with_test_route_set
187
+ with_routing do |set|
188
+ set.draw do |map|
189
+ match ':action', :to => ::TestSessionStore::TestController
190
+ end
191
+
192
+ @app = self.class.build_app(set) do |middleware|
193
+ middleware.use ActionDispatch::Session::DalliStore, :key => '_session_id'
194
+ middleware.delete "ActionDispatch::ShowExceptions"
195
+ end
196
+
197
+ yield
198
+ end
199
+ end
200
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 2
9
- version: 0.9.2
8
+ - 3
9
+ version: 0.9.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mike Perham
@@ -55,8 +55,7 @@ dependencies:
55
55
  - 3
56
56
  - 0
57
57
  - 0
58
- - rc2
59
- version: 3.0.0.rc2
58
+ version: 3.0.0
60
59
  type: :development
61
60
  version_requirements: *id003
62
61
  - !ruby/object:Gem::Dependency
@@ -83,14 +82,14 @@ extensions: []
83
82
  extra_rdoc_files: []
84
83
 
85
84
  files:
85
+ - lib/action_dispatch/middleware/session/dalli_store.rb
86
86
  - lib/active_support/cache/dalli_store.rb
87
+ - lib/active_support/cache/dalli_store23.rb
87
88
  - lib/dalli/client.rb
88
89
  - lib/dalli/options.rb
89
90
  - lib/dalli/ring.rb
90
91
  - lib/dalli/sasl/anonymous.rb
91
92
  - lib/dalli/sasl/base.rb
92
- - lib/dalli/sasl/base64.rb
93
- - lib/dalli/sasl/digest_md5.rb
94
93
  - lib/dalli/sasl/plain.rb
95
94
  - lib/dalli/server.rb
96
95
  - lib/dalli/version.rb
@@ -103,12 +102,15 @@ files:
103
102
  - Gemfile
104
103
  - dalli.gemspec
105
104
  - Performance.md
105
+ - Upgrade.md
106
+ - test/abstract_unit.rb
107
+ - test/benchmark_test.rb
106
108
  - test/helper.rb
107
109
  - test/memcached_mock.rb
108
110
  - test/test_active_support.rb
109
- - test/test_benchmark.rb
110
111
  - test/test_dalli.rb
111
112
  - test/test_network.rb
113
+ - test/test_session_store.rb
112
114
  has_rdoc: true
113
115
  homepage: http://github.com/mperham/dalli
114
116
  licenses: []
@@ -142,9 +144,11 @@ signing_key:
142
144
  specification_version: 3
143
145
  summary: High performance memcached client for Ruby
144
146
  test_files:
147
+ - test/abstract_unit.rb
148
+ - test/benchmark_test.rb
145
149
  - test/helper.rb
146
150
  - test/memcached_mock.rb
147
151
  - test/test_active_support.rb
148
- - test/test_benchmark.rb
149
152
  - test/test_dalli.rb
150
153
  - test/test_network.rb
154
+ - test/test_session_store.rb
@@ -1,14 +0,0 @@
1
- begin
2
- require 'base64'
3
- rescue LoadError
4
- # Ruby 1.9 compat
5
- module Base64
6
- def self.encode64(data)
7
- [data].pack('m')
8
- end
9
-
10
- def self.decode64(data64)
11
- data64.unpack('m')[0]
12
- end
13
- end
14
- end
@@ -1,175 +0,0 @@
1
- require 'digest/md5'
2
-
3
- module SASL
4
- ##
5
- # RFC 2831:
6
- # http://tools.ietf.org/html/rfc2831
7
- class DigestMD5 < Mechanism
8
- attr_writer :cnonce
9
-
10
- def initialize(*a)
11
- super
12
- @nonce_count = 0
13
- end
14
-
15
- def start
16
- @state = nil
17
- unless defined? @nonce
18
- ['auth', nil]
19
- else
20
- # reauthentication
21
- receive('challenge', '')
22
- end
23
- end
24
-
25
- def receive(message_name, content)
26
- if message_name == 'challenge'
27
- c = decode_challenge(content)
28
-
29
- unless c['rspauth']
30
- response = {}
31
- if defined?(@nonce) && response['nonce'].nil?
32
- # Could be reauth
33
- else
34
- # No reauth:
35
- @nonce_count = 0
36
- end
37
- @nonce ||= c['nonce']
38
- response['nonce'] = @nonce
39
- response['charset'] = 'utf-8'
40
- response['username'] = preferences.username
41
- response['realm'] = c['realm'] || preferences.realm
42
- @cnonce = generate_nonce unless defined? @cnonce
43
- response['cnonce'] = @cnonce
44
- @nc = next_nc
45
- response['nc'] = @nc
46
- @qop = c['qop'] || 'auth'
47
- response['qop'] = @qop
48
- response['digest-uri'] = preferences.digest_uri #"memcached/#{self.hostname}"
49
- response['response'] = response_value(response['nonce'], response['nc'], response['cnonce'], response['qop'])
50
- ['response', encode_response(response)]
51
- else
52
- rspauth_expected = response_value(@nonce, @nc, @cnonce, @qop, '')
53
- p :rspauth_received=>c['rspauth'], :rspauth_expected=>rspauth_expected
54
- if c['rspauth'] == rspauth_expected
55
- ['response', nil]
56
- else
57
- # Bogus server?
58
- @state = :failure
59
- ['failure', nil]
60
- end
61
- end
62
- else
63
- # No challenge? Might be success or failure
64
- super
65
- end
66
- end
67
-
68
- private
69
-
70
- def decode_challenge(text)
71
- challenge = {}
72
-
73
- state = :key
74
- key = ''
75
- value = ''
76
-
77
- text.scan(/./) do |ch|
78
- if state == :key
79
- if ch == '='
80
- state = :value
81
- elsif ch =~ /\S/
82
- key += ch
83
- end
84
-
85
- elsif state == :value
86
- if ch == ','
87
- challenge[key] = value
88
- key = ''
89
- value = ''
90
- state = :key
91
- elsif ch == '"' and value == ''
92
- state = :quote
93
- else
94
- value += ch
95
- end
96
-
97
- elsif state == :quote
98
- if ch == '"'
99
- state = :value
100
- else
101
- value += ch
102
- end
103
- end
104
- end
105
- challenge[key] = value unless key == ''
106
-
107
- p :decode_challenge => challenge
108
- challenge
109
- end
110
-
111
- def encode_response(response)
112
- p :encode_response => response
113
- response.collect do |k,v|
114
- if v.include?('"')
115
- v.sub!('\\', '\\\\')
116
- v.sub!('"', '\\"')
117
- "#{k}=\"#{v}\""
118
- else
119
- "#{k}=#{v}"
120
- end
121
- end.join(',')
122
- end
123
-
124
- def generate_nonce
125
- nonce = ''
126
- while nonce.length < 16
127
- c = rand(128).chr
128
- nonce += c if c =~ /^[a-zA-Z0-9]$/
129
- end
130
- nonce
131
- end
132
-
133
- ##
134
- # Function from RFC2831
135
- def h(s); Digest::MD5.digest(s); end
136
- ##
137
- # Function from RFC2831
138
- def hh(s); Digest::MD5.hexdigest(s); end
139
-
140
- ##
141
- # Calculate the value for the response field
142
- def response_value(nonce, nc, cnonce, qop, a2_prefix='AUTHENTICATE')
143
- p :response_value => {:nonce=>nonce,
144
- :cnonce=>cnonce,
145
- :qop=>qop,
146
- :username=>preferences.username,
147
- :realm=>preferences.realm,
148
- :password=>preferences.password,
149
- :authzid=>preferences.authzid}
150
- a1_h = h("#{preferences.username}:#{preferences.realm}:#{preferences.password}")
151
- a1 = "#{a1_h}:#{nonce}:#{cnonce}"
152
- if preferences.authzid
153
- a1 += ":#{preferences.authzid}"
154
- end
155
- if qop && (qop.downcase == 'auth-int' || qop.downcase == 'auth-conf')
156
- a2 = "#{a2_prefix}:#{preferences.digest_uri}:00000000000000000000000000000000"
157
- else
158
- a2 = "#{a2_prefix}:#{preferences.digest_uri}"
159
- end
160
- hh("#{hh(a1)}:#{nonce}:#{nc}:#{cnonce}:#{qop}:#{hh(a2)}")
161
- end
162
-
163
- def next_nc
164
- @nonce_count += 1
165
- s = @nonce_count.to_s
166
- s = "0#{s}" while s.length < 8
167
- s
168
- end
169
- end
170
-
171
- # TODO: need to test
172
- #MECHANISMS['DIGEST-MD5'] = SASL::DigestMD5
173
-
174
- end
175
-