Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9823: mem_cache_store_test.rb

File mem_cache_store_test.rb, 4.7 kB (added by kamk, 1 year ago)
Line 
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       # Test availability of the connection
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         # Make CGI::Session#[] think there was no data retrieval yet.
125         # Normally, the session caches the data during its lifetime.
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     # if don't have running memcache server we use mock instead
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