| 1 |
require "#{File.dirname(__FILE__)}/../../abstract_unit" |
|---|
| 2 |
require 'action_controller/cgi_process' |
|---|
| 3 |
require 'action_controller/cgi_ext' |
|---|
| 4 |
require "mocha" |
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
class CGI::Session |
|---|
| 8 |
def cache |
|---|
| 9 |
dbman.instance_variable_get(:@cache) |
|---|
| 10 |
end |
|---|
| 11 |
end |
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
class MemCacheStoreTest < Test::Unit::TestCase |
|---|
| 15 |
|
|---|
| 16 |
SESSION_KEY_RE = /^session:[0-9a-z]+/ |
|---|
| 17 |
CONN_TEST_KEY = 'connection_test' |
|---|
| 18 |
MULTI_TEST_KEY = '0123456789' |
|---|
| 19 |
TEST_DATA = 'Hello test' |
|---|
| 20 |
|
|---|
| 21 |
def self.get_mem_cache_if_available |
|---|
| 22 |
begin |
|---|
| 23 |
require 'memcache' |
|---|
| 24 |
cache = MemCache.new('127.0.0.1') |
|---|
| 25 |
|
|---|
| 26 |
cache.set(CONN_TEST_KEY, 1) |
|---|
| 27 |
unless cache.get(CONN_TEST_KEY) == 1 |
|---|
| 28 |
puts 'Warning: memcache server available but corrupted.' |
|---|
| 29 |
return nil |
|---|
| 30 |
end |
|---|
| 31 |
rescue LoadError, MemCache::MemCacheError |
|---|
| 32 |
return nil |
|---|
| 33 |
end |
|---|
| 34 |
return cache |
|---|
| 35 |
end |
|---|
| 36 |
|
|---|
| 37 |
CACHE = get_mem_cache_if_available |
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
def test_initialization |
|---|
| 41 |
assert_raise(ArgumentError) { new_session('session_id' => '!invalid_id') } |
|---|
| 42 |
new_session do |s| |
|---|
| 43 |
assert_equal Hash.new, s.cache.get('session:' + s.session_id) |
|---|
| 44 |
end |
|---|
| 45 |
end |
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
def test_storage |
|---|
| 49 |
d = rand(0xffff) |
|---|
| 50 |
new_session do |s| |
|---|
| 51 |
session_key = 'session:' + s.session_id |
|---|
| 52 |
unless CACHE |
|---|
| 53 |
s.cache.expects(:get).with(session_key) \ |
|---|
| 54 |
.returns(:test => d) |
|---|
| 55 |
s.cache.expects(:set).with(session_key, |
|---|
| 56 |
has_entry(:test, d), |
|---|
| 57 |
0) |
|---|
| 58 |
end |
|---|
| 59 |
s[:test] = d |
|---|
| 60 |
s.close |
|---|
| 61 |
assert_equal d, s.cache.get(session_key)[:test] |
|---|
| 62 |
assert_equal d, s[:test] |
|---|
| 63 |
end |
|---|
| 64 |
end |
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
def test_deletion |
|---|
| 68 |
new_session do |s| |
|---|
| 69 |
session_key = 'session:' + s.session_id |
|---|
| 70 |
unless CACHE |
|---|
| 71 |
s.cache.expects(:delete) |
|---|
| 72 |
s.cache.expects(:get).with(session_key) \ |
|---|
| 73 |
.returns(nil) |
|---|
| 74 |
end |
|---|
| 75 |
s[:test] = rand(0xffff) |
|---|
| 76 |
s.delete |
|---|
| 77 |
assert_nil s.cache.get(session_key) |
|---|
| 78 |
end |
|---|
| 79 |
end |
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
def test_other_session_retrieval |
|---|
| 83 |
new_session do |sa| |
|---|
| 84 |
unless CACHE |
|---|
| 85 |
sa.cache.expects(:set).with('session:' + sa.session_id, |
|---|
| 86 |
has_entry(:test, TEST_DATA), |
|---|
| 87 |
0) |
|---|
| 88 |
end |
|---|
| 89 |
sa[:test] = TEST_DATA |
|---|
| 90 |
sa.close |
|---|
| 91 |
new_session('session_id' => sa.session_id) do |sb| |
|---|
| 92 |
unless CACHE |
|---|
| 93 |
sb.cache.expects(:[]).with('session:' + sb.session_id) \ |
|---|
| 94 |
.returns(:test => TEST_DATA) |
|---|
| 95 |
end |
|---|
| 96 |
assert_equal(TEST_DATA, sb[:test]) |
|---|
| 97 |
end |
|---|
| 98 |
end |
|---|
| 99 |
end |
|---|
| 100 |
|
|---|
| 101 |
|
|---|
| 102 |
def test_multiple_sessions |
|---|
| 103 |
s_slots = Array.new(10) |
|---|
| 104 |
operation = :write |
|---|
| 105 |
last_data = nil |
|---|
| 106 |
reads = writes = 0 |
|---|
| 107 |
50.times do |
|---|
| 108 |
current = rand(10) |
|---|
| 109 |
s_slots[current] ||= new_session('session_id' => MULTI_TEST_KEY, |
|---|
| 110 |
'new_session' => true) |
|---|
| 111 |
s = s_slots[current] |
|---|
| 112 |
case operation |
|---|
| 113 |
when :write |
|---|
| 114 |
last_data = rand(0xffff) |
|---|
| 115 |
unless CACHE |
|---|
| 116 |
s.cache.expects(:set).with('session:' + MULTI_TEST_KEY, |
|---|
| 117 |
{ :test => last_data }, |
|---|
| 118 |
0) |
|---|
| 119 |
end |
|---|
| 120 |
s[:test] = last_data |
|---|
| 121 |
s.close |
|---|
| 122 |
writes += 1 |
|---|
| 123 |
when :read |
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 |
s.instance_variable_set(:@data, nil) |
|---|
| 127 |
unless CACHE |
|---|
| 128 |
s.cache.expects(:[]).with('session:' + MULTI_TEST_KEY) \ |
|---|
| 129 |
.returns(:test => last_data) |
|---|
| 130 |
end |
|---|
| 131 |
d = s[:test] |
|---|
| 132 |
assert_equal(last_data, d, "OK reads: #{reads}, OK writes: #{writes}") |
|---|
| 133 |
reads += 1 |
|---|
| 134 |
end |
|---|
| 135 |
operation = rand(5) == 0 ? :write : :read |
|---|
| 136 |
end |
|---|
| 137 |
end |
|---|
| 138 |
|
|---|
| 139 |
|
|---|
| 140 |
|
|---|
| 141 |
private |
|---|
| 142 |
def obtain_session_options |
|---|
| 143 |
options = { 'database_manager' => CGI::Session::MemCacheStore, |
|---|
| 144 |
'session_key' => '_test_app_session' |
|---|
| 145 |
} |
|---|
| 146 |
|
|---|
| 147 |
unless CACHE |
|---|
| 148 |
options['cache'] = c = mock |
|---|
| 149 |
c.stubs(:[]).with(regexp_matches(SESSION_KEY_RE)) |
|---|
| 150 |
c.stubs(:get).with(regexp_matches(SESSION_KEY_RE)) \ |
|---|
| 151 |
.returns(Hash.new) |
|---|
| 152 |
c.stubs(:add).with(regexp_matches(SESSION_KEY_RE), |
|---|
| 153 |
instance_of(Hash), |
|---|
| 154 |
0) |
|---|
| 155 |
end |
|---|
| 156 |
options |
|---|
| 157 |
end |
|---|
| 158 |
|
|---|
| 159 |
|
|---|
| 160 |
def new_session(options = {}) |
|---|
| 161 |
with_cgi do |cgi| |
|---|
| 162 |
@options = obtain_session_options.merge(options) |
|---|
| 163 |
session = CGI::Session.new(cgi, @options) |
|---|
| 164 |
yield session if block_given? |
|---|
| 165 |
return session |
|---|
| 166 |
end |
|---|
| 167 |
end |
|---|
| 168 |
|
|---|
| 169 |
def with_cgi |
|---|
| 170 |
ENV['REQUEST_METHOD'] = 'GET' |
|---|
| 171 |
ENV['HTTP_HOST'] = 'example.com' |
|---|
| 172 |
ENV['QUERY_STRING'] = '' |
|---|
| 173 |
|
|---|
| 174 |
cgi = CGI.new('query', StringIO.new('')) |
|---|
| 175 |
yield cgi if block_given? |
|---|
| 176 |
cgi |
|---|
| 177 |
end |
|---|
| 178 |
end |
|---|