diff options
author | francis <francis> | 2008-01-23 01:48:14 +0000 |
---|---|---|
committer | francis <francis> | 2008-01-23 01:48:14 +0000 |
commit | 60eaae4f7df1f1dae91defb87d3707451c359cf4 (patch) | |
tree | e74835c37779a2f094e810960cda07b99a75330e /vendor/rails-2.0.2/actionpack/test/controller/session | |
parent | 71d22c740302e1f83bbbd89b229734ea9c67493c (diff) |
Freeze in rails 2.0.2 (Am I going to regret having this beast in CVS?)
Diffstat (limited to 'vendor/rails-2.0.2/actionpack/test/controller/session')
-rwxr-xr-x | vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb | 246 | ||||
-rw-r--r-- | vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb | 182 |
2 files changed, 428 insertions, 0 deletions
diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb new file mode 100755 index 000000000..b2655c72d --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb @@ -0,0 +1,246 @@ +require "#{File.dirname(__FILE__)}/../../abstract_unit" +require 'action_controller/cgi_process' +require 'action_controller/cgi_ext' + +require 'stringio' + + +class CGI::Session::CookieStore + def ensure_secret_secure_with_test_hax(secret) + if secret == CookieStoreTest.default_session_options['secret'] + return true + else + ensure_secret_secure_without_test_hax(secret) + end + end + alias_method_chain :ensure_secret_secure, :test_hax +end + + +# Expose for tests. +class CGI + attr_reader :output_cookies, :output_hidden + + class Session + attr_reader :dbman + + class CookieStore + attr_reader :data, :original, :cookie_options + end + end +end + +class CookieStoreTest < Test::Unit::TestCase + def self.default_session_options + { 'database_manager' => CGI::Session::CookieStore, + 'session_key' => '_myapp_session', + 'secret' => 'Keep it secret; keep it safe.', + 'no_cookies' => true, + 'no_hidden' => true } + end + + def self.cookies + { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}], + :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }], + :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }] } + end + + def setup + ENV.delete('HTTP_COOKIE') + end + + def test_raises_argument_error_if_missing_session_key + [nil, ''].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank } + end + end + + def test_raises_argument_error_if_missing_secret + [nil, ''].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } + end + end + + def test_raises_argument_error_if_secret_is_probably_insecure + ["password", "secret", "12345678901234567890123456789"].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } + end + end + + def test_reconfigures_session_to_omit_id_cookie_and_hidden_field + new_session do |session| + assert_equal true, @options['no_hidden'] + assert_equal true, @options['no_cookies'] + end + end + + def test_restore_unmarshals_missing_cookie_as_empty_hash + new_session do |session| + assert_nil session.dbman.data + assert_nil session['test'] + assert_equal Hash.new, session.dbman.data + end + end + + def test_restore_unmarshals_good_cookies + cookies(:empty, :a_one, :typical).each do |value, expected| + set_cookie! value + new_session do |session| + assert_nil session['lazy loads the data hash'] + assert_equal expected, session.dbman.data + end + end + end + + def test_restore_deletes_tampered_cookies + set_cookie! 'a--b' + new_session do |session| + assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] } + assert_cookie_deleted session + end + end + + def test_close_doesnt_write_cookie_if_data_is_blank + new_session do |session| + assert_no_cookies session + session.close + assert_no_cookies session + end + end + + def test_close_doesnt_write_cookie_if_data_is_unchanged + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session['user_id'] = session['user_id'] + session.close + assert_no_cookies session + end + end + + def test_close_raises_when_data_overflows + set_cookie! cookie_value(:empty) + new_session do |session| + session['overflow'] = 'bye!' * 1024 + assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close } + assert_no_cookies session + end + end + + def test_close_marshals_and_writes_cookie + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session['flash'] = {} + assert_no_cookies session + session.close + assert_equal 1, session.cgi.output_cookies.size + cookie = session.cgi.output_cookies.first + assert_cookie cookie, cookie_value(:flashed) + end + end + + def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session.delete + assert_cookie_deleted session + + # @data is set to nil so #close doesn't send another cookie. + session.close + assert_cookie_deleted session + end + end + + def test_new_session_doesnt_reuse_deleted_cookie_data + set_cookie! cookie_value(:typical) + + new_session do |session| + assert_not_nil session['user_id'] + session.delete + + # Start a new session using the same CGI instance. + post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options) + assert_nil post_delete_session['user_id'] + end + end + + private + def assert_no_cookies(session) + assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect + end + + def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set') + assert_equal 1, session.cgi.output_cookies.size + cookie = session.cgi.output_cookies.first + assert_cookie cookie, nil, 1.year.ago.to_date, message + end + + def assert_cookie(cookie, value = nil, expires = nil, message = nil) + assert_equal '_myapp_session', cookie.name, message + assert_equal [value].compact, cookie.value, message + assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message + end + + + def cookies(*which) + self.class.cookies.values_at(*which) + end + + def cookie_value(which) + self.class.cookies[which].first + end + + def set_cookie!(value) + ENV['HTTP_COOKIE'] = "_myapp_session=#{value}" + end + + def new_session(options = {}) + with_cgi do |cgi| + assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" + assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" + + @options = self.class.default_session_options.merge(options) + session = CGI::Session.new(cgi, @options) + + assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" + assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" + + yield session if block_given? + session + end + end + + def with_cgi + ENV['REQUEST_METHOD'] = 'GET' + ENV['HTTP_HOST'] = 'example.com' + ENV['QUERY_STRING'] = '' + + cgi = CGI.new('query', StringIO.new('')) + yield cgi if block_given? + cgi + end +end + + +class CookieStoreWithBlockAsSecretTest < CookieStoreTest + def self.default_session_options + CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' } + end +end + + +class CookieStoreWithMD5DigestTest < CookieStoreTest + def self.default_session_options + CookieStoreTest.default_session_options.merge 'digest' => 'MD5' + end + + def self.cookies + { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}], + :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }], + :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }] } + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb new file mode 100644 index 000000000..3afb7a8ea --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb @@ -0,0 +1,182 @@ +require "#{File.dirname(__FILE__)}/../../abstract_unit" +require 'action_controller/cgi_process' +require 'action_controller/cgi_ext' + + +class CGI::Session + def cache + dbman.instance_variable_get(:@cache) + end +end + + +uses_mocha 'MemCacheStore tests' do +if defined? MemCache::MemCacheError + +class MemCacheStoreTest < Test::Unit::TestCase + SESSION_KEY_RE = /^session:[0-9a-z]+/ + CONN_TEST_KEY = 'connection_test' + MULTI_TEST_KEY = '0123456789' + TEST_DATA = 'Hello test' + + def self.get_mem_cache_if_available + begin + require 'memcache' + cache = MemCache.new('127.0.0.1') + # Test availability of the connection + cache.set(CONN_TEST_KEY, 1) + unless cache.get(CONN_TEST_KEY) == 1 + puts 'Warning: memcache server available but corrupted.' + return nil + end + rescue LoadError, MemCache::MemCacheError + return nil + end + return cache + end + + CACHE = get_mem_cache_if_available + + + def test_initialization + assert_raise(ArgumentError) { new_session('session_id' => '!invalid_id') } + new_session do |s| + assert_equal Hash.new, s.cache.get('session:' + s.session_id) + end + end + + + def test_storage + d = rand(0xffff) + new_session do |s| + session_key = 'session:' + s.session_id + unless CACHE + s.cache.expects(:get).with(session_key) \ + .returns(:test => d) + s.cache.expects(:set).with(session_key, + has_entry(:test, d), + 0) + end + s[:test] = d + s.close + assert_equal d, s.cache.get(session_key)[:test] + assert_equal d, s[:test] + end + end + + + def test_deletion + new_session do |s| + session_key = 'session:' + s.session_id + unless CACHE + s.cache.expects(:delete) + s.cache.expects(:get).with(session_key) \ + .returns(nil) + end + s[:test] = rand(0xffff) + s.delete + assert_nil s.cache.get(session_key) + end + end + + + def test_other_session_retrieval + new_session do |sa| + unless CACHE + sa.cache.expects(:set).with('session:' + sa.session_id, + has_entry(:test, TEST_DATA), + 0) + end + sa[:test] = TEST_DATA + sa.close + new_session('session_id' => sa.session_id) do |sb| + unless CACHE + sb.cache.expects(:[]).with('session:' + sb.session_id) \ + .returns(:test => TEST_DATA) + end + assert_equal(TEST_DATA, sb[:test]) + end + end + end + + + def test_multiple_sessions + s_slots = Array.new(10) + operation = :write + last_data = nil + reads = writes = 0 + 50.times do + current = rand(10) + s_slots[current] ||= new_session('session_id' => MULTI_TEST_KEY, + 'new_session' => true) + s = s_slots[current] + case operation + when :write + last_data = rand(0xffff) + unless CACHE + s.cache.expects(:set).with('session:' + MULTI_TEST_KEY, + { :test => last_data }, + 0) + end + s[:test] = last_data + s.close + writes += 1 + when :read + # Make CGI::Session#[] think there was no data retrieval yet. + # Normally, the session caches the data during its lifetime. + s.instance_variable_set(:@data, nil) + unless CACHE + s.cache.expects(:[]).with('session:' + MULTI_TEST_KEY) \ + .returns(:test => last_data) + end + d = s[:test] + assert_equal(last_data, d, "OK reads: #{reads}, OK writes: #{writes}") + reads += 1 + end + operation = rand(5) == 0 ? :write : :read + end + end + + + + private + def obtain_session_options + options = { 'database_manager' => CGI::Session::MemCacheStore, + 'session_key' => '_test_app_session' + } + # if don't have running memcache server we use mock instead + unless CACHE + options['cache'] = c = mock + c.stubs(:[]).with(regexp_matches(SESSION_KEY_RE)) + c.stubs(:get).with(regexp_matches(SESSION_KEY_RE)) \ + .returns(Hash.new) + c.stubs(:add).with(regexp_matches(SESSION_KEY_RE), + instance_of(Hash), + 0) + end + options + end + + + def new_session(options = {}) + with_cgi do |cgi| + @options = obtain_session_options.merge(options) + session = CGI::Session.new(cgi, @options) + yield session if block_given? + return session + end + end + + def with_cgi + ENV['REQUEST_METHOD'] = 'GET' + ENV['HTTP_HOST'] = 'example.com' + ENV['QUERY_STRING'] = '' + + cgi = CGI.new('query', StringIO.new('')) + yield cgi if block_given? + cgi + end +end + +end # defined? MemCache +end # uses_mocha |