aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test/activerecord/active_record_store_test.rb
blob: f85bdeb466309a62028d816a5a83ea358440cc1d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# Unfurl the safety net.
path_to_ar = File.dirname(__FILE__) + '/../../../activerecord'
if Object.const_defined?(:ActiveRecord) or File.exist?(path_to_ar)
  begin

# These tests exercise CGI::Session::ActiveRecordStore, so you're going to
# need AR in a sibling directory to AP and have SQLite installed.

unless Object.const_defined?(:ActiveRecord)
  require File.join(path_to_ar, 'lib', 'active_record')
end

require File.dirname(__FILE__) + '/../abstract_unit'
require 'action_controller/session/active_record_store'

#ActiveRecord::Base.logger = Logger.new($stdout)
begin
  CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
  CGI::Session::ActiveRecordStore::Session.connection
rescue Object
  $stderr.puts 'SQLite 3 unavailable; falling back to SQLite 2.'
  begin
    CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite', :database => ':memory:')
    CGI::Session::ActiveRecordStore::Session.connection
  rescue Object
    $stderr.puts 'SQLite 2 unavailable; skipping ActiveRecordStore test suite.'
    raise SystemExit
  end
end


module CommonActiveRecordStoreTests
  def test_basics
    s = session_class.new(:session_id => '1234', :data => { 'foo' => 'bar' })
    assert_equal 'bar', s.data['foo']
    assert s.save
    assert_equal 'bar', s.data['foo']

    assert_not_nil t = session_class.find_by_session_id('1234')
    assert_not_nil t.data
    assert_equal 'bar', t.data['foo']
  end

  def test_reload_same_session
    @new_session.update
    reloaded = CGI::Session.new(CGI.new, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore)
    assert_equal 'bar', reloaded['foo']
  end

  def test_tolerates_close_close
    assert_nothing_raised do
      @new_session.close
      @new_session.close
    end
  end
end

class ActiveRecordStoreTest < Test::Unit::TestCase
  include CommonActiveRecordStoreTests

  def session_class
    CGI::Session::ActiveRecordStore::Session
  end

  def session_id_column
    "session_id"
  end

  def setup
    session_class.create_table!

    ENV['REQUEST_METHOD'] = 'GET'
    ENV['REQUEST_URI'] = '/'
    CGI::Session::ActiveRecordStore.session_class = session_class

    @cgi = CGI.new
    @new_session = CGI::Session.new(@cgi, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true)
    @new_session['foo'] = 'bar'
  end

# this test only applies for eager sesssion saving
#  def test_another_instance
#    @another = CGI::Session.new(@cgi, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore)
#    assert_equal @new_session.session_id, @another.session_id
#  end

  def test_model_attribute
    assert_kind_of CGI::Session::ActiveRecordStore::Session, @new_session.model
    assert_equal({ 'foo' => 'bar' }, @new_session.model.data)
  end

  def test_save_unloaded_session
    c = session_class.connection
    bogus_class = c.quote(Base64.encode64("\004\010o:\vBlammo\000"))
    c.insert("INSERT INTO #{session_class.table_name} ('#{session_id_column}', 'data') VALUES ('abcdefghijklmnop', #{bogus_class})")

    sess = session_class.find_by_session_id('abcdefghijklmnop')
    assert_not_nil sess
    assert !sess.loaded?

    # because the session is not loaded, the save should be a no-op. If it
    # isn't, this'll try and unmarshall the bogus class, and should get an error.
    assert_nothing_raised { sess.save }
  end

  def teardown
    session_class.drop_table!
  end
end

class ColumnLimitTest < Test::Unit::TestCase
  def setup
    @session_class = CGI::Session::ActiveRecordStore::Session
    @session_class.create_table!
  end

  def teardown
    @session_class.drop_table!
  end

  def test_protection_from_data_larger_than_column
    # Can't test this unless there is a limit
    return unless limit = @session_class.data_column_size_limit
    too_big = ':(' * limit
    s = @session_class.new(:session_id => '666', :data => {'foo' => too_big})
    s.data
    assert_raise(ActionController::SessionOverflowError) { s.save }
  end
end

class DeprecatedActiveRecordStoreTest < ActiveRecordStoreTest
  def session_id_column
    "sessid"
  end

  def setup
    session_class.connection.execute 'create table old_sessions (id integer primary key, sessid text unique, data text)'
    session_class.table_name = 'old_sessions'
    session_class.send :setup_sessid_compatibility!

    ENV['REQUEST_METHOD'] = 'GET'
    CGI::Session::ActiveRecordStore.session_class = session_class

    @new_session = CGI::Session.new(CGI.new, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true)
    @new_session['foo'] = 'bar'
  end

  def teardown
    session_class.connection.execute 'drop table old_sessions'
    session_class.table_name = 'sessions'
  end
end

class SqlBypassActiveRecordStoreTest < ActiveRecordStoreTest
  def session_class
    unless @session_class
      @session_class = CGI::Session::ActiveRecordStore::SqlBypass
      @session_class.connection = CGI::Session::ActiveRecordStore::Session.connection
    end
    @session_class
  end

  def test_model_attribute
    assert_kind_of CGI::Session::ActiveRecordStore::SqlBypass, @new_session.model
    assert_equal({ 'foo' => 'bar' }, @new_session.model.data)
  end
end


# End of safety net.
  rescue Object => e
    $stderr.puts "Skipping CGI::Session::ActiveRecordStore tests: #{e}"
    #$stderr.puts "  #{e.backtrace.join("\n  ")}"
  end
end